88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- #![ allow( unused_imports, unused_variables, dead_code) ]
12-
1311use rustc:: middle:: allocator:: AllocatorKind ;
1412use rustc_errors;
15- use syntax:: ast:: { Attribute , Crate , LitKind , StrStyle } ;
16- use syntax:: ast:: { Arg , FnHeader , Generics , Mac , Mutability , Ty , Unsafety } ;
17- use syntax:: ast:: { self , Expr , Ident , Item , ItemKind , TyKind , VisibilityKind } ;
18- use syntax:: attr;
19- use syntax:: codemap:: respan;
20- use syntax:: codemap:: { ExpnInfo , MacroAttribute } ;
21- use syntax:: ext:: base:: ExtCtxt ;
22- use syntax:: ext:: base:: Resolver ;
23- use syntax:: ext:: build:: AstBuilder ;
24- use syntax:: ext:: expand:: ExpansionConfig ;
25- use syntax:: ext:: hygiene:: { self , Mark , SyntaxContext } ;
26- use syntax:: fold:: { self , Folder } ;
27- use syntax:: parse:: ParseSess ;
28- use syntax:: ptr:: P ;
29- use syntax:: symbol:: Symbol ;
30- use syntax:: util:: small_vector:: SmallVector ;
31- use syntax_pos:: { Span , DUMMY_SP } ;
13+ use syntax:: {
14+ ast:: {
15+ self , Arg , Attribute , Crate , Expr , FnHeader , Generics , Ident , Item , ItemKind ,
16+ LitKind , Mod , Mutability , StrStyle , Ty , TyKind , Unsafety , VisibilityKind ,
17+ } ,
18+ attr,
19+ codemap:: {
20+ respan, ExpnInfo , MacroAttribute ,
21+ } ,
22+ ext:: {
23+ base:: { ExtCtxt , Resolver } ,
24+ build:: AstBuilder ,
25+ expand:: ExpansionConfig ,
26+ hygiene:: { self , Mark , SyntaxContext } ,
27+ } ,
28+ fold:: { self , Folder } ,
29+ parse:: ParseSess ,
30+ ptr:: P ,
31+ symbol:: Symbol ,
32+ util:: small_vector:: SmallVector ,
33+ } ;
34+ use syntax_pos:: Span ;
3235
3336use { AllocatorMethod , AllocatorTy , ALLOCATOR_METHODS } ;
3437
@@ -45,6 +48,7 @@ pub fn modify(
4548 resolver,
4649 found : false ,
4750 crate_name : Some ( crate_name) ,
51+ in_submod : -1 , // -1 to account for the "root" module
4852 } . fold_crate ( krate)
4953}
5054
@@ -54,10 +58,16 @@ struct ExpandAllocatorDirectives<'a> {
5458 sess : & ' a ParseSess ,
5559 resolver : & ' a mut Resolver ,
5660 crate_name : Option < String > ,
61+
62+ // For now, we disallow `global_allocator` in submodules because hygiene is hard. Keep track of
63+ // whether we are in a submodule or not. If `in_submod > 0` we are in a submodule.
64+ in_submod : isize ,
5765}
5866
5967impl < ' a > Folder for ExpandAllocatorDirectives < ' a > {
6068 fn fold_item ( & mut self , item : P < Item > ) -> SmallVector < P < Item > > {
69+ info ! ( "in submodule {}" , self . in_submod) ;
70+
6171 let name = if attr:: contains_name ( & item. attrs , "global_allocator" ) {
6272 "global_allocator"
6373 } else {
@@ -72,20 +82,23 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
7282 }
7383 }
7484
85+ if self . in_submod > 0 {
86+ self . handler
87+ . span_err ( item. span , "`global_allocator` cannot be used in submodules" ) ;
88+ return SmallVector :: one ( item) ;
89+ }
90+
7591 if self . found {
76- self . handler . span_err (
77- item. span ,
78- "cannot define more than one \
79- #[global_allocator]",
80- ) ;
92+ self . handler
93+ . span_err ( item. span , "cannot define more than one #[global_allocator]" ) ;
8194 return SmallVector :: one ( item) ;
8295 }
8396 self . found = true ;
8497
8598 // Create a fresh Mark for the new macro expansion we are about to do
8699 let mark = Mark :: fresh ( Mark :: root ( ) ) ;
87100 mark. set_expn_info ( ExpnInfo {
88- call_site : item. span ,
101+ call_site : item. span , // use the call site of the static
89102 def_site : None ,
90103 format : MacroAttribute ( Symbol :: intern ( name) ) ,
91104 allow_internal_unstable : true ,
@@ -104,27 +117,55 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
104117 span,
105118 kind : AllocatorKind :: Global ,
106119 global : item. ident ,
107- core : Ident :: with_empty_ctxt ( Symbol :: gensym ( "core" ) ) ,
120+ core : Ident :: from_str ( "core" ) ,
108121 cx : ExtCtxt :: new ( self . sess , ecfg, self . resolver ) ,
109122 } ;
110123
111- let extcore = {
112- let extcore = f. cx . item_extern_crate ( item. span , f. core ) ;
113- f. cx . monotonic_expander ( ) . fold_item ( extcore) . pop ( ) . unwrap ( )
114- } ;
124+ // We will generate a new submodule. To `use` the static from that module, we need to get
125+ // the `super::...` path.
126+ let super_path = f. cx . path ( f. span , vec ! [ Ident :: from_str( "super" ) , f. global] ) ;
127+
128+ // Generate the items in the submodule
129+ let mut items = vec ! [
130+ // import `core` to use allocators
131+ f. cx. item_extern_crate( f. span, f. core) ,
132+ // `use` the `global_allocator` in `super`
133+ f. cx. item_use_simple(
134+ f. span,
135+ respan( f. span. shrink_to_lo( ) , VisibilityKind :: Inherited ) ,
136+ super_path,
137+ ) ,
138+ ] ;
139+
140+ // Add the allocator methods to the submodule
141+ items. extend (
142+ ALLOCATOR_METHODS
143+ . iter ( )
144+ . map ( |method| f. allocator_fn ( method) ) ,
145+ ) ;
115146
116- let mut ret = SmallVector :: new ( ) ;
147+ // Generate the submodule itself
148+ let name = f. kind . fn_name ( "allocator_abi" ) ;
149+ let allocator_abi = Ident :: with_empty_ctxt ( Symbol :: gensym ( & name) ) ;
150+ let module = f. cx . item_mod ( span, span, allocator_abi, Vec :: new ( ) , items) ;
151+ let module = f. cx . monotonic_expander ( ) . fold_item ( module) . pop ( ) . unwrap ( ) ;
152+
153+ // Return the item and new submodule
154+ let mut ret = SmallVector :: with_capacity ( 2 ) ;
117155 ret. push ( item) ;
118- ret. push ( extcore) ;
119- ret. extend ( ALLOCATOR_METHODS . iter ( ) . map ( |method| {
120- let method = f. allocator_fn ( method) ;
121- f. cx . monotonic_expander ( ) . fold_item ( method) . pop ( ) . unwrap ( )
122- } ) ) ;
156+ ret. push ( module) ;
157+
123158 return ret;
124159 }
125160
126- fn fold_mac ( & mut self , mac : Mac ) -> Mac {
127- fold:: noop_fold_mac ( mac, self )
161+ // If we enter a submodule, take note.
162+ fn fold_mod ( & mut self , m : Mod ) -> Mod {
163+ info ! ( "enter submodule" ) ;
164+ self . in_submod += 1 ;
165+ let ret = fold:: noop_fold_mod ( m, self ) ;
166+ self . in_submod -= 1 ;
167+ info ! ( "exit submodule" ) ;
168+ ret
128169 }
129170}
130171
@@ -173,7 +214,6 @@ impl<'a> AllocFnFactory<'a> {
173214 let method = self . cx . path (
174215 self . span ,
175216 vec ! [
176- Ident :: from_str( "self" ) ,
177217 self . core,
178218 Ident :: from_str( "alloc" ) ,
179219 Ident :: from_str( "GlobalAlloc" ) ,
@@ -224,7 +264,6 @@ impl<'a> AllocFnFactory<'a> {
224264 let layout_new = self . cx . path (
225265 self . span ,
226266 vec ! [
227- Ident :: from_str( "self" ) ,
228267 self . core,
229268 Ident :: from_str( "alloc" ) ,
230269 Ident :: from_str( "Layout" ) ,
0 commit comments