diff options
Diffstat (limited to 'src/test/ui/where-clauses')
28 files changed, 511 insertions, 0 deletions
diff --git a/src/test/ui/where-clauses/auxiliary/where_clauses_xc.rs b/src/test/ui/where-clauses/auxiliary/where_clauses_xc.rs new file mode 100644 index 000000000..7c8043b20 --- /dev/null +++ b/src/test/ui/where-clauses/auxiliary/where_clauses_xc.rs @@ -0,0 +1,19 @@ +pub trait Equal { + fn equal(&self, other: &Self) -> bool; + fn equals<T,U>(&self, this: &T, that: &T, x: &U, y: &U) -> bool + where T: Eq, U: Eq; +} + +impl<T> Equal for T where T: Eq { + fn equal(&self, other: &T) -> bool { + self == other + } + fn equals<U,X>(&self, this: &U, other: &U, x: &X, y: &X) -> bool + where U: Eq, X: Eq { + this == other && x == y + } +} + +pub fn equal<T>(x: &T, y: &T) -> bool where T: Eq { + x == y +} diff --git a/src/test/ui/where-clauses/where-clause-bounds-inconsistency.rs b/src/test/ui/where-clauses/where-clause-bounds-inconsistency.rs new file mode 100644 index 000000000..cf7d06b61 --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-bounds-inconsistency.rs @@ -0,0 +1,23 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Bound { + fn dummy(&self) { } +} + +trait Trait { + fn a<T>(&self, _: T) where T: Bound; + fn b<T>(&self, _: T) where T: Bound; + fn c<T: Bound>(&self, _: T); + fn d<T: Bound>(&self, _: T); +} + +impl Trait for bool { + fn a<T: Bound>(&self, _: T) {} + //^~ This gets rejected but should be accepted + fn b<T>(&self, _: T) where T: Bound {} + fn c<T: Bound>(&self, _: T) {} + fn d<T>(&self, _: T) where T: Bound {} +} + +fn main() {} diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs new file mode 100644 index 000000000..0e8bb61a7 --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs @@ -0,0 +1,18 @@ +fn require_copy<T: Copy>(x: T) {} + +struct Foo<T> { x: T } + +// Ensure constraints are only attached to methods locally +impl<T> Foo<T> { + fn needs_copy(self) where T: Copy { + require_copy(self.x); + + } + + fn fails_copy(self) { + require_copy(self.x); + //~^ ERROR the trait bound `T: Copy` is not satisfied + } +} + +fn main() {} diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr new file mode 100644 index 000000000..43fbc0a90 --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:22 + | +LL | require_copy(self.x); + | ------------ ^^^^^^ the trait `Copy` is not implemented for `T` + | | + | required by a bound introduced by this call + | +note: required by a bound in `require_copy` + --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:20 + | +LL | fn require_copy<T: Copy>(x: T) {} + | ^^^^ required by this bound in `require_copy` +help: consider restricting type parameter `T` + | +LL | impl<T: std::marker::Copy> Foo<T> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs new file mode 100644 index 000000000..25c46330e --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs @@ -0,0 +1,23 @@ +fn require_copy<T: Copy>(x: T) {} + +struct Bar<T> { x: T } + +trait Foo<T> { + fn needs_copy(self) where T: Copy; + fn fails_copy(self); +} + +// Ensure constraints are only attached to methods locally +impl<T> Foo<T> for Bar<T> { + fn needs_copy(self) where T: Copy { + require_copy(self.x); + + } + + fn fails_copy(self) { + require_copy(self.x); + //~^ ERROR the trait bound `T: Copy` is not satisfied + } +} + +fn main() {} diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr new file mode 100644 index 000000000..f2db8fcc4 --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:22 + | +LL | require_copy(self.x); + | ------------ ^^^^^^ the trait `Copy` is not implemented for `T` + | | + | required by a bound introduced by this call + | +note: required by a bound in `require_copy` + --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:20 + | +LL | fn require_copy<T: Copy>(x: T) {} + | ^^^^ required by this bound in `require_copy` +help: consider restricting type parameter `T` + | +LL | impl<T: std::marker::Copy> Foo<T> for Bar<T> { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-clause-early-bound-lifetimes.rs b/src/test/ui/where-clauses/where-clause-early-bound-lifetimes.rs new file mode 100644 index 000000000..6fc570b9b --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-early-bound-lifetimes.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// pretty-expanded FIXME #23616 + +trait TheTrait { fn dummy(&self) { } } + +impl TheTrait for &'static isize { } + +fn foo<'a,T>(_: &'a T) where &'a T : TheTrait { } + +fn bar<T>(_: &'static T) where &'static T : TheTrait { } + +fn main() { + static x: isize = 1; + foo(&x); + bar(&x); +} diff --git a/src/test/ui/where-clauses/where-clause-method-substituion-rpass.rs b/src/test/ui/where-clauses/where-clause-method-substituion-rpass.rs new file mode 100644 index 000000000..daa3c8dd8 --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-method-substituion-rpass.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +trait Foo<T> { fn dummy(&self, arg: T) { } } + +trait Bar<A> { + fn method<B>(&self) where A: Foo<B>; +} + +struct S; +struct X; + +impl Foo<S> for X {} + +impl Bar<X> for i32 { + fn method<U>(&self) where X: Foo<U> { + } +} + +fn main() { + 1.method::<S>(); +} diff --git a/src/test/ui/where-clauses/where-clause-method-substituion.rs b/src/test/ui/where-clauses/where-clause-method-substituion.rs new file mode 100644 index 000000000..4607783c0 --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-method-substituion.rs @@ -0,0 +1,22 @@ +trait Foo<T> { + fn dummy(&self, t: T) { } +} + +trait Bar<A> { + fn method<B>(&self) where A: Foo<B>; +} + +struct S; +struct X; + +// Remove this impl causing the below resolution to fail // impl Foo<S> for X {} + +impl Bar<X> for isize { + fn method<U>(&self) where X: Foo<U> { + } +} + +fn main() { + 1.method::<X>(); + //~^ ERROR the trait bound `X: Foo<X>` is not satisfied +} diff --git a/src/test/ui/where-clauses/where-clause-method-substituion.stderr b/src/test/ui/where-clauses/where-clause-method-substituion.stderr new file mode 100644 index 000000000..f431deee7 --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-method-substituion.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `X: Foo<X>` is not satisfied + --> $DIR/where-clause-method-substituion.rs:20:7 + | +LL | 1.method::<X>(); + | ^^^^^^ the trait `Foo<X>` is not implemented for `X` + | +note: required by a bound in `Bar::method` + --> $DIR/where-clause-method-substituion.rs:6:34 + | +LL | fn method<B>(&self) where A: Foo<B>; + | ^^^^^^ required by this bound in `Bar::method` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-clause-region-outlives.rs b/src/test/ui/where-clauses/where-clause-region-outlives.rs new file mode 100644 index 000000000..84925345d --- /dev/null +++ b/src/test/ui/where-clauses/where-clause-region-outlives.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +struct A<'a, 'b> where 'a : 'b { x: &'a isize, y: &'b isize } + +fn main() { + let x = 1; + let y = 1; + let a = A { x: &x, y: &y }; +} diff --git a/src/test/ui/where-clauses/where-clauses-cross-crate.rs b/src/test/ui/where-clauses/where-clauses-cross-crate.rs new file mode 100644 index 000000000..9edf0bd5b --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses-cross-crate.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:where_clauses_xc.rs + +extern crate where_clauses_xc; + +use where_clauses_xc::{Equal, equal}; + +fn main() { + println!("{}", equal(&1, &2)); + println!("{}", equal(&1, &1)); + println!("{}", "hello".equal(&"hello")); + println!("{}", "hello".equals::<isize,&str>(&1, &1, &"foo", &"bar")); +} diff --git a/src/test/ui/where-clauses/where-clauses-lifetimes.rs b/src/test/ui/where-clauses/where-clauses-lifetimes.rs new file mode 100644 index 000000000..4bfd9e659 --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses-lifetimes.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +fn foo<'a, I>(mut it: I) where I: Iterator<Item=&'a isize> {} + +fn main() { + foo([1, 2].iter()); +} diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.rs b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.rs new file mode 100644 index 000000000..a8ae02964 --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.rs @@ -0,0 +1,20 @@ +// Test that a where clause attached to a method allows us to add +// additional constraints to a parameter out of scope. + +struct Foo<T> { + value: T +} + +struct Bar; // does not implement Eq + +impl<T> Foo<T> { + fn equals(&self, u: &Foo<T>) -> bool where T : Eq { + self.value == u.value + } +} + +fn main() { + let x = Foo { value: Bar }; + x.equals(&x); + //~^ ERROR `Bar: Eq` is not satisfied +} diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr new file mode 100644 index 000000000..c13552bc2 --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `Bar: Eq` is not satisfied + --> $DIR/where-clauses-method-unsatisfied.rs:18:14 + | +LL | x.equals(&x); + | ------ ^^ the trait `Eq` is not implemented for `Bar` + | | + | required by a bound introduced by this call + | +note: required by a bound in `Foo::<T>::equals` + --> $DIR/where-clauses-method-unsatisfied.rs:11:52 + | +LL | fn equals(&self, u: &Foo<T>) -> bool where T : Eq { + | ^^ required by this bound in `Foo::<T>::equals` +help: consider annotating `Bar` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-clauses-method.rs b/src/test/ui/where-clauses/where-clauses-method.rs new file mode 100644 index 000000000..feecff435 --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses-method.rs @@ -0,0 +1,20 @@ +// run-pass +// Test that a where clause attached to a method allows us to add +// additional constraints to a parameter out of scope. + +struct Foo<T> { + value: T +} + +impl<T> Foo<T> { + fn equals(&self, u: &Foo<T>) -> bool where T : Eq { + self.value == u.value + } +} + +fn main() { + let x = Foo { value: 1 }; + let y = Foo { value: 2 }; + println!("{}", x.equals(&x)); + println!("{}", x.equals(&y)); +} diff --git a/src/test/ui/where-clauses/where-clauses-unboxed-closures.rs b/src/test/ui/where-clauses/where-clauses-unboxed-closures.rs new file mode 100644 index 000000000..6964cfa2e --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses-unboxed-closures.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +struct Bencher; + +// ICE +fn warm_up<'a, F>(f: F) where F: Fn(&'a mut Bencher) { +} + +fn main() { + // ICE trigger + warm_up(|b: &mut Bencher| () ); + + // OK + warm_up(|b| () ); +} diff --git a/src/test/ui/where-clauses/where-clauses-unsatisfied.rs b/src/test/ui/where-clauses/where-clauses-unsatisfied.rs new file mode 100644 index 000000000..8b067d30a --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses-unsatisfied.rs @@ -0,0 +1,8 @@ +fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b } + +struct Struct; + +fn main() { + drop(equal(&Struct, &Struct)) + //~^ ERROR the trait bound `Struct: Eq` is not satisfied +} diff --git a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr new file mode 100644 index 000000000..b1805a452 --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Struct: Eq` is not satisfied + --> $DIR/where-clauses-unsatisfied.rs:6:10 + | +LL | drop(equal(&Struct, &Struct)) + | ^^^^^ the trait `Eq` is not implemented for `Struct` + | +note: required by a bound in `equal` + --> $DIR/where-clauses-unsatisfied.rs:1:45 + | +LL | fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b } + | ^^ required by this bound in `equal` +help: consider annotating `Struct` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-clauses.rs b/src/test/ui/where-clauses/where-clauses.rs new file mode 100644 index 000000000..905ef7c5e --- /dev/null +++ b/src/test/ui/where-clauses/where-clauses.rs @@ -0,0 +1,27 @@ +// run-pass +trait Equal { + fn equal(&self, other: &Self) -> bool; + fn equals<T,U>(&self, this: &T, that: &T, x: &U, y: &U) -> bool + where T: Eq, U: Eq; +} + +impl<T> Equal for T where T: Eq { + fn equal(&self, other: &T) -> bool { + self == other + } + fn equals<U,X>(&self, this: &U, other: &U, x: &X, y: &X) -> bool + where U: Eq, X: Eq { + this == other && x == y + } +} + +fn equal<T>(x: &T, y: &T) -> bool where T: Eq { + x == y +} + +fn main() { + println!("{}", equal(&1, &2)); + println!("{}", equal(&1, &1)); + println!("{}", "hello".equal(&"hello")); + println!("{}", "hello".equals::<isize,&str>(&1, &1, &"foo", &"bar")); +} diff --git a/src/test/ui/where-clauses/where-equality-constraints.rs b/src/test/ui/where-clauses/where-equality-constraints.rs new file mode 100644 index 000000000..8828f09d9 --- /dev/null +++ b/src/test/ui/where-clauses/where-equality-constraints.rs @@ -0,0 +1,6 @@ +fn f() where u8 = u16 {} +//~^ ERROR equality constraints are not yet supported in `where` clauses +fn g() where for<'a> &'static (u8,) == u16, {} +//~^ ERROR equality constraints are not yet supported in `where` clauses + +fn main() {} diff --git a/src/test/ui/where-clauses/where-equality-constraints.stderr b/src/test/ui/where-clauses/where-equality-constraints.stderr new file mode 100644 index 000000000..9d8fac02e --- /dev/null +++ b/src/test/ui/where-clauses/where-equality-constraints.stderr @@ -0,0 +1,18 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/where-equality-constraints.rs:1:14 + | +LL | fn f() where u8 = u16 {} + | ^^^^^^^^ not supported + | + = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/where-equality-constraints.rs:3:14 + | +LL | fn g() where for<'a> &'static (u8,) == u16, {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs new file mode 100644 index 000000000..37c6954fd --- /dev/null +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -0,0 +1,24 @@ +// Test that we can quantify lifetimes outside a constraint (i.e., including +// the self type) in a where clause. Specifically, test that implementing for a +// specific lifetime is not enough to satisfy the `for<'a> ...` constraint, which +// should require *all* lifetimes. + +static X: &'static u32 = &42; + +trait Bar { + fn bar(&self); +} + +impl Bar for &'static u32 { + fn bar(&self) {} +} + +fn foo<T>(x: &T) +where + for<'a> &'a T: Bar, +{ +} + +fn main() { + foo(&X); //~ ERROR implementation of `Bar` is not general enough +} diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr new file mode 100644 index 000000000..f65db78fc --- /dev/null +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -0,0 +1,11 @@ +error: implementation of `Bar` is not general enough + --> $DIR/where-for-self-2.rs:23:5 + | +LL | foo(&X); + | ^^^^^^^ implementation of `Bar` is not general enough + | + = note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'static u32` + +error: aborting due to previous error + diff --git a/src/test/ui/where-clauses/where-for-self.rs b/src/test/ui/where-clauses/where-for-self.rs new file mode 100644 index 000000000..9380e72cd --- /dev/null +++ b/src/test/ui/where-clauses/where-for-self.rs @@ -0,0 +1,19 @@ +// Test that we can quantify lifetimes outside a constraint (i.e., including +// the self type) in a where clause. Specifically, test that we cannot nest +// quantification in constraints (to be clear, there is no reason this should not +// we're testing we don't crash or do something stupid). + +trait Bar<'a> { + fn bar(&self); +} + +impl<'a, 'b> Bar<'b> for &'a u32 { + fn bar(&self) {} +} + +fn foo<T>(x: &T) + where for<'a> &'a T: for<'b> Bar<'b> + //~^ error: nested quantification of lifetimes +{} + +fn main() {} diff --git a/src/test/ui/where-clauses/where-for-self.stderr b/src/test/ui/where-clauses/where-for-self.stderr new file mode 100644 index 000000000..d06afc1e4 --- /dev/null +++ b/src/test/ui/where-clauses/where-for-self.stderr @@ -0,0 +1,9 @@ +error[E0316]: nested quantification of lifetimes + --> $DIR/where-for-self.rs:15:26 + | +LL | where for<'a> &'a T: for<'b> Bar<'b> + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0316`. diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.rs b/src/test/ui/where-clauses/where-lifetime-resolution.rs new file mode 100644 index 000000000..d8677ee95 --- /dev/null +++ b/src/test/ui/where-clauses/where-lifetime-resolution.rs @@ -0,0 +1,12 @@ +trait Trait1<'a> {} +trait Trait2<'a, 'b> {} + +fn f() where + for<'a> dyn Trait1<'a>: Trait1<'a>, // OK + (dyn for<'a> Trait1<'a>): Trait1<'a>, + //~^ ERROR use of undeclared lifetime name `'a` + for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, + //~^ ERROR use of undeclared lifetime name `'b` +{} + +fn main() {} diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.stderr b/src/test/ui/where-clauses/where-lifetime-resolution.stderr new file mode 100644 index 000000000..e8df02fba --- /dev/null +++ b/src/test/ui/where-clauses/where-lifetime-resolution.stderr @@ -0,0 +1,42 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/where-lifetime-resolution.rs:6:38 + | +LL | (dyn for<'a> Trait1<'a>): Trait1<'a>, + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | (dyn for<'a> Trait1<'a>): for<'a> Trait1<'a>, + | +++++++ +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | for<'a> (dyn for<'a> Trait1<'a>): Trait1<'a>, + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | fn f<'a>() where + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/where-lifetime-resolution.rs:8:52 + | +LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, + | ^^ undeclared lifetime + | +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | for<'a> dyn for<'b> Trait2<'a, 'b>: for<'b> Trait2<'a, 'b>, + | +++++++ +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | for<'b, 'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn f<'b>() where + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. |