]> git.lizzy.rs Git - rust.git/commitdiff
Handle placeholder types in canonicalization
authorscalexm <alexandre@scalexm.fr>
Fri, 2 Nov 2018 18:46:30 +0000 (19:46 +0100)
committerscalexm <alexandre@scalexm.fr>
Sat, 24 Nov 2018 00:24:40 +0000 (01:24 +0100)
src/librustc/ich/impls_ty.rs
src/librustc/infer/canonical/canonicalizer.rs
src/librustc/infer/canonical/mod.rs
src/librustc/infer/mod.rs
src/librustc/infer/type_variable.rs

index 4b465c7ad54a94e41b3c31d11dbd75db55b4c8d5..e9fac5b923961da4d4f60f1db1737d623736d742 100644 (file)
@@ -1099,12 +1099,13 @@ struct infer::canonical::CanonicalVarValues<'tcx> {
 
 impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
     Ty(k),
+    PlaceholderTy(placeholder),
     Region(ui),
     PlaceholderRegion(placeholder),
 });
 
 impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
-    General,
+    General(ui),
     Int,
     Float
 });
index a9c6c3b50853dbbbefcf54b4aba444c1a7e07813..7a9527573c7d69aa33ceeaf3b119bafb1a6c5da4 100644 (file)
@@ -339,11 +339,35 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match t.sty {
-            ty::Infer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t),
+            ty::Infer(ty::TyVar(vid)) => {
+                match self.infcx.unwrap().probe_ty_var(vid) {
+                    // `t` could be a float / int variable: canonicalize that instead
+                    Ok(t) => self.fold_ty(t),
+
+                    // `TyVar(vid)` is unresolved, track its universe index in the canonicalized
+                    // result
+                    Err(ui) => self.canonicalize_ty_var(
+                        CanonicalVarInfo {
+                            kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
+                        },
+                        t
+                    )
+                }
+            }
 
-            ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t),
+            ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
+                CanonicalVarInfo {
+                    kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+                },
+                t
+            ),
 
-            ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t),
+            ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
+                CanonicalVarInfo {
+                    kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
+                },
+                t
+            ),
 
             ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
@@ -351,6 +375,13 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 bug!("encountered a fresh type during canonicalization")
             }
 
