about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <github35764891676564198441@oli-obk.de>2021-03-02 12:13:17 +0000
committerOli Scherer <github35764891676564198441@oli-obk.de>2021-03-12 12:23:11 +0000
commit5e8a89b2e5a036688d12eb6da4a1b97cadb6949f (patch)
tree37a3712caf4b6a596177a957ad08141cd9cd8fd3
parent4d917faa9905432a4ca18fdab29d3d8b951b7d97 (diff)
downloadrust-5e8a89b2e5a036688d12eb6da4a1b97cadb6949f.tar.gz
rust-5e8a89b2e5a036688d12eb6da4a1b97cadb6949f.zip
Reduce the duplication in the relation logic for constants
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs112
1 files changed, 45 insertions, 67 deletions
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<R: TypeRelation<'tcx>>(
     // 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));
-
-                            // 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)))
+                    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)?;
                         }
+
+                        true
+                    } else {
+                        false
                     }
                 }
 
-                _ => 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(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<R: TypeRelation<'tcx>>(
         ) 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<ty::Binder<ty::ExistentialPredicate<'tcx>>> {