Rollup merge of #66529 - petrochenkov:reshelp2, r=davidtwco

resolve: Give derive helpers highest priority during resolution

So they just shadow everything else and don't create ambiguity errors.
This matches the old pre-#64694 behavior most closely.

---
The change doesn't apply to this "compatibility" case
```rust
#[trait_helper] // The helper attribute is used before it introduced.
                        // Sadly, compiles on stable, supported via hacks.
                        // I plan to make a compatibility warning for this.
#[derive(Trait)]
struct S;
```
, such attributes still create ambiguities, but #64694 didn't change anything for this case.

Fixes https://github.com/rust-lang/rust/issues/66508
Fixes https://github.com/rust-lang/rust/issues/66525
This commit is contained in:
Mazdak Farrokhzad 2019-11-19 13:10:23 +01:00 committed by GitHub
commit 1f0f0adbf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 48 deletions

View File

@ -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) &&

View File

@ -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()
}

View File

@ -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() {}

View File

@ -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 {

View File

@ -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`.