checker: check error for fn call argument mismatch (fix #14280) (#14283)
ci/woodpecker/push/vc Pipeline was successful Details
ci/woodpecker/push/docker Pipeline was successful Details
ci/woodpecker/push/arch Pipeline was successful Details

yuyi 2022-05-04 17:13:22 +08:00 committed by Jef Roosens
parent 95d94e683e
commit 41857b0acf
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
5 changed files with 35 additions and 17 deletions

View File

@ -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<int> == &Type<>`. This is a common case we are implementing a function
// with generic parameters like `compare(bst Bst<T> 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<int> 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<int> == &Type<>`. This is a common case we are implementing a function
// with generic parameters like `compare(bst Bst<T> 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<int> 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`')
}

View File

@ -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)

View File

@ -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 |

View File

@ -0,0 +1,7 @@
fn main() {
foo(bar())
}
fn foo(x int) {}
fn bar() {}