@@ -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,44 @@ 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 {
86+ span : _,
87+ reason : Some ( reason) ,
88+ } ) => Some ( reason. clone ( ) ) ,
89+ _ => None ,
90+ } ;
91+
92+ hir:: Attribute :: Parsed ( AttributeKind :: MustUse { span, reason } )
93+ } ,
94+ flag : DelegationFnSigAttrs :: MUST_USE ,
95+ } ,
96+ } ,
97+ AttributeAdditionInfo {
98+ equals : |a| matches ! ( a, hir:: Attribute :: Parsed ( AttributeKind :: Inline ( ..) ) ) ,
99+ kind : AttributeAdditionKind :: Default {
100+ factory : |span| hir:: Attribute :: Parsed ( AttributeKind :: Inline ( InlineAttr :: Hint , span) ) ,
101+ } ,
102+ } ,
103+ ] ;
104+
65105impl < ' hir > LoweringContext < ' _ , ' hir > {
66106 fn is_method ( & self , def_id : DefId , span : Span ) -> bool {
67107 match self . tcx . def_kind ( def_id) {
@@ -88,7 +128,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
88128 let sig_id = self . get_delegation_sig_id ( item_id, delegation. id , span, is_in_trait_impl) ;
89129 match sig_id {
90130 Ok ( sig_id) => {
91- self . add_inline_attribute_if_needed ( span) ;
131+ self . add_attributes_if_needed ( span, sig_id ) ;
92132
93133 let is_method = self . is_method ( sig_id, span) ;
94134 let ( param_count, c_variadic) = self . param_count ( sig_id) ;
@@ -103,29 +143,100 @@ impl<'hir> LoweringContext<'_, 'hir> {
103143 }
104144 }
105145
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 ( ..) ) ) )
146+ fn add_attributes_if_needed ( & mut self , span : Span , sig_id : DefId ) {
147+ let new_attributes = self . create_new_attributes (
148+ ATTRIBUTES_ADDITIONS ,
149+ span,
150+ sig_id,
151+ self . attrs . get ( & PARENT_ID ) ,
152+ ) ;
153+
154+ if new_attributes. is_empty ( ) {
155+ return ;
156+ }
157+
158+ let new_arena_allocated_attributes = match self . attrs . get ( & PARENT_ID ) {
159+ Some ( existing_attrs) => self . arena . alloc_from_iter (
160+ existing_attrs. iter ( ) . map ( |a| a. clone ( ) ) . chain ( new_attributes. into_iter ( ) ) ,
161+ ) ,
162+ None => self . arena . alloc_from_iter ( new_attributes. into_iter ( ) ) ,
163+ } ;
164+
165+ self . attrs . insert ( PARENT_ID , new_arena_allocated_attributes) ;
166+ }
167+
168+ fn create_new_attributes (
169+ & self ,
170+ candidate_additions : & [ AttributeAdditionInfo ] ,
171+ span : Span ,
172+ sig_id : DefId ,
173+ existing_attrs : Option < & & [ hir:: Attribute ] > ,
174+ ) -> Vec < hir:: Attribute > {
175+ let local_original_attributes = self . parse_local_original_attributes ( sig_id) ;
176+
177+ candidate_additions
178+ . iter ( )
179+ . filter_map ( |addition_info| {
180+ if let Some ( existing_attrs) = existing_attrs
181+ && existing_attrs
182+ . iter ( )
183+ . any ( |existing_attr| ( addition_info. equals ) ( existing_attr) )
117184 {
118- return ;
185+ return None ;
119186 }
120187
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- } ;
188+ match addition_info. kind {
189+ AttributeAdditionKind :: Default { factory } => Some ( factory ( span) ) ,
190+ AttributeAdditionKind :: Inherit { flag, factory } => {
191+ let original_attribute = match sig_id. as_local ( ) {
192+ Some ( local_id) => self
193+ . resolver
194+ . delegation_fn_sigs
195+ . get ( & local_id)
196+ . is_some_and ( |sig| sig. attrs_flags . contains ( flag) )
197+ . then ( || {
198+ local_original_attributes
199+ . as_ref ( )
200+ . map ( |attrs| {
201+ attrs
202+ . iter ( )
203+ . find ( |base_attr| ( addition_info. equals ) ( base_attr) )
204+ } )
205+ . flatten ( )
206+ } )
207+ . flatten ( ) ,
208+ None => self
209+ . tcx
210+ . get_all_attrs ( sig_id)
211+ . iter ( )
212+ . find ( |base_attr| ( addition_info. equals ) ( base_attr) ) ,
213+ } ;
127214
128- self . attrs . insert ( PARENT_ID , new_attributes) ;
215+ original_attribute. map ( |a| factory ( span, a) )
216+ }
217+ }
218+ } )
219+ . collect :: < Vec < _ > > ( )
220+ }
221+
222+ fn parse_local_original_attributes ( & self , sig_id : DefId ) -> Option < Vec < hir:: Attribute > > {
223+ if let Some ( local_id) = sig_id. as_local ( )
224+ && let Some ( info) = self . resolver . delegation_fn_sigs . get ( & local_id)
225+ && !info. to_inherit_attrs . is_empty ( )
226+ {
227+ Some ( AttributeParser :: parse_limited_all (
228+ self . tcx . sess ,
229+ info. to_inherit_attrs . as_slice ( ) ,
230+ None ,
231+ Target :: Fn ,
232+ DUMMY_SP ,
233+ DUMMY_NODE_ID ,
234+ Some ( self . tcx . features ( ) ) ,
235+ ShouldEmit :: Nothing ,
236+ ) )
237+ } else {
238+ None
239+ }
129240 }
130241
131242 fn get_delegation_sig_id (
@@ -220,7 +331,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
220331 // We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
221332 // and here we need the hir attributes.
222333 let default_safety =
223- if sig. target_feature || self . tcx . def_kind ( parent) == DefKind :: ForeignMod {
334+ if sig. attrs_flags . contains ( DelegationFnSigAttrs :: TARGET_FEATURE )
335+ || self . tcx . def_kind ( parent) == DefKind :: ForeignMod
336+ {
224337 hir:: Safety :: Unsafe
225338 } else {
226339 hir:: Safety :: Safe
0 commit comments