From: Vadim Petrochenkov Date: Sat, 8 Sep 2018 19:19:53 +0000 (+0300) Subject: resolve: Introduce two sub-namespaces in macro namespace X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=beb3b5d22c709c19600ca6514d94f9cf1be44dca;p=rust.git resolve: Introduce two sub-namespaces in macro namespace --- diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index f687e022a41..cf5a53b6318 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -118,11 +118,21 @@ pub struct ProcMacError { warn_msg: &'static str, } -// For compatibility bang macros are skipped when resolving potentially built-in attributes. -fn macro_kind_mismatch(name: Name, requirement: Option, candidate: Option) - -> bool { - requirement == Some(MacroKind::Attr) && candidate == Some(MacroKind::Bang) && - (name == "test" || name == "bench" || is_builtin_attr_name(name)) +// Macro namespace is separated into two sub-namespaces, one for bang macros and +// one for attribute-like macros (attributes, derives). +// We ignore resolutions from one sub-namespace when searching names in scope for another. +fn sub_namespace_mismatch(requirement: Option, candidate: Option) -> bool { + #[derive(PartialEq)] + enum SubNS { Bang, AttrLike } + let sub_ns = |kind| match kind { + MacroKind::Bang => Some(SubNS::Bang), + MacroKind::Attr | MacroKind::Derive => Some(SubNS::AttrLike), + MacroKind::ProcMacroStub => None, + }; + let requirement = requirement.and_then(|kind| sub_ns(kind)); + let candidate = candidate.and_then(|kind| sub_ns(kind)); + // "No specific sub-namespace" means "matches anything" for both requirements and candidates. + candidate.is_some() && requirement.is_some() && candidate != requirement } impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { @@ -641,10 +651,7 @@ enum WhereToResolve<'a> { } } WhereToResolve::BuiltinAttrs => { - // FIXME: Only built-in attributes are not considered as candidates for - // non-attributes to fight off regressions on stable channel (#53205). - // We need to come up with some more principled approach instead. - if kind == Some(MacroKind::Attr) && is_builtin_attr_name(ident.name) { + if is_builtin_attr_name(ident.name) { let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin), ty::Visibility::Public, ident.span, Mark::root()) .to_name_binding(self.arenas); @@ -765,7 +772,7 @@ macro_rules! continue_search { () => { match result { Ok(result) => { - if macro_kind_mismatch(ident.name, kind, result.0.macro_kind()) { + if sub_namespace_mismatch(kind, result.0.macro_kind()) { continue_search!(); } @@ -829,7 +836,7 @@ fn resolve_legacy_scope( parent_scope: &ParentScope<'a>, record_used: bool, ) -> Option<&'a NameBinding<'a>> { - if macro_kind_mismatch(ident.name, kind, Some(MacroKind::Bang)) { + if sub_namespace_mismatch(kind, Some(MacroKind::Bang)) { return None; } diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs new file mode 100644 index 00000000000..9912a89dafb --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs @@ -0,0 +1,2 @@ +#[macro_export] +macro_rules! my_attr { () => () } diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs new file mode 100644 index 00000000000..4e701710f42 --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs @@ -0,0 +1,11 @@ +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(MyTrait, attributes(my_attr))] +pub fn foo(_: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs new file mode 100644 index 00000000000..792b54b3b94 --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs @@ -0,0 +1,16 @@ +// compile-pass +// aux-build:derive-helper-shadowed.rs +// aux-build:derive-helper-shadowed-2.rs + +#[macro_use] +extern crate derive_helper_shadowed; +#[macro_use(my_attr)] +extern crate derive_helper_shadowed_2; + +macro_rules! my_attr { () => () } + +#[derive(MyTrait)] +#[my_attr] // OK +struct S; + +fn main() {} diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs index 2e94a27838e..a4b8b48384d 100644 --- a/src/test/ui/issues/issue-11692-2.rs +++ b/src/test/ui/issues/issue-11692-2.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - concat!(test!()); //~ ERROR `test` can only be used in attributes + concat!(test!()); //~ ERROR cannot find macro `test!` in this scope } diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr index 186c59a6149..85f600dbff2 100644 --- a/src/test/ui/issues/issue-11692-2.stderr +++ b/src/test/ui/issues/issue-11692-2.stderr @@ -1,7 +1,7 @@ -error: `test` can only be used in attributes +error: cannot find macro `test!` in this scope --> $DIR/issue-11692-2.rs:12:13 | -LL | concat!(test!()); //~ ERROR `test` can only be used in attributes +LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.rs b/src/test/ui/macros/macro-path-prelude-fail-3.rs index c706b8f613d..597053d6251 100644 --- a/src/test/ui/macros/macro-path-prelude-fail-3.rs +++ b/src/test/ui/macros/macro-path-prelude-fail-3.rs @@ -1,16 +1,3 @@ -// 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. - -#[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope -struct S; - fn main() { inline!(); //~ ERROR cannot find macro `inline!` in this scope } diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr index a8edf54d220..17723251181 100644 --- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr +++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr @@ -1,14 +1,8 @@ -error: cannot find derive macro `inline` in this scope - --> $DIR/macro-path-prelude-fail-3.rs:11:10 - | -LL | #[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope - | ^^^^^^ - error: cannot find macro `inline!` in this scope - --> $DIR/macro-path-prelude-fail-3.rs:15:5 + --> $DIR/macro-path-prelude-fail-3.rs:2:5 | LL | inline!(); //~ ERROR cannot find macro `inline!` in this scope | ^^^^^^ help: you could try the macro: `line` -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.rs b/src/test/ui/macros/macro-path-prelude-fail-4.rs new file mode 100644 index 00000000000..283427b9ace --- /dev/null +++ b/src/test/ui/macros/macro-path-prelude-fail-4.rs @@ -0,0 +1,4 @@ +#[derive(inline)] //~ ERROR expected a macro, found built-in attribute +struct S; + +fn main() {} diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.stderr b/src/test/ui/macros/macro-path-prelude-fail-4.stderr new file mode 100644 index 00000000000..e354f345a4c --- /dev/null +++ b/src/test/ui/macros/macro-path-prelude-fail-4.stderr @@ -0,0 +1,8 @@ +error: expected a macro, found built-in attribute + --> $DIR/macro-path-prelude-fail-4.rs:1:10 + | +LL | #[derive(inline)] //~ ERROR expected a macro, found built-in attribute + | ^^^^^^ + +error: aborting due to previous error +