From 554bbead6331d94bc37d42500530c66f06667554 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 11 Mar 2026 16:34:22 +0300 Subject: [PATCH] checker: error behavior in array of sumtype has array subtype (fixes #26363) --- vlib/v/checker/checker.v | 10 ++++++++++ vlib/v/checker/containers.v | 19 +++++++++--------- vlib/v/gen/c/infix.v | 3 ++- .../sumtype_array_push_array_variant_test.v | 20 +++++++++++++++++++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index e7259a8b5..aeb89eee7 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -4004,7 +4004,17 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } old_inside_integer_literal_cast := c.inside_integer_literal_cast c.inside_integer_literal_cast = to_type.is_int() && node.expr is ast.IntegerLiteral + old_expected_type := c.expected_type + if mut node.expr is ast.ArrayInit && node.expr.typ == ast.void_type + && c.table.final_sym(to_type).kind == .sum_type + && c.table.final_sym(c.expected_type).kind == .array + && c.table.value_type(c.expected_type) == to_type { + // `arr << SumType([Alias(1), 2])` should infer the inner array variant, + // not force the literal to become `[]SumType` from the surrounding append. + c.expected_type = ast.void_type + } node.expr_type = c.expr(mut node.expr) // type to be casted + c.expected_type = old_expected_type c.inside_integer_literal_cast = old_inside_integer_literal_cast if mut node.expr is ast.ComptimeSelector { diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index cf1fbb587..eab9c2893 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -850,18 +850,17 @@ fn (mut c Checker) check_append(mut node ast.InfixExpr, left_type ast.Type, righ } return ast.void_type } else if left_value_sym.kind == .sum_type { - if right_sym.kind != .array { - if !c.table.is_sumtype_or_in_variant(left_value_type, ast.mktyp(c.unwrap_generic(right_type))) { - c.error('cannot append `${right_sym.name}` to `${left_sym.name}`', right_pos) - } - } else { - right_value_type := c.table.value_type(c.unwrap_generic(right_type)) - left_sumtype := c.table.unaliased_type(c.unwrap_generic(left_value_type)) - right_sumtype := c.table.unaliased_type(c.unwrap_generic(right_value_type)) - if left_sumtype != right_sumtype { - c.error('cannot append `${right_sym.name}` to `${left_sym.name}`', right_pos) + base_right_type := c.unwrap_generic(right_type) + if c.check_types(base_right_type, left_value_type) { + return ast.void_type + } + if right_sym.kind == .array { + right_value_type := c.table.value_type(base_right_type) + if c.check_types(right_value_type, left_value_type) { + return ast.void_type } } + c.error('cannot append `${right_sym.name}` to `${left_sym.name}`', right_pos) return ast.void_type } // []T << T or []T << []T diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 7e7b39a5a..fb2e5a25c 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -1137,7 +1137,8 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) { if needs_clone { g.write('builtin__string_clone(') } - if node.right is ast.CastExpr && node.right.expr is ast.ArrayInit { + if node.right is ast.CastExpr && node.right.expr is ast.ArrayInit + && elem_sym.kind != .sum_type { g.expr(node.right.expr) } else if elem_sym.info is ast.ArrayFixed && node.right in [ast.CallExpr, ast.DumpExpr] { diff --git a/vlib/v/tests/sumtype_array_push_array_variant_test.v b/vlib/v/tests/sumtype_array_push_array_variant_test.v index ecaddd805..aad38c80f 100644 --- a/vlib/v/tests/sumtype_array_push_array_variant_test.v +++ b/vlib/v/tests/sumtype_array_push_array_variant_test.v @@ -4,6 +4,8 @@ // the compiler incorrectly used PUSH_MANY instead of pushing as a single element. type Prim = int | string | []Prim +type AliasInt = int +type ArrayPrim = []AliasInt | int | []u8 fn test_push_array_literal_to_sumtype_array() { mut args := []Prim{} @@ -50,3 +52,21 @@ fn test_empty_sumtype_array_init() { } assert args.len == 3 } + +fn test_push_array_subtype_variant_to_sumtype_array() { + mut args := []ArrayPrim{} + args << [u8(1), 2, 3] + assert args.len == 1 + + inner := args[0] as []u8 + assert inner == [u8(1), 2, 3] +} + +fn test_push_cast_array_subtype_variant_to_sumtype_array() { + mut args := []ArrayPrim{} + args << ArrayPrim([AliasInt(1), 2]) + assert args.len == 1 + + inner := args[0] as []AliasInt + assert inner == [AliasInt(1), 2] +} -- 2.39.5