11use rustc_ast:: token:: { Delimiter , TokenKind } ;
22use rustc_ast:: tokenstream:: { DelimSpacing , DelimSpan , Spacing , TokenStream , TokenTree } ;
33use rustc_ast:: {
4- Attribute , DUMMY_NODE_ID , EiiExternTarget , EiiImpl , ItemKind , MetaItem , Path , Stmt , StmtKind ,
4+ Attribute , DUMMY_NODE_ID , EiiExternTarget , EiiImpl , ItemKind , MetaItem , Path , StmtKind ,
55 Visibility , ast,
66} ;
77use rustc_ast_pretty:: pprust:: path_to_string;
@@ -12,6 +12,7 @@ use thin_vec::{ThinVec, thin_vec};
1212use crate :: errors:: {
1313 EiiExternTargetExpectedList , EiiExternTargetExpectedMacro , EiiExternTargetExpectedUnsafe ,
1414 EiiMacroExpectedMaxOneArgument , EiiOnlyOnce , EiiSharedMacroExpectedFunction ,
15+ EiiSharedMacroNotInStatementPosition ,
1516} ;
1617
1718/// ```rust
@@ -55,29 +56,29 @@ fn eii_(
5556 ecx : & mut ExtCtxt < ' _ > ,
5657 eii_attr_span : Span ,
5758 meta_item : & ast:: MetaItem ,
58- item : Annotatable ,
59+ orig_item : Annotatable ,
5960 impl_unsafe : bool ,
6061) -> Vec < Annotatable > {
6162 let eii_attr_span = ecx. with_def_site_ctxt ( eii_attr_span) ;
6263
63- let ( item, wrap_item ) : ( _ , & dyn Fn ( _ ) -> _ ) = if let Annotatable :: Item ( item) = item {
64- ( item, & Annotatable :: Item )
65- } else if let Annotatable :: Stmt ( ref stmt) = item
64+ let item = if let Annotatable :: Item ( item) = orig_item {
65+ item
66+ } else if let Annotatable :: Stmt ( ref stmt) = orig_item
6667 && let StmtKind :: Item ( ref item) = stmt. kind
68+ && let ItemKind :: Fn ( ref f) = item. kind
6769 {
68- ( item. clone ( ) , & |item| {
69- Annotatable :: Stmt ( Box :: new ( Stmt {
70- id : DUMMY_NODE_ID ,
71- kind : StmtKind :: Item ( item) ,
72- span : eii_attr_span,
73- } ) )
74- } )
70+ ecx. dcx ( ) . emit_err ( EiiSharedMacroNotInStatementPosition {
71+ span : eii_attr_span. to ( item. span ) ,
72+ name : path_to_string ( & meta_item. path ) ,
73+ item_span : f. ident . span ,
74+ } ) ;
75+ return vec ! [ orig_item] ;
7576 } else {
7677 ecx. dcx ( ) . emit_err ( EiiSharedMacroExpectedFunction {
7778 span : eii_attr_span,
7879 name : path_to_string ( & meta_item. path ) ,
7980 } ) ;
80- return vec ! [ item ] ;
81+ return vec ! [ orig_item ] ;
8182 } ;
8283
8384 let ast:: Item { attrs, id : _, span : _, vis, kind : ItemKind :: Fn ( func) , tokens : _ } =
@@ -87,7 +88,7 @@ fn eii_(
8788 span : eii_attr_span,
8889 name : path_to_string ( & meta_item. path ) ,
8990 } ) ;
90- return vec ! [ wrap_item ( item) ] ;
91+ return vec ! [ Annotatable :: Item ( item) ] ;
9192 } ;
9293 // only clone what we need
9394 let attrs = attrs. clone ( ) ;
@@ -98,7 +99,9 @@ fn eii_(
9899 filter_attrs_for_multiple_eii_attr ( ecx, attrs, eii_attr_span, & meta_item. path ) ;
99100
100101 let Ok ( macro_name) = name_for_impl_macro ( ecx, & func, & meta_item) else {
101- return vec ! [ wrap_item( item) ] ;
102+ // we don't need to wrap in Annotatable::Stmt conditionally since
103+ // EII can't be used on items in statement position
104+ return vec ! [ Annotatable :: Item ( item) ] ;
102105 } ;
103106
104107 // span of the declaring item without attributes
@@ -136,7 +139,9 @@ fn eii_(
136139 & attrs_from_decl,
137140 ) ) ;
138141
139- module_items. into_iter ( ) . map ( wrap_item) . collect ( )
142+ // we don't need to wrap in Annotatable::Stmt conditionally since
143+ // EII can't be used on items in statement position
144+ module_items. into_iter ( ) . map ( Annotatable :: Item ) . collect ( )
140145}
141146
142147/// Decide on the name of the macro that can be used to implement the EII.
@@ -214,6 +219,7 @@ fn generate_default_impl(
214219 extern_item_path : ecx. path (
215220 foreign_item_name. span ,
216221 // prefix super to explicitly escape the const block generated below
222+ // NOTE: this is why EIIs can't be used on statements
217223 vec ! [ Ident :: from_str_and_span( "self" , foreign_item_name. span) , foreign_item_name] ,
218224 ) ,
219225 impl_unsafe,
0 commit comments