Skip to content

Commit fdcd4a4

Browse files
committed
Auto merge of #53936 - petrochenkov:2macpre, r=alexcrichton
resolve: Split macro prelude into built-in and user-defined parts This is a refactoring that will help to remove `unshadowable_attrs` when #53410 lands. UPDATE: The second commit actually removes `unshadowable_attrs`.
2 parents 2d4e34c + 62c7d78 commit fdcd4a4

File tree

8 files changed

+81
-79
lines changed

8 files changed

+81
-79
lines changed

src/librustc_resolve/build_reduced_graph.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
833833
binding: &'a NameBinding<'a>,
834834
span: Span,
835835
allow_shadowing: bool) {
836-
if self.macro_prelude.insert(name, binding).is_some() && !allow_shadowing {
836+
if self.macro_use_prelude.insert(name, binding).is_some() && !allow_shadowing {
837837
let msg = format!("`{}` is already in scope", name);
838838
let note =
839839
"macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";

src/librustc_resolve/lib.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,13 @@ impl<'a> NameBinding<'a> {
12781278
}
12791279
}
12801280

1281+
fn macro_kind(&self) -> Option<MacroKind> {
1282+
match self.def_ignoring_ambiguity() {
1283+
Def::Macro(_, kind) => Some(kind),
1284+
_ => None,
1285+
}
1286+
}
1287+
12811288
fn descr(&self) -> &'static str {
12821289
if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() }
12831290
}
@@ -1440,8 +1447,8 @@ pub struct Resolver<'a, 'b: 'a> {
14401447

14411448
crate_loader: &'a mut CrateLoader<'b>,
14421449
macro_names: FxHashSet<Ident>,
1443-
macro_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
1444-
unshadowable_attrs: FxHashMap<Name, &'a NameBinding<'a>>,
1450+
builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
1451+
macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
14451452
pub all_macros: FxHashMap<Name, Def>,
14461453
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
14471454
macro_defs: FxHashMap<Mark, DefId>,
@@ -1757,8 +1764,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
17571764

17581765
crate_loader,
17591766
macro_names: FxHashSet(),
1760-
macro_prelude: FxHashMap(),
1761-
unshadowable_attrs: FxHashMap(),
1767+
builtin_macros: FxHashMap(),
1768+
macro_use_prelude: FxHashMap(),
17621769
all_macros: FxHashMap(),
17631770
macro_map: FxHashMap(),
17641771
invocations,
@@ -3340,10 +3347,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
33403347
};
33413348
}
33423349
}
3343-
let is_global = self.macro_prelude.get(&path[0].name).cloned()
3344-
.map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
3345-
if primary_ns != MacroNS && (is_global ||
3346-
self.macro_names.contains(&path[0].modern())) {
3350+
if primary_ns != MacroNS &&
3351+
(self.macro_names.contains(&path[0].modern()) ||
3352+
self.builtin_macros.get(&path[0].name).cloned()
3353+
.and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) ||
3354+
self.macro_use_prelude.get(&path[0].name).cloned()
3355+
.and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) {
33473356
// Return some dummy definition, it's enough for error reporting.
33483357
return Some(
33493358
PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))

src/librustc_resolve/macros.rs

+53-52
Original file line numberDiff line numberDiff line change
@@ -214,24 +214,10 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
214214
vis: ty::Visibility::Invisible,
215215
expansion: Mark::root(),
216216
});
217-
self.macro_prelude.insert(ident.name, binding);
218-
}
219-
220-
fn add_unshadowable_attr(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
221-
let def_id = DefId {
222-
krate: BUILTIN_MACROS_CRATE,
223-
index: DefIndex::from_array_index(self.macro_map.len(),
224-
DefIndexAddressSpace::Low),
225-
};
226-
let kind = ext.kind();
227-
self.macro_map.insert(def_id, ext);
228-
let binding = self.arenas.alloc_name_binding(NameBinding {
229-
kind: NameBindingKind::Def(Def::Macro(def_id, kind), false),
230-
span: DUMMY_SP,
231-
vis: ty::Visibility::Invisible,
232-
expansion: Mark::root(),
233-
});
234-
self.unshadowable_attrs.insert(ident.name, binding);
217+
if self.builtin_macros.insert(ident.name, binding).is_some() {
218+
self.session.span_err(ident.span,
219+
&format!("built-in macro `{}` was already defined", ident));
220+
}
235221
}
236222

237223
fn resolve_imports(&mut self) {
@@ -249,7 +235,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
249235
attr::mark_known(&attrs[i]);
250236
}
251237

