about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhkalbasi <hamidrezakalbasi@protonmail.com>2023-05-17 01:27:45 +0330
committerhkalbasi <hamidrezakalbasi@protonmail.com>2023-05-17 01:27:45 +0330
commitfd034bea1a13cf557f9fa3446f8f31fa18c084f9 (patch)
treed8b2d2a82748d95452ec06014e50adae4492ec08
parentcbd14e98403dc5e19f19fdf913808656d81a0516 (diff)
downloadrust-fd034bea1a13cf557f9fa3446f8f31fa18c084f9.tar.gz
rust-fd034bea1a13cf557f9fa3446f8f31fa18c084f9.zip
Fix evaluating negative for floating point types
-rw-r--r--crates/hir-ty/src/consteval/tests.rs4
-rw-r--r--crates/hir-ty/src/mir/eval.rs39
2 files changed, 30 insertions, 13 deletions
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 12b15065ddf..aa84103dd8a 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -113,6 +113,10 @@ fn floating_point() {
         r#"const GOAL: f32 = 2.0 + 3.0 * 5.5 - 8.;"#,
         i128::from_le_bytes(pad16(&f32::to_le_bytes(10.5), true)),
     );
+    check_number(
+        r#"const GOAL: f32 = -90.0 + 36.0;"#,
+        i128::from_le_bytes(pad16(&f32::to_le_bytes(-54.0), true)),
+    );
 }
 
 #[test]
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 8ce16df8295..c55ecb056c0 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -759,25 +759,38 @@ impl Evaluator<'_> {
                     let size = self.size_of_sized(&ty, locals, "operand of unary op")?;
                     c = self.read_memory(Address::from_bytes(c)?, size)?;
                 }
-                let mut c = c.to_vec();
-                if ty.as_builtin() == Some(BuiltinType::Bool) {
-                    c[0] = 1 - c[0];
+                if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) {
+                    match f {
+                        chalk_ir::FloatTy::F32 => {
+                            let c = -from_bytes!(f32, c);
+                            Owned(c.to_le_bytes().into())
+                        }
+                        chalk_ir::FloatTy::F64 => {
+                            let c = -from_bytes!(f32, c);
+                            Owned(c.to_le_bytes().into())
+                        }
+                    }
                 } else {
-                    match op {
-                        UnOp::Not => c.iter_mut().for_each(|x| *x = !*x),
-                        UnOp::Neg => {
-                            c.iter_mut().for_each(|x| *x = !*x);
-                            for k in c.iter_mut() {
-                                let o;
-                                (*k, o) = k.overflowing_add(1);
-                                if !o {
-                                    break;
+                    let mut c = c.to_vec();
+                    if ty.as_builtin() == Some(BuiltinType::Bool) {
+                        c[0] = 1 - c[0];
+                    } else {
+                        match op {
+                            UnOp::Not => c.iter_mut().for_each(|x| *x = !*x),
+                            UnOp::Neg => {
+                                c.iter_mut().for_each(|x| *x = !*x);
+                                for k in c.iter_mut() {
+                                    let o;
+                                    (*k, o) = k.overflowing_add(1);
+                                    if !o {
+                                        break;
+                                    }
                                 }
                             }
                         }
                     }
+                    Owned(c)
                 }
-                Owned(c)
             }
             Rvalue::CheckedBinaryOp(op, lhs, rhs) => {
                 let lc = self.eval_operand(lhs, locals)?;