diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2020-11-21 05:45:13 -0500 |
|---|---|---|
| committer | Mark Rousskov <mark.simulacrum@gmail.com> | 2021-08-19 17:28:24 -0400 |
| commit | 5a8edc0b7607b997dd926b5d882cd39000386cdc (patch) | |
| tree | 9403e68ddc795ffead57a23995637d8943e69a08 | |
| parent | 5eca626e4025fc4f4695aeba03cd60b344001378 (diff) | |
| download | rust-5a8edc0b7607b997dd926b5d882cd39000386cdc.tar.gz rust-5a8edc0b7607b997dd926b5d882cd39000386cdc.zip | |
cleanup: extract a helper for coercion from inference variables
| -rw-r--r-- | compiler/rustc_typeck/src/check/coercion.rs | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 0f39d2819ab..7e03ef18144 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -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. |
