From 33005becf14d6a2c1167da510a02f4ec86203c30 Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 19 Apr 2022 18:04:41 +0800 Subject: [PATCH] checker: check fn return type mismatch (#14081) --- vlib/v/checker/return.v | 19 +++++++++++-------- .../checker/tests/fn_return_type_mismatch.out | 7 +++++++ .../checker/tests/fn_return_type_mismatch.vv | 9 +++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 vlib/v/checker/tests/fn_return_type_mismatch.out create mode 100644 vlib/v/checker/tests/fn_return_type_mismatch.vv diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index c38792a0c0..a545dfe54d 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -32,7 +32,8 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { } } mut got_types := []ast.Type{} - for expr in node.exprs { + mut expr_idxs := []int{} + for i, expr in node.exprs { typ := c.expr(expr) if typ == ast.void_type { c.error('`$expr` used as value', node.pos) @@ -42,9 +43,11 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { if sym.kind == .multi_return { for t in sym.mr_info().types { got_types << t + expr_idxs << i } } else { got_types << typ + expr_idxs << i } } node.types = got_types @@ -82,7 +85,7 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { got_typ := c.unwrap_generic(got_types[i]) if got_typ.has_flag(.optional) && (!exp_type.has_flag(.optional) || c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type)) { - pos := node.exprs[i].pos() + pos := node.exprs[expr_idxs[i]].pos() c.error('cannot use `${c.table.type_to_str(got_typ)}` as type `${c.table.type_to_str(exp_type)}` in return argument', pos) } @@ -93,19 +96,19 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { if c.type_implements(got_typ, exp_type, node.pos) { if !got_typ.is_ptr() && !got_typ.is_pointer() && got_typ_sym.kind != .interface_ && !c.inside_unsafe { - c.mark_as_referenced(mut &node.exprs[i], true) + c.mark_as_referenced(mut &node.exprs[expr_idxs[i]], true) } } continue } - pos := node.exprs[i].pos() + pos := node.exprs[expr_idxs[i]].pos() c.error('cannot use `$got_typ_sym.name` as type `${c.table.type_to_str(exp_type)}` in return argument', pos) } if (got_typ.is_ptr() || got_typ.is_pointer()) && (!exp_type.is_ptr() && !exp_type.is_pointer()) { - pos := node.exprs[i].pos() - if node.exprs[i].is_auto_deref_var() { + pos := node.exprs[expr_idxs[i]].pos() + if node.exprs[expr_idxs[i]].is_auto_deref_var() { continue } c.error('fn `$c.table.cur_fn.name` expects you to return a non reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead', @@ -114,8 +117,8 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { if (exp_type.is_ptr() || exp_type.is_pointer()) && (!got_typ.is_ptr() && !got_typ.is_pointer()) && got_typ != ast.int_literal_type && !c.pref.translated && !c.file.is_translated { - pos := node.exprs[i].pos() - if node.exprs[i].is_auto_deref_var() { + pos := node.exprs[expr_idxs[i]].pos() + if node.exprs[expr_idxs[i]].is_auto_deref_var() { continue } c.error('fn `$c.table.cur_fn.name` expects you to return a reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead', diff --git a/vlib/v/checker/tests/fn_return_type_mismatch.out b/vlib/v/checker/tests/fn_return_type_mismatch.out new file mode 100644 index 0000000000..9dfa73c50f --- /dev/null +++ b/vlib/v/checker/tests/fn_return_type_mismatch.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/fn_return_type_mismatch.vv:6:9: error: cannot use `i64` as type `int` in return argument + 4 | + 5 | fn func2() (int, int) { + 6 | return func1() + | ~~~~~~~ + 7 | } + 8 | diff --git a/vlib/v/checker/tests/fn_return_type_mismatch.vv b/vlib/v/checker/tests/fn_return_type_mismatch.vv new file mode 100644 index 0000000000..ab4d4e1bf1 --- /dev/null +++ b/vlib/v/checker/tests/fn_return_type_mismatch.vv @@ -0,0 +1,9 @@ +fn func1() (i64, i64) { + return i64(1), i64(2) +} + +fn func2() (int, int) { + return func1() +} + +fn main() {}