checker: fix the argument mismatch of fn call (#12479)

pull/12486/head
yuyi 2021-11-16 23:19:02 +08:00 committed by GitHub
parent 3fab0a5d05
commit 2984751a57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 10 deletions

View File

@ -1161,7 +1161,7 @@ fn is_excluding_latin(table &RangeTable, r rune) bool {
}
r32 := &table.r32
if r32.len > 0 && r >= rune((*r32)[0].lo) {
return is_32(r32, u32(r))
return is_32(*r32, u32(r))
}
return false
}

View File

@ -6,7 +6,7 @@ module checker
import v.ast
import v.token
pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language) ? {
pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language, arg ast.CallArg) ? {
mut expected := expected_
// variadic
if expected.has_flag(.variadic) {
@ -34,9 +34,6 @@ pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type,
return
}
}
if c.check_types(got, expected) {
return
}
idx_got := got.idx()
idx_expected := expected.idx()
if idx_got in [ast.byteptr_type_idx, ast.charptr_type_idx]
@ -72,6 +69,13 @@ pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type,
return
}
}
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.get_type_symbol(expected_).kind !in [.array, .map] {
return
}
}
return error('cannot use `${c.table.type_to_str(got.clear_flag(.variadic))}` as `${c.table.type_to_str(expected.clear_flag(.variadic))}`')
}

View File

@ -2185,7 +2185,8 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
if exp_arg_typ.has_flag(.generic) {
continue
}
c.check_expected_call_arg(got_arg_typ, c.unwrap_generic(exp_arg_typ), node.language) or {
c.check_expected_call_arg(got_arg_typ, c.unwrap_generic(exp_arg_typ), node.language,
arg) or {
// str method, allow type with str method if fn arg is string
// Passing an int or a string array produces a c error here
// Deleting this condition results in propper V error messages
@ -2326,7 +2327,8 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
if i < info.func.params.len {
exp_arg_typ := info.func.params[i].typ
c.check_expected_call_arg(targ, c.unwrap_generic(exp_arg_typ), node.language) or {
c.check_expected_call_arg(targ, c.unwrap_generic(exp_arg_typ), node.language,
arg) or {
if targ != ast.void_type {
c.error('$err.msg in argument ${i + 1} to `${left_sym.name}.$method_name`',
arg.pos)
@ -2372,7 +2374,7 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type ast.
}
info := left_sym.info as ast.Map
arg_type := c.expr(node.args[0].expr)
c.check_expected_call_arg(arg_type, info.key_type, node.language) or {
c.check_expected_call_arg(arg_type, info.key_type, node.language, node.args[0]) or {
c.error('$err.msg in argument 1 to `Map.delete`', node.args[0].pos)
}
}
@ -2866,7 +2868,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
}
continue
}
c.check_expected_call_arg(typ, c.unwrap_generic(param.typ), node.language) or {
c.check_expected_call_arg(typ, c.unwrap_generic(param.typ), node.language, call_arg) or {
// str method, allow type with str method if fn arg is string
// Passing an int or a string array produces a c error here
// Deleting this condition results in propper V error messages
@ -2942,7 +2944,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
}
continue
}
c.check_expected_call_arg(utyp, unwrap_typ, node.language) or {
c.check_expected_call_arg(utyp, unwrap_typ, node.language, call_arg) or {
c.error('$err.msg in argument ${i + 1} to `$fn_name`', call_arg.pos)
}
}

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/fn_call_arg_mismatch.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)
| ~~
8 | println('done')
9 | }

View File

@ -0,0 +1,9 @@
fn abc(x []int) {
println(x)
}
fn main() {
a := [1, 2, 3]
go abc(&a)
println('done')
}