about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2020-11-21 05:45:13 -0500
committerMark Rousskov <mark.simulacrum@gmail.com>2021-08-19 17:28:24 -0400
commit5a8edc0b7607b997dd926b5d882cd39000386cdc (patch)
tree9403e68ddc795ffead57a23995637d8943e69a08
parent5eca626e4025fc4f4695aeba03cd60b344001378 (diff)
downloadrust-5a8edc0b7607b997dd926b5d882cd39000386cdc.tar.gz
rust-5a8edc0b7607b997dd926b5d882cd39000386cdc.zip
cleanup: extract a helper for coercion from inference variables
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs19
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.