about summary refs log tree commit diff
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
parentc3f74bcb39849b10c8b336db18530c79d7cb8701 (diff)
parent14cd467001aa5324fb3b067c80debfffda12c527 (diff)
downloadrust-9ab2a0e353f44eaa1df4246006dbc693f8e24899.tar.gz
rust-9ab2a0e353f44eaa1df4246006dbc693f8e24899.zip
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`
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs30
-rw-r--r--tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed (renamed from tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.fixed)9
-rw-r--r--tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr (renamed from tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr)4
-rw-r--r--tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed31
-rw-r--r--tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr25
-rw-r--r--tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs9
6 files changed, 86 insertions, 22 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)
         })
     }
 }
diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.fixed b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed
index 85b1853c23b..922c883f4f7 100644
--- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.fixed
+++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed
@@ -1,16 +1,17 @@
 //@ run-rustfix
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
 #![allow(unused_variables, dead_code)]
-use std::collections::BTreeMap;
-use std::collections::HashSet;
+use std::collections::{BTreeMap, HashSet};
 
-#[derive(Debug,Eq,PartialEq,Hash)]
+#[derive(Debug, Eq, PartialEq, Hash)]
 #[derive(Clone)]
 enum Day {
     Mon,
 }
 
 struct Class {
-    days: BTreeMap<u32, HashSet<Day>>
+    days: BTreeMap<u32, HashSet<Day>>,
 }
 
 impl Class {
diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr
index 6a9d76f7998..301f3c3a458 100644
--- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr
+++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39
+  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39
    |
 LL |             let mut x: HashSet<Day> = v.clone();
    |                        ------------   ^^^^^^^^^ expected `HashSet<Day>`, found `&HashSet<Day>`
@@ -9,7 +9,7 @@ LL |             let mut x: HashSet<Day> = v.clone();
    = note: expected struct `HashSet<_>`
            found reference `&HashSet<_>`
 note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead
-  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39
+  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39
    |
 LL |             let mut x: HashSet<Day> = v.clone();
    |                                       ^
diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed
new file mode 100644
index 00000000000..922c883f4f7
--- /dev/null
+++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed
@@ -0,0 +1,31 @@
+//@ run-rustfix
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+#![allow(unused_variables, dead_code)]
+use std::collections::{BTreeMap, HashSet};
+
+#[derive(Debug, Eq, PartialEq, Hash)]
+#[derive(Clone)]
+enum Day {
+    Mon,
+}
+
+struct Class {
+    days: BTreeMap<u32, HashSet<Day>>,
+}
+
+impl Class {
+    fn do_stuff(&self) {
+        for (_, v) in &self.days {
+            let mut x: HashSet<Day> = v.clone(); //~ ERROR
+            let y: Vec<Day> = x.drain().collect();
+            println!("{:?}", x);
+        }
+    }
+}
+
+fn fail() {
+    let c = Class { days: BTreeMap::new() };
+    c.do_stuff();
+}
+fn main() {}
diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr
new file mode 100644
index 00000000000..301f3c3a458
--- /dev/null
+++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39
+   |
+LL |             let mut x: HashSet<Day> = v.clone();
+   |                        ------------   ^^^^^^^^^ expected `HashSet<Day>`, found `&HashSet<Day>`
+   |                        |
+   |                        expected due to this
+   |
+   = note: expected struct `HashSet<_>`
+           found reference `&HashSet<_>`
+note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead
+  --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39
+   |
+LL |             let mut x: HashSet<Day> = v.clone();
+   |                                       ^
+   = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied
+help: consider annotating `Day` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | enum Day {
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs
index 740cda470d9..6f7b55be8bd 100644
--- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs
+++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs
@@ -1,15 +1,16 @@
 //@ run-rustfix
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
 #![allow(unused_variables, dead_code)]
-use std::collections::BTreeMap;
-use std::collections::HashSet;
+use std::collections::{BTreeMap, HashSet};
 
-#[derive(Debug,Eq,PartialEq,Hash)]
+#[derive(Debug, Eq, PartialEq, Hash)]
 enum Day {
     Mon,
 }
 
 struct Class {
-    days: BTreeMap<u32, HashSet<Day>>
+    days: BTreeMap<u32, HashSet<Day>>,
 }
 
 impl Class {