11use rustc_ast:: token:: { Delimiter , TokenKind } ;
22use rustc_ast:: tokenstream:: { DelimSpacing , DelimSpan , Spacing , TokenStream , TokenTree } ;
33use rustc_ast:: {
4- Attribute , DUMMY_NODE_ID , EiiDecl , EiiImpl , ItemKind , MetaItem , Path , Stmt , StmtKind ,
5- Visibility , ast,
4+ Attribute , DUMMY_NODE_ID , EiiDecl , EiiImpl , ItemKind , MetaItem , Path , StmtKind , Visibility , ast,
65} ;
76use rustc_ast_pretty:: pprust:: path_to_string;
87use rustc_expand:: base:: { Annotatable , ExtCtxt } ;
@@ -12,6 +11,7 @@ use thin_vec::{ThinVec, thin_vec};
1211use crate :: errors:: {
1312 EiiExternTargetExpectedList , EiiExternTargetExpectedMacro , EiiExternTargetExpectedUnsafe ,
1413 EiiMacroExpectedMaxOneArgument , EiiOnlyOnce , EiiSharedMacroExpectedFunction ,
14+ EiiSharedMacroInStatementPosition ,
1515} ;
1616
1717/// ```rust
@@ -55,29 +55,29 @@ fn eii_(
5555 ecx : & mut ExtCtxt < ' _ > ,
5656 eii_attr_span : Span ,
5757 meta_item : & ast:: MetaItem ,
58- item : Annotatable ,
58+ orig_item : Annotatable ,
5959 impl_unsafe : bool ,
6060) -> Vec < Annotatable > {
6161 let eii_attr_span = ecx. with_def_site_ctxt ( eii_attr_span) ;
6262
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
63+ let item = if let Annotatable :: Item ( item) = orig_item {
64+ item
65+ } else if let Annotatable :: Stmt ( ref stmt) = orig_item
6666 && let StmtKind :: Item ( ref item) = stmt. kind
67+ && let ItemKind :: Fn ( ref f) = item. kind
6768 {
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- } )
69+ ecx. dcx ( ) . emit_err ( EiiSharedMacroInStatementPosition {
70+ span : eii_attr_span. to ( item. span ) ,
71+ name : path_to_string ( & meta_item. path ) ,
72+ item_span : f. ident . span ,
73+ } ) ;
74+ return vec ! [ orig_item] ;
7575 } else {
7676 ecx. dcx ( ) . emit_err ( EiiSharedMacroExpectedFunction {
7777 span : eii_attr_span,
7878 name : path_to_string ( & meta_item. path ) ,
7979 } ) ;
80- return vec ! [ item ] ;
80+ return vec ! [ orig_item ] ;
8181 } ;
8282
8383 let ast:: Item { attrs, id : _, span : _, vis, kind : ItemKind :: Fn ( func) , tokens : _ } =
@@ -87,7 +87,7 @@ fn eii_(
8787 span : eii_attr_span,
8888 name : path_to_string ( & meta_item. path ) ,
8989 } ) ;
90- return vec ! [ wrap_item ( item) ] ;
90+ return vec ! [ Annotatable :: Item ( item) ] ;
9191 } ;
9292 // only clone what we need
9393 let attrs = attrs. clone ( ) ;
@@ -98,7 +98,9 @@ fn eii_(
9898 filter_attrs_for_multiple_eii_attr ( ecx, attrs, eii_attr_span, & meta_item. path ) ;
9999
100100 let Ok ( macro_name) = name_for_impl_macro ( ecx, & func, & meta_item) else {
101- return vec ! [ wrap_item( item) ] ;
101+ // we don't need to wrap in Annotatable::Stmt conditionally since
102+ // EII can't be used on items in statement position
103+ return vec ! [ Annotatable :: Item ( item) ] ;
102104 } ;
103105
104106 // span of the declaring item without attributes
@@ -136,7 +138,9 @@ fn eii_(
136138 & attrs_from_decl,
137139 ) ) ;
138140
139- module_items. into_iter ( ) . map ( wrap_item) . collect ( )
141+ // we don't need to wrap in Annotatable::Stmt conditionally since
142+ // EII can't be used on items in statement position
143+ module_items. into_iter ( ) . map ( Annotatable :: Item ) . collect ( )
140144}
141145
142146/// Decide on the name of the macro that can be used to implement the EII.
@@ -213,7 +217,8 @@ fn generate_default_impl(
213217 known_eii_macro_resolution : Some ( ast:: EiiDecl {
214218 foreign_item : ecx. path (
215219 foreign_item_name. span ,
216- // prefix super to explicitly escape the const block generated below
220+ // prefix self to explicitly escape the const block generated below
221+ // NOTE: this is why EIIs can't be used on statements
217222 vec ! [ Ident :: from_str_and_span( "self" , foreign_item_name. span) , foreign_item_name] ,
218223 ) ,
219224 impl_unsafe,
0 commit comments