authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-09-18 14:49:18+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-09-23 22:01:08+01:00
log09a57583a4ccce30603ffc8d0e3d7359dc3cb978
treeaab67cf7749a799ae9b236cd4f26bc9f115b82c5
parent01906a3ad8b792627e55551686c25d02fef64e98
signaturelock-open Commit is signed but in an unrecognized format.

compiler: preserve result type information through address-of operator

This commit introduces the new `ref_coerced_ty` result type into AstGen. This represents a expression which we want to treat as an lvalue, and the pointer will be coerced to a given type. This change gives known result types to many expressions, in particular struct and array initializations. This allows certain casts to work which previously required explicitly specifying types via `@as`. It also eliminates our dependence on anonymous struct types for expressions of the form `&.{ ... }` - this paves the way for #16865, and also results in less Sema magic happening for such initializations, also leading to potentially better runtime code. As part of these changes, this commit also implements #17194 by disallowing RLS on explicitly-typed struct and array initializations. Apologies for linking these changes - it seemed rather pointless to try and separate them, since they both make big changes to struct and array initializations in AstGen. The rationale for this change can be found in the proposal - in essence, performing RLS whilst maintaining the semantics of the intermediary type is a very difficult problem to solve. This allowed the problematic `coerce_result_ptr` ZIR instruction to be completely eliminated, which in turn also simplified the logic for inferred allocations in Sema - thanks to this, we almost break even on line count! In doing this, the ZIR instructions surrounding these initializations have been restructured - some have been added and removed, and others renamed for clarity (and their semantics changed slightly). In order to optimize ZIR tag count, the `struct_init_anon_ref` and `array_init_anon_ref` instructions have been removed in favour of using `ref` on a standard anonymous value initialization, since these instructions are now virtually never used. Lastly, it's worth noting that this commit introduces a slightly strange source of generic poison types: in the expression `@as(*anyopaque, &x)`, the sub-expression `x` has a generic poison result type, despite no generic code being involved. This turns out to be a logical choice, because we don't know the result type for `x`, and the generic poison type represents precisely this case, providing the semantics we need. Resolves: #16512 Resolves: #17194

35 files changed, 1251 insertions(+), 1025 deletions(-)

