cleanup: extract a helper for coercion from inference variables

This commit is contained in:
Niko Matsakis 2020-11-21 05:45:13 -05:00 committed by Mark Rousskov
parent 5eca626e40
commit 5a8edc0b76

View file

@ -146,6 +146,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
// First, remove any resolved type variables (at the top level, at least):
let a = self.shallow_resolve(a);
let b = self.shallow_resolve(b);
debug!("Coerce.tys({:?} => {:?})", a, b);
@ -155,6 +156,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
return success(vec![], self.fcx.tcx.ty_error(), vec![]);
}
// Coercing from `!` to any type is allowed:
if a.is_never() {
// Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
// type variable, we want `?T` to fallback to `!` if not
@ -176,6 +178,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
};
}
// Coercing *from* an unresolved inference variable means that
// we have no information about the source type. This will always
// ultimately fall back to some form of subtyping.
if a.is_ty_var() {
return self.coerce_from_inference_variable(a, b);
}
// Consider coercing the subtype to a DST
//
// NOTE: this is wrapped in a `commit_if_ok` because it creates
@ -233,6 +242,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
}
/// Coercing *from* an inference variable. In this case, we have no information
/// about the source type, so we can't really do a true coercion and we always
/// fall back to subtyping (`unify_and`).
fn coerce_from_inference_variable(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
assert!(a.is_ty_var() && self.infcx.shallow_resolve(a) == a);
assert!(self.infcx.shallow_resolve(b) == b);
self.unify_and(a, b, identity)
}
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
/// To match `A` with `B`, autoderef will be performed,
/// calling `deref`/`deref_mut` where necessary.