]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/infer/combine.rs
Remove ty::BrFresh and new_bound
[rust.git] / src / librustc / infer / combine.rs
index 885b439ef1ca58c44c7eb4cfce5f05f438c7e327..048c0a7a8fd0a5cdba566f6ad5df6d0b967f55d1 100644 (file)
 use super::lub::Lub;
 use super::sub::Sub;
 use super::type_variable::TypeVariableValue;
+use super::unify_key::{ConstVarValue, ConstVariableValue, ConstVariableOrigin};
 
 use crate::hir::def_id::DefId;
+use crate::mir::interpret::ConstValue;
 use crate::ty::{IntType, UintType};
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt, InferConst};
 use crate::ty::error::TypeError;
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use crate::ty::subst::SubstsRef;
 use crate::traits::{Obligation, PredicateObligations};
 
 use syntax::ast;
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
 
 #[derive(Clone)]
 pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@@ -107,13 +109,69 @@ pub fn super_combine_tys<R>(&self,
                 Err(TypeError::Sorts(ty::relate::expected_found(relation, &a, &b)))
             }
 
-
             _ => {
                 ty::relate::super_relate_tys(relation, a, b)
             }
         }
     }
 
+    pub fn super_combine_consts<R>(
+        &self,
+        relation: &mut R,
+        a: &'tcx ty::Const<'tcx>,
+        b: &'tcx ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>>
+    where
+        R: TypeRelation<'infcx, 'gcx, 'tcx>,
+    {
+        let a_is_expected = relation.a_is_expected();
+
+        match (a.val, b.val) {
+            (ConstValue::Infer(InferConst::Var(a_vid)),
+                ConstValue::Infer(InferConst::Var(b_vid))) => {
+                self.const_unification_table
+                    .borrow_mut()
+                    .unify_var_var(a_vid, b_vid)
+                    .map_err(|e| const_unification_error(a_is_expected, e))?;
+                return Ok(a);
+            }
+
+            // All other cases of inference with other variables are errors.
+            (ConstValue::Infer(InferConst::Var(_)), ConstValue::Infer(_)) |
+            (ConstValue::Infer(_), ConstValue::Infer(InferConst::Var(_))) => {
+                bug!("tried to combine ConstValue::Infer/ConstValue::Infer(InferConst::Var)")
+            }
+
+            (ConstValue::Infer(InferConst::Var(vid)), _) => {
+                return self.unify_const_variable(a_is_expected, vid, b);
+            }
+
+            (_, ConstValue::Infer(InferConst::Var(vid))) => {
+                return self.unify_const_variable(!a_is_expected, vid, a);
+            }
+
+            _ => {}
+        }
+
+        ty::relate::super_relate_consts(relation, a, b)
+    }
+
+    pub fn unify_const_variable(
+        &self,
+        vid_is_expected: bool,
+        vid: ty::ConstVid<'tcx>,
+        value: &'tcx ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
+        self.const_unification_table
+            .borrow_mut()
+            .unify_var_value(vid, ConstVarValue {
+                origin: ConstVariableOrigin::ConstInference(DUMMY_SP),
+                val: ConstVariableValue::Known { value },
+            })
+            .map_err(|e| const_unification_error(vid_is_expected, e))?;
+        Ok(value)
+    }
+
     fn unify_integral_variable(&self,
                                vid_is_expected: bool,
                                vid: ty::IntVid,
@@ -407,7 +465,7 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
 
         debug!("generalize: t={:?}", t);
 
-        // Check to see whether the type we are genealizing references
+        // Check to see whether the type we are generalizing references
         // any other type variable related to `vid` via
         // subtyping. This is basically our "occurs check", preventing
         // us from creating infinitely sized types.
@@ -519,6 +577,29 @@ fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>)
         // very descriptive origin for this region variable.
         Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
     }
+
+    fn consts(
+        &mut self,
+        c: &'tcx ty::Const<'tcx>,
+        c2: &'tcx ty::Const<'tcx>
+    ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
+        assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
+
+        match c {
+            ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => {
+                let mut variable_table = self.infcx.const_unification_table.borrow_mut();
+                match variable_table.probe_value(*vid).val.known() {
+                    Some(u) => {
+                        self.relate(&u, &u)
+                    }
+                    None => Ok(c),
+                }
+            }
+            _ => {
+                relate::super_relate_consts(self, c, c)
+            }
+        }
+    }
 }
 
 pub trait RelateResultCompare<'tcx, T> {
@@ -540,6 +621,13 @@ fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> where
     }
 }
 
+pub fn const_unification_error<'tcx>(
+    a_is_expected: bool,
+    (a, b): (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>),
+) -> TypeError<'tcx> {
+    TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
+}
+
 fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::IntVarValue))
                                -> TypeError<'tcx>
 {