From 8162396783d8118e6c45cc77f4bdda8cf06edb6c Mon Sep 17 00:00:00 2001 From: zakuro Date: Thu, 28 Jan 2021 06:10:51 +0900 Subject: [PATCH] checker: deny multi-value in a singe-value context (#8328) --- vlib/v/checker/checker.v | 28 ++++--- .../v/checker/tests/assign_multi_mismatch.out | 81 +++++++++++++++++++ vlib/v/checker/tests/assign_multi_mismatch.vv | 30 +++++++ 3 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 vlib/v/checker/tests/assign_multi_mismatch.out create mode 100644 vlib/v/checker/tests/assign_multi_mismatch.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 0bad3784f9..ca48c698ab 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2358,17 +2358,23 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { right_first := assign_stmt.right[0] mut right_len := assign_stmt.right.len mut right_type0 := table.void_type - if right_first is ast.CallExpr || right_first is ast.IfExpr || right_first is ast.MatchExpr { - right_type0 = c.expr(right_first) - assign_stmt.right_types = [ - c.check_expr_opt_call(right_first, right_type0), - ] - right_type_sym0 := c.table.get_type_symbol(right_type0) - if right_type_sym0.kind == .multi_return { - assign_stmt.right_types = right_type_sym0.mr_info().types - right_len = assign_stmt.right_types.len - } else if right_type0 == table.void_type { - right_len = 0 + for right in assign_stmt.right { + if right is ast.CallExpr || right is ast.IfExpr || right is ast.MatchExpr { + right_type0 = c.expr(right) + assign_stmt.right_types = [ + c.check_expr_opt_call(right, right_type0), + ] + right_type_sym0 := c.table.get_type_symbol(right_type0) + if right_type_sym0.kind == .multi_return { + if assign_stmt.right.len > 1 { + c.error('cannot use multi-value $right_type_sym0.name in signle-value context', + right.position()) + } + assign_stmt.right_types = right_type_sym0.mr_info().types + right_len = assign_stmt.right_types.len + } else if right_type0 == table.void_type { + right_len = 0 + } } } if assign_stmt.left.len != right_len { diff --git a/vlib/v/checker/tests/assign_multi_mismatch.out b/vlib/v/checker/tests/assign_multi_mismatch.out new file mode 100644 index 0000000000..23c1ef9a6a --- /dev/null +++ b/vlib/v/checker/tests/assign_multi_mismatch.out @@ -0,0 +1,81 @@ +vlib/v/checker/tests/assign_multi_mismatch.vv:5:3: error: assignment mismatch: 1 variable(s) 2 value(s) + 3 | } + 4 | + 5 | _ := 0, 0 + | ~~ + 6 | _ := f() + 7 | _, _ := f() +vlib/v/checker/tests/assign_multi_mismatch.vv:6:3: error: assignment mismatch: 1 variable(s) but `f()` returns 2 value(s) + 4 | + 5 | _ := 0, 0 + 6 | _ := f() + | ~~ + 7 | _, _ := f() + 8 | _, _ := 0, f() +vlib/v/checker/tests/assign_multi_mismatch.vv:8:12: error: cannot use multi-value (int, int) in signle-value context + 6 | _ := f() + 7 | _, _ := f() + 8 | _, _ := 0, f() + | ~~~ + 9 | _, _ := f(), 0 + 10 | _, _, _ := 0, f() +vlib/v/checker/tests/assign_multi_mismatch.vv:9:9: error: cannot use multi-value (int, int) in signle-value context + 7 | _, _ := f() + 8 | _, _ := 0, f() + 9 | _, _ := f(), 0 + | ~~~ + 10 | _, _, _ := 0, f() + 11 | _, _, _ := f(), 0 +vlib/v/checker/tests/assign_multi_mismatch.vv:10:15: error: cannot use multi-value (int, int) in signle-value context + 8 | _, _ := 0, f() + 9 | _, _ := f(), 0 + 10 | _, _, _ := 0, f() + | ~~~ + 11 | _, _, _ := f(), 0 + 12 | _, _ := f(), f() +vlib/v/checker/tests/assign_multi_mismatch.vv:11:12: error: cannot use multi-value (int, int) in signle-value context + 9 | _, _ := f(), 0 + 10 | _, _, _ := 0, f() + 11 | _, _, _ := f(), 0 + | ~~~ + 12 | _, _ := f(), f() + 13 | _, _, _, _ := f(), f() +vlib/v/checker/tests/assign_multi_mismatch.vv:12:9: error: cannot use multi-value (int, int) in signle-value context + 10 | _, _, _ := 0, f() + 11 | _, _, _ := f(), 0 + 12 | _, _ := f(), f() + | ~~~ + 13 | _, _, _, _ := f(), f() + 14 | +vlib/v/checker/tests/assign_multi_mismatch.vv:13:15: error: cannot use multi-value (int, int) in signle-value context + 11 | _, _, _ := f(), 0 + 12 | _, _ := f(), f() + 13 | _, _, _, _ := f(), f() + | ~~~ + 14 | + 15 | _, _ := 0, match 4 { +vlib/v/checker/tests/assign_multi_mismatch.vv:19:3: error: assignment mismatch: 1 variable(s) 2 value(s) + 17 | else { 1 } + 18 | } + 19 | _ := match 4 { + | ~~ + 20 | 1 { f() } + 21 | else { f() } +vlib/v/checker/tests/assign_multi_mismatch.vv:23:12: error: cannot use multi-value (int, int) in signle-value context + 21 | else { f() } + 22 | } + 23 | _, _ := 0, match 4 { + | ~~~~~~~~~ + 24 | 1 { f() } + 25 | else { f() } +vlib/v/checker/tests/assign_multi_mismatch.vv:29:3: error: assignment mismatch: 1 variable(s) 2 value(s) + 27 | + 28 | _, _ := 0, if true { 0 } else { 1 } + 29 | _ := if true { f() } else { f() } + | ~~ + 30 | _, _ := 0, if true { f() } else { f() } +vlib/v/checker/tests/assign_multi_mismatch.vv:30:12: error: cannot use multi-value (int, int) in signle-value context + 28 | _, _ := 0, if true { 0 } else { 1 } + 29 | _ := if true { f() } else { f() } + 30 | _, _ := 0, if true { f() } else { f() } + | ~~ diff --git a/vlib/v/checker/tests/assign_multi_mismatch.vv b/vlib/v/checker/tests/assign_multi_mismatch.vv new file mode 100644 index 0000000000..d25815c454 --- /dev/null +++ b/vlib/v/checker/tests/assign_multi_mismatch.vv @@ -0,0 +1,30 @@ +fn f() (int, int) { + return 0, 0 +} + +_ := 0, 0 +_ := f() +_, _ := f() +_, _ := 0, f() +_, _ := f(), 0 +_, _, _ := 0, f() +_, _, _ := f(), 0 +_, _ := f(), f() +_, _, _, _ := f(), f() + +_, _ := 0, match 4 { + 1 { 0 } + else { 1 } +} +_ := match 4 { + 1 { f() } + else { f() } +} +_, _ := 0, match 4 { + 1 { f() } + else { f() } +} + +_, _ := 0, if true { 0 } else { 1 } +_ := if true { f() } else { f() } +_, _ := 0, if true { f() } else { f() }