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:
commit
5748825cc8
@ -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 } => {}
|
||||
}
|
||||
}
|
||||
```
|
@ -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"]
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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));
|
||||
}
|
@ -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));
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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]
|
||||
}
|
@ -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`.
|
@ -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
|
||||
}
|
@ -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`.
|
@ -1,10 +0,0 @@
|
||||
#![feature(type_alias_enum_variants)]
|
||||
|
||||
enum E {
|
||||
V
|
||||
}
|
||||
|
||||
fn check() -> <E>::V {}
|
||||
//~^ ERROR expected type, found variant `V`
|
||||
|
||||
fn main() {}
|
@ -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() {}
|
@ -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
|
||||
}
|
@ -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);
|
||||
}
|
@ -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]
|
||||
}
|
@ -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`.
|
@ -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
|
||||
}
|
@ -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`.
|
@ -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() {}
|
@ -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;
|
||||
| ^^^^^^^
|
@ -1,4 +1,3 @@
|
||||
#![feature(type_alias_enum_variants)]
|
||||
pub enum Enum {
|
||||
A(usize),
|
||||
}
|
@ -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 => (),
|
||||
| ^^^^^^^
|
@ -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]
|
||||
}
|
@ -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`.
|
@ -1,7 +1,5 @@
|
||||
// compile-pass
|
||||
|
||||
#![feature(type_alias_enum_variants)]
|
||||
|
||||
enum Outer<T> {
|
||||
A(T)
|
||||
}
|
@ -3,8 +3,6 @@
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(type_alias_enum_variants)]
|
||||
|
||||
enum Opt<T> {
|
||||
N,
|
||||
S(T),
|
||||
|
@ -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
|
||||
}
|
@ -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
|
@ -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() {}
|
@ -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 {}
|
||||
| ^^^^^^
|
@ -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));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user