From e93c344b56cbeb56d4cba558a2cf44f6d1580d1f Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 12 May 2025 07:00:03 -0300 Subject: [PATCH] checker: fix generic option array arg passing to `[]T` (fix #24423) (#24457) --- vlib/v/checker/fn.v | 12 +++++++ .../tests/generics/generic_array_pass_test.v | 31 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 vlib/v/tests/generics/generic_array_pass_test.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index da40e36f8f..51f9d88e03 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1852,6 +1852,12 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. c.handle_generic_lambda_arg(node, mut call_arg.expr) continue } + // passing []?T to []T + if !unwrap_typ.has_flag(.variadic) && unwrap_sym.kind == .array + && c.table.final_sym(utyp).kind == .array + && c.check_basic(c.table.value_type(utyp).clear_flag(.option), c.table.value_type(unwrap_typ)) { + continue + } c.error('${err.msg()} in argument ${i + 1} to `${fn_name}`', call_arg.pos) } } @@ -2607,6 +2613,12 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool) continue } } + // passing []?T to []T + if !exp_arg_typ.has_flag(.variadic) && param_typ_sym.kind == .array + && c.table.final_sym(got_arg_typ).kind == .array + && c.check_basic(c.table.value_type(got_arg_typ).clear_flag(.option), c.table.value_type(exp_arg_typ)) { + continue + } c.error('${err.msg()} in argument ${i + 1} to `${left_sym.name}.${method_name}`', arg.pos) } diff --git a/vlib/v/tests/generics/generic_array_pass_test.v b/vlib/v/tests/generics/generic_array_pass_test.v new file mode 100644 index 0000000000..b3e0c5790c --- /dev/null +++ b/vlib/v/tests/generics/generic_array_pass_test.v @@ -0,0 +1,31 @@ +struct Decoder {} + +pub fn decode[T](val string) !T { + mut decoder := Decoder{} + mut result := T{} + decoder.decode_value(mut result)! + return result +} + +fn (mut decoder Decoder) decode_value[T](mut val T) ! { + $if T.unaliased_typ is $array { + // checking wrongly. `decode_array` think that `[]?int` is `[]int` + decoder.decode_array(mut val)! + return + } $else $if T.unaliased_typ is $struct { + $for field in T.fields { + decoder.decode_value(mut val.$(field.name))! + } + } +} + +fn (mut decoder Decoder) decode_array[T](mut val []T) ! {} + +struct Foo { + int []int + oint []?int +} + +fn test_main() { + decode[Foo]('')! +}