diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index b828c56b90..ab2aa0356b 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -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 } } diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 7736c2d2d0..7080096378 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -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) } } diff --git a/vlib/v/checker/tests/fn_return_fn_type_mismatch_err.out b/vlib/v/checker/tests/fn_return_fn_type_mismatch_err.out new file mode 100644 index 0000000000..dfef25bc0f --- /dev/null +++ b/vlib/v/checker/tests/fn_return_fn_type_mismatch_err.out @@ -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 diff --git a/vlib/v/checker/tests/fn_return_fn_type_mismatch_err.vv b/vlib/v/checker/tests/fn_return_fn_type_mismatch_err.vv new file mode 100644 index 0000000000..7d13a339e2 --- /dev/null +++ b/vlib/v/checker/tests/fn_return_fn_type_mismatch_err.vv @@ -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) +}