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/object-safety | |
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/object-safety')
30 files changed, 744 insertions, 0 deletions
diff --git a/src/test/ui/object-safety/issue-19538.rs b/src/test/ui/object-safety/issue-19538.rs new file mode 100644 index 000000000..7054ef41b --- /dev/null +++ b/src/test/ui/object-safety/issue-19538.rs @@ -0,0 +1,20 @@ +trait Foo { + fn foo<T>(&self, val: T); +} + +trait Bar: Foo { } + +pub struct Thing; + +impl Foo for Thing { + fn foo<T>(&self, val: T) { } +} + +impl Bar for Thing { } + +fn main() { + let mut thing = Thing; + let test: &mut dyn Bar = &mut thing; + //~^ ERROR E0038 + //~| ERROR E0038 +} diff --git a/src/test/ui/object-safety/issue-19538.stderr b/src/test/ui/object-safety/issue-19538.stderr new file mode 100644 index 000000000..7b37e1f95 --- /dev/null +++ b/src/test/ui/object-safety/issue-19538.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-19538.rs:17:15 + | +LL | let test: &mut dyn Bar = &mut thing; + | ^^^^^^^^^^^^ `Bar` 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-19538.rs:2:8 + | +LL | fn foo<T>(&self, val: T); + | ^^^ ...because method `foo` has generic type parameters +... +LL | trait Bar: Foo { } + | --- this trait cannot be made into an object... + = help: consider moving `foo` to another trait + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-19538.rs:17:30 + | +LL | let test: &mut dyn Bar = &mut thing; + | ^^^^^^^^^^ `Bar` 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-19538.rs:2:8 + | +LL | fn foo<T>(&self, val: T); + | ^^^ ...because method `foo` has generic type parameters +... +LL | trait Bar: Foo { } + | --- this trait cannot be made into an object... + = help: consider moving `foo` to another trait + = note: required because of the requirements on the impl of `CoerceUnsized<&mut dyn Bar>` for `&mut Thing` + = note: required by cast to type `&mut dyn Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr new file mode 100644 index 000000000..9dd144fee --- /dev/null +++ b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-associated-consts.rs:12:30 + | +LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + | ^^^^^^^^ `Bar` 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/object-safety-associated-consts.rs:9:11 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | const X: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..9ba3b251e --- /dev/null +++ b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr @@ -0,0 +1,20 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-associated-consts.rs:14:5 + | +LL | t + | ^ `Bar` 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/object-safety-associated-consts.rs:9:11 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | const X: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait + = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-associated-consts.rs b/src/test/ui/object-safety/object-safety-associated-consts.rs new file mode 100644 index 000000000..e1a772e5a --- /dev/null +++ b/src/test/ui/object-safety/object-safety-associated-consts.rs @@ -0,0 +1,19 @@ +// Check that we correctly prevent users from making trait objects +// from traits with associated consts. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +trait Bar { + const X: usize; +} + +fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn main() { +} diff --git a/src/test/ui/object-safety/object-safety-bounds.rs b/src/test/ui/object-safety/object-safety-bounds.rs new file mode 100644 index 000000000..44bd36932 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-bounds.rs @@ -0,0 +1,12 @@ +// Traits with bounds mentioning `Self` are not object safe + +trait X { + type U: PartialEq<Self>; +} + +fn f() -> Box<dyn X<U = u32>> { + //~^ ERROR the trait `X` cannot be made into an object + loop {} +} + +fn main() {} diff --git a/src/test/ui/object-safety/object-safety-bounds.stderr b/src/test/ui/object-safety/object-safety-bounds.stderr new file mode 100644 index 000000000..89c4f8ced --- /dev/null +++ b/src/test/ui/object-safety/object-safety-bounds.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/object-safety-bounds.rs:7:11 + | +LL | fn f() -> Box<dyn X<U = u32>> { + | ^^^^^^^^^^^^^^^^^^^ `X` 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/object-safety-bounds.rs:4:13 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type U: PartialEq<Self>; + | ^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.rs b/src/test/ui/object-safety/object-safety-by-value-self-use.rs new file mode 100644 index 000000000..8e93c5382 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-by-value-self-use.rs @@ -0,0 +1,18 @@ +// Check that while a trait with by-value self is object-safe, we +// can't actually invoke it from an object (yet...?). + +#![feature(rustc_attrs)] + +trait Bar { + fn bar(self); +} + +trait Baz { + fn baz(self: Self); +} + +fn use_bar(t: Box<dyn Bar>) { + t.bar() //~ ERROR cannot move a value of type `dyn Bar` +} + +fn main() { } diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.stderr b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr new file mode 100644 index 000000000..94fdcdf26 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr @@ -0,0 +1,9 @@ +error[E0161]: cannot move a value of type `dyn Bar` + --> $DIR/object-safety-by-value-self-use.rs:15:5 + | +LL | t.bar() + | ^^^^^^^ the size of `dyn Bar` 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/object-safety/object-safety-by-value-self.rs b/src/test/ui/object-safety/object-safety-by-value-self.rs new file mode 100644 index 000000000..c74a4d1cb --- /dev/null +++ b/src/test/ui/object-safety/object-safety-by-value-self.rs @@ -0,0 +1,46 @@ +// Check that a trait with by-value self is considered object-safe. + +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +#![allow(trivial_casts)] + +trait Bar { + fn bar(self); +} + +trait Baz { + fn baz(self: Self); +} + +trait Quux { + // Legal because of the where clause: + fn baz(self: Self) where Self : Sized; +} + +fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + t // legal +} + +fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar { + t as &dyn Bar // legal +} + +fn make_baz<T:Baz>(t: &T) -> &dyn Baz { + t // legal +} + +fn make_baz_explicit<T:Baz>(t: &T) -> &dyn Baz { + t as &dyn Baz // legal +} + +fn make_quux<T:Quux>(t: &T) -> &dyn Quux { + t +} + +fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux { + t as &dyn Quux +} + + +fn main() { +} diff --git a/src/test/ui/object-safety/object-safety-generics.curr.stderr b/src/test/ui/object-safety/object-safety-generics.curr.stderr new file mode 100644 index 000000000..345950f1a --- /dev/null +++ b/src/test/ui/object-safety/object-safety-generics.curr.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:18:30 + | +LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + | ^^^^^^^^ `Bar` 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/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar<T>(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:24:39 + | +LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar { + | ^^^^^^^^ `Bar` 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/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar<T>(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..86355627c --- /dev/null +++ b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:20:5 + | +LL | t + | ^ `Bar` 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/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar<T>(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:26:5 + | +LL | t as &dyn Bar + | ^ `Bar` 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/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar<T>(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-generics.rs b/src/test/ui/object-safety/object-safety-generics.rs new file mode 100644 index 000000000..63dcd1699 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-generics.rs @@ -0,0 +1,39 @@ +// Check that we correctly prevent users from making trait objects +// from traits with generic methods, unless `where Self : Sized` is +// present. +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + + +trait Bar { + fn bar<T>(&self, t: T); +} + +trait Quux { + fn bar<T>(&self, t: T) + where Self : Sized; +} + +fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t as &dyn Bar + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn make_quux<T:Quux>(t: &T) -> &dyn Quux { + t +} + +fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux { + t as &dyn Quux +} + +fn main() { +} diff --git a/src/test/ui/object-safety/object-safety-issue-22040.rs b/src/test/ui/object-safety/object-safety-issue-22040.rs new file mode 100644 index 000000000..1fc5c5442 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-issue-22040.rs @@ -0,0 +1,42 @@ +// Regression test for #22040. + +use std::fmt::Debug; + +trait Expr: Debug + PartialEq { + fn print_element_count(&self); +} + +//#[derive(PartialEq)] +#[derive(Debug)] +struct SExpr<'x> { + elements: Vec<Box<dyn Expr + 'x>>, + //~^ ERROR E0038 +} + +impl<'x> PartialEq for SExpr<'x> { + fn eq(&self, other:&SExpr<'x>) -> bool { + println!("L1: {} L2: {}", self.elements.len(), other.elements.len()); + + let result = self.elements.len() == other.elements.len(); + + println!("Got compare {}", result); + return result; + } +} + +impl <'x> SExpr<'x> { + fn new() -> SExpr<'x> { return SExpr{elements: Vec::new(),}; } +} + +impl <'x> Expr for SExpr<'x> { + fn print_element_count(&self) { + println!("element count: {}", self.elements.len()); + } +} + +fn main() { + let a: Box<dyn Expr> = Box::new(SExpr::new()); + let b: Box<dyn Expr> = Box::new(SExpr::new()); + + // assert_eq!(a , b); +} diff --git a/src/test/ui/object-safety/object-safety-issue-22040.stderr b/src/test/ui/object-safety/object-safety-issue-22040.stderr new file mode 100644 index 000000000..0262d5362 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-issue-22040.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Expr` cannot be made into an object + --> $DIR/object-safety-issue-22040.rs:12:23 + | +LL | elements: Vec<Box<dyn Expr + 'x>>, + | ^^^^^^^^^^^^^ `Expr` 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/object-safety-issue-22040.rs:5:21 + | +LL | trait Expr: Debug + PartialEq { + | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr new file mode 100644 index 000000000..f91c9b985 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:22:30 + | +LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + | ^^^^^^^^ `Bar` 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/object-safety-mentions-Self.rs:11:22 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, x: &Self); + | ^^^^^ ...because method `bar` references the `Self` type in this parameter + = help: consider moving `bar` to another trait + +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:28:30 + | +LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz { + | ^^^^^^^^ `Baz` 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/object-safety-mentions-Self.rs:15:22 + | +LL | trait Baz { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> Self; + | ^^^^ ...because method `baz` references the `Self` type in its return type + = help: consider moving `baz` to another trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..f48628c9d --- /dev/null +++ b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:24:5 + | +LL | t + | ^ `Bar` 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/object-safety-mentions-Self.rs:11:22 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, x: &Self); + | ^^^^^ ...because method `bar` references the `Self` type in this parameter + = help: consider moving `bar` to another trait + = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:30:5 + | +LL | t + | ^ `Baz` 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/object-safety-mentions-Self.rs:15:22 + | +LL | trait Baz { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> Self; + | ^^^^ ...because method `baz` references the `Self` type in its return type + = help: consider moving `baz` to another trait + = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Baz>` for `&T` + = note: required by cast to type `&dyn Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.rs b/src/test/ui/object-safety/object-safety-mentions-Self.rs new file mode 100644 index 000000000..412d16ff3 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-mentions-Self.rs @@ -0,0 +1,42 @@ +// Check that we correctly prevent users from making trait objects +// form traits that make use of `Self` in an argument or return +// position, unless `where Self : Sized` is present.. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + + +trait Bar { + fn bar(&self, x: &Self); +} + +trait Baz { + fn baz(&self) -> Self; +} + +trait Quux { + fn quux(&self, s: &Self) -> Self where Self : Sized; +} + +fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn make_baz<T:Baz>(t: &T) -> &dyn Baz { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn make_quux<T:Quux>(t: &T) -> &dyn Quux { + t +} + +fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux { + t as &dyn Quux +} + +fn main() {} diff --git a/src/test/ui/object-safety/object-safety-no-static.curr.stderr b/src/test/ui/object-safety/object-safety-no-static.curr.stderr new file mode 100644 index 000000000..bd8cf4e30 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-no-static.curr.stderr @@ -0,0 +1,25 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-no-static.rs:12:18 + | +LL | fn diverges() -> Box<dyn Foo> { + | ^^^^^^^^^^^^ `Foo` 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/object-safety-no-static.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo() {} + | ^^^ ...because associated function `foo` has no `self` parameter +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) {} + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized {} + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..ea1c575ff --- /dev/null +++ b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-no-static.rs:22:27 + | +LL | let b: Box<dyn Foo> = Box::new(Bar); + | ^^^^^^^^^^^^^ `Foo` 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/object-safety-no-static.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo() {} + | ^^^ ...because associated function `foo` has no `self` parameter + = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<Bar>` + = note: required by cast to type `Box<dyn Foo>` +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) {} + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized {} + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-no-static.rs b/src/test/ui/object-safety/object-safety-no-static.rs new file mode 100644 index 000000000..03b622174 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-no-static.rs @@ -0,0 +1,24 @@ +// Check that we correctly prevent users from making trait objects +// from traits with static methods. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +trait Foo { + fn foo() {} +} + +fn diverges() -> Box<dyn Foo> { + //[curr]~^ ERROR E0038 + loop { } +} + +struct Bar; + +impl Foo for Bar {} + +fn main() { + let b: Box<dyn Foo> = Box::new(Bar); + //[object_safe_for_dispatch]~^ ERROR E0038 +} diff --git a/src/test/ui/object-safety/object-safety-phantom-fn.rs b/src/test/ui/object-safety/object-safety-phantom-fn.rs new file mode 100644 index 000000000..3ffeb81c1 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-phantom-fn.rs @@ -0,0 +1,22 @@ +// Check that `Self` appearing in a phantom fn does not make a trait not object safe. + +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] + +trait Baz { +} + +trait Bar<T> { +} + +fn make_bar<T:Bar<u32>>(t: &T) -> &dyn Bar<u32> { + t +} + +fn make_baz<T:Baz>(t: &T) -> &dyn Baz { + t +} + + +fn main() { +} diff --git a/src/test/ui/object-safety/object-safety-sized-2.curr.stderr b/src/test/ui/object-safety/object-safety-sized-2.curr.stderr new file mode 100644 index 000000000..71236c8e3 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-sized-2.curr.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized-2.rs:14:30 + | +LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + | ^^^^^^^^ `Bar` 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/object-safety-sized-2.rs:9:18 + | +LL | trait Bar + | --- this trait cannot be made into an object... +LL | where Self : Sized + | ^^^^^ ...because it requires `Self: Sized` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..b6e4903b0 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized-2.rs:16:5 + | +LL | t + | ^ `Bar` 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/object-safety-sized-2.rs:9:18 + | +LL | trait Bar + | --- this trait cannot be made into an object... +LL | where Self : Sized + | ^^^^^ ...because it requires `Self: Sized` + = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-sized-2.rs b/src/test/ui/object-safety/object-safety-sized-2.rs new file mode 100644 index 000000000..1e79b8cd9 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-sized-2.rs @@ -0,0 +1,21 @@ +// Check that we correctly prevent users from making trait objects +// from traits where `Self : Sized`. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +trait Bar + where Self : Sized +{ + fn bar<T>(&self, t: T); +} + +fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn main() { +} diff --git a/src/test/ui/object-safety/object-safety-sized.curr.stderr b/src/test/ui/object-safety/object-safety-sized.curr.stderr new file mode 100644 index 000000000..94b06ee93 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-sized.curr.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized.rs:12:30 + | +LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + | ^^^^^^^^ `Bar` 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/object-safety-sized.rs:8:13 + | +LL | trait Bar : Sized { + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..645852c7e --- /dev/null +++ b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized.rs:14:5 + | +LL | t + | ^ `Bar` 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/object-safety-sized.rs:8:13 + | +LL | trait Bar : Sized { + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-sized.rs b/src/test/ui/object-safety/object-safety-sized.rs new file mode 100644 index 000000000..b424b892d --- /dev/null +++ b/src/test/ui/object-safety/object-safety-sized.rs @@ -0,0 +1,19 @@ +// Check that we correctly prevent users from making trait objects +// from traits where `Self : Sized`. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +trait Bar : Sized { + fn bar<T>(&self, t: T); +} + +fn make_bar<T:Bar>(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn main() { +} diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.rs b/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.rs new file mode 100644 index 000000000..2445b33c8 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.rs @@ -0,0 +1,21 @@ +// Check that we correctly prevent users from making trait objects +// form traits that make use of `Self` in an argument or return position. + +trait Bar<T> { + fn bar(&self, x: &T); +} + +trait Baz : Bar<Self> { +} + +fn make_bar<T:Bar<u32>>(t: &T) -> &dyn Bar<u32> { + t +} + +fn make_baz<T:Baz>(t: &T) -> &dyn Baz { + //~^ ERROR E0038 + t +} + +fn main() { +} diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.stderr new file mode 100644 index 000000000..a106ab995 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-Self.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-supertrait-mentions-Self.rs:15:31 + | +LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz { + | ^^^^^^^ `Baz` 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/object-safety-supertrait-mentions-Self.rs:8:13 + | +LL | trait Baz : Bar<Self> { + | --- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. |