about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-11-09 19:00:41 +0100
committerGitHub <noreply@github.com>2021-11-09 19:00:41 +0100
commit610b4e503ccc5cb6d4ef98bb5016ba42eaf94522 (patch)
treec8db226e573691cc2ffcd379127dc226d48bd564 /src
parentfd74c93403c455187c343f3828274824addc9881 (diff)
parent926892ddc0b75b50f5d0a3483d829e501aa8e895 (diff)
downloadrust-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.md33
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr12
-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.stderr22
-rw-r--r--src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs43
-rw-r--r--src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr15
-rw-r--r--src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs57
-rw-r--r--src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr30
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`.