diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:13 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:13 +0000 |
commit | 218caa410aa38c29984be31a5229b9fa717560ee (patch) | |
tree | c54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/wf | |
parent | Releasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/wf')
101 files changed, 2109 insertions, 0 deletions
diff --git a/tests/ui/wf/hir-wf-canonicalized.rs b/tests/ui/wf/hir-wf-canonicalized.rs new file mode 100644 index 000000000..bdb84409d --- /dev/null +++ b/tests/ui/wf/hir-wf-canonicalized.rs @@ -0,0 +1,18 @@ +// incremental + +trait Foo { + type V; +} + +trait Callback<T: Foo>: Fn(&Bar<'_, T>, &T::V) {} + +struct Bar<'a, T> { + callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>, + //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied + //~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied + //~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time +} + +impl<T: Foo> Bar<'_, Bar<'_, T>> {} + +fn main() {} diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr new file mode 100644 index 000000000..9fd0f9c81 --- /dev/null +++ b/tests/ui/wf/hir-wf-canonicalized.stderr @@ -0,0 +1,32 @@ +error[E0277]: the trait bound `Bar<'a, T>: Foo` is not satisfied + --> $DIR/hir-wf-canonicalized.rs:10:15 + | +LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar<'a, T>` + +error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied + --> $DIR/hir-wf-canonicalized.rs:10:15 + | +LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` + +error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time + --> $DIR/hir-wf-canonicalized.rs:10:15 + | +LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` +note: required by a bound in `Bar` + --> $DIR/hir-wf-canonicalized.rs:9:16 + | +LL | struct Bar<'a, T> { + | ^ required by this bound in `Bar` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Bar<'a, T: ?Sized> { + | ++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/hir-wf-check-erase-regions.rs b/tests/ui/wf/hir-wf-check-erase-regions.rs new file mode 100644 index 000000000..2b4b480df --- /dev/null +++ b/tests/ui/wf/hir-wf-check-erase-regions.rs @@ -0,0 +1,14 @@ +// Regression test for #87549. +// incremental + +pub struct Table<T, const N: usize>([Option<T>; N]); + +impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> { + type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>; //~ ERROR `&T` is not an iterator + type Item = &'a T; + + fn into_iter(self) -> Self::IntoIter { //~ ERROR `&T` is not an iterator + unimplemented!() + } +} +fn main() {} diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.stderr new file mode 100644 index 000000000..7bc19dd2e --- /dev/null +++ b/tests/ui/wf/hir-wf-check-erase-regions.stderr @@ -0,0 +1,27 @@ +error[E0277]: `&T` is not an iterator + --> $DIR/hir-wf-check-erase-regions.rs:7:21 + | +LL | type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` + = note: required for `&T` to implement `IntoIterator` +note: required by a bound in `Flatten` + --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL + +error[E0277]: `&T` is not an iterator + --> $DIR/hir-wf-check-erase-regions.rs:10:27 + | +LL | fn into_iter(self) -> Self::IntoIter { + | ^^^^^^^^^^^^^^ `&T` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` + = note: required for `&T` to implement `IntoIterator` +note: required by a bound in `Flatten` + --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/issue-103573.rs b/tests/ui/wf/issue-103573.rs new file mode 100644 index 000000000..bcbf4f941 --- /dev/null +++ b/tests/ui/wf/issue-103573.rs @@ -0,0 +1,22 @@ +trait TraitA { + type TypeA; +} + +trait TraitD { + type TypeD; +} + +pub trait TraitB { + type TypeB: TraitD; + + fn f(_: &<Self::TypeB as TraitD>::TypeD); +} + +pub trait TraitC<E> { + type TypeC<'a>: TraitB; + + fn g<'a>(_: &<<Self::TypeC<'a> as TraitB>::TypeB as TraitA>::TypeA); + //~^ ERROR the trait bound `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied +} + +fn main() {} diff --git a/tests/ui/wf/issue-103573.stderr b/tests/ui/wf/issue-103573.stderr new file mode 100644 index 000000000..5227badb7 --- /dev/null +++ b/tests/ui/wf/issue-103573.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied + --> $DIR/issue-103573.rs:18:18 + | +LL | fn g<'a>(_: &<<Self::TypeC<'a> as TraitB>::TypeB as TraitA>::TypeA); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB` + | +help: consider further restricting the associated type + | +LL | fn g<'a>(_: &<<Self::TypeC<'a> as TraitB>::TypeB as TraitA>::TypeA) where <<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB: TraitA; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/issue-48638.rs b/tests/ui/wf/issue-48638.rs new file mode 100644 index 000000000..f07843103 --- /dev/null +++ b/tests/ui/wf/issue-48638.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait D {} +pub struct DT; +impl D for DT {} + +pub trait A<R: D>: Sized { + type AS; +} + +pub struct As<R: D>(R); + +pub struct AT; +impl<R: D> A<R> for AT { + type AS = As<R>; +} + +#[repr(packed)] +struct S(<AT as A<DT>>::AS); + +fn main() {} diff --git a/tests/ui/wf/issue-87495.rs b/tests/ui/wf/issue-87495.rs new file mode 100644 index 000000000..5aab74311 --- /dev/null +++ b/tests/ui/wf/issue-87495.rs @@ -0,0 +1,8 @@ +// Regression test for the ICE described in #87495. + +trait T { + const CONST: (bool, dyn T); + //~^ ERROR: the trait `T` cannot be made into an object [E0038] +} + +fn main() {} diff --git a/tests/ui/wf/issue-87495.stderr b/tests/ui/wf/issue-87495.stderr new file mode 100644 index 000000000..c924cd879 --- /dev/null +++ b/tests/ui/wf/issue-87495.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `T` cannot be made into an object + --> $DIR/issue-87495.rs:4:25 + | +LL | const CONST: (bool, dyn T); + | ^^^^^ `T` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-87495.rs:4:11 + | +LL | trait T { + | - this trait cannot be made into an object... +LL | const CONST: (bool, dyn T); + | ^^^^^ ...because it contains this associated `const` + = help: consider moving `CONST` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/issue-95665.rs b/tests/ui/wf/issue-95665.rs new file mode 100644 index 000000000..67923cbb2 --- /dev/null +++ b/tests/ui/wf/issue-95665.rs @@ -0,0 +1,18 @@ +// Regression test for the ICE described in #95665. +// Ensure that the expected error is output (and thus that there is no ICE) + +pub trait Trait: {} + +pub struct Struct<T: Trait> { + member: T, +} + +// uncomment and bug goes away +// impl Trait for u8 {} + +extern "C" { + static VAR: Struct<u8>; + //~^ 14:17: 14:27: the trait bound `u8: Trait` is not satisfied [E0277] +} + +fn main() {} diff --git a/tests/ui/wf/issue-95665.stderr b/tests/ui/wf/issue-95665.stderr new file mode 100644 index 000000000..b1cda59a9 --- /dev/null +++ b/tests/ui/wf/issue-95665.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u8: Trait` is not satisfied + --> $DIR/issue-95665.rs:14:17 + | +LL | static VAR: Struct<u8>; + | ^^^^^^^^^^ the trait `Trait` is not implemented for `u8` + | +note: required by a bound in `Struct` + --> $DIR/issue-95665.rs:6:22 + | +LL | pub struct Struct<T: Trait> { + | ^^^^^ required by this bound in `Struct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/issue-96810.rs b/tests/ui/wf/issue-96810.rs new file mode 100644 index 000000000..c2948086b --- /dev/null +++ b/tests/ui/wf/issue-96810.rs @@ -0,0 +1,12 @@ +struct S<T: Tr>(T::Assoc); + +trait Tr { + type Assoc; +} + +struct Hoge<K> { + s: S<K>, //~ ERROR the trait bound `K: Tr` is not satisfied + a: u32, +} + +fn main() {} diff --git a/tests/ui/wf/issue-96810.stderr b/tests/ui/wf/issue-96810.stderr new file mode 100644 index 000000000..1407e62b1 --- /dev/null +++ b/tests/ui/wf/issue-96810.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `K: Tr` is not satisfied + --> $DIR/issue-96810.rs:8:8 + | +LL | s: S<K>, + | ^^^^ the trait `Tr` is not implemented for `K` + | +note: required by a bound in `S` + --> $DIR/issue-96810.rs:1:13 + | +LL | struct S<T: Tr>(T::Assoc); + | ^^ required by this bound in `S` +help: consider restricting type parameter `K` + | +LL | struct Hoge<K: Tr> { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-array-elem-sized.rs b/tests/ui/wf/wf-array-elem-sized.rs new file mode 100644 index 000000000..34bf22034 --- /dev/null +++ b/tests/ui/wf/wf-array-elem-sized.rs @@ -0,0 +1,11 @@ +// Check that array element types must be Sized. Issue #25692. + + +#![allow(dead_code)] + +struct Foo { + foo: [[u8]], //~ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-array-elem-sized.stderr b/tests/ui/wf/wf-array-elem-sized.stderr new file mode 100644 index 000000000..7f3c58d6b --- /dev/null +++ b/tests/ui/wf/wf-array-elem-sized.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-array-elem-sized.rs:7:10 + | +LL | foo: [[u8]], + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: slice and array elements must have `Sized` type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-complex-assoc-type.rs b/tests/ui/wf/wf-complex-assoc-type.rs new file mode 100644 index 000000000..c3811e823 --- /dev/null +++ b/tests/ui/wf/wf-complex-assoc-type.rs @@ -0,0 +1,12 @@ +trait MyTrait {} +struct AssertMyTrait<T: MyTrait>(T); + +trait HelperTrait { + type MyItem; +} + +impl HelperTrait for () { + type MyItem = Option<((AssertMyTrait<bool>, u8))>; //~ ERROR the trait bound +} + +fn main() {} diff --git a/tests/ui/wf/wf-complex-assoc-type.stderr b/tests/ui/wf/wf-complex-assoc-type.stderr new file mode 100644 index 000000000..ef613e313 --- /dev/null +++ b/tests/ui/wf/wf-complex-assoc-type.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `bool: MyTrait` is not satisfied + --> $DIR/wf-complex-assoc-type.rs:9:28 + | +LL | type MyItem = Option<((AssertMyTrait<bool>, u8))>; + | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `bool` + | +note: required by a bound in `AssertMyTrait` + --> $DIR/wf-complex-assoc-type.rs:2:25 + | +LL | struct AssertMyTrait<T: MyTrait>(T); + | ^^^^^^^ required by this bound in `AssertMyTrait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-const-type.rs b/tests/ui/wf/wf-const-type.rs new file mode 100644 index 000000000..df79aa267 --- /dev/null +++ b/tests/ui/wf/wf-const-type.rs @@ -0,0 +1,14 @@ +// Test that we check the types of constants are well-formed. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy<T:Copy> { t: T } +struct NotCopy; + +const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None }; +//~^ ERROR E0277 + + +fn main() { } diff --git a/tests/ui/wf/wf-const-type.stderr b/tests/ui/wf/wf-const-type.stderr new file mode 100644 index 000000000..85938364e --- /dev/null +++ b/tests/ui/wf/wf-const-type.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `NotCopy: Copy` is not satisfied + --> $DIR/wf-const-type.rs:10:12 + | +LL | const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None }; + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` + | + = note: required for `Option<NotCopy>` to implement `Copy` +note: required by a bound in `IsCopy` + --> $DIR/wf-const-type.rs:7:17 + | +LL | struct IsCopy<T:Copy> { t: T } + | ^^^^ required by this bound in `IsCopy` +help: consider annotating `NotCopy` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs new file mode 100644 index 000000000..ffdb49a3b --- /dev/null +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs @@ -0,0 +1,18 @@ +// Check that we do not allow casts or coercions +// to object unsafe trait objects inside a Box + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +fn takes_box(t: Box<dyn Trait>) {} + +fn main() { + Box::new(S) as Box<dyn Trait>; //~ ERROR E0038 + let t_box: Box<dyn Trait> = Box::new(S); //~ ERROR E0038 + takes_box(Box::new(S)); //~ ERROR E0038 +} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr new file mode 100644 index 000000000..6cf4f33f9 --- /dev/null +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr @@ -0,0 +1,51 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33 + | +LL | let t_box: Box<dyn Trait> = Box::new(S); + | ^^^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>` + = note: required by cast to type `Box<dyn Trait>` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15 + | +LL | takes_box(Box::new(S)); + | ^^^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>` + = note: required by cast to type `Box<(dyn Trait + 'static)>` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5 + | +LL | Box::new(S) as Box<dyn Trait>; + | ^^^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>` + = note: required by cast to type `Box<dyn Trait>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs new file mode 100644 index 000000000..143b854ed --- /dev/null +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs @@ -0,0 +1,18 @@ +// Check that we do not allow casts or coercions +// to object unsafe trait objects by ref + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +fn takes_trait(t: &dyn Trait) {} + +fn main() { + &S as &dyn Trait; //~ ERROR E0038 + let t: &dyn Trait = &S; //~ ERROR E0038 + takes_trait(&S); //~ ERROR E0038 +} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr new file mode 100644 index 000000000..c9bd4549a --- /dev/null +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr @@ -0,0 +1,51 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25 + | +LL | let t: &dyn Trait = &S; + | ^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17 + | +LL | takes_trait(&S); + | ^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5 + | +LL | &S as &dyn Trait; + | ^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-enum-bound.rs b/tests/ui/wf/wf-enum-bound.rs new file mode 100644 index 000000000..042a2cb09 --- /dev/null +++ b/tests/ui/wf/wf-enum-bound.rs @@ -0,0 +1,16 @@ +// Test that we check enum bounds for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy<T:Copy> { } + +enum SomeEnum<T,U> + where T: ExtraCopy<U> //~ ERROR E0277 +{ + SomeVariant(T,U) +} + + +fn main() { } diff --git a/tests/ui/wf/wf-enum-bound.stderr b/tests/ui/wf/wf-enum-bound.stderr new file mode 100644 index 000000000..d39fc0c6a --- /dev/null +++ b/tests/ui/wf/wf-enum-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-enum-bound.rs:10:14 + | +LL | where T: ExtraCopy<U> + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-enum-bound.rs:7:19 + | +LL | trait ExtraCopy<T:Copy> { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | where T: ExtraCopy<U>, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-enum-fields-struct-variant.rs b/tests/ui/wf/wf-enum-fields-struct-variant.rs new file mode 100644 index 000000000..c25622fa7 --- /dev/null +++ b/tests/ui/wf/wf-enum-fields-struct-variant.rs @@ -0,0 +1,18 @@ +// Test that we check struct fields for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy<T:Copy> { + value: T +} + +enum AnotherEnum<A> { + AnotherVariant { + f: IsCopy<A> //~ ERROR E0277 + } +} + + +fn main() { } diff --git a/tests/ui/wf/wf-enum-fields-struct-variant.stderr b/tests/ui/wf/wf-enum-fields-struct-variant.stderr new file mode 100644 index 000000000..c12d62521 --- /dev/null +++ b/tests/ui/wf/wf-enum-fields-struct-variant.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `A: Copy` is not satisfied + --> $DIR/wf-enum-fields-struct-variant.rs:13:12 + | +LL | f: IsCopy<A> + | ^^^^^^^^^ the trait `Copy` is not implemented for `A` + | +note: required by a bound in `IsCopy` + --> $DIR/wf-enum-fields-struct-variant.rs:7:17 + | +LL | struct IsCopy<T:Copy> { + | ^^^^ required by this bound in `IsCopy` +help: consider restricting type parameter `A` + | +LL | enum AnotherEnum<A: std::marker::Copy> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-enum-fields.rs b/tests/ui/wf/wf-enum-fields.rs new file mode 100644 index 000000000..a465ffe5e --- /dev/null +++ b/tests/ui/wf/wf-enum-fields.rs @@ -0,0 +1,16 @@ +// Test that we check struct fields for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy<T:Copy> { + value: T +} + +enum SomeEnum<A> { + SomeVariant(IsCopy<A>) //~ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-enum-fields.stderr b/tests/ui/wf/wf-enum-fields.stderr new file mode 100644 index 000000000..ac3301a96 --- /dev/null +++ b/tests/ui/wf/wf-enum-fields.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `A: Copy` is not satisfied + --> $DIR/wf-enum-fields.rs:12:17 + | +LL | SomeVariant(IsCopy<A>) + | ^^^^^^^^^ the trait `Copy` is not implemented for `A` + | +note: required by a bound in `IsCopy` + --> $DIR/wf-enum-fields.rs:7:17 + | +LL | struct IsCopy<T:Copy> { + | ^^^^ required by this bound in `IsCopy` +help: consider restricting type parameter `A` + | +LL | enum SomeEnum<A: std::marker::Copy> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-fn-where-clause.rs b/tests/ui/wf/wf-fn-where-clause.rs new file mode 100644 index 000000000..adae53613 --- /dev/null +++ b/tests/ui/wf/wf-fn-where-clause.rs @@ -0,0 +1,20 @@ +// Test that we check where-clauses on fn items. + + +#![allow(dead_code)] + +trait ExtraCopy<T:Copy> { } + +fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277 +{ +} + +fn bar() where Vec<dyn Copy>:, {} +//~^ ERROR E0277 +//~| ERROR E0038 + +struct Vec<T> { + t: T, +} + +fn main() { } diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr new file mode 100644 index 000000000..2aec641e7 --- /dev/null +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -0,0 +1,49 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-fn-where-clause.rs:8:24 + | +LL | fn foo<T,U>() where T: ExtraCopy<U> + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-fn-where-clause.rs:6:19 + | +LL | trait ExtraCopy<T:Copy> { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | fn foo<T,U>() where T: ExtraCopy<U>, U: std::marker::Copy + | ++++++++++++++++++++++ + +error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time + --> $DIR/wf-fn-where-clause.rs:12:16 + | +LL | fn bar() where Vec<dyn Copy>:, {} + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)` +note: required by a bound in `Vec` + --> $DIR/wf-fn-where-clause.rs:16:12 + | +LL | struct Vec<T> { + | ^ required by this bound in `Vec` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` + --> $DIR/wf-fn-where-clause.rs:16:12 + | +LL | struct Vec<T> { + | ^ this could be changed to `T: ?Sized`... +LL | t: T, + | - ...if indirection were used here: `Box<T>` + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/wf-fn-where-clause.rs:12:16 + | +LL | fn bar() where Vec<dyn Copy>:, {} + | ^^^^^^^^^^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-foreign-fn-decl-ret.rs b/tests/ui/wf/wf-foreign-fn-decl-ret.rs new file mode 100644 index 000000000..b9d956c05 --- /dev/null +++ b/tests/ui/wf/wf-foreign-fn-decl-ret.rs @@ -0,0 +1,18 @@ +pub trait Unsatisfied {} + +#[repr(transparent)] +pub struct Bar<T: Unsatisfied>(T); + +pub trait Foo { + type Assoc; +} + +extern "C" { + pub fn lint_me() -> <() as Foo>::Assoc; + //~^ ERROR: the trait bound `(): Foo` is not satisfied [E0277] + + pub fn lint_me_aswell() -> Bar<u32>; + //~^ ERROR: the trait bound `u32: Unsatisfied` is not satisfied [E0277] +} + +fn main() {} diff --git a/tests/ui/wf/wf-foreign-fn-decl-ret.stderr b/tests/ui/wf/wf-foreign-fn-decl-ret.stderr new file mode 100644 index 000000000..b03023b5f --- /dev/null +++ b/tests/ui/wf/wf-foreign-fn-decl-ret.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/wf-foreign-fn-decl-ret.rs:11:25 + | +LL | pub fn lint_me() -> <() as Foo>::Assoc; + | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + +error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied + --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 + | +LL | pub fn lint_me_aswell() -> Bar<u32>; + | ^^^^^^^^ the trait `Unsatisfied` is not implemented for `u32` + | +note: required by a bound in `Bar` + --> $DIR/wf-foreign-fn-decl-ret.rs:4:19 + | +LL | pub struct Bar<T: Unsatisfied>(T); + | ^^^^^^^^^^^ required by this bound in `Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-impl-associated-type-region.rs b/tests/ui/wf/wf-impl-associated-type-region.rs new file mode 100644 index 000000000..1bf8d3663 --- /dev/null +++ b/tests/ui/wf/wf-impl-associated-type-region.rs @@ -0,0 +1,14 @@ +// Check that we require that associated types in an impl are well-formed. + + + +pub trait Foo<'a> { + type Bar; +} + +impl<'a, T> Foo<'a> for T { + type Bar = &'a T; //~ ERROR E0309 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-impl-associated-type-region.stderr b/tests/ui/wf/wf-impl-associated-type-region.stderr new file mode 100644 index 000000000..b9d4857a3 --- /dev/null +++ b/tests/ui/wf/wf-impl-associated-type-region.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/wf-impl-associated-type-region.rs:10:16 + | +LL | type Bar = &'a T; + | ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Foo<'a> for T { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/wf/wf-impl-associated-type-trait.rs b/tests/ui/wf/wf-impl-associated-type-trait.rs new file mode 100644 index 000000000..84e628e21 --- /dev/null +++ b/tests/ui/wf/wf-impl-associated-type-trait.rs @@ -0,0 +1,22 @@ +// Check that we require that associated types in an impl are well-formed. + + +#![allow(dead_code)] + +pub trait MyHash { } + +pub struct MySet<T:MyHash> { + data: Vec<T> +} + +pub trait Foo { + type Bar; +} + +impl<T> Foo for T { + type Bar = MySet<T>; + //~^ ERROR the trait bound `T: MyHash` is not satisfied +} + + +fn main() { } diff --git a/tests/ui/wf/wf-impl-associated-type-trait.stderr b/tests/ui/wf/wf-impl-associated-type-trait.stderr new file mode 100644 index 000000000..bdf8bba5e --- /dev/null +++ b/tests/ui/wf/wf-impl-associated-type-trait.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: MyHash` is not satisfied + --> $DIR/wf-impl-associated-type-trait.rs:17:16 + | +LL | type Bar = MySet<T>; + | ^^^^^^^^ the trait `MyHash` is not implemented for `T` + | +note: required by a bound in `MySet` + --> $DIR/wf-impl-associated-type-trait.rs:8:20 + | +LL | pub struct MySet<T:MyHash> { + | ^^^^^^ required by this bound in `MySet` +help: consider restricting type parameter `T` + | +LL | impl<T: MyHash> Foo for T { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-impl-self-type.rs b/tests/ui/wf/wf-impl-self-type.rs new file mode 100644 index 000000000..2dd9b4ef0 --- /dev/null +++ b/tests/ui/wf/wf-impl-self-type.rs @@ -0,0 +1,7 @@ +// Tests that we point at the proper location for an error +// involving the self-type of an impl + +trait Foo {} +impl Foo for Option<[u8]> {} //~ ERROR the size for + +fn main() {} diff --git a/tests/ui/wf/wf-impl-self-type.stderr b/tests/ui/wf/wf-impl-self-type.stderr new file mode 100644 index 000000000..1ca368729 --- /dev/null +++ b/tests/ui/wf/wf-impl-self-type.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-impl-self-type.rs:5:14 + | +LL | impl Foo for Option<[u8]> {} + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Option` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-arg.rs b/tests/ui/wf/wf-in-fn-arg.rs new file mode 100644 index 000000000..18df72336 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-arg.rs @@ -0,0 +1,14 @@ +// Check that we enforce WF conditions also for argument types in fn items. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +struct MustBeCopy<T:Copy> { + t: T +} + +fn bar<T>(_: &MustBeCopy<T>) //~ ERROR E0277 +{ +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-arg.stderr b/tests/ui/wf/wf-in-fn-arg.stderr new file mode 100644 index 000000000..83a4a592a --- /dev/null +++ b/tests/ui/wf/wf-in-fn-arg.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-fn-arg.rs:10:15 + | +LL | fn bar<T>(_: &MustBeCopy<T>) + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-arg.rs:6:21 + | +LL | struct MustBeCopy<T:Copy> { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | fn bar<T: std::marker::Copy>(_: &MustBeCopy<T>) + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-ret.rs b/tests/ui/wf/wf-in-fn-ret.rs new file mode 100644 index 000000000..4c9535184 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-ret.rs @@ -0,0 +1,14 @@ +// Check that we enforce WF conditions also for return types in fn items. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +struct MustBeCopy<T:Copy> { + t: T +} + +fn bar<T>() -> MustBeCopy<T> //~ ERROR E0277 +{ +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-ret.stderr b/tests/ui/wf/wf-in-fn-ret.stderr new file mode 100644 index 000000000..7eeb97472 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-ret.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-fn-ret.rs:10:16 + | +LL | fn bar<T>() -> MustBeCopy<T> + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-ret.rs:6:21 + | +LL | struct MustBeCopy<T:Copy> { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | fn bar<T: std::marker::Copy>() -> MustBeCopy<T> + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-type-arg.rs b/tests/ui/wf/wf-in-fn-type-arg.rs new file mode 100644 index 000000000..2917a8aa9 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-arg.rs @@ -0,0 +1,12 @@ +// Check that we enforce WF conditions also for types in fns. + +struct MustBeCopy<T:Copy> { + t: T +} + +struct Bar<T> { + // needs T: Copy + x: fn(MustBeCopy<T>) //~ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-type-arg.stderr b/tests/ui/wf/wf-in-fn-type-arg.stderr new file mode 100644 index 000000000..be5e9d418 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-arg.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-fn-type-arg.rs:9:11 + | +LL | x: fn(MustBeCopy<T>) + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-type-arg.rs:3:21 + | +LL | struct MustBeCopy<T:Copy> { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | struct Bar<T: std::marker::Copy> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-type-ret.rs b/tests/ui/wf/wf-in-fn-type-ret.rs new file mode 100644 index 000000000..ab8e697e3 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-ret.rs @@ -0,0 +1,12 @@ +// Check that we enforce WF conditions also for types in fns. + +struct MustBeCopy<T:Copy> { + t: T +} + +struct Foo<T> { + // needs T: 'static + x: fn() -> MustBeCopy<T> //~ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-type-ret.stderr b/tests/ui/wf/wf-in-fn-type-ret.stderr new file mode 100644 index 000000000..8fcfcb0b2 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-ret.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-fn-type-ret.rs:9:16 + | +LL | x: fn() -> MustBeCopy<T> + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-type-ret.rs:3:21 + | +LL | struct MustBeCopy<T:Copy> { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | struct Foo<T: std::marker::Copy> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-type-static.rs b/tests/ui/wf/wf-in-fn-type-static.rs new file mode 100644 index 000000000..73071dd23 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-static.rs @@ -0,0 +1,22 @@ +// Check that we enforce WF conditions related to regions also for +// types in fns. + +#![allow(dead_code)] + + +struct MustBeCopy<T:Copy> { + t: T +} + +struct Foo<T> { + // needs T: 'static + x: fn() -> &'static T //~ ERROR E0310 +} + +struct Bar<T> { + // needs T: Copy + x: fn(&'static T) //~ ERROR E0310 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-type-static.stderr b/tests/ui/wf/wf-in-fn-type-static.stderr new file mode 100644 index 000000000..73fbb9ca6 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-static.stderr @@ -0,0 +1,25 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-in-fn-type-static.rs:13:8 + | +LL | x: fn() -> &'static T + | ^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | struct Foo<T: 'static> { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-in-fn-type-static.rs:18:8 + | +LL | x: fn(&'static T) + | ^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | struct Bar<T: 'static> { + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/wf/wf-in-fn-where-clause.rs b/tests/ui/wf/wf-in-fn-where-clause.rs new file mode 100644 index 000000000..e55295a3b --- /dev/null +++ b/tests/ui/wf/wf-in-fn-where-clause.rs @@ -0,0 +1,15 @@ +// Check that we enforce WF conditions also for where clauses in fn items. + + +#![allow(dead_code)] + +trait MustBeCopy<T:Copy> { +} + +fn bar<T,U>() + where T: MustBeCopy<U> //~ ERROR E0277 +{ +} + + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-where-clause.stderr b/tests/ui/wf/wf-in-fn-where-clause.stderr new file mode 100644 index 000000000..160a73840 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-in-fn-where-clause.rs:10:14 + | +LL | where T: MustBeCopy<U> + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-where-clause.rs:6:20 + | +LL | trait MustBeCopy<T:Copy> { + | ^^^^ required by this bound in `MustBeCopy` +help: consider further restricting type parameter `U` + | +LL | where T: MustBeCopy<U>, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs new file mode 100644 index 000000000..4fcf8f403 --- /dev/null +++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs @@ -0,0 +1,17 @@ +// Regression test for #80468. + +#![crate_type = "lib"] + +pub trait Trait {} + +#[repr(transparent)] +pub struct Wrapper<T: Trait>(T); + +#[repr(transparent)] +pub struct Ref<'a>(&'a u8); + +impl Trait for Ref {} //~ ERROR: implicit elided lifetime not allowed here + +extern "C" { + pub fn repro(_: Wrapper<Ref>); //~ ERROR: incompatible lifetime on type +} diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr new file mode 100644 index 000000000..94f6dc266 --- /dev/null +++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr @@ -0,0 +1,37 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:16 + | +LL | impl Trait for Ref {} + | ^^^ expected lifetime parameter + | + = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +LL | impl Trait for Ref<'_> {} + | ++++ + +error: incompatible lifetime on type + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21 + | +LL | pub fn repro(_: Wrapper<Ref>); + | ^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:8:23 + | +LL | pub struct Wrapper<T: Trait>(T); + | ^^^^^ introduces a `'static` lifetime requirement +note: the anonymous lifetime as defined here... + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:29 + | +LL | pub fn repro(_: Wrapper<Ref>); + | ^^^ +note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1 + | +LL | impl Trait for Ref {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/wf/wf-in-obj-type-static.rs b/tests/ui/wf/wf-in-obj-type-static.rs new file mode 100644 index 000000000..1ad2fd1ed --- /dev/null +++ b/tests/ui/wf/wf-in-obj-type-static.rs @@ -0,0 +1,18 @@ +// Check that we enforce WF conditions also for types in fns. + + +#![allow(dead_code)] + +trait Object<T> { } + +struct MustBeCopy<T:Copy> { + t: T +} + +struct Foo<T> { + // needs T: 'static + x: dyn Object<&'static T> //~ ERROR E0310 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-in-obj-type-static.stderr b/tests/ui/wf/wf-in-obj-type-static.stderr new file mode 100644 index 000000000..c3ad42dd5 --- /dev/null +++ b/tests/ui/wf/wf-in-obj-type-static.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-in-obj-type-static.rs:14:8 + | +LL | x: dyn Object<&'static T> + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | struct Foo<T: 'static> { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/wf/wf-in-obj-type-trait.rs b/tests/ui/wf/wf-in-obj-type-trait.rs new file mode 100644 index 000000000..170fad55f --- /dev/null +++ b/tests/ui/wf/wf-in-obj-type-trait.rs @@ -0,0 +1,14 @@ +// Check that we enforce WF conditions also for types in fns. + +trait Object<T> { } + +struct MustBeCopy<T:Copy> { + t: T +} + +struct Bar<T> { + // needs T: Copy + x: dyn Object<MustBeCopy<T>> //~ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-obj-type-trait.stderr b/tests/ui/wf/wf-in-obj-type-trait.stderr new file mode 100644 index 000000000..f556b678e --- /dev/null +++ b/tests/ui/wf/wf-in-obj-type-trait.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-obj-type-trait.rs:11:19 + | +LL | x: dyn Object<MustBeCopy<T>> + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-obj-type-trait.rs:5:21 + | +LL | struct MustBeCopy<T:Copy> { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | struct Bar<T: std::marker::Copy> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-inherent-impl-method-where-clause.rs b/tests/ui/wf/wf-inherent-impl-method-where-clause.rs new file mode 100644 index 000000000..eb50fc010 --- /dev/null +++ b/tests/ui/wf/wf-inherent-impl-method-where-clause.rs @@ -0,0 +1,17 @@ +// Test that we check where-clauses on inherent impl methods. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy<T:Copy> { } + +struct Foo<T,U>(T,U); + +impl<T,U> Foo<T,U> { + fn foo(self) where T: ExtraCopy<U> //~ ERROR E0277 + {} +} + + +fn main() { } diff --git a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr new file mode 100644 index 000000000..e723d1ba7 --- /dev/null +++ b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-inherent-impl-method-where-clause.rs:12:27 + | +LL | fn foo(self) where T: ExtraCopy<U> + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-inherent-impl-method-where-clause.rs:7:19 + | +LL | trait ExtraCopy<T:Copy> { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider restricting type parameter `U` + | +LL | impl<T,U: std::marker::Copy> Foo<T,U> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-inherent-impl-where-clause.rs b/tests/ui/wf/wf-inherent-impl-where-clause.rs new file mode 100644 index 000000000..ac194fb13 --- /dev/null +++ b/tests/ui/wf/wf-inherent-impl-where-clause.rs @@ -0,0 +1,16 @@ +// Test that we check where-clauses on inherent impls. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy<T:Copy> { } + +struct Foo<T,U>(T,U); + +impl<T,U> Foo<T,U> where T: ExtraCopy<U> //~ ERROR E0277 +{ +} + + +fn main() { } diff --git a/tests/ui/wf/wf-inherent-impl-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-where-clause.stderr new file mode 100644 index 000000000..39e0d348e --- /dev/null +++ b/tests/ui/wf/wf-inherent-impl-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-inherent-impl-where-clause.rs:11:29 + | +LL | impl<T,U> Foo<T,U> where T: ExtraCopy<U> + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-inherent-impl-where-clause.rs:7:19 + | +LL | trait ExtraCopy<T:Copy> { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | impl<T,U> Foo<T,U> where T: ExtraCopy<U>, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-misc-methods-issue-28609.rs b/tests/ui/wf/wf-misc-methods-issue-28609.rs new file mode 100644 index 000000000..050f866e1 --- /dev/null +++ b/tests/ui/wf/wf-misc-methods-issue-28609.rs @@ -0,0 +1,74 @@ +// check that misc. method calls are well-formed + +use std::marker::PhantomData; +use std::ops::{Deref, Shl}; + +#[derive(Copy, Clone)] +struct S<'a, 'b: 'a> { + marker: PhantomData<&'a &'b ()>, + bomb: Option<&'b u32> +} + +type S2<'a> = S<'a, 'a>; + +impl<'a, 'b> S<'a, 'b> { + fn transmute_inherent(&self, a: &'b u32) -> &'a u32 { + a + } +} + +fn return_dangling_pointer_inherent(s: S2) -> &u32 { + let s = s; + s.transmute_inherent(&mut 42) //~ ERROR cannot return value referencing temporary value +} + +impl<'a, 'b> Deref for S<'a, 'b> { + type Target = &'a u32; + fn deref(&self) -> &&'a u32 { + self.bomb.as_ref().unwrap() + } +} + +fn return_dangling_pointer_coerce(s: S2) -> &u32 { + let four = 4; + let mut s = s; + s.bomb = Some(&four); + &s //~ ERROR cannot return value referencing local variable `four` +} + +fn return_dangling_pointer_unary_op(s: S2) -> &u32 { + let four = 4; + let mut s = s; + s.bomb = Some(&four); + &*s //~ ERROR cannot return value referencing local variable `four` +} + +impl<'a, 'b> Shl<&'b u32> for S<'a, 'b> { + type Output = &'a u32; + fn shl(self, t: &'b u32) -> &'a u32 { t } +} + +fn return_dangling_pointer_binary_op(s: S2) -> &u32 { + let s = s; + s << &mut 3 //~ ERROR cannot return value referencing temporary value +} + +fn return_dangling_pointer_method(s: S2) -> &u32 { + let s = s; + s.shl(&mut 3) //~ ERROR cannot return value referencing temporary value +} + +fn return_dangling_pointer_ufcs(s: S2) -> &u32 { + let s = s; + S2::shl(s, &mut 3) //~ ERROR cannot return value referencing temporary value +} + +fn main() { + let s = S { marker: PhantomData, bomb: None }; + let _inherent_dp = return_dangling_pointer_inherent(s); + let _coerce_dp = return_dangling_pointer_coerce(s); + let _unary_dp = return_dangling_pointer_unary_op(s); + let _binary_dp = return_dangling_pointer_binary_op(s); + let _method_dp = return_dangling_pointer_method(s); + let _ufcs_dp = return_dangling_pointer_ufcs(s); +} diff --git a/tests/ui/wf/wf-misc-methods-issue-28609.stderr b/tests/ui/wf/wf-misc-methods-issue-28609.stderr new file mode 100644 index 000000000..fc5898434 --- /dev/null +++ b/tests/ui/wf/wf-misc-methods-issue-28609.stderr @@ -0,0 +1,55 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/wf-misc-methods-issue-28609.rs:22:5 + | +LL | s.transmute_inherent(&mut 42) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^--^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing local variable `four` + --> $DIR/wf-misc-methods-issue-28609.rs:36:5 + | +LL | s.bomb = Some(&four); + | ----- `four` is borrowed here +LL | &s + | ^^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing local variable `four` + --> $DIR/wf-misc-methods-issue-28609.rs:43:5 + | +LL | s.bomb = Some(&four); + | ----- `four` is borrowed here +LL | &*s + | ^^^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/wf-misc-methods-issue-28609.rs:53:5 + | +LL | s << &mut 3 + | ^^^^^^^^^^- + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/wf-misc-methods-issue-28609.rs:58:5 + | +LL | s.shl(&mut 3) + | ^^^^^^^^^^^-^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/wf-misc-methods-issue-28609.rs:63:5 + | +LL | S2::shl(s, &mut 3) + | ^^^^^^^^^^^^^^^^-^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/wf/wf-object-safe.rs b/tests/ui/wf/wf-object-safe.rs new file mode 100644 index 000000000..42e691755 --- /dev/null +++ b/tests/ui/wf/wf-object-safe.rs @@ -0,0 +1,10 @@ +// Check that object-safe traits are not WF when used as object types. +// Issue #21953. + +trait A { + fn foo(&self, _x: &Self); +} + +fn main() { + let _x: &dyn A; //~ ERROR E0038 +} diff --git a/tests/ui/wf/wf-object-safe.stderr b/tests/ui/wf/wf-object-safe.stderr new file mode 100644 index 000000000..64969fbe3 --- /dev/null +++ b/tests/ui/wf/wf-object-safe.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/wf-object-safe.rs:9:13 + | +LL | let _x: &dyn A; + | ^^^^^^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-object-safe.rs:5:23 + | +LL | trait A { + | - this trait cannot be made into an object... +LL | fn foo(&self, _x: &Self); + | ^^^^^ ...because method `foo` references the `Self` type in this parameter + = help: consider moving `foo` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.rs b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.rs new file mode 100644 index 000000000..85a332e24 --- /dev/null +++ b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.rs @@ -0,0 +1,22 @@ +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait Trait<'a, T> { + type Out; +} + +impl<'a, T> Trait<'a, T> for usize { + type Out = &'a fn(T); //~ ERROR `T` may not live long enough +} + +struct Foo<'a,T> { + f: &'a fn(T), +} + +trait Baz<T> { } + +impl<'a, T> Trait<'a, T> for u32 { + type Out = &'a dyn Baz<T>; //~ ERROR `T` may not live long enough +} + +fn main() { } diff --git a/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr new file mode 100644 index 000000000..4d4d8b2ab --- /dev/null +++ b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr @@ -0,0 +1,25 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:16 + | +LL | type Out = &'a fn(T); + | ^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Trait<'a, T> for usize { + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:16 + | +LL | type Out = &'a dyn Baz<T>; + | ^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Trait<'a, T> for u32 { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs new file mode 100644 index 000000000..d0167c8c2 --- /dev/null +++ b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs @@ -0,0 +1,31 @@ +// rust-lang/rust#58158: We have special-case code to deal with case +// when a type is both packed and needs drop glue, (we move the fields +// out of their potentially unaligned locations before dropping them, +// which requires they be Sized; see PR #44884). +// +// So, we need to check if a given type needs drop-glue. That requires +// that we actually know that the concrete type, and we guard against +// the type having unknown parts (i.e. type variables) by ICE'ing in +// that scenario. +// +// But in a case where we have a projection (`Type as Trait::Assoc`) +// where `Type` does not actually implement `Trait`, we of course +// cannot have a concrete type, because there is no impl to look up +// the concrete type for the associated type `Assoc`. +// +// So, this test is just making sure that in such a case that we do +// not immediately ICE, and instead allow the underlying type error to +// surface. + +pub struct Matrix<S>(S); +pub struct DefaultAllocator; + +pub trait Allocator { type Buffer; } + +// impl Allocator for DefaultAllocator { type Buffer = (); } + +#[repr(packed)] +struct Foo(Matrix<<DefaultAllocator as Allocator>::Buffer>); +//~^ ERROR the trait bound `DefaultAllocator: Allocator` is not satisfied + +fn main() { } diff --git a/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr new file mode 100644 index 000000000..e460cdcd3 --- /dev/null +++ b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `DefaultAllocator: Allocator` is not satisfied + --> $DIR/wf-packed-on-proj-of-type-as-unimpl-trait.rs:28:12 + | +LL | struct Foo(Matrix<<DefaultAllocator as Allocator>::Buffer>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Allocator` is not implemented for `DefaultAllocator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-static-method.rs b/tests/ui/wf/wf-static-method.rs new file mode 100644 index 000000000..7ff195230 --- /dev/null +++ b/tests/ui/wf/wf-static-method.rs @@ -0,0 +1,59 @@ +// check that static methods don't get to assume their trait-ref +// is well-formed. +// FIXME(#27579): this is just a bug. However, our checking with +// static inherent methods isn't quite working - need to +// fix that before removing the check. + +trait Foo<'a, 'b, T>: Sized { + fn make_me() -> Self { loop {} } + fn static_evil(u: &'b u32) -> &'a u32; +} + +struct Evil<'a, 'b: 'a>(Option<&'a &'b ()>); + +impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { + fn make_me() -> Self { } + fn static_evil(u: &'b u32) -> &'a u32 { + u + //~^ ERROR lifetime may not live long enough + } +} + +struct IndirectEvil<'a, 'b: 'a>(Option<&'a &'b ()>); + +impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { + fn make_me() -> Self { IndirectEvil(None) } + fn static_evil(u: &'b u32) -> &'a u32 { + let me = Self::make_me(); + //~^ ERROR lifetime may not live long enough + loop {} // (`me` could be used for the lifetime transmute). + } +} + +impl<'a, 'b> Evil<'a, 'b> { + fn inherent_evil(u: &'b u32) -> &'a u32 { + u + //~^ ERROR lifetime may not live long enough + } +} + +// while static methods don't get to *assume* this, we still +// *check* that they hold. + +fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { + <()>::static_evil(b) + //~^ ERROR lifetime may not live long enough +} + +fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + <IndirectEvil>::static_evil(b) + //~^ ERROR lifetime may not live long enough +} + +fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + <Evil>::inherent_evil(b) + //~^ ERROR lifetime may not live long enough +} + + +fn main() {} diff --git a/tests/ui/wf/wf-static-method.stderr b/tests/ui/wf/wf-static-method.stderr new file mode 100644 index 000000000..161609a5f --- /dev/null +++ b/tests/ui/wf/wf-static-method.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:17:9 + | +LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | u + | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:27:18 + | +LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let me = Self::make_me(); + | ^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:35:9 + | +LL | impl<'a, 'b> Evil<'a, 'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | fn inherent_evil(u: &'b u32) -> &'a u32 { +LL | u + | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:44:5 + | +LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | <()>::static_evil(b) + | ^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:49:5 + | +LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | <IndirectEvil>::static_evil(b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:54:5 + | +LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | <Evil>::inherent_evil(b) + | ^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/wf/wf-static-type.rs b/tests/ui/wf/wf-static-type.rs new file mode 100644 index 000000000..1c35e1daf --- /dev/null +++ b/tests/ui/wf/wf-static-type.rs @@ -0,0 +1,14 @@ +// Test that we check the types of statics are well-formed. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy<T:Copy> { t: T } +struct NotCopy; + +static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None }; +//~^ ERROR E0277 + + +fn main() { } diff --git a/tests/ui/wf/wf-static-type.stderr b/tests/ui/wf/wf-static-type.stderr new file mode 100644 index 000000000..16c6124b6 --- /dev/null +++ b/tests/ui/wf/wf-static-type.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `NotCopy: Copy` is not satisfied + --> $DIR/wf-static-type.rs:10:13 + | +LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None }; + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` + | + = note: required for `Option<NotCopy>` to implement `Copy` +note: required by a bound in `IsCopy` + --> $DIR/wf-static-type.rs:7:17 + | +LL | struct IsCopy<T:Copy> { t: T } + | ^^^^ required by this bound in `IsCopy` +help: consider annotating `NotCopy` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-struct-bound.rs b/tests/ui/wf/wf-struct-bound.rs new file mode 100644 index 000000000..6e558ca8f --- /dev/null +++ b/tests/ui/wf/wf-struct-bound.rs @@ -0,0 +1,16 @@ +// Test that we check struct bounds for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy<T:Copy> { } + +struct SomeStruct<T,U> + where T: ExtraCopy<U> //~ ERROR E0277 +{ + data: (T,U) +} + + +fn main() { } diff --git a/tests/ui/wf/wf-struct-bound.stderr b/tests/ui/wf/wf-struct-bound.stderr new file mode 100644 index 000000000..6248e3e4e --- /dev/null +++ b/tests/ui/wf/wf-struct-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-struct-bound.rs:10:14 + | +LL | where T: ExtraCopy<U> + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-struct-bound.rs:7:19 + | +LL | trait ExtraCopy<T:Copy> { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | where T: ExtraCopy<U>, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-struct-field.rs b/tests/ui/wf/wf-struct-field.rs new file mode 100644 index 000000000..63f8b4382 --- /dev/null +++ b/tests/ui/wf/wf-struct-field.rs @@ -0,0 +1,16 @@ +// Test that we check struct fields for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy<T:Copy> { + value: T +} + +struct SomeStruct<A> { + data: IsCopy<A> //~ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-struct-field.stderr b/tests/ui/wf/wf-struct-field.stderr new file mode 100644 index 000000000..78a8da860 --- /dev/null +++ b/tests/ui/wf/wf-struct-field.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `A: Copy` is not satisfied + --> $DIR/wf-struct-field.rs:12:11 + | +LL | data: IsCopy<A> + | ^^^^^^^^^ the trait `Copy` is not implemented for `A` + | +note: required by a bound in `IsCopy` + --> $DIR/wf-struct-field.rs:7:17 + | +LL | struct IsCopy<T:Copy> { + | ^^^^ required by this bound in `IsCopy` +help: consider restricting type parameter `A` + | +LL | struct SomeStruct<A: std::marker::Copy> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-associated-type-bound.rs b/tests/ui/wf/wf-trait-associated-type-bound.rs new file mode 100644 index 000000000..2f20e65e5 --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-bound.rs @@ -0,0 +1,14 @@ +// Test that we check associated type bounds for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy<T:Copy> { } + +trait SomeTrait<T> { + type Type1: ExtraCopy<T>; //~ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-associated-type-bound.stderr b/tests/ui/wf/wf-trait-associated-type-bound.stderr new file mode 100644 index 000000000..829770017 --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-trait-associated-type-bound.rs:10:17 + | +LL | type Type1: ExtraCopy<T>; + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-trait-associated-type-bound.rs:7:19 + | +LL | trait ExtraCopy<T:Copy> { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider restricting type parameter `T` + | +LL | trait SomeTrait<T: std::marker::Copy> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-associated-type-region.rs b/tests/ui/wf/wf-trait-associated-type-region.rs new file mode 100644 index 000000000..0dfc9f098 --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-region.rs @@ -0,0 +1,14 @@ +// Test that we check associated type default values for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait SomeTrait<'a> { + type Type1; + type Type2 = &'a Self::Type1; + //~^ ERROR E0309 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-associated-type-region.stderr b/tests/ui/wf/wf-trait-associated-type-region.stderr new file mode 100644 index 000000000..6e2cc8aba --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-region.stderr @@ -0,0 +1,12 @@ +error[E0309]: the associated type `<Self as SomeTrait<'a>>::Type1` may not live long enough + --> $DIR/wf-trait-associated-type-region.rs:9:18 + | +LL | type Type2 = &'a Self::Type1; + | ^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<Self as SomeTrait<'a>>::Type1: 'a`... + = note: ...so that the reference type `&'a <Self as SomeTrait<'a>>::Type1` does not outlive the data it points at + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/wf/wf-trait-associated-type-trait.rs b/tests/ui/wf/wf-trait-associated-type-trait.rs new file mode 100644 index 000000000..d67e110ed --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-trait.rs @@ -0,0 +1,16 @@ +// Test that we check associated type default values for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy<T:Copy> { x: T } + +trait SomeTrait { + type Type1; + type Type2 = (IsCopy<Self::Type1>, bool); + //~^ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-associated-type-trait.stderr b/tests/ui/wf/wf-trait-associated-type-trait.stderr new file mode 100644 index 000000000..a73c3a2ae --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-trait.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `<Self as SomeTrait>::Type1: Copy` is not satisfied + --> $DIR/wf-trait-associated-type-trait.rs:11:19 + | +LL | type Type2 = (IsCopy<Self::Type1>, bool); + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `<Self as SomeTrait>::Type1` + | +note: required by a bound in `IsCopy` + --> $DIR/wf-trait-associated-type-trait.rs:7:17 + | +LL | struct IsCopy<T:Copy> { x: T } + | ^^^^ required by this bound in `IsCopy` +help: consider further restricting the associated type + | +LL | trait SomeTrait where <Self as SomeTrait>::Type1: Copy { + | ++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-bound.rs b/tests/ui/wf/wf-trait-bound.rs new file mode 100644 index 000000000..62a1eb5b0 --- /dev/null +++ b/tests/ui/wf/wf-trait-bound.rs @@ -0,0 +1,15 @@ +// Test that we check supertrait bounds for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy<T:Copy> { } + +trait SomeTrait<T,U> + where T: ExtraCopy<U> //~ ERROR E0277 +{ +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-bound.stderr b/tests/ui/wf/wf-trait-bound.stderr new file mode 100644 index 000000000..bace3e3ef --- /dev/null +++ b/tests/ui/wf/wf-trait-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-trait-bound.rs:10:14 + | +LL | where T: ExtraCopy<U> + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-trait-bound.rs:7:19 + | +LL | trait ExtraCopy<T:Copy> { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | where T: ExtraCopy<U>, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-arg.rs b/tests/ui/wf/wf-trait-default-fn-arg.rs new file mode 100644 index 000000000..64fc35aeb --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-arg.rs @@ -0,0 +1,19 @@ +// Check that we test WF conditions for fn arguments. Because the +// current code is so goofy, this is only a warning for now. + + +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar<T:Eq+?Sized> { value: Box<T> } + +trait Foo { + fn bar(&self, x: &Bar<Self>) { + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. + } +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-default-fn-arg.stderr b/tests/ui/wf/wf-trait-default-fn-arg.stderr new file mode 100644 index 000000000..8c3d0568f --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-arg.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-default-fn-arg.rs:11:23 + | +LL | fn bar(&self, x: &Bar<Self>) { + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-default-fn-arg.rs:8:14 + | +LL | struct Bar<T:Eq+?Sized> { value: Box<T> } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self, x: &Bar<Self>) where Self: Eq { + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-ret.rs b/tests/ui/wf/wf-trait-default-fn-ret.rs new file mode 100644 index 000000000..2103dae8d --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-ret.rs @@ -0,0 +1,19 @@ +// Check that we test WF conditions for fn arguments. Because the +// current code is so goofy, this is only a warning for now. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar<T:Eq+?Sized> { value: Box<T> } + +trait Foo { + fn bar(&self) -> Bar<Self> { + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. + loop { } + } +} + +fn main() { } diff --git a/tests/ui/wf/wf-trait-default-fn-ret.stderr b/tests/ui/wf/wf-trait-default-fn-ret.stderr new file mode 100644 index 000000000..6422e862d --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-ret.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-default-fn-ret.rs:11:22 + | +LL | fn bar(&self) -> Bar<Self> { + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-default-fn-ret.rs:8:14 + | +LL | struct Bar<T:Eq+?Sized> { value: Box<T> } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self) -> Bar<Self> where Self: Eq { + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-where-clause.rs b/tests/ui/wf/wf-trait-default-fn-where-clause.rs new file mode 100644 index 000000000..ded97214f --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-where-clause.rs @@ -0,0 +1,19 @@ +// Check that we test WF conditions for fn arguments. Because the +// current code is so goofy, this is only a warning for now. + + +#![allow(dead_code)] +#![allow(unused_variables)] + +trait Bar<T:Eq+?Sized> { } + +trait Foo { + fn bar<A>(&self) where A: Bar<Self> { + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. + } +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-default-fn-where-clause.stderr b/tests/ui/wf/wf-trait-default-fn-where-clause.stderr new file mode 100644 index 000000000..f260d5750 --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-default-fn-where-clause.rs:11:31 + | +LL | fn bar<A>(&self) where A: Bar<Self> { + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-default-fn-where-clause.rs:8:13 + | +LL | trait Bar<T:Eq+?Sized> { } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar<A>(&self) where A: Bar<Self>, Self: Eq { + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-arg.rs b/tests/ui/wf/wf-trait-fn-arg.rs new file mode 100644 index 000000000..044569942 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-arg.rs @@ -0,0 +1,16 @@ +// Check that we test WF conditions for fn arguments in a trait definition. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar<T:Eq+?Sized> { value: Box<T> } + +trait Foo { + fn bar(&self, x: &Bar<Self>); + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. +} + +fn main() { } diff --git a/tests/ui/wf/wf-trait-fn-arg.stderr b/tests/ui/wf/wf-trait-fn-arg.stderr new file mode 100644 index 000000000..3bd1f4892 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-arg.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-arg.rs:10:23 + | +LL | fn bar(&self, x: &Bar<Self>); + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-arg.rs:7:14 + | +LL | struct Bar<T:Eq+?Sized> { value: Box<T> } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self, x: &Bar<Self>) where Self: Eq; + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-ret.rs b/tests/ui/wf/wf-trait-fn-ret.rs new file mode 100644 index 000000000..f49e43087 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-ret.rs @@ -0,0 +1,16 @@ +// Check that we test WF conditions for fn return types in a trait definition. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar<T:Eq+?Sized> { value: Box<T> } + +trait Foo { + fn bar(&self) -> &Bar<Self>; + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. +} + +fn main() { } diff --git a/tests/ui/wf/wf-trait-fn-ret.stderr b/tests/ui/wf/wf-trait-fn-ret.stderr new file mode 100644 index 000000000..9bd3cc771 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-ret.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-ret.rs:10:23 + | +LL | fn bar(&self) -> &Bar<Self>; + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-ret.rs:7:14 + | +LL | struct Bar<T:Eq+?Sized> { value: Box<T> } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self) -> &Bar<Self> where Self: Eq; + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-where-clause.rs b/tests/ui/wf/wf-trait-fn-where-clause.rs new file mode 100644 index 000000000..1d2427ff9 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-where-clause.rs @@ -0,0 +1,17 @@ +// Check that we test WF conditions for fn where clauses in a trait definition. + + +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar<T:Eq+?Sized> { value: Box<T> } + +trait Foo { + fn bar(&self) where Self: Sized, Bar<Self>: Copy; + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-fn-where-clause.stderr b/tests/ui/wf/wf-trait-fn-where-clause.stderr new file mode 100644 index 000000000..d064f7fc5 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-where-clause.rs:10:49 + | +LL | fn bar(&self) where Self: Sized, Bar<Self>: Copy; + | ^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-where-clause.rs:7:14 + | +LL | struct Bar<T:Eq+?Sized> { value: Box<T> } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self) where Self: Sized, Bar<Self>: Copy, Self: Eq; + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-superbound.rs b/tests/ui/wf/wf-trait-superbound.rs new file mode 100644 index 000000000..8905a8820 --- /dev/null +++ b/tests/ui/wf/wf-trait-superbound.rs @@ -0,0 +1,12 @@ +// Test that we check supertrait bounds for WFedness. + +#![feature(associated_type_defaults)] +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait ExtraCopy<T:Copy> { } + +trait SomeTrait<T>: ExtraCopy<T> { //~ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/wf/wf-trait-superbound.stderr b/tests/ui/wf/wf-trait-superbound.stderr new file mode 100644 index 000000000..cd49243a4 --- /dev/null +++ b/tests/ui/wf/wf-trait-superbound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-trait-superbound.rs:9:21 + | +LL | trait SomeTrait<T>: ExtraCopy<T> { + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-trait-superbound.rs:7:19 + | +LL | trait ExtraCopy<T:Copy> { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider restricting type parameter `T` + | +LL | trait SomeTrait<T: std::marker::Copy>: ExtraCopy<T> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.rs b/tests/ui/wf/wf-unsafe-trait-obj-match.rs new file mode 100644 index 000000000..c8731a8ec --- /dev/null +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.rs @@ -0,0 +1,29 @@ +// Check that we do not allow coercions to object +// unsafe trait objects in match arms + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +struct R; + +impl Trait for R {} + +fn opt() -> Option<()> { + Some(()) +} + +fn main() { + match opt() { + Some(()) => &S, + None => &R, //~ ERROR E0308 + } + let t: &dyn Trait = match opt() { //~ ERROR E0038 + Some(()) => &S, //~ ERROR E0038 + None => &R, + }; +} diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr new file mode 100644 index 000000000..96fc1d36b --- /dev/null +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr @@ -0,0 +1,54 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/wf-unsafe-trait-obj-match.rs:23:17 + | +LL | / match opt() { +LL | | Some(()) => &S, + | | -- this is found to be of type `&S` +LL | | None => &R, + | | ^^ expected struct `S`, found struct `R` +LL | | } + | |_____- `match` arms have incompatible types + | + = note: expected reference `&S` + found reference `&R` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-unsafe-trait-obj-match.rs:26:21 + | +LL | Some(()) => &S, + | ^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-unsafe-trait-obj-match.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-unsafe-trait-obj-match.rs:25:25 + | +LL | let t: &dyn Trait = match opt() { + | _________________________^ +LL | | Some(()) => &S, +LL | | None => &R, +LL | | }; + | |_____^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/wf-unsafe-trait-obj-match.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&R` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0308. +For more information about an error, try `rustc --explain E0038`. |