diff options
Diffstat (limited to 'tests/ui/structs/default-field-values')
6 files changed, 320 insertions, 0 deletions
diff --git a/tests/ui/structs/default-field-values/auxiliary/struct_field_default.rs b/tests/ui/structs/default-field-values/auxiliary/struct_field_default.rs new file mode 100644 index 00000000000..b315df5dba2 --- /dev/null +++ b/tests/ui/structs/default-field-values/auxiliary/struct_field_default.rs @@ -0,0 +1,5 @@ +#![feature(default_field_values)] + +pub struct A { + pub a: isize = 42, +} diff --git a/tests/ui/structs/default-field-values/failures.rs b/tests/ui/structs/default-field-values/failures.rs new file mode 100644 index 00000000000..0ac071d91d6 --- /dev/null +++ b/tests/ui/structs/default-field-values/failures.rs @@ -0,0 +1,64 @@ +#![feature(default_field_values)] + +#[derive(Debug)] +pub struct S; + +#[derive(Debug, Default)] +pub struct Foo { + pub bar: S = S, + pub baz: i32 = 42 + 3, +} + +#[derive(Debug, Default)] +pub struct Bar { + pub bar: S, //~ ERROR the trait bound `S: Default` is not satisfied + pub baz: i32 = 42 + 3, +} + +#[derive(Default)] +pub struct Qux<const C: i32> { + bar: S = Self::S, //~ ERROR generic `Self` types are currently not permitted in anonymous constants + baz: i32 = foo(), + bat: i32 = <Qux<{ C }> as T>::K, //~ ERROR generic parameters may not be used in const operations + bay: i32 = C, +} + +pub struct Rak(i32 = 42); //~ ERROR default fields are not supported in tuple structs + +impl<const C: i32> Qux<C> { + const S: S = S; +} + +trait T { + const K: i32; +} + +impl<const C: i32> T for Qux<C> { + const K: i32 = 2; +} + +const fn foo() -> i32 { + 42 +} + +#[derive(Debug, Default)] +enum E { + #[default] + Variant {} //~ ERROR the `#[default]` attribute may only be used on unit enum variants +} + +fn main () { + let _ = Foo { .. }; // ok + let _ = Foo::default(); // ok + let _ = Bar { .. }; //~ ERROR mandatory field + let _ = Bar::default(); // silenced + let _ = Bar { bar: S, .. }; // ok + let _ = Qux::<4> { .. }; + let _ = Rak(..); //~ ERROR E0308 + //~^ you might have meant to use `..` to skip providing + let _ = Rak(0, ..); //~ ERROR E0061 + //~^ you might have meant to use `..` to skip providing + let _ = Rak(.., 0); //~ ERROR E0061 + //~^ you might have meant to use `..` to skip providing + let _ = Rak { .. }; // ok +} diff --git a/tests/ui/structs/default-field-values/failures.stderr b/tests/ui/structs/default-field-values/failures.stderr new file mode 100644 index 00000000000..65ec100fe2e --- /dev/null +++ b/tests/ui/structs/default-field-values/failures.stderr @@ -0,0 +1,118 @@ +error: the `#[default]` attribute may only be used on unit enum variants or variants where every field has a default value + --> $DIR/failures.rs:47:5 + | +LL | Variant {} + | ^^^^^^^ + | + = help: consider a manual implementation of `Default` + +error: generic parameters may not be used in const operations + --> $DIR/failures.rs:22:23 + | +LL | bat: i32 = <Qux<{ C }> as T>::K, + | ^ cannot perform const operation using `C` + | + = help: const parameters may only be used as standalone arguments, i.e. `C` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: default fields are not supported in tuple structs + --> $DIR/failures.rs:26:22 + | +LL | pub struct Rak(i32 = 42); + | ^^ default fields are only supported on structs + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/failures.rs:20:14 + | +LL | bar: S = Self::S, + | ^^^^ + +error[E0277]: the trait bound `S: Default` is not satisfied + --> $DIR/failures.rs:14:5 + | +LL | #[derive(Debug, Default)] + | ------- in this derive macro expansion +LL | pub struct Bar { +LL | pub bar: S, + | ^^^^^^^^^^ the trait `Default` is not implemented for `S` + | + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `S` with `#[derive(Default)]` + | +LL + #[derive(Default)] +LL | pub struct S; + | + +error: missing mandatory field `bar` + --> $DIR/failures.rs:53:21 + | +LL | let _ = Bar { .. }; + | ^ + +error[E0308]: mismatched types + --> $DIR/failures.rs:57:17 + | +LL | let _ = Rak(..); + | --- ^^ expected `i32`, found `RangeFull` + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/failures.rs:26:12 + | +LL | pub struct Rak(i32 = 42); + | ^^^ +help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal + --> $DIR/failures.rs:57:17 + | +LL | let _ = Rak(..); + | ^^ + +error[E0061]: this struct takes 1 argument but 2 arguments were supplied + --> $DIR/failures.rs:59:13 + | +LL | let _ = Rak(0, ..); + | ^^^ -- unexpected argument #2 of type `RangeFull` + | +help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal + --> $DIR/failures.rs:59:20 + | +LL | let _ = Rak(0, ..); + | ^^ +note: tuple struct defined here + --> $DIR/failures.rs:26:12 + | +LL | pub struct Rak(i32 = 42); + | ^^^ +help: remove the extra argument + | +LL - let _ = Rak(0, ..); +LL + let _ = Rak(0); + | + +error[E0061]: this struct takes 1 argument but 2 arguments were supplied + --> $DIR/failures.rs:61:13 + | +LL | let _ = Rak(.., 0); + | ^^^ -- unexpected argument #1 of type `RangeFull` + | +help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal + --> $DIR/failures.rs:61:17 + | +LL | let _ = Rak(.., 0); + | ^^ +note: tuple struct defined here + --> $DIR/failures.rs:26:12 + | +LL | pub struct Rak(i32 = 42); + | ^^^ +help: remove the extra argument + | +LL - let _ = Rak(.., 0); +LL + let _ = Rak(0); + | + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0061, E0277, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/structs/default-field-values/invalid-const.rs b/tests/ui/structs/default-field-values/invalid-const.rs new file mode 100644 index 00000000000..203a712868b --- /dev/null +++ b/tests/ui/structs/default-field-values/invalid-const.rs @@ -0,0 +1,16 @@ +#![feature(default_field_values, generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Bat { + pub bax: u8 = panic!("asdf"), + //~^ ERROR evaluation of constant value failed +} + +pub struct Baz<const C: u8> { + pub bax: u8 = 130 + C, // ok + pub bat: u8 = 130 + 130, + //~^ ERROR evaluation of `Baz::<C>::bat::{constant#0}` failed + pub bay: u8 = 1, // ok +} + +fn main() {} diff --git a/tests/ui/structs/default-field-values/invalid-const.stderr b/tests/ui/structs/default-field-values/invalid-const.stderr new file mode 100644 index 00000000000..f4a3437031b --- /dev/null +++ b/tests/ui/structs/default-field-values/invalid-const.stderr @@ -0,0 +1,17 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-const.rs:5:19 + | +LL | pub bax: u8 = panic!("asdf"), + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'asdf', $DIR/invalid-const.rs:5:19 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of `Baz::<C>::bat::{constant#0}` failed + --> $DIR/invalid-const.rs:11:19 + | +LL | pub bat: u8 = 130 + 130, + | ^^^^^^^^^ attempt to compute `130_u8 + 130_u8`, which would overflow + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/structs/default-field-values/support.rs b/tests/ui/structs/default-field-values/support.rs new file mode 100644 index 00000000000..8209d6dd4a0 --- /dev/null +++ b/tests/ui/structs/default-field-values/support.rs @@ -0,0 +1,100 @@ +// Exercise the `default_field_values` feature to confirm it interacts correctly with other nightly +// features. In particular, we want to verify that interaction with consts coming from different +// contexts are usable as a default field value. +//@ run-pass +//@ aux-build:struct_field_default.rs +#![feature(const_trait_impl, default_field_values, generic_const_exprs)] +#![allow(unused_variables, dead_code, incomplete_features)] + +extern crate struct_field_default as xc; + +pub struct S; + +// Basic expressions and `Default` expansion +#[derive(Default)] +pub struct Foo { + pub bar: S = S, + pub baz: i32 = 42 + 3, +} + +// Enum support for deriving `Default` when all fields have default values +#[derive(Default)] +pub enum Bar { + #[default] + Foo { + bar: S = S, + baz: i32 = 42 + 3, + } +} + +#[const_trait] pub trait ConstDefault { + fn value() -> Self; +} + +impl const ConstDefault for i32 { + fn value() -> i32 { + 101 + } +} + +pub struct Qux<A, const C: i32, X: const ConstDefault> { + bar: S = Qux::<A, C, X>::S, // Associated constant from inherent impl + baz: i32 = foo(), // Constant function + bat: i32 = <Qux<A, C, X> as T>::K, // Associated constant from explicit trait + baq: i32 = Self::K, // Associated constant from implicit trait + bay: i32 = C, // `const` parameter + bak: Vec<A> = Vec::new(), // Associated constant function + ban: X = X::value(), // Associated constant function from `const` trait parameter +} + +impl<A, const C: i32, X: const ConstDefault> Qux<A, C, X> { + const S: S = S; +} + +trait T { + const K: i32; +} + +impl<A, const C: i32, X: const ConstDefault> T for Qux<A, C, X> { + const K: i32 = 2; +} + +const fn foo() -> i32 { + 42 +} + +fn main () { + let x = Foo { .. }; + let y = Foo::default(); + let z = Foo { baz: 1, .. }; + + assert_eq!(45, x.baz); + assert_eq!(45, y.baz); + assert_eq!(1, z.baz); + + let x = Bar::Foo { .. }; + let y = Bar::default(); + let z = Bar::Foo { baz: 1, .. }; + + assert!(matches!(Bar::Foo { bar: S, baz: 45 }, x)); + assert!(matches!(Bar::Foo { bar: S, baz: 45 }, y)); + assert!(matches!(Bar::Foo { bar: S, baz: 1 }, z)); + + let x = Qux::<i32, 4, i32> { .. }; + assert!(matches!( + Qux::<i32, 4, i32> { + bar: S, + baz: 42, + bat: 2, + baq: 2, + bay: 4, + ban: 101, + .. + }, + x, + )); + assert!(x.bak.is_empty()); + + let x = xc::A { .. }; + assert!(matches!(xc::A { a: 42 }, x)); +} |
