From 497d05f93e6fb011eb904e3fbccf1fa44532783c Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 11 Mar 2026 15:39:50 +0300 Subject: [PATCH] checker: generics compile failure (fixes #24471) --- vlib/v/checker/checker.v | 12 ++--- ...ime_if_generic_struct_init_selector_test.v | 47 +++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 vlib/v/tests/comptime/comptime_if_generic_struct_init_selector_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 6931a1aee..050c1c585 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3488,12 +3488,6 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt, expected_o fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type { if typ.has_flag(.generic) { - if c.inside_generic_struct_init { - generic_names := c.cur_struct_generic_types.map(c.table.sym(it).name) - if t_typ := c.table.convert_generic_type(typ, generic_names, c.cur_struct_concrete_types) { - return t_typ - } - } if c.table.cur_fn != unsafe { nil } { if t_typ := c.table.convert_generic_type(typ, c.table.cur_fn.generic_names, c.table.cur_concrete_types) @@ -3508,6 +3502,12 @@ fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type { } } } + if c.inside_generic_struct_init { + generic_names := c.cur_struct_generic_types.map(c.table.sym(it).name) + if t_typ := c.table.convert_generic_type(typ, generic_names, c.cur_struct_concrete_types) { + return t_typ + } + } } return typ } diff --git a/vlib/v/tests/comptime/comptime_if_generic_struct_init_selector_test.v b/vlib/v/tests/comptime/comptime_if_generic_struct_init_selector_test.v new file mode 100644 index 000000000..f99f5780e --- /dev/null +++ b/vlib/v/tests/comptime/comptime_if_generic_struct_init_selector_test.v @@ -0,0 +1,47 @@ +struct CtType1 { + item f32 +} + +struct CtType2 { + item int +} + +struct CtGenericThing[T] { + part1 T + part2 T +} + +struct CtAnotherGenericThing[T] { + part3 T +} + +fn (thing CtGenericThing[T]) inline_weird() CtAnotherGenericThing[int] { + $if T is CtType2 { + return CtAnotherGenericThing[int]{thing.part1.item + thing.part2.item} + } $else $if T is CtType1 { + return CtAnotherGenericThing[int]{int(thing.part1.item + thing.part2.item)} + } $else { + $compile_error('unrecognised type') + } +} + +fn (thing CtGenericThing[T]) temp_var_weird() CtAnotherGenericThing[int] { + result := thing.part1.item + thing.part2.item + $if T is CtType2 { + return CtAnotherGenericThing[int]{result} + } $else $if T is CtType1 { + return CtAnotherGenericThing[int]{int(result)} + } $else { + $compile_error('unrecognised type') + } +} + +fn test_comptime_if_generic_struct_init_selector() { + thing1 := CtGenericThing{CtType1{1}, CtType1{2}} + assert thing1.inline_weird().part3 == 3 + assert thing1.temp_var_weird().part3 == 3 + + thing2 := CtGenericThing{CtType2{1}, CtType2{2}} + assert thing2.inline_weird().part3 == 3 + assert thing2.temp_var_weird().part3 == 3 +} -- 2.39.5