prefer universal from lower universe

In case a variable is unified with two universal regions from different
universes, use the one with the lower universe as it has a higher chance
of being compatible with the variable.
This commit is contained in:
Ali MJ Al-Nasrawy 2023-03-08 14:17:58 +03:00
parent 228f40820d
commit 0b232d022f

View File

@ -57,11 +57,27 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
type Error = NoError;
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
// We pick the value of the least universe because it is compatible with more variables.
// This is *not* neccessary for soundness, but it allows more region variables to be
// resolved to the said value.
#[cold]
fn min_universe<'tcx>(r1: Region<'tcx>, r2: Region<'tcx>) -> Region<'tcx> {
cmp::min_by_key(r1, r2, |r| match r.kind() {
ty::ReStatic
| ty::ReErased
| ty::ReFree(..)
| ty::ReEarlyBound(..)
| ty::ReError(_) => ty::UniverseIndex::ROOT,
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReVar(..) | ty::ReLateBound(..) => bug!("not a universal region"),
})
}
Ok(match (value1.value, value2.value) {
// Here we can just pick one value, because the full constraints graph
// will be handled later. Ideally, we might want a `MultipleValues`
// variant or something. For now though, this is fine.
(Some(_), Some(_)) => *value1,
(Some(val1), Some(val2)) => Self { value: Some(min_universe(val1, val2)) },
(Some(_), _) => *value1,
(_, Some(_)) => *value2,