1
Fork 0

implement valtrees as the type-system representation for constant values

This commit is contained in:
b-naber 2022-02-16 10:56:01 +01:00
parent edab34ab2a
commit 705d818bd5
116 changed files with 1606 additions and 1032 deletions

View file

@ -6,6 +6,7 @@ use super::*;
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxt;
use crate::traits::project::ProjectAndUnifyResult;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::{Region, RegionVid, Term};
@ -834,7 +835,16 @@ impl<'tcx> AutoTraitFinder<'tcx> {
unevaluated,
Some(obligation.cause.span),
) {
Ok(val) => Ok(ty::Const::from_value(select.tcx(), val, c.ty())),
Ok(Some(valtree)) => {
Ok(ty::Const::from_value(select.tcx(), valtree, c.ty()))
}
Ok(None) => {
let tcx = self.tcx;
let def_id = unevaluated.def.did;
let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();
Err(ErrorHandled::Reported(reported))
}
Err(err) => Err(err),
}
} else {

View file

@ -13,9 +13,7 @@ use rustc_hir::def::DefKind;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::InferCtxt;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{
ConstValue, ErrorHandled, LitToConstError, LitToConstInput, Scalar,
};
use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
use rustc_middle::thir;
use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
use rustc_middle::ty::subst::{Subst, SubstsRef};
@ -449,9 +447,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
self.nodes.push(Node::Leaf(constant))
}
&ExprKind::NonHirLiteral { lit , user_ty: _} => {
// FIXME Construct a Valtree from this ScalarInt when introducing Valtrees
let const_value = ConstValue::Scalar(Scalar::Int(lit));
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, const_value, node.ty)))
let val = ty::ValTree::from_scalar_int(lit);
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty)))
}
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);

View file

@ -407,7 +407,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
let pred =
ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
ProcessResult::Changed(mk_pending(vec![
obligation.with(pred.to_predicate(self.selcx.tcx())),
obligation.with(pred.to_predicate(self.selcx.tcx()))
]))
}
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
@ -594,22 +594,24 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
let mut evaluate = |c: Const<'tcx>| {
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
match self.selcx.infcx().const_eval_resolve(
match self.selcx.infcx().try_const_eval_resolve(
obligation.param_env,
unevaluated,
c.ty(),
Some(obligation.cause.span),
) {
Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty())),
Err(ErrorHandled::TooGeneric) => {
stalled_on.extend(
unevaluated
.substs
.iter()
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
);
Err(ErrorHandled::TooGeneric)
}
Err(err) => Err(err),
Ok(val) => Ok(val),
Err(e) => match e {
ErrorHandled::TooGeneric => {
stalled_on.extend(
unevaluated.substs.iter().filter_map(
TyOrConstInferVar::maybe_from_generic_arg,
),
);
Err(ErrorHandled::TooGeneric)
}
_ => Err(e),
},
}
} else {
Ok(c)

View file

@ -618,11 +618,14 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
}
}
#[instrument(skip(self), level = "debug")]
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
constant
} else {
let constant = constant.super_fold_with(self);
debug!(?constant);
debug!("self.param_env: {:?}", self.param_env);
constant.eval(self.selcx.tcx(), self.param_env)
}
}

View file

@ -100,7 +100,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
}
}
/// Visitor to find the maximum escaping bound var
// Visitor to find the maximum escaping bound var
struct MaxEscapingBoundVarVisitor {
// The index which would count as escaping
outer_index: ty::DebruijnIndex,
@ -336,12 +336,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
Ok(match constant {
mir::ConstantKind::Ty(c) => {
let const_folded = c.try_fold_with(self)?;
let const_folded = c.try_super_fold_with(self)?;
match const_folded.kind() {
ty::ConstKind::Value(cv) => {
// FIXME With Valtrees we need to convert `cv: ValTree`
// to a `ConstValue` here.
mir::ConstantKind::Val(cv, const_folded.ty())
ty::ConstKind::Value(valtree) => {
let tcx = self.infcx.tcx;
let ty = const_folded.ty();
let const_val = tcx.valtree_to_const_val((ty, valtree));
debug!(?ty, ?valtree, ?const_val);
mir::ConstantKind::Val(const_val, ty)
}
_ => mir::ConstantKind::Ty(const_folded),
}

View file

@ -636,13 +636,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let evaluate = |c: ty::Const<'tcx>| {
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
self.infcx
.const_eval_resolve(
obligation.param_env,
unevaluated,
Some(obligation.cause.span),
)
.map(|val| ty::Const::from_value(self.tcx(), val, c.ty()))
match self.infcx.try_const_eval_resolve(
obligation.param_env,
unevaluated,
c.ty(),
Some(obligation.cause.span),
) {
Ok(val) => Ok(val),
Err(e) => Err(e),
}
} else {
Ok(c)
}
@ -2576,7 +2578,11 @@ impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> {
}
fn depth(&self) -> usize {
if let Some(head) = self.head { head.depth } else { 0 }
if let Some(head) = self.head {
head.depth
} else {
0
}
}
}