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;
1513use rustc_target:: spec:: abi:: Abi ;
16- use syntax:: ast:: { Attribute , Crate , LitKind , StrStyle } ;
17- use syntax:: ast:: { Arg , Constness , Generics , Mac , Mutability , Ty , Unsafety } ;
18- use syntax:: ast:: { self , Expr , Ident , Item , ItemKind , TyKind , VisibilityKind } ;
19- use syntax:: attr;
20- use syntax:: codemap:: { dummy_spanned, respan} ;
21- use syntax:: codemap:: { ExpnInfo , MacroAttribute , NameAndSpan } ;
22- use syntax:: ext:: base:: ExtCtxt ;
23- use syntax:: ext:: base:: Resolver ;
24- use syntax:: ext:: build:: AstBuilder ;
25- use syntax:: ext:: expand:: ExpansionConfig ;
26- use syntax:: ext:: hygiene:: { self , Mark , SyntaxContext } ;
27- use syntax:: fold:: { self , Folder } ;
28- use syntax:: parse:: ParseSess ;
29- use syntax:: ptr:: P ;
30- use syntax:: symbol:: Symbol ;
31- use syntax:: util:: small_vector:: SmallVector ;
32- use syntax_pos:: { Span , DUMMY_SP } ;
14+ use syntax:: {
15+ ast:: {
16+ self , Arg , Attribute , Constness , Crate , Expr , Generics , Ident , Item , ItemKind ,
17+ LitKind , Mac , Mod , Mutability , StrStyle , Ty , TyKind , Unsafety , VisibilityKind ,
18+ } ,
19+ attr,
20+ codemap:: {
21+ dummy_spanned, respan, ExpnInfo , MacroAttribute , NameAndSpan ,
22+ } ,
23+ ext:: {
24+ base:: { ExtCtxt , Resolver } ,
25+ build:: AstBuilder ,
26+ expand:: ExpansionConfig ,
27+ hygiene:: { self , Mark , SyntaxContext } ,
28+ } ,
29+ fold:: { self , Folder } ,
30+ parse:: ParseSess ,
31+ ptr:: P ,
32+ symbol:: Symbol ,
33+ util:: small_vector:: SmallVector ,
34+ } ;
35+ use syntax_pos:: Span ;
3336
3437use { AllocatorMethod , AllocatorTy , ALLOCATOR_METHODS } ;
3538
@@ -46,6 +49,7 @@ pub fn modify(
4649 resolver,
4750 found : false ,
4851 crate_name : Some ( crate_name) ,
52+ in_submod : -1 , // -1 to account for the "root" module
4953 } . fold_crate ( krate)
5054}
5155
@@ -55,10 +59,16 @@ struct ExpandAllocatorDirectives<'a> {
5559 sess : & ' a ParseSess ,
5660 resolver : & ' a mut Resolver ,
5761 crate_name : Option < String > ,
62+
63+ // For now, we disallow `global_allocator` in submodules because hygiene is hard. Keep track of
64+ // whether we are in a submodule or not. If `in_submod > 0` we are in a submodule.
65+ in_submod : isize ,
5866}
5967
6068impl < ' a > Folder for ExpandAllocatorDirectives < ' a > {
6169 fn fold_item ( & mut self , item : P < Item > ) -> SmallVector < P < Item > > {
70+ info ! ( "in submodule {}" , self . in_submod) ;
71+
6272 let name = if attr:: contains_name ( & item. attrs , "global_allocator" ) {
6373 "global_allocator"
6474 } else {
@@ -73,20 +83,23 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
7383 }
7484 }
7585
86+ if self . in_submod > 0 {
87+ self . handler
88+ . span_err ( item. span , "`global_allocator` cannot be used in submodules" ) ;
89+ return SmallVector :: one ( item) ;
90+ }
91+
7692 if self . found {
77- self . handler . span_err (
78- item. span ,
79- "cannot define more than one \
80- #[global_allocator]",
81- ) ;
93+ self . handler
94+ . span_err ( item. span , "cannot define more than one #[global_allocator]" ) ;
8295 return SmallVector :: one ( item) ;
8396 }
8497 self . found = true ;
8598
8699 // Create a fresh Mark for the new macro expansion we are about to do
87100 let mark = Mark :: fresh ( Mark :: root ( ) ) ;
88101 mark. set_expn_info ( ExpnInfo {
89- call_site : item. span ,
102+ call_site : item. span , // use the call site of the static
90103 callee : NameAndSpan {
91104 format : MacroAttribute ( Symbol :: intern ( name) ) ,
92105 span : None ,
@@ -107,27 +120,55 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
107120 span,
108121 kind : AllocatorKind :: Global ,
109122 global : item. ident ,
110- core : Ident :: with_empty_ctxt ( Symbol :: gensym ( "core" ) ) ,
123+ core : Ident :: from_str ( "core" ) ,
111124 cx : ExtCtxt :: new ( self . sess , ecfg, self . resolver ) ,
112125 } ;
113126
114- let extcore = {
115- let extcore = f. cx . item_extern_crate ( item. span , f. core ) ;
116- f. cx . monotonic_expander ( ) . fold_item ( extcore) . pop ( ) . unwrap ( )
117- } ;
127+ // We will generate a new submodule. To `use` the static from that module, we need to get
128+ // the `super::...` path.
129+ let super_path = f. cx . path ( f. span , vec ! [ Ident :: from_str( "super" ) , f. global] ) ;
130+
131+ // Generate the items in the submodule
132+ let mut items = vec ! [
133+ // import `core` to use allocators
134+ f. cx. item_extern_crate( f. span, f. core) ,
135+ // `use` the `global_allocator` in `super`
136+ f. cx. item_use_simple(
137+ f. span,
138+ respan( f. span. shrink_to_lo( ) , VisibilityKind :: Inherited ) ,
139+ super_path,
140+ ) ,
141+ ] ;
142+
143+ // Add the allocator methods to the submodule
144+ items. extend (
145+ ALLOCATOR_METHODS
146+ . iter ( )
147+ . map ( |method| f. allocator_fn ( method) ) ,
148+ ) ;
118149
119- let mut ret = SmallVector :: new ( ) ;
150+ // Generate the submodule itself
151+ let name = f. kind . fn_name ( "allocator_abi" ) ;
152+ let allocator_abi = Ident :: with_empty_ctxt ( Symbol :: gensym ( & name) ) ;
153+ let module = f. cx . item_mod ( span, span, allocator_abi, Vec :: new ( ) , items) ;
154+ let module = f. cx . monotonic_expander ( ) . fold_item ( module) . pop ( ) . unwrap ( ) ;
155+
156+ // Return the item and new submodule
157+ let mut ret = SmallVector :: with_capacity ( 2 ) ;
120158 ret. push ( item) ;
121- ret. push ( extcore) ;
122- ret. extend ( ALLOCATOR_METHODS . iter ( ) . map ( |method| {
123- let method = f. allocator_fn ( method) ;
124- f. cx . monotonic_expander ( ) . fold_item ( method) . pop ( ) . unwrap ( )
125- } ) ) ;
159+ ret. push ( module) ;
160+
126161 return ret;
127162 }
128163
129- fn fold_mac ( & mut self , mac : Mac ) -> Mac {
130- fold:: noop_fold_mac ( mac, self )
164+ // If we enter a submodule, take note.
165+ fn fold_mod ( & mut self , m : Mod ) -> Mod {
166+ info ! ( "enter submodule" ) ;
167+ self . in_submod += 1 ;
168+ let ret = fold:: noop_fold_mod ( m, self ) ;
169+ self . in_submod -= 1 ;
170+ info ! ( "exit submodule" ) ;
171+ ret
131172 }
132173}
133174
@@ -175,7 +216,6 @@ impl<'a> AllocFnFactory<'a> {
175216 let method = self . cx . path (
176217 self . span ,
177218 vec ! [
178- Ident :: from_str( "self" ) ,
179219 self . core,
180220 Ident :: from_str( "alloc" ) ,
181221 Ident :: from_str( "GlobalAlloc" ) ,
@@ -226,7 +266,6 @@ impl<'a> AllocFnFactory<'a> {
226266 let layout_new = self . cx . path (
227267 self . span ,
228268 vec ! [
229- Ident :: from_str( "self" ) ,
230269 self . core,
231270 Ident :: from_str( "alloc" ) ,
232271 Ident :: from_str( "Layout" ) ,
0 commit comments