1
Fork 0

Prefer lower TraitUpcasting candidates

This commit is contained in:
Michael Goulet 2025-01-14 17:54:53 +00:00
parent 2ae9916816
commit bf545ce2fe
6 changed files with 54 additions and 6 deletions

View file

@ -117,6 +117,10 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(a)),
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(b)),
) => a >= b,
(
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(a)),
CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(b)),
) => a >= b,
// Prefer dyn candidates over non-dyn candidates. This is necessary to
// handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`.
(

View file

@ -1090,7 +1090,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)?
.expect("did not expect ambiguity during confirmation");
Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting, nested))
Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting(idx), nested))
}
fn confirm_builtin_unsize_candidate(

View file

@ -1895,6 +1895,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
Some(None) => {}
None => return None,
}
// Same for upcasting.
let upcast_bound = candidates
.iter()
.filter_map(|c| {
if let TraitUpcastingUnsizeCandidate(i) = c.candidate { Some(i) } else { None }
})
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
match upcast_bound {
Some(Some(index)) => return Some(TraitUpcastingUnsizeCandidate(index)),
Some(None) => {}
None => return None,
}
// Finally, handle overlapping user-written impls.
let impls = candidates.iter().filter_map(|c| {