1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker, cgen: fix contains() with array of interfaces (#18241)

This commit is contained in:
yuyi 2023-05-23 20:46:14 +08:00 committed by GitHub
parent 37618c9465
commit 6698fe4f60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 12 deletions

View File

@ -2509,6 +2509,9 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
c.error('${err.msg()} in argument 1 to `.contains()`', node.args[0].pos) c.error('${err.msg()} in argument 1 to `.contains()`', node.args[0].pos)
} }
} }
for i, arg in node.args {
node.args[i].typ = c.expr(arg.expr)
}
node.return_type = ast.bool_type node.return_type = ast.bool_type
} else if method_name == 'index' { } else if method_name == 'index' {
if node.args.len != 1 { if node.args.len != 1 {

View File

@ -885,22 +885,32 @@ fn (mut g Gen) gen_array_contains_methods() {
} }
// `nums.contains(2)` // `nums.contains(2)`
fn (mut g Gen) gen_array_contains(typ ast.Type, left ast.Expr, right ast.Expr) { fn (mut g Gen) gen_array_contains(left_type ast.Type, left ast.Expr, right_type ast.Type, right ast.Expr) {
fn_name := g.get_array_contains_method(typ) fn_name := g.get_array_contains_method(left_type)
g.write('${fn_name}(') g.write('${fn_name}(')
g.write(strings.repeat(`*`, typ.nr_muls())) g.write(strings.repeat(`*`, left_type.nr_muls()))
if typ.share() == .shared_t { if left_type.share() == .shared_t {
g.go_back(1) g.go_back(1)
} }
g.expr(left) g.expr(left)
if typ.share() == .shared_t { if left_type.share() == .shared_t {
g.write('->val') g.write('->val')
} }
g.write(', ') g.write(', ')
if right.is_auto_deref_var() { if right.is_auto_deref_var() {
g.write('*') g.write('*')
} }
g.expr(right) left_sym := g.table.final_sym(left_type)
elem_typ := if left_sym.kind == .array {
left_sym.array_info().elem_type
} else {
left_sym.array_fixed_info().elem_type
}
if g.table.sym(elem_typ).kind in [.interface_, .sum_type] {
g.expr_with_cast(right, right_type, elem_typ)
} else {
g.expr(right)
}
g.write(')') g.write(')')
} }

View File

@ -891,7 +891,7 @@ fn (mut g Gen) gen_array_method_call(node ast.CallExpr, left_type ast.Type) bool
return true return true
} }
'contains' { 'contains' {
g.gen_array_contains(left_type, node.left, node.args[0].expr) g.gen_array_contains(left_type, node.left, node.args[0].typ, node.args[0].expr)
return true return true
} }
'index' { 'index' {

View File

@ -488,12 +488,21 @@ fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
expr: node.left expr: node.left
expr_type: ast.mktyp(node.left_type) expr_type: ast.mktyp(node.left_type)
} }
g.gen_array_contains(node.right_type, node.right, new_node_left) g.gen_array_contains(node.right_type, node.right, elem_type, new_node_left)
return return
} }
} else if elem_type_.sym.kind == .interface_ {
new_node_left := ast.CastExpr{
arg: ast.empty_expr
typ: elem_type
expr: node.left
expr_type: ast.mktyp(node.left_type)
}
g.gen_array_contains(node.right_type, node.right, elem_type, new_node_left)
return
} }
} }
g.gen_array_contains(node.right_type, node.right, node.left) g.gen_array_contains(node.right_type, node.right, node.left_type, node.left)
} else if right.unaliased_sym.kind == .map { } else if right.unaliased_sym.kind == .map {
g.write('_IN_MAP(') g.write('_IN_MAP(')
if !left.typ.is_ptr() { if !left.typ.is_ptr() {
@ -558,12 +567,12 @@ fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
expr: node.left expr: node.left
expr_type: ast.mktyp(node.left_type) expr_type: ast.mktyp(node.left_type)
} }
g.gen_array_contains(node.right_type, node.right, new_node_left) g.gen_array_contains(node.right_type, node.right, elem_type, new_node_left)
return return
} }
} }
} }
g.gen_array_contains(node.right_type, node.right, node.left) g.gen_array_contains(node.right_type, node.right, node.left_type, node.left)
} else if right.unaliased_sym.kind == .string { } else if right.unaliased_sym.kind == .string {
g.write('string_contains(') g.write('string_contains(')
g.expr(node.right) g.expr(node.right)

View File

@ -24,8 +24,12 @@ fn get_component[T](entity Entity) !&T {
fn test_array_of_interfaces_index() { fn test_array_of_interfaces_index() {
entity := Entity{1, [IsControlledByPlayerTag{}]} entity := Entity{1, [IsControlledByPlayerTag{}]}
id := entity.components.index(*get_component[IsControlledByPlayerTag](entity)!)
id := entity.components.index(*get_component[IsControlledByPlayerTag](entity)!)
println('id = ${id}') println('id = ${id}')
assert id == 0 assert id == 0
ret := entity.components.contains(*get_component[IsControlledByPlayerTag](entity)!)
println(ret)
assert ret
} }