about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakob Degen <jakob.e.degen@gmail.com>2022-05-05 21:15:20 -0400
committerJakob Degen <jakob.e.degen@gmail.com>2022-05-06 15:40:32 -0400
commit5289bbece312fb6704febea1a95a601f0dd27b02 (patch)
treef5803a3a8687624535cb82e118e86ce1fff89fb8
parente209e85e39b4851c3ec122a45ddeabe318b2d522 (diff)
downloadrust-5289bbece312fb6704febea1a95a601f0dd27b02.tar.gz
rust-5289bbece312fb6704febea1a95a601f0dd27b02.zip
Expand validator to be more precise on checked binary ops
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs44
1 files changed, 41 insertions, 3 deletions
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index f71bc586b48..a790a723305 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -291,7 +291,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     ty::Array(..) | ty::Slice(..)
                 );
             }
-            Rvalue::BinaryOp(op, vals) | Rvalue::CheckedBinaryOp(op, vals) => {
+            Rvalue::BinaryOp(op, vals) => {
                 use BinOp::*;
                 let a = vals.0.ty(&self.body.local_decls, self.tcx);
                 let b = vals.1.ty(&self.body.local_decls, self.tcx);
@@ -355,17 +355,55 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         for x in [a, b] {
                             check_kinds!(
                                 x,
-                                "Cannot perform op on type {:?}",
+                                "Cannot perform arithmetic on type {:?}",
                                 ty::Uint(..) | ty::Int(..) | ty::Float(..)
                             )
                         }
                         if a != b {
                             self.fail(
                                 location,
-                                format!("Cannot perform op on unequal types {:?} and {:?}", a, b),
+                                format!(
+                                    "Cannot perform arithmetic on unequal types {:?} and {:?}",
+                                    a, b
+                                ),
+                            );
+                        }
+                    }
+                }
+            }
+            Rvalue::CheckedBinaryOp(op, vals) => {
+                use BinOp::*;
+                let a = vals.0.ty(&self.body.local_decls, self.tcx);
+                let b = vals.1.ty(&self.body.local_decls, self.tcx);
+                match op {
+                    Add | Sub | Mul => {
+                        for x in [a, b] {
+                            check_kinds!(
+                                x,
+                                "Cannot perform checked arithmetic on type {:?}",
+                                ty::Uint(..) | ty::Int(..)
+                            )
+                        }
+                        if a != b {
+                            self.fail(
+                                location,
+                                format!(
+                                    "Cannot perform checked arithmetic on unequal types {:?} and {:?}",
+                                    a, b
+                                ),
                             );
                         }
                     }
+                    Shl | Shr => {
+                        for x in [a, b] {
+                            check_kinds!(
+                                x,
+                                "Cannot perform checked shift on non-integer type {:?}",
+                                ty::Uint(..) | ty::Int(..)
+                            )
+                        }
+                    }
+                    _ => self.fail(location, format!("There is no checked version of {:?}", op)),
                 }
             }
             Rvalue::UnaryOp(op, operand) => {