1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: check fn returning fn type mismatch (fix #15988) (#15997)

This commit is contained in:
yuyi 2022-10-09 00:28:41 +08:00 committed by GitHub
parent 49aac93d87
commit ce1ba2ad02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 9 deletions

View File

@ -384,8 +384,10 @@ pub fn (mut c Checker) check_matching_function_symbols(got_type_sym &ast.TypeSym
}
for i, got_arg in got_fn.params {
exp_arg := exp_fn.params[i]
exp_arg_is_ptr := exp_arg.typ.is_ptr() || exp_arg.typ.is_pointer()
got_arg_is_ptr := got_arg.typ.is_ptr() || got_arg.typ.is_pointer()
exp_arg_typ := c.unwrap_generic(exp_arg.typ)
got_arg_typ := c.unwrap_generic(got_arg.typ)
exp_arg_is_ptr := exp_arg_typ.is_ptr() || exp_arg_typ.is_pointer()
got_arg_is_ptr := got_arg_typ.is_ptr() || got_arg_typ.is_pointer()
if exp_arg_is_ptr != got_arg_is_ptr {
exp_arg_pointedness := if exp_arg_is_ptr { 'a pointer' } else { 'NOT a pointer' }
got_arg_pointedness := if got_arg_is_ptr { 'a pointer' } else { 'NOT a pointer' }
@ -397,9 +399,11 @@ pub fn (mut c Checker) check_matching_function_symbols(got_type_sym &ast.TypeSym
}
return false
} else if exp_arg_is_ptr && got_arg_is_ptr {
continue
if exp_arg_typ.is_pointer() || got_arg_typ.is_pointer() {
continue
}
}
if got_arg.typ != exp_arg.typ {
if c.table.unaliased_type(got_arg_typ).idx() != c.table.unaliased_type(exp_arg_typ).idx() {
return false
}
}

View File

@ -134,12 +134,12 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) {
}
continue
}
if got_typ_sym.kind == .function && exp_typ_sym.kind == .function {
if (got_typ_sym.info as ast.FnType).is_anon {
continue
}
got_typ_name := if got_typ_sym.kind == .function {
'${c.table.type_to_str(got_typ)}'
} else {
got_typ_sym.name
}
c.error('cannot use `$got_typ_sym.name` as type `${c.table.type_to_str(exp_type)}` in return argument',
c.error('cannot use `$got_typ_name` as type `${c.table.type_to_str(exp_type)}` in return argument',
pos)
}
}

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/fn_return_fn_type_mismatch_err.vv:22:9: error: cannot use `fn (&WrongType, i64, u64) int` as type `fn (&ExpectedType, i64, u64) int` in return argument
20 | pub fn bad_signature() Fn {
21 | // create closure that has nonmatching signature due to first arg. Compiler should reject it
22 | return fn (n &WrongType, a i64, b u64) int {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 | println('bad signature param0=$n')
24 | return 0

View File

@ -0,0 +1,39 @@
pub struct ExpectedType {
a u32
b u32
}
struct WrongType {
c string
d int
}
pub type Fn = fn (&ExpectedType, i64, u64) int
pub fn good_signature() Fn {
return fn (n &ExpectedType, a i64, b u64) int {
println('good signature param0=$n')
return 0
}
}
pub fn bad_signature() Fn {
// create closure that has nonmatching signature due to first arg. Compiler should reject it
return fn (n &WrongType, a i64, b u64) int {
println('bad signature param0=$n')
return 0
}
}
fn main() {
arg := &ExpectedType{
a: 3
b: 7
}
mut cb := good_signature()
cb(arg, 1, 1)
cb = bad_signature()
cb(arg, 1, 1)
}