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
This commit is contained in:
bors 2017-12-13 11:09:55 +00:00
commit 3dfbc88a62
30 changed files with 174 additions and 140 deletions

View file

@ -40,6 +40,7 @@ use syntax::ext::base::Determinacy::Undetermined;
use syntax::ext::hygiene::Mark;
use syntax::ext::tt::macro_rules;
use syntax::parse::token::{self, Token};
use syntax::std_inject::injected_crate_name;
use syntax::symbol::keywords;
use syntax::symbol::Symbol;
use syntax::visit::{self, Visitor};
@ -262,6 +263,10 @@ impl<'a> Resolver<'a> {
let module =
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(module);
if injected_crate_name().map_or(false, |name| item.ident.name == name) {
self.injected_crate = Some(module);
}
let used = self.process_legacy_macro_imports(item, module, expansion);
let binding =
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
@ -558,8 +563,7 @@ impl<'a> Resolver<'a> {
if let Some(id) = self.definitions.as_local_node_id(def_id) {
self.local_macro_def_scopes[&id]
} else if def_id.krate == BUILTIN_MACROS_CRATE {
// FIXME(jseyfried): This happens when `include!()`ing a `$crate::` path, c.f, #40469.
self.graph_root
self.injected_crate.unwrap_or(self.graph_root)
} else {
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
self.get_module(module_def_id)

View file

@ -1338,6 +1338,8 @@ pub struct Resolver<'a> {
// Only used for better errors on `fn(): fn()`
current_type_ascription: Vec<Span>,
injected_crate: Option<Module<'a>>,
}
pub struct ResolverArenas<'a> {
@ -1537,6 +1539,7 @@ impl<'a> Resolver<'a> {
found_unresolved_macro: false,
unused_macros: FxHashSet(),
current_type_ascription: Vec::new(),
injected_crate: None,
}
}

View file

@ -25,7 +25,7 @@ use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
use syntax::ext::hygiene::Mark;
use syntax::ext::hygiene::{Mark, MarkKind};
use syntax::ext::placeholders::placeholder;
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{self, emit_feature_err, GateIssue};
@ -297,16 +297,19 @@ impl<'a> base::Resolver for Resolver<'a> {
InvocationKind::Attr { attr: None, .. } => return Ok(None),
_ => self.resolve_invoc_to_def(invoc, scope, force)?,
};
let def_id = def.def_id();
self.macro_defs.insert(invoc.expansion_data.mark, def.def_id());
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
let normal_module_def_id =
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id);
self.unused_macros.remove(&def.def_id());
self.unused_macros.remove(&def_id);
let ext = self.get_macro(def);
if ext.is_modern() {
invoc.expansion_data.mark.set_modern();
invoc.expansion_data.mark.set_kind(MarkKind::Modern);
} else if def_id.krate == BUILTIN_MACROS_CRATE {
invoc.expansion_data.mark.set_kind(MarkKind::Builtin);
}
Ok(Some(ext))
}