summaryrefslogtreecommitdiffstats
path: root/src/test/ui/hrtb
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/hrtb
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/test/ui/hrtb/complex.rs28
-rw-r--r--src/test/ui/hrtb/due-to-where-clause.rs13
-rw-r--r--src/test/ui/hrtb/due-to-where-clause.stderr11
-rw-r--r--src/test/ui/hrtb/hrtb-cache-issue-54302.rs24
-rw-r--r--src/test/ui/hrtb/hrtb-cache-issue-54302.stderr11
-rw-r--r--src/test/ui/hrtb/hrtb-conflate-regions.rs31
-rw-r--r--src/test/ui/hrtb/hrtb-conflate-regions.stderr20
-rw-r--r--src/test/ui/hrtb/hrtb-debruijn-in-receiver.rs18
-rw-r--r--src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr14
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-fn.rs18
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-fn.stderr12
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs36
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr11
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs37
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs29
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr11
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs50
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr23
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs48
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr43
-rw-r--r--src/test/ui/hrtb/hrtb-identity-fn-borrows.rs26
-rw-r--r--src/test/ui/hrtb/hrtb-identity-fn-borrows.stderr14
-rw-r--r--src/test/ui/hrtb/hrtb-just-for-static.rs35
-rw-r--r--src/test/ui/hrtb/hrtb-just-for-static.stderr28
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.polonius.stderr71
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.rs56
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.stderr73
-rw-r--r--src/test/ui/hrtb/issue-30786.rs134
-rw-r--r--src/test/ui/hrtb/issue-30786.stderr53
-rw-r--r--src/test/ui/hrtb/issue-46989.rs40
-rw-r--r--src/test/ui/hrtb/issue-46989.stderr11
-rw-r--r--src/test/ui/hrtb/issue-57639.rs29
-rw-r--r--src/test/ui/hrtb/issue-58451.rs13
-rw-r--r--src/test/ui/hrtb/issue-58451.stderr19
-rw-r--r--src/test/ui/hrtb/issue-62203-hrtb-ice.rs50
-rw-r--r--src/test/ui/hrtb/issue-62203-hrtb-ice.stderr53
-rw-r--r--src/test/ui/hrtb/issue-88446.rs35
-rw-r--r--src/test/ui/hrtb/issue-90177.rs32
-rw-r--r--src/test/ui/hrtb/issue-95034.rs98
-rw-r--r--src/test/ui/hrtb/issue-95034.stderr1
-rw-r--r--src/test/ui/hrtb/issue-95230.rs7
41 files changed, 1366 insertions, 0 deletions
diff --git a/src/test/ui/hrtb/complex.rs b/src/test/ui/hrtb/complex.rs
new file mode 100644
index 000000000..8cdfe247e
--- /dev/null
+++ b/src/test/ui/hrtb/complex.rs
@@ -0,0 +1,28 @@
+// check-pass
+
+trait A<'a> {}
+trait B<'b> {}
+fn foo<T>() where for<'a> T: A<'a> + 'a {}
+trait C<'c>: for<'a> A<'a> + for<'b> B<'b> {
+ type As;
+}
+struct D<T> where T: for<'c> C<'c, As=&'c ()> {
+ t: std::marker::PhantomData<T>,
+}
+trait E<'e, 'g> {
+ type As;
+}
+trait F<'f>: for<'a> A<'a> + for<'e> E<'e, 'f> {}
+struct G<T> where T: for<'f> F<'f, As=&'f ()> {
+ t: std::marker::PhantomData<T>,
+}
+trait H<'a, 'b> {
+ type As;
+}
+trait I<'a>: for<'b> H<'a, 'b> {}
+
+struct J<T> where T: for<'i> I<'i, As=&'i ()> {
+ t: std::marker::PhantomData<T>,
+}
+
+fn main() {}
diff --git a/src/test/ui/hrtb/due-to-where-clause.rs b/src/test/ui/hrtb/due-to-where-clause.rs
new file mode 100644
index 000000000..1afd15613
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.rs
@@ -0,0 +1,13 @@
+fn main() {
+ test::<FooS>(&mut 42); //~ ERROR implementation of `Foo` is not general enough
+}
+
+trait Foo<'a> {}
+
+struct FooS<'a> {
+ data: &'a mut u32,
+}
+
+impl<'a, 'b: 'a> Foo<'b> for FooS<'a> {}
+
+fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
diff --git a/src/test/ui/hrtb/due-to-where-clause.stderr b/src/test/ui/hrtb/due-to-where-clause.stderr
new file mode 100644
index 000000000..520938a63
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Foo` is not general enough
+ --> $DIR/due-to-where-clause.rs:2:5
+ |
+LL | test::<FooS>(&mut 42);
+ | ^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`...
+ = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.rs b/src/test/ui/hrtb/hrtb-cache-issue-54302.rs
new file mode 100644
index 000000000..a20d03c77
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.rs
@@ -0,0 +1,24 @@
+// Regression test for #54302.
+//
+// We were incorrectly using the "evaluation cache" (which ignored
+// region results) to conclude that `&'static str: Deserialize`, even
+// though it would require that `for<'de> 'de: 'static`, which is
+// clearly false.
+
+trait Deserialize<'de> {}
+
+trait DeserializeOwned: for<'de> Deserialize<'de> {}
+impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
+
+// Based on this impl, `&'static str` only implements Deserialize<'static>.
+// It does not implement for<'de> Deserialize<'de>.
+impl<'de: 'a, 'a> Deserialize<'de> for &'a str {}
+
+fn main() {
+ fn assert_deserialize_owned<T: DeserializeOwned>() {}
+ assert_deserialize_owned::<&'static str>(); //~ ERROR
+
+ // It correctly does not implement for<'de> Deserialize<'de>.
+ // fn assert_hrtb<T: for<'de> Deserialize<'de>>() {}
+ // assert_hrtb::<&'static str>();
+}
diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
new file mode 100644
index 000000000..f014eab86
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Deserialize` is not general enough
+ --> $DIR/hrtb-cache-issue-54302.rs:19:5
+ |
+LL | assert_deserialize_owned::<&'static str>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
+ |
+ = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
+ = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.rs b/src/test/ui/hrtb/hrtb-conflate-regions.rs
new file mode 100644
index 000000000..e83686404
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-conflate-regions.rs
@@ -0,0 +1,31 @@
+// Test that an impl with only one bound region `'a` cannot be used to
+// satisfy a constraint where there are two bound regions.
+
+trait Foo<X> {
+ fn foo(&self, x: X) { }
+}
+
+fn want_foo2<T>()
+ where T : for<'a,'b> Foo<(&'a isize, &'b isize)>
+{
+}
+
+fn want_foo1<T>()
+ where T : for<'z> Foo<(&'z isize, &'z isize)>
+{
+}
+
+// Expressed as a where clause
+
+struct SomeStruct;
+
+impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct
+{
+}
+
+fn a() { want_foo1::<SomeStruct>(); } // OK -- foo wants just one region
+fn b() { want_foo2::<SomeStruct>(); }
+//~^ ERROR implementation of
+//~| ERROR implementation of
+
+fn main() { }
diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr
new file mode 100644
index 000000000..46f5308dd
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr
@@ -0,0 +1,20 @@
+error: implementation of `Foo` is not general enough
+ --> $DIR/hrtb-conflate-regions.rs:27:10
+ |
+LL | fn b() { want_foo2::<SomeStruct>(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
+
+error: implementation of `Foo` is not general enough
+ --> $DIR/hrtb-conflate-regions.rs:27:10
+ |
+LL | fn b() { want_foo2::<SomeStruct>(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/hrtb/hrtb-debruijn-in-receiver.rs b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.rs
new file mode 100644
index 000000000..05d3e1a43
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.rs
@@ -0,0 +1,18 @@
+// Test the case where the `Self` type has a bound lifetime that must
+// be adjusted in the fn signature. Issue #19537.
+
+use std::collections::HashMap;
+
+struct Foo<'a> {
+ map: HashMap<usize, &'a str>
+}
+
+impl<'a> Foo<'a> {
+ fn new() -> Foo<'a> { panic!() }
+ fn insert(&'a mut self) { }
+}
+fn main() {
+ let mut foo = Foo::new();
+ foo.insert();
+ foo.insert(); //~ ERROR cannot borrow
+}
diff --git a/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr
new file mode 100644
index 000000000..fa391ecba
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+ --> $DIR/hrtb-debruijn-in-receiver.rs:17:5
+ |
+LL | foo.insert();
+ | ------------ first mutable borrow occurs here
+LL | foo.insert();
+ | ^^^^^^^^^^^^
+ | |
+ | second mutable borrow occurs here
+ | first borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
new file mode 100644
index 000000000..567802376
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
@@ -0,0 +1,18 @@
+// Test an `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+fn foo<'a>() -> fn(&'a u32) {
+ panic!()
+}
+
+fn main() {
+ // Here, proving that `fn(&'a u32) <: for<'b> fn(&'b u32)`:
+ //
+ // - instantiates `'b` with a placeholder `!b`,
+ // - requires that `&!b u32 <: &'a u32` and hence that `!b: 'a`,
+ // - but we can never know this.
+
+ let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
new file mode 100644
index 000000000..9914783d9
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/hrtb-exists-forall-fn.rs:17:34
+ |
+LL | let _: for<'b> fn(&'b u32) = foo();
+ | ^^^^^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'b> fn(&'b u32)`
+ found fn pointer `fn(&u32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
new file mode 100644
index 000000000..921061916
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
@@ -0,0 +1,36 @@
+// Test a case where variance and higher-ranked types interact in surprising ways.
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+ T: Trait<for<'b> fn(&'b u32)>,
+{
+}
+
+impl<'a> Trait<fn(&'a u32)> for () {}
+
+fn main() {
+ // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+ //
+ // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }`
+ // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>`
+ // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` -- this does a
+ // "bidirectional" subtyping check, so we wind up with:
+ // - `fn(&?a u32) <: for<'b> fn(&'b u32)` :-
+ // - `&'!b u32 <: &?a u32`
+ // - `!'b: ?a` -- solveable if `?a` is inferred to `'empty`
+ // - `for<'b> fn(&'b u32) <: fn(&?a u32)` :-
+ // - `&?a u32 u32 <: &?b u32`
+ // - `?a: ?b` -- solveable if `?b` is also inferred to `'empty`
+ // - So the subtyping check succeeds, somewhat surprisingly.
+ // This is because we can use `'empty`.
+ //
+ // NB. *However*, the reinstated leak-check gives an error here.
+
+ foo::<()>();
+ //~^ ERROR implementation of `Trait` is not general enough
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
new file mode 100644
index 000000000..364b613fc
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Trait` is not general enough
+ --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
+ |
+LL | foo::<()>();
+ | ^^^^^^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `()` must implement `Trait<for<'b> fn(&'b u32)>`
+ = note: ...but it actually implements `Trait<fn(&'0 u32)>`, for some specific lifetime `'0`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs
new file mode 100644
index 000000000..f95496a6c
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs
@@ -0,0 +1,37 @@
+// Test a case where variance and higher-ranked types interact in surprising ways.
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+//
+// check-pass
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+ T: Trait<for<'b> fn(fn(&'b u32))>,
+{
+}
+
+impl<'a> Trait<fn(fn(&'a u32))> for () {}
+
+fn main() {
+ // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+ //
+ // - The impl provides the clause `forall<'a> { (): Trait<fn(fn(&'a u32))> }`
+ // - We instantiate `'a` existentially to get `(): Trait<fn(fn(&?a u32))>`
+ // - We unify `fn(fn(&?a u32))` with `for<'b> fn(fn(&'b u32))` -- this does a
+ // "bidirectional" subtyping check, so we wind up with:
+ // - `fn(fn(&?a u32)) <: for<'b> fn(fn(&'b u32))` :-
+ // - `fn(&!b u32) <: fn(&?a u32)`
+ // - `&?a u32 <: &!b u32`
+ // - `?a: !'b` -- solveable if `?a` is inferred to `'static`
+ // - `for<'b> fn(fn(&'b u32)) <: fn(fn(&?a u32))` :-
+ // - `fn(&?a u32) <: fn(&?b u32)`
+ // - `&?b u32 <: &?a u32`
+ // - `?b: ?a` -- solveable if `?b` is inferred to `'static`
+ // - So the subtyping check succeeds, somewhat surprisingly.
+ // This is because we can use `'static`.
+
+ foo::<()>();
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
new file mode 100644
index 000000000..9b9e4496a
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
@@ -0,0 +1,29 @@
+// Test an `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+use std::cell::Cell;
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+ T: Trait<for<'b> fn(Cell<&'b u32>)>,
+{
+}
+
+impl<'a> Trait<fn(Cell<&'a u32>)> for () {}
+
+fn main() {
+ // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+ //
+ // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }`
+ // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>`
+ // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)`
+ // - This requires (among other things) instantiating `'b` universally,
+ // yielding `fn(&!b u32)`, in a fresh universe U1
+ // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`.
+
+ foo::<()>(); //~ ERROR implementation of `Trait` is not general enough
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
new file mode 100644
index 000000000..cb2ce8a41
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Trait` is not general enough
+ --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
+ |
+LL | foo::<()>();
+ | ^^^^^^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `()` must implement `Trait<for<'b> fn(Cell<&'b u32>)>`
+ = note: ...but it actually implements `Trait<fn(Cell<&'0 u32>)>`, for some specific lifetime `'0`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs
new file mode 100644
index 000000000..f9ae1429e
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs
@@ -0,0 +1,50 @@
+// Test HRTB supertraits with several levels of expansion required.
+
+trait Foo<'tcx>
+{
+ fn foo(&'tcx self) -> &'tcx isize;
+}
+
+trait Bar<'ccx>
+ : for<'tcx> Foo<'tcx>
+{
+ fn bar(&'ccx self) -> &'ccx isize;
+}
+
+trait Baz
+ : for<'ccx> Bar<'ccx>
+{
+ fn dummy(&self);
+}
+
+trait Qux
+ : Bar<'static>
+{
+ fn dummy(&self);
+}
+
+fn want_foo_for_any_tcx<F>(f: &F)
+ where F : for<'tcx> Foo<'tcx>
+{
+}
+
+fn want_bar_for_any_ccx<B>(b: &B)
+ where B : for<'ccx> Bar<'ccx>
+{
+}
+
+fn want_baz<B>(b: &B)
+ where B : Baz
+{
+ want_foo_for_any_tcx(b);
+ want_bar_for_any_ccx(b);
+}
+
+fn want_qux<B>(b: &B)
+ where B : Qux
+{
+ want_foo_for_any_tcx(b);
+ want_bar_for_any_ccx(b); //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
new file mode 100644
index 000000000..8cda76b94
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -0,0 +1,23 @@
+error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
+ --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26
+ |
+LL | want_bar_for_any_ccx(b);
+ | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `want_bar_for_any_ccx`
+ --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15
+ |
+LL | fn want_bar_for_any_ccx<B>(b: &B)
+ | -------------------- required by a bound in this
+LL | where B : for<'ccx> Bar<'ccx>
+ | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx`
+help: consider further restricting this bound
+ |
+LL | where B : Qux + for<'ccx> Bar<'ccx>
+ | +++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs
new file mode 100644
index 000000000..48ebe5017
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs
@@ -0,0 +1,48 @@
+// Test a trait (`Bar`) with a higher-ranked supertrait.
+
+trait Foo<'tcx>
+{
+ fn foo(&'tcx self) -> &'tcx isize;
+}
+
+trait Bar<'ccx>
+ : for<'tcx> Foo<'tcx>
+{
+ fn bar(&'ccx self) -> &'ccx isize;
+}
+
+fn want_foo_for_some_tcx<'x,F>(f: &'x F)
+ where F : Foo<'x>
+{
+ want_foo_for_some_tcx(f);
+ want_foo_for_any_tcx(f); //~ ERROR not satisfied
+}
+
+fn want_foo_for_any_tcx<F>(f: &F)
+ where F : for<'tcx> Foo<'tcx>
+{
+ want_foo_for_some_tcx(f);
+ want_foo_for_any_tcx(f);
+}
+
+fn want_bar_for_some_ccx<'x,B>(b: &B)
+ where B : Bar<'x>
+{
+ want_foo_for_some_tcx(b);
+ want_foo_for_any_tcx(b);
+
+ want_bar_for_some_ccx(b);
+ want_bar_for_any_ccx(b); //~ ERROR not satisfied
+}
+
+fn want_bar_for_any_ccx<B>(b: &B)
+ where B : for<'ccx> Bar<'ccx>
+{
+ want_foo_for_some_tcx(b);
+ want_foo_for_any_tcx(b);
+
+ want_bar_for_some_ccx(b);
+ want_bar_for_any_ccx(b);
+}
+
+fn main() {}
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
new file mode 100644
index 000000000..88793a152
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
@@ -0,0 +1,43 @@
+error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
+ --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26
+ |
+LL | want_foo_for_any_tcx(f);
+ | -------------------- ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `want_foo_for_any_tcx`
+ --> $DIR/hrtb-higher-ranker-supertraits.rs:22:15
+ |
+LL | fn want_foo_for_any_tcx<F>(f: &F)
+ | -------------------- required by a bound in this
+LL | where F : for<'tcx> Foo<'tcx>
+ | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo_for_any_tcx`
+help: consider further restricting this bound
+ |
+LL | where F : Foo<'x> + for<'tcx> Foo<'tcx>
+ | +++++++++++++++++++++
+
+error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
+ --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
+ |
+LL | want_bar_for_any_ccx(b);
+ | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `want_bar_for_any_ccx`
+ --> $DIR/hrtb-higher-ranker-supertraits.rs:39:15
+ |
+LL | fn want_bar_for_any_ccx<B>(b: &B)
+ | -------------------- required by a bound in this
+LL | where B : for<'ccx> Bar<'ccx>
+ | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx`
+help: consider further restricting this bound
+ |
+LL | where B : Bar<'x> + for<'ccx> Bar<'ccx>
+ | +++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.rs b/src/test/ui/hrtb/hrtb-identity-fn-borrows.rs
new file mode 100644
index 000000000..89fc4705a
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.rs
@@ -0,0 +1,26 @@
+// Test that the `'a` in the where clause correctly links the region
+// of the output to the region of the input.
+
+trait FnLike<A,R> {
+ fn call(&self, arg: A) -> R;
+}
+
+fn call_repeatedly<F>(f: F)
+ where F : for<'a> FnLike<&'a isize, &'a isize>
+{
+ // Result is stored: cannot re-assign `x`
+ let mut x = 3;
+ let y = f.call(&x);
+ x = 5; //~ ERROR cannot assign to `x` because it is borrowed
+
+ // Result is not stored: can re-assign `x`
+ let mut x = 3;
+ f.call(&x);
+ f.call(&x);
+ f.call(&x);
+ x = 5;
+ drop(y);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/hrtb/hrtb-identity-fn-borrows.stderr b/src/test/ui/hrtb/hrtb-identity-fn-borrows.stderr
new file mode 100644
index 000000000..4886a3c8b
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-identity-fn-borrows.stderr
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+ --> $DIR/hrtb-identity-fn-borrows.rs:14:5
+ |
+LL | let y = f.call(&x);
+ | -- borrow of `x` occurs here
+LL | x = 5;
+ | ^^^^^ assignment to borrowed `x` occurs here
+...
+LL | drop(y);
+ | - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/hrtb/hrtb-just-for-static.rs b/src/test/ui/hrtb/hrtb-just-for-static.rs
new file mode 100644
index 000000000..8fb4218f8
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-just-for-static.rs
@@ -0,0 +1,35 @@
+// Test a case where you have an impl of `Foo<X>` for all `X` that
+// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
+
+trait Foo<X> {
+ fn foo(&self, x: X) { }
+}
+
+fn want_hrtb<T>()
+ where T : for<'a> Foo<&'a isize>
+{
+}
+
+// AnyInt implements Foo<&'a isize> for any 'a, so it is a match.
+struct AnyInt;
+impl<'a> Foo<&'a isize> for AnyInt { }
+fn give_any() {
+ want_hrtb::<AnyInt>()
+}
+
+// StaticInt only implements Foo<&'static isize>, so it is an error.
+struct StaticInt;
+impl Foo<&'static isize> for StaticInt { }
+fn give_static() {
+ want_hrtb::<StaticInt>() //~ ERROR
+}
+
+// &'a u32 only implements Foo<&'a isize> for specific 'a, so it is an error.
+impl<'a> Foo<&'a isize> for &'a u32 { }
+fn give_some<'a>() {
+ want_hrtb::<&'a u32>()
+ //~^ ERROR lifetime may not live long enough
+ //~| ERROR implementation of `Foo` is not general enough
+}
+
+fn main() { }
diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr
new file mode 100644
index 000000000..b4312091e
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr
@@ -0,0 +1,28 @@
+error: implementation of `Foo` is not general enough
+ --> $DIR/hrtb-just-for-static.rs:24:5
+ |
+LL | want_hrtb::<StaticInt>()
+ | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Foo<&'static isize>`
+
+error: lifetime may not live long enough
+ --> $DIR/hrtb-just-for-static.rs:30:5
+ |
+LL | fn give_some<'a>() {
+ | -- lifetime `'a` defined here
+LL | want_hrtb::<&'a u32>()
+ | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: implementation of `Foo` is not general enough
+ --> $DIR/hrtb-just-for-static.rs:30:5
+ |
+LL | want_hrtb::<&'a u32>()
+ | ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `Foo<&'0 isize>` would have to be implemented for the type `&u32`, for any lifetime `'0`...
+ = note: ...but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.polonius.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.polonius.stderr
new file mode 100644
index 000000000..a94c80eb3
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.polonius.stderr
@@ -0,0 +1,71 @@
+warning: function cannot return without recursing
+ --> $DIR/hrtb-perfect-forwarding.rs:16:1
+ |
+LL | / fn no_hrtb<'b, T>(mut t: T)
+LL | | where
+LL | | T: Bar<&'b isize>,
+LL | | {
+... |
+LL | | no_hrtb(&mut t);
+ | | --------------- recursive call site
+LL | | }
+ | |_^ cannot return without recursing
+ |
+ = note: `#[warn(unconditional_recursion)]` on by default
+ = help: a `loop` may express intention better if this is on purpose
+
+warning: function cannot return without recursing
+ --> $DIR/hrtb-perfect-forwarding.rs:25:1
+ |
+LL | / fn bar_hrtb<T>(mut t: T)
+LL | | where
+LL | | T: for<'b> Bar<&'b isize>,
+LL | | {
+... |
+LL | | bar_hrtb(&mut t);
+ | | ---------------- recursive call site
+LL | | }
+ | |_^ cannot return without recursing
+ |
+ = help: a `loop` may express intention better if this is on purpose
+
+warning: function cannot return without recursing
+ --> $DIR/hrtb-perfect-forwarding.rs:35:1
+ |
+LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T)
+LL | | where
+LL | | T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
+LL | | {
+... |
+LL | | foo_hrtb_bar_not(&mut t);
+ | | ------------------------ recursive call site
+LL | |
+LL | |
+LL | | }
+ | |_^ cannot return without recursing
+ |
+ = help: a `loop` may express intention better if this is on purpose
+
+error: higher-ranked subtype error
+ --> $DIR/hrtb-perfect-forwarding.rs:43:5
+ |
+LL | foo_hrtb_bar_not(&mut t);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: function cannot return without recursing
+ --> $DIR/hrtb-perfect-forwarding.rs:48:1
+ |
+LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T)
+LL | | where
+LL | | T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>,
+LL | | {
+LL | | // OK -- now we have `T : for<'b> Bar<&'b isize>`.
+LL | | foo_hrtb_bar_hrtb(&mut t);
+ | | ------------------------- recursive call site
+LL | | }
+ | |_^ cannot return without recursing
+ |
+ = help: a `loop` may express intention better if this is on purpose
+
+error: aborting due to previous error; 4 warnings emitted
+
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
new file mode 100644
index 000000000..d45fa183c
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
@@ -0,0 +1,56 @@
+// Test a case where you have an impl of `Foo<X>` for all `X` that
+// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
+
+trait Foo<X> {
+ fn foo(&mut self, x: X) {}
+}
+
+trait Bar<X> {
+ fn bar(&mut self, x: X) {}
+}
+
+impl<'a, X, F> Foo<X> for &'a mut F where F: Foo<X> + Bar<X> {}
+
+impl<'a, X, F> Bar<X> for &'a mut F where F: Bar<X> {}
+
+fn no_hrtb<'b, T>(mut t: T) //~ WARN function cannot return
+where
+ T: Bar<&'b isize>,
+{
+ // OK -- `T : Bar<&'b isize>`, and thus the impl above ensures that
+ // `&mut T : Bar<&'b isize>`.
+ no_hrtb(&mut t);
+}
+
+fn bar_hrtb<T>(mut t: T) //~ WARN function cannot return
+where
+ T: for<'b> Bar<&'b isize>,
+{
+ // OK -- `T : for<'b> Bar<&'b isize>`, and thus the impl above
+ // ensures that `&mut T : for<'b> Bar<&'b isize>`. This is an
+ // example of a "perfect forwarding" impl.
+ bar_hrtb(&mut t);
+}
+
+fn foo_hrtb_bar_not<'b, T>(mut t: T) //~ WARN function cannot return
+where
+ T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
+{
+ // Not OK -- The forwarding impl for `Foo` requires that `Bar` also
+ // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a
+ // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where
+ // clause only specifies `T : Bar<&'b isize>`.
+ foo_hrtb_bar_not(&mut t);
+ //~^ ERROR implementation of `Bar` is not general enough
+ //~^^ ERROR lifetime may not live long enough
+}
+
+fn foo_hrtb_bar_hrtb<T>(mut t: T) //~ WARN function cannot return
+where
+ T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>,
+{
+ // OK -- now we have `T : for<'b> Bar<&'b isize>`.
+ foo_hrtb_bar_hrtb(&mut t);
+}
+
+fn main() {}
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
new file mode 100644
index 000000000..1461e7fd2
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
@@ -0,0 +1,73 @@
+warning: function cannot return without recursing
+ --> $DIR/hrtb-perfect-forwarding.rs:16:1
+ |
+LL | / fn no_hrtb<'b, T>(mut t: T)
+LL | | where
+LL | | T: Bar<&'b isize>,
+ | |______________________^ cannot return without recursing
+...
+LL | no_hrtb(&mut t);
+ | --------------- recursive call site
+ |
+ = note: `#[warn(unconditional_recursion)]` on by default
+ = help: a `loop` may express intention better if this is on purpose
+
+warning: function cannot return without recursing
+ --> $DIR/hrtb-perfect-forwarding.rs:25:1
+ |
+LL | / fn bar_hrtb<T>(mut t: T)
+LL | | where
+LL | | T: for<'b> Bar<&'b isize>,
+ | |______________________________^ cannot return without recursing
+...
+LL | bar_hrtb(&mut t);
+ | ---------------- recursive call site
+ |
+ = help: a `loop` may express intention better if this is on purpose
+
+warning: function cannot return without recursing
+ --> $DIR/hrtb-perfect-forwarding.rs:35:1
+ |
+LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T)
+LL | | where
+LL | | T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
+ | |_______________________________________________^ cannot return without recursing
+...
+LL | foo_hrtb_bar_not(&mut t);
+ | ------------------------ recursive call site
+ |
+ = help: a `loop` may express intention better if this is on purpose
+
+error: lifetime may not live long enough
+ --> $DIR/hrtb-perfect-forwarding.rs:43:5
+ |
+LL | fn foo_hrtb_bar_not<'b, T>(mut t: T)
+ | -- lifetime `'b` defined here
+...
+LL | foo_hrtb_bar_not(&mut t);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+
+error: implementation of `Bar` is not general enough
+ --> $DIR/hrtb-perfect-forwarding.rs:43:5
+ |
+LL | foo_hrtb_bar_not(&mut t);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough
+ |
+ = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1`
+
+warning: function cannot return without recursing
+ --> $DIR/hrtb-perfect-forwarding.rs:48:1
+ |
+LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T)
+LL | | where
+LL | | T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>,
+ | |_______________________________________________________^ cannot return without recursing
+...
+LL | foo_hrtb_bar_hrtb(&mut t);
+ | ------------------------- recursive call site
+ |
+ = help: a `loop` may express intention better if this is on purpose
+
+error: aborting due to 2 previous errors; 4 warnings emitted
+
diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs
new file mode 100644
index 000000000..e5f46f711
--- /dev/null
+++ b/src/test/ui/hrtb/issue-30786.rs
@@ -0,0 +1,134 @@
+// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T`
+// should act as assertion that item does not borrow from its stream;
+// but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
+// have such an item.
+//
+// This tests double-checks that we do not allow such behavior to leak
+// through again.
+
+pub trait Stream {
+ type Item;
+ fn next(self) -> Option<Self::Item>;
+}
+
+// Example stream
+pub struct Repeat(u64);
+
+impl<'a> Stream for &'a mut Repeat {
+ type Item = &'a u64;
+ fn next(self) -> Option<Self::Item> {
+ Some(&self.0)
+ }
+}
+
+pub struct Map<S, F> {
+ stream: S,
+ func: F,
+}
+
+impl<'a, A, F, T> Stream for &'a mut Map<A, F>
+where
+ &'a mut A: Stream,
+ F: FnMut(<&'a mut A as Stream>::Item) -> T,
+{
+ type Item = T;
+ fn next(self) -> Option<T> {
+ match self.stream.next() {
+ Some(item) => Some((self.func)(item)),
+ None => None,
+ }
+ }
+}
+
+pub struct Filter<S, F> {
+ stream: S,
+ func: F,
+}
+
+impl<'a, A, F, T> Stream for &'a mut Filter<A, F>
+where
+ for<'b> &'b mut A: Stream<Item = T>, // <---- BAD
+ F: FnMut(&T) -> bool,
+{
+ type Item = <&'a mut A as Stream>::Item;
+ fn next(self) -> Option<Self::Item> {
+ while let Some(item) = self.stream.next() {
+ if (self.func)(&item) {
+ return Some(item);
+ }
+ }
+ None
+ }
+}
+
+pub trait StreamExt
+where
+ for<'b> &'b mut Self: Stream,
+{
+ fn mapx<F>(self, func: F) -> Map<Self, F>
+ where
+ Self: Sized,
+ for<'a> &'a mut Map<Self, F>: Stream,
+ {
+ Map { func: func, stream: self }
+ }
+
+ fn filterx<F>(self, func: F) -> Filter<Self, F>
+ where
+ Self: Sized,
+ for<'a> &'a mut Filter<Self, F>: Stream,
+ {
+ Filter { func: func, stream: self }
+ }
+
+ fn countx(mut self) -> usize
+ where
+ Self: Sized,
+ {
+ let mut count = 0;
+ while let Some(_) = self.next() {
+ count += 1;
+ }
+ count
+ }
+}
+
+impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
+
+fn identity<T>(x: &T) -> &T {
+ x
+}
+
+fn variant1() {
+ let source = Repeat(10);
+
+ // Here, the call to `mapx` returns a type `T` to which `StreamExt`
+ // is not applicable, because `for<'b> &'b mut T: Stream`) doesn't hold.
+ //
+ // More concretely, the type `T` is `Map<Repeat, Closure>`, and
+ // the where clause doesn't hold because the signature of the
+ // closure gets inferred to a signature like `|&'_ Stream| -> &'_`
+ // for some specific `'_`, rather than a more generic
+ // signature.
+ //
+ // Why *exactly* we opt for this signature is a bit unclear to me,
+ // we deduce it somehow from a reuqirement that `Map: Stream` I
+ // guess.
+ let map = source.mapx(|x: &_| x);
+ let filter = map.filterx(|x: &_| true);
+ //~^ ERROR the method
+}
+
+fn variant2() {
+ let source = Repeat(10);
+
+ // Here, we use a function, which is not subject to the vagaries
+ // of closure signature inference. In this case, we get the error
+ // on `countx` as, I think, the test originally expected.
+ let map = source.mapx(identity);
+ let filter = map.filterx(|x: &_| true);
+ let count = filter.countx();
+ //~^ ERROR the method
+}
+
+fn main() {}
diff --git a/src/test/ui/hrtb/issue-30786.stderr b/src/test/ui/hrtb/issue-30786.stderr
new file mode 100644
index 000000000..bc7b5e914
--- /dev/null
+++ b/src/test/ui/hrtb/issue-30786.stderr
@@ -0,0 +1,53 @@
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>`, but its trait bounds were not satisfied
+ --> $DIR/issue-30786.rs:118:22
+ |
+LL | pub struct Map<S, F> {
+ | --------------------
+ | |
+ | method `filterx` not found for this struct
+ | doesn't satisfy `_: StreamExt`
+...
+LL | let filter = map.filterx(|x: &_| true);
+ | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>` due to unsatisfied trait bounds
+ |
+note: the following trait bounds were not satisfied:
+ `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
+ `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
+ `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
+ --> $DIR/issue-30786.rs:96:50
+ |
+LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
+ | --------- - ^^^^^^ unsatisfied trait bound introduced here
+help: one of the expressions' fields has a method of the same name
+ |
+LL | let filter = map.stream.filterx(|x: &_| true);
+ | +++++++
+
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied
+ --> $DIR/issue-30786.rs:130:24
+ |
+LL | pub struct Filter<S, F> {
+ | -----------------------
+ | |
+ | method `countx` not found for this struct
+ | doesn't satisfy `_: StreamExt`
+...
+LL | let count = filter.countx();
+ | ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds
+ |
+note: the following trait bounds were not satisfied:
+ `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
+ `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
+ `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
+ --> $DIR/issue-30786.rs:96:50
+ |
+LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
+ | --------- - ^^^^^^ unsatisfied trait bound introduced here
+help: one of the expressions' fields has a method of the same name
+ |
+LL | let count = filter.stream.countx();
+ | +++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs
new file mode 100644
index 000000000..4a09f4be1
--- /dev/null
+++ b/src/test/ui/hrtb/issue-46989.rs
@@ -0,0 +1,40 @@
+// Regression test for #46989:
+//
+// In the move to universes, this test started passing.
+// It is not necessarily WRONG to do so, but it was a bit
+// surprising. The reason that it passed is that when we were
+// asked to prove that
+//
+// for<'a> fn(&'a i32): Foo
+//
+// we were able to use the impl below to prove
+//
+// fn(&'empty i32): Foo
+//
+// and then we were able to prove that
+//
+// fn(&'empty i32) = for<'a> fn(&'a i32)
+//
+// This last fact is somewhat surprising, but essentially "falls out"
+// from handling variance correctly. In particular, consider the subtyping
+// relations. First:
+//
+// fn(&'empty i32) <: for<'a> fn(&'a i32)
+//
+// This holds because -- intuitively -- a fn that takes a reference but doesn't use
+// it can be given a reference with any lifetime. Similarly, the opposite direction:
+//
+// for<'a> fn(&'a i32) <: fn(&'empty i32)
+//
+// holds because 'a can be instantiated to 'empty.
+
+trait Foo {}
+
+impl<A> Foo for fn(A) {}
+
+fn assert_foo<T: Foo>() {}
+
+fn main() {
+ assert_foo::<fn(&i32)>();
+ //~^ ERROR implementation of `Foo` is not general enough
+}
diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr
new file mode 100644
index 000000000..309e1a676
--- /dev/null
+++ b/src/test/ui/hrtb/issue-46989.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Foo` is not general enough
+ --> $DIR/issue-46989.rs:38:5
+ |
+LL | assert_foo::<fn(&i32)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)`
+ = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/issue-57639.rs b/src/test/ui/hrtb/issue-57639.rs
new file mode 100644
index 000000000..392e7233b
--- /dev/null
+++ b/src/test/ui/hrtb/issue-57639.rs
@@ -0,0 +1,29 @@
+// Regression test for #57639:
+//
+// In the move to universes, this test stopped working. The problem
+// was that when the trait solver was asked to prove `for<'a> T::Item:
+// Foo<'a>` as part of WF checking, it wound up "eagerly committing"
+// to the where clause, which says that `T::Item: Foo<'a>`, but it
+// should instead have been using the bound found in the trait
+// declaration. Pre-universe, this used to work out ok because we got
+// "eager errors" due to the leak check.
+//
+// See [this comment on GitHub][c] for more details.
+//
+// check-pass
+//
+// [c]: https://github.com/rust-lang/rust/issues/57639#issuecomment-455685861
+
+trait Foo<'a> {}
+
+trait Bar {
+ type Item: for<'a> Foo<'a>;
+}
+
+fn foo<'a, T>(_: T)
+where
+ T: Bar,
+ T::Item: Foo<'a>,
+{}
+
+fn main() { }
diff --git a/src/test/ui/hrtb/issue-58451.rs b/src/test/ui/hrtb/issue-58451.rs
new file mode 100644
index 000000000..f36d549e4
--- /dev/null
+++ b/src/test/ui/hrtb/issue-58451.rs
@@ -0,0 +1,13 @@
+// Regression test for #58451:
+//
+// Error reporting here encountered an ICE in the shift to universes.
+
+fn f<I>(i: I)
+where
+ I: IntoIterator,
+ I::Item: for<'a> Into<&'a ()>,
+{}
+
+fn main() {
+ f(&[f()]); //~ ERROR this function takes 1 argument
+}
diff --git a/src/test/ui/hrtb/issue-58451.stderr b/src/test/ui/hrtb/issue-58451.stderr
new file mode 100644
index 000000000..22ba63c3e
--- /dev/null
+++ b/src/test/ui/hrtb/issue-58451.stderr
@@ -0,0 +1,19 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+ --> $DIR/issue-58451.rs:12:9
+ |
+LL | f(&[f()]);
+ | ^-- an argument is missing
+ |
+note: function defined here
+ --> $DIR/issue-58451.rs:5:4
+ |
+LL | fn f<I>(i: I)
+ | ^ ----
+help: provide the argument
+ |
+LL | f(&[f(/* value */)]);
+ | ~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.rs b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs
new file mode 100644
index 000000000..80f099ce3
--- /dev/null
+++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.rs
@@ -0,0 +1,50 @@
+trait T0<'a, A> {
+ type O;
+}
+
+struct L<T> {
+ f: T,
+}
+
+// explicitly named variants of what one would normally denote by the
+// unit type `()`. Why do this? So that we can differentiate them in
+// the diagnostic output.
+struct Unit1;
+struct Unit2;
+struct Unit3;
+struct Unit4;
+
+impl<'a, A, T> T0<'a, A> for L<T>
+where
+ T: FnMut(A) -> Unit3,
+{
+ type O = T::Output;
+}
+
+trait T1: for<'r> Ty<'r> {
+ fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1
+ where
+ F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
+ {
+ unimplemented!();
+ }
+}
+
+trait Ty<'a> {
+ type V;
+}
+
+fn main() {
+ let v = Unit2.m(
+ //~^ ERROR type mismatch
+ L {
+ //~^ ERROR type mismatch
+ f : |x| { drop(x); Unit4 }
+ });
+}
+
+impl<'a> Ty<'a> for Unit2 {
+ type V = &'a u8;
+}
+
+impl T1 for Unit2 {}
diff --git a/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr
new file mode 100644
index 000000000..79ef56b9f
--- /dev/null
+++ b/src/test/ui/hrtb/issue-62203-hrtb-ice.stderr
@@ -0,0 +1,53 @@
+error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
+ --> $DIR/issue-62203-hrtb-ice.rs:38:19
+ |
+LL | let v = Unit2.m(
+ | ^ type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
+ |
+note: expected this to be `<_ as Ty<'_>>::V`
+ --> $DIR/issue-62203-hrtb-ice.rs:21:14
+ |
+LL | type O = T::Output;
+ | ^^^^^^^^^
+ = note: expected associated type `<_ as Ty<'_>>::V`
+ found struct `Unit4`
+ = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` or calling a method that returns `<_ as Ty<'_>>::V`
+ = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+note: required by a bound in `T1::m`
+ --> $DIR/issue-62203-hrtb-ice.rs:27:51
+ |
+LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1
+ | - required by a bound in this
+LL | where
+LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
+ | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
+
+error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20] as FnOnce<((&'r u8,),)>>::Output == Unit3`
+ --> $DIR/issue-62203-hrtb-ice.rs:40:9
+ |
+LL | let v = Unit2.m(
+ | - required by a bound introduced by this call
+LL |
+LL | / L {
+LL | |
+LL | | f : |x| { drop(x); Unit4 }
+LL | | });
+ | |_________^ expected struct `Unit3`, found struct `Unit4`
+ |
+note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:20]>`
+ --> $DIR/issue-62203-hrtb-ice.rs:17:16
+ |
+LL | impl<'a, A, T> T0<'a, A> for L<T>
+ | ^^^^^^^^^ ^^^^
+note: required by a bound in `T1::m`
+ --> $DIR/issue-62203-hrtb-ice.rs:27:12
+ |
+LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1
+ | - required by a bound in this
+LL | where
+LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/hrtb/issue-88446.rs b/src/test/ui/hrtb/issue-88446.rs
new file mode 100644
index 000000000..571b85317
--- /dev/null
+++ b/src/test/ui/hrtb/issue-88446.rs
@@ -0,0 +1,35 @@
+// check-pass
+
+trait Yokeable<'a> {
+ type Output: 'a;
+}
+impl<'a> Yokeable<'a> for () {
+ type Output = ();
+}
+
+trait DataMarker<'data> {
+ type Yokeable: for<'a> Yokeable<'a>;
+}
+impl<'data> DataMarker<'data> for () {
+ type Yokeable = ();
+}
+
+struct DataPayload<'data, M>(&'data M);
+
+impl DataPayload<'static, ()> {
+ pub fn map_project_with_capture<M2, T>(
+ _: for<'a> fn(
+ capture: T,
+ std::marker::PhantomData<&'a ()>,
+ ) -> <M2::Yokeable as Yokeable<'a>>::Output,
+ ) -> DataPayload<'static, M2>
+ where
+ M2: DataMarker<'static>,
+ {
+ todo!()
+ }
+}
+
+fn main() {
+ let _: DataPayload<()> = DataPayload::<()>::map_project_with_capture::<_, &()>(|_, _| todo!());
+}
diff --git a/src/test/ui/hrtb/issue-90177.rs b/src/test/ui/hrtb/issue-90177.rs
new file mode 100644
index 000000000..b151a9d3a
--- /dev/null
+++ b/src/test/ui/hrtb/issue-90177.rs
@@ -0,0 +1,32 @@
+// check-pass
+
+trait Base<'f> {
+ type Assoc;
+
+ fn do_something(&self);
+}
+
+trait ForAnyLifetime: for<'f> Base<'f> {}
+
+impl<T> ForAnyLifetime for T where T: for<'f> Base<'f> {}
+
+trait CanBeDynamic: ForAnyLifetime + for<'f> Base<'f, Assoc = ()> {}
+
+fn foo(a: &dyn CanBeDynamic) {
+ a.do_something();
+}
+
+struct S;
+
+impl<'a> Base<'a> for S {
+ type Assoc = ();
+
+ fn do_something(&self) {}
+}
+
+impl CanBeDynamic for S {}
+
+fn main() {
+ let s = S;
+ foo(&s);
+}
diff --git a/src/test/ui/hrtb/issue-95034.rs b/src/test/ui/hrtb/issue-95034.rs
new file mode 100644
index 000000000..d8edbe7e5
--- /dev/null
+++ b/src/test/ui/hrtb/issue-95034.rs
@@ -0,0 +1,98 @@
+// known-bug: #95034
+// failure-status: 101
+// compile-flags: --edition=2021 --crate-type=lib
+// rustc-env:RUST_BACKTRACE=0
+
+// normalize-stderr-test "thread 'rustc' panicked.*" -> "thread 'rustc' panicked"
+// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
+// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
+// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
+// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
+// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
+// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
+// normalize-stderr-test "query stack during panic:\n" -> ""
+// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
+// normalize-stderr-test "end of query stack\n" -> ""
+// normalize-stderr-test "#.*\n" -> ""
+
+// This should not ICE.
+
+// Refer to the issue for more minimized versions.
+
+use std::{
+ future::Future,
+ marker::PhantomData,
+ pin::Pin,
+ task::{Context, Poll},
+};
+
+mod object {
+ use super::*;
+
+ pub trait Object<'a> {
+ type Error;
+ type Future: Future<Output = Self>;
+ fn create() -> Self::Future;
+ }
+
+ impl<'a> Object<'a> for u8 {
+ type Error = ();
+ type Future = Pin<Box<dyn Future<Output = Self>>>;
+ fn create() -> Self::Future {
+ unimplemented!()
+ }
+ }
+
+ impl<'a, E, A: Object<'a, Error = E>> Object<'a> for (A,) {
+ type Error = ();
+ type Future = CustomFut<'a, E, A>;
+ fn create() -> Self::Future {
+ unimplemented!()
+ }
+ }
+
+ pub struct CustomFut<'f, E, A: Object<'f, Error = E>> {
+ ph: PhantomData<(A::Future,)>,
+ }
+
+ impl<'f, E, A: Object<'f, Error = E>> Future for CustomFut<'f, E, A> {
+ type Output = (A,);
+ fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
+ unimplemented!()
+ }
+ }
+}
+
+mod async_fn {
+ use super::*;
+
+ pub trait AsyncFn {
+ type Future: Future<Output = ()>;
+ fn call(&self) -> Self::Future;
+ }
+
+ impl<F, Fut> AsyncFn for F
+ where
+ F: Fn() -> Fut,
+ Fut: Future<Output = ()>,
+ {
+ type Future = Fut;
+ fn call(&self) -> Self::Future {
+ (self)()
+ }
+ }
+}
+
+pub async fn test() {
+ use self::{async_fn::AsyncFn, object::Object};
+
+ async fn create<T: Object<'static>>() {
+ T::create().await;
+ }
+
+ async fn call_async_fn(inner: impl AsyncFn) {
+ inner.call().await;
+ }
+
+ call_async_fn(create::<(u8,)>).await;
+}
diff --git a/src/test/ui/hrtb/issue-95034.stderr b/src/test/ui/hrtb/issue-95034.stderr
new file mode 100644
index 000000000..1d8329142
--- /dev/null
+++ b/src/test/ui/hrtb/issue-95034.stderr
@@ -0,0 +1 @@
+thread 'rustc' panicked
diff --git a/src/test/ui/hrtb/issue-95230.rs b/src/test/ui/hrtb/issue-95230.rs
new file mode 100644
index 000000000..92c506eab
--- /dev/null
+++ b/src/test/ui/hrtb/issue-95230.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+pub struct Bar
+where
+ for<'a> &'a mut Self:;
+
+fn main() {}