change thir to use mir::ConstantKind instead of ty::Const

This commit is contained in:
b-naber 2022-02-21 22:43:15 +01:00
parent 9d843171d1
commit b38077ea0b
29 changed files with 534 additions and 112 deletions

View file

@ -37,9 +37,14 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
param_env: ty::ParamEnv<'tcx>,
span: Span,
) -> Result<(), NotConstEvaluatable> {
<<<<<<< HEAD
let tcx = infcx.tcx;
if tcx.features().generic_const_exprs {
=======
if infcx.tcx.features().generic_const_exprs {
let tcx = infcx.tcx;
>>>>>>> 6064f16d846 (change thir to use mir::ConstantKind instead of ty::Const)
match AbstractConst::new(tcx, uv)? {
// We are looking at a generic abstract constant.
Some(ct) => {
@ -244,7 +249,7 @@ impl<'tcx> AbstractConst<'tcx> {
Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs }))
}
pub fn from_const(
pub fn from_constant(
tcx: TyCtxt<'tcx>,
ct: ty::Const<'tcx>,
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
@ -376,6 +381,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
visit::walk_pat(self, pat);
}
}
fn visit_constant(&mut self, ct: mir::ConstantKind<'tcx>) {
self.is_poly |= ct.has_param_types_or_consts();
}
}
let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body };
@ -414,10 +423,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
self.recurse_build(self.body_id)?;
for n in self.nodes.iter() {
if let Node::Leaf(ty::Const(Interned(
if let Node::Leaf(mir::ConstantKind::Ty(ty::Const(Interned(
ty::ConstS { val: ty::ConstKind::Unevaluated(ct), ty: _ },
_,
))) = n
)))) = n
{
// `AbstractConst`s should not contain any promoteds as they require references which
// are not allowed.
@ -637,6 +646,7 @@ pub(super) fn thir_abstract_const<'tcx>(
}
}
#[instrument(skip(tcx), level = "debug")]
pub(super) fn try_unify_abstract_consts<'tcx>(
tcx: TyCtxt<'tcx>,
(a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>),
@ -806,3 +816,51 @@ impl<'tcx> ConstUnifyCtxt<'tcx> {
}
}
}
/* Think I need these changes
=======
match (a_ct, b_ct) {
(mir::ConstantKind::Ty(a_ct), mir::ConstantKind::Ty(b_ct)) => {
match (a_ct.val(), b_ct.val()) {
// We can just unify errors with everything to reduce the amount of
// emitted errors here.
(ty::ConstKind::Error(_), _) | (_, ty::ConstKind::Error(_)) => true,
(ty::ConstKind::Param(a_param), ty::ConstKind::Param(b_param)) => {
a_param == b_param
}
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
a_val == b_val
}
// If we have `fn a<const N: usize>() -> [u8; N + 1]` and `fn b<const M: usize>() -> [u8; 1 + M]`
// we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This
// means that we only allow inference variables if they are equal.
(ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => {
a_val == b_val
}
// We expand generic anonymous constants at the start of this function, so this
// branch should only be taking when dealing with associated constants, at
// which point directly comparing them seems like the desired behavior.
//
// FIXME(generic_const_exprs): This isn't actually the case.
// We also take this branch for concrete anonymous constants and
// expand generic anonymous constants with concrete substs.
(ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => {
a_uv == b_uv
}
// FIXME(generic_const_exprs): We may want to either actually try
// to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
// this, for now we just return false here.
_ => false,
}
}
(mir::ConstantKind::Val(a_val, a_ty), mir::ConstantKind::Val(b_val, b_ty)) => {
a_val == b_val && a_ty == b_ty
}
_ => {
// FIXME Can it happen that we need to compare ConstantKind::Ty(ConstKind::Value)
// with a ConstantKind::Val and vice versa?
false
>>>>>>> 6064f16d846 (change thir to use mir::ConstantKind instead of ty::Const)
*/

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(..) => {

View file

@ -17,6 +17,7 @@ use crate::traits::{self, Obligation, ObligationCause};
use rustc_errors::FatalError;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::ConstantKind;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor};
use rustc_middle::ty::{Predicate, ToPredicate};
@ -836,7 +837,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) {
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| {
match node.root(self.tcx) {
Node::Leaf(leaf) => self.visit_const(leaf),
Node::Leaf(leaf) => match leaf {
ConstantKind::Ty(c) => self.visit_const(c),
ConstantKind::Val(_, ty) => self.visit_ty(ty),
},
Node::Cast(_, _, ty) => self.visit_ty(ty),
Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
ControlFlow::CONTINUE