mirror of
https://github.com/vlang/v.git
synced 2025-09-17 11:26:17 -04:00
checker: cleanup the checking of array method calls (#22338)
This commit is contained in:
parent
350846e11b
commit
4a01b2cca8
@ -30,7 +30,7 @@ const generic_fn_postprocess_iterations_cutoff_limit = 1000_000
|
|||||||
// Note that methods that do not return anything, or that return known types, are not listed here, since they are just ordinary non generic methods.
|
// Note that methods that do not return anything, or that return known types, are not listed here, since they are just ordinary non generic methods.
|
||||||
pub const array_builtin_methods = ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort',
|
pub const array_builtin_methods = ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice', 'sort',
|
||||||
'sort_with_compare', 'sorted', 'sorted_with_compare', 'contains', 'index', 'wait', 'any', 'all',
|
'sort_with_compare', 'sorted', 'sorted_with_compare', 'contains', 'index', 'wait', 'any', 'all',
|
||||||
'first', 'last', 'pop', 'delete']
|
'first', 'last', 'pop', 'delete', 'insert', 'prepend']
|
||||||
pub const array_builtin_methods_chk = token.new_keywords_matcher_from_array_trie(array_builtin_methods)
|
pub const array_builtin_methods_chk = token.new_keywords_matcher_from_array_trie(array_builtin_methods)
|
||||||
// TODO: remove `byte` from this list when it is no longer supported
|
// TODO: remove `byte` from this list when it is no longer supported
|
||||||
pub const reserved_type_names = ['byte', 'bool', 'char', 'i8', 'i16', 'int', 'i64', 'u8', 'u16',
|
pub const reserved_type_names = ['byte', 'bool', 'char', 'i8', 'i16', 'int', 'i64', 'u8', 'u16',
|
||||||
|
@ -2018,44 +2018,9 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
|||||||
// c.error('`void` type has no methods', node.left.pos())
|
// c.error('`void` type has no methods', node.left.pos())
|
||||||
return ast.void_type
|
return ast.void_type
|
||||||
}
|
}
|
||||||
if final_left_sym.kind == .array {
|
if final_left_sym.kind == .array && array_builtin_methods_chk.matches(method_name)
|
||||||
if array_builtin_methods_chk.matches(method_name) && (left_sym.kind == .array
|
&& !(left_sym.kind == .alias && left_sym.has_method(method_name)) {
|
||||||
|| (left_sym.kind == .alias && !left_sym.has_method(method_name))) {
|
return c.array_builtin_method_call(mut node, left_type)
|
||||||
return c.array_builtin_method_call(mut node, left_type)
|
|
||||||
} else if method_name in ['insert', 'prepend'] {
|
|
||||||
if method_name == 'insert' {
|
|
||||||
if node.args.len != 2 {
|
|
||||||
c.error('`array.insert()` should have 2 arguments, e.g. `insert(1, val)`',
|
|
||||||
node.pos)
|
|
||||||
return ast.void_type
|
|
||||||
} else {
|
|
||||||
arg_type := c.expr(mut node.args[0].expr)
|
|
||||||
if arg_type !in [ast.int_type, ast.int_literal_type] {
|
|
||||||
c.error('the first argument of `array.insert()` should be integer',
|
|
||||||
node.args[0].expr.pos())
|
|
||||||
return ast.void_type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if node.args.len != 1 {
|
|
||||||
c.error('`array.prepend()` should have 1 argument, e.g. `prepend(val)`',
|
|
||||||
node.pos)
|
|
||||||
return ast.void_type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info := final_left_sym.info as ast.Array
|
|
||||||
mut arg_expr := if method_name == 'insert' {
|
|
||||||
node.args[1].expr
|
|
||||||
} else {
|
|
||||||
node.args[0].expr
|
|
||||||
}
|
|
||||||
arg_type := c.expr(mut arg_expr)
|
|
||||||
arg_sym := c.table.sym(arg_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 == .map
|
} else if final_left_sym.kind == .map
|
||||||
&& method_name in ['clone', 'keys', 'values', 'move', 'delete'] && !(left_sym.kind == .alias
|
&& method_name in ['clone', 'keys', 'values', 'move', 'delete'] && !(left_sym.kind == .alias
|
||||||
&& left_sym.has_method(method_name)) {
|
&& left_sym.has_method(method_name)) {
|
||||||
@ -3166,6 +3131,52 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
// position of `it` doesn't matter
|
// position of `it` doesn't matter
|
||||||
scope_register_it(mut node.scope, node.pos, elem_typ)
|
scope_register_it(mut node.scope, node.pos, elem_typ)
|
||||||
}
|
}
|
||||||
|
} else if method_name in ['insert', 'prepend'] {
|
||||||
|
if method_name == 'insert' {
|
||||||
|
if node.args.len != 2 {
|
||||||
|
c.error('`array.insert()` should have 2 arguments, e.g. `insert(1, val)`',
|
||||||
|
node.pos)
|
||||||
|
return ast.void_type
|
||||||
|
} else {
|
||||||
|
arg_type := c.expr(mut node.args[0].expr)
|
||||||
|
if arg_type !in [ast.int_type, ast.int_literal_type] {
|
||||||
|
c.error('the first argument of `array.insert()` should be integer',
|
||||||
|
node.args[0].expr.pos())
|
||||||
|
return ast.void_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if node.args.len != 1 {
|
||||||
|
c.error('`array.prepend()` should have 1 argument, e.g. `prepend(val)`',
|
||||||
|
node.pos)
|
||||||
|
return ast.void_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info := left_sym.info as ast.Array
|
||||||
|
mut arg_expr := if method_name == 'insert' {
|
||||||
|
node.args[1].expr
|
||||||
|
} else {
|
||||||
|
node.args[0].expr
|
||||||
|
}
|
||||||
|
arg_type := c.expr(mut arg_expr)
|
||||||
|
arg_sym := c.table.sym(arg_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())
|
||||||
|
}
|
||||||
|
for i, mut arg in node.args {
|
||||||
|
node.args[i].typ = c.expr(mut arg.expr)
|
||||||
|
}
|
||||||
|
node.receiver_type = ast.array_type.ref()
|
||||||
|
node.return_type = ast.void_type
|
||||||
|
if method := c.table.find_method(left_sym, method_name) {
|
||||||
|
for i, arg in node.args {
|
||||||
|
c.check_expected_call_arg(arg.typ, method.params[i + 1].typ, node.language,
|
||||||
|
arg) or {
|
||||||
|
c.error('${err.msg()} in argument ${i + 1} to `${left_sym.name}.${method_name}`',
|
||||||
|
node.args[i].pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if method_name in ['sort_with_compare', 'sorted_with_compare'] {
|
} else if method_name in ['sort_with_compare', 'sorted_with_compare'] {
|
||||||
if node.args.len != 1 {
|
if node.args.len != 1 {
|
||||||
c.error('`.${method_name}()` expected 1 argument, but got ${node.args.len}',
|
c.error('`.${method_name}()` expected 1 argument, but got ${node.args.len}',
|
||||||
@ -3209,7 +3220,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
node.receiver_type = node.left_type
|
node.receiver_type = node.left_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if method_name == 'sort' || method_name == 'sorted' {
|
} else if method_name in ['sort', 'sorted'] {
|
||||||
if method_name == 'sort' {
|
if method_name == 'sort' {
|
||||||
if node.left is ast.CallExpr {
|
if node.left is ast.CallExpr {
|
||||||
c.error('the `sort()` method can be called only on mutable receivers, but `${node.left}` is a call expression',
|
c.error('the `sort()` method can be called only on mutable receivers, but `${node.left}` is a call expression',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user