summaryrefslogtreecommitdiffstats
path: root/src/test/ui/unsized
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/test/ui/unsized-locals/autoderef.rs49
-rw-r--r--src/test/ui/unsized-locals/auxiliary/ufuncs.rs3
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.rs43
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.stderr72
-rw-r--r--src/test/ui/unsized-locals/box-fnonce.rs10
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs25
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs23
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety.rs22
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety.stderr20
-rw-r--r--src/test/ui/unsized-locals/double-move.rs54
-rw-r--r--src/test/ui/unsized-locals/double-move.stderr78
-rw-r--r--src/test/ui/unsized-locals/issue-30276-feature-flagged.rs8
-rw-r--r--src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr22
-rw-r--r--src/test/ui/unsized-locals/issue-30276.rs5
-rw-r--r--src/test/ui/unsized-locals/issue-30276.stderr13
-rw-r--r--src/test/ui/unsized-locals/issue-50940-with-feature.rs8
-rw-r--r--src/test/ui/unsized-locals/issue-50940-with-feature.stderr26
-rw-r--r--src/test/ui/unsized-locals/issue-50940.rs5
-rw-r--r--src/test/ui/unsized-locals/issue-50940.stderr13
-rw-r--r--src/test/ui/unsized-locals/reference-unsized-locals.rs10
-rw-r--r--src/test/ui/unsized-locals/simple-unsized-locals.rs9
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs-rpass.rs33
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs.rs28
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs.stderr43
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs2.rs24
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs2.stderr12
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs3.rs10
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs3.stderr13
-rw-r--r--src/test/ui/unsized-locals/unsized-index.rs27
-rw-r--r--src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs15
-rw-r--r--src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr33
-rw-r--r--src/test/ui/unsized-locals/unsized-parameters.rs13
-rw-r--r--src/test/ui/unsized/box-instead-of-dyn-fn.rs15
-rw-r--r--src/test/ui/unsized/box-instead-of-dyn-fn.stderr42
-rw-r--r--src/test/ui/unsized/issue-30355.rs9
-rw-r--r--src/test/ui/unsized/issue-30355.stderr13
-rw-r--r--src/test/ui/unsized/issue-40231-1.rs54
-rw-r--r--src/test/ui/unsized/issue-40231-2.rs54
-rw-r--r--src/test/ui/unsized/issue-71659.rs32
-rw-r--r--src/test/ui/unsized/issue-71659.stderr18
-rw-r--r--src/test/ui/unsized/issue-75707.rs17
-rw-r--r--src/test/ui/unsized/issue-75707.stderr15
-rw-r--r--src/test/ui/unsized/issue-91801.rs19
-rw-r--r--src/test/ui/unsized/issue-91801.stderr15
-rw-r--r--src/test/ui/unsized/issue-91803.rs8
-rw-r--r--src/test/ui/unsized/issue-91803.stderr15
-rw-r--r--src/test/ui/unsized/issue-97732.rs28
-rw-r--r--src/test/ui/unsized/maybe-bounds-where-cpass.rs9
-rw-r--r--src/test/ui/unsized/maybe-bounds-where.rs28
-rw-r--r--src/test/ui/unsized/maybe-bounds-where.stderr51
-rw-r--r--src/test/ui/unsized/param-mentioned-by-different-field.rs10
-rw-r--r--src/test/ui/unsized/param-mentioned-by-different-field.stderr14
-rw-r--r--src/test/ui/unsized/return-unsized-from-trait-method.rs14
-rw-r--r--src/test/ui/unsized/return-unsized-from-trait-method.stderr9
-rw-r--r--src/test/ui/unsized/unchanged-param.rs11
-rw-r--r--src/test/ui/unsized/unsized-bare-typaram.rs4
-rw-r--r--src/test/ui/unsized/unsized-bare-typaram.stderr22
-rw-r--r--src/test/ui/unsized/unsized-enum.rs11
-rw-r--r--src/test/ui/unsized/unsized-enum.stderr29
-rw-r--r--src/test/ui/unsized/unsized-enum2.rs74
-rw-r--r--src/test/ui/unsized/unsized-enum2.stderr411
-rw-r--r--src/test/ui/unsized/unsized-fn-arg.fixed6
-rw-r--r--src/test/ui/unsized/unsized-fn-arg.rs6
-rw-r--r--src/test/ui/unsized/unsized-fn-arg.stderr22
-rw-r--r--src/test/ui/unsized/unsized-fn-param.rs20
-rw-r--r--src/test/ui/unsized/unsized-fn-param.stderr63
-rw-r--r--src/test/ui/unsized/unsized-inherent-impl-self-type.rs11
-rw-r--r--src/test/ui/unsized/unsized-inherent-impl-self-type.stderr29
-rw-r--r--src/test/ui/unsized/unsized-struct.rs18
-rw-r--r--src/test/ui/unsized/unsized-struct.stderr53
-rw-r--r--src/test/ui/unsized/unsized-trait-impl-self-type.rs14
-rw-r--r--src/test/ui/unsized/unsized-trait-impl-self-type.stderr29
-rw-r--r--src/test/ui/unsized/unsized-trait-impl-trait-arg.rs12
-rw-r--r--src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr26
-rw-r--r--src/test/ui/unsized/unsized-tuple-impls.rs21
-rw-r--r--src/test/ui/unsized/unsized.rs25
-rw-r--r--src/test/ui/unsized/unsized2.rs96
-rw-r--r--src/test/ui/unsized/unsized3-rpass.rs93
-rw-r--r--src/test/ui/unsized/unsized3.rs50
-rw-r--r--src/test/ui/unsized/unsized3.stderr159
-rw-r--r--src/test/ui/unsized/unsized5.rs34
-rw-r--r--src/test/ui/unsized/unsized5.stderr136
-rw-r--r--src/test/ui/unsized/unsized6.rs44
-rw-r--r--src/test/ui/unsized/unsized6.stderr222
-rw-r--r--src/test/ui/unsized/unsized7.rs16
-rw-r--r--src/test/ui/unsized/unsized7.stderr26
86 files changed, 3051 insertions, 0 deletions
diff --git a/src/test/ui/unsized-locals/autoderef.rs b/src/test/ui/unsized-locals/autoderef.rs
new file mode 100644
index 000000000..5dd5898c1
--- /dev/null
+++ b/src/test/ui/unsized-locals/autoderef.rs
@@ -0,0 +1,49 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
+
+pub trait Foo {
+ fn foo(self) -> String;
+}
+
+impl Foo for [char] {
+ fn foo(self) -> String {
+ self.iter().collect()
+ }
+}
+
+impl Foo for str {
+ fn foo(self) -> String {
+ self.to_owned()
+ }
+}
+
+impl Foo for dyn FnMut() -> String {
+ fn foo(mut self) -> String {
+ self()
+ }
+}
+
+fn main() {
+ let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>);
+ assert_eq!(&x.foo() as &str, "hello");
+
+ let x = Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>;
+ assert_eq!(&x.foo() as &str, "hello");
+
+ let x = "hello".to_owned().into_boxed_str();
+ assert_eq!(&x.foo() as &str, "hello");
+
+ let x = *("hello".to_owned().into_boxed_str());
+ assert_eq!(&x.foo() as &str, "hello");
+
+ let x = "hello".to_owned().into_boxed_str();
+ assert_eq!(&x.foo() as &str, "hello");
+
+ let x = *(Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>);
+ assert_eq!(&x.foo() as &str, "hello");
+
+ let x = Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>;
+ assert_eq!(&x.foo() as &str, "hello");
+}
diff --git a/src/test/ui/unsized-locals/auxiliary/ufuncs.rs b/src/test/ui/unsized-locals/auxiliary/ufuncs.rs
new file mode 100644
index 000000000..5954abf3a
--- /dev/null
+++ b/src/test/ui/unsized-locals/auxiliary/ufuncs.rs
@@ -0,0 +1,3 @@
+#![feature(unsized_locals, unsized_fn_params)]
+
+pub fn udrop<T: ?Sized>(_x: T) {}
diff --git a/src/test/ui/unsized-locals/borrow-after-move.rs b/src/test/ui/unsized-locals/borrow-after-move.rs
new file mode 100644
index 000000000..ad73b720f
--- /dev/null
+++ b/src/test/ui/unsized-locals/borrow-after-move.rs
@@ -0,0 +1,43 @@
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
+
+pub trait Foo {
+ fn foo(self) -> String;
+}
+
+impl Foo for str {
+ fn foo(self) -> String {
+ self.to_owned()
+ }
+}
+
+fn drop_unsized<T: ?Sized>(_: T) {}
+
+fn main() {
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ let y = *x;
+ drop_unsized(y);
+ println!("{}", &x);
+ //~^ERROR borrow of moved value
+ println!("{}", &y);
+ //~^ERROR borrow of moved value
+ }
+
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ let y = *x;
+ y.foo();
+ println!("{}", &x);
+ //~^ERROR borrow of moved value
+ println!("{}", &y);
+ //~^ERROR borrow of moved value
+ }
+
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ x.foo();
+ println!("{}", &x);
+ //~^ERROR borrow of moved value
+ }
+}
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
new file mode 100644
index 000000000..4f2bc06d4
--- /dev/null
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -0,0 +1,72 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/borrow-after-move.rs:1:12
+ |
+LL | #![feature(unsized_locals, unsized_fn_params)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
+error[E0382]: borrow of moved value: `x`
+ --> $DIR/borrow-after-move.rs:21:24
+ |
+LL | let y = *x;
+ | -- value moved here
+LL | drop_unsized(y);
+LL | println!("{}", &x);
+ | ^^ value borrowed here after move
+ |
+ = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `y`
+ --> $DIR/borrow-after-move.rs:23:24
+ |
+LL | let y = *x;
+ | - move occurs because `y` has type `str`, which does not implement the `Copy` trait
+LL | drop_unsized(y);
+ | - value moved here
+...
+LL | println!("{}", &y);
+ | ^^ value borrowed here after move
+
+error[E0382]: borrow of moved value: `x`
+ --> $DIR/borrow-after-move.rs:31:24
+ |
+LL | let y = *x;
+ | -- value moved here
+LL | y.foo();
+LL | println!("{}", &x);
+ | ^^ value borrowed here after move
+ |
+ = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: borrow of moved value: `y`
+ --> $DIR/borrow-after-move.rs:33:24
+ |
+LL | let y = *x;
+ | - move occurs because `y` has type `str`, which does not implement the `Copy` trait
+LL | y.foo();
+ | ----- `y` moved due to this method call
+...
+LL | println!("{}", &y);
+ | ^^ value borrowed here after move
+ |
+note: this function takes ownership of the receiver `self`, which moves `y`
+ --> $DIR/borrow-after-move.rs:5:12
+ |
+LL | fn foo(self) -> String;
+ | ^^^^
+
+error[E0382]: borrow of moved value: `x`
+ --> $DIR/borrow-after-move.rs:40:24
+ |
+LL | let x = "hello".to_owned().into_boxed_str();
+ | - move occurs because `x` has type `Box<str>`, which does not implement the `Copy` trait
+LL | x.foo();
+ | - value moved here
+LL | println!("{}", &x);
+ | ^^ value borrowed here after move
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unsized-locals/box-fnonce.rs b/src/test/ui/unsized-locals/box-fnonce.rs
new file mode 100644
index 000000000..8b2f9b4c9
--- /dev/null
+++ b/src/test/ui/unsized-locals/box-fnonce.rs
@@ -0,0 +1,10 @@
+// run-pass
+
+fn call_it<T>(f: Box<dyn FnOnce() -> T>) -> T {
+ f()
+}
+
+fn main() {
+ let s = "hello".to_owned();
+ assert_eq!(&call_it(Box::new(|| s)) as &str, "hello");
+}
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs
new file mode 100644
index 000000000..b9881defa
--- /dev/null
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(unsized_locals)]
+
+pub trait Foo {
+ fn foo(self) -> String;
+}
+
+struct A;
+
+impl Foo for A {
+ fn foo(self) -> String {
+ format!("hello")
+ }
+}
+
+fn main() {
+ let x = *(Box::new(A) as Box<dyn Foo>);
+ assert_eq!(x.foo(), format!("hello"));
+
+ // I'm not sure whether we want this to work
+ let x = Box::new(A) as Box<dyn Foo>;
+ assert_eq!(x.foo(), format!("hello"));
+}
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs
new file mode 100644
index 000000000..957991f85
--- /dev/null
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
+
+pub trait Foo {
+ fn foo(self) -> String {
+ format!("hello")
+ }
+}
+
+struct A;
+
+impl Foo for A {}
+
+fn main() {
+ let x = *(Box::new(A) as Box<dyn Foo>);
+ assert_eq!(x.foo(), format!("hello"));
+
+ // I'm not sure whether we want this to work
+ let x = Box::new(A) as Box<dyn Foo>;
+ assert_eq!(x.foo(), format!("hello"));
+}
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
new file mode 100644
index 000000000..d0ba6944a
--- /dev/null
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
@@ -0,0 +1,22 @@
+#![feature(unsized_locals)]
+//~^ WARN the feature `unsized_locals` is incomplete
+
+pub trait Foo {
+ fn foo(self) -> String
+ where
+ Self: Sized;
+}
+
+struct A;
+
+impl Foo for A {
+ fn foo(self) -> String {
+ format!("hello")
+ }
+}
+
+fn main() {
+ let x = *(Box::new(A) as Box<dyn Foo>);
+ x.foo();
+ //~^ERROR the `foo` method cannot be invoked on a trait object
+}
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
new file mode 100644
index 000000000..59d91bc0c
--- /dev/null
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
@@ -0,0 +1,20 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/by-value-trait-object-safety.rs:1:12
+ |
+LL | #![feature(unsized_locals)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
+error: the `foo` method cannot be invoked on a trait object
+ --> $DIR/by-value-trait-object-safety.rs:20:7
+ |
+LL | Self: Sized;
+ | ----- this has a `Sized` requirement
+...
+LL | x.foo();
+ | ^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/unsized-locals/double-move.rs b/src/test/ui/unsized-locals/double-move.rs
new file mode 100644
index 000000000..9e46ef9be
--- /dev/null
+++ b/src/test/ui/unsized-locals/double-move.rs
@@ -0,0 +1,54 @@
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
+
+pub trait Foo {
+ fn foo(self) -> String;
+}
+
+impl Foo for str {
+ fn foo(self) -> String {
+ self.to_owned()
+ }
+}
+
+fn drop_unsized<T: ?Sized>(_: T) {}
+
+fn main() {
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ let y = *x;
+ drop_unsized(y);
+ drop_unsized(y); //~ERROR use of moved value
+ }
+
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ let _y = *x;
+ drop_unsized(x); //~ERROR use of moved value
+ }
+
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ drop_unsized(x);
+ let _y = *x; //~ERROR use of moved value
+ }
+
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ let y = *x;
+ y.foo();
+ y.foo(); //~ERROR use of moved value
+ }
+
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ let _y = *x;
+ x.foo(); //~ERROR use of moved value
+ }
+
+ {
+ let x = "hello".to_owned().into_boxed_str();
+ x.foo();
+ let _y = *x; //~ERROR use of moved value
+ }
+}
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
new file mode 100644
index 000000000..4bb2ad88f
--- /dev/null
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -0,0 +1,78 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/double-move.rs:1:12
+ |
+LL | #![feature(unsized_locals, unsized_fn_params)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
+error[E0382]: use of moved value: `y`
+ --> $DIR/double-move.rs:21:22
+ |
+LL | let y = *x;
+ | - move occurs because `y` has type `str`, which does not implement the `Copy` trait
+LL | drop_unsized(y);
+ | - value moved here
+LL | drop_unsized(y);
+ | ^ value used here after move
+
+error[E0382]: use of moved value: `x`
+ --> $DIR/double-move.rs:27:22
+ |
+LL | let _y = *x;
+ | -- value moved here
+LL | drop_unsized(x);
+ | ^ value used here after move
+ |
+ = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `*x`
+ --> $DIR/double-move.rs:33:18
+ |
+LL | let x = "hello".to_owned().into_boxed_str();
+ | - move occurs because `x` has type `Box<str>`, which does not implement the `Copy` trait
+LL | drop_unsized(x);
+ | - value moved here
+LL | let _y = *x;
+ | ^^ value used here after move
+
+error[E0382]: use of moved value: `y`
+ --> $DIR/double-move.rs:40:9
+ |
+LL | let y = *x;
+ | - move occurs because `y` has type `str`, which does not implement the `Copy` trait
+LL | y.foo();
+ | ----- `y` moved due to this method call
+LL | y.foo();
+ | ^ value used here after move
+ |
+note: this function takes ownership of the receiver `self`, which moves `y`
+ --> $DIR/double-move.rs:5:12
+ |
+LL | fn foo(self) -> String;
+ | ^^^^
+
+error[E0382]: use of moved value: `x`
+ --> $DIR/double-move.rs:46:9
+ |
+LL | let _y = *x;
+ | -- value moved here
+LL | x.foo();
+ | ^ value used here after move
+ |
+ = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `*x`
+ --> $DIR/double-move.rs:52:18
+ |
+LL | let x = "hello".to_owned().into_boxed_str();
+ | - move occurs because `x` has type `Box<str>`, which does not implement the `Copy` trait
+LL | x.foo();
+ | - value moved here
+LL | let _y = *x;
+ | ^^ value used here after move
+
+error: aborting due to 6 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs b/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs
new file mode 100644
index 000000000..635d34f82
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs
@@ -0,0 +1,8 @@
+#![feature(unsized_locals)]
+//~^ WARN the feature `unsized_locals` is incomplete
+
+struct Test([i32]);
+
+fn main() {
+ let _x: fn(_) -> Test = Test;
+} //~^the size for values of type `[i32]` cannot be known at compilation time
diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
new file mode 100644
index 000000000..0f0ff5793
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
@@ -0,0 +1,22 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/issue-30276-feature-flagged.rs:1:12
+ |
+LL | #![feature(unsized_locals)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+ --> $DIR/issue-30276-feature-flagged.rs:7:29
+ |
+LL | let _x: fn(_) -> Test = Test;
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[i32]`
+ = note: all function arguments must have a statically known size
+ = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/issue-30276.rs b/src/test/ui/unsized-locals/issue-30276.rs
new file mode 100644
index 000000000..9c4bf062a
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-30276.rs
@@ -0,0 +1,5 @@
+struct Test([i32]);
+
+fn main() {
+ let _x: fn(_) -> Test = Test;
+} //~^the size for values of type `[i32]` cannot be known at compilation time
diff --git a/src/test/ui/unsized-locals/issue-30276.stderr b/src/test/ui/unsized-locals/issue-30276.stderr
new file mode 100644
index 000000000..8cccbd792
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-30276.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+ --> $DIR/issue-30276.rs:4:29
+ |
+LL | let _x: fn(_) -> Test = Test;
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[i32]`
+ = note: all function arguments must have a statically known size
+ = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.rs b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
new file mode 100644
index 000000000..63b0e830b
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
@@ -0,0 +1,8 @@
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
+
+fn main() {
+ struct A<X: ?Sized>(X);
+ A as fn(str) -> A<str>;
+ //~^ERROR the size for values of type `str` cannot be known at compilation time
+}
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
new file mode 100644
index 000000000..4523d41b6
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
@@ -0,0 +1,26 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/issue-50940-with-feature.rs:1:12
+ |
+LL | #![feature(unsized_locals, unsized_fn_params)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/issue-50940-with-feature.rs:6:5
+ |
+LL | A as fn(str) -> A<str>;
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: within `A<str>`, the trait `Sized` is not implemented for `str`
+note: required because it appears within the type `A<str>`
+ --> $DIR/issue-50940-with-feature.rs:5:12
+ |
+LL | struct A<X: ?Sized>(X);
+ | ^
+ = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/issue-50940.rs b/src/test/ui/unsized-locals/issue-50940.rs
new file mode 100644
index 000000000..7ba809b7e
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-50940.rs
@@ -0,0 +1,5 @@
+fn main() {
+ struct A<X: ?Sized>(X);
+ A as fn(str) -> A<str>;
+ //~^ERROR the size for values of type `str` cannot be known at compilation time
+}
diff --git a/src/test/ui/unsized-locals/issue-50940.stderr b/src/test/ui/unsized-locals/issue-50940.stderr
new file mode 100644
index 000000000..8f09b460e
--- /dev/null
+++ b/src/test/ui/unsized-locals/issue-50940.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/issue-50940.rs:3:5
+ |
+LL | A as fn(str) -> A<str>;
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: all function arguments must have a statically known size
+ = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/reference-unsized-locals.rs b/src/test/ui/unsized-locals/reference-unsized-locals.rs
new file mode 100644
index 000000000..4e887f327
--- /dev/null
+++ b/src/test/ui/unsized-locals/reference-unsized-locals.rs
@@ -0,0 +1,10 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(unsized_locals)]
+
+fn main() {
+ let foo: Box<[u8]> = Box::new(*b"foo");
+ let foo: [u8] = *foo;
+ assert_eq!(&foo, b"foo" as &[u8]);
+}
diff --git a/src/test/ui/unsized-locals/simple-unsized-locals.rs b/src/test/ui/unsized-locals/simple-unsized-locals.rs
new file mode 100644
index 000000000..02b7c299a
--- /dev/null
+++ b/src/test/ui/unsized-locals/simple-unsized-locals.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(unsized_locals)]
+
+fn main() {
+ let foo: Box<[u8]> = Box::new(*b"foo");
+ let _foo: [u8] = *foo;
+}
diff --git a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
new file mode 100644
index 000000000..175b02fcb
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
@@ -0,0 +1,33 @@
+// run-pass
+#![allow(incomplete_features, unused_braces, unused_parens)]
+#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
+
+struct A<X: ?Sized>(#[allow(unused_tuple_struct_fields)] X);
+
+fn udrop<T: ?Sized>(_x: T) {}
+fn foo() -> Box<[u8]> {
+ Box::new(*b"foo")
+}
+fn tfoo() -> Box<(i32, [u8])> {
+ Box::new((42, *b"foo"))
+}
+fn afoo() -> Box<A<[u8]>> {
+ Box::new(A(*b"foo"))
+}
+
+impl std::ops::Add<i32> for A<[u8]> {
+ type Output = ();
+ fn add(self, _rhs: i32) -> Self::Output {}
+}
+
+fn main() {
+ udrop::<[u8]>(loop {
+ break *foo();
+ });
+ udrop::<[u8]>(if true { *foo() } else { *foo() });
+ udrop::<[u8]>({ *foo() });
+ udrop::<[u8]>((*foo()));
+ udrop::<[u8]>((*tfoo()).1);
+ *afoo() + 42;
+ udrop as fn([u8]);
+}
diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs
new file mode 100644
index 000000000..1729b9ffa
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs.rs
@@ -0,0 +1,28 @@
+#![feature(unsized_tuple_coercion, unsized_fn_params)]
+
+struct A<X: ?Sized>(X);
+
+fn udrop<T: ?Sized>(_x: T) {}
+fn foo() -> Box<[u8]> {
+ Box::new(*b"foo")
+}
+fn tfoo() -> Box<(i32, [u8])> {
+ Box::new((42, *b"foo"))
+}
+fn afoo() -> Box<A<[u8]>> {
+ Box::new(A(*b"foo"))
+}
+
+impl std::ops::Add<i32> for A<[u8]> {
+ type Output = ();
+ fn add(self, _rhs: i32) -> Self::Output {}
+}
+
+fn main() {
+ udrop::<(i32, [u8])>((42, *foo()));
+ //~^ERROR E0277
+ udrop::<A<[u8]>>(A { 0: *foo() });
+ //~^ERROR E0277
+ udrop::<A<[u8]>>(A(*foo()));
+ //~^ERROR E0277
+}
diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr
new file mode 100644
index 000000000..6960255d9
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs.stderr
@@ -0,0 +1,43 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized-exprs.rs:22:26
+ |
+LL | udrop::<(i32, [u8])>((42, *foo()));
+ | ^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]`
+ = note: required because it appears within the type `({integer}, [u8])`
+ = note: tuples must have a statically known size to be initialized
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized-exprs.rs:24:22
+ |
+LL | udrop::<A<[u8]>>(A { 0: *foo() });
+ | ---------------- ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `A<[u8]>`
+ --> $DIR/unsized-exprs.rs:3:8
+ |
+LL | struct A<X: ?Sized>(X);
+ | ^
+ = note: structs must have a statically known size to be initialized
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized-exprs.rs:26:22
+ |
+LL | udrop::<A<[u8]>>(A(*foo()));
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `A<[u8]>`
+ --> $DIR/unsized-exprs.rs:3:8
+ |
+LL | struct A<X: ?Sized>(X);
+ | ^
+ = note: the return type of a function must have a statically known size
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs
new file mode 100644
index 000000000..127d8717e
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs2.rs
@@ -0,0 +1,24 @@
+#![feature(unsized_tuple_coercion, unsized_fn_params)]
+
+struct A<X: ?Sized>(X);
+
+fn udrop<T: ?Sized>(_x: T) {}
+fn foo() -> Box<[u8]> {
+ Box::new(*b"foo")
+}
+fn tfoo() -> Box<(i32, [u8])> {
+ Box::new((42, *b"foo"))
+}
+fn afoo() -> Box<A<[u8]>> {
+ Box::new(A(*b"foo"))
+}
+
+impl std::ops::Add<i32> for A<[u8]> {
+ type Output = ();
+ fn add(self, _rhs: i32) -> Self::Output {}
+}
+
+fn main() {
+ udrop::<[u8]>(foo()[..]);
+ //~^ERROR cannot move out of type `[u8]`, a non-copy slice
+}
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.stderr b/src/test/ui/unsized-locals/unsized-exprs2.stderr
new file mode 100644
index 000000000..88269f237
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs2.stderr
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[u8]`, a non-copy slice
+ --> $DIR/unsized-exprs2.rs:22:5
+ |
+LL | udrop::<[u8]>(foo()[..]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | cannot move out of here
+ | move occurs because value has type `[u8]`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs3.rs b/src/test/ui/unsized-locals/unsized-exprs3.rs
new file mode 100644
index 000000000..2133b01e0
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs3.rs
@@ -0,0 +1,10 @@
+// aux-build:ufuncs.rs
+
+extern crate ufuncs;
+
+use ufuncs::udrop;
+
+fn main() {
+ udrop as fn([u8]);
+ //~^ERROR E0277
+}
diff --git a/src/test/ui/unsized-locals/unsized-exprs3.stderr b/src/test/ui/unsized-locals/unsized-exprs3.stderr
new file mode 100644
index 000000000..57d997822
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-exprs3.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized-exprs3.rs:8:5
+ |
+LL | udrop as fn([u8]);
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
+ = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/unsized-index.rs b/src/test/ui/unsized-locals/unsized-index.rs
new file mode 100644
index 000000000..e8782e894
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-index.rs
@@ -0,0 +1,27 @@
+// run-pass
+
+#![feature(unsized_fn_params)]
+
+use std::ops;
+use std::ops::Index;
+
+pub struct A;
+
+impl ops::Index<str> for A {
+ type Output = ();
+ fn index(&self, _: str) -> &Self::Output {
+ &()
+ }
+}
+
+impl ops::IndexMut<str> for A {
+ fn index_mut(&mut self, _: str) -> &mut Self::Output {
+ panic!()
+ }
+}
+
+fn main() {
+ let a = A {};
+ let s = String::new().into_boxed_str();
+ assert_eq!(&(), a.index(*s));
+}
diff --git a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs
new file mode 100644
index 000000000..15263954c
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs
@@ -0,0 +1,15 @@
+#![feature(box_patterns)]
+#![feature(unsized_fn_params)]
+
+#[allow(dead_code)]
+fn f1(box box _b: Box<Box<[u8]>>) {}
+//~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time [E0277]
+
+fn f2((_x, _y): (i32, [i32])) {}
+//~^ ERROR: the size for values of type `[i32]` cannot be known at compilation time [E0277]
+
+fn main() {
+ let foo: Box<[u8]> = Box::new(*b"foo");
+ let _foo: [u8] = *foo;
+ //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time [E0277]
+}
diff --git a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr
new file mode 100644
index 000000000..da7702667
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized-locals-using-unsized-fn-params.rs:5:15
+ |
+LL | fn f1(box box _b: Box<Box<[u8]>>) {}
+ | ^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+ --> $DIR/unsized-locals-using-unsized-fn-params.rs:8:12
+ |
+LL | fn f2((_x, _y): (i32, [i32])) {}
+ | ^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[i32]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized-locals-using-unsized-fn-params.rs:13:9
+ |
+LL | let _foo: [u8] = *foo;
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/unsized-parameters.rs b/src/test/ui/unsized-locals/unsized-parameters.rs
new file mode 100644
index 000000000..a1b772a7e
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-parameters.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(unsized_fn_params)]
+
+pub fn f0(_f: dyn FnOnce()) {}
+pub fn f1(_s: str) {}
+pub fn f2(_x: i32, _y: [i32]) {}
+
+fn main() {
+ let foo = "foo".to_string().into_boxed_str();
+ f1(*foo);
+}
diff --git a/src/test/ui/unsized/box-instead-of-dyn-fn.rs b/src/test/ui/unsized/box-instead-of-dyn-fn.rs
new file mode 100644
index 000000000..2fa741bc1
--- /dev/null
+++ b/src/test/ui/unsized/box-instead-of-dyn-fn.rs
@@ -0,0 +1,15 @@
+use std::fmt::Debug;
+
+// Test to suggest boxing the return type, and the closure branch of the `if`
+
+fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a {
+ //~^ ERROR return type cannot have an unboxed trait object
+ if a % 2 == 0 {
+ move || println!("{a}")
+ } else {
+ Box::new(move || println!("{}", b))
+ //~^ ERROR `if` and `else` have incompatible types
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/unsized/box-instead-of-dyn-fn.stderr b/src/test/ui/unsized/box-instead-of-dyn-fn.stderr
new file mode 100644
index 000000000..c96c59afc
--- /dev/null
+++ b/src/test/ui/unsized/box-instead-of-dyn-fn.stderr
@@ -0,0 +1,42 @@
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/box-instead-of-dyn-fn.rs:10:9
+ |
+LL | / if a % 2 == 0 {
+LL | | move || println!("{a}")
+ | | -----------------------
+ | | |
+ | | the expected closure
+ | | expected because of this
+LL | | } else {
+LL | | Box::new(move || println!("{}", b))
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found struct `Box`
+LL | |
+LL | | }
+ | |_____- `if` and `else` have incompatible types
+ |
+ = note: expected closure `[closure@$DIR/box-instead-of-dyn-fn.rs:8:9: 8:16]`
+ found struct `Box<[closure@$DIR/box-instead-of-dyn-fn.rs:10:18: 10:25]>`
+
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/box-instead-of-dyn-fn.rs:5:56
+ |
+LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a {
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+ = note: if all the returned values were of the same type you could use `impl Fn() + 'a` as the return type
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+ = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+ |
+LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box<dyn Fn() + 'a> {
+ | ++++ +
+help: ... and box this value
+ |
+LL | Box::new(move || println!("{a}"))
+ | +++++++++ +
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0746.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unsized/issue-30355.rs b/src/test/ui/unsized/issue-30355.rs
new file mode 100644
index 000000000..6ff5b37f6
--- /dev/null
+++ b/src/test/ui/unsized/issue-30355.rs
@@ -0,0 +1,9 @@
+pub struct X([u8]);
+
+pub static Y: &'static X = {
+ const Y: &'static [u8] = b"";
+ &X(*Y)
+ //~^ ERROR E0277
+};
+
+fn main() {}
diff --git a/src/test/ui/unsized/issue-30355.stderr b/src/test/ui/unsized/issue-30355.stderr
new file mode 100644
index 000000000..71bbdf5de
--- /dev/null
+++ b/src/test/ui/unsized/issue-30355.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/issue-30355.rs:5:8
+ |
+LL | &X(*Y)
+ | ^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
+ = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/issue-40231-1.rs b/src/test/ui/unsized/issue-40231-1.rs
new file mode 100644
index 000000000..999399ec8
--- /dev/null
+++ b/src/test/ui/unsized/issue-40231-1.rs
@@ -0,0 +1,54 @@
+// check-pass
+
+#![allow(dead_code)]
+
+trait Structure<E>: Sized where E: Encoding {
+ type RefTarget: ?Sized;
+ type FfiPtr;
+ unsafe fn borrow_from_ffi_ptr<'a>(ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget>;
+}
+
+enum Slice {}
+
+impl<E> Structure<E> for Slice where E: Encoding {
+ type RefTarget = [E::Unit];
+ type FfiPtr = (*const E::FfiUnit, usize);
+ unsafe fn borrow_from_ffi_ptr<'a>(_ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget> {
+ panic!()
+ }
+}
+
+trait Encoding {
+ type Unit: Unit;
+ type FfiUnit;
+}
+
+trait Unit {}
+
+enum Utf16 {}
+
+impl Encoding for Utf16 {
+ type Unit = Utf16Unit;
+ type FfiUnit = u16;
+}
+
+struct Utf16Unit(pub u16);
+
+impl Unit for Utf16Unit {}
+
+type SUtf16Str = SeStr<Slice, Utf16>;
+
+struct SeStr<S, E> where S: Structure<E>, E: Encoding {
+ _data: S::RefTarget,
+}
+
+impl<S, E> SeStr<S, E> where S: Structure<E>, E: Encoding {
+ pub unsafe fn from_ptr<'a>(_ptr: S::FfiPtr) -> Option<&'a Self> {
+ panic!()
+ }
+}
+
+fn main() {
+ const TEXT_U16: &'static [u16] = &[];
+ let _ = unsafe { SUtf16Str::from_ptr((TEXT_U16.as_ptr(), TEXT_U16.len())).unwrap() };
+}
diff --git a/src/test/ui/unsized/issue-40231-2.rs b/src/test/ui/unsized/issue-40231-2.rs
new file mode 100644
index 000000000..780433b28
--- /dev/null
+++ b/src/test/ui/unsized/issue-40231-2.rs
@@ -0,0 +1,54 @@
+// check-pass
+
+#![allow(dead_code)]
+
+trait Structure<E>: Sized where E: Encoding {
+ type RefTarget: ?Sized;
+ type FfiPtr;
+ unsafe fn borrow_from_ffi_ptr<'a>(ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget>;
+}
+
+enum Slice {}
+
+impl<E> Structure<E> for Slice where E: Encoding {
+ type RefTarget = [E::Unit];
+ type FfiPtr = (*const E::FfiUnit, usize);
+ unsafe fn borrow_from_ffi_ptr<'a>(_ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget> {
+ panic!()
+ }
+}
+
+trait Encoding {
+ type Unit: Unit;
+ type FfiUnit;
+}
+
+trait Unit {}
+
+enum Utf16 {}
+
+impl Encoding for Utf16 {
+ type Unit = Utf16Unit;
+ type FfiUnit = u16;
+}
+
+struct Utf16Unit(pub u16);
+
+impl Unit for Utf16Unit {}
+
+struct SUtf16Str {
+ _data: <Slice as Structure<Utf16>>::RefTarget,
+}
+
+impl SUtf16Str {
+ pub unsafe fn from_ptr<'a>(ptr: <Slice as Structure<Utf16>>::FfiPtr)
+ -> Option<&'a Self> {
+ std::mem::transmute::<Option<&[<Utf16 as Encoding>::Unit]>, _>(
+ <Slice as Structure<Utf16>>::borrow_from_ffi_ptr(ptr))
+ }
+}
+
+fn main() {
+ const TEXT_U16: &'static [u16] = &[];
+ let _ = unsafe { SUtf16Str::from_ptr((TEXT_U16.as_ptr(), TEXT_U16.len())).unwrap() };
+}
diff --git a/src/test/ui/unsized/issue-71659.rs b/src/test/ui/unsized/issue-71659.rs
new file mode 100644
index 000000000..3524ca02b
--- /dev/null
+++ b/src/test/ui/unsized/issue-71659.rs
@@ -0,0 +1,32 @@
+#![feature(unsize)]
+
+use std::marker::Unsize;
+
+pub trait CastTo<T: ?Sized>: Unsize<T> {
+ fn cast_to(&self) -> &T;
+}
+
+impl<T: ?Sized, U: ?Sized + Unsize<T>> CastTo<T> for U {
+ fn cast_to(&self) -> &T {
+ self
+ }
+}
+
+impl<T: ?Sized> Cast for T {}
+pub trait Cast {
+ fn cast<T: ?Sized>(&self) -> &T
+ where
+ Self: CastTo<T>,
+ {
+ self
+ }
+}
+
+pub trait Foo: CastTo<[i32]> {}
+impl Foo for [i32; 0] {}
+
+fn main() {
+ let x: &dyn Foo = &[];
+ let x = x.cast::<[i32]>();
+ //~^ ERROR: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
+}
diff --git a/src/test/ui/unsized/issue-71659.stderr b/src/test/ui/unsized/issue-71659.stderr
new file mode 100644
index 000000000..d7b95f557
--- /dev/null
+++ b/src/test/ui/unsized/issue-71659.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
+ --> $DIR/issue-71659.rs:30:15
+ |
+LL | let x = x.cast::<[i32]>();
+ | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
+ |
+note: required by a bound in `Cast::cast`
+ --> $DIR/issue-71659.rs:19:15
+ |
+LL | fn cast<T: ?Sized>(&self) -> &T
+ | ---- required by a bound in this
+LL | where
+LL | Self: CastTo<T>,
+ | ^^^^^^^^^ required by this bound in `Cast::cast`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/issue-75707.rs b/src/test/ui/unsized/issue-75707.rs
new file mode 100644
index 000000000..9f04cdbb9
--- /dev/null
+++ b/src/test/ui/unsized/issue-75707.rs
@@ -0,0 +1,17 @@
+pub trait Callback {
+ fn cb();
+}
+
+pub trait Processing {
+ type Call: Callback;
+}
+
+fn f<P: Processing + ?Sized>() {
+ P::Call::cb();
+}
+
+fn main() {
+ struct MyCall;
+ f::<dyn Processing<Call = MyCall>>();
+ //~^ ERROR: the trait bound `MyCall: Callback` is not satisfied
+}
diff --git a/src/test/ui/unsized/issue-75707.stderr b/src/test/ui/unsized/issue-75707.stderr
new file mode 100644
index 000000000..7d0a2cb85
--- /dev/null
+++ b/src/test/ui/unsized/issue-75707.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `MyCall: Callback` is not satisfied
+ --> $DIR/issue-75707.rs:15:5
+ |
+LL | f::<dyn Processing<Call = MyCall>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Callback` is not implemented for `MyCall`
+ |
+note: required by a bound in `f`
+ --> $DIR/issue-75707.rs:9:9
+ |
+LL | fn f<P: Processing + ?Sized>() {
+ | ^^^^^^^^^^ required by this bound in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/issue-91801.rs b/src/test/ui/unsized/issue-91801.rs
new file mode 100644
index 000000000..096b1a935
--- /dev/null
+++ b/src/test/ui/unsized/issue-91801.rs
@@ -0,0 +1,19 @@
+pub struct Something;
+
+type Validator<'a> = dyn 'a + Send + Sync + Fn(&'a Something) -> Result<(), ()>;
+
+pub static ALL_VALIDATORS: &[(&'static str, &'static Validator)] =
+ &[("validate that credits and debits balance", &validate_something)];
+
+fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> {
+ //~^ ERROR return type cannot have an unboxed trait object
+ return Box::new(move |something: &'_ Something| -> Result<(), ()> {
+ first(something).or_else(|_| second(something))
+ });
+}
+
+fn validate_something(_: &Something) -> Result<(), ()> {
+ Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/unsized/issue-91801.stderr b/src/test/ui/unsized/issue-91801.stderr
new file mode 100644
index 000000000..8795aa168
--- /dev/null
+++ b/src/test/ui/unsized/issue-91801.stderr
@@ -0,0 +1,15 @@
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/issue-91801.rs:8:77
+ |
+LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> {
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: use `impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` as the return type, as all return paths are of type `Box<[closure@$DIR/issue-91801.rs:10:21: 10:70]>`, which implements `Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a`
+ |
+LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0746`.
diff --git a/src/test/ui/unsized/issue-91803.rs b/src/test/ui/unsized/issue-91803.rs
new file mode 100644
index 000000000..c74897cc4
--- /dev/null
+++ b/src/test/ui/unsized/issue-91803.rs
@@ -0,0 +1,8 @@
+trait Foo<'a> {}
+
+fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> {
+ //~^ ERROR return type cannot have an unboxed trait object
+ return Box::new(panic!());
+}
+
+fn main() {}
diff --git a/src/test/ui/unsized/issue-91803.stderr b/src/test/ui/unsized/issue-91803.stderr
new file mode 100644
index 000000000..2dad9e892
--- /dev/null
+++ b/src/test/ui/unsized/issue-91803.stderr
@@ -0,0 +1,15 @@
+error[E0746]: return type cannot have an unboxed trait object
+ --> $DIR/issue-91803.rs:3:43
+ |
+LL | fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> {
+ | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: use `impl Foo<'a>` as the return type, as all return paths are of type `Box<_>`, which implements `Foo<'a>`
+ |
+LL | fn or<'a>(first: &'static dyn Foo<'a>) -> impl Foo<'a> {
+ | ~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0746`.
diff --git a/src/test/ui/unsized/issue-97732.rs b/src/test/ui/unsized/issue-97732.rs
new file mode 100644
index 000000000..72f765033
--- /dev/null
+++ b/src/test/ui/unsized/issue-97732.rs
@@ -0,0 +1,28 @@
+// check-pass
+
+#![feature(coerce_unsized)]
+
+// Ensure that unsizing structs that contain ZSTs at non-zero offsets don't ICE
+
+use std::ops::CoerceUnsized;
+
+#[repr(C)]
+pub struct BoxWithZstTail<T: ?Sized>(Box<T>, ());
+
+impl<S: ?Sized, T: ?Sized> CoerceUnsized<BoxWithZstTail<T>> for BoxWithZstTail<S> where
+ Box<S>: CoerceUnsized<Box<T>>
+{
+}
+
+pub fn noop_dyn_upcast_with_zst_tail(
+ b: BoxWithZstTail<dyn ToString + Send>,
+) -> BoxWithZstTail<dyn ToString> {
+ b
+}
+
+fn main() {
+ let original = "foo";
+ let boxed = BoxWithZstTail(Box::new(original) as Box<dyn ToString + Send>, ());
+ let noop_upcasted = noop_dyn_upcast_with_zst_tail(boxed);
+ assert_eq!(original, noop_upcasted.0.to_string());
+}
diff --git a/src/test/ui/unsized/maybe-bounds-where-cpass.rs b/src/test/ui/unsized/maybe-bounds-where-cpass.rs
new file mode 100644
index 000000000..0e018cdab
--- /dev/null
+++ b/src/test/ui/unsized/maybe-bounds-where-cpass.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+struct S<T>(*const T) where T: ?Sized;
+
+
+fn main() {
+ let u = vec![1, 2, 3];
+ let _s: S<[u8]> = S(&u[..]);
+}
diff --git a/src/test/ui/unsized/maybe-bounds-where.rs b/src/test/ui/unsized/maybe-bounds-where.rs
new file mode 100644
index 000000000..d7af0c424
--- /dev/null
+++ b/src/test/ui/unsized/maybe-bounds-where.rs
@@ -0,0 +1,28 @@
+struct S1<T>(T) where (T): ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+struct S2<T>(T) where u8: ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+struct S3<T>(T) where &'static T: ?Sized;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+
+trait Trait<'a> {}
+
+struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+//~| WARN default bound relaxed for a type parameter
+
+struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+//~^ ERROR type parameter has more than one relaxed default bound
+//~| WARN default bound relaxed for a type parameter
+
+impl<T> S1<T> {
+ fn f() where T: ?Sized {}
+ //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+}
+
+fn main() {
+ let u = vec![1, 2, 3];
+ let _s: S5<[u8]> = S5(&u[..]); // OK
+}
diff --git a/src/test/ui/unsized/maybe-bounds-where.stderr b/src/test/ui/unsized/maybe-bounds-where.stderr
new file mode 100644
index 000000000..39bc1b88e
--- /dev/null
+++ b/src/test/ui/unsized/maybe-bounds-where.stderr
@@ -0,0 +1,51 @@
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+ --> $DIR/maybe-bounds-where.rs:1:28
+ |
+LL | struct S1<T>(T) where (T): ?Sized;
+ | ^^^^^^
+
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+ --> $DIR/maybe-bounds-where.rs:4:27
+ |
+LL | struct S2<T>(T) where u8: ?Sized;
+ | ^^^^^^
+
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+ --> $DIR/maybe-bounds-where.rs:7:35
+ |
+LL | struct S3<T>(T) where &'static T: ?Sized;
+ | ^^^^^^
+
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+ --> $DIR/maybe-bounds-where.rs:12:34
+ |
+LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+ | ^^^^^^^^^^
+
+error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+ --> $DIR/maybe-bounds-where.rs:21:21
+ |
+LL | fn f() where T: ?Sized {}
+ | ^^^^^^
+
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+ --> $DIR/maybe-bounds-where.rs:12:11
+ |
+LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+ | ^
+
+error[E0203]: type parameter has more than one relaxed default bound, only one is supported
+ --> $DIR/maybe-bounds-where.rs:16:11
+ |
+LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+ | ^
+
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+ --> $DIR/maybe-bounds-where.rs:16:11
+ |
+LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
+ | ^
+
+error: aborting due to 6 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0203`.
diff --git a/src/test/ui/unsized/param-mentioned-by-different-field.rs b/src/test/ui/unsized/param-mentioned-by-different-field.rs
new file mode 100644
index 000000000..cda94b306
--- /dev/null
+++ b/src/test/ui/unsized/param-mentioned-by-different-field.rs
@@ -0,0 +1,10 @@
+// We must not allow this with our current setup as `T`
+// is mentioned both in the tail of `Foo` and by another
+// field.
+struct Foo<T: ?Sized>(Box<T>, T);
+
+fn main() {
+ let x: Foo<[u8; 1]> = Foo(Box::new([2]), [3]);
+ let y: &Foo<[u8]> = &x; //~ ERROR mismatched types
+ assert_eq!(y.0.len(), 1);
+}
diff --git a/src/test/ui/unsized/param-mentioned-by-different-field.stderr b/src/test/ui/unsized/param-mentioned-by-different-field.stderr
new file mode 100644
index 000000000..d18fa6456
--- /dev/null
+++ b/src/test/ui/unsized/param-mentioned-by-different-field.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/param-mentioned-by-different-field.rs:8:25
+ |
+LL | let y: &Foo<[u8]> = &x;
+ | ---------- ^^ expected slice `[u8]`, found array `[u8; 1]`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&Foo<[u8]>`
+ found reference `&Foo<[u8; 1]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.rs b/src/test/ui/unsized/return-unsized-from-trait-method.rs
new file mode 100644
index 000000000..f053f4b0a
--- /dev/null
+++ b/src/test/ui/unsized/return-unsized-from-trait-method.rs
@@ -0,0 +1,14 @@
+// regression test for #26376
+
+trait Foo {
+ fn foo(&self) -> [u8];
+}
+
+fn foo(f: Option<&dyn Foo>) {
+ if let Some(f) = f {
+ let _ = f.foo();
+ //~^ ERROR cannot move a value of type `[u8]`
+ }
+}
+
+fn main() { foo(None) }
diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.stderr b/src/test/ui/unsized/return-unsized-from-trait-method.stderr
new file mode 100644
index 000000000..671d40993
--- /dev/null
+++ b/src/test/ui/unsized/return-unsized-from-trait-method.stderr
@@ -0,0 +1,9 @@
+error[E0161]: cannot move a value of type `[u8]`
+ --> $DIR/return-unsized-from-trait-method.rs:9:17
+ |
+LL | let _ = f.foo();
+ | ^^^^^^^ the size of `[u8]` cannot be statically determined
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0161`.
diff --git a/src/test/ui/unsized/unchanged-param.rs b/src/test/ui/unsized/unchanged-param.rs
new file mode 100644
index 000000000..6bdc89310
--- /dev/null
+++ b/src/test/ui/unsized/unchanged-param.rs
@@ -0,0 +1,11 @@
+// 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>(#[allow(unused_tuple_struct_fields)] T, B<T, U>);
+struct B<T, U: ?Sized>(#[allow(unused_tuple_struct_fields)] 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);
+}
diff --git a/src/test/ui/unsized/unsized-bare-typaram.rs b/src/test/ui/unsized/unsized-bare-typaram.rs
new file mode 100644
index 000000000..e611da915
--- /dev/null
+++ b/src/test/ui/unsized/unsized-bare-typaram.rs
@@ -0,0 +1,4 @@
+fn bar<T: Sized>() { }
+fn foo<T: ?Sized>() { bar::<T>() }
+//~^ ERROR the size for values of type
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr
new file mode 100644
index 000000000..1eff14be8
--- /dev/null
+++ b/src/test/ui/unsized/unsized-bare-typaram.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/unsized-bare-typaram.rs:2:29
+ |
+LL | fn foo<T: ?Sized>() { bar::<T>() }
+ | - ^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `bar`
+ --> $DIR/unsized-bare-typaram.rs:1:8
+ |
+LL | fn bar<T: Sized>() { }
+ | ^ required by this bound in `bar`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn foo<T: ?Sized>() { bar::<T>() }
+LL + fn foo<T>() { bar::<T>() }
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-enum.rs b/src/test/ui/unsized/unsized-enum.rs
new file mode 100644
index 000000000..02ad1c878
--- /dev/null
+++ b/src/test/ui/unsized/unsized-enum.rs
@@ -0,0 +1,11 @@
+fn is_sized<T:Sized>() { }
+fn not_sized<T: ?Sized>() { }
+
+enum Foo<U> { FooSome(U), FooNone }
+fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
+fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+//~^ ERROR the size for values of type
+//
+// Not OK: `T` is not sized.
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr
new file mode 100644
index 000000000..5f2e22430
--- /dev/null
+++ b/src/test/ui/unsized/unsized-enum.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/unsized-enum.rs:6:36
+ |
+LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+ | - ^^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/unsized-enum.rs:4:10
+ |
+LL | enum Foo<U> { FooSome(U), FooNone }
+ | ^ required by this bound in `Foo`
+help: you could relax the implicit `Sized` bound on `U` if it were used through indirection like `&U` or `Box<U>`
+ --> $DIR/unsized-enum.rs:4:10
+ |
+LL | enum Foo<U> { FooSome(U), FooNone }
+ | ^ - ...if indirection were used here: `Box<U>`
+ | |
+ | this could be changed to `U: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+LL + fn foo2<T>() { not_sized::<Foo<T>>() }
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-enum2.rs b/src/test/ui/unsized/unsized-enum2.rs
new file mode 100644
index 000000000..d589f5ae5
--- /dev/null
+++ b/src/test/ui/unsized/unsized-enum2.rs
@@ -0,0 +1,74 @@
+use std::ops::Deref;
+
+// Due to aggressive error message deduplication, we require 20 *different*
+// unsized types (even Path and [u8] are considered the "same").
+
+trait Foo {}
+trait Bar {}
+trait FooBar {}
+trait BarFoo {}
+
+trait PathHelper1 {}
+trait PathHelper2 {}
+trait PathHelper3 {}
+trait PathHelper4 {}
+
+struct Path1(dyn PathHelper1);
+struct Path2(dyn PathHelper2);
+struct Path3(dyn PathHelper3);
+struct Path4(dyn PathHelper4);
+
+enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+ // parameter
+ VA(W),
+ //~^ ERROR the size for values of type
+ VB{x: X},
+ //~^ ERROR the size for values of type
+ VC(isize, Y),
+ //~^ ERROR the size for values of type
+ VD{u: isize, x: Z},
+ //~^ ERROR the size for values of type
+
+ // slice / str
+ VE([u8]),
+ //~^ ERROR the size for values of type
+ VF{x: str},
+ //~^ ERROR the size for values of type
+ VG(isize, [f32]),
+ //~^ ERROR the size for values of type
+ VH{u: isize, x: [u32]},
+ //~^ ERROR the size for values of type
+
+ // unsized struct
+ VI(Path1),
+ //~^ ERROR the size for values of type
+ VJ{x: Path2},
+ //~^ ERROR the size for values of type
+ VK(isize, Path3),
+ //~^ ERROR the size for values of type
+ VL{u: isize, x: Path4},
+ //~^ ERROR the size for values of type
+
+ // plain trait
+ VM(dyn Foo),
+ //~^ ERROR the size for values of type
+ VN{x: dyn Bar},
+ //~^ ERROR the size for values of type
+ VO(isize, dyn FooBar),
+ //~^ ERROR the size for values of type
+ VP{u: isize, x: dyn BarFoo},
+ //~^ ERROR the size for values of type
+
+ // projected
+ VQ(<&'static [i8] as Deref>::Target),
+ //~^ ERROR the size for values of type
+ VR{x: <&'static [char] as Deref>::Target},
+ //~^ ERROR the size for values of type
+ VS(isize, <&'static [f64] as Deref>::Target),
+ //~^ ERROR the size for values of type
+ VT{u: isize, x: <&'static [i32] as Deref>::Target},
+ //~^ ERROR the size for values of type
+}
+
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-enum2.stderr b/src/test/ui/unsized/unsized-enum2.stderr
new file mode 100644
index 000000000..00b80327c
--- /dev/null
+++ b/src/test/ui/unsized/unsized-enum2.stderr
@@ -0,0 +1,411 @@
+error[E0277]: the size for values of type `W` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:23:8
+ |
+LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | // parameter
+LL | VA(W),
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+LL + enum E<W, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+ |
+help: borrowed types always have a statically known size
+ |
+LL | VA(&W),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VA(Box<W>),
+ | ++++ +
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:25:11
+ |
+LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | VB{x: X},
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+LL + enum E<W: ?Sized, X, Y: ?Sized, Z: ?Sized> {
+ |
+help: borrowed types always have a statically known size
+ |
+LL | VB{x: &X},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VB{x: Box<X>},
+ | ++++ +
+
+error[E0277]: the size for values of type `Y` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:27:15
+ |
+LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | VC(isize, Y),
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+LL + enum E<W: ?Sized, X: ?Sized, Y, Z: ?Sized> {
+ |
+help: borrowed types always have a statically known size
+ |
+LL | VC(isize, &Y),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VC(isize, Box<Y>),
+ | ++++ +
+
+error[E0277]: the size for values of type `Z` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:29:21
+ |
+LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | VD{u: isize, x: Z},
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
+LL + enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z> {
+ |
+help: borrowed types always have a statically known size
+ |
+LL | VD{u: isize, x: &Z},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VD{u: isize, x: Box<Z>},
+ | ++++ +
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:33:8
+ |
+LL | VE([u8]),
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VE(&[u8]),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VE(Box<[u8]>),
+ | ++++ +
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:35:11
+ |
+LL | VF{x: str},
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VF{x: &str},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VF{x: Box<str>},
+ | ++++ +
+
+error[E0277]: the size for values of type `[f32]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:37:15
+ |
+LL | VG(isize, [f32]),
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[f32]`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VG(isize, &[f32]),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VG(isize, Box<[f32]>),
+ | ++++ +
+
+error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:39:21
+ |
+LL | VH{u: isize, x: [u32]},
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u32]`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VH{u: isize, x: &[u32]},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VH{u: isize, x: Box<[u32]>},
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:53:8
+ |
+LL | VM(dyn Foo),
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VM(&dyn Foo),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VM(Box<dyn Foo>),
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn Bar + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:55:11
+ |
+LL | VN{x: dyn Bar},
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Bar + 'static)`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VN{x: &dyn Bar},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VN{x: Box<dyn Bar>},
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn FooBar + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:57:15
+ |
+LL | VO(isize, dyn FooBar),
+ | ^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn FooBar + 'static)`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VO(isize, &dyn FooBar),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VO(isize, Box<dyn FooBar>),
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn BarFoo + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:59:21
+ |
+LL | VP{u: isize, x: dyn BarFoo},
+ | ^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn BarFoo + 'static)`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VP{u: isize, x: &dyn BarFoo},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VP{u: isize, x: Box<dyn BarFoo>},
+ | ++++ +
+
+error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:63:8
+ |
+LL | VQ(<&'static [i8] as Deref>::Target),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[i8]`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VQ(&<&'static [i8] as Deref>::Target),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VQ(Box<<&'static [i8] as Deref>::Target>),
+ | ++++ +
+
+error[E0277]: the size for values of type `[char]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:65:11
+ |
+LL | VR{x: <&'static [char] as Deref>::Target},
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[char]`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VR{x: &<&'static [char] as Deref>::Target},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VR{x: Box<<&'static [char] as Deref>::Target>},
+ | ++++ +
+
+error[E0277]: the size for values of type `[f64]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:67:15
+ |
+LL | VS(isize, <&'static [f64] as Deref>::Target),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[f64]`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VS(isize, &<&'static [f64] as Deref>::Target),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VS(isize, Box<<&'static [f64] as Deref>::Target>),
+ | ++++ +
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:69:21
+ |
+LL | VT{u: isize, x: <&'static [i32] as Deref>::Target},
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[i32]`
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VT{u: isize, x: &<&'static [i32] as Deref>::Target},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VT{u: isize, x: Box<<&'static [i32] as Deref>::Target>},
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn PathHelper1 + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:43:8
+ |
+LL | VI(Path1),
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)`
+note: required because it appears within the type `Path1`
+ --> $DIR/unsized-enum2.rs:16:8
+ |
+LL | struct Path1(dyn PathHelper1);
+ | ^^^^^
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VI(&Path1),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VI(Box<Path1>),
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn PathHelper2 + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:45:11
+ |
+LL | VJ{x: Path2},
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)`
+note: required because it appears within the type `Path2`
+ --> $DIR/unsized-enum2.rs:17:8
+ |
+LL | struct Path2(dyn PathHelper2);
+ | ^^^^^
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VJ{x: &Path2},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VJ{x: Box<Path2>},
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn PathHelper3 + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:47:15
+ |
+LL | VK(isize, Path3),
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)`
+note: required because it appears within the type `Path3`
+ --> $DIR/unsized-enum2.rs:18:8
+ |
+LL | struct Path3(dyn PathHelper3);
+ | ^^^^^
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VK(isize, &Path3),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VK(isize, Box<Path3>),
+ | ++++ +
+
+error[E0277]: the size for values of type `(dyn PathHelper4 + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:49:21
+ |
+LL | VL{u: isize, x: Path4},
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)`
+note: required because it appears within the type `Path4`
+ --> $DIR/unsized-enum2.rs:19:8
+ |
+LL | struct Path4(dyn PathHelper4);
+ | ^^^^^
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | VL{u: isize, x: &Path4},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | VL{u: isize, x: Box<Path4>},
+ | ++++ +
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-fn-arg.fixed b/src/test/ui/unsized/unsized-fn-arg.fixed
new file mode 100644
index 000000000..fd9b159a4
--- /dev/null
+++ b/src/test/ui/unsized/unsized-fn-arg.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+#![crate_type="lib"]
+#![allow(unused)]
+
+fn f<T>(t: &T) {}
+//~^ ERROR the size for values of type `T` cannot be known at compilation time
diff --git a/src/test/ui/unsized/unsized-fn-arg.rs b/src/test/ui/unsized/unsized-fn-arg.rs
new file mode 100644
index 000000000..9fc08bd6d
--- /dev/null
+++ b/src/test/ui/unsized/unsized-fn-arg.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+#![crate_type="lib"]
+#![allow(unused)]
+
+fn f<T: ?Sized>(t: T) {}
+//~^ ERROR the size for values of type `T` cannot be known at compilation time
diff --git a/src/test/ui/unsized/unsized-fn-arg.stderr b/src/test/ui/unsized/unsized-fn-arg.stderr
new file mode 100644
index 000000000..404fa5291
--- /dev/null
+++ b/src/test/ui/unsized/unsized-fn-arg.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/unsized-fn-arg.rs:5:17
+ |
+LL | fn f<T: ?Sized>(t: T) {}
+ | - ^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+ = help: unsized fn params are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f<T: ?Sized>(t: T) {}
+LL + fn f<T>(t: T) {}
+ |
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | fn f<T: ?Sized>(t: &T) {}
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-fn-param.rs b/src/test/ui/unsized/unsized-fn-param.rs
new file mode 100644
index 000000000..32efc7e17
--- /dev/null
+++ b/src/test/ui/unsized/unsized-fn-param.rs
@@ -0,0 +1,20 @@
+use std::convert::AsRef;
+use std::path::Path;
+
+fn foo11(_bar: &dyn AsRef<Path>, _baz: &str) {}
+fn foo12(_bar: &str, _baz: &dyn AsRef<Path>) {}
+
+fn foo21(_bar: &dyn AsRef<str>, _baz: &str) {}
+fn foo22(_bar: &str, _baz: &dyn AsRef<str>) {}
+
+fn main() {
+ foo11("bar", &"baz"); //~ ERROR the size for values of type
+ foo11(&"bar", &"baz");
+ foo12(&"bar", "baz"); //~ ERROR the size for values of type
+ foo12(&"bar", &"baz");
+
+ foo21("bar", &"baz"); //~ ERROR the size for values of type
+ foo21(&"bar", &"baz");
+ foo22(&"bar", "baz"); //~ ERROR the size for values of type
+ foo22(&"bar", &"baz");
+}
diff --git a/src/test/ui/unsized/unsized-fn-param.stderr b/src/test/ui/unsized/unsized-fn-param.stderr
new file mode 100644
index 000000000..0221ef16b
--- /dev/null
+++ b/src/test/ui/unsized/unsized-fn-param.stderr
@@ -0,0 +1,63 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-fn-param.rs:11:11
+ |
+LL | foo11("bar", &"baz");
+ | ----- ^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
+help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<Path>`
+ |
+LL | foo11(&"bar", &"baz");
+ | +
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-fn-param.rs:13:19
+ |
+LL | foo12(&"bar", "baz");
+ | ----- ^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
+help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<Path>`
+ |
+LL | foo12(&"bar", &"baz");
+ | +
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-fn-param.rs:16:11
+ |
+LL | foo21("bar", &"baz");
+ | ----- ^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: required for the cast from `str` to the object type `dyn AsRef<str>`
+help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<str>`
+ |
+LL | foo21(&"bar", &"baz");
+ | +
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-fn-param.rs:18:19
+ |
+LL | foo22(&"bar", "baz");
+ | ----- ^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: required for the cast from `str` to the object type `dyn AsRef<str>`
+help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<str>`
+ |
+LL | foo22(&"bar", &"baz");
+ | +
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.rs b/src/test/ui/unsized/unsized-inherent-impl-self-type.rs
new file mode 100644
index 000000000..8bdf80c94
--- /dev/null
+++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.rs
@@ -0,0 +1,11 @@
+// Test sized-ness checking in substitution in impls.
+
+// impl - struct
+
+struct S5<Y>(Y);
+
+impl<X: ?Sized> S5<X> {
+ //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr
new file mode 100644
index 000000000..a952aa063
--- /dev/null
+++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized-inherent-impl-self-type.rs:7:17
+ |
+LL | impl<X: ?Sized> S5<X> {
+ | - ^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `S5`
+ --> $DIR/unsized-inherent-impl-self-type.rs:5:11
+ |
+LL | struct S5<Y>(Y);
+ | ^ required by this bound in `S5`
+help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box<Y>`
+ --> $DIR/unsized-inherent-impl-self-type.rs:5:11
+ |
+LL | struct S5<Y>(Y);
+ | ^ - ...if indirection were used here: `Box<Y>`
+ | |
+ | this could be changed to `Y: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - impl<X: ?Sized> S5<X> {
+LL + impl<X> S5<X> {
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-struct.rs b/src/test/ui/unsized/unsized-struct.rs
new file mode 100644
index 000000000..bfa5aa0a5
--- /dev/null
+++ b/src/test/ui/unsized/unsized-struct.rs
@@ -0,0 +1,18 @@
+fn is_sized<T:Sized>() { }
+fn not_sized<T: ?Sized>() { }
+
+struct Foo<T> { data: T }
+fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
+fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+//~^ ERROR the size for values of type
+//
+// Not OK: `T` is not sized.
+
+struct Bar<T: ?Sized> { data: T }
+fn bar1<T: ?Sized>() { not_sized::<Bar<T>>() }
+fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
+//~^ ERROR the size for values of type
+//
+// Not OK: `Bar<T>` is not sized, but it should be.
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr
new file mode 100644
index 000000000..c9510e92f
--- /dev/null
+++ b/src/test/ui/unsized/unsized-struct.stderr
@@ -0,0 +1,53 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/unsized-struct.rs:6:36
+ |
+LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+ | - ^^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `Foo`
+ --> $DIR/unsized-struct.rs:4:12
+ |
+LL | struct Foo<T> { data: T }
+ | ^ required by this bound in `Foo`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/unsized-struct.rs:4:12
+ |
+LL | struct Foo<T> { data: T }
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
+LL + fn foo2<T>() { not_sized::<Foo<T>>() }
+ |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> $DIR/unsized-struct.rs:13:24
+ |
+LL | fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
+ | - ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required because it appears within the type `Bar<T>`
+ --> $DIR/unsized-struct.rs:11:8
+ |
+LL | struct Bar<T: ?Sized> { data: T }
+ | ^^^
+note: required by a bound in `is_sized`
+ --> $DIR/unsized-struct.rs:1:13
+ |
+LL | fn is_sized<T:Sized>() { }
+ | ^ required by this bound in `is_sized`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
+LL + fn bar2<T>() { is_sized::<Bar<T>>() }
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.rs b/src/test/ui/unsized/unsized-trait-impl-self-type.rs
new file mode 100644
index 000000000..df571a833
--- /dev/null
+++ b/src/test/ui/unsized/unsized-trait-impl-self-type.rs
@@ -0,0 +1,14 @@
+// Test sized-ness checking in substitution in impls.
+
+// impl - struct
+trait T3<Z: ?Sized> {
+ fn foo(&self, z: &Z);
+}
+
+struct S5<Y>(Y);
+
+impl<X: ?Sized> T3<X> for S5<X> {
+ //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr
new file mode 100644
index 000000000..f6ba9a80c
--- /dev/null
+++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized-trait-impl-self-type.rs:10:27
+ |
+LL | impl<X: ?Sized> T3<X> for S5<X> {
+ | - ^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `S5`
+ --> $DIR/unsized-trait-impl-self-type.rs:8:11
+ |
+LL | struct S5<Y>(Y);
+ | ^ required by this bound in `S5`
+help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box<Y>`
+ --> $DIR/unsized-trait-impl-self-type.rs:8:11
+ |
+LL | struct S5<Y>(Y);
+ | ^ - ...if indirection were used here: `Box<Y>`
+ | |
+ | this could be changed to `Y: ?Sized`...
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - impl<X: ?Sized> T3<X> for S5<X> {
+LL + impl<X> T3<X> for S5<X> {
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.rs b/src/test/ui/unsized/unsized-trait-impl-trait-arg.rs
new file mode 100644
index 000000000..96e7e371f
--- /dev/null
+++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.rs
@@ -0,0 +1,12 @@
+// Test sized-ness checking in substitution in impls.
+
+// impl - unbounded
+trait T2<Z> {
+ fn foo(&self, z: Z);
+}
+struct S4<Y: ?Sized>(Box<Y>);
+impl<X: ?Sized> T2<X> for S4<X> {
+ //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr
new file mode 100644
index 000000000..f81487d52
--- /dev/null
+++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized-trait-impl-trait-arg.rs:8:17
+ |
+LL | impl<X: ?Sized> T2<X> for S4<X> {
+ | - ^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `T2`
+ --> $DIR/unsized-trait-impl-trait-arg.rs:4:10
+ |
+LL | trait T2<Z> {
+ | ^ required by this bound in `T2`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - impl<X: ?Sized> T2<X> for S4<X> {
+LL + impl<X> T2<X> for S4<X> {
+ |
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | trait T2<Z: ?Sized> {
+ | ++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized-tuple-impls.rs b/src/test/ui/unsized/unsized-tuple-impls.rs
new file mode 100644
index 000000000..5e385f33b
--- /dev/null
+++ b/src/test/ui/unsized/unsized-tuple-impls.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+#![feature(unsized_tuple_coercion)]
+
+use std::collections::HashSet;
+
+fn main() {
+ let x : &(i32, i32, [i32]) = &(0, 1, [2, 3]);
+ let y : &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]);
+ let mut a = [y, x];
+ a.sort();
+ assert_eq!(a, [x, y]);
+
+ assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]");
+
+ let mut h = HashSet::new();
+ h.insert(x);
+ h.insert(y);
+ assert!(h.contains(x));
+ assert!(h.contains(y));
+}
diff --git a/src/test/ui/unsized/unsized.rs b/src/test/ui/unsized/unsized.rs
new file mode 100644
index 000000000..54304834d
--- /dev/null
+++ b/src/test/ui/unsized/unsized.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+#![allow(type_alias_bounds)]
+#![allow(dead_code)]
+// Test syntax checks for `?Sized` syntax.
+
+use std::marker::PhantomData;
+
+trait T1 { }
+pub trait T2 { }
+trait T3<X: T1> : T2 { }
+trait T4<X: ?Sized> { }
+trait T5<X: ?Sized, Y> { }
+trait T6<Y, X: ?Sized> { }
+trait T7<X: ?Sized, Y: ?Sized> { }
+trait T8<X: ?Sized+T2> { }
+trait T9<X: T2 + ?Sized> { }
+struct S1<X: ?Sized>(PhantomData<X>);
+enum E<X: ?Sized> { E1(PhantomData<X>) }
+impl <X: ?Sized> T1 for S1<X> {}
+fn f<X: ?Sized>() {}
+type TT<T: ?Sized> = T;
+
+pub fn main() {
+}
diff --git a/src/test/ui/unsized/unsized2.rs b/src/test/ui/unsized/unsized2.rs
new file mode 100644
index 000000000..bbeb00d5f
--- /dev/null
+++ b/src/test/ui/unsized/unsized2.rs
@@ -0,0 +1,96 @@
+// run-pass
+
+#![allow(unconditional_recursion)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_imports)]
+
+// Test sized-ness checking in substitution.
+
+use std::marker;
+
+// Unbounded.
+fn f1<X: ?Sized>(x: &X) {
+ f1::<X>(x);
+}
+fn f2<X>(x: &X) {
+ f1::<X>(x);
+ f2::<X>(x);
+}
+
+// Bounded.
+trait T { fn dummy(&self) { } }
+fn f3<X: T+?Sized>(x: &X) {
+ f3::<X>(x);
+}
+fn f4<X: T>(x: &X) {
+ f3::<X>(x);
+ f4::<X>(x);
+}
+
+// Self type.
+trait T2 {
+ fn f() -> Box<Self>;
+}
+struct S;
+impl T2 for S {
+ fn f() -> Box<S> {
+ Box::new(S)
+ }
+}
+fn f5<X: ?Sized+T2>(x: &X) {
+ let _: Box<X> = T2::f();
+}
+fn f6<X: T2>(x: &X) {
+ let _: Box<X> = T2::f();
+}
+
+trait T3 {
+ fn f() -> Box<Self>;
+}
+impl T3 for S {
+ fn f() -> Box<S> {
+ Box::new(S)
+ }
+}
+fn f7<X: ?Sized+T3>(x: &X) {
+ // This is valid, but the unsized bound on X is irrelevant because any type
+ // which implements T3 must have statically known size.
+ let _: Box<X> = T3::f();
+}
+
+trait T4<X> {
+ fn dummy(&self) { }
+ fn m1(&self, x: &dyn T4<X>, y: X);
+ fn m2(&self, x: &dyn T5<X>, y: X);
+}
+trait T5<X: ?Sized> {
+ fn dummy(&self) { }
+ // not an error (for now)
+ fn m1(&self, x: &dyn T4<X>);
+ fn m2(&self, x: &dyn T5<X>);
+}
+
+trait T6<X: T> {
+ fn dummy(&self) { }
+ fn m1(&self, x: &dyn T4<X>);
+ fn m2(&self, x: &dyn T5<X>);
+}
+trait T7<X: ?Sized+T> {
+ fn dummy(&self) { }
+ // not an error (for now)
+ fn m1(&self, x: &dyn T4<X>);
+ fn m2(&self, x: &dyn T5<X>);
+}
+
+// The last field in a struct may be unsized
+struct S2<X: ?Sized> {
+ f: X,
+}
+struct S3<X: ?Sized> {
+ f1: isize,
+ f2: X,
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/unsized/unsized3-rpass.rs b/src/test/ui/unsized/unsized3-rpass.rs
new file mode 100644
index 000000000..4d5e89575
--- /dev/null
+++ b/src/test/ui/unsized/unsized3-rpass.rs
@@ -0,0 +1,93 @@
+// run-pass
+// Test structs with always-unsized fields.
+
+#![allow(warnings)]
+#![feature(unsize, ptr_metadata)]
+
+use std::mem;
+use std::ptr;
+use std::slice;
+
+struct Foo<T> {
+ f: [T],
+}
+
+struct Bar {
+ f1: usize,
+ f2: [usize],
+}
+
+struct Baz {
+ f1: usize,
+ f2: str,
+}
+
+trait Tr {
+ fn foo(&self) -> usize;
+}
+
+struct St {
+ f: usize,
+}
+
+impl Tr for St {
+ fn foo(&self) -> usize {
+ self.f
+ }
+}
+
+struct Qux<'a> {
+ f: Tr + 'a,
+}
+
+pub fn main() {
+ let _: &Foo<f64>;
+ let _: &Bar;
+ let _: &Baz;
+
+ let _: Box<Foo<i32>>;
+ let _: Box<Bar>;
+ let _: Box<Baz>;
+
+ let _ = mem::size_of::<Box<Foo<u8>>>();
+ let _ = mem::size_of::<Box<Bar>>();
+ let _ = mem::size_of::<Box<Baz>>();
+
+ unsafe {
+ struct Foo_<T> {
+ f: [T; 3],
+ }
+
+ let data: Box<Foo_<i32>> = Box::new(Foo_ { f: [1, 2, 3] });
+ let x: &Foo<i32> = mem::transmute(slice::from_raw_parts(&*data, 3));
+ assert_eq!(x.f.len(), 3);
+ assert_eq!(x.f[0], 1);
+
+ struct Baz_ {
+ f1: usize,
+ f2: [u8; 5],
+ }
+
+ let data: Box<_> =
+ Box::new(Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] });
+ let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5));
+ assert_eq!(x.f1, 42);
+ let chs: Vec<char> = x.f2.chars().collect();
+ assert_eq!(chs.len(), 5);
+ assert_eq!(chs[0], 'a');
+ assert_eq!(chs[1], 'b');
+ assert_eq!(chs[2], 'c');
+ assert_eq!(chs[3], 'd');
+ assert_eq!(chs[4], 'e');
+
+ struct Qux_ {
+ f: St,
+ }
+
+ let obj: Box<St> = Box::new(St { f: 42 });
+ let obj: &Tr = &*obj;
+ let data: Box<_> = Box::new(Qux_ { f: St { f: 234 } });
+ let x: &Qux = &*ptr::from_raw_parts::<Qux>((&*data as *const _).cast(), ptr::metadata(obj));
+ assert_eq!(x.f.foo(), 234);
+ }
+}
diff --git a/src/test/ui/unsized/unsized3.rs b/src/test/ui/unsized/unsized3.rs
new file mode 100644
index 000000000..af76aca2c
--- /dev/null
+++ b/src/test/ui/unsized/unsized3.rs
@@ -0,0 +1,50 @@
+// Test sized-ness checking in substitution within fn bodies..
+
+use std::marker;
+
+// Unbounded.
+fn f1<X: ?Sized>(x: &X) {
+ f2::<X>(x);
+ //~^ ERROR the size for values of type
+}
+fn f2<X>(x: &X) {
+}
+
+// Bounded.
+trait T {
+ fn foo(&self) { }
+}
+fn f3<X: ?Sized + T>(x: &X) {
+ f4::<X>(x);
+ //~^ ERROR the size for values of type
+}
+fn f4<X: T>(x: &X) {
+}
+
+fn f5<Y>(x: &Y) {}
+fn f6<X: ?Sized>(x: &X) {}
+
+// Test with unsized struct.
+struct S<X: ?Sized> {
+ x: X,
+}
+
+fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
+ f5(x1);
+ //~^ ERROR the size for values of type
+ f6(x2); // ok
+}
+
+// Test some tuples.
+fn f9<X: ?Sized>(x1: Box<S<X>>) {
+ f5(&(*x1, 34));
+ //~^ ERROR the size for values of type
+}
+
+fn f10<X: ?Sized>(x1: Box<S<X>>) {
+ f5(&(32, *x1));
+ //~^ ERROR the size for values of type
+ //~| ERROR the size for values of type
+}
+
+pub fn main() {}
diff --git a/src/test/ui/unsized/unsized3.stderr b/src/test/ui/unsized/unsized3.stderr
new file mode 100644
index 000000000..d64091b15
--- /dev/null
+++ b/src/test/ui/unsized/unsized3.stderr
@@ -0,0 +1,159 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized3.rs:7:13
+ |
+LL | fn f1<X: ?Sized>(x: &X) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f2::<X>(x);
+ | ------- ^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `f2`
+ --> $DIR/unsized3.rs:10:7
+ |
+LL | fn f2<X>(x: &X) {
+ | ^ required by this bound in `f2`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f1<X: ?Sized>(x: &X) {
+LL + fn f1<X>(x: &X) {
+ |
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | fn f2<X: ?Sized>(x: &X) {
+ | ++++++++
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized3.rs:18:13
+ |
+LL | fn f3<X: ?Sized + T>(x: &X) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f4::<X>(x);
+ | ------- ^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `f4`
+ --> $DIR/unsized3.rs:21:7
+ |
+LL | fn f4<X: T>(x: &X) {
+ | ^ required by this bound in `f4`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f3<X: ?Sized + T>(x: &X) {
+LL + fn f3<X: T>(x: &X) {
+ |
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | fn f4<X: T + ?Sized>(x: &X) {
+ | ++++++++
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized3.rs:33:8
+ |
+LL | fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f5(x1);
+ | -- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `S<X>`
+ --> $DIR/unsized3.rs:28:8
+ |
+LL | struct S<X: ?Sized> {
+ | ^
+note: required by a bound in `f5`
+ --> $DIR/unsized3.rs:24:7
+ |
+LL | fn f5<Y>(x: &Y) {}
+ | ^ required by this bound in `f5`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
+LL + fn f8<X>(x1: &S<X>, x2: &S<X>) {
+ |
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | fn f5<Y: ?Sized>(x: &Y) {}
+ | ++++++++
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized3.rs:40:8
+ |
+LL | fn f9<X: ?Sized>(x1: Box<S<X>>) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f5(&(*x1, 34));
+ | -- ^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `S<X>`
+ --> $DIR/unsized3.rs:28:8
+ |
+LL | struct S<X: ?Sized> {
+ | ^
+ = note: only the last element of a tuple may have a dynamically sized type
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f9<X: ?Sized>(x1: Box<S<X>>) {
+LL + fn f9<X>(x1: Box<S<X>>) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized3.rs:45:9
+ |
+LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f5(&(32, *x1));
+ | -- ^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `S<X>`
+ --> $DIR/unsized3.rs:28:8
+ |
+LL | struct S<X: ?Sized> {
+ | ^
+ = note: required because it appears within the type `({integer}, S<X>)`
+ = note: tuples must have a statically known size to be initialized
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
+LL + fn f10<X>(x1: Box<S<X>>) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized3.rs:45:8
+ |
+LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f5(&(32, *x1));
+ | -- ^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+note: required because it appears within the type `S<X>`
+ --> $DIR/unsized3.rs:28:8
+ |
+LL | struct S<X: ?Sized> {
+ | ^
+ = note: required because it appears within the type `({integer}, S<X>)`
+note: required by a bound in `f5`
+ --> $DIR/unsized3.rs:24:7
+ |
+LL | fn f5<Y>(x: &Y) {}
+ | ^ required by this bound in `f5`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
+LL + fn f10<X>(x1: Box<S<X>>) {
+ |
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | fn f5<Y: ?Sized>(x: &Y) {}
+ | ++++++++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized5.rs b/src/test/ui/unsized/unsized5.rs
new file mode 100644
index 000000000..befd2244d
--- /dev/null
+++ b/src/test/ui/unsized/unsized5.rs
@@ -0,0 +1,34 @@
+// Test `?Sized` types not allowed in fields (except the last one).
+
+struct S1<X: ?Sized> {
+ f1: X,
+ //~^ ERROR the size for values of type
+ f2: isize,
+}
+struct S2<X: ?Sized> {
+ f: isize,
+ g: X,
+ //~^ ERROR the size for values of type
+ h: isize,
+}
+struct S3 {
+ f: str,
+ //~^ ERROR the size for values of type
+ g: [usize]
+}
+struct S4 {
+ f: [u8],
+ //~^ ERROR the size for values of type
+ g: usize
+}
+enum E<X: ?Sized> {
+ V1(X, isize),
+ //~^ ERROR the size for values of type
+}
+enum F<X: ?Sized> {
+ V2{f1: X, f: isize},
+ //~^ ERROR the size for values of type
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/unsized/unsized5.stderr b/src/test/ui/unsized/unsized5.stderr
new file mode 100644
index 000000000..03ed0c457
--- /dev/null
+++ b/src/test/ui/unsized/unsized5.stderr
@@ -0,0 +1,136 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized5.rs:4:9
+ |
+LL | struct S1<X: ?Sized> {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f1: X,
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: only the last field of a struct may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - struct S1<X: ?Sized> {
+LL + struct S1<X> {
+ |
+help: borrowed types always have a statically known size
+ |
+LL | f1: &X,
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | f1: Box<X>,
+ | ++++ +
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized5.rs:10:8
+ |
+LL | struct S2<X: ?Sized> {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | f: isize,
+LL | g: X,
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: only the last field of a struct may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - struct S2<X: ?Sized> {
+LL + struct S2<X> {
+ |
+help: borrowed types always have a statically known size
+ |
+LL | g: &X,
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | g: Box<X>,
+ | ++++ +
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized5.rs:15:8
+ |
+LL | f: str,
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: only the last field of a struct may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | f: &str,
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | f: Box<str>,
+ | ++++ +
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized5.rs:20:8
+ |
+LL | f: [u8],
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: only the last field of a struct may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | f: &[u8],
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | f: Box<[u8]>,
+ | ++++ +
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized5.rs:25:8
+ |
+LL | enum E<X: ?Sized> {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | V1(X, isize),
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - enum E<X: ?Sized> {
+LL + enum E<X> {
+ |
+help: borrowed types always have a statically known size
+ |
+LL | V1(&X, isize),
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | V1(Box<X>, isize),
+ | ++++ +
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized5.rs:29:12
+ |
+LL | enum F<X: ?Sized> {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | V2{f1: X, f: isize},
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: no field of an enum variant may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - enum F<X: ?Sized> {
+LL + enum F<X> {
+ |
+help: borrowed types always have a statically known size
+ |
+LL | V2{f1: &X, f: isize},
+ | +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | V2{f1: Box<X>, f: isize},
+ | ++++ +
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized6.rs b/src/test/ui/unsized/unsized6.rs
new file mode 100644
index 000000000..79133554d
--- /dev/null
+++ b/src/test/ui/unsized/unsized6.rs
@@ -0,0 +1,44 @@
+// Test `?Sized` local variables.
+
+trait T {}
+
+fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
+ let _: W; // <-- this is OK, no bindings created, no initializer.
+ let _: (isize, (X, isize));
+ //~^ ERROR the size for values of type
+ let y: Y;
+ //~^ ERROR the size for values of type
+ let y: (isize, (Z, usize));
+ //~^ ERROR the size for values of type
+}
+fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
+ let y: X;
+ //~^ ERROR the size for values of type
+ let y: (isize, (Y, isize));
+ //~^ ERROR the size for values of type
+}
+
+fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ let y: X = *x1;
+ //~^ ERROR the size for values of type
+ let y = *x2;
+ //~^ ERROR the size for values of type
+ let (y, z) = (*x3, 4);
+ //~^ ERROR the size for values of type
+}
+fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ let y: X = *x1;
+ //~^ ERROR the size for values of type
+ let y = *x2;
+ //~^ ERROR the size for values of type
+ let (y, z) = (*x3, 4);
+ //~^ ERROR the size for values of type
+}
+
+fn g1<X: ?Sized>(x: X) {}
+//~^ ERROR the size for values of type
+fn g2<X: ?Sized + T>(x: X) {}
+//~^ ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/src/test/ui/unsized/unsized6.stderr b/src/test/ui/unsized/unsized6.stderr
new file mode 100644
index 000000000..011f2b426
--- /dev/null
+++ b/src/test/ui/unsized/unsized6.stderr
@@ -0,0 +1,222 @@
+error[E0277]: the size for values of type `Y` cannot be known at compilation time
+ --> $DIR/unsized6.rs:9:9
+ |
+LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | let y: Y;
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
+LL + fn f1<W: ?Sized, X: ?Sized, Y, Z: ?Sized>(x: &X) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:7:12
+ |
+LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | let _: W; // <-- this is OK, no bindings created, no initializer.
+LL | let _: (isize, (X, isize));
+ | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: only the last element of a tuple may have a dynamically sized type
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
+LL + fn f1<W: ?Sized, X, Y: ?Sized, Z: ?Sized>(x: &X) {
+ |
+
+error[E0277]: the size for values of type `Z` cannot be known at compilation time
+ --> $DIR/unsized6.rs:11:12
+ |
+LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | let y: (isize, (Z, usize));
+ | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: only the last element of a tuple may have a dynamically sized type
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
+LL + fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z>(x: &X) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:15:9
+ |
+LL | fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | let y: X;
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
+LL + fn f2<X, Y: ?Sized>(x: &X) {
+ |
+
+error[E0277]: the size for values of type `Y` cannot be known at compilation time
+ --> $DIR/unsized6.rs:17:12
+ |
+LL | fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | let y: (isize, (Y, isize));
+ | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = note: only the last element of a tuple may have a dynamically sized type
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
+LL + fn f2<X: ?Sized, Y>(x: &X) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:22:9
+ |
+LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | let y: X = *x1;
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+LL + fn f3<X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:24:9
+ |
+LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | let y = *x2;
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+LL + fn f3<X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:26:10
+ |
+LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | let (y, z) = (*x3, 4);
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+LL + fn f3<X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:30:9
+ |
+LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ | - this type parameter needs to be `std::marker::Sized`
+LL | let y: X = *x1;
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+LL + fn f4<X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:32:9
+ |
+LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | let y = *x2;
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+LL + fn f4<X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:34:10
+ |
+LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ | - this type parameter needs to be `std::marker::Sized`
+...
+LL | let (y, z) = (*x3, 4);
+ | ^ doesn't have a size known at compile-time
+ |
+ = note: all local variables must have a statically known size
+ = help: unsized locals are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+LL + fn f4<X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+ |
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:38:18
+ |
+LL | fn g1<X: ?Sized>(x: X) {}
+ | - ^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+ = help: unsized fn params are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn g1<X: ?Sized>(x: X) {}
+LL + fn g1<X>(x: X) {}
+ |
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | fn g1<X: ?Sized>(x: &X) {}
+ | +
+
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized6.rs:40:22
+ |
+LL | fn g2<X: ?Sized + T>(x: X) {}
+ | - ^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+ = help: unsized fn params are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - fn g2<X: ?Sized + T>(x: X) {}
+LL + fn g2<X: T>(x: X) {}
+ |
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | fn g2<X: ?Sized + T>(x: &X) {}
+ | +
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized/unsized7.rs b/src/test/ui/unsized/unsized7.rs
new file mode 100644
index 000000000..422a78481
--- /dev/null
+++ b/src/test/ui/unsized/unsized7.rs
@@ -0,0 +1,16 @@
+// Test sized-ness checking in substitution in impls.
+
+trait T {}
+
+// I would like these to fail eventually.
+// impl - bounded
+trait T1<Z: T> {
+ fn dummy(&self) -> Z;
+}
+
+struct S3<Y: ?Sized>(Box<Y>);
+impl<X: ?Sized + T> T1<X> for S3<X> {
+ //~^ ERROR the size for values of type
+}
+
+fn main() { }
diff --git a/src/test/ui/unsized/unsized7.stderr b/src/test/ui/unsized/unsized7.stderr
new file mode 100644
index 000000000..1555b9df4
--- /dev/null
+++ b/src/test/ui/unsized/unsized7.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the size for values of type `X` cannot be known at compilation time
+ --> $DIR/unsized7.rs:12:21
+ |
+LL | impl<X: ?Sized + T> T1<X> for S3<X> {
+ | - ^^^^^ doesn't have a size known at compile-time
+ | |
+ | this type parameter needs to be `std::marker::Sized`
+ |
+note: required by a bound in `T1`
+ --> $DIR/unsized7.rs:7:10
+ |
+LL | trait T1<Z: T> {
+ | ^ required by this bound in `T1`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+ |
+LL - impl<X: ?Sized + T> T1<X> for S3<X> {
+LL + impl<X: T> T1<X> for S3<X> {
+ |
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | trait T1<Z: T + ?Sized> {
+ | ++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.