Eagerly evaluate in super_relate_consts

This commit is contained in:
varkor 2019-05-13 21:15:08 +01:00
parent 908d97d03c
commit d5c6cb8778
2 changed files with 39 additions and 58 deletions

View file

@ -8,8 +8,7 @@ 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, Scalar};
use syntax_pos::DUMMY_SP;
use crate::mir::interpret::{ConstValue, Scalar, GlobalId};
use std::rc::Rc;
use std::iter;
use rustc_target::spec::abi;
@ -473,54 +472,8 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
{
let t = relation.relate(&a_t, &b_t)?;
let to_u64 = |ct: &'tcx ty::Const<'tcx>| -> Option<u64> {
match ct.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();
if let Some(substs) = tcx.lift_to_global(&substs) {
let instance = ty::Instance::resolve(
tcx.global_tcx(),
param_env,
def_id,
substs,
);
if let Some(instance) = instance {
let cid = GlobalId {
instance,
promoted: None,
};
return tcx.const_eval(param_env.and(cid))
.ok()
.map(|c| c.unwrap_usize(tcx));
}
}
None
}
_ => ct.assert_usize(tcx),
}
};
match (to_u64(sz_a), to_u64(sz_b)) {
(Some(sz_a_u64), Some(sz_b_u64)) => {
if sz_a_u64 == sz_b_u64 {
Ok(tcx.mk_ty(ty::Array(t, sz_a)))
} else {
Err(TypeError::FixedArraySize(
expected_found(relation, &sz_a_u64, &sz_b_u64)))
}
}
_ => {
if let Ok(sz) = relation.relate(&sz_a, &sz_b) {
Ok(tcx.mk_ty(ty::Array(t, sz)))
} else {
tcx.sess.delay_span_bug(DUMMY_SP, "array length could not be evaluated");
Ok(tcx.types.err)
}
}
}
let sz = relation.relate(&sz_a, &sz_b)?;
Ok(tcx.mk_ty(ty::Array(t, sz)))
}
(&ty::Slice(a_t), &ty::Slice(b_t)) =>
@ -594,11 +547,36 @@ where
{
let tcx = relation.tcx();
let eagerly_eval = |x: &'tcx ty::Const<'tcx>| {
if let ConstValue::Unevaluated(def_id, substs) = x.val {
// FIXME(eddyb) get the right param_env.
let param_env = ty::ParamEnv::empty();
if let Some(substs) = tcx.lift_to_global(&substs) {
let instance = ty::Instance::resolve(
tcx.global_tcx(),
param_env,
def_id,
substs,
);
if let Some(instance) = instance {
let cid = GlobalId {
instance,
promoted: None,
};
if let Ok(ct) = tcx.const_eval(param_env.and(cid)) {
return ct.val;
}
}
}
}
x.val
};
// Currently, the values that can be unified are those that
// implement both `PartialEq` and `Eq`, corresponding to
// `structural_match` types.
// FIXME(const_generics): check for `structural_match` synthetic attribute.
match (a.val, b.val) {
match (eagerly_eval(a), eagerly_eval(b)) {
(ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => {
// The caller should handle these cases!
bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
@ -609,8 +587,13 @@ where
(ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => {
Ok(a)
}
(ConstValue::Scalar(Scalar::Raw { .. }), _) if a == b => {
Ok(a)
(a_val @ ConstValue::Scalar(Scalar::Raw { .. }), b_val @ _)
if a.ty == b.ty && a_val == b_val =>
{
Ok(tcx.mk_const(ty::Const {
val: a_val,
ty: a.ty,
}))
}
(ConstValue::ByRef(..), _) => {
bug!(
@ -631,9 +614,7 @@ where
}))
}
_ => {
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
}
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
}
}

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/const-array-oob-arith.rs:7:45
|
LL | const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
| ^^^ expected an array with a fixed size of 2 elements, found one with 1 elements
| ^^^ expected `Const { ty: usize, val: Scalar(Bits { size: 8, bits: 2 }) }`, found `Const { ty: usize, val: Scalar(Bits { size: 8, bits: 1 }) }`
|
= note: expected type `[i32; 2]`
found type `[i32; 1]`
@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/const-array-oob-arith.rs:8:44
|
LL | const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
| ^^^^^^^ expected an array with a fixed size of 1 elements, found one with 2 elements
| ^^^^^^^ expected `Const { ty: usize, val: Scalar(Bits { size: 8, bits: 1 }) }`, found `Const { ty: usize, val: Scalar(Bits { size: 8, bits: 2 }) }`
|
= note: expected type `[i32; 1]`
found type `[i32; 2]`