From 36e31d6908311b87e0d447bbcbc9ac3b96bd88e0 Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Wed, 3 Jul 2024 01:35:20 +0530 Subject: [PATCH] checker: disallow nil in non-nil arrays and vice versa (#21786) --- vlib/v/checker/check_types.v | 14 ++++++++++++++ .../tests/non_nil_array_with_nil_element_err.out | 8 ++++++++ .../tests/non_nil_array_with_nil_element_err.vv | 2 ++ .../struct_field_assign_internal_types_nil_err.out | 7 +++++++ vlib/v/tests/cast_fixed_array_to_ptr_ptr_test.v | 2 +- 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 vlib/v/checker/tests/non_nil_array_with_nil_element_err.out create mode 100644 vlib/v/checker/tests/non_nil_array_with_nil_element_err.vv diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 028f5b7df47e1e..3ee37d2f99f389 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -129,6 +129,20 @@ fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool { return true } } + + if (exp_idx == ast.nil_type_idx && got_idx == ast.string_type_idx) + || (got_idx == ast.nil_type_idx && exp_idx == ast.string_type_idx) { + got_sym := c.table.sym(got) + exp_sym := c.table.sym(expected) + + if expected.is_ptr() || got.is_ptr() { + return true + } + if got_sym.language != .c || exp_sym.language != .c { + return false + } + } + // allow direct int-literal assignment for pointers for now // maybe in the future options should be used for that if expected.is_any_kind_of_pointer() { diff --git a/vlib/v/checker/tests/non_nil_array_with_nil_element_err.out b/vlib/v/checker/tests/non_nil_array_with_nil_element_err.out new file mode 100644 index 00000000000000..20128caea0858a --- /dev/null +++ b/vlib/v/checker/tests/non_nil_array_with_nil_element_err.out @@ -0,0 +1,8 @@ +vlib/v/checker/tests/non_nil_array_with_nil_element_err.vv:1:23: error: invalid array element: expected `string`, not `voidptr` + 1 | const spnames = ['f', unsafe { nil }]! + | ~~~~~~ + 2 | const spnames1 = [unsafe { nil }, 'f']! +vlib/v/checker/tests/non_nil_array_with_nil_element_err.vv:2:35: error: invalid array element: expected `voidptr`, not `string` + 1 | const spnames = ['f', unsafe { nil }]! + 2 | const spnames1 = [unsafe { nil }, 'f']! + | ~~~ diff --git a/vlib/v/checker/tests/non_nil_array_with_nil_element_err.vv b/vlib/v/checker/tests/non_nil_array_with_nil_element_err.vv new file mode 100644 index 00000000000000..67c7e1f5f867cc --- /dev/null +++ b/vlib/v/checker/tests/non_nil_array_with_nil_element_err.vv @@ -0,0 +1,2 @@ +const spnames = ['f', unsafe { nil }]! +const spnames1 = [unsafe { nil }, 'f']! 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 index 37b765408b00b3..9bf7b9e622d90d 100644 --- 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 @@ -1,3 +1,10 @@ +vlib/v/checker/tests/struct_field_assign_internal_types_nil_err.vv:15:2: error: cannot assign to field `name`: expected `string`, not `voidptr` + 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:15:8: error: cannot assign `nil` to struct field `name` with type `string` 13 | 14 | a := &Foo{ diff --git a/vlib/v/tests/cast_fixed_array_to_ptr_ptr_test.v b/vlib/v/tests/cast_fixed_array_to_ptr_ptr_test.v index 09ceec74c15a43..b0f5cee0a9f4bd 100644 --- a/vlib/v/tests/cast_fixed_array_to_ptr_ptr_test.v +++ b/vlib/v/tests/cast_fixed_array_to_ptr_ptr_test.v @@ -5,7 +5,7 @@ struct Foo { fn test_main() { foo := Foo{ bar: unsafe { - &&char(['a', 'b', nil]!) + &&char([c'a', c'b', nil]!) } } println(foo)