8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- #![ allow( unused_imports, unused_variables, dead_code) ]
12
-
13
11
use rustc:: middle:: allocator:: AllocatorKind ;
14
12
use 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 ;
32
35
33
36
use { AllocatorMethod , AllocatorTy , ALLOCATOR_METHODS } ;
34
37
@@ -45,6 +48,7 @@ pub fn modify(
45
48
resolver,
46
49
found : false ,
47
50
crate_name : Some ( crate_name) ,
51
+ in_submod : -1 , // -1 to account for the "root" module
48
52
} . fold_crate ( krate)
49
53
}
50
54
@@ -54,10 +58,16 @@ struct ExpandAllocatorDirectives<'a> {
54
58
sess : & ' a ParseSess ,
55
59
resolver : & ' a mut Resolver ,
56
60
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 ,
57
65
}
58
66
59
67
impl < ' a > Folder for ExpandAllocatorDirectives < ' a > {
60
68
fn fold_item ( & mut self , item : P < Item > ) -> SmallVector < P < Item > > {
69
+ info ! ( "in submodule {}" , self . in_submod) ;
70
+
61
71
let name = if attr:: contains_name ( & item. attrs , "global_allocator" ) {
62
72
"global_allocator"
63
73
} else {
@@ -72,20 +82,23 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
72
82
}
73
83
}
74
84
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
+
75
91
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]" ) ;
81
94
return SmallVector :: one ( item) ;
82
95
}
83
96
self . found = true ;
84
97
85
98
// Create a fresh Mark for the new macro expansion we are about to do
86
99
let mark = Mark :: fresh ( Mark :: root ( ) ) ;
87
100
mark. set_expn_info ( ExpnInfo {
88
- call_site : item. span ,
101
+ call_site : item. span , // use the call site of the static
89
102
def_site : None ,
90
103
format : MacroAttribute ( Symbol :: intern ( name) ) ,
91
104
allow_internal_unstable : true ,
@@ -104,27 +117,55 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
104
117
span,
105
118
kind : AllocatorKind :: Global ,
106
119
global : item. ident ,
107
- core : Ident :: with_empty_ctxt ( Symbol :: gensym ( "core" ) ) ,
120
+ core : Ident :: from_str ( "core" ) ,
108
121
cx : ExtCtxt :: new ( self . sess , ecfg, self . resolver ) ,
109
122
} ;
110
123
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
+ ) ;
115
146
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 ) ;
117
155
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
+
123
158
return ret;
124
159
}
125
160
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
128
169
}
129
170
}
130
171
@@ -173,7 +214,6 @@ impl<'a> AllocFnFactory<'a> {
173
214
let method = self . cx . path (
174
215
self . span ,
175
216
vec ! [
176
- Ident :: from_str( "self" ) ,
177
217
self . core,
178
218
Ident :: from_str( "alloc" ) ,
179
219
Ident :: from_str( "GlobalAlloc" ) ,
@@ -224,7 +264,6 @@ impl<'a> AllocFnFactory<'a> {
224
264
let layout_new = self . cx . path (
225
265
self . span ,
226
266
vec ! [
227
- Ident :: from_str( "self" ) ,
228
267
self . core,
229
268
Ident :: from_str( "alloc" ) ,
230
269
Ident :: from_str( "Layout" ) ,
0 commit comments