@@ -41,6 +41,7 @@ trait MacroGenerable: Sized {
4141
4242 // Fold this node or list of nodes using the given folder.
4343 fn fold_with < F : Folder > ( self , folder : & mut F ) -> Self ;
44+ fn visit_with < ' v , V : Visitor < ' v > > ( & ' v self , visitor : & mut V ) ;
4445
4546 // Return a placeholder expansion to allow compilation to continue after an erroring expansion.
4647 fn dummy ( span : Span ) -> Self ;
@@ -50,7 +51,9 @@ trait MacroGenerable: Sized {
5051}
5152
5253macro_rules! impl_macro_generable {
53- ( $( $ty: ty: $kind_name: expr, . $make: ident, $( . $fold: ident) * $( lift . $fold_elt: ident) * ,
54+ ( $( $ty: ty: $kind_name: expr, . $make: ident,
55+ $( . $fold: ident) * $( lift . $fold_elt: ident) * ,
56+ $( . $visit: ident) * $( lift . $visit_elt: ident) * ,
5457 |$span: ident| $dummy: expr; ) * ) => { $(
5558 impl MacroGenerable for $ty {
5659 fn kind_name( ) -> & ' static str { $kind_name }
@@ -59,21 +62,27 @@ macro_rules! impl_macro_generable {
5962 $( folder. $fold( self ) ) *
6063 $( self . into_iter( ) . flat_map( |item| folder. $fold_elt ( item) ) . collect( ) ) *
6164 }
65+ fn visit_with<' v, V : Visitor <' v>>( & ' v self , visitor: & mut V ) {
66+ $( visitor. $visit( self ) ) *
67+ $( for item in self . as_slice( ) { visitor. $visit_elt ( item) } ) *
68+ }
6269 fn dummy( $span: Span ) -> Self { $dummy }
6370 }
6471 ) * }
6572}
6673
6774impl_macro_generable ! {
68- P <ast:: Expr >: "expression" , . make_expr, . fold_expr, |span| DummyResult :: raw_expr( span) ;
69- P <ast:: Pat >: "pattern" , . make_pat, . fold_pat, |span| P ( DummyResult :: raw_pat( span) ) ;
70- P <ast:: Ty >: "type" , . make_ty, . fold_ty, |span| DummyResult :: raw_ty( span) ;
71- SmallVector <ast:: ImplItem >:
72- "impl item" , . make_impl_items, lift . fold_impl_item, |_span| SmallVector :: zero( ) ;
73- SmallVector <P <ast:: Item >>:
74- "item" , . make_items, lift . fold_item, |_span| SmallVector :: zero( ) ;
75+ P <ast:: Pat >: "pattern" , . make_pat, . fold_pat, . visit_pat, |span| P ( DummyResult :: raw_pat( span) ) ;
76+ P <ast:: Ty >: "type" , . make_ty, . fold_ty, . visit_ty, |span| DummyResult :: raw_ty( span) ;
77+ P <ast:: Expr >:
78+ "expression" , . make_expr, . fold_expr, . visit_expr, |span| DummyResult :: raw_expr( span) ;
7579 SmallVector <ast:: Stmt >:
76- "statement" , . make_stmts, lift . fold_stmt, |_span| SmallVector :: zero( ) ;
80+ "statement" , . make_stmts, lift . fold_stmt, lift . visit_stmt, |_span| SmallVector :: zero( ) ;
81+ SmallVector <P <ast:: Item >>:
82+ "item" , . make_items, lift . fold_item, lift . visit_item, |_span| SmallVector :: zero( ) ;
83+ SmallVector <ast:: ImplItem >:
84+ "impl item" , . make_impl_items, lift . fold_impl_item, lift . visit_impl_item,
85+ |_span| SmallVector :: zero( ) ;
7786}
7887
7988impl MacroGenerable for Option < P < ast:: Expr > > {
@@ -85,6 +94,9 @@ impl MacroGenerable for Option<P<ast::Expr>> {
8594 fn fold_with < F : Folder > ( self , folder : & mut F ) -> Self {
8695 self . and_then ( |expr| folder. fold_opt_expr ( expr) )
8796 }
97+ fn visit_with < ' v , V : Visitor < ' v > > ( & ' v self , visitor : & mut V ) {
98+ self . as_ref ( ) . map ( |expr| visitor. visit_expr ( expr) ) ;
99+ }
88100}
89101
90102pub fn expand_expr ( expr : ast:: Expr , fld : & mut MacroExpander ) -> P < ast:: Expr > {
@@ -320,6 +332,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr
320332
321333 let marked = expanded. fold_with ( & mut Marker { mark : mark, expn_id : Some ( fld. cx . backtrace ( ) ) } ) ;
322334 let configured = marked. fold_with ( & mut fld. strip_unconfigured ( ) ) ;
335+ fld. load_macros ( & configured) ;
323336 let fully_expanded = configured. fold_with ( fld) ;
324337 fld. cx . bt_pop ( ) ;
325338 fully_expanded
@@ -742,15 +755,6 @@ fn expand_annotatable(a: Annotatable,
742755 }
743756 result
744757 } ,
745- ast:: ItemKind :: ExternCrate ( _) => {
746- // We need to error on `#[macro_use] extern crate` when it isn't at the
747- // crate root, because `$crate` won't work properly.
748- let allows_macros = fld. cx . syntax_env . is_crate_root ( ) ;
749- for def in fld. cx . loader . load_crate ( & it, allows_macros) {
750- fld. cx . insert_macro ( def) ;
751- }
752- SmallVector :: one ( it)
753- } ,
754758 _ => noop_fold_item ( it, fld) ,
755759 } . into_iter ( ) . map ( |i| Annotatable :: Item ( i) ) . collect ( ) ,
756760
@@ -999,6 +1003,40 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
9991003 & self . cx . parse_sess . span_diagnostic ,
10001004 self . cx . feature_gated_cfgs )
10011005 }
1006+
1007+ fn load_macros < T : MacroGenerable > ( & mut self , node : & T ) {
1008+ struct MacroLoadingVisitor < ' a , ' b : ' a > {
1009+ cx : & ' a mut ExtCtxt < ' b > ,
1010+ at_crate_root : bool ,
1011+ }
1012+
1013+ impl < ' a , ' b , ' v > Visitor < ' v > for MacroLoadingVisitor < ' a , ' b > {
1014+ fn visit_mac ( & mut self , _: & ' v ast:: Mac ) { }
1015+ fn visit_item ( & mut self , item : & ' v ast:: Item ) {
1016+ if let ast:: ItemKind :: ExternCrate ( ..) = item. node {
1017+ // We need to error on `#[macro_use] extern crate` when it isn't at the
1018+ // crate root, because `$crate` won't work properly.
1019+ for def in self . cx . loader . load_crate ( item, self . at_crate_root ) {
1020+ self . cx . insert_macro ( def) ;
1021+ }
1022+ } else {
1023+ let at_crate_root = :: std:: mem:: replace ( & mut self . at_crate_root , false ) ;
1024+ visit:: walk_item ( self , item) ;
1025+ self . at_crate_root = at_crate_root;
1026+ }
1027+ }
1028+ fn visit_block ( & mut self , block : & ' v ast:: Block ) {
1029+ let at_crate_root = :: std:: mem:: replace ( & mut self . at_crate_root , false ) ;
1030+ visit:: walk_block ( self , block) ;
1031+ self . at_crate_root = at_crate_root;
1032+ }
1033+ }
1034+
1035+ node. visit_with ( & mut MacroLoadingVisitor {
1036+ at_crate_root : self . cx . syntax_env . is_crate_root ( ) ,
1037+ cx : self . cx ,
1038+ } ) ;
1039+ }
10021040}
10031041
10041042impl < ' a , ' b > Folder for MacroExpander < ' a , ' b > {
@@ -1142,7 +1180,7 @@ impl<'feat> ExpansionConfig<'feat> {
11421180
11431181pub fn expand_crate ( mut cx : ExtCtxt ,
11441182 user_exts : Vec < NamedSyntaxExtension > ,
1145- c : Crate ) -> ( Crate , HashSet < Name > ) {
1183+ mut c : Crate ) -> ( Crate , HashSet < Name > ) {
11461184 if std_inject:: no_core ( & c) {
11471185 cx. crate_root = None ;
11481186 } else if std_inject:: no_std ( & c) {
@@ -1157,6 +1195,10 @@ pub fn expand_crate(mut cx: ExtCtxt,
11571195 expander. cx . syntax_env . insert ( name, extension) ;
11581196 }
11591197
1198+ let items = SmallVector :: many ( c. module . items ) ;
1199+ expander. load_macros ( & items) ;
1200+ c. module . items = items. into ( ) ;
1201+
11601202 let err_count = cx. parse_sess . span_diagnostic . err_count ( ) ;
11611203 let mut ret = expander. fold_crate ( c) ;
11621204 ret. exported_macros = expander. cx . exported_macros . clone ( ) ;
0 commit comments