@@ -47,9 +47,9 @@ use rustc_errors::ErrorGuaranteed;
4747use rustc_hir:: attrs:: { AttributeKind , InlineAttr } ;
4848use rustc_hir:: def_id:: DefId ;
4949use rustc_middle:: span_bug;
50- use rustc_middle:: ty:: { Asyncness , ResolverAstLowering } ;
50+ use rustc_middle:: ty:: { Asyncness , DelegationFnSigAttrs , ResolverAstLowering } ;
5151use rustc_span:: symbol:: kw;
52- use rustc_span:: { Ident , Span , Symbol } ;
52+ use rustc_span:: { Ident , Span , Symbol , sym } ;
5353use { rustc_ast as ast, rustc_hir as hir} ;
5454
5555use super :: { GenericArgsMode , ImplTraitContext , LoweringContext , ParamMode } ;
@@ -62,6 +62,40 @@ pub(crate) struct DelegationResults<'hir> {
6262 pub generics : & ' hir hir:: Generics < ' hir > ,
6363}
6464
65+ struct AttributeAdditionInfo {
66+ pub factory : fn ( Span ) -> hir:: Attribute ,
67+ pub equals : fn ( & hir:: Attribute ) -> bool ,
68+ pub kind : AttributeAdditionKind ,
69+ }
70+
71+ struct AttributeAdditionStatus {
72+ pub info : & ' static AttributeAdditionInfo ,
73+ pub already_exists : bool ,
74+ }
75+
76+ enum AttributeAdditionKind {
77+ Default ,
78+ Inherit { symbol : Symbol , flag : DelegationFnSigAttrs } ,
79+ }
80+
81+ const PARENT_ID : hir:: ItemLocalId = hir:: ItemLocalId :: ZERO ;
82+
83+ static ATTRS_ADDITIONS : & ' static [ AttributeAdditionInfo ; 2 ] = & [
84+ AttributeAdditionInfo {
85+ factory : |span| hir:: Attribute :: Parsed ( AttributeKind :: MustUse { span, reason : None } ) ,
86+ equals : |a| matches ! ( a, hir:: Attribute :: Parsed ( AttributeKind :: MustUse { .. } ) ) ,
87+ kind : AttributeAdditionKind :: Inherit {
88+ symbol : sym:: must_use,
89+ flag : DelegationFnSigAttrs :: MUST_USE ,
90+ } ,
91+ } ,
92+ AttributeAdditionInfo {
93+ factory : |span| hir:: Attribute :: Parsed ( AttributeKind :: Inline ( InlineAttr :: Hint , span) ) ,
94+ equals : |a| matches ! ( a, hir:: Attribute :: Parsed ( AttributeKind :: Inline ( ..) ) ) ,
95+ kind : AttributeAdditionKind :: Default ,
96+ } ,
97+ ] ;
98+
6599impl < ' hir > LoweringContext < ' _ , ' hir > {
66100 fn is_method ( & self , def_id : DefId , span : Span ) -> bool {
67101 match self . tcx . def_kind ( def_id) {
@@ -88,7 +122,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
88122 let sig_id = self . get_delegation_sig_id ( item_id, delegation. id , span, is_in_trait_impl) ;
89123 match sig_id {
90124 Ok ( sig_id) => {
91- self . add_inline_attribute_if_needed ( span) ;
125+ self . add_attributes_if_needed ( span, sig_id ) ;
92126
93127 let is_method = self . is_method ( sig_id, span) ;
94128 let ( param_count, c_variadic) = self . param_count ( sig_id) ;
@@ -103,29 +137,80 @@ impl<'hir> LoweringContext<'_, 'hir> {
103137 }
104138 }
105139
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 ( ..) ) ) )
117- {
118- return ;
119- }
140+ fn add_attributes_if_needed ( & mut self , span : Span , sig_id : DefId ) {
141+ let mut candidate_additions = ATTRS_ADDITIONS
142+ . iter ( )
143+ . map ( |a| AttributeAdditionStatus { info : a, already_exists : false } )
144+ . collect :: < Vec < _ > > ( ) ;
120145
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 ( ) ) ,
146+ self . check_if_attributes_already_exist ( & mut candidate_additions) ;
147+ let new_attributes = self . create_new_attributes ( & candidate_additions, span, sig_id) ;
148+
149+ if new_attributes. is_empty ( ) {
150+ return ;
151+ }
152+
153+ let new_arena_allocated_attributes = match self . attrs . get ( & PARENT_ID ) {
154+ Some ( existing_attrs) => self . arena . alloc_from_iter (
155+ existing_attrs. iter ( ) . map ( |a| a. clone ( ) ) . chain ( new_attributes. into_iter ( ) ) ,
156+ ) ,
157+ None => self . arena . alloc_from_iter ( new_attributes. into_iter ( ) ) ,
126158 } ;
127159
128- self . attrs . insert ( PARENT_ID , new_attributes) ;
160+ self . attrs . insert ( PARENT_ID , new_arena_allocated_attributes) ;
161+ }
162+
163+ fn check_if_attributes_already_exist (
164+ & mut self ,
165+ candidate_additions : & mut Vec < AttributeAdditionStatus > ,
166+ ) {
167+ if let Some ( existing_attrs) = self . attrs . get ( & PARENT_ID ) {
168+ for attr in existing_attrs. iter ( ) {
169+ for addition in candidate_additions. iter_mut ( ) {
170+ if addition. already_exists {
171+ continue ;
172+ }
173+
174+ if ( addition. info . equals ) ( attr) {
175+ addition. already_exists = true ;
176+ }
177+ }
178+ }
179+ }
180+ }
181+
182+ fn create_new_attributes (
183+ & mut self ,
184+ candidate_additions : & Vec < AttributeAdditionStatus > ,
185+ span : Span ,
186+ sig_id : DefId ,
187+ ) -> Vec < hir:: Attribute > {
188+ candidate_additions
189+ . into_iter ( )
190+ . filter_map ( |a| match a. already_exists {
191+ true => None ,
192+ false => match a. info . kind {
193+ AttributeAdditionKind :: Default => Some ( ( a. info . factory ) ( span) ) ,
194+ AttributeAdditionKind :: Inherit { symbol, flag } => {
195+ // Check if an anttribute present on the target of delegation,
196+ // either in this crate or others
197+ let should_inherit = match sig_id. as_local ( ) {
198+ None => self . tcx . get_attr ( sig_id, symbol) . is_some ( ) ,
199+ Some ( local_id) => self
200+ . resolver
201+ . delegation_fn_sigs
202+ . get ( & local_id)
203+ . is_some_and ( |sig| sig. attrs_flags . contains ( flag) ) ,
204+ } ;
205+
206+ match should_inherit {
207+ true => Some ( ( a. info . factory ) ( span) ) ,
208+ false => None ,
209+ }
210+ }
211+ } ,
212+ } )
213+ . collect :: < Vec < _ > > ( )
129214 }
130215
131216 fn get_delegation_sig_id (
@@ -220,7 +305,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
220305 // We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
221306 // and here we need the hir attributes.
222307 let default_safety =
223- if sig. target_feature || self . tcx . def_kind ( parent) == DefKind :: ForeignMod {
308+ if sig. attrs_flags . contains ( DelegationFnSigAttrs :: TARGET_FEATURE )
309+ || self . tcx . def_kind ( parent) == DefKind :: ForeignMod
310+ {
224311 hir:: Safety :: Unsafe
225312 } else {
226313 hir:: Safety :: Safe
0 commit comments