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

resolve: Give derive helpers highest priority during resolution #66529

Merged
merged 1 commit into from Nov 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 16 additions & 9 deletions src/librustc_resolve/macros.rs
Expand Up @@ -466,11 +466,12 @@ impl<'a> Resolver<'a> {
) -> 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;
}
}

Expand Down Expand Up @@ -528,8 +529,10 @@ impl<'a> Resolver<'a> {
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) => {}
Expand Down Expand Up @@ -659,13 +662,17 @@ impl<'a> Resolver<'a> {
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) &&
Expand Down
12 changes: 12 additions & 0 deletions 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()
}
16 changes: 16 additions & 0 deletions 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() {}
4 changes: 2 additions & 2 deletions src/test/ui/proc-macro/derive-helper-shadowing.rs
Expand Up @@ -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 {
Expand Down
38 changes: 1 addition & 37 deletions src/test/ui/proc-macro/derive-helper-shadowing.stderr
Expand Up @@ -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`.