diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2021-11-09 19:00:41 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-09 19:00:41 +0100 |
| commit | 610b4e503ccc5cb6d4ef98bb5016ba42eaf94522 (patch) | |
| tree | c8db226e573691cc2ffcd379127dc226d48bd564 /src | |
| parent | fd74c93403c455187c343f3828274824addc9881 (diff) | |
| parent | 926892ddc0b75b50f5d0a3483d829e501aa8e895 (diff) | |
| download | rust-610b4e503ccc5cb6d4ef98bb5016ba42eaf94522.tar.gz rust-610b4e503ccc5cb6d4ef98bb5016ba42eaf94522.zip | |
Rollup merge of #90035 - SparrowLii:rfc2528, r=jackh726
implement rfc-2528 type_changing-struct-update This PR implement rfc2528-type_changing-struct-update. The main change process is as follows: 1. Move the processing part of `base_expr` into `check_expr_struct_fields` to avoid returning `remaining_fields` (a relatively complex hash table) 2. Before performing the type consistency check(`check_expr_has_type_or_error`), if the `type_changing_struct_update` feature is set, enter a different processing flow, otherwise keep the original flow 3. In the case of the same structure definition, check each field in `remaining_fields`. If the field in `base_expr` is not the suptype of the field in `adt_ty`, an error(`FeildMisMatch`) will be reported. The MIR part does not need to be changed, because only the items contained in `remaining_fields` will be extracted from `base_expr` when MIR is generated. This means that fields with different types in `base_expr` will not be used Updates #86618 cc `@nikomatsakis`
Diffstat (limited to 'src')
| -rw-r--r-- | src/doc/unstable-book/src/language-features/type-changing-struct-update.md | 33 | ||||
| -rw-r--r-- | src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr | 12 | ||||
| -rw-r--r-- | src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs (renamed from src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs) | 7 | ||||
| -rw-r--r-- | src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr | 22 | ||||
| -rw-r--r-- | src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs | 43 | ||||
| -rw-r--r-- | src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr | 15 | ||||
| -rw-r--r-- | src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs | 57 | ||||
| -rw-r--r-- | src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr | 30 |
8 files changed, 205 insertions, 14 deletions
diff --git a/src/doc/unstable-book/src/language-features/type-changing-struct-update.md b/src/doc/unstable-book/src/language-features/type-changing-struct-update.md new file mode 100644 index 00000000000..9909cf35b5b --- /dev/null +++ b/src/doc/unstable-book/src/language-features/type-changing-struct-update.md @@ -0,0 +1,33 @@ +# `type_changing_struct_update` + +The tracking issue for this feature is: [#86555] + +[#86555]: https://github.com/rust-lang/rust/issues/86555 + +------------------------ + +This implements [RFC2528]. When turned on, you can create instances of the same struct +that have different generic type or lifetime parameters. + +[RFC2528]: https://github.com/rust-lang/rfcs/blob/master/text/2528-type-changing-struct-update-syntax.md + +```rust +#![allow(unused_variables, dead_code)] +#![feature(type_changing_struct_update)] + +fn main () { + struct Foo<T, U> { + field1: T, + field2: U, + } + + let base: Foo<String, i32> = Foo { + field1: String::from("hello"), + field2: 1234, + }; + let updated: Foo<f64, i32> = Foo { + field1: 3.14, + ..base + }; +} +``` diff --git a/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr b/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr deleted file mode 100644 index 9934fe68164..00000000000 --- a/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/feature-gate-type_changing_struct_update.rs:20:11 - | -LL | ..m1 - | ^^ expected struct `State2`, found struct `State1` - | - = note: expected struct `Machine<State2>` - found struct `Machine<State1>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs index 520c1478f32..1e8b99ba564 100644 --- a/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs @@ -1,3 +1,5 @@ +// gate-test-type_changing_struct_update + #[derive(Debug)] struct Machine<S> { state: S, @@ -17,9 +19,10 @@ fn update_to_state2() { }; let m2: Machine<State2> = Machine { state: State2, - ..m1 //~ ERROR mismatched types + ..m1 + //~^ ERROR type changing struct updating is experimental [E0658] + //~| ERROR mismatched types [E0308] }; - // FIXME: this should trigger feature gate assert_eq!(State2, m2.state); } diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr new file mode 100644 index 00000000000..2217b8c0498 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr @@ -0,0 +1,22 @@ +error[E0658]: type changing struct updating is experimental + --> $DIR/feature-gate.rs:22:11 + | +LL | ..m1 + | ^^ + | + = note: see issue #86555 <https://github.com/rust-lang/rust/issues/86555> for more information + = help: add `#![feature(type_changing_struct_update)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/feature-gate.rs:22:11 + | +LL | ..m1 + | ^^ expected struct `State2`, found struct `State1` + | + = note: expected struct `Machine<State2>` + found struct `Machine<State1>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs new file mode 100644 index 00000000000..df2fef55dd2 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs @@ -0,0 +1,43 @@ +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +#[derive(Clone)] +struct Machine<'a, S> { + state: S, + lt_str: &'a str, + common_field: i32, +} + +#[derive(Clone)] +struct State1; +#[derive(Clone)] +struct State2; + +fn update_to_state2() { + let s = String::from("hello"); + let m1: Machine<State1> = Machine { + state: State1, + lt_str: &s, + //~^ ERROR `s` does not live long enough [E0597] + // FIXME: The error here actually comes from line 34. The + // span of the error message should be corrected to line 34 + common_field: 2, + }; + // update lifetime + let m3: Machine<'static, State1> = Machine { + lt_str: "hello, too", + ..m1.clone() + }; + // update lifetime and type + let m4: Machine<'static, State2> = Machine { + state: State2, + lt_str: "hello, again", + ..m1.clone() + }; + // updating to `static should fail. + let m2: Machine<'static, State1> = Machine { + ..m1 + }; +} + +fn main() {} diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr new file mode 100644 index 00000000000..5f93ad6e027 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr @@ -0,0 +1,15 @@ +error[E0597]: `s` does not live long enough + --> $DIR/lifetime-update.rs:20:17 + | +LL | lt_str: &s, + | ^^ borrowed value does not live long enough +... +LL | let m2: Machine<'static, State1> = Machine { + | ------------------------ type annotation requires that `s` is borrowed for `'static` +... +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs new file mode 100644 index 00000000000..d8b1396a692 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs @@ -0,0 +1,57 @@ +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +struct Machine<'a, S, M> { + state: S, + message: M, + lt_str: &'a str, + common_field: i32, +} + +struct State1; +struct State2; + +struct Message1; +struct Message2; + +fn update() { + let m1: Machine<State1, Message1> = Machine { + state: State1, + message: Message1, + lt_str: "hello", + common_field: 2, + }; + // single type update + let m2: Machine<State2, Message1> = Machine { + state: State2, + ..m1 + }; + // multiple type update + let m3: Machine<State2, Message2> = Machine { + state: State2, + message: Message2, + ..m1 + }; +} + +fn fail_update() { + let m1: Machine<f64, f64> = Machine { + state: 3.2, + message: 6.4, + lt_str: "hello", + common_field: 2, + }; + // single type update fail + let m2: Machine<i32, f64> = Machine { + ..m1 + //~^ ERROR mismatched types [E0308] + }; + // multiple type update fail + let m3 = Machine::<i32, i32> { + ..m1 + //~^ ERROR mismatched types [E0308] + //~| ERROR mismatched types [E0308] + }; +} + +fn main() {} diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr new file mode 100644 index 00000000000..fa8d6ee23d5 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/type-generic-update.rs:46:11 + | +LL | ..m1 + | ^^ field type mismatch: Machine.state + | + = note: expected type `i32` + found type `f64` + +error[E0308]: mismatched types + --> $DIR/type-generic-update.rs:51:11 + | +LL | ..m1 + | ^^ field type mismatch: Machine.state + | + = note: expected type `i32` + found type `f64` + +error[E0308]: mismatched types + --> $DIR/type-generic-update.rs:51:11 + | +LL | ..m1 + | ^^ field type mismatch: Machine.message + | + = note: expected type `i32` + found type `f64` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. |
