about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs120
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs20
-rw-r--r--tests/ui/higher-ranked/builtin-closure-like-bounds.rs58
-rw-r--r--tests/ui/higher-ranked/closure-bound-codegen-ice.rs33
-rw-r--r--tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr19
-rw-r--r--tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr19
-rw-r--r--tests/ui/higher-ranked/trait-bounds/fn-ptr.rs3
-rw-r--r--tests/ui/higher-ranked/trait-bounds/future.classic.stderr6
-rw-r--r--tests/ui/higher-ranked/trait-bounds/future.current.stderr6
-rw-r--r--tests/ui/higher-ranked/trait-bounds/future.rs9
-rw-r--r--tests/ui/lifetimes/issue-105675.rs2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/issue_74400.rs4
12 files changed, 158 insertions, 141 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 6f512a1173f..0459246553b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -28,7 +28,7 @@ use crate::traits::{
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
     ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, PolyTraitObligation,
     PredicateObligation, Selection, SelectionError, SignatureMismatch, TraitNotObjectSafe,
-    Unimplemented,
+    TraitObligation, Unimplemented,
 };
 
 use super::BuiltinImplConditions;
@@ -678,17 +678,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         fn_host_effect: ty::Const<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         debug!(?obligation, "confirm_fn_pointer_candidate");
+        let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
+        let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
 
         let tcx = self.tcx();
-
-        let Some(self_ty) = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars()) else {
-            // FIXME: Ideally we'd support `for<'a> fn(&'a ()): Fn(&'a ())`,
-            // but we do not currently. Luckily, such a bound is not
-            // particularly useful, so we don't expect users to write
-            // them often.
-            return Err(SelectionError::Unimplemented);
-        };
-
         let sig = self_ty.fn_sig(tcx);
         let trait_ref = closure_trait_ref_and_return_type(
             tcx,
@@ -700,7 +693,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         )
         .map_bound(|(trait_ref, _)| trait_ref);
 
-        let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+        let mut nested =
+            self.equate_trait_refs(obligation.with(tcx, placeholder_predicate), trait_ref)?;
         let cause = obligation.derived_cause(BuiltinDerivedObligation);
 
         // Confirm the `type Output: Sized;` bound that is present on `FnOnce`
@@ -748,10 +742,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the args on coroutine types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
+        let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
         let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
@@ -760,15 +752,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let coroutine_sig = args.as_coroutine().sig();
 
-        // NOTE: The self-type is a coroutine type and hence is
-        // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation).
-        let self_ty = obligation
-            .predicate
-            .self_ty()
-            .no_bound_vars()
-            .expect("unboxed closure type should not capture bound vars from the predicate");
-
         let (trait_ref, _, _) = super::util::coroutine_trait_ref_and_outputs(
             self.tcx(),
             obligation.predicate.def_id(),
@@ -776,7 +759,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             coroutine_sig,
         );
 
-        let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?;
+        let nested = self.equate_trait_refs(
+            obligation.with(self.tcx(), placeholder_predicate),
+            ty::Binder::dummy(trait_ref),
+        )?;
         debug!(?trait_ref, ?nested, "coroutine candidate obligations");
 
         Ok(nested)
@@ -786,10 +772,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the args on coroutine types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
+        let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
         let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
@@ -801,11 +785,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let (trait_ref, _) = super::util::future_trait_ref_and_outputs(
             self.tcx(),
             obligation.predicate.def_id(),
-            obligation.predicate.no_bound_vars().expect("future has no bound vars").self_ty(),
+            self_ty,
             coroutine_sig,
         );
 
-        let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?;
+        let nested = self.equate_trait_refs(
+            obligation.with(self.tcx(), placeholder_predicate),
+            ty::Binder::dummy(trait_ref),
+        )?;
         debug!(?trait_ref, ?nested, "future candidate obligations");
 
         Ok(nested)
@@ -815,10 +802,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the args on coroutine types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
+        let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
         let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
@@ -830,11 +815,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let (trait_ref, _) = super::util::iterator_trait_ref_and_outputs(
             self.tcx(),
             obligation.predicate.def_id(),
-            obligation.predicate.no_bound_vars().expect("iterator has no bound vars").self_ty(),
+            self_ty,
             gen_sig,
         );
 
-        let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?;
+        let nested = self.equate_trait_refs(
+            obligation.with(self.tcx(), placeholder_predicate),
+            ty::Binder::dummy(trait_ref),
+        )?;
         debug!(?trait_ref, ?nested, "iterator candidate obligations");
 
         Ok(nested)
