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
13
use 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 ;
33
36
34
37
use { AllocatorMethod , AllocatorTy , ALLOCATOR_METHODS } ;
35
38
@@ -46,6 +49,7 @@ pub fn modify(
46
49
resolver,
47
50
found : false ,
48
51
crate_name : Some ( crate_name) ,
52
+ in_submod : -1 , // -1 to account for the "root" module
49
53
} . fold_crate ( krate)
50
54
}
51
55
@@ -55,10 +59,16 @@ struct ExpandAllocatorDirectives<'a> {
55
59
sess : & ' a ParseSess ,
56
60
resolver : & ' a mut Resolver ,
57
61
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 ,
58
66
}
59
67
60
68
impl < ' a > Folder for ExpandAllocatorDirectives < ' a > {
61
69
fn fold_item ( & mut self , item : P < Item > ) -> SmallVector < P < Item > > {
70
+ info ! ( "in submodule {}" , self . in_submod) ;
71
+
62
72
let name = if attr:: contains_name ( & item. attrs , "global_allocator" ) {
63
73
"global_allocator"
64
74
} else {
@@ -73,20 +83,23 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
73
83
}
74
84
}
75
85
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
+
76
92
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]" ) ;
82
95
return SmallVector :: one ( item) ;
83
96
}
84
97
self . found = true ;
85
98
86
99
// Create a fresh Mark for the new macro expansion we are about to do
87
100
let mark = Mark :: fresh ( Mark :: root ( ) ) ;
88
101
mark. set_expn_info ( ExpnInfo {
89
- call_site : item. span ,
102
+ call_site : item. span , // use the call site of the static
90
103
callee : NameAndSpan {
91
104
format : MacroAttribute ( Symbol :: intern ( name) ) ,
92
105
span : None ,
@@ -107,27 +120,55 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
107
120
span,
108
121
kind : AllocatorKind :: Global ,
109
122
global : item. ident ,
110
- core : Ident :: with_empty_ctxt ( Symbol :: gensym ( "core" ) ) ,
123
+ core : Ident :: from_str ( "core" ) ,
111
124
cx : ExtCtxt :: new ( self . sess , ecfg, self . resolver ) ,
112
125
} ;
113
126
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
+ ) ;
118
149
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 ) ;
120
158
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
+
126
161
return ret;
127
162
}
128
163
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
131
172
}
132
173
}
133
174
@@ -175,7 +216,6 @@ impl<'a> AllocFnFactory<'a> {
175
216
let method = self . cx . path (
176
217
self . span ,
177
218
vec ! [
178
- Ident :: from_str( "self" ) ,
179
219
self . core,
180
220
Ident :: from_str( "alloc" ) ,
181
221
Ident :: from_str( "GlobalAlloc" ) ,
@@ -226,7 +266,6 @@ impl<'a> AllocFnFactory<'a> {
226
266
let layout_new = self . cx . path (
227
267
self . span ,
228
268
vec ! [
229
- Ident :: from_str( "self" ) ,
230
269
self . core,
231
270
Ident :: from_str( "alloc" ) ,
232
271
Ident :: from_str( "Layout" ) ,
0 commit comments