diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 25d5893daed60a..eec6e7d0ebfcda 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -596,6 +596,13 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini inited_fields << struct_field.name } } + expected_type_sym := c.table.final_sym(init_field.expected_type) + if expected_type_sym.kind in [.string, .array, .map, .array_fixed, .chan, .struct_] + && init_field.expr.is_nil() && !init_field.expected_type.is_ptr() + && mut init_field.expr is ast.UnsafeExpr { + c.error('cannot assign `nil` to struct field `${init_field.name}` with type `${expected_type_sym.name}`', + init_field.expr.pos.extend(init_field.expr.expr.pos())) + } } // Check uninitialized refs/sum types // The variable `fields` contains two parts, the first part is the same as info.fields, diff --git a/vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.out b/vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.out new file mode 100644 index 00000000000000..2503d7d3eb3914 --- /dev/null +++ b/vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.out @@ -0,0 +1,42 @@ +vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv:15:8: error: cannot assign `nil` to struct field `name` with type `string` + 13 | + 14 | a := &Foo{ + 15 | name: unsafe { nil } + | ~~~~~~~~~~~~ + 16 | bar: unsafe { nil } + 17 | name2: unsafe { nil } +vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv:16:7: error: cannot assign `nil` to struct field `bar` with type `Bar` + 14 | a := &Foo{ + 15 | name: unsafe { nil } + 16 | bar: unsafe { nil } + | ~~~~~~~~~~~~ + 17 | name2: unsafe { nil } + 18 | arr: unsafe { nil } +vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv:17:9: error: cannot assign `nil` to struct field `name2` with type `string` + 15 | name: unsafe { nil } + 16 | bar: unsafe { nil } + 17 | name2: unsafe { nil } + | ~~~~~~~~~~~~ + 18 | arr: unsafe { nil } + 19 | mp: unsafe { nil } +vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv:18:7: error: cannot assign `nil` to struct field `arr` with type `[]int` + 16 | bar: unsafe { nil } + 17 | name2: unsafe { nil } + 18 | arr: unsafe { nil } + | ~~~~~~~~~~~~ + 19 | mp: unsafe { nil } + 20 | arr_fix: unsafe { nil } +vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv:19:6: error: cannot assign `nil` to struct field `mp` with type `map[string]string` + 17 | name2: unsafe { nil } + 18 | arr: unsafe { nil } + 19 | mp: unsafe { nil } + | ~~~~~~~~~~~~ + 20 | arr_fix: unsafe { nil } + 21 | } +vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv:20:11: error: cannot assign `nil` to struct field `arr_fix` with type `[3]int` + 18 | arr: unsafe { nil } + 19 | mp: unsafe { nil } + 20 | arr_fix: unsafe { nil } + | ~~~~~~~~~~~~ + 21 | } + 22 | println(a) diff --git a/vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv b/vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv new file mode 100644 index 00000000000000..95079c1f376e55 --- /dev/null +++ b/vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv @@ -0,0 +1,22 @@ +type String = string + +struct Bar {} + +struct Foo { + name string + bar Bar + name2 String + arr []int + mp map[string]string + arr_fix [3]int +} + +a := &Foo{ + name: unsafe { nil } + bar: unsafe { nil } + name2: unsafe { nil } + arr: unsafe { nil } + mp: unsafe { nil } + arr_fix: unsafe { nil } +} +println(a)