@@ -43,13 +43,15 @@ use hir::def::{DefKind, PartialRes, Res};
4343use hir:: { BodyId , HirId } ;
4444use rustc_abi:: ExternAbi ;
4545use rustc_ast:: * ;
46+ use rustc_attr_parsing:: { AttributeParser , ShouldEmit } ;
4647use rustc_errors:: ErrorGuaranteed ;
48+ use rustc_hir:: Target ;
4749use rustc_hir:: attrs:: { AttributeKind , InlineAttr } ;
4850use rustc_hir:: def_id:: DefId ;
4951use rustc_middle:: span_bug;
50- use rustc_middle:: ty:: { Asyncness , ResolverAstLowering } ;
52+ use rustc_middle:: ty:: { Asyncness , DelegationFnSigAttrs , ResolverAstLowering } ;
5153use rustc_span:: symbol:: kw;
52- use rustc_span:: { Ident , Span , Symbol } ;
54+ use rustc_span:: { DUMMY_SP , Ident , Span , Symbol } ;
5355use { rustc_ast as ast, rustc_hir as hir} ;
5456
5557use super :: { GenericArgsMode , ImplTraitContext , LoweringContext , ParamMode } ;
@@ -62,6 +64,41 @@ pub(crate) struct DelegationResults<'hir> {
6264 pub generics : & ' hir hir:: Generics < ' hir > ,
6365}
6466
67+ struct AttributeAdditionInfo {
68+ pub equals : fn ( & hir:: Attribute ) -> bool ,
69+ pub kind : AttributeAdditionKind ,
70+ }
71+
72+ enum AttributeAdditionKind {
73+ Default { factory : fn ( Span ) -> hir:: Attribute } ,
74+ Inherit { flag : DelegationFnSigAttrs , factory : fn ( Span , & hir:: Attribute ) -> hir:: Attribute } ,
75+ }
76+
77+ const PARENT_ID : hir:: ItemLocalId = hir:: ItemLocalId :: ZERO ;
78+
79+ static ATTRIBUTES_ADDITIONS : & [ AttributeAdditionInfo ] = & [
80+ AttributeAdditionInfo {
81+ equals : |a| matches ! ( a, hir:: Attribute :: Parsed ( AttributeKind :: MustUse { .. } ) ) ,
82+ kind : AttributeAdditionKind :: Inherit {
83+ factory : |span, original_attribute| {
84+ let reason = match original_attribute {
85+ hir:: Attribute :: Parsed ( AttributeKind :: MustUse { reason, .. } ) => * reason,
86+ _ => None ,
87+ } ;
88+
89+ hir:: Attribute :: Parsed ( AttributeKind :: MustUse { span, reason } )
90+ } ,
91+ flag : DelegationFnSigAttrs :: MUST_USE ,
92+ } ,
93+ } ,
94+ AttributeAdditionInfo {
95+ equals : |a| matches ! ( a, hir:: Attribute :: Parsed ( AttributeKind :: Inline ( ..) ) ) ,
96+ kind : AttributeAdditionKind :: Default {
97+ factory : |span| hir:: Attribute :: Parsed ( AttributeKind :: Inline ( InlineAttr :: Hint , span) ) ,
98+ } ,
99+ } ,
100+ ] ;
101+
65102impl < ' hir > LoweringContext < ' _ , ' hir > {
66103 fn is_method ( & self , def_id : DefId , span : Span ) -> bool {
67104 match self . tcx . def_kind ( def_id) {
@@ -88,7 +125,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
88125 let sig_id = self . get_delegation_sig_id ( item_id, delegation. id , span, is_in_trait_impl) ;
89126 match sig_id {
90127 Ok ( sig_id) => {
91- self . add_inline_attribute_if_needed ( span) ;
128+ self . add_attributes_if_needed ( span, sig_id ) ;
92129
93130 let is_method = self . is_method ( sig_id, span) ;
94131 let ( param_count, c_variadic) = self . param_count ( sig_id) ;
@@ -103,29 +140,100 @@ impl<'hir> LoweringContext<'_, 'hir> {
103140 }
104141 }
105142
106- fn add_inline_attribute_if_needed ( & mut self , span : Span ) {
107- const PARENT_ID : hir:: ItemLocalId = hir:: ItemLocalId :: ZERO ;
108- let create_inline_attr_slice =
109- || [ hir:: Attribute :: Parsed ( AttributeKind :: Inline ( InlineAttr :: Hint , span) ) ] ;
110-
111- let new_attributes = match self . attrs . get ( & PARENT_ID ) {
112- Some ( attrs) => {
113- // Check if reuse already specifies any inline attribute, if so, do nothing
114- if attrs
115- . iter ( )
116- . any ( |a| matches ! ( a, hir:: Attribute :: Parsed ( AttributeKind :: Inline ( ..) ) ) )
143+ fn add_attributes_if_needed ( & mut self , span : Span , sig_id : DefId ) {
144+ let new_attributes = self . create_new_attributes (
145+ ATTRIBUTES_ADDITIONS ,
146+ span,
147+ sig_id,
148+ self . attrs . get ( & PARENT_ID ) ,
149+ ) ;
150+
151+ if new_attributes. is_empty ( ) {
152+ return ;
153+ }
154+
155+ let new_arena_allocated_attributes = match self . attrs . get ( & PARENT_ID ) {
156+ Some ( existing_attrs) => self . arena . alloc_from_iter (
157+ existing_attrs. iter ( ) . map ( |a| a. clone ( ) ) . chain ( new_attributes. into_iter ( ) ) ,
158+ ) ,
159+ None => self . arena . alloc_from_iter ( new_attributes. into_iter ( ) ) ,
160+ } ;
161+
162+ self . attrs . insert ( PARENT_ID , new_arena_allocated_attributes) ;
163+ }
164+
165+ fn create_new_attributes (
166+ & self ,
167+ candidate_additions : & [ AttributeAdditionInfo ] ,
168+ span : Span ,
169+ sig_id : DefId ,
170+ existing_attrs : Option < & & [ hir:: Attribute ] > ,
171+ ) -> Vec < hir:: Attribute > {
172+ let local_original_attributes = self . parse_local_original_attributes ( sig_id) ;
173+
174+ candidate_additions
175+ . iter ( )
176+ . filter_map ( |addition_info| {
177+ if let Some ( existing_attrs) = existing_attrs
178+ && existing_attrs
179+ . iter ( )
180+ . any ( |existing_attr| ( addition_info. equals ) ( existing_attr) )
117181 {
118- return ;
182+ return None ;
119183 }
120184
121- self . arena . alloc_from_iter (
122- attrs. into_iter ( ) . map ( |a| a. clone ( ) ) . chain ( create_inline_attr_slice ( ) ) ,
123- )
124- }
125- None => self . arena . alloc_from_iter ( create_inline_attr_slice ( ) ) ,
126- } ;
185+ match addition_info. kind {
186+ AttributeAdditionKind :: Default { factory } => Some ( factory ( span) ) ,
187+ AttributeAdditionKind :: Inherit { flag, factory } => {
188+ let original_attribute = match sig_id. as_local ( ) {
189+ Some ( local_id) => self
190+ . resolver
191+ . delegation_fn_sigs
192+ . get ( & local_id)
193+ . is_some_and ( |sig| sig. attrs_flags . contains ( flag) )
194+ . then ( || {
195+ local_original_attributes
196+ . as_ref ( )
197+ . map ( |attrs| {
198+ attrs
199+ . iter ( )
200+ . find ( |base_attr| ( addition_info. equals ) ( base_attr) )
201+ } )
202+ . flatten ( )
203+ } )
204+ . flatten ( ) ,
205+ None => self
206+ . tcx
207+ . get_all_attrs ( sig_id)
208+ . iter ( )
209+ . find ( |base_attr| ( addition_info. equals ) ( base_attr) ) ,
210+ } ;
127211
128- self . attrs . insert ( PARENT_ID , new_attributes) ;
212+ original_attribute. map ( |a| factory ( span, a) )
213+ }
214+ }
215+ } )
216+ . collect :: < Vec < _ > > ( )
217+ }
218+
219+ fn parse_local_original_attributes ( & self , sig_id : DefId ) -> Option < Vec < hir:: Attribute > > {
220+ if let Some ( local_id) = sig_id. as_local ( )
221+ && let Some ( info) = self . resolver . delegation_fn_sigs . get ( & local_id)
222+ && !info. to_inherit_attrs . is_empty ( )
223+ {
224+ Some ( AttributeParser :: parse_limited_all (
225+ self . tcx . sess ,
226+ info. to_inherit_attrs . as_slice ( ) ,
227+ None ,
228+ Target :: Fn ,
229+ DUMMY_SP ,
230+ DUMMY_NODE_ID ,
231+ Some ( self . tcx . features ( ) ) ,
232+ ShouldEmit :: Nothing ,
233+ ) )
234+ } else {
235+ None
236+ }
129237 }
130238
131239 fn get_delegation_sig_id (
@@ -220,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
220328 // We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
221329 // and here we need the hir attributes.
222330 let default_safety =
223- if sig. target_feature || self . tcx . def_kind ( parent) == DefKind :: ForeignMod {
331+ if sig. attrs_flags . contains ( DelegationFnSigAttrs :: TARGET_FEATURE )
332+ || self . tcx . def_kind ( parent) == DefKind :: ForeignMod
333+ {
224334 hir:: Safety :: Unsafe
225335 } else {
226336 hir:: Safety :: Safe
0 commit comments