about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs34
-rw-r--r--src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr2
-rw-r--r--src/test/ui/closures/print/closure-print-generic-verbose-2.stderr2
-rw-r--r--src/test/ui/closures/print/closure-print-verbose.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-88459.rs19
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs (renamed from src/test/ui/issues/issue-44005.rs)3
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr31
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs4
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr20
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr92
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr8
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs64
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs30
-rw-r--r--src/test/ui/issues/issue-44005.stderr20
17 files changed, 263 insertions, 87 deletions
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index b11a54d5dcb..742005e245f 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -744,6 +744,7 @@ pub trait PrettyPrinter<'tcx>:
                     p!(print_def_path(did, substs));
                     if !substs.as_closure().is_valid() {
                         p!(" closure_substs=(unavailable)");
+                        p!(write(" substs={:?}", substs));
                     } else {
                         p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
                         p!(
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index db8a6d96204..b8c66931cbe 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1734,7 +1734,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         ty: ret_type,
     });
 
-    confirm_param_env_candidate(selcx, obligation, predicate, false)
+    confirm_param_env_candidate(selcx, obligation, predicate, true)
 }
 
 fn confirm_param_env_candidate<'cx, 'tcx>(
@@ -1754,8 +1754,18 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
     );
 
     let cache_projection = cache_entry.projection_ty;
-    let obligation_projection = obligation.predicate;
     let mut nested_obligations = Vec::new();
+    let obligation_projection = obligation.predicate;
+    let obligation_projection = ensure_sufficient_stack(|| {
+        normalize_with_depth_to(
+            selcx,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            obligation_projection,
+            &mut nested_obligations,
+        )
+    });
     let cache_projection = if potentially_unnormalized_candidate {
         ensure_sufficient_stack(|| {
             normalize_with_depth_to(
@@ -1771,6 +1781,8 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
         cache_projection
     };
 
+    debug!(?cache_projection, ?obligation_projection);
+
     match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) {
         Ok(InferOk { value: _, obligations }) => {
             nested_obligations.extend(obligations);
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index a36cb1358b6..a4e2e502833 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -620,23 +620,37 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => bug!("closure candidate for non-closure {:?}", obligation),
         };
 
+        let obligation_predicate = obligation.predicate.to_poly_trait_ref();
+        let Normalized { value: obligation_predicate, mut obligations } =
+            ensure_sufficient_stack(|| {
+                normalize_with_depth(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    obligation_predicate,
+                )
+            });
+
         let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
-        let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
-            normalize_with_depth(
-                self,
-                obligation.param_env,
-                obligation.cause.clone(),
-                obligation.recursion_depth + 1,
-                trait_ref,
-            )
-        });
+        let Normalized { value: trait_ref, obligations: trait_ref_obligations } =
+            ensure_sufficient_stack(|| {
+                normalize_with_depth(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    trait_ref,
+                )
+            });
 
         debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations");
 
+        obligations.extend(trait_ref_obligations);
         obligations.extend(self.confirm_poly_trait_refs(
             obligation.cause.clone(),
             obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
+            obligation_predicate,
             trait_ref,
         )?);
 
diff --git a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
index d9479002b6c..36d6450c9a2 100644
--- a/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
+++ b/src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable)]`
+                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
diff --git a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
index 880e38df2d7..91926f233d3 100644
--- a/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
+++ b/src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[f<T>::{closure#0} closure_substs=(unavailable)]`
+                found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
diff --git a/src/test/ui/closures/print/closure-print-verbose.stderr b/src/test/ui/closures/print/closure-print-verbose.stderr
index d19b07acbf1..083717b3334 100644
--- a/src/test/ui/closures/print/closure-print-verbose.stderr
+++ b/src/test/ui/closures/print/closure-print-verbose.stderr
@@ -7,7 +7,7 @@ LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
    |              expected due to this
    |
    = note: expected fn pointer `fn(u8) -> u8`
