From 0d86bf88de2ebc897faffbb7596e6c29372a9cbd Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 29 Jan 2026 15:57:43 +0000 Subject: [PATCH 1/2] [mypyc] ircheck: Check for incompatible signs in int ops This is still a bit lenient, and only the most problematic cases are reported. --- mypyc/analysis/ircheck.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mypyc/analysis/ircheck.py b/mypyc/analysis/ircheck.py index e8954c01c6adb..fcedcb5e088a3 100644 --- a/mypyc/analysis/ircheck.py +++ b/mypyc/analysis/ircheck.py @@ -241,6 +241,10 @@ def expect_non_float(self, op: Op, v: Value) -> None: if is_float_rprimitive(v.type): self.fail(op, "Float not expected") + def expect_primitive_type(self, op: Op, v: Value) -> None: + if not isinstance(v.type, RPrimitive): + self.fail(op, f"RPrimitive expected, got {v.type.__name__}") + def visit_goto(self, op: Goto) -> None: self.check_control_op_targets(op) @@ -397,8 +401,23 @@ def visit_load_global(self, op: LoadGlobal) -> None: pass def visit_int_op(self, op: IntOp) -> None: + self.expect_primitive_type(op, op.lhs) + self.expect_primitive_type(op, op.rhs) self.expect_non_float(op, op.lhs) self.expect_non_float(op, op.rhs) + left = op.lhs.type + right = op.rhs.type + op_str = op.op_str[op.op] + if ( + isinstance(left, RPrimitive) + and isinstance(right, RPrimitive) + and left.is_signed != right.is_signed + and ( + op_str in ("+", "-", "*", "/", "%") + or (op_str not in ("<<", ">>") and left.size != right.size) + ) + ): + self.fail(op, f"Operand types have incompatible signs: {op.lhs.type}, {op.rhs.type}") def visit_comparison_op(self, op: ComparisonOp) -> None: self.check_compatibility(op, op.lhs.type, op.rhs.type) From b1b116b345803991bb1fd3cbb47882e77a113739 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 29 Jan 2026 16:41:21 +0000 Subject: [PATCH 2/2] Fix --- mypyc/analysis/ircheck.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/analysis/ircheck.py b/mypyc/analysis/ircheck.py index fcedcb5e088a3..fc09e1aa926e7 100644 --- a/mypyc/analysis/ircheck.py +++ b/mypyc/analysis/ircheck.py @@ -243,7 +243,7 @@ def expect_non_float(self, op: Op, v: Value) -> None: def expect_primitive_type(self, op: Op, v: Value) -> None: if not isinstance(v.type, RPrimitive): - self.fail(op, f"RPrimitive expected, got {v.type.__name__}") + self.fail(op, f"RPrimitive expected, got {type(v.type).__name__}") def visit_goto(self, op: Goto) -> None: self.check_control_op_targets(op)