about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-07-04 18:06:41 +0000
committerMichael Goulet <michael@errs.io>2023-07-05 06:18:48 +0000
commitd2a1803d6fa30f102e2cce3c7f05da7a0d488eb1 (patch)
treebbaaa2aa480bcddb6d651c8863668a761d94dea5
parent9227ff28aff55b252314076fcf21c9a66f10ac1e (diff)
downloadrust-d2a1803d6fa30f102e2cce3c7f05da7a0d488eb1.tar.gz
rust-d2a1803d6fa30f102e2cce3c7f05da7a0d488eb1.zip
Winnow specializing impls
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs15
-rw-r--r--tests/ui/traits/new-solver/winnow-specializing-impls.rs22
3 files changed, 37 insertions, 4 deletions
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index c0d591430f7..96750e4ab85 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -410,8 +410,8 @@ impl<'tcx> Instance<'tcx> {
     ) -> Instance<'tcx> {
         match ty::Instance::resolve(tcx, param_env, def_id, substs) {
             Ok(Some(instance)) => instance,
-            _ => bug!(
-                "failed to resolve instance for {}",
+            instance => bug!(
+                "failed to resolve instance for {}: {instance:#?}",
                 tcx.def_path_str_with_substs(def_id, substs)
             ),
         }
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 466a03e2163..18332d6811d 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -52,7 +52,11 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
                 let mut i = 0;
                 while i < candidates.len() {
                     let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| {
-                        candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j])
+                        candidate_should_be_dropped_in_favor_of(
+                            ecx.tcx(),
+                            &candidates[i],
+                            &candidates[j],
+                        )
                     });
                     if should_drop_i {
                         candidates.swap_remove(i);
@@ -160,12 +164,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
 }
 
 fn candidate_should_be_dropped_in_favor_of<'tcx>(
+    tcx: TyCtxt<'tcx>,
     victim: &Candidate<'tcx>,
     other: &Candidate<'tcx>,
 ) -> bool {
     match (victim.source, other.source) {
-        (CandidateSource::ParamEnv(i), CandidateSource::ParamEnv(j)) => i >= j,
+        (CandidateSource::ParamEnv(victim_idx), CandidateSource::ParamEnv(other_idx)) => {
+            victim_idx >= other_idx
+        }
         (_, CandidateSource::ParamEnv(_)) => true,
+        (CandidateSource::Impl(victim_def_id), CandidateSource::Impl(other_def_id)) => {
+            tcx.specializes((other_def_id, victim_def_id))
+                && other.result.value.certainty == Certainty::Yes
+        }
         _ => false,
     }
 }
diff --git a/tests/ui/traits/new-solver/winnow-specializing-impls.rs b/tests/ui/traits/new-solver/winnow-specializing-impls.rs
new file mode 100644
index 00000000000..06f64de7403
--- /dev/null
+++ b/tests/ui/traits/new-solver/winnow-specializing-impls.rs
@@ -0,0 +1,22 @@
+// build-pass
+// compile-flags: -Ztrait-solver=next
+
+// Tests that the specializing impl `<() as Foo>` holds during codegen.
+
+#![feature(min_specialization)]
+
+trait Foo {
+    fn bar();
+}
+
+impl<T> Foo for T {
+    default fn bar() {}
+}
+
+impl Foo for () {
+    fn bar() {}
+}
+
+fn main() {
+    <() as Foo>::bar();
+}