Winnow specializing impls

This commit is contained in:
Michael Goulet 2023-07-04 18:06:41 +00:00
parent 9227ff28af
commit d2a1803d6f
3 changed files with 37 additions and 4 deletions

View file

@ -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)
),
}

View file

@ -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,
}
}

View file

@ -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();
}