checker: disallow invalid expr for filter, count, any, all (fix #24508) (#24540)

This commit is contained in:
Swastik Baranwal 2025-05-21 16:30:20 +05:30 committed by GitHub
parent c27bc602bd
commit be49e2bf6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 55 additions and 7 deletions

View File

@ -2983,8 +2983,8 @@ fn (mut c Checker) check_predicate_param(is_map bool, elem_typ ast.Type, node as
// Finish early so that it doesn't fail later
return
}
arg_expr := node.args[0].expr
match arg_expr {
mut arg_expr := node.args[0].expr
match mut arg_expr {
ast.AnonFn {
if arg_expr.decl.return_type.has_flag(.option) {
c.error('option needs to be unwrapped before using it in map/filter',
@ -3024,7 +3024,7 @@ fn (mut c Checker) check_predicate_param(is_map bool, elem_typ ast.Type, node as
arg_expr.pos)
}
} else if arg_expr.kind == .variable {
if arg_expr.obj is ast.Var {
if mut arg_expr.obj is ast.Var {
expr := arg_expr.obj.expr
if expr is ast.AnonFn {
// copied from above
@ -3084,13 +3084,18 @@ fn (mut c Checker) check_predicate_param(is_map bool, elem_typ ast.Type, node as
}
}
ast.LambdaExpr {
if arg_expr.expr is ast.CallExpr && is_map
if mut arg_expr.expr is ast.CallExpr && is_map
&& arg_expr.expr.return_type in [ast.void_type, 0] {
c.error('type mismatch, `${arg_expr.expr.name}` does not return anything',
arg_expr.expr.pos)
}
}
else {}
else {
if !is_map && c.expr(mut arg_expr) != ast.bool_type {
c.error('invalid expression, expected infix expr, lambda or function',
arg_expr.pos())
}
}
}
}

View File

@ -1,3 +1,10 @@
vlib/v/checker/tests/array_count_err.vv:3:10: error: invalid expression, expected infix expr, lambda or function
1 | fn main() {
2 | a := []int{}
3 | a.count(1)
| ^
4 | a.count(1, 2)
5 | a.count('')
vlib/v/checker/tests/array_count_err.vv:4:4: error: expected 1 argument, but got 2
2 | a := []int{}
3 | a.count(1)

View File

@ -0,0 +1,24 @@
vlib/v/checker/tests/array_method_invalid_expr.vv:2:16: error: invalid expression, expected infix expr, lambda or function
1 | runes := [`a`, `b`, `c`, `a`]
2 | dump(runes.all(`a`))
| ~~~
3 | dump(runes.any(`a`))
4 | dump(runes.count(`a`))
vlib/v/checker/tests/array_method_invalid_expr.vv:3:16: error: invalid expression, expected infix expr, lambda or function
1 | runes := [`a`, `b`, `c`, `a`]
2 | dump(runes.all(`a`))
3 | dump(runes.any(`a`))
| ~~~
4 | dump(runes.count(`a`))
5 | dump(runes.filter(`a`))
vlib/v/checker/tests/array_method_invalid_expr.vv:4:18: error: invalid expression, expected infix expr, lambda or function
2 | dump(runes.all(`a`))
3 | dump(runes.any(`a`))
4 | dump(runes.count(`a`))
| ~~~
5 | dump(runes.filter(`a`))
vlib/v/checker/tests/array_method_invalid_expr.vv:5:19: error: invalid expression, expected infix expr, lambda or function
3 | dump(runes.any(`a`))
4 | dump(runes.count(`a`))
5 | dump(runes.filter(`a`))
| ~~~

View File

@ -0,0 +1,5 @@
runes := [`a`, `b`, `c`, `a`]
dump(runes.all(`a`))
dump(runes.any(`a`))
dump(runes.count(`a`))
dump(runes.filter(`a`))

View File

@ -33,6 +33,13 @@ vlib/v/checker/tests/fixed_array_builtin_method_args_err.vv:8:11: error: `.any`
| ~~~~~
9 | _ := arr.any(22)
10 | _ := arr.all()
vlib/v/checker/tests/fixed_array_builtin_method_args_err.vv:9:15: error: invalid expression, expected infix expr, lambda or function
7 | _ := arr.contains('hello')
8 | _ := arr.any()
9 | _ := arr.any(22)
| ~~
10 | _ := arr.all()
11 | _ := arr.all('hello')
vlib/v/checker/tests/fixed_array_builtin_method_args_err.vv:10:11: error: `.all` expected 1 argument, but got 0
8 | _ := arr.any()
9 | _ := arr.any(22)

View File

@ -987,7 +987,7 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
dyld_fallback_paths := os.getenv('DYLD_FALLBACK_LIBRARY_PATH')
so_dir := os.dir(so_path)
if !dyld_fallback_paths.contains(so_dir) {
env := [dyld_fallback_paths, so_dir].filter(it.len).join(':')
env := [dyld_fallback_paths, so_dir].filter(it.len != 0).join(':')
os.setenv('DYLD_FALLBACK_LIBRARY_PATH', env, true)
}
}

View File

@ -254,7 +254,7 @@ pub fn get_modules() []Module {
// get_functions returns the functions built with V source
pub fn get_funcs() []Function {
mut out := g_reflection.funcs.clone()
out << arrays.flatten[Function](get_types().map(it.sym.methods).filter(it.len))
out << arrays.flatten[Function](get_types().map(it.sym.methods).filter(it.len != 0))
return out
}