about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs18
-rw-r--r--tests/ui/traits/normalize-supertrait.rs3
2 files changed, 16 insertions, 5 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index 16fe045b82d..4d474b8e707 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -58,6 +58,12 @@ impl<'tcx> inspect::ProofTreeVisitor<'tcx> for Select {
             )));
         }
 
+        // Don't winnow until `Certainty::Yes` -- we don't need to winnow until
+        // codegen, and only on the good path.
+        if matches!(goal.result().unwrap(), Certainty::Maybe(..)) {
+            return ControlFlow::Break(Ok(None));
+        }
+
         // We need to winnow. See comments on `candidate_should_be_dropped_in_favor_of`.
         let mut i = 0;
         while i < candidates.len() {
@@ -86,7 +92,7 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
     other: &inspect::InspectCandidate<'_, 'tcx>,
 ) -> bool {
     // Don't winnow until `Certainty::Yes` -- we don't need to winnow until
-    // codegen, technically.
+    // codegen, and only on the good path.
     if matches!(other.result().unwrap(), Certainty::Maybe(..)) {
         return false;
     }
@@ -105,13 +111,15 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
             bug!("should not have assembled a CoherenceUnknowable candidate")
         }
 
+        // In the old trait solver, we arbitrarily choose lower vtable candidates
+        // over higher ones.
+        (
+            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base: a }),
+            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { vtable_base: b }),
+        ) => a >= b,
         // Prefer dyn candidates over non-dyn candidates. This is necessary to
         // handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`.
         (
-            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
-            CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
-        ) => false,
-        (
             CandidateSource::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound,
             CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
         ) => true,
diff --git a/tests/ui/traits/normalize-supertrait.rs b/tests/ui/traits/normalize-supertrait.rs
index 1ab2b8ecfc1..3ba4a8b8bab 100644
--- a/tests/ui/traits/normalize-supertrait.rs
+++ b/tests/ui/traits/normalize-supertrait.rs
@@ -4,6 +4,9 @@
 // comparing the supertrait `Derived<()>` to the expected trait.
 
 //@ build-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 trait Proj {
     type S;