From 39f1a9d7a344293798f3e07c3d434417f9d8af26 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 00:33:52 +0300 Subject: [PATCH] checker: fix type promotion not working with bitwise operators (fixes #9943) --- vlib/v/checker/assign.v | 9 ++++++++- vlib/v/tests/shift_test.v | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 69dac437d..9fb3ce499 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -59,6 +59,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { c.inside_assign = prev_inside_assign } is_decl := node.op == .decl_assign + original_op := node.op mut right_first := node.right[0] node.left_types = [] mut right_len := node.right.len @@ -992,7 +993,13 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.', right.pos()) } // Dual sides check (compatibility check) - c.check_expected(right_type_unwrapped, left_type_unwrapped) or { + assign_right_type := if original_op in [.left_shift_assign, .right_shift_assign, + .unsigned_right_shift_assign] { + left_type_unwrapped + } else { + right_type_unwrapped + } + c.check_expected(assign_right_type, left_type_unwrapped) or { if left.is_auto_deref_arg() && left_type.is_ptr() { left_deref := left_type.deref() right_deref := if right.is_pure_literal() { diff --git a/vlib/v/tests/shift_test.v b/vlib/v/tests/shift_test.v index 22e08e627..a9304bec7 100644 --- a/vlib/v/tests/shift_test.v +++ b/vlib/v/tests/shift_test.v @@ -86,6 +86,15 @@ fn test_shift_operators() { assert x << 2 == 8 } +fn test_shift_assign_accepts_int_count_for_unsigned_left_operand() { + mut value := u64(1) + shift := int(3) + value <<= shift + assert value == u64(8) + value >>= shift + assert value == u64(1) +} + fn oversized_shift_count() u64 { return u64(64) } -- 2.39.5