]> git.lizzy.rs Git - rust.git/commitdiff
Handle generic consts in relate and infer
authorvarkor <github@varkor.com>
Fri, 8 Mar 2019 01:20:33 +0000 (01:20 +0000)
committervarkor <github@varkor.com>
Wed, 1 May 2019 22:10:57 +0000 (23:10 +0100)
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
src/librustc/infer/canonical/query_response.rs
src/librustc/infer/resolve.rs
src/librustc/ty/relate.rs

index e605aae0fae0d39490553480f48e65e3e933b48b..65c579aedf2f44953f836a59e3206fb4e3501553 100644 (file)
@@ -16,6 +16,7 @@
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::InferCtxtBuilder;
 use crate::infer::{InferCtxt, InferOk, InferResult};
+use crate::mir::interpret::ConstValue;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::fmt::Debug;
@@ -25,7 +26,7 @@
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
 use crate::ty::fold::TypeFoldable;
 use crate::ty::subst::{Kind, UnpackedKind};
-use crate::ty::{self, BoundVar, Lift, Ty, TyCtxt};
+use crate::ty::{self, BoundVar, InferConst, Lift, Ty, TyCtxt};
 use crate::util::captures::Captures;
 
 impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
@@ -479,8 +480,17 @@ fn query_response_substitution_guess<R>(
                         opt_values[br.assert_bound_var()] = Some(*original_value);
                     }
                 }
-                UnpackedKind::Const(..) => {
-                    unimplemented!() // FIXME(const_generics)
+                UnpackedKind::Const(result_value) => {
+                    if let ty::LazyConst::Evaluated(ty::Const {
+                        val: ConstValue::Infer(InferConst::Canonical(debrujin, b)),
+                        ..
+                    }) = result_value {
+                        // ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
+
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(*debrujin, ty::INNERMOST);
+                        opt_values[*b] = Some(*original_value);
+                    }
                 }
             }
         }
index 6adbf2bcef866931c2a1f65f41396030564029ed..30a398de19ae77715e1cc1e7c4866920223ef7ce 100644 (file)
@@ -1,5 +1,6 @@
 use super::{InferCtxt, FixupError, FixupResult, Span, type_variable::TypeVariableOrigin};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
+use crate::mir::interpret::ConstValue;
+use crate::ty::{self, Ty, TyCtxt, TypeFoldable, InferConst};
 use crate::ty::fold::{TypeFolder, TypeVisitor};
 
 ///////////////////////////////////////////////////////////////////////////
@@ -7,7 +8,7 @@
 
 /// The opportunistic type resolver can be used at any time. It simply replaces
 /// type variables that have been unified with the things they have
-/// been unified with (similar to `shallow_resolve`, but deep). This is
+/// been unified with (similar to `shallow_resolve_type`, but deep). This is
 /// useful for printing messages etc but also required at various
 /// points for correctness.
 pub struct OpportunisticTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
@@ -30,7 +31,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         if !t.has_infer_types() {
             t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
-            let t0 = self.infcx.shallow_resolve(t);
+            let t0 = self.infcx.shallow_resolve_type(t);
             t0.super_fold_with(self)
         }
     }
@@ -58,7 +59,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         if !t.needs_infer() {
             t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
-            let t0 = self.infcx.shallow_resolve(t);
+            let t0 = self.infcx.shallow_resolve_type(t);
             t0.super_fold_with(self)
         }
     }
@@ -72,6 +73,15 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                 r,
         }
     }
