From 599ae8087aaa3dccf495aaea23e9bf2238de6c55 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 05:13:43 +0300 Subject: [PATCH] checker: fix enum taking function as init value when cast to int (fixes #25908) --- vlib/v/checker/checker.v | 17 +++++++++++++++++ .../tests/enum_non_comptime_cast_call_err.out | 7 +++++++ .../tests/enum_non_comptime_cast_call_err.vv | 9 +++++++++ .../enums/enum_with_comptime_fn_calls_test.v | 12 ++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 vlib/v/checker/tests/enum_non_comptime_cast_call_err.out create mode 100644 vlib/v/checker/tests/enum_non_comptime_cast_call_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index aa6808a02..66c0e3772 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3359,9 +3359,26 @@ fn (mut c Checker) enum_decl(mut node ast.EnumDecl) { if field.expr.expr.val !in seen_enum_field_names { c.error('`${field.expr.expr.enum_name}.${field.expr.expr.val}` should be declared before using it', field.expr.pos) + continue } } } + cast_expr := ast.Expr(field.expr) + if comptime_value := c.eval_comptime_const_expr(cast_expr, 0) { + comptime_lit := c.comptime_value_to_integer_literal(comptime_value, + field.expr.pos) or { + c.error('the default value for an enum has to be an integer', + field.expr.pos) + continue + } + c.check_enum_field_integer_literal(comptime_lit, signed, + node.is_multi_allowed, senum_type, field.expr.pos, mut useen, + enum_umin, enum_umax, mut iseen, enum_imin, enum_imax) + field.expr = comptime_lit + } else { + c.error('the default value for an enum has to be an integer', + field.expr.pos) + } } ast.CallExpr, ast.IfExpr { call_ret_type := c.expr(mut field.expr) diff --git a/vlib/v/checker/tests/enum_non_comptime_cast_call_err.out b/vlib/v/checker/tests/enum_non_comptime_cast_call_err.out new file mode 100644 index 000000000..990637394 --- /dev/null +++ b/vlib/v/checker/tests/enum_non_comptime_cast_call_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/enum_non_comptime_cast_call_err.vv:6:8: error: the default value for an enum has to be an integer + 4 | + 5 | enum Color { + 6 | red = int(get_value(1, 2, 3, 4)) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + 7 | } + 8 | diff --git a/vlib/v/checker/tests/enum_non_comptime_cast_call_err.vv b/vlib/v/checker/tests/enum_non_comptime_cast_call_err.vv new file mode 100644 index 000000000..23680d95b --- /dev/null +++ b/vlib/v/checker/tests/enum_non_comptime_cast_call_err.vv @@ -0,0 +1,9 @@ +fn get_value(a u8, b u8, c u8, d u8) u32 { + return (u32(a) << 24) | (u32(b) << 16) | (u32(c) << 8) | u32(d) +} + +enum Color { + red = int(get_value(1, 2, 3, 4)) +} + +fn main() {} diff --git a/vlib/v/tests/enums/enum_with_comptime_fn_calls_test.v b/vlib/v/tests/enums/enum_with_comptime_fn_calls_test.v index e015673b6..490f496f2 100644 --- a/vlib/v/tests/enums/enum_with_comptime_fn_calls_test.v +++ b/vlib/v/tests/enums/enum_with_comptime_fn_calls_test.v @@ -9,8 +9,20 @@ enum Colors as u32 { blue = pack_color(0, 0, 255, 255) } +enum CastedColors { + red = int(pack_color(1, 2, 3, 4)) + green = int(pack_color(5, 6, 7, 8)) + blue = int(pack_color(9, 10, 11, 12)) +} + fn test_enum_values_from_comptime_function_calls() { assert u32(Colors.red) == u32(0xff0000ff) assert u32(Colors.green) == u32(0x00ff00ff) assert u32(Colors.blue) == u32(0x0000ffff) } + +fn test_enum_values_from_casted_comptime_function_calls() { + assert int(CastedColors.red) == 0x01020304 + assert int(CastedColors.green) == 0x05060708 + assert int(CastedColors.blue) == 0x090a0b0c +} -- 2.39.5