252-
match self.macro_prelude.get(&name).cloned() {
238+
match self.builtin_macros.get(&name).cloned() {
253239
Some(binding) => match *binding.get_macro(self) {
254240
MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
255241
return Some(attrs.remove(i))
@@ -285,7 +271,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
285271
}
286272
let trait_name = traits[j].segments[0].ident.name;
287273
let legacy_name = Symbol::intern(&format!("derive_{}", trait_name));
288-
if !self.macro_prelude.contains_key(&legacy_name) {
274+
if !self.builtin_macros.contains_key(&legacy_name) {
289275
continue
290276
}
291277
let span = traits.remove(j).span;
@@ -490,14 +476,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
490476
return def;
491477
}
492478

493-
if kind == MacroKind::Attr {
494-
if let Some(ext) = self.unshadowable_attrs.get(&path[0].name) {
495-
return Ok(ext.def());
496-
}
497-
}
498-
499479
let legacy_resolution = self.resolve_legacy_scope(
500-
path[0], invoc_id, invocation.parent_legacy_scope.get(), false
480+
path[0], invoc_id, invocation.parent_legacy_scope.get(), false, kind == MacroKind::Attr
501481
);
502482
let result = if let Some(legacy_binding) = legacy_resolution {
503483
Ok(legacy_binding.def())
@@ -585,14 +565,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
585565
// (Macro NS)
586566
// 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
587567
// (open, not controlled).
588-
// 2. Macro prelude (language, standard library, user-defined legacy plugins lumped into
589-
// one set) (open, the open part is from macro expansions, not controlled).
568+
// 2. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
590569
// 2a. User-defined prelude from macro-use
591570
// (open, the open part is from macro expansions, not controlled).
592-
// 2b. Standard library prelude, currently just a macro-use (closed, controlled)
593-
// 2c. Language prelude, perhaps including builtin attributes
594-
// (closed, controlled, except for legacy plugins).
595-
// 3. Builtin attributes (closed, controlled).
571+
// 2b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
572+
// 3. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
573+
// 4. Language prelude: builtin attributes (closed, controlled).
596574

597575
assert!(ns == TypeNS || ns == MacroNS);
598576
assert!(force || !record_used); // `record_used` implies `force`
@@ -613,12 +591,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
613591

614592
enum WhereToResolve<'a> {
615593
Module(Module<'a>),
616-
MacroPrelude,
594+
MacroUsePrelude,
595+
BuiltinMacros,
617596
BuiltinAttrs,
618597
ExternPrelude,
619598
ToolPrelude,
620599
StdLibPrelude,
621-
PrimitiveTypes,
600+
BuiltinTypes,
622601
}
623602

624603
// Go through all the scopes and try to resolve the name.
@@ -639,8 +618,26 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
639618
self.current_module = orig_current_module;
640619
binding.map(|binding| (binding, FromPrelude(false)))
641620
}
642-
WhereToResolve::MacroPrelude => {
643-
match self.macro_prelude.get(&ident.name).cloned() {
621+
WhereToResolve::MacroUsePrelude => {
622+
match self.macro_use_prelude.get(&ident.name).cloned() {
623+
Some(binding) => {
624+
let mut result = Ok((binding, FromPrelude(true)));
625+
// FIXME: Keep some built-in macros working even if they are
626+
// shadowed by non-attribute macros imported with `macro_use`.
627+
// We need to come up with some more principled approach instead.
628+
if is_attr && (ident.name == "test" || ident.name == "bench") {
629+
if let Def::Macro(_, MacroKind::Bang) =
630+
binding.def_ignoring_ambiguity() {
631+
result = Err(Determinacy::Determined);
632+
}
633+
}
634+
result
635+
}
636+
None => Err(Determinacy::Determined),
637+
}
638+
}
639+
WhereToResolve::BuiltinMacros => {
640+
match self.builtin_macros.get(&ident.name).cloned() {
644641
Some(binding) => Ok((binding, FromPrelude(true))),
645642
None => Err(Determinacy::Determined),
646643
}
@@ -708,7 +705,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
708705
}
709706
result
710707
}
711-
WhereToResolve::PrimitiveTypes => {
708+
WhereToResolve::BuiltinTypes => {
712709
if let Some(prim_ty) =
713710
self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
714711
let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
@@ -728,19 +725,20 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
728725
None => {
729726
use_prelude = !module.no_implicit_prelude;
730727
if ns == MacroNS {
731-
WhereToResolve::MacroPrelude
728+
WhereToResolve::MacroUsePrelude
732729
} else {
733730
WhereToResolve::ExternPrelude
734731
}
735732
}
736733
}
737734
}
738-
WhereToResolve::MacroPrelude => WhereToResolve::BuiltinAttrs,
735+
WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
736+
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
739737
WhereToResolve::BuiltinAttrs => break, // nowhere else to search
740738
WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
741739
WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
742-
WhereToResolve::StdLibPrelude => WhereToResolve::PrimitiveTypes,
743-
WhereToResolve::PrimitiveTypes => break, // nowhere else to search
740+
WhereToResolve::StdLibPrelude => WhereToResolve::BuiltinTypes,
741+
WhereToResolve::BuiltinTypes => break, // nowhere else to search
744742
};
745743

746744
continue;
@@ -802,8 +800,16 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
802800
ident: Ident,
803801
invoc_id: Mark,
804802
invoc_parent_legacy_scope: LegacyScope<'a>,
805-
record_used: bool)
803+
record_used: bool,
804+
is_attr: bool)
806805
-> Option<&'a NameBinding<'a>> {
806+
if is_attr && (ident.name == "test" || ident.name == "bench") {
807+
// FIXME: Keep some built-in macros working even if they are
808+
// shadowed by user-defined `macro_rules`.
809+
// We need to come up with some more principled approach instead.
810+
return None;
811+
}
812+
807813
let ident = ident.modern();
808814

809815
// This is *the* result, resolution from the scope closest to the resolved identifier.
@@ -889,7 +895,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
889895
let span = ident.span;
890896
let invocation = self.invocations[&invoc_id];
891897
let legacy_resolution = self.resolve_legacy_scope(
892-
ident, invoc_id, invocation.parent_legacy_scope.get(), true
898+
ident, invoc_id, invocation.parent_legacy_scope.get(), true, kind == MacroKind::Attr
893899
);
894900
let resolution = self.resolve_lexical_macro_path_segment(
895901
ident, MacroNS, invoc_id, true, true, kind == MacroKind::Attr, span
@@ -958,14 +964,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
958964
None
959965
// Then check global macros.
960966
}.or_else(|| {
961-
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
962-
let macro_prelude = self.macro_prelude.clone();
963-
let names = macro_prelude.iter().filter_map(|(name, binding)| {
964-
if binding.get_macro(self).kind() == kind {
965-
Some(name)
966-
} else {
967-
None
968-
}
967+
let names = self.builtin_macros.iter().chain(self.macro_use_prelude.iter())
968+
.filter_map(|(name, binding)| {
969+
if binding.macro_kind() == Some(kind) { Some(name) } else { None }
969970
});
970971
find_best_match_for_name(names, name, None)
971972
// Then check modules.

src/libsyntax/ext/base.rs

-2
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,6 @@ pub trait Resolver {
721721
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
722722
derives: &[Mark]);
723723
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
724-
fn add_unshadowable_attr(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
725724

726725
fn resolve_imports(&mut self);
727726
// Resolves attribute and derive legacy macros from `#![plugin(..)]`.
@@ -761,7 +760,6 @@ impl Resolver for DummyResolver {
761760
fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
762761
_derives: &[Mark]) {}
763762
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
764-
fn add_unshadowable_attr(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
765763

766764
fn resolve_imports(&mut self) {}
767765
fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool)

src/libsyntax_ext/lib.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,6 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
7272
enable_quotes: bool) {
7373
deriving::register_builtin_derives(resolver);
7474

75-
{
76-
let mut register_unshadowable = |name, ext| {
77-
resolver.add_unshadowable_attr(ast::Ident::with_empty_ctxt(name), Lrc::new(ext));
78-
};
79-
80-
register_unshadowable(Symbol::intern("test"),
81-
MultiModifier(Box::new(test::expand_test)));
82-
83-
register_unshadowable(Symbol::intern("bench"),
84-
MultiModifier(Box::new(test::expand_bench)));
85-
}
86-
8775
let mut register = |name, ext| {
8876
resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext));
8977
};
@@ -147,6 +135,8 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
147135
}
148136

149137
register(Symbol::intern("test_case"), MultiModifier(Box::new(test_case::expand)));
138+
register(Symbol::intern("test"), MultiModifier(Box::new(test::expand_test)));
139+
register(Symbol::intern("bench"), MultiModifier(Box::new(test::expand_bench)));
150140

151141
// format_args uses `unstable` things internally.
152142
register(Symbol::intern("format_args"),

src/test/ui/issues/issue-11692-2.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
concat!(test!());
13-
//~^ error: cannot find macro `test!` in this scope
12+
concat!(test!()); //~ ERROR `test` can only be used in attributes
1413
}

src/test/ui/issues/issue-11692-2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
error: cannot find macro `test!` in this scope
1+
error: `test` can only be used in attributes
22
--> $DIR/issue-11692-2.rs:12:13
33
|
4-
LL | concat!(test!());
4+
LL | concat!(test!()); //~ ERROR `test` can only be used in attributes
55
| ^^^^
66

77
error: aborting due to previous error

src/test/ui/test-shadowing/test-cant-be-shadowed.rs

+5
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,8 @@
1616

1717
#[test]
1818
fn foo(){}
19+
20+
macro_rules! test { () => () }
21+
22+
#[test]
23+
fn bar() {}

0 commit comments

Comments
 (0)