From: varkor Date: Fri, 8 Mar 2019 01:20:33 +0000 (+0000) Subject: Handle generic consts in relate and infer X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=d113ff8ada02d4ea253d78b77186637a7d7344bb;p=rust.git Handle generic consts in relate and infer Co-Authored-By: Gabriel Smith --- diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index e605aae0fae..65c579aedf2 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -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( 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); + } } } } diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index 6adbf2bcef8..30a398de19a 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -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 + 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, + err: Option>, } 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) + } + } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 2034795a0b5..5980192a507 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -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 { 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 { fn relate<'a, 'gcx, R>(relation: &mut R, a: &ty::Binder, @@ -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) } } }