+            ty::Placeholder(placeholder) => self.canonicalize_ty_var(
+                CanonicalVarInfo {
+                    kind: CanonicalVarKind::PlaceholderTy(placeholder)
+                },
+                t
+            ),
+
             ty::Bound(bound_ty) => {
                 if bound_ty.index >= self.binder_index {
                     bug!("escaping bound type during canonicalization")
@@ -380,7 +411,6 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             | ty::Never
             | ty::Tuple(..)
             | ty::Projection(..)
-            | ty::Placeholder(..)
             | ty::UnnormalizedProjection(..)
             | ty::Foreign(..)
             | ty::Param(..)
@@ -579,15 +609,12 @@ fn canonical_var_for_region(
     /// if `ty_var` is bound to anything; if so, canonicalize
     /// *that*. Otherwise, create a new canonical variable for
     /// `ty_var`.
-    fn canonicalize_ty_var(&mut self, ty_kind: CanonicalTyVarKind, ty_var: Ty<'tcx>) -> Ty<'tcx> {
+    fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo, ty_var: Ty<'tcx>) -> Ty<'tcx> {
         let infcx = self.infcx.expect("encountered ty-var without infcx");
         let bound_to = infcx.shallow_resolve(ty_var);
         if bound_to != ty_var {
             self.fold_ty(bound_to)
         } else {
-            let info = CanonicalVarInfo {
-                kind: CanonicalVarKind::Ty(ty_kind),
-            };
             let var = self.canonical_var(info, ty_var.into());
             self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
         }
index 41839d61d32606d01c019742d02d636b5c5066f0..230f8958b33851f81326e8cf01c2a10ad567551b 100644 (file)
@@ -122,6 +122,7 @@ pub fn universe(&self) -> ty::UniverseIndex {
     pub fn is_existential(&self) -> bool {
         match self.kind {
             CanonicalVarKind::Ty(_) => true,
+            CanonicalVarKind::PlaceholderTy(_) => false,
             CanonicalVarKind::Region(_) => true,
             CanonicalVarKind::PlaceholderRegion(..) => false,
         }
@@ -136,6 +137,9 @@ pub enum CanonicalVarKind {
     /// Some kind of type inference variable.
     Ty(CanonicalTyVarKind),
 
+    /// A "placeholder" that represents "any type".
+    PlaceholderTy(ty::PlaceholderType),
+
     /// Region variable `'?R`.
     Region(ty::UniverseIndex),
 
@@ -148,12 +152,12 @@ pub enum CanonicalVarKind {
 impl CanonicalVarKind {
     pub fn universe(self) -> ty::UniverseIndex {
         match self {
-            // At present, we don't support higher-ranked
-            // quantification over types, so all type variables are in
-            // the root universe.
-            CanonicalVarKind::Ty(_) => ty::UniverseIndex::ROOT,
+            CanonicalVarKind::Ty(kind) => match kind {
+                CanonicalTyVarKind::General(ui) => ui,
+                CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
+            }
 
-            // Region variables can be created in sub-universes.
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
             CanonicalVarKind::Region(ui) => ui,
             CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
         }
@@ -168,7 +172,7 @@ pub fn universe(self) -> ty::UniverseIndex {
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
 pub enum CanonicalTyVarKind {
     /// General type variable `?T` that can be unified with arbitrary types.
-    General,
+    General(ty::UniverseIndex),
 
     /// Integral type variable `?I` (that can only be unified with integral types).
     Int,
@@ -358,8 +362,11 @@ fn instantiate_canonical_var(
         match cv_info.kind {
             CanonicalVarKind::Ty(ty_kind) => {
                 let ty = match ty_kind {
-                    CanonicalTyVarKind::General => {
-                        self.next_ty_var(TypeVariableOrigin::MiscVariable(span))
+                    CanonicalTyVarKind::General(ui) => {
+                        self.next_ty_var_in_universe(
+                            TypeVariableOrigin::MiscVariable(span),
+                            universe_map(ui)
+                        )
                     }
 
                     CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()),
@@ -369,6 +376,15 @@ fn instantiate_canonical_var(
                 ty.into()
             }
 
+            CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => {
+                let universe_mapped = universe_map(universe);
+                let placeholder_mapped = ty::PlaceholderType {
+                    universe: universe_mapped,
+                    name,
+                };
+                self.tcx.mk_ty(ty::Placeholder(placeholder_mapped)).into()
+            }
+
             CanonicalVarKind::Region(ui) => self.next_region_var_in_universe(
                 RegionVariableOrigin::MiscVariable(span),
                 universe_map(ui),
@@ -380,9 +396,7 @@ fn instantiate_canonical_var(
                     universe: universe_mapped,
                     name,
                 };
-                self.tcx
-                    .mk_region(ty::RePlaceholder(placeholder_mapped))
-                    .into()
+                self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
             }
         }
     }
index dfe6aa160b3ad2bbe97ae0f3838b63aa2ab5ce14..6f041fdfb0ac4a86e923d52d83085b2ac1475840 100644 (file)
@@ -972,6 +972,17 @@ pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
         self.tcx.mk_var(self.next_ty_var_id(false, origin))
     }
 
+    pub fn next_ty_var_in_universe(
+        &self,
+        origin: TypeVariableOrigin,
+        universe: ty::UniverseIndex
+    ) -> Ty<'tcx> {
+        let vid = self.type_variables
+            .borrow_mut()
+            .new_var(universe, false, origin);
+        self.tcx.mk_var(vid)
+    }
+
     pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
         self.tcx.mk_var(self.next_ty_var_id(true, origin))
     }
@@ -1227,6 +1238,17 @@ pub fn inlined_shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
+    /// If `TyVar(vid)` resolves to a type, return that type. Else, return the
+    /// universe index of `TyVar(vid)`.
+    pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
+        use self::type_variable::TypeVariableValue;
+
+        match self.type_variables.borrow_mut().probe(vid) {
+            TypeVariableValue::Known { value } => Ok(value),
+            TypeVariableValue::Unknown { universe } => Err(universe),
+        }
+    }
+
     pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
         self.inlined_shallow_resolve(typ)
     }
index bec19ba9099dce782ca07af507ecaaa5c371c858..5624961ea6e67a23dcf7aa23b22e881e5b3b31e6 100644 (file)
@@ -72,7 +72,7 @@ pub enum TypeVariableOrigin {
 
 struct TypeVariableData {
     origin: TypeVariableOrigin,
-    diverging: bool
+    diverging: bool,
 }
 
 #[derive(Copy, Clone, Debug)]