diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 503a421beac..8814a334fbb 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -4,13 +4,12 @@ //! types or regions but can be other things. Examples of type relations are //! 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::subst::{GenericArg, GenericArgKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; -use rustc_span::DUMMY_SP; use rustc_target::spec::abi; use std::iter; @@ -513,81 +512,63 @@ pub fn super_relate_consts>( // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. - match (a.val, b.val) { + let is_match = match (a.val, b.val) { (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { // The caller should handle these cases! bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) } - (ty::ConstKind::Error(_), _) => Ok(a), - (_, ty::ConstKind::Error(_)) => Ok(b), + (ty::ConstKind::Error(_), _) => return Ok(a), + (_, ty::ConstKind::Error(_)) => return Ok(b), - (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => { - return Ok(a); - } - (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) if p1 == p2 => { - return Ok(a); - } + (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index, + (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2, (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => { match (a_val, b_val) { - (ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) => { - if a_val == b_val { - Ok(a) - } else if let ty::FnPtr(_) = a.ty.kind() { - 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(); - if a_instance == b_instance { - Ok(a) - } else { - Err(TypeError::ConstMismatch(expected_found(relation, a, b))) + ( + ConstValue::Scalar(Scalar::Int(a_val)), + ConstValue::Scalar(Scalar::Int(b_val)), + ) => a_val == b_val, + ( + ConstValue::Scalar(Scalar::Ptr(a_val)), + ConstValue::Scalar(Scalar::Ptr(b_val)), + ) => { + a_val == b_val + || 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 { .. }) => { - let a_bytes = get_slice_bytes(&tcx, a_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))) - } + get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val) } (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => { - match a.ty.kind() { - ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => { - let a_destructured = tcx.destructure_const(relation.param_env().and(a)); - 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. - if a_destructured.variant == b_destructured.variant { - for (a_field, b_field) in - a_destructured.fields.iter().zip(b_destructured.fields.iter()) - { - relation.consts(a_field, b_field)?; - } + // Both the variant and each field have to be equal. + if a_destructured.variant == b_destructured.variant { + for (a_field, b_field) in + a_destructured.fields.iter().zip(b_destructured.fields.iter()) + { + relation.consts(a_field, b_field)?; + } - Ok(a) - } else { - Err(TypeError::ConstMismatch(expected_found(relation, a, b))) - } - } - // 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))) - } + true + } else { + false } } - _ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))), + _ => false, } } @@ -595,11 +576,7 @@ pub fn super_relate_consts>( ty::ConstKind::Unevaluated(a_def, a_substs, None), ty::ConstKind::Unevaluated(b_def, b_substs, None), ) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => { - if tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) { - Ok(a) - } else { - Err(TypeError::ConstMismatch(expected_found(relation, a, b))) - } + tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) } // While this is slightly incorrect, it shouldn't matter for `min_const_generics` @@ -611,13 +588,14 @@ pub fn super_relate_consts>( ) if a_def == b_def && a_promoted == b_promoted => { let 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), 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>> {