checker: deny multi-value in a singe-value context (#8328)

pull/8386/head
zakuro 2021-01-28 06:10:51 +09:00 committed by GitHub
parent f4baa3f39c
commit 8162396783
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 128 additions and 11 deletions

View File

@ -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 {

View File

@ -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() }
| ~~

View File

@ -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() }