Auto merge of #61682 - Centril:stabilize-type_alias_enum_variants, r=petrochenkov

Stabilize `type_alias_enum_variants` in Rust 1.37.0

Stabilize `#![feature(type_alias_enum_variants)]` which allows type-relative resolution with highest priority to `enum` variants in both expression and pattern contexts. For example, you may now write:

```rust
enum Option<T> {
    None,
    Some(T),
}

type OptAlias<T> = Option<T>;

fn work_on_alias(x: Option<u8>) -> u8 {
    match x {
        OptAlias::Some(y) => y + 1,
        OptAlias::None => 0,
    }
}
```

Closes https://github.com/rust-lang/rfcs/issues/2218
Closes https://github.com/rust-lang/rust/issues/52118

r? @petrochenkov
This commit is contained in:
bors 2019-07-01 03:11:19 +00:00
commit 5748825cc8
35 changed files with 399 additions and 323 deletions

View File

@ -1,36 +0,0 @@
# `type_alias_enum_variants`
The tracking issue for this feature is: [#49683]
[#49683]: https://github.com/rust-lang/rust/issues/49683
------------------------
The `type_alias_enum_variants` feature enables the use of variants on type
aliases that refer to enums, as both a constructor and a pattern. That is,
it allows for the syntax `EnumAlias::Variant`, which behaves exactly the same
as `Enum::Variant` (assuming that `EnumAlias` is an alias for some enum type
`Enum`).
Note that since `Self` exists as a type alias, this feature also enables the
use of the syntax `Self::Variant` within an impl block for an enum type.
```rust
#![feature(type_alias_enum_variants)]
enum Foo {
Bar(i32),
Baz { i: i32 },
}
type Alias = Foo;
fn main() {
let t = Alias::Bar(0);
let t = Alias::Baz { i: 0 };
match t {
Alias::Bar(_i) => {}
Alias::Baz { i: _i } => {}
}
}
```

View File

@ -6,7 +6,7 @@
#![feature(label_break_value)]
#![feature(nll)]
#![feature(rustc_diagnostic_macros)]
#![feature(type_alias_enum_variants)]
#![cfg_attr(bootstrap, feature(type_alias_enum_variants))]
#![recursion_limit="256"]

View File

@ -34,7 +34,6 @@ use std::collections::BTreeSet;
use std::iter;
use std::slice;
use super::{check_type_alias_enum_variants_enabled};
use rustc_data_structures::fx::FxHashSet;
#[derive(Debug)]
@ -1595,7 +1594,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
});
if let Some(variant_def) = variant_def {
if permit_variants {
check_type_alias_enum_variants_enabled(tcx, span);
tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
} else {

View File

@ -26,7 +26,6 @@ use rustc::infer::{self, InferOk};
use syntax::ast;
use syntax_pos::Span;
use crate::{check_type_alias_enum_variants_enabled};
use self::probe::{IsSuggestion, ProbeScope};
pub fn provide(providers: &mut ty::query::Providers<'_>) {
@ -417,8 +416,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
});
if let Some(variant_def) = variant_def {
check_type_alias_enum_variants_enabled(tcx, span);
// Braced variants generate unusable names in value namespace (reserved for
// possible future use), so variants resolved as associated items may refer to
// them as well. It's ok to use the variant's id as a ctor id since an

View File

@ -105,7 +105,7 @@ use rustc::lint;
use rustc::middle;
use rustc::session;
use rustc::util::common::ErrorReported;
use rustc::session::config::{EntryFnType, nightly_options};
use rustc::session::config::EntryFnType;
use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt};
@ -124,21 +124,6 @@ pub struct TypeAndSubsts<'tcx> {
ty: Ty<'tcx>,
}
fn check_type_alias_enum_variants_enabled<'tcx>(tcx: TyCtxt<'tcx>, span: Span) {
if !tcx.features().type_alias_enum_variants {
let mut err = tcx.sess.struct_span_err(
span,
"enum variants on type aliases are experimental"
);
if nightly_options::is_nightly_build() {
help!(&mut err,
"add `#![feature(type_alias_enum_variants)]` to the \
crate attributes to enable");
}
err.emit();
}
}
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl, abi: Abi, span: Span) {
if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
let mut err = struct_span_err!(tcx.sess, span, E0045,

View File

@ -530,9 +530,6 @@ declare_features! (
// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
(active, lint_reasons, "1.31.0", Some(54503), None),
// Allows paths to enum variants on type aliases.
(active, type_alias_enum_variants, "1.31.0", Some(49683), None),
// Allows exhaustive integer pattern matching on `usize` and `isize`.
(active, precise_pointer_size_matching, "1.32.0", Some(56354), None),
@ -853,6 +850,8 @@ declare_features! (
(accepted, extern_crate_self, "1.34.0", Some(56409), None),
// Allows arbitrary delimited token streams in non-macro attributes.
(accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None),
// Allows paths to enum variants on type aliases including `Self`.
(accepted, type_alias_enum_variants, "1.37.0", Some(49683), None),
// Allows using `#[repr(align(X))]` on enums with equivalent semantics
// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`.
(accepted, repr_align_enum, "1.37.0", Some(57996), None),

View File

@ -1,30 +0,0 @@
#![feature(type_alias_enum_variants)]
#[derive(Debug, PartialEq, Eq)]
enum Foo {
Bar(i32),
Baz { i: i32 },
}
type FooAlias = Foo;
type OptionAlias = Option<i32>;
impl Foo {
fn foo() -> Self {
Self::Bar(3)
}
}
fn main() {
let t = FooAlias::Bar(1);
assert_eq!(t, Foo::Bar(1));
let t = FooAlias::Baz { i: 2 };
assert_eq!(t, Foo::Baz { i: 2 });
match t {
FooAlias::Bar(_i) => {}
FooAlias::Baz { i } => { assert_eq!(i, 2); }
}
assert_eq!(Foo::foo(), Foo::Bar(3));
assert_eq!(OptionAlias::Some(4), Option::Some(4));
}

View File

@ -1,30 +0,0 @@
#![feature(type_alias_enum_variants)]
#[derive(Debug, PartialEq, Eq)]
enum Foo {
Bar(i32),
Baz { i: i32 },
}
type FooAlias = Foo;
type OptionAlias = Option<i32>;
impl Foo {
fn foo() -> Self {
Self::Bar(3)
}
}
fn main() {
let t = FooAlias::Bar(1);
assert_eq!(t, Foo::Bar(1));
let t = FooAlias::Baz { i: 2 };
assert_eq!(t, Foo::Baz { i: 2 });
match t {
FooAlias::Bar(_i) => {}
FooAlias::Baz { i } => { assert_eq!(i, 2); }
}
assert_eq!(Foo::foo(), Foo::Bar(3));
assert_eq!(OptionAlias::Some(4), Option::Some(4));
}

View File

@ -1,19 +0,0 @@
enum Foo {
Bar(i32),
Baz { i: i32 },
}
type Alias = Foo;
fn main() {
let t = Alias::Bar(0);
//~^ ERROR enum variants on type aliases are experimental
let t = Alias::Baz { i: 0 };
//~^ ERROR enum variants on type aliases are experimental
match t {
Alias::Bar(_i) => {}
//~^ ERROR enum variants on type aliases are experimental
Alias::Baz { i: _i } => {}
//~^ ERROR enum variants on type aliases are experimental
}
}

View File

@ -1,34 +0,0 @@
error: enum variants on type aliases are experimental
--> $DIR/feature-gate-type_alias_enum_variants.rs:9:13
|
LL | let t = Alias::Bar(0);
| ^^^^^^^^^^
|
= help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
error: enum variants on type aliases are experimental
--> $DIR/feature-gate-type_alias_enum_variants.rs:11:13
|
LL | let t = Alias::Baz { i: 0 };
| ^^^^^^^^^^
|
= help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
error: enum variants on type aliases are experimental
--> $DIR/feature-gate-type_alias_enum_variants.rs:14:9
|
LL | Alias::Bar(_i) => {}
| ^^^^^^^^^^^^^^
|
= help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
error: enum variants on type aliases are experimental
--> $DIR/feature-gate-type_alias_enum_variants.rs:16:9
|
LL | Alias::Baz { i: _i } => {}
| ^^^^^^^^^^
|
= help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
error: aborting due to 4 previous errors

View File

@ -1,17 +0,0 @@
// ignore-tidy-linelength
#![feature(type_alias_enum_variants)]
#![allow(unreachable_code)]
enum Enum { Variant {} }
type Alias = Enum;
fn main() {
Alias::Variant;
//~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533]
let Alias::Variant = panic!();
//~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533]
let Alias::Variant(..) = panic!();
//~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Variant` [E0164]
}

View File

@ -1,21 +0,0 @@
error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant`
--> $DIR/type-alias-enum-variants-panic.rs:11:5
|
LL | Alias::Variant;
| ^^^^^^^^^^^^^^
error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant`
--> $DIR/type-alias-enum-variants-panic.rs:13:9
|
LL | let Alias::Variant = panic!();
| ^^^^^^^^^^^^^^
error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Variant`
--> $DIR/type-alias-enum-variants-panic.rs:15:9
|
LL | let Alias::Variant(..) = panic!();
| ^^^^^^^^^^^^^^^^^^ not a tuple variant or struct
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0164`.

View File

@ -1,13 +0,0 @@
#![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

@ -1,12 +0,0 @@
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();
| ^^^^^^^^ expected 1 parameter
error: aborting due to previous error
For more information about this error, try `rustc --explain E0061`.

View File

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

View File

@ -1,19 +0,0 @@
#![feature(type_alias_enum_variants)]
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

@ -1,11 +0,0 @@
#![feature(type_alias_enum_variants)]
type Alias<T> = Option<T>;
fn main() {
let _ = Option::<u8>::None; // OK
let _ = Option::None::<u8>; // OK (Lint in future!)
let _ = Alias::<u8>::None; // OK
let _ = Alias::None::<u8>; // Error
//~^ type arguments are not allowed for this type
}

View File

@ -1,17 +1,22 @@
// run-pass
#![feature(type_alias_enum_variants)]
// Check that resolving, in the value namespace, to an `enum` variant
// through a type alias is well behaved in the presence of generics.
// We check for situations with:
// 1. a generic type `Alias<T>`, we can type-apply `Alias` when referring to a variant.
// 2. a monotype `AliasFixed` of generic `Enum<T>`, we can refer to variants
// and the type-application of `T` in `AliasFixed` is kept.
#![allow(irrefutable_let_patterns)]
#[allow(dead_code)]
enum Enum<T> { TSVariant(T), SVariant { v: T } }
enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
type Alias<T> = Enum<T>;
type AliasFixed = Enum<()>;
macro_rules! is_variant {
(TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr));
(SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr));
(UVariant, $expr:expr) => (is_variant!(@check UVariant, {}, $expr));
(@check $variant:ident, $matcher:tt, $expr:expr) => (
assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false },
"expr does not have correct type");
@ -40,4 +45,15 @@ fn main() {
is_variant!(SVariant, Alias::<()>::SVariant { v: () });
is_variant!(SVariant, AliasFixed::SVariant { v: () });
// Unit variant
is_variant!(UVariant, Enum::UVariant);
is_variant!(UVariant, Enum::UVariant::<()>);
is_variant!(UVariant, Enum::<()>::UVariant);
is_variant!(UVariant, Alias::UVariant);
is_variant!(UVariant, Alias::<()>::UVariant);
is_variant!(UVariant, AliasFixed::UVariant);
}

View File

@ -1,6 +1,10 @@
#![feature(type_alias_enum_variants)]
// Checks that applied type arguments of enums, and aliases to them, are respected.
// For example, `Self` is never a type constructor. Therefore, no types can be applied to it.
//
// We also check that the variant to an type-aliased enum cannot be type applied whether
// that alias is generic or monomorphic.
enum Enum<T> { TSVariant(T), SVariant { v: T } }
enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
type Alias<T> = Enum<T>;
type AliasFixed = Enum<()>;
@ -32,6 +36,16 @@ impl<T> Enum<T> {
//~^^ ERROR type arguments are not allowed for this type [E0109]
//~^^^ ERROR mismatched types [E0308]
}
fn u_variant() {
Self::UVariant::<()>;
//~^ ERROR type arguments are not allowed for this type [E0109]
Self::<()>::UVariant;
//~^ ERROR type arguments are not allowed for this type [E0109]
Self::<()>::UVariant::<()>;
//~^ ERROR type arguments are not allowed for this type [E0109]
//~^^ ERROR type arguments are not allowed for this type [E0109]
}
}
fn main() {
@ -70,4 +84,22 @@ fn main() {
AliasFixed::<()>::SVariant::<()> { v: () };
//~^ ERROR type arguments are not allowed for this type [E0109]
//~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
// Unit variant
Enum::<()>::UVariant::<()>;
//~^ ERROR type arguments are not allowed for this type [E0109]
Alias::UVariant::<()>;
//~^ ERROR type arguments are not allowed for this type [E0109]
Alias::<()>::UVariant::<()>;
//~^ ERROR type arguments are not allowed for this type [E0109]
AliasFixed::UVariant::<()>;
//~^ ERROR type arguments are not allowed for this type [E0109]
AliasFixed::<()>::UVariant;
//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
AliasFixed::<()>::UVariant::<()>;
//~^ ERROR type arguments are not allowed for this type [E0109]
//~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
}

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/enum-variant-generic-args.rs:9:25
--> $DIR/enum-variant-generic-args.rs:13:25
|
LL | Self::TSVariant(());
| ^^ expected type parameter, found ()
@ -8,19 +8,19 @@ LL | Self::TSVariant(());
found type `()`
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:11:27
--> $DIR/enum-variant-generic-args.rs:15:27
|
LL | Self::TSVariant::<()>(());
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:13:16
--> $DIR/enum-variant-generic-args.rs:17:16
|
LL | Self::<()>::TSVariant(());
| ^^ type argument not allowed
error[E0308]: mismatched types
--> $DIR/enum-variant-generic-args.rs:13:31
--> $DIR/enum-variant-generic-args.rs:17:31
|
LL | Self::<()>::TSVariant(());
| ^^ expected type parameter, found ()
@ -29,19 +29,19 @@ LL | Self::<()>::TSVariant(());
found type `()`
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:16:16
--> $DIR/enum-variant-generic-args.rs:20:16
|
LL | Self::<()>::TSVariant::<()>(());
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:16:33
--> $DIR/enum-variant-generic-args.rs:20:33
|
LL | Self::<()>::TSVariant::<()>(());
| ^^ type argument not allowed
error[E0308]: mismatched types
--> $DIR/enum-variant-generic-args.rs:22:29
--> $DIR/enum-variant-generic-args.rs:26:29
|
LL | Self::SVariant { v: () };
| ^^ expected type parameter, found ()
@ -50,13 +50,13 @@ LL | Self::SVariant { v: () };
found type `()`
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:24:26
--> $DIR/enum-variant-generic-args.rs:28:26
|
LL | Self::SVariant::<()> { v: () };
| ^^ type argument not allowed
error[E0308]: mismatched types
--> $DIR/enum-variant-generic-args.rs:24:35
--> $DIR/enum-variant-generic-args.rs:28:35
|
LL | Self::SVariant::<()> { v: () };
| ^^ expected type parameter, found ()
@ -65,13 +65,13 @@ LL | Self::SVariant::<()> { v: () };
found type `()`
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:27:16
--> $DIR/enum-variant-generic-args.rs:31:16
|
LL | Self::<()>::SVariant { v: () };
| ^^ type argument not allowed
error[E0308]: mismatched types
--> $DIR/enum-variant-generic-args.rs:27:35
--> $DIR/enum-variant-generic-args.rs:31:35
|
LL | Self::<()>::SVariant { v: () };
| ^^ expected type parameter, found ()
@ -80,19 +80,19 @@ LL | Self::<()>::SVariant { v: () };
found type `()`
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:30:16
--> $DIR/enum-variant-generic-args.rs:34:16
|
LL | Self::<()>::SVariant::<()> { v: () };
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:30:32
--> $DIR/enum-variant-generic-args.rs:34:32
|
LL | Self::<()>::SVariant::<()> { v: () };
| ^^ type argument not allowed
error[E0308]: mismatched types
--> $DIR/enum-variant-generic-args.rs:30:41
--> $DIR/enum-variant-generic-args.rs:34:41
|
LL | Self::<()>::SVariant::<()> { v: () };
| ^^ expected type parameter, found ()
@ -101,90 +101,156 @@ LL | Self::<()>::SVariant::<()> { v: () };
found type `()`
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:40:29
--> $DIR/enum-variant-generic-args.rs:41:26
|
LL | Self::UVariant::<()>;
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:43:16
|
LL | Self::<()>::UVariant;
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:45:16
|
LL | Self::<()>::UVariant::<()>;
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:45:32
|
LL | Self::<()>::UVariant::<()>;
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:54:29
|
LL | Enum::<()>::TSVariant::<()>(());
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:43:24
--> $DIR/enum-variant-generic-args.rs:57:24
|
LL | Alias::TSVariant::<()>(());
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:45:30
--> $DIR/enum-variant-generic-args.rs:59:30
|
LL | Alias::<()>::TSVariant::<()>(());
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:48:29
--> $DIR/enum-variant-generic-args.rs:62:29
|
LL | AliasFixed::TSVariant::<()>(());
| ^^ type argument not allowed
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/enum-variant-generic-args.rs:50:18
--> $DIR/enum-variant-generic-args.rs:64:18
|
LL | AliasFixed::<()>::TSVariant(());
| ^^ unexpected type argument
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/enum-variant-generic-args.rs:52:18
--> $DIR/enum-variant-generic-args.rs:66:18
|
LL | AliasFixed::<()>::TSVariant::<()>(());
| ^^ unexpected type argument
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:52:35
--> $DIR/enum-variant-generic-args.rs:66:35
|
LL | AliasFixed::<()>::TSVariant::<()>(());
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:58:28
--> $DIR/enum-variant-generic-args.rs:72:28
|
LL | Enum::<()>::SVariant::<()> { v: () };
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:61:23
--> $DIR/enum-variant-generic-args.rs:75:23
|
LL | Alias::SVariant::<()> { v: () };
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:63:29
--> $DIR/enum-variant-generic-args.rs:77:29
|
LL | Alias::<()>::SVariant::<()> { v: () };
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:66:28
--> $DIR/enum-variant-generic-args.rs:80:28
|
LL | AliasFixed::SVariant::<()> { v: () };
| ^^ type argument not allowed
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/enum-variant-generic-args.rs:68:18
--> $DIR/enum-variant-generic-args.rs:82:18
|
LL | AliasFixed::<()>::SVariant { v: () };
| ^^ unexpected type argument
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/enum-variant-generic-args.rs:70:18
--> $DIR/enum-variant-generic-args.rs:84:18
|
LL | AliasFixed::<()>::SVariant::<()> { v: () };
| ^^ unexpected type argument
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:70:34
--> $DIR/enum-variant-generic-args.rs:84:34
|
LL | AliasFixed::<()>::SVariant::<()> { v: () };
| ^^ type argument not allowed
error: aborting due to 28 previous errors
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:90:28
|
LL | Enum::<()>::UVariant::<()>;
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:93:23
|
LL | Alias::UVariant::<()>;
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:95:29
|
LL | Alias::<()>::UVariant::<()>;
| ^^ type argument not allowed
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:98:28
|
LL | AliasFixed::UVariant::<()>;
| ^^ type argument not allowed
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/enum-variant-generic-args.rs:100:18
|
LL | AliasFixed::<()>::UVariant;
| ^^ unexpected type argument
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/enum-variant-generic-args.rs:102:18
|
LL | AliasFixed::<()>::UVariant::<()>;
| ^^ unexpected type argument
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:102:34
|
LL | AliasFixed::<()>::UVariant::<()>;
| ^^ type argument not allowed
error: aborting due to 39 previous errors
Some errors have detailed explanations: E0107, E0109, E0308.
For more information about an error, try `rustc --explain E0107`.

View File

@ -0,0 +1,23 @@
// Check that an `enum` variant is resolved, in the value namespace,
// with higher priority than other inherent items when there is a conflict.
enum E {
V(u8)
}
impl E {
fn V() {}
}
enum E2 {
V,
}
impl E2 {
const V: u8 = 0;
}
fn main() {
<E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
let _: u8 = <E2>::V; //~ ERROR mismatched types
}

View File

@ -0,0 +1,22 @@
error[E0061]: this function takes 1 parameter but 0 parameters were supplied
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
|
LL | V(u8)
| ----- defined here
...
LL | <E>::V();
| ^^^^^^^^ expected 1 parameter
error[E0308]: mismatched types
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
|
LL | let _: u8 = <E2>::V;
| ^^^^^^^ expected u8, found enum `E2`
|
= note: expected type `u8`
found type `E2`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0061, E0308.
For more information about an error, try `rustc --explain E0061`.

View File

@ -0,0 +1,37 @@
// Check that a projection `Self::V` in a trait implementation,
// with an associated type named `V`, for an `enum` with a variant named `V`,
// results in triggering the deny-by-default lint `ambiguous_associated_items`.
// The lint suggests that qualified syntax should be used instead.
// That is, the user would write `<Self as Tr>::V`.
//
// The rationale for this is that while `enum` variants do currently
// not exist in the type namespace but solely in the value namespace,
// RFC #2593 "Enum variant types", would add enum variants to the type namespace.
// However, currently `enum` variants are resolved with high priority as
// they are resolved as inherent associated items.
// Should #2953 therefore be implemented, `Self::V` would suddenly switch
// from referring to the associated type `V` instead of the variant `V`.
// The lint exists to keep us forward compatible with #2593.
//
// As a closing note, provided that #2933 was implemented and
// if `enum` variants were given lower priority than associated types,
// it would be impossible to refer to the `enum` variant `V` whereas
// the associated type could be referred to with qualified syntax as seen above.
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

@ -1,5 +1,5 @@
error: ambiguous associated item
--> $DIR/type-alias-enum-variants-priority.rs:14:15
--> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15
|
LL | fn f() -> Self::V { 0 }
| ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
@ -8,12 +8,12 @@ LL | fn f() -> Self::V { 0 }
= 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:4:5
--> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5
|
LL | V
| ^
note: `V` could also refer to associated type defined here
--> $DIR/type-alias-enum-variants-priority.rs:8:5
--> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5
|
LL | type V;
| ^^^^^^^

View File

@ -1,4 +1,3 @@
#![feature(type_alias_enum_variants)]
pub enum Enum {
A(usize),
}

View File

@ -1,5 +1,5 @@
error[E0533]: expected unit struct/variant or constant, found tuple variant `<Self>::A`
--> $DIR/issue-58006.rs:9:13
--> $DIR/incorrect-variant-form-through-Self-issue-58006.rs:8:13
|
LL | Self::A => (),
| ^^^^^^^

View File

@ -0,0 +1,21 @@
// ignore-tidy-linelength
// Check that creating/matching on an enum variant through an alias with
// the wrong braced/unit form is caught as an error.
enum Enum { Braced {}, Unit, Tuple() }
type Alias = Enum;
fn main() {
Alias::Braced;
//~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Braced` [E0533]
let Alias::Braced = panic!();
//~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Braced` [E0533]
let Alias::Braced(..) = panic!();
//~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Braced` [E0164]
Alias::Unit();
//~^ ERROR expected function, found enum variant `<Alias>::Unit`
let Alias::Unit() = panic!();
//~^ ERROR expected tuple struct/variant, found unit variant `<Alias>::Unit` [E0164]
}

View File

@ -0,0 +1,43 @@
error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Braced`
--> $DIR/incorrect-variant-form-through-alias-caught.rs:10:5
|
LL | Alias::Braced;
| ^^^^^^^^^^^^^
error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Braced`
--> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9
|
LL | let Alias::Braced = panic!();
| ^^^^^^^^^^^^^
error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Braced`
--> $DIR/incorrect-variant-form-through-alias-caught.rs:14:9
|
LL | let Alias::Braced(..) = panic!();
| ^^^^^^^^^^^^^^^^^ not a tuple variant or struct
error[E0618]: expected function, found enum variant `<Alias>::Unit`
--> $DIR/incorrect-variant-form-through-alias-caught.rs:17:5
|
LL | enum Enum { Braced {}, Unit, Tuple() }
| ---- `<Alias>::Unit` defined here
...
LL | Alias::Unit();
| ^^^^^^^^^^^--
| |
| call expression requires function
help: `<Alias>::Unit` is a unit variant, you need to write it without the parenthesis
|
LL | <Alias>::Unit;
| ^^^^^^^^^^^^^
error[E0164]: expected tuple struct/variant, found unit variant `<Alias>::Unit`
--> $DIR/incorrect-variant-form-through-alias-caught.rs:19:9
|
LL | let Alias::Unit() = panic!();
| ^^^^^^^^^^^^^ not a tuple variant or struct
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0164, E0618.
For more information about an error, try `rustc --explain E0164`.

View File

@ -1,7 +1,5 @@
// compile-pass
#![feature(type_alias_enum_variants)]
enum Outer<T> {
A(T)
}

View File

@ -3,8 +3,6 @@
// compile-pass
#![feature(type_alias_enum_variants)]
enum Opt<T> {
N,
S(T),

View File

@ -0,0 +1,14 @@
// Check that a generic type for an `enum` admits type application
// on both the type constructor and the generic type's variant.
//
// Also check that a type alias to said generic type admits type application
// on the type constructor but *NOT* the variant.
type Alias<T> = Option<T>;
fn main() {
let _ = Option::<u8>::None; // OK
let _ = Option::None::<u8>; // OK (Lint in future!)
let _ = Alias::<u8>::None; // OK
let _ = Alias::None::<u8>; //~ ERROR type arguments are not allowed for this type
}

View File

@ -1,7 +1,7 @@
error[E0109]: type arguments are not allowed for this type
--> $DIR/type-alias-enum-variants.rs:9:27
--> $DIR/no-type-application-on-aliased-enum-variant.rs:13:27
|
LL | let _ = Alias::None::<u8>; // Error
LL | let _ = Alias::None::<u8>;
| ^^ type argument not allowed
error: aborting due to previous error

View File

@ -0,0 +1,11 @@
// Check that the compiler will resolve `<E>::V` to the variant `V` in the type namespace
// but will reject this because `enum` variants do not exist in the type namespace.
enum E {
V
}
fn check() -> <E>::V {}
//~^ ERROR expected type, found variant `V`
fn main() {}

View File

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

View File

@ -0,0 +1,69 @@
// run-pass
// Check that it is possible to resolve, in the value namespace,
// to an `enum` variant through a type alias. This includes `Self`.
// Type qualified syntax `<Type>::Variant` also works when syntactically valid.
#[derive(Debug, PartialEq, Eq)]
enum Foo {
Bar(i32),
Baz { i: i32 },
Qux,
}
type FooAlias = Foo;
type OptionAlias = Option<i32>;
macro_rules! check_pat {
($x:expr, $p:pat) => {
assert!(if let $p = $x { true } else { false });
};
}
impl Foo {
fn bar() -> Self {
let x = Self::Bar(3);
assert_eq!(x, <Self>::Bar(3));
check_pat!(x, Self::Bar(3));
x
}
fn baz() -> Self {
let x = Self::Baz { i: 42 };
check_pat!(x, Self::Baz { i: 42 });
x
}
fn qux() -> Self {
let x = Self::Qux;
assert_eq!(x, <Self>::Qux);
check_pat!(x, Self::Qux);
check_pat!(x, <Self>::Qux);
x
}
}
fn main() {
let bar = Foo::Bar(1);
assert_eq!(bar, FooAlias::Bar(1));
assert_eq!(bar, <FooAlias>::Bar(1));
check_pat!(bar, FooAlias::Bar(1));
let baz = FooAlias::Baz { i: 2 };
assert_eq!(baz, Foo::Baz { i: 2 });
check_pat!(baz, FooAlias::Baz { i: 2 });
let qux = Foo::Qux;
assert_eq!(qux, FooAlias::Qux);
assert_eq!(qux, <FooAlias>::Qux);
check_pat!(qux, FooAlias::Qux);
check_pat!(qux, <FooAlias>::Qux);
assert_eq!(Foo::bar(), Foo::Bar(3));
assert_eq!(Foo::baz(), Foo::Baz { i: 42 });
assert_eq!(Foo::qux(), Foo::Qux);
let some = Option::Some(4);
assert_eq!(some, OptionAlias::Some(4));
check_pat!(some, OptionAlias::Some(4));
}