diff options
Diffstat (limited to 'tests/ui/traits/bound')
34 files changed, 1109 insertions, 0 deletions
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`. |