about summary refs log tree commit diff
path: root/tests/ui/where-clauses
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/ui/where-clauses
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/ui/where-clauses')
-rw-r--r--tests/ui/where-clauses/auxiliary/where_clauses_xc.rs19
-rw-r--r--tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr18
-rw-r--r--tests/ui/where-clauses/higher-ranked-fn-type.rs25
-rw-r--r--tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr18
-rw-r--r--tests/ui/where-clauses/where-clause-bounds-inconsistency.rs23
-rw-r--r--tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs18
-rw-r--r--tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr21
-rw-r--r--tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs23
-rw-r--r--tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr21
-rw-r--r--tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs18
-rw-r--r--tests/ui/where-clauses/where-clause-method-substituion-rpass.rs23
-rw-r--r--tests/ui/where-clauses/where-clause-method-substituion.rs22
-rw-r--r--tests/ui/where-clauses/where-clause-method-substituion.stderr15
-rw-r--r--tests/ui/where-clauses/where-clause-region-outlives.rs12
-rw-r--r--tests/ui/where-clauses/where-clauses-cross-crate.rs13
-rw-r--r--tests/ui/where-clauses/where-clauses-lifetimes.rs10
-rw-r--r--tests/ui/where-clauses/where-clauses-method-unsatisfied.rs20
-rw-r--r--tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr19
-rw-r--r--tests/ui/where-clauses/where-clauses-method.rs20
-rw-r--r--tests/ui/where-clauses/where-clauses-unboxed-closures.rs17
-rw-r--r--tests/ui/where-clauses/where-clauses-unsatisfied.rs8
-rw-r--r--tests/ui/where-clauses/where-clauses-unsatisfied.stderr19
-rw-r--r--tests/ui/where-clauses/where-clauses.rs27
-rw-r--r--tests/ui/where-clauses/where-equality-constraints.rs6
-rw-r--r--tests/ui/where-clauses/where-equality-constraints.stderr18
-rw-r--r--tests/ui/where-clauses/where-for-self-2.rs24
-rw-r--r--tests/ui/where-clauses/where-for-self-2.stderr11
-rw-r--r--tests/ui/where-clauses/where-for-self.rs19
-rw-r--r--tests/ui/where-clauses/where-for-self.stderr9
-rw-r--r--tests/ui/where-clauses/where-lifetime-resolution.rs12
-rw-r--r--tests/ui/where-clauses/where-lifetime-resolution.stderr42
31 files changed, 570 insertions, 0 deletions
diff --git a/tests/ui/where-clauses/auxiliary/where_clauses_xc.rs b/tests/ui/where-clauses/auxiliary/where_clauses_xc.rs
new file mode 100644
index 00000000000..7c8043b2002
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
new file mode 100644
index 00000000000..30248a7a397
--- /dev/null
+++ b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied
+  --> $DIR/higher-ranked-fn-type.rs:20:5
+   |
+LL |     called()
+   |     ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())`
+   |
+note: required by a bound in `called`
+  --> $DIR/higher-ranked-fn-type.rs:12:25
+   |
+LL | fn called()
+   |    ------ required by a bound in this
+LL | where
+LL |     for<'b> fn(&'b ()): Foo,
+   |                         ^^^ required by this bound in `called`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.rs b/tests/ui/where-clauses/higher-ranked-fn-type.rs
new file mode 100644
index 00000000000..c19e75eb7bf
--- /dev/null
+++ b/tests/ui/where-clauses/higher-ranked-fn-type.rs
@@ -0,0 +1,25 @@
+// revisions: quiet verbose
+// [verbose]compile-flags: -Zverbose
+
+#![allow(unused_parens)]
+
+trait Foo {
+    type Assoc;
+}
+
+fn called()
+where
+    for<'b> fn(&'b ()): Foo,
+{
+}
+
+fn caller()
+where
+    (for<'a> fn(&'a ())): Foo,
+{
+    called()
+    //[quiet]~^ ERROR the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied
+    //[verbose]~^^ ERROR the trait bound `for<Region(
+}
+
+fn main() {}
diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
new file mode 100644
index 00000000000..268cef6e275
--- /dev/null
+++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `for<Region(BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b))> fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ()): Foo` is not satisfied
+  --> $DIR/higher-ranked-fn-type.rs:20:5
+   |
+LL |     called()
+   |     ^^^^^^ the trait `for<Region(BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b))> Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ())`
+   |
+note: required by a bound in `called`
+  --> $DIR/higher-ranked-fn-type.rs:12:25
+   |
+LL | fn called()
+   |    ------ required by a bound in this
+LL | where
+LL |     for<'b> fn(&'b ()): Foo,
+   |                         ^^^ required by this bound in `called`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs
new file mode 100644
index 00000000000..cf7d06b6179
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs
new file mode 100644
index 00000000000..0e8bb61a79b
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
new file mode 100644
index 00000000000..43fbc0a9061
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs
new file mode 100644
index 00000000000..25c46330e4d
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
new file mode 100644
index 00000000000..f2db8fcc4a3
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs
new file mode 100644
index 00000000000..6fc570b9b5b
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs
new file mode 100644
index 00000000000..daa3c8dd8e3
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clause-method-substituion.rs b/tests/ui/where-clauses/where-clause-method-substituion.rs
new file mode 100644
index 00000000000..4607783c098
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clause-method-substituion.stderr b/tests/ui/where-clauses/where-clause-method-substituion.stderr
new file mode 100644
index 00000000000..8c47ed6d431
--- /dev/null
+++ b/tests/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:16
+   |
+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/tests/ui/where-clauses/where-clause-region-outlives.rs b/tests/ui/where-clauses/where-clause-region-outlives.rs
new file mode 100644
index 00000000000..84925345de1
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clauses-cross-crate.rs b/tests/ui/where-clauses/where-clauses-cross-crate.rs
new file mode 100644
index 00000000000..9edf0bd5b1d
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clauses-lifetimes.rs b/tests/ui/where-clauses/where-clauses-lifetimes.rs
new file mode 100644
index 00000000000..4bfd9e6590f
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs b/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs
new file mode 100644
index 00000000000..a8ae0296407
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr
new file mode 100644
index 00000000000..e90502977ff
--- /dev/null
+++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `Bar: Eq` is not satisfied
+  --> $DIR/where-clauses-method-unsatisfied.rs:18:7
+   |
+LL |     x.equals(&x);
+   |       ^^^^^^ the trait `Eq` is not implemented for `Bar`
+   |
+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/tests/ui/where-clauses/where-clauses-method.rs b/tests/ui/where-clauses/where-clauses-method.rs
new file mode 100644
index 00000000000..feecff43565
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clauses-unboxed-closures.rs b/tests/ui/where-clauses/where-clauses-unboxed-closures.rs
new file mode 100644
index 00000000000..6964cfa2eb0
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clauses-unsatisfied.rs b/tests/ui/where-clauses/where-clauses-unsatisfied.rs
new file mode 100644
index 00000000000..8b067d30a2a
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clauses-unsatisfied.stderr b/tests/ui/where-clauses/where-clauses-unsatisfied.stderr
new file mode 100644
index 00000000000..b1805a4522f
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-clauses.rs b/tests/ui/where-clauses/where-clauses.rs
new file mode 100644
index 00000000000..905ef7c5e8c
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-equality-constraints.rs b/tests/ui/where-clauses/where-equality-constraints.rs
new file mode 100644
index 00000000000..8828f09d92d
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-equality-constraints.stderr b/tests/ui/where-clauses/where-equality-constraints.stderr
new file mode 100644
index 00000000000..9d8fac02ed3
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-for-self-2.rs b/tests/ui/where-clauses/where-for-self-2.rs
new file mode 100644
index 00000000000..37c6954fd52
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-for-self-2.stderr b/tests/ui/where-clauses/where-for-self-2.stderr
new file mode 100644
index 00000000000..f65db78fc89
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-for-self.rs b/tests/ui/where-clauses/where-for-self.rs
new file mode 100644
index 00000000000..9380e72cd7c
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-for-self.stderr b/tests/ui/where-clauses/where-for-self.stderr
new file mode 100644
index 00000000000..d06afc1e423
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-lifetime-resolution.rs b/tests/ui/where-clauses/where-lifetime-resolution.rs
new file mode 100644
index 00000000000..d8677ee959a
--- /dev/null
+++ b/tests/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/tests/ui/where-clauses/where-lifetime-resolution.stderr b/tests/ui/where-clauses/where-lifetime-resolution.stderr
new file mode 100644
index 00000000000..e8df02fbad6
--- /dev/null
+++ b/tests/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`.