mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen, checker: fix indexexpr with sumtype of array types (#18515)
This commit is contained in:
parent
4c9c515f8b
commit
2abd2e2c2a
@ -4035,8 +4035,8 @@ fn (mut c Checker) type_error_for_operator(op_label string, types_label string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) check_index(typ_sym &ast.TypeSymbol, index ast.Expr, index_type ast.Type, pos token.Pos, range_index bool, is_gated bool) {
|
fn (mut c Checker) check_index(typ_sym &ast.TypeSymbol, index ast.Expr, index_type ast.Type, pos token.Pos, range_index bool, is_gated bool) {
|
||||||
index_type_sym := c.table.sym(index_type)
|
|
||||||
if typ_sym.kind in [.array, .array_fixed, .string] {
|
if typ_sym.kind in [.array, .array_fixed, .string] {
|
||||||
|
index_type_sym := c.table.sym(index_type)
|
||||||
if !(index_type.is_int() || index_type_sym.kind == .enum_
|
if !(index_type.is_int() || index_type_sym.kind == .enum_
|
||||||
|| (index_type_sym.kind == .alias
|
|| (index_type_sym.kind == .alias
|
||||||
&& (index_type_sym.info as ast.Alias).parent_type.is_int())
|
&& (index_type_sym.info as ast.Alias).parent_type.is_int())
|
||||||
@ -4102,10 +4102,17 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
|
|||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
is_aggregate_arr := typ_sym.kind == .aggregate
|
||||||
|
&& (typ_sym.info as ast.Aggregate).types.filter(c.table.type_kind(it) !in [.array, .array_fixed, .string, .map]).len == 0
|
||||||
if typ_sym.kind !in [.array, .array_fixed, .string, .map] && !typ.is_ptr()
|
if typ_sym.kind !in [.array, .array_fixed, .string, .map] && !typ.is_ptr()
|
||||||
&& typ !in [ast.byteptr_type, ast.charptr_type] && !typ.has_flag(.variadic) {
|
&& typ !in [ast.byteptr_type, ast.charptr_type] && !typ.has_flag(.variadic)
|
||||||
|
&& !is_aggregate_arr {
|
||||||
c.error('type `${typ_sym.name}` does not support indexing', node.pos)
|
c.error('type `${typ_sym.name}` does not support indexing', node.pos)
|
||||||
}
|
}
|
||||||
|
if is_aggregate_arr {
|
||||||
|
// treating indexexpr of sumtype of array types
|
||||||
|
typ = (typ_sym.info as ast.Aggregate).types[0]
|
||||||
|
}
|
||||||
if typ.has_flag(.option) {
|
if typ.has_flag(.option) {
|
||||||
if node.left is ast.Ident && (node.left as ast.Ident).or_expr.kind == .absent {
|
if node.left is ast.Ident && (node.left as ast.Ident).or_expr.kind == .absent {
|
||||||
c.error('type `?${typ_sym.name}` is an Option, it must be unwrapped first; use `var?[]` to do it',
|
c.error('type `?${typ_sym.name}` is an Option, it must be unwrapped first; use `var?[]` to do it',
|
||||||
|
@ -48,6 +48,12 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
|||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if sym.kind == .aggregate
|
||||||
|
&& (sym.info as ast.Aggregate).types.filter(g.table.type_kind(it) !in [.array, .array_fixed, .string, .map]).len == 0 {
|
||||||
|
// treating sumtype of array types
|
||||||
|
unwrapped_got_type := (sym.info as ast.Aggregate).types[g.aggregate_type_idx]
|
||||||
|
g.index_expr(ast.IndexExpr{ ...node, left_type: unwrapped_got_type })
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write('[')
|
g.write('[')
|
||||||
@ -56,6 +62,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) {
|
fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) {
|
||||||
sym := g.table.final_sym(node.left_type)
|
sym := g.table.final_sym(node.left_type)
|
||||||
|
43
vlib/v/tests/match_sumtype_arr_test.v
Normal file
43
vlib/v/tests/match_sumtype_arr_test.v
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
type MySumType = []MyStructA | []MyStructB
|
||||||
|
type MySumTypePtr = []&MyStructA | []&MyStructB
|
||||||
|
|
||||||
|
struct ParentStruct {
|
||||||
|
parent_field string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyStructA {
|
||||||
|
ParentStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyStructB {
|
||||||
|
ParentStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check(mut t MySumType) {
|
||||||
|
match mut t {
|
||||||
|
[]MyStructA, []MyStructB {
|
||||||
|
println(t[0].parent_field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check2(mut t MySumTypePtr) {
|
||||||
|
match mut t {
|
||||||
|
[]&MyStructA, []&MyStructB {
|
||||||
|
println(t[0].parent_field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
s := MyStructA{
|
||||||
|
parent_field: 'common'
|
||||||
|
}
|
||||||
|
|
||||||
|
mut t := MySumType([s])
|
||||||
|
mut t2 := MySumTypePtr([&s])
|
||||||
|
|
||||||
|
check(mut t)
|
||||||
|
check2(mut t2)
|
||||||
|
assert true
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user