Winnow specializing impls
This commit is contained in:
parent
9227ff28af
commit
d2a1803d6f
3 changed files with 37 additions and 4 deletions
|
@ -410,8 +410,8 @@ impl<'tcx> Instance<'tcx> {
|
||||||
) -> Instance<'tcx> {
|
) -> Instance<'tcx> {
|
||||||
match ty::Instance::resolve(tcx, param_env, def_id, substs) {
|
match ty::Instance::resolve(tcx, param_env, def_id, substs) {
|
||||||
Ok(Some(instance)) => instance,
|
Ok(Some(instance)) => instance,
|
||||||
_ => bug!(
|
instance => bug!(
|
||||||
"failed to resolve instance for {}",
|
"failed to resolve instance for {}: {instance:#?}",
|
||||||
tcx.def_path_str_with_substs(def_id, substs)
|
tcx.def_path_str_with_substs(def_id, substs)
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,11 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < candidates.len() {
|
while i < candidates.len() {
|
||||||
let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| {
|
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 {
|
if should_drop_i {
|
||||||
candidates.swap_remove(i);
|
candidates.swap_remove(i);
|
||||||
|
@ -160,12 +164,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn candidate_should_be_dropped_in_favor_of<'tcx>(
|
fn candidate_should_be_dropped_in_favor_of<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
victim: &Candidate<'tcx>,
|
victim: &Candidate<'tcx>,
|
||||||
other: &Candidate<'tcx>,
|
other: &Candidate<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match (victim.source, other.source) {
|
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::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,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
tests/ui/traits/new-solver/winnow-specializing-impls.rs
Normal file
22
tests/ui/traits/new-solver/winnow-specializing-impls.rs
Normal 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();
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue