diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0f6a9742309..65fe01ff96a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1412,6 +1412,7 @@ pub struct Resolver<'a, 'b: 'a> { crate_loader: &'a mut CrateLoader<'b>, macro_names: FxHashSet, macro_prelude: FxHashMap>, + unshadowable_attrs: FxHashMap>, pub all_macros: FxHashMap, macro_map: FxHashMap>, macro_defs: FxHashMap, @@ -1729,6 +1730,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { crate_loader, macro_names: FxHashSet(), macro_prelude: FxHashMap(), + unshadowable_attrs: FxHashMap(), all_macros: FxHashMap(), macro_map: FxHashMap(), invocations, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0d3e615b446..4cc8d348667 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -207,6 +207,23 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { self.macro_prelude.insert(ident.name, binding); } + fn add_unshadowable_attr(&mut self, ident: ast::Ident, ext: Lrc) { + let def_id = DefId { + krate: BUILTIN_MACROS_CRATE, + index: DefIndex::from_array_index(self.macro_map.len(), + DefIndexAddressSpace::Low), + }; + let kind = ext.kind(); + self.macro_map.insert(def_id, ext); + let binding = self.arenas.alloc_name_binding(NameBinding { + kind: NameBindingKind::Def(Def::Macro(def_id, kind), false), + span: DUMMY_SP, + vis: ty::Visibility::Invisible, + expansion: Mark::root(), + }); + self.unshadowable_attrs.insert(ident.name, binding); + } + fn resolve_imports(&mut self) { ImportResolver { resolver: self }.resolve_imports() } @@ -462,8 +479,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> { return def; } - if kind == MacroKind::Attr && *&path[0].as_str() == "test" { - return Ok(self.macro_prelude.get(&path[0].name).unwrap().def()) + if kind == MacroKind::Attr && path.len() == 1 { + if let Some(ext) = self.unshadowable_attrs.get(&path[0].name) { + return Ok(ext.def()); + } } let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e8a68b6d767..0e059bc4a6c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -721,6 +721,7 @@ pub trait Resolver { fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, derives: &[Mark]); fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc); + fn add_unshadowable_attr(&mut self, ident: ast::Ident, ext: Lrc); fn resolve_imports(&mut self); // Resolves attribute and derive legacy macros from `#![plugin(..)]`. @@ -729,6 +730,7 @@ pub trait Resolver { fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool) -> Result>, Determinacy>; + fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark, derives_in_scope: &[ast::Path], force: bool) -> Result, Determinacy>; @@ -759,6 +761,7 @@ impl Resolver for DummyResolver { fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment, _derives: &[Mark]) {} fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc) {} + fn add_unshadowable_attr(&mut self, _ident: ast::Ident, _ext: Lrc) {} fn resolve_imports(&mut self) {} fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec, _allow_derive: bool) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 35cb5aa5475..c94c7874a05 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -769,8 +769,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG ("cfg_attr", Normal, Ungated), ("main", Normal, Ungated), ("start", Normal, Ungated), - ("test", Normal, Ungated), - ("bench", Normal, Ungated), ("repr", Normal, Ungated), ("path", Normal, Ungated), ("abi", Normal, Ungated), diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index bbbf338c4f3..a9990cdeabf 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -71,6 +71,18 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, enable_quotes: bool) { deriving::register_builtin_derives(resolver); + { + let mut register_unshadowable = |name, ext| { + resolver.add_unshadowable_attr(ast::Ident::with_empty_ctxt(name), Lrc::new(ext)); + }; + + register_unshadowable(Symbol::intern("test"), + MultiModifier(Box::new(test::expand_test))); + + register_unshadowable(Symbol::intern("bench"), + MultiModifier(Box::new(test::expand_bench))); + } + let mut register = |name, ext| { resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext)); }; @@ -133,8 +145,6 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, assert: assert::expand_assert, } - register(Symbol::intern("test"), MultiModifier(Box::new(test::expand_test))); - register(Symbol::intern("bench"), MultiModifier(Box::new(test::expand_bench))); // format_args uses `unstable` things internally. register(Symbol::intern("format_args"), diff --git a/src/test/ui/test-shadowing/auxiliary/test_macro.rs b/src/test/ui/test-shadowing/auxiliary/test_macro.rs new file mode 100644 index 00000000000..ba7ed73b822 --- /dev/null +++ b/src/test/ui/test-shadowing/auxiliary/test_macro.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_export] +macro_rules! test { + () => {}; +} \ No newline at end of file diff --git a/src/test/ui/test-shadowing/test-cant-be-shadowed.rs b/src/test/ui/test-shadowing/test-cant-be-shadowed.rs new file mode 100644 index 00000000000..4ae8b7ffe8b --- /dev/null +++ b/src/test/ui/test-shadowing/test-cant-be-shadowed.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +// aux-build:test_macro.rs +// compile-flags:--test + +#[macro_use] extern crate test_macro; + +#[test] +fn foo(){} \ No newline at end of file