diff options
Diffstat (limited to 'tests/ui/traits')
595 files changed, 18631 insertions, 0 deletions
diff --git a/tests/ui/traits/alias/ambiguous.rs b/tests/ui/traits/alias/ambiguous.rs new file mode 100644 index 000000000..28409e0c6 --- /dev/null +++ b/tests/ui/traits/alias/ambiguous.rs @@ -0,0 +1,24 @@ +#![feature(trait_alias)] + +mod inner { + pub trait A { fn foo(&self); } + pub trait B { fn foo(&self); } + + impl A for u8 { + fn foo(&self) {} + } + impl B for u8 { + fn foo(&self) {} + } + + pub trait C = A + B; +} + +use inner::C; + +fn main() { + let t = 1u8; + t.foo(); //~ ERROR E0034 + + inner::A::foo(&t); // ok +} diff --git a/tests/ui/traits/alias/ambiguous.stderr b/tests/ui/traits/alias/ambiguous.stderr new file mode 100644 index 000000000..0fe1a7967 --- /dev/null +++ b/tests/ui/traits/alias/ambiguous.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/ambiguous.rs:21:7 + | +LL | t.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `u8` + --> $DIR/ambiguous.rs:8:9 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `u8` + --> $DIR/ambiguous.rs:11:9 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | A::foo(&t); + | ~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | B::foo(&t); + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/traits/alias/auxiliary/greeter.rs b/tests/ui/traits/alias/auxiliary/greeter.rs new file mode 100644 index 000000000..9e4122155 --- /dev/null +++ b/tests/ui/traits/alias/auxiliary/greeter.rs @@ -0,0 +1,13 @@ +#![feature(trait_alias)] + +pub trait Hello { + fn hello(&self); +} + +pub struct Hi; + +impl Hello for Hi { + fn hello(&self) {} +} + +pub trait Greet = Hello; diff --git a/tests/ui/traits/alias/auxiliary/send_sync.rs b/tests/ui/traits/alias/auxiliary/send_sync.rs new file mode 100644 index 000000000..9e56b87e0 --- /dev/null +++ b/tests/ui/traits/alias/auxiliary/send_sync.rs @@ -0,0 +1,3 @@ +#![feature(trait_alias)] + +pub trait SendSync = Send + Sync; diff --git a/tests/ui/traits/alias/basic.rs b/tests/ui/traits/alias/basic.rs new file mode 100644 index 000000000..d8168f299 --- /dev/null +++ b/tests/ui/traits/alias/basic.rs @@ -0,0 +1,8 @@ +// run-pass + +#![feature(trait_alias)] + +pub trait Foo {} +pub trait FooAlias = Foo; + +fn main() {} diff --git a/tests/ui/traits/alias/bounds.rs b/tests/ui/traits/alias/bounds.rs new file mode 100644 index 000000000..b97eb38c5 --- /dev/null +++ b/tests/ui/traits/alias/bounds.rs @@ -0,0 +1,57 @@ +// run-pass + +#![feature(trait_alias)] + +use std::marker::PhantomData; + +trait Empty {} +trait EmptyAlias = Empty; +trait CloneDefault = Clone + Default; +trait SendSyncAlias = Send + Sync; +trait WhereSendAlias = where Self: Send; +trait SendEqAlias<T> = Send where T: PartialEq<Self>; +trait I32Iterator = Iterator<Item = i32>; + +#[allow(dead_code)] +struct Foo<T: SendSyncAlias>(PhantomData<T>); +#[allow(dead_code)] +struct Bar<T>(PhantomData<T>) where T: SendSyncAlias; + +impl dyn EmptyAlias {} + +impl<T: SendSyncAlias> Empty for T {} + +fn a<T: CloneDefault>() -> (T, T) { + let one = T::default(); + let two = one.clone(); + (one, two) +} + +fn b(x: &impl SendEqAlias<i32>) -> bool { + 22_i32 == *x +} + +fn c<T: I32Iterator>(x: &mut T) -> Option<i32> { + x.next() +} + +fn d<T: SendSyncAlias>() { + is_send_and_sync::<T>(); +} + +fn is_send_and_sync<T: Send + Sync>() {} + +fn main() { + let both = a::<i32>(); + assert_eq!(both.0, 0); + assert_eq!(both.1, 0); + let both: (i32, i32) = a(); + assert_eq!(both.0, 0); + assert_eq!(both.1, 0); + + assert!(b(&22)); + + assert_eq!(c(&mut vec![22].into_iter()), Some(22)); + + d::<i32>(); +} diff --git a/tests/ui/traits/alias/cross-crate.rs b/tests/ui/traits/alias/cross-crate.rs new file mode 100644 index 000000000..8919c6434 --- /dev/null +++ b/tests/ui/traits/alias/cross-crate.rs @@ -0,0 +1,17 @@ +// aux-build:send_sync.rs + +#![feature(trait_alias)] + +extern crate send_sync; + +use std::rc::Rc; +use send_sync::SendSync; + +fn use_alias<T: SendSync>() {} + +fn main() { + use_alias::<u32>(); + use_alias::<Rc<u32>>(); + //~^ ERROR `Rc<u32>` cannot be sent between threads safely [E0277] + //~^^ ERROR `Rc<u32>` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr new file mode 100644 index 000000000..ae9d7d0a9 --- /dev/null +++ b/tests/ui/traits/alias/cross-crate.stderr @@ -0,0 +1,31 @@ +error[E0277]: `Rc<u32>` cannot be sent between threads safely + --> $DIR/cross-crate.rs:14:17 + | +LL | use_alias::<Rc<u32>>(); + | ^^^^^^^ `Rc<u32>` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `Rc<u32>` + = note: required for `Rc<u32>` to implement `SendSync` +note: required by a bound in `use_alias` + --> $DIR/cross-crate.rs:10:17 + | +LL | fn use_alias<T: SendSync>() {} + | ^^^^^^^^ required by this bound in `use_alias` + +error[E0277]: `Rc<u32>` cannot be shared between threads safely + --> $DIR/cross-crate.rs:14:17 + | +LL | use_alias::<Rc<u32>>(); + | ^^^^^^^ `Rc<u32>` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Rc<u32>` + = note: required for `Rc<u32>` to implement `SendSync` +note: required by a bound in `use_alias` + --> $DIR/cross-crate.rs:10:17 + | +LL | fn use_alias<T: SendSync>() {} + | ^^^^^^^^ required by this bound in `use_alias` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/generic-default-in-dyn.rs b/tests/ui/traits/alias/generic-default-in-dyn.rs new file mode 100644 index 000000000..d44e1c2a9 --- /dev/null +++ b/tests/ui/traits/alias/generic-default-in-dyn.rs @@ -0,0 +1,10 @@ +trait SendEqAlias<T> = PartialEq; +//~^ ERROR trait aliases are experimental + +struct Foo<T>(dyn SendEqAlias<T>); +//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393] + +struct Bar<T>(dyn SendEqAlias<T>, T); +//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393] + +fn main() {} diff --git a/tests/ui/traits/alias/generic-default-in-dyn.stderr b/tests/ui/traits/alias/generic-default-in-dyn.stderr new file mode 100644 index 000000000..0d3f794aa --- /dev/null +++ b/tests/ui/traits/alias/generic-default-in-dyn.stderr @@ -0,0 +1,35 @@ +error[E0658]: trait aliases are experimental + --> $DIR/generic-default-in-dyn.rs:1:1 + | +LL | trait SendEqAlias<T> = PartialEq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #41517 <https://github.com/rust-lang/rust/issues/41517> for more information + = help: add `#![feature(trait_alias)]` to the crate attributes to enable + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/generic-default-in-dyn.rs:4:19 + | +LL | struct Foo<T>(dyn SendEqAlias<T>); + | ^^^^^^^^^^^^^^ missing reference to `Rhs` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: type parameter `Rhs` must be specified for this + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/generic-default-in-dyn.rs:7:19 + | +LL | struct Bar<T>(dyn SendEqAlias<T>, T); + | ^^^^^^^^^^^^^^ missing reference to `Rhs` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: type parameter `Rhs` must be specified for this + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0393, E0658. +For more information about an error, try `rustc --explain E0393`. diff --git a/tests/ui/traits/alias/impl.rs b/tests/ui/traits/alias/impl.rs new file mode 100644 index 000000000..6e35793a0 --- /dev/null +++ b/tests/ui/traits/alias/impl.rs @@ -0,0 +1,7 @@ +#![feature(trait_alias)] + +trait DefaultAlias = Default; + +impl DefaultAlias for () {} //~ ERROR expected trait, found trait alias + +fn main() {} diff --git a/tests/ui/traits/alias/impl.stderr b/tests/ui/traits/alias/impl.stderr new file mode 100644 index 000000000..cedcd1021 --- /dev/null +++ b/tests/ui/traits/alias/impl.stderr @@ -0,0 +1,9 @@ +error[E0404]: expected trait, found trait alias `DefaultAlias` + --> $DIR/impl.rs:5:6 + | +LL | impl DefaultAlias for () {} + | ^^^^^^^^^^^^ not a trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/alias/import-cross-crate.rs b/tests/ui/traits/alias/import-cross-crate.rs new file mode 100644 index 000000000..868585cd0 --- /dev/null +++ b/tests/ui/traits/alias/import-cross-crate.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:greeter.rs + +#![feature(trait_alias)] + +extern crate greeter; + +// Import only the alias, not the real trait. +use greeter::{Greet, Hi}; + +fn main() { + let hi = Hi; + hi.hello(); // From `Hello`, via `Greet` alias. +} diff --git a/tests/ui/traits/alias/import.rs b/tests/ui/traits/alias/import.rs new file mode 100644 index 000000000..802a8f156 --- /dev/null +++ b/tests/ui/traits/alias/import.rs @@ -0,0 +1,40 @@ +// run-pass + +#![feature(trait_alias)] + +mod inner { + pub trait Foo { + fn foo(&self); + } + + pub struct Qux; + + impl Foo for Qux { + fn foo(&self) {} + } + + pub trait Bar = Foo; +} + +mod two { + pub trait A { + fn foo(); + } + + impl A for u8 { + fn foo() {} + } +} + +// Import only the alias, not the `Foo` trait. +use inner::{Bar, Qux}; + +// Declaring an alias also brings in aliased methods. +trait Two = two::A; + +fn main() { + let q = Qux; + q.foo(); // From Bar. + + u8::foo(); // From A. +} diff --git a/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs b/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs new file mode 100644 index 000000000..5e27ed3c6 --- /dev/null +++ b/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(trait_alias)] + +trait SomeTrait { + fn map(&self) {} +} + +impl<T> SomeTrait for Option<T> {} + +trait SomeAlias = SomeTrait; + +fn main() { + let x = Some(123); + // This should resolve to the trait impl for Option + Option::map(x, |z| z); + // This should resolve to the trait impl for SomeTrait + SomeTrait::map(&x); +} diff --git a/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs b/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs new file mode 100644 index 000000000..e49125d10 --- /dev/null +++ b/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(trait_alias)] + +trait Bounded { const MAX: Self; } + +impl Bounded for u32 { + // This should correctly resolve to the associated const in the inherent impl of u32. + const MAX: Self = u32::MAX; +} + +trait Num = Bounded + Copy; + +fn main() {} diff --git a/tests/ui/traits/alias/issue-75983.rs b/tests/ui/traits/alias/issue-75983.rs new file mode 100644 index 000000000..f9a7f36de --- /dev/null +++ b/tests/ui/traits/alias/issue-75983.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(trait_alias)] + +struct Bar; +trait Foo {} +impl Foo for Bar {} + +trait Baz = Foo where Bar: Foo; + +fn new() -> impl Baz { + Bar +} + +fn main() { + let _ = new(); +} diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs new file mode 100644 index 000000000..2462e703a --- /dev/null +++ b/tests/ui/traits/alias/issue-83613.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] +trait OpaqueTrait {} +impl<T> OpaqueTrait for T {} +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { + || 0 +} +trait AnotherTrait {} +impl<T: Send> AnotherTrait for T {} +impl AnotherTrait for OpaqueType {} +//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +fn main() {} diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr new file mode 100644 index 000000000..a78294da6 --- /dev/null +++ b/tests/ui/traits/alias/issue-83613.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` + --> $DIR/issue-83613.rs:10:1 + | +LL | impl<T: Send> AnotherTrait for T {} + | -------------------------------- first implementation here +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/alias/maybe-bound.rs b/tests/ui/traits/alias/maybe-bound.rs new file mode 100644 index 000000000..284baa481 --- /dev/null +++ b/tests/ui/traits/alias/maybe-bound.rs @@ -0,0 +1,29 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay. + +#![feature(trait_alias)] + +trait Foo {} + +trait S = ?Sized; + +// Nest a couple of levels deep: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1 + Foo; + +// In second position: +type _T1 = dyn Foo + _1; + +// ... and with an auto trait: +type _T2 = dyn Foo + Send + _1; + +// Twice: +trait _2 = _1 + _1; + +type _T3 = dyn _2 + Foo; + +fn main() {} diff --git a/tests/ui/traits/alias/no-duplicates.rs b/tests/ui/traits/alias/no-duplicates.rs new file mode 100644 index 000000000..88feb8917 --- /dev/null +++ b/tests/ui/traits/alias/no-duplicates.rs @@ -0,0 +1,126 @@ +// The purpose of this test is to demonstrate that duplicating object safe traits +// that are not auto traits is rejected with trait aliases even though one could +// reasonably accept this. + +#![feature(trait_alias)] + +use std::marker::Unpin; + +// Some arbitrary object-safe trait: +trait Obj {} + +// Nest a few levels deep: +trait _0 = Obj; +trait _1 = _0; + +type _T00 = dyn _0 + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T01 = dyn _1 + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T02 = dyn _1 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T03 = dyn Obj + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T04 = dyn _1 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more and in weird ways: + +trait _2 = _0 + _1; +trait _3 = Obj; +trait _4 = _3; + +type _T10 = dyn _2 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T11 = dyn _3 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T12 = dyn Obj + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T13 = dyn _2 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T14 = dyn _1 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T15 = dyn _3 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T16 = dyn _1 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T17 = dyn _4 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Include auto traits: + +trait _5 = Obj + Send; + +type _T20 = dyn _5 + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T21 = dyn Obj + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T22 = dyn _5 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T23 = dyn _5 + Send + Sync + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Also nest: + +trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + +type _T30 = dyn _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T31 = dyn _6 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T32 = dyn Send + _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more: + +trait _7 = _5 + Sync; +trait _8 = Unpin + _7; + +type _T40 = dyn _8 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T41 = dyn Obj + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T42 = dyn _8 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T43 = dyn _4 + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T44 = dyn _4 + Send + Sync + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Take higher ranked types into account. + +// Note that `'a` and `'b` are intentionally different to make sure we consider +// them semantically the same. +trait ObjL<'l> {} +trait _9 = for<'a> ObjL<'a>; +trait _10 = for<'b> ObjL<'b>; +type _T50 = dyn _9 + _10; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +trait ObjT<T> {} +trait _11 = ObjT<for<'a> fn(&'a u8)>; +trait _12 = ObjT<for<'b> fn(&'b u8)>; +type _T60 = dyn _11 + _12; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/tests/ui/traits/alias/no-duplicates.stderr b/tests/ui/traits/alias/no-duplicates.stderr new file mode 100644 index 000000000..bf244b97e --- /dev/null +++ b/tests/ui/traits/alias/no-duplicates.stderr @@ -0,0 +1,527 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:16:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T00 = dyn _0 + _0; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:19:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | type _T01 = dyn _1 + _0; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:22:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +... +LL | type _T02 = dyn _1 + _1; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:25:23 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | type _T03 = dyn Obj + _1; + | --- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:28:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | type _T04 = dyn _1 + Obj; + | -- ^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:37:17 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _2 = _0 + _1; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T10 = dyn _2 + _3; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:40:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- referenced here (additional use) +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T11 = dyn _3 + _2; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:43:23 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- referenced here (additional use) +... +LL | type _T12 = dyn Obj + _2; + | --- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:46:17 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _2 = _0 + _1; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T13 = dyn _2 + Obj; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:49:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _3 = Obj; + | --- additional non-auto trait +... +LL | type _T14 = dyn _1 + _3; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:52:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T15 = dyn _3 + _1; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:55:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- referenced here (additional use) +... +LL | type _T16 = dyn _1 + _4; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:58:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _3 = Obj; + | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) +... +LL | type _T17 = dyn _4 + _1; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:65:22 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | +LL | type _T20 = dyn _5 + _5; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:68:23 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | type _T21 = dyn Obj + _5; + | --- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:71:22 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T22 = dyn _5 + Obj; + | -- ^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:74:36 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T23 = dyn _5 + Send + Sync + Obj; + | -- ^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:81:17 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- referenced here (additional use) + | | + | referenced here (first use) +LL | +LL | type _T30 = dyn _6; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:84:17 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T31 = dyn _6 + Send; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:87:24 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T32 = dyn Send + _6; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:95:22 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (first use) +LL | trait _8 = Unpin + _7; + | -- referenced here (first use) +LL | +LL | type _T40 = dyn _8 + Obj; + | -- ^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:98:23 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _8 = Unpin + _7; + | -- referenced here (additional use) +... +LL | type _T41 = dyn Obj + _8; + | --- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:101:22 + | +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- referenced here (additional use) +... +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (first use) +LL | trait _8 = Unpin + _7; + | -- referenced here (first use) +... +LL | type _T42 = dyn _8 + _4; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:104:22 + | +LL | trait _3 = Obj; + | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) +... +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _8 = Unpin + _7; + | -- referenced here (additional use) +... +LL | type _T43 = dyn _4 + _8; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:107:36 + | +LL | trait _3 = Obj; + | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) +... +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _8 = Unpin + _7; + | -- referenced here (additional use) +... +LL | type _T44 = dyn _4 + Send + Sync + _8; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:117:22 + | +LL | trait _9 = for<'a> ObjL<'a>; + | ---------------- first non-auto trait +LL | trait _10 = for<'b> ObjL<'b>; + | ---------------- additional non-auto trait +LL | type _T50 = dyn _9 + _10; + | -- ^^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:123:23 + | +LL | trait _11 = ObjT<for<'a> fn(&'a u8)>; + | ------------------------ first non-auto trait +LL | trait _12 = ObjT<for<'b> fn(&'b u8)>; + | ------------------------ additional non-auto trait +LL | type _T60 = dyn _11 + _12; + | --- ^^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error: aborting due to 27 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/alias/no-extra-traits.rs b/tests/ui/traits/alias/no-extra-traits.rs new file mode 100644 index 000000000..4dad8c0f8 --- /dev/null +++ b/tests/ui/traits/alias/no-extra-traits.rs @@ -0,0 +1,121 @@ +// The purpose of this test is to demonstrate that trait alias expansion +// preserves the rule that `dyn Trait` may only reference one non-auto trait. + +#![feature(trait_alias)] + +use std::marker::Unpin; + +// Some arbitrary object-safe traits: +trait ObjA {} +trait ObjB {} + +// Nest a few levels deep: +trait _0 = ObjA; +trait _1 = _0; + +type _T00 = dyn _0 + ObjB; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T01 = dyn ObjB + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T02 = dyn ObjB + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T03 = dyn _1 + ObjB; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more and in weird ways: + +trait _2 = ObjB; +trait _3 = _2; +trait _4 = _3; + +type _T10 = dyn _2 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T11 = dyn _3 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T12 = dyn _2 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T13 = dyn _4 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Include auto traits: + +trait _5 = Sync + ObjB + Send; + +type _T20 = dyn _5 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T21 = dyn _1 + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T22 = dyn _5 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T23 = dyn ObjA + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T24 = dyn Send + _5 + _1 + Sync; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T25 = dyn _1 + Sync + _5 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T26 = dyn Sync + Send + _5 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T27 = dyn Send + Sync + ObjA + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Also nest: + +trait _6 = _1 + _5; +trait _7 = _6; +trait _8 = _7; + +type _T30 = dyn _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T31 = dyn _6 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T32 = dyn Send + _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T33 = dyn _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T34 = dyn _8 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T35 = dyn Send + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more: + +trait _9 = _5 + Sync; +trait _10 = Unpin + _9; + +type _T40 = dyn _10 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T41 = dyn ObjA + _10; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T42 = dyn _10 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T43 = dyn Send + _10 + Sync + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T44 = dyn ObjA + _10 + Send + Sync; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T45 = dyn Sync + Send + _10 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/tests/ui/traits/alias/no-extra-traits.stderr b/tests/ui/traits/alias/no-extra-traits.stderr new file mode 100644 index 000000000..4b1ddf684 --- /dev/null +++ b/tests/ui/traits/alias/no-extra-traits.stderr @@ -0,0 +1,579 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:16:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | type _T00 = dyn _0 + ObjB; + | -- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:19:24 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +... +LL | type _T01 = dyn ObjB + _0; + | ---- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:22:24 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | type _T02 = dyn ObjB + _1; + | ---- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:25:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | type _T03 = dyn _1 + ObjB; + | -- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:34:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (additional use) +... +LL | type _T10 = dyn _2 + _3; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:37:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (first use) +... +LL | type _T11 = dyn _3 + _2; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:40:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (additional use) +LL | trait _4 = _3; + | -- referenced here (additional use) +... +LL | type _T12 = dyn _2 + _4; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:43:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (first use) +LL | trait _4 = _3; + | -- referenced here (first use) +... +LL | type _T13 = dyn _4 + _2; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:50:22 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +LL | +LL | type _T20 = dyn _5 + _1; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:53:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T21 = dyn _1 + _5; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:56:22 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T22 = dyn _5 + ObjA; + | -- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:59:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T23 = dyn ObjA + _5; + | ---- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:62:29 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T24 = dyn Send + _5 + _1 + Sync; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:65:29 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T25 = dyn _1 + Sync + _5 + Send; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:68:36 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T26 = dyn Sync + Send + _5 + ObjA; + | -- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:71:38 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T27 = dyn Send + Sync + ObjA + _5; + | ---- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:80:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T30 = dyn _6; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:83:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T31 = dyn _6 + Send; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:86:24 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T32 = dyn Send + _6; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:89:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +... +LL | type _T33 = dyn _8; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:92:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +... +LL | type _T34 = dyn _8 + Send; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:95:24 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +... +LL | type _T35 = dyn Send + _8; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:103:23 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +LL | +LL | type _T40 = dyn _10 + ObjA; + | --- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:106:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _10 = Unpin + _9; + | -- referenced here (additional use) +... +LL | type _T41 = dyn ObjA + _10; + | ---- ^^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:109:23 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... +LL | type _T42 = dyn _10 + _1; + | --- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:112:37 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... +LL | type _T43 = dyn Send + _10 + Sync + ObjA; + | --- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:115:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _10 = Unpin + _9; + | -- referenced here (additional use) +... +LL | type _T44 = dyn ObjA + _10 + Send + Sync; + | ---- ^^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:118:37 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... +LL | type _T45 = dyn Sync + Send + _10 + _1; + | --- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error: aborting due to 28 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/alias/object-fail.rs b/tests/ui/traits/alias/object-fail.rs new file mode 100644 index 000000000..5c753ff20 --- /dev/null +++ b/tests/ui/traits/alias/object-fail.rs @@ -0,0 +1,11 @@ +#![feature(trait_alias)] + +trait EqAlias = Eq; +trait IteratorAlias = Iterator; + +fn main() { + let _: &dyn EqAlias = &123; + //~^ ERROR the trait `Eq` cannot be made into an object [E0038] + let _: &dyn IteratorAlias = &vec![123].into_iter(); + //~^ ERROR must be specified +} diff --git a/tests/ui/traits/alias/object-fail.stderr b/tests/ui/traits/alias/object-fail.stderr new file mode 100644 index 000000000..048a150df --- /dev/null +++ b/tests/ui/traits/alias/object-fail.stderr @@ -0,0 +1,21 @@ +error[E0038]: the trait `Eq` cannot be made into an object + --> $DIR/object-fail.rs:7:13 + | +LL | let _: &dyn EqAlias = &123; + | ^^^^^^^^^^^ `Eq` 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> + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter + +error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified + --> $DIR/object-fail.rs:9:17 + | +LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); + | ^^^^^^^^^^^^^ help: specify the associated type: `IteratorAlias<Item = Type>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0191. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/object-wf.rs b/tests/ui/traits/alias/object-wf.rs new file mode 100644 index 000000000..1440f02df --- /dev/null +++ b/tests/ui/traits/alias/object-wf.rs @@ -0,0 +1,85 @@ +// check-pass + +// This test checks that trait objects involving trait aliases are well-formed. + +#![feature(trait_alias)] + +trait Obj {} + +trait _0 = Send + Sync; + +// Just auto traits: + +trait _1 = _0 + Send + Sync; + +use std::marker::Unpin; + +fn _f0() { + let _: Box<dyn _0>; + let _: Box<dyn _1>; + let _: Box<dyn Unpin + _1 + Send + Sync>; +} + +// Include object safe traits: + +fn _f1() { + let _: Box<dyn Obj + _0>; + let _: Box<dyn Obj + _1>; + let _: Box<dyn Obj + _1 + _0>; +} + +// And when the object safe trait is in a trait alias: + +trait _2 = Obj; + +fn _f2() { + let _: Box<dyn _2 + _0>; + let _: Box<dyn _2 + _1>; + let _: Box<dyn _2 + _1 + _0>; +} + +// And it should also work when that trait is has auto traits to the right of it. + +trait _3 = Obj + Unpin; + +fn _f3() { + let _: Box<dyn _3 + _0>; + let _: Box<dyn _3 + _1>; + let _: Box<dyn _3 + _1 + _0>; +} + +// Nest the trait deeply: + +trait _4 = _3; +trait _5 = _4 + Sync + _0 + Send; +trait _6 = _5 + Send + _1 + Sync; + +fn _f4() { + let _: Box<dyn _6 + _0>; + let _: Box<dyn _6 + _1>; + let _: Box<dyn _6 + _1 + _0>; +} + +// Just nest the trait alone: + +trait _7 = _2; +trait _8 = _7; +trait _9 = _8; + +fn _f5() { + let _: Box<dyn _9>; +} + +// First bound is auto trait: + +trait _10 = Send + Obj; +trait _11 = Obj + Send; +trait _12 = Sync + _11; +trait _13 = Send + _12; + +fn f6() { + let _: Box<dyn _10>; + let _: Box<dyn _13>; +} + +fn main() {} diff --git a/tests/ui/traits/alias/object.rs b/tests/ui/traits/alias/object.rs new file mode 100644 index 000000000..12177cd82 --- /dev/null +++ b/tests/ui/traits/alias/object.rs @@ -0,0 +1,18 @@ +// run-pass + +#![feature(trait_alias)] + +trait Foo = PartialEq<i32> + Send; +trait Bar = Foo + Sync; + +trait I32Iterator = Iterator<Item = i32>; + +pub fn main() { + let a: &dyn Bar = &123; + assert!(*a == 123); + let b = Box::new(456) as Box<dyn Foo>; + assert!(*b == 456); + + let c: &mut dyn I32Iterator = &mut vec![123].into_iter(); + assert_eq!(c.next(), Some(123)); +} diff --git a/tests/ui/traits/alias/only-maybe-bound.rs b/tests/ui/traits/alias/only-maybe-bound.rs new file mode 100644 index 000000000..e4abf314e --- /dev/null +++ b/tests/ui/traits/alias/only-maybe-bound.rs @@ -0,0 +1,22 @@ +// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed, when just +// `?Sized` results from trait alias expansion. + +#![feature(trait_alias)] + +trait S = ?Sized; + +// Nest a couple of levels deep: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1; +//~^ ERROR at least one trait is required for an object type [E0224] + +// Twice: +trait _2 = _1 + _1; + +type _T1 = dyn _2; +//~^ ERROR at least one trait is required for an object type [E0224] + +fn main() {} diff --git a/tests/ui/traits/alias/only-maybe-bound.stderr b/tests/ui/traits/alias/only-maybe-bound.stderr new file mode 100644 index 000000000..175ec8120 --- /dev/null +++ b/tests/ui/traits/alias/only-maybe-bound.stderr @@ -0,0 +1,21 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/only-maybe-bound.rs:13:12 + | +LL | trait _1 = _0; + | -------- this alias does not contain a trait +... +LL | type _T0 = dyn _1; + | ^^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/only-maybe-bound.rs:19:12 + | +LL | trait _2 = _1 + _1; + | -------- this alias does not contain a trait +LL | +LL | type _T1 = dyn _2; + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/alias/self-in-const-generics.rs b/tests/ui/traits/alias/self-in-const-generics.rs new file mode 100644 index 000000000..b0de8ccd6 --- /dev/null +++ b/tests/ui/traits/alias/self-in-const-generics.rs @@ -0,0 +1,12 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![feature(trait_alias)] + +trait Bar<const N: usize> {} + +trait BB = Bar<{ 2 + 1 }>; + +fn foo(x: &dyn BB) {} +//~^ ERROR the trait alias `BB` cannot be made into an object [E0038] + +fn main() {} diff --git a/tests/ui/traits/alias/self-in-const-generics.stderr b/tests/ui/traits/alias/self-in-const-generics.stderr new file mode 100644 index 000000000..61cc217cf --- /dev/null +++ b/tests/ui/traits/alias/self-in-const-generics.stderr @@ -0,0 +1,11 @@ +error[E0038]: the trait alias `BB` cannot be made into an object + --> $DIR/self-in-const-generics.rs:9:16 + | +LL | fn foo(x: &dyn BB) {} + | ^^ + | + = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/self-in-generics.rs b/tests/ui/traits/alias/self-in-generics.rs new file mode 100644 index 000000000..0bb6335f9 --- /dev/null +++ b/tests/ui/traits/alias/self-in-generics.rs @@ -0,0 +1,15 @@ +// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects. +// This `FreshTy(0)` can leak into substs, causing ICEs in several places. +// Using `save-analysis` triggers type-checking `f` that would be normally skipped +// as `type_of` emitted an error. +// +// compile-flags: -Zsave-analysis + +#![feature(trait_alias)] + +pub trait SelfInput = Fn(&mut Self); + +pub fn f(_f: &dyn SelfInput) {} +//~^ ERROR the trait alias `SelfInput` cannot be made into an object [E0038] + +fn main() {} diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr new file mode 100644 index 000000000..110d60e6e --- /dev/null +++ b/tests/ui/traits/alias/self-in-generics.stderr @@ -0,0 +1,11 @@ +error[E0038]: the trait alias `SelfInput` cannot be made into an object + --> $DIR/self-in-generics.rs:12:19 + | +LL | pub fn f(_f: &dyn SelfInput) {} + | ^^^^^^^^^ + | + = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/style_lint.rs b/tests/ui/traits/alias/style_lint.rs new file mode 100644 index 000000000..33be20054 --- /dev/null +++ b/tests/ui/traits/alias/style_lint.rs @@ -0,0 +1,8 @@ +// check-pass + +#![feature(trait_alias)] + +trait Foo = std::fmt::Display + std::fmt::Debug; +trait bar = std::fmt::Display + std::fmt::Debug; //~WARN trait alias `bar` should have an upper camel case name + +fn main() {} diff --git a/tests/ui/traits/alias/style_lint.stderr b/tests/ui/traits/alias/style_lint.stderr new file mode 100644 index 000000000..91e2ea90e --- /dev/null +++ b/tests/ui/traits/alias/style_lint.stderr @@ -0,0 +1,10 @@ +warning: trait alias `bar` should have an upper camel case name + --> $DIR/style_lint.rs:6:7 + | +LL | trait bar = std::fmt::Display + std::fmt::Debug; + | ^^^ help: convert the identifier to upper camel case: `Bar` + | + = note: `#[warn(non_camel_case_types)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed new file mode 100644 index 000000000..8a94abaeb --- /dev/null +++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed @@ -0,0 +1,13 @@ +// Regression test of #43913. + +// run-rustfix + +#![feature(trait_alias)] +#![allow(bare_trait_objects, dead_code)] + +trait Strings = Iterator<Item=String>; + +struct Struct<S: Strings>(S); +//~^ ERROR: expected trait, found type alias `Strings` + +fn main() {} diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs new file mode 100644 index 000000000..40c678c28 --- /dev/null +++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs @@ -0,0 +1,13 @@ +// Regression test of #43913. + +// run-rustfix + +#![feature(trait_alias)] +#![allow(bare_trait_objects, dead_code)] + +type Strings = Iterator<Item=String>; + +struct Struct<S: Strings>(S); +//~^ ERROR: expected trait, found type alias `Strings` + +fn main() {} diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr new file mode 100644 index 000000000..6e03eeada --- /dev/null +++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr @@ -0,0 +1,14 @@ +error[E0404]: expected trait, found type alias `Strings` + --> $DIR/suggest-trait-alias-instead-of-type.rs:10:18 + | +LL | struct Struct<S: Strings>(S); + | ^^^^^^^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait Strings = Iterator<Item=String>; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/alias/syntax-fail.rs b/tests/ui/traits/alias/syntax-fail.rs new file mode 100644 index 000000000..039bbce8c --- /dev/null +++ b/tests/ui/traits/alias/syntax-fail.rs @@ -0,0 +1,10 @@ +#![feature(trait_alias)] + +trait Foo {} +auto trait A = Foo; //~ ERROR trait aliases cannot be `auto` +unsafe trait B = Foo; //~ ERROR trait aliases cannot be `unsafe` + +trait C: Ord = Eq; //~ ERROR bounds are not allowed on trait aliases +trait D: = Eq; //~ ERROR bounds are not allowed on trait aliases + +fn main() {} diff --git a/tests/ui/traits/alias/syntax-fail.stderr b/tests/ui/traits/alias/syntax-fail.stderr new file mode 100644 index 000000000..748b92056 --- /dev/null +++ b/tests/ui/traits/alias/syntax-fail.stderr @@ -0,0 +1,26 @@ +error: trait aliases cannot be `auto` + --> $DIR/syntax-fail.rs:4:1 + | +LL | auto trait A = Foo; + | ^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto` + +error: trait aliases cannot be `unsafe` + --> $DIR/syntax-fail.rs:5:1 + | +LL | unsafe trait B = Foo; + | ^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe` + +error: bounds are not allowed on trait aliases + --> $DIR/syntax-fail.rs:7:8 + | +LL | trait C: Ord = Eq; + | ^^^^^ + +error: bounds are not allowed on trait aliases + --> $DIR/syntax-fail.rs:8:8 + | +LL | trait D: = Eq; + | ^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/alias/syntax.rs b/tests/ui/traits/alias/syntax.rs new file mode 100644 index 000000000..17557a51a --- /dev/null +++ b/tests/ui/traits/alias/syntax.rs @@ -0,0 +1,24 @@ +// run-pass + +#![feature(trait_alias)] + +trait SimpleAlias = Default; +trait GenericAlias<T> = Iterator<Item = T>; +trait Partial<T> = IntoIterator<Item = T>; +trait SpecificAlias = GenericAlias<i32>; +trait PartialEqRef<'a, T: 'a> = PartialEq<&'a T>; +trait StaticAlias = 'static; + +trait Things<T> {} +trait Romeo {} +#[allow(dead_code)] +struct The<T>(T); +#[allow(dead_code)] +struct Fore<T>(T); +impl<T, U> Things<T> for The<U> {} +impl<T> Romeo for Fore<T> {} + +trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; +trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>; + +fn main() {} diff --git a/tests/ui/traits/alias/wf.rs b/tests/ui/traits/alias/wf.rs new file mode 100644 index 000000000..d10e2abb0 --- /dev/null +++ b/tests/ui/traits/alias/wf.rs @@ -0,0 +1,7 @@ +#![feature(trait_alias)] + +trait Foo {} +trait A<T: Foo> {} +trait B<T> = A<T>; //~ ERROR `T: Foo` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/alias/wf.stderr b/tests/ui/traits/alias/wf.stderr new file mode 100644 index 000000000..7172008d3 --- /dev/null +++ b/tests/ui/traits/alias/wf.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Foo` is not satisfied + --> $DIR/wf.rs:5:14 + | +LL | trait B<T> = A<T>; + | ^^^^ the trait `Foo` is not implemented for `T` + | +note: required by a bound in `A` + --> $DIR/wf.rs:4:12 + | +LL | trait A<T: Foo> {} + | ^^^ required by this bound in `A` +help: consider restricting type parameter `T` + | +LL | trait B<T: Foo> = A<T>; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alignment-gep-tup-like-1.rs b/tests/ui/traits/alignment-gep-tup-like-1.rs new file mode 100644 index 000000000..eb503dcf3 --- /dev/null +++ b/tests/ui/traits/alignment-gep-tup-like-1.rs @@ -0,0 +1,37 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +struct pair<A,B> { + a: A, b: B +} + +trait Invokable<A> { + fn f(&self) -> (A, u16); +} + +struct Invoker<A> { + a: A, + b: u16, +} + +impl<A:Clone> Invokable<A> for Invoker<A> { + fn f(&self) -> (A, u16) { + (self.a.clone(), self.b) + } +} + +fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> { + Box::new(Invoker { + a: a, + b: b, + }) as Box<dyn Invokable<A>+'static> +} + +pub fn main() { + let (a, b) = f(22_u64, 44u16).f(); + println!("a={} b={}", a, b); + assert_eq!(a, 22u64); + assert_eq!(b, 44u16); +} diff --git a/tests/ui/traits/anon-static-method.rs b/tests/ui/traits/anon-static-method.rs new file mode 100644 index 000000000..ede01afae --- /dev/null +++ b/tests/ui/traits/anon-static-method.rs @@ -0,0 +1,15 @@ +// run-pass +struct Foo { + x: isize +} + +impl Foo { + pub fn new() -> Foo { + Foo { x: 3 } + } +} + +pub fn main() { + let x = Foo::new(); + println!("{}", x.x); +} diff --git a/tests/ui/traits/anon_trait_static_method_exe.rs b/tests/ui/traits/anon_trait_static_method_exe.rs new file mode 100644 index 000000000..b49302954 --- /dev/null +++ b/tests/ui/traits/anon_trait_static_method_exe.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(non_camel_case_types)] + +// aux-build:anon_trait_static_method_lib.rs + +extern crate anon_trait_static_method_lib; +use anon_trait_static_method_lib::Foo; + +pub fn main() { + let x = Foo::new(); + println!("{}", x.x); +} diff --git a/tests/ui/traits/as-struct-constructor.rs b/tests/ui/traits/as-struct-constructor.rs new file mode 100644 index 000000000..13ebf9d8d --- /dev/null +++ b/tests/ui/traits/as-struct-constructor.rs @@ -0,0 +1,6 @@ +trait TraitNotAStruct {} + +fn main() { + TraitNotAStruct{ value: 0 }; + //~^ ERROR expected struct, variant or union type, found trait `TraitNotAStruct` +} diff --git a/tests/ui/traits/as-struct-constructor.stderr b/tests/ui/traits/as-struct-constructor.stderr new file mode 100644 index 000000000..d06e85f3a --- /dev/null +++ b/tests/ui/traits/as-struct-constructor.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found trait `TraitNotAStruct` + --> $DIR/as-struct-constructor.rs:4:5 + | +LL | TraitNotAStruct{ value: 0 }; + | ^^^^^^^^^^^^^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/traits/assignability-trait.rs b/tests/ui/traits/assignability-trait.rs new file mode 100644 index 000000000..a8547c1d2 --- /dev/null +++ b/tests/ui/traits/assignability-trait.rs @@ -0,0 +1,47 @@ +// run-pass +#![allow(non_camel_case_types)] + +// Tests that type assignability is used to search for instances when +// making method calls, but only if there aren't any matches without +// it. + +trait iterable<A> { + fn iterate<F>(&self, blk: F) -> bool where F: FnMut(&A) -> bool; +} + +impl<'a,A> iterable<A> for &'a [A] { + fn iterate<F>(&self, f: F) -> bool where F: FnMut(&A) -> bool { + self.iter().all(f) + } +} + +impl<A> iterable<A> for Vec<A> { + fn iterate<F>(&self, f: F) -> bool where F: FnMut(&A) -> bool { + self.iter().all(f) + } +} + +fn length<A, T: iterable<A>>(x: T) -> usize { + let mut len = 0; + x.iterate(|_y| { + len += 1; + true + }); + return len; +} + +pub fn main() { + let x: Vec<isize> = vec![0,1,2,3]; + // Call a method + x.iterate(|y| { assert_eq!(x[*y as usize], *y); true }); + // Call a parameterized function + assert_eq!(length(x.clone()), x.len()); + // Call a parameterized function, with type arguments that require + // a borrow + assert_eq!(length::<isize, &[isize]>(&*x), x.len()); + + // Now try it with a type that *needs* to be borrowed + let z = [0,1,2,3]; + // Call a parameterized function + assert_eq!(length::<isize, &[isize]>(&z), z.len()); +} diff --git a/tests/ui/traits/assoc-type-in-superbad.rs b/tests/ui/traits/assoc-type-in-superbad.rs new file mode 100644 index 000000000..65340b2a2 --- /dev/null +++ b/tests/ui/traits/assoc-type-in-superbad.rs @@ -0,0 +1,16 @@ +// Test case where an associated type is referenced from within the +// supertrait definition, and the impl makes the wrong +// associations. Issue #20220. + +use std::vec::IntoIter; + +pub trait Foo: Iterator<Item = <Self as Foo>::Key> { + type Key; +} + +impl Foo for IntoIter<i32> { + type Key = u32; + //~^ ERROR expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32` +} + +fn main() {} diff --git a/tests/ui/traits/assoc-type-in-superbad.stderr b/tests/ui/traits/assoc-type-in-superbad.stderr new file mode 100644 index 000000000..7fa1d2c2e --- /dev/null +++ b/tests/ui/traits/assoc-type-in-superbad.stderr @@ -0,0 +1,15 @@ +error[E0271]: expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32` + --> $DIR/assoc-type-in-superbad.rs:12:16 + | +LL | type Key = u32; + | ^^^ expected `u32`, found `i32` + | +note: required by a bound in `Foo` + --> $DIR/assoc-type-in-superbad.rs:7:25 + | +LL | pub trait Foo: Iterator<Item = <Self as Foo>::Key> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/assoc-type-in-supertrait.rs b/tests/ui/traits/assoc-type-in-supertrait.rs new file mode 100644 index 000000000..7d6a754cc --- /dev/null +++ b/tests/ui/traits/assoc-type-in-supertrait.rs @@ -0,0 +1,23 @@ +// run-pass +// Test case where an associated type is referenced from within the +// supertrait definition. Issue #20220. + + +use std::vec::IntoIter; + +pub trait Foo: Iterator<Item=<Self as Foo>::Key> { + type Key; +} + +impl Foo for IntoIter<i32> { + type Key = i32; +} + +fn sum_foo<F:Foo<Key=i32>>(f: F) -> i32 { + f.fold(0, |a,b| a + b) +} + +fn main() { + let x = sum_foo(vec![11, 10, 1].into_iter()); + assert_eq!(x, 22); +} diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs new file mode 100644 index 000000000..471a6b836 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs @@ -0,0 +1,23 @@ +trait Bar { + type Baz; +} + +struct Foo<T> where T: Bar, <T as Bar>::Baz: String { //~ ERROR expected trait, found struct + t: T, +} + +struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found struct + t: &'a T, +} + +fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { //~ ERROR expected trait, found struct +} + +fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found +} + +fn issue_95327() where <u8 as Unresolved>::Assoc: String {} +//~^ ERROR expected trait, found struct +//~| ERROR use of undeclared type `Unresolved` + +fn main() {} diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr new file mode 100644 index 000000000..5be334986 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr @@ -0,0 +1,91 @@ +error[E0433]: failed to resolve: use of undeclared type `Unresolved` + --> $DIR/assoc_type_bound_with_struct.rs:19:31 + | +LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {} + | ^^^^^^^^^^ use of undeclared type `Unresolved` + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:5:46 + | +LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String { + | ^^^^^^ not a trait + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + | +help: constrain the associated type to `String` + | +LL | struct Foo<T> where T: Bar, T: Bar<Baz = String> { + | ~~~~~~~~~~~~~~~~~~~~ +help: a trait with a similar name exists + | +LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: ToString { + | ~~~~~~~~ + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:9:54 + | +LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { + | ^^^^^^ not a trait + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + | +help: constrain the associated type to `String` + | +LL | struct Qux<'a, T> where T: Bar, &'a T: Bar<Baz = String> { + | ~~~~~~~~~~~~~~~~~~~~~~~~ +help: a trait with a similar name exists + | +LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: ToString { + | ~~~~~~~~ + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:13:45 + | +LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { + | ^^^^^^ not a trait + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + | +help: constrain the associated type to `String` + | +LL | fn foo<T: Bar>(_: T) where T: Bar<Baz = String> { + | ~~~~~~~~~~~~~~~~~~~~ +help: a trait with a similar name exists + | +LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: ToString { + | ~~~~~~~~ + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:16:57 + | +LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { + | ^^^^^^ not a trait + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + | +help: constrain the associated type to `String` + | +LL | fn qux<'a, T: Bar>(_: &'a T) where &'a T: Bar<Baz = String> { + | ~~~~~~~~~~~~~~~~~~~~~~~~ +help: a trait with a similar name exists + | +LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString { + | ~~~~~~~~ + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:19:51 + | +LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {} + | ^^^^^^ help: a trait with a similar name exists: `ToString` + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0404, E0433. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs new file mode 100644 index 000000000..b1f124c7e --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs @@ -0,0 +1,14 @@ +// Check that we validate associated type bounds for trait objects + +trait X { + type Y: Clone; +} + +fn f<T: X + ?Sized>() { + None::<T::Y>.clone(); +} + +fn main() { + f::<dyn X<Y = str>>(); + //~^ ERROR the trait bound `str: Clone` is not satisfied +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr new file mode 100644 index 000000000..fa7a8a2a0 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/check-trait-object-bounds-1.rs:12:9 + | +LL | f::<dyn X<Y = str>>(); + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `f` + --> $DIR/check-trait-object-bounds-1.rs:7:9 + | +LL | fn f<T: X + ?Sized>() { + | ^ required by this bound in `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs new file mode 100644 index 000000000..1422dda27 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs @@ -0,0 +1,15 @@ +// Make sure that we're handling bound lifetimes correctly when validating trait +// bounds. +// run-pass + +trait X<'a> { + type F: FnOnce(&i32) -> &'a i32; +} + +fn f<T: for<'r> X<'r> + ?Sized>() { + None::<T::F>.map(|f| f(&0)); +} + +fn main() { + f::<dyn for<'x> X<'x, F = fn(&i32) -> &'x i32>>(); +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs new file mode 100644 index 000000000..eb2fb6e84 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs @@ -0,0 +1,15 @@ +// Check that we validate associated type bounds for trait objects when they +// have bound lifetimes + +trait X<'a> { + type F: FnOnce(&i32) -> &'a i32; +} + +fn f<T: for<'r> X<'r> + ?Sized>() { + None::<T::F>.map(|f| f(&0)); +} + +fn main() { + f::<dyn for<'x> X<'x, F = i32>>(); + //~^ expected a `FnOnce<(&i32,)>` closure, found `i32` +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr new file mode 100644 index 000000000..10e82c54e --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr @@ -0,0 +1,16 @@ +error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32` + --> $DIR/check-trait-object-bounds-2.rs:13:9 + | +LL | f::<dyn for<'x> X<'x, F = i32>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32` + | + = help: the trait `for<'a> FnOnce<(&'a i32,)>` is not implemented for `i32` +note: required by a bound in `f` + --> $DIR/check-trait-object-bounds-2.rs:8:9 + | +LL | fn f<T: for<'r> X<'r> + ?Sized>() { + | ^^^^^^^^^^^^^ required by this bound in `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs new file mode 100644 index 000000000..ba04fd93a --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs @@ -0,0 +1,20 @@ +// Check that we validate associated type bounds for trait objects + +trait X<'a> { + type Y: Into<&'static str> + From<&'a str>; +} + +fn f<'a, T: X<'a> + ?Sized>(s: &'a str) -> &'static str { + T::Y::from(s).into() +} + +pub fn main() { + let z; + { + let s = String::from("abcdef"); + z = f::<dyn X<Y = &str>>(&s); + //~^ ERROR `s` does not live long enough + } + + println!("{}", z) +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr new file mode 100644 index 000000000..ade552c4b --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr @@ -0,0 +1,15 @@ +error[E0597]: `s` does not live long enough + --> $DIR/check-trait-object-bounds-3.rs:15:34 + | +LL | z = f::<dyn X<Y = &str>>(&s); + | ---------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `s` is borrowed for `'static` +LL | +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs new file mode 100644 index 000000000..e9ca1563f --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs @@ -0,0 +1,17 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Super { + type Y: Clone; +} + +trait X: Super {} + +fn f<T: X + ?Sized>() { + None::<T::Y>.clone(); +} + +fn main() { + f::<dyn X<Y = str>>(); + //~^ ERROR the trait bound `str: Clone` is not satisfied +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr new file mode 100644 index 000000000..4891ee9c2 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/check-trait-object-bounds-4.rs:15:9 + | +LL | f::<dyn X<Y = str>>(); + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `f` + --> $DIR/check-trait-object-bounds-4.rs:10:9 + | +LL | fn f<T: X + ?Sized>() { + | ^ required by this bound in `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs new file mode 100644 index 000000000..7d733ad26 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs @@ -0,0 +1,27 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Is { + type T; +} + +impl<U> Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is<T = Self::V>; +} + +fn is_obj<T: ?Sized + Obj>(_: &T) {} + +fn f(x: &dyn Obj<U = i32, V = i64>) { + is_obj(x) + //~^ type mismatch resolving `<i32 as Is>::T == i64` +} + +fn main() {} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr new file mode 100644 index 000000000..00fdb3753 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `<i32 as Is>::T == i64` + --> $DIR/check-trait-object-bounds-5.rs:23:12 + | +LL | is_obj(x) + | ------ ^ type mismatch resolving `<i32 as Is>::T == i64` + | | + | required by a bound introduced by this call + | +note: expected this to be `i64` + --> $DIR/check-trait-object-bounds-5.rs:9:14 + | +LL | type T = U; + | ^ +note: required by a bound in `is_obj` + --> $DIR/check-trait-object-bounds-5.rs:20:23 + | +LL | fn is_obj<T: ?Sized + Obj>(_: &T) {} + | ^^^ required by this bound in `is_obj` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs new file mode 100644 index 000000000..cb196d67f --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs @@ -0,0 +1,24 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Is { + type T; +} + +impl<U> Is for U { + type T = U; +} + +trait Obj { + type U: Is<T = Self::V>; + type V; +} + +fn is_obj<T: ?Sized + Obj>(_: &T) {} + +fn f(x: &dyn Obj<U = i32, V = i64>) { + is_obj(x) + //~^ ERROR type mismatch resolving `<i32 as Is>::T == i64` +} + +fn main() {} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr new file mode 100644 index 000000000..9b0975e5e --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `<i32 as Is>::T == i64` + --> $DIR/check-trait-object-bounds-6.rs:20:12 + | +LL | is_obj(x) + | ------ ^ type mismatch resolving `<i32 as Is>::T == i64` + | | + | required by a bound introduced by this call + | +note: expected this to be `i64` + --> $DIR/check-trait-object-bounds-6.rs:9:14 + | +LL | type T = U; + | ^ +note: required by a bound in `is_obj` + --> $DIR/check-trait-object-bounds-6.rs:17:23 + | +LL | fn is_obj<T: ?Sized + Obj>(_: &T) {} + | ^^^ required by this bound in `is_obj` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/associated_type_bound/issue-51446.rs b/tests/ui/traits/associated_type_bound/issue-51446.rs new file mode 100644 index 000000000..7dd95de73 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/issue-51446.rs @@ -0,0 +1,34 @@ +// Regression test for #51446. +// check-pass + +trait Foo { + type Item; + fn get(&self) -> Self::Item; +} + +fn blah<T, F>(x: T, f: F) -> B<T::Item, impl Fn(T::Item)> +where + T: Foo, + F: Fn(T::Item), +{ + B { x: x.get(), f } +} + +pub struct B<T, F> +where + F: Fn(T), +{ + pub x: T, + pub f: F, +} + +impl Foo for i32 { + type Item = i32; + fn get(&self) -> i32 { + *self + } +} + +fn main() { + let _ = blah(0, |_| ()); +} diff --git a/tests/ui/traits/astconv-cycle-between-and-type.rs b/tests/ui/traits/astconv-cycle-between-and-type.rs new file mode 100644 index 000000000..cc8f9dc51 --- /dev/null +++ b/tests/ui/traits/astconv-cycle-between-and-type.rs @@ -0,0 +1,29 @@ +// run-pass +// Test that we are able to successfully compile a setup where a trait +// (`Trait1`) references a struct (`SomeType<u32>`) which in turn +// carries a predicate that references the trait (`u32 : Trait1`, +// substituted). + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Trait1 : Trait2<SomeType<u32>> { + fn dumb(&self) { } +} + +trait Trait2<A> { + fn dumber(&self, _: A) { } +} + +struct SomeType<A> + where A : Trait1 +{ + a: A +} + +impl Trait1 for u32 { } + +impl Trait2<SomeType<u32>> for u32 { } + +fn main() { } diff --git a/tests/ui/traits/augmented-assignments-trait.rs b/tests/ui/traits/augmented-assignments-trait.rs new file mode 100644 index 000000000..747a5393f --- /dev/null +++ b/tests/ui/traits/augmented-assignments-trait.rs @@ -0,0 +1,12 @@ +// run-pass +use std::ops::AddAssign; + +struct Int(#[allow(unused_tuple_struct_fields)] i32); + +impl AddAssign for Int { + fn add_assign(&mut self, _: Int) { + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs b/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs new file mode 100644 index 000000000..dceec7e3e --- /dev/null +++ b/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs @@ -0,0 +1,9 @@ +pub struct Foo { + pub x: isize +} + +impl Foo { + pub fn new() -> Foo { + Foo { x: 3 } + } +} diff --git a/tests/ui/traits/auxiliary/go_trait.rs b/tests/ui/traits/auxiliary/go_trait.rs new file mode 100644 index 000000000..aa0ec2289 --- /dev/null +++ b/tests/ui/traits/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go<G:Go>(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once<G:GoOnce>(this: G, arg: isize) { + this.go_once(arg) +} + +impl<G> GoMut for G + where G : Go +{ + default fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +impl<G> GoOnce for G + where G : GoMut +{ + default fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs b/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs new file mode 100644 index 000000000..769e89731 --- /dev/null +++ b/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs @@ -0,0 +1,60 @@ +// This is the auxiliary crate for the regression test for issue #89119, minimized +// from `zvariant-2.8.0`. + +use std::convert::TryFrom; +use std::borrow::Cow; + +pub struct Str<'a>(Cow<'a, str>); +impl<'a> Str<'a> { + pub fn to_owned(&self) -> Str<'static> { + todo!() + } +} + +pub enum Value<'a> { + Str(Str<'a>), + Value(Box<Value<'a>>), +} +impl<'a> Value<'a> { + pub fn to_owned(&self) -> Value<'static> { + match self { + Value::Str(v) => Value::Str(v.to_owned()), + Value::Value(v) => { + let o = OwnedValue::from(&**v); + Value::Value(Box::new(o.into_inner())) + } + } + } +} + +struct OwnedValue(Value<'static>); +impl OwnedValue { + pub(crate) fn into_inner(self) -> Value<'static> { + todo!() + } +} +impl<'a, T> TryFrom<OwnedValue> for Vec<T> +where + T: TryFrom<Value<'a>, Error = ()>, +{ + type Error = (); + fn try_from(_: OwnedValue) -> Result<Self, Self::Error> { + todo!() + } +} +impl TryFrom<OwnedValue> for Vec<OwnedValue> { + type Error = (); + fn try_from(_: OwnedValue) -> Result<Self, Self::Error> { + todo!() + } +} +impl<'a> From<Value<'a>> for OwnedValue { + fn from(_: Value<'a>) -> Self { + todo!() + } +} +impl<'a> From<&Value<'a>> for OwnedValue { + fn from(_: &Value<'a>) -> Self { + todo!() + } +} diff --git a/tests/ui/traits/auxiliary/trait_safety_lib.rs b/tests/ui/traits/auxiliary/trait_safety_lib.rs new file mode 100644 index 000000000..6fc432ed4 --- /dev/null +++ b/tests/ui/traits/auxiliary/trait_safety_lib.rs @@ -0,0 +1,9 @@ +// Simple smoke test that unsafe traits can be compiled etc. + +pub unsafe trait Foo { + fn foo(&self) -> isize; +} + +unsafe impl Foo for isize { + fn foo(&self) -> isize { *self } +} diff --git a/tests/ui/traits/auxiliary/traitimpl.rs b/tests/ui/traits/auxiliary/traitimpl.rs new file mode 100644 index 000000000..fda5314cd --- /dev/null +++ b/tests/ui/traits/auxiliary/traitimpl.rs @@ -0,0 +1,7 @@ +// Test inherent trait impls work cross-crait. + +pub trait Bar<'a> : 'a {} + +impl<'a> Bar<'a> { + pub fn bar(&self) {} +} diff --git a/tests/ui/traits/bad-method-typaram-kind.rs b/tests/ui/traits/bad-method-typaram-kind.rs new file mode 100644 index 000000000..b088eae1c --- /dev/null +++ b/tests/ui/traits/bad-method-typaram-kind.rs @@ -0,0 +1,14 @@ +fn foo<T:'static>() { + 1.bar::<T>(); //~ ERROR `T` cannot be sent between threads safely +} + +trait Bar { + fn bar<T:Send>(&self); +} + +impl Bar for usize { + fn bar<T:Send>(&self) { + } +} + +fn main() {} diff --git a/tests/ui/traits/bad-method-typaram-kind.stderr b/tests/ui/traits/bad-method-typaram-kind.stderr new file mode 100644 index 000000000..56acfbe80 --- /dev/null +++ b/tests/ui/traits/bad-method-typaram-kind.stderr @@ -0,0 +1,19 @@ +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/bad-method-typaram-kind.rs:2:13 + | +LL | 1.bar::<T>(); + | ^ `T` cannot be sent between threads safely + | +note: required by a bound in `Bar::bar` + --> $DIR/bad-method-typaram-kind.rs:6:14 + | +LL | fn bar<T:Send>(&self); + | ^^^^ required by this bound in `Bar::bar` +help: consider further restricting this bound + | +LL | fn foo<T:'static + std::marker::Send>() { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bad-sized.rs b/tests/ui/traits/bad-sized.rs new file mode 100644 index 000000000..a15219679 --- /dev/null +++ b/tests/ui/traits/bad-sized.rs @@ -0,0 +1,9 @@ +trait Trait {} + +pub fn main() { + let x: Vec<dyn Trait + Sized> = Vec::new(); + //~^ ERROR only auto traits can be used as additional traits in a trait object + //~| ERROR the size for values of type + //~| ERROR the size for values of type + //~| ERROR the size for values of type +} diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr new file mode 100644 index 000000000..fb9900bc5 --- /dev/null +++ b/tests/ui/traits/bad-sized.stderr @@ -0,0 +1,45 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/bad-sized.rs:4:28 + | +LL | let x: Vec<dyn Trait + Sized> = Vec::new(); + | ----- ^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Trait + Sized {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/bad-sized.rs:4:12 + | +LL | let x: Vec<dyn Trait + Sized> = Vec::new(); + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/bad-sized.rs:4:37 + | +LL | let x: Vec<dyn Trait + Sized> = Vec::new(); + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` +note: required by a bound in `Vec::<T>::new` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/bad-sized.rs:4:37 + | +LL | let x: Vec<dyn Trait + Sized> = Vec::new(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0225, E0277. +For more information about an error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs new file mode 100644 index 000000000..f9a934764 --- /dev/null +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs @@ -0,0 +1,11 @@ +fn strip_lf(s: &str) -> &str { + s.strip_suffix(b'\n').unwrap_or(s) + //~^ ERROR expected a `FnMut<(char,)>` closure, found `u8` + //~| NOTE expected an `FnMut<(char,)>` closure, found `u8` + //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8` + //~| HELP the following other types implement trait `Pattern<'a>`: + //~| NOTE required for `u8` to implement `Pattern<'_>` + +} + +fn main() {} diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr new file mode 100644 index 000000000..ce9ab2d81 --- /dev/null +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `FnMut<(char,)>` closure, found `u8` + --> $DIR/assoc-fn-bound-root-obligation.rs:2:7 + | +LL | s.strip_suffix(b'\n').unwrap_or(s) + | ^^^^^^^^^^^^ expected an `FnMut<(char,)>` closure, found `u8` + | + = help: the trait `FnMut<(char,)>` is not implemented for `u8` + = help: the following other types implement trait `Pattern<'a>`: + &'b String + &'b [char; N] + &'b [char] + &'b str + &'c &'b str + [char; N] + char + = note: required for `u8` to implement `Pattern<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/auxiliary/crate_a1.rs b/tests/ui/traits/bound/auxiliary/crate_a1.rs new file mode 100644 index 000000000..6aa010258 --- /dev/null +++ b/tests/ui/traits/bound/auxiliary/crate_a1.rs @@ -0,0 +1,9 @@ +pub trait Bar {} + +pub fn try_foo(x: impl Bar) {} + +pub struct ImplementsTraitForUsize<T> { + _marker: std::marker::PhantomData<T>, +} + +impl Bar for ImplementsTraitForUsize<usize> {} diff --git a/tests/ui/traits/bound/auxiliary/crate_a2.rs b/tests/ui/traits/bound/auxiliary/crate_a2.rs new file mode 100644 index 000000000..d6057db5e --- /dev/null +++ b/tests/ui/traits/bound/auxiliary/crate_a2.rs @@ -0,0 +1,13 @@ +pub struct Foo; + +pub trait Bar {} + +impl Bar for Foo {} + +pub struct DoesNotImplementTrait; + +pub struct ImplementsWrongTraitConditionally<T> { + _marker: std::marker::PhantomData<T>, +} + +impl Bar for ImplementsWrongTraitConditionally<isize> {} diff --git a/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs b/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs new file mode 100644 index 000000000..7e9592eee --- /dev/null +++ b/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs @@ -0,0 +1,13 @@ +pub trait Trait { + fn dummy(&self) { } +} + +pub struct Foo<T:Trait> { + pub x: T, +} + +pub enum Bar<T:Trait> { + ABar(isize), + BBar(T), + CBar(usize), +} diff --git a/tests/ui/traits/bound/basic.rs b/tests/ui/traits/bound/basic.rs new file mode 100644 index 000000000..8c8a7eb7d --- /dev/null +++ b/tests/ui/traits/bound/basic.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +#![allow(unconditional_recursion)] + +// pretty-expanded FIXME #23616 + +trait Foo { +} + +fn b(_x: Box<dyn Foo+Send>) { +} + +fn c(x: Box<dyn Foo+Sync+Send>) { + e(x); +} + +fn d(x: Box<dyn Foo+Send>) { + e(x); +} + +fn e(x: Box<dyn Foo>) { + e(x); +} + +pub fn main() { } diff --git a/tests/ui/traits/bound/generic_trait.rs b/tests/ui/traits/bound/generic_trait.rs new file mode 100644 index 000000000..18382bb59 --- /dev/null +++ b/tests/ui/traits/bound/generic_trait.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +trait connection { + fn read(&self) -> isize; +} + +trait connection_factory<C:connection> { + fn create(&self) -> C; +} + +type my_connection = (); +type my_connection_factory = (); + +impl connection for () { + fn read(&self) -> isize { 43 } +} + +impl connection_factory<my_connection> for my_connection_factory { + fn create(&self) -> my_connection { () } +} + +pub fn main() { + let factory = (); + let connection = factory.create(); + let result = connection.read(); + assert_eq!(result, 43); +} diff --git a/tests/ui/traits/bound/impl-comparison-duplicates.rs b/tests/ui/traits/bound/impl-comparison-duplicates.rs new file mode 100644 index 000000000..de6c2afa2 --- /dev/null +++ b/tests/ui/traits/bound/impl-comparison-duplicates.rs @@ -0,0 +1,16 @@ +// run-pass +// Tests that type parameter bounds on an implementation need not match the +// trait exactly, as long as the implementation doesn't demand *more* bounds +// than the trait. + +// pretty-expanded FIXME #23616 + +trait A { + fn foo<T: Eq + Ord>(&self); +} + +impl A for isize { + fn foo<T: Ord>(&self) {} // Ord implies Eq, so this is ok. +} + +fn main() {} diff --git a/tests/ui/traits/bound/in-arc.rs b/tests/ui/traits/bound/in-arc.rs new file mode 100644 index 000000000..a1492c0b9 --- /dev/null +++ b/tests/ui/traits/bound/in-arc.rs @@ -0,0 +1,108 @@ +// run-pass +#![allow(unused_must_use)] +// Tests that a heterogeneous list of existential `dyn` types can be put inside an Arc +// and shared between threads as long as all types fulfill Send. + +// ignore-emscripten no threads support + +use std::sync::Arc; +use std::sync::mpsc::channel; +use std::thread; + +trait Pet { + fn name(&self, blk: Box<dyn FnMut(&str)>); + fn num_legs(&self) -> usize; + fn of_good_pedigree(&self) -> bool; +} + +struct Catte { + num_whiskers: usize, + name: String, +} + +struct Dogge { + bark_decibels: usize, + tricks_known: usize, + name: String, +} + +struct Goldfyshe { + swim_speed: usize, + name: String, +} + +impl Pet for Catte { + fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) } + fn num_legs(&self) -> usize { 4 } + fn of_good_pedigree(&self) -> bool { self.num_whiskers >= 4 } +} +impl Pet for Dogge { + fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) } + fn num_legs(&self) -> usize { 4 } + fn of_good_pedigree(&self) -> bool { + self.bark_decibels < 70 || self.tricks_known > 20 + } +} +impl Pet for Goldfyshe { + fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) } + fn num_legs(&self) -> usize { 0 } + fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 } +} + +pub fn main() { + let catte = Catte { num_whiskers: 7, name: "alonzo_church".to_string() }; + let dogge1 = Dogge { + bark_decibels: 100, + tricks_known: 42, + name: "alan_turing".to_string(), + }; + let dogge2 = Dogge { + bark_decibels: 55, + tricks_known: 11, + name: "albert_einstein".to_string(), + }; + let fishe = Goldfyshe { + swim_speed: 998, + name: "alec_guinness".to_string(), + }; + let arc = Arc::new(vec![ + Box::new(catte) as Box<dyn Pet+Sync+Send>, + Box::new(dogge1) as Box<dyn Pet+Sync+Send>, + Box::new(fishe) as Box<dyn Pet+Sync+Send>, + Box::new(dogge2) as Box<dyn Pet+Sync+Send>]); + let (tx1, rx1) = channel(); + let arc1 = arc.clone(); + let t1 = thread::spawn(move|| { check_legs(arc1); tx1.send(()); }); + let (tx2, rx2) = channel(); + let arc2 = arc.clone(); + let t2 = thread::spawn(move|| { check_names(arc2); tx2.send(()); }); + let (tx3, rx3) = channel(); + let arc3 = arc.clone(); + let t3 = thread::spawn(move|| { check_pedigree(arc3); tx3.send(()); }); + rx1.recv(); + rx2.recv(); + rx3.recv(); + t1.join(); + t2.join(); + t3.join(); +} + +fn check_legs(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) { + let mut legs = 0; + for pet in arc.iter() { + legs += pet.num_legs(); + } + assert!(legs == 12); +} +fn check_names(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) { + for pet in arc.iter() { + pet.name(Box::new(|name| { + assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8); + })) + } +} +fn check_pedigree(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) { + for pet in arc.iter() { + assert!(pet.of_good_pedigree()); + } +} diff --git a/tests/ui/traits/bound/multiple.rs b/tests/ui/traits/bound/multiple.rs new file mode 100644 index 000000000..868b33407 --- /dev/null +++ b/tests/ui/traits/bound/multiple.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn f<T:PartialEq + PartialOrd>(_: T) { +} + +pub fn main() { + f(3); +} diff --git a/tests/ui/traits/bound/not-on-bare-trait.rs b/tests/ui/traits/bound/not-on-bare-trait.rs new file mode 100644 index 000000000..daf18c670 --- /dev/null +++ b/tests/ui/traits/bound/not-on-bare-trait.rs @@ -0,0 +1,13 @@ +trait Foo { + fn dummy(&self) {} +} + +// This should emit the less confusing error, not the more confusing one. + +fn foo(_x: Foo + Send) { + //~^ ERROR the size for values of type + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} + +fn main() {} diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr new file mode 100644 index 000000000..36b08a7d3 --- /dev/null +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -0,0 +1,34 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/not-on-bare-trait.rs:7:12 + | +LL | fn foo(_x: Foo + Send) { + | ^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | fn foo(_x: dyn Foo + Send) { + | +++ + +error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time + --> $DIR/not-on-bare-trait.rs:7:8 + | +LL | fn foo(_x: Foo + Send) { + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | fn foo(_x: impl Foo + Send) { + | ++++ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo(_x: &Foo + Send) { + | + + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/not-on-struct.rs b/tests/ui/traits/bound/not-on-struct.rs new file mode 100644 index 000000000..8633e9d7a --- /dev/null +++ b/tests/ui/traits/bound/not-on-struct.rs @@ -0,0 +1,38 @@ +// We don't need those errors. Ideally we would silence them, but to do so we need to move the +// lint from being an early-lint during parsing to a late-lint, because it needs to be aware of +// the types involved. +#![allow(bare_trait_objects)] + +struct Foo; + +fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected trait, found struct `Foo` + +type TypeAlias<T> = Box<dyn Vec<T>>; //~ ERROR expected trait, found struct `Vec` + +struct A; +fn a() -> A + 'static { //~ ERROR expected trait, found + A +} +fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) { //~ ERROR expected trait, found + panic!() +} +fn c() -> 'static + A { //~ ERROR expected trait, found + A +} +fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) { //~ ERROR expected trait, found + panic!() +} +fn e() -> 'static + A + 'static { //~ ERROR expected trait, found +//~^ ERROR only a single explicit lifetime bound is permitted + A +} +fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) { //~ ERROR expected trait, found +//~^ ERROR only a single explicit lifetime bound is permitted + panic!() +} +struct Traitor; +trait Trait {} +fn g() -> Traitor + 'static { //~ ERROR expected trait, found struct `Traitor` + A +} +fn main() {} diff --git a/tests/ui/traits/bound/not-on-struct.stderr b/tests/ui/traits/bound/not-on-struct.stderr new file mode 100644 index 000000000..2de35dc7f --- /dev/null +++ b/tests/ui/traits/bound/not-on-struct.stderr @@ -0,0 +1,175 @@ +error[E0226]: only a single explicit lifetime bound is permitted + --> $DIR/not-on-struct.rs:25:25 + | +LL | fn e() -> 'static + A + 'static { + | ^^^^^^^ + +error[E0226]: only a single explicit lifetime bound is permitted + --> $DIR/not-on-struct.rs:29:53 + | +LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) { + | ^^ + +error[E0404]: expected trait, found struct `Foo` + --> $DIR/not-on-struct.rs:8:16 + | +LL | fn foo(_x: Box<Foo + Send>) { } + | ^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:8:22 + | +LL | fn foo(_x: Box<Foo + Send>) { } + | --- ^^^^ ...because of this bound + | | + | expected this type to be a trait... + +error[E0404]: expected trait, found struct `Vec` + --> $DIR/not-on-struct.rs:10:29 + | +LL | type TypeAlias<T> = Box<dyn Vec<T>>; + | ^^^^^^ not a trait + +error[E0404]: expected trait, found struct `A` + --> $DIR/not-on-struct.rs:13:11 + | +LL | fn a() -> A + 'static { + | ^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:13:15 + | +LL | fn a() -> A + 'static { + | - ^^^^^^^ ...because of this bound + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn a() -> A + 'static { +LL + fn a() -> A { + | + +error[E0404]: expected trait, found enum `Result` + --> $DIR/not-on-struct.rs:16:34 + | +LL | fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) { + | ^^^^^^^^^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:16:48 + | +LL | fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) { + | ----------- ^^ ...because of this bound + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) { +LL + fn b<'a,T,E>(iter: Iterator<Item=Result<T,E>>) { + | + +error[E0404]: expected trait, found struct `A` + --> $DIR/not-on-struct.rs:19:21 + | +LL | fn c() -> 'static + A { + | ^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:19:11 + | +LL | fn c() -> 'static + A { + | ^^^^^^^ - expected this type to be a trait... + | | + | ...because of this bound +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn c() -> 'static + A { +LL + fn c() -> A { + | + +error[E0404]: expected trait, found enum `Result` + --> $DIR/not-on-struct.rs:22:39 + | +LL | fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) { + | ^^^^^^^^^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:22:34 + | +LL | fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) { + | ^^ ----------- expected this type to be a trait... + | | + | ...because of this bound +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) { +LL + fn d<'a,T,E>(iter: Iterator<Item=Result<T,E>>) { + | + +error[E0404]: expected trait, found struct `A` + --> $DIR/not-on-struct.rs:25:21 + | +LL | fn e() -> 'static + A + 'static { + | ^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:25:11 + | +LL | fn e() -> 'static + A + 'static { + | ^^^^^^^ - ^^^^^^^ ...because of these bounds + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn e() -> 'static + A + 'static { +LL + fn e() -> A { + | + +error[E0404]: expected trait, found enum `Result` + --> $DIR/not-on-struct.rs:29:39 + | +LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) { + | ^^^^^^^^^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:29:34 + | +LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) { + | ^^ ----------- ^^ ...because of these bounds + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) { +LL + fn f<'a,T,E>(iter: Iterator<Item=Result<T,E>>) { + | + +error[E0404]: expected trait, found struct `Traitor` + --> $DIR/not-on-struct.rs:35:11 + | +LL | trait Trait {} + | ----------- similarly named trait `Trait` defined here +LL | fn g() -> Traitor + 'static { + | ^^^^^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:35:21 + | +LL | fn g() -> Traitor + 'static { + | ------- ^^^^^^^ ...because of this bound + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn g() -> Traitor + 'static { +LL + fn g() -> Traitor { + | +help: a trait with a similar name exists + | +LL | fn g() -> Trait + 'static { + | ~~~~~ + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0226, E0404. +For more information about an error, try `rustc --explain E0226`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs b/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs new file mode 100644 index 000000000..6a6fcf530 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs @@ -0,0 +1,20 @@ +trait Trait {} + +struct Foo<T:Trait> { + x: T, +} + +enum Bar<T:Trait> { + ABar(isize), + BBar(T), + CBar(usize), +} + +fn explode(x: Foo<u32>) {} +//~^ ERROR E0277 + +fn kaboom(y: Bar<f32>) {} +//~^ ERROR E0277 + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr new file mode 100644 index 000000000..61237a63e --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `u32: Trait` is not satisfied + --> $DIR/on-structs-and-enums-in-fns.rs:13:15 + | +LL | fn explode(x: Foo<u32>) {} + | ^^^^^^^^ the trait `Trait` is not implemented for `u32` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-in-fns.rs:3:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `f32: Trait` is not satisfied + --> $DIR/on-structs-and-enums-in-fns.rs:16:14 + | +LL | fn kaboom(y: Bar<f32>) {} + | ^^^^^^^^ the trait `Trait` is not implemented for `f32` + | +note: required by a bound in `Bar` + --> $DIR/on-structs-and-enums-in-fns.rs:7:12 + | +LL | enum Bar<T:Trait> { + | ^^^^^ 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/traits/bound/on-structs-and-enums-in-impls.rs b/tests/ui/traits/bound/on-structs-and-enums-in-impls.rs new file mode 100644 index 000000000..d37949952 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.rs @@ -0,0 +1,25 @@ +trait Trait {} + +struct Foo<T:Trait> { + x: T, +} + +enum Bar<T:Trait> { + ABar(isize), + BBar(T), + CBar(usize), +} + +trait PolyTrait<T> +{ + fn whatever(&self, t: T) {} +} + +struct Struct; + +impl PolyTrait<Foo<u16>> for Struct { +//~^ ERROR E0277 +} + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr new file mode 100644 index 000000000..8a4374226 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u16: Trait` is not satisfied + --> $DIR/on-structs-and-enums-in-impls.rs:20:6 + | +LL | impl PolyTrait<Foo<u16>> for Struct { + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-in-impls.rs:3:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-locals.rs b/tests/ui/traits/bound/on-structs-and-enums-locals.rs new file mode 100644 index 000000000..60ba343bb --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-locals.rs @@ -0,0 +1,17 @@ +trait Trait { + fn dummy(&self) { } +} + +struct Foo<T:Trait> { + x: T, +} + +fn main() { + let foo = Foo { + x: 3 + //~^ ERROR E0277 + }; + + let baz: Foo<usize> = loop { }; + //~^ ERROR E0277 +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-locals.stderr b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr new file mode 100644 index 000000000..20bbe69c0 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums-locals.rs:15:14 + | +LL | let baz: Foo<usize> = loop { }; + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-locals.rs:5:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `{integer}: Trait` is not satisfied + --> $DIR/on-structs-and-enums-locals.rs:11:12 + | +LL | x: 3 + | ^ the trait `Trait` is not implemented for `{integer}` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-locals.rs:5:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-rpass.rs b/tests/ui/traits/bound/on-structs-and-enums-rpass.rs new file mode 100644 index 000000000..4dc4fecc9 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-rpass.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +trait U {} +trait T<X: U> { fn get(self) -> X; } + +trait S2<Y: U> { + fn m(x: Box<dyn T<Y>+'static>) {} +} + +struct St<X: U> { + f: Box<dyn T<X>+'static>, +} + +impl<X: U> St<X> { + fn blah() {} +} + +fn main() {} diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.rs b/tests/ui/traits/bound/on-structs-and-enums-static.rs new file mode 100644 index 000000000..df3f8b8a5 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-static.rs @@ -0,0 +1,15 @@ +trait Trait { + fn dummy(&self) { } +} + +struct Foo<T:Trait> { + x: T, +} + +static X: Foo<usize> = Foo { +//~^ ERROR E0277 + x: 1, +}; + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.stderr b/tests/ui/traits/bound/on-structs-and-enums-static.stderr new file mode 100644 index 000000000..fda734e85 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-static.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums-static.rs:9:11 + | +LL | static X: Foo<usize> = Foo { + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-static.rs:5:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc.rs b/tests/ui/traits/bound/on-structs-and-enums-xc.rs new file mode 100644 index 000000000..94316d240 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-xc.rs @@ -0,0 +1,14 @@ +// aux-build:on_structs_and_enums_xc.rs + +extern crate on_structs_and_enums_xc; + +use on_structs_and_enums_xc::{Bar, Foo, Trait}; + +fn explode(x: Foo<usize>) {} +//~^ ERROR E0277 + +fn kaboom(y: Bar<f32>) {} +//~^ ERROR E0277 + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc.stderr b/tests/ui/traits/bound/on-structs-and-enums-xc.stderr new file mode 100644 index 000000000..5064b60bf --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-xc.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc.rs:7:15 + | +LL | fn explode(x: Foo<usize>) {} + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +note: required by a bound in `Foo` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18 + | +LL | pub struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `f32: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc.rs:10:14 + | +LL | fn kaboom(y: Bar<f32>) {} + | ^^^^^^^^ the trait `Trait` is not implemented for `f32` + | +note: required by a bound in `Bar` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:9:16 + | +LL | pub enum Bar<T:Trait> { + | ^^^^^ 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/traits/bound/on-structs-and-enums-xc1.rs b/tests/ui/traits/bound/on-structs-and-enums-xc1.rs new file mode 100644 index 000000000..5ef35b513 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-xc1.rs @@ -0,0 +1,15 @@ +// aux-build:on_structs_and_enums_xc.rs + +extern crate on_structs_and_enums_xc; + +use on_structs_and_enums_xc::{Bar, Foo, Trait}; + +fn main() { + let foo = Foo { + x: 3 + //~^ ERROR E0277 + }; + let bar: Bar<f64> = return; + //~^ ERROR E0277 + let _ = bar; +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr b/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr new file mode 100644 index 000000000..3fb5decb7 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `f64: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc1.rs:12:14 + | +LL | let bar: Bar<f64> = return; + | ^^^^^^^^ the trait `Trait` is not implemented for `f64` + | +note: required by a bound in `Bar` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:9:16 + | +LL | pub enum Bar<T:Trait> { + | ^^^^^ required by this bound in `Bar` + +error[E0277]: the trait bound `{integer}: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc1.rs:9:12 + | +LL | x: 3 + | ^ the trait `Trait` is not implemented for `{integer}` + | +note: required by a bound in `Foo` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18 + | +LL | pub struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums.rs b/tests/ui/traits/bound/on-structs-and-enums.rs new file mode 100644 index 000000000..024084fa7 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums.rs @@ -0,0 +1,43 @@ +trait Trait {} + +struct Foo<T:Trait> { + x: T, +} + +enum Bar<T:Trait> { + ABar(isize), + BBar(T), + CBar(usize), +} + +impl<T> Foo<T> { +//~^ ERROR `T: Trait` is not satisfied + fn uhoh() {} +} + +struct Baz { + a: Foo<isize>, //~ ERROR E0277 +} + +enum Boo { + Quux(Bar<usize>), //~ ERROR E0277 +} + +struct Badness<U> { + b: Foo<U>, //~ ERROR E0277 +} + +enum MoreBadness<V> { + EvenMoreBadness(Bar<V>), //~ ERROR E0277 +} + +struct TupleLike( + Foo<i32>, //~ ERROR E0277 +); + +enum Enum { + DictionaryLike { field: Bar<u8> }, //~ ERROR E0277 +} + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums.stderr b/tests/ui/traits/bound/on-structs-and-enums.stderr new file mode 100644 index 000000000..fe05b8634 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums.stderr @@ -0,0 +1,99 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:13:9 + | +LL | impl<T> Foo<T> { + | ^^^^^^ the trait `Trait` is not implemented for `T` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums.rs:3:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` +help: consider restricting type parameter `T` + | +LL | impl<T: Trait> Foo<T> { + | +++++++ + +error[E0277]: the trait bound `isize: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:19:8 + | +LL | a: Foo<isize>, + | ^^^^^^^^^^ the trait `Trait` is not implemented for `isize` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums.rs:3:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:23:10 + | +LL | Quux(Bar<usize>), + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +note: required by a bound in `Bar` + --> $DIR/on-structs-and-enums.rs:7:12 + | +LL | enum Bar<T:Trait> { + | ^^^^^ required by this bound in `Bar` + +error[E0277]: the trait bound `U: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:27:8 + | +LL | b: Foo<U>, + | ^^^^^^ the trait `Trait` is not implemented for `U` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums.rs:3:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` +help: consider restricting type parameter `U` + | +LL | struct Badness<U: Trait> { + | +++++++ + +error[E0277]: the trait bound `V: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:31:21 + | +LL | EvenMoreBadness(Bar<V>), + | ^^^^^^ the trait `Trait` is not implemented for `V` + | +note: required by a bound in `Bar` + --> $DIR/on-structs-and-enums.rs:7:12 + | +LL | enum Bar<T:Trait> { + | ^^^^^ required by this bound in `Bar` +help: consider restricting type parameter `V` + | +LL | enum MoreBadness<V: Trait> { + | +++++++ + +error[E0277]: the trait bound `i32: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:35:5 + | +LL | Foo<i32>, + | ^^^^^^^^ the trait `Trait` is not implemented for `i32` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums.rs:3:14 + | +LL | struct Foo<T:Trait> { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `u8: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:39:29 + | +LL | DictionaryLike { field: Bar<u8> }, + | ^^^^^^^ the trait `Trait` is not implemented for `u8` + | +note: required by a bound in `Bar` + --> $DIR/on-structs-and-enums.rs:7:12 + | +LL | enum Bar<T:Trait> { + | ^^^^^ required by this bound in `Bar` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/recursion.rs b/tests/ui/traits/bound/recursion.rs new file mode 100644 index 000000000..0023ff654 --- /dev/null +++ b/tests/ui/traits/bound/recursion.rs @@ -0,0 +1,20 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait I { fn i(&self) -> Self; } + +trait A<T:I> { + fn id(x:T) -> T { x.i() } +} + +trait J<T> { fn j(&self) -> T; } + +trait B<T:J<T>> { + fn id(x:T) -> T { x.j() } +} + +trait C { + fn id<T:J<T>>(x:T) -> T { x.j() } +} + +pub fn main() { } diff --git a/tests/ui/traits/bound/same-crate-name.rs b/tests/ui/traits/bound/same-crate-name.rs new file mode 100644 index 000000000..8d646a414 --- /dev/null +++ b/tests/ui/traits/bound/same-crate-name.rs @@ -0,0 +1,55 @@ +// aux-build:crate_a1.rs +// aux-build:crate_a2.rs + +// Issue 22750 +// This tests the extra help message reported when a trait bound +// is not met but the struct implements a trait with the same path. + +fn main() { + let foo = { + extern crate crate_a2 as a; + a::Foo + }; + + let implements_no_traits = { + extern crate crate_a2 as a; + a::DoesNotImplementTrait + }; + + let other_variant_implements_mismatched_trait = { + extern crate crate_a2 as a; + a::ImplementsWrongTraitConditionally { _marker: std::marker::PhantomData::<isize> } + }; + + let other_variant_implements_correct_trait = { + extern crate crate_a1 as a; + a::ImplementsTraitForUsize { _marker: std::marker::PhantomData::<isize> } + }; + + { + extern crate crate_a1 as a; + a::try_foo(foo); + //~^ ERROR E0277 + //~| trait impl with same name found + //~| perhaps two different versions of crate `crate_a2` + + // We don't want to see the "version mismatch" help message here + // because `implements_no_traits` has no impl for `Foo` + a::try_foo(implements_no_traits); + //~^ ERROR E0277 + + // We don't want to see the "version mismatch" help message here + // because `other_variant_implements_mismatched_trait` + // does not have an impl for its `<isize>` variant, + // only for its `<usize>` variant. + a::try_foo(other_variant_implements_mismatched_trait); + //~^ ERROR E0277 + + // We don't want to see the "version mismatch" help message here + // because `ImplementsTraitForUsize` only has + // impls for the correct trait where the path is not misleading. + a::try_foo(other_variant_implements_correct_trait); + //~^ ERROR E0277 + //~| the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` + } +} diff --git a/tests/ui/traits/bound/same-crate-name.stderr b/tests/ui/traits/bound/same-crate-name.stderr new file mode 100644 index 000000000..f66cad77f --- /dev/null +++ b/tests/ui/traits/bound/same-crate-name.stderr @@ -0,0 +1,75 @@ +error[E0277]: the trait bound `Foo: main::a::Bar` is not satisfied + --> $DIR/same-crate-name.rs:31:20 + | +LL | a::try_foo(foo); + | ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | +help: trait impl with same name found + --> $DIR/auxiliary/crate_a2.rs:5:1 + | +LL | impl Bar for Foo {} + | ^^^^^^^^^^^^^^^^ + = note: perhaps two different versions of crate `crate_a2` are being used? + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` +note: required by a bound in `try_foo` + --> $DIR/auxiliary/crate_a1.rs:3:24 + | +LL | pub fn try_foo(x: impl Bar) {} + | ^^^ required by this bound in `try_foo` + +error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satisfied + --> $DIR/same-crate-name.rs:38:20 + | +LL | a::try_foo(implements_no_traits); + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait` + | | + | required by a bound introduced by this call + | + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` +note: required by a bound in `try_foo` + --> $DIR/auxiliary/crate_a1.rs:3:24 + | +LL | pub fn try_foo(x: impl Bar) {} + | ^^^ required by this bound in `try_foo` + +error[E0277]: the trait bound `ImplementsWrongTraitConditionally<isize>: main::a::Bar` is not satisfied + --> $DIR/same-crate-name.rs:45:20 + | +LL | a::try_foo(other_variant_implements_mismatched_trait); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>` + | | + | required by a bound introduced by this call + | +help: trait impl with same name found + --> $DIR/auxiliary/crate_a2.rs:13:1 + | +LL | impl Bar for ImplementsWrongTraitConditionally<isize> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: perhaps two different versions of crate `crate_a2` are being used? + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` +note: required by a bound in `try_foo` + --> $DIR/auxiliary/crate_a1.rs:3:24 + | +LL | pub fn try_foo(x: impl Bar) {} + | ^^^ required by this bound in `try_foo` + +error[E0277]: the trait bound `ImplementsTraitForUsize<isize>: main::a::Bar` is not satisfied + --> $DIR/same-crate-name.rs:51:20 + | +LL | a::try_foo(other_variant_implements_correct_trait); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>` + | | + | required by a bound introduced by this call + | + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` +note: required by a bound in `try_foo` + --> $DIR/auxiliary/crate_a1.rs:3:24 + | +LL | pub fn try_foo(x: impl Bar) {} + | ^^^ required by this bound in `try_foo` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/sugar.rs b/tests/ui/traits/bound/sugar.rs new file mode 100644 index 000000000..65b6f6faa --- /dev/null +++ b/tests/ui/traits/bound/sugar.rs @@ -0,0 +1,19 @@ +// Tests for "default" bounds inferred for traits with no bounds list. + +trait Foo {} + +fn a(_x: Box<dyn Foo + Send>) { +} + +fn b(_x: &'static (dyn Foo + 'static)) { +} + +fn c(x: Box<dyn Foo + Sync>) { + a(x); //~ ERROR mismatched types +} + +fn d(x: &'static (dyn Foo + Sync)) { + b(x); +} + +fn main() {} diff --git a/tests/ui/traits/bound/sugar.stderr b/tests/ui/traits/bound/sugar.stderr new file mode 100644 index 000000000..b67648c7b --- /dev/null +++ b/tests/ui/traits/bound/sugar.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/sugar.rs:12:7 + | +LL | a(x); + | - ^ expected trait `Foo + Send`, found trait `Foo + Sync` + | | + | arguments to this function are incorrect + | + = note: expected struct `Box<(dyn Foo + Send + 'static)>` + found struct `Box<(dyn Foo + Sync + 'static)>` +note: function defined here + --> $DIR/sugar.rs:5:4 + | +LL | fn a(_x: Box<dyn Foo + Send>) { + | ^ ----------------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/bug-7183-generics.rs b/tests/ui/traits/bug-7183-generics.rs new file mode 100644 index 000000000..f53a17361 --- /dev/null +++ b/tests/ui/traits/bug-7183-generics.rs @@ -0,0 +1,36 @@ +// run-pass + +trait Speak : Sized { + fn say(&self, s:&str) -> String; + fn hi(&self) -> String { hello(self) } +} + +fn hello<S:Speak>(s:&S) -> String{ + s.say("hello") +} + +impl Speak for isize { + fn say(&self, s:&str) -> String { + format!("{}: {}", s, *self) + } +} + +impl<T: Speak> Speak for Option<T> { + fn say(&self, s:&str) -> String { + match *self { + None => format!("{} - none", s), + Some(ref x) => { format!("something!{}", x.say(s)) } + } + } +} + + +pub fn main() { + assert_eq!(3.hi(), "hello: 3".to_string()); + assert_eq!(Some(Some(3)).hi(), + "something!something!hello: 3".to_string()); + assert_eq!(None::<isize>.hi(), "hello - none".to_string()); + + assert_eq!(Some(None::<isize>).hi(), "something!hello - none".to_string()); + assert_eq!(Some(3).hi(), "something!hello: 3".to_string()); +} diff --git a/tests/ui/traits/bug-7295.rs b/tests/ui/traits/bug-7295.rs new file mode 100644 index 000000000..156ff2ee8 --- /dev/null +++ b/tests/ui/traits/bug-7295.rs @@ -0,0 +1,14 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub trait Foo<T> { + fn func1<U>(&self, t: U, w: T); + + fn func2<U>(&self, t: U, w: T) { + self.func1(t, w); + } +} + +pub fn main() { + +} diff --git a/tests/ui/traits/cache-issue-18209.rs b/tests/ui/traits/cache-issue-18209.rs new file mode 100644 index 000000000..15676e455 --- /dev/null +++ b/tests/ui/traits/cache-issue-18209.rs @@ -0,0 +1,20 @@ +// run-pass +// Test that the cache results from the default method do not pollute +// the cache for the later call in `load()`. +// +// See issue #18209. + +// pretty-expanded FIXME #23616 + +pub trait Foo { + fn load_from() -> Box<Self>; + fn load() -> Box<Self> { + Foo::load_from() + } +} + +pub fn load<M: Foo>() -> Box<M> { + Foo::load() +} + +fn main() { } diff --git a/tests/ui/traits/cache-reached-depth-ice.rs b/tests/ui/traits/cache-reached-depth-ice.rs new file mode 100644 index 000000000..c36ac0857 --- /dev/null +++ b/tests/ui/traits/cache-reached-depth-ice.rs @@ -0,0 +1,45 @@ +#![feature(rustc_attrs)] + +// Test for a particular corner case where the evaluation +// cache can get out of date. The problem here is that +// when we cache C, we have observed that it reaches +// to depth 2 (the node for B), but we later realize +// that B itself depends on A (reached depth 0). We +// failed to update the depth for C transitively, which +// resulted in an assertion failure when it was referenced +// from D. +// +// A (reached depth 0) +// E +// B // depth 2 -- reached depth = 0 +// C // depth 3 -- reached depth = 2 (should be 0) +// B +// A // depth 0 +// D (depth 1) +// C (cache -- reached depth = 2) + +struct A { + e: E, + d: C, +} + +struct E { + b: B, +} + +struct B { + a: Option<Box<A>>, + c: C, +} + +struct C { + b: Option<Box<B>>, +} + +#[rustc_evaluate_where_clauses] +fn test<X: ?Sized + Send>() {} + +fn main() { + test::<A>(); + //~^ ERROR evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk) +} diff --git a/tests/ui/traits/cache-reached-depth-ice.stderr b/tests/ui/traits/cache-reached-depth-ice.stderr new file mode 100644 index 000000000..082aa0f5c --- /dev/null +++ b/tests/ui/traits/cache-reached-depth-ice.stderr @@ -0,0 +1,11 @@ +error: evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/cache-reached-depth-ice.rs:43:5 + | +LL | fn test<X: ?Sized + Send>() {} + | ---- predicate +... +LL | test::<A>(); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/coercion-generic-bad.rs b/tests/ui/traits/coercion-generic-bad.rs new file mode 100644 index 000000000..2e115c732 --- /dev/null +++ b/tests/ui/traits/coercion-generic-bad.rs @@ -0,0 +1,19 @@ +struct Struct { + person: &'static str +} + +trait Trait<T> { + fn f(&self, x: T); +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println!("Hello, {}!", x); + } +} + +fn main() { + let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" }); + //~^ ERROR `Struct: Trait<isize>` is not satisfied + s.f(1); +} diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr new file mode 100644 index 000000000..93d6770eb --- /dev/null +++ b/tests/ui/traits/coercion-generic-bad.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Struct: Trait<isize>` is not satisfied + --> $DIR/coercion-generic-bad.rs:16:36 + | +LL | let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct` + | + = help: the trait `Trait<&'static str>` is implemented for `Struct` + = note: required for the cast from `Struct` to the object type `dyn Trait<isize>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/coercion-generic-regions.rs b/tests/ui/traits/coercion-generic-regions.rs new file mode 100644 index 000000000..af478df6d --- /dev/null +++ b/tests/ui/traits/coercion-generic-regions.rs @@ -0,0 +1,19 @@ +struct Struct { + person: &'static str +} + +trait Trait<T> { + fn f(&self, x: T); +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println!("Hello, {}!", x); + } +} + +fn main() { + let person = "Fred".to_string(); + let person: &str = &person; //~ ERROR `person` does not live long enough + let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person }); +} diff --git a/tests/ui/traits/coercion-generic-regions.stderr b/tests/ui/traits/coercion-generic-regions.stderr new file mode 100644 index 000000000..5cfb64901 --- /dev/null +++ b/tests/ui/traits/coercion-generic-regions.stderr @@ -0,0 +1,15 @@ +error[E0597]: `person` does not live long enough + --> $DIR/coercion-generic-regions.rs:17:24 + | +LL | let person: &str = &person; + | ^^^^^^^ + | | + | borrowed value does not live long enough + | assignment requires that `person` is borrowed for `'static` +LL | let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person }); +LL | } + | - `person` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/traits/coercion-generic.rs b/tests/ui/traits/coercion-generic.rs new file mode 100644 index 000000000..bf4dda495 --- /dev/null +++ b/tests/ui/traits/coercion-generic.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +trait Trait<T> { + fn f(&self, x: T); +} + +#[derive(Copy, Clone)] +struct Struct { + x: isize, + y: isize, +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println!("Hi, {}!", x); + } +} + +pub fn main() { + let a = Struct { x: 1, y: 2 }; + let b: Box<dyn Trait<&'static str>> = Box::new(a); + b.f("Mary"); + let c: &dyn Trait<&'static str> = &a; + c.f("Joe"); +} diff --git a/tests/ui/traits/coercion.rs b/tests/ui/traits/coercion.rs new file mode 100644 index 000000000..e62742bac --- /dev/null +++ b/tests/ui/traits/coercion.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(unused_variables)] + +use std::io::{self, Write}; + +trait Trait { + fn f(&self); +} + +#[derive(Copy, Clone)] +struct Struct { + x: isize, + y: isize, +} + +impl Trait for Struct { + fn f(&self) { + println!("Hi!"); + } +} + +fn foo(mut a: Box<dyn Write>) {} + +pub fn main() { + let a = Struct { x: 1, y: 2 }; + let b: Box<dyn Trait> = Box::new(a); + b.f(); + let c: &dyn Trait = &a; + c.f(); + + let out = io::stdout(); + foo(Box::new(out)); +} diff --git a/tests/ui/traits/composition-trivial.rs b/tests/ui/traits/composition-trivial.rs new file mode 100644 index 000000000..90e5dcd68 --- /dev/null +++ b/tests/ui/traits/composition-trivial.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Foo { + fn foo(&self); +} + +trait Bar : Foo { + fn bar(&self); +} + +pub fn main() {} diff --git a/tests/ui/traits/conditional-dispatch.rs b/tests/ui/traits/conditional-dispatch.rs new file mode 100644 index 000000000..dd882dce6 --- /dev/null +++ b/tests/ui/traits/conditional-dispatch.rs @@ -0,0 +1,34 @@ +// run-pass +// Test that we are able to resolve conditional dispatch. Here, the +// blanket impl for T:Copy coexists with an impl for Box<T>, because +// Box does not impl Copy. + + +trait Get { + fn get(&self) -> Self; +} + +trait MyCopy { fn copy(&self) -> Self; } +impl MyCopy for u16 { fn copy(&self) -> Self { *self } } +impl MyCopy for u32 { fn copy(&self) -> Self { *self } } +impl MyCopy for i32 { fn copy(&self) -> Self { *self } } +impl<T:Copy> MyCopy for Option<T> { fn copy(&self) -> Self { *self } } + +impl<T:MyCopy> Get for T { + fn get(&self) -> T { self.copy() } +} + +impl Get for Box<i32> { + fn get(&self) -> Box<i32> { Box::new(get_it(&**self)) } +} + +fn get_it<T:Get>(t: &T) -> T { + (*t).get() +} + +fn main() { + assert_eq!(get_it(&1_u32), 1_u32); + assert_eq!(get_it(&1_u16), 1_u16); + assert_eq!(get_it(&Some(1_u16)), Some(1_u16)); + assert_eq!(get_it(&Box::new(1)), Box::new(1)); +} diff --git a/tests/ui/traits/conditional-model-fn.rs b/tests/ui/traits/conditional-model-fn.rs new file mode 100644 index 000000000..ba8867003 --- /dev/null +++ b/tests/ui/traits/conditional-model-fn.rs @@ -0,0 +1,53 @@ +// run-pass +#![allow(unused_imports)] +// A model for how the `Fn` traits could work. You can implement at +// most one of `Go`, `GoMut`, or `GoOnce`, and then the others follow +// automatically. + +// aux-build:go_trait.rs + +extern crate go_trait; + +use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once}; + +use std::rc::Rc; +use std::cell::Cell; + +struct SomeGoableThing { + counter: Rc<Cell<isize>> +} + +impl Go for SomeGoableThing { + fn go(&self, arg: isize) { + self.counter.set(self.counter.get() + arg); + } +} + +struct SomeGoOnceableThing { + counter: Rc<Cell<isize>> +} + +impl GoOnce for SomeGoOnceableThing { + fn go_once(self, arg: isize) { + self.counter.set(self.counter.get() + arg); + } +} + +fn main() { + let counter = Rc::new(Cell::new(0)); + let mut x = SomeGoableThing { counter: counter.clone() }; + + go(&x, 10); + assert_eq!(counter.get(), 10); + + go_mut(&mut x, 100); + assert_eq!(counter.get(), 110); + + go_once(x, 1_000); + assert_eq!(counter.get(), 1_110); + + let x = SomeGoOnceableThing { counter: counter.clone() }; + + go_once(x, 10_000); + assert_eq!(counter.get(), 11_110); +} diff --git a/tests/ui/traits/conservative_impl_trait.rs b/tests/ui/traits/conservative_impl_trait.rs new file mode 100644 index 000000000..4f25e57be --- /dev/null +++ b/tests/ui/traits/conservative_impl_trait.rs @@ -0,0 +1,8 @@ +// build-pass (FIXME(62277): could be check-pass?) +// #39665 + +fn batches(n: &u32) -> impl Iterator<Item=&u32> { + std::iter::once(n) +} + +fn main() {} diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs new file mode 100644 index 000000000..f031dd9ca --- /dev/null +++ b/tests/ui/traits/copy-guessing.rs @@ -0,0 +1,38 @@ +// run-pass +#![allow(dead_code)] +// "guessing" in trait selection can affect `copy_or_move`. Check that this +// is correctly handled. I am not sure what is the "correct" behaviour, +// but we should at least not ICE. + +use std::mem; + +struct U([u8; 1337]); + +struct S<'a,T:'a>(&'a T); +impl<'a, T> Clone for S<'a, T> { fn clone(&self) -> Self { S(self.0) } } +/// This impl triggers inference "guessing" - S<_>: Copy => _ = U +impl<'a> Copy for S<'a, Option<U>> {} + +fn assert_impls_fn<R,T: Fn()->R>(_: &T){} + +fn main() { + let n = None; + let e = S(&n); + let f = || { + // S being copy is critical for this to work + drop(e); + mem::size_of_val(e.0) + }; + assert_impls_fn(&f); + assert_eq!(f(), 1337+1); + + assert_eq!((|| { + // S being Copy is not critical here, but + // we check it anyway. + let n = None; + let e = S(&n); + let ret = mem::size_of_val(e.0); + drop(e); + ret + })(), 1337+1); +} diff --git a/tests/ui/traits/copy-impl-cannot-normalize.rs b/tests/ui/traits/copy-impl-cannot-normalize.rs new file mode 100644 index 000000000..a78ff046e --- /dev/null +++ b/tests/ui/traits/copy-impl-cannot-normalize.rs @@ -0,0 +1,25 @@ +trait TraitFoo { + type Bar; +} + +struct Foo<T> +where + T: TraitFoo, +{ + inner: T::Bar, +} + +impl<T> Clone for Foo<T> +where + T: TraitFoo, + T::Bar: Clone, +{ + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } +} + +impl<T> Copy for Foo<T> {} +//~^ ERROR the trait bound `T: TraitFoo` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr new file mode 100644 index 000000000..86c511c08 --- /dev/null +++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: TraitFoo` is not satisfied + --> $DIR/copy-impl-cannot-normalize.rs:22:18 + | +LL | impl<T> Copy for Foo<T> {} + | ^^^^^^ the trait `TraitFoo` is not implemented for `T` + | +note: required for `Foo<T>` to implement `Clone` + --> $DIR/copy-impl-cannot-normalize.rs:12:9 + | +LL | impl<T> Clone for Foo<T> + | ^^^^^ ^^^^^^ +LL | where +LL | T: TraitFoo, + | -------- unsatisfied trait bound introduced here +note: required by a bound in `Copy` + --> $SRC_DIR/core/src/marker.rs:LL:COL +help: consider restricting type parameter `T` + | +LL | impl<T: TraitFoo> Copy for Foo<T> {} + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr new file mode 100644 index 000000000..edd94d201 --- /dev/null +++ b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr @@ -0,0 +1,22 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/copy-is-not-modulo-regions.rs:13:21 + | +LL | struct Bar<'lt>(Foo<'lt>); + | -------- this field does not implement `Copy` +... +LL | impl<'any> Copy for Bar<'any> {} + | ^^^^^^^^^ + | +note: the `Copy` impl for `Foo<'any>` requires that `'any: 'static` + --> $DIR/copy-is-not-modulo-regions.rs:10:17 + | +LL | struct Bar<'lt>(Foo<'lt>); + | ^^^^^^^^ +help: consider restricting type parameter `'any` + | +LL | impl<'any: 'static> Copy for Bar<'any> {} + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/copy-is-not-modulo-regions.rs b/tests/ui/traits/copy-is-not-modulo-regions.rs new file mode 100644 index 000000000..adb870237 --- /dev/null +++ b/tests/ui/traits/copy-is-not-modulo-regions.rs @@ -0,0 +1,19 @@ +// revisions: not_static yes_static +//[yes_static] check-pass + +#[derive(Clone)] +struct Foo<'lt>(&'lt ()); + +impl Copy for Foo<'static> {} + +#[derive(Clone)] +struct Bar<'lt>(Foo<'lt>); + +#[cfg(not_static)] +impl<'any> Copy for Bar<'any> {} +//[not_static]~^ the trait `Copy` may not be implemented for this type + +#[cfg(yes_static)] +impl<'any> Copy for Bar<'static> {} + +fn main() {} diff --git a/tests/ui/traits/copy-requires-self-wf.rs b/tests/ui/traits/copy-requires-self-wf.rs new file mode 100644 index 000000000..9abfdfab9 --- /dev/null +++ b/tests/ui/traits/copy-requires-self-wf.rs @@ -0,0 +1,14 @@ +// check-pass + +#[derive(Clone)] +struct A<'a, T>(&'a T); + +impl<'a, T: Copy + 'a> Copy for A<'a, T> {} + +#[derive(Clone)] +struct B<'a, T>(A<'a, T>); + +// `T: '_` should be implied by `WF(B<'_, T>)`. +impl<T: Copy> Copy for B<'_, T> {} + +fn main() {} diff --git a/tests/ui/traits/cycle-cache-err-60010.rs b/tests/ui/traits/cycle-cache-err-60010.rs new file mode 100644 index 000000000..94e718317 --- /dev/null +++ b/tests/ui/traits/cycle-cache-err-60010.rs @@ -0,0 +1,74 @@ +// Test that we properly detect the cycle amongst the traits +// here and report an error. + +use std::panic::RefUnwindSafe; + +trait Database { + type Storage; +} +trait HasQueryGroup {} +trait Query<DB> { + type Data; +} +trait SourceDatabase { + fn parse(&self) { + loop {} + } +} + +struct ParseQuery; +struct RootDatabase { + _runtime: Runtime<RootDatabase>, +} +struct Runtime<DB: Database> { + _storage: Box<DB::Storage>, +} +struct SalsaStorage { + _parse: <ParseQuery as Query<RootDatabase>>::Data, + //~^ ERROR overflow +} + +impl Database for RootDatabase { + // This would also be an error if we didn't abort compilation on the error + // above. + type Storage = SalsaStorage; +} +impl HasQueryGroup for RootDatabase {} +impl<DB> Query<DB> for ParseQuery +where + DB: SourceDatabase, + DB: Database, +{ + type Data = RootDatabase; +} +impl<T> SourceDatabase for T +where + T: RefUnwindSafe, + T: HasQueryGroup, +{ +} + +pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 { + // This is not satisfied: + // + // - `RootDatabase: SourceDatabase` + // - requires `RootDatabase: RefUnwindSafe` + `RootDatabase: HasQueryGroup` + // - `RootDatabase: RefUnwindSafe` + // - requires `Runtime<RootDatabase>: RefUnwindSafe` + // - `Runtime<RootDatabase>: RefUnwindSafe` + // - requires `DB::Storage: RefUnwindSafe` (`SalsaStorage: RefUnwindSafe`) + // - `SalsaStorage: RefUnwindSafe` + // - requires `<ParseQuery as Query<RootDatabase>>::Data: RefUnwindSafe`, + // which means `ParseQuery: Query<RootDatabase>` + // - `ParseQuery: Query<RootDatabase>` + // - requires `RootDatabase: SourceDatabase`, + // - `RootDatabase: SourceDatabase` is already on the stack, so we have a + // cycle with non-coinductive participants + // + // we used to fail to report an error here because we got the + // caching wrong. + SourceDatabase::parse(db); + 22 +} + +fn main() {} diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr new file mode 100644 index 000000000..eeee99760 --- /dev/null +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -0,0 +1,39 @@ +error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe` + --> $DIR/cycle-cache-err-60010.rs:27:13 + | +LL | _parse: <ParseQuery as Query<RootDatabase>>::Data, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because it appears within the type `PhantomData<SalsaStorage>` + = note: required because it appears within the type `Unique<SalsaStorage>` + = note: required because it appears within the type `Box<SalsaStorage>` +note: required because it appears within the type `Runtime<RootDatabase>` + --> $DIR/cycle-cache-err-60010.rs:23:8 + | +LL | struct Runtime<DB: Database> { + | ^^^^^^^ +note: required because it appears within the type `RootDatabase` + --> $DIR/cycle-cache-err-60010.rs:20:8 + | +LL | struct RootDatabase { + | ^^^^^^^^^^^^ +note: required for `RootDatabase` to implement `SourceDatabase` + --> $DIR/cycle-cache-err-60010.rs:44:9 + | +LL | impl<T> SourceDatabase for T + | ^^^^^^^^^^^^^^ ^ +LL | where +LL | T: RefUnwindSafe, + | ------------- unsatisfied trait bound introduced here +note: required for `ParseQuery` to implement `Query<RootDatabase>` + --> $DIR/cycle-cache-err-60010.rs:37:10 + | +LL | impl<DB> Query<DB> for ParseQuery + | ^^^^^^^^^ ^^^^^^^^^^ +LL | where +LL | DB: SourceDatabase, + | -------------- unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/cycle-generic-bound.rs b/tests/ui/traits/cycle-generic-bound.rs new file mode 100644 index 000000000..9241f3789 --- /dev/null +++ b/tests/ui/traits/cycle-generic-bound.rs @@ -0,0 +1,11 @@ +// run-pass +// Regression test for #15477. This test just needs to compile. + +// pretty-expanded FIXME #23616 + +trait Chromosome<X: Chromosome<i32>> { +} + +impl Chromosome<i32> for i32 { } + +fn main() { } diff --git a/tests/ui/traits/cycle-type-trait.rs b/tests/ui/traits/cycle-type-trait.rs new file mode 100644 index 000000000..c62d01403 --- /dev/null +++ b/tests/ui/traits/cycle-type-trait.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// Test a case where a supertrait references a type that references +// the original trait. This poses no problem at the moment. + +// pretty-expanded FIXME #23616 + +trait Chromosome: Get<Struct<i32>> { +} + +trait Get<A> { + fn get(&self) -> A; +} + +struct Struct<C:Chromosome> { c: C } + +impl Chromosome for i32 { } + +impl Get<Struct<i32>> for i32 { + fn get(&self) -> Struct<i32> { + Struct { c: *self } + } +} + +fn main() { } diff --git a/tests/ui/traits/default-method/auxiliary/xc.rs b/tests/ui/traits/default-method/auxiliary/xc.rs new file mode 100644 index 000000000..0fb26af80 --- /dev/null +++ b/tests/ui/traits/default-method/auxiliary/xc.rs @@ -0,0 +1,40 @@ +pub struct Something { pub x: isize } + +pub trait A { + fn f(&self) -> isize; + fn g(&self) -> isize { 10 } + fn h(&self) -> isize { 11 } + fn lurr(x: &Self, y: &Self) -> isize { x.g() + y.h() } +} + + +impl A for isize { + fn f(&self) -> isize { 10 } +} + +impl A for Something { + fn f(&self) -> isize { 10 } +} + +pub trait B<T> { + fn thing<U>(&self, x: T, y: U) -> (T, U) { (x, y) } + fn staticthing<U>(_z: &Self, x: T, y: U) -> (T, U) { (x, y) } +} + +impl<T> B<T> for isize { } +impl B<f64> for bool { } + + + +pub trait TestEquality { + fn test_eq(&self, rhs: &Self) -> bool; + fn test_neq(&self, rhs: &Self) -> bool { + !self.test_eq(rhs) + } +} + +impl TestEquality for isize { + fn test_eq(&self, rhs: &isize) -> bool { + *self == *rhs + } +} diff --git a/tests/ui/traits/default-method/auxiliary/xc_2.rs b/tests/ui/traits/default-method/auxiliary/xc_2.rs new file mode 100644 index 000000000..979233820 --- /dev/null +++ b/tests/ui/traits/default-method/auxiliary/xc_2.rs @@ -0,0 +1,17 @@ +// aux-build:xc.rs + +extern crate xc as aux; +use aux::A; + +pub struct a_struct { pub x: isize } + +impl A for a_struct { + fn f(&self) -> isize { 10 } +} + +// This function will need to get inlined, and badness may result. +pub fn welp<A>(x: A) -> A { + let a = a_struct { x: 0 }; + a.g(); + x +} diff --git a/tests/ui/traits/default-method/bound-subst.rs b/tests/ui/traits/default-method/bound-subst.rs new file mode 100644 index 000000000..6a5d5c8ba --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst.rs @@ -0,0 +1,18 @@ +// run-pass + + +trait A<T> { + fn g<U>(&self, x: T, y: U) -> (T, U) { (x, y) } +} + +impl A<i32> for i32 { } +impl<T> A<T> for u32 { } + +fn f<T, U, V: A<T>>(i: V, j: T, k: U) -> (T, U) { + i.g(j, k) +} + +pub fn main () { + assert_eq!(f(0, 1, 2), (1, 2)); + assert_eq!(f(0, 1, 2), (1, 2)); +} diff --git a/tests/ui/traits/default-method/bound-subst2.rs b/tests/ui/traits/default-method/bound-subst2.rs new file mode 100644 index 000000000..78eabba2d --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst2.rs @@ -0,0 +1,16 @@ +// run-pass + + +trait A<T> { + fn g(&self, x: T) -> T { x } +} + +impl A<isize> for isize { } + +fn f<T, V: A<T>>(i: V, j: T) -> T { + i.g(j) +} + +pub fn main () { + assert_eq!(f(0, 2), 2); +} diff --git a/tests/ui/traits/default-method/bound-subst3.rs b/tests/ui/traits/default-method/bound-subst3.rs new file mode 100644 index 000000000..dd39dec4b --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst3.rs @@ -0,0 +1,17 @@ +// run-pass + + +trait A { + fn g<T>(&self, x: T, y: T) -> (T, T) { (x, y) } +} + +impl A for isize { } + +fn f<T, V: A>(i: V, j: T, k: T) -> (T, T) { + i.g(j, k) +} + +pub fn main () { + assert_eq!(f(0, 1, 2), (1, 2)); + assert_eq!(f(0, 1u8, 2u8), (1u8, 2u8)); +} diff --git a/tests/ui/traits/default-method/bound-subst4.rs b/tests/ui/traits/default-method/bound-subst4.rs new file mode 100644 index 000000000..ef1330645 --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst4.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(unused_variables)] + + +trait A<T> { + fn g(&self, x: usize) -> usize { x } + fn h(&self, x: T) { } +} + +impl<T> A<T> for isize { } + +fn f<T, V: A<T>>(i: V, j: usize) -> usize { + i.g(j) +} + +pub fn main () { + assert_eq!(f::<f64, isize>(0, 2), 2); + assert_eq!(f::<usize, isize>(0, 2), 2); +} diff --git a/tests/ui/traits/default-method/bound.rs b/tests/ui/traits/default-method/bound.rs new file mode 100644 index 000000000..0855a9db8 --- /dev/null +++ b/tests/ui/traits/default-method/bound.rs @@ -0,0 +1,16 @@ +// run-pass + + +trait A { + fn g(&self) -> isize { 10 } +} + +impl A for isize { } + +fn f<T:A>(i: T) { + assert_eq!(i.g(), 10); +} + +pub fn main () { + f(0); +} diff --git a/tests/ui/traits/default-method/macro.rs b/tests/ui/traits/default-method/macro.rs new file mode 100644 index 000000000..2b50ee9b4 --- /dev/null +++ b/tests/ui/traits/default-method/macro.rs @@ -0,0 +1,20 @@ +// run-pass + + +trait Foo { + fn bar(&self) -> String { + format!("test") + } +} + +enum Baz { + Quux +} + +impl Foo for Baz { +} + +pub fn main() { + let q = Baz::Quux; + assert_eq!(q.bar(), "test".to_string()); +} diff --git a/tests/ui/traits/default-method/mut.rs b/tests/ui/traits/default-method/mut.rs new file mode 100644 index 000000000..5f8e983b0 --- /dev/null +++ b/tests/ui/traits/default-method/mut.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_assignments)] +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +trait Foo { + fn foo(&self, mut v: isize) { v = 1; } +} + +pub fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of.rs new file mode 100644 index 000000000..5ba2f5ce3 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of.rs @@ -0,0 +1,44 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(eq, neq)] +trait Equal { + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +struct T0; +struct T1; +struct T2; +struct T3; + +impl Equal for T0 { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl Equal for T1 { + fn neq(&self, _other: &Self) -> bool { + false + } +} + +impl Equal for T2 { + fn eq(&self, _other: &Self) -> bool { + true + } + + fn neq(&self, _other: &Self) -> bool { + false + } +} + +impl Equal for T3 {} +//~^ not all trait items implemented, missing one of: `eq`, `neq` + +fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr new file mode 100644 index 000000000..5a4dd1388 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr @@ -0,0 +1,15 @@ +error[E0046]: not all trait items implemented, missing one of: `eq`, `neq` + --> $DIR/rustc_must_implement_one_of.rs:41:1 + | +LL | impl Equal for T3 {} + | ^^^^^^^^^^^^^^^^^ missing one of `eq`, `neq` in implementation + | +note: required because of this annotation + --> $DIR/rustc_must_implement_one_of.rs:3:1 + | +LL | #[rustc_must_implement_one_of(eq, neq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs new file mode 100644 index 000000000..8db5fa615 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs @@ -0,0 +1,19 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, a)] +//~^ functions names are duplicated +trait Trait { + fn a() {} +} + +#[rustc_must_implement_one_of(b, a, a, c, b, c)] +//~^ functions names are duplicated +//~| functions names are duplicated +//~| functions names are duplicated +trait Trait1 { + fn a() {} + fn b() {} + fn c() {} +} + +fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr new file mode 100644 index 000000000..cd1476a6e --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr @@ -0,0 +1,34 @@ +error: functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, a)] + | ^ ^ + | + = note: all `#[rustc_must_implement_one_of]` arguments must be unique + +error: functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: all `#[rustc_must_implement_one_of]` arguments must be unique + +error: functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: all `#[rustc_must_implement_one_of]` arguments must be unique + +error: functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: all `#[rustc_must_implement_one_of]` arguments must be unique + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs new file mode 100644 index 000000000..ec2995872 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs @@ -0,0 +1,13 @@ +#[rustc_must_implement_one_of(eq, neq)] +//~^ the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std +trait Equal { + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr new file mode 100644 index 000000000..228bc3e35 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std + --> $DIR/rustc_must_implement_one_of_gated.rs:1:1 + | +LL | #[rustc_must_implement_one_of(eq, neq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs new file mode 100644 index 000000000..b1b91966c --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs @@ -0,0 +1,46 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, b)] +//~^ function not found in this trait +//~| function not found in this trait +trait Tr0 {} + +#[rustc_must_implement_one_of(a, b)] +//~^ function not found in this trait +trait Tr1 { + fn a() {} +} + +#[rustc_must_implement_one_of(a)] +//~^ the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +trait Tr2 { + fn a() {} +} + +#[rustc_must_implement_one_of] +//~^ malformed `rustc_must_implement_one_of` attribute input +trait Tr3 {} + +#[rustc_must_implement_one_of(A, B)] +trait Tr4 { + const A: u8 = 1; //~ not a function + + type B; //~ not a function +} + +#[rustc_must_implement_one_of(a, b)] +trait Tr5 { + fn a(); //~ function doesn't have a default implementation + + fn b(); //~ function doesn't have a default implementation +} + +#[rustc_must_implement_one_of(abc, xyz)] +//~^ attribute should be applied to a trait +fn function() {} + +#[rustc_must_implement_one_of(abc, xyz)] +//~^ attribute should be applied to a trait +struct Struct {} + +fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr new file mode 100644 index 000000000..38e692521 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -0,0 +1,100 @@ +error: malformed `rustc_must_implement_one_of` attribute input + --> $DIR/rustc_must_implement_one_of_misuse.rs:20:1 + | +LL | #[rustc_must_implement_one_of] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]` + +error: attribute should be applied to a trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:38:1 + | +LL | #[rustc_must_implement_one_of(abc, xyz)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn function() {} + | ---------------- not a trait + +error: attribute should be applied to a trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:42:1 + | +LL | #[rustc_must_implement_one_of(abc, xyz)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Struct {} + | ---------------- not a trait + +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args + --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1 + | +LL | #[rustc_must_implement_one_of(a)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: not a function + --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 + | +LL | const A: u8 = 1; + | ^^^^^^^^^^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1 + | +LL | #[rustc_must_implement_one_of(A, B)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names + +error: not a function + --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5 + | +LL | type B; + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1 + | +LL | #[rustc_must_implement_one_of(A, B)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names + +error: function doesn't have a default implementation + --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5 + | +LL | fn a(); + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: function doesn't have a default implementation + --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5 + | +LL | fn b(); + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 11 previous errors + diff --git a/tests/ui/traits/default-method/self.rs b/tests/ui/traits/default-method/self.rs new file mode 100644 index 000000000..cdf4d1e14 --- /dev/null +++ b/tests/ui/traits/default-method/self.rs @@ -0,0 +1,18 @@ +// run-pass + + +trait Cat { + fn meow(&self) -> bool; + fn scratch(&self) -> bool { self.purr() } + fn purr(&self) -> bool { true } +} + +impl Cat for isize { + fn meow(&self) -> bool { + self.scratch() + } +} + +pub fn main() { + assert!(5.meow()); +} diff --git a/tests/ui/traits/default-method/supervtable.rs b/tests/ui/traits/default-method/supervtable.rs new file mode 100644 index 000000000..939ad5135 --- /dev/null +++ b/tests/ui/traits/default-method/supervtable.rs @@ -0,0 +1,28 @@ +// run-pass + + +// Tests that we can call a function bounded over a supertrait from +// a default method + +fn require_y<T: Y>(x: T) -> isize { x.y() } + +trait Y { + fn y(self) -> isize; +} + + +trait Z: Y + Sized { + fn x(self) -> isize { + require_y(self) + } +} + +impl Y for isize { + fn y(self) -> isize { self } +} + +impl Z for isize {} + +pub fn main() { + assert_eq!(12.x(), 12); +} diff --git a/tests/ui/traits/default-method/trivial.rs b/tests/ui/traits/default-method/trivial.rs new file mode 100644 index 000000000..dc41938ec --- /dev/null +++ b/tests/ui/traits/default-method/trivial.rs @@ -0,0 +1,21 @@ +// run-pass + + +trait Cat { + fn meow(&self) -> bool; + fn scratch(&self) -> bool; + fn purr(&self) -> bool { true } +} + +impl Cat for isize { + fn meow(&self) -> bool { + self.scratch() + } + fn scratch(&self) -> bool { + self.purr() + } +} + +pub fn main() { + assert!(5.meow()); +} diff --git a/tests/ui/traits/default-method/xc-2.rs b/tests/ui/traits/default-method/xc-2.rs new file mode 100644 index 000000000..1de61dcf8 --- /dev/null +++ b/tests/ui/traits/default-method/xc-2.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:xc.rs +// aux-build:xc_2.rs + + + +extern crate xc as aux; +extern crate xc_2 as aux2; +use aux::A; +use aux2::{a_struct, welp}; + + +pub fn main () { + + let a = a_struct { x: 0 }; + let b = a_struct { x: 1 }; + + assert_eq!(0.g(), 10); + assert_eq!(a.g(), 10); + assert_eq!(a.h(), 11); + assert_eq!(b.g(), 10); + assert_eq!(b.h(), 11); + assert_eq!(A::lurr(&a, &b), 21); + + welp(&0); +} diff --git a/tests/ui/traits/default-method/xc.rs b/tests/ui/traits/default-method/xc.rs new file mode 100644 index 000000000..76a1573d6 --- /dev/null +++ b/tests/ui/traits/default-method/xc.rs @@ -0,0 +1,81 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// aux-build:xc.rs + + +extern crate xc as aux; +use aux::{A, TestEquality, Something}; +use aux::B; + +fn f<T: aux::A>(i: T) { + assert_eq!(i.g(), 10); +} + +fn welp<T>(i: isize, _x: &T) -> isize { + i.g() +} + +mod stuff { + pub struct thing { pub x: isize } +} + +impl A for stuff::thing { + fn f(&self) -> isize { 10 } +} + +fn g<T, U, V: B<T>>(i: V, j: T, k: U) -> (T, U) { + i.thing(j, k) +} + +fn eq<T: TestEquality>(lhs: &T, rhs: &T) -> bool { + lhs.test_eq(rhs) +} +fn neq<T: TestEquality>(lhs: &T, rhs: &T) -> bool { + lhs.test_neq(rhs) +} + + +impl TestEquality for stuff::thing { + fn test_eq(&self, rhs: &stuff::thing) -> bool { + //self.x.test_eq(&rhs.x) + eq(&self.x, &rhs.x) + } +} + + +pub fn main() { + // Some tests of random things + f(0); + + assert_eq!(A::lurr(&0, &1), 21); + + let a = stuff::thing { x: 0 }; + let b = stuff::thing { x: 1 }; + let c = Something { x: 1 }; + + assert_eq!(0.g(), 10); + assert_eq!(a.g(), 10); + assert_eq!(a.h(), 11); + assert_eq!(c.h(), 11); + + assert_eq!(0.thing(3.14f64, 1), (3.14f64, 1)); + assert_eq!(B::staticthing(&0, 3.14f64, 1), (3.14f64, 1)); + assert_eq!(B::<f64>::staticthing::<isize>(&0, 3.14, 1), (3.14, 1)); + + assert_eq!(g(0, 3.14f64, 1), (3.14f64, 1)); + assert_eq!(g(false, 3.14f64, 1), (3.14, 1)); + + + // Trying out a real one + assert!(12.test_neq(&10)); + assert!(!10.test_neq(&10)); + assert!(a.test_neq(&b)); + assert!(!a.test_neq(&a)); + + assert!(neq(&12, &10)); + assert!(!neq(&10, &10)); + assert!(neq(&a, &b)); + assert!(!neq(&a, &a)); +} diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs new file mode 100644 index 000000000..9a444be50 --- /dev/null +++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs @@ -0,0 +1,20 @@ +struct Thing<X>(X); + +trait Method<T> { + fn method(self, _: i32) -> T; +} + +impl<X> Method<i32> for Thing<X> { + fn method(self, _: i32) -> i32 { 0 } +} + +impl<X> Method<u32> for Thing<X> { + fn method(self, _: i32) -> u32 { 0 } +} + +fn main() { + let thing = Thing(true); + thing.method(42); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr new file mode 100644 index 000000000..57b2587ae --- /dev/null +++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr @@ -0,0 +1,34 @@ +error[E0282]: type annotations needed + --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11 + | +LL | thing.method(42); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | <Thing<bool> as Method<T>>::method(thing, 42); + | +++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11 + | +LL | thing.method(42); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing<bool>: Method<_>` found + --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:7:1 + | +LL | impl<X> Method<i32> for Thing<X> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl<X> Method<u32> for Thing<X> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing<bool> as Method<T>>::method(thing, 42); + | +++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/duplicate-methods.rs b/tests/ui/traits/duplicate-methods.rs new file mode 100644 index 000000000..1f9bdf56f --- /dev/null +++ b/tests/ui/traits/duplicate-methods.rs @@ -0,0 +1,6 @@ +trait Foo { + fn orange(&self); + fn orange(&self); //~ ERROR the name `orange` is defined multiple times +} + +fn main() {} diff --git a/tests/ui/traits/duplicate-methods.stderr b/tests/ui/traits/duplicate-methods.stderr new file mode 100644 index 000000000..6aa88d0df --- /dev/null +++ b/tests/ui/traits/duplicate-methods.stderr @@ -0,0 +1,13 @@ +error[E0428]: the name `orange` is defined multiple times + --> $DIR/duplicate-methods.rs:3:5 + | +LL | fn orange(&self); + | ----------------- previous definition of the value `orange` here +LL | fn orange(&self); + | ^^^^^^^^^^^^^^^^^ `orange` redefined here + | + = note: `orange` must be defined only once in the value namespace of this trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/dyn-trait.rs b/tests/ui/traits/dyn-trait.rs new file mode 100644 index 000000000..e1c1a8de5 --- /dev/null +++ b/tests/ui/traits/dyn-trait.rs @@ -0,0 +1,17 @@ +// run-pass +// ignore-pretty `dyn ::foo` parses differently in the current edition + +use std::fmt::Display; + +static BYTE: u8 = 33; + +fn main() { + let x: &(dyn 'static + Display) = &BYTE; + let y: Box<dyn Display + 'static> = Box::new(BYTE); + let _: &dyn (Display) = &BYTE; + let _: &dyn (::std::fmt::Display) = &BYTE; + let xstr = format!("{}", x); + let ystr = format!("{}", y); + assert_eq!(xstr, "33"); + assert_eq!(ystr, "33"); +} diff --git a/tests/ui/traits/early-vtbl-resolution.rs b/tests/ui/traits/early-vtbl-resolution.rs new file mode 100644 index 000000000..f4b69c140 --- /dev/null +++ b/tests/ui/traits/early-vtbl-resolution.rs @@ -0,0 +1,19 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait thing<A> { + fn foo(&self) -> Option<A>; +} +impl<A> thing<A> for isize { + fn foo(&self) -> Option<A> { None } +} +fn foo_func<A, B: thing<A>>(x: B) -> Option<A> { x.foo() } + +struct A { a: isize } + +pub fn main() { + let _x: Option<f64> = foo_func(0); +} diff --git a/tests/ui/traits/elaborate-type-region.rs b/tests/ui/traits/elaborate-type-region.rs new file mode 100644 index 000000000..03aef0184 --- /dev/null +++ b/tests/ui/traits/elaborate-type-region.rs @@ -0,0 +1,49 @@ +// run-pass +#![allow(dead_code)] + +// Test that we elaborate `Type: 'region` constraints and infer various important things. + +trait Master<'a, T: ?Sized> { + fn foo() where T: 'a; +} + +// [U]: 'a => U: 'a +impl<'a, U> Master<'a, [U]> for () { + fn foo() where U: 'a { } +} + +// &'b U: 'a => 'b: 'a, U: 'a +impl<'a, 'b, U> Master<'a, &'b U> for () { + fn foo() where 'b: 'a, U: 'a { } +} + +// &'b [U]: 'a => 'b: 'a, U: 'a +impl<'a, 'b, U> Master<'a, &'b [U]> for () { + fn foo() where 'b: 'a, U: 'a { } +} + +// Foo<'b>: 'a => 'b: 'a +struct Foo<'a> { x: &'a () } +impl<'a, 'b> Master<'a, Foo<'b>> for () { + fn foo() where 'b: 'a { } +} + +// Bar<'b, T>: 'a => 'b: 'a, T: 'a +struct Bar<'a, T: 'a> { x: &'a T } +impl<'a, 'b, T> Master<'a, Bar<'b, T>> for () { + fn foo() where 'b: 'a, T: 'a { } +} + +// fn(T): 'a => T: 'a +impl<'a, T> Master<'a, fn(T)> for () { + fn foo() where T: 'a { } +} + +// fn() -> T: 'a => T: 'a +impl<'a, T> Master<'a, fn() -> T> for () { + fn foo() where T: 'a { } +} + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs b/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs new file mode 100644 index 000000000..3413db6a6 --- /dev/null +++ b/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs @@ -0,0 +1,16 @@ +// run-pass +// Test that we do not error out because of a (False) ambiguity +// between the builtin rules for Sized and the where clause. Issue +// #20959. + +// pretty-expanded FIXME #23616 + +fn foo<K>(x: Option<K>) + where Option<K> : Sized +{ + let _y = x; +} + +fn main() { + foo(Some(22)); +} diff --git a/tests/ui/traits/fmt-pointer-trait.rs b/tests/ui/traits/fmt-pointer-trait.rs new file mode 100644 index 000000000..b7876b9bd --- /dev/null +++ b/tests/ui/traits/fmt-pointer-trait.rs @@ -0,0 +1,24 @@ +// run-pass +use std::ptr; +use std::rc::Rc; +use std::sync::Arc; + +fn main() { + let p: *const u8 = ptr::null(); + let rc = Rc::new(1usize); + let arc = Arc::new(1usize); + let b = Box::new("hi"); + + let _ = format!("{:p}{:p}{:p}", + rc, arc, b); + + if cfg!(target_pointer_width = "32") { + assert_eq!(format!("{:#p}", p), + "0x00000000"); + } else { + assert_eq!(format!("{:#p}", p), + "0x0000000000000000"); + } + assert_eq!(format!("{:p}", p), + "0x0"); +} diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.rs b/tests/ui/traits/fn-trait-cast-diagnostic.rs new file mode 100644 index 000000000..e20aa210e --- /dev/null +++ b/tests/ui/traits/fn-trait-cast-diagnostic.rs @@ -0,0 +1,26 @@ +// There are two different instances to check that even if +// the trait is implemented for the output of a function, +// it will still be displayed if the function itself implements a trait. +trait Foo {} + +impl Foo for fn() -> bool {} +impl Foo for bool {} + +fn example() -> bool { + true +} + +trait NoOtherFoo {} + +impl NoOtherFoo for fn() -> bool {} + +fn do_on_foo(v: impl Foo) {} +fn do_on_single_foo(v: impl NoOtherFoo) {} + +fn main() { + do_on_foo(example); + //~^ ERROR the trait bound + + do_on_single_foo(example); + //~^ ERROR the trait bound +} diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.stderr b/tests/ui/traits/fn-trait-cast-diagnostic.stderr new file mode 100644 index 000000000..6851dcdd5 --- /dev/null +++ b/tests/ui/traits/fn-trait-cast-diagnostic.stderr @@ -0,0 +1,43 @@ +error[E0277]: the trait bound `fn() -> bool {example}: Foo` is not satisfied + --> $DIR/fn-trait-cast-diagnostic.rs:21:15 + | +LL | do_on_foo(example); + | --------- ^^^^^^^ the trait `Foo` is not implemented for fn item `fn() -> bool {example}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_on_foo` + --> $DIR/fn-trait-cast-diagnostic.rs:17:22 + | +LL | fn do_on_foo(v: impl Foo) {} + | ^^^ required by this bound in `do_on_foo` +help: use parentheses to call this function + | +LL | do_on_foo(example()); + | ++ +help: the trait `Foo` is implemented for fn pointer `fn() -> bool`, try casting using `as` + | +LL | do_on_foo(example as fn() -> bool); + | +++++++++++++++ + +error[E0277]: the trait bound `fn() -> bool {example}: NoOtherFoo` is not satisfied + --> $DIR/fn-trait-cast-diagnostic.rs:24:22 + | +LL | do_on_single_foo(example); + | ---------------- ^^^^^^^ the trait `NoOtherFoo` is not implemented for fn item `fn() -> bool {example}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_on_single_foo` + --> $DIR/fn-trait-cast-diagnostic.rs:18:29 + | +LL | fn do_on_single_foo(v: impl NoOtherFoo) {} + | ^^^^^^^^^^ required by this bound in `do_on_single_foo` +help: the trait `NoOtherFoo` is implemented for fn pointer `fn() -> bool`, try casting using `as` + | +LL | do_on_single_foo(example as fn() -> bool); + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/generic.rs b/tests/ui/traits/generic.rs new file mode 100644 index 000000000..80efe1c93 --- /dev/null +++ b/tests/ui/traits/generic.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(non_camel_case_types)] + + + +trait to_str { + fn to_string_(&self) -> String; +} +impl to_str for isize { + fn to_string_(&self) -> String { self.to_string() } +} +impl to_str for String { + fn to_string_(&self) -> String { self.clone() } +} +impl to_str for () { + fn to_string_(&self) -> String { "()".to_string() } +} + +trait map<T> { + fn map<U, F>(&self, f: F) -> Vec<U> where F: FnMut(&T) -> U; +} +impl<T> map<T> for Vec<T> { + fn map<U, F>(&self, mut f: F) -> Vec<U> where F: FnMut(&T) -> U { + let mut r = Vec::new(); + for i in self { + r.push(f(i)); + } + r + } +} + +fn foo<U, T: map<U>>(x: T) -> Vec<String> { + x.map(|_e| "hi".to_string() ) +} +fn bar<U:to_str,T:map<U>>(x: T) -> Vec<String> { + x.map(|_e| _e.to_string_() ) +} + +pub fn main() { + assert_eq!(foo(vec![1]), ["hi".to_string()]); + assert_eq!(bar::<isize, Vec<isize> >(vec![4, 5]), ["4".to_string(), "5".to_string()]); + assert_eq!(bar::<String, Vec<String> >(vec!["x".to_string(), "y".to_string()]), + ["x".to_string(), "y".to_string()]); + assert_eq!(bar::<(), Vec<()>>(vec![()]), ["()".to_string()]); +} diff --git a/tests/ui/traits/ignore-err-impls.rs b/tests/ui/traits/ignore-err-impls.rs new file mode 100644 index 000000000..67e880b00 --- /dev/null +++ b/tests/ui/traits/ignore-err-impls.rs @@ -0,0 +1,9 @@ +pub struct S; + +trait Generic<T> {} + +impl<'a, T> Generic<&'a T> for S {} +impl Generic<Type> for S {} +//~^ ERROR cannot find type `Type` in this scope + +fn main() {} diff --git a/tests/ui/traits/ignore-err-impls.stderr b/tests/ui/traits/ignore-err-impls.stderr new file mode 100644 index 000000000..45bd533b5 --- /dev/null +++ b/tests/ui/traits/ignore-err-impls.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Type` in this scope + --> $DIR/ignore-err-impls.rs:6:14 + | +LL | impl Generic<Type> for S {} + | ^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl<Type> Generic<Type> for S {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/impl-1.rs b/tests/ui/traits/impl-1.rs new file mode 100644 index 000000000..d22ac72d1 --- /dev/null +++ b/tests/ui/traits/impl-1.rs @@ -0,0 +1,16 @@ +// Test calling methods on an impl for a bare trait. This test checks that the +// trait impl is only applied to a trait object, not concrete types which implement +// the trait. + +trait T {} + +impl<'a> dyn T + 'a { + fn foo(&self) {} +} + +impl T for i32 {} + +fn main() { + let x = &42i32; + x.foo(); //~ERROR: no method named `foo` found +} diff --git a/tests/ui/traits/impl-1.stderr b/tests/ui/traits/impl-1.stderr new file mode 100644 index 000000000..7694e3f5c --- /dev/null +++ b/tests/ui/traits/impl-1.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `foo` found for reference `&i32` in the current scope + --> $DIR/impl-1.rs:15:7 + | +LL | x.foo(); + | ^^^ method not found in `&i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/impl-2.rs b/tests/ui/traits/impl-2.rs new file mode 100644 index 000000000..804ffec12 --- /dev/null +++ b/tests/ui/traits/impl-2.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +// pretty-expanded FIXME #23616 + +pub mod Foo { + pub trait Trait { + fn foo(&self); + } +} + +mod Bar { + impl<'a> dyn (::Foo::Trait) + 'a { + fn bar(&self) { self.foo() } + } +} + +fn main() {} diff --git a/tests/ui/traits/impl-bounds-checking.rs b/tests/ui/traits/impl-bounds-checking.rs new file mode 100644 index 000000000..5e65a27bf --- /dev/null +++ b/tests/ui/traits/impl-bounds-checking.rs @@ -0,0 +1,14 @@ +pub trait Clone2 { + fn clone(&self) -> Self; +} + + +trait Getter<T: Clone2> { + fn get(&self) -> T; +} + +impl Getter<isize> for isize { //~ ERROR `isize: Clone2` is not satisfied + fn get(&self) -> isize { *self } +} + +fn main() { } diff --git a/tests/ui/traits/impl-bounds-checking.stderr b/tests/ui/traits/impl-bounds-checking.stderr new file mode 100644 index 000000000..1f969efe1 --- /dev/null +++ b/tests/ui/traits/impl-bounds-checking.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `isize: Clone2` is not satisfied + --> $DIR/impl-bounds-checking.rs:10:24 + | +LL | impl Getter<isize> for isize { + | ^^^^^ the trait `Clone2` is not implemented for `isize` + | +note: required by a bound in `Getter` + --> $DIR/impl-bounds-checking.rs:6:17 + | +LL | trait Getter<T: Clone2> { + | ^^^^^^ required by this bound in `Getter` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/impl-can-not-have-untraitful-items.rs b/tests/ui/traits/impl-can-not-have-untraitful-items.rs new file mode 100644 index 000000000..0c885447b --- /dev/null +++ b/tests/ui/traits/impl-can-not-have-untraitful-items.rs @@ -0,0 +1,9 @@ +trait A { } + +impl A for isize { + const BAR: () = (); //~ ERROR const `BAR` is not a member of trait `A` + type Baz = (); //~ ERROR type `Baz` is not a member of trait `A` + fn foo(&self) { } //~ ERROR method `foo` is not a member of trait `A` +} + +fn main() { } diff --git a/tests/ui/traits/impl-can-not-have-untraitful-items.stderr b/tests/ui/traits/impl-can-not-have-untraitful-items.stderr new file mode 100644 index 000000000..7f56f34ea --- /dev/null +++ b/tests/ui/traits/impl-can-not-have-untraitful-items.stderr @@ -0,0 +1,22 @@ +error[E0438]: const `BAR` is not a member of trait `A` + --> $DIR/impl-can-not-have-untraitful-items.rs:4:5 + | +LL | const BAR: () = (); + | ^^^^^^^^^^^^^^^^^^^ not a member of trait `A` + +error[E0437]: type `Baz` is not a member of trait `A` + --> $DIR/impl-can-not-have-untraitful-items.rs:5:5 + | +LL | type Baz = (); + | ^^^^^^^^^^^^^^ not a member of trait `A` + +error[E0407]: method `foo` is not a member of trait `A` + --> $DIR/impl-can-not-have-untraitful-items.rs:6:5 + | +LL | fn foo(&self) { } + | ^^^^^^^^^^^^^^^^^ not a member of trait `A` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0407, E0437, E0438. +For more information about an error, try `rustc --explain E0407`. diff --git a/tests/ui/traits/impl-different-num-params.rs b/tests/ui/traits/impl-different-num-params.rs new file mode 100644 index 000000000..53400622d --- /dev/null +++ b/tests/ui/traits/impl-different-num-params.rs @@ -0,0 +1,12 @@ +trait Foo { + fn bar(&self, x: usize) -> Self; +} +impl Foo for isize { + fn bar(&self) -> isize { + //~^ ERROR method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2 + *self + } +} + +fn main() { +} diff --git a/tests/ui/traits/impl-different-num-params.stderr b/tests/ui/traits/impl-different-num-params.stderr new file mode 100644 index 000000000..910ba3510 --- /dev/null +++ b/tests/ui/traits/impl-different-num-params.stderr @@ -0,0 +1,12 @@ +error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2 + --> $DIR/impl-different-num-params.rs:5:12 + | +LL | fn bar(&self, x: usize) -> Self; + | --------------- trait requires 2 parameters +... +LL | fn bar(&self) -> isize { + | ^^^^^ expected 2 parameters, found 1 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0050`. diff --git a/tests/ui/traits/impl-evaluation-order.rs b/tests/ui/traits/impl-evaluation-order.rs new file mode 100644 index 000000000..57809d89a --- /dev/null +++ b/tests/ui/traits/impl-evaluation-order.rs @@ -0,0 +1,39 @@ +// Regression test for #79902 + +// Check that evaluation (which is used to determine whether to copy a type in +// MIR building) evaluates bounds from normalizing an impl after evaluating +// any bounds on the impl. + +// check-pass + +trait A { + type B; +} +trait M {} + +struct G<T, U>(*const T, *const U); + +impl<T, U> Clone for G<T, U> { + fn clone(&self) -> Self { + G { ..*self } + } +} + +impl<T, U> Copy for G<T, U::B> +where + T: A<B = U>, + U: A, +{ +} + +impl A for () { + type B = (); +} + +fn is_m<T: M>(_: T) {} + +fn main() { + let x = G(&(), &()); + drop(x); + drop(x); +} diff --git a/tests/ui/traits/impl-for-module.rs b/tests/ui/traits/impl-for-module.rs new file mode 100644 index 000000000..9004627c5 --- /dev/null +++ b/tests/ui/traits/impl-for-module.rs @@ -0,0 +1,11 @@ +mod a { +} + +trait A { +} + +impl A for a { //~ ERROR expected type, found module +} + +fn main() { +} diff --git a/tests/ui/traits/impl-for-module.stderr b/tests/ui/traits/impl-for-module.stderr new file mode 100644 index 000000000..6ec4083b5 --- /dev/null +++ b/tests/ui/traits/impl-for-module.stderr @@ -0,0 +1,12 @@ +error[E0573]: expected type, found module `a` + --> $DIR/impl-for-module.rs:7:12 + | +LL | trait A { + | ------- similarly named trait `A` defined here +... +LL | impl A for a { + | ^ help: a trait with a similar name exists: `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/traits/impl-implicit-trait.rs b/tests/ui/traits/impl-implicit-trait.rs new file mode 100644 index 000000000..fac2bcce2 --- /dev/null +++ b/tests/ui/traits/impl-implicit-trait.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum option_<T> { + none_, + some_(T), +} + +impl<T> option_<T> { + pub fn foo(&self) -> bool { true } +} + +enum option__ { + none__, + some__(isize) +} + +impl option__ { + pub fn foo(&self) -> bool { true } +} + +pub fn main() { +} diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.rs b/tests/ui/traits/impl-inherent-prefer-over-trait.rs new file mode 100644 index 000000000..827607888 --- /dev/null +++ b/tests/ui/traits/impl-inherent-prefer-over-trait.rs @@ -0,0 +1,30 @@ +// run-pass + +struct Foo; + +trait Trait { + fn bar(&self); +} + +// Inherent impls should be preferred over trait ones. +impl Foo { + fn bar(&self) {} +} + +impl dyn Trait { + fn baz(_: &Foo) {} +} + +impl Trait for Foo { + fn bar(&self) { panic!("wrong method called!") } +} + +fn main() { + Foo.bar(); + Foo::bar(&Foo); + <Foo>::bar(&Foo); + + // Should work even if Trait::baz doesn't exist. + // N.B: `<Trait>::bar` would be ambiguous. + <dyn Trait>::baz(&Foo); +} diff --git a/tests/ui/traits/impl-method-mismatch.rs b/tests/ui/traits/impl-method-mismatch.rs new file mode 100644 index 000000000..62580755c --- /dev/null +++ b/tests/ui/traits/impl-method-mismatch.rs @@ -0,0 +1,13 @@ +trait Mumbo { + fn jumbo(&self, x: &usize) -> usize; +} + +impl Mumbo for usize { + // Cannot have a larger effect than the trait: + unsafe fn jumbo(&self, x: &usize) { *self + *x; } + //~^ ERROR method `jumbo` has an incompatible type for trait + //~| expected signature `fn + //~| found signature `unsafe fn +} + +fn main() {} diff --git a/tests/ui/traits/impl-method-mismatch.stderr b/tests/ui/traits/impl-method-mismatch.stderr new file mode 100644 index 000000000..252b5aff9 --- /dev/null +++ b/tests/ui/traits/impl-method-mismatch.stderr @@ -0,0 +1,17 @@ +error[E0053]: method `jumbo` has an incompatible type for trait + --> $DIR/impl-method-mismatch.rs:7:5 + | +LL | unsafe fn jumbo(&self, x: &usize) { *self + *x; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn + | +note: type in trait + --> $DIR/impl-method-mismatch.rs:2:5 + | +LL | fn jumbo(&self, x: &usize) -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn(&usize, &usize) -> usize` + found signature `unsafe fn(&usize, &usize)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.rs b/tests/ui/traits/impl-object-overlap-issue-23853.rs new file mode 100644 index 000000000..e490967b6 --- /dev/null +++ b/tests/ui/traits/impl-object-overlap-issue-23853.rs @@ -0,0 +1,18 @@ +// run-pass +// Test that we are able to compile the case where both a blanket impl +// and the object type itself supply the required trait obligation. +// In this case, the blanket impl for `Foo` applies to any type, +// including `Bar`, but the object type `Bar` also implicitly supplies +// this context. + +trait Foo { fn dummy(&self) { } } + +trait Bar: Foo { } + +impl<T:?Sized> Foo for T { } + +fn want_foo<B:?Sized+Foo>() { } + +fn main() { + want_foo::<dyn Bar>(); +} diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs new file mode 100644 index 000000000..05b9db972 --- /dev/null +++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs @@ -0,0 +1,31 @@ +// Check that when we test the supertrait we ensure consistent use of +// lifetime parameters. In this case, implementing T2<'a,'b> requires +// an impl of T1<'a>, but we have an impl of T1<'b>. + +trait T1<'x> { + fn x(&self) -> &'x isize; +} + +trait T2<'x, 'y> : T1<'x> { + fn y(&self) -> &'y isize; +} + +struct S<'a, 'b> { + a: &'a isize, + b: &'b isize +} + +impl<'a,'b> T1<'b> for S<'a, 'b> { + fn x(&self) -> &'b isize { + self.b + } +} + +impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { //~ ERROR cannot infer an appropriate lifetime + fn y(&self) -> &'b isize { + self.b + } +} + +pub fn main() { +} diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr new file mode 100644 index 000000000..1bace8ab2 --- /dev/null +++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -0,0 +1,27 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28 + | +LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { + | ^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6 + | +LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { + | ^^ +note: ...but the lifetime must also be valid for the lifetime `'b` as defined here... + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:9 + | +LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { + | ^^ +note: ...so that the types are compatible + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28 + | +LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { + | ^^^^^^^^^ + = note: expected `T1<'a>` + found `T1<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/traits/impl.rs b/tests/ui/traits/impl.rs new file mode 100644 index 000000000..f512d91eb --- /dev/null +++ b/tests/ui/traits/impl.rs @@ -0,0 +1,41 @@ +// run-pass +// Test calling methods on an impl for a bare trait. + +// aux-build:traitimpl.rs + +extern crate traitimpl; +use traitimpl::Bar; + +static mut COUNT: usize = 1; + +trait T { + fn t(&self) {} +} + +impl<'a> dyn T+'a { + fn foo(&self) { + unsafe { COUNT *= 2; } + } + fn bar() { + unsafe { COUNT *= 3; } + } +} + +impl T for isize {} + +struct Foo; +impl<'a> Bar<'a> for Foo {} + +fn main() { + let x: &dyn T = &42; + + x.foo(); + <dyn T>::foo(x); + <dyn T>::bar(); + + unsafe { assert_eq!(COUNT, 12); } + + // Cross-crait case + let x: &dyn Bar = &Foo; + x.bar(); +} diff --git a/tests/ui/traits/impl_trait_as_trait_return_position.rs b/tests/ui/traits/impl_trait_as_trait_return_position.rs new file mode 100644 index 000000000..c3325fd80 --- /dev/null +++ b/tests/ui/traits/impl_trait_as_trait_return_position.rs @@ -0,0 +1,17 @@ +// check-pass + +trait A { + type Foo; +} + +impl<T> A for T { + type Foo = (); +} + +fn foo() -> impl std::borrow::Borrow<<u8 as A>::Foo> { + () +} + +fn main() { + foo(); +} diff --git a/tests/ui/traits/inductive-overflow/lifetime.rs b/tests/ui/traits/inductive-overflow/lifetime.rs new file mode 100644 index 000000000..bf536d21c --- /dev/null +++ b/tests/ui/traits/inductive-overflow/lifetime.rs @@ -0,0 +1,33 @@ +// Test that we don't hit the recursion limit for short cycles involving lifetimes. + +// Shouldn't hit this, we should realize that we're in a cycle sooner. +#![recursion_limit="20"] + +trait NotAuto {} +trait Y { + type P; +} + +impl<'a> Y for C<'a> { + type P = Box<X<C<'a>>>; +} + +struct C<'a>(&'a ()); +struct X<T: Y>(T::P); + +impl<T: NotAuto> NotAuto for Box<T> {} //~ NOTE: required +//~^ NOTE unsatisfied trait bound introduced here +impl<T: Y> NotAuto for X<T> where T::P: NotAuto {} +impl<'a> NotAuto for C<'a> {} + +fn is_send<S: NotAuto>() {} +//~^ NOTE: required +//~| NOTE: required + +fn main() { + // Should only be a few notes. + is_send::<X<C<'static>>>(); + //~^ ERROR overflow evaluating + //~| 3 redundant requirements hidden + //~| required for +} diff --git a/tests/ui/traits/inductive-overflow/lifetime.stderr b/tests/ui/traits/inductive-overflow/lifetime.stderr new file mode 100644 index 000000000..357e59991 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/lifetime.stderr @@ -0,0 +1,24 @@ +error[E0275]: overflow evaluating the requirement `X<C<'_>>: NotAuto` + --> $DIR/lifetime.rs:29:5 + | +LL | is_send::<X<C<'static>>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required for `Box<X<C<'_>>>` to implement `NotAuto` + --> $DIR/lifetime.rs:18:18 + | +LL | impl<T: NotAuto> NotAuto for Box<T> {} + | ------- ^^^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 3 redundant requirements hidden + = note: required for `X<C<'static>>` to implement `NotAuto` +note: required by a bound in `is_send` + --> $DIR/lifetime.rs:23:15 + | +LL | fn is_send<S: NotAuto>() {} + | ^^^^^^^ required by this bound in `is_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/inductive-overflow/simultaneous.rs b/tests/ui/traits/inductive-overflow/simultaneous.rs new file mode 100644 index 000000000..40ac92146 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/simultaneous.rs @@ -0,0 +1,20 @@ +// Regression test for #33344, initial version. This example allowed +// arbitrary trait bounds to be synthesized. + +trait Tweedledum: IntoIterator {} +trait Tweedledee: IntoIterator {} + +impl<T: Tweedledum> Tweedledee for T {} +impl<T: Tweedledee> Tweedledum for T {} + +trait Combo: IntoIterator {} +impl<T: Tweedledee + Tweedledum> Combo for T {} + +fn is_ee<T: Combo>(t: T) { + t.into_iter(); +} + +fn main() { + is_ee(4); + //~^ ERROR overflow evaluating the requirement `{integer}: Tweedle +} diff --git a/tests/ui/traits/inductive-overflow/simultaneous.stderr b/tests/ui/traits/inductive-overflow/simultaneous.stderr new file mode 100644 index 000000000..e3b4ec07d --- /dev/null +++ b/tests/ui/traits/inductive-overflow/simultaneous.stderr @@ -0,0 +1,22 @@ +error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum` + --> $DIR/simultaneous.rs:18:5 + | +LL | is_ee(4); + | ^^^^^ + | +note: required for `{integer}` to implement `Combo` + --> $DIR/simultaneous.rs:11:34 + | +LL | impl<T: Tweedledee + Tweedledum> Combo for T {} + | ---------- ^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `is_ee` + --> $DIR/simultaneous.rs:13:13 + | +LL | fn is_ee<T: Combo>(t: T) { + | ^^^^^ required by this bound in `is_ee` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs new file mode 100644 index 000000000..5fea47a1b --- /dev/null +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs @@ -0,0 +1,18 @@ +// Auto-trait-based version of #29859, supertrait version. Test that using +// a simple auto trait `..` impl alone still doesn't allow arbitrary bounds +// to be synthesized. + +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait Magic: Copy {} //~ ERROR E0568 + +fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); //~ ERROR + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr new file mode 100644 index 000000000..3ec288d13 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -0,0 +1,35 @@ +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/supertrait-auto-trait.rs:8:17 + | +LL | auto trait Magic: Copy {} + | -----^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error[E0277]: the trait bound `NoClone: Copy` is not satisfied + --> $DIR/supertrait-auto-trait.rs:16:23 + | +LL | let (a, b) = copy(NoClone); + | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone` + | | + | required by a bound introduced by this call + | +note: required for `NoClone` to implement `Magic` + --> $DIR/supertrait-auto-trait.rs:8:12 + | +LL | auto trait Magic: Copy {} + | ^^^^^ +note: required by a bound in `copy` + --> $DIR/supertrait-auto-trait.rs:10:12 + | +LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } + | ^^^^^ required by this bound in `copy` +help: consider annotating `NoClone` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0568. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/inductive-overflow/supertrait.rs b/tests/ui/traits/inductive-overflow/supertrait.rs new file mode 100644 index 000000000..c7aa4d90f --- /dev/null +++ b/tests/ui/traits/inductive-overflow/supertrait.rs @@ -0,0 +1,15 @@ +// Regression test for #29859, supertrait version. This example +// allowed arbitrary trait bounds to be synthesized. + +trait Magic: Copy {} +impl<T: Magic> Magic for T {} + +fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); //~ ERROR E0275 + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/traits/inductive-overflow/supertrait.stderr b/tests/ui/traits/inductive-overflow/supertrait.stderr new file mode 100644 index 000000000..b537ecf17 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/supertrait.stderr @@ -0,0 +1,22 @@ +error[E0275]: overflow evaluating the requirement `NoClone: Magic` + --> $DIR/supertrait.rs:13:18 + | +LL | let (a, b) = copy(NoClone); + | ^^^^ + | +note: required for `NoClone` to implement `Magic` + --> $DIR/supertrait.rs:5:16 + | +LL | impl<T: Magic> Magic for T {} + | ----- ^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `copy` + --> $DIR/supertrait.rs:7:12 + | +LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } + | ^^^^^ required by this bound in `copy` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/inductive-overflow/two-traits.rs b/tests/ui/traits/inductive-overflow/two-traits.rs new file mode 100644 index 000000000..463b55d85 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/two-traits.rs @@ -0,0 +1,22 @@ +// Regression test for #29859, initial version. This example allowed +// arbitrary trait bounds to be synthesized. + +// Trait that you want all types to implement. +use std::marker::{Sync as Trait}; + +pub trait Magic { + type X: Trait; +} +impl<T: Magic> Magic for T { + type X = Self; + //~^ ERROR E0277 +} + +fn check<T: Trait>() {} + +fn wizard<T: Magic>() { check::<<T as Magic>::X>(); } + +fn main() { + wizard::<*mut ()>(); //~ ERROR E0275 + // check::<*mut ()>(); +} diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr new file mode 100644 index 000000000..0d0bf8861 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/two-traits.stderr @@ -0,0 +1,32 @@ +error[E0277]: `T` cannot be shared between threads safely + --> $DIR/two-traits.rs:11:14 + | +LL | type X = Self; + | ^^^^ `T` cannot be shared between threads safely + | +note: required by a bound in `Magic::X` + --> $DIR/two-traits.rs:8:13 + | +LL | type X: Trait; + | ^^^^^ required by this bound in `Magic::X` +help: consider further restricting this bound + | +LL | impl<T: Magic + std::marker::Sync> Magic for T { + | +++++++++++++++++++ + +error[E0275]: overflow evaluating the requirement `*mut (): Magic` + --> $DIR/two-traits.rs:20:5 + | +LL | wizard::<*mut ()>(); + | ^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `wizard` + --> $DIR/two-traits.rs:17:14 + | +LL | fn wizard<T: Magic>() { check::<<T as Magic>::X>(); } + | ^^^^^ required by this bound in `wizard` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0275, E0277. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/infer-from-object-issue-26952.rs b/tests/ui/traits/infer-from-object-issue-26952.rs new file mode 100644 index 000000000..ed258dbb2 --- /dev/null +++ b/tests/ui/traits/infer-from-object-issue-26952.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that when we match a trait reference like `Foo<A>: Foo<_#0t>`, +// we unify with `_#0t` with `A`. In this code, if we failed to do +// that, then you get an unconstrained type-variable in `call`. +// +// Also serves as a regression test for issue #26952, though the test +// was derived from another reported regression with the same cause. + +use std::marker::PhantomData; + +trait Trait<A> { fn foo(&self); } + +struct Type<A> { a: PhantomData<A> } + +fn as_trait<A>(t: &Type<A>) -> &dyn Trait<A> { loop { } } + +fn want<A,T:Trait<A>+?Sized>(t: &T) { } + +fn call<A>(p: Type<A>) { + let q = as_trait(&p); + want(q); // parameter A to `want` *would* be unconstrained +} + +fn main() { } diff --git a/tests/ui/traits/inherent-method-order.rs b/tests/ui/traits/inherent-method-order.rs new file mode 100644 index 000000000..f632ae8a9 --- /dev/null +++ b/tests/ui/traits/inherent-method-order.rs @@ -0,0 +1,25 @@ +// run-pass + +struct Foo; + +impl Foo { + #[allow(dead_code)] + fn foo(self) { + panic!("wrong method!") + } +} + +trait Trait { + fn foo(self); +} + +impl<'a,'b,'c> Trait for &'a &'b &'c Foo { + fn foo(self) { + // ok + } +} + +fn main() { + let x = &(&(&Foo)); + x.foo(); +} diff --git a/tests/ui/traits/inheritance/auto-xc-2.rs b/tests/ui/traits/inheritance/auto-xc-2.rs new file mode 100644 index 000000000..f2130228d --- /dev/null +++ b/tests/ui/traits/inheritance/auto-xc-2.rs @@ -0,0 +1,23 @@ +// run-pass +// aux-build:auto_xc_2.rs + + +extern crate auto_xc_2 as aux; + +// aux defines impls of Foo, Bar and Baz for A +use aux::{Foo, Bar, Baz, A}; + +// We want to extend all Foo, Bar, Bazes to Quuxes +pub trait Quux: Foo + Bar + Baz { } +impl<T:Foo + Bar + Baz> Quux for T { } + +fn f<T:Quux>(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auto-xc.rs b/tests/ui/traits/inheritance/auto-xc.rs new file mode 100644 index 000000000..3d5ae182a --- /dev/null +++ b/tests/ui/traits/inheritance/auto-xc.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// aux-build:auto_xc.rs + + +extern crate auto_xc as aux; + +use aux::{Foo, Bar, Baz, Quux}; + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +fn f<T:Quux>(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auto.rs b/tests/ui/traits/inheritance/auto.rs new file mode 100644 index 000000000..0be67a55e --- /dev/null +++ b/tests/ui/traits/inheritance/auto.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +// Testing that this impl turns A into a Quux, because +// A is already a Foo Bar Baz + +impl<T:Foo + Bar + Baz> Quux for T { } + +trait Foo { fn f(&self) -> isize; } +trait Bar { fn g(&self) -> isize; } +trait Baz { fn h(&self) -> isize; } + +trait Quux: Foo + Bar + Baz { } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +fn f<T:Quux>(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auxiliary/auto_xc.rs b/tests/ui/traits/inheritance/auxiliary/auto_xc.rs new file mode 100644 index 000000000..9af26cb2e --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/auto_xc.rs @@ -0,0 +1,7 @@ +pub trait Foo { fn f(&self) -> isize; } +pub trait Bar { fn g(&self) -> isize; } +pub trait Baz { fn h(&self) -> isize; } + +pub trait Quux: Foo + Bar + Baz { } + +impl<T:Foo + Bar + Baz> Quux for T { } diff --git a/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs b/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs new file mode 100644 index 000000000..e9327676d --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs @@ -0,0 +1,9 @@ +pub trait Foo { fn f(&self) -> isize; } +pub trait Bar { fn g(&self) -> isize; } +pub trait Baz { fn h(&self) -> isize; } + +pub struct A { pub x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } diff --git a/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs b/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs new file mode 100644 index 000000000..a25704412 --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs @@ -0,0 +1,38 @@ +use std::cmp::PartialEq; +use std::ops::{Add, Sub, Mul}; + +pub trait MyNum : Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + PartialEq + Clone { +} + +#[derive(Clone, Debug)] +pub struct MyInt { + pub val: isize +} + +impl Add for MyInt { + type Output = MyInt; + + fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl Sub for MyInt { + type Output = MyInt; + + fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) } +} + +impl Mul for MyInt { + type Output = MyInt; + + fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) } +} + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } diff --git a/tests/ui/traits/inheritance/auxiliary/xc_call.rs b/tests/ui/traits/inheritance/auxiliary/xc_call.rs new file mode 100644 index 000000000..b76c52e62 --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/xc_call.rs @@ -0,0 +1,11 @@ +pub trait Foo { + fn f(&self) -> isize; +} + +pub struct A { + pub x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} diff --git a/tests/ui/traits/inheritance/basic.rs b/tests/ui/traits/inheritance/basic.rs new file mode 100644 index 000000000..5bfa60b1a --- /dev/null +++ b/tests/ui/traits/inheritance/basic.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar { fn g(&self) -> isize; } +trait Baz { fn h(&self) -> isize; } + +trait Quux: Foo + Bar + Baz { } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } +impl Quux for A {} + +fn f<T:Quux + Foo + Bar + Baz>(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/call-bound-inherited.rs b/tests/ui/traits/inheritance/call-bound-inherited.rs new file mode 100644 index 000000000..37c2ff63c --- /dev/null +++ b/tests/ui/traits/inheritance/call-bound-inherited.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } + +// Call a function on Foo, given a T: Bar +fn gg<T:Bar>(a: &T) -> isize { + a.f() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(gg(a), 10); +} diff --git a/tests/ui/traits/inheritance/call-bound-inherited2.rs b/tests/ui/traits/inheritance/call-bound-inherited2.rs new file mode 100644 index 000000000..8576d29f2 --- /dev/null +++ b/tests/ui/traits/inheritance/call-bound-inherited2.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } +trait Baz : Bar { fn h(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +// Call a function on Foo, given a T: Baz, +// which is inherited via Bar +fn gg<T:Baz>(a: &T) -> isize { + a.f() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(gg(a), 10); +} diff --git a/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs b/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs new file mode 100644 index 000000000..25159c1ad --- /dev/null +++ b/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] +// Testing that we can cast to a subtrait and call subtrait +// methods. Not testing supertrait methods + + +trait Foo { + fn f(&self) -> isize; +} + +trait Bar : Foo { + fn g(&self) -> isize; +} + +struct A { + x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} + +impl Bar for A { + fn g(&self) -> isize { 20 } +} + +pub fn main() { + let a = &A { x: 3 }; + let afoo = a as &dyn Foo; + let abar = a as &dyn Bar; + assert_eq!(afoo.f(), 10); + assert_eq!(abar.g(), 20); +} diff --git a/tests/ui/traits/inheritance/cast.rs b/tests/ui/traits/inheritance/cast.rs new file mode 100644 index 000000000..9070b9d1f --- /dev/null +++ b/tests/ui/traits/inheritance/cast.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] +// Testing that supertrait methods can be called on subtrait object types + + +trait Foo { + fn f(&self) -> isize; +} + +trait Bar : Foo { + fn g(&self) -> isize; +} + +struct A { + x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} + +impl Bar for A { + fn g(&self) -> isize { 20 } +} + +pub fn main() { + let a = &A { x: 3 }; + let afoo = a as &dyn Foo; + let abar = a as &dyn Bar; + assert_eq!(afoo.f(), 10); + assert_eq!(abar.g(), 20); + assert_eq!(abar.f(), 10); +} diff --git a/tests/ui/traits/inheritance/cross-trait-call-xc.rs b/tests/ui/traits/inheritance/cross-trait-call-xc.rs new file mode 100644 index 000000000..99fbb5c61 --- /dev/null +++ b/tests/ui/traits/inheritance/cross-trait-call-xc.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:xc_call.rs + + +extern crate xc_call as aux; + +use aux::Foo; + +trait Bar : Foo { + fn g(&self) -> isize; +} + +impl Bar for aux::A { + fn g(&self) -> isize { self.f() } +} + +pub fn main() { + let a = &aux::A { x: 3 }; + assert_eq!(a.g(), 10); +} diff --git a/tests/ui/traits/inheritance/cross-trait-call.rs b/tests/ui/traits/inheritance/cross-trait-call.rs new file mode 100644 index 000000000..512c928ca --- /dev/null +++ b/tests/ui/traits/inheritance/cross-trait-call.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } + +impl Bar for A { + // Testing that this impl can call the impl of Foo + fn g(&self) -> isize { self.f() } +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(a.g(), 10); +} diff --git a/tests/ui/traits/inheritance/diamond.rs b/tests/ui/traits/inheritance/diamond.rs new file mode 100644 index 000000000..32ad0fb4d --- /dev/null +++ b/tests/ui/traits/inheritance/diamond.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +// B and C both require A, so D does as well, twice, but that's just fine + + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } +trait D: B + C { fn d(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } +impl D for S { fn d(&self) -> isize { 40 } } + +fn f<T:D>(x: &T) { + assert_eq!(x.a(), 10); + assert_eq!(x.b(), 20); + assert_eq!(x.c(), 30); + assert_eq!(x.d(), 40); +} + +pub fn main() { + let value = &S { bogus: () }; + f(value); +} diff --git a/tests/ui/traits/inheritance/multiple-inheritors.rs b/tests/ui/traits/inheritance/multiple-inheritors.rs new file mode 100644 index 000000000..77ecbd8eb --- /dev/null +++ b/tests/ui/traits/inheritance/multiple-inheritors.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } + +// Both B and C inherit from A +fn f<T:B + C>(x: &T) { + assert_eq!(x.a(), 10); + assert_eq!(x.b(), 20); + assert_eq!(x.c(), 30); +} + +pub fn main() { + f(&S { bogus: () }) +} diff --git a/tests/ui/traits/inheritance/multiple-params.rs b/tests/ui/traits/inheritance/multiple-params.rs new file mode 100644 index 000000000..8ff5ba541 --- /dev/null +++ b/tests/ui/traits/inheritance/multiple-params.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } + +// Multiple type params, multiple levels of inheritance +fn f<X:A,Y:B,Z:C>(x: &X, y: &Y, z: &Z) { + assert_eq!(x.a(), 10); + assert_eq!(y.a(), 10); + assert_eq!(y.b(), 20); + assert_eq!(z.a(), 10); + assert_eq!(z.c(), 30); +} + +pub fn main() { + let s = &S { bogus: () }; + f(s, s, s); +} diff --git a/tests/ui/traits/inheritance/num.rs b/tests/ui/traits/inheritance/num.rs new file mode 100644 index 000000000..3d63d78ca --- /dev/null +++ b/tests/ui/traits/inheritance/num.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +pub trait NumExt: PartialEq + PartialOrd {} + +pub trait FloatExt: NumExt {} + +fn greater_than_one<T: NumExt>(n: &T) -> bool { loop {} } +fn greater_than_one_float<T: FloatExt>(n: &T) -> bool { loop {} } + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num0.rs b/tests/ui/traits/inheritance/num0.rs new file mode 100644 index 000000000..cee52542d --- /dev/null +++ b/tests/ui/traits/inheritance/num0.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +// Extending Num and using inherited static methods + +// pretty-expanded FIXME #23616 + +use std::cmp::PartialOrd; + +pub trait NumCast: Sized { + fn from(i: i32) -> Option<Self>; +} + +pub trait Num { + fn from_int(i: isize) -> Self; + fn gt(&self, other: &Self) -> bool; +} + +pub trait NumExt: NumCast + PartialOrd { } + +fn greater_than_one<T:NumExt>(n: &T) -> bool { + n.gt(&NumCast::from(1).unwrap()) +} + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num1.rs b/tests/ui/traits/inheritance/num1.rs new file mode 100644 index 000000000..663dd3a5e --- /dev/null +++ b/tests/ui/traits/inheritance/num1.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub trait NumCast: Sized { + fn from(i: i32) -> Option<Self>; +} + +pub trait NumExt: NumCast + PartialOrd { } + +fn greater_than_one<T:NumExt>(n: &T) -> bool { + *n > NumCast::from(1).unwrap() +} + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num2.rs b/tests/ui/traits/inheritance/num2.rs new file mode 100644 index 000000000..b713c66a3 --- /dev/null +++ b/tests/ui/traits/inheritance/num2.rs @@ -0,0 +1,86 @@ +// run-pass +// A more complex example of numeric extensions + +pub trait TypeExt {} + +impl TypeExt for u8 {} +impl TypeExt for u16 {} +impl TypeExt for u32 {} +impl TypeExt for u64 {} +impl TypeExt for usize {} + +impl TypeExt for i8 {} +impl TypeExt for i16 {} +impl TypeExt for i32 {} +impl TypeExt for i64 {} +impl TypeExt for isize {} + +impl TypeExt for f32 {} +impl TypeExt for f64 {} + + +pub trait NumExt: TypeExt + PartialEq + PartialOrd {} + +impl NumExt for u8 {} +impl NumExt for u16 {} +impl NumExt for u32 {} +impl NumExt for u64 {} +impl NumExt for usize {} + +impl NumExt for i8 {} +impl NumExt for i16 {} +impl NumExt for i32 {} +impl NumExt for i64 {} +impl NumExt for isize {} + +impl NumExt for f32 {} +impl NumExt for f64 {} + + +pub trait UnSignedExt: NumExt {} + +impl UnSignedExt for u8 {} +impl UnSignedExt for u16 {} +impl UnSignedExt for u32 {} +impl UnSignedExt for u64 {} +impl UnSignedExt for usize {} + + +pub trait SignedExt: NumExt {} + +impl SignedExt for i8 {} +impl SignedExt for i16 {} +impl SignedExt for i32 {} +impl SignedExt for i64 {} +impl SignedExt for isize {} + +impl SignedExt for f32 {} +impl SignedExt for f64 {} + + +pub trait IntegerExt: NumExt {} + +impl IntegerExt for u8 {} +impl IntegerExt for u16 {} +impl IntegerExt for u32 {} +impl IntegerExt for u64 {} +impl IntegerExt for usize {} + +impl IntegerExt for i8 {} +impl IntegerExt for i16 {} +impl IntegerExt for i32 {} +impl IntegerExt for i64 {} +impl IntegerExt for isize {} + + +pub trait FloatExt: NumExt {} + +impl FloatExt for f32 {} +impl FloatExt for f64 {} + + +fn test_float_ext<T:FloatExt>(n: T) { println!("{}", n < n) } + +pub fn main() { + test_float_ext(1f32); +} diff --git a/tests/ui/traits/inheritance/num3.rs b/tests/ui/traits/inheritance/num3.rs new file mode 100644 index 000000000..c40be6f83 --- /dev/null +++ b/tests/ui/traits/inheritance/num3.rs @@ -0,0 +1,19 @@ +// run-pass +pub trait NumCast: Sized { + fn from(i: i32) -> Option<Self>; +} + +pub trait NumExt: PartialEq + PartialOrd + NumCast {} + +impl NumExt for f32 {} +impl NumCast for f32 { + fn from(i: i32) -> Option<f32> { Some(i as f32) } +} + +fn num_eq_one<T: NumExt>(n: T) { + println!("{}", n == NumCast::from(1).unwrap()) +} + +pub fn main() { + num_eq_one(1f32); // you need to actually use the function to trigger the ICE +} diff --git a/tests/ui/traits/inheritance/num5.rs b/tests/ui/traits/inheritance/num5.rs new file mode 100644 index 000000000..f478618f7 --- /dev/null +++ b/tests/ui/traits/inheritance/num5.rs @@ -0,0 +1,26 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub trait NumCast: Sized { + fn from(i: i32) -> Option<Self>; +} + +pub trait NumExt: PartialEq + NumCast {} + +impl NumExt for f32 {} +impl NumExt for isize {} + +impl NumCast for f32 { + fn from(i: i32) -> Option<f32> { Some(i as f32) } +} +impl NumCast for isize { + fn from(i: i32) -> Option<isize> { Some(i as isize) } +} + +fn num_eq_one<T:NumExt>() -> T { + NumCast::from(1).unwrap() +} + +pub fn main() { + num_eq_one::<isize>(); // you need to actually use the function to trigger the ICE +} diff --git a/tests/ui/traits/inheritance/overloading-simple.rs b/tests/ui/traits/inheritance/overloading-simple.rs new file mode 100644 index 000000000..c306aa2cd --- /dev/null +++ b/tests/ui/traits/inheritance/overloading-simple.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +use std::cmp::PartialEq; + +trait MyNum : PartialEq { } + +#[derive(Debug)] +struct MyInt { val: isize } + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn f<T:MyNum>(x: T, y: T) -> bool { + return x == y; +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y, z) = (mi(3), mi(5), mi(3)); + assert!(x != y); + assert_eq!(x, z); +} diff --git a/tests/ui/traits/inheritance/overloading-xc-exe.rs b/tests/ui/traits/inheritance/overloading-xc-exe.rs new file mode 100644 index 000000000..08778061b --- /dev/null +++ b/tests/ui/traits/inheritance/overloading-xc-exe.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:overloading_xc.rs + + +extern crate overloading_xc; +use overloading_xc::{MyNum, MyInt}; + +fn f<T:MyNum>(x: T, y: T) -> (T, T, T) { + return (x.clone() + y.clone(), x.clone() - y.clone(), x * y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let (a, b, c) = f(x, y); + assert_eq!(a, mi(8)); + assert_eq!(b, mi(-2)); + assert_eq!(c, mi(15)); +} diff --git a/tests/ui/traits/inheritance/overloading.rs b/tests/ui/traits/inheritance/overloading.rs new file mode 100644 index 000000000..083643e82 --- /dev/null +++ b/tests/ui/traits/inheritance/overloading.rs @@ -0,0 +1,47 @@ +// run-pass +use std::cmp::PartialEq; +use std::ops::{Add, Sub, Mul}; + +trait MyNum : Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + PartialEq + Clone { } + +#[derive(Clone, Debug)] +struct MyInt { val: isize } + +impl Add for MyInt { + type Output = MyInt; + + fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl Sub for MyInt { + type Output = MyInt; + + fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) } +} + +impl Mul for MyInt { + type Output = MyInt; + + fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) } +} + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn f<T:MyNum>(x: T, y: T) -> (T, T, T) { + return (x.clone() + y.clone(), x.clone() - y.clone(), x * y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let (a, b, c) = f(x, y); + assert_eq!(a, mi(8)); + assert_eq!(b, mi(-2)); + assert_eq!(c, mi(15)); +} diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs b/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs new file mode 100644 index 000000000..727897d20 --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs @@ -0,0 +1,43 @@ +// Test a case of a trait which extends the same supertrait twice, but +// with difference type parameters. Test then that when we don't give +// enough information to pick between these, no selection is made. In +// this particular case, the two choices are i64/u64 -- so when we use +// an integer literal, we wind up falling this literal back to i32. +// See also `run-pass/trait-repeated-supertrait.rs`. + +trait CompareTo<T> { + fn same_as(&self, t: T) -> bool; +} + +trait CompareToInts : CompareTo<i64> + CompareTo<u64> { +} + +impl CompareTo<i64> for i64 { + fn same_as(&self, t: i64) -> bool { *self == t } +} + +impl CompareTo<u64> for i64 { + fn same_as(&self, t: u64) -> bool { *self == (t as i64) } +} + +impl CompareToInts for i64 { } + +fn with_obj(c: &dyn CompareToInts) -> bool { + c.same_as(22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied +} + +fn with_trait<C:CompareToInts>(c: &C) -> bool { + c.same_as(22) //~ ERROR `C: CompareTo<i32>` is not satisfied +} + +fn with_ufcs1<C:CompareToInts>(c: &C) -> bool { + <dyn CompareToInts>::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfi +} + +fn with_ufcs2<C:CompareToInts>(c: &C) -> bool { + CompareTo::same_as(c, 22) //~ ERROR `C: CompareTo<i32>` is not satisfied +} + +fn main() { + assert_eq!(22_i64.same_as(22), true); //~ ERROR `i64: CompareTo<i32>` is not satisfied +} diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr new file mode 100644 index 000000000..656e0d0bf --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:26:15 + | +LL | c.same_as(22) + | ------- ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo<T>`: + <i64 as CompareTo<i64>> + <i64 as CompareTo<u64>> + +error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:30:15 + | +LL | c.same_as(22) + | ------- ^^ the trait `CompareTo<i32>` is not implemented for `C` + | | + | required by a bound introduced by this call + | +help: consider further restricting this bound + | +LL | fn with_trait<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool { + | ++++++++++++++++ + +error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:34:37 + | +LL | <dyn CompareToInts>::same_as(c, 22) + | ---------------------------- ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo<T>`: + <i64 as CompareTo<i64>> + <i64 as CompareTo<u64>> + +error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:38:27 + | +LL | CompareTo::same_as(c, 22) + | ------------------ ^^ the trait `CompareTo<i32>` is not implemented for `C` + | | + | required by a bound introduced by this call + | +help: consider further restricting this bound + | +LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool { + | ++++++++++++++++ + +error[E0277]: the trait bound `i64: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:42:31 + | +LL | assert_eq!(22_i64.same_as(22), true); + | ------- ^^ the trait `CompareTo<i32>` is not implemented for `i64` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo<T>`: + <i64 as CompareTo<i64>> + <i64 as CompareTo<u64>> + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/inheritance/repeated-supertrait.rs b/tests/ui/traits/inheritance/repeated-supertrait.rs new file mode 100644 index 000000000..cb2581ffa --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait.rs @@ -0,0 +1,48 @@ +// run-pass +// Test a case of a trait which extends the same supertrait twice, but +// with difference type parameters. Test that we can invoke the +// various methods in various ways successfully. +// See also `ui/traits/trait-repeated-supertrait-ambig.rs`. + + +trait CompareTo<T> { + fn same_as(&self, t: T) -> bool; +} + +trait CompareToInts : CompareTo<i64> + CompareTo<u64> { +} + +impl CompareTo<i64> for i64 { + fn same_as(&self, t: i64) -> bool { *self == t } +} + +impl CompareTo<u64> for i64 { + fn same_as(&self, t: u64) -> bool { *self == (t as i64) } +} + +impl CompareToInts for i64 { } + +fn with_obj(c: &dyn CompareToInts) -> bool { + c.same_as(22_i64) && c.same_as(22_u64) +} + +fn with_trait<C:CompareToInts>(c: &C) -> bool { + c.same_as(22_i64) && c.same_as(22_u64) +} + +fn with_ufcs1<C:CompareToInts>(c: &C) -> bool { + <dyn CompareToInts>::same_as(c, 22_i64) && <dyn CompareToInts>::same_as(c, 22_u64) +} + +fn with_ufcs2<C:CompareToInts>(c: &C) -> bool { + CompareTo::same_as(c, 22_i64) && CompareTo::same_as(c, 22_u64) +} + +fn main() { + assert_eq!(22_i64.same_as(22_i64), true); + assert_eq!(22_i64.same_as(22_u64), true); + assert_eq!(with_trait(&22), true); + assert_eq!(with_obj(&22), true); + assert_eq!(with_ufcs1(&22), true); + assert_eq!(with_ufcs2(&22), true); +} diff --git a/tests/ui/traits/inheritance/self-in-supertype.rs b/tests/ui/traits/inheritance/self-in-supertype.rs new file mode 100644 index 000000000..e8a2bd791 --- /dev/null +++ b/tests/ui/traits/inheritance/self-in-supertype.rs @@ -0,0 +1,62 @@ +// run-pass +// Test for issue #4183: use of Self in supertraits. + +pub static FUZZY_EPSILON: f64 = 0.1; + +pub trait FuzzyEq<Eps> { + fn fuzzy_eq(&self, other: &Self) -> bool; + fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool; +} + +trait Float: Sized+FuzzyEq<Self> { + fn two_pi() -> Self; +} + +impl FuzzyEq<f32> for f32 { + fn fuzzy_eq(&self, other: &f32) -> bool { + self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f32)) + } + + fn fuzzy_eq_eps(&self, other: &f32, epsilon: &f32) -> bool { + (*self - *other).abs() < *epsilon + } +} + +impl Float for f32 { + fn two_pi() -> f32 { 6.28318530717958647692528676655900576_f32 } +} + +impl FuzzyEq<f64> for f64 { + fn fuzzy_eq(&self, other: &f64) -> bool { + self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f64)) + } + + fn fuzzy_eq_eps(&self, other: &f64, epsilon: &f64) -> bool { + (*self - *other).abs() < *epsilon + } +} + +impl Float for f64 { + fn two_pi() -> f64 { 6.28318530717958647692528676655900576_f64 } +} + +fn compare<F:Float>(f1: F) -> bool { + let f2 = Float::two_pi(); + f1.fuzzy_eq(&f2) +} + +pub fn main() { + assert!(compare::<f32>(6.28318530717958647692528676655900576)); + assert!(compare::<f32>(6.29)); + assert!(compare::<f32>(6.3)); + assert!(compare::<f32>(6.19)); + assert!(!compare::<f32>(7.28318530717958647692528676655900576)); + assert!(!compare::<f32>(6.18)); + + assert!(compare::<f64>(6.28318530717958647692528676655900576)); + assert!(compare::<f64>(6.29)); + assert!(compare::<f64>(6.3)); + assert!(compare::<f64>(6.19)); + assert!(!compare::<f64>(7.28318530717958647692528676655900576)); + assert!(!compare::<f64>(6.18)); +} diff --git a/tests/ui/traits/inheritance/self.rs b/tests/ui/traits/inheritance/self.rs new file mode 100644 index 000000000..5f2559f48 --- /dev/null +++ b/tests/ui/traits/inheritance/self.rs @@ -0,0 +1,29 @@ +// run-pass +trait Foo<T> { + fn f(&self, x: &T); +} + +trait Bar : Sized + Foo<Self> { + fn g(&self); +} + +struct S { + x: isize +} + +impl Foo<S> for S { + fn f(&self, x: &S) { + println!("{}", x.x); + } +} + +impl Bar for S { + fn g(&self) { + self.f(self); + } +} + +pub fn main() { + let s = S { x: 1 }; + s.g(); +} diff --git a/tests/ui/traits/inheritance/simple.rs b/tests/ui/traits/inheritance/simple.rs new file mode 100644 index 000000000..ca3a284e5 --- /dev/null +++ b/tests/ui/traits/inheritance/simple.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } + +fn ff<T:Foo>(a: &T) -> isize { + a.f() +} + +fn gg<T:Bar>(a: &T) -> isize { + a.g() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(ff(a), 10); + assert_eq!(gg(a), 20); +} diff --git a/tests/ui/traits/inheritance/static.rs b/tests/ui/traits/inheritance/static.rs new file mode 100644 index 000000000..16218fbd2 --- /dev/null +++ b/tests/ui/traits/inheritance/static.rs @@ -0,0 +1,26 @@ +// run-pass + +pub trait MyNum { + fn from_int(_: isize) -> Self; +} + +pub trait NumExt: MyNum { } + +struct S { v: isize } + +impl MyNum for S { + fn from_int(i: isize) -> S { + S { + v: i + } + } +} + +impl NumExt for S { } + +fn greater_than_one<T:NumExt>() -> T { MyNum::from_int(1) } + +pub fn main() { + let v: S = greater_than_one(); + assert_eq!(v.v, 1); +} diff --git a/tests/ui/traits/inheritance/static2.rs b/tests/ui/traits/inheritance/static2.rs new file mode 100644 index 000000000..bc78e1e23 --- /dev/null +++ b/tests/ui/traits/inheritance/static2.rs @@ -0,0 +1,29 @@ +// run-pass +pub trait MyEq {} + +pub trait MyNum { + fn from_int(_: isize) -> Self; +} + +pub trait NumExt: MyEq + MyNum { } + +struct S { v: isize } + +impl MyEq for S { } + +impl MyNum for S { + fn from_int(i: isize) -> S { + S { + v: i + } + } +} + +impl NumExt for S { } + +fn greater_than_one<T:NumExt>() -> T { MyNum::from_int(1) } + +pub fn main() { + let v: S = greater_than_one(); + assert_eq!(v.v, 1); +} diff --git a/tests/ui/traits/inheritance/subst.rs b/tests/ui/traits/inheritance/subst.rs new file mode 100644 index 000000000..b2b650366 --- /dev/null +++ b/tests/ui/traits/inheritance/subst.rs @@ -0,0 +1,27 @@ +// run-pass + +pub trait Add<RHS,Result> { + fn add(&self, rhs: &RHS) -> Result; +} + +trait MyNum : Sized + Add<Self,Self> { } + +struct MyInt { val: isize } + +impl Add<MyInt, MyInt> for MyInt { + fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl MyNum for MyInt {} + +fn f<T:MyNum>(x: T, y: T) -> T { + return x.add(&y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let z = f(x, y); + assert_eq!(z.val, 8) +} diff --git a/tests/ui/traits/inheritance/subst2.rs b/tests/ui/traits/inheritance/subst2.rs new file mode 100644 index 000000000..ccc9628c7 --- /dev/null +++ b/tests/ui/traits/inheritance/subst2.rs @@ -0,0 +1,37 @@ +// run-pass + +trait Panda<T> { + fn chomp(&self, bamboo: &T) -> T; +} + +trait Add<RHS,Result>: Panda<RHS> { + fn add(&self, rhs: &RHS) -> Result; +} + +trait MyNum : Sized + Add<Self,Self> { } + +struct MyInt { val: isize } + +impl Panda<MyInt> for MyInt { + fn chomp(&self, bamboo: &MyInt) -> MyInt { + mi(self.val + bamboo.val) + } +} + +impl Add<MyInt, MyInt> for MyInt { + fn add(&self, other: &MyInt) -> MyInt { self.chomp(other) } +} + +impl MyNum for MyInt {} + +fn f<T:MyNum>(x: T, y: T) -> T { + return x.add(&y).chomp(&y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let z = f(x, y); + assert_eq!(z.val, 13); +} diff --git a/tests/ui/traits/inheritance/visibility.rs b/tests/ui/traits/inheritance/visibility.rs new file mode 100644 index 000000000..6ad864926 --- /dev/null +++ b/tests/ui/traits/inheritance/visibility.rs @@ -0,0 +1,20 @@ +// run-pass + +mod traits { + pub trait Foo { fn f(&self) -> isize; } + + impl Foo for isize { fn f(&self) -> isize { 10 } } +} + +trait Quux: traits::Foo { } +impl<T:traits::Foo> Quux for T { } + +// Foo is not in scope but because Quux is we can still access +// Foo's methods on a Quux bound typaram +fn f<T:Quux>(x: &T) { + assert_eq!(x.f(), 10); +} + +pub fn main() { + f(&0) +} diff --git a/tests/ui/traits/invalid_operator_trait.rs b/tests/ui/traits/invalid_operator_trait.rs new file mode 100644 index 000000000..7ea3b0d5b --- /dev/null +++ b/tests/ui/traits/invalid_operator_trait.rs @@ -0,0 +1,23 @@ +#![crate_type = "lib"] +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] + +#[lang="sized"] +pub trait Sized { + // Empty. +} + +#[lang = "add"] +trait Add<RHS=Self> { + type Output; + + fn add<Y>(self, _: RHS) -> Self::Output; + //~^ ERROR `add` must not have any generic parameters +} + +#[allow(unreachable_code)] +fn ice(a: usize) { + let r = loop {}; + r = r + a; +} diff --git a/tests/ui/traits/invalid_operator_trait.stderr b/tests/ui/traits/invalid_operator_trait.stderr new file mode 100644 index 000000000..8c6e36959 --- /dev/null +++ b/tests/ui/traits/invalid_operator_trait.stderr @@ -0,0 +1,8 @@ +error: `add` must not have any generic parameters + --> $DIR/invalid_operator_trait.rs:15:5 + | +LL | fn add<Y>(self, _: RHS) -> Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/issue-102989.rs b/tests/ui/traits/issue-102989.rs new file mode 100644 index 000000000..216cd78e5 --- /dev/null +++ b/tests/ui/traits/issue-102989.rs @@ -0,0 +1,14 @@ +// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib" + +#![feature(lang_items)] +#[lang="sized"] +trait Sized { } //~ ERROR found duplicate lang item `sized` + +fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + //~^ ERROR `self` parameter is only allowed in associated functions + //~| ERROR cannot find type `Struct` in this scope + let x = x << 1; + //~^ ERROR cannot find value `x` in this scope +} + +fn main() {} diff --git a/tests/ui/traits/issue-102989.stderr b/tests/ui/traits/issue-102989.stderr new file mode 100644 index 000000000..7d0098fe8 --- /dev/null +++ b/tests/ui/traits/issue-102989.stderr @@ -0,0 +1,34 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/issue-102989.rs:7:15 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0412]: cannot find type `Struct` in this scope + --> $DIR/issue-102989.rs:7:22 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-102989.rs:10:13 + | +LL | let x = x << 1; + | ^ help: a local variable with a similar name exists: `f` + +error[E0152]: found duplicate lang item `sized` + --> $DIR/issue-102989.rs:5:1 + | +LL | trait Sized { } + | ^^^^^^^^^^^ + | + = note: the lang item is first defined in crate `core` (which `std` depends on) + = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib + = note: second definition in the local crate (`issue_102989`) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0152, E0412, E0425. +For more information about an error, try `rustc --explain E0152`. diff --git a/tests/ui/traits/issue-104322.rs b/tests/ui/traits/issue-104322.rs new file mode 100644 index 000000000..dcc27f1f0 --- /dev/null +++ b/tests/ui/traits/issue-104322.rs @@ -0,0 +1,80 @@ +// build-pass +// +// Tests that overflows do not occur in certain situations +// related to generic diesel code + +use mini_diesel::*; + +pub trait HandleDelete<K> {} + +pub fn handle_delete<D, R>() +where + R: HasTable, + R::Table: HandleDelete<D> + 'static, +{ +} + +impl<K, T> HandleDelete<K> for T +where + T: Table + HasTable<Table = T> + 'static, + K: 'static, + &'static K: Identifiable<Table = T>, + T::PrimaryKey: EqAll<<&'static K as Identifiable>::Id>, + T::Query: FilterDsl<<T::PrimaryKey as EqAll<<&'static K as Identifiable>::Id>>::Output>, + Filter<T::Query, <T::PrimaryKey as EqAll<<&'static K as Identifiable>::Id>>::Output>: + IntoUpdateTarget<Table = T>, +{ +} + +mod mini_diesel { + pub trait HasTable { + type Table: Table; + } + + pub trait Identifiable: HasTable { + type Id; + } + + pub trait EqAll<Rhs> { + type Output; + } + + pub trait IntoUpdateTarget: HasTable { + type WhereClause; + } + + pub trait Query { + type SqlType; + } + + pub trait AsQuery { + type Query: Query; + } + impl<T: Query> AsQuery for T { + type Query = Self; + } + + pub trait FilterDsl<Predicate> { + type Output; + } + + impl<T, Predicate> FilterDsl<Predicate> for T + where + T: Table, + T::Query: FilterDsl<Predicate>, + { + type Output = Filter<T::Query, Predicate>; + } + + pub trait QuerySource { + type FromClause; + } + + pub trait Table: QuerySource + AsQuery + Sized { + type PrimaryKey; + } + + pub type Filter<Source, Predicate> = <Source as FilterDsl<Predicate>>::Output; +} + +fn main() {} diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs new file mode 100644 index 000000000..7064a39d2 --- /dev/null +++ b/tests/ui/traits/issue-106072.rs @@ -0,0 +1,5 @@ +#[derive(Clone)] //~ trait objects must include the `dyn` keyword + //~| trait objects must include the `dyn` keyword +struct Foo; +trait Foo {} //~ the name `Foo` is defined multiple times +fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr new file mode 100644 index 000000000..f9b7b8146 --- /dev/null +++ b/tests/ui/traits/issue-106072.stderr @@ -0,0 +1,30 @@ +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/issue-106072.rs:4:1 + | +LL | struct Foo; + | ----------- previous definition of the type `Foo` here +LL | trait Foo {} + | ^^^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the type namespace of this module + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/issue-106072.rs:1:10 + | +LL | #[derive(Clone)] + | ^^^^^ + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/issue-106072.rs:1:10 + | +LL | #[derive(Clone)] + | ^^^^^ + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0428, E0782. +For more information about an error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/issue-18400.rs b/tests/ui/traits/issue-18400.rs new file mode 100644 index 000000000..fdd11512d --- /dev/null +++ b/tests/ui/traits/issue-18400.rs @@ -0,0 +1,26 @@ +trait Set<T> { + fn contains(&self, _: T) -> bool; + fn set(&mut self, _: T); +} + +impl<'a, T, S> Set<&'a [T]> for S where + T: Copy, + S: Set<T>, +{ + fn contains(&self, bits: &[T]) -> bool { + bits.iter().all(|&bit| self.contains(bit)) + } + + fn set(&mut self, bits: &[T]) { + for &bit in bits { + self.set(bit) + } + } +} + +fn main() { + let bits: &[_] = &[0, 1]; + + 0.contains(bits); + //~^ ERROR overflow +} diff --git a/tests/ui/traits/issue-18400.stderr b/tests/ui/traits/issue-18400.stderr new file mode 100644 index 000000000..edaf08f49 --- /dev/null +++ b/tests/ui/traits/issue-18400.stderr @@ -0,0 +1,20 @@ +error[E0275]: overflow evaluating the requirement `_: Sized` + --> $DIR/issue-18400.rs:24:7 + | +LL | 0.contains(bits); + | ^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_18400`) +note: required for `{integer}` to implement `Set<&[_]>` + --> $DIR/issue-18400.rs:6:16 + | +LL | impl<'a, T, S> Set<&'a [T]> for S where + | - ^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 128 redundant requirements hidden + = note: required for `{integer}` to implement `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/issue-18412.rs b/tests/ui/traits/issue-18412.rs new file mode 100644 index 000000000..fe1cfb3df --- /dev/null +++ b/tests/ui/traits/issue-18412.rs @@ -0,0 +1,26 @@ +// run-pass +// Test that non-static methods can be assigned to local variables as +// function pointers. + + +trait Foo { + fn foo(&self) -> usize; +} + +struct A(usize); + +impl A { + fn bar(&self) -> usize { self.0 } +} + +impl Foo for A { + fn foo(&self) -> usize { self.bar() } +} + +fn main() { + let f = A::bar; + let g = Foo::foo; + let a = A(42); + + assert_eq!(f(&a), g(&a)); +} diff --git a/tests/ui/traits/issue-20692.rs b/tests/ui/traits/issue-20692.rs new file mode 100644 index 000000000..1cb2d8c73 --- /dev/null +++ b/tests/ui/traits/issue-20692.rs @@ -0,0 +1,11 @@ +trait Array: Sized + Copy {} + +fn f<T: Array>(x: &T) { + let _ = x + //~^ ERROR `Array` cannot be made into an object + as + &dyn Array; + //~^ ERROR `Array` cannot be made into an object +} + +fn main() {} diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr new file mode 100644 index 000000000..2028994cd --- /dev/null +++ b/tests/ui/traits/issue-20692.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Array` cannot be made into an object + --> $DIR/issue-20692.rs:7:5 + | +LL | &dyn Array; + | ^^^^^^^^^^ `Array` 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-20692.rs:1:14 + | +LL | trait Array: Sized + Copy {} + | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized` + | | | + | | ...because it requires `Self: Sized` + | this trait cannot be made into an object... + +error[E0038]: the trait `Array` cannot be made into an object + --> $DIR/issue-20692.rs:4:13 + | +LL | let _ = x + | ^ `Array` 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-20692.rs:1:14 + | +LL | trait Array: Sized + Copy {} + | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized` + | | | + | | ...because it requires `Self: Sized` + | this trait cannot be made into an object... + = note: required for `&T` to implement `CoerceUnsized<&dyn Array>` + = note: required by cast to type `&dyn Array` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-22019.rs b/tests/ui/traits/issue-22019.rs new file mode 100644 index 000000000..1a887f0f3 --- /dev/null +++ b/tests/ui/traits/issue-22019.rs @@ -0,0 +1,34 @@ +// run-pass +// Test an issue where global caching was causing free regions from +// distinct scopes to be compared (`'g` and `'h`). The only important +// thing is that compilation succeeds here. + +// pretty-expanded FIXME #23616 + +#![allow(missing_copy_implementations)] +#![allow(unused_variables)] + +use std::borrow::ToOwned; + +pub struct CFGNode; + +pub type Node<'a> = &'a CFGNode; + +pub trait GraphWalk<'c, N> { + /// Returns all the nodes in this graph. + fn nodes(&'c self) where [N]:ToOwned<Owned=Vec<N>>; +} + +impl<'g> GraphWalk<'g, Node<'g>> for u32 +{ + fn nodes(&'g self) where [Node<'g>]:ToOwned<Owned=Vec<Node<'g>>> + { loop { } } +} + +impl<'h> GraphWalk<'h, Node<'h>> for u64 +{ + fn nodes(&'h self) where [Node<'h>]:ToOwned<Owned=Vec<Node<'h>>> + { loop { } } +} + +fn main() { } diff --git a/tests/ui/traits/issue-22110.rs b/tests/ui/traits/issue-22110.rs new file mode 100644 index 000000000..bdbfee799 --- /dev/null +++ b/tests/ui/traits/issue-22110.rs @@ -0,0 +1,27 @@ +// run-pass +// Test an issue where we reported ambiguity between the where-clause +// and the blanket impl. The only important thing is that compilation +// succeeds here. Issue #22110. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Foo<A> { + fn foo(&self, a: A); +} + +impl<A,F:Fn(A)> Foo<A> for F { + fn foo(&self, _: A) { } +} + +fn baz<A,F:for<'a> Foo<(&'a A,)>>(_: F) { } + +fn components<T,A>(t: fn(&A)) + where fn(&A) : for<'a> Foo<(&'a A,)>, +{ + baz(t) +} + +fn main() { +} diff --git a/tests/ui/traits/issue-22655.rs b/tests/ui/traits/issue-22655.rs new file mode 100644 index 000000000..bc08ca0a2 --- /dev/null +++ b/tests/ui/traits/issue-22655.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] +// Regression test for issue #22655: This test should not lead to +// infinite recursion. + +// pretty-expanded FIXME #23616 + +unsafe impl<T: Send + ?Sized> Send for Unique<T> { } + +pub struct Unique<T:?Sized> { + pointer: *const T, +} + +pub struct Node<V> { + vals: V, + edges: Unique<Node<V>>, +} + +fn is_send<T: Send>() {} + +fn main() { + is_send::<Node<&'static ()>>(); +} diff --git a/tests/ui/traits/issue-23003-overflow.rs b/tests/ui/traits/issue-23003-overflow.rs new file mode 100644 index 000000000..c5f471f23 --- /dev/null +++ b/tests/ui/traits/issue-23003-overflow.rs @@ -0,0 +1,29 @@ +// A variant of traits-issue-23003 in which an infinite series of +// types are required. This test now just compiles fine, since the +// relevant rules that triggered the overflow were removed. + +// check-pass +#![allow(dead_code)] + +use std::marker::PhantomData; + +trait Async { + type Cancel; +} + +struct Receipt<A:Async> { + marker: PhantomData<A>, +} + +struct Complete<B> { + core: Option<B>, +} + +impl<B> Async for Complete<B> { + type Cancel = Receipt<Complete<Option<B>>>; +} + +fn foo(_: Receipt<Complete<()>>) { } + + +fn main() { } diff --git a/tests/ui/traits/issue-23003.rs b/tests/ui/traits/issue-23003.rs new file mode 100644 index 000000000..24c2b2ad6 --- /dev/null +++ b/tests/ui/traits/issue-23003.rs @@ -0,0 +1,32 @@ +// run-pass +// Test stack overflow triggered by evaluating the implications. To be +// WF, the type `Receipt<Complete>` would require that `<Complete as +// Async>::Cancel` be WF. This normalizes to `Receipt<Complete>` +// again, leading to an infinite cycle. Issue #23003. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] +#![allow(unused_variables)] + +use std::marker::PhantomData; + +trait Async { + type Cancel; +} + +struct Receipt<A:Async> { + marker: PhantomData<A>, +} + +struct Complete { + core: Option<()>, +} + +impl Async for Complete { + type Cancel = Receipt<Complete>; +} + +fn foo(r: Receipt<Complete>) { } + +fn main() { } diff --git a/tests/ui/traits/issue-23825.rs b/tests/ui/traits/issue-23825.rs new file mode 100644 index 000000000..a9f0095d2 --- /dev/null +++ b/tests/ui/traits/issue-23825.rs @@ -0,0 +1,21 @@ +// run-pass +trait Stringify { + fn to_string(&self) -> String; +} + +impl Stringify for u32 { + fn to_string(&self) -> String { format!("u32: {}", *self) } +} + +impl Stringify for f32 { + fn to_string(&self) -> String { format!("f32: {}", *self) } +} + +fn print<T: Stringify>(x: T) -> String { + x.to_string() +} + +fn main() { + assert_eq!(&print(5), "u32: 5"); + assert_eq!(&print(5.0), "f32: 5"); +} diff --git a/tests/ui/traits/issue-24010.rs b/tests/ui/traits/issue-24010.rs new file mode 100644 index 000000000..f18185334 --- /dev/null +++ b/tests/ui/traits/issue-24010.rs @@ -0,0 +1,14 @@ +// run-pass + +trait Foo: Fn(i32) -> i32 + Send {} + +impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {} + +fn wants_foo(f: Box<dyn Foo>) -> i32 { + f(42) +} + +fn main() { + let f = Box::new(|x| x); + assert_eq!(wants_foo(f), 42); +} diff --git a/tests/ui/traits/issue-26339.rs b/tests/ui/traits/issue-26339.rs new file mode 100644 index 000000000..bedd87cc4 --- /dev/null +++ b/tests/ui/traits/issue-26339.rs @@ -0,0 +1,31 @@ +// run-pass +// Test that the right implementation is called through a trait +// object when supertraits include multiple references to the +// same trait, with different type parameters. + +trait A: PartialEq<Foo> + PartialEq<Bar> { } + +struct Foo; +struct Bar; + +struct Aimpl; + +impl PartialEq<Foo> for Aimpl { + fn eq(&self, _rhs: &Foo) -> bool { + true + } +} + +impl PartialEq<Bar> for Aimpl { + fn eq(&self, _rhs: &Bar) -> bool { + false + } +} + +impl A for Aimpl { } + +fn main() { + let a = &Aimpl as &dyn A; + + assert!(*a == Foo); +} diff --git a/tests/ui/traits/issue-28576.rs b/tests/ui/traits/issue-28576.rs new file mode 100644 index 000000000..972c839b6 --- /dev/null +++ b/tests/ui/traits/issue-28576.rs @@ -0,0 +1,12 @@ +pub trait Foo<RHS=Self> { + type Assoc; +} + +pub trait Bar: Foo<Assoc=()> { + fn new(&self, b: & + dyn Bar //~ ERROR the trait `Bar` cannot be made into an object + <Assoc=()> + ); +} + +fn main() {} diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr new file mode 100644 index 000000000..203cd0630 --- /dev/null +++ b/tests/ui/traits/issue-28576.stderr @@ -0,0 +1,20 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-28576.rs:7:12 + | +LL | / dyn Bar +LL | | <Assoc=()> + | |________________________^ `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-28576.rs:5:16 + | +LL | pub trait Bar: Foo<Assoc=()> { + | --- ^^^^^^^^^^^^^ + | | | | + | | | ...because it uses `Self` as a type parameter + | | ...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/tests/ui/traits/issue-32963.rs b/tests/ui/traits/issue-32963.rs new file mode 100644 index 000000000..56a68f3a2 --- /dev/null +++ b/tests/ui/traits/issue-32963.rs @@ -0,0 +1,11 @@ +use std::mem; + +trait Misc {} + +fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() } + +fn main() { + size_of_copy::<dyn Misc + Copy>(); + //~^ ERROR only auto traits can be used as additional traits in a trait object + //~| ERROR the trait bound `dyn Misc: Copy` is not satisfied +} diff --git a/tests/ui/traits/issue-32963.stderr b/tests/ui/traits/issue-32963.stderr new file mode 100644 index 000000000..bad45e54d --- /dev/null +++ b/tests/ui/traits/issue-32963.stderr @@ -0,0 +1,27 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/issue-32963.rs:8:31 + | +LL | size_of_copy::<dyn Misc + Copy>(); + | ---- ^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0277]: the trait bound `dyn Misc: Copy` is not satisfied + --> $DIR/issue-32963.rs:8:20 + | +LL | size_of_copy::<dyn Misc + Copy>(); + | ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `dyn Misc` + | +note: required by a bound in `size_of_copy` + --> $DIR/issue-32963.rs:5:20 + | +LL | fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() } + | ^^^^ required by this bound in `size_of_copy` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0225, E0277. +For more information about an error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/issue-33140-hack-boundaries.rs b/tests/ui/traits/issue-33140-hack-boundaries.rs new file mode 100644 index 000000000..d091162fc --- /dev/null +++ b/tests/ui/traits/issue-33140-hack-boundaries.rs @@ -0,0 +1,70 @@ +#![feature(negative_impls)] +#![allow(order_dependent_trait_objects)] + +// Check that the issue #33140 hack does not allow unintended things. + +// OK +trait Trait0 {} + +impl Trait0 for dyn Send {} +impl Trait0 for dyn Send {} + +// Problem 1: associated types +trait Trait1 { + fn my_fn(&self) {} +} + +impl Trait1 for dyn Send {} +impl Trait1 for dyn Send {} +//~^ ERROR E0119 + +// Problem 2: negative impl +trait Trait2 {} + +impl Trait2 for dyn Send {} +impl !Trait2 for dyn Send {} +//~^ ERROR E0751 + +// Problem 3: type parameter +trait Trait3<T: ?Sized> {} + +impl Trait3<dyn Sync> for dyn Send {} +impl Trait3<dyn Sync> for dyn Send {} +//~^ ERROR E0119 + +// Problem 4a: not a trait object - generic +trait Trait4a {} + +impl<T: ?Sized> Trait4a for T {} +impl Trait4a for dyn Send {} +//~^ ERROR E0119 + +// Problem 4b: not a trait object - misc +trait Trait4b {} + +impl Trait4b for () {} +impl Trait4b for () {} +//~^ ERROR E0119 + +// Problem 4c: not a principal-less trait object +trait Trait4c {} + +impl Trait4c for dyn Trait1 + Send {} +impl Trait4c for dyn Trait1 + Send {} +//~^ ERROR E0119 + +// Problem 4d: lifetimes +trait Trait4d {} + +impl<'a> Trait4d for dyn Send + 'a {} +impl<'a> Trait4d for dyn Send + 'a {} +//~^ ERROR E0119 + +// Problem 5: where-clauses +trait Trait5 {} + +impl Trait5 for dyn Send {} +impl Trait5 for dyn Send where u32: Copy {} +//~^ ERROR E0119 + +fn main() {} diff --git a/tests/ui/traits/issue-33140-hack-boundaries.stderr b/tests/ui/traits/issue-33140-hack-boundaries.stderr new file mode 100644 index 000000000..80a502c63 --- /dev/null +++ b/tests/ui/traits/issue-33140-hack-boundaries.stderr @@ -0,0 +1,85 @@ +error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:18:1 + | +LL | impl Trait1 for dyn Send {} + | ------------------------ first implementation here +LL | impl Trait1 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + +error[E0751]: found both positive and negative implementation of trait `Trait2` for type `(dyn Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:25:1 + | +LL | impl Trait2 for dyn Send {} + | ------------------------ positive implementation here +LL | impl !Trait2 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error[E0119]: conflicting implementations of trait `Trait3<(dyn Sync + 'static)>` for type `(dyn Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:32:1 + | +LL | impl Trait3<dyn Sync> for dyn Send {} + | ---------------------------------- first implementation here +LL | impl Trait3<dyn Sync> for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:39:1 + | +LL | impl<T: ?Sized> Trait4a for T {} + | ----------------------------- first implementation here +LL | impl Trait4a for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4b` for type `()` + --> $DIR/issue-33140-hack-boundaries.rs:46:1 + | +LL | impl Trait4b for () {} + | ------------------- first implementation here +LL | impl Trait4b for () {} + | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:53:1 + | +LL | impl Trait4c for dyn Trait1 + Send {} + | ---------------------------------- first implementation here +LL | impl Trait4c for dyn Trait1 + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn Send` + --> $DIR/issue-33140-hack-boundaries.rs:60:1 + | +LL | impl<'a> Trait4d for dyn Send + 'a {} + | ---------------------------------- first implementation here +LL | impl<'a> Trait4d for dyn Send + 'a {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn Send` + +error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:67:1 + | +LL | impl Trait5 for dyn Send {} + | ------------------------ first implementation here +LL | impl Trait5 for dyn Send where u32: Copy {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0119, E0751. +For more information about an error, try `rustc --explain E0119`. +Future incompatibility report: Future breakage diagnostic: +warning: conflicting implementations of trait `Trait0` for type `(dyn Send + 'static)`: (E0119) + --> $DIR/issue-33140-hack-boundaries.rs:10:1 + | +LL | impl Trait0 for dyn Send {} + | ------------------------ first implementation here +LL | impl Trait0 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> +note: the lint level is defined here + --> $DIR/issue-33140-hack-boundaries.rs:2:10 + | +LL | #![allow(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/traits/issue-33140.rs b/tests/ui/traits/issue-33140.rs new file mode 100644 index 000000000..9bdac4b83 --- /dev/null +++ b/tests/ui/traits/issue-33140.rs @@ -0,0 +1,47 @@ +trait Trait { + fn xyz() -> bool; +} + +impl Trait for dyn Send + Sync { + fn xyz() -> bool { false } +} + +impl Trait for dyn Sync + Send { +//~^ ERROR conflicting implementations + fn xyz() -> bool { true } +} + +trait Trait2 { + fn uvw() -> bool; +} + +impl Trait2 for dyn Send + Sync { + fn uvw() -> bool { false } +} + +impl Trait2 for dyn Sync + Send + Sync { +//~^ ERROR conflicting implementations + fn uvw() -> bool { true } +} + +struct Foo<T: ?Sized>(T); +impl Foo<dyn Send + Sync> { + fn abc() -> bool { //~ ERROR duplicate definitions with name `abc` + false + } +} + +impl Foo<dyn Sync + Send> { + fn abc() -> bool { + true + } +} + +fn main() { + assert_eq!(<dyn Send + Sync>::xyz(), false); + assert_eq!(<dyn Sync + Send>::xyz(), true); + assert_eq!(<dyn Send + Sync>::uvw(), false); + assert_eq!(<dyn Sync + Send+ Sync>::uvw(), true); + assert_eq!(<Foo<dyn Send + Sync>>::abc(), false); + assert_eq!(<Foo<dyn Sync + Send>>::abc(), true); +} diff --git a/tests/ui/traits/issue-33140.stderr b/tests/ui/traits/issue-33140.stderr new file mode 100644 index 000000000..d31281f72 --- /dev/null +++ b/tests/ui/traits/issue-33140.stderr @@ -0,0 +1,31 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)` + --> $DIR/issue-33140.rs:9:1 + | +LL | impl Trait for dyn Send + Sync { + | ------------------------------ first implementation here +... +LL | impl Trait for dyn Sync + Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + +error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn Send + Sync + 'static)` + --> $DIR/issue-33140.rs:22:1 + | +LL | impl Trait2 for dyn Send + Sync { + | ------------------------------- first implementation here +... +LL | impl Trait2 for dyn Sync + Send + Sync { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + +error[E0592]: duplicate definitions with name `abc` + --> $DIR/issue-33140.rs:29:5 + | +LL | fn abc() -> bool { + | ^^^^^^^^^^^^^^^^ duplicate definitions for `abc` +... +LL | fn abc() -> bool { + | ---------------- other definition for `abc` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0119, E0592. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/issue-35869.rs b/tests/ui/traits/issue-35869.rs new file mode 100644 index 000000000..b9b4c972e --- /dev/null +++ b/tests/ui/traits/issue-35869.rs @@ -0,0 +1,21 @@ +trait Foo { + fn foo(_: fn(u8) -> ()); + fn bar(_: Option<u8>); + fn baz(_: (u8, u16)); + fn qux() -> u8; +} + +struct Bar; + +impl Foo for Bar { + fn foo(_: fn(u16) -> ()) {} + //~^ ERROR method `foo` has an incompatible type for trait + fn bar(_: Option<u16>) {} + //~^ ERROR method `bar` has an incompatible type for trait + fn baz(_: (u16, u16)) {} + //~^ ERROR method `baz` has an incompatible type for trait + fn qux() -> u16 { 5u16 } + //~^ ERROR method `qux` has an incompatible type for trait +} + +fn main() {} diff --git a/tests/ui/traits/issue-35869.stderr b/tests/ui/traits/issue-35869.stderr new file mode 100644 index 000000000..6d985bdea --- /dev/null +++ b/tests/ui/traits/issue-35869.stderr @@ -0,0 +1,71 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/issue-35869.rs:11:15 + | +LL | fn foo(_: fn(u16) -> ()) {} + | ^^^^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `fn(u8)` + | +note: type in trait + --> $DIR/issue-35869.rs:2:15 + | +LL | fn foo(_: fn(u8) -> ()); + | ^^^^^^^^^^^^ + = note: expected signature `fn(fn(u8))` + found signature `fn(fn(u16))` + +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/issue-35869.rs:13:15 + | +LL | fn bar(_: Option<u16>) {} + | ^^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `Option<u8>` + | +note: type in trait + --> $DIR/issue-35869.rs:3:15 + | +LL | fn bar(_: Option<u8>); + | ^^^^^^^^^^ + = note: expected signature `fn(Option<u8>)` + found signature `fn(Option<u16>)` + +error[E0053]: method `baz` has an incompatible type for trait + --> $DIR/issue-35869.rs:15:15 + | +LL | fn baz(_: (u16, u16)) {} + | ^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `(u8, u16)` + | +note: type in trait + --> $DIR/issue-35869.rs:4:15 + | +LL | fn baz(_: (u8, u16)); + | ^^^^^^^^^ + = note: expected signature `fn((u8, _))` + found signature `fn((u16, _))` + +error[E0053]: method `qux` has an incompatible type for trait + --> $DIR/issue-35869.rs:17:17 + | +LL | fn qux() -> u16 { 5u16 } + | ^^^ + | | + | expected `u8`, found `u16` + | help: change the output type to match the trait: `u8` + | +note: type in trait + --> $DIR/issue-35869.rs:5:17 + | +LL | fn qux() -> u8; + | ^^ + = note: expected signature `fn() -> u8` + found signature `fn() -> u16` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/traits/issue-3683.rs b/tests/ui/traits/issue-3683.rs new file mode 100644 index 000000000..b12c450c9 --- /dev/null +++ b/tests/ui/traits/issue-3683.rs @@ -0,0 +1,18 @@ +// run-pass + +trait Foo { + fn a(&self) -> isize; + fn b(&self) -> isize { + self.a() + 2 + } +} + +impl Foo for isize { + fn a(&self) -> isize { + 3 + } +} + +pub fn main() { + assert_eq!(3.b(), 5); +} diff --git a/tests/ui/traits/issue-38033.rs b/tests/ui/traits/issue-38033.rs new file mode 100644 index 000000000..16b867ec8 --- /dev/null +++ b/tests/ui/traits/issue-38033.rs @@ -0,0 +1,79 @@ +// run-pass +use std::marker; +use std::mem; + +fn main() { + let workers = (0..0).map(|_| result::<u32, ()>()); + drop(join_all(workers).poll()); +} + +trait Future { + type Item; + type Error; + + fn poll(&mut self) -> Result<Self::Item, Self::Error>; +} + +trait IntoFuture { + type Future: Future<Item=Self::Item, Error=Self::Error>; + type Item; + type Error; + + fn into_future(self) -> Self::Future; +} + +impl<F: Future> IntoFuture for F { + type Future = F; + type Item = F::Item; + type Error = F::Error; + + fn into_future(self) -> F { + self + } +} + +struct FutureResult<T, E> { + _inner: marker::PhantomData<(T, E)>, +} + +fn result<T, E>() -> FutureResult<T, E> { + loop {} +} + +impl<T, E> Future for FutureResult<T, E> { + type Item = T; + type Error = E; + + fn poll(&mut self) -> Result<T, E> { + loop {} + } +} + +struct JoinAll<I> + where I: IntoIterator, + I::Item: IntoFuture, +{ + elems: Vec<<I::Item as IntoFuture>::Item>, +} + +fn join_all<I>(_: I) -> JoinAll<I> + where I: IntoIterator, + I::Item: IntoFuture, +{ + JoinAll { elems: vec![] } +} + +impl<I> Future for JoinAll<I> + where I: IntoIterator, + I::Item: IntoFuture, +{ + type Item = Vec<<I::Item as IntoFuture>::Item>; + type Error = <I::Item as IntoFuture>::Error; + + fn poll(&mut self) -> Result<Self::Item, Self::Error> { + let elems = mem::replace(&mut self.elems, Vec::new()); + Ok(elems.into_iter().map(|e| { + e + }).collect::<Vec<_>>()) + } +} diff --git a/tests/ui/traits/issue-38404.rs b/tests/ui/traits/issue-38404.rs new file mode 100644 index 000000000..1a92acc34 --- /dev/null +++ b/tests/ui/traits/issue-38404.rs @@ -0,0 +1,6 @@ +trait A<T>: std::ops::Add<Self> + Sized {} +trait B<T>: A<T> {} +trait C<T>: A<dyn B<T, Output=usize>> {} +//~^ ERROR the trait `B` cannot be made into an object + +fn main() {} diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr new file mode 100644 index 000000000..d7721d7e6 --- /dev/null +++ b/tests/ui/traits/issue-38404.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/issue-38404.rs:3:15 + | +LL | trait C<T>: A<dyn B<T, Output=usize>> {} + | ^^^^^^^^^^^^^^^^^^^^^^ `B` 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-38404.rs:1:13 + | +LL | trait A<T>: std::ops::Add<Self> + Sized {} + | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter +LL | trait B<T>: A<T> {} + | - 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/tests/ui/traits/issue-38604.rs b/tests/ui/traits/issue-38604.rs new file mode 100644 index 000000000..002a3c43f --- /dev/null +++ b/tests/ui/traits/issue-38604.rs @@ -0,0 +1,16 @@ +trait Q<T:?Sized> {} +trait Foo where u32: Q<Self> { + fn foo(&self); +} + +impl Q<()> for u32 {} +impl Foo for () { + fn foo(&self) { + println!("foo!"); + } +} + +fn main() { + let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object + Box::new(()); //~ ERROR `Foo` cannot be made into an object +} diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr new file mode 100644 index 000000000..50d6fb054 --- /dev/null +++ b/tests/ui/traits/issue-38604.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/issue-38604.rs:14:13 + | +LL | let _f: 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/issue-38604.rs:2:22 + | +LL | trait Foo where u32: Q<Self> { + | --- ^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/issue-38604.rs:15:9 + | +LL | Box::new(()); + | ^^^^^^^^^^^^ `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/issue-38604.rs:2:22 + | +LL | trait Foo where u32: Q<Self> { + | --- ^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + = note: required for `Box<()>` to implement `CoerceUnsized<Box<dyn Foo>>` + = note: required by cast to type `Box<dyn Foo>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-3973.rs b/tests/ui/traits/issue-3973.rs new file mode 100644 index 000000000..a5ed5b870 --- /dev/null +++ b/tests/ui/traits/issue-3973.rs @@ -0,0 +1,25 @@ +struct Point { + x: f64, + y: f64, +} + +trait ToString_ { + fn to_string(&self) -> String; +} + +impl ToString_ for Point { + fn new(x: f64, y: f64) -> Point { + //~^ ERROR method `new` is not a member of trait `ToString_` + Point { x: x, y: y } + } + + fn to_string(&self) -> String { + format!("({}, {})", self.x, self.y) + } +} + +fn main() { + let p = Point::new(0.0, 0.0); + //~^ ERROR no function or associated item named `new` found for struct `Point` + println!("{}", p.to_string()); +} diff --git a/tests/ui/traits/issue-3973.stderr b/tests/ui/traits/issue-3973.stderr new file mode 100644 index 000000000..87ee08049 --- /dev/null +++ b/tests/ui/traits/issue-3973.stderr @@ -0,0 +1,22 @@ +error[E0407]: method `new` is not a member of trait `ToString_` + --> $DIR/issue-3973.rs:11:5 + | +LL | / fn new(x: f64, y: f64) -> Point { +LL | | +LL | | Point { x: x, y: y } +LL | | } + | |_____^ not a member of trait `ToString_` + +error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope + --> $DIR/issue-3973.rs:22:20 + | +LL | struct Point { + | ------------ function or associated item `new` not found for this struct +... +LL | let p = Point::new(0.0, 0.0); + | ^^^ function or associated item not found in `Point` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0407, E0599. +For more information about an error, try `rustc --explain E0407`. diff --git a/tests/ui/traits/issue-4107.rs b/tests/ui/traits/issue-4107.rs new file mode 100644 index 000000000..98433e806 --- /dev/null +++ b/tests/ui/traits/issue-4107.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] + +pub fn main() { + let _id: &Mat2<f64> = &Matrix::identity(1.0); +} + +pub trait Index<Index,Result> { fn get(&self, _: Index) -> Result { panic!() } } +pub trait Dimensional<T>: Index<usize, T> { } + +pub struct Mat2<T> { x: T } +pub struct Vec2<T> { x: T } + +impl<T> Dimensional<Vec2<T>> for Mat2<T> { } +impl<T> Index<usize, Vec2<T>> for Mat2<T> { } + +impl<T> Dimensional<T> for Vec2<T> { } +impl<T> Index<usize, T> for Vec2<T> { } + +pub trait Matrix<T,V>: Dimensional<V> { + fn identity(t:T) -> Self; +} + +impl<T> Matrix<T, Vec2<T>> for Mat2<T> { + fn identity(t:T) -> Mat2<T> { Mat2{ x: t } } +} diff --git a/tests/ui/traits/issue-43132.rs b/tests/ui/traits/issue-43132.rs new file mode 100644 index 000000000..c886f4b0a --- /dev/null +++ b/tests/ui/traits/issue-43132.rs @@ -0,0 +1,65 @@ +// run-pass +#![allow(unused)] + +fn main() { +} + +fn foo() { + let b = mk::< + Forward<(Box<dyn Future<Error = u32>>,)>, + >(); + b.map_err(|_| ()).join(); +} + +fn mk<T>() -> T { + loop {} +} + +impl<I: Future<Error = E>, E> Future for (I,) { + type Error = E; +} + +struct Forward<T: Future> { + _a: T, +} + +impl<T: Future> Future for Forward<T> +where + T::Error: From<u32>, +{ + type Error = T::Error; +} + +trait Future { + type Error; + + fn map_err<F, E>(self, _: F) -> (Self, F) + where + F: FnOnce(Self::Error) -> E, + Self: Sized, + { + loop {} + } + + fn join(self) -> (MaybeDone<Self>, ()) + where + Self: Sized, + { + loop {} + } +} + +impl<S: ?Sized + Future> Future for Box<S> { + type Error = S::Error; +} + +enum MaybeDone<A: Future> { + _Done(A::Error), +} + +impl<U, A: Future, F> Future for (A, F) +where + F: FnOnce(A::Error) -> U, +{ + type Error = U; +} diff --git a/tests/ui/traits/issue-43784-supertrait.rs b/tests/ui/traits/issue-43784-supertrait.rs new file mode 100644 index 000000000..55c26ccd2 --- /dev/null +++ b/tests/ui/traits/issue-43784-supertrait.rs @@ -0,0 +1,10 @@ +pub trait Partial: Copy { +} + +pub trait Complete: Partial { +} + +impl<T> Partial for T where T: Complete {} +impl<T> Complete for T {} //~ ERROR the trait bound `T: Copy` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr new file mode 100644 index 000000000..6b5b72138 --- /dev/null +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-43784-supertrait.rs:8:22 + | +LL | impl<T> Complete for T {} + | ^ the trait `Copy` is not implemented for `T` + | +note: required for `T` to implement `Partial` + --> $DIR/issue-43784-supertrait.rs:1:11 + | +LL | pub trait Partial: Copy { + | ^^^^^^^ +note: required by a bound in `Complete` + --> $DIR/issue-43784-supertrait.rs:4:21 + | +LL | pub trait Complete: Partial { + | ^^^^^^^ required by this bound in `Complete` +help: consider restricting type parameter `T` + | +LL | impl<T: std::marker::Copy> Complete for T {} + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs new file mode 100644 index 000000000..005939e0c --- /dev/null +++ b/tests/ui/traits/issue-50480.rs @@ -0,0 +1,15 @@ +#[derive(Clone, Copy)] +//~^ ERROR the trait `Copy` may not be implemented for this type +struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); +//~^ ERROR cannot find type `NotDefined` in this scope +//~| ERROR cannot find type `NotDefined` in this scope +//~| ERROR cannot find type `N` in this scope +//~| ERROR cannot find type `N` in this scope + +#[derive(Clone, Copy)] +//~^ ERROR the trait `Copy` may not be implemented for this type +struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); +//~^ ERROR cannot find type `NotDefined` in this scope +//~| ERROR cannot find type `N` in this scope + +fn main() {} diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr new file mode 100644 index 000000000..5063fdca0 --- /dev/null +++ b/tests/ui/traits/issue-50480.stderr @@ -0,0 +1,92 @@ +error[E0412]: cannot find type `N` in this scope + --> $DIR/issue-50480.rs:3:12 + | +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo<N>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | +++ + +error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:3:15 + | +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `N` in this scope + --> $DIR/issue-50480.rs:3:12 + | +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo<N>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | +++ + +error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:3:15 + | +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo<NotDefined>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ++++++++++++ + +error[E0412]: cannot find type `N` in this scope + --> $DIR/issue-50480.rs:11:18 + | +LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | struct Bar<T>(T, T, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ~ +help: you might be missing a type parameter + | +LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | +++ + +error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:11:21 + | +LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^ not found in this scope + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/issue-50480.rs:1:17 + | +LL | #[derive(Clone, Copy)] + | ^^^^ +LL | +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | -------- ------ this field does not implement `Copy` + | | + | this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/issue-50480.rs:9:17 + | +LL | #[derive(Clone, Copy)] + | ^^^^ +LL | +LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | -------- ------ this field does not implement `Copy` + | | + | this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0204, E0412. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/issue-52893.rs b/tests/ui/traits/issue-52893.rs new file mode 100644 index 000000000..d72598d5d --- /dev/null +++ b/tests/ui/traits/issue-52893.rs @@ -0,0 +1,57 @@ +// check-fail +// +// regression test for issue 52893 +trait At<Name> { + type AtRes; + fn at(self) -> Self::AtRes; +} + +trait Push<T> { + type PushRes; + fn push(self, other: T) -> Self::PushRes; +} + +trait AddClass<Name, F> { + type AddRes; + fn init(self, func: F); +} + +trait ToRef { + type RefRes; + fn to_ref(&self) -> Self::RefRes; +} + +struct Class<P>(P); + +impl<P> Class<P> { + fn with<Name, F>(self) -> <Self as AddClass<Name, F>>::AddRes + where + Self: AddClass<Name, F>, + { + todo!() + } + + fn from<F>(self) -> <Self as AddClass<P, F>>::AddRes + where + Self: AddClass<P, F>, + { + todo!() + } +} + +impl<F, Name, P> AddClass<Name, F> for Class<P> +where + Self: At<Name>, + <Self as At<Name>>::AtRes: Push<F>, + <<Self as At<Name>>::AtRes as Push<F>>::PushRes: ToRef<RefRes = Self> + Push<F>, +{ + type AddRes = (); + + fn init(self, func: F) { + let builder = self.at().push(func); + let output = builder.to_ref(); + builder.push(output); //~ ERROR mismatched types [E0308] + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr new file mode 100644 index 000000000..a11867c03 --- /dev/null +++ b/tests/ui/traits/issue-52893.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> $DIR/issue-52893.rs:53:22 + | +LL | impl<F, Name, P> AddClass<Name, F> for Class<P> + | - this type parameter +... +LL | builder.push(output); + | ---- ^^^^^^ expected type parameter `F`, found struct `Class` + | | + | arguments to this method are incorrect + | + = note: expected type parameter `F` + found struct `Class<P>` +help: the return type of this call is `Class<P>` due to the type of the argument passed + --> $DIR/issue-52893.rs:53:9 + | +LL | builder.push(output); + | ^^^^^^^^^^^^^------^ + | | + | this argument influences the return type of `push` +note: associated function defined here + --> $DIR/issue-52893.rs:11:8 + | +LL | fn push(self, other: T) -> Self::PushRes; + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/issue-56202.rs b/tests/ui/traits/issue-56202.rs new file mode 100644 index 000000000..0952843e6 --- /dev/null +++ b/tests/ui/traits/issue-56202.rs @@ -0,0 +1,17 @@ +// build-pass + +trait FooTrait {} + +trait BarTrait { + fn foo<T: FooTrait>(_: T) -> Self; +} + +struct FooStruct(u32); + +impl BarTrait for FooStruct { + fn foo<T: FooTrait>(_: T) -> Self { + Self(u32::default()) + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-56488.rs b/tests/ui/traits/issue-56488.rs new file mode 100644 index 000000000..e2f399692 --- /dev/null +++ b/tests/ui/traits/issue-56488.rs @@ -0,0 +1,13 @@ +// run-pass + +#![feature(trait_alias)] + +mod alpha { + pub trait A {} + pub trait C = A; +} + +#[allow(unused_imports)] +use alpha::C; + +fn main() {} diff --git a/tests/ui/traits/issue-59029-1.rs b/tests/ui/traits/issue-59029-1.rs new file mode 100644 index 000000000..8ab47a4af --- /dev/null +++ b/tests/ui/traits/issue-59029-1.rs @@ -0,0 +1,9 @@ +#![feature(trait_alias)] + +trait Svc<Req> { type Res; } + +trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>; +//~^ ERROR associated type `Res` not found for `Self` +//~| ERROR associated type `Res` not found for `Self` + +fn main() {} diff --git a/tests/ui/traits/issue-59029-1.stderr b/tests/ui/traits/issue-59029-1.stderr new file mode 100644 index 000000000..203a89285 --- /dev/null +++ b/tests/ui/traits/issue-59029-1.stderr @@ -0,0 +1,15 @@ +error[E0220]: associated type `Res` not found for `Self` + --> $DIR/issue-59029-1.rs:5:52 + | +LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>; + | ^^^ there is a similarly named associated type `Res` in the trait `Svc` + +error[E0220]: associated type `Res` not found for `Self` + --> $DIR/issue-59029-1.rs:5:52 + | +LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>; + | ^^^ there is a similarly named associated type `Res` in the trait `Svc` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/traits/issue-59029-2.rs b/tests/ui/traits/issue-59029-2.rs new file mode 100644 index 000000000..2bdb128d8 --- /dev/null +++ b/tests/ui/traits/issue-59029-2.rs @@ -0,0 +1,8 @@ +// run-pass +#![feature(trait_alias)] + +trait Svc<Req> { type Res; } + +trait MkSvc<Target, Req> = Svc<Target> where <Self as Svc<Target>>::Res: Svc<Req>; + +fn main() {} diff --git a/tests/ui/traits/issue-6128.rs b/tests/ui/traits/issue-6128.rs new file mode 100644 index 000000000..07d92f8f8 --- /dev/null +++ b/tests/ui/traits/issue-6128.rs @@ -0,0 +1,22 @@ +// run-pass + +use std::collections::HashMap; + +trait Graph<Node, Edge> { + fn f(&self, _: Edge); + fn g(&self, _: Node); +} + +impl<E> Graph<isize, E> for HashMap<isize, isize> { + fn f(&self, _e: E) { + panic!(); + } + fn g(&self, _e: isize) { + panic!(); + } +} + +pub fn main() { + let g : Box<HashMap<isize,isize>> = Box::new(HashMap::new()); + let _g2 : Box<dyn Graph<isize,isize>> = g as Box<dyn Graph<isize,isize>>; +} diff --git a/tests/ui/traits/issue-6334.rs b/tests/ui/traits/issue-6334.rs new file mode 100644 index 000000000..acf48da15 --- /dev/null +++ b/tests/ui/traits/issue-6334.rs @@ -0,0 +1,46 @@ +// run-pass +// Tests that everything still compiles and runs fine even when +// we reorder the bounds. + + +trait A { + fn a(&self) -> usize; +} + +trait B { + fn b(&self) -> usize; +} + +trait C { + fn combine<T:A+B>(&self, t: &T) -> usize; +} + +struct Foo; + +impl A for Foo { + fn a(&self) -> usize { 1 } +} + +impl B for Foo { + fn b(&self) -> usize { 2 } +} + +struct Bar; + +impl C for Bar { + // Note below: bounds in impl decl are in reverse order. + fn combine<T:B+A>(&self, t: &T) -> usize { + (t.a() * 100) + t.b() + } +} + +fn use_c<S:C, T:B+A>(s: &S, t: &T) -> usize { + s.combine(t) +} + +pub fn main() { + let foo = Foo; + let bar = Bar; + let r = use_c(&bar, &foo); + assert_eq!(r, 102); +} diff --git a/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs new file mode 100644 index 000000000..018ce0459 --- /dev/null +++ b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs @@ -0,0 +1,11 @@ +trait Foo { + fn foo(&self); +} + +trait Bar {} + +fn do_stuff<T : Bar>(t : T) { + t.foo() //~ ERROR no method named `foo` found +} + +fn main() {} diff --git a/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr new file mode 100644 index 000000000..ae33e61d8 --- /dev/null +++ b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `foo` found for type parameter `T` in the current scope + --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7 + | +LL | fn do_stuff<T : Bar>(t : T) { + | - method `foo` not found for this type parameter +LL | t.foo() + | ^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `foo`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn do_stuff<T : Bar + Foo>(t : T) { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/issue-65673.rs b/tests/ui/traits/issue-65673.rs new file mode 100644 index 000000000..e5c2fccb2 --- /dev/null +++ b/tests/ui/traits/issue-65673.rs @@ -0,0 +1,12 @@ +#![feature(trait_alias)] // Enabled to reduce stderr output, but can be triggered even if disabled. +trait Trait {} +trait WithType { + type Ctx; +} +trait Alias<T> = where T: Trait; + +impl<T> WithType for T { + type Ctx = dyn Alias<T>; + //~^ ERROR at least one trait is required for an object type [E0224] +} +fn main() {} diff --git a/tests/ui/traits/issue-65673.stderr b/tests/ui/traits/issue-65673.stderr new file mode 100644 index 000000000..8f01d7c53 --- /dev/null +++ b/tests/ui/traits/issue-65673.stderr @@ -0,0 +1,12 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-65673.rs:9:16 + | +LL | trait Alias<T> = where T: Trait; + | -------------- this alias does not contain a trait +... +LL | type Ctx = dyn Alias<T>; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/issue-68295.rs b/tests/ui/traits/issue-68295.rs new file mode 100644 index 000000000..7ff54539a --- /dev/null +++ b/tests/ui/traits/issue-68295.rs @@ -0,0 +1,47 @@ +// check-fail +// +// regression test for #68295 + +struct Matrix<R, C, S>(R, C, S); + +impl<R, C, S> Matrix<R, C, S> { + fn into_owned(self) -> Matrix<R, C, Owned<R, C, ()>> + where + (): Allocator<R, C>, + { + unimplemented!() + } +} + +impl<D, S> Matrix<D, D, S> { + fn hermitian_part(&self) -> Matrix<D, D, Owned<D, D, ()>> + where + (): Allocator<D, D>, + { + unimplemented!() + } +} + +trait Allocator<R, C> { + type Buffer; +} + +trait Trait<R, C, A> { + type Power; +} + +impl<R, C, A: Allocator<R, C>> Trait<R, C, A> for () { + type Power = A::Buffer; +} + +type Owned<R, C, G> = <G as Trait<R, C, ()>>::Power; + +fn crash<R, C>(input: Matrix<R, C, ()>) -> Matrix<R, C, u32> +where + (): Allocator<R, C>, +{ + input.into_owned() + //~^ ERROR mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/traits/issue-68295.stderr b/tests/ui/traits/issue-68295.stderr new file mode 100644 index 000000000..cb6e6e076 --- /dev/null +++ b/tests/ui/traits/issue-68295.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-68295.rs:43:5 + | +LL | fn crash<R, C>(input: Matrix<R, C, ()>) -> Matrix<R, C, u32> + | ----------------- expected `Matrix<R, C, u32>` because of return type +... +LL | input.into_owned() + | ^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type + | + = note: expected struct `Matrix<_, _, u32>` + found struct `Matrix<_, _, <() as Allocator<R, C>>::Buffer>` + = help: consider constraining the associated type `<() as Allocator<R, C>>::Buffer` to `u32` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/issue-7013.rs b/tests/ui/traits/issue-7013.rs new file mode 100644 index 000000000..1fb01303c --- /dev/null +++ b/tests/ui/traits/issue-7013.rs @@ -0,0 +1,26 @@ +use std::cell::RefCell; +use std::rc::Rc; + +trait Foo { + fn set(&mut self, v: Rc<RefCell<A>>); +} + +struct B { + v: Option<Rc<RefCell<A>>> +} + +impl Foo for B { + fn set(&mut self, v: Rc<RefCell<A>>) + { + self.v = Some(v); + } +} + +struct A { + v: Box<dyn Foo + Send>, +} + +fn main() { + let a = A {v: Box::new(B{v: None}) as Box<dyn Foo + Send>}; + //~^ ERROR `Rc<RefCell<A>>` cannot be sent between threads safely +} diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr new file mode 100644 index 000000000..4575f4dba --- /dev/null +++ b/tests/ui/traits/issue-7013.stderr @@ -0,0 +1,18 @@ +error[E0277]: `Rc<RefCell<A>>` cannot be sent between threads safely + --> $DIR/issue-7013.rs:24:19 + | +LL | let a = A {v: Box::new(B{v: None}) as Box<dyn Foo + Send>}; + | ^^^^^^^^^^^^^^^^^^^^ `Rc<RefCell<A>>` cannot be sent between threads safely + | + = help: within `B`, the trait `Send` is not implemented for `Rc<RefCell<A>>` + = note: required because it appears within the type `Option<Rc<RefCell<A>>>` +note: required because it appears within the type `B` + --> $DIR/issue-7013.rs:8:8 + | +LL | struct B { + | ^ + = note: required for the cast from `B` to the object type `dyn Foo + Send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-70944.rs b/tests/ui/traits/issue-70944.rs new file mode 100644 index 000000000..3286de9d5 --- /dev/null +++ b/tests/ui/traits/issue-70944.rs @@ -0,0 +1,23 @@ +// check-pass +// Regression test of #70944, should compile fine. + +use std::ops::Index; + +pub struct KeyA; +pub struct KeyB; +pub struct KeyC; + +pub trait Foo: Index<KeyA> + Index<KeyB> + Index<KeyC> {} +pub trait FooBuilder { + type Inner: Foo; + fn inner(&self) -> &Self::Inner; +} + +pub fn do_stuff(foo: &impl FooBuilder) { + let inner = foo.inner(); + &inner[KeyA]; + &inner[KeyB]; + &inner[KeyC]; +} + +fn main() {} diff --git a/tests/ui/traits/issue-71036.rs b/tests/ui/traits/issue-71036.rs new file mode 100644 index 000000000..69eed0c04 --- /dev/null +++ b/tests/ui/traits/issue-71036.rs @@ -0,0 +1,17 @@ +#![feature(unsize, dispatch_from_dyn)] + +use std::marker::Unsize; +use std::ops::DispatchFromDyn; + +#[allow(unused)] +struct Foo<'a, T: ?Sized> { + _inner: &'a &'a T, +} + +impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {} +//~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied +//~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T` +//~| NOTE all implementations of `Unsize` are provided automatically by the compiler +//~| NOTE required for + +fn main() {} diff --git a/tests/ui/traits/issue-71036.stderr b/tests/ui/traits/issue-71036.stderr new file mode 100644 index 000000000..79eb7a2ae --- /dev/null +++ b/tests/ui/traits/issue-71036.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied + --> $DIR/issue-71036.rs:11:1 + | +LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T` + | + = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information + = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-71136.rs b/tests/ui/traits/issue-71136.rs new file mode 100644 index 000000000..b21756e2b --- /dev/null +++ b/tests/ui/traits/issue-71136.rs @@ -0,0 +1,8 @@ +struct Foo(u8); + +#[derive(Clone)] +struct FooHolster { + the_foos: Vec<Foo>, //~ERROR Clone +} + +fn main() {} diff --git a/tests/ui/traits/issue-71136.stderr b/tests/ui/traits/issue-71136.stderr new file mode 100644 index 000000000..f54173392 --- /dev/null +++ b/tests/ui/traits/issue-71136.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Foo: Clone` is not satisfied + --> $DIR/issue-71136.rs:5:5 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct FooHolster { +LL | the_foos: Vec<Foo>, + | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo` + | + = note: required for `Vec<Foo>` to implement `Clone` + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Foo` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-72410.rs b/tests/ui/traits/issue-72410.rs new file mode 100644 index 000000000..c95f1dfdc --- /dev/null +++ b/tests/ui/traits/issue-72410.rs @@ -0,0 +1,18 @@ +// Regression test for #72410, this should be used with debug assertion enabled. + +// should be fine +pub trait Foo { + fn map() + where + Self: Sized, + for<'a> &'a mut [u8]: ; +} + +// should fail +pub trait Bar { + fn map() + where for<'a> &'a mut [dyn Bar]: ; + //~^ ERROR: the trait `Bar` cannot be made into an object +} + +fn main() {} diff --git a/tests/ui/traits/issue-72410.stderr b/tests/ui/traits/issue-72410.stderr new file mode 100644 index 000000000..c7beb834b --- /dev/null +++ b/tests/ui/traits/issue-72410.stderr @@ -0,0 +1,25 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-72410.rs:14:19 + | +LL | where for<'a> &'a mut [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/issue-72410.rs:13:8 + | +LL | pub trait Bar { + | --- this trait cannot be made into an object... +LL | fn map() + | ^^^ ...because associated function `map` has no `self` parameter +help: consider turning `map` into a method by giving it a `&self` argument + | +LL | fn map(&self) + | +++++ +help: alternatively, consider constraining `map` so it does not apply to trait objects + | +LL | where for<'a> &'a mut [dyn Bar]:, Self: Sized ; + | +++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-72455.rs b/tests/ui/traits/issue-72455.rs new file mode 100644 index 000000000..b6c3bb222 --- /dev/null +++ b/tests/ui/traits/issue-72455.rs @@ -0,0 +1,27 @@ +// check-pass + +pub trait ResultExt { + type Ok; + fn err_eprint_and_ignore(self) -> Option<Self::Ok>; +} + +impl<O, E> ResultExt for std::result::Result<O, E> +where + E: std::error::Error, +{ + type Ok = O; + fn err_eprint_and_ignore(self) -> Option<O> + where + Self: , + { + match self { + Err(e) => { + eprintln!("{}", e); + None + } + Ok(o) => Some(o), + } + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-75627.rs b/tests/ui/traits/issue-75627.rs new file mode 100644 index 000000000..93a2ec1cc --- /dev/null +++ b/tests/ui/traits/issue-75627.rs @@ -0,0 +1,6 @@ +struct Foo<T>(T, *const ()); + +unsafe impl Send for Foo<T> {} +//~^ ERROR cannot find type + +fn main() {} diff --git a/tests/ui/traits/issue-75627.stderr b/tests/ui/traits/issue-75627.stderr new file mode 100644 index 000000000..1675edc9f --- /dev/null +++ b/tests/ui/traits/issue-75627.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/issue-75627.rs:3:26 + | +LL | unsafe impl Send for Foo<T> {} + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | unsafe impl<T> Send for Foo<T> {} + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/issue-77982.rs b/tests/ui/traits/issue-77982.rs new file mode 100644 index 000000000..f5be6cf21 --- /dev/null +++ b/tests/ui/traits/issue-77982.rs @@ -0,0 +1,41 @@ +use std::collections::HashMap; + +fn what() { + let descr = String::new(); + let mut opts = HashMap::<String, ()>::new(); + let opt = String::new(); + + opts.get(opt.as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed +} + +fn main() { + let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); + //~^ ERROR type annotations needed +} + +trait Foo<'a, T: ?Sized> { + fn foo(&self) -> Box<T> { + todo!() + } +} + +trait Bar<'a, T: ?Sized> { + fn bar(&self) -> Box<T> { + todo!() + } +} + +impl Foo<'static, u32> for () {} +impl<'a> Foo<'a, i16> for () {} + +impl<'a> Bar<'static, u32> for &'a () {} +impl<'a> Bar<'a, i16> for &'a () {} + +fn foo() { + let _ = ().foo(); //~ ERROR type annotations needed +} + +fn bar() { + let _ = (&()).bar(); //~ ERROR type annotations needed +} diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr new file mode 100644 index 000000000..0b57a8212 --- /dev/null +++ b/tests/ui/traits/issue-77982.stderr @@ -0,0 +1,98 @@ +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:8:10 + | +LL | opts.get(opt.as_ref()); + | ^^^ ------------ type must be known at this point + | | + | cannot infer type of the type parameter `Q` declared on the associated function `get` + | + = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: + - impl Borrow<str> for String; + - impl<T> Borrow<T> for T + where T: ?Sized; +note: required by a bound in `HashMap::<K, V, S>::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL +help: consider specifying the generic argument + | +LL | opts.get::<Q>(opt.as_ref()); + | +++++ + +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:8:10 + | +LL | opts.get(opt.as_ref()); + | ^^^ ------ type must be known at this point + | | + | cannot infer type of the type parameter `Q` declared on the associated function `get` + | + = note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`: + - impl AsRef<OsStr> for String; + - impl AsRef<Path> for String; + - impl AsRef<[u8]> for String; + - impl AsRef<str> for String; +help: consider specifying the generic argument + | +LL | opts.get::<Q>(opt.as_ref()); + | +++++ + +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:13:59 + | +LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); + | --------- ^^^^ + | | + | required by a bound introduced by this call + | + = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`: + - impl From<Ipv4Addr> for u32; + - impl From<NonZeroU32> for u32; + - impl From<bool> for u32; + - impl From<char> for u32; + - impl From<u16> for u32; + - impl From<u8> for u32; + - impl<T> From<!> for T; + - impl<T> From<T> for T; +help: try using a fully qualified path to specify the expected types + | +LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect(); + | +++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed for `Box<T>` + --> $DIR/issue-77982.rs:36:9 + | +LL | let _ = ().foo(); + | ^ --- type must be known at this point + | +note: multiple `impl`s satisfying `(): Foo<'_, _>` found + --> $DIR/issue-77982.rs:29:1 + | +LL | impl Foo<'static, u32> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> Foo<'a, i16> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: Box<T> = ().foo(); + | ++++++++ + +error[E0283]: type annotations needed for `Box<T>` + --> $DIR/issue-77982.rs:40:9 + | +LL | let _ = (&()).bar(); + | ^ --- type must be known at this point + | +note: multiple `impl`s satisfying `&(): Bar<'_, _>` found + --> $DIR/issue-77982.rs:32:1 + | +LL | impl<'a> Bar<'static, u32> for &'a () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> Bar<'a, i16> for &'a () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: Box<T> = (&()).bar(); + | ++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs new file mode 100644 index 000000000..92f9f4b46 --- /dev/null +++ b/tests/ui/traits/issue-78372.rs @@ -0,0 +1,13 @@ +use std::ops::DispatchFromDyn; //~ ERROR use of unstable library feature 'dispatch_from_dyn' +struct Smaht<T, MISC>(PhantomData); //~ ERROR cannot find type `PhantomData` in this scope +impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U` in this scope +//~^ ERROR cannot find type `MISC` in this scope +//~| ERROR use of unstable library feature 'dispatch_from_dyn' +//~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures +trait Foo: X<u32> {} +trait X<T> { + fn foo(self: Smaht<Self, T>); +} +trait Marker {} +impl Marker for dyn Foo {} +fn main() {} diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr new file mode 100644 index 000000000..8e7fd5f25 --- /dev/null +++ b/tests/ui/traits/issue-78372.stderr @@ -0,0 +1,65 @@ +error[E0412]: cannot find type `PhantomData` in this scope + --> $DIR/issue-78372.rs:2:23 + | +LL | struct Smaht<T, MISC>(PhantomData); + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::marker::PhantomData; + | + +error[E0412]: cannot find type `U` in this scope + --> $DIR/issue-78372.rs:3:31 + | +LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | impl<T> DispatchFromDyn<Smaht<T, MISC>> for T {} + | ~ +help: you might be missing a type parameter + | +LL | impl<T, U> DispatchFromDyn<Smaht<U, MISC>> for T {} + | +++ + +error[E0412]: cannot find type `MISC` in this scope + --> $DIR/issue-78372.rs:3:34 + | +LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} + | ^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl<T, MISC> DispatchFromDyn<Smaht<U, MISC>> for T {} + | ++++++ + +error[E0658]: use of unstable library feature 'dispatch_from_dyn' + --> $DIR/issue-78372.rs:1:5 + | +LL | use std::ops::DispatchFromDyn; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'dispatch_from_dyn' + --> $DIR/issue-78372.rs:3:9 + | +LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable + +error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures + --> $DIR/issue-78372.rs:3:1 + | +LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0378, E0412, E0658. +For more information about an error, try `rustc --explain E0378`. diff --git a/tests/ui/traits/issue-78632.rs b/tests/ui/traits/issue-78632.rs new file mode 100644 index 000000000..c72a2aef4 --- /dev/null +++ b/tests/ui/traits/issue-78632.rs @@ -0,0 +1,59 @@ +// check-pass +// +// Regression test for issue #78632 + +#![crate_type = "lib"] + +pub trait Corge<T> { + type Fred; +} + +impl Corge<u8> for () { + type Fred = u32; +} + +pub trait Waldo { + type Quax; +} + +impl Waldo for u32 { + type Quax = u8; +} + +pub trait Grault +where + (): Corge<Self::Thud>, +{ + type Thud; + fn bar(_: <() as Corge<Self::Thud>>::Fred) {} +} + +impl<T> Grault for T +where + T: Waldo, + (): Corge<T::Quax>, + <() as Corge<T::Quax>>::Fred: Waldo, +{ + type Thud = u8; +} + +pub trait Plugh<I> { + fn baz(); +} + +#[derive(Copy, Clone, Debug)] +pub struct Qiz<T> { + foo: T, +} + +impl<T> Plugh<<() as Corge<T::Thud>>::Fred> for Qiz<T> +where + T: Grault, + (): Corge<T::Thud>, +{ + fn baz() {} +} + +pub fn test() { + <Qiz<u32> as Plugh<u32>>::baz(); +} diff --git a/tests/ui/traits/issue-79458.rs b/tests/ui/traits/issue-79458.rs new file mode 100644 index 000000000..a41add6a1 --- /dev/null +++ b/tests/ui/traits/issue-79458.rs @@ -0,0 +1,10 @@ +// Negative implementations should not be shown in trait suggestions. +// This is a regression test of #79458. + +#[derive(Clone)] +struct Foo<'a, T> { + bar: &'a mut T + //~^ ERROR the trait bound `&mut T: Clone` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/issue-79458.stderr b/tests/ui/traits/issue-79458.stderr new file mode 100644 index 000000000..08f7bbbf0 --- /dev/null +++ b/tests/ui/traits/issue-79458.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `&mut T: Clone` is not satisfied + --> $DIR/issue-79458.rs:6:5 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct Foo<'a, T> { +LL | bar: &'a mut T + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T` + | + = help: the trait `Clone` is implemented for `&T` + = note: `Clone` is implemented for `&T`, but not for `&mut T` + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-8153.rs b/tests/ui/traits/issue-8153.rs new file mode 100644 index 000000000..81a8f5338 --- /dev/null +++ b/tests/ui/traits/issue-8153.rs @@ -0,0 +1,16 @@ +// Test that duplicate methods in impls are not allowed + +struct Foo; + +trait Bar { + fn bar(&self) -> isize; +} + +impl Bar for Foo { + fn bar(&self) -> isize {1} + fn bar(&self) -> isize {2} //~ ERROR duplicate definitions +} + +fn main() { + println!("{}", Foo.bar()); +} diff --git a/tests/ui/traits/issue-8153.stderr b/tests/ui/traits/issue-8153.stderr new file mode 100644 index 000000000..ae214bb9e --- /dev/null +++ b/tests/ui/traits/issue-8153.stderr @@ -0,0 +1,14 @@ +error[E0201]: duplicate definitions with name `bar`: + --> $DIR/issue-8153.rs:11:5 + | +LL | fn bar(&self) -> isize; + | ----------------------- item in trait +... +LL | fn bar(&self) -> isize {1} + | -------------------------- previous definition here +LL | fn bar(&self) -> isize {2} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0201`. diff --git a/tests/ui/traits/issue-82830.rs b/tests/ui/traits/issue-82830.rs new file mode 100644 index 000000000..37bae2e90 --- /dev/null +++ b/tests/ui/traits/issue-82830.rs @@ -0,0 +1,18 @@ +// check-pass + +trait A<Y, N> { + type B; +} + +type MaybeBox<T> = <T as A<T, Box<T>>>::B; +struct P { + t: MaybeBox<P>, +} + +impl<Y, N> A<Y, N> for P { + type B = N; +} + +fn main() { + let t: MaybeBox<P>; +} diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs new file mode 100644 index 000000000..3cd68ff6f --- /dev/null +++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs @@ -0,0 +1,66 @@ +// Regression test for issue #83538. The problem here is that we have +// two cycles: +// +// * `Ty` embeds `Box<Ty>` indirectly, which depends on `Global: 'static`, which is OkModuloRegions. +// * But `Ty` also references `First`, which has a cycle on itself. That should just be `Ok`. +// +// But our caching mechanism was blending both cycles and giving the incorrect result. + +#![feature(rustc_attrs)] +#![allow(bad_style)] + +struct First { + b: Vec<First>, +} + +pub struct Second { + d: Vec<First>, +} + +struct Third<'a, f> { + g: Vec<(f, &'a f)>, +} + +enum Ty { + j(Fourth, Fifth, Sixth), +} + +struct Fourth { + o: Vec<Ty>, +} + +struct Fifth { + bounds: First, +} + +struct Sixth { + p: Box<Ty>, +} + +#[rustc_evaluate_where_clauses] +fn forward<'a>() +where + Vec<First>: Unpin, + Third<'a, Ty>: Unpin, +{ +} + +#[rustc_evaluate_where_clauses] +fn reverse<'a>() +where + Third<'a, Ty>: Unpin, + Vec<First>: Unpin, +{ +} + +fn main() { + // Key is that Vec<First> is "ok" and Third<'_, Ty> is "ok modulo regions": + + forward(); + //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + + reverse(); + //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) +} diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr new file mode 100644 index 000000000..7c4041144 --- /dev/null +++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr @@ -0,0 +1,38 @@ +error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 + | +LL | Vec<First>: Unpin, + | ----- predicate +... +LL | forward(); + | ^^^^^^^ + +error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 + | +LL | Third<'a, Ty>: Unpin, + | ----- predicate +... +LL | forward(); + | ^^^^^^^ + +error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 + | +LL | Third<'a, Ty>: Unpin, + | ----- predicate +... +LL | reverse(); + | ^^^^^^^ + +error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 + | +LL | Vec<First>: Unpin, + | ----- predicate +... +LL | reverse(); + | ^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/issue-84399-bad-fresh-caching.rs b/tests/ui/traits/issue-84399-bad-fresh-caching.rs new file mode 100644 index 000000000..149400156 --- /dev/null +++ b/tests/ui/traits/issue-84399-bad-fresh-caching.rs @@ -0,0 +1,55 @@ +// compile-flags: --crate-type lib +// check-pass +// +// Regression test for issue #84399 +// Tests that we keep the full `ParamEnv` when +// caching predicates with freshened types in the global cache + +use std::marker::PhantomData; +pub trait Allocator<R> { + type Buffer; +} +pub struct DefaultAllocator; +impl <R> Allocator<R> for DefaultAllocator { + type Buffer = (); +} +pub type Owned<R> = <DefaultAllocator as Allocator<R>>::Buffer; +pub type MatrixMN<R> = Matrix<R, Owned<R>>; +pub type Matrix4<N> = Matrix<N, ()>; +pub struct Matrix<R, S> { + pub data: S, + _phantoms: PhantomData<R>, +} +pub fn set_object_transform(matrix: &Matrix4<()>) { + matrix.js_buffer_view(); +} +pub trait Storable { + type Cell; + fn slice_to_items(_buffer: &()) -> &[Self::Cell] { + unimplemented!() + } +} +pub type Cell<T> = <T as Storable>::Cell; +impl<R> Storable for MatrixMN<R> +where + DefaultAllocator: Allocator<R>, +{ + type Cell = (); +} +pub trait JsBufferView { + fn js_buffer_view(&self) -> usize { + unimplemented!() + } +} +impl<R> JsBufferView for [MatrixMN<R>] +where + DefaultAllocator: Allocator<R>, + MatrixMN<R>: Storable, + [Cell<MatrixMN<R>>]: JsBufferView, +{ + fn js_buffer_view(&self) -> usize { + <MatrixMN<R> as Storable>::slice_to_items(&()).js_buffer_view() + } +} +impl JsBufferView for [()] {} +impl<R> JsBufferView for MatrixMN<R> where DefaultAllocator: Allocator<R> {} diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs new file mode 100644 index 000000000..19131684a --- /dev/null +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs @@ -0,0 +1,143 @@ +// compile-flags: --edition=2021 + +#![feature(rustc_attrs)] + +use core::any::Any; +use core::marker::PhantomData; + +fn main() { + test::<MaskedStorage<GenericComp<Pos>>>(make()); + //~^ ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + + test::<MaskedStorage<GenericComp2<Pos>>>(make()); + //~^ ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp2<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + //~| ERROR evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp2<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) +} + +#[rustc_evaluate_where_clauses] +fn test<T: Sized>(_: T) {} + +fn make<T>() -> T { + todo!() +} + +struct DerefWrap<T>(T); + +impl<T> core::ops::Deref for DerefWrap<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +struct Storage<T, D> { + phantom: PhantomData<(T, D)>, +} + +type ReadStorage<T> = Storage<T, DerefWrap<MaskedStorage<T>>>; + +pub trait Component { + type Storage; +} + +struct VecStorage; + +struct Pos; + +impl Component for Pos { + type Storage = VecStorage; +} + +struct GenericComp<T> { + _t: T, +} + +impl<T: 'static> Component for GenericComp<T> { + type Storage = VecStorage; +} + +struct GenericComp2<T> { + _t: T, +} + +impl<T: 'static> Component for GenericComp2<T> where for<'a> &'a bool: 'a { + type Storage = VecStorage; +} + +struct ReadData { + pos_interpdata: ReadStorage<GenericComp<Pos>>, +} + +trait System { + type SystemData; + + fn run(data: Self::SystemData, any: Box<dyn Any>); +} + +struct Sys; + +impl System for Sys { + type SystemData = (ReadData, ReadStorage<Pos>); + + fn run((data, pos): Self::SystemData, any: Box<dyn Any>) { + <ReadStorage<GenericComp<Pos>> as SystemData>::setup(any); + + ParJoin::par_join((&pos, &data.pos_interpdata)); + } +} + +trait ParJoin { + fn par_join(self) + where + Self: Sized, + { + } +} + +impl<'a, T, D> ParJoin for &'a Storage<T, D> +where + T: Component, + D: core::ops::Deref<Target = MaskedStorage<T>>, + T::Storage: Sync, +{ +} + +impl<A, B> ParJoin for (A, B) +where + A: ParJoin, + B: ParJoin, +{ +} + +pub trait SystemData { + fn setup(any: Box<dyn Any>); +} + +impl<T: 'static> SystemData for ReadStorage<T> +where + T: Component, +{ + fn setup(any: Box<dyn Any>) { + let storage: &MaskedStorage<T> = any.downcast_ref().unwrap(); + + <dyn Any as CastFrom<MaskedStorage<T>>>::cast(&storage); + } +} + +pub struct MaskedStorage<T: Component> { + _inner: T::Storage, +} + +pub unsafe trait CastFrom<T> { + fn cast(t: &T) -> &Self; +} + +unsafe impl<T> CastFrom<T> for dyn Any +where + T: Any + 'static, +{ + fn cast(t: &T) -> &Self { + t + } +} diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr new file mode 100644 index 000000000..ebf977dd6 --- /dev/null +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr @@ -0,0 +1,38 @@ +error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 + | +LL | test::<MaskedStorage<GenericComp<Pos>>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test<T: Sized>(_: T) {} + | - predicate + +error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 + | +LL | test::<MaskedStorage<GenericComp<Pos>>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test<T: Sized>(_: T) {} + | ----- predicate + +error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp2<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 + | +LL | test::<MaskedStorage<GenericComp2<Pos>>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test<T: Sized>(_: T) {} + | - predicate + +error: evaluate(Binder(TraitPredicate(<MaskedStorage<GenericComp2<Pos>> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 + | +LL | test::<MaskedStorage<GenericComp2<Pos>>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test<T: Sized>(_: T) {} + | ----- predicate + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/issue-85735.rs b/tests/ui/traits/issue-85735.rs new file mode 100644 index 000000000..fb387a9c9 --- /dev/null +++ b/tests/ui/traits/issue-85735.rs @@ -0,0 +1,13 @@ +// Regression test for the invalid suggestion in #85735 (the +// underlying issue #21974 still exists here). + +trait Foo {} +impl<'a, 'b, T> Foo for T +where + T: FnMut(&'a ()), + //~^ ERROR: type annotations needed + T: FnMut(&'b ()), +{ +} + +fn main() {} diff --git a/tests/ui/traits/issue-85735.stderr b/tests/ui/traits/issue-85735.stderr new file mode 100644 index 000000000..9e80497ca --- /dev/null +++ b/tests/ui/traits/issue-85735.stderr @@ -0,0 +1,18 @@ +error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>` + --> $DIR/issue-85735.rs:7:8 + | +LL | T: FnMut(&'a ()), + | ^^^^^^^^^^^^^ + | +note: multiple `impl`s or `where` clauses satisfying `T: FnMut<(&'a (),)>` found + --> $DIR/issue-85735.rs:7:8 + | +LL | T: FnMut(&'a ()), + | ^^^^^^^^^^^^^ +LL | +LL | T: FnMut(&'b ()), + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/issue-87558.rs b/tests/ui/traits/issue-87558.rs new file mode 100644 index 000000000..c5d86bd63 --- /dev/null +++ b/tests/ui/traits/issue-87558.rs @@ -0,0 +1,9 @@ +struct ErrorKind; +struct Error(ErrorKind); +impl Fn(&isize) for Error { + //~^ ERROR manual implementations of `Fn` are experimental + //~| ERROR associated type bindings are not allowed here + fn from() {} //~ ERROR method `from` is not a member of trait `Fn` +} + +fn main() {} diff --git a/tests/ui/traits/issue-87558.stderr b/tests/ui/traits/issue-87558.stderr new file mode 100644 index 000000000..494274d8c --- /dev/null +++ b/tests/ui/traits/issue-87558.stderr @@ -0,0 +1,24 @@ +error[E0407]: method `from` is not a member of trait `Fn` + --> $DIR/issue-87558.rs:6:5 + | +LL | fn from() {} + | ^^^^^^^^^^^^ not a member of trait `Fn` + +error[E0183]: manual implementations of `Fn` are experimental + --> $DIR/issue-87558.rs:3:6 + | +LL | impl Fn(&isize) for Error { + | ^^^^^^^^^^ manual implementations of `Fn` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-87558.rs:3:6 + | +LL | impl Fn(&isize) for Error { + | ^^^^^^^^^^ associated type not allowed here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0183, E0229, E0407. +For more information about an error, try `rustc --explain E0183`. diff --git a/tests/ui/traits/issue-89119.rs b/tests/ui/traits/issue-89119.rs new file mode 100644 index 000000000..170f69915 --- /dev/null +++ b/tests/ui/traits/issue-89119.rs @@ -0,0 +1,11 @@ +// This is a regression test for issue #89119: an issue in intercrate mode caching. +// +// It requires multiple crates, of course, but the bug is triggered by the code in the dependency, +// not the main crate. This is why this file is empty. +// +// The auxiliary crate used in the test contains the code minimized from `zvariant-2.8.0`. + +// check-pass +// aux-build: issue_89119_intercrate_caching.rs + +fn main() {} diff --git a/tests/ui/traits/issue-90195-2.rs b/tests/ui/traits/issue-90195-2.rs new file mode 100644 index 000000000..b739dc46e --- /dev/null +++ b/tests/ui/traits/issue-90195-2.rs @@ -0,0 +1,20 @@ +// check-pass +pub trait Archive { + type Archived; +} + +impl<T> Archive for Option<T> { + type Archived = (); +} +pub type Archived<T> = <T as Archive>::Archived; + +pub trait Deserialize<D> {} + +const ARRAY_SIZE: usize = 32; +impl<__D> Deserialize<__D> for () +where + Option<[u8; ARRAY_SIZE]>: Archive, + Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>, +{ +} +fn main() {} diff --git a/tests/ui/traits/issue-90195.rs b/tests/ui/traits/issue-90195.rs new file mode 100644 index 000000000..543c9f197 --- /dev/null +++ b/tests/ui/traits/issue-90195.rs @@ -0,0 +1,21 @@ +// check-pass +pub trait Archive { + type Archived; +} + +impl<T> Archive for Option<T> { + type Archived = (); +} +pub type Archived<T> = <T as Archive>::Archived; + +pub trait Deserialize<D> {} + +const ARRAY_SIZE: usize = 32; +impl<__D> Deserialize<__D> for () +where + Option<[u8; ARRAY_SIZE]>: Archive, + Option<[u8; ARRAY_SIZE]>: Archive, + Archived<Option<[u8; ARRAY_SIZE]>>: Deserialize<__D>, +{ +} +fn main() {} diff --git a/tests/ui/traits/issue-90662-projection-caching.rs b/tests/ui/traits/issue-90662-projection-caching.rs new file mode 100644 index 000000000..879f30071 --- /dev/null +++ b/tests/ui/traits/issue-90662-projection-caching.rs @@ -0,0 +1,34 @@ +// check-pass + +// Regression test for issue #90662 +// Tests that projection caching does not cause a spurious error + +trait HasProvider<T: ?Sized> {} +trait Provider<M> { + type Interface: ?Sized; +} + +trait Repository {} +trait Service {} + +struct DbConnection; +impl<M> Provider<M> for DbConnection { + type Interface = DbConnection; +} + +struct RepositoryImpl; +impl<M: HasProvider<DbConnection>> Provider<M> for RepositoryImpl { + type Interface = dyn Repository; +} + +struct ServiceImpl; +impl<M: HasProvider<dyn Repository>> Provider<M> for ServiceImpl { + type Interface = dyn Service; +} + +struct TestModule; +impl HasProvider<<DbConnection as Provider<Self>>::Interface> for TestModule {} +impl HasProvider<<RepositoryImpl as Provider<Self>>::Interface> for TestModule {} +impl HasProvider<<ServiceImpl as Provider<Self>>::Interface> for TestModule {} + +fn main() {} diff --git a/tests/ui/traits/issue-91594.rs b/tests/ui/traits/issue-91594.rs new file mode 100644 index 000000000..930f7f0c6 --- /dev/null +++ b/tests/ui/traits/issue-91594.rs @@ -0,0 +1,17 @@ +// #91594: This used to ICE. + +trait Component<M> { + type Interface; +} +trait HasComponent<I> {} + +struct Foo; + +impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {} +//~^ ERROR the trait bound `Foo: HasComponent<()>` is not satisfied + +impl<M: HasComponent<()>> Component<M> for Foo { + type Interface = u8; +} + +fn main() {} diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr new file mode 100644 index 000000000..85d903fad --- /dev/null +++ b/tests/ui/traits/issue-91594.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied + --> $DIR/issue-91594.rs:10:19 + | +LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` + | + = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo` +note: required for `Foo` to implement `Component<Foo>` + --> $DIR/issue-91594.rs:13:27 + | +LL | impl<M: HasComponent<()>> Component<M> for Foo { + | ---------------- ^^^^^^^^^^^^ ^^^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.rs b/tests/ui/traits/issue-91949-hangs-on-recursion.rs new file mode 100644 index 000000000..6474b2b38 --- /dev/null +++ b/tests/ui/traits/issue-91949-hangs-on-recursion.rs @@ -0,0 +1,32 @@ +// build-fail +// compile-flags: -Zinline-mir=no +// error-pattern: overflow evaluating the requirement `(): Sized` +// error-pattern: function cannot return without recursing +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" + +// Regression test for #91949. +// This hanged *forever* on 1.56, fixed by #90423. + +#![recursion_limit = "256"] + +struct Wrapped<T>(T); + +struct IteratorOfWrapped<T, I: Iterator<Item = T>>(I); + +impl<T, I: Iterator<Item = T>> Iterator for IteratorOfWrapped<T, I> { + type Item = Wrapped<T>; + fn next(&mut self) -> Option<Wrapped<T>> { + self.0.next().map(Wrapped) + } +} + +fn recurse<T>(elements: T) -> Vec<char> +where + T: Iterator<Item = ()>, +{ + recurse(IteratorOfWrapped(elements).map(|t| t.0)) +} + +fn main() { + recurse(std::iter::empty()); +} diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr new file mode 100644 index 000000000..1f18c5daf --- /dev/null +++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -0,0 +1,25 @@ +warning: function cannot return without recursing + --> $DIR/issue-91949-hangs-on-recursion.rs:23:1 + | +LL | / fn recurse<T>(elements: T) -> Vec<char> +LL | | where +LL | | T: Iterator<Item = ()>, + | |___________________________^ cannot return without recursing +LL | { +LL | recurse(IteratorOfWrapped(elements).map(|t| t.0)) + | ------------------------------------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0275]: overflow evaluating the requirement `(): Sized` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`) + = note: required for `std::iter::Empty<()>` to implement `Iterator` + = note: 171 redundant requirements hidden + = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>, ...>>` to implement `Iterator` + = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt' + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/issue-92292.rs b/tests/ui/traits/issue-92292.rs new file mode 100644 index 000000000..bb3700a2b --- /dev/null +++ b/tests/ui/traits/issue-92292.rs @@ -0,0 +1,32 @@ +// check-pass + +use std::marker::PhantomData; + +pub struct MyGenericType<T> { + _marker: PhantomData<*const T>, +} + +pub struct MyNonGenericType; + +impl<T> From<MyGenericType<T>> for MyNonGenericType { + fn from(_: MyGenericType<T>) -> Self { + todo!() + } +} + +pub trait MyTrait { + const MY_CONSTANT: i32; +} + +impl<T> MyTrait for MyGenericType<T> +where + Self: Into<MyNonGenericType>, +{ + const MY_CONSTANT: i32 = 1; +} + +impl<T> MyGenericType<T> { + const MY_OTHER_CONSTANT: i32 = <MyGenericType<T> as MyTrait>::MY_CONSTANT; +} + +fn main() {} diff --git a/tests/ui/traits/issue-9394-inherited-calls.rs b/tests/ui/traits/issue-9394-inherited-calls.rs new file mode 100644 index 000000000..cc0dd4fc1 --- /dev/null +++ b/tests/ui/traits/issue-9394-inherited-calls.rs @@ -0,0 +1,62 @@ +// run-pass + +trait Base: Base2 + Base3{ + fn foo(&self) -> String; + fn foo1(&self) -> String; + fn foo2(&self) -> String{ + "base foo2".to_string() + } +} + +trait Base2: Base3{ + fn baz(&self) -> String; +} + +trait Base3{ + fn root(&self) -> String; +} + +trait Super: Base{ + fn bar(&self) -> String; +} + +struct X; + +impl Base for X { + fn foo(&self) -> String{ + "base foo".to_string() + } + fn foo1(&self) -> String{ + "base foo1".to_string() + } + +} + +impl Base2 for X { + fn baz(&self) -> String{ + "base2 baz".to_string() + } +} + +impl Base3 for X { + fn root(&self) -> String{ + "base3 root".to_string() + } +} + +impl Super for X { + fn bar(&self) -> String{ + "super bar".to_string() + } +} + +pub fn main() { + let n = X; + let s = &n as &dyn Super; + assert_eq!(s.bar(),"super bar".to_string()); + assert_eq!(s.foo(),"base foo".to_string()); + assert_eq!(s.foo1(),"base foo1".to_string()); + assert_eq!(s.foo2(),"base foo2".to_string()); + assert_eq!(s.baz(),"base2 baz".to_string()); + assert_eq!(s.root(),"base3 root".to_string()); +} diff --git a/tests/ui/traits/issue-95311.rs b/tests/ui/traits/issue-95311.rs new file mode 100644 index 000000000..9d40d254a --- /dev/null +++ b/tests/ui/traits/issue-95311.rs @@ -0,0 +1,19 @@ +// check-pass + +// Test to check that pointee trait doesn't let region variables escape into the cache + +#![feature(ptr_metadata)] + +trait Bar: Sized + 'static {} + +struct Foo<B: Bar> { + marker: std::marker::PhantomData<B>, +} + +impl<B: Bar> Foo<B> { + fn foo<T: ?Sized>(value: &T) { + std::ptr::metadata(value); + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-95898.rs b/tests/ui/traits/issue-95898.rs new file mode 100644 index 000000000..41a20b899 --- /dev/null +++ b/tests/ui/traits/issue-95898.rs @@ -0,0 +1,9 @@ +// Test for #95898: The trait suggestion had an extra `:` after the trait. +// edition:2021 + +fn foo<T:>(t: T) { + t.clone(); + //~^ ERROR no method named `clone` found for type parameter `T` in the current scope +} + +fn main() {} diff --git a/tests/ui/traits/issue-95898.stderr b/tests/ui/traits/issue-95898.stderr new file mode 100644 index 000000000..ca7bacdbf --- /dev/null +++ b/tests/ui/traits/issue-95898.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `clone` found for type parameter `T` in the current scope + --> $DIR/issue-95898.rs:5:7 + | +LL | fn foo<T:>(t: T) { + | - method `clone` not found for this type parameter +LL | t.clone(); + | ^^^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `clone`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn foo<T: Clone>(t: T) { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/issue-96664.rs b/tests/ui/traits/issue-96664.rs new file mode 100644 index 000000000..3c5314af7 --- /dev/null +++ b/tests/ui/traits/issue-96664.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(trait_alias)] + +pub trait State = Clone + Send + Sync + PartialOrd + PartialEq + std::fmt::Display; +pub trait RandState<S: State> = FnMut() -> S + Send; + +pub trait Evaluator { + type State; +} + +pub struct Evolver<E: Evaluator> { + rand_state: Box<dyn RandState<E::State>>, +} + +fn main() {} diff --git a/tests/ui/traits/issue-96665.rs b/tests/ui/traits/issue-96665.rs new file mode 100644 index 000000000..a571d48d9 --- /dev/null +++ b/tests/ui/traits/issue-96665.rs @@ -0,0 +1,16 @@ +// check-pass + +pub trait Sequence<Item, Subsequence: Sequence<Item, Subsequence>> {} + +pub trait NodeWalk<Graph: GraphBase, NodeSubwalk: NodeWalk<Graph, NodeSubwalk>>: + Sequence<Graph::NodeIndex, NodeSubwalk> +{ +} + +pub trait GraphBase { + type NodeIndex; +} + +pub trait WalkableGraph: GraphBase {} + +fn main() {} diff --git a/tests/ui/traits/issue-97576.rs b/tests/ui/traits/issue-97576.rs new file mode 100644 index 000000000..fdc85e9fa --- /dev/null +++ b/tests/ui/traits/issue-97576.rs @@ -0,0 +1,13 @@ +struct Foo { + bar: String, +} + +impl Foo { + pub fn new(bar: impl ToString) -> Self { + Self { + bar: bar.into(), //~ ERROR the trait bound `String: From<impl ToString>` is not satisfied + } + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-97576.stderr b/tests/ui/traits/issue-97576.stderr new file mode 100644 index 000000000..9062a0fab --- /dev/null +++ b/tests/ui/traits/issue-97576.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied + --> $DIR/issue-97576.rs:8:22 + | +LL | bar: bar.into(), + | ^^^^ the trait `From<impl ToString>` is not implemented for `String` + | + = note: required for `impl ToString` to implement `Into<String>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-97695-double-trivial-bound.rs b/tests/ui/traits/issue-97695-double-trivial-bound.rs new file mode 100644 index 000000000..213605b51 --- /dev/null +++ b/tests/ui/traits/issue-97695-double-trivial-bound.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zinline-mir --emit=mir +// build-pass + +pub trait Associate { + type Associated; +} + +pub struct Wrap<'a> { + pub field: &'a i32, +} + +pub trait Create<T> { + fn create() -> Self; +} + +pub fn oh_no<'a, T>() +where + Wrap<'a>: Associate, + <Wrap<'a> as Associate>::Associated: Create<T>, +{ + <Wrap<'a> as Associate>::Associated::create(); +} + +pub fn main() {} diff --git a/tests/ui/traits/issue-99875.rs b/tests/ui/traits/issue-99875.rs new file mode 100644 index 000000000..cf73fd8d3 --- /dev/null +++ b/tests/ui/traits/issue-99875.rs @@ -0,0 +1,16 @@ +struct Argument; +struct Return; + +fn function(_: Argument) -> Return { todo!() } + +trait Trait {} +impl Trait for fn(Argument) -> Return {} + +fn takes(_: impl Trait) {} + +fn main() { + takes(function); + //~^ ERROR the trait bound + takes(|_: Argument| -> Return { todo!() }); + //~^ ERROR the trait bound +} diff --git a/tests/ui/traits/issue-99875.stderr b/tests/ui/traits/issue-99875.stderr new file mode 100644 index 000000000..fb6eebbd2 --- /dev/null +++ b/tests/ui/traits/issue-99875.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied + --> $DIR/issue-99875.rs:12:11 + | +LL | takes(function); + | ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `takes` + --> $DIR/issue-99875.rs:9:18 + | +LL | fn takes(_: impl Trait) {} + | ^^^^^ required by this bound in `takes` +help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, try casting using `as` + | +LL | takes(function as fn(Argument) -> Return); + | +++++++++++++++++++++++++ + +error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied + --> $DIR/issue-99875.rs:14:11 + | +LL | takes(|_: Argument| -> Return { todo!() }); + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]` + | | + | required by a bound introduced by this call + | + = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return` +note: required by a bound in `takes` + --> $DIR/issue-99875.rs:9:18 + | +LL | fn takes(_: impl Trait) {} + | ^^^^^ required by this bound in `takes` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/item-inside-macro.rs b/tests/ui/traits/item-inside-macro.rs new file mode 100644 index 000000000..54bf872d0 --- /dev/null +++ b/tests/ui/traits/item-inside-macro.rs @@ -0,0 +1,30 @@ +// run-pass +// Issue #34183 + +macro_rules! foo { + () => { + fn foo() { } + } +} + +macro_rules! bar { + () => { + fn bar(); + } +} + +trait Bleh { + foo!(); + bar!(); +} + +struct Test; + +impl Bleh for Test { + fn bar() {} +} + +fn main() { + Test::bar(); + Test::foo(); +} diff --git a/tests/ui/traits/item-privacy.rs b/tests/ui/traits/item-privacy.rs new file mode 100644 index 000000000..38d06b967 --- /dev/null +++ b/tests/ui/traits/item-privacy.rs @@ -0,0 +1,134 @@ +#![feature(associated_type_defaults)] + +struct S; + +mod method { + trait A { + fn a(&self) { } + } + + pub trait B { + fn b(&self) { } + } + + pub trait C: A + B { + fn c(&self) { } + } + + impl A for ::S {} + impl B for ::S {} + impl C for ::S {} +} + +mod assoc_const { + trait A { + const A: u8 = 0; + } + + pub trait B { + const B: u8 = 0; + } + + pub trait C: A + B { + const C: u8 = 0; + } + + impl A for ::S {} + impl B for ::S {} + impl C for ::S {} +} + +mod assoc_ty { + trait A { + type A = u8; + } + + pub trait B { + type B = u8; + } + + pub trait C: A + B { + type C = u8; + } + + impl A for ::S {} + impl B for ::S {} + impl C for ::S {} +} + +fn check_method() { + // A is private + // B is pub, not in scope + // C : A + B is pub, in scope + use method::C; + + // Methods, method call + // a, b, c are resolved as trait items, their traits need to be in scope + S.a(); //~ ERROR no method named `a` found + S.b(); //~ ERROR no method named `b` found + S.c(); // OK + // a, b, c are resolved as inherent items, their traits don't need to be in scope + let c = &S as &dyn C; + c.a(); //~ ERROR associated function `a` is private + c.b(); // OK + c.c(); // OK + + // Methods, UFCS + // a, b, c are resolved as trait items, their traits need to be in scope + S::a(&S); + //~^ ERROR no function or associated item named `a` found + S::b(&S); + //~^ ERROR no function or associated item named `b` found + S::c(&S); // OK + // a, b, c are resolved as inherent items, their traits don't need to be in scope + <dyn C>::a(&S); //~ ERROR associated function `a` is private + <dyn C>::b(&S); // OK + C::c(&S); // OK +} + +fn check_assoc_const() { + // A is private + // B is pub, not in scope + // C : A + B is pub, in scope + use assoc_const::C; + + // Associated constants + // A, B, C are resolved as trait items, their traits need to be in scope + S::A; //~ ERROR no associated item named `A` found + S::B; //~ ERROR no associated item named `B` found + S::C; // OK + // A, B, C are resolved as inherent items, their traits don't need to be in scope + <dyn C>::A; //~ ERROR associated constant `A` is private + //~^ ERROR the trait `assoc_const::C` cannot be made into an object + <dyn C>::B; // ERROR the trait `assoc_const::C` cannot be made into an object + C::C; // OK +} + +fn check_assoc_ty<T: assoc_ty::C>() { + // A is private + // B is pub, not in scope + // C : A + B is pub, in scope + use assoc_ty::C; + + // Associated types + // A, B, C are resolved as trait items, their traits need to be in scope, not implemented yet + let _: S::A; //~ ERROR ambiguous associated type + let _: S::B; //~ ERROR ambiguous associated type + let _: S::C; //~ ERROR ambiguous associated type + // A, B, C are resolved as inherent items, their traits don't need to be in scope + let _: T::A; //~ ERROR associated type `A` is private + let _: T::B; // OK + let _: T::C; // OK + + // Associated types, bindings + let _: dyn assoc_ty::B< + B = u8, // OK + >; + let _: dyn C< + A = u8, //~ ERROR associated type `A` is private + B = u8, // OK + C = u8, // OK + >; +} + +fn main() {} diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr new file mode 100644 index 000000000..293cfbda8 --- /dev/null +++ b/tests/ui/traits/item-privacy.stderr @@ -0,0 +1,188 @@ +error[E0599]: no method named `a` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:67:7 + | +LL | struct S; + | -------- method `a` not found for this struct +... +LL | S.a(); + | ^ method not found in `S` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `method::A` defines an item `a`, perhaps you need to implement it + --> $DIR/item-privacy.rs:6:5 + | +LL | trait A { + | ^^^^^^^ + +error[E0599]: no method named `b` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:68:7 + | +LL | struct S; + | -------- method `b` not found for this struct +... +LL | fn b(&self) { } + | - the method is available for `S` here +... +LL | S.b(); + | ^ method not found in `S` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use method::B; + | + +error[E0624]: associated function `a` is private + --> $DIR/item-privacy.rs:72:7 + | +LL | fn a(&self) { } + | ----------- private associated function defined here +... +LL | c.a(); + | ^ private associated function + +error[E0599]: no function or associated item named `a` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:78:8 + | +LL | struct S; + | -------- function or associated item `a` not found for this struct +... +LL | S::a(&S); + | ^ function or associated item not found in `S` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `method::A` defines an item `a`, perhaps you need to implement it + --> $DIR/item-privacy.rs:6:5 + | +LL | trait A { + | ^^^^^^^ + +error[E0599]: no function or associated item named `b` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:80:8 + | +LL | struct S; + | -------- function or associated item `b` not found for this struct +... +LL | S::b(&S); + | ^ function or associated item not found in `S` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use method::B; + | + +error[E0624]: associated function `a` is private + --> $DIR/item-privacy.rs:84:14 + | +LL | fn a(&self) { } + | ----------- private associated function defined here +... +LL | <dyn C>::a(&S); + | ^ private associated function + +error[E0599]: no associated item named `A` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:97:8 + | +LL | struct S; + | -------- associated item `A` not found for this struct +... +LL | S::A; + | ^ associated item not found in `S` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `assoc_const::A` defines an item `A`, perhaps you need to implement it + --> $DIR/item-privacy.rs:24:5 + | +LL | trait A { + | ^^^^^^^ + +error[E0599]: no associated item named `B` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:98:8 + | +LL | struct S; + | -------- associated item `B` not found for this struct +... +LL | S::B; + | ^ associated item not found in `S` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use assoc_const::B; + | + +error[E0624]: associated constant `A` is private + --> $DIR/item-privacy.rs:101:14 + | +LL | const A: u8 = 0; + | ----------- private associated constant defined here +... +LL | <dyn C>::A; + | ^ private associated constant + +error[E0038]: the trait `assoc_const::C` cannot be made into an object + --> $DIR/item-privacy.rs:101:6 + | +LL | <dyn C>::A; + | ^^^^^ `assoc_const::C` 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/item-privacy.rs:25:15 + | +LL | const A: u8 = 0; + | ^ ...because it contains this associated `const` +... +LL | const B: u8 = 0; + | ^ ...because it contains this associated `const` +... +LL | pub trait C: A + B { + | - this trait cannot be made into an object... +LL | const C: u8 = 0; + | ^ ...because it contains this associated `const` + = help: consider moving `C` to another trait + = help: consider moving `A` to another trait + = help: consider moving `B` to another trait + +error[E0223]: ambiguous associated type + --> $DIR/item-privacy.rs:115:12 + | +LL | let _: S::A; + | ^^^^ + | +help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path + | +LL | let _: <S as Example>::A; + | ~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/item-privacy.rs:116:12 + | +LL | let _: S::B; + | ^^^^ help: use the fully-qualified path: `<S as assoc_ty::B>::B` + +error[E0223]: ambiguous associated type + --> $DIR/item-privacy.rs:117:12 + | +LL | let _: S::C; + | ^^^^ help: use the fully-qualified path: `<S as assoc_ty::C>::C` + +error[E0624]: associated type `A` is private + --> $DIR/item-privacy.rs:119:12 + | +LL | type A = u8; + | ------ associated type defined here +... +LL | let _: T::A; + | ^^^^ private associated type + +error: associated type `A` is private + --> $DIR/item-privacy.rs:128:9 + | +LL | A = u8, + | ^^^^^^ private associated type + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0038, E0223, E0599, E0624. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/kindck-owned-contains-1.rs b/tests/ui/traits/kindck-owned-contains-1.rs new file mode 100644 index 000000000..8adb06ba3 --- /dev/null +++ b/tests/ui/traits/kindck-owned-contains-1.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(non_snake_case)] +#![allow(non_camel_case_types)] + +trait repeat<A> { fn get(&self) -> A; } + +impl<A:Clone + 'static> repeat<A> for Box<A> { + fn get(&self) -> A { + (**self).clone() + } +} + +fn repeater<A:Clone + 'static>(v: Box<A>) -> Box<dyn repeat<A>+'static> { + Box::new(v) as Box<dyn repeat<A>+'static> // No +} + +pub fn main() { + let x = 3; + let y = repeater(Box::new(x)); + assert_eq!(x, y.get()); +} diff --git a/tests/ui/traits/map-types.rs b/tests/ui/traits/map-types.rs new file mode 100644 index 000000000..dc33b9618 --- /dev/null +++ b/tests/ui/traits/map-types.rs @@ -0,0 +1,19 @@ +use std::collections::HashMap; + + + +trait Map<K, V> +{ + fn get(&self, k: K) -> V { panic!() } +} + +impl<K, V> Map<K, V> for HashMap<K, V> {} + +// Test that trait types printed in error msgs include the type arguments. + +fn main() { + let x: Box<HashMap<isize, isize>> = HashMap::new().into(); + let x: Box<dyn Map<isize, isize>> = x; + let y: Box<dyn Map<usize, isize>> = Box::new(x); + //~^ ERROR `Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied +} diff --git a/tests/ui/traits/map-types.stderr b/tests/ui/traits/map-types.stderr new file mode 100644 index 000000000..f685c50b0 --- /dev/null +++ b/tests/ui/traits/map-types.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied + --> $DIR/map-types.rs:17:41 + | +LL | let y: Box<dyn Map<usize, isize>> = Box::new(x); + | ^^^^^^^^^^^ the trait `Map<usize, isize>` is not implemented for `Box<dyn Map<isize, isize>>` + | + = help: the trait `Map<K, V>` is implemented for `HashMap<K, V>` + = note: required for the cast from `Box<dyn Map<isize, isize>>` to the object type `dyn Map<usize, isize>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/matching-lifetimes.rs b/tests/ui/traits/matching-lifetimes.rs new file mode 100644 index 000000000..1430dc655 --- /dev/null +++ b/tests/ui/traits/matching-lifetimes.rs @@ -0,0 +1,20 @@ +// Tests that the trait matching code takes lifetime parameters into account. +// (Issue #15517.) + +struct Foo<'a,'b> { + x: &'a isize, + y: &'b isize, +} + +trait Tr : Sized { + fn foo(x: Self) {} +} + +impl<'a,'b> Tr for Foo<'a,'b> { + fn foo(x: Foo<'b,'a>) { + //~^ ERROR method not compatible with trait + //~^^ ERROR method not compatible with trait + } +} + +fn main(){} diff --git a/tests/ui/traits/matching-lifetimes.stderr b/tests/ui/traits/matching-lifetimes.stderr new file mode 100644 index 000000000..f8119ed41 --- /dev/null +++ b/tests/ui/traits/matching-lifetimes.stderr @@ -0,0 +1,41 @@ +error[E0308]: method not compatible with trait + --> $DIR/matching-lifetimes.rs:14:5 + | +LL | fn foo(x: Foo<'b,'a>) { + | ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(Foo<'a, 'b>)` + found signature `fn(Foo<'b, 'a>)` +note: the lifetime `'b` as defined here... + --> $DIR/matching-lifetimes.rs:13:9 + | +LL | impl<'a,'b> Tr for Foo<'a,'b> { + | ^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/matching-lifetimes.rs:13:6 + | +LL | impl<'a,'b> Tr for Foo<'a,'b> { + | ^^ + +error[E0308]: method not compatible with trait + --> $DIR/matching-lifetimes.rs:14:5 + | +LL | fn foo(x: Foo<'b,'a>) { + | ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(Foo<'a, 'b>)` + found signature `fn(Foo<'b, 'a>)` +note: the lifetime `'a` as defined here... + --> $DIR/matching-lifetimes.rs:13:6 + | +LL | impl<'a,'b> Tr for Foo<'a,'b> { + | ^^ +note: ...does not necessarily outlive the lifetime `'b` as defined here + --> $DIR/matching-lifetimes.rs:13:9 + | +LL | impl<'a,'b> Tr for Foo<'a,'b> { + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/method-private.rs b/tests/ui/traits/method-private.rs new file mode 100644 index 000000000..4cd184854 --- /dev/null +++ b/tests/ui/traits/method-private.rs @@ -0,0 +1,20 @@ +mod inner { + pub trait Bar { + fn method(&self); + } + + pub struct Foo; + + impl Foo { + fn method(&self) {} + } + + impl Bar for Foo { + fn method(&self) {} + } +} + +fn main() { + let foo = inner::Foo; + foo.method(); //~ ERROR is private +} diff --git a/tests/ui/traits/method-private.stderr b/tests/ui/traits/method-private.stderr new file mode 100644 index 000000000..8e991ec01 --- /dev/null +++ b/tests/ui/traits/method-private.stderr @@ -0,0 +1,18 @@ +error[E0624]: associated function `method` is private + --> $DIR/method-private.rs:19:9 + | +LL | fn method(&self) {} + | ---------------- private associated function defined here +... +LL | foo.method(); + | ^^^^^^ private associated function + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use inner::Bar; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/traits/monad.rs b/tests/ui/traits/monad.rs new file mode 100644 index 000000000..5d0612cf8 --- /dev/null +++ b/tests/ui/traits/monad.rs @@ -0,0 +1,48 @@ +// run-pass + +#![allow(non_camel_case_types)] + + + +trait vec_monad<A> { + fn bind<B, F>(&self, f: F ) -> Vec<B> where F: FnMut(&A) -> Vec<B> ; +} + +impl<A> vec_monad<A> for Vec<A> { + fn bind<B, F>(&self, mut f: F) -> Vec<B> where F: FnMut(&A) -> Vec<B> { + let mut r = Vec::new(); + for elt in self { + r.extend(f(elt)); + } + r + } +} + +trait option_monad<A> { + fn bind<B, F>(&self, f: F) -> Option<B> where F: FnOnce(&A) -> Option<B>; +} + +impl<A> option_monad<A> for Option<A> { + fn bind<B, F>(&self, f: F) -> Option<B> where F: FnOnce(&A) -> Option<B> { + match *self { + Some(ref a) => { f(a) } + None => { None } + } + } +} + +fn transform(x: Option<isize>) -> Option<String> { + x.bind(|n| Some(*n + 1) ).bind(|n| Some(n.to_string()) ) +} + +pub fn main() { + assert_eq!(transform(Some(10)), Some("11".to_string())); + assert_eq!(transform(None), None); + assert_eq!((vec!["hi".to_string()]) + .bind(|x| vec![x.clone(), format!("{}!", x)] ) + .bind(|x| vec![x.clone(), format!("{}?", x)] ), + ["hi".to_string(), + "hi?".to_string(), + "hi!".to_string(), + "hi!?".to_string()]); +} diff --git a/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs b/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs new file mode 100644 index 000000000..bc314a39d --- /dev/null +++ b/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs @@ -0,0 +1,32 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Serializer { +} + +trait Serializable { + fn serialize<S:Serializer>(&self, s: S); +} + +impl Serializable for isize { + fn serialize<S:Serializer>(&self, _s: S) { } +} + +struct F<A> { a: A } + +impl<A:Serializable> Serializable for F<A> { + fn serialize<S:Serializer>(&self, s: S) { + self.a.serialize(s); + } +} + +impl Serializer for isize { +} + +pub fn main() { + let foo = F { a: 1 }; + foo.serialize(1); + + let bar = F { a: F {a: 1 } }; + bar.serialize(2); +} diff --git a/tests/ui/traits/multidispatch-bad.rs b/tests/ui/traits/multidispatch-bad.rs new file mode 100644 index 000000000..b625b9615 --- /dev/null +++ b/tests/ui/traits/multidispatch-bad.rs @@ -0,0 +1,22 @@ +// Test that we detect an illegal combination of types. + +trait Convert<Target> { + fn convert(&self) -> Target; +} + +impl Convert<u32> for i32 { + fn convert(&self) -> u32 { + *self as u32 + } +} + +fn test<T,U>(_: T, _: U) +where T : Convert<U> +{ +} + +fn a() { + test(22i32, 44i32); //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/traits/multidispatch-bad.stderr b/tests/ui/traits/multidispatch-bad.stderr new file mode 100644 index 000000000..d58f1e2d9 --- /dev/null +++ b/tests/ui/traits/multidispatch-bad.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/multidispatch-bad.rs:19:17 + | +LL | test(22i32, 44i32); + | ---- ^^^^^ expected `u32`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/multidispatch-bad.rs:13:4 + | +LL | fn test<T,U>(_: T, _: U) + | ^^^^ ---- +help: change the type of the numeric literal from `i32` to `u32` + | +LL | test(22i32, 44u32); + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs new file mode 100644 index 000000000..f845e198a --- /dev/null +++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that we correctly ignore the blanket impl +// because (in this case) `T` does not impl `Clone`. +// +// Issue #17594. + +use std::cell::RefCell; + +trait Foo { + fn foo(&self) {} +} + +impl<T> Foo for T where T: Clone {} + +struct Bar; + +impl Bar { + fn foo(&self) {} +} + +fn main() { + let b = RefCell::new(Bar); + b.borrow().foo(); +} diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.rs b/tests/ui/traits/multidispatch-convert-ambig-dest.rs new file mode 100644 index 000000000..aa74e11c3 --- /dev/null +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.rs @@ -0,0 +1,31 @@ +// Check that we get an error in a multidisptach scenario where the +// set of impls is ambiguous. + +trait Convert<Target> { + fn convert(&self) -> Target; +} + +impl Convert<i8> for i32 { + fn convert(&self) -> i8 { + *self as i8 + } +} + +impl Convert<i16> for i32 { + fn convert(&self) -> i16 { + *self as i16 + } +} + +fn test<T,U>(_: T, _: U) +where T : Convert<U> +{ +} + +fn a() { + test(22, std::default::Default::default()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr new file mode 100644 index 000000000..6e6172eea --- /dev/null +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr @@ -0,0 +1,43 @@ +error[E0282]: type annotations needed + --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 + | +LL | test(22, std::default::Default::default()); + | ^^^^ cannot infer type of the type parameter `U` declared on the function `test` + | +help: consider specifying the generic arguments + | +LL | test::<i32, U>(22, std::default::Default::default()); + | ++++++++++ + +error[E0283]: type annotations needed + --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 + | +LL | test(22, std::default::Default::default()); + | ^^^^ -------------------------------- type must be known at this point + | | + | cannot infer type of the type parameter `U` declared on the function `test` + | +note: multiple `impl`s satisfying `i32: Convert<_>` found + --> $DIR/multidispatch-convert-ambig-dest.rs:8:1 + | +LL | impl Convert<i8> for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Convert<i16> for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `test` + --> $DIR/multidispatch-convert-ambig-dest.rs:21:11 + | +LL | fn test<T,U>(_: T, _: U) + | ---- required by a bound in this +LL | where T : Convert<U> + | ^^^^^^^^^^ required by this bound in `test` +help: consider specifying the generic arguments + | +LL | test::<i32, U>(22, std::default::Default::default()); + | ++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/multidispatch-infer-convert-target.rs b/tests/ui/traits/multidispatch-infer-convert-target.rs new file mode 100644 index 000000000..626e1ae71 --- /dev/null +++ b/tests/ui/traits/multidispatch-infer-convert-target.rs @@ -0,0 +1,36 @@ +// run-pass +// Test that we can infer the Target based on the Self or vice versa. + + +use std::mem; + +trait Convert<Target> { + fn convert(&self) -> Target; +} + +impl Convert<u32> for i16 { + fn convert(&self) -> u32 { + *self as u32 + } +} + +impl Convert<i16> for u32 { + fn convert(&self) -> i16 { + *self as i16 + } +} + +fn test<T,U>(_: T, _: U, t_size: usize, u_size: usize) +where T : Convert<U> +{ + assert_eq!(mem::size_of::<T>(), t_size); + assert_eq!(mem::size_of::<U>(), u_size); +} + +fn main() { + // T = i16, U = u32 + test(22_i16, Default::default(), 2, 4); + + // T = u32, U = i16 + test(22_u32, Default::default(), 4, 2); +} diff --git a/tests/ui/traits/multidispatch1.rs b/tests/ui/traits/multidispatch1.rs new file mode 100644 index 000000000..f2469e149 --- /dev/null +++ b/tests/ui/traits/multidispatch1.rs @@ -0,0 +1,33 @@ +// run-pass + +use std::fmt::Debug; + +trait MyTrait<T> { + fn get(&self) -> T; +} + +#[derive(Copy, Clone)] +struct MyType { + dummy: usize +} + +impl MyTrait<usize> for MyType { + fn get(&self) -> usize { self.dummy } +} + +impl MyTrait<u8> for MyType { + fn get(&self) -> u8 { self.dummy as u8 } +} + +fn test_eq<T,M>(m: M, v: T) +where T : Eq + Debug, + M : MyTrait<T> +{ + assert_eq!(m.get(), v); +} + +pub fn main() { + let value = MyType { dummy: 256 + 22 }; + test_eq::<usize, _>(value, value.dummy); + test_eq::<u8, _>(value, value.dummy as u8); +} diff --git a/tests/ui/traits/multidispatch2.rs b/tests/ui/traits/multidispatch2.rs new file mode 100644 index 000000000..20608aabb --- /dev/null +++ b/tests/ui/traits/multidispatch2.rs @@ -0,0 +1,39 @@ +// run-pass + +use std::fmt::Debug; +use std::default::Default; + +trait MyTrait<T> { + fn get(&self) -> T; +} + +impl<T> MyTrait<T> for T + where T : Default +{ + fn get(&self) -> T { + Default::default() + } +} + +#[derive(Copy, Clone)] +struct MyType { + dummy: usize +} + +impl MyTrait<usize> for MyType { + fn get(&self) -> usize { self.dummy } +} + +fn test_eq<T,M>(m: M, v: T) +where T : Eq + Debug, + M : MyTrait<T> +{ + assert_eq!(m.get(), v); +} + +pub fn main() { + test_eq(22_usize, 0_usize); + + let value = MyType { dummy: 256 + 22 }; + test_eq(value, value.dummy); +} diff --git a/tests/ui/traits/mutual-recursion-issue-75860.rs b/tests/ui/traits/mutual-recursion-issue-75860.rs new file mode 100644 index 000000000..d7d7307b4 --- /dev/null +++ b/tests/ui/traits/mutual-recursion-issue-75860.rs @@ -0,0 +1,15 @@ +pub fn iso<A, B, F1, F2>(a: F1, b: F2) -> (Box<dyn Fn(A) -> B>, Box<dyn Fn(B) -> A>) + where + F1: (Fn(A) -> B) + 'static, + F2: (Fn(B) -> A) + 'static, +{ + (Box::new(a), Box::new(b)) +} +pub fn iso_un_option<A, B>() -> (Box<dyn Fn(A) -> B>, Box<dyn Fn(B) -> A>) { + let left = |o_a: Option<_>| o_a.unwrap(); + let right = |o_b: Option<_>| o_b.unwrap(); + iso(left, right) + //~^ ERROR overflow +} + +fn main() {} diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr new file mode 100644 index 000000000..23e182738 --- /dev/null +++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr @@ -0,0 +1,13 @@ +error[E0275]: overflow evaluating the requirement `Option<_>: Sized` + --> $DIR/mutual-recursion-issue-75860.rs:11:5 + | +LL | iso(left, right) + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`) +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 E0275`. diff --git a/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs new file mode 100644 index 000000000..0e17f0890 --- /dev/null +++ b/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs @@ -0,0 +1,7 @@ +#![feature(negative_impls)] +#![feature(with_negative_coherence)] + +pub trait ForeignTrait {} + +impl ForeignTrait for u32 {} +impl !ForeignTrait for String {} diff --git a/tests/ui/traits/negative-impls/eager-mono.rs b/tests/ui/traits/negative-impls/eager-mono.rs new file mode 100644 index 000000000..ce770376c --- /dev/null +++ b/tests/ui/traits/negative-impls/eager-mono.rs @@ -0,0 +1,12 @@ +// build-pass +// compile-flags:-C link-dead-code=y + +#![feature(negative_impls)] + +trait Foo { + fn foo() {} +} + +impl !Foo for () {} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs new file mode 100644 index 000000000..17ddaa312 --- /dev/null +++ b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs @@ -0,0 +1,53 @@ +// This tests issue #79683: note in the error message that the trait is +// explicitly unimplemented instead of suggesting to implement it. + +#![feature(negative_impls)] + +struct Qux; +//~^ NOTE method `clone` not found for this +//~^^ NOTE method `foo` not found for this + +impl !Clone for Qux {} + +trait Bar { + fn bar(&self); +} + +impl !Bar for u32 {} + +trait Foo { + fn foo(&self); +} +//~^^^ NOTE `Foo` defines an item `foo`, perhaps you need to implement it + +trait FooBar { + fn foo(&self); +} + +impl !Foo for Qux {} + +impl !FooBar for Qux {} + +impl !FooBar for u32 {} + +fn main() { + Qux.clone(); + //~^ ERROR no method named `clone` found for struct `Qux` + //~| NOTE method not found in `Qux` + //~| NOTE `Clone` defines an item `clone`, but is explicitly unimplemented + + 0_u32.bar(); + //~^ ERROR no method named `bar` found for type `u32` + //~| NOTE method not found in `u32` + //~| NOTE `Bar` defines an item `bar`, but is explicitly unimplemented + + Qux.foo(); + //~^ ERROR no method named `foo` found for struct `Qux` + //~| NOTE method not found in `Qux` + //~| NOTE the following traits define an item `foo`, but are explicitly unimplemented + + 0_u32.foo(); + //~^ ERROR no method named `foo` found for type `u32` + //~| NOTE method not found in `u32` + //~| NOTE `FooBar` defines an item `foo`, but is explicitly unimplemented +} diff --git a/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr new file mode 100644 index 000000000..b29442d7b --- /dev/null +++ b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr @@ -0,0 +1,52 @@ +error[E0599]: no method named `clone` found for struct `Qux` in the current scope + --> $DIR/explicitly-unimplemented-error-message.rs:34:9 + | +LL | struct Qux; + | ---------- method `clone` not found for this struct +... +LL | Qux.clone(); + | ^^^^^ method not found in `Qux` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the trait `Clone` defines an item `clone`, but is explicitly unimplemented + +error[E0599]: no method named `bar` found for type `u32` in the current scope + --> $DIR/explicitly-unimplemented-error-message.rs:39:11 + | +LL | 0_u32.bar(); + | ^^^ method not found in `u32` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the trait `Bar` defines an item `bar`, but is explicitly unimplemented + +error[E0599]: no method named `foo` found for struct `Qux` in the current scope + --> $DIR/explicitly-unimplemented-error-message.rs:44:9 + | +LL | struct Qux; + | ---------- method `foo` not found for this struct +... +LL | Qux.foo(); + | ^^^ method not found in `Qux` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `foo`, but are explicitly unimplemented: + Foo + FooBar + +error[E0599]: no method named `foo` found for type `u32` in the current scope + --> $DIR/explicitly-unimplemented-error-message.rs:49:11 + | +LL | 0_u32.foo(); + | ^^^ method not found in `u32` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo`, perhaps you need to implement it + --> $DIR/explicitly-unimplemented-error-message.rs:18:1 + | +LL | trait Foo { + | ^^^^^^^^^ + = note: the trait `FooBar` defines an item `foo`, but is explicitly unimplemented + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs new file mode 100644 index 000000000..683fd6db6 --- /dev/null +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs @@ -0,0 +1,3 @@ +trait MyTrait {} +impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not yet fully implemented +fn main() {} diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr new file mode 100644 index 000000000..b253fbd0d --- /dev/null +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr @@ -0,0 +1,12 @@ +error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now + --> $DIR/feature-gate-negative_impls.rs:2:6 + | +LL | impl !MyTrait for u32 {} + | ^^^^^^^^ + | + = note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information + = help: add `#![feature(negative_impls)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.rs b/tests/ui/traits/negative-impls/negated-auto-traits-error.rs new file mode 100644 index 000000000..4bdad5dc5 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.rs @@ -0,0 +1,68 @@ +// The dummy functions are used to avoid adding new cfail files. +// What happens is that the compiler attempts to squash duplicates and some +// errors are not reported. This way, we make sure that, for each function, different +// typeck phases are involved and all errors are reported. + +#![feature(negative_impls)] + +use std::marker::Send; + +struct Outer<T: Send>(T); + +struct Outer2<T>(T); + +unsafe impl<T: Send> Sync for Outer2<T> {} + +fn is_send<T: Send>(_: T) {} +fn is_sync<T: Sync>(_: T) {} + +fn dummy() { + struct TestType; + impl !Send for TestType {} + + Outer(TestType); + //~^ ERROR `dummy::TestType` cannot be sent between threads safely + //~| ERROR `dummy::TestType` cannot be sent between threads safely +} + +fn dummy1b() { + struct TestType; + impl !Send for TestType {} + + is_send(TestType); + //~^ ERROR `dummy1b::TestType` cannot be sent between threads safely +} + +fn dummy1c() { + struct TestType; + impl !Send for TestType {} + + is_send((8, TestType)); + //~^ ERROR `dummy1c::TestType` cannot be sent between threads safely +} + +fn dummy2() { + struct TestType; + impl !Send for TestType {} + + is_send(Box::new(TestType)); + //~^ ERROR `dummy2::TestType` cannot be sent between threads safely +} + +fn dummy3() { + struct TestType; + impl !Send for TestType {} + + is_send(Box::new(Outer2(TestType))); + //~^ ERROR `dummy3::TestType` cannot be sent between threads safely +} + +fn main() { + struct TestType; + impl !Send for TestType {} + + // This will complain about a missing Send impl because `Sync` is implement *just* + // for T that are `Send`. Look at #20366 and #19950 + is_sync(Outer2(TestType)); + //~^ ERROR `main::TestType` cannot be sent between threads safely +} diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr new file mode 100644 index 000000000..ce690b749 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -0,0 +1,127 @@ +error[E0277]: `dummy::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:23:11 + | +LL | Outer(TestType); + | ----- ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `dummy::TestType` +note: required by a bound in `Outer` + --> $DIR/negated-auto-traits-error.rs:10:17 + | +LL | struct Outer<T: Send>(T); + | ^^^^ required by this bound in `Outer` + +error[E0277]: `dummy::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:23:5 + | +LL | Outer(TestType); + | ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `dummy::TestType` +note: required by a bound in `Outer` + --> $DIR/negated-auto-traits-error.rs:10:17 + | +LL | struct Outer<T: Send>(T); + | ^^^^ required by this bound in `Outer` + +error[E0277]: `dummy1b::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:32:13 + | +LL | is_send(TestType); + | ------- ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `dummy1b::TestType` +note: required by a bound in `is_send` + --> $DIR/negated-auto-traits-error.rs:16:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error[E0277]: `dummy1c::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:40:13 + | +LL | is_send((8, TestType)); + | ------- ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType` + = note: required because it appears within the type `({integer}, TestType)` +note: required by a bound in `is_send` + --> $DIR/negated-auto-traits-error.rs:16:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error[E0277]: `dummy2::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:48:13 + | +LL | is_send(Box::new(TestType)); + | ------- ^^^^^^^^^^^^^^^^^^ the trait `Send` is not implemented for `Unique<dummy2::TestType>` + | | + | required by a bound introduced by this call + | + = note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied + = note: required for `Unique<dummy2::TestType>` to implement `Send` + = note: required because it appears within the type `Box<TestType>` +note: required by a bound in `is_send` + --> $DIR/negated-auto-traits-error.rs:16:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` +help: consider borrowing here + | +LL | is_send(&Box::new(TestType)); + | + + +error[E0277]: `dummy3::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:56:13 + | +LL | is_send(Box::new(Outer2(TestType))); + | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType` +note: required because it appears within the type `Outer2<TestType>` + --> $DIR/negated-auto-traits-error.rs:12:8 + | +LL | struct Outer2<T>(T); + | ^^^^^^ + = note: required for `Unique<Outer2<dummy3::TestType>>` to implement `Send` + = note: required because it appears within the type `Box<Outer2<TestType>>` +note: required by a bound in `is_send` + --> $DIR/negated-auto-traits-error.rs:16:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error[E0277]: `main::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:66:13 + | +LL | is_sync(Outer2(TestType)); + | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `main::TestType` +note: required for `Outer2<main::TestType>` to implement `Sync` + --> $DIR/negated-auto-traits-error.rs:14:22 + | +LL | unsafe impl<T: Send> Sync for Outer2<T> {} + | ---- ^^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `is_sync` + --> $DIR/negated-auto-traits-error.rs:17:15 + | +LL | fn is_sync<T: Sync>(_: T) {} + | ^^^^ required by this bound in `is_sync` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs new file mode 100644 index 000000000..a1042f831 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_variables)] +#![feature(negative_impls)] + +use std::marker::Send; + +pub struct WaitToken; +impl !Send for WaitToken {} + +pub struct Test<T>(#[allow(unused_tuple_struct_fields)] T); +unsafe impl<T: 'static> Send for Test<T> {} + +pub fn spawn<F>(_: F) -> () where F: FnOnce(), F: Send + 'static {} + +fn main() { + let wt = Test(WaitToken); + spawn(move || { + let x = wt; + println!("Hello, World!"); + }); +} diff --git a/tests/ui/traits/negative-impls/negative-default-impls.rs b/tests/ui/traits/negative-impls/negative-default-impls.rs new file mode 100644 index 000000000..c68bca432 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-default-impls.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait MyTrait { + type Foo; +} + +default impl !MyTrait for u32 {} //~ ERROR negative impls cannot be default impls + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-default-impls.stderr b/tests/ui/traits/negative-impls/negative-default-impls.stderr new file mode 100644 index 000000000..7b54cf542 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-default-impls.stderr @@ -0,0 +1,19 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-default-impls.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0750]: negative impls cannot be default impls + --> $DIR/negative-default-impls.rs:9:1 + | +LL | default impl !MyTrait for u32 {} + | ^^^^^^^ ^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0750`. diff --git a/tests/ui/traits/negative-impls/negative-impls-basic.rs b/tests/ui/traits/negative-impls/negative-impls-basic.rs new file mode 100644 index 000000000..474e03817 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-impls-basic.rs @@ -0,0 +1,17 @@ +// A simple test that we are able to create negative impls, when the +// feature gate is given. +// +// run-pass + +#![feature(negative_impls)] +#![allow(dead_code)] + +struct TestType; + +trait TestTrait { + fn dummy(&self) {} +} + +impl !TestTrait for TestType {} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.rs b/tests/ui/traits/negative-impls/negative-specializes-negative.rs new file mode 100644 index 000000000..35297ab12 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-negative.rs @@ -0,0 +1,13 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(negative_impls)] + +// Test a negative impl that "specializes" another negative impl. +// +// run-pass + +trait MyTrait {} + +impl<T> !MyTrait for T {} +impl !MyTrait for u32 {} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.stderr b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr new file mode 100644 index 000000000..751e29c3b --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-negative.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs new file mode 100644 index 000000000..4281eedaf --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs @@ -0,0 +1,13 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(negative_impls)] + +// Negative impl for u32 cannot "specialize" the base impl. +trait MyTrait { + fn foo(); +} +impl<T> MyTrait for T { + default fn foo() {} +} +impl !MyTrait for u32 {} //~ ERROR E0751 + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr new file mode 100644 index 000000000..1cfa49b20 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr @@ -0,0 +1,22 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-positive-item.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/negative-specializes-positive-item.rs:11:1 + | +LL | impl<T> MyTrait for T { + | --------------------- positive implementation here +... +LL | impl !MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.rs b/tests/ui/traits/negative-impls/negative-specializes-positive.rs new file mode 100644 index 000000000..0e227691e --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-positive.rs @@ -0,0 +1,14 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(negative_impls)] + +// Negative impl for u32 cannot "specialize" the base impl. +trait MyTrait {} +impl<T> MyTrait for T {} +impl !MyTrait for u32 {} //~ ERROR E0751 + +// The second impl specializes the first, no error. +trait MyTrait2 {} +impl<T> MyTrait2 for T {} +impl MyTrait2 for u32 {} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr new file mode 100644 index 000000000..9f9e28678 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-positive.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/negative-specializes-positive.rs:7:1 + | +LL | impl<T> MyTrait for T {} + | --------------------- positive implementation here +LL | impl !MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/no-items.rs b/tests/ui/traits/negative-impls/no-items.rs new file mode 100644 index 000000000..5fc6be9b3 --- /dev/null +++ b/tests/ui/traits/negative-impls/no-items.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] + +trait MyTrait { + type Foo; +} + +impl !MyTrait for u32 { + type Foo = i32; //~ ERROR negative impls cannot have any items +} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/no-items.stderr b/tests/ui/traits/negative-impls/no-items.stderr new file mode 100644 index 000000000..67b94bba1 --- /dev/null +++ b/tests/ui/traits/negative-impls/no-items.stderr @@ -0,0 +1,9 @@ +error[E0749]: negative impls cannot have any items + --> $DIR/no-items.rs:8:5 + | +LL | type Foo = i32; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0749`. diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs new file mode 100644 index 000000000..a5b856465 --- /dev/null +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs @@ -0,0 +1,26 @@ +use std::cell::Cell; +use std::marker::PhantomPinned; +use std::pin::Pin; + +struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned); + +impl<'a> Clone for &'a mut MyType<'a> { + //~^ ERROR E0751 + fn clone(&self) -> &'a mut MyType<'a> { + self.0.take().unwrap() + } +} + +fn main() { + let mut unpinned = MyType(Cell::new(None), PhantomPinned); + let bad_addr = &unpinned as *const MyType<'_> as usize; + let mut p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned)); + + // p_mut1 is okay: it does not point to the bad_addr + let p_mut1: Pin<&mut MyType<'_>> = p.as_mut(); + assert_ne!(bad_addr, &*p_mut1 as *const _ as usize); + + // but p_mut2 does point to bad_addr! this is unsound + let p_mut2: Pin<&mut MyType<'_>> = p_mut1.clone(); + assert_eq!(bad_addr, &*p_mut2 as *const _ as usize); +} diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr new file mode 100644 index 000000000..a87acb1fb --- /dev/null +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr @@ -0,0 +1,11 @@ +error[E0751]: found both positive and negative implementation of trait `Clone` for type `&mut MyType<'_>`: + --> $DIR/pin-unsound-issue-66544-clone.rs:7:1 + | +LL | impl<'a> Clone for &'a mut MyType<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here + | + = note: negative implementation in crate `core` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs new file mode 100644 index 000000000..606cc65a8 --- /dev/null +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs @@ -0,0 +1,33 @@ +// Demonstrate that "rogue" `DerefMut` impls for `&T` are not allowed. +// +// https://github.com/rust-lang/rust/issues/66544 + +use std::cell::Cell; +use std::marker::PhantomPinned; +use std::ops::DerefMut; +use std::pin::Pin; + +struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned); + +impl<'a> DerefMut for &'a MyType<'a> { + //~^ ERROR E0751 + fn deref_mut(&mut self) -> &mut MyType<'a> { + self.0.take().unwrap() + } +} + +fn main() { + let mut unpinned = MyType(Cell::new(None), PhantomPinned); + let bad_addr = &unpinned as *const MyType<'_> as usize; + let p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned)); + + // p_ref is okay: it does not point to the bad_addr + let mut p_ref: Pin<&MyType<'_>> = p.as_ref(); + assert_ne!(bad_addr, &*p_ref as *const _ as usize); + + // but p_mut does point to bad_addr! this is unsound + let p_mut: Pin<&mut MyType<'_>> = p_ref.as_mut(); + assert_eq!(bad_addr, &*p_mut as *const _ as usize); + + println!("oh no!"); +} diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr new file mode 100644 index 000000000..9185e8f84 --- /dev/null +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr @@ -0,0 +1,11 @@ +error[E0751]: found both positive and negative implementation of trait `DerefMut` for type `&MyType<'_>`: + --> $DIR/pin-unsound-issue-66544-derefmut.rs:12:1 + | +LL | impl<'a> DerefMut for &'a MyType<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here + | + = note: negative implementation in crate `core` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.rs b/tests/ui/traits/negative-impls/positive-specializes-negative.rs new file mode 100644 index 000000000..a06b35765 --- /dev/null +++ b/tests/ui/traits/negative-impls/positive-specializes-negative.rs @@ -0,0 +1,9 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(negative_impls)] + +trait MyTrait {} + +impl<T> !MyTrait for T {} +impl MyTrait for u32 {} //~ ERROR E0751 + +fn main() {} diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.stderr b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr new file mode 100644 index 000000000..545f94143 --- /dev/null +++ b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/positive-specializes-negative.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/positive-specializes-negative.rs:7:1 + | +LL | impl<T> !MyTrait for T {} + | ---------------------- negative implementation here +LL | impl MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^ positive implementation here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs new file mode 100644 index 000000000..c1f96ab8c --- /dev/null +++ b/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(with_negative_coherence)] + +// aux-build: foreign_trait.rs + +// Test that we cannot implement `LocalTrait` for `String`, +// even though there is a `String: !ForeignTrait` impl. +// +// This may not be the behavior we want long term, but it's the +// current semantics that we implemented so as to land `!Foo` impls +// quickly. See internals thread: +// +// https://internals.rust-lang.org/t/foo/11587/ + +extern crate foreign_trait; +use foreign_trait::ForeignTrait; + +trait LocalTrait {} +impl<T: ForeignTrait> LocalTrait for T {} +impl LocalTrait for String {} + +fn main() {} diff --git a/tests/ui/traits/new-solver/fn-trait-closure.rs b/tests/ui/traits/new-solver/fn-trait-closure.rs new file mode 100644 index 000000000..c0ecf1c91 --- /dev/null +++ b/tests/ui/traits/new-solver/fn-trait-closure.rs @@ -0,0 +1,15 @@ +// compile-flags: -Ztrait-solver=next +// known-bug: unknown +// failure-status: 101 +// dont-check-compiler-stderr + +// This test will fail until we fix `FulfillmentCtxt::relationships`. That's +// because we create a type variable for closure upvar types, which is not +// constrained until after we try to do fallback on diverging type variables. +// Thus, we will call that function, which is unimplemented. + +fn require_fn(_: impl Fn() -> i32) {} + +fn main() { + require_fn(|| -> i32 { 1i32 }); +} diff --git a/tests/ui/traits/new-solver/fn-trait.rs b/tests/ui/traits/new-solver/fn-trait.rs new file mode 100644 index 000000000..d566ead10 --- /dev/null +++ b/tests/ui/traits/new-solver/fn-trait.rs @@ -0,0 +1,13 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +fn require_fn(_: impl Fn() -> i32) {} + +fn f() -> i32 { + 1i32 +} + +fn main() { + require_fn(f); + require_fn(f as fn() -> i32); +} diff --git a/tests/ui/traits/new-solver/pointer-sized.rs b/tests/ui/traits/new-solver/pointer-sized.rs new file mode 100644 index 000000000..15681cd13 --- /dev/null +++ b/tests/ui/traits/new-solver/pointer-sized.rs @@ -0,0 +1,12 @@ +#![feature(pointer_sized_trait)] + +use std::marker::PointerSized; + +fn require_pointer_sized(_: impl PointerSized) {} + +fn main() { + require_pointer_sized(1usize); + require_pointer_sized(1u16); + //~^ ERROR `u16` needs to be a pointer-sized type + require_pointer_sized(&1i16); +} diff --git a/tests/ui/traits/new-solver/pointer-sized.stderr b/tests/ui/traits/new-solver/pointer-sized.stderr new file mode 100644 index 000000000..b250b1331 --- /dev/null +++ b/tests/ui/traits/new-solver/pointer-sized.stderr @@ -0,0 +1,24 @@ +error[E0277]: `u16` needs to be a pointer-sized type + --> $DIR/pointer-sized.rs:9:27 + | +LL | require_pointer_sized(1u16); + | --------------------- ^^^^ the trait `PointerSized` is not implemented for `u16` + | | + | required by a bound introduced by this call + | + = note: the trait bound `u16: PointerSized` is not satisfied +note: required by a bound in `require_pointer_sized` + --> $DIR/pointer-sized.rs:5:34 + | +LL | fn require_pointer_sized(_: impl PointerSized) {} + | ^^^^^^^^^^^^ required by this bound in `require_pointer_sized` +help: consider borrowing here + | +LL | require_pointer_sized(&1u16); + | + +LL | require_pointer_sized(&mut 1u16); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/no-fallback-multiple-impls.rs b/tests/ui/traits/no-fallback-multiple-impls.rs new file mode 100644 index 000000000..7ed3796f0 --- /dev/null +++ b/tests/ui/traits/no-fallback-multiple-impls.rs @@ -0,0 +1,16 @@ +trait Fallback { + fn foo(&self) {} +} + +impl Fallback for i32 {} + +impl Fallback for u64 {} + +impl Fallback for usize {} + +fn main() { + missing(); + //~^ ERROR cannot find function `missing` in this scope + 0.foo(); + // But then we shouldn't report an inference ambiguity here... +} diff --git a/tests/ui/traits/no-fallback-multiple-impls.stderr b/tests/ui/traits/no-fallback-multiple-impls.stderr new file mode 100644 index 000000000..61c9e5aaa --- /dev/null +++ b/tests/ui/traits/no-fallback-multiple-impls.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `missing` in this scope + --> $DIR/no-fallback-multiple-impls.rs:12:5 + | +LL | missing(); + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/traits/no_send-struct.rs b/tests/ui/traits/no_send-struct.rs new file mode 100644 index 000000000..75a363f9f --- /dev/null +++ b/tests/ui/traits/no_send-struct.rs @@ -0,0 +1,17 @@ +#![feature(negative_impls)] + +use std::marker::Send; + +struct Foo { + a: isize, +} + +impl !Send for Foo {} + +fn bar<T: Send>(_: T) {} + +fn main() { + let x = Foo { a: 5 }; + bar(x); + //~^ ERROR `Foo` cannot be sent between threads safely +} diff --git a/tests/ui/traits/no_send-struct.stderr b/tests/ui/traits/no_send-struct.stderr new file mode 100644 index 000000000..ee7bdf282 --- /dev/null +++ b/tests/ui/traits/no_send-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: `Foo` cannot be sent between threads safely + --> $DIR/no_send-struct.rs:15:9 + | +LL | bar(x); + | --- ^ `Foo` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `Foo` +note: required by a bound in `bar` + --> $DIR/no_send-struct.rs:11:11 + | +LL | fn bar<T: Send>(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/normalize-supertrait.rs b/tests/ui/traits/normalize-supertrait.rs new file mode 100644 index 000000000..021a93eac --- /dev/null +++ b/tests/ui/traits/normalize-supertrait.rs @@ -0,0 +1,37 @@ +// Regression test for #77653 +// When monomorphizing `f` we need to prove `dyn Derived<()>: Base<()>`. This +// requires us to normalize the `Base<<() as Proj>::S>` to `Base<()>` when +// comparing the supertrait `Derived<()>` to the expected trait. + +// build-pass + +trait Proj { + type S; +} + +impl Proj for () { + type S = (); +} + +impl Proj for i32 { + type S = i32; +} + +trait Base<T> { + fn is_base(&self); +} + +trait Derived<B: Proj>: Base<B::S> + Base<()> { + fn is_derived(&self); +} + +fn f<P: Proj>(obj: &dyn Derived<P>) { + obj.is_derived(); + Base::<P::S>::is_base(obj); + Base::<()>::is_base(obj); +} + +fn main() { + let x: fn(_) = f::<()>; + let x: fn(_) = f::<i32>; +} diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs new file mode 100644 index 000000000..538e74ee1 --- /dev/null +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs @@ -0,0 +1,24 @@ +struct A<T>(T); +struct B; + +trait I<T> {} +impl I<i32> for B {} +impl I<u32> for B {} + +trait V<U> { + fn method(self) -> U; +} + +impl<T, U> V<U> for A<T> +where + T: I<U>, +{ + fn method(self) -> U { unimplemented!() } +} + +fn main() { + let a = A(B); + a.method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr new file mode 100644 index 000000000..92d9d32cf --- /dev/null +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr @@ -0,0 +1,41 @@ +error[E0282]: type annotations needed + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7 + | +LL | a.method(); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | <A<B> as V<U>>::method(a); + | +++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7 + | +LL | a.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `B: I<_>` found + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:5:1 + | +LL | impl I<i32> for B {} + | ^^^^^^^^^^^^^^^^^ +LL | impl I<u32> for B {} + | ^^^^^^^^^^^^^^^^^ +note: required for `A<B>` to implement `V<_>` + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:12:12 + | +LL | impl<T, U> V<U> for A<T> + | ^^^^ ^^^^ +LL | where +LL | T: I<U>, + | ---- unsatisfied trait bound introduced here +help: try using a fully qualified path to specify the expected types + | +LL | <A<B> as V<U>>::method(a); + | +++++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/object-does-not-impl-trait.rs b/tests/ui/traits/object-does-not-impl-trait.rs new file mode 100644 index 000000000..b3b679813 --- /dev/null +++ b/tests/ui/traits/object-does-not-impl-trait.rs @@ -0,0 +1,8 @@ +// Test that an object type `Box<Foo>` is not considered to implement the +// trait `Foo`. Issue #5087. + +trait Foo {} +fn take_foo<F:Foo>(f: F) {} +fn take_object(f: Box<dyn Foo>) { take_foo(f); } +//~^ ERROR `Box<dyn Foo>: Foo` is not satisfied +fn main() {} diff --git a/tests/ui/traits/object-does-not-impl-trait.stderr b/tests/ui/traits/object-does-not-impl-trait.stderr new file mode 100644 index 000000000..f1dd508a4 --- /dev/null +++ b/tests/ui/traits/object-does-not-impl-trait.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied + --> $DIR/object-does-not-impl-trait.rs:6:44 + | +LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); } + | -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>` + | | + | required by a bound introduced by this call + | +note: required by a bound in `take_foo` + --> $DIR/object-does-not-impl-trait.rs:5:15 + | +LL | fn take_foo<F:Foo>(f: F) {} + | ^^^ required by this bound in `take_foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/object-one-type-two-traits.rs b/tests/ui/traits/object-one-type-two-traits.rs new file mode 100644 index 000000000..86a2094ee --- /dev/null +++ b/tests/ui/traits/object-one-type-two-traits.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Testing creating two vtables with the same self type, but different +// traits. + +use std::any::Any; + +trait Wrap { + fn get(&self) -> isize; + fn wrap(self: Box<Self>) -> Box<dyn Any+'static>; +} + +impl Wrap for isize { + fn get(&self) -> isize { + *self + } + fn wrap(self: Box<isize>) -> Box<dyn Any+'static> { + self as Box<dyn Any+'static> + } +} + +fn is<T:Any>(x: &dyn Any) -> bool { + x.is::<T>() +} + +fn main() { + let x = Box::new(22isize) as Box<dyn Wrap>; + println!("x={}", x.get()); + let y = x.wrap(); +} diff --git a/tests/ui/traits/object/auto-dedup-in-impl.rs b/tests/ui/traits/object/auto-dedup-in-impl.rs new file mode 100644 index 000000000..85698f194 --- /dev/null +++ b/tests/ui/traits/object/auto-dedup-in-impl.rs @@ -0,0 +1,19 @@ +// Checks to make sure that `dyn Trait + Send` and `dyn Trait + Send + Send` are the same type. +// Issue: #47010 + +struct Struct; +impl Trait for Struct {} +trait Trait {} + +type Send1 = dyn Trait + Send; +type Send2 = dyn Trait + Send + Send; + +fn main () {} + +impl dyn Trait + Send { + fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test` +} + +impl dyn Trait + Send + Send { + fn test(&self) { println!("two"); } +} diff --git a/tests/ui/traits/object/auto-dedup-in-impl.stderr b/tests/ui/traits/object/auto-dedup-in-impl.stderr new file mode 100644 index 000000000..5f13c7813 --- /dev/null +++ b/tests/ui/traits/object/auto-dedup-in-impl.stderr @@ -0,0 +1,12 @@ +error[E0592]: duplicate definitions with name `test` + --> $DIR/auto-dedup-in-impl.rs:14:5 + | +LL | fn test(&self) { println!("one"); } + | ^^^^^^^^^^^^^^ duplicate definitions for `test` +... +LL | fn test(&self) { println!("two"); } + | -------------- other definition for `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/traits/object/auto-dedup.rs b/tests/ui/traits/object/auto-dedup.rs new file mode 100644 index 000000000..39d25eb7f --- /dev/null +++ b/tests/ui/traits/object/auto-dedup.rs @@ -0,0 +1,46 @@ +// run-pass + +#![allow(unused_assignments)] + +// Test that duplicate auto trait bounds in trait objects don't create new types. +#[allow(unused_assignments)] +use std::marker::Send as SendAlias; + +// A dummy trait for the non-auto trait. +trait Trait {} + +// A dummy struct to implement `Trait` and `Send`. +struct Struct; + +impl Trait for Struct {} + +// These three functions should be equivalent. +fn takes_dyn_trait_send(_: Box<dyn Trait + Send>) {} +fn takes_dyn_trait_send_send(_: Box<dyn Trait + Send + Send>) {} +fn takes_dyn_trait_send_sendalias(_: Box<dyn Trait + Send + SendAlias>) {} + +impl dyn Trait + Send + Send { + fn do_nothing(&self) {} +} + +fn main() { + // 1. Moving into a variable with more `Send`s and back. + let mut dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>; + let dyn_trait_send_send: Box<dyn Trait + Send + Send> = dyn_trait_send; + dyn_trait_send = dyn_trait_send_send; + + // 2. Calling methods with different number of `Send`s. + let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>; + takes_dyn_trait_send_send(dyn_trait_send); + + let dyn_trait_send_send = Box::new(Struct) as Box<dyn Trait + Send + Send>; + takes_dyn_trait_send(dyn_trait_send_send); + + // 3. Aliases to the trait are transparent. + let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>; + takes_dyn_trait_send_sendalias(dyn_trait_send); + + // 4. Calling an impl that duplicates an auto trait. + let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>; + dyn_trait_send.do_nothing(); +} diff --git a/tests/ui/traits/object/bounds-cycle-1.rs b/tests/ui/traits/object/bounds-cycle-1.rs new file mode 100644 index 000000000..314676492 --- /dev/null +++ b/tests/ui/traits/object/bounds-cycle-1.rs @@ -0,0 +1,24 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl<U> Is for U { + type T = U; +} + +trait Obj { + type U: Is<T = Self::U>; +} + +fn is_obj<T: ?Sized + Obj>(_: &T) {} + +fn f(x: &dyn Obj<U = i32>) { + is_obj(x) +} + +fn main() {} diff --git a/tests/ui/traits/object/bounds-cycle-2.rs b/tests/ui/traits/object/bounds-cycle-2.rs new file mode 100644 index 000000000..4c1df3805 --- /dev/null +++ b/tests/ui/traits/object/bounds-cycle-2.rs @@ -0,0 +1,28 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl<U> Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is<T = Self::V>; +} + +fn is_obj<T: ?Sized + Obj>(_: &T) {} + +fn f(x: &dyn Obj<U = i32, V = i32>) { + is_obj(x) +} + +fn main() {} diff --git a/tests/ui/traits/object/bounds-cycle-3.rs b/tests/ui/traits/object/bounds-cycle-3.rs new file mode 100644 index 000000000..55726a5ae --- /dev/null +++ b/tests/ui/traits/object/bounds-cycle-3.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl<U> Is for U { + type T = U; +} + +trait Obj { + type U: Is<T = Self::V>; + type V; +} + +fn is_obj<T: ?Sized + Obj>(_: &T) {} + +fn f(x: &dyn Obj<U = i32, V = i32>) { + is_obj(x) +} + +fn main() {} diff --git a/tests/ui/traits/object/bounds-cycle-4.rs b/tests/ui/traits/object/bounds-cycle-4.rs new file mode 100644 index 000000000..f83cb75c7 --- /dev/null +++ b/tests/ui/traits/object/bounds-cycle-4.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. Make sure that having a lifetime on the trait object doesn't break things + +// check-pass + +trait Is { + type T; +} + +impl<U> Is for U { + type T = U; +} + +trait Obj<'a> { + type U: Is<T = Self::V>; + type V; +} + +fn is_obj<'a, T: ?Sized + Obj<'a>>(_: &T) {} + +fn f<'a>(x: &dyn Obj<'a, U = i32, V = i32>) { + is_obj(x) +} + +fn main() {} diff --git a/tests/ui/traits/object/enforce-supertrait-projection.rs b/tests/ui/traits/object/enforce-supertrait-projection.rs new file mode 100644 index 000000000..2c9b41eea --- /dev/null +++ b/tests/ui/traits/object/enforce-supertrait-projection.rs @@ -0,0 +1,24 @@ +trait SuperTrait { + type A; + type B; +} + +trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {} + +fn transmute<A, B>(x: A) -> B { + foo::<A, B, dyn Trait<A = A, B = B>>(x) + //~^ ERROR type mismatch resolving `<dyn Trait<B = B, A = A> as SuperTrait>::A == B` +} + +fn foo<A, B, T: ?Sized>(x: T::A) -> B +where + T: Trait<B = B>, +{ + x +} + +static X: u8 = 0; +fn main() { + let x = transmute::<&u8, &[u8; 1_000_000]>(&X); + println!("{:?}", x[100_000]); +} diff --git a/tests/ui/traits/object/enforce-supertrait-projection.stderr b/tests/ui/traits/object/enforce-supertrait-projection.stderr new file mode 100644 index 000000000..cbf093866 --- /dev/null +++ b/tests/ui/traits/object/enforce-supertrait-projection.stderr @@ -0,0 +1,26 @@ +error[E0271]: type mismatch resolving `<dyn Trait<B = B, A = A> as SuperTrait>::A == B` + --> $DIR/enforce-supertrait-projection.rs:9:17 + | +LL | fn transmute<A, B>(x: A) -> B { + | - - expected type parameter + | | + | found type parameter +LL | foo::<A, B, dyn Trait<A = A, B = B>>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` + | + = note: expected type parameter `B` + found type parameter `A` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +note: required by a bound in `foo` + --> $DIR/enforce-supertrait-projection.rs:15:8 + | +LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B + | --- required by a bound in this +LL | where +LL | T: Trait<B = B>, + | ^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/object/exclusion.rs b/tests/ui/traits/object/exclusion.rs new file mode 100644 index 000000000..766dceeaf --- /dev/null +++ b/tests/ui/traits/object/exclusion.rs @@ -0,0 +1,19 @@ +// run-pass +trait Future: 'static { + // The requirement for Self: Sized must prevent instantiation of + // Future::forget in vtables, otherwise there's an infinite type + // recursion through <Map<...> as Future>::forget. + fn forget(self) where Self: Sized { + Box::new(Map(self)) as Box<dyn Future>; + } +} + +struct Map<A>(#[allow(unused_tuple_struct_fields)] A); +impl<A: Future> Future for Map<A> {} + +pub struct Promise; +impl Future for Promise {} + +fn main() { + Promise.forget(); +} diff --git a/tests/ui/traits/object/generics.rs b/tests/ui/traits/object/generics.rs new file mode 100644 index 000000000..5a4a6aecc --- /dev/null +++ b/tests/ui/traits/object/generics.rs @@ -0,0 +1,41 @@ +// run-pass +// test for #8664 + +use std::marker; + +pub trait Trait2<A> { + fn doit(&self) -> A; +} + +pub struct Impl<A1, A2, A3> { + m1: marker::PhantomData<(A1,A2,A3)>, + /* + * With A2 we get the ICE: + * task <unnamed> failed at 'index out of bounds: the len is 1 but the index is 1', + * src/librustc/middle/subst.rs:58 + */ + t: Box<dyn Trait2<A2>+'static> +} + +impl<A1, A2, A3> Impl<A1, A2, A3> { + pub fn step(&self) { + self.t.doit(); + } +} + +// test for #8601 + +enum Type<T> { Constant(#[allow(unused_tuple_struct_fields)] T) } + +trait Trait<K,V> { + fn method(&self, _: Type<(K,V)>) -> isize; +} + +impl<V> Trait<u8,V> for () { + fn method(&self, _x: Type<(u8,V)>) -> isize { 0 } +} + +pub fn main() { + let a = Box::new(()) as Box<dyn Trait<u8, u8>>; + assert_eq!(a.method(Type::Constant((1, 2))), 0); +} diff --git a/tests/ui/traits/object/issue-33140-traitobject-crate.rs b/tests/ui/traits/object/issue-33140-traitobject-crate.rs new file mode 100644 index 000000000..8abd92da3 --- /dev/null +++ b/tests/ui/traits/object/issue-33140-traitobject-crate.rs @@ -0,0 +1,108 @@ +// check-pass + +#![warn(order_dependent_trait_objects)] +#![allow(dyn_drop)] + +// Check that traitobject 0.1.0 compiles + +//! # traitobject +//! +//! Unsafe helpers for working with raw TraitObjects. + +/// A trait implemented for all trait objects. +/// +/// Implementations for all traits in std are provided. +pub unsafe trait Trait {} + +unsafe impl Trait for dyn (::std::any::Any) + Send { } +unsafe impl Trait for dyn (::std::any::Any) + Sync { } +unsafe impl Trait for dyn (::std::any::Any) + Send + Sync { } +unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Send { } +unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Sync { } +unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Send + Sync { } +unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Send { } +unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Sync { } +unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Send + Sync { } +unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Send { } +unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Sync { } +unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Send + Sync { } +unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Send { } +unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Sync { } +unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Send + Sync { } +unsafe impl Trait for dyn (::std::error::Error) + Send { } +unsafe impl Trait for dyn (::std::error::Error) + Sync { } +unsafe impl Trait for dyn (::std::error::Error) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Send { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Send { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Display) + Send { } +unsafe impl Trait for dyn (::std::fmt::Display) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Display) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Send { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Send { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Write) + Send { } +unsafe impl Trait for dyn (::std::fmt::Write) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Write) + Send + Sync { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Send { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Sync { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::BufRead) + Send { } +unsafe impl Trait for dyn (::std::io::BufRead) + Sync { } +unsafe impl Trait for dyn (::std::io::BufRead) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Read) + Send { } +unsafe impl Trait for dyn (::std::io::Read) + Sync { } +unsafe impl Trait for dyn (::std::io::Read) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Seek) + Send { } +unsafe impl Trait for dyn (::std::io::Seek) + Sync { } +unsafe impl Trait for dyn (::std::io::Seek) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Write) + Send { } +unsafe impl Trait for dyn (::std::io::Write) + Sync { } +unsafe impl Trait for dyn (::std::io::Write) + Send + Sync { } +unsafe impl<T, I> Trait for dyn (::std::iter::IntoIterator<IntoIter=I, Item=T>) { } +unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Send { } +unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Sync { } +unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Send + Sync { } +unsafe impl Trait for dyn (::std::marker::Send) + Send { } +unsafe impl Trait for dyn (::std::marker::Send) + Sync { } +unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::marker::Sync) + Send { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::marker::Sync) + Sync { } +unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::ops::Drop) + Send { } +unsafe impl Trait for dyn (::std::ops::Drop) + Sync { } +unsafe impl Trait for dyn (::std::ops::Drop) + Send + Sync { } +unsafe impl Trait for dyn (::std::string::ToString) + Send { } +unsafe impl Trait for dyn (::std::string::ToString) + Sync { } +unsafe impl Trait for dyn (::std::string::ToString) + Send + Sync { } +fn assert_trait<T: Trait + ?Sized>() {} + +fn main() { + assert_trait::<dyn Send>(); + assert_trait::<dyn Sync>(); + assert_trait::<dyn Send + Sync>(); +} diff --git a/tests/ui/traits/object/issue-33140-traitobject-crate.stderr b/tests/ui/traits/object/issue-33140-traitobject-crate.stderr new file mode 100644 index 000000000..525401f9d --- /dev/null +++ b/tests/ui/traits/object/issue-33140-traitobject-crate.stderr @@ -0,0 +1,95 @@ +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:86:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { } + | ------------------------------------------------------ first implementation here +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:89:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ------------------------------------------------------------- first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> + +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:93:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ------------------------------------------------------ first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> + +warning: 3 warnings emitted + +Future incompatibility report: Future breakage diagnostic: +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:86:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { } + | ------------------------------------------------------ first implementation here +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:89:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ------------------------------------------------------------- first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:93:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ------------------------------------------------------ first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/traits/object/issue-44454-1.rs b/tests/ui/traits/object/issue-44454-1.rs new file mode 100644 index 000000000..bbaf3188a --- /dev/null +++ b/tests/ui/traits/object/issue-44454-1.rs @@ -0,0 +1,22 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issue-256435333 + +trait Animal<X>: 'static {} + +fn foo<Y, X>() +where + Y: Animal<X> + ?Sized, +{ + // `Y` implements `Animal<X>` so `Y` is 'static. + baz::<Y>() +} + +fn bar<'a>(_arg: &'a i32) { + foo::<dyn Animal<&'a i32>, &'a i32>() //~ ERROR: lifetime may not live long enough +} + +fn baz<T: 'static + ?Sized>() {} + +fn main() { + let a = 5; + bar(&a); +} diff --git a/tests/ui/traits/object/issue-44454-1.stderr b/tests/ui/traits/object/issue-44454-1.stderr new file mode 100644 index 000000000..859487f50 --- /dev/null +++ b/tests/ui/traits/object/issue-44454-1.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/issue-44454-1.rs:14:5 + | +LL | fn bar<'a>(_arg: &'a i32) { + | -- lifetime `'a` defined here +LL | foo::<dyn Animal<&'a i32>, &'a i32>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/traits/object/issue-44454-2.rs b/tests/ui/traits/object/issue-44454-2.rs new file mode 100644 index 000000000..f5178bcdb --- /dev/null +++ b/tests/ui/traits/object/issue-44454-2.rs @@ -0,0 +1,22 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1175925928 + +trait Trait<ARG: 'static>: 'static { + type Assoc: AsRef<str>; +} + +fn hr<T: ?Sized, ARG>(x: T::Assoc) -> Box<dyn AsRef<str> + 'static> +where + T: Trait<ARG> +{ + Box::new(x) +} + +fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> { + type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>; + hr::<DynTrait, _>(x) //~ ERROR: borrowed data escapes outside of function +} + +fn main() { + let extended = extend_lt(&String::from("hello")); + println!("{}", extended.as_ref().as_ref()); +} diff --git a/tests/ui/traits/object/issue-44454-2.stderr b/tests/ui/traits/object/issue-44454-2.stderr new file mode 100644 index 000000000..7f574769b --- /dev/null +++ b/tests/ui/traits/object/issue-44454-2.stderr @@ -0,0 +1,17 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-44454-2.rs:16:5 + | +LL | fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>; +LL | hr::<DynTrait, _>(x) + | ^^^^^^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/traits/object/issue-44454-3.rs b/tests/ui/traits/object/issue-44454-3.rs new file mode 100644 index 000000000..bff727035 --- /dev/null +++ b/tests/ui/traits/object/issue-44454-3.rs @@ -0,0 +1,33 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1332781290 + +use std::any::Any; + +trait Animal<X>: 'static {} + +trait Projector { + type Foo; +} + +impl<X> Projector for dyn Animal<X> { + type Foo = X; +} + +fn make_static<'a, T>(t: &'a T) -> &'static T { + let x: <dyn Animal<&'a T> as Projector>::Foo = t; + let any = generic::<dyn Animal<&'a T>, &'a T>(x); + //~^ ERROR: lifetime may not live long enough + any.downcast_ref::<&'static T>().unwrap() +} + +fn generic<T: Projector + Animal<U> + ?Sized, U>(x: <T as Projector>::Foo) -> Box<dyn Any> { + make_static_any(x) +} + +fn make_static_any<U: 'static>(u: U) -> Box<dyn Any> { + Box::new(u) +} + +fn main() { + let a = make_static(&"salut".to_string()); + println!("{}", *a); +} diff --git a/tests/ui/traits/object/issue-44454-3.stderr b/tests/ui/traits/object/issue-44454-3.stderr new file mode 100644 index 000000000..294684d26 --- /dev/null +++ b/tests/ui/traits/object/issue-44454-3.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-44454-3.rs:17:15 + | +LL | fn make_static<'a, T>(t: &'a T) -> &'static T { + | -- lifetime `'a` defined here +LL | let x: <dyn Animal<&'a T> as Projector>::Foo = t; +LL | let any = generic::<dyn Animal<&'a T>, &'a T>(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/traits/object/lifetime-first.rs b/tests/ui/traits/object/lifetime-first.rs new file mode 100644 index 000000000..33757cb7c --- /dev/null +++ b/tests/ui/traits/object/lifetime-first.rs @@ -0,0 +1,13 @@ +// run-pass +use std::fmt::Display; + +static BYTE: u8 = 33; + +fn main() { + let x: &(dyn 'static + Display) = &BYTE; + let y: Box<dyn 'static + Display> = Box::new(BYTE); + let xstr = format!("{}", x); + let ystr = format!("{}", y); + assert_eq!(xstr, "33"); + assert_eq!(ystr, "33"); +} diff --git a/tests/ui/traits/object/macro-matcher.rs b/tests/ui/traits/object/macro-matcher.rs new file mode 100644 index 000000000..910978749 --- /dev/null +++ b/tests/ui/traits/object/macro-matcher.rs @@ -0,0 +1,12 @@ +// `ty` matcher accepts trait object types + +macro_rules! m { + ($t: ty) => ( let _: $t; ) +} + +fn main() { + m!(dyn Copy + Send + 'static); + //~^ ERROR the trait `Copy` cannot be made into an object + m!(dyn 'static + Send); + m!(dyn 'static +); //~ ERROR at least one trait is required for an object type +} diff --git a/tests/ui/traits/object/macro-matcher.stderr b/tests/ui/traits/object/macro-matcher.stderr new file mode 100644 index 000000000..6d1e236c0 --- /dev/null +++ b/tests/ui/traits/object/macro-matcher.stderr @@ -0,0 +1,19 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/macro-matcher.rs:11:8 + | +LL | m!(dyn 'static +); + | ^^^^^^^^^^^^^ + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/macro-matcher.rs:8:8 + | +LL | m!(dyn Copy + Send + 'static); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `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 2 previous errors + +Some errors have detailed explanations: E0038, E0224. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/safety.rs b/tests/ui/traits/object/safety.rs new file mode 100644 index 000000000..f43d332d6 --- /dev/null +++ b/tests/ui/traits/object/safety.rs @@ -0,0 +1,17 @@ +// Check that static methods are not object-safe. + +trait Tr { + fn foo(); + fn bar(&self) { } +} + +struct St; + +impl Tr for St { + fn foo() {} +} + +fn main() { + let _: &dyn Tr = &St; //~ ERROR E0038 + //~^ ERROR E0038 +} diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr new file mode 100644 index 000000000..dc18adeaf --- /dev/null +++ b/tests/ui/traits/object/safety.stderr @@ -0,0 +1,49 @@ +error[E0038]: the trait `Tr` cannot be made into an object + --> $DIR/safety.rs:15:22 + | +LL | let _: &dyn Tr = &St; + | ^^^ `Tr` 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/safety.rs:4:8 + | +LL | trait Tr { + | -- this trait cannot be made into an object... +LL | fn foo(); + | ^^^ ...because associated function `foo` has no `self` parameter + = note: required for `&St` to implement `CoerceUnsized<&dyn Tr>` + = note: required by cast to type `&dyn Tr` +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[E0038]: the trait `Tr` cannot be made into an object + --> $DIR/safety.rs:15:12 + | +LL | let _: &dyn Tr = &St; + | ^^^^^^^ `Tr` 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/safety.rs:4:8 + | +LL | trait Tr { + | -- 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 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/supertrait-lifetime-bound.rs b/tests/ui/traits/object/supertrait-lifetime-bound.rs new file mode 100644 index 000000000..f929a9bb6 --- /dev/null +++ b/tests/ui/traits/object/supertrait-lifetime-bound.rs @@ -0,0 +1,14 @@ +trait Foo: 'static { } + +trait Bar<T>: Foo { } + +fn test1<T: ?Sized + Bar<S>, S>() { } + +fn test2<'a>() { + // Here: the type `dyn Bar<&'a u32>` references `'a`, + // and so it does not outlive `'static`. + test1::<dyn Bar<&'a u32>, _>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/traits/object/supertrait-lifetime-bound.stderr b/tests/ui/traits/object/supertrait-lifetime-bound.stderr new file mode 100644 index 000000000..ed2f86243 --- /dev/null +++ b/tests/ui/traits/object/supertrait-lifetime-bound.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/supertrait-lifetime-bound.rs:10:5 + | +LL | fn test2<'a>() { + | -- lifetime `'a` defined here +... +LL | test1::<dyn Bar<&'a u32>, _>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/traits/object/vs-lifetime-2.rs b/tests/ui/traits/object/vs-lifetime-2.rs new file mode 100644 index 000000000..0b33dc7f6 --- /dev/null +++ b/tests/ui/traits/object/vs-lifetime-2.rs @@ -0,0 +1,11 @@ +// A few contrived examples where lifetime should (or should not) be parsed as an object type. +// Lifetimes parsed as types are still rejected later by semantic checks. + +// `'static` is a lifetime, `'static +` is a type, `'a` is a type +fn g() where + 'static: 'static, + dyn 'static +: 'static + Copy, + //~^ ERROR at least one trait is required for an object type +{} + +fn main() {} diff --git a/tests/ui/traits/object/vs-lifetime-2.stderr b/tests/ui/traits/object/vs-lifetime-2.stderr new file mode 100644 index 000000000..9b8e793df --- /dev/null +++ b/tests/ui/traits/object/vs-lifetime-2.stderr @@ -0,0 +1,9 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime-2.rs:7:5 + | +LL | dyn 'static +: 'static + Copy, + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/object/vs-lifetime.rs b/tests/ui/traits/object/vs-lifetime.rs new file mode 100644 index 000000000..14ae67cff --- /dev/null +++ b/tests/ui/traits/object/vs-lifetime.rs @@ -0,0 +1,17 @@ +// A few contrived examples where lifetime should (or should not) be parsed as an object type. +// Lifetimes parsed as types are still rejected later by semantic checks. + +struct S<'a, T>(&'a u8, T); + +fn main() { + // `'static` is a lifetime argument, `'static +` is a type argument + let _: S<'static, u8>; + let _: S<'static, dyn 'static +>; + //~^ at least one trait is required for an object type + let _: S<'static, 'static>; + //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| ERROR this struct takes 1 generic argument but 0 generic arguments were supplied + let _: S<dyn 'static +, 'static>; + //~^ ERROR type provided when a lifetime was expected + //~| ERROR at least one trait is required for an object type +} diff --git a/tests/ui/traits/object/vs-lifetime.stderr b/tests/ui/traits/object/vs-lifetime.stderr new file mode 100644 index 000000000..224465228 --- /dev/null +++ b/tests/ui/traits/object/vs-lifetime.stderr @@ -0,0 +1,52 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime.rs:9:23 + | +LL | let _: S<'static, dyn 'static +>; + | ^^^^^^^^^^^^^ + +error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/vs-lifetime.rs:11:12 + | +LL | let _: S<'static, 'static>; + | ^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/vs-lifetime.rs:4:8 + | +LL | struct S<'a, T>(&'a u8, T); + | ^ -- + +error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/vs-lifetime.rs:11:12 + | +LL | let _: S<'static, 'static>; + | ^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/vs-lifetime.rs:4:8 + | +LL | struct S<'a, T>(&'a u8, T); + | ^ - +help: add missing generic argument + | +LL | let _: S<'static, 'static, T>; + | +++ + +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime.rs:14:14 + | +LL | let _: S<dyn 'static +, 'static>; + | ^^^^^^^^^^^^^ + +error[E0747]: type provided when a lifetime was expected + --> $DIR/vs-lifetime.rs:14:14 + | +LL | let _: S<dyn 'static +, 'static>; + | ^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0107, E0224, E0747. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/object/with-lifetime-bound.rs b/tests/ui/traits/object/with-lifetime-bound.rs new file mode 100644 index 000000000..05aab5e3b --- /dev/null +++ b/tests/ui/traits/object/with-lifetime-bound.rs @@ -0,0 +1,34 @@ +// run-pass +// Uncovered during work on new scoping rules for safe destructors +// as an important use case to support properly. + + +pub struct E<'a> { + pub f: &'a u8, +} +impl<'b> E<'b> { + pub fn m(&self) -> &'b u8 { self.f } +} + +pub struct P<'c> { + pub g: &'c u8, +} +pub trait M { + fn n(&self) -> u8; +} +impl<'d> M for P<'d> { + fn n(&self) -> u8 { *self.g } +} + +fn extension<'e>(x: &'e E<'e>) -> Box<dyn M+'e> { + loop { + let p = P { g: x.m() }; + return Box::new(p) as Box<dyn M+'e>; + } +} + +fn main() { + let w = E { f: &10 }; + let o = extension(&w); + assert_eq!(o.n(), 10); +} diff --git a/tests/ui/traits/object/with-self-in-projection-output-bad.rs b/tests/ui/traits/object/with-self-in-projection-output-bad.rs new file mode 100644 index 000000000..f34fa80a0 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-bad.rs @@ -0,0 +1,50 @@ +// Regression test for #56288. Checks that if a supertrait defines an associated type +// projection that references `Self`, then that associated type must still be explicitly +// specified in the `dyn Trait` variant, since we don't know what `Self` is anymore. + +trait Base { + type Output; +} + +trait Helper: Base<Output=<Self as Helper>::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +trait ConstI32 { + type Out; +} + +impl<T: ?Sized> ConstI32 for T { + type Out = i32; +} + +// Test that you still need to manually give a projection type if the Output type +// is normalizable. +trait NormalizableHelper: + Base<Output=<Self as ConstI32>::Out> +{ + type Target; +} + +impl NormalizableHelper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from trait `Base`) must be specified + + let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from trait `Base`) must be specified +} diff --git a/tests/ui/traits/object/with-self-in-projection-output-bad.stderr b/tests/ui/traits/object/with-self-in-projection-output-bad.stderr new file mode 100644 index 000000000..641bfe236 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-bad.stderr @@ -0,0 +1,21 @@ +error[E0191]: the value of the associated type `Output` (from trait `Base`) must be specified + --> $DIR/with-self-in-projection-output-bad.rs:45:21 + | +LL | type Output; + | ----------- `Output` defined here +... +LL | let _x: Box<dyn Helper<Target=i32>> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^ help: specify the associated type: `Helper<Target=i32, Output = Type>` + +error[E0191]: the value of the associated type `Output` (from trait `Base`) must be specified + --> $DIR/with-self-in-projection-output-bad.rs:48:21 + | +LL | type Output; + | ----------- `Output` defined here +... +LL | let _y: Box<dyn NormalizableHelper<Target=i32>> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `NormalizableHelper<Target=i32, Output = Type>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/traits/object/with-self-in-projection-output-good.rs b/tests/ui/traits/object/with-self-in-projection-output-good.rs new file mode 100644 index 000000000..d1b7bf6c2 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-good.rs @@ -0,0 +1,28 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` can be ok if it is referencing a projection (of +// `Self::Target`, in this case). Note that we still require the user to manually +// specify both `Target` and `Output` for now. + +trait Base { + type Output; +} + +trait Helper: Base<Output=<Self as Helper>::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box<dyn Helper<Target=i32, Output=i32>> = Box::new(2u32); +} diff --git a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs new file mode 100644 index 000000000..39e817168 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs @@ -0,0 +1,51 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// FIXME(eddyb) shorten the name so windows doesn't choke on it. +#![crate_name = "trait_test"] + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` is ok if there is another occurrence of +// the same supertrait that specifies the projection explicitly, even if +// the projection's associated type is not explicitly specified in the object type. +// +// Note that in order for this to compile, we need the `Self`-referencing projection +// to normalize fairly directly to a concrete type, otherwise the trait resolver +// will hate us. +// +// There is a test in `trait-object-with-self-in-projection-output-bad.rs` that +// having a normalizing, but `Self`-containing projection does not *by itself* +// allow you to avoid writing the projected type (`Output`, in this example) +// explicitly. + +trait ConstI32 { + type Out; +} + +impl<T: ?Sized> ConstI32 for T { + type Out = i32; +} + +trait Base { + type Output; +} + +trait NormalizingHelper: Base<Output=<Self as ConstI32>::Out> + Base<Output=i32> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl NormalizingHelper for u32 +{ + type Target = i32; +} + +fn main() { + // Make sure this works both with and without the associated type + // being specified. + let _x: Box<dyn NormalizingHelper<Target=i32>> = Box::new(2u32); + let _y: Box<dyn NormalizingHelper<Target=i32, Output=i32>> = Box::new(2u32); +} diff --git a/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs b/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs new file mode 100644 index 000000000..fce1341fc --- /dev/null +++ b/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs @@ -0,0 +1,30 @@ +// run-pass +// Test invoked `&self` methods on owned objects where the values +// closed over do not contain managed values, and thus the boxes do +// not have headers. + +trait FooTrait { + fn foo(&self) -> usize; +} + +struct BarStruct { + x: usize +} + +impl FooTrait for BarStruct { + fn foo(&self) -> usize { + self.x + } +} + +pub fn main() { + let foos: Vec<Box<dyn FooTrait>> = vec![ + Box::new(BarStruct{ x: 0 }) as Box<dyn FooTrait>, + Box::new(BarStruct{ x: 1 }) as Box<dyn FooTrait>, + Box::new(BarStruct{ x: 2 }) as Box<dyn FooTrait>, + ]; + + for i in 0..foos.len() { + assert_eq!(i, foos[i].foo()); + } +} diff --git a/tests/ui/traits/operator-overloading-issue-52025.rs b/tests/ui/traits/operator-overloading-issue-52025.rs new file mode 100644 index 000000000..7ce638832 --- /dev/null +++ b/tests/ui/traits/operator-overloading-issue-52025.rs @@ -0,0 +1,57 @@ +// only-x86_64 +// build-pass + +use std::arch::x86_64::*; +use std::fmt::Debug; +use std::ops::*; + +pub trait Simd { + type Vf32: Copy + Debug + Add<Self::Vf32, Output = Self::Vf32> + Add<f32, Output = Self::Vf32>; + + unsafe fn set1_ps(a: f32) -> Self::Vf32; + unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32; +} + +#[derive(Copy, Debug, Clone)] +pub struct F32x4(pub __m128); + +impl Add<F32x4> for F32x4 { + type Output = F32x4; + + fn add(self, rhs: F32x4) -> F32x4 { + F32x4(unsafe { _mm_add_ps(self.0, rhs.0) }) + } +} + +impl Add<f32> for F32x4 { + type Output = F32x4; + fn add(self, rhs: f32) -> F32x4 { + F32x4(unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }) + } +} + +pub struct Sse2; +impl Simd for Sse2 { + type Vf32 = F32x4; + + #[inline(always)] + unsafe fn set1_ps(a: f32) -> Self::Vf32 { + F32x4(_mm_set1_ps(a)) + } + + #[inline(always)] + unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32 { + F32x4(_mm_add_ps(a.0, b.0)) + } +} + +unsafe fn test<S: Simd>() -> S::Vf32 { + let a = S::set1_ps(3.0); + let b = S::set1_ps(2.0); + let result = a + b; + result +} + +fn main() { + println!("{:?}", unsafe { test::<Sse2>() }); +} diff --git a/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs new file mode 100644 index 000000000..4106f56d6 --- /dev/null +++ b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] +#![feature(negative_impls)] + +// Overlapping negative impls for `MyStruct` are not permitted: +struct MyStruct; +impl !Send for MyStruct {} +impl !Send for MyStruct {} +//~^ ERROR conflicting implementations of trait + +fn main() {} diff --git a/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr new file mode 100644 index 000000000..e24ed695d --- /dev/null +++ b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Send` for type `MyStruct` + --> $DIR/overlap-not-permitted-for-builtin-trait.rs:7:1 + | +LL | impl !Send for MyStruct {} + | ----------------------- first implementation here +LL | impl !Send for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/overlap-permitted-for-marker-traits.rs b/tests/ui/traits/overlap-permitted-for-marker-traits.rs new file mode 100644 index 000000000..00823d13b --- /dev/null +++ b/tests/ui/traits/overlap-permitted-for-marker-traits.rs @@ -0,0 +1,28 @@ +// run-pass +// Tests for RFC 1268: we allow overlapping impls of marker traits, +// that is, traits without items. In this case, a type `T` is +// `MyMarker` if it is either `Debug` or `Display`. + +#![feature(marker_trait_attr)] +#![feature(negative_impls)] + +use std::fmt::{Debug, Display}; + +#[marker] +trait MyMarker {} + +impl<T: Debug> MyMarker for T {} +impl<T: Display> MyMarker for T {} + +fn foo<T: MyMarker>(t: T) -> T { + t +} + +fn main() { + // Debug && Display: + assert_eq!(1, foo(1)); + assert_eq!(2.0, foo(2.0)); + + // Debug && !Display: + assert_eq!(vec![1], foo(vec![1])); +} diff --git a/tests/ui/traits/param-without-lifetime-constraint.rs b/tests/ui/traits/param-without-lifetime-constraint.rs new file mode 100644 index 000000000..a79b74dcd --- /dev/null +++ b/tests/ui/traits/param-without-lifetime-constraint.rs @@ -0,0 +1,20 @@ +struct Article { + proof_reader: ProofReader, +} + +struct ProofReader { + name: String, +} + +pub trait HaveRelationship<To> { + fn get_relation(&self) -> To; +} + +impl HaveRelationship<&ProofReader> for Article { + fn get_relation(&self) -> &ProofReader { + //~^ ERROR `impl` item signature doesn't match `trait` item signature + &self.proof_reader + } +} + +fn main() {} diff --git a/tests/ui/traits/param-without-lifetime-constraint.stderr b/tests/ui/traits/param-without-lifetime-constraint.stderr new file mode 100644 index 000000000..b128b6518 --- /dev/null +++ b/tests/ui/traits/param-without-lifetime-constraint.stderr @@ -0,0 +1,19 @@ +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/param-without-lifetime-constraint.rs:14:5 + | +LL | fn get_relation(&self) -> To; + | ----------------------------- expected `fn(&'1 Article) -> &'2 ProofReader` +... +LL | fn get_relation(&self) -> &ProofReader { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader` + | + = note: expected signature `fn(&'1 Article) -> &'2 ProofReader` + found signature `fn(&'1 Article) -> &'1 ProofReader` +help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + --> $DIR/param-without-lifetime-constraint.rs:10:31 + | +LL | fn get_relation(&self) -> To; + | ^^ consider borrowing this type parameter in the trait + +error: aborting due to previous error + diff --git a/tests/ui/traits/parameterized-with-bounds.rs b/tests/ui/traits/parameterized-with-bounds.rs new file mode 100644 index 000000000..832d4f6c8 --- /dev/null +++ b/tests/ui/traits/parameterized-with-bounds.rs @@ -0,0 +1,21 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + + +trait A<T> { fn get(self) -> T; } +trait B<T, U> { fn get(self) -> (T,U); } +trait C<'a, U> { fn get(self) -> &'a U; } + +mod foo { + pub trait D<'a, T> { fn get(self) -> &'a T; } +} + +fn foo1<T>(_: &(dyn A<T> + Send)) {} +fn foo2<T>(_: Box<dyn A<T> + Send + Sync>) {} +fn foo3<T>(_: Box<dyn B<isize, usize> + 'static>) {} +fn foo4<'a, T>(_: Box<dyn C<'a, T> + 'static + Send>) {} +fn foo5<'a, T>(_: Box<dyn foo::D<'a, T> + 'static + Send>) {} + +pub fn main() {} diff --git a/tests/ui/traits/pointee-deduction.rs b/tests/ui/traits/pointee-deduction.rs new file mode 100644 index 000000000..c333b0129 --- /dev/null +++ b/tests/ui/traits/pointee-deduction.rs @@ -0,0 +1,22 @@ +// run-pass + +#![feature(ptr_metadata)] + +use std::alloc::Layout; +use std::ptr::Pointee; + +trait Foo { + type Bar; +} + +impl Foo for () { + type Bar = (); +} + +struct Wrapper1<T: Foo>(#[allow(unused_tuple_struct_fields)] <T as Foo>::Bar); +struct Wrapper2<T: Foo>(#[allow(unused_tuple_struct_fields)] <Wrapper1<T> as Pointee>::Metadata); + +fn main() { + let _: Wrapper2<()> = Wrapper2(()); + let _ = Layout::new::<Wrapper2<()>>(); +} diff --git a/tests/ui/traits/pointee-tail-is-generic-errors.rs b/tests/ui/traits/pointee-tail-is-generic-errors.rs new file mode 100644 index 000000000..28bc1da96 --- /dev/null +++ b/tests/ui/traits/pointee-tail-is-generic-errors.rs @@ -0,0 +1,22 @@ +// edition:2018 + +#![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] + +type Opaque = impl std::fmt::Debug + ?Sized; + +fn opaque() -> &'static Opaque { + &[1] as &[i32] +} + +fn a<T: ?Sized>() { + is_thin::<T>(); + //~^ ERROR type mismatch resolving `<T as Pointee>::Metadata == ()` + + is_thin::<Opaque>(); + //~^ ERROR type mismatch resolving `<Opaque as Pointee>::Metadata == ()` +} + +fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {} + +fn main() {} diff --git a/tests/ui/traits/pointee-tail-is-generic-errors.stderr b/tests/ui/traits/pointee-tail-is-generic-errors.stderr new file mode 100644 index 000000000..0c3d7060d --- /dev/null +++ b/tests/ui/traits/pointee-tail-is-generic-errors.stderr @@ -0,0 +1,40 @@ +error[E0271]: type mismatch resolving `<T as Pointee>::Metadata == ()` + --> $DIR/pointee-tail-is-generic-errors.rs:13:15 + | +LL | is_thin::<T>(); + | ^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `<T as Pointee>::Metadata` + = help: consider constraining the associated type `<T as Pointee>::Metadata` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `is_thin` + --> $DIR/pointee-tail-is-generic-errors.rs:20:33 + | +LL | fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {} + | ^^^^^^^^^^^^^ required by this bound in `is_thin` + +error[E0271]: type mismatch resolving `<Opaque as Pointee>::Metadata == ()` + --> $DIR/pointee-tail-is-generic-errors.rs:16:15 + | +LL | type Opaque = impl std::fmt::Debug + ?Sized; + | ----------------------------- the found opaque type +... +LL | is_thin::<Opaque>(); + | ^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `<Opaque as Pointee>::Metadata` +note: required by a bound in `is_thin` + --> $DIR/pointee-tail-is-generic-errors.rs:20:33 + | +LL | fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {} + | ^^^^^^^^^^^^^ required by this bound in `is_thin` +help: consider constraining the associated type `<Opaque as Pointee>::Metadata` to `()` + | +LL | type Opaque = impl std::fmt::Debug<Metadata = ()> + ?Sized; + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/pointee-tail-is-generic.rs b/tests/ui/traits/pointee-tail-is-generic.rs new file mode 100644 index 000000000..e0da0fc38 --- /dev/null +++ b/tests/ui/traits/pointee-tail-is-generic.rs @@ -0,0 +1,29 @@ +// check-pass +// edition:2018 + +#![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] + +type Opaque = impl std::future::Future; + +fn opaque() -> Opaque { + async {} +} + +fn a<T>() { + // type parameter T is known to be sized + is_thin::<T>(); + // tail of ADT (which is a type param) is known to be sized + is_thin::<std::cell::Cell<T>>(); + // opaque type is known to be sized + is_thin::<Opaque>(); +} + +fn a2<T: Iterator>() { + // associated type is known to be sized + is_thin::<T::Item>(); +} + +fn is_thin<T: std::ptr::Pointee<Metadata = ()>>() {} + +fn main() {} diff --git a/tests/ui/traits/principal-less-objects.rs b/tests/ui/traits/principal-less-objects.rs new file mode 100644 index 000000000..62bad0d7d --- /dev/null +++ b/tests/ui/traits/principal-less-objects.rs @@ -0,0 +1,42 @@ +// run-pass +// Check that trait objects without a principal codegen properly. + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::mem; + +// Array is to make sure the size is not exactly pointer-size, so +// we can be sure we are measuring the right size in the +// `size_of_val` test. +struct SetOnDrop<'a>(&'a AtomicUsize, #[allow(unused_tuple_struct_fields)] [u8; 64]); +impl<'a> Drop for SetOnDrop<'a> { + fn drop(&mut self) { + self.0.store(self.0.load(Ordering::Relaxed) + 1, Ordering::Relaxed); + } +} + +trait TypeEq<V: ?Sized> {} +impl<T: ?Sized> TypeEq<T> for T {} +fn assert_types_eq<U: ?Sized, V: ?Sized>() where U: TypeEq<V> {} + +fn main() { + // Check that different ways of writing the same type are equal. + assert_types_eq::<dyn Sync, dyn Sync + Sync>(); + assert_types_eq::<dyn Sync + Send, dyn Send + Sync>(); + assert_types_eq::<dyn Sync + Send + Sync, dyn Send + Sync>(); + + // Check that codegen works. + // + // Using `AtomicUsize` here because `Cell<u32>` is not `Sync`, and + // so can't be made into a `Box<dyn Sync>`. + let c = AtomicUsize::new(0); + { + let d: Box<dyn Sync> = Box::new(SetOnDrop(&c, [0; 64])); + + assert_eq!(mem::size_of_val(&*d), + mem::size_of::<SetOnDrop>()); + assert_eq!(mem::align_of_val(&*d), + mem::align_of::<SetOnDrop>()); + assert_eq!(c.load(Ordering::Relaxed), 0); + } + assert_eq!(c.load(Ordering::Relaxed), 1); +} diff --git a/tests/ui/traits/privacy.rs b/tests/ui/traits/privacy.rs new file mode 100644 index 000000000..17a2e05e9 --- /dev/null +++ b/tests/ui/traits/privacy.rs @@ -0,0 +1,24 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +mod foo { + pub use self::bar::T; + mod bar { + pub trait T { + fn f(&self) {} + } + impl T for () {} + } +} + +fn g() { + use foo::T; + ().f(); // Check that this does not trigger a privacy error +} + +fn f() { + let error = ::std::thread::spawn(|| {}).join().unwrap_err(); + error.type_id(); // Regression test for #21670 +} + + +fn main() {} diff --git a/tests/ui/traits/project-modulo-regions.rs b/tests/ui/traits/project-modulo-regions.rs new file mode 100644 index 000000000..f0c0dd3ed --- /dev/null +++ b/tests/ui/traits/project-modulo-regions.rs @@ -0,0 +1,55 @@ +// revisions: with_clause without_clause +// Tests that `EvaluatedToOkModuloRegions` from a projection sub-obligation +// is correctly propagated + +#![feature(rustc_attrs)] + +trait MyTrait { + type Assoc; +} + +struct MyStruct; + +impl MyTrait for MyStruct { + // Evaluating this projection will result in `EvaluatedToOkModuloRegions` + // (when `with_clause` is enabled) + type Assoc = <Bar as MyTrait>::Assoc; +} + +struct Bar; + +// The `where` clause on this impl will cause us to produce `EvaluatedToOkModuloRegions` +// when evaluating a projection involving this impl +#[cfg(with_clause)] +impl MyTrait for Bar where for<'b> &'b (): 'b { + type Assoc = bool; +} + +// This impl tests that the `EvaluatedToOkModuoRegions` result that we get +// is really due to the `where` clause on the `with_clause` impl +#[cfg(without_clause)] +impl MyTrait for Bar { + type Assoc = bool; +} + +// The implementation of `#[rustc_evaluate_where_clauses]` doesn't perform +// normalization, so we need to place the projection predicate behind a normal +// trait predicate +struct Helper {} +trait HelperTrait {} +impl HelperTrait for Helper where <MyStruct as MyTrait>::Assoc: Sized {} + +// Evaluating this 'where' clause will (recursively) end up evaluating +// `for<'b> &'b (): 'b`, which will produce `EvaluatedToOkModuloRegions` +#[rustc_evaluate_where_clauses] +fn test(val: MyStruct) where Helper: HelperTrait { + panic!() +} + +fn foo(val: MyStruct) { + test(val); + //[with_clause]~^ ERROR evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + //[without_clause]~^^ ERROR evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOk) +} + +fn main() {} diff --git a/tests/ui/traits/project-modulo-regions.with_clause.stderr b/tests/ui/traits/project-modulo-regions.with_clause.stderr new file mode 100644 index 000000000..2434c32c8 --- /dev/null +++ b/tests/ui/traits/project-modulo-regions.with_clause.stderr @@ -0,0 +1,11 @@ +error: evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/project-modulo-regions.rs:50:5 + | +LL | fn test(val: MyStruct) where Helper: HelperTrait { + | ----------- predicate +... +LL | test(val); + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/project-modulo-regions.without_clause.stderr b/tests/ui/traits/project-modulo-regions.without_clause.stderr new file mode 100644 index 000000000..9d35690d5 --- /dev/null +++ b/tests/ui/traits/project-modulo-regions.without_clause.stderr @@ -0,0 +1,11 @@ +error: evaluate(Binder(TraitPredicate(<Helper as HelperTrait>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/project-modulo-regions.rs:50:5 + | +LL | fn test(val: MyStruct) where Helper: HelperTrait { + | ----------- predicate +... +LL | test(val); + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/region-pointer-simple.rs b/tests/ui/traits/region-pointer-simple.rs new file mode 100644 index 000000000..0456ca931 --- /dev/null +++ b/tests/ui/traits/region-pointer-simple.rs @@ -0,0 +1,21 @@ +// run-pass +trait Foo { + fn f(&self) -> isize; +} + +struct A { + x: isize +} + +impl Foo for A { + fn f(&self) -> isize { + println!("Today's number is {}", self.x); + return self.x; + } +} + +pub fn main() { + let a = A { x: 3 }; + let b = (&a) as &dyn Foo; + assert_eq!(b.f(), 3); +} diff --git a/tests/ui/traits/reservation-impl/coherence-conflict.rs b/tests/ui/traits/reservation-impl/coherence-conflict.rs new file mode 100644 index 000000000..fa4a30931 --- /dev/null +++ b/tests/ui/traits/reservation-impl/coherence-conflict.rs @@ -0,0 +1,14 @@ +// check that reservation impls are accounted for in negative reasoning. + +#![feature(rustc_attrs)] + +trait MyTrait {} +#[rustc_reservation_impl="this impl is reserved"] +impl MyTrait for () {} + +trait OtherTrait {} +impl OtherTrait for () {} +impl<T: MyTrait> OtherTrait for T {} +//~^ ERROR conflicting implementations + +fn main() {} diff --git a/tests/ui/traits/reservation-impl/coherence-conflict.stderr b/tests/ui/traits/reservation-impl/coherence-conflict.stderr new file mode 100644 index 000000000..a811d7e32 --- /dev/null +++ b/tests/ui/traits/reservation-impl/coherence-conflict.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `OtherTrait` for type `()` + --> $DIR/coherence-conflict.rs:11:1 + | +LL | impl OtherTrait for () {} + | ---------------------- first implementation here +LL | impl<T: MyTrait> OtherTrait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: this impl is reserved + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/reservation-impl/no-use.rs b/tests/ui/traits/reservation-impl/no-use.rs new file mode 100644 index 000000000..65a55d9e2 --- /dev/null +++ b/tests/ui/traits/reservation-impl/no-use.rs @@ -0,0 +1,12 @@ +// check that reservation impls can't be used as normal impls in positive reasoning. + +#![feature(rustc_attrs)] + +trait MyTrait { fn foo(&self); } +#[rustc_reservation_impl = "foo"] +impl MyTrait for () { fn foo(&self) {} } + +fn main() { + <() as MyTrait>::foo(&()); + //~^ ERROR the trait bound `(): MyTrait` is not satisfied +} diff --git a/tests/ui/traits/reservation-impl/no-use.stderr b/tests/ui/traits/reservation-impl/no-use.stderr new file mode 100644 index 000000000..cefb2a879 --- /dev/null +++ b/tests/ui/traits/reservation-impl/no-use.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `(): MyTrait` is not satisfied + --> $DIR/no-use.rs:10:26 + | +LL | <() as MyTrait>::foo(&()); + | -------------------- ^^^ the trait `MyTrait` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the trait `MyTrait` is implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/reservation-impl/non-lattice-ok.rs b/tests/ui/traits/reservation-impl/non-lattice-ok.rs new file mode 100644 index 000000000..a71051243 --- /dev/null +++ b/tests/ui/traits/reservation-impl/non-lattice-ok.rs @@ -0,0 +1,59 @@ +// build-pass + +// Check that a reservation impl does not force other impls to follow +// a lattice discipline. + +// Why did we ever want to do this? +// +// We want to eventually add an `impl<T> From<!> for T` impl. That impl conflicts +// with existing impls - at least the `impl<T> From<T> for T` impl. There are +// 2 ways we thought of for dealing with that conflict: +// +// 1. Using specialization and doing some handling for the +// overlap. The current thought is to require ["intersection +// impls"][ii], specialization", which means providing an +// (higher-priority) impl for the intersection of every 2 conflicting +// impls that determines what happens in the intersection case. That's +// the first thing we thought about - see e.g. +// https://github.com/rust-lang/rust/issues/57012#issuecomment-452150775 +// +// 2. The other way is to notice that `impl From<!> for T` is basically a +// marker trait since its only method is uninhabited, and allow for "marker +// trait overlap", where the conflict "doesn't matter" because it can't +// actually cause any ambiguity. +// +// Now it turned out lattice specialization doesn't work it, because an +// `impl<T> From<T> for Smaht<T>` would require an `impl From<!> for Smaht<!>`, +// breaking backwards-compatibility in a fairly painful way. So if we want to +// go with a known approach, we should go with a "marker trait overlap"-style +// approach. +// +// [ii]: https://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/ + +#![feature(rustc_attrs, never_type)] + +trait MyTrait {} + +impl MyTrait for ! {} + +trait MyFrom<T> { + fn my_from(x: T) -> Self; +} + +// Given the "normal" impls for From +#[rustc_reservation_impl="this impl is reserved"] +impl<T> MyFrom<!> for T { + fn my_from(x: !) -> Self { match x {} } +} + +impl<T> MyFrom<T> for T { + fn my_from(x: T) -> Self { x } +} + +// ... we *do* want to allow this common pattern, of `From<!> for MySmaht<T>` +struct MySmaht<T>(T); +impl<T> MyFrom<T> for MySmaht<T> { + fn my_from(x: T) -> Self { MySmaht(x) } +} + +fn main() {} diff --git a/tests/ui/traits/reservation-impl/ok.rs b/tests/ui/traits/reservation-impl/ok.rs new file mode 100644 index 000000000..611c8d884 --- /dev/null +++ b/tests/ui/traits/reservation-impl/ok.rs @@ -0,0 +1,28 @@ +// run-pass + +// rpass test for reservation impls. Not 100% required because `From` uses them, +// but still. + +#![feature(rustc_attrs)] + +use std::mem; + +trait MyTrait<S> { + fn foo(&self, s: S) -> usize; +} + +#[rustc_reservation_impl = "foo"] +impl<T> MyTrait<u64> for T { + fn foo(&self, _x: u64) -> usize { 0 } +} + +// reservation impls don't create coherence conflicts, even with +// non-chain overlap. +impl<S> MyTrait<S> for u32 { + fn foo(&self, _x: S) -> usize { mem::size_of::<S>() } +} + +fn main() { + // ...and the non-reservation impl gets picked.XS + assert_eq!(0u32.foo(0u64), mem::size_of::<u64>()); +} diff --git a/tests/ui/traits/resolution-in-overloaded-op.rs b/tests/ui/traits/resolution-in-overloaded-op.rs new file mode 100644 index 000000000..a9bacc357 --- /dev/null +++ b/tests/ui/traits/resolution-in-overloaded-op.rs @@ -0,0 +1,11 @@ +// #12402 Operator overloading only considers the method name, not which trait is implemented + +trait MyMul<Rhs, Res> { + fn mul(&self, rhs: &Rhs) -> Res; +} + +fn foo<T: MyMul<f64, f64>>(a: &T, b: f64) -> f64 { + a * b //~ ERROR cannot multiply `&T` by `f64` +} + +fn main() {} diff --git a/tests/ui/traits/resolution-in-overloaded-op.stderr b/tests/ui/traits/resolution-in-overloaded-op.stderr new file mode 100644 index 000000000..fe5e1d6d2 --- /dev/null +++ b/tests/ui/traits/resolution-in-overloaded-op.stderr @@ -0,0 +1,16 @@ +error[E0369]: cannot multiply `&T` by `f64` + --> $DIR/resolution-in-overloaded-op.rs:8:7 + | +LL | a * b + | - ^ - f64 + | | + | &T + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn foo<T: MyMul<f64, f64>>(a: &T, b: f64) -> f64 where &T: Mul<f64, Output = f64> { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/traits/safety-fn-body.mir.stderr b/tests/ui/traits/safety-fn-body.mir.stderr new file mode 100644 index 000000000..ea7b2048e --- /dev/null +++ b/tests/ui/traits/safety-fn-body.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/safety-fn-body.rs:14:9 + | +LL | *self += 1; + | ^^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/traits/safety-fn-body.rs b/tests/ui/traits/safety-fn-body.rs new file mode 100644 index 000000000..2cc4fe1b3 --- /dev/null +++ b/tests/ui/traits/safety-fn-body.rs @@ -0,0 +1,19 @@ +// Check that an unsafe impl does not imply that unsafe actions are +// legal in the methods. + +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +unsafe trait UnsafeTrait : Sized { + fn foo(self) { } +} + +unsafe impl UnsafeTrait for *mut isize { + fn foo(self) { + // Unsafe actions are not made legal by taking place in an unsafe trait: + *self += 1; + //~^ ERROR E0133 + } +} + +fn main() { } diff --git a/tests/ui/traits/safety-fn-body.thir.stderr b/tests/ui/traits/safety-fn-body.thir.stderr new file mode 100644 index 000000000..23696c32b --- /dev/null +++ b/tests/ui/traits/safety-fn-body.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/safety-fn-body.rs:14:9 + | +LL | *self += 1; + | ^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/traits/safety-inherent-impl.rs b/tests/ui/traits/safety-inherent-impl.rs new file mode 100644 index 000000000..50e15f0d2 --- /dev/null +++ b/tests/ui/traits/safety-inherent-impl.rs @@ -0,0 +1,9 @@ +// Check that inherent impls cannot be unsafe. + +struct SomeStruct; + +unsafe impl SomeStruct { //~ ERROR inherent impls cannot be unsafe + fn foo(self) { } +} + +fn main() { } diff --git a/tests/ui/traits/safety-inherent-impl.stderr b/tests/ui/traits/safety-inherent-impl.stderr new file mode 100644 index 000000000..1c8f43fec --- /dev/null +++ b/tests/ui/traits/safety-inherent-impl.stderr @@ -0,0 +1,11 @@ +error[E0197]: inherent impls cannot be unsafe + --> $DIR/safety-inherent-impl.rs:5:13 + | +LL | unsafe impl SomeStruct { + | ------ ^^^^^^^^^^ inherent impl for this type + | | + | unsafe because of this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0197`. diff --git a/tests/ui/traits/safety-ok-cc.rs b/tests/ui/traits/safety-ok-cc.rs new file mode 100644 index 000000000..099ba80e5 --- /dev/null +++ b/tests/ui/traits/safety-ok-cc.rs @@ -0,0 +1,24 @@ +// run-pass +// aux-build:trait_safety_lib.rs + +// Simple smoke test that unsafe traits can be compiled across crates. + + +extern crate trait_safety_lib as lib; + +use lib::Foo; + +struct Bar { x: isize } +unsafe impl Foo for Bar { + fn foo(&self) -> isize { self.x } +} + +fn take_foo<F:Foo>(f: &F) -> isize { f.foo() } + +fn main() { + let x: isize = 22; + assert_eq!(22, take_foo(&x)); + + let x: Bar = Bar { x: 23 }; + assert_eq!(23, take_foo(&x)); +} diff --git a/tests/ui/traits/safety-ok.rs b/tests/ui/traits/safety-ok.rs new file mode 100644 index 000000000..d456a78b6 --- /dev/null +++ b/tests/ui/traits/safety-ok.rs @@ -0,0 +1,18 @@ +// run-pass +// Simple smoke test that unsafe traits can be compiled etc. + + +unsafe trait Foo { + fn foo(&self) -> isize; +} + +unsafe impl Foo for isize { + fn foo(&self) -> isize { *self } +} + +fn take_foo<F:Foo>(f: &F) -> isize { f.foo() } + +fn main() { + let x: isize = 22; + assert_eq!(22, take_foo(&x)); +} diff --git a/tests/ui/traits/safety-trait-impl-cc.rs b/tests/ui/traits/safety-trait-impl-cc.rs new file mode 100644 index 000000000..6f125e5f9 --- /dev/null +++ b/tests/ui/traits/safety-trait-impl-cc.rs @@ -0,0 +1,15 @@ +// aux-build:trait_safety_lib.rs + +// Check that unsafe traits require unsafe impls and that inherent +// impls cannot be unsafe. + +extern crate trait_safety_lib as lib; + +struct Bar; +impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration + fn foo(&self) -> isize { + panic!(); + } +} + +fn main() { } diff --git a/tests/ui/traits/safety-trait-impl-cc.stderr b/tests/ui/traits/safety-trait-impl-cc.stderr new file mode 100644 index 000000000..0ca565787 --- /dev/null +++ b/tests/ui/traits/safety-trait-impl-cc.stderr @@ -0,0 +1,15 @@ +error[E0200]: the trait `Foo` requires an `unsafe impl` declaration + --> $DIR/safety-trait-impl-cc.rs:9:1 + | +LL | impl lib::Foo for Bar { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl lib::Foo for Bar { + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0200`. diff --git a/tests/ui/traits/safety-trait-impl.rs b/tests/ui/traits/safety-trait-impl.rs new file mode 100644 index 000000000..45258b78d --- /dev/null +++ b/tests/ui/traits/safety-trait-impl.rs @@ -0,0 +1,18 @@ +// Check that unsafe traits require unsafe impls and that inherent +// impls cannot be unsafe. + +trait SafeTrait { + fn foo(&self) { } +} + +unsafe trait UnsafeTrait { + fn foo(&self) { } +} + +unsafe impl UnsafeTrait for u8 { } // OK + +impl UnsafeTrait for u16 { } //~ ERROR requires an `unsafe impl` declaration + +unsafe impl SafeTrait for u32 { } //~ ERROR the trait `SafeTrait` is not unsafe + +fn main() { } diff --git a/tests/ui/traits/safety-trait-impl.stderr b/tests/ui/traits/safety-trait-impl.stderr new file mode 100644 index 000000000..e78e0e3a6 --- /dev/null +++ b/tests/ui/traits/safety-trait-impl.stderr @@ -0,0 +1,28 @@ +error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration + --> $DIR/safety-trait-impl.rs:14:1 + | +LL | impl UnsafeTrait for u16 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl UnsafeTrait for u16 { } + | ++++++ + +error[E0199]: implementing the trait `SafeTrait` is not unsafe + --> $DIR/safety-trait-impl.rs:16:1 + | +LL | unsafe impl SafeTrait for u32 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `unsafe` from this trait implementation + | +LL - unsafe impl SafeTrait for u32 { } +LL + impl SafeTrait for u32 { } + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0199, E0200. +For more information about an error, try `rustc --explain E0199`. diff --git a/tests/ui/traits/self-without-lifetime-constraint.rs b/tests/ui/traits/self-without-lifetime-constraint.rs new file mode 100644 index 000000000..99013d32a --- /dev/null +++ b/tests/ui/traits/self-without-lifetime-constraint.rs @@ -0,0 +1,53 @@ +use std::error::Error; +use std::fmt; + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ValueRef<'a> { + Null, + Integer(i64), + Real(f64), + Text(&'a [u8]), + Blob(&'a [u8]), +} + +impl<'a> ValueRef<'a> { + pub fn as_str(&self) -> FromSqlResult<&'a str, &'a &'a str> { + match *self { + ValueRef::Text(t) => { + std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x)) + } + _ => Err(FromSqlError::InvalidType), + } + } +} + +#[derive(Debug)] +#[non_exhaustive] +pub enum FromSqlError { + InvalidType +} + +impl fmt::Display for FromSqlError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "InvalidType") + } +} + +impl Error for FromSqlError {} + +pub type FromSqlResult<T, K> = Result<(T, K), FromSqlError>; + +pub trait FromSql: Sized { + fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>; +} + +impl FromSql for &str { + fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { + //~^ ERROR `impl` item signature doesn't match `trait` item signature + value.as_str() + } +} + +pub fn main() { + println!("{}", "Hello World"); +} diff --git a/tests/ui/traits/self-without-lifetime-constraint.stderr b/tests/ui/traits/self-without-lifetime-constraint.stderr new file mode 100644 index 000000000..05a49820a --- /dev/null +++ b/tests/ui/traits/self-without-lifetime-constraint.stderr @@ -0,0 +1,19 @@ +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/self-without-lifetime-constraint.rs:45:5 + | +LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>; + | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` +... +LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` + | + = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` + found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` +help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + --> $DIR/self-without-lifetime-constraint.rs:41:60 + | +LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>; + | ^^^^ consider borrowing this type parameter in the trait + +error: aborting due to previous error + diff --git a/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs b/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs new file mode 100644 index 000000000..5449f5f00 --- /dev/null +++ b/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs @@ -0,0 +1,69 @@ +// check-pass + +// This test checks that we're correctly dealing with inductive cycles +// with canonical inference variables. + +trait Trait<T, U> {} + +trait IsNotU32 {} +impl IsNotU32 for i32 {} +impl<T: IsNotU32, U> Trait<T, U> for () // impl 1 +where + (): Trait<U, T> +{} + +impl<T> Trait<u32, T> for () {} // impl 2 + +// If we now check whether `(): Trait<?0, ?1>` holds this has to +// result in ambiguity as both `for<T> (): Trait<u32, T>` and `(): Trait<i32, u32>` +// applies. The remainder of this test asserts that. + +// If we were to error on inductive cycles with canonical inference variables +// this would be wrong: + +// (): Trait<?0, ?1> +// - impl 1 +// - ?0: IsNotU32 // ambig +// - (): Trait<?1, ?0> // canonical cycle -> err +// - ERR +// - impl 2 +// - OK ?0 == u32 +// +// Result: OK ?0 == u32. + +// (): Trait<i32, u32> +// - impl 1 +// - i32: IsNotU32 // ok +// - (): Trait<u32, i32> +// - impl 1 +// - u32: IsNotU32 // err +// - ERR +// - impl 2 +// - OK +// - OK +// - impl 2 (trivial ERR) +// +// Result OK + +// This would mean that `(): Trait<?0, ?1>` is not complete, +// which is unsound if we're in coherence. + +fn implements_trait<T, U>() -> (T, U) +where + (): Trait<T, U>, +{ + todo!() +} + +// A hack to only constrain the infer vars after first checking +// the `(): Trait<_, _>`. +trait Constrain<T> {} +impl<T> Constrain<T> for T {} +fn constrain<T: Constrain<U>, U>(_: U) {} + +fn main() { + let (x, y) = implements_trait::<_, _>(); + + constrain::<i32, _>(x); + constrain::<u32, _>(y); +} diff --git a/tests/ui/traits/static-method-generic-inference.rs b/tests/ui/traits/static-method-generic-inference.rs new file mode 100644 index 000000000..f4e94c4f7 --- /dev/null +++ b/tests/ui/traits/static-method-generic-inference.rs @@ -0,0 +1,28 @@ +// Issue #3902. We are (at least currently) unable to infer `Self` +// based on `T`, even though there is only a single impl, because of +// the possibility of associated types and other things (basically: no +// constraints on `Self` here at all). + +mod base { + pub trait HasNew<T> { + fn new() -> T; + fn dummy(&self) { } + } + + pub struct Foo { + dummy: (), + } + + impl HasNew<Foo> for Foo { + fn new() -> Foo { + Foo { dummy: () } + } + } +} + +pub fn foo() { + let _f: base::Foo = base::HasNew::new(); + //~^ ERROR E0790 +} + +fn main() { } diff --git a/tests/ui/traits/static-method-generic-inference.stderr b/tests/ui/traits/static-method-generic-inference.stderr new file mode 100644 index 000000000..575ace237 --- /dev/null +++ b/tests/ui/traits/static-method-generic-inference.stderr @@ -0,0 +1,17 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/static-method-generic-inference.rs:24:25 + | +LL | fn new() -> T; + | -------------- `HasNew::new` defined here +... +LL | let _f: base::Foo = base::HasNew::new(); + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | let _f: base::Foo = <Foo as base::HasNew>::new(); + | +++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/traits/static-method-overwriting.rs b/tests/ui/traits/static-method-overwriting.rs new file mode 100644 index 000000000..f669ffae6 --- /dev/null +++ b/tests/ui/traits/static-method-overwriting.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(dead_code)] +mod base { + pub trait HasNew { + fn new() -> Self; + } + + pub struct Foo { + dummy: (), + } + + impl ::base::HasNew for Foo { + fn new() -> Foo { + println!("Foo"); + Foo { dummy: () } + } + } + + pub struct Bar { + dummy: (), + } + + impl ::base::HasNew for Bar { + fn new() -> Bar { + println!("Bar"); + Bar { dummy: () } + } + } +} + +pub fn main() { + let _f: base::Foo = base::HasNew::new(); + let _b: base::Bar = base::HasNew::new(); +} diff --git a/tests/ui/traits/static-outlives-a-where-clause.rs b/tests/ui/traits/static-outlives-a-where-clause.rs new file mode 100644 index 000000000..f0c2c1082 --- /dev/null +++ b/tests/ui/traits/static-outlives-a-where-clause.rs @@ -0,0 +1,23 @@ +// run-pass + +trait Foo<'a> { + fn xyz(self); +} +impl<'a, T> Foo<'a> for T where 'static: 'a { + fn xyz(self) {} +} + +trait Bar { + fn uvw(self); +} +impl<T> Bar for T where for<'a> T: Foo<'a> { + fn uvw(self) { self.xyz(); } +} + +fn foo<T>(t: T) where T: Bar { + t.uvw(); +} + +fn main() { + foo(0); +} diff --git a/tests/ui/traits/staticness-mismatch.rs b/tests/ui/traits/staticness-mismatch.rs new file mode 100644 index 000000000..8710d0112 --- /dev/null +++ b/tests/ui/traits/staticness-mismatch.rs @@ -0,0 +1,11 @@ +trait Foo { + fn dummy(&self) { } + fn bar(); +} + +impl Foo for isize { + fn bar(&self) {} + //~^ ERROR method `bar` has a `&self` declaration in the impl, but not in the trait +} + +fn main() {} diff --git a/tests/ui/traits/staticness-mismatch.stderr b/tests/ui/traits/staticness-mismatch.stderr new file mode 100644 index 000000000..b67ac5adb --- /dev/null +++ b/tests/ui/traits/staticness-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0185]: method `bar` has a `&self` declaration in the impl, but not in the trait + --> $DIR/staticness-mismatch.rs:7:5 + | +LL | fn bar(); + | --------- trait method declared without `&self` +... +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^ `&self` used in impl + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0185`. diff --git a/tests/ui/traits/suggest-deferences/issue-39029.fixed b/tests/ui/traits/suggest-deferences/issue-39029.fixed new file mode 100644 index 000000000..a1abf668b --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-39029.fixed @@ -0,0 +1,18 @@ +// run-rustfix +use std::net::TcpListener; + +struct NoToSocketAddrs(String); + +impl std::ops::Deref for NoToSocketAddrs { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let _works = TcpListener::bind("some string"); + let bad = NoToSocketAddrs("bad".to_owned()); + let _errors = TcpListener::bind(&*bad); + //~^ ERROR the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/issue-39029.rs b/tests/ui/traits/suggest-deferences/issue-39029.rs new file mode 100644 index 000000000..90d097105 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-39029.rs @@ -0,0 +1,18 @@ +// run-rustfix +use std::net::TcpListener; + +struct NoToSocketAddrs(String); + +impl std::ops::Deref for NoToSocketAddrs { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let _works = TcpListener::bind("some string"); + let bad = NoToSocketAddrs("bad".to_owned()); + let _errors = TcpListener::bind(&bad); + //~^ ERROR the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/issue-39029.stderr b/tests/ui/traits/suggest-deferences/issue-39029.stderr new file mode 100644 index 000000000..49e20c6a7 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-39029.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied + --> $DIR/issue-39029.rs:16:37 + | +LL | let _errors = TcpListener::bind(&bad); + | ----------------- ^^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` + | | + | required by a bound introduced by this call + | + = note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs` +note: required by a bound in `TcpListener::bind` + --> $SRC_DIR/std/src/net/tcp.rs:LL:COL +help: consider dereferencing here + | +LL | let _errors = TcpListener::bind(&*bad); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/issue-62530.fixed b/tests/ui/traits/suggest-deferences/issue-62530.fixed new file mode 100644 index 000000000..406caaa00 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-62530.fixed @@ -0,0 +1,15 @@ +// run-rustfix +fn takes_str(_x: &str) {} + +fn takes_type_parameter<T>(_x: T) where T: SomeTrait {} + +trait SomeTrait {} +impl SomeTrait for &'_ str {} +impl SomeTrait for char {} + +fn main() { + let string = String::new(); + takes_str(&string); // Ok + takes_type_parameter(&*string); // Error + //~^ ERROR the trait bound `&String: SomeTrait` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/issue-62530.rs b/tests/ui/traits/suggest-deferences/issue-62530.rs new file mode 100644 index 000000000..53846be73 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-62530.rs @@ -0,0 +1,15 @@ +// run-rustfix +fn takes_str(_x: &str) {} + +fn takes_type_parameter<T>(_x: T) where T: SomeTrait {} + +trait SomeTrait {} +impl SomeTrait for &'_ str {} +impl SomeTrait for char {} + +fn main() { + let string = String::new(); + takes_str(&string); // Ok + takes_type_parameter(&string); // Error + //~^ ERROR the trait bound `&String: SomeTrait` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/issue-62530.stderr b/tests/ui/traits/suggest-deferences/issue-62530.stderr new file mode 100644 index 000000000..e47ae0b65 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-62530.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `&String: SomeTrait` is not satisfied + --> $DIR/issue-62530.rs:13:26 + | +LL | takes_type_parameter(&string); // Error + | -------------------- ^^^^^^^ the trait `SomeTrait` is not implemented for `&String` + | | + | required by a bound introduced by this call + | +note: required by a bound in `takes_type_parameter` + --> $DIR/issue-62530.rs:4:44 + | +LL | fn takes_type_parameter<T>(_x: T) where T: SomeTrait {} + | ^^^^^^^^^ required by this bound in `takes_type_parameter` +help: consider dereferencing here + | +LL | takes_type_parameter(&*string); // Error + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/multiple-0.fixed b/tests/ui/traits/suggest-deferences/multiple-0.fixed new file mode 100644 index 000000000..b7160b75c --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-0.fixed @@ -0,0 +1,36 @@ +// run-rustfix +use std::ops::Deref; + +trait Happy {} +struct LDM; +impl Happy for &LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn foo<T>(_: T) where T: Happy {} + +fn main() { + let baz = Baz(Bar(Foo(LDM))); + foo(&***baz); + //~^ ERROR the trait bound `&Baz: Happy` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/multiple-0.rs b/tests/ui/traits/suggest-deferences/multiple-0.rs new file mode 100644 index 000000000..9ac55177f --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-0.rs @@ -0,0 +1,36 @@ +// run-rustfix +use std::ops::Deref; + +trait Happy {} +struct LDM; +impl Happy for &LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn foo<T>(_: T) where T: Happy {} + +fn main() { + let baz = Baz(Bar(Foo(LDM))); + foo(&baz); + //~^ ERROR the trait bound `&Baz: Happy` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/multiple-0.stderr b/tests/ui/traits/suggest-deferences/multiple-0.stderr new file mode 100644 index 000000000..6a4d4b8d5 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-0.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `&Baz: Happy` is not satisfied + --> $DIR/multiple-0.rs:34:9 + | +LL | foo(&baz); + | --- ^^^^ the trait `Happy` is not implemented for `&Baz` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/multiple-0.rs:30:26 + | +LL | fn foo<T>(_: T) where T: Happy {} + | ^^^^^ required by this bound in `foo` +help: consider dereferencing here + | +LL | foo(&***baz); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/multiple-1.rs b/tests/ui/traits/suggest-deferences/multiple-1.rs new file mode 100644 index 000000000..91c6c7924 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-1.rs @@ -0,0 +1,54 @@ +use std::ops::{Deref, DerefMut}; + +trait Happy {} +struct LDM; +impl Happy for &mut LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Bar { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Baz { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + + +fn foo<T>(_: T) where T: Happy {} + +fn main() { + // Currently the compiler doesn't try to suggest dereferences for situations + // where DerefMut involves. So this test is meant to ensure compiler doesn't + // generate incorrect help message. + let mut baz = Baz(Bar(Foo(LDM))); + foo(&mut baz); + //~^ ERROR the trait bound `&mut Baz: Happy` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/multiple-1.stderr b/tests/ui/traits/suggest-deferences/multiple-1.stderr new file mode 100644 index 000000000..6e12321c2 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-1.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `&mut Baz: Happy` is not satisfied + --> $DIR/multiple-1.rs:52:9 + | +LL | foo(&mut baz); + | --- ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz` + | | + | required by a bound introduced by this call + | + = help: the trait `Happy` is implemented for `&mut LDM` +note: required by a bound in `foo` + --> $DIR/multiple-1.rs:45:26 + | +LL | fn foo<T>(_: T) where T: Happy {} + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/root-obligation.fixed b/tests/ui/traits/suggest-deferences/root-obligation.fixed new file mode 100644 index 000000000..7a8433f90 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/root-obligation.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +fn get_vowel_count(string: &str) -> usize { + string + .chars() + .filter(|c| "aeiou".contains(*c)) + //~^ ERROR expected a `Fn<(char,)>` closure, found `char` + .count() +} + +fn main() { + let _ = get_vowel_count("asdf"); +} diff --git a/tests/ui/traits/suggest-deferences/root-obligation.rs b/tests/ui/traits/suggest-deferences/root-obligation.rs new file mode 100644 index 000000000..51bac2107 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/root-obligation.rs @@ -0,0 +1,13 @@ +// run-rustfix + +fn get_vowel_count(string: &str) -> usize { + string + .chars() + .filter(|c| "aeiou".contains(c)) + //~^ ERROR expected a `Fn<(char,)>` closure, found `char` + .count() +} + +fn main() { + let _ = get_vowel_count("asdf"); +} diff --git a/tests/ui/traits/suggest-deferences/root-obligation.stderr b/tests/ui/traits/suggest-deferences/root-obligation.stderr new file mode 100644 index 000000000..1363fb8c4 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/root-obligation.stderr @@ -0,0 +1,21 @@ +error[E0277]: expected a `Fn<(char,)>` closure, found `char` + --> $DIR/root-obligation.rs:6:38 + | +LL | .filter(|c| "aeiou".contains(c)) + | -------- ^ expected an `Fn<(char,)>` closure, found `char` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<(char,)>` is not implemented for `char` + = note: required for `&char` to implement `FnOnce<(char,)>` + = note: required for `&char` to implement `Pattern<'_>` +note: required by a bound in `core::str::<impl str>::contains` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL +help: consider dereferencing here + | +LL | .filter(|c| "aeiou".contains(*c)) + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed new file mode 100644 index 000000000..ea3d1bf85 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +struct TargetStruct; + +impl From<usize> for TargetStruct { + fn from(_unchecked: usize) -> Self { + TargetStruct + } +} + +fn main() { + let a = &3; + let _b: TargetStruct = (*a).into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs new file mode 100644 index 000000000..9eda68027 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs @@ -0,0 +1,14 @@ +// run-rustfix + +struct TargetStruct; + +impl From<usize> for TargetStruct { + fn from(_unchecked: usize) -> Self { + TargetStruct + } +} + +fn main() { + let a = &3; + let _b: TargetStruct = a.into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr new file mode 100644 index 000000000..ede31a2c7 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied + --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30 + | +LL | let _b: TargetStruct = a.into(); + | ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct` + | + = note: required for `&{integer}` to implement `Into<TargetStruct>` +help: consider dereferencing here + | +LL | let _b: TargetStruct = (*a).into(); + | ++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-fully-qualified-closure.rs b/tests/ui/traits/suggest-fully-qualified-closure.rs new file mode 100644 index 000000000..c077921c0 --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-closure.rs @@ -0,0 +1,24 @@ +// check-fail +// known-bug: #103705 +// normalize-stderr-test "\[closure@.*\]" -> "[closure@]" +// normalize-stderr-test "\+* ~" -> "+++ ~" + +// The output of this currently suggests writing a closure in the qualified path. + +trait MyTrait<T> { + fn lol<F:FnOnce()>(&self, f:F) -> u16; +} + +struct Qqq; + +impl MyTrait<u32> for Qqq{ + fn lol<F:FnOnce()>(&self, _f:F) -> u16 { 5 } +} +impl MyTrait<u64> for Qqq{ + fn lol<F:FnOnce()>(&self, _f:F) -> u16 { 6 } +} + +fn main() { + let q = Qqq; + q.lol(||()); +} diff --git a/tests/ui/traits/suggest-fully-qualified-closure.stderr b/tests/ui/traits/suggest-fully-qualified-closure.stderr new file mode 100644 index 000000000..3df623c14 --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-closure.stderr @@ -0,0 +1,34 @@ +error[E0282]: type annotations needed + --> $DIR/suggest-fully-qualified-closure.rs:23:7 + | +LL | q.lol(||()); + | ^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | <Qqq as MyTrait<T>>::lol::<[closure@]>(&q, ||()); + | +++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-closure.rs:23:7 + | +LL | q.lol(||()); + | ^^^ + | +note: multiple `impl`s satisfying `Qqq: MyTrait<_>` found + --> $DIR/suggest-fully-qualified-closure.rs:14:1 + | +LL | impl MyTrait<u32> for Qqq{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MyTrait<u64> for Qqq{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Qqq as MyTrait<T>>::lol::<[closure@]>(&q, ||()); + | +++ ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs new file mode 100644 index 000000000..9a2cf469d --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs @@ -0,0 +1,60 @@ +use std::ops::{Deref, DerefMut}; + +struct Thing; + +trait Method<T> { + fn method(&self) -> T; + fn mut_method(&mut self) -> T; +} + +impl Method<i32> for Thing { + fn method(&self) -> i32 { 0 } + fn mut_method(&mut self) -> i32 { 0 } +} + +impl Method<u32> for Thing { + fn method(&self) -> u32 { 0 } + fn mut_method(&mut self) -> u32 { 0 } +} +trait MethodRef<T> { + fn by_self(self); +} +impl MethodRef<i32> for &Thing { + fn by_self(self) {} +} +impl MethodRef<u32> for &Thing { + fn by_self(self) {} +} + + +struct DerefsTo<T>(T); +impl<T> Deref for DerefsTo<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl<T> DerefMut for DerefsTo<T> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() { + let mut thing = Thing; + thing.method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + thing.mut_method(); //~ ERROR type annotations needed + thing.by_self(); //~ ERROR type annotations needed + + let mut deref_to = DerefsTo(Thing); + deref_to.method(); //~ ERROR type annotations needed + deref_to.mut_method(); //~ ERROR type annotations needed + deref_to.by_self(); //~ ERROR type annotations needed + + let mut deref_deref_to = DerefsTo(DerefsTo(Thing)); + deref_deref_to.method(); //~ ERROR type annotations needed + deref_deref_to.mut_method(); //~ ERROR type annotations needed + deref_deref_to.by_self(); //~ ERROR type annotations needed +} diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr new file mode 100644 index 000000000..68b31a1ca --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr @@ -0,0 +1,186 @@ +error[E0282]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11 + | +LL | thing.method(); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(&thing); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11 + | +LL | thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(&thing); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:48:11 + | +LL | thing.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::mut_method(&mut thing); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:49:11 + | +LL | thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef<i32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef<u32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef<T>>::by_self(&thing); + | +++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:52:14 + | +LL | deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(&deref_to); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:53:14 + | +LL | deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::mut_method(&mut deref_to); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:54:14 + | +LL | deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef<i32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef<u32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef<T>>::by_self(&deref_to); + | +++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:57:20 + | +LL | deref_deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(&deref_deref_to); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:58:20 + | +LL | deref_deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::mut_method(&mut deref_deref_to); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:59:20 + | +LL | deref_deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef<i32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef<u32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef<T>>::by_self(&deref_deref_to); + | +++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs new file mode 100644 index 000000000..da640c8c8 --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs @@ -0,0 +1,64 @@ +use std::ops::{Deref, DerefMut}; + +struct Thing; + +trait Method<T> { + fn method(&self) -> T; + fn mut_method(&mut self) -> T; +} + +impl Method<i32> for Thing { + fn method(&self) -> i32 { 0 } + fn mut_method(&mut self) -> i32 { 0 } +} + +impl Method<u32> for Thing { + fn method(&self) -> u32 { 0 } + fn mut_method(&mut self) -> u32 { 0 } +} + +trait MethodRef<T> { + fn by_self(self); +} +impl MethodRef<i32> for &Thing { + fn by_self(self) {} +} +impl MethodRef<u32> for &Thing { + fn by_self(self) {} +} + +struct DerefsTo<T>(T); +impl<T> Deref for DerefsTo<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl<T> DerefMut for DerefsTo<T> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() { + let mut ref_thing = &Thing; + ref_thing.method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + ref_thing.by_self(); //~ ERROR type annotations needed + + let mut mut_thing = &mut Thing; + mut_thing.method(); //~ ERROR type annotations needed + mut_thing.mut_method(); //~ ERROR type annotations needed + mut_thing.by_self(); //~ ERROR type annotations needed + + let mut deref_to = &DerefsTo(Thing); + deref_to.method(); //~ ERROR type annotations needed + deref_to.mut_method(); //~ ERROR type annotations needed + deref_to.by_self(); //~ ERROR type annotations needed + + let mut deref_deref_to = &DerefsTo(DerefsTo(Thing)); + deref_deref_to.method(); //~ ERROR type annotations needed + deref_deref_to.mut_method(); //~ ERROR type annotations needed + deref_deref_to.by_self(); //~ ERROR type annotations needed +} diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr new file mode 100644 index 000000000..27518a54e --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr @@ -0,0 +1,224 @@ +error[E0282]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15 + | +LL | ref_thing.method(); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(ref_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15 + | +LL | ref_thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(ref_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:48:15 + | +LL | ref_thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef<i32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef<u32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef<T>>::by_self(ref_thing); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:51:15 + | +LL | mut_thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(mut_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:52:15 + | +LL | mut_thing.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::mut_method(mut_thing); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:53:15 + | +LL | mut_thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef<i32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef<u32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef<T>>::by_self(mut_thing); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:56:14 + | +LL | deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(deref_to); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:57:14 + | +LL | deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::mut_method(deref_to); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:58:14 + | +LL | deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef<i32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef<u32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef<T>>::by_self(deref_to); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:61:20 + | +LL | deref_deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::method(deref_deref_to); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:62:20 + | +LL | deref_deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method<i32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method<u32> for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <Thing as Method<T>>::mut_method(deref_deref_to); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:63:20 + | +LL | deref_deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef<i32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef<u32> for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef<T>>::by_self(deref_deref_to); + | ++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/suggest-where-clause.rs b/tests/ui/traits/suggest-where-clause.rs new file mode 100644 index 000000000..46d047a2d --- /dev/null +++ b/tests/ui/traits/suggest-where-clause.rs @@ -0,0 +1,36 @@ +use std::mem; + +struct Misc<T:?Sized>(T); + +fn check<T: Iterator, U: ?Sized>() { + // suggest a where-clause, if needed + mem::size_of::<U>(); + //~^ ERROR the size for values of type + + mem::size_of::<Misc<U>>(); + //~^ ERROR the size for values of type + + // ... even if T occurs as a type parameter + + <u64 as From<T>>::from; + //~^ ERROR `u64: From<T>` is not satisfied + + <u64 as From<<T as Iterator>::Item>>::from; + //~^ ERROR `u64: From<<T as Iterator>::Item>` is not satisfied + + // ... but not if there are inference variables + + <Misc<_> as From<T>>::from; + //~^ ERROR `Misc<_>: From<T>` is not satisfied + + // ... and also not if the error is not related to the type + + mem::size_of::<[T]>(); + //~^ ERROR the size for values of type + + mem::size_of::<[&U]>(); + //~^ ERROR the size for values of type +} + +fn main() { +} diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr new file mode 100644 index 000000000..44e63b78c --- /dev/null +++ b/tests/ui/traits/suggest-where-clause.stderr @@ -0,0 +1,90 @@ +error[E0277]: the size for values of type `U` cannot be known at compilation time + --> $DIR/suggest-where-clause.rs:7:20 + | +LL | fn check<T: Iterator, U: ?Sized>() { + | - this type parameter needs to be `std::marker::Sized` +LL | // suggest a where-clause, if needed +LL | mem::size_of::<U>(); + | ^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn check<T: Iterator, U: ?Sized>() { +LL + fn check<T: Iterator, U>() { + | + +error[E0277]: the size for values of type `U` cannot be known at compilation time + --> $DIR/suggest-where-clause.rs:10:20 + | +LL | fn check<T: Iterator, U: ?Sized>() { + | - this type parameter needs to be `std::marker::Sized` +... +LL | mem::size_of::<Misc<U>>(); + | ^^^^^^^ doesn't have a size known at compile-time + | +note: required because it appears within the type `Misc<U>` + --> $DIR/suggest-where-clause.rs:3:8 + | +LL | struct Misc<T:?Sized>(T); + | ^^^^ +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn check<T: Iterator, U: ?Sized>() { +LL + fn check<T: Iterator, U>() { + | + +error[E0277]: the trait bound `u64: From<T>` is not satisfied + --> $DIR/suggest-where-clause.rs:15:5 + | +LL | <u64 as From<T>>::from; + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn check<T: Iterator, U: ?Sized>() where u64: From<T> { + | ++++++++++++++++++ + +error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfied + --> $DIR/suggest-where-clause.rs:18:5 + | +LL | <u64 as From<<T as Iterator>::Item>>::from; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn check<T: Iterator, U: ?Sized>() where u64: From<<T as Iterator>::Item> { + | ++++++++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied + --> $DIR/suggest-where-clause.rs:23:5 + | +LL | <Misc<_> as From<T>>::from; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `Misc<_>` + +error[E0277]: the size for values of type `[T]` cannot be known at compilation time + --> $DIR/suggest-where-clause.rs:28:20 + | +LL | mem::size_of::<[T]>(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[T]` +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error[E0277]: the size for values of type `[&U]` cannot be known at compilation time + --> $DIR/suggest-where-clause.rs:31:20 + | +LL | mem::size_of::<[&U]>(); + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[&U]` +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/superdefault-generics.rs b/tests/ui/traits/superdefault-generics.rs new file mode 100644 index 000000000..e862c0e97 --- /dev/null +++ b/tests/ui/traits/superdefault-generics.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +// There is some other borrowck bug, so we make the stuff not mut. + + +use std::ops::Add; + +trait Positioned<S> { + fn SetX(&mut self, _: S); + fn X(&self) -> S; +} + +trait Movable<S: Add<Output=S>>: Positioned<S> { + fn translate(&mut self, dx: S) { + let x = self.X() + dx; + self.SetX(x); + } +} + +struct Point<S> { x: S, y: S } + +impl<S: Clone> Positioned<S> for Point<S> { + fn SetX(&mut self, x: S) { + self.x = x; + } + fn X(&self) -> S { + self.x.clone() + } +} + +impl<S: Clone + Add<Output=S>> Movable<S> for Point<S> {} + +pub fn main() { + let mut p = Point{ x: 1, y: 2}; + p.translate(3); + assert_eq!(p.X(), 4); +} diff --git a/tests/ui/traits/syntax-polarity.rs b/tests/ui/traits/syntax-polarity.rs new file mode 100644 index 000000000..c809f9e89 --- /dev/null +++ b/tests/ui/traits/syntax-polarity.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#![feature(negative_impls)] + +struct TestType; + +impl TestType {} + +trait TestTrait {} + +impl !Send for TestType {} + +struct TestType2<T>(T); + +impl<T> TestType2<T> {} + +impl<T> !Send for TestType2<T> {} + +fn main() {} diff --git a/tests/ui/traits/syntax-trait-polarity.rs b/tests/ui/traits/syntax-trait-polarity.rs new file mode 100644 index 000000000..ed2947493 --- /dev/null +++ b/tests/ui/traits/syntax-trait-polarity.rs @@ -0,0 +1,25 @@ +#![feature(negative_impls)] + +use std::marker::Send; + +struct TestType; + +impl !TestType {} +//~^ ERROR inherent impls cannot be negative + +trait TestTrait {} + +unsafe impl !Send for TestType {} +//~^ ERROR negative impls cannot be unsafe +impl !TestTrait for TestType {} + +struct TestType2<T>(T); + +impl<T> !TestType2<T> {} +//~^ ERROR inherent impls cannot be negative + +unsafe impl<T> !Send for TestType2<T> {} +//~^ ERROR negative impls cannot be unsafe +impl<T> !TestTrait for TestType2<T> {} + +fn main() {} diff --git a/tests/ui/traits/syntax-trait-polarity.stderr b/tests/ui/traits/syntax-trait-polarity.stderr new file mode 100644 index 000000000..1fd40fb66 --- /dev/null +++ b/tests/ui/traits/syntax-trait-polarity.stderr @@ -0,0 +1,37 @@ +error: inherent impls cannot be negative + --> $DIR/syntax-trait-polarity.rs:7:7 + | +LL | impl !TestType {} + | -^^^^^^^^ inherent impl for this type + | | + | negative because of this + +error[E0198]: negative impls cannot be unsafe + --> $DIR/syntax-trait-polarity.rs:12:13 + | +LL | unsafe impl !Send for TestType {} + | ------ -^^^^ + | | | + | | negative because of this + | unsafe because of this + +error: inherent impls cannot be negative + --> $DIR/syntax-trait-polarity.rs:18:10 + | +LL | impl<T> !TestType2<T> {} + | -^^^^^^^^^^^^ inherent impl for this type + | | + | negative because of this + +error[E0198]: negative impls cannot be unsafe + --> $DIR/syntax-trait-polarity.rs:21:16 + | +LL | unsafe impl<T> !Send for TestType2<T> {} + | ------ -^^^^ + | | | + | | negative because of this + | unsafe because of this + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0198`. diff --git a/tests/ui/traits/test-2.rs b/tests/ui/traits/test-2.rs new file mode 100644 index 000000000..342928e88 --- /dev/null +++ b/tests/ui/traits/test-2.rs @@ -0,0 +1,17 @@ +#[allow(non_camel_case_types)] + + +trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } +impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} } +impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} } + +fn main() { + 10.dup::<i32>(); + //~^ ERROR this associated function takes 0 generic arguments but 1 + 10.blah::<i32, i32>(); + //~^ ERROR this associated function takes 1 generic argument but 2 + (Box::new(10) as Box<dyn bar>).dup(); + //~^ ERROR E0038 + //~| ERROR E0038 + //~| ERROR E0038 +} diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr new file mode 100644 index 000000000..eaa20b0b4 --- /dev/null +++ b/tests/ui/traits/test-2.stderr @@ -0,0 +1,85 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/test-2.rs:9:8 + | +LL | 10.dup::<i32>(); + | ^^^------- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/test-2.rs:4:16 + | +LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } + | ^^^ + +error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/test-2.rs:11:8 + | +LL | 10.blah::<i32, i32>(); + | ^^^^ --- help: remove this generic argument + | | + | expected 1 generic argument + | +note: associated function defined here, with 1 generic parameter: `X` + --> $DIR/test-2.rs:4:39 + | +LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } + | ^^^^ - + +error[E0038]: the trait `bar` cannot be made into an object + --> $DIR/test-2.rs:13:22 + | +LL | (Box::new(10) as Box<dyn bar>).dup(); + | ^^^^^^^^^^^^ `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/test-2.rs:4:30 + | +LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } + | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type + | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait + +error[E0038]: the trait `bar` cannot be made into an object + --> $DIR/test-2.rs:13:5 + | +LL | (Box::new(10) as Box<dyn bar>).dup(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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/test-2.rs:4:30 + | +LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } + | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type + | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait + +error[E0038]: the trait `bar` cannot be made into an object + --> $DIR/test-2.rs:13:6 + | +LL | (Box::new(10) as Box<dyn bar>).dup(); + | ^^^^^^^^^^^^ `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/test-2.rs:4:30 + | +LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } + | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type + | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait + = note: required for `Box<{integer}>` to implement `CoerceUnsized<Box<dyn bar>>` + = note: required by cast to type `Box<dyn bar>` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/test.rs b/tests/ui/traits/test.rs new file mode 100644 index 000000000..72fc66f74 --- /dev/null +++ b/tests/ui/traits/test.rs @@ -0,0 +1,6 @@ +#[allow(non_camel_case_types)] +trait foo { fn foo(&self); } + +impl isize for usize { fn foo(&self) {} } //~ ERROR trait + +fn main() {} diff --git a/tests/ui/traits/test.stderr b/tests/ui/traits/test.stderr new file mode 100644 index 000000000..668228abe --- /dev/null +++ b/tests/ui/traits/test.stderr @@ -0,0 +1,9 @@ +error[E0404]: expected trait, found builtin type `isize` + --> $DIR/test.rs:4:6 + | +LL | impl isize for usize { fn foo(&self) {} } + | ^^^^^ not a trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/to-str.rs b/tests/ui/traits/to-str.rs new file mode 100644 index 000000000..9670edbfa --- /dev/null +++ b/tests/ui/traits/to-str.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(non_camel_case_types)] + + +trait to_str { + fn to_string_(&self) -> String; +} + +impl to_str for isize { + fn to_string_(&self) -> String { self.to_string() } +} + +impl<T:to_str> to_str for Vec<T> { + fn to_string_(&self) -> String { + format!("[{}]", + self.iter() + .map(|e| e.to_string_()) + .collect::<Vec<String>>() + .join(", ")) + } +} + +pub fn main() { + assert_eq!(1.to_string_(), "1".to_string()); + assert_eq!((vec![2, 3, 4]).to_string_(), "[2, 3, 4]".to_string()); + + fn indirect<T:to_str>(x: T) -> String { + format!("{}!", x.to_string_()) + } + assert_eq!(indirect(vec![10, 20]), "[10, 20]!".to_string()); + + fn indirect2<T:to_str>(x: T) -> String { + indirect(x) + } + assert_eq!(indirect2(vec![1]), "[1]!".to_string()); +} diff --git a/tests/ui/traits/track-obligations.rs b/tests/ui/traits/track-obligations.rs new file mode 100644 index 000000000..77e753c13 --- /dev/null +++ b/tests/ui/traits/track-obligations.rs @@ -0,0 +1,88 @@ +// These are simplifications of the tower traits by the same name: + +pub trait Service<Request> { + type Response; +} + +pub trait Layer<C> { + type Service; +} + +// Any type will do here: + +pub struct Req; +pub struct Res; + +// This is encoding a trait alias. + +pub trait ParticularService: + Service<Req, Response = Res> { +} + +impl<T> ParticularService for T +where + T: Service<Req, Response = Res>, +{ +} + +// This is also a trait alias. +// The weird = <Self as ...> bound is there so that users of the trait do not +// need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671 +// for context, and in particular the workaround in: +// https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828 + +pub trait ParticularServiceLayer<C>: + Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service> +{ + type Service: ParticularService; +} + +impl<T, C> ParticularServiceLayer<C> for T +where + T: Layer<C>, + T::Service: ParticularService, +{ + type Service = T::Service; +} + +// These are types that implement the traits that the trait aliases refer to. +// They should also implement the alias traits due to the blanket impls. + +struct ALayer<C>(C); +impl<C> Layer<C> for ALayer<C> { + type Service = AService; +} + +struct AService; +impl Service<Req> for AService { + // However, AService does _not_ meet the blanket implementation, + // since its Response type is bool, not Res as it should be. + type Response = bool; +} + +// This is a wrapper type around ALayer that uses the trait alias +// as a way to communicate the requirements of the provided types. +struct Client<C>(C); + +// The method and the free-standing function below both have the same bounds. + +impl<C> Client<C> +where + ALayer<C>: ParticularServiceLayer<C>, +{ + fn check(&self) {} +} + +fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {} + +// But, they give very different error messages. + +fn main() { + // This gives a very poor error message that does nothing to point the user + // at the underlying cause of why the types involved do not meet the bounds. + Client(()).check(); //~ ERROR E0599 + + // This gives a good(ish) error message that points the user at _why_ the + // bound isn't met, and thus how they might fix it. + check(()); //~ ERROR E0271 +} diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr new file mode 100644 index 000000000..894774759 --- /dev/null +++ b/tests/ui/traits/track-obligations.stderr @@ -0,0 +1,76 @@ +error[E0599]: the method `check` exists for struct `Client<()>`, but its trait bounds were not satisfied + --> $DIR/track-obligations.rs:83:16 + | +LL | struct ALayer<C>(C); + | ---------------- + | | + | doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` + | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>` +... +LL | struct Client<C>(C); + | ---------------- method `check` not found for this struct +... +LL | Client(()).check(); + | ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds + | +note: trait bound `<ALayer<()> as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` was not satisfied + --> $DIR/track-obligations.rs:35:14 + | +LL | pub trait ParticularServiceLayer<C>: + | ---------------------- +LL | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied + --> $DIR/track-obligations.rs:71:16 + | +LL | impl<C> Client<C> + | --------- +LL | where +LL | ALayer<C>: ParticularServiceLayer<C>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: the trait `ParticularServiceLayer` must be implemented + --> $DIR/track-obligations.rs:34:1 + | +LL | / pub trait ParticularServiceLayer<C>: +LL | | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service> + | |____________________________________________________________________^ + +error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res` + --> $DIR/track-obligations.rs:87:11 + | +LL | check(()); + | ----- ^^ type mismatch resolving `<AService as Service<Req>>::Response == Res` + | | + | required by a bound introduced by this call + | +note: expected this to be `Res` + --> $DIR/track-obligations.rs:60:21 + | +LL | type Response = bool; + | ^^^^ +note: required for `AService` to implement `ParticularService` + --> $DIR/track-obligations.rs:22:9 + | +LL | impl<T> ParticularService for T + | ^^^^^^^^^^^^^^^^^ ^ +LL | where +LL | T: Service<Req, Response = Res>, + | -------------- unsatisfied trait bound introduced here +note: required for `ALayer<_>` to implement `ParticularServiceLayer<_>` + --> $DIR/track-obligations.rs:40:12 + | +LL | impl<T, C> ParticularServiceLayer<C> for T + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +... +LL | T::Service: ParticularService, + | ----------------- unsatisfied trait bound introduced here +note: required by a bound in `check` + --> $DIR/track-obligations.rs:76:36 + | +LL | fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0599. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/trait-or-new-type-instead.rs b/tests/ui/traits/trait-or-new-type-instead.rs new file mode 100644 index 000000000..572b03efc --- /dev/null +++ b/tests/ui/traits/trait-or-new-type-instead.rs @@ -0,0 +1,6 @@ +impl<T> Option<T> { +//~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined + pub fn foo(&self) { } +} + +fn main() { } diff --git a/tests/ui/traits/trait-or-new-type-instead.stderr b/tests/ui/traits/trait-or-new-type-instead.stderr new file mode 100644 index 000000000..4726b0668 --- /dev/null +++ b/tests/ui/traits/trait-or-new-type-instead.stderr @@ -0,0 +1,14 @@ +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/trait-or-new-type-instead.rs:1:1 + | +LL | / impl<T> Option<T> { +LL | | +LL | | pub fn foo(&self) { } +LL | | } + | |_^ impl for type defined outside of crate. + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0116`. diff --git a/tests/ui/traits/trait-upcasting/basic.rs b/tests/ui/traits/trait-upcasting/basic.rs new file mode 100644 index 000000000..570ec5160 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/basic.rs @@ -0,0 +1,86 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz: Bar { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let bar: &dyn Bar = baz; + let _: &dyn std::fmt::Debug = bar; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let foo: &dyn Foo = baz; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let foo: &dyn Foo = bar; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} diff --git a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs new file mode 100644 index 000000000..eae5cf8d5 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs @@ -0,0 +1,38 @@ +// run-pass +#![feature(trait_upcasting)] + +trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {} +trait Bar<T: Default + ToString> { + fn bar(&self) -> String { + T::default().to_string() + } +} + +struct S1; + +impl Bar<i32> for S1 {} +impl Foo<i32> for S1 {} + +struct S2; +impl Bar<i32> for S2 {} +impl Bar<bool> for S2 {} +impl Foo<bool> for S2 {} + +fn test1(x: &dyn Foo<i32>) { + let s = x as &dyn Bar<i32>; + assert_eq!("0", &s.bar().to_string()); +} + +fn test2(x: &dyn Foo<bool>) { + let p = x as &dyn Bar<i32>; + assert_eq!("0", &p.bar().to_string()); + let q = x as &dyn Bar<bool>; + assert_eq!("false", &q.bar().to_string()); +} + +fn main() { + let s1 = S1; + test1(&s1); + let s2 = S2; + test2(&s2); +} diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs new file mode 100644 index 000000000..511e41562 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs @@ -0,0 +1,13 @@ +trait A: B + A {} +//~^ ERROR cycle detected when computing the super predicates of `A` [E0391] + +trait B {} + +impl A for () {} + +impl B for () {} + +fn main() { + let a: Box<dyn A> = Box::new(()); + let _b: Box<dyn B> = a; +} diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr new file mode 100644 index 000000000..15faab16a --- /dev/null +++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when computing the super predicates of `A` + --> $DIR/cyclic-trait-resolution.rs:1:1 + | +LL | trait A: B + A {} + | ^^^^^^^^^^^^^^ + | +note: ...which requires computing the super traits of `A`... + --> $DIR/cyclic-trait-resolution.rs:1:14 + | +LL | trait A: B + A {} + | ^ + = note: ...which again requires computing the super predicates of `A`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/cyclic-trait-resolution.rs:1:1 + | +LL | trait A: B + A {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/trait-upcasting/diamond.rs b/tests/ui/traits/trait-upcasting/diamond.rs new file mode 100644 index 000000000..a4f81c464 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/diamond.rs @@ -0,0 +1,114 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar1: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Bar2: Foo { + fn c(&self) -> i32 { + 30 + } + + fn v(&self) -> i32 { + 31 + } +} + +trait Baz: Bar1 + Bar2 { + fn d(&self) -> i32 { + 40 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar1 for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Bar2 for i32 { + fn c(&self) -> i32 { + 300 + } +} + +impl Baz for i32 { + fn d(&self) -> i32 { + 400 + } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.d(), 400); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + assert_eq!(baz.v(), 31); + + let bar1: &dyn Bar1 = baz; + let _: &dyn std::fmt::Debug = bar1; + assert_eq!(*bar1, 1); + assert_eq!(bar1.a(), 100); + assert_eq!(bar1.b(), 200); + assert_eq!(bar1.z(), 11); + assert_eq!(bar1.y(), 12); + assert_eq!(bar1.w(), 21); + + let bar2: &dyn Bar2 = baz; + let _: &dyn std::fmt::Debug = bar2; + assert_eq!(*bar2, 1); + assert_eq!(bar2.a(), 100); + assert_eq!(bar2.c(), 300); + assert_eq!(bar2.z(), 11); + assert_eq!(bar2.y(), 12); + assert_eq!(bar2.v(), 31); + + let foo: &dyn Foo = baz; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + + let foo: &dyn Foo = bar1; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + + let foo: &dyn Foo = bar2; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); +} diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.rs b/tests/ui/traits/trait-upcasting/invalid-upcast.rs new file mode 100644 index 000000000..e634bbd5a --- /dev/null +++ b/tests/ui/traits/trait-upcasting/invalid-upcast.rs @@ -0,0 +1,86 @@ +#![feature(trait_upcasting)] + +trait Foo { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + //~^ ERROR mismatched types [E0308] + let _: &dyn Send = baz; + //~^ ERROR mismatched types [E0308] + let _: &dyn Sync = baz; + //~^ ERROR mismatched types [E0308] + + let bar: &dyn Bar = baz; + //~^ ERROR mismatched types [E0308] + let _: &dyn std::fmt::Debug = bar; + //~^ ERROR mismatched types [E0308] + let _: &dyn Send = bar; + //~^ ERROR mismatched types [E0308] + let _: &dyn Sync = bar; + //~^ ERROR mismatched types [E0308] + + let foo: &dyn Foo = baz; + //~^ ERROR mismatched types [E0308] + let _: &dyn std::fmt::Debug = foo; + //~^ ERROR mismatched types [E0308] + let _: &dyn Send = foo; + //~^ ERROR mismatched types [E0308] + let _: &dyn Sync = foo; + //~^ ERROR mismatched types [E0308] + + let foo: &dyn Foo = bar; + //~^ ERROR mismatched types [E0308] + let _: &dyn std::fmt::Debug = foo; + //~^ ERROR mismatched types [E0308] + let _: &dyn Send = foo; + //~^ ERROR mismatched types [E0308] + let _: &dyn Sync = foo; + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr new file mode 100644 index 000000000..3aa21ee3d --- /dev/null +++ b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr @@ -0,0 +1,168 @@ +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:53:35 + | +LL | let _: &dyn std::fmt::Debug = baz; + | -------------------- ^^^ expected trait `Debug`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Debug` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:55:24 + | +LL | let _: &dyn Send = baz; + | --------- ^^^ expected trait `Send`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Send` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:57:24 + | +LL | let _: &dyn Sync = baz; + | --------- ^^^ expected trait `Sync`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Sync` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:60:25 + | +LL | let bar: &dyn Bar = baz; + | -------- ^^^ expected trait `Bar`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Bar` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:62:35 + | +LL | let _: &dyn std::fmt::Debug = bar; + | -------------------- ^^^ expected trait `Debug`, found trait `Bar` + | | + | expected due to this + | + = note: expected reference `&dyn Debug` + found reference `&dyn Bar` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:64:24 + | +LL | let _: &dyn Send = bar; + | --------- ^^^ expected trait `Send`, found trait `Bar` + | | + | expected due to this + | + = note: expected reference `&dyn Send` + found reference `&dyn Bar` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:66:24 + | +LL | let _: &dyn Sync = bar; + | --------- ^^^ expected trait `Sync`, found trait `Bar` + | | + | expected due to this + | + = note: expected reference `&dyn Sync` + found reference `&dyn Bar` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:69:25 + | +LL | let foo: &dyn Foo = baz; + | -------- ^^^ expected trait `Foo`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Foo` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:71:35 + | +LL | let _: &dyn std::fmt::Debug = foo; + | -------------------- ^^^ expected trait `Debug`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Debug` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:73:24 + | +LL | let _: &dyn Send = foo; + | --------- ^^^ expected trait `Send`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Send` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:75:24 + | +LL | let _: &dyn Sync = foo; + | --------- ^^^ expected trait `Sync`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Sync` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:78:25 + | +LL | let foo: &dyn Foo = bar; + | -------- ^^^ expected trait `Foo`, found trait `Bar` + | | + | expected due to this + | + = note: expected reference `&dyn Foo` + found reference `&dyn Bar` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:80:35 + | +LL | let _: &dyn std::fmt::Debug = foo; + | -------------------- ^^^ expected trait `Debug`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Debug` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:82:24 + | +LL | let _: &dyn Send = foo; + | --------- ^^^ expected trait `Send`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Send` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:84:24 + | +LL | let _: &dyn Sync = foo; + | --------- ^^^ expected trait `Sync`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Sync` + found reference `&dyn Foo` + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs new file mode 100644 index 000000000..b672963ae --- /dev/null +++ b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs @@ -0,0 +1,12 @@ +// run-pass +#![feature(trait_upcasting)] + +struct Test { + func: Box<dyn FnMut() + 'static>, +} + +fn main() { + let closure: Box<dyn Fn() + 'static> = Box::new(|| ()); + let mut test = Box::new(Test { func: closure }); + (test.func)(); +} diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs new file mode 100644 index 000000000..9825158c2 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/lifetime.rs @@ -0,0 +1,94 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz: Bar { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +// Note: upcast lifetime means a shorter lifetime. +fn upcast_baz<'a: 'b, 'b, T>(v: Box<dyn Baz + 'a>, _l: &'b T) -> Box<dyn Baz + 'b> { + v +} +fn upcast_bar<'a: 'b, 'b, T>(v: Box<dyn Bar + 'a>, _l: &'b T) -> Box<dyn Bar + 'b> { + v +} +fn upcast_foo<'a: 'b, 'b, T>(v: Box<dyn Foo + 'a>, _l: &'b T) -> Box<dyn Foo + 'b> { + v +} + +fn main() { + let v = Box::new(1); + let l = &(); // dummy lifetime (shorter than `baz`) + + let baz: Box<dyn Baz> = v.clone(); + let u = upcast_baz(baz, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + assert_eq!(u.b(), 200); + assert_eq!(u.c(), 300); + + let baz: Box<dyn Baz> = v.clone(); + let bar: Box<dyn Bar> = baz; + let u = upcast_bar(bar, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + assert_eq!(u.b(), 200); + + let baz: Box<dyn Baz> = v.clone(); + let foo: Box<dyn Foo> = baz; + let u = upcast_foo(foo, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + + let baz: Box<dyn Baz> = v.clone(); + let bar: Box<dyn Bar> = baz; + let foo: Box<dyn Foo> = bar; + let u = upcast_foo(foo, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); +} diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs new file mode 100644 index 000000000..d62418756 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs @@ -0,0 +1,27 @@ +#![deny(deref_into_dyn_supertrait)] + +extern crate core; + +use core::ops::Deref; + +// issue 89190 +trait A {} +trait B: A {} + +impl<'a> Deref for dyn 'a + B { + //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target + //~| WARN this was previously accepted by the compiler but is being phased out; + + type Target = dyn A; + fn deref(&self) -> &Self::Target { + todo!() + } +} + +fn take_a(_: &dyn A) {} + +fn whoops(b: &dyn B) { + take_a(b) +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr new file mode 100644 index 000000000..4533b1163 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr @@ -0,0 +1,19 @@ +error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target + --> $DIR/migrate-lint-deny.rs:11:1 + | +LL | impl<'a> Deref for dyn 'a + B { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | type Target = dyn A; + | -------------------- target type is set here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460> +note: the lint level is defined here + --> $DIR/migrate-lint-deny.rs:1:9 + | +LL | #![deny(deref_into_dyn_supertrait)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs new file mode 100644 index 000000000..2e53a00a9 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs @@ -0,0 +1,21 @@ +// check-fail +#![feature(trait_upcasting)] + +trait Bar<T> { + fn bar(&self, _: T) {} +} + +trait Foo: Bar<i32> + Bar<u32> { + fn foo(&self, _: ()) {} +} + +struct S; + +impl Bar<i32> for S {} +impl Bar<u32> for S {} +impl Foo for S {} + +fn main() { + let s: &dyn Foo = &S; + let t: &dyn Bar<_> = s; //~ ERROR mismatched types +} diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr new file mode 100644 index 000000000..0ad18be03 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/multiple-occurrence-ambiguousity.rs:20:26 + | +LL | let t: &dyn Bar<_> = s; + | ----------- ^ expected trait `Bar`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Bar<_>` + found reference `&dyn Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs new file mode 100644 index 000000000..9ccfc9306 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs @@ -0,0 +1,48 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait A { + fn foo_a(&self); +} + +trait B { + fn foo_b(&self); +} + +trait C: A + B { + fn foo_c(&self); +} + +struct S(i32); + +impl A for S { + fn foo_a(&self) { + unreachable!(); + } +} + +impl B for S { + fn foo_b(&self) { + assert_eq!(42, self.0); + } +} + +impl C for S { + fn foo_c(&self) { + unreachable!(); + } +} + +fn invoke_inner(b: &dyn B) { + b.foo_b(); +} + +fn invoke_outer(c: &dyn C) { + invoke_inner(c); +} + +fn main() { + let s = S(42); + invoke_outer(&s); +} diff --git a/tests/ui/traits/trait-upcasting/struct.rs b/tests/ui/traits/trait-upcasting/struct.rs new file mode 100644 index 000000000..a3e416969 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/struct.rs @@ -0,0 +1,173 @@ +// run-pass + +#![feature(trait_upcasting)] + +use std::rc::Rc; +use std::sync::Arc; + +trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz: Bar { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +fn test_box() { + let v = Box::new(1); + + let baz: Box<dyn Baz> = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Box<dyn Baz> = v.clone(); + let bar: Box<dyn Bar> = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Box<dyn Baz> = v.clone(); + let foo: Box<dyn Foo> = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Box<dyn Baz> = v.clone(); + let bar: Box<dyn Bar> = baz; + let foo: Box<dyn Foo> = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn test_rc() { + let v = Rc::new(1); + + let baz: Rc<dyn Baz> = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Rc<dyn Baz> = v.clone(); + let bar: Rc<dyn Bar> = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Rc<dyn Baz> = v.clone(); + let foo: Rc<dyn Foo> = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Rc<dyn Baz> = v.clone(); + let bar: Rc<dyn Bar> = baz; + let foo: Rc<dyn Foo> = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn test_arc() { + let v = Arc::new(1); + + let baz: Arc<dyn Baz> = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Arc<dyn Baz> = v.clone(); + let bar: Arc<dyn Bar> = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Arc<dyn Baz> = v.clone(); + let foo: Arc<dyn Foo> = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Arc<dyn Baz> = v.clone(); + let bar: Arc<dyn Bar> = baz; + let foo: Arc<dyn Foo> = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn main() { + test_box(); + test_rc(); + test_arc(); +} diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs new file mode 100644 index 000000000..136d15af0 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs @@ -0,0 +1,69 @@ +#![feature(trait_upcasting)] + +trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz: Bar { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +fn main() { + let baz: &dyn Baz = &1; + + let bar: &dyn Bar = baz; + bar.c(); + //~^ ERROR no method named `c` found for reference `&dyn Bar` in the current scope [E0599] + + let foo: &dyn Foo = baz; + foo.b(); + //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] + foo.c(); + //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] + + let foo: &dyn Foo = bar; + foo.b(); + //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] + foo.c(); + //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] +} diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr new file mode 100644 index 000000000..918159e84 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr @@ -0,0 +1,68 @@ +error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope + --> $DIR/subtrait-method.rs:55:9 + | +LL | bar.c(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:27:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:59:9 + | +LL | foo.b(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `b`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:17:1 + | +LL | trait Bar: Foo { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:61:9 + | +LL | foo.c(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:27:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:65:9 + | +LL | foo.b(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `b`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:17:1 + | +LL | trait Bar: Foo { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:67:9 + | +LL | foo.c(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:27:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs new file mode 100644 index 000000000..6bc9f4a75 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs @@ -0,0 +1,26 @@ +#![feature(trait_upcasting)] + +trait Foo: Bar<i32> + Bar<u32> {} +trait Bar<T> { + fn bar(&self) -> Option<T> { + None + } +} + +fn test_specific(x: &dyn Foo) { + let _ = x as &dyn Bar<i32>; // OK + let _ = x as &dyn Bar<u32>; // OK +} + +fn test_unknown_version(x: &dyn Foo) { + let _ = x as &dyn Bar<_>; // Ambiguous + //~^ ERROR non-primitive cast + //~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied +} + +fn test_infer_version(x: &dyn Foo) { + let a = x as &dyn Bar<_>; // OK + let _: Option<u32> = a.bar(); +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr new file mode 100644 index 000000000..fe269d8e9 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr @@ -0,0 +1,23 @@ +error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` + --> $DIR/type-checking-test-1.rs:16:13 + | +LL | let _ = x as &dyn Bar<_>; // Ambiguous + | ^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let _ = &x as &dyn Bar<_>; // Ambiguous + | + + +error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied + --> $DIR/type-checking-test-1.rs:16:13 + | +LL | let _ = x as &dyn Bar<_>; // Ambiguous + | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` + | + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0605. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs new file mode 100644 index 000000000..36b11dffd --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs @@ -0,0 +1,31 @@ +#![feature(trait_upcasting)] + +trait Foo<T>: Bar<i32> + Bar<T> {} +trait Bar<T> { + fn bar(&self) -> Option<T> { + None + } +} + +fn test_specific(x: &dyn Foo<i32>) { + let _ = x as &dyn Bar<i32>; // OK +} + +fn test_specific2(x: &dyn Foo<u32>) { + let _ = x as &dyn Bar<i32>; // OK +} + +fn test_specific3(x: &dyn Foo<i32>) { + let _ = x as &dyn Bar<u32>; // Error + //~^ ERROR non-primitive cast + //~^^ ERROR the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied +} + +fn test_infer_arg(x: &dyn Foo<u32>) { + let a = x as &dyn Bar<_>; // Ambiguous + //~^ ERROR non-primitive cast + //~^^ ERROR the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied + let _ = a.bar(); +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr new file mode 100644 index 000000000..ef007d5cb --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr @@ -0,0 +1,42 @@ +error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>` + --> $DIR/type-checking-test-2.rs:19:13 + | +LL | let _ = x as &dyn Bar<u32>; // Error + | ^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let _ = &x as &dyn Bar<u32>; // Error + | + + +error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied + --> $DIR/type-checking-test-2.rs:19:13 + | +LL | let _ = x as &dyn Bar<u32>; // Error + | ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>` + | + = note: required for the cast from `&dyn Foo<i32>` to the object type `dyn Bar<u32>` + +error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>` + --> $DIR/type-checking-test-2.rs:25:13 + | +LL | let a = x as &dyn Bar<_>; // Ambiguous + | ^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let a = &x as &dyn Bar<_>; // Ambiguous + | + + +error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied + --> $DIR/type-checking-test-2.rs:25:13 + | +LL | let a = x as &dyn Bar<_>; // Ambiguous + | ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>` + | + = note: required for the cast from `&dyn Foo<u32>` to the object type `dyn Bar<_>` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0605. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr new file mode 100644 index 000000000..e6cb6a753 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/type-checking-test-3.rs:11:13 + | +LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'a>; // Error + | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-3.rs:16:13 + | +LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'static>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs new file mode 100644 index 000000000..b2db3a127 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs @@ -0,0 +1,20 @@ +#![feature(trait_upcasting)] + +trait Foo<'a>: Bar<'a> {} +trait Bar<'a> {} + +fn test_correct(x: &dyn Foo<'static>) { + let _ = x as &dyn Bar<'static>; +} + +fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + let _ = x as &dyn Bar<'a>; // Error + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong2<'a>(x: &dyn Foo<'a>) { + let _ = x as &dyn Bar<'static>; // Error + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr new file mode 100644 index 000000000..e6cb6a753 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/type-checking-test-3.rs:11:13 + | +LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'a>; // Error + | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-3.rs:16:13 + | +LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'static>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr new file mode 100644 index 000000000..8d506e580 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr @@ -0,0 +1,52 @@ +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:15:13 + | +LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'static, 'a>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:20:13 + | +LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'a, 'static>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:26:5 + | +LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | let y = x as &dyn Bar<'_, '_>; +LL | y.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:31:5 + | +LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:36:5 + | +LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:44:5 + | +LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +... +LL | z.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs new file mode 100644 index 000000000..f40c48f0d --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs @@ -0,0 +1,48 @@ +#![feature(trait_upcasting)] + +trait Foo<'a>: Bar<'a, 'a> {} +trait Bar<'a, 'b> { + fn get_b(&self) -> Option<&'a u32> { + None + } +} + +fn test_correct(x: &dyn Foo<'static>) { + let _ = x as &dyn Bar<'static, 'static>; +} + +fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + let _ = x as &dyn Bar<'static, 'a>; // Error + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { + let _ = x as &dyn Bar<'a, 'static>; // Error + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + let y = x as &dyn Bar<'_, '_>; + y.get_b() // ERROR + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + <_ as Bar>::get_b(x) // ERROR + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + <_ as Bar<'_, '_>>::get_b(x) // ERROR + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + let y = x as &dyn Bar<'_, '_>; + y.get_b(); // ERROR + let z = y; + z.get_b() // ERROR + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr new file mode 100644 index 000000000..8d506e580 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -0,0 +1,52 @@ +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:15:13 + | +LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'static, 'a>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:20:13 + | +LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'a, 'static>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:26:5 + | +LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | let y = x as &dyn Bar<'_, '_>; +LL | y.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:31:5 + | +LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:36:5 + | +LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:44:5 + | +LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +... +LL | z.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/traits/typeclasses-eq-example-static.rs b/tests/ui/traits/typeclasses-eq-example-static.rs new file mode 100644 index 000000000..f982ad6a0 --- /dev/null +++ b/tests/ui/traits/typeclasses-eq-example-static.rs @@ -0,0 +1,68 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +// Example from lkuper's intern talk, August 2012 -- now with static +// methods! +use Color::{cyan, magenta, yellow, black}; +use ColorTree::{leaf, branch}; + +trait Equal { + fn isEq(a: &Self, b: &Self) -> bool; +} + +#[derive(Clone, Copy)] +enum Color { cyan, magenta, yellow, black } + +impl Equal for Color { + fn isEq(a: &Color, b: &Color) -> bool { + match (*a, *b) { + (cyan, cyan) => { true } + (magenta, magenta) => { true } + (yellow, yellow) => { true } + (black, black) => { true } + _ => { false } + } + } +} + +#[derive(Clone)] +enum ColorTree { + leaf(Color), + branch(Box<ColorTree>, Box<ColorTree>) +} + +impl Equal for ColorTree { + fn isEq(a: &ColorTree, b: &ColorTree) -> bool { + match (a, b) { + (&leaf(ref x), &leaf(ref y)) => { + Equal::isEq(&(*x).clone(), &(*y).clone()) + } + (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => { + Equal::isEq(&(**l1).clone(), &(**l2).clone()) && + Equal::isEq(&(**r1).clone(), &(**r2).clone()) + } + _ => { false } + } + } +} + +pub fn main() { + assert!(Equal::isEq(&cyan, &cyan)); + assert!(Equal::isEq(&magenta, &magenta)); + assert!(!Equal::isEq(&cyan, &yellow)); + assert!(!Equal::isEq(&magenta, &cyan)); + + assert!(Equal::isEq(&leaf(cyan), &leaf(cyan))); + assert!(!Equal::isEq(&leaf(cyan), &leaf(yellow))); + + assert!(Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))), + &branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))))); + + assert!(!Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))), + &branch(Box::new(leaf(magenta)), Box::new(leaf(magenta))))); + + println!("Assertions all succeeded!"); +} diff --git a/tests/ui/traits/typeclasses-eq-example.rs b/tests/ui/traits/typeclasses-eq-example.rs new file mode 100644 index 000000000..4400301e6 --- /dev/null +++ b/tests/ui/traits/typeclasses-eq-example.rs @@ -0,0 +1,64 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +// Example from lkuper's intern talk, August 2012. +use Color::{cyan, magenta, yellow, black}; +use ColorTree::{leaf, branch}; + +trait Equal { + fn isEq(&self, a: &Self) -> bool; +} + +#[derive(Clone, Copy)] +enum Color { cyan, magenta, yellow, black } + +impl Equal for Color { + fn isEq(&self, a: &Color) -> bool { + match (*self, *a) { + (cyan, cyan) => { true } + (magenta, magenta) => { true } + (yellow, yellow) => { true } + (black, black) => { true } + _ => { false } + } + } +} + +#[derive(Clone)] +enum ColorTree { + leaf(Color), + branch(Box<ColorTree>, Box<ColorTree>) +} + +impl Equal for ColorTree { + fn isEq(&self, a: &ColorTree) -> bool { + match (self, a) { + (&leaf(ref x), &leaf(ref y)) => { x.isEq(&(*y).clone()) } + (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => { + (*l1).isEq(&(**l2).clone()) && (*r1).isEq(&(**r2).clone()) + } + _ => { false } + } + } +} + +pub fn main() { + assert!(cyan.isEq(&cyan)); + assert!(magenta.isEq(&magenta)); + assert!(!cyan.isEq(&yellow)); + assert!(!magenta.isEq(&cyan)); + + assert!(leaf(cyan).isEq(&leaf(cyan))); + assert!(!leaf(cyan).isEq(&leaf(yellow))); + + assert!(branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))) + .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))))); + + assert!(!branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))) + .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(magenta))))); + + println!("Assertions all succeeded!"); +} diff --git a/tests/ui/traits/ufcs-object.rs b/tests/ui/traits/ufcs-object.rs new file mode 100644 index 000000000..700488c22 --- /dev/null +++ b/tests/ui/traits/ufcs-object.rs @@ -0,0 +1,17 @@ +// run-pass +// Test that when you use ufcs form to invoke a trait method (on a +// trait object) everything works fine. + + +trait Foo { + fn test(&self) -> i32; +} + +impl Foo for i32 { + fn test(&self) -> i32 { *self } +} + +fn main() { + let a: &dyn Foo = &22; + assert_eq!(Foo::test(a), 22); +} diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.rs b/tests/ui/traits/unspecified-self-in-trait-ref.rs new file mode 100644 index 000000000..158b5a985 --- /dev/null +++ b/tests/ui/traits/unspecified-self-in-trait-ref.rs @@ -0,0 +1,30 @@ +pub trait Foo<A=Self> { + fn foo(&self); +} + +pub trait Bar<X=usize, A=Self> { + fn foo(&self); +} + +fn main() { + let a = Foo::lol(); + //~^ ERROR no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let b = Foo::<_>::lol(); + //~^ ERROR no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let c = Bar::lol(); + //~^ ERROR no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let d = Bar::<usize, _>::lol(); + //~^ ERROR no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let e = Bar::<usize>::lol(); + //~^ ERROR must be explicitly specified + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.stderr b/tests/ui/traits/unspecified-self-in-trait-ref.stderr new file mode 100644 index 000000000..b5e8e8867 --- /dev/null +++ b/tests/ui/traits/unspecified-self-in-trait-ref.stderr @@ -0,0 +1,105 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:10:13 + | +LL | let a = Foo::lol(); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | let a = <dyn Foo>::lol(); + | ++++ + + +error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope + --> $DIR/unspecified-self-in-trait-ref.rs:10:18 + | +LL | let a = Foo::lol(); + | ^^^ function or associated item not found in `dyn Foo<_>` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:14:13 + | +LL | let b = Foo::<_>::lol(); + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | let b = <dyn Foo::<_>>::lol(); + | ++++ + + +error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope + --> $DIR/unspecified-self-in-trait-ref.rs:14:23 + | +LL | let b = Foo::<_>::lol(); + | ^^^ function or associated item not found in `dyn Foo<_>` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:18:13 + | +LL | let c = Bar::lol(); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | let c = <dyn Bar>::lol(); + | ++++ + + +error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<_, _>` in the current scope + --> $DIR/unspecified-self-in-trait-ref.rs:18:18 + | +LL | let c = Bar::lol(); + | ^^^ function or associated item not found in `dyn Bar<_, _>` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:22:13 + | +LL | let d = Bar::<usize, _>::lol(); + | ^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | let d = <dyn Bar::<usize, _>>::lol(); + | ++++ + + +error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<usize, _>` in the current scope + --> $DIR/unspecified-self-in-trait-ref.rs:22:30 + | +LL | let d = Bar::<usize, _>::lol(); + | ^^^ function or associated item not found in `dyn Bar<usize, _>` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:26:13 + | +LL | let e = Bar::<usize>::lol(); + | ^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | let e = <dyn Bar::<usize>>::lol(); + | ++++ + + +error[E0393]: the type parameter `A` must be explicitly specified + --> $DIR/unspecified-self-in-trait-ref.rs:26:13 + | +LL | pub trait Bar<X=usize, A=Self> { + | ------------------------------ type parameter `A` must be specified for this +... +LL | let e = Bar::<usize>::lol(); + | ^^^^^^^^^^^^ missing reference to `A` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to 5 previous errors; 5 warnings emitted + +Some errors have detailed explanations: E0393, E0599. +For more information about an error, try `rustc --explain E0393`. diff --git a/tests/ui/traits/use-before-def.rs b/tests/ui/traits/use-before-def.rs new file mode 100644 index 000000000..1ee2b9419 --- /dev/null +++ b/tests/ui/traits/use-before-def.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(non_camel_case_types)] + +// Issue #1761 + +// pretty-expanded FIXME #23616 + +impl foo for isize { fn foo(&self) -> isize { 10 } } +trait foo { fn foo(&self) -> isize; } +pub fn main() {} diff --git a/tests/ui/traits/vtable-res-trait-param.rs b/tests/ui/traits/vtable-res-trait-param.rs new file mode 100644 index 000000000..3d7c2eb08 --- /dev/null +++ b/tests/ui/traits/vtable-res-trait-param.rs @@ -0,0 +1,23 @@ +trait TraitA { + fn method_a(&self) -> isize; +} + +trait TraitB { + fn gimme_an_a<A:TraitA>(&self, a: A) -> isize; +} + +impl TraitB for isize { + fn gimme_an_a<A:TraitA>(&self, a: A) -> isize { + a.method_a() + *self + } +} + +fn call_it<B:TraitB>(b: B) -> isize { + let y = 4; + b.gimme_an_a(y) //~ ERROR `{integer}: TraitA` is not satisfied +} + +fn main() { + let x = 3; + assert_eq!(call_it(x), 22); +} diff --git a/tests/ui/traits/vtable-res-trait-param.stderr b/tests/ui/traits/vtable-res-trait-param.stderr new file mode 100644 index 000000000..2b3e3de9b --- /dev/null +++ b/tests/ui/traits/vtable-res-trait-param.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `{integer}: TraitA` is not satisfied + --> $DIR/vtable-res-trait-param.rs:17:18 + | +LL | b.gimme_an_a(y) + | ---------- ^ the trait `TraitA` is not implemented for `{integer}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `TraitB::gimme_an_a` + --> $DIR/vtable-res-trait-param.rs:6:21 + | +LL | fn gimme_an_a<A:TraitA>(&self, a: A) -> isize; + | ^^^^^^ required by this bound in `TraitB::gimme_an_a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/vtable/issue-91807.rs b/tests/ui/traits/vtable/issue-91807.rs new file mode 100644 index 000000000..f435ff09d --- /dev/null +++ b/tests/ui/traits/vtable/issue-91807.rs @@ -0,0 +1,17 @@ +// check-pass +// incremental + +struct Struct<T>(T); + +impl<T> std::ops::Deref for Struct<T> { + type Target = dyn Fn(T); + fn deref(&self) -> &Self::Target { + unimplemented!() + } +} + +fn main() { + let f = Struct(Default::default()); + f(0); + f(0); +} diff --git a/tests/ui/traits/vtable/issue-97381.rs b/tests/ui/traits/vtable/issue-97381.rs new file mode 100644 index 000000000..393cf91ef --- /dev/null +++ b/tests/ui/traits/vtable/issue-97381.rs @@ -0,0 +1,30 @@ +use std::ops::Deref; +trait MyTrait: Deref<Target = u32> {} +struct MyStruct(u32); +impl MyTrait for MyStruct {} +impl Deref for MyStruct { + type Target = u32; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} +fn get_concrete_value(i: u32) -> MyStruct { + MyStruct(i) +} +fn get_boxed_value(i: u32) -> Box<dyn MyTrait> { + Box::new(get_concrete_value(i)) +} +fn main() { + let v = [1, 2, 3] + .iter() + .map(|i| get_boxed_value(*i)) + .collect::<Vec<_>>(); + + let el = &v[0]; + + for _ in v { + //~^ ERROR cannot move out of `v` because it is borrowed + println!("{}", ***el > 0); + } +} diff --git a/tests/ui/traits/vtable/issue-97381.stderr b/tests/ui/traits/vtable/issue-97381.stderr new file mode 100644 index 000000000..c4f8294e2 --- /dev/null +++ b/tests/ui/traits/vtable/issue-97381.stderr @@ -0,0 +1,15 @@ +error[E0505]: cannot move out of `v` because it is borrowed + --> $DIR/issue-97381.rs:26:14 + | +LL | let el = &v[0]; + | - borrow of `v` occurs here +LL | +LL | for _ in v { + | ^ move out of `v` occurs here +LL | +LL | println!("{}", ***el > 0); + | ---- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/traits/vtable/vtable-diamond.rs b/tests/ui/traits/vtable/vtable-diamond.rs new file mode 100644 index 000000000..dc3c17ac3 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-diamond.rs @@ -0,0 +1,44 @@ +// build-fail +#![feature(rustc_attrs)] + +#[rustc_dump_vtable] +trait A { + fn foo_a(&self) {} +} + +#[rustc_dump_vtable] +trait B: A { + fn foo_b(&self) {} +} + +#[rustc_dump_vtable] +trait C: A { + //~^ error vtable + fn foo_c(&self) {} +} + +#[rustc_dump_vtable] +trait D: B + C { + //~^ error vtable + fn foo_d(&self) {} +} + +struct S; + +impl A for S {} +impl B for S {} +impl C for S {} +impl D for S {} + +fn foo(d: &dyn D) { + d.foo_d(); +} + +fn bar(d: &dyn C) { + d.foo_c(); +} + +fn main() { + foo(&S); + bar(&S); +} diff --git a/tests/ui/traits/vtable/vtable-diamond.stderr b/tests/ui/traits/vtable/vtable-diamond.stderr new file mode 100644 index 000000000..f3718c5d8 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-diamond.stderr @@ -0,0 +1,29 @@ +error: vtable entries for `<S as D>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as B>::foo_b), + Method(<S as C>::foo_c), + TraitVPtr(<S as C>), + Method(<S as D>::foo_d), + ] + --> $DIR/vtable-diamond.rs:21:1 + | +LL | trait D: B + C { + | ^^^^^^^^^^^^^^ + +error: vtable entries for `<S as C>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as C>::foo_c), + ] + --> $DIR/vtable-diamond.rs:15:1 + | +LL | trait C: A { + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/vtable/vtable-multi-level.rs b/tests/ui/traits/vtable/vtable-multi-level.rs new file mode 100644 index 000000000..ebd55bcf3 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-multi-level.rs @@ -0,0 +1,143 @@ +// build-fail +#![feature(rustc_attrs)] + +// O --> G --> C --> A +// \ \ \-> B +// | |-> F --> D +// | \-> E +// |-> N --> J --> H +// \ \-> I +// |-> M --> K +// \-> L + +#[rustc_dump_vtable] +trait A { + //~^ error vtable + fn foo_a(&self) {} +} + +#[rustc_dump_vtable] +trait B { + //~^ error vtable + fn foo_b(&self) {} +} + +#[rustc_dump_vtable] +trait C: A + B { + //~^ error vtable + fn foo_c(&self) {} +} + +#[rustc_dump_vtable] +trait D { + //~^ error vtable + fn foo_d(&self) {} +} + +#[rustc_dump_vtable] +trait E { + //~^ error vtable + fn foo_e(&self) {} +} + +#[rustc_dump_vtable] +trait F: D + E { + //~^ error vtable + fn foo_f(&self) {} +} + +#[rustc_dump_vtable] +trait G: C + F { + fn foo_g(&self) {} +} + +#[rustc_dump_vtable] +trait H { + //~^ error vtable + fn foo_h(&self) {} +} + +#[rustc_dump_vtable] +trait I { + //~^ error vtable + fn foo_i(&self) {} +} + +#[rustc_dump_vtable] +trait J: H + I { + //~^ error vtable + fn foo_j(&self) {} +} + +#[rustc_dump_vtable] +trait K { + //~^ error vtable + fn foo_k(&self) {} +} + +#[rustc_dump_vtable] +trait L { + //~^ error vtable + fn foo_l(&self) {} +} + +#[rustc_dump_vtable] +trait M: K + L { + //~^ error vtable + fn foo_m(&self) {} +} + +#[rustc_dump_vtable] +trait N: J + M { + //~^ error vtable + fn foo_n(&self) {} +} + +#[rustc_dump_vtable] +trait O: G + N { + //~^ error vtable + fn foo_o(&self) {} +} + +struct S; + +impl A for S {} +impl B for S {} +impl C for S {} +impl D for S {} +impl E for S {} +impl F for S {} +impl G for S {} +impl H for S {} +impl I for S {} +impl J for S {} +impl K for S {} +impl L for S {} +impl M for S {} +impl N for S {} +impl O for S {} + +macro_rules! monomorphize_vtable { + ($trait:ident) => {{ + fn foo(_ : &dyn $trait) {} + foo(&S); + }} +} + +fn main() { + monomorphize_vtable!(O); + + monomorphize_vtable!(A); + monomorphize_vtable!(B); + monomorphize_vtable!(C); + monomorphize_vtable!(D); + monomorphize_vtable!(E); + monomorphize_vtable!(F); + monomorphize_vtable!(H); + monomorphize_vtable!(I); + monomorphize_vtable!(J); + monomorphize_vtable!(K); + monomorphize_vtable!(L); + monomorphize_vtable!(M); + monomorphize_vtable!(N); +} diff --git a/tests/ui/traits/vtable/vtable-multi-level.stderr b/tests/ui/traits/vtable/vtable-multi-level.stderr new file mode 100644 index 000000000..c4389e23f --- /dev/null +++ b/tests/ui/traits/vtable/vtable-multi-level.stderr @@ -0,0 +1,203 @@ +error: vtable entries for `<S as O>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as B>::foo_b), + TraitVPtr(<S as B>), + Method(<S as C>::foo_c), + Method(<S as D>::foo_d), + TraitVPtr(<S as D>), + Method(<S as E>::foo_e), + TraitVPtr(<S as E>), + Method(<S as F>::foo_f), + TraitVPtr(<S as F>), + Method(<S as G>::foo_g), + Method(<S as H>::foo_h), + TraitVPtr(<S as H>), + Method(<S as I>::foo_i), + TraitVPtr(<S as I>), + Method(<S as J>::foo_j), + TraitVPtr(<S as J>), + Method(<S as K>::foo_k), + TraitVPtr(<S as K>), + Method(<S as L>::foo_l), + TraitVPtr(<S as L>), + Method(<S as M>::foo_m), + TraitVPtr(<S as M>), + Method(<S as N>::foo_n), + TraitVPtr(<S as N>), + Method(<S as O>::foo_o), + ] + --> $DIR/vtable-multi-level.rs:97:1 + | +LL | trait O: G + N { + | ^^^^^^^^^^^^^^ + +error: vtable entries for `<S as A>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + ] + --> $DIR/vtable-multi-level.rs:14:1 + | +LL | trait A { + | ^^^^^^^ + +error: vtable entries for `<S as B>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as B>::foo_b), + ] + --> $DIR/vtable-multi-level.rs:20:1 + | +LL | trait B { + | ^^^^^^^ + +error: vtable entries for `<S as C>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as B>::foo_b), + TraitVPtr(<S as B>), + Method(<S as C>::foo_c), + ] + --> $DIR/vtable-multi-level.rs:26:1 + | +LL | trait C: A + B { + | ^^^^^^^^^^^^^^ + +error: vtable entries for `<S as D>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as D>::foo_d), + ] + --> $DIR/vtable-multi-level.rs:32:1 + | +LL | trait D { + | ^^^^^^^ + +error: vtable entries for `<S as E>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as E>::foo_e), + ] + --> $DIR/vtable-multi-level.rs:38:1 + | +LL | trait E { + | ^^^^^^^ + +error: vtable entries for `<S as F>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as D>::foo_d), + Method(<S as E>::foo_e), + TraitVPtr(<S as E>), + Method(<S as F>::foo_f), + ] + --> $DIR/vtable-multi-level.rs:44:1 + | +LL | trait F: D + E { + | ^^^^^^^^^^^^^^ + +error: vtable entries for `<S as H>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as H>::foo_h), + ] + --> $DIR/vtable-multi-level.rs:55:1 + | +LL | trait H { + | ^^^^^^^ + +error: vtable entries for `<S as I>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as I>::foo_i), + ] + --> $DIR/vtable-multi-level.rs:61:1 + | +LL | trait I { + | ^^^^^^^ + +error: vtable entries for `<S as J>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as H>::foo_h), + Method(<S as I>::foo_i), + TraitVPtr(<S as I>), + Method(<S as J>::foo_j), + ] + --> $DIR/vtable-multi-level.rs:67:1 + | +LL | trait J: H + I { + | ^^^^^^^^^^^^^^ + +error: vtable entries for `<S as K>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as K>::foo_k), + ] + --> $DIR/vtable-multi-level.rs:73:1 + | +LL | trait K { + | ^^^^^^^ + +error: vtable entries for `<S as L>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as L>::foo_l), + ] + --> $DIR/vtable-multi-level.rs:79:1 + | +LL | trait L { + | ^^^^^^^ + +error: vtable entries for `<S as M>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as K>::foo_k), + Method(<S as L>::foo_l), + TraitVPtr(<S as L>), + Method(<S as M>::foo_m), + ] + --> $DIR/vtable-multi-level.rs:85:1 + | +LL | trait M: K + L { + | ^^^^^^^^^^^^^^ + +error: vtable entries for `<S as N>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as H>::foo_h), + Method(<S as I>::foo_i), + TraitVPtr(<S as I>), + Method(<S as J>::foo_j), + Method(<S as K>::foo_k), + TraitVPtr(<S as K>), + Method(<S as L>::foo_l), + TraitVPtr(<S as L>), + Method(<S as M>::foo_m), + TraitVPtr(<S as M>), + Method(<S as N>::foo_n), + ] + --> $DIR/vtable-multi-level.rs:91:1 + | +LL | trait N: J + M { + | ^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors + diff --git a/tests/ui/traits/vtable/vtable-multiple.rs b/tests/ui/traits/vtable/vtable-multiple.rs new file mode 100644 index 000000000..7a0111c5e --- /dev/null +++ b/tests/ui/traits/vtable/vtable-multiple.rs @@ -0,0 +1,33 @@ +// build-fail +#![feature(rustc_attrs)] + +#[rustc_dump_vtable] +trait A { + fn foo_a(&self) {} +} + +#[rustc_dump_vtable] +trait B { + //~^ error vtable + fn foo_b(&self) {} +} + +#[rustc_dump_vtable] +trait C: A + B { + //~^ error vtable + fn foo_c(&self) {} +} + +struct S; + +impl A for S {} +impl B for S {} +impl C for S {} + +fn foo(c: &dyn C) {} +fn bar(c: &dyn B) {} + +fn main() { + foo(&S); + bar(&S); +} diff --git a/tests/ui/traits/vtable/vtable-multiple.stderr b/tests/ui/traits/vtable/vtable-multiple.stderr new file mode 100644 index 000000000..0dcd84433 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-multiple.stderr @@ -0,0 +1,27 @@ +error: vtable entries for `<S as C>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a), + Method(<S as B>::foo_b), + TraitVPtr(<S as B>), + Method(<S as C>::foo_c), + ] + --> $DIR/vtable-multiple.rs:16:1 + | +LL | trait C: A + B { + | ^^^^^^^^^^^^^^ + +error: vtable entries for `<S as B>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as B>::foo_b), + ] + --> $DIR/vtable-multiple.rs:10:1 + | +LL | trait B { + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.rs b/tests/ui/traits/vtable/vtable-non-object-safe.rs new file mode 100644 index 000000000..7661bb574 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-non-object-safe.rs @@ -0,0 +1,18 @@ +// build-fail +#![feature(rustc_attrs)] + +// Ensure that non-object-safe methods in Iterator does not generate +// vtable entries. + +#[rustc_dump_vtable] +trait A: Iterator {} +//~^ error vtable + +impl<T> A for T where T: Iterator {} + +fn foo(_a: &mut dyn A<Item=u8>) { +} + +fn main() { + foo(&mut vec![0, 1, 2, 3].into_iter()); +} diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.stderr b/tests/ui/traits/vtable/vtable-non-object-safe.stderr new file mode 100644 index 000000000..9345c2711 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-non-object-safe.stderr @@ -0,0 +1,16 @@ +error: vtable entries for `<std::vec::IntoIter<u8> as A>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<std::vec::IntoIter<u8> as Iterator>::next), + Method(<std::vec::IntoIter<u8> as Iterator>::size_hint), + Method(<std::vec::IntoIter<u8> as Iterator>::advance_by), + Method(<std::vec::IntoIter<u8> as Iterator>::nth), + ] + --> $DIR/vtable-non-object-safe.rs:8:1 + | +LL | trait A: Iterator {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/vtable/vtable-vacant.rs b/tests/ui/traits/vtable/vtable-vacant.rs new file mode 100644 index 000000000..a64796358 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-vacant.rs @@ -0,0 +1,31 @@ +// build-fail +#![feature(rustc_attrs)] +#![feature(negative_impls)] +#![allow(where_clauses_object_safety)] + +// B --> A + +#[rustc_dump_vtable] +trait A { + fn foo_a1(&self) {} + fn foo_a2(&self) where Self: Send {} +} + +#[rustc_dump_vtable] +trait B: A { + //~^ error vtable + fn foo_b1(&self) {} + fn foo_b2(&self) where Self: Send {} +} + +struct S; +impl !Send for S {} + +impl A for S {} +impl B for S {} + +fn foo(_: &dyn B) {} + +fn main() { + foo(&S); +} diff --git a/tests/ui/traits/vtable/vtable-vacant.stderr b/tests/ui/traits/vtable/vtable-vacant.stderr new file mode 100644 index 000000000..5346a7027 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-vacant.stderr @@ -0,0 +1,16 @@ +error: vtable entries for `<S as B>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(<S as A>::foo_a1), + Vacant, + Method(<S as B>::foo_b1), + Vacant, + ] + --> $DIR/vtable-vacant.rs:15:1 + | +LL | trait B: A { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/wf-object/maybe-bound.rs b/tests/ui/traits/wf-object/maybe-bound.rs new file mode 100644 index 000000000..17771e976 --- /dev/null +++ b/tests/ui/traits/wf-object/maybe-bound.rs @@ -0,0 +1,18 @@ +// Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects). + +trait Foo {} + +type _0 = dyn ?Sized + Foo; +//~^ ERROR `?Trait` is not permitted in trait object types + +type _1 = dyn Foo + ?Sized; +//~^ ERROR `?Trait` is not permitted in trait object types + +type _2 = dyn Foo + ?Sized + ?Sized; +//~^ ERROR `?Trait` is not permitted in trait object types +//~| ERROR `?Trait` is not permitted in trait object types + +type _3 = dyn ?Sized + Foo; +//~^ ERROR `?Trait` is not permitted in trait object types + +fn main() {} diff --git a/tests/ui/traits/wf-object/maybe-bound.stderr b/tests/ui/traits/wf-object/maybe-bound.stderr new file mode 100644 index 000000000..2fe3f0fc3 --- /dev/null +++ b/tests/ui/traits/wf-object/maybe-bound.stderr @@ -0,0 +1,32 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:5:15 + | +LL | type _0 = dyn ?Sized + Foo; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:8:21 + | +LL | type _1 = dyn Foo + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:11:21 + | +LL | type _2 = dyn Foo + ?Sized + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:11:30 + | +LL | type _2 = dyn Foo + ?Sized + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:15:15 + | +LL | type _3 = dyn ?Sized + Foo; + | ^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/traits/wf-object/no-duplicates.rs b/tests/ui/traits/wf-object/no-duplicates.rs new file mode 100644 index 000000000..678ede582 --- /dev/null +++ b/tests/ui/traits/wf-object/no-duplicates.rs @@ -0,0 +1,33 @@ +// The purpose of this test is to demonstrate that duplicating object safe traits +// that are not auto-traits is rejected even though one could reasonably accept this. + +// Some arbitrary object-safe trait: +trait Obj {} + +// Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior: +type _0 = dyn Obj + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Some variations: + +type _1 = dyn Send + Obj + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _2 = dyn Obj + Send + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _3 = dyn Obj + Send + Send; // But it is OK to duplicate auto traits. + +// Take higher ranked types into account. + +// Note that `'a` and `'b` are intentionally different to make sure we consider +// them semantically the same. +trait ObjL<'l> {} +type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +trait ObjT<T> {} +type _5 = dyn ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)>; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/tests/ui/traits/wf-object/no-duplicates.stderr b/tests/ui/traits/wf-object/no-duplicates.stderr new file mode 100644 index 000000000..50dfcf956 --- /dev/null +++ b/tests/ui/traits/wf-object/no-duplicates.stderr @@ -0,0 +1,58 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:8:21 + | +LL | type _0 = dyn Obj + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:13:28 + | +LL | type _1 = dyn Send + Obj + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:16:28 + | +LL | type _2 = dyn Obj + Send + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:26:34 + | +LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; + | ---------------- ^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:30:42 + | +LL | type _5 = dyn ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)>; + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/wf-object/only-maybe-bound.rs b/tests/ui/traits/wf-object/only-maybe-bound.rs new file mode 100644 index 000000000..3e6db3e99 --- /dev/null +++ b/tests/ui/traits/wf-object/only-maybe-bound.rs @@ -0,0 +1,7 @@ +// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed. + +type _0 = dyn ?Sized; +//~^ ERROR at least one trait is required for an object type [E0224] +//~| ERROR ?Trait` is not permitted in trait object types + +fn main() {} diff --git a/tests/ui/traits/wf-object/only-maybe-bound.stderr b/tests/ui/traits/wf-object/only-maybe-bound.stderr new file mode 100644 index 000000000..cbc41feec --- /dev/null +++ b/tests/ui/traits/wf-object/only-maybe-bound.stderr @@ -0,0 +1,15 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/only-maybe-bound.rs:3:15 + | +LL | type _0 = dyn ?Sized; + | ^^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/only-maybe-bound.rs:3:11 + | +LL | type _0 = dyn ?Sized; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs new file mode 100644 index 000000000..4f676cbe3 --- /dev/null +++ b/tests/ui/traits/wf-object/reverse-order.rs @@ -0,0 +1,15 @@ +// run-pass + +// Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. + +use std::marker::Unpin; + +// Some arbitrary object-safe trait: +trait Obj {} + +type _0 = dyn Unpin; +type _1 = dyn Send + Obj; +type _2 = dyn Send + Unpin + Obj; +type _3 = dyn Send + Unpin + Sync + Obj; + +fn main() {} diff --git a/tests/ui/traits/where-clause-vs-impl.rs b/tests/ui/traits/where-clause-vs-impl.rs new file mode 100644 index 000000000..7cfee27ef --- /dev/null +++ b/tests/ui/traits/where-clause-vs-impl.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that when there is a conditional (but blanket) impl and a +// where clause, we don't get confused in trait resolution. +// +// Issue #18453. + +// pretty-expanded FIXME #23616 + +use std::rc::Rc; + +pub trait Foo<M> { + fn foo(&mut self, msg: M); +} + +pub trait Bar<M> { + fn dummy(&self) -> M; +} + +impl<M, F: Bar<M>> Foo<M> for F { + fn foo(&mut self, msg: M) { + } +} + +pub struct Both<M, F> { + inner: Rc<(M, F)>, +} + +impl<M, F: Foo<M>> Clone for Both<M, F> { + fn clone(&self) -> Both<M, F> { + Both { inner: self.inner.clone() } + } +} + +fn repro1<M, F: Foo<M>>(_both: Both<M, F>) { +} + +fn repro2<M, F: Foo<M>>(msg: M, foo: F) { + let both = Both { inner: Rc::new((msg, foo)) }; + repro1(both.clone()); // <--- This clone causes problem +} + +pub fn main() { +} diff --git a/tests/ui/traits/with-bounds-default.rs b/tests/ui/traits/with-bounds-default.rs new file mode 100644 index 000000000..31f73d79c --- /dev/null +++ b/tests/ui/traits/with-bounds-default.rs @@ -0,0 +1,32 @@ +// run-pass + +pub trait Clone2 { + /// Returns a copy of the value. The contents of boxes + /// are copied to maintain uniqueness, while the contents of + /// managed pointers are not copied. + fn clone(&self) -> Self; +} + +trait Getter<T: Clone> { + fn do_get(&self) -> T; + + fn do_get2(&self) -> (T, T) { + let x = self.do_get(); + (x.clone(), x.clone()) + } + +} + +impl Getter<isize> for isize { + fn do_get(&self) -> isize { *self } +} + +impl<T: Clone> Getter<T> for Option<T> { + fn do_get(&self) -> T { self.as_ref().unwrap().clone() } +} + + +pub fn main() { + assert_eq!(3.do_get2(), (3, 3)); + assert_eq!(Some("hi".to_string()).do_get2(), ("hi".to_string(), "hi".to_string())); +} diff --git a/tests/ui/traits/with-dst.rs b/tests/ui/traits/with-dst.rs new file mode 100644 index 000000000..a3e3b31df --- /dev/null +++ b/tests/ui/traits/with-dst.rs @@ -0,0 +1,22 @@ +// build-pass (FIXME(62277): could be check-pass?) +// #55266 + +struct VTable<DST: ?Sized> { + _to_dst_ptr: fn(*mut ()) -> *mut DST, +} + +trait HasVTableFor<DST: ?Sized + 'static> { + const VTABLE: &'static VTable<DST>; +} + +impl<T, DST: ?Sized + 'static> HasVTableFor<DST> for T { + const VTABLE: &'static VTable<DST> = &VTable { + _to_dst_ptr: |_: *mut ()| unsafe { std::mem::zeroed() }, + }; +} + +pub fn push<DST: ?Sized + 'static, T>() { + <T as HasVTableFor<DST>>::VTABLE; +} + +fn main() {} |