diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/unsized | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/unsized')
54 files changed, 2282 insertions, 0 deletions
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`. |