Reduce the duplication in the relation logic for constants
This commit is contained in:
parent
4d917faa99
commit
5e8a89b2e5
1 changed files with 44 additions and 66 deletions
|
@ -4,13 +4,12 @@
|
||||||
//! types or regions but can be other things. Examples of type relations are
|
//! types or regions but can be other things. Examples of type relations are
|
||||||
//! subtyping, type equality, etc.
|
//! subtyping, type equality, etc.
|
||||||
|
|
||||||
use crate::mir::interpret::{get_slice_bytes, ConstValue};
|
use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar};
|
||||||
use crate::ty::error::{ExpectedFound, TypeError};
|
use crate::ty::error::{ExpectedFound, TypeError};
|
||||||
use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
||||||
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
|
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc_hir as ast;
|
use rustc_hir as ast;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
|
@ -513,81 +512,63 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||||
// Currently, the values that can be unified are primitive types,
|
// Currently, the values that can be unified are primitive types,
|
||||||
// and those that derive both `PartialEq` and `Eq`, corresponding
|
// and those that derive both `PartialEq` and `Eq`, corresponding
|
||||||
// to structural-match types.
|
// to structural-match types.
|
||||||
match (a.val, b.val) {
|
let is_match = match (a.val, b.val) {
|
||||||
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
|
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
|
||||||
// The caller should handle these cases!
|
// The caller should handle these cases!
|
||||||
bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
|
bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
(ty::ConstKind::Error(_), _) => Ok(a),
|
(ty::ConstKind::Error(_), _) => return Ok(a),
|
||||||
(_, ty::ConstKind::Error(_)) => Ok(b),
|
(_, ty::ConstKind::Error(_)) => return Ok(b),
|
||||||
|
|
||||||
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => {
|
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index,
|
||||||
return Ok(a);
|
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
|
||||||
}
|
|
||||||
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) if p1 == p2 => {
|
|
||||||
return Ok(a);
|
|
||||||
}
|
|
||||||
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
|
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
|
||||||
match (a_val, b_val) {
|
match (a_val, b_val) {
|
||||||
(ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) => {
|
(
|
||||||
if a_val == b_val {
|
ConstValue::Scalar(Scalar::Int(a_val)),
|
||||||
Ok(a)
|
ConstValue::Scalar(Scalar::Int(b_val)),
|
||||||
} else if let ty::FnPtr(_) = a.ty.kind() {
|
) => a_val == b_val,
|
||||||
let a_instance = tcx.global_alloc(a_val.assert_ptr().alloc_id).unwrap_fn();
|
(
|
||||||
let b_instance = tcx.global_alloc(b_val.assert_ptr().alloc_id).unwrap_fn();
|
ConstValue::Scalar(Scalar::Ptr(a_val)),
|
||||||
if a_instance == b_instance {
|
ConstValue::Scalar(Scalar::Ptr(b_val)),
|
||||||
Ok(a)
|
) => {
|
||||||
} else {
|
a_val == b_val
|
||||||
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
|
|| match (
|
||||||
|
tcx.global_alloc(a_val.alloc_id),
|
||||||
|
tcx.global_alloc(b_val.alloc_id),
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
GlobalAlloc::Function(a_instance),
|
||||||
|
GlobalAlloc::Function(b_instance),
|
||||||
|
) => a_instance == b_instance,
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
|
(ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
|
||||||
let a_bytes = get_slice_bytes(&tcx, a_val);
|
get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
|
||||||
let b_bytes = get_slice_bytes(&tcx, b_val);
|
|
||||||
if a_bytes == b_bytes {
|
|
||||||
Ok(a)
|
|
||||||
} else {
|
|
||||||
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
|
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
|
||||||
match a.ty.kind() {
|
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
|
||||||
ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
|
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
|
||||||
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
|
|
||||||
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
|
|
||||||
|
|
||||||
// Both the variant and each field have to be equal.
|
// Both the variant and each field have to be equal.
|
||||||
if a_destructured.variant == b_destructured.variant {
|
if a_destructured.variant == b_destructured.variant {
|
||||||
for (a_field, b_field) in
|
for (a_field, b_field) in
|
||||||
a_destructured.fields.iter().zip(b_destructured.fields.iter())
|
a_destructured.fields.iter().zip(b_destructured.fields.iter())
|
||||||
{
|
{
|
||||||
relation.consts(a_field, b_field)?;
|
relation.consts(a_field, b_field)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(a)
|
true
|
||||||
} else {
|
} else {
|
||||||
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
|
false
|
||||||
}
|
|
||||||
}
|
|
||||||
// FIXME(const_generics): There are probably some `TyKind`s
|
|
||||||
// which should be handled here.
|
|
||||||
_ => {
|
|
||||||
tcx.sess.delay_span_bug(
|
|
||||||
DUMMY_SP,
|
|
||||||
&format!("unexpected consts: a: {:?}, b: {:?}", a, b),
|
|
||||||
);
|
|
||||||
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,11 +576,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||||
ty::ConstKind::Unevaluated(a_def, a_substs, None),
|
ty::ConstKind::Unevaluated(a_def, a_substs, None),
|
||||||
ty::ConstKind::Unevaluated(b_def, b_substs, None),
|
ty::ConstKind::Unevaluated(b_def, b_substs, None),
|
||||||
) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => {
|
) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => {
|
||||||
if tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) {
|
tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs)))
|
||||||
Ok(a)
|
|
||||||
} else {
|
|
||||||
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
|
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
|
||||||
|
@ -611,13 +588,14 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||||
) if a_def == b_def && a_promoted == b_promoted => {
|
) if a_def == b_def && a_promoted == b_promoted => {
|
||||||
let substs =
|
let substs =
|
||||||
relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
|
relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
|
||||||
Ok(tcx.mk_const(ty::Const {
|
return Ok(tcx.mk_const(ty::Const {
|
||||||
val: ty::ConstKind::Unevaluated(a_def, substs, a_promoted),
|
val: ty::ConstKind::Unevaluated(a_def, substs, a_promoted),
|
||||||
ty: a.ty,
|
ty: a.ty,
|
||||||
}))
|
}));
|
||||||
}
|
}
|
||||||
_ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
|
_ => false,
|
||||||
}
|
};
|
||||||
|
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>> {
|
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue