rust/tests/ui/structs/default-field-values-support.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

69 lines
1.3 KiB
Rust
Raw Normal View History

Introduce `default_field_values` feature Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681. Support default fields in enum struct variant Allow default values in an enum struct variant definition: ```rust pub enum Bar { Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Allow using `..` without a base on an enum struct variant ```rust Bar::Foo { .. } ``` `#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants. Support `#[derive(Default)]` on enum struct variants with all defaulted fields ```rust pub enum Bar { #[default] Foo { bar: S = S, baz: i32 = 42 + 3, } } ``` Check for missing fields in typeck instead of mir_build. Expand test with `const` param case (needs `generic_const_exprs` enabled). Properly instantiate MIR const The following works: ```rust struct S<A> { a: Vec<A> = Vec::new(), } S::<i32> { .. } ``` Add lint for default fields that will always fail const-eval We *allow* this to happen for API writers that might want to rely on users' getting a compile error when using the default field, different to the error that they would get when the field isn't default. We could change this to *always* error instead of being a lint, if we wanted. This will *not* catch errors for partially evaluated consts, like when the expression relies on a const parameter. Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`: - Suggest adding a base expression if there are missing fields. - Suggest enabling the feature if all the missing fields have optional values. - Suggest removing `..` if there are no missing fields.
2024-08-24 17:22:48 +00:00
//@ run-pass
#![feature(default_field_values, generic_const_exprs)]
#![allow(unused_variables, dead_code, incomplete_features)]
pub struct S;
#[derive(Default)]
pub struct Foo {
pub bar: S = S,
pub baz: i32 = 42 + 3,
}
#[derive(Default)]
pub enum Bar {
#[default]
Foo {
bar: S = S,
baz: i32 = 42 + 3,
}
}
#[derive(Default)]
pub struct Qux<A, const C: i32> {
bar: S = Qux::<A, C>::S,
baz: i32 = foo(),
bat: i32 = <Qux<A, C> as T>::K,
baq: i32 = Self::K,
bay: i32 = C,
bak: Vec<A> = Vec::new(),
}
impl<A, const C: i32> Qux<A, C> {
const S: S = S;
}
trait T {
const K: i32;
}
impl<A, const C: i32> T for Qux<A, C> {
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> { .. };
assert!(matches!(Qux::<i32, 4> { bar: S, baz: 42, bat: 2, baq: 2, bay: 4, .. }, x));
assert!(x.bak.is_empty());
}