Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix imports of built-in macros (mostly) #61877

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions src/librustc/hir/def_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ newtype_index! {

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CrateNum {
/// Virtual crate for builtin macros
// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
// `CrateNum`s.
BuiltinMacros,
/// Virtual crate for legacy proc macros registered with `#![plugin]`.
LegacyProcMacros,
/// A special CrateNum that we use for the tcx.rcache when decoding from
/// the incr. comp. cache.
ReservedForIncrCompCache,
Expand All @@ -27,7 +25,7 @@ impl ::std::fmt::Debug for CrateNum {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match self {
CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"),
CrateNum::LegacyProcMacros => write!(fmt, "legacy proc macros crate"),
CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
}
}
Expand Down Expand Up @@ -87,7 +85,7 @@ impl fmt::Display for CrateNum {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
CrateNum::BuiltinMacros => write!(f, "builtin macros crate"),
CrateNum::LegacyProcMacros => write!(f, "legacy proc macros crate"),
CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,11 @@ impl Definitions {
#[inline]
pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId {
let node_id = self.def_index_to_node[def_index.index()];
self.node_to_hir_id[node_id]
if unlikely!(node_id == ast::DUMMY_NODE_ID) {
hir::DUMMY_HIR_ID
} else {
self.node_to_hir_id[node_id]
}
}

#[inline]
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,10 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
}

impl cstore::CStore {
pub fn is_proc_macro_untracked(&self, def_id: DefId) -> bool {
self.get_crate_data(def_id.krate).is_proc_macro(def_id.index)
}

pub fn export_macros_untracked(&self, cnum: CrateNum) {
let data = self.get_crate_data(cnum);
let mut dep_kind = data.dep_kind.lock();
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>,
}

impl<'a, 'tcx> CrateMetadata {
fn is_proc_macro(&self, id: DefIndex) -> bool {
crate fn is_proc_macro(&self, id: DefIndex) -> bool {
self.proc_macros.is_some() && id != CRATE_DEF_INDEX
}

Expand Down Expand Up @@ -665,7 +665,10 @@ impl<'a, 'tcx> CrateMetadata {
pub fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
match self.is_proc_macro(id) {
true => None,
false => self.entry(id).deprecation.map(|depr| depr.decode(self)),
// Deprecation may be queried for built-in macro imports
// for which the entry doesn't exist.
false => self.maybe_entry(id).and_then(|e| e.decode(self).deprecation)
.map(|depr| depr.decode(self)),
}
}

Expand Down
26 changes: 25 additions & 1 deletion src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{resolve_error, resolve_struct_error, ResolutionError};
use rustc::bug;
use rustc::hir::def::{self, *};
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
use rustc::hir::map::definitions::FIRST_FREE_DEF_INDEX;
use rustc::ty;
use rustc::middle::cstore::CrateStore;
use rustc_metadata::cstore::LoadedMacro;
Expand Down Expand Up @@ -757,11 +758,25 @@ impl<'a> Resolver<'a> {
module
}

crate fn is_builtin_macro(&self, def_id: DefId) -> bool {
// Built-in macros are supposed to occupy a continuous range of `DefIndex`es immediately
// following `GlobalMetaData` entries. This is ensured by calling
// `syntax_ext::register_builtins` immediately after initializing `Definitions`.
// This range is identical in both the local crate and other crates in cstore.
// Proc-macro "views" of other crates in cstore don't have this range, thus the last
// condition.
let index_match = def_id.index.index() < FIRST_FREE_DEF_INDEX + self.num_builtin_macros;
let crate_match = def_id.is_local() ||
def_id.krate != CrateNum::LegacyProcMacros &&
!self.cstore.is_proc_macro_untracked(def_id);
index_match && crate_match
}

pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
let def_id = self.macro_defs[&expansion];
if let Some(id) = self.definitions.as_local_node_id(def_id) {
self.local_macro_def_scopes[&id]
} else if def_id.krate == CrateNum::BuiltinMacros {
} else if self.is_builtin_macro(def_id) || def_id.krate == CrateNum::LegacyProcMacros {
self.injected_crate.unwrap_or(self.graph_root)
} else {
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
Expand All @@ -777,6 +792,15 @@ impl<'a> Resolver<'a> {
}),
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
};

// Built-in macro from another crate is the same as its local equivalent,
// which always can be found in the `macro_map`.
let def_id = if self.is_builtin_macro(def_id) {
DefId::local(def_id.index)
} else {
def_id
};

if let Some(ext) = self.macro_map.get(&def_id) {
return ext.clone();
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,8 @@ pub struct Resolver<'a> {
crate_loader: &'a mut CrateLoader<'a>,
macro_names: FxHashSet<Ident>,
builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
/// Number of built-in macros excluding user extensions from `#![plugin]`.
num_builtin_macros: usize,
macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
pub all_macros: FxHashMap<Name, Res>,
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
Expand Down Expand Up @@ -2016,6 +2018,7 @@ impl<'a> Resolver<'a> {
crate_loader,
macro_names: FxHashSet::default(),
builtin_macros: FxHashMap::default(),
num_builtin_macros: 0,
macro_use_prelude: FxHashMap::default(),
all_macros: FxHashMap::default(),
macro_map: FxHashMap::default(),
Expand Down
21 changes: 16 additions & 5 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
use crate::resolve_imports::ImportResolver;
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
use rustc::hir::map::{self, DefCollector};
use rustc::hir::map::{self, DefCollector, DefPathData};
use rustc::{ty, lint};
use rustc::{bug, span_bug};
use syntax::ast::{self, Ident};
Expand Down Expand Up @@ -169,10 +169,21 @@ impl<'a> base::Resolver for Resolver<'a> {
invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope));
}

fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
let def_id = DefId {
krate: CrateNum::BuiltinMacros,
index: DefIndex::from(self.macro_map.len()),
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>, is_user_ext: bool) {
let def_id = if is_user_ext {
DefId {
krate: CrateNum::LegacyProcMacros,
index: DefIndex::from(self.macro_map.len()),
}
} else {
self.num_builtin_macros += 1;
DefId::local(self.definitions.create_def_with_parent(
CRATE_DEF_INDEX,
ast::DUMMY_NODE_ID,
DefPathData::MacroNs(ident.as_interned_str()),
Mark::root(),
DUMMY_SP,
))
};
let kind = ext.kind();
self.macro_map.insert(def_id, ext);
Expand Down
19 changes: 15 additions & 4 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use rustc::{bug, span_bug};
use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::hygiene::Mark;
use syntax::feature_gate::{emit_feature_err, GateIssue};
use syntax::symbol::{kw, sym};
use syntax::util::lev_distance::find_best_match_for_name;
use syntax::{struct_span_err, unwrap_or};
Expand Down Expand Up @@ -1226,12 +1227,22 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() {
let mut res = binding.res();
if let Res::Def(DefKind::Macro(_), def_id) = res {
// `DefId`s from the "built-in macro crate" should not leak from resolve because
// `DefId`s from the "legacy proc macro crate" should not leak from resolve because
// later stages are not ready to deal with them and produce lots of ICEs. Replace
// them with `Res::Err` until some saner scheme is implemented for built-in macros.
if def_id.krate == CrateNum::BuiltinMacros {
// them with `Res::Err` until legacy proc macros are removed.
if def_id.krate == CrateNum::LegacyProcMacros {
this.session.span_err(directive.span, "cannot import a built-in macro");
res = Res::Err;
} else if this.is_builtin_macro(def_id) {
if !this.session.features_untracked().builtin_macro_imports {
emit_feature_err(
&this.session.parse_sess,
sym::builtin_macro_imports,
directive.span,
GateIssue::Language,
"imports of built-in macros are unstable",
);
}
}
}
this.import_res_map.entry(directive.id).or_default()[ns] = Some(res);
Expand Down Expand Up @@ -1398,7 +1409,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
let res = binding.res();
if res != Res::Err {
if let Some(def_id) = res.opt_def_id() {
if !def_id.is_local() && def_id.krate != CrateNum::BuiltinMacros {
if !def_id.is_local() && def_id.krate != CrateNum::LegacyProcMacros {
self.cstore.export_macros_untracked(def_id.krate);
}
}
Expand Down
27 changes: 1 addition & 26 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ pub trait Resolver {
fn resolve_dollar_crates(&mut self, fragment: &AstFragment);
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
derives: &[Mark]);
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>, is_user_ext: bool);

fn resolve_imports(&mut self);

Expand All @@ -699,31 +699,6 @@ impl Determinacy {
}
}

pub struct DummyResolver;

impl Resolver for DummyResolver {
fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }

fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }

fn resolve_dollar_crates(&mut self, _fragment: &AstFragment) {}
fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
_derives: &[Mark]) {}
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}

fn resolve_imports(&mut self) {}
fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool)
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
Err(Determinacy::Determined)
}
fn resolve_macro_path(&mut self, _path: &ast::Path, _kind: MacroKind, _invoc_id: Mark,
_derives_in_scope: Vec<ast::Path>, _force: bool)
-> Result<Lrc<SyntaxExtension>, Determinacy> {
Err(Determinacy::Determined)
}
fn check_unused_macros(&self) {}
}

#[derive(Clone)]
pub struct ModuleData {
pub mod_path: Vec<ast::Ident>,
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,9 @@ declare_features! (
// #[repr(transparent)] on unions.
(active, transparent_unions, "1.37.0", Some(60405), None),

// `use builtin_macro`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// `use builtin_macro`.
// Allows `use builtin_macro;`.

(active, builtin_macro_imports, "1.37.0", Some(61875), None),

// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion src/libsyntax_ext/deriving/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ macro_rules! derive_traits {
$(
resolver.add_builtin(
ast::Ident::with_empty_ctxt(Symbol::intern($name)),
Lrc::new(SyntaxExtension::LegacyDerive(Box::new(BuiltinDerive($func))))
Lrc::new(SyntaxExtension::LegacyDerive(Box::new(BuiltinDerive($func)))),
false,
);
)*
}
Expand Down
7 changes: 5 additions & 2 deletions src/libsyntax_ext/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
edition: Edition) {
deriving::register_builtin_derives(resolver);

let mut register_user = |name, ext, is_user_ext| {
resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext), is_user_ext);
};
let mut register = |name, ext| {
resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext));
register_user(name, ext, false);
};
macro_rules! register {
($( $name:ident: $f:expr, )*) => { $(
Expand Down Expand Up @@ -126,6 +129,6 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
});

for (name, ext) in user_exts {
register(name, ext);
register_user(name, ext, true);
}
}
1 change: 1 addition & 0 deletions src/libsyntax_pos/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ symbols! {
box_patterns,
box_syntax,
braced_empty_structs,
builtin_macro_imports,
C,
cdylib,
cfg,
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn main() {}

// END RUST SOURCE
// START rustc.main.mir_map.0.dot
// digraph Mir_0_12 { // The name here MUST be an ASCII identifier.
// digraph Mir_0_52 { // The name here MUST be an ASCII identifier.
// graph [fontname="monospace"];
// node [fontname="monospace"];
// edge [fontname="monospace"];
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/inline-closure-borrows-arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fn foo<T: Copy>(_t: T, q: &i32) -> i32 {
// ...
// bb0: {
// ...
// _3 = [closure@HirId { owner: DefIndex(13), local_id: 31 }];
// _3 = [closure@HirId { owner: DefIndex(53), local_id: 31 }];
// ...
// _4 = &_3;
// ...
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/inline-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn foo<T: Copy>(_t: T, q: i32) -> i32 {
// ...
// bb0: {
// ...
// _3 = [closure@HirId { owner: DefIndex(13), local_id: 15 }];
// _3 = [closure@HirId { owner: DefIndex(53), local_id: 15 }];
// ...
// _4 = &_3;
// ...
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/retag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ fn main() {
// }
// END rustc.main.EraseRegions.after.mir
// START rustc.main-{{closure}}.EraseRegions.after.mir
// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(20), local_id: 72 }], _2: &i32) -> &i32 {
// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(60), local_id: 72 }], _2: &i32) -> &i32 {
// ...
// bb0: {
// Retag([fn entry] _1);
Expand Down
16 changes: 11 additions & 5 deletions src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,25 @@
#![feature(plugin_registrar)]
#![feature(rustc_private)]

extern crate syntax;

extern crate rustc;
extern crate rustc_plugin;
extern crate syntax_pos;
extern crate syntax;

use syntax::symbol::Symbol;
use syntax::feature_gate::AttributeType;
use rustc_plugin::Registry;
use syntax_pos::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
use syntax::feature_gate::AttributeType;
use syntax::symbol::Symbol;
use syntax::tokenstream::TokenTree;

fn empty(_: &mut ExtCtxt, _: Span, _: &[TokenTree]) -> Box<dyn MacResult + 'static> {
MacEager::items(Default::default())
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_attribute(Symbol::intern("foo"), AttributeType::Normal);
reg.register_attribute(Symbol::intern("bar"), AttributeType::CrateLevel);
reg.register_attribute(Symbol::intern("baz"), AttributeType::Whitelisted);
reg.register_macro("empty", empty);
}
10 changes: 10 additions & 0 deletions src/test/ui-fulldeps/plugin-import.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// edition:2018
// ignore-stage1
// aux-build:attr-plugin-test.rs

#![feature(plugin)]
#![plugin(attr_plugin_test)]

use empty as full; //~ ERROR cannot import a built-in macro

fn main() {}
8 changes: 8 additions & 0 deletions src/test/ui-fulldeps/plugin-import.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: cannot import a built-in macro
--> $DIR/plugin-import.rs:8:5
|
LL | use empty as full;
| ^^^^^^^^^^^^^

error: aborting due to previous error

Loading