about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-03-10 19:43:20 -0400
committerMichael Goulet <michael@errs.io>2024-04-21 20:10:12 -0400
commitff4653a08f0c9dad1db927727e102c51f0ea39b2 (patch)
tree6b6afbe549efdfa7fddf2240beff60c7a2e6c7d9
parentc13af7db21c8e7978f5d6bd462a397f5f7a29c8d (diff)
downloadrust-ff4653a08f0c9dad1db927727e102c51f0ea39b2.tar.gz
rust-ff4653a08f0c9dad1db927727e102c51f0ea39b2.zip
Use fulfillment, not evaluate, during method probe
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs431
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs13
-rw-r--r--tests/ui/derives/issue-91550.stderr27
-rw-r--r--tests/ui/impl-trait/issues/issue-62742.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-62742.stderr50
-rw-r--r--tests/ui/impl-trait/issues/issue-84073.rs3
-rw-r--r--tests/ui/impl-trait/issues/issue-84073.stderr28
-rw-r--r--tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr1
-rw-r--r--tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr1
-rw-r--r--tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr1
-rw-r--r--tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr1
-rw-r--r--tests/ui/methods/fulfillment-disqualifies-method.rs32
-rw-r--r--tests/ui/methods/leak-check-disquality.rs26
-rw-r--r--tests/ui/mismatched_types/issue-36053-2.stderr10
-rw-r--r--tests/ui/missing-trait-bounds/issue-35677.stderr2
-rw-r--r--tests/ui/nll/issue-57362-2.rs3
-rw-r--r--tests/ui/nll/issue-57362-2.stderr6
-rw-r--r--tests/ui/nll/issue-57642-higher-ranked-subtype.rs3
-rw-r--r--tests/ui/nll/issue-57642-higher-ranked-subtype.stderr8
-rw-r--r--tests/ui/resolve/issue-85671.rs3
-rw-r--r--tests/ui/resolve/issue-85671.stderr17
-rw-r--r--tests/ui/suggestions/derive-trait-for-method-call.stderr24
-rw-r--r--tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr7
-rw-r--r--tests/ui/traits/method-on-unbounded-type-param.stderr2
-rw-r--r--tests/ui/traits/track-obligations.stderr30
-rw-r--r--tests/ui/typeck/issue-31173.stderr2
27 files changed, 328 insertions, 407 deletions
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index d6d22a43fe0..618d90a07ec 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             [candidate] => format!(
                 "the method of the same name on {} `{}`",
                 match candidate.kind {
-                    probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
+                    probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for",
                     _ => "trait",
                 },
                 self.tcx.def_path_str(candidate.item.container_id(self.tcx))
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 7e480d66695..c31b54c642d 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -31,13 +31,12 @@ use rustc_span::edit_distance::{
 };
 use rustc_span::symbol::sym;
 use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
 use rustc_trait_selection::traits::query::method_autoderef::{
     CandidateStep, MethodAutoderefStepsResult,
 };
 use rustc_trait_selection::traits::query::CanonicalTyGoal;
-use rustc_trait_selection::traits::NormalizeExt;
+use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{self, ObligationCause};
 use std::cell::RefCell;
 use std::cmp::max;
@@ -99,39 +98,6 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
 
 #[derive(Debug, Clone)]
 pub(crate) struct Candidate<'tcx> {
-    // Candidates are (I'm not quite sure, but they are mostly) basically
-    // some metadata on top of a `ty::AssocItem` (without args).
-    //
-    // However, method probing wants to be able to evaluate the predicates
-    // for a function with the args applied - for example, if a function
-    // has `where Self: Sized`, we don't want to consider it unless `Self`
-    // is actually `Sized`, and similarly, return-type suggestions want
-    // to consider the "actual" return type.
-    //
-    // The way this is handled is through `xform_self_ty`. It contains
-    // the receiver type of this candidate, but `xform_self_ty`,
-    // `xform_ret_ty` and `kind` (which contains the predicates) have the
-    // generic parameters of this candidate instantiated with the *same set*
-    // of inference variables, which acts as some weird sort of "query".
-    //
-    // When we check out a candidate, we require `xform_self_ty` to be
-    // a subtype of the passed-in self-type, and this equates the type
-    // variables in the rest of the fields.
-    //
-    // For example, if we have this candidate:
-    // ```
-    //    trait Foo {
-    //        fn foo(&self) where Self: Sized;
-    //    }
-    // ```
-    //
-    // Then `xform_self_ty` will be `&'erased ?X` and `kind` will contain
-    // the predicate `?X: Sized`, so if we are evaluating `Foo` for a
-    // the receiver `&T`, we'll do the subtyping which will make `?X`
-    // get the right value, then when we evaluate the predicate we'll check
-    // if `T: Sized`.
-    xform_self_ty: Ty<'tcx>,
-    xform_ret_ty: Option<Ty<'tcx>>,
     pub(crate) item: ty::AssocItem,
     pub(crate) kind: CandidateKind<'tcx>,
     pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
@@ -139,17 +105,10 @@ pub(crate) struct Candidate<'tcx> {
 
 #[derive(Debug, Clone)]
 pub(crate) enum CandidateKind<'tcx> {
-    InherentImplCandidate(
-        GenericArgsRef<'tcx>,
-        // Normalize obligations
-        Vec<traits::PredicateObligation<'tcx>>,
-    ),
-    ObjectCandidate,
-    TraitCandidate(ty::TraitRef<'tcx>),
-    WhereClauseCandidate(
-        // Trait
-        ty::PolyTraitRef<'tcx>,
-    ),
+    InherentImplCandidate(DefId),
+    ObjectCandidate(ty::PolyTraitRef<'tcx>),
+    TraitCandidate(ty::PolyTraitRef<'tcx>),
+    WhereClauseCandidate(ty::PolyTraitRef<'tcx>),
 }
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
@@ -743,41 +702,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 self.record_static_candidate(CandidateSource::Impl(impl_def_id));
                 continue;
             }
-
-            let (impl_ty, impl_args) = self.impl_ty_and_args(impl_def_id);
-
-            debug!("impl_ty: {:?}", impl_ty);
-
-            // Determine the receiver type that the method itself expects.
-            let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, impl_ty, impl_args);
-            debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty);
-
-            // We can't use `FnCtxt::normalize` as it will pollute the
-            // fcx's fulfillment context after this probe is over.
-            //
-            // Note: we only normalize `xform_self_ty` here since the normalization
-            // of the return type can lead to inference results that prohibit
-            // valid candidates from being found, see issue #85671
-            //
-            // FIXME Postponing the normalization of the return type likely only hides a deeper bug,
-            // which might be caused by the `param_env` itself. The clauses of the `param_env`
-            // maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized,
-            // see issue #89650
-            let cause = traits::ObligationCause::misc(self.span, self.body_id);
-            let InferOk { value: xform_self_ty, obligations } =
-                self.fcx.at(&cause, self.param_env).normalize(xform_self_ty);
-
-            debug!(
-                "assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}",
-                xform_self_ty, xform_ret_ty
-            );
-
             self.push_candidate(
                 Candidate {
-                    xform_self_ty,
-                    xform_ret_ty,
                     item,
-                    kind: InherentImplCandidate(impl_args, obligations),
+                    kind: InherentImplCandidate(impl_def_id),
                     import_ids: smallvec![],
                 },
                 true,
@@ -809,26 +737,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         // a `&self` method will wind up with an argument type like `&dyn Trait`.
         let trait_ref = principal.with_self_ty(self.tcx, self_ty);
         self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| {
-            if new_trait_ref.has_non_region_bound_vars() {
-                this.dcx().span_delayed_bug(
-                    this.span,
-                    "tried to select method from HRTB with non-lifetime bound vars",
-                );
-                return;
-            }
-
-            let new_trait_ref = this.tcx.instantiate_bound_regions_with_erased(new_trait_ref);
-
-            let (xform_self_ty, xform_ret_ty) =
-                this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
             this.push_candidate(
-                Candidate {
-                    xform_self_ty,
-                    xform_ret_ty,
-                    item,
-                    kind: ObjectCandidate,
-                    import_ids: smallvec![],
-                },
+                Candidate { item, kind: ObjectCandidate(new_trait_ref), import_ids: smallvec![] },
                 true,
             );
         });
@@ -859,19 +769,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         });
 
         self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
