Skip to content

Commit 792772a

Browse files
committed
Prohibit global_allocator in submodules for now
- we need to figure out hygiene first - change the test to check that the prohibition works with a good error msg - leaves some comments and debugging code - leaves some of our supposed fixes
1 parent 5da4ff8 commit 792772a

File tree

6 files changed

+91
-41
lines changed

6 files changed

+91
-41
lines changed

src/Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,6 +2035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
20352035
name = "rustc_allocator"
20362036
version = "0.0.0"
20372037
dependencies = [
2038+
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
20382039
"rustc 0.0.0",
20392040
"rustc_errors 0.0.0",
20402041
"rustc_target 0.0.0",

src/librustc_allocator/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ rustc_errors = { path = "../librustc_errors" }
1414
rustc_target = { path = "../librustc_target" }
1515
syntax = { path = "../libsyntax" }
1616
syntax_pos = { path = "../libsyntax_pos" }
17+
log = "0.4"

src/librustc_allocator/expand.rs

Lines changed: 79 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,30 @@
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-
1311
use rustc::middle::allocator::AllocatorKind;
1412
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;
3235

3336
use {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

5967
impl<'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"),

src/librustc_allocator/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#![feature(rustc_private)]
1212

13+
#[macro_use] extern crate log;
1314
extern crate rustc;
1415
extern crate rustc_errors;
1516
extern crate rustc_target;

src/test/ui/allocator-submodule.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ mod submod {
3131
use super::MyAlloc;
3232

3333
#[global_allocator]
34-
static MY_HEAP: MyAlloc = MyAlloc;
34+
static MY_HEAP: MyAlloc = MyAlloc; //~ ERROR global_allocator
3535
}
3636

3737
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: `global_allocator` cannot be used in submodules
2+
--> $DIR/allocator-submodule.rs:34:5
3+
|
4+
LL | static MY_HEAP: MyAlloc = MyAlloc; //~ ERROR global_allocator
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)