about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2021-02-05 12:25:52 +0100
committerGitHub <noreply@github.com>2021-02-05 12:25:52 +0100
commit676ff77fb7bd45aaa56ff636fdaee3a084c23c1f (patch)
tree4d6c2ec0130435a594a51f16a14d66c387c50356 /src
parentdeec6a96d428d20250bfad2317c00fc67e4b70f0 (diff)
parent031cce8cfc7fef922989e8b820da236ee17e016a (diff)
downloadrust-676ff77fb7bd45aaa56ff636fdaee3a084c23c1f.tar.gz
rust-676ff77fb7bd45aaa56ff636fdaee3a084c23c1f.zip
Rollup merge of #80726 - lcnr:unsize-query, r=oli-obk
relax adt unsizing requirements

Changes unsizing of structs in case the last struct field shares generic params with other adt fields which do not change.
This change is currently insta stable and changes the language, so it at least requires a lang fcp. I feel like the current state is fairly unintuitive.

An example for what's now allowed would be https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=6dd331d23f5c9ffc8c978175aae2e967
```rust
struct A<T, U: ?Sized>(T, B<T, U>); // previously ERR
// struct A<T, U: ?Sized>(T, B<[u32; 1], U>); // ok
struct B<T, U: ?Sized>(T, U);

fn main() {
    let x = A([0; 1], B([0; 1], [0; 1]));
    let y: &A<[u32; 1], [u32]> = &x;
    assert_eq!(y.1.1.len(), 1);
}
```
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs10
-rw-r--r--src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr14
-rw-r--r--src/test/ui/unsized/unchanged-param.rs12
3 files changed, 36 insertions, 0 deletions
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs
new file mode 100644
index 00000000000..0cfd0a0b978
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs
@@ -0,0 +1,10 @@
+// Test that we allow unsizing even if there is an unchanged param in the
+// field getting unsized.
+struct A<T, U: ?Sized + 'static>(T, B<T, U>);
+struct B<T, U: ?Sized>(T, U);
+
+fn main() {
+    let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
+    let y: &A<[u32; 1], [u32]> = &x; //~ ERROR mismatched types
+    assert_eq!(y.1.1.len(), 1);
+}
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr
new file mode 100644
index 00000000000..f62def47726
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-relaxed_struct_unsize.rs:8:34
+   |
+LL |     let y: &A<[u32; 1], [u32]> = &x;
+   |            -------------------   ^^ expected slice `[u32]`, found array `[u32; 1]`
+   |            |
+   |            expected due to this
+   |
+   = note: expected reference `&A<[u32; 1], [u32]>`
+              found reference `&A<[u32; 1], [u32; 1]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unsized/unchanged-param.rs b/src/test/ui/unsized/unchanged-param.rs
new file mode 100644
index 00000000000..83199e8112e
--- /dev/null
+++ b/src/test/ui/unsized/unchanged-param.rs
@@ -0,0 +1,12 @@
+#![feature(relaxed_struct_unsize)]
+// run-pass
+// Test that we allow unsizing even if there is an unchanged param in the
+// field getting unsized.
+struct A<T, U: ?Sized + 'static>(T, B<T, U>);
+struct B<T, U: ?Sized>(T, U);
+
+fn main() {
+    let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
+    let y: &A<[u32; 1], [u32]> = &x;
+    assert_eq!(y.1.1.len(), 1);
+}