Skip to content

Commit

Permalink
Rollup merge of #113337 - compiler-errors:next-solver-winnow-speciali…
Browse files Browse the repository at this point in the history
…zing, 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``
  • Loading branch information
compiler-errors authored Jul 5, 2023
2 parents b2b1a50 + d2a1803 commit c31fe41
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
),
}
Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
}
}
Expand Down
22 changes: 22 additions & 0 deletions tests/ui/traits/new-solver/winnow-specializing-impls.rs
Original file line number Diff line number Diff line change
@@ -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();
}

0 comments on commit c31fe41

Please sign in to comment.