+
+    fn fold_const(&mut self, ct: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+        if !ct.needs_infer() {
+            ct // micro-optimize -- if there is nothing in this const that this fold affects...
+        } else {
+            let c0 = self.infcx.shallow_resolve_const(ct);
+            c0.super_fold_with(self)
+        }
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -96,7 +106,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
 
 impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx> {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
-        let t = self.infcx.shallow_resolve(t);
+        let t = self.infcx.shallow_resolve_type(t);
         if t.has_infer_types() {
             if let ty::Infer(infer_ty) = t.sty {
                 // Since we called `shallow_resolve` above, this must
@@ -136,7 +146,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
 /// their concrete results. If any variable cannot be replaced (never unified, etc)
 /// then an `Err` result is returned.
 pub fn fully_resolve<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                                        value: &T) -> FixupResult<T>
+                                        value: &T) -> FixupResult<'tcx, T>
     where T : TypeFoldable<'tcx>
 {
     let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
@@ -151,7 +161,7 @@ pub fn fully_resolve<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 // `err` field is not enforcable otherwise.
 struct FullTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    err: Option<FixupError>,
+    err: Option<FixupError<'tcx>>,
 }
 
 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> {
@@ -165,7 +175,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
               // ^ we need to have the `keep_local` check to un-default
               // defaulted tuples.
         } else {
-            let t = self.infcx.shallow_resolve(t);
+            let t = self.infcx.shallow_resolve_type(t);
             match t.sty {
                 ty::Infer(ty::TyVar(vid)) => {
                     self.err = Some(FixupError::UnresolvedTy(vid));
@@ -199,4 +209,30 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             _ => r,
         }
     }
+
+    fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+        if !c.needs_infer() && !ty::keep_local(&c) {
+            c // micro-optimize -- if there is nothing in this const that this fold affects...
+              // ^ we need to have the `keep_local` check to un-default
+              // defaulted tuples.
+        } else {
+            let c = self.infcx.shallow_resolve_const(c);
+            match c {
+                ty::LazyConst::Evaluated(ty::Const { val, .. }) => {
+                    match val {
+                        ConstValue::Infer(InferConst::Var(vid)) => {
+                            self.err = Some(FixupError::UnresolvedConst(*vid));
+                            return self.tcx().types.ct_err;
+                        }
+                        ConstValue::Infer(InferConst::Fresh(_)) => {
+                            bug!("Unexpected const in full const resolver: {:?}", c);
+                        }
+                        _ => {}
+                    }
+                }
+                _ => {}
+            }
+            c.super_fold_with(self)
+        }
+    }
 }
index 2034795a0b58245d002027768d8c0a84e6e962f4..5980192a5070f0860b75995d327a4b15e012a5b2 100644 (file)
@@ -7,8 +7,8 @@
 use crate::hir::def_id::DefId;
 use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
-use crate::ty::error::{ExpectedFound, TypeError};
-use crate::mir::interpret::{GlobalId, ConstValue};
+use crate::ty::error::{ExpectedFound, TypeError, ConstError};
+use crate::mir::interpret::{GlobalId, ConstValue, Scalar};
 use crate::util::common::ErrorReported;
 use syntax_pos::DUMMY_SP;
 use std::rc::Rc;
@@ -476,6 +476,8 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             let t = relation.relate(&a_t, &b_t)?;
             let to_u64 = |x: ty::Const<'tcx>| -> Result<u64, ErrorReported> {
                 match x.val {
+                    // FIXME(const_generics): this doesn't work right now,
+                    // because it tries to relate an `Infer` to a `Param`.
                     ConstValue::Unevaluated(def_id, substs) => {
                         // FIXME(eddyb) get the right param_env.
                         let param_env = ty::ParamEnv::empty();
@@ -489,7 +491,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
                             if let Some(instance) = instance {
                                 let cid = GlobalId {
                                     instance,
-                                    promoted: None
+                                    promoted: None,
                                 };
                                 if let Some(s) = tcx.const_eval(param_env.and(cid))
                                                     .ok()
@@ -718,6 +720,17 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
     }
 }
 
+impl<'tcx> Relate<'tcx> for &'tcx ty::LazyConst<'tcx> {
+    fn relate<'a, 'gcx, R>(relation: &mut R,
+                           a: &&'tcx ty::LazyConst<'tcx>,
+                           b: &&'tcx ty::LazyConst<'tcx>)
+                           -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>>
+        where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
+    {
+        relation.consts(*a, *b)
+    }
+}
+
 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<T> {
     fn relate<'a, 'gcx, R>(relation: &mut R,
                            a: &ty::Binder<T>,
@@ -771,14 +784,17 @@ fn relate<'a, 'gcx, R>(
             (UnpackedKind::Type(a_ty), UnpackedKind::Type(b_ty)) => {
                 Ok(relation.relate(&a_ty, &b_ty)?.into())
             }
+            (UnpackedKind::Const(a_ct), UnpackedKind::Const(b_ct)) => {
+                Ok(relation.relate(&a_ct, &b_ct)?.into())
+            }
             (UnpackedKind::Lifetime(unpacked), x) => {
                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
             }
             (UnpackedKind::Type(unpacked), x) => {
                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
             }
-            (UnpackedKind::Const(_), _) => {
-                unimplemented!() // FIXME(const_generics)
+            (UnpackedKind::Const(unpacked), x) => {
+                bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
             }
         }
     }