Skip to content

Commit 5da4ff8

Browse files
committed
Attempt to fix hygiene for global_allocator
1 parent 01cc982 commit 5da4ff8

File tree

3 files changed

+74
-21
lines changed

3 files changed

+74
-21
lines changed

src/librustc_allocator/expand.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
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+
1113
use rustc::middle::allocator::AllocatorKind;
1214
use rustc_errors;
1315
use syntax::ast::{Attribute, Crate, LitKind, StrStyle};
@@ -34,13 +36,15 @@ pub fn modify(
3436
sess: &ParseSess,
3537
resolver: &mut Resolver,
3638
krate: Crate,
39+
crate_name: String,
3740
handler: &rustc_errors::Handler,
3841
) -> ast::Crate {
3942
ExpandAllocatorDirectives {
4043
handler,
4144
sess,
4245
resolver,
4346
found: false,
47+
crate_name: Some(crate_name),
4448
}.fold_crate(krate)
4549
}
4650

@@ -49,6 +53,7 @@ struct ExpandAllocatorDirectives<'a> {
4953
handler: &'a rustc_errors::Handler,
5054
sess: &'a ParseSess,
5155
resolver: &'a mut Resolver,
56+
crate_name: Option<String>,
5257
}
5358

5459
impl<'a> Folder for ExpandAllocatorDirectives<'a> {
@@ -77,44 +82,44 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
7782
}
7883
self.found = true;
7984

85+
// Create a fresh Mark for the new macro expansion we are about to do
8086
let mark = Mark::fresh(Mark::root());
8187
mark.set_expn_info(ExpnInfo {
82-
call_site: DUMMY_SP,
88+
call_site: item.span,
8389
def_site: None,
8490
format: MacroAttribute(Symbol::intern(name)),
8591
allow_internal_unstable: true,
8692
allow_internal_unsafe: false,
8793
edition: hygiene::default_edition(),
8894
});
95+
96+
// Tie the span to the macro expansion info we just created
8997
let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
90-
let ecfg = ExpansionConfig::default(name.to_string());
98+
99+
// Create an expansion config
100+
let ecfg = ExpansionConfig::default(self.crate_name.take().unwrap());
101+
102+
// Generate a bunch of new items using the AllocFnFactory
91103
let mut f = AllocFnFactory {
92104
span,
93105
kind: AllocatorKind::Global,
94106
global: item.ident,
95-
core: Ident::from_str("core"),
107+
core: Ident::with_empty_ctxt(Symbol::gensym("core")),
96108
cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
97109
};
98-
let super_path = f.cx.path(f.span, vec![Ident::from_str("super"), f.global]);
99-
let mut items = vec![
100-
f.cx.item_extern_crate(f.span, f.core),
101-
f.cx.item_use_simple(
102-
f.span,
103-
respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
104-
super_path,
105-
),
106-
];
107-
for method in ALLOCATOR_METHODS {
108-
items.push(f.allocator_fn(method));
109-
}
110-
let name = f.kind.fn_name("allocator_abi");
111-
let allocator_abi = Ident::with_empty_ctxt(Symbol::gensym(&name));
112-
let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items);
113-
let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap();
110+
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+
};
114115

115116
let mut ret = SmallVector::new();
116117
ret.push(item);
117-
ret.push(module);
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+
}));
118123
return ret;
119124
}
120125

@@ -168,6 +173,7 @@ impl<'a> AllocFnFactory<'a> {
168173
let method = self.cx.path(
169174
self.span,
170175
vec![
176+
Ident::from_str("self"),
171177
self.core,
172178
Ident::from_str("alloc"),
173179
Ident::from_str("GlobalAlloc"),
@@ -218,6 +224,7 @@ impl<'a> AllocFnFactory<'a> {
218224
let layout_new = self.cx.path(
219225
self.span,
220226
vec![
227+
Ident::from_str("self"),
221228
self.core,
222229
Ident::from_str("alloc"),
223230
Ident::from_str("Layout"),

src/librustc_driver/driver.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1051,10 +1051,19 @@ where
10511051
});
10521052
}
10531053

1054+
// Expand global allocators, which are treated as an in-tree proc macro
10541055
krate = time(sess, "creating allocators", || {
1055-
allocator::expand::modify(&sess.parse_sess, &mut resolver, krate, sess.diagnostic())
1056+
allocator::expand::modify(
1057+
&sess.parse_sess,
1058+
&mut resolver,
1059+
krate,
1060+
crate_name.to_string(),
1061+
sess.diagnostic(),
1062+
)
10561063
});
10571064

1065+
// Done with macro expansion!
1066+
10581067
after_expand(&krate)?;
10591068

10601069
if sess.opts.debugging_opts.input_stats {

src/test/ui/allocator-submodule.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Tests that it is possible to create a global allocator in a submodule, rather than in the crate
12+
// root.
13+
14+
#![feature(alloc, allocator_api, global_allocator)]
15+
16+
extern crate alloc;
17+
18+
use std::alloc::{GlobalAlloc, Layout, Opaque};
19+
20+
struct MyAlloc;
21+
22+
unsafe impl GlobalAlloc for MyAlloc {
23+
unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
24+
0 as usize as *mut Opaque
25+
}
26+
27+
unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {}
28+
}
29+
30+
mod submod {
31+
use super::MyAlloc;
32+
33+
#[global_allocator]
34+
static MY_HEAP: MyAlloc = MyAlloc;
35+
}
36+
37+
fn main() {}

0 commit comments

Comments
 (0)