@@ -844,10 +832,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the args on coroutine types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
+        let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
         let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
@@ -859,11 +845,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let (trait_ref, _) = super::util::async_iterator_trait_ref_and_outputs(
             self.tcx(),
             obligation.predicate.def_id(),
-            obligation.predicate.no_bound_vars().expect("iterator has no bound vars").self_ty(),
+            self_ty,
             gen_sig,
         );
 
-        let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?;
+        let nested = self.equate_trait_refs(
+            obligation.with(self.tcx(), placeholder_predicate),
+            ty::Binder::dummy(trait_ref),
+        )?;
         debug!(?trait_ref, ?nested, "iterator candidate obligations");
 
         Ok(nested)
@@ -874,14 +863,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the args on closure types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
+        let self_ty: Ty<'_> = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
+
         let trait_ref = match *self_ty.kind() {
-            ty::Closure(_, args) => {
-                self.closure_trait_ref_unnormalized(obligation, args, self.tcx().consts.true_)
-            }
+            ty::Closure(..) => self.closure_trait_ref_unnormalized(
+                self_ty,
+                obligation.predicate.def_id(),
+                self.tcx().consts.true_,
+            ),
             ty::CoroutineClosure(_, args) => {
                 args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
                     ty::TraitRef::new(
@@ -896,7 +886,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         };
 
-        self.confirm_poly_trait_refs(obligation, trait_ref)
+        self.equate_trait_refs(obligation.with(self.tcx(), placeholder_predicate), trait_ref)
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -904,8 +894,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
+        let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty());
+
         let tcx = self.tcx();
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
 
         let mut nested = vec![];
         let (trait_ref, kind_ty) = match *self_ty.kind() {
@@ -972,7 +964,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => bug!("expected callable type for AsyncFn candidate"),
         };
 
-        nested.extend(self.confirm_poly_trait_refs(obligation, trait_ref)?);
+        nested.extend(
+            self.equate_trait_refs(obligation.with(tcx, placeholder_predicate), trait_ref)?,
+        );
 
         let goal_kind =
             self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
@@ -1025,34 +1019,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// selection of the impl. Therefore, if there is a mismatch, we
     /// report an error to the user.
     #[instrument(skip(self), level = "trace")]
-    fn confirm_poly_trait_refs(
+    fn equate_trait_refs(
         &mut self,
-        obligation: &PolyTraitObligation<'tcx>,
-        self_ty_trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: TraitObligation<'tcx>,
+        found_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        let obligation_trait_ref =
-            self.infcx.enter_forall_and_leak_universe(obligation.predicate.to_poly_trait_ref());
-        let self_ty_trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
+        let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
             obligation.cause.span,
             HigherRankedType,
-            self_ty_trait_ref,
+            found_trait_ref,
         );
         // Normalize the obligation and expected trait refs together, because why not
-        let Normalized { obligations: nested, value: (obligation_trait_ref, expected_trait_ref) } =
+        let Normalized { obligations: nested, value: (obligation_trait_ref, found_trait_ref) } =
             ensure_sufficient_stack(|| {
                 normalize_with_depth(
                     self,
                     obligation.param_env,
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
-                    (obligation_trait_ref, self_ty_trait_ref),
+                    (obligation.predicate.trait_ref, found_trait_ref),
                 )
             });
 
         // needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
         self.infcx
             .at(&obligation.cause, obligation.param_env)
-            .eq(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref)
+            .eq(DefineOpaqueTypes::Yes, obligation_trait_ref, found_trait_ref)
             .map(|InferOk { mut obligations, .. }| {
                 obligations.extend(nested);
                 obligations
@@ -1060,7 +1052,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .map_err(|terr| {
                 SignatureMismatch(Box::new(SignatureMismatchData {
                     expected_trait_ref: ty::Binder::dummy(obligation_trait_ref),
-                    found_trait_ref: ty::Binder::dummy(expected_trait_ref),
+                    found_trait_ref: ty::Binder::dummy(found_trait_ref),
                     terr,
                 }))
             })
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 1894fbba302..084f7b1a8c2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2679,26 +2679,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     fn closure_trait_ref_unnormalized(
         &mut self,
-        obligation: &PolyTraitObligation<'tcx>,
-        args: GenericArgsRef<'tcx>,
+        self_ty: Ty<'tcx>,
+        fn_trait_def_id: DefId,
         fn_host_effect: ty::Const<'tcx>,
     ) -> ty::PolyTraitRef<'tcx> {
+        let ty::Closure(_, args) = *self_ty.kind() else {
+            bug!("expected closure, found {self_ty}");
+        };
         let closure_sig = args.as_closure().sig();
 
-        debug!(?closure_sig);
-
-        // NOTE: The self-type is an unboxed closure type and hence is
-        // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation).
-        let self_ty = obligation
-            .predicate
-            .self_ty()
-            .no_bound_vars()
-            .expect("unboxed closure type should not capture bound vars from the predicate");
-
         closure_trait_ref_and_return_type(
             self.tcx(),
-            obligation.predicate.def_id(),
+            fn_trait_def_id,
             self_ty,
             closure_sig,
             util::TupleArgumentsFlag::No,
diff --git a/tests/ui/higher-ranked/builtin-closure-like-bounds.rs b/tests/ui/higher-ranked/builtin-closure-like-bounds.rs
new file mode 100644
index 00000000000..dee290cc439
--- /dev/null
+++ b/tests/ui/higher-ranked/builtin-closure-like-bounds.rs
@@ -0,0 +1,58 @@
+//@ edition:2024
+//@ compile-flags: -Zunstable-options
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Makes sure that we support closure/coroutine goals where the signature of
+// the item references higher-ranked lifetimes from the *predicate* binder,
+// not its own internal signature binder.
+//
+// This was fixed in <https://github.com/rust-lang/rust/pull/122267>.
+
+#![feature(unboxed_closures, gen_blocks)]
+
+trait Dispatch {
+    fn dispatch(self);
+}
+
+struct Fut<T>(T);
+impl<T: for<'a> Fn<(&'a (),)>> Dispatch for Fut<T>
+where
+    for<'a> <T as FnOnce<(&'a (),)>>::Output: Future,
+{
+    fn dispatch(self) {
+        (self.0)(&());
+    }
+}
+
+struct Gen<T>(T);
+impl<T: for<'a> Fn<(&'a (),)>> Dispatch for Gen<T>
+where
+    for<'a> <T as FnOnce<(&'a (),)>>::Output: Iterator,
+{
+    fn dispatch(self) {
+        (self.0)(&());
+    }
+}
+
+struct Closure<T>(T);
+impl<T: for<'a> Fn<(&'a (),)>> Dispatch for Closure<T>
+where
+    for<'a> <T as FnOnce<(&'a (),)>>::Output: Fn<(&'a (),)>,
+{
+    fn dispatch(self) {
+        (self.0)(&())(&());
+    }
+}
+
+fn main() {
+    async fn foo(_: &()) {}
+    Fut(foo).dispatch();
+
+    gen fn bar(_: &()) {}
+    Gen(bar).dispatch();
+
+    fn uwu<'a>(x: &'a ()) -> impl Fn(&'a ()) { |_| {} }
+    Closure(uwu).dispatch();
+}
diff --git a/tests/ui/higher-ranked/closure-bound-codegen-ice.rs b/tests/ui/higher-ranked/closure-bound-codegen-ice.rs
new file mode 100644
index 00000000000..4d7ae12d7a7
--- /dev/null
+++ b/tests/ui/higher-ranked/closure-bound-codegen-ice.rs
@@ -0,0 +1,33 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ build-pass
+
+// Regression test for incomplete handling of Fn-trait goals,
+// fixed in #122267.
+
+trait Trait {
+    type Assoc<'a>: FnOnce(&'a ());
+}
+
+impl Trait for () {
+    type Assoc<'a> = fn(&'a ());
+}
+
+trait Indir {
+    fn break_me() {}
+}
+
+impl<F: Trait> Indir for F
+where
+    for<'a> F::Assoc<'a>: FnOnce(&'a ()),
+{
+    fn break_me() {}
+}
+
+fn foo<F: Trait>() {
+    F::break_me()
+}
+
+fn main() {
+    foo::<()>();
+}
diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr
deleted file mode 100644
index b322ea41c43..00000000000
--- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0277]: expected a `Fn(&'w ())` closure, found `fn(&'w ())`
-  --> $DIR/fn-ptr.rs:12:5
-   |
-LL |     ice();
-   |     ^^^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())`
-   |
-   = help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())`
-note: required by a bound in `ice`
-  --> $DIR/fn-ptr.rs:7:25
-   |
-LL | fn ice()
-   |    --- required by a bound in this function
-LL | where
-LL |     for<'w> fn(&'w ()): Fn(&'w ()),
-   |                         ^^^^^^^^^^ required by this bound in `ice`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr
deleted file mode 100644
index f3583cd218b..00000000000
--- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0277]: expected a `Fn(&'w ())` closure, found `fn(&'w ())`
-  --> $DIR/fn-ptr.rs:13:5
-   |
-LL |     ice();
-   |     ^^^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())`
-   |
-   = help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())`
-note: required by a bound in `ice`
-  --> $DIR/fn-ptr.rs:8:25
-   |
-LL | fn ice()
-   |    --- required by a bound in this function
-LL | where
-LL |     for<'w> fn(&'w ()): Fn(&'w ()),
-   |                         ^^^^^^^^^^ required by this bound in `ice`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs b/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs
index 9298c10c341..7a4c15f4d4b 100644
--- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs
+++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs
@@ -1,7 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
 
 fn ice()
 where
@@ -11,5 +11,4 @@ where
 
 fn main() {
     ice();
-    //[current]~^ ERROR expected a `Fn(&'w ())` closure, found `fn(&'w ())`
 }
diff --git a/tests/ui/higher-ranked/trait-bounds/future.classic.stderr b/tests/ui/higher-ranked/trait-bounds/future.classic.stderr
deleted file mode 100644
index ef31b7266c7..00000000000
--- a/tests/ui/higher-ranked/trait-bounds/future.classic.stderr
+++ /dev/null
@@ -1,6 +0,0 @@
-error: the compiler unexpectedly panicked. this is a bug.
-
-query stack during panic:
-#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body@$DIR/future.rs:32:35: 34:2}: core::future::future::Future`
-#1 [codegen_select_candidate] computing candidate for `<strlen as Trait>`
-end of query stack
diff --git a/tests/ui/higher-ranked/trait-bounds/future.current.stderr b/tests/ui/higher-ranked/trait-bounds/future.current.stderr
deleted file mode 100644
index 673bc48a424..00000000000
--- a/tests/ui/higher-ranked/trait-bounds/future.current.stderr
+++ /dev/null
@@ -1,6 +0,0 @@
-error: the compiler unexpectedly panicked. this is a bug.
-
-query stack during panic:
-#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body of strlen()}: core::future::future::Future`
-#1 [codegen_select_candidate] computing candidate for `<strlen as Trait>`
-end of query stack
diff --git a/tests/ui/higher-ranked/trait-bounds/future.rs b/tests/ui/higher-ranked/trait-bounds/future.rs
index 4b52f04dbe0..7105015b690 100644
--- a/tests/ui/higher-ranked/trait-bounds/future.rs
+++ b/tests/ui/higher-ranked/trait-bounds/future.rs
@@ -3,14 +3,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
-//@[next] check-pass
-//@[current] known-bug: #112347
-//@[current] build-fail
-//@[current] failure-status: 101
-//@[current] normalize-stderr-test "note: .*\n\n" -> ""
-//@[current] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
-//@[current] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
-//@[current] rustc-env:RUST_BACKTRACE=0
+//@ check-pass
 
 #![feature(unboxed_closures)]
 
diff --git a/tests/ui/lifetimes/issue-105675.rs b/tests/ui/lifetimes/issue-105675.rs
index 2e2eaca0d33..0472537e7f3 100644
--- a/tests/ui/lifetimes/issue-105675.rs
+++ b/tests/ui/lifetimes/issue-105675.rs
@@ -4,7 +4,7 @@ fn main() {
     let f = | _ , y: &u32 , z | ();
     thing(f);
     //~^ ERROR implementation of `FnOnce` is not general enough
-    //~^^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
     let f = | x, y: _  , z: u32 | ();
     thing(f);
     //~^ ERROR implementation of `FnOnce` is not general enough
diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
index b02e38bec3b..72345fa294a 100644
--- a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
+++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
@@ -1,5 +1,5 @@
 //! Regression test for #74400: Type mismatch in function arguments E0631, E0271 are falsely
-//! recognized as E0308 mismatched types.
+//! recognized as "implementation of `FnOnce` is not general enough".
 
 use std::convert::identity;
 
@@ -13,6 +13,6 @@ fn g<T>(data: &[T]) {
     //~^ ERROR the parameter type
     //~| ERROR the parameter type
     //~| ERROR the parameter type
-    //~| ERROR implementation of `FnOnce` is not general
+    //~| ERROR implementation of `FnOnce` is not general enough
     //~| ERROR implementation of `Fn` is not general enough
 }