-            let trait_ref = this.instantiate_binder_with_fresh_vars(
-                this.span,
-                infer::BoundRegionConversionTime::FnCall,
-                poly_trait_ref,
-            );
-
-            let (xform_self_ty, xform_ret_ty) =
-                this.xform_self_ty(item, trait_ref.self_ty(), trait_ref.args);
-
             this.push_candidate(
                 Candidate {
-                    xform_self_ty,
-                    xform_ret_ty,
                     item,
                     kind: WhereClauseCandidate(poly_trait_ref),
                     import_ids: smallvec![],
@@ -962,21 +861,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                             bound_trait_ref.def_id(),
                         ));
                     } else {
-                        let new_trait_ref = self.instantiate_binder_with_fresh_vars(
-                            self.span,
-                            infer::BoundRegionConversionTime::FnCall,
-                            bound_trait_ref,
-                        );
-
-                        let (xform_self_ty, xform_ret_ty) =
-                            self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
                         self.push_candidate(
                             Candidate {
-                                xform_self_ty,
-                                xform_ret_ty,
                                 item,
                                 import_ids: import_ids.clone(),
-                                kind: TraitCandidate(new_trait_ref),
+                                kind: TraitCandidate(bound_trait_ref),
                             },
                             false,
                         );
@@ -995,16 +884,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     self.record_static_candidate(CandidateSource::Trait(trait_def_id));
                     continue;
                 }
-
-                let (xform_self_ty, xform_ret_ty) =
-                    self.xform_self_ty(item, trait_ref.self_ty(), trait_args);
                 self.push_candidate(
                     Candidate {
-                        xform_self_ty,
-                        xform_ret_ty,
                         item,
                         import_ids: import_ids.clone(),
-                        kind: TraitCandidate(trait_ref),
+                        kind: TraitCandidate(ty::Binder::dummy(trait_ref)),
                     },
                     false,
                 );
