From 41857b0acf60ad6371a4e85f252f0a6a6bd7ecaf Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 4 May 2022 17:13:22 +0800 Subject: [PATCH] checker: check error for fn call argument mismatch (fix #14280) (#14283) --- vlib/v/checker/check_types.v | 37 +++++++++++-------- ...tch.out => fn_call_arg_mismatch_err_a.out} | 2 +- ...match.vv => fn_call_arg_mismatch_err_a.vv} | 0 .../tests/fn_call_arg_mismatch_err_b.out | 6 +++ .../tests/fn_call_arg_mismatch_err_b.vv | 7 ++++ 5 files changed, 35 insertions(+), 17 deletions(-) rename vlib/v/checker/tests/{fn_call_arg_mismatch.out => fn_call_arg_mismatch_err_a.out} (52%) rename vlib/v/checker/tests/{fn_call_arg_mismatch.vv => fn_call_arg_mismatch_err_a.vv} (100%) create mode 100644 vlib/v/checker/tests/fn_call_arg_mismatch_err_b.out create mode 100644 vlib/v/checker/tests/fn_call_arg_mismatch_err_b.vv diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 135bc2548a..071af72844 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -205,30 +205,35 @@ pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, return } } + got_typ_sym := c.table.sym(got) + got_typ_str := c.table.type_to_str(got.clear_flag(.variadic)) + expected_typ_sym := c.table.sym(expected_) + expected_typ_str := c.table.type_to_str(expected.clear_flag(.variadic)) + if c.check_types(got, expected) { if language != .v || expected.is_ptr() == got.is_ptr() || arg.is_mut || arg.expr.is_auto_deref_var() || got.has_flag(.shared_f) || c.table.sym(expected_).kind !in [.array, .map] { return } - } - - // Check on Generics types, there are some case where we have the following case - // `&Type == &Type<>`. This is a common case we are implementing a function - // with generic parameters like `compare(bst Bst node) {}` - got_typ_sym := c.table.sym(got) - got_typ_str := c.table.type_to_str(got.clear_flag(.variadic)) - expected_typ_sym := c.table.sym(expected_) - expected_typ_str := c.table.type_to_str(expected.clear_flag(.variadic)) - - if got_typ_sym.symbol_name_except_generic() == expected_typ_sym.symbol_name_except_generic() { - // Check if we are making a comparison between two different types of - // the same type like `Type and &Type<>` - if (got.is_ptr() != expected.is_ptr()) || !c.check_same_module(got, expected) { - return error('cannot use `$got_typ_str` as `$expected_typ_str`') + } else { + // Check on Generics types, there are some case where we have the following case + // `&Type == &Type<>`. This is a common case we are implementing a function + // with generic parameters like `compare(bst Bst node) {}` + if got_typ_sym.symbol_name_except_generic() == expected_typ_sym.symbol_name_except_generic() { + // Check if we are making a comparison between two different types of + // the same type like `Type and &Type<>` + if (got.is_ptr() != expected.is_ptr()) || !c.check_same_module(got, expected) { + return error('cannot use `$got_typ_str` as `$expected_typ_str`') + } + return } - return + if got == ast.void_type { + return error('`$arg.expr` (no value) used as value') + } + return error('cannot use `$got_typ_str` as `$expected_typ_str`') } + if got != ast.void_type { return error('cannot use `$got_typ_str` as `$expected_typ_str`') } diff --git a/vlib/v/checker/tests/fn_call_arg_mismatch.out b/vlib/v/checker/tests/fn_call_arg_mismatch_err_a.out similarity index 52% rename from vlib/v/checker/tests/fn_call_arg_mismatch.out rename to vlib/v/checker/tests/fn_call_arg_mismatch_err_a.out index eade10ddfe..dd940f8262 100644 --- a/vlib/v/checker/tests/fn_call_arg_mismatch.out +++ b/vlib/v/checker/tests/fn_call_arg_mismatch_err_a.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/fn_call_arg_mismatch.vv:7:9: error: cannot use `&[]int` as `[]int` in argument 1 to `abc` +vlib/v/checker/tests/fn_call_arg_mismatch_err_a.vv:7:9: error: cannot use `&[]int` as `[]int` in argument 1 to `abc` 5 | fn main() { 6 | a := [1, 2, 3] 7 | go abc(&a) diff --git a/vlib/v/checker/tests/fn_call_arg_mismatch.vv b/vlib/v/checker/tests/fn_call_arg_mismatch_err_a.vv similarity index 100% rename from vlib/v/checker/tests/fn_call_arg_mismatch.vv rename to vlib/v/checker/tests/fn_call_arg_mismatch_err_a.vv diff --git a/vlib/v/checker/tests/fn_call_arg_mismatch_err_b.out b/vlib/v/checker/tests/fn_call_arg_mismatch_err_b.out new file mode 100644 index 0000000000..af83ecb67d --- /dev/null +++ b/vlib/v/checker/tests/fn_call_arg_mismatch_err_b.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/fn_call_arg_mismatch_err_b.vv:2:6: error: `bar()` (no value) used as value in argument 1 to `foo` + 1 | fn main() { + 2 | foo(bar()) + | ~~~~~ + 3 | } + 4 | diff --git a/vlib/v/checker/tests/fn_call_arg_mismatch_err_b.vv b/vlib/v/checker/tests/fn_call_arg_mismatch_err_b.vv new file mode 100644 index 0000000000..cced295dd1 --- /dev/null +++ b/vlib/v/checker/tests/fn_call_arg_mismatch_err_b.vv @@ -0,0 +1,7 @@ +fn main() { + foo(bar()) +} + +fn foo(x int) {} + +fn bar() {}