checker: fix or-expr check on invalid method call (fix #22949) (#22950)

This commit is contained in:
Felipe Pena 2024-11-23 16:35:44 -03:00 committed by GitHub
parent 2f53e2d219
commit f8fb57d1aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 88 additions and 2 deletions

View File

@ -688,7 +688,7 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
mut continue_check := true
// Now call `method_call` or `fn_call` for specific checks.
typ := if node.is_method {
c.method_call(mut node)
c.method_call(mut node, mut continue_check)
} else {
c.fn_call(mut node, mut continue_check)
}
@ -2133,7 +2133,7 @@ fn (mut c Checker) check_type_and_visibility(name string, type_idx int, expected
return true
}
fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool) ast.Type {
// `(if true { 'foo.bar' } else { 'foo.bar.baz' }).all_after('foo.')`
mut left_expr := node.left
for mut left_expr is ast.ParExpr {
@ -2150,6 +2150,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
left_type := c.expr(mut node.left)
if left_type == ast.void_type {
// c.error('cannot call a method using an invalid expression', node.pos)
continue_check = false
return ast.void_type
}
if c.pref.skip_unused && !c.is_builtin_mod && c.mod != 'strings' {
@ -2190,6 +2191,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
// No need to print this error, since this means that the variable is unknown,
// and there already was an error before.
// c.error('`void` type has no methods', node.left.pos())
continue_check = false
return ast.void_type
}
if final_left_sym.kind == .array && array_builtin_methods_chk.matches(method_name)

View File

@ -0,0 +1,65 @@
vlib/v/checker/tests/method_call_on_undefined_err.vv:6:10: error: undefined ident: `input`
4 | fn foo() !string {
5 | // without next error does not occurs
6 | a, b := input.split_once('%') or { '', 'empty' }
| ~~~~~
7 | if b == '' {
8 | return error('')
vlib/v/checker/tests/method_call_on_undefined_err.vv:6:32: error: unexpected `or` block, the function `split_once` does not return an Option or a Result
4 | fn foo() !string {
5 | // without next error does not occurs
6 | a, b := input.split_once('%') or { '', 'empty' }
| ~~~~~~~~~~~~~~~~~~
7 | if b == '' {
8 | return error('')
vlib/v/checker/tests/method_call_on_undefined_err.vv:6:7: error: assignment mismatch: 2 variables but `split_once()` returns 0 values
4 | fn foo() !string {
5 | // without next error does not occurs
6 | a, b := input.split_once('%') or { '', 'empty' }
| ~~
7 | if b == '' {
8 | return error('')
vlib/v/checker/tests/method_call_on_undefined_err.vv:7:5: error: invalid variable `b`
5 | // without next error does not occurs
6 | a, b := input.split_once('%') or { '', 'empty' }
7 | if b == '' {
| ^
8 | return error('')
9 | }
vlib/v/checker/tests/method_call_on_undefined_err.vv:7:5: error: non-bool type `void` used as if condition
5 | // without next error does not occurs
6 | a, b := input.split_once('%') or { '', 'empty' }
7 | if b == '' {
| ~~~~~~~
8 | return error('')
9 | }
vlib/v/checker/tests/method_call_on_undefined_err.vv:10:9: error: invalid variable `a`
8 | return error('')
9 | }
10 | return a
| ^
11 | }
12 |
vlib/v/checker/tests/method_call_on_undefined_err.vv:10:2: error: `a` used as value
8 | return error('')
9 | }
10 | return a
| ~~~~~~~~
11 | }
12 |
vlib/v/checker/tests/method_call_on_undefined_err.vv:14:13: error: expected 0 arguments, but got 1
12 |
13 | fn main() {
14 | res := foo('fe80::1234%ne0') or {
| ~~~~~~~~~~~~~~~~
15 | eprintln(err)
16 | exit(1)
Details: have (string)
want ()
vlib/v/checker/tests/method_call_on_undefined_err.vv:14:31: error: unexpected `or` block, the function `foo` does not return an Option or a Result
12 |
13 | fn main() {
14 | res := foo('fe80::1234%ne0') or {
| ~~~~
15 | eprintln(err)
16 | exit(1)

View File

@ -0,0 +1,19 @@
module main
// note missing `input` argument in fn signature
fn foo() !string {
// without next error does not occurs
a, b := input.split_once('%') or { '', 'empty' }
if b == '' {
return error('')
}
return a
}
fn main() {
res := foo('fe80::1234%ne0') or {
eprintln(err)
exit(1)
}
println(res)
}