lib/std/debug.zig+6-1
...@@ -514,7 +514,12 @@ pub const StackIterator = struct {...@@ -514,7 +514,12 @@ pub const StackIterator = struct {
514514
515 return StackIterator{515 return StackIterator{
516 .first_address = first_address,516 .first_address = first_address,
517 .fp = fp orelse @frameAddress(),517 // TODO: this is a workaround for #16876
518 //.fp = fp orelse @frameAddress(),
519 .fp = fp orelse blk: {
520 const fa = @frameAddress();
521 break :blk fa;
522 },
518 };523 };
519 }524 }
520525
src/AstGen.zig+318-305
...@@ -265,14 +265,17 @@ const ResultInfo = struct {...@@ -265,14 +265,17 @@ const ResultInfo = struct {
265 discard,265 discard,
266 /// The expression has an inferred type, and it will be evaluated as an rvalue.266 /// The expression has an inferred type, and it will be evaluated as an rvalue.
267 none,267 none,
268 /// The expression must generate a pointer rather than a value. For example, the left hand side
269 /// of an assignment uses this kind of result location.
270 ref,
271 /// The expression will be coerced into this type, but it will be evaluated as an rvalue.268 /// The expression will be coerced into this type, but it will be evaluated as an rvalue.
272 ty: Zir.Inst.Ref,269 ty: Zir.Inst.Ref,
273 /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion,270 /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion,
274 /// so no `as` instruction needs to be emitted.271 /// so no `as` instruction needs to be emitted.
275 coerced_ty: Zir.Inst.Ref,272 coerced_ty: Zir.Inst.Ref,
273 /// The expression must generate a pointer rather than a value. For example, the left hand side
274 /// of an assignment uses this kind of result location.
275 ref,
276 /// The expression must generate a pointer rather than a value, and the pointer will be coerced
277 /// by other code to this type, which is guaranteed by earlier instructions to be a pointer type.
278 ref_coerced_ty: Zir.Inst.Ref,
276 /// The expression must store its result into this typed pointer. The result instruction279 /// The expression must store its result into this typed pointer. The result instruction
277 /// from the expression must be ignored.280 /// from the expression must be ignored.
278 ptr: PtrResultLoc,281 ptr: PtrResultLoc,
...@@ -303,26 +306,30 @@ const ResultInfo = struct {...@@ -303,26 +306,30 @@ const ResultInfo = struct {
303 /// Find the result type for a cast builtin given the result location.306 /// Find the result type for a cast builtin given the result location.
304 /// If the location does not have a known result type, emits an error on307 /// If the location does not have a known result type, emits an error on
305 /// the given node.308 /// the given node.
306 fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref {309 fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref {
307 const astgen = gz.astgen;310 return switch (rl) {
308 switch (rl) {311 .discard, .none, .ref, .inferred_ptr, .destructure => null,
309 .discard, .none, .ref, .inferred_ptr => {},312 .ty, .coerced_ty => |ty_ref| ty_ref,
310 .ty, .coerced_ty => |ty_ref| return ty_ref,313 .ref_coerced_ty => |ptr_ty| try gz.addUnNode(.elem_type, ptr_ty, node),
311 .ptr => |ptr| {314 .ptr => |ptr| {
312 const ptr_ty = try gz.addUnNode(.typeof, ptr.inst, node);315 const ptr_ty = try gz.addUnNode(.typeof, ptr.inst, node);
313 return gz.addUnNode(.elem_type, ptr_ty, node);316 return try gz.addUnNode(.elem_type, ptr_ty, node);
314 },
315 .destructure => |destructure| {
316 return astgen.failNodeNotes(node, "{s} must have a known result type", .{builtin_name}, &.{
317 try astgen.errNoteNode(destructure.src_node, "destructure expressions do not provide a single result type", .{}),
318 try astgen.errNoteNode(node, "use @as to provide explicit result type", .{}),
319 });
320 },317 },
321 }318 };
319 }
322320
323 return astgen.failNodeNotes(node, "{s} must have a known result type", .{builtin_name}, &.{321 fn resultTypeForCast(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref {
324 try astgen.errNoteNode(node, "use @as to provide explicit result type", .{}),322 const astgen = gz.astgen;
325 });323 if (try rl.resultType(gz, node)) |ty| return ty;
324 switch (rl) {
325 .destructure => |destructure| return astgen.failNodeNotes(node, "{s} must have a known result type", .{builtin_name}, &.{
326 try astgen.errNoteNode(destructure.src_node, "destructure expressions do not provide a single result type", .{}),
327 try astgen.errNoteNode(node, "use @as to provide explicit result type", .{}),
328 }),
329 else => return astgen.failNodeNotes(node, "{s} must have a known result type", .{builtin_name}, &.{
330 try astgen.errNoteNode(node, "use @as to provide explicit result type", .{}),
331 }),
332 }
326 }333 }
327 };334 };
328335
...@@ -933,7 +940,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -933,7 +940,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
933 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);940 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
934 _ = try gz.addUnNode(.validate_deref, lhs, node);941 _ = try gz.addUnNode(.validate_deref, lhs, node);
935 switch (ri.rl) {942 switch (ri.rl) {
936 .ref => return lhs,943 .ref, .ref_coerced_ty => return lhs,
937 else => {944 else => {
938 const result = try gz.addUnNode(.load, lhs, node);945 const result = try gz.addUnNode(.load, lhs, node);
939 return rvalue(gz, ri, result, node);946 return rvalue(gz, ri, result, node);
...@@ -941,7 +948,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -941,7 +948,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
941 }948 }
942 },949 },
943 .address_of => {950 .address_of => {
944 const result = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);951 const operand_rl: ResultInfo.Loc = if (try ri.rl.resultType(gz, node)) |res_ty_inst| rl: {
952 _ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node));
953 break :rl .{ .ref_coerced_ty = res_ty_inst };
954 } else .ref;
955 const result = try expr(gz, scope, .{ .rl = operand_rl }, node_datas[node].lhs);
945 return rvalue(gz, ri, result, node);956 return rvalue(gz, ri, result, node);
946 },957 },
947 .optional_type => {958 .optional_type => {
...@@ -950,7 +961,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -950,7 +961,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
950 return rvalue(gz, ri, result, node);961 return rvalue(gz, ri, result, node);
951 },962 },
952 .unwrap_optional => switch (ri.rl) {963 .unwrap_optional => switch (ri.rl) {
953 .ref => {964 .ref, .ref_coerced_ty => {
954 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);965 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
955966
956 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);967 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
...@@ -1001,7 +1012,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1001,7 +1012,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1001 else1012 else
1002 null;1013 null;
1003 switch (ri.rl) {1014 switch (ri.rl) {
1004 .ref => return orelseCatchExpr(1015 .ref, .ref_coerced_ty => return orelseCatchExpr(
1005 gz,1016 gz,
1006 scope,1017 scope,
1007 ri,1018 ri,
...@@ -1028,7 +1039,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1028,7 +1039,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1028 }1039 }
1029 },1040 },
1030 .@"orelse" => switch (ri.rl) {1041 .@"orelse" => switch (ri.rl) {
1031 .ref => return orelseCatchExpr(1042 .ref, .ref_coerced_ty => return orelseCatchExpr(
1032 gz,1043 gz,
1033 scope,1044 scope,
1034 ri,1045 ri,
...@@ -1432,73 +1443,75 @@ fn arrayInitExpr(...@@ -1432,73 +1443,75 @@ fn arrayInitExpr(
1432 break :inst .{ array_type_inst, .none };1443 break :inst .{ array_type_inst, .none };
1433 };1444 };
14341445
1446 if (array_ty != .none) {
1447 // Typed inits do not use RLS for language simplicity.
1448 switch (ri.rl) {
1449 .discard => {
1450 if (elem_ty != .none) {
1451 const elem_ri: ResultInfo = .{ .rl = .{ .ty = elem_ty } };
1452 for (array_init.ast.elements) |elem_init| {
1453 _ = try expr(gz, scope, elem_ri, elem_init);
1454 }
1455 } else {
1456 for (array_init.ast.elements, 0..) |elem_init, i| {
1457 const this_elem_ty = try gz.add(.{
1458 .tag = .array_init_elem_type,
1459 .data = .{ .bin = .{
1460 .lhs = array_ty,
1461 .rhs = @enumFromInt(i),
1462 } },
1463 });
1464 _ = try expr(gz, scope, .{ .rl = .{ .ty = this_elem_ty } }, elem_init);
1465 }
1466 }
1467 return .void_value;
1468 },
1469 .ref => return arrayInitExprTyped(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, true),
1470 else => {
1471 const array_inst = try arrayInitExprTyped(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, false);
1472 return rvalue(gz, ri, array_inst, node);
1473 },
1474 }
1475 }
1476
1435 switch (ri.rl) {1477 switch (ri.rl) {
1478 .none => return arrayInitExprAnon(gz, scope, node, array_init.ast.elements),
1436 .discard => {1479 .discard => {
1437 if (elem_ty != .none) {1480 for (array_init.ast.elements) |elem_init| {
1438 const elem_ri: ResultInfo = .{ .rl = .{ .ty = elem_ty } };1481 _ = try expr(gz, scope, .{ .rl = .discard }, elem_init);
1439 for (array_init.ast.elements) |elem_init| {
1440 _ = try expr(gz, scope, elem_ri, elem_init);
1441 }
1442 } else if (array_ty != .none) {
1443 for (array_init.ast.elements, 0..) |elem_init, i| {
1444 const this_elem_ty = try gz.add(.{
1445 .tag = .elem_type_index,
1446 .data = .{ .bin = .{
1447 .lhs = array_ty,
1448 .rhs = @enumFromInt(i),
1449 } },
1450 });
1451 _ = try expr(gz, scope, .{ .rl = .{ .ty = this_elem_ty } }, elem_init);
1452 }
1453 } else {
1454 for (array_init.ast.elements) |elem_init| {
1455 _ = try expr(gz, scope, .{ .rl = .discard }, elem_init);
1456 }
1457 }1482 }
1458 return Zir.Inst.Ref.void_value;1483 return Zir.Inst.Ref.void_value;
1459 },1484 },
1460 .ref => {1485 .ref => {
1461 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init_ref else .array_init_anon_ref;1486 const result = try arrayInitExprAnon(gz, scope, node, array_init.ast.elements);
1462 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, tag);1487 return gz.addUnTok(.ref, result, tree.firstToken(node));
1463 },
1464 .none => {
1465 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init else .array_init_anon;
1466 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, tag);
1467 },
1468 .ty, .coerced_ty => |ty_inst| {
1469 const arr_ty = if (array_ty != .none) array_ty else blk: {
1470 const arr_ty = try gz.addUnNode(.opt_eu_base_ty, ty_inst, node);
1471 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{
1472 .ty = arr_ty,
1473 .init_count = @intCast(array_init.ast.elements.len),
1474 });
1475 break :blk arr_ty;
1476 };
1477 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, arr_ty, elem_ty, .array_init);
1478 return rvalue(gz, ri, result, node);
1479 },1488 },
1480 .ptr => |ptr_res| {1489 .ref_coerced_ty => |ptr_ty_inst| {
1481 return arrayInitExprRlPtr(gz, scope, node, ptr_res.inst, array_init.ast.elements, array_ty);1490 const dest_arr_ty_inst = try gz.addPlNode(.validate_array_init_ref_ty, node, Zir.Inst.ArrayInitRefTy{
1482 },1491 .ptr_ty = ptr_ty_inst,
1483 .inferred_ptr => |ptr_inst| {1492 .elem_count = @intCast(array_init.ast.elements.len),
1484 if (array_ty == .none) {1493 });
1485 // We treat this case differently so that we don't get a crash when1494 return arrayInitExprTyped(gz, scope, node, array_init.ast.elements, dest_arr_ty_inst, .none, true);
1486 // analyzing array_base_ptr against an alloc_inferred_mut.1495 },
1487 // See corresponding logic in structInitExpr.1496 .ty, .coerced_ty => |result_ty_inst| {
1488 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);1497 _ = try gz.addPlNode(.validate_array_init_result_ty, node, Zir.Inst.ArrayInit{
1489 return rvalue(gz, ri, result, node);1498 .ty = result_ty_inst,
1490 } else {1499 .init_count = @intCast(array_init.ast.elements.len),
1491 return arrayInitExprRlPtr(gz, scope, node, ptr_inst, array_init.ast.elements, array_ty);1500 });
1492 }1501 return arrayInitExprTyped(gz, scope, node, array_init.ast.elements, result_ty_inst, .none, false);
1502 },
1503 .ptr => |ptr| {
1504 try arrayInitExprPtr(gz, scope, node, array_init.ast.elements, ptr.inst);
1505 return .void_value;
1506 },
1507 .inferred_ptr => {
1508 // We can't get elem pointers of an untyped inferred alloc, so must perform a
1509 // standard anonymous initialization followed by an rvalue store.
1510 // See corresponding logic in structInitExpr.
1511 const result = try arrayInitExprAnon(gz, scope, node, array_init.ast.elements);
1512 return rvalue(gz, ri, result, node);
1493 },1513 },
1494 .destructure => |destructure| {1514 .destructure => |destructure| {
1495 if (array_ty != .none) {
1496 // We have a specific type, so there may be things like default
1497 // field values messing with us. Do this as a standard typed
1498 // init followed by an rvalue destructure.
1499 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, .array_init);
1500 return rvalue(gz, ri, result, node);
1501 }
1502 // Untyped init - destructure directly into result pointers1515 // Untyped init - destructure directly into result pointers
1503 if (array_init.ast.elements.len != destructure.components.len) {1516 if (array_init.ast.elements.len != destructure.components.len) {
1504 return astgen.failNodeNotes(node, "expected {} elements for destructure, found {}", .{1517 return astgen.failNodeNotes(node, "expected {} elements for destructure, found {}", .{
...@@ -1521,12 +1534,12 @@ fn arrayInitExpr(...@@ -1521,12 +1534,12 @@ fn arrayInitExpr(
1521 }1534 }
1522}1535}
15231536
1524fn arrayInitExprRlNone(1537/// An array initialization expression using an `array_init_anon` instruction.
1538fn arrayInitExprAnon(
1525 gz: *GenZir,1539 gz: *GenZir,
1526 scope: *Scope,1540 scope: *Scope,
1527 node: Ast.Node.Index,1541 node: Ast.Node.Index,
1528 elements: []const Ast.Node.Index,1542 elements: []const Ast.Node.Index,
1529 tag: Zir.Inst.Tag,
1530) InnerError!Zir.Inst.Ref {1543) InnerError!Zir.Inst.Ref {
1531 const astgen = gz.astgen;1544 const astgen = gz.astgen;
15321545
...@@ -1540,95 +1553,84 @@ fn arrayInitExprRlNone(...@@ -1540,95 +1553,84 @@ fn arrayInitExprRlNone(
1540 astgen.extra.items[extra_index] = @intFromEnum(elem_ref);1553 astgen.extra.items[extra_index] = @intFromEnum(elem_ref);
1541 extra_index += 1;1554 extra_index += 1;
1542 }1555 }
1543 return try gz.addPlNodePayloadIndex(tag, node, payload_index);1556 return try gz.addPlNodePayloadIndex(.array_init_anon, node, payload_index);
1544}1557}
15451558
1546fn arrayInitExprInner(1559/// An array initialization expression using an `array_init` or `array_init_ref` instruction.
1560fn arrayInitExprTyped(
1547 gz: *GenZir,1561 gz: *GenZir,
1548 scope: *Scope,1562 scope: *Scope,
1549 node: Ast.Node.Index,1563 node: Ast.Node.Index,
1550 elements: []const Ast.Node.Index,1564 elements: []const Ast.Node.Index,
1551 array_ty_inst: Zir.Inst.Ref,1565 ty_inst: Zir.Inst.Ref,
1552 elem_ty: Zir.Inst.Ref,1566 maybe_elem_ty_inst: Zir.Inst.Ref,
1553 tag: Zir.Inst.Tag,1567 is_ref: bool,
1554) InnerError!Zir.Inst.Ref {1568) InnerError!Zir.Inst.Ref {
1555 const astgen = gz.astgen;1569 const astgen = gz.astgen;
15561570
1557 const len = elements.len + @intFromBool(array_ty_inst != .none);1571 const len = elements.len + 1; // +1 for type
1558 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{1572 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
1559 .operands_len = @intCast(len),1573 .operands_len = @intCast(len),
1560 });1574 });
1561 var extra_index = try reserveExtra(astgen, len);1575 var extra_index = try reserveExtra(astgen, len);
1562 if (array_ty_inst != .none) {1576 astgen.extra.items[extra_index] = @intFromEnum(ty_inst);
1563 astgen.extra.items[extra_index] = @intFromEnum(array_ty_inst);1577 extra_index += 1;
1564 extra_index += 1;
1565 }
15661578
1567 for (elements, 0..) |elem_init, i| {1579 if (maybe_elem_ty_inst != .none) {
1568 const ri = if (elem_ty != .none)1580 const elem_ri: ResultInfo = .{ .rl = .{ .coerced_ty = maybe_elem_ty_inst } };
1569 ResultInfo{ .rl = .{ .coerced_ty = elem_ty } }1581 for (elements) |elem_init| {
1570 else if (array_ty_inst != .none) ri: {1582 const elem_inst = try expr(gz, scope, elem_ri, elem_init);
1571 const ty_expr = try gz.add(.{1583 astgen.extra.items[extra_index] = @intFromEnum(elem_inst);
1572 .tag = .elem_type_index,1584 extra_index += 1;
1585 }
1586 } else {
1587 for (elements, 0..) |elem_init, i| {
1588 const ri: ResultInfo = .{ .rl = .{ .coerced_ty = try gz.add(.{
1589 .tag = .array_init_elem_type,
1573 .data = .{ .bin = .{1590 .data = .{ .bin = .{
1574 .lhs = array_ty_inst,1591 .lhs = ty_inst,
1575 .rhs = @enumFromInt(i),1592 .rhs = @enumFromInt(i),
1576 } },1593 } },
1577 });1594 }) } };
1578 break :ri ResultInfo{ .rl = .{ .coerced_ty = ty_expr } };
1579 } else ResultInfo{ .rl = .{ .none = {} } };
15801595
1581 const elem_ref = try expr(gz, scope, ri, elem_init);1596 const elem_inst = try expr(gz, scope, ri, elem_init);
1582 astgen.extra.items[extra_index] = @intFromEnum(elem_ref);1597 astgen.extra.items[extra_index] = @intFromEnum(elem_inst);
1583 extra_index += 1;1598 extra_index += 1;
1599 }
1584 }1600 }
15851601
1602 const tag: Zir.Inst.Tag = if (is_ref) .array_init_ref else .array_init;
1586 return try gz.addPlNodePayloadIndex(tag, node, payload_index);1603 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
1587}1604}
15881605
1589fn arrayInitExprRlPtr(1606/// An array initialization expression using element pointers.
1607fn arrayInitExprPtr(
1590 gz: *GenZir,1608 gz: *GenZir,
1591 scope: *Scope,1609 scope: *Scope,
1592 node: Ast.Node.Index,1610 node: Ast.Node.Index,
1593 result_ptr: Zir.Inst.Ref,
1594 elements: []const Ast.Node.Index,1611 elements: []const Ast.Node.Index,
1595 array_ty: Zir.Inst.Ref,1612 ptr_inst: Zir.Inst.Ref,
1596) InnerError!Zir.Inst.Ref {1613) InnerError!void {
1597 if (array_ty == .none) {
1598 const base_ptr = try gz.addUnNode(.array_base_ptr, result_ptr, node);
1599 return arrayInitExprRlPtrInner(gz, scope, node, base_ptr, elements);
1600 }
1601
1602 const casted_ptr = try gz.addPlNode(.coerce_result_ptr, node, Zir.Inst.Bin{ .lhs = array_ty, .rhs = result_ptr });
1603 return arrayInitExprRlPtrInner(gz, scope, node, casted_ptr, elements);
1604}
1605
1606fn arrayInitExprRlPtrInner(
1607 gz: *GenZir,
1608 scope: *Scope,
1609 node: Ast.Node.Index,
1610 result_ptr: Zir.Inst.Ref,
1611 elements: []const Ast.Node.Index,
1612) InnerError!Zir.Inst.Ref {
1613 const astgen = gz.astgen;1614 const astgen = gz.astgen;
16141615
1616 const array_ptr_inst = try gz.addUnNode(.opt_eu_base_ptr_init, ptr_inst, node);
1617
1615 const payload_index = try addExtra(astgen, Zir.Inst.Block{1618 const payload_index = try addExtra(astgen, Zir.Inst.Block{
1616 .body_len = @intCast(elements.len),1619 .body_len = @intCast(elements.len),
1617 });1620 });
1618 var extra_index = try reserveExtra(astgen, elements.len);1621 var extra_index = try reserveExtra(astgen, elements.len);
16191622
1620 for (elements, 0..) |elem_init, i| {1623 for (elements, 0..) |elem_init, i| {
1621 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{1624 const elem_ptr_inst = try gz.addPlNode(.array_init_elem_ptr, elem_init, Zir.Inst.ElemPtrImm{
1622 .ptr = result_ptr,1625 .ptr = array_ptr_inst,
1623 .index = @intCast(i),1626 .index = @intCast(i),
1624 });1627 });
1625 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;1628 astgen.extra.items[extra_index] = refToIndex(elem_ptr_inst).?;
1626 extra_index += 1;1629 extra_index += 1;
1627 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = elem_ptr } } }, elem_init);1630 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = elem_ptr_inst } } }, elem_init);
1628 }1631 }
16291632
1630 _ = try gz.addPlNodePayloadIndex(.validate_array_init, node, payload_index);1633 _ = try gz.addPlNodePayloadIndex(.validate_ptr_array_init, node, payload_index);
1631 return .void_value;
1632}1634}
16331635
1634fn structInitExpr(1636fn structInitExpr(
...@@ -1643,7 +1645,26 @@ fn structInitExpr(...@@ -1643,7 +1645,26 @@ fn structInitExpr(
16431645
1644 if (struct_init.ast.type_expr == 0) {1646 if (struct_init.ast.type_expr == 0) {
1645 if (struct_init.ast.fields.len == 0) {1647 if (struct_init.ast.fields.len == 0) {
1646 return rvalue(gz, ri, .empty_struct, node);1648 // Anonymous init with no fields.
1649 switch (ri.rl) {
1650 .discard => return .void_value,
1651 .ref_coerced_ty => |ptr_ty_inst| return gz.addUnNode(.struct_init_empty_ref_result, ptr_ty_inst, node),
1652 .ty, .coerced_ty => |ty_inst| return gz.addUnNode(.struct_init_empty_result, ty_inst, node),
1653 .ptr => {
1654 // TODO: should we modify this to use RLS for the field stores here?
1655 const ty_inst = (try ri.rl.resultType(gz, node)).?;
1656 const val = try gz.addUnNode(.struct_init_empty_result, ty_inst, node);
1657 return rvalue(gz, ri, val, node);
1658 },
1659 .none, .ref, .inferred_ptr => {
1660 return rvalue(gz, ri, .empty_struct, node);
1661 },
1662 .destructure => |destructure| {
1663 return astgen.failNodeNotes(node, "empty initializer cannot be destructured", .{}, &.{
1664 try astgen.errNoteNode(destructure.src_node, "result destructured here", .{}),
1665 });
1666 },
1667 }
1647 }1668 }
1648 } else array: {1669 } else array: {
1649 const node_tags = tree.nodes.items(.tag);1670 const node_tags = tree.nodes.items(.tag);
...@@ -1694,86 +1715,67 @@ fn structInitExpr(...@@ -1694,86 +1715,67 @@ fn structInitExpr(
1694 }1715 }
1695 }1716 }
16961717
1718 if (struct_init.ast.type_expr != 0) {
1719 // Typed inits do not use RLS for language simplicity.
1720 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1721 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
1722 switch (ri.rl) {
1723 .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true),
1724 else => {
1725 const struct_inst = try structInitExprTyped(gz, scope, node, struct_init, ty_inst, false);
1726 return rvalue(gz, ri, struct_inst, node);
1727 },
1728 }
1729 }
1730
1697 switch (ri.rl) {1731 switch (ri.rl) {
1732 .none => return structInitExprAnon(gz, scope, node, struct_init),
1698 .discard => {1733 .discard => {
1699 if (struct_init.ast.type_expr != 0) {1734 // Even if discarding we must perform an anonymous init to check for duplicate field names.
1700 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1735 // TODO: should duplicate field names be caught in AstGen?
1701 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);1736 _ = try structInitExprAnon(gz, scope, node, struct_init);
1702 _ = try structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init);1737 return .void_value;
1703 } else {
1704 _ = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);
1705 }
1706 return Zir.Inst.Ref.void_value;
1707 },1738 },
1708 .ref => {1739 .ref => {
1709 if (struct_init.ast.type_expr != 0) {1740 const result = try structInitExprAnon(gz, scope, node, struct_init);
1710 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1741 return gz.addUnTok(.ref, result, tree.firstToken(node));
1711 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
1712 return structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init_ref);
1713 } else {
1714 return structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon_ref);
1715 }
1716 },1742 },
1717 .none => {1743 .ref_coerced_ty => |ptr_ty_inst| {
1718 if (struct_init.ast.type_expr != 0) {1744 const result_ty_inst = try gz.addUnNode(.elem_type, ptr_ty_inst, node);
1719 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1745 _ = try gz.addUnNode(.validate_struct_init_result_ty, result_ty_inst, node);
1720 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);1746 return structInitExprTyped(gz, scope, node, struct_init, result_ty_inst, true);
1721 return structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init);
1722 } else {
1723 return structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);
1724 }
1725 },1747 },
1726 .ty, .coerced_ty => |ty_inst| {1748 .ty, .coerced_ty => |result_ty_inst| {
1727 if (struct_init.ast.type_expr == 0) {1749 _ = try gz.addUnNode(.validate_struct_init_result_ty, result_ty_inst, node);
1728 const struct_ty_inst = try gz.addUnNode(.opt_eu_base_ty, ty_inst, node);1750 return structInitExprTyped(gz, scope, node, struct_init, result_ty_inst, false);
1729 _ = try gz.addUnNode(.validate_struct_init_ty, struct_ty_inst, node);
1730 const result = try structInitExprRlTy(gz, scope, node, struct_init, struct_ty_inst, .struct_init);
1731 return rvalue(gz, ri, result, node);
1732 }
1733 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1734 _ = try gz.addUnNode(.validate_struct_init_ty, inner_ty_inst, node);
1735 const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init);
1736 return rvalue(gz, ri, result, node);
1737 },1751 },
1738 .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, node, struct_init, ptr_res.inst),1752 .ptr => |ptr| {
1739 .inferred_ptr => |ptr_inst| {1753 try structInitExprPtr(gz, scope, node, struct_init, ptr.inst);
1740 if (struct_init.ast.type_expr == 0) {1754 return .void_value;
1741 // We treat this case differently so that we don't get a crash when1755 },
1742 // analyzing field_base_ptr against an alloc_inferred_mut.1756 .inferred_ptr => {
1743 // See corresponding logic in arrayInitExpr.1757 // We can't get field pointers of an untyped inferred alloc, so must perform a
1744 const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);1758 // standard anonymous initialization followed by an rvalue store.
1745 return rvalue(gz, ri, result, node);1759 // See corresponding logic in arrayInitExpr.
1746 } else {1760 const struct_inst = try structInitExprAnon(gz, scope, node, struct_init);
1747 return structInitExprRlPtr(gz, scope, node, struct_init, ptr_inst);1761 return rvalue(gz, ri, struct_inst, node);
1748 }
1749 },1762 },
1750 .destructure => |destructure| {1763 .destructure => |destructure| {
1751 if (struct_init.ast.type_expr == 0) {1764 // This is an untyped init, so is an actual struct, which does
1752 // This is an untyped init, so is an actual struct, which does1765 // not support destructuring.
1753 // not support destructuring.1766 return astgen.failNodeNotes(node, "struct value cannot be destructured", .{}, &.{
1754 return astgen.failNodeNotes(node, "struct value cannot be destructured", .{}, &.{1767 try astgen.errNoteNode(destructure.src_node, "result destructured here", .{}),
1755 try astgen.errNoteNode(destructure.src_node, "result destructured here", .{}),1768 });
1756 });
1757 }
1758 // You can init tuples using struct init syntax and numeric field
1759 // names, but as with array inits, we could be bitten by default
1760 // fields. Therefore, we do a normal typed init then an rvalue
1761 // destructure.
1762 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1763 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
1764 const result = try structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init);
1765 return rvalue(gz, ri, result, node);
1766 },1769 },
1767 }1770 }
1768}1771}
17691772
1770fn structInitExprRlNone(1773/// A struct initialization expression using a `struct_init_anon` instruction.
1774fn structInitExprAnon(
1771 gz: *GenZir,1775 gz: *GenZir,
1772 scope: *Scope,1776 scope: *Scope,
1773 node: Ast.Node.Index,1777 node: Ast.Node.Index,
1774 struct_init: Ast.full.StructInit,1778 struct_init: Ast.full.StructInit,
1775 ty_inst: Zir.Inst.Ref,
1776 tag: Zir.Inst.Tag,
1777) InnerError!Zir.Inst.Ref {1779) InnerError!Zir.Inst.Ref {
1778 const astgen = gz.astgen;1780 const astgen = gz.astgen;
1779 const tree = astgen.tree;1781 const tree = astgen.tree;
...@@ -1787,104 +1789,83 @@ fn structInitExprRlNone(...@@ -1787,104 +1789,83 @@ fn structInitExprRlNone(
1787 for (struct_init.ast.fields) |field_init| {1789 for (struct_init.ast.fields) |field_init| {
1788 const name_token = tree.firstToken(field_init) - 2;1790 const name_token = tree.firstToken(field_init) - 2;
1789 const str_index = try astgen.identAsString(name_token);1791 const str_index = try astgen.identAsString(name_token);
1790 const sub_ri: ResultInfo = if (ty_inst != .none)
1791 ResultInfo{ .rl = .{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
1792 .container_type = ty_inst,
1793 .name_start = str_index,
1794 }) } }
1795 else
1796 .{ .rl = .none };
1797 setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{1792 setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{
1798 .field_name = str_index,1793 .field_name = str_index,
1799 .init = try expr(gz, scope, sub_ri, field_init),1794 .init = try expr(gz, scope, .{ .rl = .none }, field_init),
1800 });1795 });
1801 extra_index += field_size;1796 extra_index += field_size;
1802 }1797 }
18031798
1804 return try gz.addPlNodePayloadIndex(tag, node, payload_index);1799 return gz.addPlNodePayloadIndex(.struct_init_anon, node, payload_index);
1805}
1806
1807fn structInitExprRlPtr(
1808 gz: *GenZir,
1809 scope: *Scope,
1810 node: Ast.Node.Index,
1811 struct_init: Ast.full.StructInit,
1812 result_ptr: Zir.Inst.Ref,
1813) InnerError!Zir.Inst.Ref {
1814 if (struct_init.ast.type_expr == 0) {
1815 const base_ptr = try gz.addUnNode(.field_base_ptr, result_ptr, node);
1816 return structInitExprRlPtrInner(gz, scope, node, struct_init, base_ptr);
1817 }
1818 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1819 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
1820
1821 const casted_ptr = try gz.addPlNode(.coerce_result_ptr, node, Zir.Inst.Bin{ .lhs = ty_inst, .rhs = result_ptr });
1822 return structInitExprRlPtrInner(gz, scope, node, struct_init, casted_ptr);
1823}1800}
18241801
1825fn structInitExprRlPtrInner(1802/// A struct initialization expression using a `struct_init` or `struct_init_ref` instruction.
1803fn structInitExprTyped(
1826 gz: *GenZir,1804 gz: *GenZir,
1827 scope: *Scope,1805 scope: *Scope,
1828 node: Ast.Node.Index,1806 node: Ast.Node.Index,
1829 struct_init: Ast.full.StructInit,1807 struct_init: Ast.full.StructInit,
1830 result_ptr: Zir.Inst.Ref,1808 ty_inst: Zir.Inst.Ref,
1809 is_ref: bool,
1831) InnerError!Zir.Inst.Ref {1810) InnerError!Zir.Inst.Ref {
1832 const astgen = gz.astgen;1811 const astgen = gz.astgen;
1833 const tree = astgen.tree;1812 const tree = astgen.tree;
18341813
1835 const payload_index = try addExtra(astgen, Zir.Inst.Block{1814 const payload_index = try addExtra(astgen, Zir.Inst.StructInit{
1836 .body_len = @intCast(struct_init.ast.fields.len),1815 .fields_len = @intCast(struct_init.ast.fields.len),
1837 });1816 });
1838 var extra_index = try reserveExtra(astgen, struct_init.ast.fields.len);1817 const field_size = @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len;
1818 var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size);
18391819
1840 for (struct_init.ast.fields) |field_init| {1820 for (struct_init.ast.fields) |field_init| {
1841 const name_token = tree.firstToken(field_init) - 2;1821 const name_token = tree.firstToken(field_init) - 2;
1842 const str_index = try astgen.identAsString(name_token);1822 const str_index = try astgen.identAsString(name_token);
1843 const field_ptr = try gz.addPlNode(.field_ptr_init, field_init, Zir.Inst.Field{1823 const field_ty_inst = try gz.addPlNode(.struct_init_field_type, field_init, Zir.Inst.FieldType{
1844 .lhs = result_ptr,1824 .container_type = ty_inst,
1845 .field_name_start = str_index,1825 .name_start = str_index,
1846 });1826 });
1847 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;1827 setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{
1848 extra_index += 1;1828 .field_type = refToIndex(field_ty_inst).?,
1849 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = field_ptr } } }, field_init);1829 .init = try expr(gz, scope, .{ .rl = .{ .coerced_ty = field_ty_inst } }, field_init),
1830 });
1831 extra_index += field_size;
1850 }1832 }
18511833
1852 _ = try gz.addPlNodePayloadIndex(.validate_struct_init, node, payload_index);1834 const tag: Zir.Inst.Tag = if (is_ref) .struct_init_ref else .struct_init;
1853 return Zir.Inst.Ref.void_value;1835 return gz.addPlNodePayloadIndex(tag, node, payload_index);
1854}1836}
18551837
1856fn structInitExprRlTy(1838/// A struct initialization expression using field pointers.
1839fn structInitExprPtr(
1857 gz: *GenZir,1840 gz: *GenZir,
1858 scope: *Scope,1841 scope: *Scope,
1859 node: Ast.Node.Index,1842 node: Ast.Node.Index,
1860 struct_init: Ast.full.StructInit,1843 struct_init: Ast.full.StructInit,
1861 ty_inst: Zir.Inst.Ref,1844 ptr_inst: Zir.Inst.Ref,
1862 tag: Zir.Inst.Tag,1845) InnerError!void {
1863) InnerError!Zir.Inst.Ref {
1864 const astgen = gz.astgen;1846 const astgen = gz.astgen;
1865 const tree = astgen.tree;1847 const tree = astgen.tree;
18661848
1867 const payload_index = try addExtra(astgen, Zir.Inst.StructInit{1849 const struct_ptr_inst = try gz.addUnNode(.opt_eu_base_ptr_init, ptr_inst, node);
1868 .fields_len = @intCast(struct_init.ast.fields.len),1850
1851 const payload_index = try addExtra(astgen, Zir.Inst.Block{
1852 .body_len = @intCast(struct_init.ast.fields.len),
1869 });1853 });
1870 const field_size = @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len;1854 var extra_index = try reserveExtra(astgen, struct_init.ast.fields.len);
1871 var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size);
18721855
1873 for (struct_init.ast.fields) |field_init| {1856 for (struct_init.ast.fields) |field_init| {
1874 const name_token = tree.firstToken(field_init) - 2;1857 const name_token = tree.firstToken(field_init) - 2;
1875 const str_index = try astgen.identAsString(name_token);1858 const str_index = try astgen.identAsString(name_token);
1876 const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{1859 const field_ptr = try gz.addPlNode(.struct_init_field_ptr, field_init, Zir.Inst.Field{
1877 .container_type = ty_inst,1860 .lhs = struct_ptr_inst,
1878 .name_start = str_index,1861 .field_name_start = str_index,
1879 });
1880 setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{
1881 .field_type = refToIndex(field_ty_inst).?,
1882 .init = try expr(gz, scope, .{ .rl = .{ .ty = field_ty_inst } }, field_init),
1883 });1862 });
1884 extra_index += field_size;1863 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;
1864 extra_index += 1;
1865 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = field_ptr } } }, field_init);
1885 }1866 }
18861867
1887 return try gz.addPlNodePayloadIndex(tag, node, payload_index);1868 _ = try gz.addPlNodePayloadIndex(.validate_ptr_struct_init, node, payload_index);
1888}1869}
18891870
1890/// This explicitly calls expr in a comptime scope by wrapping it in a `block_comptime` if1871/// This explicitly calls expr in a comptime scope by wrapping it in a `block_comptime` if
...@@ -2314,7 +2295,7 @@ fn labeledBlockExpr(...@@ -2314,7 +2295,7 @@ fn labeledBlockExpr(
2314 const need_rl = astgen.nodes_need_rl.contains(block_node);2295 const need_rl = astgen.nodes_need_rl.contains(block_node);
2315 const block_ri: ResultInfo = if (need_rl) ri else .{2296 const block_ri: ResultInfo = if (need_rl) ri else .{
2316 .rl = switch (ri.rl) {2297 .rl = switch (ri.rl) {
2317 .ptr => .{ .ty = try ri.rl.resultType(gz, block_node, undefined) },2298 .ptr => .{ .ty = (try ri.rl.resultType(gz, block_node)).? },
2318 .inferred_ptr => .none,2299 .inferred_ptr => .none,
2319 else => ri.rl,2300 else => ri.rl,
2320 },2301 },
...@@ -2504,7 +2485,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2504,7 +2485,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2504 .array_mul,2485 .array_mul,
2505 .array_type,2486 .array_type,
2506 .array_type_sentinel,2487 .array_type_sentinel,
2507 .elem_type_index,
2508 .elem_type,2488 .elem_type,
2509 .indexable_ptr_elem_type,2489 .indexable_ptr_elem_type,
2510 .vector_elem_type,2490 .vector_elem_type,
...@@ -2531,7 +2511,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2531,7 +2511,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2531 .cmp_gte,2511 .cmp_gte,
2532 .cmp_gt,2512 .cmp_gt,
2533 .cmp_neq,2513 .cmp_neq,
2534 .coerce_result_ptr,
2535 .decl_ref,2514 .decl_ref,
2536 .decl_val,2515 .decl_val,
2537 .load,2516 .load,
...@@ -2539,11 +2518,9 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2539,11 +2518,9 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2539 .elem_ptr,2518 .elem_ptr,
2540 .elem_val,2519 .elem_val,
2541 .elem_ptr_node,2520 .elem_ptr_node,
2542 .elem_ptr_imm,
2543 .elem_val_node,2521 .elem_val_node,
2544 .elem_val_imm,2522 .elem_val_imm,
2545 .field_ptr,2523 .field_ptr,
2546 .field_ptr_init,
2547 .field_val,2524 .field_val,
2548 .field_ptr_named,2525 .field_ptr_named,
2549 .field_val_named,2526 .field_val_named,
...@@ -2599,17 +2576,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2599,17 +2576,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2599 .import,2576 .import,
2600 .switch_block,2577 .switch_block,
2601 .switch_block_ref,2578 .switch_block_ref,
2602 .struct_init_empty,
2603 .struct_init,
2604 .struct_init_ref,
2605 .struct_init_anon,
2606 .struct_init_anon_ref,
2607 .array_init,
2608 .array_init_anon,
2609 .array_init_ref,
2610 .array_init_anon_ref,
2611 .union_init,2579 .union_init,
2612 .field_type,
2613 .field_type_ref,2580 .field_type_ref,
2614 .error_set_decl,2581 .error_set_decl,
2615 .error_set_decl_anon,2582 .error_set_decl_anon,
...@@ -2680,14 +2647,27 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2680,14 +2647,27 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2680 .@"await",2647 .@"await",
2681 .ret_err_value_code,2648 .ret_err_value_code,
2682 .closure_get,2649 .closure_get,
2683 .array_base_ptr,
2684 .field_base_ptr,
2685 .ret_ptr,2650 .ret_ptr,
2686 .ret_type,2651 .ret_type,
2687 .for_len,2652 .for_len,
2688 .@"try",2653 .@"try",
2689 .try_ptr,2654 .try_ptr,
2690 .opt_eu_base_ty,2655 .opt_eu_base_ptr_init,
2656 .coerce_ptr_elem_ty,
2657 .struct_init_empty,
2658 .struct_init_empty_result,
2659 .struct_init_empty_ref_result,
2660 .struct_init_anon,
2661 .struct_init,
2662 .struct_init_ref,
2663 .struct_init_field_type,
2664 .struct_init_field_ptr,
2665 .array_init_anon,
2666 .array_init,
2667 .array_init_ref,
2668 .validate_array_init_ref_ty,
2669 .array_init_elem_type,
2670 .array_init_elem_ptr,
2691 => break :b false,2671 => break :b false,
26922672
2693 .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) {2673 .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) {
...@@ -2738,18 +2718,21 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2738,18 +2718,21 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2738 .store_node,2718 .store_node,
2739 .store_to_inferred_ptr,2719 .store_to_inferred_ptr,
2740 .resolve_inferred_alloc,2720 .resolve_inferred_alloc,
2741 .validate_struct_init,
2742 .validate_array_init,
2743 .set_runtime_safety,2721 .set_runtime_safety,
2744 .closure_capture,2722 .closure_capture,
2745 .memcpy,2723 .memcpy,
2746 .memset,2724 .memset,
2747 .validate_array_init_ty,
2748 .validate_struct_init_ty,
2749 .validate_deref,2725 .validate_deref,
2750 .validate_destructure,2726 .validate_destructure,
2751 .save_err_ret_index,2727 .save_err_ret_index,
2752 .restore_err_ret_index,2728 .restore_err_ret_index,
2729 .validate_struct_init_ty,
2730 .validate_struct_init_result_ty,
2731 .validate_ptr_struct_init,
2732 .validate_array_init_ty,
2733 .validate_array_init_result_ty,
2734 .validate_ptr_array_init,
2735 .validate_ref_ty,
2753 => break :b true,2736 => break :b true,
27542737
2755 .@"defer" => unreachable,2738 .@"defer" => unreachable,
...@@ -5635,7 +5618,7 @@ fn tryExpr(...@@ -5635,7 +5618,7 @@ fn tryExpr(
5635 const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };5618 const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
56365619
5637 const operand_ri: ResultInfo = switch (ri.rl) {5620 const operand_ri: ResultInfo = switch (ri.rl) {
5638 .ref => .{ .rl = .ref, .ctx = .error_handling_expr },5621 .ref, .ref_coerced_ty => .{ .rl = .ref, .ctx = .error_handling_expr },
5639 else => .{ .rl = .none, .ctx = .error_handling_expr },5622 else => .{ .rl = .none, .ctx = .error_handling_expr },
5640 };5623 };
5641 // This could be a pointer or value depending on the `ri` parameter.5624 // This could be a pointer or value depending on the `ri` parameter.
...@@ -5648,7 +5631,7 @@ fn tryExpr(...@@ -5648,7 +5631,7 @@ fn tryExpr(
5648 defer else_scope.unstack();5631 defer else_scope.unstack();
56495632
5650 const err_tag = switch (ri.rl) {5633 const err_tag = switch (ri.rl) {
5651 .ref => Zir.Inst.Tag.err_union_code_ptr,5634 .ref, .ref_coerced_ty => Zir.Inst.Tag.err_union_code_ptr,
5652 else => Zir.Inst.Tag.err_union_code,5635 else => Zir.Inst.Tag.err_union_code,
5653 };5636 };
5654 const err_code = try else_scope.addUnNode(err_tag, operand, node);5637 const err_code = try else_scope.addUnNode(err_tag, operand, node);
...@@ -5659,7 +5642,7 @@ fn tryExpr(...@@ -5659,7 +5642,7 @@ fn tryExpr(
5659 try else_scope.setTryBody(try_inst, operand);5642 try else_scope.setTryBody(try_inst, operand);
5660 const result = indexToRef(try_inst);5643 const result = indexToRef(try_inst);
5661 switch (ri.rl) {5644 switch (ri.rl) {
5662 .ref => return result,5645 .ref, .ref_coerced_ty => return result,
5663 else => return rvalue(parent_gz, ri, result, node),5646 else => return rvalue(parent_gz, ri, result, node),
5664 }5647 }
5665}5648}
...@@ -5682,7 +5665,7 @@ fn orelseCatchExpr(...@@ -5682,7 +5665,7 @@ fn orelseCatchExpr(
5682 const need_rl = astgen.nodes_need_rl.contains(node);5665 const need_rl = astgen.nodes_need_rl.contains(node);
5683 const block_ri: ResultInfo = if (need_rl) ri else .{5666 const block_ri: ResultInfo = if (need_rl) ri else .{
5684 .rl = switch (ri.rl) {5667 .rl = switch (ri.rl) {
5685 .ptr => .{ .ty = try ri.rl.resultType(parent_gz, node, undefined) },5668 .ptr => .{ .ty = (try ri.rl.resultType(parent_gz, node)).? },
5686 .inferred_ptr => .none,5669 .inferred_ptr => .none,
5687 else => ri.rl,5670 else => ri.rl,
5688 },5671 },
...@@ -5700,7 +5683,7 @@ fn orelseCatchExpr(...@@ -5700,7 +5683,7 @@ fn orelseCatchExpr(
5700 defer block_scope.unstack();5683 defer block_scope.unstack();
57015684
5702 const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) {5685 const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) {
5703 .ref => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none },5686 .ref, .ref_coerced_ty => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none },
5704 else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none },5687 else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none },
5705 };5688 };
5706 // This could be a pointer or value depending on the `operand_ri` parameter.5689 // This could be a pointer or value depending on the `operand_ri` parameter.
...@@ -5722,7 +5705,7 @@ fn orelseCatchExpr(...@@ -5722,7 +5705,7 @@ fn orelseCatchExpr(
5722 // This could be a pointer or value depending on `unwrap_op`.5705 // This could be a pointer or value depending on `unwrap_op`.
5723 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);5706 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);
5724 const then_result = switch (ri.rl) {5707 const then_result = switch (ri.rl) {
5725 .ref => unwrapped_payload,5708 .ref, .ref_coerced_ty => unwrapped_payload,
5726 else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node),5709 else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node),
5727 };5710 };
5728 _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, node);5711 _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, node);
...@@ -5793,7 +5776,7 @@ fn fieldAccess(...@@ -5793,7 +5776,7 @@ fn fieldAccess(
5793 node: Ast.Node.Index,5776 node: Ast.Node.Index,
5794) InnerError!Zir.Inst.Ref {5777) InnerError!Zir.Inst.Ref {
5795 switch (ri.rl) {5778 switch (ri.rl) {
5796 .ref => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node),5779 .ref, .ref_coerced_ty => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node),
5797 else => {5780 else => {
5798 const access = try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node);5781 const access = try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node);
5799 return rvalue(gz, ri, access, node);5782 return rvalue(gz, ri, access, node);
...@@ -5837,7 +5820,7 @@ fn arrayAccess(...@@ -5837,7 +5820,7 @@ fn arrayAccess(
5837 const tree = gz.astgen.tree;5820 const tree = gz.astgen.tree;
5838 const node_datas = tree.nodes.items(.data);5821 const node_datas = tree.nodes.items(.data);
5839 switch (ri.rl) {5822 switch (ri.rl) {
5840 .ref => {5823 .ref, .ref_coerced_ty => {
5841 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);5824 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
58425825
5843 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);5826 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
...@@ -5951,7 +5934,7 @@ fn ifExpr(...@@ -5951,7 +5934,7 @@ fn ifExpr(
5951 const need_rl = astgen.nodes_need_rl.contains(node);5934 const need_rl = astgen.nodes_need_rl.contains(node);
5952 const block_ri: ResultInfo = if (need_rl) ri else .{5935 const block_ri: ResultInfo = if (need_rl) ri else .{
5953 .rl = switch (ri.rl) {5936 .rl = switch (ri.rl) {
5954 .ptr => .{ .ty = try ri.rl.resultType(parent_gz, node, undefined) },5937 .ptr => .{ .ty = (try ri.rl.resultType(parent_gz, node)).? },
5955 .inferred_ptr => .none,5938 .inferred_ptr => .none,
5956 else => ri.rl,5939 else => ri.rl,
5957 },5940 },
...@@ -6181,7 +6164,7 @@ fn whileExpr(...@@ -6181,7 +6164,7 @@ fn whileExpr(
6181 const need_rl = astgen.nodes_need_rl.contains(node);6164 const need_rl = astgen.nodes_need_rl.contains(node);
6182 const block_ri: ResultInfo = if (need_rl) ri else .{6165 const block_ri: ResultInfo = if (need_rl) ri else .{
6183 .rl = switch (ri.rl) {6166 .rl = switch (ri.rl) {
6184 .ptr => .{ .ty = try ri.rl.resultType(parent_gz, node, undefined) },6167 .ptr => .{ .ty = (try ri.rl.resultType(parent_gz, node)).? },
6185 .inferred_ptr => .none,6168 .inferred_ptr => .none,
6186 else => ri.rl,6169 else => ri.rl,
6187 },6170 },
...@@ -6455,7 +6438,7 @@ fn forExpr(...@@ -6455,7 +6438,7 @@ fn forExpr(
6455 const need_rl = astgen.nodes_need_rl.contains(node);6438 const need_rl = astgen.nodes_need_rl.contains(node);
6456 const block_ri: ResultInfo = if (need_rl) ri else .{6439 const block_ri: ResultInfo = if (need_rl) ri else .{
6457 .rl = switch (ri.rl) {6440 .rl = switch (ri.rl) {
6458 .ptr => .{ .ty = try ri.rl.resultType(parent_gz, node, undefined) },6441 .ptr => .{ .ty = (try ri.rl.resultType(parent_gz, node)).? },
6459 .inferred_ptr => .none,6442 .inferred_ptr => .none,
6460 else => ri.rl,6443 else => ri.rl,
6461 },6444 },
...@@ -6773,7 +6756,7 @@ fn switchExpr(...@@ -6773,7 +6756,7 @@ fn switchExpr(
6773 const need_rl = astgen.nodes_need_rl.contains(switch_node);6756 const need_rl = astgen.nodes_need_rl.contains(switch_node);
6774 const block_ri: ResultInfo = if (need_rl) ri else .{6757 const block_ri: ResultInfo = if (need_rl) ri else .{
6775 .rl = switch (ri.rl) {6758 .rl = switch (ri.rl) {
6776 .ptr => .{ .ty = try ri.rl.resultType(parent_gz, switch_node, undefined) },6759 .ptr => .{ .ty = (try ri.rl.resultType(parent_gz, switch_node)).? },
6777 .inferred_ptr => .none,6760 .inferred_ptr => .none,
6778 else => ri.rl,6761 else => ri.rl,
6779 },6762 },
...@@ -7465,7 +7448,7 @@ fn localVarRef(...@@ -7465,7 +7448,7 @@ fn localVarRef(
7465 gpa,7448 gpa,
7466 );7449 );
74677450
7468 return rvalue(gz, ri, value_inst, ident);7451 return rvalueNoCoercePreRef(gz, ri, value_inst, ident);
7469 }7452 }
7470 s = local_val.parent;7453 s = local_val.parent;
7471 },7454 },
...@@ -7498,10 +7481,10 @@ fn localVarRef(...@@ -7498,10 +7481,10 @@ fn localVarRef(
7498 );7481 );
74997482
7500 switch (ri.rl) {7483 switch (ri.rl) {
7501 .ref => return ptr_inst,7484 .ref, .ref_coerced_ty => return ptr_inst,
7502 else => {7485 else => {
7503 const loaded = try gz.addUnNode(.load, ptr_inst, ident);7486 const loaded = try gz.addUnNode(.load, ptr_inst, ident);
7504 return rvalue(gz, ri, loaded, ident);7487 return rvalueNoCoercePreRef(gz, ri, loaded, ident);
7505 },7488 },
7506 }7489 }
7507 }7490 }
...@@ -7535,10 +7518,10 @@ fn localVarRef(...@@ -7535,10 +7518,10 @@ fn localVarRef(
7535 // Decl references happen by name rather than ZIR index so that when unrelated7518 // Decl references happen by name rather than ZIR index so that when unrelated
7536 // decls are modified, ZIR code containing references to them can be unmodified.7519 // decls are modified, ZIR code containing references to them can be unmodified.
7537 switch (ri.rl) {7520 switch (ri.rl) {
7538 .ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),7521 .ref, .ref_coerced_ty => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
7539 else => {7522 else => {
7540 const result = try gz.addStrTok(.decl_val, name_str_index, ident_token);7523 const result = try gz.addStrTok(.decl_val, name_str_index, ident_token);
7541 return rvalue(gz, ri, result, ident);7524 return rvalueNoCoercePreRef(gz, ri, result, ident);
7542 },7525 },
7543 }7526 }
7544}7527}
...@@ -7924,7 +7907,7 @@ fn bitCast(...@@ -7924,7 +7907,7 @@ fn bitCast(
7924 node: Ast.Node.Index,7907 node: Ast.Node.Index,
7925 operand_node: Ast.Node.Index,7908 operand_node: Ast.Node.Index,
7926) InnerError!Zir.Inst.Ref {7909) InnerError!Zir.Inst.Ref {
7927 const dest_type = try ri.rl.resultType(gz, node, "@bitCast");7910 const dest_type = try ri.rl.resultTypeForCast(gz, node, "@bitCast");
7928 const operand = try reachableExpr(gz, scope, .{ .rl = .none }, operand_node, node);7911 const operand = try reachableExpr(gz, scope, .{ .rl = .none }, operand_node, node);
7929 const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{7912 const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{
7930 .lhs = dest_type,7913 .lhs = dest_type,
...@@ -8024,7 +8007,7 @@ fn ptrCast(...@@ -8024,7 +8007,7 @@ fn ptrCast(
8024 // Full cast including result type8007 // Full cast including result type
80258008
8026 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);8009 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
8027 const result_type = try ri.rl.resultType(gz, root_node, flags.needResultTypeBuiltinName());8010 const result_type = try ri.rl.resultTypeForCast(gz, root_node, flags.needResultTypeBuiltinName());
8028 const operand = try expr(gz, scope, .{ .rl = .none }, node);8011 const operand = try expr(gz, scope, .{ .rl = .none }, node);
8029 try emitDbgStmt(gz, cursor);8012 try emitDbgStmt(gz, cursor);
8030 const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_i, Zir.Inst.BinNode{8013 const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_i, Zir.Inst.BinNode{
...@@ -8208,7 +8191,7 @@ fn builtinCall(...@@ -8208,7 +8191,7 @@ fn builtinCall(
8208 return rvalue(gz, ri, result, node);8191 return rvalue(gz, ri, result, node);
8209 },8192 },
8210 .field => {8193 .field => {
8211 if (ri.rl == .ref) {8194 if (ri.rl == .ref or ri.rl == .ref_coerced_ty) {
8212 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{8195 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
8213 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),8196 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
8214 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]),8197 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]),
...@@ -8475,7 +8458,7 @@ fn builtinCall(...@@ -8475,7 +8458,7 @@ fn builtinCall(
8475 try emitDbgNode(gz, node);8458 try emitDbgNode(gz, node);
84768459
8477 const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{8460 const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{
8478 .lhs = try ri.rl.resultType(gz, node, "@errSetCast"),8461 .lhs = try ri.rl.resultTypeForCast(gz, node, "@errSetCast"),
8479 .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]),8462 .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
8480 .node = gz.nodeIndexToRelative(node),8463 .node = gz.nodeIndexToRelative(node),
8481 });8464 });
...@@ -8548,7 +8531,7 @@ fn builtinCall(...@@ -8548,7 +8531,7 @@ fn builtinCall(
8548 },8531 },
85498532
8550 .splat => {8533 .splat => {
8551 const result_type = try ri.rl.resultType(gz, node, "@splat");8534 const result_type = try ri.rl.resultTypeForCast(gz, node, "@splat");
8552 const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);8535 const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);
8553 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);8536 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
8554 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{8537 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
...@@ -8810,7 +8793,7 @@ fn typeCast(...@@ -8810,7 +8793,7 @@ fn typeCast(
8810 builtin_name: []const u8,8793 builtin_name: []const u8,
8811) InnerError!Zir.Inst.Ref {8794) InnerError!Zir.Inst.Ref {
8812 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);8795 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
8813 const result_type = try ri.rl.resultType(gz, node, builtin_name);8796 const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
8814 const operand = try expr(gz, scope, .{ .rl = .none }, operand_node);8797 const operand = try expr(gz, scope, .{ .rl = .none }, operand_node);
88158798
8816 try emitDbgStmt(gz, cursor);8799 try emitDbgStmt(gz, cursor);
...@@ -10069,6 +10052,29 @@ fn rvalue(...@@ -10069,6 +10052,29 @@ fn rvalue(
10069 ri: ResultInfo,10052 ri: ResultInfo,
10070 raw_result: Zir.Inst.Ref,10053 raw_result: Zir.Inst.Ref,
10071 src_node: Ast.Node.Index,10054 src_node: Ast.Node.Index,
10055) InnerError!Zir.Inst.Ref {
10056 return rvalueInner(gz, ri, raw_result, src_node, true);
10057}
10058
10059/// Like `rvalue`, but refuses to perform coercions before taking references for
10060/// the `ref_coerced_ty` result type. This is used for local variables which do
10061/// not have `alloc`s, because we want variables to have consistent addresses,
10062/// i.e. we want them to act like lvalues.
10063fn rvalueNoCoercePreRef(
10064 gz: *GenZir,
10065 ri: ResultInfo,
10066 raw_result: Zir.Inst.Ref,
10067 src_node: Ast.Node.Index,
10068) InnerError!Zir.Inst.Ref {
10069 return rvalueInner(gz, ri, raw_result, src_node, false);
10070}
10071
10072fn rvalueInner(
10073 gz: *GenZir,
10074 ri: ResultInfo,
10075 raw_result: Zir.Inst.Ref,
10076 src_node: Ast.Node.Index,
10077 allow_coerce_pre_ref: bool,
10072) InnerError!Zir.Inst.Ref {10078) InnerError!Zir.Inst.Ref {
10073 const result = r: {10079 const result = r: {
10074 if (refToIndex(raw_result)) |result_index| {10080 if (refToIndex(raw_result)) |result_index| {
...@@ -10088,7 +10094,14 @@ fn rvalue(...@@ -10088,7 +10094,14 @@ fn rvalue(
10088 _ = try gz.addUnNode(.ensure_result_non_error, result, src_node);10094 _ = try gz.addUnNode(.ensure_result_non_error, result, src_node);
10089 return .void_value;10095 return .void_value;
10090 },10096 },
10091 .ref => {10097 .ref, .ref_coerced_ty => {
10098 const coerced_result = if (allow_coerce_pre_ref and ri.rl == .ref_coerced_ty) res: {
10099 const ptr_ty = ri.rl.ref_coerced_ty;
10100 break :res try gz.addPlNode(.coerce_ptr_elem_ty, src_node, Zir.Inst.Bin{
10101 .lhs = ptr_ty,
10102 .rhs = result,
10103 });
10104 } else result;
10092 // We need a pointer but we have a value.10105 // We need a pointer but we have a value.
10093 // Unfortunately it's not quite as simple as directly emitting a ref10106 // Unfortunately it's not quite as simple as directly emitting a ref
10094 // instruction here because we need subsequent address-of operator on10107 // instruction here because we need subsequent address-of operator on
...@@ -10096,14 +10109,14 @@ fn rvalue(...@@ -10096,14 +10109,14 @@ fn rvalue(
10096 const astgen = gz.astgen;10109 const astgen = gz.astgen;
10097 const tree = astgen.tree;10110 const tree = astgen.tree;
10098 const src_token = tree.firstToken(src_node);10111 const src_token = tree.firstToken(src_node);
10099 const result_index = refToIndex(result) orelse10112 const result_index = refToIndex(coerced_result) orelse
10100 return gz.addUnTok(.ref, result, src_token);10113 return gz.addUnTok(.ref, coerced_result, src_token);
10101 const zir_tags = gz.astgen.instructions.items(.tag);10114 const zir_tags = gz.astgen.instructions.items(.tag);
10102 if (zir_tags[result_index].isParam() or astgen.isInferred(result))10115 if (zir_tags[result_index].isParam() or astgen.isInferred(coerced_result))
10103 return gz.addUnTok(.ref, result, src_token);10116 return gz.addUnTok(.ref, coerced_result, src_token);
10104 const gop = try astgen.ref_table.getOrPut(astgen.gpa, result_index);10117 const gop = try astgen.ref_table.getOrPut(astgen.gpa, result_index);
10105 if (!gop.found_existing) {10118 if (!gop.found_existing) {
10106 gop.value_ptr.* = try gz.makeUnTok(.ref, result, src_token);10119 gop.value_ptr.* = try gz.makeUnTok(.ref, coerced_result, src_token);
10107 }10120 }
10108 return indexToRef(gop.value_ptr.*);10121 return indexToRef(gop.value_ptr.*);
10109 },10122 },
src/AstRlAnnotate.zig+26-18
...@@ -669,17 +669,21 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -669,17 +669,21 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
669 => {669 => {
670 var buf: [2]Ast.Node.Index = undefined;670 var buf: [2]Ast.Node.Index = undefined;
671 const full = tree.fullArrayInit(&buf, node).?;671 const full = tree.fullArrayInit(&buf, node).?;
672 const have_type = if (full.ast.type_expr != 0) have_type: {672
673 if (full.ast.type_expr != 0) {
674 // Explicitly typed init does not participate in RLS
673 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);675 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
674 break :have_type true;
675 } else ri.have_type;
676 if (have_type) {
677 const elem_ri: ResultInfo = .{
678 .have_type = true,
679 .have_ptr = ri.have_ptr,
680 };
681 for (full.ast.elements) |elem_init| {676 for (full.ast.elements) |elem_init| {
682 _ = try astrl.expr(elem_init, block, elem_ri);677 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);
678 }
679 return false;
680 }
681
682 if (ri.have_type) {
683 // Always forward type information
684 // If we have a result pointer, we use and forward it
685 for (full.ast.elements) |elem_init| {
686 _ = try astrl.expr(elem_init, block, ri);
683 }687 }
684 return ri.have_ptr;688 return ri.have_ptr;
685 } else {689 } else {
...@@ -702,17 +706,21 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -702,17 +706,21 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
702 => {706 => {
703 var buf: [2]Ast.Node.Index = undefined;707 var buf: [2]Ast.Node.Index = undefined;
704 const full = tree.fullStructInit(&buf, node).?;708 const full = tree.fullStructInit(&buf, node).?;
705 const have_type = if (full.ast.type_expr != 0) have_type: {709
710 if (full.ast.type_expr != 0) {
711 // Explicitly typed init does not participate in RLS
706 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);712 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
707 break :have_type true;
708 } else ri.have_type;
709 if (have_type) {
710 const elem_ri: ResultInfo = .{
711 .have_type = true,
712 .have_ptr = ri.have_ptr,
713 };
714 for (full.ast.fields) |field_init| {713 for (full.ast.fields) |field_init| {
715 _ = try astrl.expr(field_init, block, elem_ri);714 _ = try astrl.expr(field_init, block, ResultInfo.type_only);
715 }
716 return false;
717 }
718
719 if (ri.have_type) {
720 // Always forward type information
721 // If we have a result pointer, we use and forward it
722 for (full.ast.fields) |field_init| {
723 _ = try astrl.expr(field_init, block, ri);
716 }724 }
717 return ri.have_ptr;725 return ri.have_ptr;
718 } else {726 } else {
src/Autodoc.zig+3-34
...@@ -2391,34 +2391,6 @@ fn walkInstruction(...@@ -2391,34 +2391,6 @@ fn walkInstruction(
2391 .expr = .{ .@"&" = expr_index },2391 .expr = .{ .@"&" = expr_index },
2392 };2392 };
2393 },2393 },
2394 .array_init_anon_ref => {
2395 const pl_node = data[inst_index].pl_node;
2396 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
2397 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
2398 const array_data = try self.arena.alloc(usize, operands.len);
2399
2400 for (operands, 0..) |op, idx| {
2401 const wr = try self.walkRef(
2402 file,
2403 parent_scope,
2404 parent_src,
2405 op,
2406 false,
2407 call_ctx,
2408 );
2409 const expr_index = self.exprs.items.len;
2410 try self.exprs.append(self.arena, wr.expr);
2411 array_data[idx] = expr_index;
2412 }
2413
2414 const expr_index = self.exprs.items.len;
2415 try self.exprs.append(self.arena, .{ .array = array_data });
2416
2417 return DocData.WalkResult{
2418 .typeRef = null,
2419 .expr = .{ .@"&" = expr_index },
2420 };
2421 },
2422 .float => {2394 .float => {
2423 const float = data[inst_index].float;2395 const float = data[inst_index].float;
2424 return DocData.WalkResult{2396 return DocData.WalkResult{
...@@ -2709,9 +2681,7 @@ fn walkInstruction(...@@ -2709,9 +2681,7 @@ fn walkInstruction(
2709 .expr = .{ .declRef = decl_status },2681 .expr = .{ .declRef = decl_status },
2710 };2682 };
2711 },2683 },
2712 .field_val, .field_ptr, .field_type => {2684 .field_val, .field_ptr => {
2713 // TODO: field type uses Zir.Inst.FieldType, it just happens to have the
2714 // same layout as Zir.Inst.Field :^)
2715 const pl_node = data[inst_index].pl_node;2685 const pl_node = data[inst_index].pl_node;
2716 const extra = file.zir.extraData(Zir.Inst.Field, pl_node.payload_index);2686 const extra = file.zir.extraData(Zir.Inst.Field, pl_node.payload_index);
27172687
...@@ -2730,8 +2700,7 @@ fn walkInstruction(...@@ -2730,8 +2700,7 @@ fn walkInstruction(
2730 };2700 };
27312701
2732 if (tags[lhs] != .field_val and2702 if (tags[lhs] != .field_val and
2733 tags[lhs] != .field_ptr and2703 tags[lhs] != .field_ptr) break :blk lhs_extra.data.lhs;
2734 tags[lhs] != .field_type) break :blk lhs_extra.data.lhs;
27352704
2736 lhs_extra = file.zir.extraData(2705 lhs_extra = file.zir.extraData(
2737 Zir.Inst.Field,2706 Zir.Inst.Field,
...@@ -2870,7 +2839,7 @@ fn walkInstruction(...@@ -2870,7 +2839,7 @@ fn walkInstruction(
28702839
2871 const field_name = blk: {2840 const field_name = blk: {
2872 const field_inst_index = init_extra.data.field_type;2841 const field_inst_index = init_extra.data.field_type;
2873 if (tags[field_inst_index] != .field_type) unreachable;2842 if (tags[field_inst_index] != .struct_init_field_type) unreachable;
2874 const field_pl_node = data[field_inst_index].pl_node;2843 const field_pl_node = data[field_inst_index].pl_node;
2875 const field_extra = file.zir.extraData(2844 const field_extra = file.zir.extraData(
2876 Zir.Inst.FieldType,2845 Zir.Inst.FieldType,
src/Sema.zig+478-447
...@@ -836,16 +836,11 @@ const LabeledBlock = struct {...@@ -836,16 +836,11 @@ const LabeledBlock = struct {
836/// the items are contiguous in memory and thus can be passed to836/// the items are contiguous in memory and thus can be passed to
837/// `Module.resolvePeerTypes`.837/// `Module.resolvePeerTypes`.
838const InferredAlloc = struct {838const InferredAlloc = struct {
839 prongs: std.MultiArrayList(struct {839 /// The placeholder `store` instructions used before the result pointer type
840 /// The dummy instruction used as a peer to resolve the type.840 /// is known. These should be rewritten to perform any required coercions
841 /// Although this has a redundant type with placeholder, this is841 /// when the type is resolved.
842 /// needed in addition because it may be a constant value, which842 /// Allocated from `sema.arena`.
843 /// affects peer type resolution.843 prongs: std.ArrayListUnmanaged(Air.Inst.Index) = .{},
844 stored_inst: Air.Inst.Ref,
845 /// The bitcast instruction used as a placeholder when the
846 /// new result pointer type is not yet known.
847 placeholder: Air.Inst.Index,
848 }) = .{},
849};844};
850845
851const NeededComptimeReason = struct {846const NeededComptimeReason = struct {
...@@ -1040,17 +1035,14 @@ fn analyzeBodyInner(...@@ -1040,17 +1035,14 @@ fn analyzeBodyInner(
1040 .cmp_gte => try sema.zirCmp(block, inst, .gte),1035 .cmp_gte => try sema.zirCmp(block, inst, .gte),
1041 .cmp_gt => try sema.zirCmp(block, inst, .gt),1036 .cmp_gt => try sema.zirCmp(block, inst, .gt),
1042 .cmp_neq => try sema.zirCmpEq(block, inst, .neq, Air.Inst.Tag.fromCmpOp(.neq, block.float_mode == .Optimized)),1037 .cmp_neq => try sema.zirCmpEq(block, inst, .neq, Air.Inst.Tag.fromCmpOp(.neq, block.float_mode == .Optimized)),
1043 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
1044 .decl_ref => try sema.zirDeclRef(block, inst),1038 .decl_ref => try sema.zirDeclRef(block, inst),
1045 .decl_val => try sema.zirDeclVal(block, inst),1039 .decl_val => try sema.zirDeclVal(block, inst),
1046 .load => try sema.zirLoad(block, inst),1040 .load => try sema.zirLoad(block, inst),
1047 .elem_ptr => try sema.zirElemPtr(block, inst),1041 .elem_ptr => try sema.zirElemPtr(block, inst),
1048 .elem_ptr_node => try sema.zirElemPtrNode(block, inst),1042 .elem_ptr_node => try sema.zirElemPtrNode(block, inst),
1049 .elem_ptr_imm => try sema.zirElemPtrImm(block, inst),
1050 .elem_val => try sema.zirElemVal(block, inst),1043 .elem_val => try sema.zirElemVal(block, inst),
1051 .elem_val_node => try sema.zirElemValNode(block, inst),1044 .elem_val_node => try sema.zirElemValNode(block, inst),
1052 .elem_val_imm => try sema.zirElemValImm(block, inst),1045 .elem_val_imm => try sema.zirElemValImm(block, inst),
1053 .elem_type_index => try sema.zirElemTypeIndex(block, inst),
1054 .elem_type => try sema.zirElemType(block, inst),1046 .elem_type => try sema.zirElemType(block, inst),
1055 .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst),1047 .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst),
1056 .vector_elem_type => try sema.zirVectorElemType(block, inst),1048 .vector_elem_type => try sema.zirVectorElemType(block, inst),
...@@ -1063,8 +1055,7 @@ fn analyzeBodyInner(...@@ -1063,8 +1055,7 @@ fn analyzeBodyInner(
1063 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst),1055 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst),
1064 .error_union_type => try sema.zirErrorUnionType(block, inst),1056 .error_union_type => try sema.zirErrorUnionType(block, inst),
1065 .error_value => try sema.zirErrorValue(block, inst),1057 .error_value => try sema.zirErrorValue(block, inst),
1066 .field_ptr => try sema.zirFieldPtr(block, inst, false),1058 .field_ptr => try sema.zirFieldPtr(block, inst),
1067 .field_ptr_init => try sema.zirFieldPtr(block, inst, true),
1068 .field_ptr_named => try sema.zirFieldPtrNamed(block, inst),1059 .field_ptr_named => try sema.zirFieldPtrNamed(block, inst),
1069 .field_val => try sema.zirFieldVal(block, inst),1060 .field_val => try sema.zirFieldVal(block, inst),
1070 .field_val_named => try sema.zirFieldValNamed(block, inst),1061 .field_val_named => try sema.zirFieldValNamed(block, inst),
...@@ -1111,16 +1102,19 @@ fn analyzeBodyInner(...@@ -1111,16 +1102,19 @@ fn analyzeBodyInner(
1111 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),1102 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),
1112 .xor => try sema.zirBitwise(block, inst, .xor),1103 .xor => try sema.zirBitwise(block, inst, .xor),
1113 .struct_init_empty => try sema.zirStructInitEmpty(block, inst),1104 .struct_init_empty => try sema.zirStructInitEmpty(block, inst),
1105 .struct_init_empty_result => try sema.zirStructInitEmptyResult(block, inst, false),
1106 .struct_init_empty_ref_result => try sema.zirStructInitEmptyResult(block, inst, true),
1107 .struct_init_anon => try sema.zirStructInitAnon(block, inst),
1114 .struct_init => try sema.zirStructInit(block, inst, false),1108 .struct_init => try sema.zirStructInit(block, inst, false),
1115 .struct_init_ref => try sema.zirStructInit(block, inst, true),1109 .struct_init_ref => try sema.zirStructInit(block, inst, true),
1116 .struct_init_anon => try sema.zirStructInitAnon(block, inst, false),1110 .struct_init_field_type => try sema.zirStructInitFieldType(block, inst),
1117 .struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true),1111 .struct_init_field_ptr => try sema.zirStructInitFieldPtr(block, inst),
1112 .array_init_anon => try sema.zirArrayInitAnon(block, inst),
1118 .array_init => try sema.zirArrayInit(block, inst, false),1113 .array_init => try sema.zirArrayInit(block, inst, false),
1119 .array_init_ref => try sema.zirArrayInit(block, inst, true),1114 .array_init_ref => try sema.zirArrayInit(block, inst, true),
1120 .array_init_anon => try sema.zirArrayInitAnon(block, inst, false),1115 .array_init_elem_type => try sema.zirArrayInitElemType(block, inst),
1121 .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true),1116 .array_init_elem_ptr => try sema.zirArrayInitElemPtr(block, inst),
1122 .union_init => try sema.zirUnionInit(block, inst),1117 .union_init => try sema.zirUnionInit(block, inst),
1123 .field_type => try sema.zirFieldType(block, inst),
1124 .field_type_ref => try sema.zirFieldTypeRef(block, inst),1118 .field_type_ref => try sema.zirFieldTypeRef(block, inst),
1125 .int_from_ptr => try sema.zirIntFromPtr(block, inst),1119 .int_from_ptr => try sema.zirIntFromPtr(block, inst),
1126 .align_of => try sema.zirAlignOf(block, inst),1120 .align_of => try sema.zirAlignOf(block, inst),
...@@ -1154,10 +1148,10 @@ fn analyzeBodyInner(...@@ -1154,10 +1148,10 @@ fn analyzeBodyInner(
1154 .field_parent_ptr => try sema.zirFieldParentPtr(block, inst),1148 .field_parent_ptr => try sema.zirFieldParentPtr(block, inst),
1155 .@"resume" => try sema.zirResume(block, inst),1149 .@"resume" => try sema.zirResume(block, inst),
1156 .@"await" => try sema.zirAwait(block, inst),1150 .@"await" => try sema.zirAwait(block, inst),
1157 .array_base_ptr => try sema.zirArrayBasePtr(block, inst),
1158 .field_base_ptr => try sema.zirFieldBasePtr(block, inst),
1159 .for_len => try sema.zirForLen(block, inst),1151 .for_len => try sema.zirForLen(block, inst),
1160 .opt_eu_base_ty => try sema.zirOptEuBaseTy(block, inst),1152 .validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst),
1153 .opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst),
1154 .coerce_ptr_elem_ty => try sema.zirCoercePtrElemTy(block, inst),
11611155
1162 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),1156 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),
1163 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),1157 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),
...@@ -1386,23 +1380,33 @@ fn analyzeBodyInner(...@@ -1386,23 +1380,33 @@ fn analyzeBodyInner(
1386 i += 1;1380 i += 1;
1387 continue;1381 continue;
1388 },1382 },
1383 .validate_struct_init_ty => {
1384 try sema.zirValidateStructInitTy(block, inst, false);
1385 i += 1;
1386 continue;
1387 },
1388 .validate_struct_init_result_ty => {
1389 try sema.zirValidateStructInitTy(block, inst, true);
1390 i += 1;
1391 continue;
1392 },
1389 .validate_array_init_ty => {1393 .validate_array_init_ty => {
1390 try sema.zirValidateArrayInitTy(block, inst);1394 try sema.zirValidateArrayInitTy(block, inst, false);
1391 i += 1;1395 i += 1;
1392 continue;1396 continue;
1393 },1397 },
1394 .validate_struct_init_ty => {1398 .validate_array_init_result_ty => {
1395 try sema.zirValidateStructInitTy(block, inst);1399 try sema.zirValidateArrayInitTy(block, inst, true);
1396 i += 1;1400 i += 1;
1397 continue;1401 continue;
1398 },1402 },
1399 .validate_struct_init => {1403 .validate_ptr_struct_init => {
1400 try sema.zirValidateStructInit(block, inst);1404 try sema.zirValidatePtrStructInit(block, inst);
1401 i += 1;1405 i += 1;
1402 continue;1406 continue;
1403 },1407 },
1404 .validate_array_init => {1408 .validate_ptr_array_init => {
1405 try sema.zirValidateArrayInit(block, inst);1409 try sema.zirValidatePtrArrayInit(block, inst);
1406 i += 1;1410 i += 1;
1407 continue;1411 continue;
1408 },1412 },
...@@ -1416,6 +1420,11 @@ fn analyzeBodyInner(...@@ -1416,6 +1420,11 @@ fn analyzeBodyInner(
1416 i += 1;1420 i += 1;
1417 continue;1421 continue;
1418 },1422 },
1423 .validate_ref_ty => {
1424 try sema.zirValidateRefTy(block, inst);
1425 i += 1;
1426 continue;
1427 },
1419 .@"export" => {1428 .@"export" => {
1420 try sema.zirExport(block, inst);1429 try sema.zirExport(block, inst);
1421 i += 1;1430 i += 1;
...@@ -1922,7 +1931,11 @@ fn resolveDestType(...@@ -1922,7 +1931,11 @@ fn resolveDestType(
1922 const msg = msg: {1931 const msg = msg: {
1923 const msg = try sema.errMsg(block, src, "{s} must have a known result type", .{builtin_name});1932 const msg = try sema.errMsg(block, src, "{s} must have a known result type", .{builtin_name});
1924 errdefer msg.destroy(sema.gpa);1933 errdefer msg.destroy(sema.gpa);
1925 try sema.errNote(block, src, msg, "result type is unknown due to anytype parameter", .{});1934 switch (sema.genericPoisonReason(zir_ref)) {
1935 .anytype_param => |call_src| try sema.errNote(block, call_src, msg, "result type is unknown due to anytype parameter", .{}),
1936 .anyopaque_ptr => |ptr_src| try sema.errNote(block, ptr_src, msg, "result type is unknown due to opaque pointer type", .{}),
1937 .unknown => {},
1938 }
1926 try sema.errNote(block, src, msg, "use @as to provide explicit result type", .{});1939 try sema.errNote(block, src, msg, "use @as to provide explicit result type", .{});
1927 break :msg msg;1940 break :msg msg;
1928 };1941 };
...@@ -1944,6 +1957,65 @@ fn resolveDestType(...@@ -1944,6 +1957,65 @@ fn resolveDestType(
1944 return raw_ty;1957 return raw_ty;
1945}1958}
19461959
1960const GenericPoisonReason = union(enum) {
1961 anytype_param: LazySrcLoc,
1962 anyopaque_ptr: LazySrcLoc,
1963 unknown,
1964};
1965
1966/// Backtracks through ZIR instructions to determine the reason a generic poison
1967/// type was created. Used for error reporting.
1968fn genericPoisonReason(sema: *Sema, ref: Zir.Inst.Ref) GenericPoisonReason {
1969 var cur = ref;
1970 while (true) {
1971 const inst = Zir.refToIndex(cur) orelse return .unknown;
1972 switch (sema.code.instructions.items(.tag)[inst]) {
1973 .validate_array_init_ref_ty => {
1974 const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
1975 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data;
1976 cur = extra.ptr_ty;
1977 },
1978 .array_init_elem_type => {
1979 const bin = sema.code.instructions.items(.data)[inst].bin;
1980 cur = bin.lhs;
1981 },
1982 .indexable_ptr_elem_type, .vector_elem_type => {
1983 const un_node = sema.code.instructions.items(.data)[inst].un_node;
1984 cur = un_node.operand;
1985 },
1986 .struct_init_field_type => {
1987 const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
1988 const extra = sema.code.extraData(Zir.Inst.FieldType, pl_node.payload_index).data;
1989 cur = extra.container_type;
1990 },
1991 .elem_type => {
1992 // There are two cases here: the pointer type may already have been
1993 // generic poison, or it may have been an anyopaque pointer.
1994 const un_node = sema.code.instructions.items(.data)[inst].un_node;
1995 const operand_ref = sema.resolveInst(un_node.operand) catch |err| switch (err) {
1996 error.GenericPoison => unreachable, // this is a type, not a value
1997 };
1998 const operand_val = Air.refToInterned(operand_ref) orelse return .unknown;
1999 if (operand_val == .generic_poison_type) {
2000 // The pointer was generic poison - keep looking.
2001 cur = un_node.operand;
2002 } else {
2003 // This must be an anyopaque pointer!
2004 return .{ .anyopaque_ptr = un_node.src() };
2005 }
2006 },
2007 .call, .field_call => {
2008 // A function call can never return generic poison, so we must be
2009 // evaluating an `anytype` function parameter.
2010 // TODO: better source location - function decl rather than call
2011 const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
2012 return .{ .anytype_param = pl_node.src() };
2013 },
2014 else => return .unknown,
2015 }
2016 }
2017}
2018
1947fn analyzeAsType(2019fn analyzeAsType(
1948 sema: *Sema,2020 sema: *Sema,
1949 block: *Block,2021 block: *Block,
...@@ -2634,217 +2706,6 @@ pub fn resolveInstValue(...@@ -2634,217 +2706,6 @@ pub fn resolveInstValue(
2634 };2706 };
2635}2707}
26362708
2637fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
2638 const tracy = trace(@src());
2639 defer tracy.end();
2640
2641 const mod = sema.mod;
2642 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2643 const src = inst_data.src();
2644 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2645 const pointee_ty = try sema.resolveType(block, src, extra.lhs);
2646 const ptr = try sema.resolveInst(extra.rhs);
2647 const target = mod.getTarget();
2648 const addr_space = target_util.defaultAddressSpace(target, .local);
2649
2650 if (Air.refToIndex(ptr)) |ptr_inst| {
2651 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
2652 .inferred_alloc => {
2653 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
2654 const ia2 = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
2655 // Add the stored instruction to the set we will use to resolve peer types
2656 // for the inferred allocation.
2657 // This instruction will not make it to codegen; it is only to participate
2658 // in the `stored_inst_list` of the `inferred_alloc`.
2659 var trash_block = block.makeSubBlock();
2660 defer trash_block.instructions.deinit(sema.gpa);
2661 const operand = try trash_block.addBitCast(pointee_ty, .void_value);
2662
2663 const ptr_ty = try sema.ptrType(.{
2664 .child = pointee_ty.toIntern(),
2665 .flags = .{
2666 .alignment = ia1.alignment,
2667 .address_space = addr_space,
2668 },
2669 });
2670 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
2671
2672 try ia2.prongs.append(sema.arena, .{
2673 .stored_inst = operand,
2674 .placeholder = Air.refToIndex(bitcasted_ptr).?,
2675 });
2676
2677 try sema.checkKnownAllocPtr(ptr, bitcasted_ptr);
2678 return bitcasted_ptr;
2679 },
2680 .inferred_alloc_comptime => {
2681 const alignment = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.alignment;
2682 // There will be only one coerce_result_ptr because we are running at comptime.
2683 // The alloc will turn into a Decl.
2684 var anon_decl = try block.startAnonDecl();
2685 defer anon_decl.deinit();
2686 const decl_index = try anon_decl.finish(
2687 pointee_ty,
2688 (try mod.intern(.{ .undef = pointee_ty.toIntern() })).toValue(),
2689 alignment,
2690 );
2691 sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.decl_index = decl_index;
2692 if (alignment != .none) {
2693 try sema.resolveTypeLayout(pointee_ty);
2694 }
2695 const ptr_ty = try sema.ptrType(.{
2696 .child = pointee_ty.toIntern(),
2697 .flags = .{
2698 .alignment = alignment,
2699 .address_space = addr_space,
2700 },
2701 });
2702 try sema.maybeQueueFuncBodyAnalysis(decl_index);
2703 try sema.comptime_mutable_decls.append(decl_index);
2704 return Air.internedToRef((try mod.intern(.{ .ptr = .{
2705 .ty = ptr_ty.toIntern(),
2706 .addr = .{ .mut_decl = .{
2707 .decl = decl_index,
2708 .runtime_index = block.runtime_index,
2709 } },
2710 } })));
2711 },
2712 else => {},
2713 }
2714 }
2715
2716 // Make a dummy store through the pointer to test the coercion.
2717 // We will then use the generated instructions to decide what
2718 // kind of transformations to make on the result pointer.
2719 var trash_block = block.makeSubBlock();
2720 trash_block.is_comptime = false;
2721 defer trash_block.instructions.deinit(sema.gpa);
2722
2723 const dummy_ptr = try trash_block.addTy(.alloc, sema.typeOf(ptr));
2724 const dummy_operand = try trash_block.addBitCast(pointee_ty, .void_value);
2725 const new_ptr = try sema.coerceResultPtr(block, src, ptr, dummy_ptr, dummy_operand, &trash_block);
2726 try sema.checkKnownAllocPtr(ptr, new_ptr);
2727 return new_ptr;
2728}
2729
2730fn coerceResultPtr(
2731 sema: *Sema,
2732 block: *Block,
2733 src: LazySrcLoc,
2734 ptr: Air.Inst.Ref,
2735 dummy_ptr: Air.Inst.Ref,
2736 dummy_operand: Air.Inst.Ref,
2737 trash_block: *Block,
2738) CompileError!Air.Inst.Ref {
2739 const mod = sema.mod;
2740 const target = sema.mod.getTarget();
2741 const addr_space = target_util.defaultAddressSpace(target, .local);
2742 const pointee_ty = sema.typeOf(dummy_operand);
2743 const prev_trash_len = trash_block.instructions.items.len;
2744
2745 try sema.storePtr2(trash_block, src, dummy_ptr, src, dummy_operand, src, .bitcast);
2746
2747 {
2748 const air_tags = sema.air_instructions.items(.tag);
2749
2750 //std.debug.print("dummy storePtr instructions:\n", .{});
2751 //for (trash_block.instructions.items) |item| {
2752 // std.debug.print(" {s}\n", .{@tagName(air_tags[item])});
2753 //}
2754
2755 // The last one is always `store`.
2756 const trash_inst = trash_block.instructions.items[trash_block.instructions.items.len - 1];
2757 if (air_tags[trash_inst] != .store and air_tags[trash_inst] != .store_safe) {
2758 // no store instruction is generated for zero sized types
2759 assert((try sema.typeHasOnePossibleValue(pointee_ty)) != null);
2760 } else {
2761 trash_block.instructions.items.len -= 1;
2762 assert(trash_inst == sema.air_instructions.len - 1);
2763 sema.air_instructions.len -= 1;
2764 }
2765 }
2766
2767 const ptr_ty = try sema.ptrType(.{
2768 .child = pointee_ty.toIntern(),
2769 .flags = .{ .address_space = addr_space },
2770 });
2771
2772 var new_ptr = ptr;
2773
2774 while (true) {
2775 const air_tags = sema.air_instructions.items(.tag);
2776 const air_datas = sema.air_instructions.items(.data);
2777
2778 if (trash_block.instructions.items.len == prev_trash_len) {
2779 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
2780 return Air.internedToRef(ptr_val.toIntern());
2781 }
2782 if (pointee_ty.eql(Type.null, sema.mod)) {
2783 const null_inst = Air.internedToRef(Value.null.toIntern());
2784 _ = try block.addBinOp(.store, new_ptr, null_inst);
2785 return .void_value;
2786 }
2787 return sema.bitCast(block, ptr_ty, new_ptr, src, null);
2788 }
2789
2790 const trash_inst = trash_block.instructions.pop();
2791
2792 switch (air_tags[trash_inst]) {
2793 // Array coerced to Vector where element size is not equal but coercible.
2794 .aggregate_init => {
2795 const ty_pl = air_datas[trash_inst].ty_pl;
2796 const ptr_operand_ty = try sema.ptrType(.{
2797 .child = (try sema.analyzeAsType(block, src, ty_pl.ty)).toIntern(),
2798 .flags = .{ .address_space = addr_space },
2799 });
2800
2801 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
2802 return Air.internedToRef(ptr_val.toIntern());
2803 } else {
2804 return sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);
2805 }
2806 },
2807 .bitcast => {
2808 const ty_op = air_datas[trash_inst].ty_op;
2809 const operand_ty = sema.typeOf(ty_op.operand);
2810 const ptr_operand_ty = try sema.ptrType(.{
2811 .child = operand_ty.toIntern(),
2812 .flags = .{ .address_space = addr_space },
2813 });
2814 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
2815 new_ptr = Air.internedToRef((try mod.getCoerced(ptr_val, ptr_operand_ty)).toIntern());
2816 } else {
2817 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);
2818 }
2819 },
2820 .wrap_optional => {
2821 new_ptr = try sema.analyzeOptionalPayloadPtr(block, src, new_ptr, false, true);
2822 },
2823 .wrap_errunion_err => {
2824 return sema.fail(block, src, "TODO coerce_result_ptr wrap_errunion_err", .{});
2825 },
2826 .wrap_errunion_payload => {
2827 new_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, new_ptr, false, true);
2828 },
2829 .array_to_slice => {
2830 return sema.fail(block, src, "TODO coerce_result_ptr array_to_slice", .{});
2831 },
2832 .get_union_tag => {
2833 return sema.fail(block, src, "TODO coerce_result_ptr get_union_tag", .{});
2834 },
2835 else => {
2836 if (std.debug.runtime_safety) {
2837 std.debug.panic("unexpected AIR tag for coerce_result_ptr: {}", .{
2838 air_tags[trash_inst],
2839 });
2840 } else {
2841 unreachable;
2842 }
2843 },
2844 }
2845 }
2846}
2847
2848pub fn getStructType(2709pub fn getStructType(
2849 sema: *Sema,2710 sema: *Sema,
2850 decl: Module.Decl.Index,2711 decl: Module.Decl.Index,
...@@ -4220,8 +4081,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4220,8 +4081,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4220 .inferred_alloc => {4081 .inferred_alloc => {
4221 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;4082 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
4222 const ia2 = sema.unresolved_inferred_allocs.fetchRemove(ptr_inst).?.value;4083 const ia2 = sema.unresolved_inferred_allocs.fetchRemove(ptr_inst).?.value;
4223 const peer_inst_list = ia2.prongs.items(.stored_inst);4084 const peer_vals = try sema.arena.alloc(Air.Inst.Ref, ia2.prongs.items.len);
4224 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);4085 for (peer_vals, ia2.prongs.items) |*peer_val, store_inst| {
4086 assert(sema.air_instructions.items(.tag)[store_inst] == .store);
4087 const bin_op = sema.air_instructions.items(.data)[store_inst].bin_op;
4088 peer_val.* = bin_op.rhs;
4089 }
4090 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_vals, .none);
42254091
4226 const final_ptr_ty = try sema.ptrType(.{4092 const final_ptr_ty = try sema.ptrType(.{
4227 .child = final_elem_ty.toIntern(),4093 .child = final_elem_ty.toIntern(),
...@@ -4259,55 +4125,19 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4259,55 +4125,19 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4259 .data = .{ .ty = final_ptr_ty },4125 .data = .{ .ty = final_ptr_ty },
4260 });4126 });
42614127
4262 // Now we need to go back over all the coerce_result_ptr instructions, which4128 // Now we need to go back over all the store instructions, and do the logic as if
4263 // previously inserted a bitcast as a placeholder, and do the logic as if
4264 // the new result ptr type was available.4129 // the new result ptr type was available.
4265 const placeholders = ia2.prongs.items(.placeholder);
4266 const gpa = sema.gpa;4130 const gpa = sema.gpa;
42674131
4268 var trash_block = block.makeSubBlock();4132 for (ia2.prongs.items) |placeholder_inst| {
4269 trash_block.is_comptime = false;
4270 defer trash_block.instructions.deinit(gpa);
4271
4272 const mut_final_ptr_ty = try sema.ptrType(.{
4273 .child = final_elem_ty.toIntern(),
4274 .flags = .{
4275 .alignment = ia1.alignment,
4276 .address_space = target_util.defaultAddressSpace(target, .local),
4277 },
4278 });
4279 const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);
4280 const empty_trash_count = trash_block.instructions.items.len;
4281
4282 for (peer_inst_list, placeholders) |peer_inst, placeholder_inst| {
4283 const sub_ptr_ty = sema.typeOf(Air.indexToRef(placeholder_inst));
4284
4285 if (mut_final_ptr_ty.eql(sub_ptr_ty, mod)) {
4286 // New result location type is the same as the old one; nothing
4287 // to do here.
4288 continue;
4289 }
4290
4291 var replacement_block = block.makeSubBlock();4133 var replacement_block = block.makeSubBlock();
4292 defer replacement_block.instructions.deinit(gpa);4134 defer replacement_block.instructions.deinit(gpa);
42934135
4294 const result = switch (sema.air_instructions.items(.tag)[placeholder_inst]) {4136 assert(sema.air_instructions.items(.tag)[placeholder_inst] == .store);
4295 .bitcast => result: {4137 const bin_op = sema.air_instructions.items(.data)[placeholder_inst].bin_op;
4296 trash_block.instructions.shrinkRetainingCapacity(empty_trash_count);4138 try sema.storePtr2(&replacement_block, src, bin_op.lhs, src, bin_op.rhs, src, .store);
4297 const sub_ptr = try sema.coerceResultPtr(&replacement_block, src, ptr, dummy_ptr, peer_inst, &trash_block);
42984139
4299 assert(replacement_block.instructions.items.len > 0);4140 // If only one instruction is produced then we can replace the store
4300 break :result sub_ptr;
4301 },
4302 .store, .store_safe => result: {
4303 const bin_op = sema.air_instructions.items(.data)[placeholder_inst].bin_op;
4304 try sema.storePtr2(&replacement_block, src, bin_op.lhs, src, bin_op.rhs, src, .bitcast);
4305 break :result .void_value;
4306 },
4307 else => unreachable,
4308 };
4309
4310 // If only one instruction is produced then we can replace the bitcast
4311 // placeholder instruction with this instruction; no need for an entire block.4141 // placeholder instruction with this instruction; no need for an entire block.
4312 if (replacement_block.instructions.items.len == 1) {4142 if (replacement_block.instructions.items.len == 1) {
4313 const only_inst = replacement_block.instructions.items[0];4143 const only_inst = replacement_block.instructions.items[0];
...@@ -4315,13 +4145,9 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4315,13 +4145,9 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4315 continue;4145 continue;
4316 }4146 }
43174147
4318 // Here we replace the placeholder bitcast instruction with a block4148 // Here we replace the placeholder store instruction with a block
4319 // that does the coerce_result_ptr logic.4149 // that does the actual store logic.
4320 _ = try replacement_block.addBr(placeholder_inst, result);4150 _ = try replacement_block.addBr(placeholder_inst, .void_value);
4321 const ty_inst = if (result == .void_value)
4322 .void_type
4323 else
4324 sema.air_instructions.items(.data)[placeholder_inst].ty_op.ty;
4325 try sema.air_extra.ensureUnusedCapacity(4151 try sema.air_extra.ensureUnusedCapacity(
4326 gpa,4152 gpa,
4327 @typeInfo(Air.Block).Struct.fields.len + replacement_block.instructions.items.len,4153 @typeInfo(Air.Block).Struct.fields.len + replacement_block.instructions.items.len,
...@@ -4329,7 +4155,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4329,7 +4155,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4329 sema.air_instructions.set(placeholder_inst, .{4155 sema.air_instructions.set(placeholder_inst, .{
4330 .tag = .block,4156 .tag = .block,
4331 .data = .{ .ty_pl = .{4157 .data = .{ .ty_pl = .{
4332 .ty = ty_inst,4158 .ty = .void_type,
4333 .payload = sema.addExtraAssumeCapacity(Air.Block{4159 .payload = sema.addExtraAssumeCapacity(Air.Block{
4334 .body_len = @intCast(replacement_block.instructions.items.len),4160 .body_len = @intCast(replacement_block.instructions.items.len),
4335 }),4161 }),
...@@ -4342,64 +4168,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4342,64 +4168,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4342 }4168 }
4343}4169}
43444170
4345fn zirArrayBasePtr(
4346 sema: *Sema,
4347 block: *Block,
4348 inst: Zir.Inst.Index,
4349) CompileError!Air.Inst.Ref {
4350 const mod = sema.mod;
4351 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4352 const src = inst_data.src();
4353
4354 const start_ptr = try sema.resolveInst(inst_data.operand);
4355 var base_ptr = start_ptr;
4356 while (true) switch (sema.typeOf(base_ptr).childType(mod).zigTypeTag(mod)) {
4357 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
4358 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
4359 else => break,
4360 };
4361
4362 const elem_ty = sema.typeOf(base_ptr).childType(mod);
4363 switch (elem_ty.zigTypeTag(mod)) {
4364 .Array, .Vector => return base_ptr,
4365 .Struct => if (elem_ty.isTuple(mod)) {
4366 // TODO validate element count
4367 try sema.checkKnownAllocPtr(start_ptr, base_ptr);
4368 return base_ptr;
4369 },
4370 else => {},
4371 }
4372 return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType(mod));
4373}
4374
4375fn zirFieldBasePtr(
4376 sema: *Sema,
4377 block: *Block,
4378 inst: Zir.Inst.Index,
4379) CompileError!Air.Inst.Ref {
4380 const mod = sema.mod;
4381 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4382 const src = inst_data.src();
4383
4384 const start_ptr = try sema.resolveInst(inst_data.operand);
4385 var base_ptr = start_ptr;
4386 while (true) switch (sema.typeOf(base_ptr).childType(mod).zigTypeTag(mod)) {
4387 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
4388 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
4389 else => break,
4390 };
4391
4392 const elem_ty = sema.typeOf(base_ptr).childType(mod);
4393 switch (elem_ty.zigTypeTag(mod)) {
4394 .Struct, .Union => {
4395 try sema.checkKnownAllocPtr(start_ptr, base_ptr);
4396 return base_ptr;
4397 },
4398 else => {},
4399 }
4400 return sema.failWithStructInitNotSupported(block, src, sema.typeOf(start_ptr).childType(mod));
4401}
4402
4403fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4171fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
4404 const mod = sema.mod;4172 const mod = sema.mod;
4405 const gpa = sema.gpa;4173 const gpa = sema.gpa;
...@@ -4526,34 +4294,140 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4526,34 +4294,140 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4526 return len;4294 return len;
4527}4295}
45284296
4529fn zirOptEuBaseTy(4297/// Given any single pointer, retrieve a pointer to the payload of any optional
4298/// or error union pointed to, initializing these pointers along the way.
4299/// Given a `*E!?T`, returns a (valid) `*T`.
4300/// May invalidate already-stored payload data.
4301fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcLoc) CompileError!Air.Inst.Ref {
4302 const mod = sema.mod;
4303 var base_ptr = ptr;
4304 while (true) switch (sema.typeOf(base_ptr).childType(mod).zigTypeTag(mod)) {
4305 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
4306 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
4307 else => break,
4308 };
4309 try sema.checkKnownAllocPtr(ptr, base_ptr);
4310 return base_ptr;
4311}
4312
4313fn zirOptEuBasePtrInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
4314 const un_node = sema.code.instructions.items(.data)[inst].un_node;
4315 const ptr = try sema.resolveInst(un_node.operand);
4316 return sema.optEuBasePtrInit(block, ptr, un_node.src());
4317}
4318
4319fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
4320 const mod = sema.mod;
4321 const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
4322 const src = pl_node.src();
4323 const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data;
4324 const uncoerced_val = try sema.resolveInst(extra.rhs);
4325 const maybe_wrapped_ptr_ty = sema.resolveType(block, .unneeded, extra.lhs) catch |err| switch (err) {
4326 error.GenericPoison => return uncoerced_val,
4327 else => |e| return e,
4328 };
4329 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(mod);
4330 assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction
4331 const elem_ty = ptr_ty.childType(mod);
4332 switch (ptr_ty.ptrSize(mod)) {
4333 .One => {
4334 const uncoerced_ty = sema.typeOf(uncoerced_val);
4335 if (elem_ty.zigTypeTag(mod) == .Array and elem_ty.childType(mod).toIntern() == uncoerced_ty.toIntern()) {
4336 // We're trying to initialize a *[1]T with a reference to a T - don't perform any coercion.
4337 return uncoerced_val;
4338 }
4339 // If the destination type is anyopaque, don't coerce - the pointer will coerce instead.
4340 if (elem_ty.toIntern() == .anyopaque_type) {
4341 return uncoerced_val;
4342 } else {
4343 return sema.coerce(block, elem_ty, uncoerced_val, src);
4344 }
4345 },
4346 .Slice, .Many => {
4347 // Our goal is to coerce `uncoerced_val` to an array of `elem_ty`.
4348 const val_ty = sema.typeOf(uncoerced_val);
4349 switch (val_ty.zigTypeTag(mod)) {
4350 .Array, .Vector => {},
4351 else => if (!val_ty.isTuple(mod)) {
4352 return sema.fail(block, src, "expected array of '{}', found '{}'", .{ elem_ty.fmt(mod), val_ty.fmt(mod) });
4353 },
4354 }
4355 const want_ty = try mod.arrayType(.{
4356 .len = val_ty.arrayLen(mod),
4357 .child = elem_ty.toIntern(),
4358 .sentinel = if (ptr_ty.sentinel(mod)) |s| s.toIntern() else .none,
4359 });
4360 return sema.coerce(block, want_ty, uncoerced_val, src);
4361 },
4362 .C => {
4363 // There's nothing meaningful to do here, because we don't know if this is meant to be a
4364 // single-pointer or a many-pointer.
4365 return uncoerced_val;
4366 },
4367 }
4368}
4369
4370fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
4371 const mod = sema.mod;
4372 const un_tok = sema.code.instructions.items(.data)[inst].un_tok;
4373 const src = un_tok.src();
4374 const ty_operand = sema.resolveType(block, src, un_tok.operand) catch |err| switch (err) {
4375 error.GenericPoison => {
4376 // We don't actually have a type, so this will be treated as an untyped address-of operator.
4377 return;
4378 },
4379 else => |e| return e,
4380 };
4381 if (ty_operand.optEuBaseType(mod).zigTypeTag(mod) != .Pointer) {
4382 return sema.failWithOwnedErrorMsg(block, msg: {
4383 const msg = try sema.errMsg(block, src, "expected type '{}', found pointer", .{ty_operand.fmt(mod)});
4384 errdefer msg.destroy(sema.gpa);
4385 try sema.errNote(block, src, msg, "address-of operator always returns a pointer", .{});
4386 break :msg msg;
4387 });
4388 }
4389}
4390
4391fn zirValidateArrayInitRefTy(
4530 sema: *Sema,4392 sema: *Sema,
4531 block: *Block,4393 block: *Block,
4532 inst: Zir.Inst.Index,4394 inst: Zir.Inst.Index,
4533) CompileError!Air.Inst.Ref {4395) CompileError!Air.Inst.Ref {
4534 const mod = sema.mod;4396 const mod = sema.mod;
4535 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4397 const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
4536 var ty = sema.resolveType(block, .unneeded, inst_data.operand) catch |err| switch (err) {4398 const src = pl_node.src();
4537 // Since this is a ZIR instruction that returns a type, encountering4399 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data;
4538 // generic poison should not result in a failed compilation, but the4400 const maybe_wrapped_ptr_ty = sema.resolveType(block, .unneeded, extra.ptr_ty) catch |err| switch (err) {
4539 // generic poison type. This prevents unnecessary failures when
4540 // constructing types at compile-time.
4541 error.GenericPoison => return .generic_poison_type,4401 error.GenericPoison => return .generic_poison_type,
4542 else => |e| return e,4402 else => |e| return e,
4543 };4403 };
4544 while (true) {4404 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(mod);
4545 switch (ty.zigTypeTag(mod)) {4405 assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction
4546 .Optional => ty = ty.optionalChild(mod),4406 if (ptr_ty.isSlice(mod)) {
4547 .ErrorUnion => ty = ty.errorUnionPayload(mod),4407 // Use array of correct length
4548 else => return Air.internedToRef(ty.toIntern()),4408 const arr_ty = try mod.arrayType(.{
4549 }4409 .len = extra.elem_count,
4410 .child = ptr_ty.childType(mod).toIntern(),
4411 .sentinel = if (ptr_ty.sentinel(mod)) |s| s.toIntern() else .none,
4412 });
4413 return Air.internedToRef(arr_ty.toIntern());
4550 }4414 }
4415 // Otherwise, we just want the pointer child type
4416 const ret_ty = ptr_ty.childType(mod);
4417 if (ret_ty.toIntern() == .anyopaque_type) {
4418 // The actual array type is unknown, which we represent with a generic poison.
4419 return .generic_poison_type;
4420 }
4421 const arr_ty = ret_ty.optEuBaseType(mod);
4422 try sema.validateArrayInitTy(block, src, src, extra.elem_count, arr_ty);
4423 return Air.internedToRef(ret_ty.toIntern());
4551}4424}
45524425
4553fn zirValidateArrayInitTy(4426fn zirValidateArrayInitTy(
4554 sema: *Sema,4427 sema: *Sema,
4555 block: *Block,4428 block: *Block,
4556 inst: Zir.Inst.Index,4429 inst: Zir.Inst.Index,
4430 is_result_ty: bool,
4557) CompileError!void {4431) CompileError!void {
4558 const mod = sema.mod;4432 const mod = sema.mod;
4559 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;4433 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
...@@ -4565,22 +4439,34 @@ fn zirValidateArrayInitTy(...@@ -4565,22 +4439,34 @@ fn zirValidateArrayInitTy(
4565 error.GenericPoison => return,4439 error.GenericPoison => return,
4566 else => |e| return e,4440 else => |e| return e,
4567 };4441 };
4442 const arr_ty = if (is_result_ty) ty.optEuBaseType(mod) else ty;
4443 return sema.validateArrayInitTy(block, src, ty_src, extra.init_count, arr_ty);
4444}
45684445
4446fn validateArrayInitTy(
4447 sema: *Sema,
4448 block: *Block,
4449 src: LazySrcLoc,
4450 ty_src: LazySrcLoc,
4451 init_count: u32,
4452 ty: Type,
4453) CompileError!void {
4454 const mod = sema.mod;
4569 switch (ty.zigTypeTag(mod)) {4455 switch (ty.zigTypeTag(mod)) {
4570 .Array => {4456 .Array => {
4571 const array_len = ty.arrayLen(mod);4457 const array_len = ty.arrayLen(mod);
4572 if (extra.init_count != array_len) {4458 if (init_count != array_len) {
4573 return sema.fail(block, src, "expected {d} array elements; found {d}", .{4459 return sema.fail(block, src, "expected {d} array elements; found {d}", .{
4574 array_len, extra.init_count,4460 array_len, init_count,
4575 });4461 });
4576 }4462 }
4577 return;4463 return;
4578 },4464 },
4579 .Vector => {4465 .Vector => {
4580 const array_len = ty.arrayLen(mod);4466 const array_len = ty.arrayLen(mod);
4581 if (extra.init_count != array_len) {4467 if (init_count != array_len) {
4582 return sema.fail(block, src, "expected {d} vector elements; found {d}", .{4468 return sema.fail(block, src, "expected {d} vector elements; found {d}", .{
4583 array_len, extra.init_count,4469 array_len, init_count,
4584 });4470 });
4585 }4471 }
4586 return;4472 return;
...@@ -4588,9 +4474,9 @@ fn zirValidateArrayInitTy(...@@ -4588,9 +4474,9 @@ fn zirValidateArrayInitTy(
4588 .Struct => if (ty.isTuple(mod)) {4474 .Struct => if (ty.isTuple(mod)) {
4589 try sema.resolveTypeFields(ty);4475 try sema.resolveTypeFields(ty);
4590 const array_len = ty.arrayLen(mod);4476 const array_len = ty.arrayLen(mod);
4591 if (extra.init_count > array_len) {4477 if (init_count > array_len) {
4592 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{4478 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
4593 array_len, extra.init_count,4479 array_len, init_count,
4594 });4480 });
4595 }4481 }
4596 return;4482 return;
...@@ -4604,6 +4490,7 @@ fn zirValidateStructInitTy(...@@ -4604,6 +4490,7 @@ fn zirValidateStructInitTy(
4604 sema: *Sema,4490 sema: *Sema,
4605 block: *Block,4491 block: *Block,
4606 inst: Zir.Inst.Index,4492 inst: Zir.Inst.Index,
4493 is_result_ty: bool,
4607) CompileError!void {4494) CompileError!void {
4608 const mod = sema.mod;4495 const mod = sema.mod;
4609 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4496 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
...@@ -4613,15 +4500,16 @@ fn zirValidateStructInitTy(...@@ -4613,15 +4500,16 @@ fn zirValidateStructInitTy(
4613 error.GenericPoison => return,4500 error.GenericPoison => return,
4614 else => |e| return e,4501 else => |e| return e,
4615 };4502 };
4503 const struct_ty = if (is_result_ty) ty.optEuBaseType(mod) else ty;
46164504
4617 switch (ty.zigTypeTag(mod)) {4505 switch (struct_ty.zigTypeTag(mod)) {
4618 .Struct, .Union => return,4506 .Struct, .Union => return,
4619 else => {},4507 else => {},
4620 }4508 }
4621 return sema.failWithStructInitNotSupported(block, src, ty);4509 return sema.failWithStructInitNotSupported(block, src, struct_ty);
4622}4510}
46234511
4624fn zirValidateStructInit(4512fn zirValidatePtrStructInit(
4625 sema: *Sema,4513 sema: *Sema,
4626 block: *Block,4514 block: *Block,
4627 inst: Zir.Inst.Index,4515 inst: Zir.Inst.Index,
...@@ -4637,7 +4525,7 @@ fn zirValidateStructInit(...@@ -4637,7 +4525,7 @@ fn zirValidateStructInit(
4637 const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;4525 const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
4638 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;4526 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
4639 const object_ptr = try sema.resolveInst(field_ptr_extra.lhs);4527 const object_ptr = try sema.resolveInst(field_ptr_extra.lhs);
4640 const agg_ty = sema.typeOf(object_ptr).childType(mod);4528 const agg_ty = sema.typeOf(object_ptr).childType(mod).optEuBaseType(mod);
4641 switch (agg_ty.zigTypeTag(mod)) {4529 switch (agg_ty.zigTypeTag(mod)) {
4642 .Struct => return sema.validateStructInit(4530 .Struct => return sema.validateStructInit(
4643 block,4531 block,
...@@ -4723,10 +4611,6 @@ fn validateUnionInit(...@@ -4723,10 +4611,6 @@ fn validateUnionInit(
4723 // based only on the store instructions.4611 // based only on the store instructions.
4724 // `first_block_index` needs to point to the `field_ptr` if it exists;4612 // `first_block_index` needs to point to the `field_ptr` if it exists;
4725 // the `store` otherwise.4613 // the `store` otherwise.
4726 //
4727 // It's also possible for there to be no store instruction, in the case
4728 // of nested `coerce_result_ptr` instructions. If we see the `field_ptr`
4729 // but we have not found a `store`, treat as a runtime-known field.
4730 var first_block_index = block.instructions.items.len;4614 var first_block_index = block.instructions.items.len;
4731 var block_index = block.instructions.items.len - 1;4615 var block_index = block.instructions.items.len - 1;
4732 var init_val: ?Value = null;4616 var init_val: ?Value = null;
...@@ -4963,10 +4847,6 @@ fn validateStructInit(...@@ -4963,10 +4847,6 @@ fn validateStructInit(
4963 // based only on the store instructions.4847 // based only on the store instructions.
4964 // `first_block_index` needs to point to the `field_ptr` if it exists;4848 // `first_block_index` needs to point to the `field_ptr` if it exists;
4965 // the `store` otherwise.4849 // the `store` otherwise.
4966 //
4967 // It's also possible for there to be no store instruction, in the case
4968 // of nested `coerce_result_ptr` instructions. If we see the `field_ptr`
4969 // but we have not found a `store`, treat as a runtime-known field.
49704850
4971 // Possible performance enhancement: save the `block_index` between iterations4851 // Possible performance enhancement: save the `block_index` between iterations
4972 // of the for loop.4852 // of the for loop.
...@@ -5115,7 +4995,7 @@ fn validateStructInit(...@@ -5115,7 +4995,7 @@ fn validateStructInit(
5115 }4995 }
5116}4996}
51174997
5118fn zirValidateArrayInit(4998fn zirValidatePtrArrayInit(
5119 sema: *Sema,4999 sema: *Sema,
5120 block: *Block,5000 block: *Block,
5121 inst: Zir.Inst.Index,5001 inst: Zir.Inst.Index,
...@@ -5128,7 +5008,7 @@ fn zirValidateArrayInit(...@@ -5128,7 +5008,7 @@ fn zirValidateArrayInit(
5128 const first_elem_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;5008 const first_elem_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
5129 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data;5009 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data;
5130 const array_ptr = try sema.resolveInst(elem_ptr_extra.ptr);5010 const array_ptr = try sema.resolveInst(elem_ptr_extra.ptr);
5131 const array_ty = sema.typeOf(array_ptr).childType(mod);5011 const array_ty = sema.typeOf(array_ptr).childType(mod).optEuBaseType(mod);
5132 const array_len = array_ty.arrayLen(mod);5012 const array_len = array_ty.arrayLen(mod);
51335013
5134 if (instrs.len != array_len) switch (array_ty.zigTypeTag(mod)) {5014 if (instrs.len != array_len) switch (array_ty.zigTypeTag(mod)) {
...@@ -5227,10 +5107,6 @@ fn zirValidateArrayInit(...@@ -5227,10 +5107,6 @@ fn zirValidateArrayInit(
5227 // `first_block_index` needs to point to the `elem_ptr` if it exists;5107 // `first_block_index` needs to point to the `elem_ptr` if it exists;
5228 // the `store` otherwise.5108 // the `store` otherwise.
5229 //5109 //
5230 // It's also possible for there to be no store instruction, in the case
5231 // of nested `coerce_result_ptr` instructions. If we see the `elem_ptr`
5232 // but we have not found a `store`, treat as a runtime-known element.
5233 //
5234 // This is nearly identical to similar logic in `validateStructInit`.5110 // This is nearly identical to similar logic in `validateStructInit`.
52355111
5236 // Possible performance enhancement: save the `block_index` between iterations5112 // Possible performance enhancement: save the `block_index` between iterations
...@@ -5540,10 +5416,7 @@ fn storeToInferredAlloc(...@@ -5540,10 +5416,7 @@ fn storeToInferredAlloc(
5540 try sema.checkComptimeKnownStore(block, dummy_store);5416 try sema.checkComptimeKnownStore(block, dummy_store);
5541 // Add the stored instruction to the set we will use to resolve peer types5417 // Add the stored instruction to the set we will use to resolve peer types
5542 // for the inferred allocation.5418 // for the inferred allocation.
5543 try inferred_alloc.prongs.append(sema.arena, .{5419 try inferred_alloc.prongs.append(sema.arena, Air.refToIndex(dummy_store).?);
5544 .stored_inst = operand,
5545 .placeholder = Air.refToIndex(dummy_store).?,
5546 });
5547}5420}
55485421
5549fn storeToInferredAllocComptime(5422fn storeToInferredAllocComptime(
...@@ -8314,10 +8187,10 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -8314,10 +8187,10 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
8314 return Air.internedToRef(opt_type.toIntern());8187 return Air.internedToRef(opt_type.toIntern());
8315}8188}
83168189
8317fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8190fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8318 const mod = sema.mod;8191 const mod = sema.mod;
8319 const bin = sema.code.instructions.items(.data)[inst].bin;8192 const bin = sema.code.instructions.items(.data)[inst].bin;
8320 const indexable_ty = sema.resolveType(block, .unneeded, bin.lhs) catch |err| switch (err) {8193 const maybe_wrapped_indexable_ty = sema.resolveType(block, .unneeded, bin.lhs) catch |err| switch (err) {
8321 // Since this is a ZIR instruction that returns a type, encountering8194 // Since this is a ZIR instruction that returns a type, encountering
8322 // generic poison should not result in a failed compilation, but the8195 // generic poison should not result in a failed compilation, but the
8323 // generic poison type. This prevents unnecessary failures when8196 // generic poison type. This prevents unnecessary failures when
...@@ -8325,6 +8198,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -8325,6 +8198,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
8325 error.GenericPoison => return .generic_poison_type,8198 error.GenericPoison => return .generic_poison_type,
8326 else => |e| return e,8199 else => |e| return e,
8327 };8200 };
8201 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(mod);
8328 try sema.resolveTypeFields(indexable_ty);8202 try sema.resolveTypeFields(indexable_ty);
8329 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction8203 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
8330 if (indexable_ty.zigTypeTag(mod) == .Struct) {8204 if (indexable_ty.zigTypeTag(mod) == .Struct) {
...@@ -8339,8 +8213,18 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -8339,8 +8213,18 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
8339fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8213fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8340 const mod = sema.mod;8214 const mod = sema.mod;
8341 const un_node = sema.code.instructions.items(.data)[inst].un_node;8215 const un_node = sema.code.instructions.items(.data)[inst].un_node;
8342 const ptr_ty = try sema.resolveType(block, .unneeded, un_node.operand);8216 const maybe_wrapped_ptr_ty = sema.resolveType(block, .unneeded, un_node.operand) catch |err| switch (err) {
8217 error.GenericPoison => return .generic_poison_type,
8218 else => |e| return e,
8219 };
8220 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(mod);
8343 assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction8221 assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction
8222 const elem_ty = ptr_ty.childType(mod);
8223 if (elem_ty.toIntern() == .anyopaque_type) {
8224 // The pointer's actual child type is effectively unknown, so it makes
8225 // sense to represent it with a generic poison.
8226 return .generic_poison_type;
8227 }
8344 return Air.internedToRef(ptr_ty.childType(mod).toIntern());8228 return Air.internedToRef(ptr_ty.childType(mod).toIntern());
8345}8229}
83468230
...@@ -10083,7 +9967,21 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10083,7 +9967,21 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10083 return sema.fieldVal(block, src, object, field_name, field_name_src);9967 return sema.fieldVal(block, src, object, field_name, field_name_src);
10084}9968}
100859969
10086fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index, initializing: bool) CompileError!Air.Inst.Ref {9970fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
9971 const tracy = trace(@src());
9972 defer tracy.end();
9973
9974 const mod = sema.mod;
9975 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
9976 const src = inst_data.src();
9977 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
9978 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
9979 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start));
9980 const object_ptr = try sema.resolveInst(extra.lhs);
9981 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false);
9982}
9983
9984fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10087 const tracy = trace(@src());9985 const tracy = trace(@src());
10088 defer tracy.end();9986 defer tracy.end();
100899987
...@@ -10094,7 +9992,15 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index, initializing: b...@@ -10094,7 +9992,15 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index, initializing: b
10094 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;9992 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
10095 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start));9993 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start));
10096 const object_ptr = try sema.resolveInst(extra.lhs);9994 const object_ptr = try sema.resolveInst(extra.lhs);
10097 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, initializing);9995 const struct_ty = sema.typeOf(object_ptr).childType(mod);
9996 switch (struct_ty.zigTypeTag(mod)) {
9997 .Struct, .Union => {
9998 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, true);
9999 },
10000 else => {
10001 return sema.failWithStructInitNotSupported(block, src, struct_ty);
10002 },
10003 }
10098}10004}
1009910005
10100fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {10006fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -10587,15 +10493,23 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10587,15 +10493,23 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10587 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, true);10493 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, true);
10588}10494}
1058910495
10590fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {10496fn zirArrayInitElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10591 const tracy = trace(@src());10497 const tracy = trace(@src());
10592 defer tracy.end();10498 defer tracy.end();
1059310499
10500 const mod = sema.mod;
10594 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;10501 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
10595 const src = inst_data.src();10502 const src = inst_data.src();
10596 const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;10503 const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
10597 const array_ptr = try sema.resolveInst(extra.ptr);10504 const array_ptr = try sema.resolveInst(extra.ptr);
10598 const elem_index = try sema.mod.intRef(Type.usize, extra.index);10505 const elem_index = try sema.mod.intRef(Type.usize, extra.index);
10506 const array_ty = sema.typeOf(array_ptr).childType(mod);
10507 switch (array_ty.zigTypeTag(mod)) {
10508 .Array, .Vector => {},
10509 else => if (!array_ty.isTuple(mod)) {
10510 return sema.failWithArrayInitNotSupported(block, src, array_ty);
10511 },
10512 }
10599 return sema.elemPtr(block, src, array_ptr, elem_index, src, true, true);10513 return sema.elemPtr(block, src, array_ptr, elem_index, src, true, true);
10600}10514}
1060110515
...@@ -19213,6 +19127,52 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -19213,6 +19127,52 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
19213 }19127 }
19214}19128}
1921519129
19130fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_byref: bool) CompileError!Air.Inst.Ref {
19131 const tracy = trace(@src());
19132 defer tracy.end();
19133
19134 const mod = sema.mod;
19135 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
19136 const src = inst_data.src();
19137 const ty_operand = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) {
19138 // Generic poison means this is an untyped anonymous empty struct init
19139 error.GenericPoison => return .empty_struct,
19140 else => |e| return e,
19141 };
19142 const init_ty = if (is_byref) ty: {
19143 const ptr_ty = ty_operand.optEuBaseType(mod);
19144 assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction
19145 if (!ptr_ty.isSlice(mod)) {
19146 break :ty ptr_ty.childType(mod);
19147 }
19148 // To make `&.{}` a `[:s]T`, the init should be a `[0:s]T`.
19149 break :ty try mod.arrayType(.{
19150 .len = 0,
19151 .sentinel = if (ptr_ty.sentinel(mod)) |s| s.toIntern() else .none,
19152 .child = ptr_ty.childType(mod).toIntern(),
19153 });
19154 } else ty_operand;
19155 const obj_ty = init_ty.optEuBaseType(mod);
19156
19157 const empty_ref = switch (obj_ty.zigTypeTag(mod)) {
19158 .Struct => try sema.structInitEmpty(block, obj_ty, src, src),
19159 .Array, .Vector => try sema.arrayInitEmpty(block, src, obj_ty),
19160 .Union => return sema.fail(block, src, "union initializer must initialize one field", .{}),
19161 else => return sema.failWithArrayInitNotSupported(block, src, obj_ty),
19162 };
19163 const init_ref = try sema.coerce(block, init_ty, empty_ref, src);
19164
19165 if (is_byref) {
19166 const init_val = (try sema.resolveMaybeUndefVal(init_ref)).?;
19167 var anon_decl = try block.startAnonDecl();
19168 defer anon_decl.deinit();
19169 const decl = try anon_decl.finish(init_ty, init_val, .none);
19170 return sema.analyzeDeclRef(decl);
19171 } else {
19172 return init_ref;
19173 }
19174}
19175
19216fn structInitEmpty(19176fn structInitEmpty(
19217 sema: *Sema,19177 sema: *Sema,
19218 block: *Block,19178 block: *Block,
...@@ -19230,7 +19190,7 @@ fn structInitEmpty(...@@ -19230,7 +19190,7 @@ fn structInitEmpty(
19230 defer gpa.free(field_inits);19190 defer gpa.free(field_inits);
19231 @memset(field_inits, .none);19191 @memset(field_inits, .none);
1923219192
19233 return sema.finishStructInit(block, init_src, dest_src, field_inits, struct_ty, false);19193 return sema.finishStructInit(block, init_src, dest_src, field_inits, struct_ty, struct_ty, false);
19234}19194}
1923519195
19236fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref {19196fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref {
...@@ -19321,13 +19281,14 @@ fn zirStructInit(...@@ -19321,13 +19281,14 @@ fn zirStructInit(
19321 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;19281 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
19322 const first_field_type_data = zir_datas[first_item.field_type].pl_node;19282 const first_field_type_data = zir_datas[first_item.field_type].pl_node;
19323 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;19283 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;
19324 const resolved_ty = sema.resolveType(block, src, first_field_type_extra.container_type) catch |err| switch (err) {19284 const result_ty = sema.resolveType(block, src, first_field_type_extra.container_type) catch |err| switch (err) {
19325 error.GenericPoison => {19285 error.GenericPoison => {
19326 // The type wasn't actually known, so treat this as an anon struct init.19286 // The type wasn't actually known, so treat this as an anon struct init.
19327 return sema.structInitAnon(block, src, .typed_init, extra.data, extra.end, is_ref);19287 return sema.structInitAnon(block, src, .typed_init, extra.data, extra.end, is_ref);
19328 },19288 },
19329 else => |e| return e,19289 else => |e| return e,
19330 };19290 };
19291 const resolved_ty = result_ty.optEuBaseType(mod);
19331 try sema.resolveTypeLayout(resolved_ty);19292 try sema.resolveTypeLayout(resolved_ty);
1933219293
19333 if (resolved_ty.zigTypeTag(mod) == .Struct) {19294 if (resolved_ty.zigTypeTag(mod) == .Struct) {
...@@ -19372,7 +19333,9 @@ fn zirStructInit(...@@ -19372,7 +19333,9 @@ fn zirStructInit(
19372 return sema.failWithOwnedErrorMsg(block, msg);19333 return sema.failWithOwnedErrorMsg(block, msg);
19373 }19334 }
19374 found_fields[field_index] = item.data.field_type;19335 found_fields[field_index] = item.data.field_type;
19375 field_inits[field_index] = try sema.resolveInst(item.data.init);19336 const uncoerced_init = try sema.resolveInst(item.data.init);
19337 const field_ty = resolved_ty.structFieldType(field_index, mod);
19338 field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src);
19376 if (!is_packed) if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| {19339 if (!is_packed) if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| {
19377 const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse {19340 const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse {
19378 return sema.failWithNeededComptime(block, field_src, .{19341 return sema.failWithNeededComptime(block, field_src, .{
...@@ -19386,7 +19349,7 @@ fn zirStructInit(...@@ -19386,7 +19349,7 @@ fn zirStructInit(
19386 };19349 };
19387 }19350 }
1938819351
19389 return sema.finishStructInit(block, src, src, field_inits, resolved_ty, is_ref);19352 return sema.finishStructInit(block, src, src, field_inits, resolved_ty, result_ty, is_ref);
19390 } else if (resolved_ty.zigTypeTag(mod) == .Union) {19353 } else if (resolved_ty.zigTypeTag(mod) == .Union) {
19391 if (extra.data.fields_len != 1) {19354 if (extra.data.fields_len != 1) {
19392 return sema.fail(block, src, "union initialization expects exactly one field", .{});19355 return sema.fail(block, src, "union initialization expects exactly one field", .{});
...@@ -19401,36 +19364,60 @@ fn zirStructInit(...@@ -19401,36 +19364,60 @@ fn zirStructInit(
19401 const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src);19364 const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src);
19402 const tag_ty = resolved_ty.unionTagTypeHypothetical(mod);19365 const tag_ty = resolved_ty.unionTagTypeHypothetical(mod);
19403 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);19366 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
19367 const field_ty = mod.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index].toType();
19368
19369 if (field_ty.zigTypeTag(mod) == .NoReturn) {
19370 return sema.failWithOwnedErrorMsg(block, msg: {
19371 const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{});
19372 errdefer msg.destroy(sema.gpa);
19373
19374 try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{}' declared here", .{
19375 field_name.fmt(ip),
19376 });
19377 try sema.addDeclaredHereNote(msg, resolved_ty);
19378 break :msg msg;
19379 });
19380 }
19381
19382 const uncoerced_init_inst = try sema.resolveInst(item.data.init);
19383 const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src);
1940419384
19405 const init_inst = try sema.resolveInst(item.data.init);
19406 if (try sema.resolveMaybeUndefVal(init_inst)) |val| {19385 if (try sema.resolveMaybeUndefVal(init_inst)) |val| {
19407 const field_ty = mod.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index].toType();19386 const struct_val = (try mod.intern(.{ .un = .{
19408 return sema.addConstantMaybeRef(block, resolved_ty, (try mod.intern(.{ .un = .{
19409 .ty = resolved_ty.toIntern(),19387 .ty = resolved_ty.toIntern(),
19410 .tag = try tag_val.intern(tag_ty, mod),19388 .tag = try tag_val.intern(tag_ty, mod),
19411 .val = try val.intern(field_ty, mod),19389 .val = try val.intern(field_ty, mod),
19412 } })).toValue(), is_ref);19390 } })).toValue();
19391 const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src);
19392 const final_val = (try sema.resolveMaybeUndefVal(final_val_inst)).?;
19393 return sema.addConstantMaybeRef(block, resolved_ty, final_val, is_ref);
19394 }
19395
19396 if (try sema.typeRequiresComptime(resolved_ty)) {
19397 return sema.failWithNeededComptime(block, field_src, .{
19398 .needed_comptime_reason = "initializer of comptime only union must be comptime-known",
19399 });
19413 }19400 }
1941419401
19415 if (is_ref) {19402 if (is_ref) {
19416 const target = mod.getTarget();19403 const target = mod.getTarget();
19417 const alloc_ty = try sema.ptrType(.{19404 const alloc_ty = try sema.ptrType(.{
19418 .child = resolved_ty.toIntern(),19405 .child = result_ty.toIntern(),
19419 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },19406 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
19420 });19407 });
19421 const alloc = try block.addTy(.alloc, alloc_ty);19408 const alloc = try block.addTy(.alloc, alloc_ty);
19422 const field_ptr = try sema.unionFieldPtr(block, field_src, alloc, field_name, field_src, resolved_ty, true);19409 const base_ptr = try sema.optEuBasePtrInit(block, alloc, src);
19410 const field_ptr = try sema.unionFieldPtr(block, field_src, base_ptr, field_name, field_src, resolved_ty, true);
19423 try sema.storePtr(block, src, field_ptr, init_inst);19411 try sema.storePtr(block, src, field_ptr, init_inst);
19424 const new_tag = Air.internedToRef(tag_val.toIntern());19412 const new_tag = Air.internedToRef(tag_val.toIntern());
19425 _ = try block.addBinOp(.set_union_tag, alloc, new_tag);19413 _ = try block.addBinOp(.set_union_tag, base_ptr, new_tag);
19426 return sema.makePtrConst(block, alloc);19414 return sema.makePtrConst(block, alloc);
19427 }19415 }
1942819416
19429 try sema.requireRuntimeBlock(block, src, null);19417 try sema.requireRuntimeBlock(block, src, null);
19430 try sema.queueFullTypeResolution(resolved_ty);19418 try sema.queueFullTypeResolution(resolved_ty);
19431 return block.addUnionInit(resolved_ty, field_index, init_inst);19419 const union_val = try block.addUnionInit(resolved_ty, field_index, init_inst);
19432 } else if (resolved_ty.isAnonStruct(mod)) {19420 return sema.coerce(block, result_ty, union_val, src);
19433 return sema.fail(block, src, "TODO anon struct init validation", .{});
19434 }19421 }
19435 unreachable;19422 unreachable;
19436}19423}
...@@ -19442,6 +19429,7 @@ fn finishStructInit(...@@ -19442,6 +19429,7 @@ fn finishStructInit(
19442 dest_src: LazySrcLoc,19429 dest_src: LazySrcLoc,
19443 field_inits: []Air.Inst.Ref,19430 field_inits: []Air.Inst.Ref,
19444 struct_ty: Type,19431 struct_ty: Type,
19432 result_ty: Type,
19445 is_ref: bool,19433 is_ref: bool,
19446) CompileError!Air.Inst.Ref {19434) CompileError!Air.Inst.Ref {
19447 const mod = sema.mod;19435 const mod = sema.mod;
...@@ -19452,8 +19440,24 @@ fn finishStructInit(...@@ -19452,8 +19440,24 @@ fn finishStructInit(
1945219440
19453 switch (ip.indexToKey(struct_ty.toIntern())) {19441 switch (ip.indexToKey(struct_ty.toIntern())) {
19454 .anon_struct_type => |anon_struct| {19442 .anon_struct_type => |anon_struct| {
19455 for (anon_struct.values.get(ip), 0..) |default_val, i| {19443 // We can't get the slices, as the coercion may invalidate them.
19456 if (field_inits[i] != .none) continue;19444 for (0..anon_struct.types.len) |i| {
19445 if (field_inits[i] != .none) {
19446 // Coerce the init value to the field type.
19447 const field_ty = anon_struct.types.get(ip)[i].toType();
19448 field_inits[i] = sema.coerce(block, field_ty, field_inits[i], .unneeded) catch |err| switch (err) {
19449 error.NeededSourceLocation => {
19450 const decl = mod.declPtr(block.src_decl);
19451 const field_src = mod.initSrc(init_src.node_offset.x, decl, i);
19452 _ = try sema.coerce(block, field_ty, field_inits[i], field_src);
19453 unreachable;
19454 },
19455 else => |e| return e,
19456 };
19457 continue;
19458 }
19459
19460 const default_val = anon_struct.values.get(ip)[i];
1945719461
19458 if (default_val == .none) {19462 if (default_val == .none) {
19459 if (anon_struct.names.len == 0) {19463 if (anon_struct.names.len == 0) {
...@@ -19480,7 +19484,20 @@ fn finishStructInit(...@@ -19480,7 +19484,20 @@ fn finishStructInit(
19480 },19484 },
19481 .struct_type => |struct_type| {19485 .struct_type => |struct_type| {
19482 for (0..struct_type.field_types.len) |i| {19486 for (0..struct_type.field_types.len) |i| {
19483 if (field_inits[i] != .none) continue;19487 if (field_inits[i] != .none) {
19488 // Coerce the init value to the field type.
19489 const field_ty = struct_type.field_types.get(ip)[i].toType();
19490 field_inits[i] = sema.coerce(block, field_ty, field_inits[i], init_src) catch |err| switch (err) {
19491 error.NeededSourceLocation => {
19492 const decl = mod.declPtr(block.src_decl);
19493 const field_src = mod.initSrc(init_src.node_offset.x, decl, i);
19494 _ = try sema.coerce(block, field_ty, field_inits[i], field_src);
19495 unreachable;
19496 },
19497 else => |e| return e,
19498 };
19499 continue;
19500 }
1948419501
19485 const field_init = struct_type.fieldInit(ip, i);19502 const field_init = struct_type.fieldInit(ip, i);
19486 if (field_init == .none) {19503 if (field_init == .none) {
...@@ -19524,29 +19541,39 @@ fn finishStructInit(...@@ -19524,29 +19541,39 @@ fn finishStructInit(
1952419541
19525 const runtime_index = opt_runtime_index orelse {19542 const runtime_index = opt_runtime_index orelse {
19526 const elems = try sema.arena.alloc(InternPool.Index, field_inits.len);19543 const elems = try sema.arena.alloc(InternPool.Index, field_inits.len);
19527 for (elems, field_inits, 0..) |*elem, field_init, field_i| {19544 for (elems, field_inits) |*elem, field_init| {
19528 elem.* = try (sema.resolveMaybeUndefVal(field_init) catch unreachable).?19545 elem.* = (sema.resolveMaybeUndefVal(field_init) catch unreachable).?.toIntern();
19529 .intern(struct_ty.structFieldType(field_i, mod), mod);
19530 }19546 }
19531 const struct_val = try mod.intern(.{ .aggregate = .{19547 const struct_val = try mod.intern(.{ .aggregate = .{
19532 .ty = struct_ty.toIntern(),19548 .ty = struct_ty.toIntern(),
19533 .storage = .{ .elems = elems },19549 .storage = .{ .elems = elems },
19534 } });19550 } });
19535 return sema.addConstantMaybeRef(block, struct_ty, struct_val.toValue(), is_ref);19551 const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val), init_src);
19552 const final_val = (try sema.resolveMaybeUndefVal(final_val_inst)).?;
19553 return sema.addConstantMaybeRef(block, result_ty, final_val, is_ref);
19536 };19554 };
1953719555
19556 if (try sema.typeRequiresComptime(struct_ty)) {
19557 const decl = mod.declPtr(block.src_decl);
19558 const field_src = mod.initSrc(init_src.node_offset.x, decl, runtime_index);
19559 return sema.failWithNeededComptime(block, field_src, .{
19560 .needed_comptime_reason = "initializer of comptime only struct must be comptime-known",
19561 });
19562 }
19563
19538 if (is_ref) {19564 if (is_ref) {
19539 try sema.resolveStructLayout(struct_ty);19565 try sema.resolveStructLayout(struct_ty);
19540 const target = sema.mod.getTarget();19566 const target = sema.mod.getTarget();
19541 const alloc_ty = try sema.ptrType(.{19567 const alloc_ty = try sema.ptrType(.{
19542 .child = struct_ty.toIntern(),19568 .child = result_ty.toIntern(),
19543 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },19569 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
19544 });19570 });
19545 const alloc = try block.addTy(.alloc, alloc_ty);19571 const alloc = try block.addTy(.alloc, alloc_ty);
19572 const base_ptr = try sema.optEuBasePtrInit(block, alloc, init_src);
19546 for (field_inits, 0..) |field_init, i_usize| {19573 for (field_inits, 0..) |field_init, i_usize| {
19547 const i: u32 = @intCast(i_usize);19574 const i: u32 = @intCast(i_usize);
19548 const field_src = dest_src;19575 const field_src = dest_src;
19549 const field_ptr = try sema.structFieldPtrByIndex(block, dest_src, alloc, i, field_src, struct_ty, true);19576 const field_ptr = try sema.structFieldPtrByIndex(block, dest_src, base_ptr, i, field_src, struct_ty, true);
19550 try sema.storePtr(block, dest_src, field_ptr, field_init);19577 try sema.storePtr(block, dest_src, field_ptr, field_init);
19551 }19578 }
1955219579
...@@ -19563,19 +19590,19 @@ fn finishStructInit(...@@ -19563,19 +19590,19 @@ fn finishStructInit(
19563 else => |e| return e,19590 else => |e| return e,
19564 };19591 };
19565 try sema.queueFullTypeResolution(struct_ty);19592 try sema.queueFullTypeResolution(struct_ty);
19566 return block.addAggregateInit(struct_ty, field_inits);19593 const struct_val = try block.addAggregateInit(struct_ty, field_inits);
19594 return sema.coerce(block, result_ty, struct_val, init_src);
19567}19595}
1956819596
19569fn zirStructInitAnon(19597fn zirStructInitAnon(
19570 sema: *Sema,19598 sema: *Sema,
19571 block: *Block,19599 block: *Block,
19572 inst: Zir.Inst.Index,19600 inst: Zir.Inst.Index,
19573 is_ref: bool,
19574) CompileError!Air.Inst.Ref {19601) CompileError!Air.Inst.Ref {
19575 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;19602 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19576 const src = inst_data.src();19603 const src = inst_data.src();
19577 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);19604 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
19578 return sema.structInitAnon(block, src, .anon_init, extra.data, extra.end, is_ref);19605 return sema.structInitAnon(block, src, .anon_init, extra.data, extra.end, false);
19579}19606}
1958019607
19581fn structInitAnon(19608fn structInitAnon(
...@@ -19748,13 +19775,14 @@ fn zirArrayInit(...@@ -19748,13 +19775,14 @@ fn zirArrayInit(
19748 const args = sema.code.refSlice(extra.end, extra.data.operands_len);19775 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
19749 assert(args.len >= 2); // array_ty + at least one element19776 assert(args.len >= 2); // array_ty + at least one element
1975019777
19751 const array_ty = sema.resolveType(block, src, args[0]) catch |err| switch (err) {19778 const result_ty = sema.resolveType(block, src, args[0]) catch |err| switch (err) {
19752 error.GenericPoison => {19779 error.GenericPoison => {
19753 // The type wasn't actually known, so treat this as an anon array init.19780 // The type wasn't actually known, so treat this as an anon array init.
19754 return sema.arrayInitAnon(block, src, args[1..], is_ref);19781 return sema.arrayInitAnon(block, src, args[1..], is_ref);
19755 },19782 },
19756 else => |e| return e,19783 else => |e| return e,
19757 };19784 };
19785 const array_ty = result_ty.optEuBaseType(mod);
19758 const is_tuple = array_ty.zigTypeTag(mod) == .Struct;19786 const is_tuple = array_ty.zigTypeTag(mod) == .Struct;
19759 const sentinel_val = array_ty.sentinel(mod);19787 const sentinel_val = array_ty.sentinel(mod);
1976019788
...@@ -19810,10 +19838,12 @@ fn zirArrayInit(...@@ -19810,10 +19838,12 @@ fn zirArrayInit(
19810 // We checked that all args are comptime above.19838 // We checked that all args are comptime above.
19811 val.* = try ((sema.resolveMaybeUndefVal(arg) catch unreachable).?).intern(elem_ty, mod);19839 val.* = try ((sema.resolveMaybeUndefVal(arg) catch unreachable).?).intern(elem_ty, mod);
19812 }19840 }
19813 return sema.addConstantMaybeRef(block, array_ty, (try mod.intern(.{ .aggregate = .{19841 const arr_val = try mod.intern(.{ .aggregate = .{
19814 .ty = array_ty.toIntern(),19842 .ty = array_ty.toIntern(),
19815 .storage = .{ .elems = elem_vals },19843 .storage = .{ .elems = elem_vals },
19816 } })).toValue(), is_ref);19844 } });
19845 const result_ref = try sema.coerce(block, result_ty, Air.internedToRef(arr_val), src);
19846 return sema.addConstantMaybeRef(block, result_ty, (try sema.resolveMaybeUndefVal(result_ref)).?, is_ref);
19817 };19847 };
1981819848
19819 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {19849 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
...@@ -19830,10 +19860,11 @@ fn zirArrayInit(...@@ -19830,10 +19860,11 @@ fn zirArrayInit(
19830 if (is_ref) {19860 if (is_ref) {
19831 const target = mod.getTarget();19861 const target = mod.getTarget();
19832 const alloc_ty = try sema.ptrType(.{19862 const alloc_ty = try sema.ptrType(.{
19833 .child = array_ty.toIntern(),19863 .child = result_ty.toIntern(),
19834 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },19864 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
19835 });19865 });
19836 const alloc = try block.addTy(.alloc, alloc_ty);19866 const alloc = try block.addTy(.alloc, alloc_ty);
19867 const base_ptr = try sema.optEuBasePtrInit(block, alloc, src);
1983719868
19838 if (array_ty.isTuple(mod)) {19869 if (array_ty.isTuple(mod)) {
19839 for (resolved_args, 0..) |arg, i| {19870 for (resolved_args, 0..) |arg, i| {
...@@ -19844,7 +19875,7 @@ fn zirArrayInit(...@@ -19844,7 +19875,7 @@ fn zirArrayInit(
19844 const elem_ptr_ty_ref = Air.internedToRef(elem_ptr_ty.toIntern());19875 const elem_ptr_ty_ref = Air.internedToRef(elem_ptr_ty.toIntern());
1984519876
19846 const index = try mod.intRef(Type.usize, i);19877 const index = try mod.intRef(Type.usize, i);
19847 const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref);19878 const elem_ptr = try block.addPtrElemPtrTypeRef(base_ptr, index, elem_ptr_ty_ref);
19848 _ = try block.addBinOp(.store, elem_ptr, arg);19879 _ = try block.addBinOp(.store, elem_ptr, arg);
19849 }19880 }
19850 return sema.makePtrConst(block, alloc);19881 return sema.makePtrConst(block, alloc);
...@@ -19858,26 +19889,26 @@ fn zirArrayInit(...@@ -19858,26 +19889,26 @@ fn zirArrayInit(
1985819889
19859 for (resolved_args, 0..) |arg, i| {19890 for (resolved_args, 0..) |arg, i| {
19860 const index = try mod.intRef(Type.usize, i);19891 const index = try mod.intRef(Type.usize, i);
19861 const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref);19892 const elem_ptr = try block.addPtrElemPtrTypeRef(base_ptr, index, elem_ptr_ty_ref);
19862 _ = try block.addBinOp(.store, elem_ptr, arg);19893 _ = try block.addBinOp(.store, elem_ptr, arg);
19863 }19894 }
19864 return sema.makePtrConst(block, alloc);19895 return sema.makePtrConst(block, alloc);
19865 }19896 }
1986619897
19867 return block.addAggregateInit(array_ty, resolved_args);19898 const arr_ref = try block.addAggregateInit(array_ty, resolved_args);
19899 return sema.coerce(block, result_ty, arr_ref, src);
19868}19900}
1986919901
19870fn zirArrayInitAnon(19902fn zirArrayInitAnon(
19871 sema: *Sema,19903 sema: *Sema,
19872 block: *Block,19904 block: *Block,
19873 inst: Zir.Inst.Index,19905 inst: Zir.Inst.Index,
19874 is_ref: bool,
19875) CompileError!Air.Inst.Ref {19906) CompileError!Air.Inst.Ref {
19876 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;19907 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19877 const src = inst_data.src();19908 const src = inst_data.src();
19878 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);19909 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
19879 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);19910 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);
19880 return sema.arrayInitAnon(block, src, operands, is_ref);19911 return sema.arrayInitAnon(block, src, operands, false);
19881}19912}
1988219913
19883fn arrayInitAnon(19914fn arrayInitAnon(
...@@ -19997,14 +20028,14 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -19997,14 +20028,14 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
19997 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);20028 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);
19998}20029}
1999920030
20000fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20031fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20001 const mod = sema.mod;20032 const mod = sema.mod;
20002 const ip = &mod.intern_pool;20033 const ip = &mod.intern_pool;
20003 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;20034 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
20004 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;20035 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
20005 const ty_src = inst_data.src();20036 const ty_src = inst_data.src();
20006 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };20037 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
20007 const aggregate_ty = sema.resolveType(block, ty_src, extra.container_type) catch |err| switch (err) {20038 const wrapped_aggregate_ty = sema.resolveType(block, ty_src, extra.container_type) catch |err| switch (err) {
20008 // Since this is a ZIR instruction that returns a type, encountering20039 // Since this is a ZIR instruction that returns a type, encountering
20009 // generic poison should not result in a failed compilation, but the20040 // generic poison should not result in a failed compilation, but the
20010 // generic poison type. This prevents unnecessary failures when20041 // generic poison type. This prevents unnecessary failures when
...@@ -20012,6 +20043,7 @@ fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -20012,6 +20043,7 @@ fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
20012 error.GenericPoison => return .generic_poison_type,20043 error.GenericPoison => return .generic_poison_type,
20013 else => |e| return e,20044 else => |e| return e,
20014 };20045 };
20046 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(mod);
20015 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);20047 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
20016 const field_name = try ip.getOrPutString(sema.gpa, zir_field_name);20048 const field_name = try ip.getOrPutString(sema.gpa, zir_field_name);
20017 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);20049 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);
...@@ -20033,7 +20065,10 @@ fn fieldType(...@@ -20033,7 +20065,10 @@ fn fieldType(
20033 switch (cur_ty.zigTypeTag(mod)) {20065 switch (cur_ty.zigTypeTag(mod)) {
20034 .Struct => switch (ip.indexToKey(cur_ty.toIntern())) {20066 .Struct => switch (ip.indexToKey(cur_ty.toIntern())) {
20035 .anon_struct_type => |anon_struct| {20067 .anon_struct_type => |anon_struct| {
20036 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);20068 const field_index = if (anon_struct.names.len == 0)
20069 try sema.tupleFieldIndex(block, cur_ty, field_name, field_src)
20070 else
20071 try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
20037 return Air.internedToRef(anon_struct.types.get(ip)[field_index]);20072 return Air.internedToRef(anon_struct.types.get(ip)[field_index]);
20038 },20073 },
20039 .struct_type => |struct_type| {20074 .struct_type => |struct_type| {
...@@ -21620,7 +21655,8 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -21620,7 +21655,8 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
21620 const operand_coerced = try sema.coerce(block, operand_ty, operand_res, operand_src);21655 const operand_coerced = try sema.coerce(block, operand_ty, operand_res, operand_src);
2162121656
21622 const ptr_ty = dest_ty.scalarType(mod);21657 const ptr_ty = dest_ty.scalarType(mod);
21623 try sema.checkPtrType(block, src, ptr_ty);21658 try sema.checkPtrType(block, src, ptr_ty, true);
21659
21624 const elem_ty = ptr_ty.elemType2(mod);21660 const elem_ty = ptr_ty.elemType2(mod);
21625 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);21661 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);
2162621662
...@@ -21860,7 +21896,7 @@ fn ptrCastFull(...@@ -21860,7 +21896,7 @@ fn ptrCastFull(
21860 const mod = sema.mod;21896 const mod = sema.mod;
21861 const operand_ty = sema.typeOf(operand);21897 const operand_ty = sema.typeOf(operand);
2186221898
21863 try sema.checkPtrType(block, src, dest_ty);21899 try sema.checkPtrType(block, src, dest_ty, true);
21864 try sema.checkPtrOperand(block, operand_src, operand_ty);21900 try sema.checkPtrOperand(block, operand_src, operand_ty);
2186521901
21866 const src_info = operand_ty.ptrInfo(mod);21902 const src_info = operand_ty.ptrInfo(mod);
...@@ -22668,10 +22704,11 @@ fn checkPtrType(...@@ -22668,10 +22704,11 @@ fn checkPtrType(
22668 block: *Block,22704 block: *Block,
22669 ty_src: LazySrcLoc,22705 ty_src: LazySrcLoc,
22670 ty: Type,22706 ty: Type,
22707 allow_slice: bool,
22671) CompileError!void {22708) CompileError!void {
22672 const mod = sema.mod;22709 const mod = sema.mod;
22673 switch (ty.zigTypeTag(mod)) {22710 switch (ty.zigTypeTag(mod)) {
22674 .Pointer => return,22711 .Pointer => if (allow_slice or !ty.isSlice(mod)) return,
22675 .Fn => {22712 .Fn => {
22676 const msg = msg: {22713 const msg = msg: {
22677 const msg = try sema.errMsg(22714 const msg = try sema.errMsg(
...@@ -29577,13 +29614,6 @@ fn storePtr2(...@@ -29577,13 +29614,6 @@ fn storePtr2(
29577 return;29614 return;
29578 }29615 }
2957929616
29580 if (air_tag == .bitcast) {
29581 // `air_tag == .bitcast` is used as a special case for `zirCoerceResultPtr`
29582 // to avoid calling `requireRuntimeBlock` for the dummy block.
29583 _ = try block.addBinOp(.store, ptr, operand);
29584 return;
29585 }
29586
29587 try sema.requireRuntimeBlock(block, src, runtime_src);29617 try sema.requireRuntimeBlock(block, src, runtime_src);
29588 try sema.queueFullTypeResolution(elem_ty);29618 try sema.queueFullTypeResolution(elem_ty);
2958929619
...@@ -29719,6 +29749,7 @@ fn storePtrVal(...@@ -29719,6 +29749,7 @@ fn storePtrVal(
29719 switch (mut_kit.pointee) {29749 switch (mut_kit.pointee) {
29720 .direct => |val_ptr| {29750 .direct => |val_ptr| {
29721 if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) {29751 if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) {
29752 val_ptr.* = (try val_ptr.intern(operand_ty, mod)).toValue();
29722 if (!operand_val.eql(val_ptr.*, operand_ty, mod)) {29753 if (!operand_val.eql(val_ptr.*, operand_ty, mod)) {
29723 // TODO use failWithInvalidComptimeFieldStore29754 // TODO use failWithInvalidComptimeFieldStore
29724 return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{});29755 return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{});
src/Zir.zig+181-144
...@@ -242,10 +242,9 @@ pub const Inst = struct {...@@ -242,10 +242,9 @@ pub const Inst = struct {
242 /// Uses the `pl_node` union field with `Bin` payload.242 /// Uses the `pl_node` union field with `Bin` payload.
243 /// lhs is length, rhs is element type.243 /// lhs is length, rhs is element type.
244 vector_type,244 vector_type,
245 /// Given an indexable type, returns the type of the element at given index.245 /// Given a pointer type, returns its element type. Reaches through any optional or error
246 /// Uses the `bin` union field. lhs is the indexable type, rhs is the index.246 /// union types wrapping the pointer. Asserts that the underlying type is a pointer type.
247 elem_type_index,247 /// Returns generic poison if the element type is `anyopaque`.
248 /// Given a pointer type, returns its element type.
249 /// Uses the `un_node` field.248 /// Uses the `un_node` field.
250 elem_type,249 elem_type,
251 /// Given an indexable pointer (slice, many-ptr, single-ptr-to-array), returns its250 /// Given an indexable pointer (slice, many-ptr, single-ptr-to-array), returns its
...@@ -353,11 +352,6 @@ pub const Inst = struct {...@@ -353,11 +352,6 @@ pub const Inst = struct {
353 /// `!=`352 /// `!=`
354 /// Uses the `pl_node` union field. Payload is `Bin`.353 /// Uses the `pl_node` union field. Payload is `Bin`.
355 cmp_neq,354 cmp_neq,
356 /// Coerces a result location pointer to a new element type. It is evaluated "backwards"-
357 /// as type coercion from the new element type to the old element type.
358 /// Uses the `pl_node` union field. Payload is `Bin`.
359 /// LHS is destination element type, RHS is result pointer.
360 coerce_result_ptr,
361 /// Conditional branch. Splits control flow based on a boolean condition value.355 /// Conditional branch. Splits control flow based on a boolean condition value.
362 /// Uses the `pl_node` union field. AST node is an if, while, for, etc.356 /// Uses the `pl_node` union field. AST node is an if, while, for, etc.
363 /// Payload is `CondBr`.357 /// Payload is `CondBr`.
...@@ -419,13 +413,6 @@ pub const Inst = struct {...@@ -419,13 +413,6 @@ pub const Inst = struct {
419 /// Payload is `Bin`.413 /// Payload is `Bin`.
420 /// No OOB safety check is emitted.414 /// No OOB safety check is emitted.
421 elem_ptr,415 elem_ptr,
422 /// Same as `elem_ptr_node` except the index is stored immediately rather than
423 /// as a reference to another ZIR instruction.
424 /// Uses the `pl_node` union field. AST node is an element inside array initialization
425 /// syntax. Payload is `ElemPtrImm`.
426 /// This instruction has a way to set the result type to be a
427 /// single-pointer or a many-pointer.
428 elem_ptr_imm,
429 /// Given an array, slice, or pointer, returns the element at the provided index.416 /// Given an array, slice, or pointer, returns the element at the provided index.
430 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.417 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
431 elem_val_node,418 elem_val_node,
...@@ -463,8 +450,6 @@ pub const Inst = struct {...@@ -463,8 +450,6 @@ pub const Inst = struct {
463 /// to the named field. The field name is stored in string_bytes. Used by a.b syntax.450 /// to the named field. The field name is stored in string_bytes. Used by a.b syntax.
464 /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.451 /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.
465 field_ptr,452 field_ptr,
466 /// Same as `field_ptr` but used for struct init.
467 field_ptr_init,
468 /// Given a struct or object that contains virtual fields, returns the named field.453 /// Given a struct or object that contains virtual fields, returns the named field.
469 /// The field name is stored in string_bytes. Used by a.b syntax.454 /// The field name is stored in string_bytes. Used by a.b syntax.
470 /// This instruction also accepts a pointer.455 /// This instruction also accepts a pointer.
...@@ -688,84 +673,123 @@ pub const Inst = struct {...@@ -688,84 +673,123 @@ pub const Inst = struct {
688 /// A switch expression. Uses the `pl_node` union field.673 /// A switch expression. Uses the `pl_node` union field.
689 /// AST node is the switch, payload is `SwitchBlock`. Operand is a pointer.674 /// AST node is the switch, payload is `SwitchBlock`. Operand is a pointer.
690 switch_block_ref,675 switch_block_ref,
691 /// Given a
692 /// *A returns *A
693 /// *E!A returns *A
694 /// *?A returns *A
695 /// Uses the `un_node` field.
696 array_base_ptr,
697 /// Given a
698 /// *S returns *S
699 /// *E!S returns *S
700 /// *?S returns *S
701 /// Uses the `un_node` field.
702 field_base_ptr,
703 /// Given a type, strips all optional and error union types wrapping it.
704 /// e.g. `E!?u32` becomes `u32`, `[]u8` becomes `[]u8`.
705 /// Uses the `un_node` field.
706 opt_eu_base_ty,
707 /// Checks that the type supports array init syntax.
708 /// Returns the underlying indexable type (since the given type may be e.g. an optional).
709 /// Uses the `un_node` field.
710 validate_array_init_ty,
711 /// Checks that the type supports struct init syntax.
712 /// Returns the underlying struct type (since the given type may be e.g. an optional).
713 /// Uses the `un_node` field.
714 validate_struct_init_ty,
715 /// Given a set of `field_ptr` instructions, assumes they are all part of a struct
716 /// initialization expression, and emits compile errors for duplicate fields
717 /// as well as missing fields, if applicable.
718 /// This instruction asserts that there is at least one field_ptr instruction,
719 /// because it must use one of them to find out the struct type.
720 /// Uses the `pl_node` field. Payload is `Block`.
721 validate_struct_init,
722 /// Given a set of `elem_ptr_imm` instructions, assumes they are all part of an
723 /// array initialization expression, and emits a compile error if the number of
724 /// elements does not match the array type.
725 /// This instruction asserts that there is at least one `elem_ptr_imm` instruction,
726 /// because it must use one of them to find out the array type.
727 /// Uses the `pl_node` field. Payload is `Block`.
728 validate_array_init,
729 /// Check that operand type supports the dereference operand (.*).676 /// Check that operand type supports the dereference operand (.*).
730 /// Uses the `un_node` field.677 /// Uses the `un_node` field.
731 validate_deref,678 validate_deref,
732 /// Check that the operand's type is an array or tuple with the given number of elements.679 /// Check that the operand's type is an array or tuple with the given number of elements.
733 /// Uses the `pl_node` field. Payload is `ValidateDestructure`.680 /// Uses the `pl_node` field. Payload is `ValidateDestructure`.
734 validate_destructure,681 validate_destructure,
735 /// A struct literal with a specified type, with no fields.
736 /// Uses the `un_node` field.
737 struct_init_empty,
738 /// Given a struct or union, and a field name as a string index,
739 /// returns the field type. Uses the `pl_node` field. Payload is `FieldType`.
740 field_type,
741 /// Given a struct or union, and a field name as a Ref,682 /// Given a struct or union, and a field name as a Ref,
742 /// returns the field type. Uses the `pl_node` field. Payload is `FieldTypeRef`.683 /// returns the field type. Uses the `pl_node` field. Payload is `FieldTypeRef`.
743 field_type_ref,684 field_type_ref,
685 /// Given a pointer, initializes all error unions and optionals in the pointee to payloads,
686 /// returning the base payload pointer. For instance, converts *E!?T into a valid *T
687 /// (clobbering any existing error or null value).
688 /// Uses the `un_node` field.
689 opt_eu_base_ptr_init,
690 /// Coerce a given value such that when a reference is taken, the resulting pointer will be
691 /// coercible to the given type. For instance, given a value of type 'u32' and the pointer
692 /// type '*u64', coerces the value to a 'u64'. Asserts that the type is a pointer type.
693 /// Uses the `pl_node` field. Payload is `Bin`.
694 /// LHS is the pointer type, RHS is the value.
695 coerce_ptr_elem_ty,
696 /// Given a type, validate that it is a pointer type suitable for return from the address-of
697 /// operator. Emit a compile error if not.
698 /// Uses the `un_tok` union field. Token is the `&` operator. Operand is the type.
699 validate_ref_ty,
700
701 // The following tags all relate to struct initialization expressions.
702
703 /// A struct literal with a specified explicit type, with no fields.
704 /// Uses the `un_node` field.
705 struct_init_empty,
706 /// An anonymous struct literal with a known result type, with no fields.
707 /// Uses the `un_node` field.
708 struct_init_empty_result,
709 /// An anonymous struct literal with no fields, returned by reference, with a known result
710 /// type for the pointer. Asserts that the type is a pointer.
711 /// Uses the `un_node` field.
712 struct_init_empty_ref_result,
713 /// Struct initialization without a type. Creates a value of an anonymous struct type.
714 /// Uses the `pl_node` field. Payload is `StructInitAnon`.
715 struct_init_anon,
744 /// Finalizes a typed struct or union initialization, performs validation, and returns the716 /// Finalizes a typed struct or union initialization, performs validation, and returns the
745 /// struct or union value.717 /// struct or union value. The given type must be validated prior to this instruction, using
718 /// `validate_struct_init_ty` or `validate_struct_init_result_ty`. If the given type is
719 /// generic poison, this is downgraded to an anonymous initialization.
746 /// Uses the `pl_node` field. Payload is `StructInit`.720 /// Uses the `pl_node` field. Payload is `StructInit`.
747 struct_init,721 struct_init,
748 /// Struct initialization syntax, make the result a pointer.722 /// Struct initialization syntax, make the result a pointer. Equivalent to `struct_init`
723 /// followed by `ref` - this ZIR tag exists as an optimization for a common pattern.
749 /// Uses the `pl_node` field. Payload is `StructInit`.724 /// Uses the `pl_node` field. Payload is `StructInit`.
750 struct_init_ref,725 struct_init_ref,
751 /// Struct initialization without a type.726 /// Checks that the type supports struct init syntax. Always returns void.
752 /// Uses the `pl_node` field. Payload is `StructInitAnon`.727 /// Uses the `un_node` field.
753 struct_init_anon,728 validate_struct_init_ty,
754 /// Anonymous struct initialization syntax, make the result a pointer.729 /// Like `validate_struct_init_ty`, but additionally accepts types which structs coerce to.
755 /// Uses the `pl_node` field. Payload is `StructInitAnon`.730 /// Used on the known result type of a struct init expression. Always returns void.
756 struct_init_anon_ref,731 /// Uses the `un_node` field.
757 /// Array initialization syntax.732 validate_struct_init_result_ty,
758 /// Uses the `pl_node` field. Payload is `MultiOp`.733 /// Given a set of `struct_init_field_ptr` instructions, assumes they are all part of a
759 array_init,734 /// struct initialization expression, and emits compile errors for duplicate fields as well
760 /// Anonymous array initialization syntax.735 /// as missing fields, if applicable.
736 /// This instruction asserts that there is at least one struct_init_field_ptr instruction,
737 /// because it must use one of them to find out the struct type.
738 /// Uses the `pl_node` field. Payload is `Block`.
739 validate_ptr_struct_init,
740 /// Given a type being used for a struct initialization expression, returns the type of the
741 /// field with the given name.
742 /// Uses the `pl_node` field. Payload is `FieldType`.
743 struct_init_field_type,
744 /// Given a pointer being used as the result pointer of a struct initialization expression,
745 /// return a pointer to the field of the given name.
746 /// Uses the `pl_node` field. The AST node is the field initializer. Payload is Field.
747 struct_init_field_ptr,
748
749 // The following tags all relate to array initialization expressions.
750
751 /// Array initialization without a type. Creates a value of a tuple type.
761 /// Uses the `pl_node` field. Payload is `MultiOp`.752 /// Uses the `pl_node` field. Payload is `MultiOp`.
762 array_init_anon,753 array_init_anon,
763 /// Array initialization syntax, make the result a pointer.754 /// Array initialization syntax with a known type. The given type must be validated prior to
764 /// Uses the `pl_node` field. Payload is `MultiOp`.755 /// this instruction, using some `validate_array_init_*_ty` instruction.
756 /// Uses the `pl_node` field. Payload is `MultiOp`, where the first operand is the type.
757 array_init,
758 /// Array initialization syntax, make the result a pointer. Equivalent to `array_init`
759 /// followed by `ref`- this ZIR tag exists as an optimization for a common pattern.
760 /// Uses the `pl_node` field. Payload is `MultiOp`, where the first operand is the type.
765 array_init_ref,761 array_init_ref,
766 /// Anonymous array initialization syntax, make the result a pointer.762 /// Checks that the type supports array init syntax. Always returns void.
767 /// Uses the `pl_node` field. Payload is `MultiOp`.763 /// Uses the `pl_node` field. Payload is `ArrayInit`.
768 array_init_anon_ref,764 validate_array_init_ty,
765 /// Like `validate_array_init_ty`, but additionally accepts types which arrays coerce to.
766 /// Used on the known result type of an array init expression. Always returns void.
767 /// Uses the `pl_node` field. Payload is `ArrayInit`.
768 validate_array_init_result_ty,
769 /// Given a pointer or slice type and an element count, return the expected type of an array
770 /// initializer such that a pointer to the initializer has the given pointer type, checking
771 /// that this type supports array init syntax and emitting a compile error if not. Preserves
772 /// error union and optional wrappers on the array type, if any.
773 /// Asserts that the given type is a pointer or slice type.
774 /// Uses the `pl_node` field. Payload is `ArrayInitRefTy`.
775 validate_array_init_ref_ty,
776 /// Given a set of `array_init_elem_ptr` instructions, assumes they are all part of an array
777 /// initialization expression, and emits a compile error if the number of elements does not
778 /// match the array type.
779 /// This instruction asserts that there is at least one `array_init_elem_ptr` instruction,
780 /// because it must use one of them to find out the array type.
781 /// Uses the `pl_node` field. Payload is `Block`.
782 validate_ptr_array_init,
783 /// Given a type being used for an array initialization expression, returns the type of the
784 /// element at the given index.
785 /// Uses the `bin` union field. lhs is the indexable type, rhs is the index.
786 array_init_elem_type,
787 /// Given a pointer being used as the result pointer of an array initialization expression,
788 /// return a pointer to the element at the given index.
789 /// Uses the `pl_node` union field. AST node is an element inside array initialization
790 /// syntax. Payload is `ElemPtrImm`.
791 array_init_elem_ptr,
792
769 /// Implements the `@unionInit` builtin.793 /// Implements the `@unionInit` builtin.
770 /// Uses the `pl_node` field. Payload is `UnionInit`.794 /// Uses the `pl_node` field. Payload is `UnionInit`.
771 union_init,795 union_init,
...@@ -1038,7 +1062,6 @@ pub const Inst = struct {...@@ -1038,7 +1062,6 @@ pub const Inst = struct {
1038 .array_type,1062 .array_type,
1039 .array_type_sentinel,1063 .array_type_sentinel,
1040 .vector_type,1064 .vector_type,
1041 .elem_type_index,
1042 .elem_type,1065 .elem_type,
1043 .indexable_ptr_elem_type,1066 .indexable_ptr_elem_type,
1044 .vector_elem_type,1067 .vector_elem_type,
...@@ -1066,7 +1089,6 @@ pub const Inst = struct {...@@ -1066,7 +1089,6 @@ pub const Inst = struct {
1066 .cmp_gte,1089 .cmp_gte,
1067 .cmp_gt,1090 .cmp_gt,
1068 .cmp_neq,1091 .cmp_neq,
1069 .coerce_result_ptr,
1070 .error_set_decl,1092 .error_set_decl,
1071 .error_set_decl_anon,1093 .error_set_decl_anon,
1072 .error_set_decl_func,1094 .error_set_decl_func,
...@@ -1082,7 +1104,6 @@ pub const Inst = struct {...@@ -1082,7 +1104,6 @@ pub const Inst = struct {
1082 .elem_ptr,1104 .elem_ptr,
1083 .elem_val,1105 .elem_val,
1084 .elem_ptr_node,1106 .elem_ptr_node,
1085 .elem_ptr_imm,
1086 .elem_val_node,1107 .elem_val_node,
1087 .elem_val_imm,1108 .elem_val_imm,
1088 .ensure_result_used,1109 .ensure_result_used,
...@@ -1091,7 +1112,6 @@ pub const Inst = struct {...@@ -1091,7 +1112,6 @@ pub const Inst = struct {
1091 .@"export",1112 .@"export",
1092 .export_value,1113 .export_value,
1093 .field_ptr,1114 .field_ptr,
1094 .field_ptr_init,
1095 .field_val,1115 .field_val,
1096 .field_ptr_named,1116 .field_ptr_named,
1097 .field_val_named,1117 .field_val_named,
...@@ -1154,25 +1174,9 @@ pub const Inst = struct {...@@ -1154,25 +1174,9 @@ pub const Inst = struct {
1154 .set_eval_branch_quota,1174 .set_eval_branch_quota,
1155 .switch_block,1175 .switch_block,
1156 .switch_block_ref,1176 .switch_block_ref,
1157 .array_base_ptr,
1158 .field_base_ptr,
1159 .validate_array_init_ty,
1160 .validate_struct_init_ty,
1161 .validate_struct_init,
1162 .validate_array_init,
1163 .validate_deref,1177 .validate_deref,
1164 .validate_destructure,1178 .validate_destructure,
1165 .struct_init_empty,
1166 .struct_init,
1167 .struct_init_ref,
1168 .struct_init_anon,
1169 .struct_init_anon_ref,
1170 .array_init,
1171 .array_init_anon,
1172 .array_init_ref,
1173 .array_init_anon_ref,
1174 .union_init,1179 .union_init,
1175 .field_type,
1176 .field_type_ref,1180 .field_type_ref,
1177 .enum_from_int,1181 .enum_from_int,
1178 .int_from_enum,1182 .int_from_enum,
...@@ -1254,7 +1258,29 @@ pub const Inst = struct {...@@ -1254,7 +1258,29 @@ pub const Inst = struct {
1254 .save_err_ret_index,1258 .save_err_ret_index,
1255 .restore_err_ret_index,1259 .restore_err_ret_index,
1256 .for_len,1260 .for_len,
1257 .opt_eu_base_ty,1261 .opt_eu_base_ptr_init,
1262 .coerce_ptr_elem_ty,
1263 .struct_init_empty,
1264 .struct_init_empty_result,
1265 .struct_init_empty_ref_result,
1266 .struct_init_anon,
1267 .struct_init,
1268 .struct_init_ref,
1269 .validate_struct_init_ty,
1270 .validate_struct_init_result_ty,
1271 .validate_ptr_struct_init,
1272 .struct_init_field_type,
1273 .struct_init_field_ptr,
1274 .array_init_anon,
1275 .array_init,
1276 .array_init_ref,
1277 .validate_array_init_ty,
1278 .validate_array_init_result_ty,
1279 .validate_array_init_ref_ty,
1280 .validate_ptr_array_init,
1281 .array_init_elem_type,
1282 .array_init_elem_ptr,
1283 .validate_ref_ty,
1258 => false,1284 => false,
12591285
1260 .@"break",1286 .@"break",
...@@ -1307,10 +1333,6 @@ pub const Inst = struct {...@@ -1307,10 +1333,6 @@ pub const Inst = struct {
1307 .store_node,1333 .store_node,
1308 .store_to_inferred_ptr,1334 .store_to_inferred_ptr,
1309 .resolve_inferred_alloc,1335 .resolve_inferred_alloc,
1310 .validate_array_init_ty,
1311 .validate_struct_init_ty,
1312 .validate_struct_init,
1313 .validate_array_init,
1314 .validate_deref,1336 .validate_deref,
1315 .validate_destructure,1337 .validate_destructure,
1316 .@"export",1338 .@"export",
...@@ -1323,6 +1345,13 @@ pub const Inst = struct {...@@ -1323,6 +1345,13 @@ pub const Inst = struct {
1323 .defer_err_code,1345 .defer_err_code,
1324 .restore_err_ret_index,1346 .restore_err_ret_index,
1325 .save_err_ret_index,1347 .save_err_ret_index,
1348 .validate_struct_init_ty,
1349 .validate_struct_init_result_ty,
1350 .validate_ptr_struct_init,
1351 .validate_array_init_ty,
1352 .validate_array_init_result_ty,
1353 .validate_ptr_array_init,
1354 .validate_ref_ty,
1326 => true,1355 => true,
13271356
1328 .param,1357 .param,
...@@ -1346,7 +1375,6 @@ pub const Inst = struct {...@@ -1346,7 +1375,6 @@ pub const Inst = struct {
1346 .array_type,1375 .array_type,
1347 .array_type_sentinel,1376 .array_type_sentinel,
1348 .vector_type,1377 .vector_type,
1349 .elem_type_index,
1350 .elem_type,1378 .elem_type,
1351 .indexable_ptr_elem_type,1379 .indexable_ptr_elem_type,
1352 .vector_elem_type,1380 .vector_elem_type,
...@@ -1374,7 +1402,6 @@ pub const Inst = struct {...@@ -1374,7 +1402,6 @@ pub const Inst = struct {
1374 .cmp_gte,1402 .cmp_gte,
1375 .cmp_gt,1403 .cmp_gt,
1376 .cmp_neq,1404 .cmp_neq,
1377 .coerce_result_ptr,
1378 .error_set_decl,1405 .error_set_decl,
1379 .error_set_decl_anon,1406 .error_set_decl_anon,
1380 .error_set_decl_func,1407 .error_set_decl_func,
...@@ -1385,11 +1412,9 @@ pub const Inst = struct {...@@ -1385,11 +1412,9 @@ pub const Inst = struct {
1385 .elem_ptr,1412 .elem_ptr,
1386 .elem_val,1413 .elem_val,
1387 .elem_ptr_node,1414 .elem_ptr_node,
1388 .elem_ptr_imm,
1389 .elem_val_node,1415 .elem_val_node,
1390 .elem_val_imm,1416 .elem_val_imm,
1391 .field_ptr,1417 .field_ptr,
1392 .field_ptr_init,
1393 .field_val,1418 .field_val,
1394 .field_ptr_named,1419 .field_ptr_named,
1395 .field_val_named,1420 .field_val_named,
...@@ -1447,19 +1472,7 @@ pub const Inst = struct {...@@ -1447,19 +1472,7 @@ pub const Inst = struct {
1447 .typeof_log2_int_type,1472 .typeof_log2_int_type,
1448 .switch_block,1473 .switch_block,
1449 .switch_block_ref,1474 .switch_block_ref,
1450 .array_base_ptr,
1451 .field_base_ptr,
1452 .struct_init_empty,
1453 .struct_init,
1454 .struct_init_ref,
1455 .struct_init_anon,
1456 .struct_init_anon_ref,
1457 .array_init,
1458 .array_init_anon,
1459 .array_init_ref,
1460 .array_init_anon_ref,
1461 .union_init,1475 .union_init,
1462 .field_type,
1463 .field_type_ref,1476 .field_type_ref,
1464 .enum_from_int,1477 .enum_from_int,
1465 .int_from_enum,1478 .int_from_enum,
...@@ -1546,7 +1559,22 @@ pub const Inst = struct {...@@ -1546,7 +1559,22 @@ pub const Inst = struct {
1546 .for_len,1559 .for_len,
1547 .@"try",1560 .@"try",
1548 .try_ptr,1561 .try_ptr,
1549 .opt_eu_base_ty,1562 .opt_eu_base_ptr_init,
1563 .coerce_ptr_elem_ty,
1564 .struct_init_empty,
1565 .struct_init_empty_result,
1566 .struct_init_empty_ref_result,
1567 .struct_init_anon,
1568 .struct_init,
1569 .struct_init_ref,
1570 .struct_init_field_type,
1571 .struct_init_field_ptr,
1572 .array_init_anon,
1573 .array_init,
1574 .array_init_ref,
1575 .validate_array_init_ref_ty,
1576 .array_init_elem_type,
1577 .array_init_elem_ptr,
1550 => false,1578 => false,
15511579
1552 .extended => switch (data.extended.opcode) {1580 .extended => switch (data.extended.opcode) {
...@@ -1580,7 +1608,6 @@ pub const Inst = struct {...@@ -1580,7 +1608,6 @@ pub const Inst = struct {
1580 .array_type = .pl_node,1608 .array_type = .pl_node,
1581 .array_type_sentinel = .pl_node,1609 .array_type_sentinel = .pl_node,
1582 .vector_type = .pl_node,1610 .vector_type = .pl_node,
1583 .elem_type_index = .bin,
1584 .elem_type = .un_node,1611 .elem_type = .un_node,
1585 .indexable_ptr_elem_type = .un_node,1612 .indexable_ptr_elem_type = .un_node,
1586 .vector_elem_type = .un_node,1613 .vector_elem_type = .un_node,
...@@ -1612,7 +1639,6 @@ pub const Inst = struct {...@@ -1612,7 +1639,6 @@ pub const Inst = struct {
1612 .cmp_gte = .pl_node,1639 .cmp_gte = .pl_node,
1613 .cmp_gt = .pl_node,1640 .cmp_gt = .pl_node,
1614 .cmp_neq = .pl_node,1641 .cmp_neq = .pl_node,
1615 .coerce_result_ptr = .pl_node,
1616 .condbr = .pl_node,1642 .condbr = .pl_node,
1617 .condbr_inline = .pl_node,1643 .condbr_inline = .pl_node,
1618 .@"try" = .pl_node,1644 .@"try" = .pl_node,
...@@ -1631,7 +1657,6 @@ pub const Inst = struct {...@@ -1631,7 +1657,6 @@ pub const Inst = struct {
1631 .div = .pl_node,1657 .div = .pl_node,
1632 .elem_ptr = .pl_node,1658 .elem_ptr = .pl_node,
1633 .elem_ptr_node = .pl_node,1659 .elem_ptr_node = .pl_node,
1634 .elem_ptr_imm = .pl_node,
1635 .elem_val = .pl_node,1660 .elem_val = .pl_node,
1636 .elem_val_node = .pl_node,1661 .elem_val_node = .pl_node,
1637 .elem_val_imm = .elem_val_imm,1662 .elem_val_imm = .elem_val_imm,
...@@ -1643,7 +1668,6 @@ pub const Inst = struct {...@@ -1643,7 +1668,6 @@ pub const Inst = struct {
1643 .@"export" = .pl_node,1668 .@"export" = .pl_node,
1644 .export_value = .pl_node,1669 .export_value = .pl_node,
1645 .field_ptr = .pl_node,1670 .field_ptr = .pl_node,
1646 .field_ptr_init = .pl_node,
1647 .field_val = .pl_node,1671 .field_val = .pl_node,
1648 .field_ptr_named = .pl_node,1672 .field_ptr_named = .pl_node,
1649 .field_val_named = .pl_node,1673 .field_val_named = .pl_node,
...@@ -1701,30 +1725,16 @@ pub const Inst = struct {...@@ -1701,30 +1725,16 @@ pub const Inst = struct {
1701 .enum_literal = .str_tok,1725 .enum_literal = .str_tok,
1702 .switch_block = .pl_node,1726 .switch_block = .pl_node,
1703 .switch_block_ref = .pl_node,1727 .switch_block_ref = .pl_node,
1704 .array_base_ptr = .un_node,
1705 .field_base_ptr = .un_node,
1706 .opt_eu_base_ty = .un_node,
1707 .validate_array_init_ty = .pl_node,
1708 .validate_struct_init_ty = .un_node,
1709 .validate_struct_init = .pl_node,
1710 .validate_array_init = .pl_node,
1711 .validate_deref = .un_node,1728 .validate_deref = .un_node,
1712 .validate_destructure = .pl_node,1729 .validate_destructure = .pl_node,
1713 .struct_init_empty = .un_node,
1714 .field_type = .pl_node,
1715 .field_type_ref = .pl_node,1730 .field_type_ref = .pl_node,
1716 .struct_init = .pl_node,
1717 .struct_init_ref = .pl_node,
1718 .struct_init_anon = .pl_node,
1719 .struct_init_anon_ref = .pl_node,
1720 .array_init = .pl_node,
1721 .array_init_anon = .pl_node,
1722 .array_init_ref = .pl_node,
1723 .array_init_anon_ref = .pl_node,
1724 .union_init = .pl_node,1731 .union_init = .pl_node,
1725 .type_info = .un_node,1732 .type_info = .un_node,
1726 .size_of = .un_node,1733 .size_of = .un_node,
1727 .bit_size_of = .un_node,1734 .bit_size_of = .un_node,
1735 .opt_eu_base_ptr_init = .un_node,
1736 .coerce_ptr_elem_ty = .pl_node,
1737 .validate_ref_ty = .un_tok,
17281738
1729 .int_from_ptr = .un_node,1739 .int_from_ptr = .un_node,
1730 .compile_error = .un_node,1740 .compile_error = .un_node,
...@@ -1826,6 +1836,27 @@ pub const Inst = struct {...@@ -1826,6 +1836,27 @@ pub const Inst = struct {
1826 .save_err_ret_index = .save_err_ret_index,1836 .save_err_ret_index = .save_err_ret_index,
1827 .restore_err_ret_index = .restore_err_ret_index,1837 .restore_err_ret_index = .restore_err_ret_index,
18281838
1839 .struct_init_empty = .un_node,
1840 .struct_init_empty_result = .un_node,
1841 .struct_init_empty_ref_result = .un_node,
1842 .struct_init_anon = .pl_node,
1843 .struct_init = .pl_node,
1844 .struct_init_ref = .pl_node,
1845 .validate_struct_init_ty = .un_node,
1846 .validate_struct_init_result_ty = .un_node,
1847 .validate_ptr_struct_init = .pl_node,
1848 .struct_init_field_type = .pl_node,
1849 .struct_init_field_ptr = .pl_node,
1850 .array_init_anon = .pl_node,
1851 .array_init = .pl_node,
1852 .array_init_ref = .pl_node,
1853 .validate_array_init_ty = .pl_node,
1854 .validate_array_init_result_ty = .pl_node,
1855 .validate_array_init_ref_ty = .pl_node,
1856 .validate_ptr_array_init = .pl_node,
1857 .array_init_elem_type = .bin,
1858 .array_init_elem_ptr = .pl_node,
1859
1829 .extended = .extended,1860 .extended = .extended,
1830 });1861 });
1831 };1862 };
...@@ -2771,6 +2802,11 @@ pub const Inst = struct {...@@ -2771,6 +2802,11 @@ pub const Inst = struct {
2771 };2802 };
2772 };2803 };
27732804
2805 pub const ArrayInitRefTy = struct {
2806 ptr_ty: Ref,
2807 elem_count: u32,
2808 };
2809
2774 pub const Field = struct {2810 pub const Field = struct {
2775 lhs: Ref,2811 lhs: Ref,
2776 /// Offset into `string_bytes`.2812 /// Offset into `string_bytes`.
...@@ -3064,9 +3100,10 @@ pub const Inst = struct {...@@ -3064,9 +3100,10 @@ pub const Inst = struct {
3064 fields_len: u32,3100 fields_len: u32,
30653101
3066 pub const Item = struct {3102 pub const Item = struct {
3067 /// The `field_type` ZIR instruction for this field init.3103 /// The `struct_init_field_type` ZIR instruction for this field init.
3068 field_type: Index,3104 field_type: Index,
3069 /// The field init expression to be used as the field value.3105 /// The field init expression to be used as the field value. This value will be coerced
3106 /// to the field type if not already.
3070 init: Ref,3107 init: Ref,
3071 };3108 };
3072 };3109 };
src/print_zir.zig+51-29
...@@ -205,8 +205,6 @@ const Writer = struct {...@@ -205,8 +205,6 @@ const Writer = struct {
205 .store_to_inferred_ptr,205 .store_to_inferred_ptr,
206 => try self.writeBin(stream, inst),206 => try self.writeBin(stream, inst),
207207
208 .elem_type_index => try self.writeElemTypeIndex(stream, inst),
209
210 .alloc,208 .alloc,
211 .alloc_mut,209 .alloc_mut,
212 .alloc_comptime_mut,210 .alloc_comptime_mut,
...@@ -241,7 +239,6 @@ const Writer = struct {...@@ -241,7 +239,6 @@ const Writer = struct {
241 .is_non_err_ptr,239 .is_non_err_ptr,
242 .ret_is_non_err,240 .ret_is_non_err,
243 .typeof,241 .typeof,
244 .struct_init_empty,
245 .type_info,242 .type_info,
246 .size_of,243 .size_of,
247 .bit_size_of,244 .bit_size_of,
...@@ -281,18 +278,16 @@ const Writer = struct {...@@ -281,18 +278,16 @@ const Writer = struct {
281 .bit_reverse,278 .bit_reverse,
282 .@"resume",279 .@"resume",
283 .@"await",280 .@"await",
284 .array_base_ptr,
285 .field_base_ptr,
286 .validate_struct_init_ty,
287 .make_ptr_const,281 .make_ptr_const,
288 .validate_deref,282 .validate_deref,
289 .check_comptime_control_flow,283 .check_comptime_control_flow,
290 .opt_eu_base_ty,284 .opt_eu_base_ptr_init,
291 => try self.writeUnNode(stream, inst),285 => try self.writeUnNode(stream, inst),
292286
293 .ref,287 .ref,
294 .ret_implicit,288 .ret_implicit,
295 .closure_capture,289 .closure_capture,
290 .validate_ref_ty,
296 => try self.writeUnTok(stream, inst),291 => try self.writeUnTok(stream, inst),
297292
298 .bool_br_and,293 .bool_br_and,
...@@ -300,7 +295,6 @@ const Writer = struct {...@@ -300,7 +295,6 @@ const Writer = struct {
300 => try self.writeBoolBr(stream, inst),295 => try self.writeBoolBr(stream, inst),
301296
302 .validate_destructure => try self.writeValidateDestructure(stream, inst),297 .validate_destructure => try self.writeValidateDestructure(stream, inst),
303 .validate_array_init_ty => try self.writeValidateArrayInitTy(stream, inst),
304 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),298 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
305 .ptr_type => try self.writePtrType(stream, inst),299 .ptr_type => try self.writePtrType(stream, inst),
306 .int => try self.writeInt(stream, inst),300 .int => try self.writeInt(stream, inst),
...@@ -316,12 +310,6 @@ const Writer = struct {...@@ -316,12 +310,6 @@ const Writer = struct {
316 .@"break",310 .@"break",
317 .break_inline,311 .break_inline,
318 => try self.writeBreak(stream, inst),312 => try self.writeBreak(stream, inst),
319 .array_init,
320 .array_init_ref,
321 => try self.writeArrayInit(stream, inst),
322 .array_init_anon,
323 .array_init_anon_ref,
324 => try self.writeArrayInitAnon(stream, inst),
325313
326 .slice_start => try self.writeSliceStart(stream, inst),314 .slice_start => try self.writeSliceStart(stream, inst),
327 .slice_end => try self.writeSliceEnd(stream, inst),315 .slice_end => try self.writeSliceEnd(stream, inst),
...@@ -330,10 +318,44 @@ const Writer = struct {...@@ -330,10 +318,44 @@ const Writer = struct {
330318
331 .union_init => try self.writeUnionInit(stream, inst),319 .union_init => try self.writeUnionInit(stream, inst),
332320
321 // Struct inits
322
323 .struct_init_empty,
324 .struct_init_empty_result,
325 .struct_init_empty_ref_result,
326 => try self.writeUnNode(stream, inst),
327
328 .struct_init_anon => try self.writeStructInitAnon(stream, inst),
329
333 .struct_init,330 .struct_init,
334 .struct_init_ref,331 .struct_init_ref,
335 => try self.writeStructInit(stream, inst),332 => try self.writeStructInit(stream, inst),
336333
334 .validate_struct_init_ty,
335 .validate_struct_init_result_ty,
336 => try self.writeUnNode(stream, inst),
337
338 .validate_ptr_struct_init => try self.writeBlock(stream, inst),
339 .struct_init_field_type => try self.writeStructInitFieldType(stream, inst),
340 .struct_init_field_ptr => try self.writePlNodeField(stream, inst),
341
342 // Array inits
343
344 .array_init_anon => try self.writeArrayInitAnon(stream, inst),
345
346 .array_init,
347 .array_init_ref,
348 => try self.writeArrayInit(stream, inst),
349
350 .validate_array_init_ty,
351 .validate_array_init_result_ty,
352 => try self.writeValidateArrayInitTy(stream, inst),
353
354 .validate_array_init_ref_ty => try self.writeValidateArrayInitRefTy(stream, inst),
355 .validate_ptr_array_init => try self.writeBlock(stream, inst),
356 .array_init_elem_type => try self.writeArrayInitElemType(stream, inst),
357 .array_init_elem_ptr => try self.writeArrayInitElemPtr(stream, inst),
358
337 .atomic_load => try self.writeAtomicLoad(stream, inst),359 .atomic_load => try self.writeAtomicLoad(stream, inst),
338 .atomic_store => try self.writeAtomicStore(stream, inst),360 .atomic_store => try self.writeAtomicStore(stream, inst),
339 .atomic_rmw => try self.writeAtomicRmw(stream, inst),361 .atomic_rmw => try self.writeAtomicRmw(stream, inst),
...@@ -342,11 +364,6 @@ const Writer = struct {...@@ -342,11 +364,6 @@ const Writer = struct {
342 .field_parent_ptr => try self.writeFieldParentPtr(stream, inst),364 .field_parent_ptr => try self.writeFieldParentPtr(stream, inst),
343 .builtin_call => try self.writeBuiltinCall(stream, inst),365 .builtin_call => try self.writeBuiltinCall(stream, inst),
344366
345 .struct_init_anon,
346 .struct_init_anon_ref,
347 => try self.writeStructInitAnon(stream, inst),
348
349 .field_type => try self.writeFieldType(stream, inst),
350 .field_type_ref => try self.writeFieldTypeRef(stream, inst),367 .field_type_ref => try self.writeFieldTypeRef(stream, inst),
351368
352 .add,369 .add,
...@@ -409,16 +426,14 @@ const Writer = struct {...@@ -409,16 +426,14 @@ const Writer = struct {
409 .elem_val_node,426 .elem_val_node,
410 .elem_ptr,427 .elem_ptr,
411 .elem_val,428 .elem_val,
412 .coerce_result_ptr,
413 .array_type,429 .array_type,
430 .coerce_ptr_elem_ty,
414 => try self.writePlNodeBin(stream, inst),431 => try self.writePlNodeBin(stream, inst),
415432
416 .for_len => try self.writePlNodeMultiOp(stream, inst),433 .for_len => try self.writePlNodeMultiOp(stream, inst),
417434
418 .elem_val_imm => try self.writeElemValImm(stream, inst),435 .elem_val_imm => try self.writeElemValImm(stream, inst),
419436
420 .elem_ptr_imm => try self.writeElemPtrImm(stream, inst),
421
422 .@"export" => try self.writePlNodeExport(stream, inst),437 .@"export" => try self.writePlNodeExport(stream, inst),
423 .export_value => try self.writePlNodeExportValue(stream, inst),438 .export_value => try self.writePlNodeExportValue(stream, inst),
424439
...@@ -430,8 +445,6 @@ const Writer = struct {...@@ -430,8 +445,6 @@ const Writer = struct {
430 .block_inline,445 .block_inline,
431 .suspend_block,446 .suspend_block,
432 .loop,447 .loop,
433 .validate_struct_init,
434 .validate_array_init,
435 .c_import,448 .c_import,
436 .typeof_builtin,449 .typeof_builtin,
437 => try self.writeBlock(stream, inst),450 => try self.writeBlock(stream, inst),
...@@ -452,9 +465,8 @@ const Writer = struct {...@@ -452,9 +465,8 @@ const Writer = struct {
452 .switch_block_ref,465 .switch_block_ref,
453 => try self.writeSwitchBlock(stream, inst),466 => try self.writeSwitchBlock(stream, inst),
454467
455 .field_ptr,
456 .field_ptr_init,
457 .field_val,468 .field_val,
469 .field_ptr,
458 => try self.writePlNodeField(stream, inst),470 => try self.writePlNodeField(stream, inst),
459471
460 .field_ptr_named,472 .field_ptr_named,
...@@ -617,7 +629,7 @@ const Writer = struct {...@@ -617,7 +629,7 @@ const Writer = struct {
617 try stream.writeByte(')');629 try stream.writeByte(')');
618 }630 }
619631
620 fn writeElemTypeIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {632 fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
621 const inst_data = self.code.instructions.items(.data)[inst].bin;633 const inst_data = self.code.instructions.items(.data)[inst].bin;
622 try self.writeInstRef(stream, inst_data.lhs);634 try self.writeInstRef(stream, inst_data.lhs);
623 try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)});635 try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)});
...@@ -972,7 +984,7 @@ const Writer = struct {...@@ -972,7 +984,7 @@ const Writer = struct {
972 try stream.print(", {d})", .{inst_data.idx});984 try stream.print(", {d})", .{inst_data.idx});
973 }985 }
974986
975 fn writeElemPtrImm(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {987 fn writeArrayInitElemPtr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
976 const inst_data = self.code.instructions.items(.data)[inst].pl_node;988 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
977 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;989 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
978990
...@@ -1004,6 +1016,16 @@ const Writer = struct {...@@ -1004,6 +1016,16 @@ const Writer = struct {
1004 try self.writeSrc(stream, inst_data.src());1016 try self.writeSrc(stream, inst_data.src());
1005 }1017 }
10061018
1019 fn writeValidateArrayInitRefTy(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1020 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1021 const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data;
1022
1023 try self.writeInstRef(stream, extra.ptr_ty);
1024 try stream.writeAll(", ");
1025 try stream.print(", {}) ", .{extra.elem_count});
1026 try self.writeSrc(stream, inst_data.src());
1027 }
1028
1007 fn writeStructInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1029 fn writeStructInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1008 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1030 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1009 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);1031 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
...@@ -1134,7 +1156,7 @@ const Writer = struct {...@@ -1134,7 +1156,7 @@ const Writer = struct {
1134 try self.writeSrc(stream, inst_data.src());1156 try self.writeSrc(stream, inst_data.src());
1135 }1157 }
11361158
1137 fn writeFieldType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1159 fn writeStructInitFieldType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1138 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1160 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1139 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;1161 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
1140 try self.writeInstRef(stream, extra.container_type);1162 try self.writeInstRef(stream, extra.container_type);
src/type.zig+11
...@@ -3182,6 +3182,17 @@ pub const Type = struct {...@@ -3182,6 +3182,17 @@ pub const Type = struct {
3182 };3182 };
3183 }3183 }
31843184
3185 /// Traverses optional child types and error union payloads until the type
3186 /// is not a pointer. For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`.
3187 pub fn optEuBaseType(ty: Type, mod: *Module) Type {
3188 var cur = ty;
3189 while (true) switch (cur.zigTypeTag(mod)) {
3190 .Optional => cur = cur.optionalChild(mod),
3191 .ErrorUnion => cur = cur.errorUnionPayload(mod),
3192 else => return cur,
3193 };
3194 }
3195
3185 pub const @"u1": Type = .{ .ip_index = .u1_type };3196 pub const @"u1": Type = .{ .ip_index = .u1_type };
3186 pub const @"u8": Type = .{ .ip_index = .u8_type };3197 pub const @"u8": Type = .{ .ip_index = .u8_type };
3187 pub const @"u16": Type = .{ .ip_index = .u16_type };3198 pub const @"u16": Type = .{ .ip_index = .u16_type };
test/behavior/array.zig+34
...@@ -780,3 +780,37 @@ test "runtime side-effects in comptime-known array init" {...@@ -780,3 +780,37 @@ test "runtime side-effects in comptime-known array init" {
780 try expectEqual([4]u4{ 1, 2, 4, 8 }, init);780 try expectEqual([4]u4{ 1, 2, 4, 8 }, init);
781 try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);781 try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);
782}782}
783
784test "slice initialized through reference to anonymous array init provides result types" {
785 var my_u32: u32 = 123;
786 var my_u64: u64 = 456;
787 const foo: []const u16 = &.{
788 @intCast(my_u32),
789 @intCast(my_u64),
790 @truncate(my_u32),
791 @truncate(my_u64),
792 };
793 try std.testing.expectEqualSlices(u16, &.{ 123, 456, 123, 456 }, foo);
794}
795
796test "pointer to array initialized through reference to anonymous array init provides result types" {
797 var my_u32: u32 = 123;
798 var my_u64: u64 = 456;
799 const foo: *const [4]u16 = &.{
800 @intCast(my_u32),
801 @intCast(my_u64),
802 @truncate(my_u32),
803 @truncate(my_u64),
804 };
805 try std.testing.expectEqualSlices(u16, &.{ 123, 456, 123, 456 }, foo);
806}
807
808test "tuple initialized through reference to anonymous array init provides result types" {
809 const Tuple = struct { u64, *const u32 };
810 const foo: *const Tuple = &.{
811 @intCast(12345),
812 @ptrFromInt(0x1000),
813 };
814 try expect(foo[0] == 12345);
815 try expect(@intFromPtr(foo[1]) == 0x1000);
816}
test/behavior/cast.zig+26
...@@ -2493,3 +2493,29 @@ test "@as does not corrupt values with incompatible representations" {...@@ -2493,3 +2493,29 @@ test "@as does not corrupt values with incompatible representations" {
2493 });2493 });
2494 try std.testing.expectApproxEqAbs(@as(f32, 1.23), x, 0.001);2494 try std.testing.expectApproxEqAbs(@as(f32, 1.23), x, 0.001);
2495}2495}
2496
2497test "result information is preserved through many nested structures" {
2498 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2499 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2500 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2501 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2502 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2503 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2504
2505 const S = struct {
2506 fn doTheTest() !void {
2507 const E = error{Foo};
2508 const T = *const ?E!struct { x: ?*const E!?u8 };
2509
2510 var val: T = &.{ .x = &@truncate(0x1234) };
2511
2512 const struct_val = val.*.? catch unreachable;
2513 const int_val = (struct_val.x.?.* catch unreachable).?;
2514
2515 try expect(int_val == 0x34);
2516 }
2517 };
2518
2519 try S.doTheTest();
2520 try comptime S.doTheTest();
2521}
test/behavior/pointers.zig+18
...@@ -548,3 +548,21 @@ test "pointer to array has explicit alignment" {...@@ -548,3 +548,21 @@ test "pointer to array has explicit alignment" {
548 const casted = S.func(&bases);548 const casted = S.func(&bases);
549 try expect(casted[0].a == 2);549 try expect(casted[0].a == 2);
550}550}
551
552test "result type preserved through multiple references" {
553 const S = struct { x: u32 };
554 var my_u64: u64 = 12345;
555 const foo: *const *const *const S = &&&.{
556 .x = @intCast(my_u64),
557 };
558 try expect(foo.*.*.*.x == 12345);
559}
560
561test "result type found through optional pointer" {
562 const ptr1: ?*const u32 = &@intCast(123);
563 const ptr2: ?[]const u8 = &.{ @intCast(123), @truncate(0xABCD) };
564 try expect(ptr1.?.* == 123);
565 try expect(ptr2.?.len == 2);
566 try expect(ptr2.?[0] == 123);
567 try expect(ptr2.?[1] == 0xCD);
568}
test/behavior/struct.zig+15
...@@ -1760,3 +1760,18 @@ test "runtime side-effects in comptime-known struct init" {...@@ -1760,3 +1760,18 @@ test "runtime side-effects in comptime-known struct init" {
1760 try expectEqual(S{ .a = 1, .b = 2, .c = 4, .d = 8 }, init);1760 try expectEqual(S{ .a = 1, .b = 2, .c = 4, .d = 8 }, init);
1761 try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);1761 try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);
1762}1762}
1763
1764test "pointer to struct initialized through reference to anonymous initializer provides result types" {
1765 const S = struct { a: u8, b: u16, c: *const anyopaque };
1766 var my_u16: u16 = 0xABCD;
1767 const s: *const S = &.{
1768 // intentionally out of order
1769 .c = @ptrCast("hello"),
1770 .b = my_u16,
1771 .a = @truncate(my_u16),
1772 };
1773 try expect(s.a == 0xCD);
1774 try expect(s.b == 0xABCD);
1775 const str: *const [5]u8 = @ptrCast(s.c);
1776 try std.testing.expectEqualSlices(u8, "hello", str);
1777}
test/cases/compile_errors/anytype_param_requires_comptime.zig+2-4
...@@ -16,7 +16,5 @@ pub export fn entry() void {...@@ -16,7 +16,5 @@ pub export fn entry() void {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
19// :7:14: error: runtime-known argument passed to parameter of comptime-only type19// :7:25: error: unable to resolve comptime value
20// :9:12: note: declared here20// :7:25: note: initializer of comptime only struct must be comptime-known
21// :4:16: note: struct requires comptime because of this field
22// :4:16: note: types are not available at runtime
test/cases/compile_errors/assigning_to_struct_or_union_fields_that_are_not_optionals_with_a_function_that_returns_an_optional.zig+3-3
...@@ -18,6 +18,6 @@ export fn entry() void {...@@ -18,6 +18,6 @@ export fn entry() void {
18// backend=stage218// backend=stage2
19// target=native19// target=native
20//20//
21// :11:27: error: expected type 'u8', found '?u8'21// :11:20: error: expected type 'u8', found '?u8'
22// :11:27: note: cannot convert optional to payload type22// :11:20: note: cannot convert optional to payload type
23// :11:27: note: consider using '.?', 'orelse', or 'if'23// :11:20: note: consider using '.?', 'orelse', or 'if'
test/cases/compile_errors/cast_without_result_type_due_to_anyopaque_pointer.zig created+21
...@@ -0,0 +1,21 @@
1export fn foo() void {
2 const x: *const anyopaque = &@intCast(123);
3 _ = x;
4}
5export fn bar() void {
6 const x: *const anyopaque = &.{
7 .x = @intCast(123),
8 };
9 _ = x;
10}
11
12// error
13// backend=stage2
14// target=native
15//
16// :2:34: error: @intCast must have a known result type
17// :2:34: note: result type is unknown due to opaque pointer type
18// :2:34: note: use @as to provide explicit result type
19// :7:14: error: @intCast must have a known result type
20// :6:35: note: result type is unknown due to opaque pointer type
21// :7:14: note: use @as to provide explicit result type
test/cases/compile_errors/cast_without_result_type_due_to_generic_parameter.zig+12-4
...@@ -10,6 +10,11 @@ export fn c() void {...@@ -10,6 +10,11 @@ export fn c() void {
10export fn d() void {10export fn d() void {
11 bar(@floatFromInt(123));11 bar(@floatFromInt(123));
12}12}
13export fn f() void {
14 bar(.{
15 .x = @intCast(123),
16 });
17}
1318
14fn bar(_: anytype) void {}19fn bar(_: anytype) void {}
1520
...@@ -18,14 +23,17 @@ fn bar(_: anytype) void {}...@@ -18,14 +23,17 @@ fn bar(_: anytype) void {}
18// target=native23// target=native
19//24//
20// :2:9: error: @ptrFromInt must have a known result type25// :2:9: error: @ptrFromInt must have a known result type
21// :2:9: note: result type is unknown due to anytype parameter26// :2:8: note: result type is unknown due to anytype parameter
22// :2:9: note: use @as to provide explicit result type27// :2:9: note: use @as to provide explicit result type
23// :5:9: error: @ptrCast must have a known result type28// :5:9: error: @ptrCast must have a known result type
24// :5:9: note: result type is unknown due to anytype parameter29// :5:8: note: result type is unknown due to anytype parameter
25// :5:9: note: use @as to provide explicit result type30// :5:9: note: use @as to provide explicit result type
26// :8:9: error: @intCast must have a known result type31// :8:9: error: @intCast must have a known result type
27// :8:9: note: result type is unknown due to anytype parameter32// :8:8: note: result type is unknown due to anytype parameter
28// :8:9: note: use @as to provide explicit result type33// :8:9: note: use @as to provide explicit result type
29// :11:9: error: @floatFromInt must have a known result type34// :11:9: error: @floatFromInt must have a known result type
30// :11:9: note: result type is unknown due to anytype parameter35// :11:8: note: result type is unknown due to anytype parameter
31// :11:9: note: use @as to provide explicit result type36// :11:9: note: use @as to provide explicit result type
37// :15:14: error: @intCast must have a known result type
38// :14:8: note: result type is unknown due to anytype parameter
39// :15:14: note: use @as to provide explicit result type
test/cases/compile_errors/for_invalid_ranges.zig+2-1
...@@ -31,5 +31,6 @@ export fn e() void {...@@ -31,5 +31,6 @@ export fn e() void {
31// :2:13: error: expected type 'usize', found '*const [5:0]u8'31// :2:13: error: expected type 'usize', found '*const [5:0]u8'
32// :7:10: error: type 'usize' cannot represent integer value '-1'32// :7:10: error: type 'usize' cannot represent integer value '-1'
33// :12:10: error: expected type 'usize', found '*const [5:0]u8'33// :12:10: error: expected type 'usize', found '*const [5:0]u8'
34// :17:13: error: expected type 'usize', found '*const struct{comptime comptime_int = 97, comptime comptime_int = 98, comptime comptime_int = 99}'34// :17:13: error: expected type 'usize', found pointer
35// :17:13: note: address-of operator always returns a pointer
35// :22:20: error: overflow of integer type 'usize' with value '-1'36// :22:20: error: overflow of integer type 'usize' with value '-1'
test/cases/compile_errors/invalid_store_to_comptime_field.zig+5-4
...@@ -71,8 +71,8 @@ pub export fn entry8() void {...@@ -71,8 +71,8 @@ pub export fn entry8() void {
71// target=native71// target=native
72// backend=stage272// backend=stage2
73//73//
74// :6:19: error: value stored in comptime field does not match the default value of the field74// :6:9: error: value stored in comptime field does not match the default value of the field
75// :14:19: error: value stored in comptime field does not match the default value of the field75// :14:9: error: value stored in comptime field does not match the default value of the field
76// :19:38: error: value stored in comptime field does not match the default value of the field76// :19:38: error: value stored in comptime field does not match the default value of the field
77// :31:19: error: value stored in comptime field does not match the default value of the field77// :31:19: error: value stored in comptime field does not match the default value of the field
78// :25:29: note: default value set here78// :25:29: note: default value set here
...@@ -80,5 +80,6 @@ pub export fn entry8() void {...@@ -80,5 +80,6 @@ pub export fn entry8() void {
80// :35:29: note: default value set here80// :35:29: note: default value set here
81// :45:12: error: value stored in comptime field does not match the default value of the field81// :45:12: error: value stored in comptime field does not match the default value of the field
82// :53:25: error: value stored in comptime field does not match the default value of the field82// :53:25: error: value stored in comptime field does not match the default value of the field
83// :66:43: error: value stored in comptime field does not match the default value of the field83// :66:36: error: value stored in comptime field does not match the default value of the field
84// :59:35: error: value stored in comptime field does not match the default value of the field84// :59:30: error: value stored in comptime field does not match the default value of the field
85// :57:29: note: default value set here
test/cases/compile_errors/missing_const_in_slice_with_nested_array_type.zig+1-1
...@@ -15,4 +15,4 @@ export fn entry() void {...@@ -15,4 +15,4 @@ export fn entry() void {
15// backend=llvm15// backend=llvm
16// target=native16// target=native
17//17//
18// :4:30: error: array literal requires address-of operator (&) to coerce to slice type '[][2]f32'18// :4:26: error: array literal requires address-of operator (&) to coerce to slice type '[][2]f32'
test/cases/compile_errors/missing_else_clause.zig+3-1
...@@ -39,4 +39,6 @@ export fn entry() void {...@@ -39,4 +39,6 @@ export fn entry() void {
39// :8:25: note: type 'i32' here39// :8:25: note: type 'i32' here
40// :16:16: error: expected type 'tmp.h.T', found 'void'40// :16:16: error: expected type 'tmp.h.T', found 'void'
41// :15:15: note: struct declared here41// :15:15: note: struct declared here
42// :22:9: error: incompatible types: 'void' and 'tmp.k.T'42// :22:13: error: incompatible types: 'void' and 'tmp.k.T'
43// :22:25: note: type 'void' here
44// :24:13: note: type 'tmp.k.T' here
test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig+3-3
...@@ -16,9 +16,9 @@ comptime {...@@ -16,9 +16,9 @@ comptime {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
19// :2:29: error: expected type '[][]const u8', found '*const struct{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'19// :2:29: error: expected type '[][]const u8', found '*const [2][]const u8'
20// :2:29: note: cast discards const qualifier20// :2:29: note: cast discards const qualifier
21// :6:31: error: expected type '*[2][]const u8', found '*const struct{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'21// :6:31: error: expected type '*[2][]const u8', found '*const [2][]const u8'
22// :6:31: note: cast discards const qualifier22// :6:31: note: cast discards const qualifier
23// :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}'23// :11:19: error: expected type '*tmp.S', found '*const tmp.S'
24// :11:19: note: cast discards const qualifier24// :11:19: note: cast discards const qualifier
test/cases/compile_errors/reassign_to_array_parameter.zig+1-1
...@@ -9,4 +9,4 @@ export fn entry() void {...@@ -9,4 +9,4 @@ export fn entry() void {
9// backend=llvm9// backend=llvm
10// target=native10// target=native
11//11//
12// :2:15: error: cannot assign to constant12// :2:5: error: cannot assign to constant
test/cases/compile_errors/reassign_to_struct_parameter.zig+1-1
...@@ -12,4 +12,4 @@ export fn entry() void {...@@ -12,4 +12,4 @@ export fn entry() void {
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
15// :5:10: error: cannot assign to constant15// :5:5: error: cannot assign to constant
test/cases/compile_errors/regression_test_2980_base_type_u32_is_not_type_checked_properly_when_assigning_a_value_within_a_struct.zig+3-3
...@@ -18,6 +18,6 @@ export fn entry() void {...@@ -18,6 +18,6 @@ export fn entry() void {
18// backend=stage218// backend=stage2
19// target=native19// target=native
20//20//
21// :12:25: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'21// :12:15: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'
22// :12:25: note: cannot convert error union to payload type22// :12:15: note: cannot convert error union to payload type
23// :12:25: note: consider using 'try', 'catch', or 'if'23// :12:15: note: consider using 'try', 'catch', or 'if'
test/cases/compile_errors/result_location_incompatibility_mismatching_handle_is_ptr.zig+3-3
...@@ -15,6 +15,6 @@ pub const Container = struct {...@@ -15,6 +15,6 @@ pub const Container = struct {
15// backend=stage215// backend=stage2
16// target=native16// target=native
17//17//
18// :3:36: error: expected type 'i32', found '?i32'18// :3:23: error: expected type 'i32', found '?i32'
19// :3:36: note: cannot convert optional to payload type19// :3:23: note: cannot convert optional to payload type
20// :3:36: note: consider using '.?', 'orelse', or 'if'20// :3:23: note: consider using '.?', 'orelse', or 'if'
test/cases/compile_errors/result_location_incompatibility_mismatching_handle_is_ptr_generic_call.zig+3-3
...@@ -15,6 +15,6 @@ pub const Container = struct {...@@ -15,6 +15,6 @@ pub const Container = struct {
15// backend=stage215// backend=stage2
16// target=native16// target=native
17//17//
18// :3:36: error: expected type 'i32', found '?i32'18// :3:23: error: expected type 'i32', found '?i32'
19// :3:36: note: cannot convert optional to payload type19// :3:23: note: cannot convert optional to payload type
20// :3:36: note: consider using '.?', 'orelse', or 'if'20// :3:23: note: consider using '.?', 'orelse', or 'if'
test/cases/compile_errors/return_incompatible_generic_struct.zig+1
...@@ -18,3 +18,4 @@ export fn entry() void {...@@ -18,3 +18,4 @@ export fn entry() void {
18// :8:18: error: expected type 'tmp.A(u32)', found 'tmp.B(u32)'18// :8:18: error: expected type 'tmp.A(u32)', found 'tmp.B(u32)'
19// :5:12: note: struct declared here19// :5:12: note: struct declared here
20// :2:12: note: struct declared here20// :2:12: note: struct declared here
21// :7:11: note: function return type declared here
test/cases/compile_errors/runtime_assignment_to_comptime_struct_type.zig+2-2
...@@ -12,5 +12,5 @@ export fn f() void {...@@ -12,5 +12,5 @@ export fn f() void {
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
15// :7:29: error: unable to resolve comptime value15// :7:23: error: unable to resolve comptime value
16// :7:29: note: initializer of comptime only struct must be comptime-known16// :7:23: note: initializer of comptime only struct must be comptime-known
test/cases/compile_errors/runtime_assignment_to_comptime_union_type.zig+2-2
...@@ -12,5 +12,5 @@ export fn f() void {...@@ -12,5 +12,5 @@ export fn f() void {
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
15// :7:29: error: unable to resolve comptime value15// :7:23: error: unable to resolve comptime value
16// :7:29: note: initializer of comptime only union must be comptime-known16// :7:23: note: initializer of comptime only union must be comptime-known
test/cases/compile_errors/shift_amount_has_to_be_an_integer_type.zig+2-1
...@@ -7,4 +7,5 @@ export fn entry() void {...@@ -7,4 +7,5 @@ export fn entry() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:20: error: expected type 'comptime_int', found '*const u8'10// :2:20: error: expected type 'comptime_int', found pointer
11// :2:20: note: address-of operator always returns a pointer
test/cases/compile_errors/slice_sentinel_mismatch-1.zig+10-3
...@@ -1,11 +1,18 @@...@@ -1,11 +1,18 @@
1export fn entry() void {1export fn entry1() void {
2 const y: [:1]const u8 = &[_:2]u8{ 1, 2 };2 const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
3 _ = y;3 _ = y;
4}4}
5export fn entry2() void {
6 const x: [:2]const u8 = &.{ 1, 2 };
7 const y: [:1]const u8 = x;
8 _ = y;
9}
510
6// error11// error
7// backend=stage212// backend=stage2
8// target=native13// target=native
9//14//
10// :2:29: error: expected type '[:1]const u8', found '*const [2:2]u8'15// :2:37: error: expected type '[2:1]u8', found '[2:2]u8'
11// :2:29: note: pointer sentinel '2' cannot cast into pointer sentinel '1'16// :2:37: note: array sentinel '2' cannot cast into array sentinel '1'
17// :7:29: error: expected type '[:1]const u8', found '[:2]const u8'
18// :7:29: note: pointer sentinel '2' cannot cast into pointer sentinel '1'
test/cases/compile_errors/union_init_with_none_or_multiple_fields.zig-1
...@@ -28,7 +28,6 @@ export fn u2m() void {...@@ -28,7 +28,6 @@ export fn u2m() void {
28// target=native28// target=native
29//29//
30// :10:20: error: union initializer must initialize one field30// :10:20: error: union initializer must initialize one field
31// :1:12: note: union declared here
32// :14:20: error: cannot initialize multiple union fields at once; unions can only have one active field31// :14:20: error: cannot initialize multiple union fields at once; unions can only have one active field
33// :14:31: note: additional initializer here32// :14:31: note: additional initializer here
34// :1:12: note: union declared here33// :1:12: note: union declared here
test/cases/compile_errors/union_noreturn_field_initialized.zig+1-1
...@@ -32,7 +32,7 @@ pub export fn entry3() void {...@@ -32,7 +32,7 @@ pub export fn entry3() void {
32// backend=stage232// backend=stage2
33// target=native33// target=native
34//34//
35// :11:21: error: cannot initialize 'noreturn' field of union35// :11:14: error: cannot initialize 'noreturn' field of union
36// :4:9: note: field 'b' declared here36// :4:9: note: field 'b' declared here
37// :2:15: note: union declared here37// :2:15: note: union declared here
38// :19:10: error: cannot initialize 'noreturn' field of union38// :19:10: error: cannot initialize 'noreturn' field of union
test/cases/compile_errors/wrong_types_given_to_export.zig+1-1
...@@ -7,5 +7,5 @@ comptime {...@@ -7,5 +7,5 @@ comptime {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :3:51: error: expected type 'builtin.GlobalLinkage', found 'u32'10// :3:41: error: expected type 'builtin.GlobalLinkage', found 'u32'
11// :?:?: note: enum declared here11// :?:?: note: enum declared here
test/compile_errors.zig+2-4
...@@ -207,10 +207,8 @@ pub fn addCases(ctx: *Cases) !void {...@@ -207,10 +207,8 @@ pub fn addCases(ctx: *Cases) !void {
207 ":1:38: note: declared comptime here",207 ":1:38: note: declared comptime here",
208 ":8:36: error: runtime-known argument passed to comptime parameter",208 ":8:36: error: runtime-known argument passed to comptime parameter",
209 ":2:41: note: declared comptime here",209 ":2:41: note: declared comptime here",
210 ":13:29: error: runtime-known argument passed to parameter of comptime-only type",210 ":13:32: error: unable to resolve comptime value",
211 ":3:24: note: declared here",211 ":13:32: note: initializer of comptime only struct must be comptime-known",
212 ":12:35: note: struct requires comptime because of this field",
213 ":12:35: note: types are not available at runtime",
214 });212 });
215213
216 case.addSourceFile("import.zig",214 case.addSourceFile("import.zig",