1
0
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:
yuyi 2023-05-22 21:31:22 +08:00 committed by GitHub
parent a33ffcedfb
commit e2f18fc9cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 1 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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('*')
} }
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.expr(node.args[0].expr)
}
g.write(')') g.write(')')
} }

View 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
}