diff options
| author | Michael Goulet <michael@errs.io> | 2023-07-04 18:06:41 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-07-05 06:18:48 +0000 |
| commit | d2a1803d6fa30f102e2cce3c7f05da7a0d488eb1 (patch) | |
| tree | bbaaa2aa480bcddb6d651c8863668a761d94dea5 | |
| parent | 9227ff28aff55b252314076fcf21c9a66f10ac1e (diff) | |
| download | rust-d2a1803d6fa30f102e2cce3c7f05da7a0d488eb1.tar.gz rust-d2a1803d6fa30f102e2cce3c7f05da7a0d488eb1.zip | |
Winnow specializing impls
| -rw-r--r-- | compiler/rustc_middle/src/ty/instance.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs | 15 | ||||
| -rw-r--r-- | tests/ui/traits/new-solver/winnow-specializing-impls.rs | 22 |
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(); +} |
