Skip to content

Commit e2f18fc

Browse files
authored
checker, cgen: fix array of interfaces index() (#18232)
1 parent a33ffce commit e2f18fc

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

vlib/v/checker/check_types.v

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
module checker
55

66
import v.ast
7+
import v.token
78

89
// TODO: promote(), check_types(), symmetric_check() and check() overlap - should be rearranged
910
fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
@@ -274,6 +275,9 @@ fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, lan
274275
} else {
275276
got_typ_sym := c.table.sym(c.unwrap_generic(got))
276277
expected_typ_sym := c.table.sym(c.unwrap_generic(expected_))
278+
if expected_typ_sym.kind == .interface_ && c.type_implements(got, expected_, token.Pos{}) {
279+
return
280+
}
277281

278282
// Check on Generics types, there are some case where we have the following case
279283
// `&Type[int] == &Type[]`. This is a common case we are implementing a function

vlib/v/checker/fn.v

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,9 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
25192519
c.error('${err.msg()} in argument 1 to `.index()`', node.args[0].pos)
25202520
}
25212521
}
2522+
for i, arg in node.args {
2523+
node.args[i].typ = c.expr(arg.expr)
2524+
}
25222525
node.return_type = ast.int_type
25232526
} else if method_name in ['first', 'last', 'pop'] {
25242527
if node.args.len != 0 {

vlib/v/gen/c/array.v

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,12 @@ fn (mut g Gen) gen_array_index(node ast.CallExpr) {
986986
if node.args[0].expr.is_auto_deref_var() {
987987
g.write('*')
988988
}
989-
g.expr(node.args[0].expr)
989+
elem_typ := g.table.sym(node.left_type).array_info().elem_type
990+
if g.table.sym(elem_typ).kind in [.interface_, .sum_type] {
991+
g.expr_with_cast(node.args[0].expr, node.args[0].typ, elem_typ)
992+
} else {
993+
g.expr(node.args[0].expr)
994+
}
990995
g.write(')')
991996
}
992997

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
struct Entity {
2+
id u64
3+
mut:
4+
components []IComponent
5+
}
6+
7+
interface IComponent {
8+
hollow bool
9+
}
10+
11+
struct IsControlledByPlayerTag {
12+
hollow bool
13+
}
14+
15+
fn get_component[T](entity Entity) !&T {
16+
for component in entity.components {
17+
if component is T {
18+
return component
19+
}
20+
}
21+
22+
return error('Entity does not have component')
23+
}
24+
25+
fn test_array_of_interfaces_index() {
26+
entity := Entity{1, [IsControlledByPlayerTag{}]}
27+
id := entity.components.index(*get_component[IsControlledByPlayerTag](entity)!)
28+
29+
println('id = ${id}')
30+
assert id == 0
31+
}

0 commit comments

Comments
 (0)