about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-03-19 16:52:57 +0100
committerGitHub <noreply@github.com>2025-03-19 16:52:57 +0100
commit9ab2a0e353f44eaa1df4246006dbc693f8e24899 (patch)
tree86dd5392267171047c4e2a7302e27897a95b28c0 /compiler/rustc_trait_selection/src
parentc3f74bcb39849b10c8b336db18530c79d7cb8701 (diff)
parent14cd467001aa5324fb3b067c80debfffda12c527 (diff)
Rollup merge of #138594 - oli-obk:no-select, r=lcnr
Fix next solver handling of shallow trait impl check

I'm trying to remove unnecessary direct calls to `select`, and this one seemed like a good place to start 😆

r? `@compiler-errors` or `@lcnr`
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs30
1 files changed, 18 insertions, 12 deletions
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 5cf0600ade8..84ac229b743 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -15,7 +15,7 @@ use tracing::instrument;
 
 use crate::infer::at::ToTrace;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt, SelectionContext};
+use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt};
 
 #[extension(pub trait InferCtxtExt<'tcx>)]
 impl<'tcx> InferCtxt<'tcx> {
@@ -122,9 +122,6 @@ impl<'tcx> InferCtxt<'tcx> {
     /// - If this returns `Some([errors..])`, then the trait has an impl for
     /// the self type, but some nested obligations do not hold.
     /// - If this returns `None`, no implementation that applies could be found.
-    ///
-    /// FIXME(-Znext-solver): Due to the recursive nature of the new solver,
-    /// this will probably only ever return `Some([])` or `None`.
     fn type_implements_trait_shallow(
         &self,
         trait_def_id: DefId,
@@ -132,20 +129,29 @@ impl<'tcx> InferCtxt<'tcx> {
         param_env: ty::ParamEnv<'tcx>,
     ) -> Option<Vec<traits::FulfillmentError<'tcx>>> {
         self.probe(|_snapshot| {
-            let mut selcx = SelectionContext::new(self);
-            match selcx.select(&Obligation::new(
+            let ocx = ObligationCtxt::new_with_diagnostics(self);
+            ocx.register_obligation(Obligation::new(
                 self.tcx,
                 ObligationCause::dummy(),
                 param_env,
                 ty::TraitRef::new(self.tcx, trait_def_id, [ty]),
-            )) {
-                Ok(Some(selection)) => {
-                    let ocx = ObligationCtxt::new_with_diagnostics(self);
-                    ocx.register_obligations(selection.nested_obligations());
-                    Some(ocx.select_all_or_error())
+            ));
+            let errors = ocx.select_where_possible();
+            // Find the original predicate in the list of predicates that could definitely not be fulfilled.
+            // If it is in that list, then we know this doesn't even shallowly implement the trait.
+            // If it is not in that list, it was fulfilled, but there may be nested obligations, which we don't care about here.
+            for error in &errors {
+                let Some(trait_clause) = error.obligation.predicate.as_trait_clause() else {
+                    continue;
+                };
+                let Some(bound_ty) = trait_clause.self_ty().no_bound_vars() else { continue };
+                if trait_clause.def_id() == trait_def_id
+                    && ocx.eq(&ObligationCause::dummy(), param_env, bound_ty, ty).is_ok()
+                {
+                    return None;
                 }
-                Ok(None) | Err(_) => None,
             }
+            Some(errors)
         })
     }
 }