Skip to content

Commit

Permalink
checker, cgen: fix arrays alias built-in methods call(fix #19896) (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
shove70 committed Nov 18, 2023
1 parent fb3d0cd commit aa502c2
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 12 deletions.
11 changes: 7 additions & 4 deletions vlib/v/checker/fn.v
Expand Up @@ -1710,7 +1710,8 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
if !c.check_types(arg_type, info.elem_type) && !c.check_types(left_type, arg_type) {
c.error('cannot ${method_name} `${arg_sym.name}` to `${left_sym.name}`', arg_expr.pos())
}
} else if final_left_sym.kind == .array && method_name in ['first', 'last', 'pop'] {
} else if final_left_sym.kind == .array
&& method_name in ['filter', 'map', 'sort', 'sorted', 'contains', 'any', 'all', 'first', 'last', 'pop'] {
return c.array_builtin_method_call(mut node, left_type, final_left_sym)
} else if c.pref.backend.is_js() && left_sym.name.starts_with('Promise[')
&& method_name == 'wait' {
Expand Down Expand Up @@ -2613,10 +2614,12 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
c.error('.slice() is a private method, use `x[start..end]` instead', node.pos)
return ast.void_type
}
unwrapped_left_type := c.unwrap_generic(left_type)
unaliased_left_type := c.table.unaliased_type(unwrapped_left_type)
array_info := if left_sym.info is ast.Array {
left_sym.info as ast.Array
} else {
c.table.sym(c.unwrap_generic(left_type)).info as ast.Array
c.table.sym(unaliased_left_type).info as ast.Array
}
elem_typ = array_info.elem_type
if method_name in ['filter', 'map', 'any', 'all'] {
Expand Down Expand Up @@ -2708,7 +2711,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
}
}
// map/filter are supposed to have 1 arg only
mut arg_type := left_type
mut arg_type := unaliased_left_type
for mut arg in node.args {
arg_type = c.check_expr_opt_call(arg.expr, c.expr(mut arg.expr))
}
Expand Down Expand Up @@ -2810,7 +2813,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
}
} else if method_name == 'delete' {
c.fail_if_immutable(mut node.left)
unwrapped_left_sym := c.table.sym(c.unwrap_generic(left_type))
unwrapped_left_sym := c.table.sym(unwrapped_left_type)
if method := c.table.find_method(unwrapped_left_sym, method_name) {
node.receiver_type = method.receiver_type
}
Expand Down
14 changes: 7 additions & 7 deletions vlib/v/gen/c/array.v
Expand Up @@ -468,8 +468,8 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
}

ret_typ := g.typ(node.return_type)
ret_sym := g.table.sym(node.return_type)
inp_sym := g.table.sym(node.receiver_type)
ret_sym := g.table.final_sym(node.return_type)
inp_sym := g.table.final_sym(node.receiver_type)
ret_info := ret_sym.info as ast.Array
mut ret_elem_type := g.typ(ret_info.elem_type)
inp_info := inp_sym.info as ast.Array
Expand Down Expand Up @@ -581,7 +581,7 @@ fn (mut g Gen) gen_array_sorted(node ast.CallExpr) {
g.past_tmp_var_done(past)
}
atype := g.typ(node.return_type)
sym := g.table.sym(node.return_type)
sym := g.table.final_sym(node.return_type)
info := sym.info as ast.Array
depth := g.get_array_depth(info.elem_type)

Expand All @@ -601,7 +601,7 @@ fn (mut g Gen) gen_array_sorted(node ast.CallExpr) {
// `users.sort(a.age < b.age)`
fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
// println('filter s="$s"')
rec_sym := g.table.sym(node.receiver_type)
rec_sym := g.table.final_sym(node.receiver_type)
if rec_sym.kind != .array {
println(node.name)
println(g.typ(node.receiver_type))
Expand Down Expand Up @@ -724,7 +724,7 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
g.past_tmp_var_done(past)
}

sym := g.table.sym(node.return_type)
sym := g.table.final_sym(node.return_type)
if sym.kind != .array {
verror('filter() requires an array')
}
Expand Down Expand Up @@ -1121,7 +1121,7 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) {
g.past_tmp_var_done(past)
}

sym := g.table.sym(node.left_type)
sym := g.table.final_sym(node.left_type)
info := sym.info as ast.Array
// styp := g.typ(node.return_type)
elem_type_str := g.typ(info.elem_type)
Expand Down Expand Up @@ -1200,7 +1200,7 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) {
g.past_tmp_var_done(past)
}

sym := g.table.sym(node.left_type)
sym := g.table.final_sym(node.left_type)
info := sym.info as ast.Array
// styp := g.typ(node.return_type)
elem_type_str := g.typ(info.elem_type)
Expand Down
3 changes: 2 additions & 1 deletion vlib/v/gen/c/fn.v
Expand Up @@ -1257,7 +1257,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
}
left_sym := g.table.sym(left_type)
final_left_sym := g.table.final_sym(left_type)
if left_sym.kind == .array {
if left_sym.kind == .array || (final_left_sym.kind == .array
&& node.name in ['filter', 'map', 'sort', 'sorted', 'contains', 'any', 'all']) {
if g.gen_array_method_call(node, left_type) {
return
}
Expand Down
25 changes: 25 additions & 0 deletions vlib/v/tests/alias_array_built_in_methods_test.v
@@ -0,0 +1,25 @@
type IntArray = []int

fn test_alias_array_method() {
mut arr := IntArray([0, 1, 2, 3])
res := arr.filter(it > 0)
assert res == IntArray([1, 2, 3])

assert arr.first() == 0
assert arr.last() == 3
arr.pop()
assert arr == IntArray([0, 1, 2])

arr2 := arr.map(it)
assert arr2 == [0, 1, 2]

assert arr.any(it > 0)
assert !arr.all(it > 0)

arr.sort(a > b)
assert arr == IntArray([2, 1, 0])
arr.sort()
assert arr == IntArray([0, 1, 2])

assert arr.contains(1)
}

0 comments on commit aa502c2

Please sign in to comment.