about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/infer/freshen.rs114
1 files changed, 92 insertions, 22 deletions
diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs
index a45f01043f3..b43f78efffb 100644
--- a/src/librustc/infer/freshen.rs
+++ b/src/librustc/infer/freshen.rs
@@ -31,6 +31,7 @@
 //! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type
 //! inferencer knows "so far".
 
+use crate::mir::interpret::ConstValue;
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use crate::ty::fold::TypeFolder;
 use crate::util::nodemap::FxHashMap;
@@ -42,8 +43,10 @@ use super::unify_key::ToType;
 
 pub struct TypeFreshener<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    freshen_count: u32,
-    freshen_map: FxHashMap<ty::InferTy, Ty<'tcx>>,
+    ty_freshen_count: u32,
+    const_freshen_count: u32,
+    ty_freshen_map: FxHashMap<ty::InferTy, Ty<'tcx>>,
+    const_freshen_map: FxHashMap<ty::InferConst<'tcx>, &'tcx ty::LazyConst<'tcx>>,
 }
 
 impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> {
@@ -51,33 +54,63 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> {
                -> TypeFreshener<'a, 'gcx, 'tcx> {
         TypeFreshener {
             infcx,
-            freshen_count: 0,
-            freshen_map: Default::default(),
+            ty_freshen_count: 0,
+            const_freshen_count: 0,
+            ty_freshen_map: Default::default(),
+            const_freshen_map: Default::default(),
         }
     }
 
-    fn freshen<F>(&mut self,
-                  opt_ty: Option<Ty<'tcx>>,
-                  key: ty::InferTy,
-                  freshener: F)
-                  -> Ty<'tcx> where
+    fn freshen_ty<F>(
+        &mut self,
+        opt_ty: Option<Ty<'tcx>>,
+        key: ty::InferTy,
+        freshener: F,
+    ) -> Ty<'tcx>
+    where
         F: FnOnce(u32) -> ty::InferTy,
     {
         if let Some(ty) = opt_ty {
             return ty.fold_with(self);
         }
 
-        match self.freshen_map.entry(key) {
+        match self.ty_freshen_map.entry(key) {
             Entry::Occupied(entry) => *entry.get(),
             Entry::Vacant(entry) => {
-                let index = self.freshen_count;
-                self.freshen_count += 1;
+                let index = self.ty_freshen_count;
+                self.ty_freshen_count += 1;
                 let t = self.infcx.tcx.mk_ty_infer(freshener(index));
                 entry.insert(t);
                 t
             }
         }
     }
+
+    fn freshen_const<F>(
+        &mut self,
+        opt_ct: Option<&'tcx ty::LazyConst<'tcx>>,
+        key: ty::InferConst<'tcx>,
+        freshener: F,
+        ty: Ty<'tcx>,
+    ) -> &'tcx ty::LazyConst<'tcx>
+    where
+        F: FnOnce(u32) -> ty::InferConst<'tcx>,
+    {
+        if let Some(ct) = opt_ct {
+            return ct.fold_with(self);
+        }
+
+        match self.const_freshen_map.entry(key) {
+            Entry::Occupied(entry) => *entry.get(),
+            Entry::Vacant(entry) => {
+                let index = self.const_freshen_count;
+                self.const_freshen_count += 1;
+                let ct = self.infcx.tcx.mk_const_infer(freshener(index), ty);
+                entry.insert(ct);
+                ct
+            }
+        }
+    }
 }
 
 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
@@ -124,14 +157,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
         match t.sty {
             ty::Infer(ty::TyVar(v)) => {
                 let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known();
-                self.freshen(
+                self.freshen_ty(
                     opt_ty,
                     ty::TyVar(v),
                     ty::FreshTy)
             }
 
             ty::Infer(ty::IntVar(v)) => {
-                self.freshen(
+                self.freshen_ty(
                     self.infcx.int_unification_table.borrow_mut()
                                                     .probe_value(v)
                                                     .map(|v| v.to_type(tcx)),
@@ -140,7 +173,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
             }
 
             ty::Infer(ty::FloatVar(v)) => {
-                self.freshen(
+                self.freshen_ty(
                     self.infcx.float_unification_table.borrow_mut()
                                                       .probe_value(v)
                                                       .map(|v| v.to_type(tcx)),
@@ -148,14 +181,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
                     ty::FreshFloatTy)
             }
 
-            ty::Infer(ty::FreshTy(c)) |
-            ty::Infer(ty::FreshIntTy(c)) |
-            ty::Infer(ty::FreshFloatTy(c)) => {
-                if c >= self.freshen_count {
+            ty::Infer(ty::FreshTy(ct)) |
+            ty::Infer(ty::FreshIntTy(ct)) |
+            ty::Infer(ty::FreshFloatTy(ct)) => {
+                if ct >= self.ty_freshen_count {
                     bug!("Encountered a freshend type with id {} \
                           but our counter is only at {}",
-                         c,
-                         self.freshen_count);
+                         ct,
+                         self.ty_freshen_count);
                 }
                 t
             }
@@ -194,6 +227,43 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
-        ct // FIXME(const_generics)
+        if let ty::LazyConst::Evaluated(ty::Const{ val, ty }) = ct {
+            match val {
+                ConstValue::Infer(ty::InferConst::Var(v)) => {
+                    let opt_ct = self.infcx.const_unification_table
+                        .borrow_mut()
+                        .probe(*v)
+                        .known();
+                    return self.freshen_const(
+                        opt_ct,
+                        ty::InferConst::Var(*v),
+                        ty::InferConst::Fresh,
+                        ty,
+                    );
+                }
+                ConstValue::Infer(ty::InferConst::Fresh(i)) => {
+                    if *i >= self.const_freshen_count {
+                        bug!(
+                            "Encountered a freshend const with id {} \
+                                but our counter is only at {}",
+                            i,
+                            self.const_freshen_count,
+                        );
+                    }
+                    return ct;
+                }
+
+                ConstValue::Infer(ty::InferConst::Canonical(..)) => {
+                    bug!("unexpected const {:?}", ct)
+                }
+
+                ConstValue::Param(_) |
+                ConstValue::Scalar(_) |
+                ConstValue::Slice(..) |
+                ConstValue::ByRef(..) => {}
+            }
+        }
+
+        ct.super_fold_with(self)
     }
 }