| // 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, | |
| } | |
| } | |
| pub const trait ConstDefault { | |
| fn value() -> Self; | |
| } | |
| const impl 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> { .. }; | |
| #[rustfmt::skip] | |
| 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)); | |
| } |