mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker, cgen: fix array of interfaces index() (#18232)
This commit is contained in:
parent
a33ffcedfb
commit
e2f18fc9cc
@ -4,6 +4,7 @@
|
|||||||
module checker
|
module checker
|
||||||
|
|
||||||
import v.ast
|
import v.ast
|
||||||
|
import v.token
|
||||||
|
|
||||||
// TODO: promote(), check_types(), symmetric_check() and check() overlap - should be rearranged
|
// TODO: promote(), check_types(), symmetric_check() and check() overlap - should be rearranged
|
||||||
fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
|
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
|
|||||||
} else {
|
} else {
|
||||||
got_typ_sym := c.table.sym(c.unwrap_generic(got))
|
got_typ_sym := c.table.sym(c.unwrap_generic(got))
|
||||||
expected_typ_sym := c.table.sym(c.unwrap_generic(expected_))
|
expected_typ_sym := c.table.sym(c.unwrap_generic(expected_))
|
||||||
|
if expected_typ_sym.kind == .interface_ && c.type_implements(got, expected_, token.Pos{}) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Check on Generics types, there are some case where we have the following case
|
// Check on Generics types, there are some case where we have the following case
|
||||||
// `&Type[int] == &Type[]`. This is a common case we are implementing a function
|
// `&Type[int] == &Type[]`. This is a common case we are implementing a function
|
||||||
|
@ -2519,6 +2519,9 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
|||||||
c.error('${err.msg()} in argument 1 to `.index()`', node.args[0].pos)
|
c.error('${err.msg()} in argument 1 to `.index()`', node.args[0].pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for i, arg in node.args {
|
||||||
|
node.args[i].typ = c.expr(arg.expr)
|
||||||
|
}
|
||||||
node.return_type = ast.int_type
|
node.return_type = ast.int_type
|
||||||
} else if method_name in ['first', 'last', 'pop'] {
|
} else if method_name in ['first', 'last', 'pop'] {
|
||||||
if node.args.len != 0 {
|
if node.args.len != 0 {
|
||||||
|
@ -986,7 +986,12 @@ fn (mut g Gen) gen_array_index(node ast.CallExpr) {
|
|||||||
if node.args[0].expr.is_auto_deref_var() {
|
if node.args[0].expr.is_auto_deref_var() {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
g.expr(node.args[0].expr)
|
elem_typ := g.table.sym(node.left_type).array_info().elem_type
|
||||||
|
if g.table.sym(elem_typ).kind in [.interface_, .sum_type] {
|
||||||
|
g.expr_with_cast(node.args[0].expr, node.args[0].typ, elem_typ)
|
||||||
|
} else {
|
||||||
|
g.expr(node.args[0].expr)
|
||||||
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
31
vlib/v/tests/array_of_interfaces_index_test.v
Normal file
31
vlib/v/tests/array_of_interfaces_index_test.v
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
struct Entity {
|
||||||
|
id u64
|
||||||
|
mut:
|
||||||
|
components []IComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IComponent {
|
||||||
|
hollow bool
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IsControlledByPlayerTag {
|
||||||
|
hollow bool
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_component[T](entity Entity) !&T {
|
||||||
|
for component in entity.components {
|
||||||
|
if component is T {
|
||||||
|
return component
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error('Entity does not have component')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_array_of_interfaces_index() {
|
||||||
|
entity := Entity{1, [IsControlledByPlayerTag{}]}
|
||||||
|
id := entity.components.index(*get_component[IsControlledByPlayerTag](entity)!)
|
||||||
|
|
||||||
|
println('id = ${id}')
|
||||||
|
assert id == 0
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user