summaryrefslogtreecommitdiffstats
path: root/src/test/ui/higher-rank-trait-bounds
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/higher-rank-trait-bounds
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 'src/test/ui/higher-rank-trait-bounds')
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs29
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs16
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs27
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs27
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs28
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-parse.rs36
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs25
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs13
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs14
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs26
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs25
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs46
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs11
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs7
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr14
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-59311.rs22
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-59311.stderr18
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-60283.rs20
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs13
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs31
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs30
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs88
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs33
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs32
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr17
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs39
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs27
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs77
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs31
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr79
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs51
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr79
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs30
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs15
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs71
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs21
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs21
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs19
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr25
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs32
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr63
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs44
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs43
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs37
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs31
45 files changed, 1483 insertions, 0 deletions
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs
new file mode 100644
index 000000000..cc766c060
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs
@@ -0,0 +1,29 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Test that we handle binder levels in object types correctly.
+// Initially, the reference to `'tcx` in the object type
+// `&Typer<'tcx>` was getting an incorrect binder level, yielding
+// weird compilation ICEs and so forth.
+
+// pretty-expanded FIXME #23616
+
+trait Typer<'tcx> {
+ fn method(&self, data: &'tcx isize) -> &'tcx isize { data }
+}
+
+struct Tcx<'tcx> {
+ fields: &'tcx isize
+}
+
+impl<'tcx> Typer<'tcx> for Tcx<'tcx> {
+}
+
+fn g<'tcx>(typer: &dyn Typer<'tcx>) {
+}
+
+fn check_static_type<'x>(tcx: &Tcx<'x>) {
+ g(tcx)
+}
+
+fn main() { }
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs
new file mode 100644
index 000000000..8431226a3
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+trait Typer<'tcx> {
+ fn method(&self, data: &'tcx isize) -> &'tcx isize { data }
+ fn dummy(&self) { }
+}
+
+fn g<F>(_: F) where F: FnOnce(&dyn Typer) {}
+
+fn h() {
+ g(|typer| typer.dummy())
+}
+
+fn main() { }
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs
new file mode 100644
index 000000000..ff84ad9d2
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs
@@ -0,0 +1,27 @@
+// run-pass
+// A basic test of using a higher-ranked trait bound.
+
+
+trait FnLike<A,R> {
+ fn call(&self, arg: A) -> R;
+}
+
+type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b;
+
+struct Identity;
+
+impl<'a, T> FnLike<&'a T, &'a T> for Identity {
+ fn call(&self, arg: &'a T) -> &'a T {
+ arg
+ }
+}
+
+fn call_repeatedly(f: &FnObject) {
+ let x = 3;
+ let y = f.call(&x);
+ assert_eq!(3, *y);
+}
+
+fn main() {
+ call_repeatedly(&Identity);
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs
new file mode 100644
index 000000000..afab9986c
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs
@@ -0,0 +1,27 @@
+// run-pass
+// A basic test of using a higher-ranked trait bound.
+
+
+trait FnLike<A,R> {
+ fn call(&self, arg: A) -> R;
+}
+
+struct Identity;
+
+impl<'a, T> FnLike<&'a T, &'a T> for Identity {
+ fn call(&self, arg: &'a T) -> &'a T {
+ arg
+ }
+}
+
+fn call_repeatedly<F>(f: F)
+ where F : for<'a> FnLike<&'a isize, &'a isize>
+{
+ let x = 3;
+ let y = f.call(&x);
+ assert_eq!(3, *y);
+}
+
+fn main() {
+ call_repeatedly(Identity);
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs
new file mode 100644
index 000000000..04519f116
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs
@@ -0,0 +1,28 @@
+// run-pass
+// Test that we handle binder levels correctly when checking whether a
+// type can implement `Copy`. In particular, we had a bug where we failed to
+// liberate the late-bound regions from the impl, and thus wound up
+// searching for an impl of `for<'tcx> Foo<&'tcx T>`. The impl that
+// exists however is `impl<T> Copy for Foo<T>` and the current rules
+// did not consider that a match (something I would like to revise in
+// a later PR).
+
+#![allow(dead_code)]
+
+use std::marker::PhantomData;
+
+#[derive(Copy, Clone)]
+struct Foo<T> { x: T }
+
+type Ty<'tcx> = &'tcx TyS<'tcx>;
+
+enum TyS<'tcx> {
+ Boop(PhantomData<*mut &'tcx ()>)
+}
+
+#[derive(Copy, Clone)]
+enum Bar<'tcx> {
+ Baz(Foo<Ty<'tcx>>)
+}
+
+fn main() { }
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-parse.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-parse.rs
new file mode 100644
index 000000000..1fab9758c
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-parse.rs
@@ -0,0 +1,36 @@
+// run-pass
+// Test that we can parse all the various places that a `for` keyword
+// can appear representing universal quantification.
+
+// pretty-expanded FIXME #23616
+
+#![allow(unused_variables)]
+#![allow(dead_code)]
+
+trait Get<A,R> {
+ fn get(&self, arg: A) -> R;
+}
+
+// Parse HRTB with explicit `for` in a where-clause:
+
+fn foo00<T>(t: T)
+ where T : for<'a> Get<&'a i32, &'a i32>
+{
+}
+
+fn foo01<T: for<'a> Get<&'a i32, &'a i32>>(t: T)
+{
+}
+
+// Parse HRTB with explicit `for` in various sorts of types:
+
+fn foo10(t: Box<dyn for<'a> Get<i32, i32>>) { }
+fn foo11(t: Box<dyn for<'a> Fn(i32) -> i32>) { }
+
+fn foo20(t: for<'a> fn(i32) -> i32) { }
+fn foo21(t: for<'a> unsafe fn(i32) -> i32) { }
+fn foo22(t: for<'a> extern "C" fn(i32) -> i32) { }
+fn foo23(t: for<'a> unsafe extern "C" fn(i32) -> i32) { }
+
+fn main() {
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs
new file mode 100644
index 000000000..42247798f
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs
@@ -0,0 +1,25 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// pretty-expanded FIXME #23616
+
+// Test that `F : Fn(isize) -> isize + Send` is interpreted as two
+// distinct bounds on `F`.
+
+fn foo1<F>(f: F)
+ where F : FnOnce(isize) -> isize + Send
+{
+ bar(f);
+}
+
+fn foo2<F>(f: F)
+ where F : FnOnce(isize) -> isize + Send
+{
+ baz(f);
+}
+
+fn bar<F:Send>(f: F) { }
+
+fn baz<F:FnOnce(isize) -> isize>(f: F) { }
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs
new file mode 100644
index 000000000..6834c392d
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs
@@ -0,0 +1,13 @@
+// run-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+// Test that `Fn(isize) -> isize + 'static` parses as `(Fn(isize) -> isize) +
+// 'static` and not `Fn(isize) -> (isize + 'static)`. The latter would
+// cause a compilation error. Issue #18772.
+
+fn adder(y: isize) -> Box<dyn Fn(isize) -> isize + 'static> {
+ Box::new(move |x| y + x)
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs
new file mode 100644
index 000000000..b97fdf4df
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![allow(dead_code)]
+// A basic test of using a higher-ranked trait bound.
+
+// pretty-expanded FIXME #23616
+
+trait FnLike<A,R> {
+ fn call(&self, arg: A) -> R;
+}
+
+type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b;
+
+fn main() {
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs
new file mode 100644
index 000000000..d8c726cdd
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs
@@ -0,0 +1,26 @@
+// run-pass
+// A basic test of using a higher-ranked trait bound.
+
+trait FnLike<A,R> {
+ fn call(&self, arg: A) -> R;
+}
+
+type FnObject<'b> = dyn for<'a> FnLike<(&'a i32,), &'a i32> + 'b;
+
+struct Identity;
+
+impl<'a, T> FnLike<(&'a T,), &'a T> for Identity {
+ fn call(&self, (arg,): (&'a T,)) -> &'a T {
+ arg
+ }
+}
+
+fn call_repeatedly(f: &FnObject) {
+ let x = 3;
+ let y = f.call((&x,));
+ assert_eq!(3, *y);
+}
+
+fn main() {
+ call_repeatedly(&Identity);
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs
new file mode 100644
index 000000000..41ebb3f5a
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs
@@ -0,0 +1,25 @@
+// run-pass
+#![allow(dead_code)]
+// Test that `&PrinterSupport`, which is really short for `&'a
+// PrinterSupport<'b>`, gets properly expanded when it appears in a
+// closure type. This used to result in messed up De Bruijn indices.
+
+// pretty-expanded FIXME #23616
+
+trait PrinterSupport<'ast> {
+ fn ast_map(&self) -> Option<&'ast usize> { None }
+}
+
+struct NoAnn<'ast> {
+ f: Option<&'ast usize>
+}
+
+impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
+}
+
+fn foo<'ast, G>(f: Option<&'ast usize>, g: G) where G: FnOnce(&dyn PrinterSupport) {
+ let annotation = NoAnn { f: f };
+ g(&annotation)
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs
new file mode 100644
index 000000000..88d396101
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs
@@ -0,0 +1,46 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Test what happens when a HR obligation is applied to an impl with
+// "outlives" bounds. Currently we're pretty conservative here; this
+// will probably improve in time.
+
+trait Foo<X> {
+ fn foo(&self, x: X) { }
+}
+
+fn want_foo<T>()
+ where T : for<'a> Foo<&'a isize>
+{
+}
+
+// Expressed as a where clause
+
+struct SomeStruct<X> {
+ x: X
+}
+
+impl<'a,X> Foo<&'a isize> for SomeStruct<X>
+ where X : 'a
+{
+}
+
+fn one() {
+ want_foo::<SomeStruct<usize>>();
+}
+
+// Expressed as shorthand
+
+struct AnotherStruct<X> {
+ x: X
+}
+
+impl<'a,X:'a> Foo<&'a isize> for AnotherStruct<X>
+{
+}
+
+fn two() {
+ want_foo::<AnotherStruct<usize>>();
+}
+
+fn main() { }
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs
new file mode 100644
index 000000000..a4a8a5ac6
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs
@@ -0,0 +1,11 @@
+// run-pass
+// Test HRTB used with the `Fn` trait.
+
+fn foo<F:Fn(&isize)>(f: F) {
+ let x = 22;
+ f(&x);
+}
+
+fn main() {
+ foo(|x: &isize| println!("{}", *x));
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs
new file mode 100644
index 000000000..1a9bb2523
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs
@@ -0,0 +1,7 @@
+fn a() where for<T> T: Copy {}
+//~^ ERROR only lifetime parameters can be used in this context
+
+fn b() where for<const C: usize> [(); C]: Copy {}
+//~^ ERROR only lifetime parameters can be used in this context
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
new file mode 100644
index 000000000..f31aa5546
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
@@ -0,0 +1,14 @@
+error: only lifetime parameters can be used in this context
+ --> $DIR/hrtb-wrong-kind.rs:1:18
+ |
+LL | fn a() where for<T> T: Copy {}
+ | ^
+
+error: only lifetime parameters can be used in this context
+ --> $DIR/hrtb-wrong-kind.rs:4:24
+ |
+LL | fn b() where for<const C: usize> [(); C]: Copy {}
+ | ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-59311.rs b/src/test/ui/higher-rank-trait-bounds/issue-59311.rs
new file mode 100644
index 000000000..3ad548450
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/issue-59311.rs
@@ -0,0 +1,22 @@
+// Regression test for #59311. The test is taken from
+// rust-lang/rust/issues/71546#issuecomment-620638437
+// as they seem to have the same cause.
+
+// FIXME: It's not clear that this code ought to report
+// an error, but the regression test is here to ensure
+// that it does not ICE. See discussion on #74889 for details.
+
+pub trait T {
+ fn t<F: Fn()>(&self, _: F) {}
+}
+
+pub fn crash<V>(v: &V)
+where
+ for<'a> &'a V: T + 'static,
+{
+ v.t(|| {});
+ //~^ ERROR: higher-ranked lifetime error
+ //~| ERROR: higher-ranked lifetime error
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr
new file mode 100644
index 000000000..c01ab8e34
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr
@@ -0,0 +1,18 @@
+error: higher-ranked lifetime error
+ --> $DIR/issue-59311.rs:17:5
+ |
+LL | v.t(|| {});
+ | ^^^^^^^^^^
+ |
+ = note: could not prove `[closure@$DIR/issue-59311.rs:17:9: 17:11] well-formed`
+
+error: higher-ranked lifetime error
+ --> $DIR/issue-59311.rs:17:9
+ |
+LL | v.t(|| {});
+ | ^^^^^
+ |
+ = note: could not prove `for<'a> &'a V: 'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs
new file mode 100644
index 000000000..05315b3f9
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+pub trait Trait<'a> {
+ type Item;
+}
+
+impl<'a> Trait<'a> for () {
+ type Item = ();
+}
+
+pub fn foo<T, F>(_: T, _: F)
+where
+ T: for<'a> Trait<'a>,
+ F: for<'a> FnMut(<T as Trait<'a>>::Item),
+{
+}
+
+fn main() {
+ foo((), drop)
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs b/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs
new file mode 100644
index 000000000..92b7c5deb
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs
@@ -0,0 +1,13 @@
+// Regression test for #88586: a higher-ranked outlives bound on Self in a trait
+// definition caused an ICE when debug_assertions were enabled.
+//
+// Made to pass as part of fixing #98095.
+//
+// check-pass
+
+trait A where
+ for<'a> Self: 'a,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs
new file mode 100644
index 000000000..f255eac0c
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs
@@ -0,0 +1,31 @@
+// check-pass
+
+pub trait Foo<'a> {
+ type Bar;
+ fn foo(&'a self) -> Self::Bar;
+}
+
+impl<'a, 'b, T: 'a> Foo<'a> for &'b T {
+ type Bar = &'a T;
+ fn foo(&'a self) -> &'a T {
+ self
+ }
+}
+
+pub fn uncallable<T, F>(x: T, f: F)
+where
+ T: for<'a> Foo<'a>,
+ F: for<'a> Fn(<T as Foo<'a>>::Bar),
+{
+ f(x.foo());
+}
+
+pub fn catalyst(x: &i32) {
+ broken(x, |_| {})
+}
+
+pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
+ uncallable(x, |y| f(y));
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs
new file mode 100644
index 000000000..4d38cb19e
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+fn foo<T>(t: T) -> usize
+where
+ for<'a> &'a T: IntoIterator,
+ for<'a> <&'a T as IntoIterator>::IntoIter: ExactSizeIterator,
+{
+ t.into_iter().len()
+}
+
+fn main() {
+ foo::<Vec<u32>>(vec![]);
+}
+
+mod another {
+ use std::ops::Deref;
+
+ fn test<T, TDeref>()
+ where
+ T: Deref<Target = TDeref>,
+ TDeref: ?Sized,
+ for<'a> &'a TDeref: IntoIterator,
+ for<'a> <&'a TDeref as IntoIterator>::IntoIter: Clone,
+ {
+ }
+
+ fn main() {
+ test::<Vec<u8>, _>();
+ }
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
new file mode 100644
index 000000000..c6f29fa59
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
@@ -0,0 +1,88 @@
+// check-pass
+
+// FamilyType (GAT workaround)
+pub trait FamilyLt<'a> {
+ type Out;
+}
+
+struct RefMutFamily<T>(std::marker::PhantomData<T>, ());
+impl<'a, T: 'a> FamilyLt<'a> for RefMutFamily<T> {
+ type Out = &'a mut T;
+}
+
+pub trait Execute {
+ type E: Inject;
+ fn execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out);
+}
+
+pub trait Inject
+where
+ Self: Sized,
+{
+ type I: for<'a> FamilyLt<'a>;
+ fn inject(_: &()) -> <Self::I as FamilyLt>::Out;
+}
+
+impl<T: 'static> Inject for RefMutFamily<T> {
+ type I = Self;
+ fn inject(_: &()) -> <Self::I as FamilyLt>::Out {
+ unimplemented!()
+ }
+}
+
+// This struct is only used to give a hint to the compiler about the type `Q`
+struct Annotate<Q>(std::marker::PhantomData<Q>);
+impl<Q> Annotate<Q> {
+ fn new() -> Self {
+ Self(std::marker::PhantomData)
+ }
+}
+
+// This function annotate a closure so it can have Higher-Rank Lifetime Bounds
+//
+// See 'annotate' workaround: https://github.com/rust-lang/rust/issues/58052
+fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
+where
+ F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
+ Q: Inject + 'static,
+{
+ let wrapper: Wrapper<Q, F> = Wrapper(std::marker::PhantomData, func);
+ wrapper
+}
+
+struct Wrapper<Q, F>(std::marker::PhantomData<Q>, F);
+impl<Q, F> Execute for Wrapper<Q, F>
+ where
+ Q: Inject,
+ F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out),
+{
+ type E = Q;
+
+ fn execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out) {
+ (self.1)(value)
+ }
+}
+
+struct Task {
+ _processor: Box<dyn FnOnce()>,
+}
+
+// This function consume the closure
+fn task<P>(processor: P) -> Task
+where P: Execute + 'static {
+ Task {
+ _processor: Box::new(move || {
+ let q = P::E::inject(&());
+ processor.execute(q);
+ })
+ }
+}
+
+fn main() {
+ task(annotate(
+ Annotate::<RefMutFamily<usize>>::new(),
+ |value: &mut usize| {
+ *value = 2;
+ }
+ ));
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs
new file mode 100644
index 000000000..002054732
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs
@@ -0,0 +1,33 @@
+// check-pass
+
+use std::marker::PhantomData;
+
+trait Lt<'a> {
+ type T;
+}
+struct Id<T>(PhantomData<T>);
+impl<'a,T> Lt<'a> for Id<T> {
+ type T = T;
+}
+
+struct Ref<T>(PhantomData<T>) where T: ?Sized;
+impl<'a,T> Lt<'a> for Ref<T>
+where T: 'a + Lt<'a> + ?Sized
+{
+ type T = &'a T;
+}
+struct Mut<T>(PhantomData<T>) where T: ?Sized;
+impl<'a,T> Lt<'a> for Mut<T>
+where T: 'a + Lt<'a> + ?Sized
+{
+ type T = &'a mut T;
+}
+
+struct C<I,O>(for<'a> fn(<I as Lt<'a>>::T) -> O) where I: for<'a> Lt<'a>;
+
+
+fn main() {
+ let c = C::<Id<_>,_>(|()| 3);
+ c.0(());
+
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs
new file mode 100644
index 000000000..d84e30f49
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs
@@ -0,0 +1,32 @@
+trait ATC<'a> {
+ type Type: Sized;
+}
+
+trait WithDefault: for<'a> ATC<'a> {
+ fn with_default<F: for<'a> Fn(<Self as ATC<'a>>::Type)>(f: F);
+}
+
+fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(<T as ATC<'a>>::Type)>(
+ f: F,
+ x: <T as ATC<'b>>::Type,
+) {
+ f(x);
+}
+
+impl<'a> ATC<'a> for () {
+ type Type = Self;
+}
+
+impl WithDefault for () {
+ fn with_default<F: for<'a> Fn(<Self as ATC<'a>>::Type)>(f: F) {
+ // Errors with a bogus type mismatch.
+ //f(());
+ // Going through another generic function works fine.
+ call(f, ());
+ //~^ expected a
+ }
+}
+
+fn main() {
+ // <()>::with_default(|_| {});
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr
new file mode 100644
index 000000000..066bf431a
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr
@@ -0,0 +1,17 @@
+error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
+ --> $DIR/issue-62529-3.rs:25:9
+ |
+LL | call(f, ());
+ | ^^^^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
+ |
+ = note: expected a closure with arguments `((),)`
+ found a closure with arguments `(<_ as ATC<'a>>::Type,)`
+note: required by a bound in `call`
+ --> $DIR/issue-62529-3.rs:9:36
+ |
+LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(<T as ATC<'a>>::Type)>(
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs
new file mode 100644
index 000000000..8c2a59868
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs
@@ -0,0 +1,39 @@
+// check-pass
+
+use std::marker::PhantomData;
+use std::mem;
+
+trait Container<'a> {
+ type Root: 'a;
+}
+
+type RootOf<'a, T> = <T as Container<'a>>::Root;
+
+struct Test<'a, T> where T: Container<'a> {
+ pub root: T::Root,
+ marker: PhantomData<&'a mut &'a mut ()>,
+}
+
+impl<'a, 'b> Container<'b> for &'a str {
+ type Root = &'b str;
+}
+
+impl<'a, T> Test<'a, T> where T: for<'b> Container<'b> {
+ fn new(root: RootOf<'a, T>) -> Test<'a, T> {
+ Test {
+ root: root,
+ marker: PhantomData
+ }
+ }
+
+ fn with_mut<F, R>(&mut self, f: F) -> R where
+ F: for<'b> FnOnce(&'b mut RootOf<'b, T>) -> R {
+ f(unsafe { mem::transmute(&mut self.root) })
+ }
+}
+
+fn main() {
+ let val = "root";
+ let mut test: Test<&str> = Test::new(val);
+ test.with_mut(|_| { });
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs
new file mode 100644
index 000000000..03f257a02
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+pub struct Struct {}
+
+pub trait Trait<'a> {
+ type Assoc;
+
+ fn method() -> Self::Assoc;
+}
+
+impl<'a> Trait<'a> for Struct {
+ type Assoc = ();
+
+ fn method() -> Self::Assoc {}
+}
+
+pub fn function<F, T>(f: F)
+where
+ F: for<'a> FnOnce(<T as Trait<'a>>::Assoc),
+ T: for<'b> Trait<'b>,
+{
+ f(T::method());
+}
+
+fn main() {
+ function::<_, Struct>(|_| {});
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs
new file mode 100644
index 000000000..74a4785e4
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs
@@ -0,0 +1,77 @@
+// check-pass
+
+use std::cell::RefMut;
+
+fn main() {
+ StateMachine2::Init.resume();
+}
+
+enum StateMachine2<'a> {
+ Init,
+ #[allow(dead_code)] // match required for ICE
+ AfterTwoYields {
+ p: Backed<'a, *mut String>,
+ },
+}
+
+impl<'a> StateMachine2<'a> {
+ fn take(&self) -> Self {
+ StateMachine2::Init
+ }
+}
+
+impl<'a> StateMachine2<'a> {
+ fn resume(&mut self) -> () {
+ use StateMachine2::*;
+ match self.take() {
+ AfterTwoYields { p } => {
+ p.with(|_| {});
+ }
+ _ => panic!("Resume after completed."),
+ }
+ }
+}
+
+unsafe trait Unpack<'a> {
+ type Unpacked: 'a;
+
+ fn unpack(&self) -> Self::Unpacked {
+ unsafe { std::mem::transmute_copy(&self) }
+ }
+}
+
+unsafe trait Pack {
+ type Packed;
+
+ fn pack(&self) -> Self::Packed {
+ unsafe { std::mem::transmute_copy(&self) }
+ }
+}
+
+unsafe impl<'a> Unpack<'a> for String {
+ type Unpacked = String;
+}
+
+unsafe impl Pack for String {
+ type Packed = String;
+}
+
+unsafe impl<'a> Unpack<'a> for *mut String {
+ type Unpacked = &'a mut String;
+}
+
+unsafe impl<'a> Pack for &'a mut String {
+ type Packed = *mut String;
+}
+
+struct Backed<'a, U>(RefMut<'a, Option<String>>, U);
+
+impl<'a, 'b, U: Unpack<'b>> Backed<'a, U> {
+ fn with<F>(self, f: F) -> Backed<'a, ()>
+ where
+ F: for<'f> FnOnce(<U as Unpack<'f>>::Unpacked) -> (),
+ {
+ let result = f(self.1.unpack());
+ Backed(self.0, result)
+ }
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs
new file mode 100644
index 000000000..3ced40230
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs
@@ -0,0 +1,31 @@
+// check-pass
+
+pub trait MyTrait<'a> {
+ type Output: 'a;
+ fn gimme_value(&self) -> Self::Output;
+}
+
+pub struct MyStruct;
+
+impl<'a> MyTrait<'a> for MyStruct {
+ type Output = &'a usize;
+ fn gimme_value(&self) -> Self::Output {
+ unimplemented!()
+ }
+}
+
+fn meow<T, F>(t: T, f: F)
+where
+ T: for<'any> MyTrait<'any>,
+ F: for<'any2> Fn(<T as MyTrait<'any2>>::Output),
+{
+ let v = t.gimme_value();
+ f(v);
+}
+
+fn main() {
+ let struc = MyStruct;
+ meow(struc, |foo| {
+ println!("{:?}", foo);
+ })
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
new file mode 100644
index 000000000..0f38f8e32
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
@@ -0,0 +1,79 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-71955.rs:54:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `for<'r, 's> FnOnce<(&'r &'s str,)>`
+ found type `for<'r> FnOnce<(&'r &str,)>`
+note: this closure does not fulfill the lifetime requirements
+ --> $DIR/issue-71955.rs:54:24
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+ --> $DIR/issue-71955.rs:34:9
+ |
+LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-71955.rs:54:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `FnOnce<(&&str,)>`
+ found type `for<'r> FnOnce<(&'r &str,)>`
+note: this closure does not fulfill the lifetime requirements
+ --> $DIR/issue-71955.rs:54:24
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+ --> $DIR/issue-71955.rs:34:44
+ |
+LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
+ | ^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-71955.rs:58:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>`
+ found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
+note: this closure does not fulfill the lifetime requirements
+ --> $DIR/issue-71955.rs:58:24
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+ --> $DIR/issue-71955.rs:34:9
+ |
+LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-71955.rs:58:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected type `FnOnce<(&Wrapper<'_>,)>`
+ found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
+note: this closure does not fulfill the lifetime requirements
+ --> $DIR/issue-71955.rs:58:24
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+ --> $DIR/issue-71955.rs:34:44
+ |
+LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
+ | ^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
new file mode 100644
index 000000000..1d90226a3
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
@@ -0,0 +1,51 @@
+// check-fail
+#![feature(rustc_attrs)]
+
+trait Parser<'s> {
+ type Output;
+
+ fn call(&self, input: &'s str) -> (&'s str, Self::Output);
+}
+
+impl<'s, F, T> Parser<'s> for F
+where F: Fn(&'s str) -> (&'s str, T) {
+ type Output = T;
+ fn call(&self, input: &'s str) -> (&'s str, T) {
+ self(input)
+ }
+}
+
+fn foo<F1, F2>(
+ f1: F1,
+ base: &'static str,
+ f2: F2
+)
+where
+ F1: for<'a> Parser<'a>,
+ F2: FnOnce(&<F1 as Parser>::Output) -> bool
+{
+ let s: String = base.to_owned();
+ let str_ref = s.as_ref();
+ let (remaining, produced) = f1.call(str_ref);
+ assert!(f2(&produced));
+ assert_eq!(remaining.len(), 0);
+}
+
+struct Wrapper<'a>(&'a str);
+
+fn main() {
+ fn bar<'a>(s: &'a str) -> (&'a str, &'a str) {
+ (&s[..1], &s[..])
+ }
+
+ fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) {
+ (&s[..1], Wrapper(&s[..]))
+ }
+
+ foo(bar, "string", |s| s.len() == 5);
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ foo(baz, "string", |s| s.0.len() == 5);
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr
new file mode 100644
index 000000000..eebce827d
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr
@@ -0,0 +1,79 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-71955.rs:45:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected trait `for<'r, 's> FnOnce<(&'r &'s str,)>`
+ found trait `for<'r> FnOnce<(&'r &str,)>`
+note: this closure does not fulfill the lifetime requirements
+ --> $DIR/issue-71955.rs:45:24
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^
+note: the lifetime requirement is introduced here
+ --> $DIR/issue-71955.rs:25:9
+ |
+LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-71955.rs:45:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected trait `for<'r, 's> FnOnce<(&'r &'s str,)>`
+ found trait `for<'r> FnOnce<(&'r &str,)>`
+note: this closure does not fulfill the lifetime requirements
+ --> $DIR/issue-71955.rs:45:24
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^
+note: the lifetime requirement is introduced here
+ --> $DIR/issue-71955.rs:25:44
+ |
+LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
+ | ^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-71955.rs:48:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected trait `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>`
+ found trait `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
+note: this closure does not fulfill the lifetime requirements
+ --> $DIR/issue-71955.rs:48:24
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^
+note: the lifetime requirement is introduced here
+ --> $DIR/issue-71955.rs:25:9
+ |
+LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/issue-71955.rs:48:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected trait `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>`
+ found trait `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
+note: this closure does not fulfill the lifetime requirements
+ --> $DIR/issue-71955.rs:48:24
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^
+note: the lifetime requirement is introduced here
+ --> $DIR/issue-71955.rs:25:44
+ |
+LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
+ | ^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs
new file mode 100644
index 000000000..93ccb4268
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+use std::marker::PhantomData;
+
+trait A<'a> {
+ type B;
+ fn b(self) -> Self::B;
+}
+
+struct T;
+struct S<'a>(PhantomData<&'a ()>);
+
+impl<'a> A<'a> for T {
+ type B = S<'a>;
+ fn b(self) -> Self::B {
+ S(PhantomData)
+ }
+}
+
+fn s<TT, F>(t: TT, f: F)
+where
+ TT: for<'a> A<'a>,
+ F: for<'a> FnOnce(<TT as A<'a>>::B)
+{
+ f(t.b());
+}
+
+fn main() {
+ s(T, |_| {});
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs
new file mode 100644
index 000000000..583470080
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+use std::ops::Deref;
+
+struct Data {
+ boxed: Box<&'static i32>
+}
+
+impl Data {
+ fn use_data(&self, user: impl for <'a> FnOnce(<Box<&'a i32> as Deref>::Target)) {
+ user(*self.boxed)
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs
new file mode 100644
index 000000000..00a866f22
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs
@@ -0,0 +1,71 @@
+// build-pass
+// edition:2018
+
+type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output=T>>>;
+
+fn main() {
+ f();
+}
+
+async fn f() {
+ run("dependency").await;
+}
+
+struct InMemoryStorage;
+
+struct User<'dep> {
+ dep: &'dep str,
+}
+
+impl<'a> StorageRequest<InMemoryStorage> for SaveUser<'a> {
+ fn execute(&self) -> BoxFuture<Result<(), String>> {
+ todo!()
+ }
+}
+
+trait Storage {
+ type Error;
+}
+
+impl Storage for InMemoryStorage {
+ type Error = String;
+}
+
+trait StorageRequestReturnType {
+ type Output;
+}
+
+trait StorageRequest<S: Storage>: StorageRequestReturnType {
+ fn execute(
+ &self,
+ ) -> BoxFuture<Result<<Self as StorageRequestReturnType>::Output, <S as Storage>::Error>>;
+}
+
+struct SaveUser<'a> {
+ name: &'a str,
+}
+
+impl<'a> StorageRequestReturnType for SaveUser<'a> {
+ type Output = ();
+}
+
+impl<'dep> User<'dep> {
+ async fn save<S>(self)
+ where
+ S: Storage,
+ for<'a> SaveUser<'a>: StorageRequest<S>,
+ {
+ SaveUser { name: "Joe" }
+ .execute()
+ .await;
+ }
+}
+
+async fn run<S>(dep: &str)
+where
+ S: Storage,
+ for<'a> SaveUser<'a>: StorageRequest<S>,
+ for<'a> SaveUser<'a>: StorageRequestReturnType,
+{
+ User { dep }.save().await;
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs
new file mode 100644
index 000000000..6316ceea1
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+trait Bar {
+ type Type;
+}
+struct Foo<'a>(&'a ());
+impl<'a> Bar for Foo<'a> {
+ type Type = ();
+}
+
+fn func<'a>(_: <Foo<'a> as Bar>::Type) {}
+fn assert_is_func<A>(_: fn(A)) {}
+
+fn test()
+where
+ for<'a> <Foo<'a> as Bar>::Type: Sized,
+{
+ assert_is_func(func);
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs
new file mode 100644
index 000000000..f6ab9c203
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+pub trait Indexable {
+ type Idx;
+}
+impl Indexable for u8 {
+ type Idx = u8;
+}
+impl Indexable for u16 {
+ type Idx = u16;
+}
+
+pub trait Indexer<T: Indexable>: std::ops::Index<T::Idx, Output = T> {}
+
+trait StoreIndex: Indexer<u8> + Indexer<u16> {}
+
+fn foo(st: &impl StoreIndex) -> &dyn StoreIndex {
+ st as &dyn StoreIndex
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
new file mode 100644
index 000000000..172bf218c
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
@@ -0,0 +1,19 @@
+#![feature(unboxed_closures)]
+
+trait SomeTrait<'a> {
+ type Associated;
+}
+
+fn give_me_ice<T>() {
+ callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+ //~^ ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277]
+ //~| ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277]
+}
+
+fn callee<T: Fn<(&'static (),)>>() {
+ println!("{}", std::any::type_name::<<T as FnOnce<(&'static (),)>>::Output>());
+}
+
+fn main() {
+ give_me_ice::<()>();
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
new file mode 100644
index 000000000..ecca4b999
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied
+ --> $DIR/issue-85455.rs:8:5
+ |
+LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'r> SomeTrait<'r>` is not implemented for `T`
+ |
+help: consider restricting type parameter `T`
+ |
+LL | fn give_me_ice<T: for<'r> SomeTrait<'r>>() {
+ | +++++++++++++++++++++++
+
+error[E0277]: the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied
+ --> $DIR/issue-85455.rs:8:14
+ |
+LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'r> SomeTrait<'r>` is not implemented for `T`
+ |
+help: consider restricting type parameter `T`
+ |
+LL | fn give_me_ice<T: for<'r> SomeTrait<'r>>() {
+ | +++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs
new file mode 100644
index 000000000..fffb54f86
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs
@@ -0,0 +1,32 @@
+trait BufferMut {}
+struct Ctx<D>(D);
+
+trait BufferUdpStateContext<B> {}
+impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
+
+trait StackContext
+where
+ Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
+{
+ type Dispatcher;
+}
+
+trait TimerContext {
+ type Handler;
+}
+impl<C> TimerContext for C
+where
+ C: StackContext,
+ //~^ ERROR: is not satisfied [E0277]
+{
+ type Handler = Ctx<C::Dispatcher>;
+ //~^ ERROR: is not satisfied [E0277]
+}
+
+struct EthernetWorker<C>(C)
+where
+ Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>;
+impl<C> EthernetWorker<C> {}
+//~^ ERROR: is not satisfied [E0277]
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
new file mode 100644
index 000000000..a6858154d
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
@@ -0,0 +1,63 @@
+error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
+ --> $DIR/issue-89118.rs:19:8
+ |
+LL | C: StackContext,
+ | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
+ |
+note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
+ --> $DIR/issue-89118.rs:5:23
+ |
+LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ ^
+note: required by a bound in `StackContext`
+ --> $DIR/issue-89118.rs:9:14
+ |
+LL | trait StackContext
+ | ------------ required by a bound in this
+LL | where
+LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
+
+error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
+ --> $DIR/issue-89118.rs:29:9
+ |
+LL | impl<C> EthernetWorker<C> {}
+ | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
+ |
+note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
+ --> $DIR/issue-89118.rs:5:23
+ |
+LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ ^
+note: required by a bound in `EthernetWorker`
+ --> $DIR/issue-89118.rs:28:14
+ |
+LL | struct EthernetWorker<C>(C)
+ | -------------- required by a bound in this
+LL | where
+LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker`
+
+error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
+ --> $DIR/issue-89118.rs:22:20
+ |
+LL | type Handler = Ctx<C::Dispatcher>;
+ | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
+ |
+note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
+ --> $DIR/issue-89118.rs:5:23
+ |
+LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ ^
+note: required by a bound in `StackContext`
+ --> $DIR/issue-89118.rs:9:14
+ |
+LL | trait StackContext
+ | ------------ required by a bound in this
+LL | where
+LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs
new file mode 100644
index 000000000..f7e467b37
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs
@@ -0,0 +1,44 @@
+// check-pass
+
+#![allow(unused)]
+
+trait MiniYokeable<'a> {
+ type Output;
+}
+
+struct MiniYoke<Y: for<'a> MiniYokeable<'a>> {
+ pub yokeable: Y,
+}
+
+fn map_project_broken<Y, P>(
+ source: MiniYoke<Y>,
+ f: impl for<'a> FnOnce(
+ <Y as MiniYokeable<'a>>::Output,
+ core::marker::PhantomData<&'a ()>,
+ ) -> <P as MiniYokeable<'a>>::Output,
+) -> MiniYoke<P>
+where
+ Y: for<'a> MiniYokeable<'a>,
+ P: for<'a> MiniYokeable<'a>
+{
+ unimplemented!()
+}
+
+struct Bar<'a> {
+ string_1: &'a str,
+ string_2: &'a str,
+}
+
+impl<'a> MiniYokeable<'a> for Bar<'static> {
+ type Output = Bar<'a>;
+}
+
+impl<'a> MiniYokeable<'a> for &'static str {
+ type Output = &'a str;
+}
+
+fn demo_broken(bar: MiniYoke<Bar<'static>>) -> MiniYoke<&'static str> {
+ map_project_broken(bar, |bar, _| bar.string_1)
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs
new file mode 100644
index 000000000..e150ecfe9
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs
@@ -0,0 +1,43 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+use std::marker::PhantomData;
+
+trait Family: Sized {
+ type Item<'a>;
+
+ fn apply_all<F>(&self, f: F)
+ where
+ F: FamilyItemFn<Self> { }
+}
+
+struct Array<T>(PhantomData<T>);
+
+impl<T: 'static> Family for Array<T> {
+ type Item<'a> = &'a T;
+}
+
+trait FamilyItemFn<T: Family> {
+ fn apply(&self, item: T::Item<'_>);
+}
+
+impl<T, F> FamilyItemFn<T> for F
+where
+ T: Family,
+ for<'a> F: Fn(T::Item<'a>)
+{
+ fn apply(&self, item: T::Item<'_>) {
+ (*self)(item);
+ }
+}
+
+fn process<T: 'static>(array: Array<T>) {
+ // Works
+ array.apply_all(|x: &T| { });
+
+ // ICE: NoSolution
+ array.apply_all(|x: <Array<T> as Family>::Item<'_>| { });
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs
new file mode 100644
index 000000000..18b7f3834
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs
@@ -0,0 +1,37 @@
+//check-pass
+
+#![feature(generic_associated_types)]
+
+trait Yokeable<'a>: 'static {
+ type Output: 'a;
+}
+
+trait IsCovariant<'a> {}
+
+struct Yoke<Y: for<'a> Yokeable<'a>> {
+ data: Y,
+}
+
+impl<Y: for<'a> Yokeable<'a>> Yoke<Y> {
+ fn project<Y2: for<'a> Yokeable<'a>>(&self, _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ())
+ -> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> {
+
+ unimplemented!()
+ }
+}
+
+fn _upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where
+ Y: for<'a> Yokeable<'a>,
+ for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a>
+ {
+ x.project(|data, _| {
+ Box::new(data)
+ })
+}
+
+
+impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> {
+ type Output = Box<dyn IsCovariant<'a> + 'a>;
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs
new file mode 100644
index 000000000..ffd6857d8
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs
@@ -0,0 +1,31 @@
+// check-pass
+
+trait Variable<'a> {
+ type Type;
+}
+
+impl Variable<'_> for () {
+ type Type = ();
+}
+
+fn check<F, T>(_: F)
+where
+ F: Fn(T), // <- if removed, all fn_* then require type annotations
+ F: for<'a> Fn(<T as Variable<'a>>::Type),
+ T: for<'a> Variable<'a>,
+{
+}
+
+fn test(arg: impl Fn(())) {
+ fn fn_1(_: ()) {}
+ let fn_2 = |_: ()| ();
+ let fn_3 = |a| fn_1(a);
+ let fn_4 = arg;
+
+ check(fn_1); // Error
+ check(fn_2); // Ok
+ check(fn_3); // Ok
+ check(fn_4); // Error
+}
+
+fn main() {}