Skip to content

Commit 9e65155

Browse files
mark-i-mpietroalbini
authored andcommitted
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 103a4d8 commit 9e65155

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,28 +8,31 @@
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;
1513
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;
3336

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

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

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)