From 6ff1c0a0b2f52bb0c967b08c21cb11852844a01e Mon Sep 17 00:00:00 2001 From: yuyi Date: Fri, 31 Mar 2023 15:59:52 +0800 Subject: [PATCH] checker: fix generic struct init with update expr (fix #17824) (#17827) --- vlib/v/checker/struct.v | 8 ++-- ...eneric_struct_init_with_update_expr_test.v | 39 +++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 vlib/v/tests/generic_struct_init_with_update_expr_test.v diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 3c3a9d3e64..aa5fe0b953 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -295,7 +295,8 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini } } if struct_sym.info.generic_types.len > 0 && struct_sym.info.concrete_types.len == 0 - && !node.is_short_syntax && c.table.cur_concrete_types.len != 0 { + && !node.is_short_syntax && c.table.cur_concrete_types.len != 0 + && !is_field_zero_struct_init { if node.generic_types.len == 0 { c.error('generic struct init must specify type parameter, e.g. Foo[T]', node.pos) @@ -648,8 +649,9 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini node.pos) } } - if !field.has_default_expr && field.name !in inited_fields && !field.typ.is_ptr() - && !field.typ.has_flag(.option) && c.table.final_sym(field.typ).kind == .struct_ { + if !node.has_update_expr && !field.has_default_expr && field.name !in inited_fields + && !field.typ.is_ptr() && !field.typ.has_flag(.option) + && c.table.final_sym(field.typ).kind == .struct_ { mut zero_struct_init := ast.StructInit{ pos: node.pos typ: field.typ diff --git a/vlib/v/tests/generic_struct_init_with_update_expr_test.v b/vlib/v/tests/generic_struct_init_with_update_expr_test.v new file mode 100644 index 0000000000..a1f139246a --- /dev/null +++ b/vlib/v/tests/generic_struct_init_with_update_expr_test.v @@ -0,0 +1,39 @@ +pub struct Time[T] { +pub mut: + start T + end T +} + +pub struct Transform[T] { +pub mut: + time Time[T] + before []T + after []T +} + +pub fn (t Transform[T]) clone() Transform[T] { + return Transform[T]{ + ...t + } +} + +pub fn (t Transform[T]) default() Transform[T] { + return Transform[T]{} +} + +fn test_generic_struct_init_with_update_expr() { + a := Transform[f64]{ + before: [0.0, 0.0] + after: [320.0, 240.0] + } + + b := a.clone() + println(b) + assert b.before == a.before + assert b.after == a.after + + c := a.default() + println(c) + assert c.before.len == 0 + assert c.after.len == 0 +}