authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-05-28 22:04:52+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-05-29 13:19:03+03:00
log0e8307789a3de41759e68c7c04c130889e277991
tree68d53b0b5669c002f26937d8f38244aed18c8ec2
parentc7b778992ec539e237d8afa7c105dcbad7ee280c

AstGen: add tuple aware elem_type_index


5 files changed, 141 insertions(+), 29 deletions(-)

src/AstGen.zig+50-18
...@@ -1273,8 +1273,14 @@ fn arrayInitExpr(...@@ -1273,8 +1273,14 @@ fn arrayInitExpr(
12731273
1274 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.1274 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
12751275
1276 const array_ty: Zir.Inst.Ref = inst: {1276 const types: struct {
1277 if (array_init.ast.type_expr == 0) break :inst .none;1277 array: Zir.Inst.Ref,
1278 elem: Zir.Inst.Ref,
1279 } = inst: {
1280 if (array_init.ast.type_expr == 0) break :inst .{
1281 .array = .none,
1282 .elem = .none,
1283 };
12781284
1279 infer: {1285 infer: {
1280 const array_type: Ast.full.ArrayType = switch (node_tags[array_init.ast.type_expr]) {1286 const array_type: Ast.full.ArrayType = switch (node_tags[array_init.ast.type_expr]) {
...@@ -1289,10 +1295,14 @@ fn arrayInitExpr(...@@ -1289,10 +1295,14 @@ fn arrayInitExpr(
1289 const len_inst = try gz.addInt(array_init.ast.elements.len);1295 const len_inst = try gz.addInt(array_init.ast.elements.len);
1290 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);1296 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1291 if (array_type.ast.sentinel == 0) {1297 if (array_type.ast.sentinel == 0) {
1292 break :inst try gz.addBin(.array_type, len_inst, elem_type);1298 const array_type_inst = try gz.addBin(.array_type, len_inst, elem_type);
1299 break :inst .{
1300 .array = array_type_inst,
1301 .elem = elem_type,
1302 };
1293 } else {1303 } else {
1294 const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);1304 const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
1295 break :inst try gz.addPlNode(1305 const array_type_inst = try gz.addPlNode(
1296 .array_type_sentinel,1306 .array_type_sentinel,
1297 array_init.ast.type_expr,1307 array_init.ast.type_expr,
1298 Zir.Inst.ArrayTypeSentinel{1308 Zir.Inst.ArrayTypeSentinel{
...@@ -1301,12 +1311,19 @@ fn arrayInitExpr(...@@ -1301,12 +1311,19 @@ fn arrayInitExpr(
1301 .sentinel = sentinel,1311 .sentinel = sentinel,
1302 },1312 },
1303 );1313 );
1314 break :inst .{
1315 .array = array_type_inst,
1316 .elem = elem_type,
1317 };
1304 }1318 }
1305 }1319 }
1306 }1320 }
1307 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);1321 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
1308 _ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);1322 _ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
1309 break :inst array_type_inst;1323 break :inst .{
1324 .array = array_type_inst,
1325 .elem = .none,
1326 };
1310 };1327 };
13111328
1312 switch (rl) {1329 switch (rl) {
...@@ -1318,40 +1335,40 @@ fn arrayInitExpr(...@@ -1318,40 +1335,40 @@ fn arrayInitExpr(
1318 return Zir.Inst.Ref.void_value;1335 return Zir.Inst.Ref.void_value;
1319 },1336 },
1320 .ref => {1337 .ref => {
1321 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init_ref else .array_init_anon_ref;1338 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init_ref else .array_init_anon_ref;
1322 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);1339 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
1323 },1340 },
1324 .none => {1341 .none => {
1325 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init else .array_init_anon;1342 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
1326 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);1343 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
1327 },1344 },
1328 .ty, .coerced_ty => {1345 .ty, .coerced_ty => {
1329 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init else .array_init_anon;1346 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
1330 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, tag);1347 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
1331 return rvalue(gz, rl, result, node);1348 return rvalue(gz, rl, result, node);
1332 },1349 },
1333 .ptr => |ptr_inst| {1350 .ptr => |ptr_inst| {
1334 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, array_ty);1351 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
1335 },1352 },
1336 .inferred_ptr => |ptr_inst| {1353 .inferred_ptr => |ptr_inst| {
1337 if (array_ty == .none) {1354 if (types.array == .none) {
1338 // We treat this case differently so that we don't get a crash when1355 // We treat this case differently so that we don't get a crash when
1339 // analyzing array_base_ptr against an alloc_inferred_mut.1356 // analyzing array_base_ptr against an alloc_inferred_mut.
1340 // See corresponding logic in structInitExpr.1357 // See corresponding logic in structInitExpr.
1341 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);1358 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1342 return rvalue(gz, rl, result, node);1359 return rvalue(gz, rl, result, node);
1343 } else {1360 } else {
1344 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, array_ty);1361 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
1345 }1362 }
1346 },1363 },
1347 .block_ptr => |block_gz| {1364 .block_ptr => |block_gz| {
1348 // This condition is here for the same reason as the above condition in `inferred_ptr`.1365 // This condition is here for the same reason as the above condition in `inferred_ptr`.
1349 // See corresponding logic in structInitExpr.1366 // See corresponding logic in structInitExpr.
1350 if (array_ty == .none and astgen.isInferred(block_gz.rl_ptr)) {1367 if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) {
1351 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);1368 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1352 return rvalue(gz, rl, result, node);1369 return rvalue(gz, rl, result, node);
1353 }1370 }
1354 return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, array_ty);1371 return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array);
1355 },1372 },
1356 }1373 }
1357}1374}
...@@ -1384,6 +1401,7 @@ fn arrayInitExprInner(...@@ -1384,6 +1401,7 @@ fn arrayInitExprInner(
1384 node: Ast.Node.Index,1401 node: Ast.Node.Index,
1385 elements: []const Ast.Node.Index,1402 elements: []const Ast.Node.Index,
1386 array_ty_inst: Zir.Inst.Ref,1403 array_ty_inst: Zir.Inst.Ref,
1404 elem_ty: Zir.Inst.Ref,
1387 tag: Zir.Inst.Tag,1405 tag: Zir.Inst.Tag,
1388) InnerError!Zir.Inst.Ref {1406) InnerError!Zir.Inst.Ref {
1389 const astgen = gz.astgen;1407 const astgen = gz.astgen;
...@@ -1398,8 +1416,21 @@ fn arrayInitExprInner(...@@ -1398,8 +1416,21 @@ fn arrayInitExprInner(
1398 extra_index += 1;1416 extra_index += 1;
1399 }1417 }
14001418
1401 for (elements) |elem_init| {1419 for (elements) |elem_init, i| {
1402 const elem_ref = try expr(gz, scope, .none, elem_init);1420 const rl = if (elem_ty != .none)
1421 ResultLoc{ .coerced_ty = elem_ty }
1422 else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) rl: {
1423 const ty_expr = try gz.add(.{
1424 .tag = .elem_type_index,
1425 .data = .{ .bin = .{
1426 .lhs = array_ty_inst,
1427 .rhs = @intToEnum(Zir.Inst.Ref, i),
1428 } },
1429 });
1430 break :rl ResultLoc{ .coerced_ty = ty_expr };
1431 } else ResultLoc{ .none = {} };
1432
1433 const elem_ref = try expr(gz, scope, rl, elem_init);
1403 astgen.extra.items[extra_index] = @enumToInt(elem_ref);1434 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
1404 extra_index += 1;1435 extra_index += 1;
1405 }1436 }
...@@ -2192,6 +2223,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner...@@ -2192,6 +2223,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
2192 .array_mul,2223 .array_mul,
2193 .array_type,2224 .array_type,
2194 .array_type_sentinel,2225 .array_type_sentinel,
2226 .elem_type_index,
2195 .vector_type,2227 .vector_type,
2196 .indexable_ptr_len,2228 .indexable_ptr_len,
2197 .anyframe_type,2229 .anyframe_type,
src/Sema.zig+49-11
...@@ -726,6 +726,7 @@ fn analyzeBodyInner(...@@ -726,6 +726,7 @@ fn analyzeBodyInner(
726 .elem_ptr_imm => try sema.zirElemPtrImm(block, inst),726 .elem_ptr_imm => try sema.zirElemPtrImm(block, inst),
727 .elem_val => try sema.zirElemVal(block, inst),727 .elem_val => try sema.zirElemVal(block, inst),
728 .elem_val_node => try sema.zirElemValNode(block, inst),728 .elem_val_node => try sema.zirElemValNode(block, inst),
729 .elem_type_index => try sema.zirElemTypeIndex(block, inst),
729 .enum_literal => try sema.zirEnumLiteral(block, inst),730 .enum_literal => try sema.zirEnumLiteral(block, inst),
730 .enum_to_int => try sema.zirEnumToInt(block, inst),731 .enum_to_int => try sema.zirEnumToInt(block, inst),
731 .int_to_enum => try sema.zirIntToEnum(block, inst),732 .int_to_enum => try sema.zirIntToEnum(block, inst),
...@@ -3021,7 +3022,10 @@ fn zirArrayBasePtr(...@@ -3021,7 +3022,10 @@ fn zirArrayBasePtr(
3021 const elem_ty = sema.typeOf(base_ptr).childType();3022 const elem_ty = sema.typeOf(base_ptr).childType();
3022 switch (elem_ty.zigTypeTag()) {3023 switch (elem_ty.zigTypeTag()) {
3023 .Array, .Vector => return base_ptr,3024 .Array, .Vector => return base_ptr,
3024 .Struct => if (elem_ty.isTuple()) return base_ptr,3025 .Struct => if (elem_ty.isTuple()) {
3026 // TODO validate element count
3027 return base_ptr;
3028 },
3025 else => {},3029 else => {},
3026 }3030 }
3027 return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType());3031 return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType());
...@@ -3062,7 +3066,10 @@ fn validateArrayInitTy(...@@ -3062,7 +3066,10 @@ fn validateArrayInitTy(
30623066
3063 switch (ty.zigTypeTag()) {3067 switch (ty.zigTypeTag()) {
3064 .Array, .Vector => return,3068 .Array, .Vector => return,
3065 .Struct => if (ty.isTuple()) return,3069 .Struct => if (ty.isTuple()) {
3070 // TODO validate element count
3071 return;
3072 },
3066 else => {},3073 else => {},
3067 }3074 }
3068 return sema.failWithArrayInitNotSupported(block, src, ty);3075 return sema.failWithArrayInitNotSupported(block, src, ty);
...@@ -5805,12 +5812,17 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -5805,12 +5812,17 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
5805 return sema.addType(opt_type);5812 return sema.addType(opt_type);
5806}5813}
58075814
5808fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5815fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
5809 const inst_data = sema.code.instructions.items(.data)[inst].un_node;5816 const bin = sema.code.instructions.items(.data)[inst].bin;
5810 const src = inst_data.src();5817 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);
5811 const array_type = try sema.resolveType(block, src, inst_data.operand);5818 assert(indexable_ty.isIndexable()); // validated by a previous instruction
5812 const elem_type = array_type.elemType();5819 if (indexable_ty.zigTypeTag() == .Struct) {
5813 return sema.addType(elem_type);5820 const elem_type = indexable_ty.tupleFields().types[@enumToInt(bin.rhs)];
5821 return sema.addType(elem_type);
5822 } else {
5823 const elem_type = indexable_ty.elemType2();
5824 return sema.addType(elem_type);
5825 }
5814}5826}
58155827
5816fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5828fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -13277,6 +13289,8 @@ fn zirStructInit(...@@ -13277,6 +13289,8 @@ fn zirStructInit(
13277 try sema.requireRuntimeBlock(block, src);13289 try sema.requireRuntimeBlock(block, src);
13278 try sema.queueFullTypeResolution(resolved_ty);13290 try sema.queueFullTypeResolution(resolved_ty);
13279 return block.addUnionInit(resolved_ty, field_index, init_inst);13291 return block.addUnionInit(resolved_ty, field_index, init_inst);
13292 } else if (resolved_ty.isAnonStruct()) {
13293 return sema.fail(block, src, "TODO anon struct init validation", .{});
13280 }13294 }
13281 unreachable;13295 unreachable;
13282}13296}
...@@ -13447,15 +13461,18 @@ fn zirArrayInit(...@@ -13447,15 +13461,18 @@ fn zirArrayInit(
1344713461
13448 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null));13462 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null));
13449 defer gpa.free(resolved_args);13463 defer gpa.free(resolved_args);
13450 const elem_ty = array_ty.elemType2();
13451 for (args[1..]) |arg, i| {13464 for (args[1..]) |arg, i| {
13452 const resolved_arg = try sema.resolveInst(arg);13465 const resolved_arg = try sema.resolveInst(arg);
13453 const arg_src = src; // TODO better source location13466 const arg_src = src; // TODO better source location
13467 const elem_ty = if (array_ty.zigTypeTag() == .Struct)
13468 array_ty.tupleFields().types[i]
13469 else
13470 array_ty.elemType2();
13454 resolved_args[i] = try sema.coerce(block, elem_ty, resolved_arg, arg_src);13471 resolved_args[i] = try sema.coerce(block, elem_ty, resolved_arg, arg_src);
13455 }13472 }
1345613473
13457 if (sentinel_val) |some| {13474 if (sentinel_val) |some| {
13458 resolved_args[resolved_args.len - 1] = try sema.addConstant(elem_ty, some);13475 resolved_args[resolved_args.len - 1] = try sema.addConstant(array_ty.elemType2(), some);
13459 }13476 }
1346013477
13461 const opt_runtime_src: ?LazySrcLoc = for (resolved_args) |arg| {13478 const opt_runtime_src: ?LazySrcLoc = for (resolved_args) |arg| {
...@@ -13487,10 +13504,27 @@ fn zirArrayInit(...@@ -13487,10 +13504,27 @@ fn zirArrayInit(
13487 });13504 });
13488 const alloc = try block.addTy(.alloc, alloc_ty);13505 const alloc = try block.addTy(.alloc, alloc_ty);
1348913506
13507 if (array_ty.isTuple()) {
13508 const types = array_ty.tupleFields().types;
13509 for (resolved_args) |arg, i| {
13510 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
13511 .mutable = true,
13512 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
13513 .pointee_type = types[i],
13514 });
13515 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
13516
13517 const index = try sema.addIntUnsigned(Type.usize, i);
13518 const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref);
13519 _ = try block.addBinOp(.store, elem_ptr, arg);
13520 }
13521 return alloc;
13522 }
13523
13490 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{13524 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
13491 .mutable = true,13525 .mutable = true,
13492 .@"addrspace" = target_util.defaultAddressSpace(target, .local),13526 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
13493 .pointee_type = elem_ty,13527 .pointee_type = array_ty.elemType2(),
13494 });13528 });
13495 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);13529 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1349613530
...@@ -13632,6 +13666,10 @@ fn fieldType(...@@ -13632,6 +13666,10 @@ fn fieldType(
13632 while (true) {13666 while (true) {
13633 switch (cur_ty.zigTypeTag()) {13667 switch (cur_ty.zigTypeTag()) {
13634 .Struct => {13668 .Struct => {
13669 if (cur_ty.isAnonStruct()) {
13670 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
13671 return sema.addType(cur_ty.tupleFields().types[field_index]);
13672 }
13635 const struct_obj = cur_ty.castTag(.@"struct").?.data;13673 const struct_obj = cur_ty.castTag(.@"struct").?.data;
13636 const field = struct_obj.fields.get(field_name) orelse13674 const field = struct_obj.fields.get(field_name) orelse
13637 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);13675 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
src/Zir.zig+6
...@@ -221,6 +221,9 @@ pub const Inst = struct {...@@ -221,6 +221,9 @@ pub const Inst = struct {
221 /// Uses the `pl_node` union field with `Bin` payload.221 /// Uses the `pl_node` union field with `Bin` payload.
222 /// lhs is length, rhs is element type.222 /// lhs is length, rhs is element type.
223 vector_type,223 vector_type,
224 /// Given an indexable type, returns the type of the element at given index.
225 /// Uses the `bin` union field. lhs is the indexable type, rhs is the index.
226 elem_type_index,
224 /// Given a pointer to an indexable object, returns the len property. This is227 /// Given a pointer to an indexable object, returns the len property. This is
225 /// used by for loops. This instruction also emits a for-loop specific compile228 /// used by for loops. This instruction also emits a for-loop specific compile
226 /// error if the indexable object is not indexable.229 /// error if the indexable object is not indexable.
...@@ -1008,6 +1011,7 @@ pub const Inst = struct {...@@ -1008,6 +1011,7 @@ pub const Inst = struct {
1008 .array_type,1011 .array_type,
1009 .array_type_sentinel,1012 .array_type_sentinel,
1010 .vector_type,1013 .vector_type,
1014 .elem_type_index,
1011 .indexable_ptr_len,1015 .indexable_ptr_len,
1012 .anyframe_type,1016 .anyframe_type,
1013 .as,1017 .as,
...@@ -1300,6 +1304,7 @@ pub const Inst = struct {...@@ -1300,6 +1304,7 @@ pub const Inst = struct {
1300 .array_type,1304 .array_type,
1301 .array_type_sentinel,1305 .array_type_sentinel,
1302 .vector_type,1306 .vector_type,
1307 .elem_type_index,
1303 .indexable_ptr_len,1308 .indexable_ptr_len,
1304 .anyframe_type,1309 .anyframe_type,
1305 .as,1310 .as,
...@@ -1537,6 +1542,7 @@ pub const Inst = struct {...@@ -1537,6 +1542,7 @@ pub const Inst = struct {
1537 .array_type = .bin,1542 .array_type = .bin,
1538 .array_type_sentinel = .pl_node,1543 .array_type_sentinel = .pl_node,
1539 .vector_type = .pl_node,1544 .vector_type = .pl_node,
1545 .elem_type_index = .bin,
1540 .indexable_ptr_len = .un_node,1546 .indexable_ptr_len = .un_node,
1541 .anyframe_type = .un_node,1547 .anyframe_type = .un_node,
1542 .as = .bin,1548 .as = .bin,
src/print_zir.zig+8
...@@ -152,6 +152,8 @@ const Writer = struct {...@@ -152,6 +152,8 @@ const Writer = struct {
152 .store_to_inferred_ptr,152 .store_to_inferred_ptr,
153 => try self.writeBin(stream, inst),153 => try self.writeBin(stream, inst),
154154
155 .elem_type_index => try self.writeElemTypeIndex(stream, inst),
156
155 .alloc,157 .alloc,
156 .alloc_mut,158 .alloc_mut,
157 .alloc_comptime_mut,159 .alloc_comptime_mut,
...@@ -538,6 +540,12 @@ const Writer = struct {...@@ -538,6 +540,12 @@ const Writer = struct {
538 try stream.writeByte(')');540 try stream.writeByte(')');
539 }541 }
540542
543 fn writeElemTypeIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
544 const inst_data = self.code.instructions.items(.data)[inst].bin;
545 try self.writeInstRef(stream, inst_data.lhs);
546 try stream.print(", {d})", .{inst_data.rhs});
547 }
548
541 fn writeUnNode(549 fn writeUnNode(
542 self: *Writer,550 self: *Writer,
543 stream: anytype,551 stream: anytype,
test/behavior/basic.zig+28
...@@ -949,3 +949,31 @@ test "vector initialized with array init syntax has proper type" {...@@ -949,3 +949,31 @@ test "vector initialized with array init syntax has proper type" {
949 try std.testing.expectEqual(@Vector(4, i32){ -1, -2, -3, -4 }, actual);949 try std.testing.expectEqual(@Vector(4, i32){ -1, -2, -3, -4 }, actual);
950 }950 }
951}951}
952
953test "weird array and tuple initializations" {
954 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
955 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
956 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
957
958 const E = enum { a, b };
959 const S = struct { e: E };
960 var a = false;
961 const b = S{ .e = .a };
962
963 _ = &[_]S{
964 if (a) .{ .e = .a } else .{ .e = .b },
965 };
966
967 if (true) return error.SkipZigTest;
968
969 const S2 = @TypeOf(.{ false, b });
970 _ = &S2{
971 true,
972 if (a) .{ .e = .a } else .{ .e = .b },
973 };
974 const S3 = @TypeOf(.{ .a = false, .b = b });
975 _ = &S3{
976 .a = true,
977 .b = if (a) .{ .e = .a } else .{ .e = .b },
978 };
979}