Rollup merge of - compiler-errors:next-solver-winnow-specializing, r=lcnr

Winnow specialized impls during selection in new solver

We need to be able to winnow impls that are specialized by more specific impls in order for codegen to be able to proceed.

r? ``@lcnr``
This commit is contained in:
Michael Goulet 2023-07-05 08:45:45 -07:00 committed by GitHub
commit c31fe41453
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 4 deletions
compiler
rustc_middle/src/ty
rustc_trait_selection/src/solve/eval_ctxt
tests/ui/traits/new-solver

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

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

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