@@ -10,10 +10,10 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
1010use thin_vec:: { ThinVec , thin_vec} ;
1111
1212use crate :: errors:: {
13- EiiExternTargetExpectedList , EiiExternTargetExpectedMacro , EiiExternTargetExpectedUnsafe ,
14- EiiMacroExpectedMaxOneArgument , EiiOnlyOnce , EiiSharedMacroInStatementPosition ,
15- EiiSharedMacroTarget , EiiStaticArgumentRequired , EiiStaticDefault ,
16- EiiStaticMultipleImplementations , EiiStaticMutable ,
13+ EiiAttributeNotSupported , EiiExternTargetExpectedList , EiiExternTargetExpectedMacro ,
14+ EiiExternTargetExpectedUnsafe , EiiMacroExpectedMaxOneArgument , EiiOnlyOnce ,
15+ EiiSharedMacroInStatementPosition , EiiSharedMacroTarget , EiiStaticArgumentRequired ,
16+ EiiStaticDefault , EiiStaticMultipleImplementations , EiiStaticMutable ,
1717} ;
1818
1919/// ```rust
@@ -128,6 +128,8 @@ fn eii_(
128128
129129 let attrs_from_decl =
130130 filter_attrs_for_multiple_eii_attr ( ecx, attrs, eii_attr_span, & meta_item. path ) ;
131+ let ( macro_attrs, foreign_item_attrs, default_func_attrs) =
132+ split_attrs ( ecx, item_span, attrs_from_decl) ;
131133
132134 let Ok ( macro_name) = name_for_impl_macro ( ecx, foreign_item_name, & meta_item) else {
133135 // we don't need to wrap in Annotatable::Stmt conditionally since
@@ -148,6 +150,7 @@ fn eii_(
148150 eii_attr_span,
149151 item_span,
150152 foreign_item_name,
153+ default_func_attrs,
151154 ) )
152155 }
153156
@@ -157,22 +160,65 @@ fn eii_(
157160 item_span,
158161 kind,
159162 vis,
160- & attrs_from_decl ,
163+ foreign_item_attrs ,
161164 ) ) ;
162165 module_items. push ( generate_attribute_macro_to_implement (
163166 ecx,
164167 eii_attr_span,
165168 macro_name,
166169 foreign_item_name,
167170 impl_unsafe,
168- & attrs_from_decl ,
171+ macro_attrs ,
169172 ) ) ;
170173
171174 // we don't need to wrap in Annotatable::Stmt conditionally since
172175 // EII can't be used on items in statement position
173176 module_items. into_iter ( ) . map ( Annotatable :: Item ) . collect ( )
174177}
175178
179+ fn split_attrs (
180+ ecx : & mut ExtCtxt < ' _ > ,
181+ span : Span ,
182+ attrs : ThinVec < Attribute > ,
183+ ) -> ( ThinVec < Attribute > , ThinVec < Attribute > , ThinVec < Attribute > ) {
184+ let mut macro_attributes = ThinVec :: new ( ) ;
185+ let mut foreign_item_attributes = ThinVec :: new ( ) ;
186+ let mut default_attributes = ThinVec :: new ( ) ;
187+
188+ for attr in attrs {
189+ match attr. name ( ) {
190+ // Inline only matters for the default function being inlined into callsites
191+ Some ( sym:: inline) => default_attributes. push ( attr) ,
192+ // If an eii is marked a lang item, that's because we want to call its declaration, so
193+ // mark the foreign item as the lang item
194+ Some ( sym:: lang) => foreign_item_attributes. push ( attr) ,
195+ // Deprecating an eii means deprecating the macro and the foreign item
196+ Some ( sym:: deprecated) => {
197+ foreign_item_attributes. push ( attr. clone ( ) ) ;
198+ macro_attributes. push ( attr) ;
199+ }
200+ // The stability of an EII affects the usage of the macro and calling the foreign item
201+ Some ( sym:: stable) | Some ( sym:: unstable) => {
202+ foreign_item_attributes. push ( attr. clone ( ) ) ;
203+ macro_attributes. push ( attr) ;
204+ }
205+ // Doc attributes should be forwarded to the macro and the foreign item, since those are
206+ // the two items you interact with as a user.
207+ // FIXME: idk yet how EIIs show up in docs, might want to customize
208+ _ if attr. is_doc_comment ( ) => {
209+ foreign_item_attributes. push ( attr. clone ( ) ) ;
210+ macro_attributes. push ( attr) ;
211+ }
212+ Some ( sym:: eii) => unreachable ! ( "should already be filtered out" ) ,
213+ _ => {
214+ ecx. dcx ( ) . emit_err ( EiiAttributeNotSupported { span, attr_span : attr. span ( ) } ) ;
215+ }
216+ }
217+ }
218+
219+ ( macro_attributes, foreign_item_attributes, default_attributes)
220+ }
221+
176222/// Decide on the name of the macro that can be used to implement the EII.
177223/// This is either an explicitly given name, or the name of the item in the
178224/// declaration of the EII.
@@ -228,10 +274,8 @@ fn generate_default_func_impl(
228274 eii_attr_span : Span ,
229275 item_span : Span ,
230276 foreign_item_name : Ident ,
277+ attrs : ThinVec < Attribute > ,
231278) -> Box < ast:: Item > {
232- // FIXME: re-add some original attrs
233- let attrs = ThinVec :: new ( ) ;
234-
235279 let mut default_func = func. clone ( ) ;
236280 default_func. eii_impls . push ( EiiImpl {
237281 node_id : DUMMY_NODE_ID ,
@@ -289,10 +333,9 @@ fn generate_foreign_item(
289333 item_span : Span ,
290334 item_kind : & ItemKind ,
291335 vis : Visibility ,
292- attrs_from_decl : & [ Attribute ] ,
336+ attrs_from_decl : ThinVec < Attribute > ,
293337) -> Box < ast:: Item > {
294- let mut foreign_item_attrs = ThinVec :: new ( ) ;
295- foreign_item_attrs. extend_from_slice ( attrs_from_decl) ;
338+ let mut foreign_item_attrs = attrs_from_decl;
296339
297340 // Add the rustc_eii_foreign_item on the foreign item. Usually, foreign items are mangled.
298341 // This attribute makes sure that we later know that this foreign item's symbol should not be.
@@ -381,13 +424,9 @@ fn generate_attribute_macro_to_implement(
381424 macro_name : Ident ,
382425 foreign_item_name : Ident ,
383426 impl_unsafe : bool ,
384- attrs_from_decl : & [ Attribute ] ,
427+ attrs_from_decl : ThinVec < Attribute > ,
385428) -> Box < ast:: Item > {
386- let mut macro_attrs = ThinVec :: new ( ) ;
387-
388- // To avoid e.g. `error: attribute macro has missing stability attribute`
389- // errors for eii's in std.
390- macro_attrs. extend_from_slice ( attrs_from_decl) ;
429+ let mut macro_attrs = attrs_from_decl;
391430
392431 // Avoid "missing stability attribute" errors for eiis in std. See #146993.
393432 macro_attrs. push ( ecx. attr_name_value_str ( sym:: rustc_macro_transparency, sym:: semiopaque, span) ) ;
0 commit comments