From 51aaf3c49f141d2ba36b335fa1f1576ee6a096bb Mon Sep 17 00:00:00 2001 From: shove Date: Sun, 17 Dec 2023 02:45:54 +0800 Subject: [PATCH] checker: fix incorrect checks when struct fields are ref and option type(fix #19555) (#20195) --- vlib/json/json_encode_recursive_ptr_test.v | 2 +- vlib/v/checker/struct.v | 5 +++-- .../tests/struct_field_init_option_ref_err.out | 7 +++++++ .../tests/struct_field_init_option_ref_err.vv | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 vlib/v/checker/tests/struct_field_init_option_ref_err.out create mode 100644 vlib/v/checker/tests/struct_field_init_option_ref_err.vv diff --git a/vlib/json/json_encode_recursive_ptr_test.v b/vlib/json/json_encode_recursive_ptr_test.v index eb98ba5902077c..7836cd5aece029 100644 --- a/vlib/json/json_encode_recursive_ptr_test.v +++ b/vlib/json/json_encode_recursive_ptr_test.v @@ -9,7 +9,7 @@ struct PostTag { } fn test_main() { - new_post_tag := PostTag{} + new_post_tag := &PostTag{} assert json.encode(new_post_tag) == '{"id":"","visibility":"","createdAt":"","metadata":""}' new_post_tag2 := PostTag{ diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index f5a156ed957329..9261a42e7ec23b 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -704,8 +704,9 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.', c.error('reference field must be initialized with reference', init_field.pos) } - } else if exp_type.is_pointer() && !got_type.is_any_kind_of_pointer() - && !got_type.is_int() { + } else if exp_type.is_any_kind_of_pointer() + && !got_type.is_any_kind_of_pointer() && !got_type.is_int() + && (!exp_type.has_flag(.option) || got_type.idx() != ast.none_type_idx) { got_typ_str := c.table.type_to_str(got_type) exp_typ_str := c.table.type_to_str(exp_type) c.error('cannot assign to field `${field_info.name}`: expected a pointer `${exp_typ_str}`, but got `${got_typ_str}`', diff --git a/vlib/v/checker/tests/struct_field_init_option_ref_err.out b/vlib/v/checker/tests/struct_field_init_option_ref_err.out new file mode 100644 index 00000000000000..3372d6a1a5880e --- /dev/null +++ b/vlib/v/checker/tests/struct_field_init_option_ref_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/struct_field_init_option_ref_err.vv:12:3: error: cannot assign to field `field`: expected a pointer `?&Foo`, but got `?Foo` + 10 | foo := ?Foo{} + 11 | _ := Bar{ + 12 | field: foo + | ~~~~~~~~~~ + 13 | } + 14 | } diff --git a/vlib/v/checker/tests/struct_field_init_option_ref_err.vv b/vlib/v/checker/tests/struct_field_init_option_ref_err.vv new file mode 100644 index 00000000000000..c25e29a998d67b --- /dev/null +++ b/vlib/v/checker/tests/struct_field_init_option_ref_err.vv @@ -0,0 +1,14 @@ +module main + +struct Foo {} + +struct Bar { + field ?&Foo +} + +fn main() { + foo := ?Foo{} + _ := Bar{ + field: foo + } +}