Skip to content

Commit

Permalink
cleanup: extract a helper for coercion from inference variables
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis authored and Mark-Simulacrum committed Aug 19, 2021
1 parent 5eca626 commit 5a8edc0
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions compiler/rustc_typeck/src/check/coercion.rs
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 5a8edc0

Please sign in to comment.