about summary refs log tree commit diff
path: root/tests/ui/structs/default-field-values
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/structs/default-field-values')
-rw-r--r--tests/ui/structs/default-field-values/auxiliary/struct_field_default.rs5
-rw-r--r--tests/ui/structs/default-field-values/failures.rs64
-rw-r--r--tests/ui/structs/default-field-values/failures.stderr118
-rw-r--r--tests/ui/structs/default-field-values/invalid-const.rs16
-rw-r--r--tests/ui/structs/default-field-values/invalid-const.stderr17
-rw-r--r--tests/ui/structs/default-field-values/support.rs100
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));
+}