diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 4f687b5ba92..8dc0fb9bd77 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -466,11 +466,12 @@ pub fn resolve_macro_path( ) -> Result<&'a NameBinding<'a>, Determinacy> { bitflags::bitflags! { struct Flags: u8 { - const MACRO_RULES = 1 << 0; - const MODULE = 1 << 1; - const MISC_SUGGEST_CRATE = 1 << 2; - const MISC_SUGGEST_SELF = 1 << 3; - const MISC_FROM_PRELUDE = 1 << 4; + const MACRO_RULES = 1 << 0; + const MODULE = 1 << 1; + const DERIVE_HELPER_COMPAT = 1 << 2; + const MISC_SUGGEST_CRATE = 1 << 3; + const MISC_SUGGEST_SELF = 1 << 4; + const MISC_FROM_PRELUDE = 1 << 5; } } @@ -528,8 +529,10 @@ struct Flags: u8 { match this.resolve_macro_path(derive, Some(MacroKind::Derive), parent_scope, true, force) { Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) { - let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); - result = ok(res, derive.span, this.arenas); + let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), + ty::Visibility::Public, derive.span, ExpnId::root()) + .to_name_binding(this.arenas); + result = Ok((binding, Flags::DERIVE_HELPER_COMPAT)); break; } Ok(_) | Err(Determinacy::Determined) => {} @@ -659,13 +662,17 @@ struct Flags: u8 { let (res, innermost_res) = (binding.res(), innermost_binding.res()); if res != innermost_res { let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin); - let derive_helper = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); + let is_derive_helper_compat = |res, flags: Flags| { + res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper) && + flags.contains(Flags::DERIVE_HELPER_COMPAT) + }; let ambiguity_error_kind = if is_import { Some(AmbiguityKind::Import) } else if innermost_res == builtin || res == builtin { Some(AmbiguityKind::BuiltinAttr) - } else if innermost_res == derive_helper || res == derive_helper { + } else if is_derive_helper_compat(innermost_res, innermost_flags) || + is_derive_helper_compat(res, flags) { Some(AmbiguityKind::DeriveHelper) } else if innermost_flags.contains(Flags::MACRO_RULES) && flags.contains(Flags::MODULE) && diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs new file mode 100644 index 00000000000..370a1a2794d --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(same_name, attributes(same_name))] +pub fn derive_a(_: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing-2.rs b/src/test/ui/proc-macro/derive-helper-shadowing-2.rs new file mode 100644 index 00000000000..5204d72b980 --- /dev/null +++ b/src/test/ui/proc-macro/derive-helper-shadowing-2.rs @@ -0,0 +1,16 @@ +// If a derive macro introduces a helper attribute with the same name as that macro, +// then make sure that it's usable without ambiguities. + +// check-pass +// aux-build:derive-helper-shadowing-2.rs + +#[macro_use] +extern crate derive_helper_shadowing_2; + +#[derive(same_name)] +struct S { + #[same_name] // OK, no ambiguity, derive helpers have highest priority + field: u8, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs index f0ca34db414..6147e96a74b 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -19,11 +19,11 @@ macro_rules! gen_helper_use { #[empty_helper] //~ ERROR `empty_helper` is ambiguous #[derive(Empty)] struct S { - #[empty_helper] //~ ERROR `empty_helper` is ambiguous + #[empty_helper] // OK, no ambiguity, derive helpers have highest priority field: [u8; { use empty_helper; //~ ERROR `empty_helper` is ambiguous - #[empty_helper] //~ ERROR `empty_helper` is ambiguous + #[empty_helper] // OK, no ambiguity, derive helpers have highest priority struct U; mod inner { diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index 9048830bee2..76434860a49 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -61,42 +61,6 @@ LL | use test_macros::empty_attr as empty_helper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously -error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) - --> $DIR/derive-helper-shadowing.rs:22:7 - | -LL | #[empty_helper] - | ^^^^^^^^^^^^ ambiguous name - | -note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:20:10 - | -LL | #[derive(Empty)] - | ^^^^^ -note: `empty_helper` could also refer to the attribute macro imported here - --> $DIR/derive-helper-shadowing.rs:10:5 - | -LL | use test_macros::empty_attr as empty_helper; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: use `crate::empty_helper` to refer to this attribute macro unambiguously - -error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) - --> $DIR/derive-helper-shadowing.rs:26:11 - | -LL | #[empty_helper] - | ^^^^^^^^^^^^ ambiguous name - | -note: `empty_helper` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:20:10 - | -LL | #[derive(Empty)] - | ^^^^^ -note: `empty_helper` could also refer to the attribute macro imported here - --> $DIR/derive-helper-shadowing.rs:10:5 - | -LL | use test_macros::empty_attr as empty_helper; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: use `crate::empty_helper` to refer to this attribute macro unambiguously - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0659`.