Skip to content

Commit

Permalink
resolve: Give derive helpers highest priority during resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Nov 18, 2019
1 parent a0d40f8 commit f74fe81
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 48 deletions.
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`.

0 comments on commit f74fe81

Please sign in to comment.