Rollup merge of #113337 - 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

View File

@ -410,8 +410,8 @@ pub fn expect_resolve(
) -> 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 @@ fn select_in_new_trait_solver(
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 @@ fn compute_canonical_trait_candidates(
}
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();
}