Rollup merge of #57501 - petrochenkov:highvar, r=alexreg

High priority resolutions for associated variants

In https://github.com/rust-lang/rust/pull/56225 variants were assigned lowest priority during name resolution to avoid crater run and potential breakage.

This PR changes the rules to give variants highest priority instead.
Some motivation:
- If variants (and their constructors) are treated as associated items, then they are obviously *inherent* associated items since they don't come from traits.
- Inherent associated items have higher priority during resolution than associated items from traits.
- The reason is that there is a way to disambiguate in favor of trait items (`<Type as Trait>::Ambiguous`), but there's no way to disambiguate in favor of inherent items, so they became unusable in case of ambiguities if they have low priority.
- It's technically problematic to fallback from associated types to anything until lazy normalization (?) is implemented.

Crater found some regressions from this change, but they are all in type positions, e.g.
```rust
fn f() -> Self::Ambiguos { ... } // Variant `Ambiguous` or associated type `Ambiguous`?
```
, so variants are not usable there right now, but they may become usable in the future if https://github.com/rust-lang/rfcs/pull/2593 is accepted.
This PR keeps code like this successfully resolving, but introduces a future-compatibility lint `ambiguous_associated_items` that recommends rewriting it as `<Self as Trait>::Ambiguous`.
This commit is contained in:
Mazdak Farrokhzad 2019-01-19 09:03:26 +01:00 committed by GitHub
commit b941f290ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 227 additions and 105 deletions

View file

@ -0,0 +1,13 @@
#![feature(type_alias_enum_variants)]
enum E {
V(u8)
}
impl E {
fn V() {}
}
fn main() {
<E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
}

View file

@ -0,0 +1,12 @@
error[E0061]: this function takes 1 parameter but 0 parameters were supplied
--> $DIR/type-alias-enum-variants-priority-2.rs:12:5
|
LL | V(u8)
| ----- defined here
...
LL | <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
| ^^^^^^^^ expected 1 parameter
error: aborting due to previous error
For more information about this error, try `rustc --explain E0061`.

View file

@ -0,0 +1,10 @@
#![feature(type_alias_enum_variants)]
enum E {
V
}
fn check() -> <E>::V {}
//~^ ERROR expected type, found variant `V`
fn main() {}

View file

@ -0,0 +1,8 @@
error: expected type, found variant `V`
--> $DIR/type-alias-enum-variants-priority-3.rs:7:15
|
LL | fn check() -> <E>::V {}
| ^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,20 @@
#![feature(type_alias_enum_variants)]
#![deny(ambiguous_associated_items)]
enum E {
V
}
trait Tr {
type V;
fn f() -> Self::V;
}
impl Tr for E {
type V = u8;
fn f() -> Self::V { 0 }
//~^ ERROR ambiguous associated item
//~| WARN this was previously accepted
}
fn main() {}

View file

@ -0,0 +1,26 @@
error: ambiguous associated item
--> $DIR/type-alias-enum-variants-priority.rs:15:15
|
LL | fn f() -> Self::V { 0 }
| ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
|
note: lint level defined here
--> $DIR/type-alias-enum-variants-priority.rs:2:9
|
LL | #![deny(ambiguous_associated_items)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644>
note: `V` could refer to variant defined here
--> $DIR/type-alias-enum-variants-priority.rs:5:5
|
LL | V
| ^
note: `V` could also refer to associated type defined here
--> $DIR/type-alias-enum-variants-priority.rs:9:5
|
LL | type V;
| ^^^^^^^
error: aborting due to previous error