@@ -1434,16 +1318,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
     fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource {
         match candidate.kind {
-            InherentImplCandidate(..) => {
+            InherentImplCandidate(_) => {
                 CandidateSource::Impl(candidate.item.container_id(self.tcx))
             }
-            ObjectCandidate | WhereClauseCandidate(_) => {
+            ObjectCandidate(_) | WhereClauseCandidate(_) => {
                 CandidateSource::Trait(candidate.item.container_id(self.tcx))
             }
             TraitCandidate(trait_ref) => self.probe(|_| {
+                let trait_ref =
+                    self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, trait_ref);
+                let (xform_self_ty, _) =
+                    self.xform_self_ty(candidate.item, trait_ref.self_ty(), trait_ref.args);
                 let _ = self.at(&ObligationCause::dummy(), self.param_env).sup(
                     DefineOpaqueTypes::No,
-                    candidate.xform_self_ty,
+                    xform_self_ty,
                     self_ty,
                 );
                 match self.select_trait_candidate(trait_ref) {
@@ -1470,54 +1358,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ) -> ProbeResult {
         debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe);
 
-        self.probe(|_| {
-            // First check that the self type can be related.
-            let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup(
-                DefineOpaqueTypes::No,
-                probe.xform_self_ty,
-                self_ty,
-            ) {
-                Ok(InferOk { obligations, value: () }) => obligations,
-                Err(err) => {
-                    debug!("--> cannot relate self-types {:?}", err);
-                    return ProbeResult::NoMatch;
-                }
-            };
+        self.probe(|snapshot| {
+            let outer_universe = self.universe();
 
             let mut result = ProbeResult::Match;
-            let mut xform_ret_ty = probe.xform_ret_ty;
-            debug!(?xform_ret_ty);
-
-            let cause = traits::ObligationCause::misc(self.span, self.body_id);
+            let cause = &self.misc(self.span);
+            let ocx = ObligationCtxt::new(self);
 
-            let mut parent_pred = None;
+            let mut trait_predicate = None;
+            let (mut xform_self_ty, mut xform_ret_ty);
 
-            // If so, impls may carry other conditions (e.g., where
-            // clauses) that must be considered. Make sure that those
-            // match as well (or at least may match, sometimes we
-            // don't have enough information to fully evaluate).
             match probe.kind {
-                InherentImplCandidate(args, ref ref_obligations) => {
-                    // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`,
-                    // see the reasons mentioned in the comments in `assemble_inherent_impl_probe`
-                    // for why this is necessary
-                    let InferOk {
-                        value: normalized_xform_ret_ty,
-                        obligations: normalization_obligations,
-                    } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty);
-                    xform_ret_ty = normalized_xform_ret_ty;
-                    debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty);
-
+                InherentImplCandidate(impl_def_id) => {
+                    let impl_args = self.fresh_args_for_item(self.span, impl_def_id);
+                    let impl_ty = self.tcx.type_of(impl_def_id).instantiate(self.tcx, impl_args);
+                    (xform_self_ty, xform_ret_ty) =
+                        self.xform_self_ty(probe.item, impl_ty, impl_args);
+                    xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
+                    // FIXME: Weirdly, we normalize the ret ty in this candidate, but no other candidates.
+                    xform_ret_ty = ocx.normalize(cause, self.param_env, xform_ret_ty);
+                    match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
+                        Err(err) => {
+                            debug!("--> cannot relate self-types {:?}", err);
+                            return ProbeResult::NoMatch;
+                        }
+                    }
                     // Check whether the impl imposes obligations we have to worry about.
                     let impl_def_id = probe.item.container_id(self.tcx);
-                    let impl_bounds = self.tcx.predicates_of(impl_def_id);
-                    let impl_bounds = impl_bounds.instantiate(self.tcx, args);
-
-                    let InferOk { value: impl_bounds, obligations: norm_obligations } =
-                        self.fcx.at(&cause, self.param_env).normalize(impl_bounds);
-
+                    let impl_bounds =
+                        self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args);
+                    let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds);
                     // Convert the bounds into obligations.
-                    let impl_obligations = traits::predicates_for_generics(
+                    ocx.register_obligations(traits::predicates_for_generics(
                         |idx, span| {
                             let code = if span.is_dummy() {
                                 traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx)
@@ -1533,106 +1406,56 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         },
                         self.param_env,
                         impl_bounds,
-                    );
-
-                    let candidate_obligations = impl_obligations
-                        .chain(norm_obligations)
-                        .chain(ref_obligations.iter().cloned())
-                        .chain(normalization_obligations);
-
-                    // Evaluate those obligations to see if they might possibly hold.
-                    for o in candidate_obligations {
-                        let o = self.resolve_vars_if_possible(o);
-                        if !self.predicate_may_hold(&o) {
-                            result = ProbeResult::NoMatch;
-                            let parent_o = o.clone();
-                            let implied_obligations = traits::elaborate(self.tcx, vec![o]);
-                            for o in implied_obligations {
-                                let parent = if o == parent_o {
-                                    None
-                                } else {
-                                    if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id())
-                                        == self.tcx.lang_items().sized_trait()
-                                    {
-                                        // We don't care to talk about implicit `Sized` bounds.
-                                        continue;
-                                    }
-                                    Some(parent_o.predicate)
-                                };
-                                if !self.predicate_may_hold(&o) {
-                                    possibly_unsatisfied_predicates.push((
-                                        o.predicate,
-                                        parent,
-                                        Some(o.cause),
-                                    ));
-                                }
-                            }
-                        }
-                    }
-                }
-
-                ObjectCandidate | WhereClauseCandidate(..) => {
-                    // These have no additional conditions to check.
+                    ));
                 }
-
-                TraitCandidate(trait_ref) => {
+                TraitCandidate(poly_trait_ref) => {
+                    // Some trait methods are excluded for arrays before 2021.
+                    // (`array.into_iter()` wants a slice iterator for compatibility.)
                     if let Some(method_name) = self.method_name {
-                        // Some trait methods are excluded for arrays before 2021.
-                        // (`array.into_iter()` wants a slice iterator for compatibility.)
                         if self_ty.is_array() && !method_name.span.at_least_rust_2021() {
-                            let trait_def = self.tcx.trait_def(trait_ref.def_id);
+                            let trait_def = self.tcx.trait_def(poly_trait_ref.def_id());
                             if trait_def.skip_array_during_method_dispatch {
                                 return ProbeResult::NoMatch;
                             }
                         }
                     }
-                    let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx);
-                    parent_pred = Some(predicate);
-                    let obligation =
-                        traits::Obligation::new(self.tcx, cause.clone(), self.param_env, predicate);
-                    if !self.predicate_may_hold(&obligation) {
-                        result = ProbeResult::NoMatch;
-                        if self.probe(|_| {
-                            match self.select_trait_candidate(trait_ref) {
-                                Err(_) => return true,
-                                Ok(Some(impl_source))
-                                    if !impl_source.borrow_nested_obligations().is_empty() =>
-                                {
-                                    for obligation in impl_source.borrow_nested_obligations() {
-                                        // Determine exactly which obligation wasn't met, so
-                                        // that we can give more context in the error.
-                                        if !self.predicate_may_hold(obligation) {
-                                            let nested_predicate =
-                                                self.resolve_vars_if_possible(obligation.predicate);
-                                            let predicate =
-                                                self.resolve_vars_if_possible(predicate);
-                                            let p = if predicate == nested_predicate {
-                                                // Avoid "`MyStruct: Foo` which is required by
-                                                // `MyStruct: Foo`" in E0599.
-                                                None
-                                            } else {
-                                                Some(predicate)
-                                            };
-                                            possibly_unsatisfied_predicates.push((
-                                                nested_predicate,
-                                                p,
-                                                Some(obligation.cause.clone()),
-                                            ));
-                                        }
-                                    }
-                                }
-                                _ => {
-                                    // Some nested subobligation of this predicate
-                                    // failed.
-                                    let predicate = self.resolve_vars_if_possible(predicate);
-                                    possibly_unsatisfied_predicates.push((predicate, None, None));
-                                }
-                            }
-                            false
-                        }) {
-                            // This candidate's primary obligation doesn't even
-                            // select - don't bother registering anything in
-                            // `potentially_unsatisfied_predicates`.
+
+                    let trait_ref = self.instantiate_binder_with_fresh_vars(
+                        self.span,
+                        infer::FnCall,
+                        poly_trait_ref,
+                    );
+                    (xform_self_ty, xform_ret_ty) =
+                        self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
+                    xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
+                    match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
+                        Err(err) => {
+                            debug!("--> cannot relate self-types {:?}", err);
+                            return ProbeResult::NoMatch;
+                        }
+                    }
+                    ocx.register_obligation(traits::Obligation::new(
+                        self.tcx,
+                        cause.clone(),
+                        self.param_env,
+                        ty::Binder::dummy(trait_ref),
+                    ));
+                    trait_predicate = Some(ty::Binder::dummy(trait_ref).to_predicate(self.tcx));
+                }
+                ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => {
+                    let trait_ref = self.instantiate_binder_with_fresh_vars(
+                        self.span,
+                        infer::FnCall,
+                        poly_trait_ref,
+                    );
+                    (xform_self_ty, xform_ret_ty) =
+                        self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
+                    xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
+                    match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
+                        Err(err) => {
+                            debug!("--> cannot relate self-types {:?}", err);
                             return ProbeResult::NoMatch;
                         }
                     }
@@ -1640,11 +1463,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             }
 
             // Evaluate those obligations to see if they might possibly hold.
-            for o in sub_obligations {
-                let o = self.resolve_vars_if_possible(o);
-                if !self.predicate_may_hold(&o) {
-                    result = ProbeResult::NoMatch;
-                    possibly_unsatisfied_predicates.push((o.predicate, parent_pred, Some(o.cause)));
+            for error in ocx.select_where_possible() {
+                result = ProbeResult::NoMatch;
+                let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate);
+                if let Some(trait_predicate) = trait_predicate
+                    && nested_predicate == self.resolve_vars_if_possible(trait_predicate)
+                {
+                    // Don't report possibly unsatisfied predicates if the root
+                    // trait obligation from a `TraitCandidate` is unsatisfied.
+                    // That just means the candidate doesn't hold.
+                } else {
+                    possibly_unsatisfied_predicates.push((
+                        nested_predicate,
+                        Some(self.resolve_vars_if_possible(error.root_obligation.predicate))
+                            .filter(|root_predicate| *root_predicate != nested_predicate),
+                        Some(error.obligation.cause),
+                    ));
                 }
             }
 
@@ -1656,38 +1490,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 // We don't normalize the other candidates for perf/backwards-compat reasons...
                 // but `self.return_type` is only set on the diagnostic-path, so we
                 // should be okay doing it here.
-                if !matches!(probe.kind, InherentImplCandidate(..)) {
-                    let InferOk {
-                        value: normalized_xform_ret_ty,
-                        obligations: normalization_obligations,
-                    } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty);
-                    xform_ret_ty = normalized_xform_ret_ty;
-                    debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty);
-                    // Evaluate those obligations to see if they might possibly hold.
-                    for o in normalization_obligations {
-                        let o = self.resolve_vars_if_possible(o);
-                        if !self.predicate_may_hold(&o) {
-                            result = ProbeResult::NoMatch;
-                            possibly_unsatisfied_predicates.push((
-                                o.predicate,
-                                None,
-                                Some(o.cause),
-                            ));
-                        }
-                    }
+                if !matches!(probe.kind, InherentImplCandidate(_)) {
+                    xform_ret_ty = ocx.normalize(&cause, self.param_env, xform_ret_ty);
                 }
 
                 debug!("comparing return_ty {:?} with xform ret ty {:?}", return_ty, xform_ret_ty);
-                if let ProbeResult::Match = result
-                    && self
-                        .at(&ObligationCause::dummy(), self.param_env)
-                        .sup(DefineOpaqueTypes::Yes, return_ty, xform_ret_ty)
-                        .is_err()
-                {
-                    result = ProbeResult::BadReturnType;
+                match ocx.sup(cause, self.param_env, return_ty, xform_ret_ty) {
+                    Ok(()) => {}
+                    Err(_) => {
+                        result = ProbeResult::BadReturnType;
+                    }
+                }
+
+                // Evaluate those obligations to see if they might possibly hold.
+                for error in ocx.select_where_possible() {
+                    result = ProbeResult::NoMatch;
+                    possibly_unsatisfied_predicates.push((
+                        error.obligation.predicate,
+                        Some(error.root_obligation.predicate)
+                            .filter(|predicate| *predicate != error.obligation.predicate),
+                        Some(error.root_obligation.cause),
+                    ));
                 }
             }
 
+            // Previously, method probe used `evaluate_predicate` to determine if a predicate
+            // was impossible to satisfy. This did a leak check, so we must also do a leak
+            // check here to prevent backwards-incompatible ambiguity being introduced. See
+            // `tests/ui/methods/leak-check-disquality.rs` for a simple example of when this
+            // may happen.
+            if let Err(_) = self.leak_check(outer_universe, Some(snapshot)) {
+                result = ProbeResult::NoMatch;
+            }
+
             result
         })
     }
@@ -1881,12 +1716,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         self.tcx.instantiate_bound_regions_with_erased(xform_fn_sig)
     }
 
-    /// Gets the type of an impl and generate generic parameters with inference vars.
-    fn impl_ty_and_args(&self, impl_def_id: DefId) -> (Ty<'tcx>, GenericArgsRef<'tcx>) {
-        let args = self.fresh_args_for_item(self.span, impl_def_id);
-        (self.tcx.type_of(impl_def_id).instantiate(self.tcx, args), args)
-    }
-
     /// Determine if the given associated item type is relevant in the current context.
     fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool {
         match (self.mode, kind) {
@@ -2008,10 +1837,10 @@ impl<'tcx> Candidate<'tcx> {
         Pick {
             item: self.item,
             kind: match self.kind {
-                InherentImplCandidate(..) => InherentImplPick,
-                ObjectCandidate => ObjectPick,
+                InherentImplCandidate(_) => InherentImplPick,
+                ObjectCandidate(_) => ObjectPick,
                 TraitCandidate(_) => TraitPick,
-                WhereClauseCandidate(ref trait_ref) => {
+                WhereClauseCandidate(trait_ref) => {
                     // Only trait derived from where-clauses should
                     // appear here, so they should not contain any
                     // inference variables or other artifacts. This
@@ -2022,7 +1851,7 @@ impl<'tcx> Candidate<'tcx> {
                             && !trait_ref.skip_binder().args.has_placeholders()
                     );
 
-                    WhereClausePick(*trait_ref)
+                    WhereClausePick(trait_ref)
                 }
             },
             import_ids: self.import_ids.clone(),
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 9fbec174ce8..68c76dcf297 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -129,6 +129,19 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
             .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
     }
 
+    pub fn eq_no_opaques<T: ToTrace<'tcx>>(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        expected: T,
+        actual: T,
+    ) -> Result<(), TypeError<'tcx>> {
+        self.infcx
+            .at(cause, param_env)
+            .eq(DefineOpaqueTypes::No, expected, actual)
+            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
+    }
+
     /// Checks whether `expected` is a subtype of `actual`: `expected <: actual`.
     pub fn sub<T: ToTrace<'tcx>>(
         &self,
diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr
index 9e171896718..4d637c97283 100644
--- a/tests/ui/derives/issue-91550.stderr
+++ b/tests/ui/derives/issue-91550.stderr
@@ -2,15 +2,13 @@ error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its tr
   --> $DIR/issue-91550.rs:8:8
    |
 LL | struct Value(u32);
-   | ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq`
+   | ------------ doesn't satisfy `Value: Eq` or `Value: Hash`
 ...
 LL |     hs.insert(Value(0));
    |        ^^^^^^
    |
    = note: the following trait bounds were not satisfied:
            `Value: Eq`
-           `Value: PartialEq`
-           which is required by `Value: Eq`
            `Value: Hash`
 help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
    |
@@ -22,7 +20,7 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
   --> $DIR/issue-91550.rs:26:9
    |
 LL | pub struct NoDerives;
-   | -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq`
+   | -------------------- doesn't satisfy `NoDerives: Eq`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_eq` not found for this struct
@@ -37,9 +35,6 @@ LL | impl<T: Eq> Object<T> {
    |         ^^  ---------
    |         |
    |         unsatisfied trait bound introduced here
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: PartialEq`
-           which is required by `NoDerives: Eq`
 help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
    |
 LL + #[derive(Eq, PartialEq)]
@@ -50,7 +45,7 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it
   --> $DIR/issue-91550.rs:27:9
    |
 LL | pub struct NoDerives;
-   | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
+   | -------------------- doesn't satisfy `NoDerives: Ord`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_ord` not found for this struct
@@ -65,13 +60,6 @@ LL | impl<T: Ord> Object<T> {
    |         ^^^  ---------
    |         |
    |         unsatisfied trait bound introduced here
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: PartialOrd`
-           which is required by `NoDerives: Ord`
-           `NoDerives: PartialEq`
-           which is required by `NoDerives: Ord`
-           `NoDerives: Eq`
-           which is required by `NoDerives: Ord`
 help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
    |
 LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
@@ -82,7 +70,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD
   --> $DIR/issue-91550.rs:28:9
    |
 LL | pub struct NoDerives;
-   | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd`
+   | -------------------- doesn't satisfy `NoDerives: Ord` or `NoDerives: PartialOrd`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_ord_and_partial_ord` not found for this struct
@@ -100,13 +88,6 @@ LL | impl<T: Ord + PartialOrd> Object<T> {
    |         |     |
    |         |     unsatisfied trait bound introduced here
    |         unsatisfied trait bound introduced here
-   = note: the following trait bounds were not satisfied:
-           `NoDerives: PartialEq`
-           which is required by `NoDerives: Ord`
-           `NoDerives: Eq`
-           which is required by `NoDerives: Ord`
-           `NoDerives: PartialEq`
-           which is required by `NoDerives: PartialOrd`
 help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
    |
 LL + #[derive(Eq, Ord, PartialEq, PartialOrd)]
diff --git a/tests/ui/impl-trait/issues/issue-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs
index 11a75737e55..bd48c51c065 100644
--- a/tests/ui/impl-trait/issues/issue-62742.rs
+++ b/tests/ui/impl-trait/issues/issue-62742.rs
@@ -3,7 +3,7 @@ use std::marker::PhantomData;
 fn _alias_check() {
     WrongImpl::foo(0i32);
     //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
-    //~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
+    //~| ERROR the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied
     WrongImpl::<()>::foo(0i32);
     //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
     //~| ERROR trait bounds were not satisfied
diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr
index 9ec581c231b..f6798f55a47 100644
--- a/tests/ui/impl-trait/issues/issue-62742.stderr
+++ b/tests/ui/impl-trait/issues/issue-62742.stderr
@@ -1,30 +1,27 @@
-error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
-  --> $DIR/issue-62742.rs:4:5
+error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied
+  --> $DIR/issue-62742.rs:4:16
    |
 LL |     WrongImpl::foo(0i32);
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
+   |                ^^^ function or associated item cannot be called on `SafeImpl<_, RawImpl<_>>` due to unsatisfied trait bounds
+...
+LL | pub struct RawImpl<T>(PhantomData<T>);
+   | --------------------- doesn't satisfy `RawImpl<_>: Raw<_>`
+...
+LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
+   | ----------------------------------------- function or associated item `foo` not found for this struct
    |
-   = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
-note: required by a bound in `SafeImpl::<T, A>::foo`
+note: trait bound `RawImpl<_>: Raw<_>` was not satisfied
   --> $DIR/issue-62742.rs:29:20
    |
 LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
-   |                    ^^^^^^ required by this bound in `SafeImpl::<T, A>::foo`
-LL |     pub fn foo(value: A::Value) {}
-   |            --- required by a bound in this associated function
-
-error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
-  --> $DIR/issue-62742.rs:4:5
-   |
-LL |     WrongImpl::foo(0i32);
-   |     ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
-   |
-   = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
-note: required by a bound in `SafeImpl`
-  --> $DIR/issue-62742.rs:27:35
+   |                    ^^^^^^  --------------
+   |                    |
+   |                    unsatisfied trait bound introduced here
+note: the trait `Raw` must be implemented
+  --> $DIR/issue-62742.rs:13:1
    |
-LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
-   |                                   ^^^^^^ required by this bound in `SafeImpl`
+LL | pub trait Raw<T: ?Sized> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
   --> $DIR/issue-62742.rs:7:22
@@ -51,6 +48,19 @@ note: the trait `Raw` must be implemented
 LL | pub trait Raw<T: ?Sized> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
+  --> $DIR/issue-62742.rs:4:5
+   |
+LL |     WrongImpl::foo(0i32);
+   |     ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
+   |
+   = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
+note: required by a bound in `SafeImpl`
+  --> $DIR/issue-62742.rs:27:35
+   |
+LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
+   |                                   ^^^^^^ required by this bound in `SafeImpl`
+
 error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
   --> $DIR/issue-62742.rs:7:5
    |
diff --git a/tests/ui/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs
index 85d9d461fd9..f2f1835dc34 100644
--- a/tests/ui/impl-trait/issues/issue-84073.rs
+++ b/tests/ui/impl-trait/issues/issue-84073.rs
@@ -29,5 +29,6 @@ where
 }
 
 fn main() {
-    Race::new(|race| race.when()); //~ ERROR overflow assigning `_` to `Option<_>`
+    Race::new(|race| race.when());
+    //~^ ERROR the method `when` exists for struct `RaceBuilder<_, Never<_>>`, but its trait bounds were not satisfied
 }
diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr
index ab119a8a4f4..eeb23b13081 100644
--- a/tests/ui/impl-trait/issues/issue-84073.stderr
+++ b/tests/ui/impl-trait/issues/issue-84073.stderr
@@ -1,9 +1,29 @@
-error[E0275]: overflow assigning `_` to `Option<_>`
-  --> $DIR/issue-84073.rs:32:22
+error[E0599]: the method `when` exists for struct `RaceBuilder<_, Never<_>>`, but its trait bounds were not satisfied
+  --> $DIR/issue-84073.rs:32:27
    |
+LL | pub struct Never<T>(PhantomData<T>);
+   | ------------------- doesn't satisfy `Never<_>: StatefulFuture<Option<_>>`
+...
+LL | pub struct RaceBuilder<F, S> {
+   | ---------------------------- method `when` not found for this struct
+...
 LL |     Race::new(|race| race.when());
-   |                      ^^^^
+   |                           ^^^^ method cannot be called on `RaceBuilder<_, Never<_>>` due to unsatisfied trait bounds
+   |
+note: trait bound `Never<_>: StatefulFuture<Option<_>>` was not satisfied
+  --> $DIR/issue-84073.rs:14:8
+   |
+LL | impl<T, F> RaceBuilder<T, F>
+   |            -----------------
+LL | where
+LL |     F: StatefulFuture<Option<T>>,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
+note: the trait `StatefulFuture` must be implemented
+  --> $DIR/issue-84073.rs:3:1
+   |
+LL | pub trait StatefulFuture<S> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
index 84247a42704..0468e0522d1 100644
--- a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
+++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
@@ -6,6 +6,7 @@ LL |     let _result = &Some(42).as_deref();
    |
    = note: the following trait bounds were not satisfied:
            `{integer}: Deref`
+           which is required by `<{integer} as Deref>::Target = _`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
index bf05ab5665c..cf4e866901c 100644
--- a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
+++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
@@ -6,6 +6,7 @@ LL |     let _result = &mut Some(42).as_deref_mut();
    |
    = note: the following trait bounds were not satisfied:
            `{integer}: Deref`
+           which is required by `<{integer} as Deref>::Target = _`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
index ac744a6d3b6..0e3e7999044 100644
--- a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
+++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
@@ -6,6 +6,7 @@ LL |     let _result = &Ok(42).as_deref();
    |
    = note: the following trait bounds were not satisfied:
            `{integer}: Deref`
+           which is required by `<{integer} as Deref>::Target = _`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
index 688d2cf3486..43143db0da7 100644
--- a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
+++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
@@ -6,6 +6,7 @@ LL |     let _result = &mut Ok(42).as_deref_mut();
    |
    = note: the following trait bounds were not satisfied:
            `{integer}: Deref`
+           which is required by `<{integer} as Deref>::Target = _`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/methods/fulfillment-disqualifies-method.rs b/tests/ui/methods/fulfillment-disqualifies-method.rs
new file mode 100644
index 00000000000..639e1c7fc5c
--- /dev/null
+++ b/tests/ui/methods/fulfillment-disqualifies-method.rs
@@ -0,0 +1,32 @@
+// Tests that using fulfillment in the trait solver means that we detect that a
+// method is impossible, leading to no ambiguity.
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#[derive(Default)]
+struct W<A, B>(A, B);
+
+trait Constrain {
+    type Output;
+}
+
+impl Constrain for i32 {
+    type Output = u32;
+}
+
+trait Impossible {}
+
+impl<A, B> W<A, B> where A: Constrain<Output = B>, B: Impossible {
+    fn method(&self) {}
+}
+
+impl W<i32, u32> {
+    fn method(&self) {}
+}
+
+fn main() {
+    let w: W<i32, _> = W::default();
+    w.method();
+}
diff --git a/tests/ui/methods/leak-check-disquality.rs b/tests/ui/methods/leak-check-disquality.rs
new file mode 100644
index 00000000000..d3b7dd4b807
--- /dev/null
+++ b/tests/ui/methods/leak-check-disquality.rs
@@ -0,0 +1,26 @@
+// Tests that using fulfillment in the trait solver means that we detect that a
+// method is impossible, leading to no ambiguity.
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+struct W<T, U>(Option<T>, Option<U>);
+
+impl<'a> W<fn(&'a ()), u32> {
+    fn method(&self) {}
+}
+
+trait Leak {}
+impl<T: Fn(&())> Leak for T {}
+
+impl<T: Leak> W<T, i32> {
+    fn method(&self) {}
+}
+
+fn test<'a>() {
+    let x: W<fn(&'a ()), _> = W(None, None);
+    x.method();
+}
+
+fn main() {}
diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr
index ffaa276b62e..5b8332016de 100644
--- a/tests/ui/mismatched_types/issue-36053-2.stderr
+++ b/tests/ui/mismatched_types/issue-36053-2.stderr
@@ -21,14 +21,16 @@ error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, {cl
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
    |                                       ---------       ^^^^^ method cannot be called due to unsatisfied trait bounds
    |                                       |
-   |                                       doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` or `_: FnMut<(&&str,)>`
+   |                                       doesn't satisfy `_: FnMut<(&&str,)>` or `_: FnOnce<(&&str,)>`
    |
    = note: the following trait bounds were not satisfied:
-           `<{closure@$DIR/issue-36053-2.rs:7:39: 7:48} as FnOnce<(&&str,)>>::Output = bool`
-           which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
            `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>`
            which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
-           `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
+           `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>`
+           which is required by `Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
+           `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>`
+           which is required by `&mut Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
+           `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>`
            which is required by `&mut Filter<Fuse<std::iter::Once<&str>>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr
index f73bff51e7a..3bfdd4da6da 100644
--- a/tests/ui/missing-trait-bounds/issue-35677.stderr
+++ b/tests/ui/missing-trait-bounds/issue-35677.stderr
@@ -6,8 +6,6 @@ LL |     this.is_subset(other)
    |
    = note: the following trait bounds were not satisfied:
            `T: Eq`
-           `T: PartialEq`
-           which is required by `T: Eq`
            `T: Hash`
 help: consider restricting the type parameters to satisfy the trait bounds
    |
diff --git a/tests/ui/nll/issue-57362-2.rs b/tests/ui/nll/issue-57362-2.rs
index a0b0ea1d038..bc0d0f5291f 100644
--- a/tests/ui/nll/issue-57362-2.rs
+++ b/tests/ui/nll/issue-57362-2.rs
@@ -19,7 +19,8 @@ impl<'a> X for fn(&'a ()) {
 }
 
 fn g() {
-    let x = <fn (&())>::make_g(); //~ ERROR the function
+    let x = <fn (&())>::make_g();
+    //~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
 }
 
 fn main() {}
diff --git a/tests/ui/nll/issue-57362-2.stderr b/tests/ui/nll/issue-57362-2.stderr
index 57477f5341e..a78c96dbd0d 100644
--- a/tests/ui/nll/issue-57362-2.stderr
+++ b/tests/ui/nll/issue-57362-2.stderr
@@ -1,11 +1,9 @@
-error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
+error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
   --> $DIR/issue-57362-2.rs:22:25
    |
 LL |     let x = <fn (&())>::make_g();
-   |                         ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
+   |                         ^^^^^^ function or associated item not found in `fn(&())`
    |
-   = note: the following trait bounds were not satisfied:
-           `for<'a> fn(&'a ()): X`
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `X` defines an item `make_g`, perhaps you need to implement it
   --> $DIR/issue-57362-2.rs:8:1
diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.rs b/tests/ui/nll/issue-57642-higher-ranked-subtype.rs
index eba859cde22..69187cab342 100644
--- a/tests/ui/nll/issue-57642-higher-ranked-subtype.rs
+++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.rs
@@ -28,7 +28,8 @@ impl<T> Y for fn(T) {
 }
 
 fn higher_ranked_region_has_lost_its_binder() {
-    let x = <fn (&())>::make_g(); //~ ERROR the function
+    let x = <fn (&())>::make_g();
+    //~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
 }
 
 fn magical() {
diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
index d1e94bc702c..998d06b7706 100644
--- a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
+++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
@@ -1,11 +1,9 @@
-error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
+error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope
   --> $DIR/issue-57642-higher-ranked-subtype.rs:31:25
    |
 LL |     let x = <fn (&())>::make_g();
-   |                         ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
+   |                         ^^^^^^ function or associated item not found in `fn(&())`
    |
-   = note: the following trait bounds were not satisfied:
-           `for<'a> fn(&'a ()): X`
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `X` defines an item `make_g`, perhaps you need to implement it
   --> $DIR/issue-57642-higher-ranked-subtype.rs:4:1
@@ -14,7 +12,7 @@ LL | trait X {
    | ^^^^^^^
 
 error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'a> fn(&'a ())` in the current scope
-  --> $DIR/issue-57642-higher-ranked-subtype.rs:35:25
+  --> $DIR/issue-57642-higher-ranked-subtype.rs:36:25
    |
 LL |     let x = <fn (&())>::make_f();
    |                         ^^^^^^ function or associated item not found in `fn(&())`
diff --git a/tests/ui/resolve/issue-85671.rs b/tests/ui/resolve/issue-85671.rs
index 54db03f774e..ac001cebda7 100644
--- a/tests/ui/resolve/issue-85671.rs
+++ b/tests/ui/resolve/issue-85671.rs
@@ -1,5 +1,3 @@
-//@ check-pass
-
 // Some trait with a function that returns a slice:
 pub trait AsSlice {
     type Element;
@@ -24,6 +22,7 @@ impl<Cont> A<Cont> {
         Self: AsSlice<Element = Coef>,
     {
         self.as_ref_a().as_ref_a();
+        //~^ ERROR no method named `as_ref_a` found for struct `A<&[Coef]>` in the current scope
     }
 
     pub fn as_ref_a<Coef>(&self) -> A<&[<Self as AsSlice>::Element]>
diff --git a/tests/ui/resolve/issue-85671.stderr b/tests/ui/resolve/issue-85671.stderr
new file mode 100644
index 00000000000..0571e600197
--- /dev/null
+++ b/tests/ui/resolve/issue-85671.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `as_ref_a` found for struct `A<&[Coef]>` in the current scope
+  --> $DIR/issue-85671.rs:24:25
+   |
+LL | pub struct A<Cont>(Cont);
+   | ------------------ method `as_ref_a` not found for this struct
+...
+LL |         self.as_ref_a().as_ref_a();
+   |         ----            ^^^^^^^^ method not found in `A<&[Coef]>`
+   |         |
+   |         method `as_ref_a` is available on `&A<Cont>`
+   |
+   = note: the method was found for
+           - `A<Cont>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr
index 9d6d29ec74e..ae3a0391eea 100644
--- a/tests/ui/suggestions/derive-trait-for-method-call.stderr
+++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr
@@ -74,22 +74,30 @@ LL | struct Struct {
 error[E0599]: the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied
   --> $DIR/derive-trait-for-method-call.rs:40:15
    |
+LL | enum Enum {
+   | --------- doesn't satisfy `Enum: Clone`
+...
 LL | struct Foo<X, Y> (X, Y);
    | ---------------- method `test` not found for this struct
 ...
 LL |     let y = x.test();
    |               ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
    |
-note: the following trait bounds were not satisfied:
-      `Instant: Default`
-      `Vec<Enum>: Clone`
-  --> $DIR/derive-trait-for-method-call.rs:20:9
+note: trait bound `Instant: Default` was not satisfied
+  --> $DIR/derive-trait-for-method-call.rs:20:40
    |
 LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
-   |         ^^^^^                          ^^^^^^^  ---------
-   |         |                              |
-   |         |                              unsatisfied trait bound introduced here
-   |         unsatisfied trait bound introduced here
+   |                                        ^^^^^^^  ---------
+   |                                        |
+   |                                        unsatisfied trait bound introduced here
+   = note: the following trait bounds were not satisfied:
+           `Enum: Clone`
+           which is required by `Vec<Enum>: Clone`
+help: consider annotating `Enum` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | enum Enum {
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
index 74526b4dbc1..49a4db7491e 100644
--- a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
+++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
@@ -12,13 +12,6 @@ note: trait bound `(): Iterator` was not satisfied
    |
 LL | trait IteratorAlias = Iterator;
    |       -------------   ^^^^^^^^ unsatisfied trait bound introduced here
-note: trait bound `(): IteratorAlias` was not satisfied
-  --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9
-   |
-LL | impl<I: IteratorAlias> Foo<I> {
-   |         ^^^^^^^^^^^^^  ------
-   |         |
-   |         unsatisfied trait bound introduced here
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr
index 4d968e7bee1..38537619365 100644
--- a/tests/ui/traits/method-on-unbounded-type-param.stderr
+++ b/tests/ui/traits/method-on-unbounded-type-param.stderr
@@ -70,7 +70,7 @@ LL |     x.cmp(&x);
            which is required by `Box<dyn T>: Iterator`
            `dyn T: Ord`
            which is required by `Box<dyn T>: Ord`
-           `Box<dyn T>: Iterator`
+           `dyn T: Iterator`
            which is required by `&mut Box<dyn T>: Iterator`
            `dyn T: Iterator`
            which is required by `&mut dyn T: Iterator`
diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr
index 822fc91e43f..141f565077a 100644
--- a/tests/ui/traits/track-obligations.stderr
+++ b/tests/ui/traits/track-obligations.stderr
@@ -2,7 +2,10 @@ error[E0599]: the method `check` exists for struct `Client<()>`, but its trait b
   --> $DIR/track-obligations.rs:83:16
    |
 LL | struct ALayer<C>(C);
-   | ---------------- doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` or `ALayer<()>: ParticularServiceLayer<()>`
+   | ---------------- doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
+...
+LL | struct AService;
+   | --------------- doesn't satisfy `<AService as Service<Req>>::Response = Res`
 ...
 LL | struct Client<C>(C);
    | ---------------- method `check` not found for this struct
@@ -10,27 +13,14 @@ LL | struct Client<C>(C);
 LL |     Client(()).check();
    |                ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds
    |
-note: trait bound `<ALayer<()> as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` was not satisfied
-  --> $DIR/track-obligations.rs:35:14
-   |
-LL | pub trait ParticularServiceLayer<C>:
-   |           ----------------------
-LL |     Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
-note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied
-  --> $DIR/track-obligations.rs:71:16
+note: trait bound `<AService as Service<Req>>::Response = Res` was not satisfied
+  --> $DIR/track-obligations.rs:24:21
    |
-LL | impl<C> Client<C>
-   |         ---------
+LL | impl<T> ParticularService for T
+   |         -----------------     -
 LL | where
-LL |     ALayer<C>: ParticularServiceLayer<C>,
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
-note: the trait `ParticularServiceLayer` must be implemented
-  --> $DIR/track-obligations.rs:34:1
-   |
-LL | / pub trait ParticularServiceLayer<C>:
-LL | |     Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
-   | |____________________________________________________________________^
+LL |     T: Service<Req, Response = Res>,
+   |                     ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
 
 error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res`
   --> $DIR/track-obligations.rs:87:11
diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr
index 0983147a5f0..5fee16b5e89 100644
--- a/tests/ui/typeck/issue-31173.stderr
+++ b/tests/ui/typeck/issue-31173.stderr
@@ -39,7 +39,7 @@ LL | |         .collect();
    = note: the following trait bounds were not satisfied:
            `<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_`
            which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator`
-           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator`
+           `<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_`
            which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator`
 
 error: aborting due to 2 previous errors