-                 found closure `[main::{closure#0} closure_substs=(unavailable)]`
+                 found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]`
 note: closures can only be coerced to `fn` types if they do not capture any variables
   --> $DIR/closure-print-verbose.rs:10:39
    |
diff --git a/src/test/ui/generic-associated-types/issue-88459.rs b/src/test/ui/generic-associated-types/issue-88459.rs
new file mode 100644
index 00000000000..3b26a180152
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-88459.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Trait {
+    type Assoc<'a>;
+}
+
+fn f<T: Trait>(_: T, _: impl Fn(T::Assoc<'_>)) {}
+
+struct Type;
+
+impl Trait for Type {
+    type Assoc<'a> = ();
+}
+
+fn main() {
+    f(Type, |_|());
+}
diff --git a/src/test/ui/issues/issue-44005.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs
index ab3b92142c8..f255eac0c4b 100644
--- a/src/test/ui/issues/issue-44005.rs
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs
@@ -1,3 +1,5 @@
+// check-pass
+
 pub trait Foo<'a> {
     type Bar;
     fn foo(&'a self) -> Self::Bar;
@@ -24,7 +26,6 @@ pub fn catalyst(x: &i32) {
 
 pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
     uncallable(x, |y| f(y));
-    //~^ type mismatch
 }
 
 fn main() {}
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
index 24ac566f9df..7c3c72e04cb 100644
--- 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
@@ -77,7 +77,7 @@ where P: Execute + 'static {
 }
 
 fn main() {
-    task(annotate( //~ type mismatch
+    task(annotate(
         //~^ the size
         //~^^ the trait bound
         Annotate::<RefMutFamily<usize>>::new(),
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
index b13226fef6e..01b14660b65 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
@@ -1,29 +1,3 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-62529-1.rs:80:10
-   |
-LL |       task(annotate(
-   |  _____----_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |
-LL | |         Annotate::<RefMutFamily<usize>>::new(),
-LL | |         |value: &mut usize| {
-   | |         ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
-LL | |             *value = 2;
-LL | |         }
-LL | |     ));
-   | |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
-   |
-note: required by a bound in `annotate`
-  --> $DIR/issue-62529-1.rs:44:8
-   |
-LL | fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
-   |    -------- required by a bound in this
-LL | where
-LL |     F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate`
-
 error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time
   --> $DIR/issue-62529-1.rs:80:10
    |
@@ -73,7 +47,6 @@ LL | fn task<P>(processor: P) -> Task
 LL | where P: Execute + 'static {
    |          ^^^^^^^ required by this bound in `task`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0277, E0631.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
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
index 87d1a250f7a..3ced40230f0 100644
--- 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
@@ -1,3 +1,5 @@
+// check-pass
+
 pub trait MyTrait<'a> {
     type Output: 'a;
     fn gimme_value(&self) -> Self::Output;
@@ -23,7 +25,7 @@ where
 
 fn main() {
     let struc = MyStruct;
-    meow(struc, |foo| { //~ type mismatch
+    meow(struc, |foo| {
         println!("{:?}", foo);
     })
 }
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr
deleted file mode 100644
index efc956888ee..00000000000
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-70120.rs:26:5
-   |
-LL |     meow(struc, |foo| {
-   |     ^^^^        ----- found signature of `for<'r> fn(&'r usize) -> _`
-   |     |
-   |     expected signature of `for<'any2> fn(<MyStruct as MyTrait<'any2>>::Output) -> _`
-   |
-note: required by a bound in `meow`
-  --> $DIR/issue-70120.rs:18:8
-   |
-LL | fn meow<T, F>(t: T, f: F)
-   |    ---- required by a bound in this
-...
-LL |     F: for<'any2> Fn(<T as MyTrait<'any2>>::Output),
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `meow`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.
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 00000000000..119cec1fa95
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
@@ -0,0 +1,92 @@
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:52:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^ implementation of `Parser` is not general enough
+   |
+   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr
new file mode 100644
index 00000000000..69ab446bc7a
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/issue-71955.rs:42:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
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 00000000000..95e3b3d4e1b
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
@@ -0,0 +1,64 @@
+// ignore-compare-mode-nll
+// revisions: migrate nll
+// [nll]compile-flags: -Zborrowck=mir
+// 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);
+
+// Because nll currently succeeds and migrate doesn't
+#[rustc_error]
+fn main() {
+    //[nll]~^ fatal
+    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);
+    //[migrate]~^ ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    foo(baz, "string", |s| s.0.len() == 5);
+    //[migrate]~^ ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[migrate]~| ERROR implementation of `Parser` is not general enough
+}
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 00000000000..93ccb42684c
--- /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/issues/issue-44005.stderr b/src/test/ui/issues/issue-44005.stderr
deleted file mode 100644
index 307e444e696..00000000000
--- a/src/test/ui/issues/issue-44005.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-44005.rs:26:5
-   |
-LL |     uncallable(x, |y| f(y));
-   |     ^^^^^^^^^^    -------- found signature of `for<'r> fn(&'r i32) -> _`
-   |     |
-   |     expected signature of `for<'a> fn(<&i32 as Foo<'a>>::Bar) -> _`
-   |
-note: required by a bound in `uncallable`
-  --> $DIR/issue-44005.rs:16:8
-   |
-LL | pub fn uncallable<T, F>(x: T, f: F)
-   |        ---------- required by a bound in this
-...
-LL |     F: for<'a> Fn(<T as Foo<'a>>::Bar),
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.