Skip to content

Commit 3dfbc88

Browse files
committed
Auto merge of #46550 - jseyfried:cleanup_builtin_hygiene, r=nrc
macros: hygienize use of `core`/`std` in builtin macros Today, if a builtin macro wants to access an item from `core` or `std` (depending `#![no_std]`), it generates `::core::path::to::item` or `::std::path::to::item` respectively (c.f. `fn std_path()` in `libsyntax/ext/base.rs`). This PR refactors the builtin macros to instead always emit `$crate::path::to::item` here. That is, the def site of builtin macros is taken to be in `extern crate core;` or `extern crate std;`. Since builtin macros are macros 1.0 (i.e. mostly unhygienic), changing the def site can only effect the resolution of `$crate`. r? @nrc
2 parents 6110084 + 85d19b3 commit 3dfbc88

30 files changed

+174
-140
lines changed

src/librustc/hir/lowering.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ pub fn lower_crate(sess: &Session,
175175
let _ignore = dep_graph.in_ignore();
176176

177177
LoweringContext {
178-
crate_root: std_inject::injected_crate_name(krate),
178+
crate_root: std_inject::injected_crate_name(),
179179
sess,
180180
cstore,
181181
parent_def: None,

src/librustc_resolve/build_reduced_graph.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use syntax::ext::base::Determinacy::Undetermined;
4040
use syntax::ext::hygiene::Mark;
4141
use syntax::ext::tt::macro_rules;
4242
use syntax::parse::token::{self, Token};
43+
use syntax::std_inject::injected_crate_name;
4344
use syntax::symbol::keywords;
4445
use syntax::symbol::Symbol;
4546
use syntax::visit::{self, Visitor};
@@ -262,6 +263,10 @@ impl<'a> Resolver<'a> {
262263
let module =
263264
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
264265
self.populate_module_if_necessary(module);
266+
if injected_crate_name().map_or(false, |name| item.ident.name == name) {
267+
self.injected_crate = Some(module);
268+
}
269+
265270
let used = self.process_legacy_macro_imports(item, module, expansion);
266271
let binding =
267272
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
@@ -558,8 +563,7 @@ impl<'a> Resolver<'a> {
558563
if let Some(id) = self.definitions.as_local_node_id(def_id) {
559564
self.local_macro_def_scopes[&id]
560565
} else if def_id.krate == BUILTIN_MACROS_CRATE {
561-
// FIXME(jseyfried): This happens when `include!()`ing a `$crate::` path, c.f, #40469.
562-
self.graph_root
566+
self.injected_crate.unwrap_or(self.graph_root)
563567
} else {
564568
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
565569
self.get_module(module_def_id)

src/librustc_resolve/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,8 @@ pub struct Resolver<'a> {
13381338

13391339
// Only used for better errors on `fn(): fn()`
13401340
current_type_ascription: Vec<Span>,
1341+
1342+
injected_crate: Option<Module<'a>>,
13411343
}
13421344

13431345
pub struct ResolverArenas<'a> {
@@ -1537,6 +1539,7 @@ impl<'a> Resolver<'a> {
15371539
found_unresolved_macro: false,
15381540
unused_macros: FxHashSet(),
15391541
current_type_ascription: Vec::new(),
1542+
injected_crate: None,
15401543
}
15411544
}
15421545

src/librustc_resolve/macros.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use syntax::errors::DiagnosticBuilder;
2525
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
2626
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
2727
use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
28-
use syntax::ext::hygiene::Mark;
28+
use syntax::ext::hygiene::{Mark, MarkKind};
2929
use syntax::ext::placeholders::placeholder;
3030
use syntax::ext::tt::macro_rules;
3131
use syntax::feature_gate::{self, emit_feature_err, GateIssue};
@@ -297,16 +297,19 @@ impl<'a> base::Resolver for Resolver<'a> {
297297
InvocationKind::Attr { attr: None, .. } => return Ok(None),
298298
_ => self.resolve_invoc_to_def(invoc, scope, force)?,
299299
};
300+
let def_id = def.def_id();
300301

301-
self.macro_defs.insert(invoc.expansion_data.mark, def.def_id());
302+
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
302303
let normal_module_def_id =
303304
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
304305
self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id);
305306

306-
self.unused_macros.remove(&def.def_id());
307+
self.unused_macros.remove(&def_id);
307308
let ext = self.get_macro(def);
308309
if ext.is_modern() {
309-
invoc.expansion_data.mark.set_modern();
310+
invoc.expansion_data.mark.set_kind(MarkKind::Modern);
311+
} else if def_id.krate == BUILTIN_MACROS_CRATE {
312+
invoc.expansion_data.mark.set_kind(MarkKind::Builtin);
310313
}
311314
Ok(Some(ext))
312315
}

src/libsyntax/ext/base.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ use fold::{self, Folder};
2121
use parse::{self, parser, DirectoryOwnership};
2222
use parse::token;
2323
use ptr::P;
24-
use symbol::Symbol;
24+
use symbol::{keywords, Ident, Symbol};
2525
use util::small_vector::SmallVector;
2626

2727
use std::collections::HashMap;
28+
use std::iter;
2829
use std::path::PathBuf;
2930
use std::rc::Rc;
3031
use std::default::Default;
@@ -664,7 +665,6 @@ pub struct ExpansionData {
664665
pub struct ExtCtxt<'a> {
665666
pub parse_sess: &'a parse::ParseSess,
666667
pub ecfg: expand::ExpansionConfig<'a>,
667-
pub crate_root: Option<&'static str>,
668668
pub root_path: PathBuf,
669669
pub resolver: &'a mut Resolver,
670670
pub resolve_err_count: usize,
@@ -680,7 +680,6 @@ impl<'a> ExtCtxt<'a> {
680680
ExtCtxt {
681681
parse_sess,
682682
ecfg,
683-
crate_root: None,
684683
root_path: PathBuf::new(),
685684
resolver,
686685
resolve_err_count: 0,
@@ -822,12 +821,10 @@ impl<'a> ExtCtxt<'a> {
822821
ast::Ident::from_str(st)
823822
}
824823
pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
825-
let mut v = Vec::new();
826-
if let Some(s) = self.crate_root {
827-
v.push(self.ident_of(s));
828-
}
829-
v.extend(components.iter().map(|s| self.ident_of(s)));
830-
v
824+
let def_site = SyntaxContext::empty().apply_mark(self.current_expansion.mark);
825+
iter::once(Ident { ctxt: def_site, ..keywords::DollarCrate.ident() })
826+
.chain(components.iter().map(|s| self.ident_of(s)))
827+
.collect()
831828
}
832829
pub fn name_of(&self, st: &str) -> ast::Name {
833830
Symbol::intern(st)

src/libsyntax/ext/build.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
319319
types: Vec<P<ast::Ty>>,
320320
bindings: Vec<ast::TypeBinding> )
321321
-> ast::Path {
322+
use syntax::parse::token;
323+
322324
let last_identifier = idents.pop().unwrap();
323325
let mut segments: Vec<ast::PathSegment> = Vec::new();
324-
if global {
326+
if global &&
327+
!idents.first().map_or(false, |&ident| token::Ident(ident).is_path_segment_keyword()) {
325328
segments.push(ast::PathSegment::crate_root(span));
326329
}
327330

src/libsyntax/ext/expand.rs

-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use parse::{DirectoryOwnership, PResult};
2525
use parse::token::{self, Token};
2626
use parse::parser::Parser;
2727
use ptr::P;
28-
use std_inject;
2928
use symbol::Symbol;
3029
use symbol::keywords;
3130
use syntax_pos::{Span, DUMMY_SP};
@@ -219,7 +218,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
219218
}
220219

221220
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
222-
self.cx.crate_root = std_inject::injected_crate_name(&krate);
223221
let mut module = ModuleData {
224222
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
225223
directory: self.cx.codemap().span_to_unmapped_path(krate.span),

src/libsyntax/print/pprust.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use util::parser::{self, AssocOp, Fixity};
1818
use attr;
1919
use codemap::{self, CodeMap};
2020
use syntax_pos::{self, BytePos};
21+
use syntax_pos::hygiene::{Mark, MarkKind, SyntaxContext};
2122
use parse::token::{self, BinOpToken, Token};
2223
use parse::lexer::comments;
2324
use parse::{self, ParseSess};
@@ -93,7 +94,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
9394
is_expanded: bool) -> io::Result<()> {
9495
let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded);
9596

96-
if is_expanded && !std_inject::injected_crate_name(krate).is_none() {
97+
if is_expanded && !std_inject::injected_crate_name().is_none() {
9798
// We need to print `#![no_std]` (and its feature gate) so that
9899
// compiling pretty-printed source won't inject libstd again.
99100
// However we don't want these attributes in the AST because
@@ -734,6 +735,8 @@ pub trait PrintState<'a> {
734735
if segment.identifier.name != keywords::CrateRoot.name() &&
735736
segment.identifier.name != keywords::DollarCrate.name() {
736737
self.writer().word(&segment.identifier.name.as_str())?;
738+
} else if segment.identifier.name == keywords::DollarCrate.name() {
739+
self.print_dollar_crate(segment.identifier.ctxt)?;
737740
}
738741
}
739742
self.writer().space()?;
@@ -822,6 +825,19 @@ pub trait PrintState<'a> {
822825
}
823826

824827
fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") }
828+
829+
fn print_dollar_crate(&mut self, mut ctxt: SyntaxContext) -> io::Result<()> {
830+
if let Some(mark) = ctxt.adjust(Mark::root()) {
831+
// Make a best effort to print something that complies
832+
if mark.kind() == MarkKind::Builtin {
833+
if let Some(name) = std_inject::injected_crate_name() {
834+
self.writer().word("::")?;
835+
self.writer().word(name)?;
836+
}
837+
}
838+
}
839+
Ok(())
840+
}
825841
}
826842

827843
impl<'a> PrintState<'a> for State<'a> {
@@ -2411,6 +2427,8 @@ impl<'a> State<'a> {
24112427
if let Some(ref parameters) = segment.parameters {
24122428
self.print_path_parameters(parameters, colons_before_params)?;
24132429
}
2430+
} else if segment.identifier.name == keywords::DollarCrate.name() {
2431+
self.print_dollar_crate(segment.identifier.ctxt)?;
24142432
}
24152433
Ok(())
24162434
}

src/libsyntax/std_inject.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use ast;
1212
use attr;
13+
use std::cell::Cell;
1314
use ext::hygiene::{Mark, SyntaxContext};
1415
use symbol::{Symbol, keywords};
1516
use syntax_pos::{DUMMY_SP, Span};
@@ -34,22 +35,25 @@ fn ignored_span(sp: Span) -> Span {
3435
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
3536
}
3637

37-
pub fn injected_crate_name(krate: &ast::Crate) -> Option<&'static str> {
38-
if attr::contains_name(&krate.attrs, "no_core") {
39-
None
40-
} else if attr::contains_name(&krate.attrs, "no_std") {
41-
Some("core")
42-
} else {
43-
Some("std")
44-
}
38+
pub fn injected_crate_name() -> Option<&'static str> {
39+
INJECTED_CRATE_NAME.with(|name| name.get())
40+
}
41+
42+
thread_local! {
43+
static INJECTED_CRATE_NAME: Cell<Option<&'static str>> = Cell::new(None);
4544
}
4645

4746
pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<String>) -> ast::Crate {
48-
let name = match injected_crate_name(&krate) {
49-
Some(name) => name,
50-
None => return krate,
47+
let name = if attr::contains_name(&krate.attrs, "no_core") {
48+
return krate;
49+
} else if attr::contains_name(&krate.attrs, "no_std") {
50+
"core"
51+
} else {
52+
"std"
5153
};
5254

55+
INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
56+
5357
let crate_name = Symbol::intern(&alt_std_name.unwrap_or_else(|| name.to_string()));
5458

5559
krate.module.items.insert(0, P(ast::Item {

src/libsyntax/test.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ fn generate_test_harness(sess: &ParseSess,
272272

273273
let mark = Mark::fresh(Mark::root());
274274

275-
let mut cx: TestCtxt = TestCtxt {
275+
let cx = TestCtxt {
276276
span_diagnostic: sd,
277277
ext_cx: ExtCtxt::new(sess, ExpansionConfig::default("test".to_string()), resolver),
278278
path: Vec::new(),
@@ -283,7 +283,6 @@ fn generate_test_harness(sess: &ParseSess,
283283
toplevel_reexport: None,
284284
ctxt: SyntaxContext::empty().apply_mark(mark),
285285
};
286-
cx.ext_cx.crate_root = Some("std");
287286

288287
mark.set_expn_info(ExpnInfo {
289288
call_site: DUMMY_SP,

src/libsyntax_ext/deriving/bounds.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use deriving::path_std;
1112
use deriving::generic::*;
1213
use deriving::generic::ty::*;
13-
1414
use syntax::ast::MetaItem;
1515
use syntax::ext::base::{Annotatable, ExtCtxt};
1616
use syntax_pos::Span;
@@ -28,15 +28,10 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt,
2828
mitem: &MetaItem,
2929
item: &Annotatable,
3030
push: &mut FnMut(Annotatable)) {
31-
let mut v = cx.crate_root.map(|s| vec![s]).unwrap_or(Vec::new());
32-
v.push("marker");
33-
v.push("Copy");
34-
let path = Path::new(v);
35-
3631
let trait_def = TraitDef {
3732
span,
3833
attributes: Vec::new(),
39-
path,
34+
path: path_std!(cx, marker::Copy),
4035
additional_bounds: Vec::new(),
4136
generics: LifetimeBounds::empty(),
4237
is_unsafe: false,

src/libsyntax_ext/deriving/clone.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use deriving::path_std;
1112
use deriving::generic::*;
1213
use deriving::generic::ty::*;
1314

@@ -55,7 +56,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
5556
}));
5657
}
5758
ItemKind::Union(..) => {
58-
bounds = vec![Literal(path_std!(cx, core::marker::Copy))];
59+
bounds = vec![Literal(path_std!(cx, marker::Copy))];
5960
is_shallow = true;
6061
substructure = combine_substructure(Box::new(|c, s, sub| {
6162
cs_clone_shallow("Clone", c, s, sub, true)
@@ -79,7 +80,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
7980
let trait_def = TraitDef {
8081
span,
8182
attributes: Vec::new(),
82-
path: path_std!(cx, core::clone::Clone),
83+
path: path_std!(cx, clone::Clone),
8384
additional_bounds: bounds,
8485
generics: LifetimeBounds::empty(),
8586
is_unsafe: false,

src/libsyntax_ext/deriving/cmp/eq.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use deriving::path_std;
1112
use deriving::generic::*;
1213
use deriving::generic::ty::*;
1314

@@ -30,7 +31,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
3031
let trait_def = TraitDef {
3132
span,
3233
attributes: Vec::new(),
33-
path: path_std!(cx, core::cmp::Eq),
34+
path: path_std!(cx, cmp::Eq),
3435
additional_bounds: Vec::new(),
3536
generics: LifetimeBounds::empty(),
3637
is_unsafe: false,

src/libsyntax_ext/deriving/cmp/ord.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use deriving::path_std;
1112
use deriving::generic::*;
1213
use deriving::generic::ty::*;
1314

@@ -28,7 +29,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
2829
let trait_def = TraitDef {
2930
span,
3031
attributes: Vec::new(),
31-
path: path_std!(cx, core::cmp::Ord),
32+
path: path_std!(cx, cmp::Ord),
3233
additional_bounds: Vec::new(),
3334
generics: LifetimeBounds::empty(),
3435
is_unsafe: false,
@@ -38,7 +39,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
3839
generics: LifetimeBounds::empty(),
3940
explicit_self: borrowed_explicit_self(),
4041
args: vec![borrowed_self()],
41-
ret_ty: Literal(path_std!(cx, core::cmp::Ordering)),
42+
ret_ty: Literal(path_std!(cx, cmp::Ordering)),
4243
attributes: attrs,
4344
is_unsafe: false,
4445
unify_fieldless_variants: true,

src/libsyntax_ext/deriving/cmp/partial_eq.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use deriving::{path_local, path_std};
1112
use deriving::generic::*;
1213
use deriving::generic::ty::*;
1314

@@ -93,7 +94,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
9394
let trait_def = TraitDef {
9495
span,
9596
attributes: Vec::new(),
96-
path: path_std!(cx, core::cmp::PartialEq),
97+
path: path_std!(cx, cmp::PartialEq),
9798
additional_bounds: Vec::new(),
9899
generics: LifetimeBounds::empty(),
99100
is_unsafe: false,

0 commit comments

Comments
 (0)