checker: check fn return type mismatch (#14081)
parent
f291e5fdd8
commit
33005becf1
|
@ -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',
|
||||
|
|
|
@ -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 |
|
|
@ -0,0 +1,9 @@
|
|||
fn func1() (i64, i64) {
|
||||
return i64(1), i64(2)
|
||||
}
|
||||
|
||||
fn func2() (int, int) {
|
||||
return func1()
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue