diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4550a3bdba..d0c2715671 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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) { - index_type_sym := c.table.sym(index_type) 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_ || (index_type_sym.kind == .alias && (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 {} } + 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() - && 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) } + 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 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', diff --git a/vlib/v/gen/c/index.v b/vlib/v/gen/c/index.v index 63741bcf29..5ce2f61328 100644 --- a/vlib/v/gen/c/index.v +++ b/vlib/v/gen/c/index.v @@ -49,10 +49,17 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { } } } else { - g.expr(node.left) - g.write('[') - g.expr(node.index) - g.write(']') + 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 { + g.expr(node.left) + g.write('[') + g.expr(node.index) + g.write(']') + } } } } diff --git a/vlib/v/tests/match_sumtype_arr_test.v b/vlib/v/tests/match_sumtype_arr_test.v new file mode 100644 index 0000000000..90b79727c9 --- /dev/null +++ b/vlib/v/tests/match_sumtype_arr_test.v @@ -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 +}