authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-24 15:19:48-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-09-24 15:19:48-07:00
logdf5f0517b33b5f7bc2a508cf6a0ee62246f02d21
tree64d664b74afd6d100be328b7225b87753bf62fd7
parenta9f25c7d642ec0ed047ae9be6ad87d102f3f75c8
parent9ff872c9829c20cb16d233534248c5cf371a8bd9
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17205 from mlugg/rls-ref

compiler: preserve result type information through address-of operator

39 files changed, 1335 insertions(+), 1029 deletions(-)

lib/std/debug.zig+6-1
......@@ -514,7 +514,12 @@ pub const StackIterator = struct {
514514
515515 return StackIterator{
516516 .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 },
518523 };
519524 }
520525
src/AstGen.zig+318-305
......@@ -265,14 +265,17 @@ const ResultInfo = struct {
265265 discard,
266266 /// The expression has an inferred type, and it will be evaluated as an rvalue.
267267 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,
271268 /// The expression will be coerced into this type, but it will be evaluated as an rvalue.
272269 ty: Zir.Inst.Ref,
273270 /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion,
274271 /// so no `as` instruction needs to be emitted.
275272 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,
276279 /// The expression must store its result into this typed pointer. The result instruction
277280 /// from the expression must be ignored.
278281 ptr: PtrResultLoc,
......@@ -303,26 +306,30 @@ const ResultInfo = struct {
303306 /// Find the result type for a cast builtin given the result location.
304307 /// If the location does not have a known result type, emits an error on
305308 /// the given node.
306 fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref {
307 const astgen = gz.astgen;
308 switch (rl) {
309 .discard, .none, .ref, .inferred_ptr => {},
310 .ty, .coerced_ty => |ty_ref| return ty_ref,
309 fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref {
310 return switch (rl) {
311 .discard, .none, .ref, .inferred_ptr, .destructure => null,
312 .ty, .coerced_ty => |ty_ref| ty_ref,
313 .ref_coerced_ty => |ptr_ty| try gz.addUnNode(.elem_type, ptr_ty, node),
311314 .ptr => |ptr| {
312315 const ptr_ty = try gz.addUnNode(.typeof, ptr.inst, node);
313 return 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 });
316 return try gz.addUnNode(.elem_type, ptr_ty, node);
320317 },
321 }
318 };
319 }
322320
323 return astgen.failNodeNotes(node, "{s} must have a known result type", .{builtin_name}, &.{
324 try astgen.errNoteNode(node, "use @as to provide explicit result type", .{}),
325 });
321 fn resultTypeForCast(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref {
322 const astgen = gz.astgen;
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 }
326333 }
327334 };
328335
......@@ -933,7 +940,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
933940 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
934941 _ = try gz.addUnNode(.validate_deref, lhs, node);
935942 switch (ri.rl) {
936 .ref => return lhs,
943 .ref, .ref_coerced_ty => return lhs,
937944 else => {
938945 const result = try gz.addUnNode(.load, lhs, node);
939946 return rvalue(gz, ri, result, node);
......@@ -941,7 +948,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
941948 }
942949 },
943950 .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);
945956 return rvalue(gz, ri, result, node);
946957 },
947958 .optional_type => {
......@@ -950,7 +961,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
950961 return rvalue(gz, ri, result, node);
951962 },
952963 .unwrap_optional => switch (ri.rl) {
953 .ref => {
964 .ref, .ref_coerced_ty => {
954965 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
955966
956967 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
......@@ -1001,7 +1012,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10011012 else
10021013 null;
10031014 switch (ri.rl) {
1004 .ref => return orelseCatchExpr(
1015 .ref, .ref_coerced_ty => return orelseCatchExpr(
10051016 gz,
10061017 scope,
10071018 ri,
......@@ -1028,7 +1039,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10281039 }
10291040 },
10301041 .@"orelse" => switch (ri.rl) {
1031 .ref => return orelseCatchExpr(
1042 .ref, .ref_coerced_ty => return orelseCatchExpr(
10321043 gz,
10331044 scope,
10341045 ri,
......@@ -1432,73 +1443,75 @@ fn arrayInitExpr(
14321443 break :inst .{ array_type_inst, .none };
14331444 };
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
14351477 switch (ri.rl) {
1478 .none => return arrayInitExprAnon(gz, scope, node, array_init.ast.elements),
14361479 .discard => {
1437 if (elem_ty != .none) {
1438 const elem_ri: ResultInfo = .{ .rl = .{ .ty = elem_ty } };
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 }
1480 for (array_init.ast.elements) |elem_init| {
1481 _ = try expr(gz, scope, .{ .rl = .discard }, elem_init);
14571482 }
14581483 return Zir.Inst.Ref.void_value;
14591484 },
14601485 .ref => {
1461 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init_ref else .array_init_anon_ref;
1462 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, tag);
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);
1486 const result = try arrayInitExprAnon(gz, scope, node, array_init.ast.elements);
1487 return gz.addUnTok(.ref, result, tree.firstToken(node));
14791488 },
1480 .ptr => |ptr_res| {
1481 return arrayInitExprRlPtr(gz, scope, node, ptr_res.inst, array_init.ast.elements, array_ty);
1482 },
1483 .inferred_ptr => |ptr_inst| {
1484 if (array_ty == .none) {
1485 // We treat this case differently so that we don't get a crash when
1486 // analyzing array_base_ptr against an alloc_inferred_mut.
1487 // See corresponding logic in structInitExpr.
1488 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1489 return rvalue(gz, ri, result, node);
1490 } else {
1491 return arrayInitExprRlPtr(gz, scope, node, ptr_inst, array_init.ast.elements, array_ty);
1492 }
1489 .ref_coerced_ty => |ptr_ty_inst| {
1490 const dest_arr_ty_inst = try gz.addPlNode(.validate_array_init_ref_ty, node, Zir.Inst.ArrayInitRefTy{
1491 .ptr_ty = ptr_ty_inst,
1492 .elem_count = @intCast(array_init.ast.elements.len),
1493 });
1494 return arrayInitExprTyped(gz, scope, node, array_init.ast.elements, dest_arr_ty_inst, .none, true);
1495 },
1496 .ty, .coerced_ty => |result_ty_inst| {
1497 _ = try gz.addPlNode(.validate_array_init_result_ty, node, Zir.Inst.ArrayInit{
1498 .ty = result_ty_inst,
1499 .init_count = @intCast(array_init.ast.elements.len),
1500 });
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);
14931513 },
14941514 .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 }
15021515 // Untyped init - destructure directly into result pointers
15031516 if (array_init.ast.elements.len != destructure.components.len) {
15041517 return astgen.failNodeNotes(node, "expected {} elements for destructure, found {}", .{
......@@ -1521,12 +1534,12 @@ fn arrayInitExpr(
15211534 }
15221535}
15231536
1524fn arrayInitExprRlNone(
1537/// An array initialization expression using an `array_init_anon` instruction.
1538fn arrayInitExprAnon(
15251539 gz: *GenZir,
15261540 scope: *Scope,
15271541 node: Ast.Node.Index,
15281542 elements: []const Ast.Node.Index,
1529 tag: Zir.Inst.Tag,
15301543) InnerError!Zir.Inst.Ref {
15311544 const astgen = gz.astgen;
15321545
......@@ -1540,95 +1553,84 @@ fn arrayInitExprRlNone(
15401553 astgen.extra.items[extra_index] = @intFromEnum(elem_ref);
15411554 extra_index += 1;
15421555 }
1543 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
1556 return try gz.addPlNodePayloadIndex(.array_init_anon, node, payload_index);
15441557}
15451558
1546fn arrayInitExprInner(
1559/// An array initialization expression using an `array_init` or `array_init_ref` instruction.
1560fn arrayInitExprTyped(
15471561 gz: *GenZir,
15481562 scope: *Scope,
15491563 node: Ast.Node.Index,
15501564 elements: []const Ast.Node.Index,
1551 array_ty_inst: Zir.Inst.Ref,
1552 elem_ty: Zir.Inst.Ref,
1553 tag: Zir.Inst.Tag,
1565 ty_inst: Zir.Inst.Ref,
1566 maybe_elem_ty_inst: Zir.Inst.Ref,
1567 is_ref: bool,
15541568) InnerError!Zir.Inst.Ref {
15551569 const astgen = gz.astgen;
15561570
1557 const len = elements.len + @intFromBool(array_ty_inst != .none);
1571 const len = elements.len + 1; // +1 for type
15581572 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
15591573 .operands_len = @intCast(len),
15601574 });
15611575 var extra_index = try reserveExtra(astgen, len);
1562 if (array_ty_inst != .none) {
1563 astgen.extra.items[extra_index] = @intFromEnum(array_ty_inst);
1564 extra_index += 1;
1565 }
1576 astgen.extra.items[extra_index] = @intFromEnum(ty_inst);
1577 extra_index += 1;
15661578
1567 for (elements, 0..) |elem_init, i| {
1568 const ri = if (elem_ty != .none)
1569 ResultInfo{ .rl = .{ .coerced_ty = elem_ty } }
1570 else if (array_ty_inst != .none) ri: {
1571 const ty_expr = try gz.add(.{
1572 .tag = .elem_type_index,
1579 if (maybe_elem_ty_inst != .none) {
1580 const elem_ri: ResultInfo = .{ .rl = .{ .coerced_ty = maybe_elem_ty_inst } };
1581 for (elements) |elem_init| {
1582 const elem_inst = try expr(gz, scope, elem_ri, elem_init);
1583 astgen.extra.items[extra_index] = @intFromEnum(elem_inst);
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,
15731590 .data = .{ .bin = .{
1574 .lhs = array_ty_inst,
1591 .lhs = ty_inst,
15751592 .rhs = @enumFromInt(i),
15761593 } },
1577 });
1578 break :ri ResultInfo{ .rl = .{ .coerced_ty = ty_expr } };
1579 } else ResultInfo{ .rl = .{ .none = {} } };
1594 }) } };
15801595
1581 const elem_ref = try expr(gz, scope, ri, elem_init);
1582 astgen.extra.items[extra_index] = @intFromEnum(elem_ref);
1583 extra_index += 1;
1596 const elem_inst = try expr(gz, scope, ri, elem_init);
1597 astgen.extra.items[extra_index] = @intFromEnum(elem_inst);
1598 extra_index += 1;
1599 }
15841600 }
15851601
1602 const tag: Zir.Inst.Tag = if (is_ref) .array_init_ref else .array_init;
15861603 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
15871604}
15881605
1589fn arrayInitExprRlPtr(
1606/// An array initialization expression using element pointers.
1607fn arrayInitExprPtr(
15901608 gz: *GenZir,
15911609 scope: *Scope,
15921610 node: Ast.Node.Index,
1593 result_ptr: Zir.Inst.Ref,
15941611 elements: []const Ast.Node.Index,
1595 array_ty: Zir.Inst.Ref,
1596) InnerError!Zir.Inst.Ref {
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 {
1612 ptr_inst: Zir.Inst.Ref,
1613) InnerError!void {
16131614 const astgen = gz.astgen;
16141615
1616 const array_ptr_inst = try gz.addUnNode(.opt_eu_base_ptr_init, ptr_inst, node);
1617
16151618 const payload_index = try addExtra(astgen, Zir.Inst.Block{
16161619 .body_len = @intCast(elements.len),
16171620 });
16181621 var extra_index = try reserveExtra(astgen, elements.len);
16191622
16201623 for (elements, 0..) |elem_init, i| {
1621 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{
1622 .ptr = result_ptr,
1624 const elem_ptr_inst = try gz.addPlNode(.array_init_elem_ptr, elem_init, Zir.Inst.ElemPtrImm{
1625 .ptr = array_ptr_inst,
16231626 .index = @intCast(i),
16241627 });
1625 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;
1628 astgen.extra.items[extra_index] = refToIndex(elem_ptr_inst).?;
16261629 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);
16281631 }
16291632
1630 _ = try gz.addPlNodePayloadIndex(.validate_array_init, node, payload_index);
1631 return .void_value;
1633 _ = try gz.addPlNodePayloadIndex(.validate_ptr_array_init, node, payload_index);
16321634}
16331635
16341636fn structInitExpr(
......@@ -1643,7 +1645,26 @@ fn structInitExpr(
16431645
16441646 if (struct_init.ast.type_expr == 0) {
16451647 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 }
16471668 }
16481669 } else array: {
16491670 const node_tags = tree.nodes.items(.tag);
......@@ -1694,86 +1715,67 @@ fn structInitExpr(
16941715 }
16951716 }
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
16971731 switch (ri.rl) {
1732 .none => return structInitExprAnon(gz, scope, node, struct_init),
16981733 .discard => {
1699 if (struct_init.ast.type_expr != 0) {
1700 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1701 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
1702 _ = try structInitExprRlTy(gz, scope, node, struct_init, ty_inst, .struct_init);
1703 } else {
1704 _ = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);
1705 }
1706 return Zir.Inst.Ref.void_value;
1734 // Even if discarding we must perform an anonymous init to check for duplicate field names.
1735 // TODO: should duplicate field names be caught in AstGen?
1736 _ = try structInitExprAnon(gz, scope, node, struct_init);
1737 return .void_value;
17071738 },
17081739 .ref => {
1709 if (struct_init.ast.type_expr != 0) {
1710 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
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 }
1740 const result = try structInitExprAnon(gz, scope, node, struct_init);
1741 return gz.addUnTok(.ref, result, tree.firstToken(node));
17161742 },
1717 .none => {
1718 if (struct_init.ast.type_expr != 0) {
1719 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1720 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
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 }
1743 .ref_coerced_ty => |ptr_ty_inst| {
1744 const result_ty_inst = try gz.addUnNode(.elem_type, ptr_ty_inst, node);
1745 _ = try gz.addUnNode(.validate_struct_init_result_ty, result_ty_inst, node);
1746 return structInitExprTyped(gz, scope, node, struct_init, result_ty_inst, true);
17251747 },
1726 .ty, .coerced_ty => |ty_inst| {
1727 if (struct_init.ast.type_expr == 0) {
1728 const struct_ty_inst = try gz.addUnNode(.opt_eu_base_ty, ty_inst, node);
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);
1748 .ty, .coerced_ty => |result_ty_inst| {
1749 _ = try gz.addUnNode(.validate_struct_init_result_ty, result_ty_inst, node);
1750 return structInitExprTyped(gz, scope, node, struct_init, result_ty_inst, false);
17371751 },
1738 .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, node, struct_init, ptr_res.inst),
1739 .inferred_ptr => |ptr_inst| {
1740 if (struct_init.ast.type_expr == 0) {
1741 // We treat this case differently so that we don't get a crash when
1742 // analyzing field_base_ptr against an alloc_inferred_mut.
1743 // See corresponding logic in arrayInitExpr.
1744 const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon);
1745 return rvalue(gz, ri, result, node);
1746 } else {
1747 return structInitExprRlPtr(gz, scope, node, struct_init, ptr_inst);
1748 }
1752 .ptr => |ptr| {
1753 try structInitExprPtr(gz, scope, node, struct_init, ptr.inst);
1754 return .void_value;
1755 },
1756 .inferred_ptr => {
1757 // We can't get field pointers of an untyped inferred alloc, so must perform a
1758 // standard anonymous initialization followed by an rvalue store.
1759 // See corresponding logic in arrayInitExpr.
1760 const struct_inst = try structInitExprAnon(gz, scope, node, struct_init);
1761 return rvalue(gz, ri, struct_inst, node);
17491762 },
17501763 .destructure => |destructure| {
1751 if (struct_init.ast.type_expr == 0) {
1752 // This is an untyped init, so is an actual struct, which does
1753 // not support destructuring.
1754 return astgen.failNodeNotes(node, "struct value cannot be destructured", .{}, &.{
1755 try astgen.errNoteNode(destructure.src_node, "result destructured here", .{}),
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);
1764 // This is an untyped init, so is an actual struct, which does
1765 // not support destructuring.
1766 return astgen.failNodeNotes(node, "struct value cannot be destructured", .{}, &.{
1767 try astgen.errNoteNode(destructure.src_node, "result destructured here", .{}),
1768 });
17661769 },
17671770 }
17681771}
17691772
1770fn structInitExprRlNone(
1773/// A struct initialization expression using a `struct_init_anon` instruction.
1774fn structInitExprAnon(
17711775 gz: *GenZir,
17721776 scope: *Scope,
17731777 node: Ast.Node.Index,
17741778 struct_init: Ast.full.StructInit,
1775 ty_inst: Zir.Inst.Ref,
1776 tag: Zir.Inst.Tag,
17771779) InnerError!Zir.Inst.Ref {
17781780 const astgen = gz.astgen;
17791781 const tree = astgen.tree;
......@@ -1787,104 +1789,83 @@ fn structInitExprRlNone(
17871789 for (struct_init.ast.fields) |field_init| {
17881790 const name_token = tree.firstToken(field_init) - 2;
17891791 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 };
17971792 setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{
17981793 .field_name = str_index,
1799 .init = try expr(gz, scope, sub_ri, field_init),
1794 .init = try expr(gz, scope, .{ .rl = .none }, field_init),
18001795 });
18011796 extra_index += field_size;
18021797 }
18031798
1804 return try gz.addPlNodePayloadIndex(tag, 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);
1799 return gz.addPlNodePayloadIndex(.struct_init_anon, node, payload_index);
18231800}
18241801
1825fn structInitExprRlPtrInner(
1802/// A struct initialization expression using a `struct_init` or `struct_init_ref` instruction.
1803fn structInitExprTyped(
18261804 gz: *GenZir,
18271805 scope: *Scope,
18281806 node: Ast.Node.Index,
18291807 struct_init: Ast.full.StructInit,
1830 result_ptr: Zir.Inst.Ref,
1808 ty_inst: Zir.Inst.Ref,
1809 is_ref: bool,
18311810) InnerError!Zir.Inst.Ref {
18321811 const astgen = gz.astgen;
18331812 const tree = astgen.tree;
18341813
1835 const payload_index = try addExtra(astgen, Zir.Inst.Block{
1836 .body_len = @intCast(struct_init.ast.fields.len),
1814 const payload_index = try addExtra(astgen, Zir.Inst.StructInit{
1815 .fields_len = @intCast(struct_init.ast.fields.len),
18371816 });
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
18401820 for (struct_init.ast.fields) |field_init| {
18411821 const name_token = tree.firstToken(field_init) - 2;
18421822 const str_index = try astgen.identAsString(name_token);
1843 const field_ptr = try gz.addPlNode(.field_ptr_init, field_init, Zir.Inst.Field{
1844 .lhs = result_ptr,
1845 .field_name_start = str_index,
1823 const field_ty_inst = try gz.addPlNode(.struct_init_field_type, field_init, Zir.Inst.FieldType{
1824 .container_type = ty_inst,
1825 .name_start = str_index,
18461826 });
1847 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;
1848 extra_index += 1;
1849 _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = field_ptr } } }, field_init);
1827 setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{
1828 .field_type = refToIndex(field_ty_inst).?,
1829 .init = try expr(gz, scope, .{ .rl = .{ .coerced_ty = field_ty_inst } }, field_init),
1830 });
1831 extra_index += field_size;
18501832 }
18511833
1852 _ = try gz.addPlNodePayloadIndex(.validate_struct_init, node, payload_index);
1853 return Zir.Inst.Ref.void_value;
1834 const tag: Zir.Inst.Tag = if (is_ref) .struct_init_ref else .struct_init;
1835 return gz.addPlNodePayloadIndex(tag, node, payload_index);
18541836}
18551837
1856fn structInitExprRlTy(
1838/// A struct initialization expression using field pointers.
1839fn structInitExprPtr(
18571840 gz: *GenZir,
18581841 scope: *Scope,
18591842 node: Ast.Node.Index,
18601843 struct_init: Ast.full.StructInit,
1861 ty_inst: Zir.Inst.Ref,
1862 tag: Zir.Inst.Tag,
1863) InnerError!Zir.Inst.Ref {
1844 ptr_inst: Zir.Inst.Ref,
1845) InnerError!void {
18641846 const astgen = gz.astgen;
18651847 const tree = astgen.tree;
18661848
1867 const payload_index = try addExtra(astgen, Zir.Inst.StructInit{
1868 .fields_len = @intCast(struct_init.ast.fields.len),
1849 const struct_ptr_inst = try gz.addUnNode(.opt_eu_base_ptr_init, ptr_inst, node);
1850
1851 const payload_index = try addExtra(astgen, Zir.Inst.Block{
1852 .body_len = @intCast(struct_init.ast.fields.len),
18691853 });
1870 const field_size = @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len;
1871 var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size);
1854 var extra_index = try reserveExtra(astgen, struct_init.ast.fields.len);
18721855
18731856 for (struct_init.ast.fields) |field_init| {
18741857 const name_token = tree.firstToken(field_init) - 2;
18751858 const str_index = try astgen.identAsString(name_token);
1876 const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
1877 .container_type = ty_inst,
1878 .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),
1859 const field_ptr = try gz.addPlNode(.struct_init_field_ptr, field_init, Zir.Inst.Field{
1860 .lhs = struct_ptr_inst,
1861 .field_name_start = str_index,
18831862 });
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);
18851866 }
18861867
1887 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
1868 _ = try gz.addPlNodePayloadIndex(.validate_ptr_struct_init, node, payload_index);
18881869}
18891870
18901871/// This explicitly calls expr in a comptime scope by wrapping it in a `block_comptime` if
......@@ -2314,7 +2295,7 @@ fn labeledBlockExpr(
23142295 const need_rl = astgen.nodes_need_rl.contains(block_node);
23152296 const block_ri: ResultInfo = if (need_rl) ri else .{
23162297 .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)).? },
23182299 .inferred_ptr => .none,
23192300 else => ri.rl,
23202301 },
......@@ -2504,7 +2485,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
25042485 .array_mul,
25052486 .array_type,
25062487 .array_type_sentinel,
2507 .elem_type_index,
25082488 .elem_type,
25092489 .indexable_ptr_elem_type,
25102490 .vector_elem_type,
......@@ -2531,7 +2511,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
25312511 .cmp_gte,
25322512 .cmp_gt,
25332513 .cmp_neq,
2534 .coerce_result_ptr,
25352514 .decl_ref,
25362515 .decl_val,
25372516 .load,
......@@ -2539,11 +2518,9 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
25392518 .elem_ptr,
25402519 .elem_val,
25412520 .elem_ptr_node,
2542 .elem_ptr_imm,
25432521 .elem_val_node,
25442522 .elem_val_imm,
25452523 .field_ptr,
2546 .field_ptr_init,
25472524 .field_val,
25482525 .field_ptr_named,
25492526 .field_val_named,
......@@ -2599,17 +2576,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
25992576 .import,
26002577 .switch_block,
26012578 .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,
26112579 .union_init,
2612 .field_type,
26132580 .field_type_ref,
26142581 .error_set_decl,
26152582 .error_set_decl_anon,
......@@ -2680,14 +2647,27 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
26802647 .@"await",
26812648 .ret_err_value_code,
26822649 .closure_get,
2683 .array_base_ptr,
2684 .field_base_ptr,
26852650 .ret_ptr,
26862651 .ret_type,
26872652 .for_len,
26882653 .@"try",
26892654 .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,
26912671 => break :b false,
26922672
26932673 .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
27382718 .store_node,
27392719 .store_to_inferred_ptr,
27402720 .resolve_inferred_alloc,
2741 .validate_struct_init,
2742 .validate_array_init,
27432721 .set_runtime_safety,
27442722 .closure_capture,
27452723 .memcpy,
27462724 .memset,
2747 .validate_array_init_ty,
2748 .validate_struct_init_ty,
27492725 .validate_deref,
27502726 .validate_destructure,
27512727 .save_err_ret_index,
27522728 .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,
27532736 => break :b true,
27542737
27552738 .@"defer" => unreachable,
......@@ -5635,7 +5618,7 @@ fn tryExpr(
56355618 const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
56365619
56375620 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 },
56395622 else => .{ .rl = .none, .ctx = .error_handling_expr },
56405623 };
56415624 // This could be a pointer or value depending on the `ri` parameter.
......@@ -5648,7 +5631,7 @@ fn tryExpr(
56485631 defer else_scope.unstack();
56495632
56505633 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,
56525635 else => Zir.Inst.Tag.err_union_code,
56535636 };
56545637 const err_code = try else_scope.addUnNode(err_tag, operand, node);
......@@ -5659,7 +5642,7 @@ fn tryExpr(
56595642 try else_scope.setTryBody(try_inst, operand);
56605643 const result = indexToRef(try_inst);
56615644 switch (ri.rl) {
5662 .ref => return result,
5645 .ref, .ref_coerced_ty => return result,
56635646 else => return rvalue(parent_gz, ri, result, node),
56645647 }
56655648}
......@@ -5682,7 +5665,7 @@ fn orelseCatchExpr(
56825665 const need_rl = astgen.nodes_need_rl.contains(node);
56835666 const block_ri: ResultInfo = if (need_rl) ri else .{
56845667 .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)).? },
56865669 .inferred_ptr => .none,
56875670 else => ri.rl,
56885671 },
......@@ -5700,7 +5683,7 @@ fn orelseCatchExpr(
57005683 defer block_scope.unstack();
57015684
57025685 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 },
57045687 else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none },
57055688 };
57065689 // This could be a pointer or value depending on the `operand_ri` parameter.
......@@ -5722,7 +5705,7 @@ fn orelseCatchExpr(
57225705 // This could be a pointer or value depending on `unwrap_op`.
57235706 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);
57245707 const then_result = switch (ri.rl) {
5725 .ref => unwrapped_payload,
5708 .ref, .ref_coerced_ty => unwrapped_payload,
57265709 else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node),
57275710 };
57285711 _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, node);
......@@ -5793,7 +5776,7 @@ fn fieldAccess(
57935776 node: Ast.Node.Index,
57945777) InnerError!Zir.Inst.Ref {
57955778 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),
57975780 else => {
57985781 const access = try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node);
57995782 return rvalue(gz, ri, access, node);
......@@ -5837,7 +5820,7 @@ fn arrayAccess(
58375820 const tree = gz.astgen.tree;
58385821 const node_datas = tree.nodes.items(.data);
58395822 switch (ri.rl) {
5840 .ref => {
5823 .ref, .ref_coerced_ty => {
58415824 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
58425825
58435826 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
......@@ -5951,7 +5934,7 @@ fn ifExpr(
59515934 const need_rl = astgen.nodes_need_rl.contains(node);
59525935 const block_ri: ResultInfo = if (need_rl) ri else .{
59535936 .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)).? },
59555938 .inferred_ptr => .none,
59565939 else => ri.rl,
59575940 },
......@@ -6181,7 +6164,7 @@ fn whileExpr(
61816164 const need_rl = astgen.nodes_need_rl.contains(node);
61826165 const block_ri: ResultInfo = if (need_rl) ri else .{
61836166 .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)).? },
61856168 .inferred_ptr => .none,
61866169 else => ri.rl,
61876170 },
......@@ -6455,7 +6438,7 @@ fn forExpr(
64556438 const need_rl = astgen.nodes_need_rl.contains(node);
64566439 const block_ri: ResultInfo = if (need_rl) ri else .{
64576440 .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)).? },
64596442 .inferred_ptr => .none,
64606443 else => ri.rl,
64616444 },
......@@ -6773,7 +6756,7 @@ fn switchExpr(
67736756 const need_rl = astgen.nodes_need_rl.contains(switch_node);
67746757 const block_ri: ResultInfo = if (need_rl) ri else .{
67756758 .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)).? },
67776760 .inferred_ptr => .none,
67786761 else => ri.rl,
67796762 },
......@@ -7465,7 +7448,7 @@ fn localVarRef(
74657448 gpa,
74667449 );
74677450
7468 return rvalue(gz, ri, value_inst, ident);
7451 return rvalueNoCoercePreRef(gz, ri, value_inst, ident);
74697452 }
74707453 s = local_val.parent;
74717454 },
......@@ -7498,10 +7481,10 @@ fn localVarRef(
74987481 );
74997482
75007483 switch (ri.rl) {
7501 .ref => return ptr_inst,
7484 .ref, .ref_coerced_ty => return ptr_inst,
75027485 else => {
75037486 const loaded = try gz.addUnNode(.load, ptr_inst, ident);
7504 return rvalue(gz, ri, loaded, ident);
7487 return rvalueNoCoercePreRef(gz, ri, loaded, ident);
75057488 },
75067489 }
75077490 }
......@@ -7535,10 +7518,10 @@ fn localVarRef(
75357518 // Decl references happen by name rather than ZIR index so that when unrelated
75367519 // decls are modified, ZIR code containing references to them can be unmodified.
75377520 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),
75397522 else => {
75407523 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);
75427525 },
75437526 }
75447527}
......@@ -7924,7 +7907,7 @@ fn bitCast(
79247907 node: Ast.Node.Index,
79257908 operand_node: Ast.Node.Index,
79267909) 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");
79287911 const operand = try reachableExpr(gz, scope, .{ .rl = .none }, operand_node, node);
79297912 const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{
79307913 .lhs = dest_type,
......@@ -8024,7 +8007,7 @@ fn ptrCast(
80248007 // Full cast including result type
80258008
80268009 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());
80288011 const operand = try expr(gz, scope, .{ .rl = .none }, node);
80298012 try emitDbgStmt(gz, cursor);
80308013 const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_i, Zir.Inst.BinNode{
......@@ -8208,7 +8191,7 @@ fn builtinCall(
82088191 return rvalue(gz, ri, result, node);
82098192 },
82108193 .field => {
8211 if (ri.rl == .ref) {
8194 if (ri.rl == .ref or ri.rl == .ref_coerced_ty) {
82128195 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
82138196 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
82148197 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]),
......@@ -8475,7 +8458,7 @@ fn builtinCall(
84758458 try emitDbgNode(gz, node);
84768459
84778460 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"),
84798462 .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
84808463 .node = gz.nodeIndexToRelative(node),
84818464 });
......@@ -8548,7 +8531,7 @@ fn builtinCall(
85488531 },
85498532
85508533 .splat => {
8551 const result_type = try ri.rl.resultType(gz, node, "@splat");
8534 const result_type = try ri.rl.resultTypeForCast(gz, node, "@splat");
85528535 const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);
85538536 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
85548537 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
......@@ -8810,7 +8793,7 @@ fn typeCast(
88108793 builtin_name: []const u8,
88118794) InnerError!Zir.Inst.Ref {
88128795 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);
88148797 const operand = try expr(gz, scope, .{ .rl = .none }, operand_node);
88158798
88168799 try emitDbgStmt(gz, cursor);
......@@ -10069,6 +10052,29 @@ fn rvalue(
1006910052 ri: ResultInfo,
1007010053 raw_result: Zir.Inst.Ref,
1007110054 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,
1007210078) InnerError!Zir.Inst.Ref {
1007310079 const result = r: {
1007410080 if (refToIndex(raw_result)) |result_index| {
......@@ -10088,7 +10094,14 @@ fn rvalue(
1008810094 _ = try gz.addUnNode(.ensure_result_non_error, result, src_node);
1008910095 return .void_value;
1009010096 },
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;
1009210105 // We need a pointer but we have a value.
1009310106 // Unfortunately it's not quite as simple as directly emitting a ref
1009410107 // instruction here because we need subsequent address-of operator on
......@@ -10096,14 +10109,14 @@ fn rvalue(
1009610109 const astgen = gz.astgen;
1009710110 const tree = astgen.tree;
1009810111 const src_token = tree.firstToken(src_node);
10099 const result_index = refToIndex(result) orelse
10100 return gz.addUnTok(.ref, result, src_token);
10112 const result_index = refToIndex(coerced_result) orelse
10113 return gz.addUnTok(.ref, coerced_result, src_token);
1010110114 const zir_tags = gz.astgen.instructions.items(.tag);
10102 if (zir_tags[result_index].isParam() or astgen.isInferred(result))
10103 return gz.addUnTok(.ref, result, src_token);
10115 if (zir_tags[result_index].isParam() or astgen.isInferred(coerced_result))
10116 return gz.addUnTok(.ref, coerced_result, src_token);
1010410117 const gop = try astgen.ref_table.getOrPut(astgen.gpa, result_index);
1010510118 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);
1010710120 }
1010810121 return indexToRef(gop.value_ptr.*);
1010910122 },
src/AstRlAnnotate.zig+26-18
......@@ -669,17 +669,21 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
669669 => {
670670 var buf: [2]Ast.Node.Index = undefined;
671671 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
673675 _ = 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 };
681676 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);
683687 }
684688 return ri.have_ptr;
685689 } else {
......@@ -702,17 +706,21 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
702706 => {
703707 var buf: [2]Ast.Node.Index = undefined;
704708 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
706712 _ = 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 };
714713 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);
716724 }
717725 return ri.have_ptr;
718726 } else {
src/Autodoc.zig+19-34
......@@ -45,6 +45,14 @@ ref_paths_pending_on_types: std.AutoHashMapUnmanaged(
4545 std.ArrayListUnmanaged(RefPathResumeInfo),
4646) = .{},
4747
48/// A set of ZIR instruction refs which have a meaning other than the
49/// instruction they refer to. For instance, during analysis of the arguments to
50/// a `call`, the index of the `call` itself is repurposed to refer to the
51/// parameter type.
52/// TODO: there should be some kind of proper handling for these instructions;
53/// currently we just ignore them!
54repurposed_insts: std.AutoHashMapUnmanaged(Zir.Inst.Index, void) = .{},
55
4856const RefPathResumeInfo = struct {
4957 file: *File,
5058 ref_path: []DocData.Expr,
......@@ -954,6 +962,11 @@ fn walkInstruction(
954962 const tags = file.zir.instructions.items(.tag);
955963 const data = file.zir.instructions.items(.data);
956964
965 if (self.repurposed_insts.contains(@intCast(inst_index))) {
966 // TODO: better handling here
967 return .{ .expr = .{ .comptimeExpr = 0 } };
968 }
969
957970 // We assume that the topmost ast_node entry corresponds to our decl
958971 const self_ast_node_index = self.ast_nodes.items.len - 1;
959972
......@@ -2378,34 +2391,6 @@ fn walkInstruction(
23782391 .expr = .{ .@"&" = expr_index },
23792392 };
23802393 },
2381 .array_init_anon_ref => {
2382 const pl_node = data[inst_index].pl_node;
2383 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
2384 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
2385 const array_data = try self.arena.alloc(usize, operands.len);
2386
2387 for (operands, 0..) |op, idx| {
2388 const wr = try self.walkRef(
2389 file,
2390 parent_scope,
2391 parent_src,
2392 op,
2393 false,
2394 call_ctx,
2395 );
2396 const expr_index = self.exprs.items.len;
2397 try self.exprs.append(self.arena, wr.expr);
2398 array_data[idx] = expr_index;
2399 }
2400
2401 const expr_index = self.exprs.items.len;
2402 try self.exprs.append(self.arena, .{ .array = array_data });
2403
2404 return DocData.WalkResult{
2405 .typeRef = null,
2406 .expr = .{ .@"&" = expr_index },
2407 };
2408 },
24092394 .float => {
24102395 const float = data[inst_index].float;
24112396 return DocData.WalkResult{
......@@ -2696,9 +2681,7 @@ fn walkInstruction(
26962681 .expr = .{ .declRef = decl_status },
26972682 };
26982683 },
2699 .field_val, .field_ptr, .field_type => {
2700 // TODO: field type uses Zir.Inst.FieldType, it just happens to have the
2701 // same layout as Zir.Inst.Field :^)
2684 .field_val, .field_ptr => {
27022685 const pl_node = data[inst_index].pl_node;
27032686 const extra = file.zir.extraData(Zir.Inst.Field, pl_node.payload_index);
27042687
......@@ -2717,8 +2700,7 @@ fn walkInstruction(
27172700 };
27182701
27192702 if (tags[lhs] != .field_val and
2720 tags[lhs] != .field_ptr and
2721 tags[lhs] != .field_type) break :blk lhs_extra.data.lhs;
2703 tags[lhs] != .field_ptr) break :blk lhs_extra.data.lhs;
27222704
27232705 lhs_extra = file.zir.extraData(
27242706 Zir.Inst.Field,
......@@ -2857,7 +2839,7 @@ fn walkInstruction(
28572839
28582840 const field_name = blk: {
28592841 const field_inst_index = init_extra.data.field_type;
2860 if (tags[field_inst_index] != .field_type) unreachable;
2842 if (tags[field_inst_index] != .struct_init_field_type) unreachable;
28612843 const field_pl_node = data[field_inst_index].pl_node;
28622844 const field_extra = file.zir.extraData(
28632845 Zir.Inst.FieldType,
......@@ -3022,6 +3004,9 @@ fn walkInstruction(
30223004 var args = try self.arena.alloc(DocData.Expr, args_len);
30233005 const body = file.zir.extra[extra.end..];
30243006
3007 try self.repurposed_insts.put(self.arena, @intCast(inst_index), {});
3008 defer _ = self.repurposed_insts.remove(@intCast(inst_index));
3009
30253010 var i: usize = 0;
30263011 while (i < args_len) : (i += 1) {
30273012 const arg_end = file.zir.extra[extra.end + i];
src/InternPool.zig+2-2
......@@ -5075,8 +5075,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
50755075 try ip.string_bytes.ensureUnusedCapacity(gpa, @as(usize, @intCast(len_including_sentinel + 1)));
50765076 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len);
50775077 switch (aggregate.storage) {
5078 .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes),
5079 .elems => |elems| for (elems) |elem| switch (ip.indexToKey(elem)) {
5078 .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes[0..@intCast(len)]),
5079 .elems => |elems| for (elems[0..@intCast(len)]) |elem| switch (ip.indexToKey(elem)) {
50805080 .undef => {
50815081 ip.string_bytes.shrinkRetainingCapacity(string_bytes_index);
50825082 break :bytes;
src/Sema.zig+478-447
......@@ -836,16 +836,11 @@ const LabeledBlock = struct {
836836/// the items are contiguous in memory and thus can be passed to
837837/// `Module.resolvePeerTypes`.
838838const InferredAlloc = struct {
839 prongs: std.MultiArrayList(struct {
840 /// The dummy instruction used as a peer to resolve the type.
841 /// Although this has a redundant type with placeholder, this is
842 /// needed in addition because it may be a constant value, which
843 /// affects peer type resolution.
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 }) = .{},
839 /// The placeholder `store` instructions used before the result pointer type
840 /// is known. These should be rewritten to perform any required coercions
841 /// when the type is resolved.
842 /// Allocated from `sema.arena`.
843 prongs: std.ArrayListUnmanaged(Air.Inst.Index) = .{},
849844};
850845
851846const NeededComptimeReason = struct {
......@@ -1040,17 +1035,14 @@ fn analyzeBodyInner(
10401035 .cmp_gte => try sema.zirCmp(block, inst, .gte),
10411036 .cmp_gt => try sema.zirCmp(block, inst, .gt),
10421037 .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),
10441038 .decl_ref => try sema.zirDeclRef(block, inst),
10451039 .decl_val => try sema.zirDeclVal(block, inst),
10461040 .load => try sema.zirLoad(block, inst),
10471041 .elem_ptr => try sema.zirElemPtr(block, inst),
10481042 .elem_ptr_node => try sema.zirElemPtrNode(block, inst),
1049 .elem_ptr_imm => try sema.zirElemPtrImm(block, inst),
10501043 .elem_val => try sema.zirElemVal(block, inst),
10511044 .elem_val_node => try sema.zirElemValNode(block, inst),
10521045 .elem_val_imm => try sema.zirElemValImm(block, inst),
1053 .elem_type_index => try sema.zirElemTypeIndex(block, inst),
10541046 .elem_type => try sema.zirElemType(block, inst),
10551047 .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst),
10561048 .vector_elem_type => try sema.zirVectorElemType(block, inst),
......@@ -1063,8 +1055,7 @@ fn analyzeBodyInner(
10631055 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst),
10641056 .error_union_type => try sema.zirErrorUnionType(block, inst),
10651057 .error_value => try sema.zirErrorValue(block, inst),
1066 .field_ptr => try sema.zirFieldPtr(block, inst, false),
1067 .field_ptr_init => try sema.zirFieldPtr(block, inst, true),
1058 .field_ptr => try sema.zirFieldPtr(block, inst),
10681059 .field_ptr_named => try sema.zirFieldPtrNamed(block, inst),
10691060 .field_val => try sema.zirFieldVal(block, inst),
10701061 .field_val_named => try sema.zirFieldValNamed(block, inst),
......@@ -1111,16 +1102,19 @@ fn analyzeBodyInner(
11111102 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),
11121103 .xor => try sema.zirBitwise(block, inst, .xor),
11131104 .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),
11141108 .struct_init => try sema.zirStructInit(block, inst, false),
11151109 .struct_init_ref => try sema.zirStructInit(block, inst, true),
1116 .struct_init_anon => try sema.zirStructInitAnon(block, inst, false),
1117 .struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true),
1110 .struct_init_field_type => try sema.zirStructInitFieldType(block, inst),
1111 .struct_init_field_ptr => try sema.zirStructInitFieldPtr(block, inst),
1112 .array_init_anon => try sema.zirArrayInitAnon(block, inst),
11181113 .array_init => try sema.zirArrayInit(block, inst, false),
11191114 .array_init_ref => try sema.zirArrayInit(block, inst, true),
1120 .array_init_anon => try sema.zirArrayInitAnon(block, inst, false),
1121 .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true),
1115 .array_init_elem_type => try sema.zirArrayInitElemType(block, inst),
1116 .array_init_elem_ptr => try sema.zirArrayInitElemPtr(block, inst),
11221117 .union_init => try sema.zirUnionInit(block, inst),
1123 .field_type => try sema.zirFieldType(block, inst),
11241118 .field_type_ref => try sema.zirFieldTypeRef(block, inst),
11251119 .int_from_ptr => try sema.zirIntFromPtr(block, inst),
11261120 .align_of => try sema.zirAlignOf(block, inst),
......@@ -1154,10 +1148,10 @@ fn analyzeBodyInner(
11541148 .field_parent_ptr => try sema.zirFieldParentPtr(block, inst),
11551149 .@"resume" => try sema.zirResume(block, inst),
11561150 .@"await" => try sema.zirAwait(block, inst),
1157 .array_base_ptr => try sema.zirArrayBasePtr(block, inst),
1158 .field_base_ptr => try sema.zirFieldBasePtr(block, inst),
11591151 .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
11621156 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),
11631157 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),
......@@ -1386,23 +1380,33 @@ fn analyzeBodyInner(
13861380 i += 1;
13871381 continue;
13881382 },
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 },
13891393 .validate_array_init_ty => {
1390 try sema.zirValidateArrayInitTy(block, inst);
1394 try sema.zirValidateArrayInitTy(block, inst, false);
13911395 i += 1;
13921396 continue;
13931397 },
1394 .validate_struct_init_ty => {
1395 try sema.zirValidateStructInitTy(block, inst);
1398 .validate_array_init_result_ty => {
1399 try sema.zirValidateArrayInitTy(block, inst, true);
13961400 i += 1;
13971401 continue;
13981402 },
1399 .validate_struct_init => {
1400 try sema.zirValidateStructInit(block, inst);
1403 .validate_ptr_struct_init => {
1404 try sema.zirValidatePtrStructInit(block, inst);
14011405 i += 1;
14021406 continue;
14031407 },
1404 .validate_array_init => {
1405 try sema.zirValidateArrayInit(block, inst);
1408 .validate_ptr_array_init => {
1409 try sema.zirValidatePtrArrayInit(block, inst);
14061410 i += 1;
14071411 continue;
14081412 },
......@@ -1416,6 +1420,11 @@ fn analyzeBodyInner(
14161420 i += 1;
14171421 continue;
14181422 },
1423 .validate_ref_ty => {
1424 try sema.zirValidateRefTy(block, inst);
1425 i += 1;
1426 continue;
1427 },
14191428 .@"export" => {
14201429 try sema.zirExport(block, inst);
14211430 i += 1;
......@@ -1922,7 +1931,11 @@ fn resolveDestType(
19221931 const msg = msg: {
19231932 const msg = try sema.errMsg(block, src, "{s} must have a known result type", .{builtin_name});
19241933 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 }
19261939 try sema.errNote(block, src, msg, "use @as to provide explicit result type", .{});
19271940 break :msg msg;
19281941 };
......@@ -1944,6 +1957,65 @@ fn resolveDestType(
19441957 return raw_ty;
19451958}
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
19472019fn analyzeAsType(
19482020 sema: *Sema,
19492021 block: *Block,
......@@ -2634,217 +2706,6 @@ pub fn resolveInstValue(
26342706 };
26352707}
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
28482709pub fn getStructType(
28492710 sema: *Sema,
28502711 decl: Module.Decl.Index,
......@@ -4220,8 +4081,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
42204081 .inferred_alloc => {
42214082 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
42224083 const ia2 = sema.unresolved_inferred_allocs.fetchRemove(ptr_inst).?.value;
4223 const peer_inst_list = ia2.prongs.items(.stored_inst);
4224 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
4084 const peer_vals = try sema.arena.alloc(Air.Inst.Ref, ia2.prongs.items.len);
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
42264092 const final_ptr_ty = try sema.ptrType(.{
42274093 .child = final_elem_ty.toIntern(),
......@@ -4259,55 +4125,19 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
42594125 .data = .{ .ty = final_ptr_ty },
42604126 });
42614127
4262 // Now we need to go back over all the coerce_result_ptr instructions, which
4263 // previously inserted a bitcast as a placeholder, and do the logic as if
4128 // Now we need to go back over all the store instructions, and do the logic as if
42644129 // the new result ptr type was available.
4265 const placeholders = ia2.prongs.items(.placeholder);
42664130 const gpa = sema.gpa;
42674131
4268 var trash_block = block.makeSubBlock();
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
4132 for (ia2.prongs.items) |placeholder_inst| {
42914133 var replacement_block = block.makeSubBlock();
42924134 defer replacement_block.instructions.deinit(gpa);
42934135
4294 const result = switch (sema.air_instructions.items(.tag)[placeholder_inst]) {
4295 .bitcast => result: {
4296 trash_block.instructions.shrinkRetainingCapacity(empty_trash_count);
4297 const sub_ptr = try sema.coerceResultPtr(&replacement_block, src, ptr, dummy_ptr, peer_inst, &trash_block);
4136 assert(sema.air_instructions.items(.tag)[placeholder_inst] == .store);
4137 const bin_op = sema.air_instructions.items(.data)[placeholder_inst].bin_op;
4138 try sema.storePtr2(&replacement_block, src, bin_op.lhs, src, bin_op.rhs, src, .store);
42984139
4299 assert(replacement_block.instructions.items.len > 0);
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
4140 // If only one instruction is produced then we can replace the store
43114141 // placeholder instruction with this instruction; no need for an entire block.
43124142 if (replacement_block.instructions.items.len == 1) {
43134143 const only_inst = replacement_block.instructions.items[0];
......@@ -4315,13 +4145,9 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
43154145 continue;
43164146 }
43174147
4318 // Here we replace the placeholder bitcast instruction with a block
4319 // that does the coerce_result_ptr logic.
4320 _ = try replacement_block.addBr(placeholder_inst, result);
4321 const ty_inst = if (result == .void_value)
4322 .void_type
4323 else
4324 sema.air_instructions.items(.data)[placeholder_inst].ty_op.ty;
4148 // Here we replace the placeholder store instruction with a block
4149 // that does the actual store logic.
4150 _ = try replacement_block.addBr(placeholder_inst, .void_value);
43254151 try sema.air_extra.ensureUnusedCapacity(
43264152 gpa,
43274153 @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
43294155 sema.air_instructions.set(placeholder_inst, .{
43304156 .tag = .block,
43314157 .data = .{ .ty_pl = .{
4332 .ty = ty_inst,
4158 .ty = .void_type,
43334159 .payload = sema.addExtraAssumeCapacity(Air.Block{
43344160 .body_len = @intCast(replacement_block.instructions.items.len),
43354161 }),
......@@ -4342,64 +4168,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
43424168 }
43434169}
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
44034171fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
44044172 const mod = sema.mod;
44054173 const gpa = sema.gpa;
......@@ -4526,34 +4294,140 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
45264294 return len;
45274295}
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(
45304392 sema: *Sema,
45314393 block: *Block,
45324394 inst: Zir.Inst.Index,
45334395) CompileError!Air.Inst.Ref {
45344396 const mod = sema.mod;
4535 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4536 var ty = sema.resolveType(block, .unneeded, inst_data.operand) catch |err| switch (err) {
4537 // Since this is a ZIR instruction that returns a type, encountering
4538 // generic poison should not result in a failed compilation, but the
4539 // generic poison type. This prevents unnecessary failures when
4540 // constructing types at compile-time.
4397 const pl_node = sema.code.instructions.items(.data)[inst].pl_node;
4398 const src = pl_node.src();
4399 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data;
4400 const maybe_wrapped_ptr_ty = sema.resolveType(block, .unneeded, extra.ptr_ty) catch |err| switch (err) {
45414401 error.GenericPoison => return .generic_poison_type,
45424402 else => |e| return e,
45434403 };
4544 while (true) {
4545 switch (ty.zigTypeTag(mod)) {
4546 .Optional => ty = ty.optionalChild(mod),
4547 .ErrorUnion => ty = ty.errorUnionPayload(mod),
4548 else => return Air.internedToRef(ty.toIntern()),
4549 }
4404 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(mod);
4405 assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction
4406 if (ptr_ty.isSlice(mod)) {
4407 // Use array of correct length
4408 const arr_ty = try mod.arrayType(.{
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());
45504414 }
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());
45514424}
45524425
45534426fn zirValidateArrayInitTy(
45544427 sema: *Sema,
45554428 block: *Block,
45564429 inst: Zir.Inst.Index,
4430 is_result_ty: bool,
45574431) CompileError!void {
45584432 const mod = sema.mod;
45594433 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
......@@ -4565,22 +4439,34 @@ fn zirValidateArrayInitTy(
45654439 error.GenericPoison => return,
45664440 else => |e| return e,
45674441 };
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;
45694455 switch (ty.zigTypeTag(mod)) {
45704456 .Array => {
45714457 const array_len = ty.arrayLen(mod);
4572 if (extra.init_count != array_len) {
4458 if (init_count != array_len) {
45734459 return sema.fail(block, src, "expected {d} array elements; found {d}", .{
4574 array_len, extra.init_count,
4460 array_len, init_count,
45754461 });
45764462 }
45774463 return;
45784464 },
45794465 .Vector => {
45804466 const array_len = ty.arrayLen(mod);
4581 if (extra.init_count != array_len) {
4467 if (init_count != array_len) {
45824468 return sema.fail(block, src, "expected {d} vector elements; found {d}", .{
4583 array_len, extra.init_count,
4469 array_len, init_count,
45844470 });
45854471 }
45864472 return;
......@@ -4588,9 +4474,9 @@ fn zirValidateArrayInitTy(
45884474 .Struct => if (ty.isTuple(mod)) {
45894475 try sema.resolveTypeFields(ty);
45904476 const array_len = ty.arrayLen(mod);
4591 if (extra.init_count > array_len) {
4477 if (init_count > array_len) {
45924478 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
4593 array_len, extra.init_count,
4479 array_len, init_count,
45944480 });
45954481 }
45964482 return;
......@@ -4604,6 +4490,7 @@ fn zirValidateStructInitTy(
46044490 sema: *Sema,
46054491 block: *Block,
46064492 inst: Zir.Inst.Index,
4493 is_result_ty: bool,
46074494) CompileError!void {
46084495 const mod = sema.mod;
46094496 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
......@@ -4613,15 +4500,16 @@ fn zirValidateStructInitTy(
46134500 error.GenericPoison => return,
46144501 else => |e| return e,
46154502 };
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)) {
46184506 .Struct, .Union => return,
46194507 else => {},
46204508 }
4621 return sema.failWithStructInitNotSupported(block, src, ty);
4509 return sema.failWithStructInitNotSupported(block, src, struct_ty);
46224510}
46234511
4624fn zirValidateStructInit(
4512fn zirValidatePtrStructInit(
46254513 sema: *Sema,
46264514 block: *Block,
46274515 inst: Zir.Inst.Index,
......@@ -4637,7 +4525,7 @@ fn zirValidateStructInit(
46374525 const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
46384526 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
46394527 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);
46414529 switch (agg_ty.zigTypeTag(mod)) {
46424530 .Struct => return sema.validateStructInit(
46434531 block,
......@@ -4723,10 +4611,6 @@ fn validateUnionInit(
47234611 // based only on the store instructions.
47244612 // `first_block_index` needs to point to the `field_ptr` if it exists;
47254613 // 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.
47304614 var first_block_index = block.instructions.items.len;
47314615 var block_index = block.instructions.items.len - 1;
47324616 var init_val: ?Value = null;
......@@ -4963,10 +4847,6 @@ fn validateStructInit(
49634847 // based only on the store instructions.
49644848 // `first_block_index` needs to point to the `field_ptr` if it exists;
49654849 // 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
49714851 // Possible performance enhancement: save the `block_index` between iterations
49724852 // of the for loop.
......@@ -5115,7 +4995,7 @@ fn validateStructInit(
51154995 }
51164996}
51174997
5118fn zirValidateArrayInit(
4998fn zirValidatePtrArrayInit(
51194999 sema: *Sema,
51205000 block: *Block,
51215001 inst: Zir.Inst.Index,
......@@ -5128,7 +5008,7 @@ fn zirValidateArrayInit(
51285008 const first_elem_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
51295009 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data;
51305010 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);
51325012 const array_len = array_ty.arrayLen(mod);
51335013
51345014 if (instrs.len != array_len) switch (array_ty.zigTypeTag(mod)) {
......@@ -5227,10 +5107,6 @@ fn zirValidateArrayInit(
52275107 // `first_block_index` needs to point to the `elem_ptr` if it exists;
52285108 // the `store` otherwise.
52295109 //
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 //
52345110 // This is nearly identical to similar logic in `validateStructInit`.
52355111
52365112 // Possible performance enhancement: save the `block_index` between iterations
......@@ -5540,10 +5416,7 @@ fn storeToInferredAlloc(
55405416 try sema.checkComptimeKnownStore(block, dummy_store);
55415417 // Add the stored instruction to the set we will use to resolve peer types
55425418 // for the inferred allocation.
5543 try inferred_alloc.prongs.append(sema.arena, .{
5544 .stored_inst = operand,
5545 .placeholder = Air.refToIndex(dummy_store).?,
5546 });
5419 try inferred_alloc.prongs.append(sema.arena, Air.refToIndex(dummy_store).?);
55475420}
55485421
55495422fn storeToInferredAllocComptime(
......@@ -8314,10 +8187,10 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
83148187 return Air.internedToRef(opt_type.toIntern());
83158188}
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 {
83188191 const mod = sema.mod;
83198192 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) {
83218194 // Since this is a ZIR instruction that returns a type, encountering
83228195 // generic poison should not result in a failed compilation, but the
83238196 // generic poison type. This prevents unnecessary failures when
......@@ -8325,6 +8198,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
83258198 error.GenericPoison => return .generic_poison_type,
83268199 else => |e| return e,
83278200 };
8201 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(mod);
83288202 try sema.resolveTypeFields(indexable_ty);
83298203 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
83308204 if (indexable_ty.zigTypeTag(mod) == .Struct) {
......@@ -8339,8 +8213,18 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
83398213fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
83408214 const mod = sema.mod;
83418215 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);
83438221 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 }
83448228 return Air.internedToRef(ptr_ty.childType(mod).toIntern());
83458229}
83468230
......@@ -10083,7 +9967,21 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
100839967 return sema.fieldVal(block, src, object, field_name, field_name_src);
100849968}
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 {
100879985 const tracy = trace(@src());
100889986 defer tracy.end();
100899987
......@@ -10094,7 +9992,15 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index, initializing: b
100949992 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
100959993 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start));
100969994 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 }
1009810004}
1009910005
1010010006fn 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
1058710493 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, true);
1058810494}
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 {
1059110497 const tracy = trace(@src());
1059210498 defer tracy.end();
1059310499
10500 const mod = sema.mod;
1059410501 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1059510502 const src = inst_data.src();
1059610503 const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
1059710504 const array_ptr = try sema.resolveInst(extra.ptr);
1059810505 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 }
1059910513 return sema.elemPtr(block, src, array_ptr, elem_index, src, true, true);
1060010514}
1060110515
......@@ -19213,6 +19127,52 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1921319127 }
1921419128}
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
1921619176fn structInitEmpty(
1921719177 sema: *Sema,
1921819178 block: *Block,
......@@ -19230,7 +19190,7 @@ fn structInitEmpty(
1923019190 defer gpa.free(field_inits);
1923119191 @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);
1923419194}
1923519195
1923619196fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref {
......@@ -19321,13 +19281,14 @@ fn zirStructInit(
1932119281 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
1932219282 const first_field_type_data = zir_datas[first_item.field_type].pl_node;
1932319283 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) {
1932519285 error.GenericPoison => {
1932619286 // The type wasn't actually known, so treat this as an anon struct init.
1932719287 return sema.structInitAnon(block, src, .typed_init, extra.data, extra.end, is_ref);
1932819288 },
1932919289 else => |e| return e,
1933019290 };
19291 const resolved_ty = result_ty.optEuBaseType(mod);
1933119292 try sema.resolveTypeLayout(resolved_ty);
1933219293
1933319294 if (resolved_ty.zigTypeTag(mod) == .Struct) {
......@@ -19372,7 +19333,9 @@ fn zirStructInit(
1937219333 return sema.failWithOwnedErrorMsg(block, msg);
1937319334 }
1937419335 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);
1937619339 if (!is_packed) if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| {
1937719340 const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse {
1937819341 return sema.failWithNeededComptime(block, field_src, .{
......@@ -19386,7 +19349,7 @@ fn zirStructInit(
1938619349 };
1938719350 }
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);
1939019353 } else if (resolved_ty.zigTypeTag(mod) == .Union) {
1939119354 if (extra.data.fields_len != 1) {
1939219355 return sema.fail(block, src, "union initialization expects exactly one field", .{});
......@@ -19401,36 +19364,60 @@ fn zirStructInit(
1940119364 const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src);
1940219365 const tag_ty = resolved_ty.unionTagTypeHypothetical(mod);
1940319366 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);
1940619385 if (try sema.resolveMaybeUndefVal(init_inst)) |val| {
19407 const field_ty = mod.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index].toType();
19408 return sema.addConstantMaybeRef(block, resolved_ty, (try mod.intern(.{ .un = .{
19386 const struct_val = (try mod.intern(.{ .un = .{
1940919387 .ty = resolved_ty.toIntern(),
1941019388 .tag = try tag_val.intern(tag_ty, mod),
1941119389 .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 });
1941319400 }
1941419401
1941519402 if (is_ref) {
1941619403 const target = mod.getTarget();
1941719404 const alloc_ty = try sema.ptrType(.{
19418 .child = resolved_ty.toIntern(),
19405 .child = result_ty.toIntern(),
1941919406 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1942019407 });
1942119408 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);
1942319411 try sema.storePtr(block, src, field_ptr, init_inst);
1942419412 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);
1942619414 return sema.makePtrConst(block, alloc);
1942719415 }
1942819416
1942919417 try sema.requireRuntimeBlock(block, src, null);
1943019418 try sema.queueFullTypeResolution(resolved_ty);
19431 return block.addUnionInit(resolved_ty, field_index, init_inst);
19432 } else if (resolved_ty.isAnonStruct(mod)) {
19433 return sema.fail(block, src, "TODO anon struct init validation", .{});
19419 const union_val = try block.addUnionInit(resolved_ty, field_index, init_inst);
19420 return sema.coerce(block, result_ty, union_val, src);
1943419421 }
1943519422 unreachable;
1943619423}
......@@ -19442,6 +19429,7 @@ fn finishStructInit(
1944219429 dest_src: LazySrcLoc,
1944319430 field_inits: []Air.Inst.Ref,
1944419431 struct_ty: Type,
19432 result_ty: Type,
1944519433 is_ref: bool,
1944619434) CompileError!Air.Inst.Ref {
1944719435 const mod = sema.mod;
......@@ -19452,8 +19440,24 @@ fn finishStructInit(
1945219440
1945319441 switch (ip.indexToKey(struct_ty.toIntern())) {
1945419442 .anon_struct_type => |anon_struct| {
19455 for (anon_struct.values.get(ip), 0..) |default_val, i| {
19456 if (field_inits[i] != .none) continue;
19443 // We can't get the slices, as the coercion may invalidate them.
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
1945819462 if (default_val == .none) {
1945919463 if (anon_struct.names.len == 0) {
......@@ -19480,7 +19484,20 @@ fn finishStructInit(
1948019484 },
1948119485 .struct_type => |struct_type| {
1948219486 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
1948519502 const field_init = struct_type.fieldInit(ip, i);
1948619503 if (field_init == .none) {
......@@ -19524,29 +19541,39 @@ fn finishStructInit(
1952419541
1952519542 const runtime_index = opt_runtime_index orelse {
1952619543 const elems = try sema.arena.alloc(InternPool.Index, field_inits.len);
19527 for (elems, field_inits, 0..) |*elem, field_init, field_i| {
19528 elem.* = try (sema.resolveMaybeUndefVal(field_init) catch unreachable).?
19529 .intern(struct_ty.structFieldType(field_i, mod), mod);
19544 for (elems, field_inits) |*elem, field_init| {
19545 elem.* = (sema.resolveMaybeUndefVal(field_init) catch unreachable).?.toIntern();
1953019546 }
1953119547 const struct_val = try mod.intern(.{ .aggregate = .{
1953219548 .ty = struct_ty.toIntern(),
1953319549 .storage = .{ .elems = elems },
1953419550 } });
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);
1953619554 };
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
1953819564 if (is_ref) {
1953919565 try sema.resolveStructLayout(struct_ty);
1954019566 const target = sema.mod.getTarget();
1954119567 const alloc_ty = try sema.ptrType(.{
19542 .child = struct_ty.toIntern(),
19568 .child = result_ty.toIntern(),
1954319569 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1954419570 });
1954519571 const alloc = try block.addTy(.alloc, alloc_ty);
19572 const base_ptr = try sema.optEuBasePtrInit(block, alloc, init_src);
1954619573 for (field_inits, 0..) |field_init, i_usize| {
1954719574 const i: u32 = @intCast(i_usize);
1954819575 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);
1955019577 try sema.storePtr(block, dest_src, field_ptr, field_init);
1955119578 }
1955219579
......@@ -19563,19 +19590,19 @@ fn finishStructInit(
1956319590 else => |e| return e,
1956419591 };
1956519592 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);
1956719595}
1956819596
1956919597fn zirStructInitAnon(
1957019598 sema: *Sema,
1957119599 block: *Block,
1957219600 inst: Zir.Inst.Index,
19573 is_ref: bool,
1957419601) CompileError!Air.Inst.Ref {
1957519602 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1957619603 const src = inst_data.src();
1957719604 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);
1957919606}
1958019607
1958119608fn structInitAnon(
......@@ -19748,13 +19775,14 @@ fn zirArrayInit(
1974819775 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
1974919776 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) {
1975219779 error.GenericPoison => {
1975319780 // The type wasn't actually known, so treat this as an anon array init.
1975419781 return sema.arrayInitAnon(block, src, args[1..], is_ref);
1975519782 },
1975619783 else => |e| return e,
1975719784 };
19785 const array_ty = result_ty.optEuBaseType(mod);
1975819786 const is_tuple = array_ty.zigTypeTag(mod) == .Struct;
1975919787 const sentinel_val = array_ty.sentinel(mod);
1976019788
......@@ -19810,10 +19838,12 @@ fn zirArrayInit(
1981019838 // We checked that all args are comptime above.
1981119839 val.* = try ((sema.resolveMaybeUndefVal(arg) catch unreachable).?).intern(elem_ty, mod);
1981219840 }
19813 return sema.addConstantMaybeRef(block, array_ty, (try mod.intern(.{ .aggregate = .{
19841 const arr_val = try mod.intern(.{ .aggregate = .{
1981419842 .ty = array_ty.toIntern(),
1981519843 .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);
1981719847 };
1981819848
1981919849 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
......@@ -19830,10 +19860,11 @@ fn zirArrayInit(
1983019860 if (is_ref) {
1983119861 const target = mod.getTarget();
1983219862 const alloc_ty = try sema.ptrType(.{
19833 .child = array_ty.toIntern(),
19863 .child = result_ty.toIntern(),
1983419864 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1983519865 });
1983619866 const alloc = try block.addTy(.alloc, alloc_ty);
19867 const base_ptr = try sema.optEuBasePtrInit(block, alloc, src);
1983719868
1983819869 if (array_ty.isTuple(mod)) {
1983919870 for (resolved_args, 0..) |arg, i| {
......@@ -19844,7 +19875,7 @@ fn zirArrayInit(
1984419875 const elem_ptr_ty_ref = Air.internedToRef(elem_ptr_ty.toIntern());
1984519876
1984619877 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);
1984819879 _ = try block.addBinOp(.store, elem_ptr, arg);
1984919880 }
1985019881 return sema.makePtrConst(block, alloc);
......@@ -19858,26 +19889,26 @@ fn zirArrayInit(
1985819889
1985919890 for (resolved_args, 0..) |arg, i| {
1986019891 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);
1986219893 _ = try block.addBinOp(.store, elem_ptr, arg);
1986319894 }
1986419895 return sema.makePtrConst(block, alloc);
1986519896 }
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);
1986819900}
1986919901
1987019902fn zirArrayInitAnon(
1987119903 sema: *Sema,
1987219904 block: *Block,
1987319905 inst: Zir.Inst.Index,
19874 is_ref: bool,
1987519906) CompileError!Air.Inst.Ref {
1987619907 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1987719908 const src = inst_data.src();
1987819909 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
1987919910 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);
1988119912}
1988219913
1988319914fn arrayInitAnon(
......@@ -19997,14 +20028,14 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
1999720028 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);
1999820029}
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 {
2000120032 const mod = sema.mod;
2000220033 const ip = &mod.intern_pool;
2000320034 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2000420035 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
2000520036 const ty_src = inst_data.src();
2000620037 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) {
2000820039 // Since this is a ZIR instruction that returns a type, encountering
2000920040 // generic poison should not result in a failed compilation, but the
2001020041 // generic poison type. This prevents unnecessary failures when
......@@ -20012,6 +20043,7 @@ fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2001220043 error.GenericPoison => return .generic_poison_type,
2001320044 else => |e| return e,
2001420045 };
20046 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(mod);
2001520047 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
2001620048 const field_name = try ip.getOrPutString(sema.gpa, zir_field_name);
2001720049 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);
......@@ -20033,7 +20065,10 @@ fn fieldType(
2003320065 switch (cur_ty.zigTypeTag(mod)) {
2003420066 .Struct => switch (ip.indexToKey(cur_ty.toIntern())) {
2003520067 .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);
2003720072 return Air.internedToRef(anon_struct.types.get(ip)[field_index]);
2003820073 },
2003920074 .struct_type => |struct_type| {
......@@ -21620,7 +21655,8 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2162021655 const operand_coerced = try sema.coerce(block, operand_ty, operand_res, operand_src);
2162121656
2162221657 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
2162421660 const elem_ty = ptr_ty.elemType2(mod);
2162521661 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);
2162621662
......@@ -21860,7 +21896,7 @@ fn ptrCastFull(
2186021896 const mod = sema.mod;
2186121897 const operand_ty = sema.typeOf(operand);
2186221898
21863 try sema.checkPtrType(block, src, dest_ty);
21899 try sema.checkPtrType(block, src, dest_ty, true);
2186421900 try sema.checkPtrOperand(block, operand_src, operand_ty);
2186521901
2186621902 const src_info = operand_ty.ptrInfo(mod);
......@@ -22668,10 +22704,11 @@ fn checkPtrType(
2266822704 block: *Block,
2266922705 ty_src: LazySrcLoc,
2267022706 ty: Type,
22707 allow_slice: bool,
2267122708) CompileError!void {
2267222709 const mod = sema.mod;
2267322710 switch (ty.zigTypeTag(mod)) {
22674 .Pointer => return,
22711 .Pointer => if (allow_slice or !ty.isSlice(mod)) return,
2267522712 .Fn => {
2267622713 const msg = msg: {
2267722714 const msg = try sema.errMsg(
......@@ -29577,13 +29614,6 @@ fn storePtr2(
2957729614 return;
2957829615 }
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
2958729617 try sema.requireRuntimeBlock(block, src, runtime_src);
2958829618 try sema.queueFullTypeResolution(elem_ty);
2958929619
......@@ -29719,6 +29749,7 @@ fn storePtrVal(
2971929749 switch (mut_kit.pointee) {
2972029750 .direct => |val_ptr| {
2972129751 if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) {
29752 val_ptr.* = (try val_ptr.intern(operand_ty, mod)).toValue();
2972229753 if (!operand_val.eql(val_ptr.*, operand_ty, mod)) {
2972329754 // TODO use failWithInvalidComptimeFieldStore
2972429755 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 {
242242 /// Uses the `pl_node` union field with `Bin` payload.
243243 /// lhs is length, rhs is element type.
244244 vector_type,
245 /// Given an indexable type, returns the type of the element at given index.
246 /// Uses the `bin` union field. lhs is the indexable type, rhs is the index.
247 elem_type_index,
248 /// Given a pointer type, returns its element type.
245 /// Given a pointer type, returns its element type. Reaches through any optional or error
246 /// union types wrapping the pointer. Asserts that the underlying type is a pointer type.
247 /// Returns generic poison if the element type is `anyopaque`.
249248 /// Uses the `un_node` field.
250249 elem_type,
251250 /// Given an indexable pointer (slice, many-ptr, single-ptr-to-array), returns its
......@@ -353,11 +352,6 @@ pub const Inst = struct {
353352 /// `!=`
354353 /// Uses the `pl_node` union field. Payload is `Bin`.
355354 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,
361355 /// Conditional branch. Splits control flow based on a boolean condition value.
362356 /// Uses the `pl_node` union field. AST node is an if, while, for, etc.
363357 /// Payload is `CondBr`.
......@@ -419,13 +413,6 @@ pub const Inst = struct {
419413 /// Payload is `Bin`.
420414 /// No OOB safety check is emitted.
421415 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,
429416 /// Given an array, slice, or pointer, returns the element at the provided index.
430417 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
431418 elem_val_node,
......@@ -463,8 +450,6 @@ pub const Inst = struct {
463450 /// to the named field. The field name is stored in string_bytes. Used by a.b syntax.
464451 /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.
465452 field_ptr,
466 /// Same as `field_ptr` but used for struct init.
467 field_ptr_init,
468453 /// Given a struct or object that contains virtual fields, returns the named field.
469454 /// The field name is stored in string_bytes. Used by a.b syntax.
470455 /// This instruction also accepts a pointer.
......@@ -688,84 +673,123 @@ pub const Inst = struct {
688673 /// A switch expression. Uses the `pl_node` union field.
689674 /// AST node is the switch, payload is `SwitchBlock`. Operand is a pointer.
690675 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,
729676 /// Check that operand type supports the dereference operand (.*).
730677 /// Uses the `un_node` field.
731678 validate_deref,
732679 /// Check that the operand's type is an array or tuple with the given number of elements.
733680 /// Uses the `pl_node` field. Payload is `ValidateDestructure`.
734681 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,
741682 /// Given a struct or union, and a field name as a Ref,
742683 /// returns the field type. Uses the `pl_node` field. Payload is `FieldTypeRef`.
743684 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,
744716 /// 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.
746720 /// Uses the `pl_node` field. Payload is `StructInit`.
747721 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.
749724 /// Uses the `pl_node` field. Payload is `StructInit`.
750725 struct_init_ref,
751 /// Struct initialization without a type.
752 /// Uses the `pl_node` field. Payload is `StructInitAnon`.
753 struct_init_anon,
754 /// Anonymous struct initialization syntax, make the result a pointer.
755 /// Uses the `pl_node` field. Payload is `StructInitAnon`.
756 struct_init_anon_ref,
757 /// Array initialization syntax.
758 /// Uses the `pl_node` field. Payload is `MultiOp`.
759 array_init,
760 /// Anonymous array initialization syntax.
726 /// Checks that the type supports struct init syntax. Always returns void.
727 /// Uses the `un_node` field.
728 validate_struct_init_ty,
729 /// Like `validate_struct_init_ty`, but additionally accepts types which structs coerce to.
730 /// Used on the known result type of a struct init expression. Always returns void.
731 /// Uses the `un_node` field.
732 validate_struct_init_result_ty,
733 /// Given a set of `struct_init_field_ptr` instructions, assumes they are all part of a
734 /// struct initialization expression, and emits compile errors for duplicate fields as well
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.
761752 /// Uses the `pl_node` field. Payload is `MultiOp`.
762753 array_init_anon,
763 /// Array initialization syntax, make the result a pointer.
764 /// Uses the `pl_node` field. Payload is `MultiOp`.
754 /// Array initialization syntax with a known type. The given type must be validated prior to
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.
765761 array_init_ref,
766 /// Anonymous array initialization syntax, make the result a pointer.
767 /// Uses the `pl_node` field. Payload is `MultiOp`.
768 array_init_anon_ref,
762 /// Checks that the type supports array init syntax. Always returns void.
763 /// Uses the `pl_node` field. Payload is `ArrayInit`.
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
769793 /// Implements the `@unionInit` builtin.
770794 /// Uses the `pl_node` field. Payload is `UnionInit`.
771795 union_init,
......@@ -1038,7 +1062,6 @@ pub const Inst = struct {
10381062 .array_type,
10391063 .array_type_sentinel,
10401064 .vector_type,
1041 .elem_type_index,
10421065 .elem_type,
10431066 .indexable_ptr_elem_type,
10441067 .vector_elem_type,
......@@ -1066,7 +1089,6 @@ pub const Inst = struct {
10661089 .cmp_gte,
10671090 .cmp_gt,
10681091 .cmp_neq,
1069 .coerce_result_ptr,
10701092 .error_set_decl,
10711093 .error_set_decl_anon,
10721094 .error_set_decl_func,
......@@ -1082,7 +1104,6 @@ pub const Inst = struct {
10821104 .elem_ptr,
10831105 .elem_val,
10841106 .elem_ptr_node,
1085 .elem_ptr_imm,
10861107 .elem_val_node,
10871108 .elem_val_imm,
10881109 .ensure_result_used,
......@@ -1091,7 +1112,6 @@ pub const Inst = struct {
10911112 .@"export",
10921113 .export_value,
10931114 .field_ptr,
1094 .field_ptr_init,
10951115 .field_val,
10961116 .field_ptr_named,
10971117 .field_val_named,
......@@ -1154,25 +1174,9 @@ pub const Inst = struct {
11541174 .set_eval_branch_quota,
11551175 .switch_block,
11561176 .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,
11631177 .validate_deref,
11641178 .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,
11741179 .union_init,
1175 .field_type,
11761180 .field_type_ref,
11771181 .enum_from_int,
11781182 .int_from_enum,
......@@ -1254,7 +1258,29 @@ pub const Inst = struct {
12541258 .save_err_ret_index,
12551259 .restore_err_ret_index,
12561260 .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,
12581284 => false,
12591285
12601286 .@"break",
......@@ -1307,10 +1333,6 @@ pub const Inst = struct {
13071333 .store_node,
13081334 .store_to_inferred_ptr,
13091335 .resolve_inferred_alloc,
1310 .validate_array_init_ty,
1311 .validate_struct_init_ty,
1312 .validate_struct_init,
1313 .validate_array_init,
13141336 .validate_deref,
13151337 .validate_destructure,
13161338 .@"export",
......@@ -1323,6 +1345,13 @@ pub const Inst = struct {
13231345 .defer_err_code,
13241346 .restore_err_ret_index,
13251347 .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,
13261355 => true,
13271356
13281357 .param,
......@@ -1346,7 +1375,6 @@ pub const Inst = struct {
13461375 .array_type,
13471376 .array_type_sentinel,
13481377 .vector_type,
1349 .elem_type_index,
13501378 .elem_type,
13511379 .indexable_ptr_elem_type,
13521380 .vector_elem_type,
......@@ -1374,7 +1402,6 @@ pub const Inst = struct {
13741402 .cmp_gte,
13751403 .cmp_gt,
13761404 .cmp_neq,
1377 .coerce_result_ptr,
13781405 .error_set_decl,
13791406 .error_set_decl_anon,
13801407 .error_set_decl_func,
......@@ -1385,11 +1412,9 @@ pub const Inst = struct {
13851412 .elem_ptr,
13861413 .elem_val,
13871414 .elem_ptr_node,
1388 .elem_ptr_imm,
13891415 .elem_val_node,
13901416 .elem_val_imm,
13911417 .field_ptr,
1392 .field_ptr_init,
13931418 .field_val,
13941419 .field_ptr_named,
13951420 .field_val_named,
......@@ -1447,19 +1472,7 @@ pub const Inst = struct {
14471472 .typeof_log2_int_type,
14481473 .switch_block,
14491474 .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,
14611475 .union_init,
1462 .field_type,
14631476 .field_type_ref,
14641477 .enum_from_int,
14651478 .int_from_enum,
......@@ -1546,7 +1559,22 @@ pub const Inst = struct {
15461559 .for_len,
15471560 .@"try",
15481561 .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,
15501578 => false,
15511579
15521580 .extended => switch (data.extended.opcode) {
......@@ -1580,7 +1608,6 @@ pub const Inst = struct {
15801608 .array_type = .pl_node,
15811609 .array_type_sentinel = .pl_node,
15821610 .vector_type = .pl_node,
1583 .elem_type_index = .bin,
15841611 .elem_type = .un_node,
15851612 .indexable_ptr_elem_type = .un_node,
15861613 .vector_elem_type = .un_node,
......@@ -1612,7 +1639,6 @@ pub const Inst = struct {
16121639 .cmp_gte = .pl_node,
16131640 .cmp_gt = .pl_node,
16141641 .cmp_neq = .pl_node,
1615 .coerce_result_ptr = .pl_node,
16161642 .condbr = .pl_node,
16171643 .condbr_inline = .pl_node,
16181644 .@"try" = .pl_node,
......@@ -1631,7 +1657,6 @@ pub const Inst = struct {
16311657 .div = .pl_node,
16321658 .elem_ptr = .pl_node,
16331659 .elem_ptr_node = .pl_node,
1634 .elem_ptr_imm = .pl_node,
16351660 .elem_val = .pl_node,
16361661 .elem_val_node = .pl_node,
16371662 .elem_val_imm = .elem_val_imm,
......@@ -1643,7 +1668,6 @@ pub const Inst = struct {
16431668 .@"export" = .pl_node,
16441669 .export_value = .pl_node,
16451670 .field_ptr = .pl_node,
1646 .field_ptr_init = .pl_node,
16471671 .field_val = .pl_node,
16481672 .field_ptr_named = .pl_node,
16491673 .field_val_named = .pl_node,
......@@ -1701,30 +1725,16 @@ pub const Inst = struct {
17011725 .enum_literal = .str_tok,
17021726 .switch_block = .pl_node,
17031727 .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,
17111728 .validate_deref = .un_node,
17121729 .validate_destructure = .pl_node,
1713 .struct_init_empty = .un_node,
1714 .field_type = .pl_node,
17151730 .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,
17241731 .union_init = .pl_node,
17251732 .type_info = .un_node,
17261733 .size_of = .un_node,
17271734 .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
17291739 .int_from_ptr = .un_node,
17301740 .compile_error = .un_node,
......@@ -1826,6 +1836,27 @@ pub const Inst = struct {
18261836 .save_err_ret_index = .save_err_ret_index,
18271837 .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
18291860 .extended = .extended,
18301861 });
18311862 };
......@@ -2771,6 +2802,11 @@ pub const Inst = struct {
27712802 };
27722803 };
27732804
2805 pub const ArrayInitRefTy = struct {
2806 ptr_ty: Ref,
2807 elem_count: u32,
2808 };
2809
27742810 pub const Field = struct {
27752811 lhs: Ref,
27762812 /// Offset into `string_bytes`.
......@@ -3064,9 +3100,10 @@ pub const Inst = struct {
30643100 fields_len: u32,
30653101
30663102 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.
30683104 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.
30703107 init: Ref,
30713108 };
30723109 };
src/print_zir.zig+110-31
......@@ -130,6 +130,63 @@ const Writer = struct {
130130 recurse_decls: bool,
131131 recurse_blocks: bool,
132132
133 /// Using `std.zig.findLineColumn` whenever we need to resolve a source location makes ZIR
134 /// printing O(N^2), which can have drastic effects - taking a ZIR dump from a few seconds to
135 /// many minutes. Since we're usually resolving source locations close to one another,
136 /// preserving state across source location resolutions speeds things up a lot.
137 line_col_cursor: struct {
138 line: usize = 0,
139 column: usize = 0,
140 line_start: usize = 0,
141 off: usize = 0,
142
143 fn find(cur: *@This(), source: []const u8, want_offset: usize) std.zig.Loc {
144 if (want_offset < cur.off) {
145 // Go back to the start of this line
146 cur.off = cur.line_start;
147 cur.column = 0;
148
149 while (want_offset < cur.off) {
150 // Go back to the newline
151 cur.off -= 1;
152
153 // Seek to the start of the previous line
154 while (cur.off > 0 and source[cur.off - 1] != '\n') {
155 cur.off -= 1;
156 }
157 cur.line_start = cur.off;
158 cur.line -= 1;
159 }
160 }
161
162 // The cursor is now positioned before `want_offset`.
163 // Seek forward as in `std.zig.findLineColumn`.
164
165 while (cur.off < want_offset) : (cur.off += 1) {
166 switch (source[cur.off]) {
167 '\n' => {
168 cur.line += 1;
169 cur.column = 0;
170 cur.line_start = cur.off + 1;
171 },
172 else => {
173 cur.column += 1;
174 },
175 }
176 }
177
178 while (cur.off < source.len and source[cur.off] != '\n') {
179 cur.off += 1;
180 }
181
182 return .{
183 .line = cur.line,
184 .column = cur.column,
185 .source_line = source[cur.line_start..cur.off],
186 };
187 }
188 } = .{},
189
133190 fn relativeToNodeIndex(self: *Writer, offset: i32) Ast.Node.Index {
134191 return @as(Ast.Node.Index, @bitCast(offset + @as(i32, @bitCast(self.parent_decl_node))));
135192 }
......@@ -148,8 +205,6 @@ const Writer = struct {
148205 .store_to_inferred_ptr,
149206 => try self.writeBin(stream, inst),
150207
151 .elem_type_index => try self.writeElemTypeIndex(stream, inst),
152
153208 .alloc,
154209 .alloc_mut,
155210 .alloc_comptime_mut,
......@@ -184,7 +239,6 @@ const Writer = struct {
184239 .is_non_err_ptr,
185240 .ret_is_non_err,
186241 .typeof,
187 .struct_init_empty,
188242 .type_info,
189243 .size_of,
190244 .bit_size_of,
......@@ -224,18 +278,16 @@ const Writer = struct {
224278 .bit_reverse,
225279 .@"resume",
226280 .@"await",
227 .array_base_ptr,
228 .field_base_ptr,
229 .validate_struct_init_ty,
230281 .make_ptr_const,
231282 .validate_deref,
232283 .check_comptime_control_flow,
233 .opt_eu_base_ty,
284 .opt_eu_base_ptr_init,
234285 => try self.writeUnNode(stream, inst),
235286
236287 .ref,
237288 .ret_implicit,
238289 .closure_capture,
290 .validate_ref_ty,
239291 => try self.writeUnTok(stream, inst),
240292
241293 .bool_br_and,
......@@ -243,7 +295,6 @@ const Writer = struct {
243295 => try self.writeBoolBr(stream, inst),
244296
245297 .validate_destructure => try self.writeValidateDestructure(stream, inst),
246 .validate_array_init_ty => try self.writeValidateArrayInitTy(stream, inst),
247298 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
248299 .ptr_type => try self.writePtrType(stream, inst),
249300 .int => try self.writeInt(stream, inst),
......@@ -259,12 +310,6 @@ const Writer = struct {
259310 .@"break",
260311 .break_inline,
261312 => try self.writeBreak(stream, inst),
262 .array_init,
263 .array_init_ref,
264 => try self.writeArrayInit(stream, inst),
265 .array_init_anon,
266 .array_init_anon_ref,
267 => try self.writeArrayInitAnon(stream, inst),
268313
269314 .slice_start => try self.writeSliceStart(stream, inst),
270315 .slice_end => try self.writeSliceEnd(stream, inst),
......@@ -273,10 +318,44 @@ const Writer = struct {
273318
274319 .union_init => try self.writeUnionInit(stream, inst),
275320
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
276330 .struct_init,
277331 .struct_init_ref,
278332 => try self.writeStructInit(stream, inst),
279333
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
280359 .atomic_load => try self.writeAtomicLoad(stream, inst),
281360 .atomic_store => try self.writeAtomicStore(stream, inst),
282361 .atomic_rmw => try self.writeAtomicRmw(stream, inst),
......@@ -285,11 +364,6 @@ const Writer = struct {
285364 .field_parent_ptr => try self.writeFieldParentPtr(stream, inst),
286365 .builtin_call => try self.writeBuiltinCall(stream, inst),
287366
288 .struct_init_anon,
289 .struct_init_anon_ref,
290 => try self.writeStructInitAnon(stream, inst),
291
292 .field_type => try self.writeFieldType(stream, inst),
293367 .field_type_ref => try self.writeFieldTypeRef(stream, inst),
294368
295369 .add,
......@@ -352,16 +426,14 @@ const Writer = struct {
352426 .elem_val_node,
353427 .elem_ptr,
354428 .elem_val,
355 .coerce_result_ptr,
356429 .array_type,
430 .coerce_ptr_elem_ty,
357431 => try self.writePlNodeBin(stream, inst),
358432
359433 .for_len => try self.writePlNodeMultiOp(stream, inst),
360434
361435 .elem_val_imm => try self.writeElemValImm(stream, inst),
362436
363 .elem_ptr_imm => try self.writeElemPtrImm(stream, inst),
364
365437 .@"export" => try self.writePlNodeExport(stream, inst),
366438 .export_value => try self.writePlNodeExportValue(stream, inst),
367439
......@@ -373,8 +445,6 @@ const Writer = struct {
373445 .block_inline,
374446 .suspend_block,
375447 .loop,
376 .validate_struct_init,
377 .validate_array_init,
378448 .c_import,
379449 .typeof_builtin,
380450 => try self.writeBlock(stream, inst),
......@@ -395,9 +465,8 @@ const Writer = struct {
395465 .switch_block_ref,
396466 => try self.writeSwitchBlock(stream, inst),
397467
398 .field_ptr,
399 .field_ptr_init,
400468 .field_val,
469 .field_ptr,
401470 => try self.writePlNodeField(stream, inst),
402471
403472 .field_ptr_named,
......@@ -560,7 +629,7 @@ const Writer = struct {
560629 try stream.writeByte(')');
561630 }
562631
563 fn writeElemTypeIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
632 fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
564633 const inst_data = self.code.instructions.items(.data)[inst].bin;
565634 try self.writeInstRef(stream, inst_data.lhs);
566635 try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)});
......@@ -915,7 +984,7 @@ const Writer = struct {
915984 try stream.print(", {d})", .{inst_data.idx});
916985 }
917986
918 fn writeElemPtrImm(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
987 fn writeArrayInitElemPtr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
919988 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
920989 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
921990
......@@ -947,6 +1016,16 @@ const Writer = struct {
9471016 try self.writeSrc(stream, inst_data.src());
9481017 }
9491018
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
9501029 fn writeStructInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
9511030 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
9521031 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
......@@ -1077,7 +1156,7 @@ const Writer = struct {
10771156 try self.writeSrc(stream, inst_data.src());
10781157 }
10791158
1080 fn writeFieldType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1159 fn writeStructInitFieldType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
10811160 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
10821161 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
10831162 try self.writeInstRef(stream, extra.container_type);
......@@ -2590,8 +2669,8 @@ const Writer = struct {
25902669 .lazy = src,
25912670 };
25922671 const src_span = src_loc.span(self.gpa) catch unreachable;
2593 const start = std.zig.findLineColumn(tree.source, src_span.start);
2594 const end = std.zig.findLineColumn(tree.source, src_span.end);
2672 const start = self.line_col_cursor.find(tree.source, src_span.start);
2673 const end = self.line_col_cursor.find(tree.source, src_span.end);
25952674 try stream.print("{s}:{d}:{d} to :{d}:{d}", .{
25962675 @tagName(src), start.line + 1, start.column + 1,
25972676 end.line + 1, end.column + 1,
src/type.zig+11
......@@ -3182,6 +3182,17 @@ pub const Type = struct {
31823182 };
31833183 }
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
31853196 pub const @"u1": Type = .{ .ip_index = .u1_type };
31863197 pub const @"u8": Type = .{ .ip_index = .u8_type };
31873198 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" {
780780 try expectEqual([4]u4{ 1, 2, 4, 8 }, init);
781781 try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);
782782}
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/bugs/12776.zig+1
......@@ -29,6 +29,7 @@ const CPU = packed struct {
2929};
3030
3131test {
32 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
3233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
3334 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3435 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
test/behavior/bugs/13664.zig+1
......@@ -17,6 +17,7 @@ test {
1717 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1818 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1919 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2021
2122 const timestamp: i64 = value();
2223 const id = ID{ .fields = Fields{
test/behavior/cast.zig+26
......@@ -2493,3 +2493,29 @@ test "@as does not corrupt values with incompatible representations" {
24932493 });
24942494 try std.testing.expectApproxEqAbs(@as(f32, 1.23), x, 0.001);
24952495}
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" {
548548 const casted = S.func(&bases);
549549 try expect(casted[0].a == 2);
550550}
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" {
17601760 try expectEqual(S{ .a = 1, .b = 2, .c = 4, .d = 8 }, init);
17611761 try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);
17621762}
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 {
1616// backend=stage2
1717// target=native
1818//
19// :7:14: error: runtime-known argument passed to parameter of comptime-only type
20// :9:12: note: declared here
21// :4:16: note: struct requires comptime because of this field
22// :4:16: note: types are not available at runtime
19// :7:25: error: unable to resolve comptime value
20// :7:25: note: initializer of comptime only struct must be comptime-known
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 {
1818// backend=stage2
1919// target=native
2020//
21// :11:27: error: expected type 'u8', found '?u8'
22// :11:27: note: cannot convert optional to payload type
23// :11:27: note: consider using '.?', 'orelse', or 'if'
21// :11:20: error: expected type 'u8', found '?u8'
22// :11:20: note: cannot convert optional to payload type
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 {
1010export fn d() void {
1111 bar(@floatFromInt(123));
1212}
13export fn f() void {
14 bar(.{
15 .x = @intCast(123),
16 });
17}
1318
1419fn bar(_: anytype) void {}
1520
......@@ -18,14 +23,17 @@ fn bar(_: anytype) void {}
1823// target=native
1924//
2025// :2:9: error: @ptrFromInt must have a known result type
21// :2:9: note: result type is unknown due to anytype parameter
26// :2:8: note: result type is unknown due to anytype parameter
2227// :2:9: note: use @as to provide explicit result type
2328// :5:9: error: @ptrCast must have a known result type
24// :5:9: note: result type is unknown due to anytype parameter
29// :5:8: note: result type is unknown due to anytype parameter
2530// :5:9: note: use @as to provide explicit result type
2631// :8:9: error: @intCast must have a known result type
27// :8:9: note: result type is unknown due to anytype parameter
32// :8:8: note: result type is unknown due to anytype parameter
2833// :8:9: note: use @as to provide explicit result type
2934// :11:9: error: @floatFromInt must have a known result type
30// :11:9: note: result type is unknown due to anytype parameter
35// :11:8: note: result type is unknown due to anytype parameter
3136// :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 {
3131// :2:13: error: expected type 'usize', found '*const [5:0]u8'
3232// :7:10: error: type 'usize' cannot represent integer value '-1'
3333// :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
3536// :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 {
7171// target=native
7272// backend=stage2
7373//
74// :6:19: 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 field
74// :6:9: error: value stored in comptime field does not match the default value of the field
75// :14:9: error: value stored in comptime field does not match the default value of the field
7676// :19:38: error: value stored in comptime field does not match the default value of the field
7777// :31:19: error: value stored in comptime field does not match the default value of the field
7878// :25:29: note: default value set here
......@@ -80,5 +80,6 @@ pub export fn entry8() void {
8080// :35:29: note: default value set here
8181// :45:12: error: value stored in comptime field does not match the default value of the field
8282// :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 field
84// :59:35: error: value stored in comptime field does not match the default value of the field
83// :66:36: error: value stored in comptime field does not match the default value of the field
84// :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 {
1515// backend=llvm
1616// target=native
1717//
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 {
3939// :8:25: note: type 'i32' here
4040// :16:16: error: expected type 'tmp.h.T', found 'void'
4141// :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 {
1616// backend=stage2
1717// target=native
1818//
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'
2020// :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'
2222// :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'
2424// :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 {
99// backend=llvm
1010// target=native
1111//
12// :2:15: error: cannot assign to constant
12// :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 {
1212// backend=stage2
1313// target=native
1414//
15// :5:10: error: cannot assign to constant
15// :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 {
1818// backend=stage2
1919// target=native
2020//
21// :12:25: 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 type
23// :12:25: note: consider using 'try', 'catch', or 'if'
21// :12:15: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(tmp.get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'
22// :12:15: note: cannot convert error union to payload type
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 {
1515// backend=stage2
1616// target=native
1717//
18// :3:36: error: expected type 'i32', found '?i32'
19// :3:36: note: cannot convert optional to payload type
20// :3:36: note: consider using '.?', 'orelse', or 'if'
18// :3:23: error: expected type 'i32', found '?i32'
19// :3:23: note: cannot convert optional to payload type
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 {
1515// backend=stage2
1616// target=native
1717//
18// :3:36: error: expected type 'i32', found '?i32'
19// :3:36: note: cannot convert optional to payload type
20// :3:36: note: consider using '.?', 'orelse', or 'if'
18// :3:23: error: expected type 'i32', found '?i32'
19// :3:23: note: cannot convert optional to payload type
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 {
1818// :8:18: error: expected type 'tmp.A(u32)', found 'tmp.B(u32)'
1919// :5:12: note: struct declared here
2020// :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 {
1212// backend=stage2
1313// target=native
1414//
15// :7:29: error: unable to resolve comptime value
16// :7:29: note: initializer of comptime only struct must be comptime-known
15// :7:23: error: unable to resolve comptime value
16// :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 {
1212// backend=stage2
1313// target=native
1414//
15// :7:29: error: unable to resolve comptime value
16// :7:29: note: initializer of comptime only union must be comptime-known
15// :7:23: error: unable to resolve comptime value
16// :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 {
77// backend=stage2
88// target=native
99//
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 @@
1export fn entry() void {
1export fn entry1() void {
22 const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
33 _ = y;
44}
5export fn entry2() void {
6 const x: [:2]const u8 = &.{ 1, 2 };
7 const y: [:1]const u8 = x;
8 _ = y;
9}
510
611// error
712// backend=stage2
813// target=native
914//
10// :2:29: error: expected type '[:1]const u8', found '*const [2:2]u8'
11// :2:29: note: pointer sentinel '2' cannot cast into pointer sentinel '1'
15// :2:37: error: expected type '[2:1]u8', found '[2:2]u8'
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 {
2828// target=native
2929//
3030// :10:20: error: union initializer must initialize one field
31// :1:12: note: union declared here
3231// :14:20: error: cannot initialize multiple union fields at once; unions can only have one active field
3332// :14:31: note: additional initializer here
3433// :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 {
3232// backend=stage2
3333// target=native
3434//
35// :11:21: error: cannot initialize 'noreturn' field of union
35// :11:14: error: cannot initialize 'noreturn' field of union
3636// :4:9: note: field 'b' declared here
3737// :2:15: note: union declared here
3838// :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 {
77// backend=stage2
88// target=native
99//
10// :3:51: error: expected type 'builtin.GlobalLinkage', found 'u32'
10// :3:41: error: expected type 'builtin.GlobalLinkage', found 'u32'
1111// :?:?: note: enum declared here
test/compile_errors.zig+2-4
......@@ -207,10 +207,8 @@ pub fn addCases(ctx: *Cases) !void {
207207 ":1:38: note: declared comptime here",
208208 ":8:36: error: runtime-known argument passed to comptime parameter",
209209 ":2:41: note: declared comptime here",
210 ":13:29: error: runtime-known argument passed to parameter of comptime-only type",
211 ":3:24: note: declared here",
212 ":12:35: note: struct requires comptime because of this field",
213 ":12:35: note: types are not available at runtime",
210 ":13:32: error: unable to resolve comptime value",
211 ":13:32: note: initializer of comptime only struct must be comptime-known",
214212 });
215213
216214 case.addSourceFile("import.zig",
test/tests.zig+5
......@@ -1034,6 +1034,11 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
10341034
10351035 these_tests.addIncludePath(.{ .path = "test" });
10361036
1037 if (test_target.target.getOs().tag == .wasi) {
1038 // WASI's default stack size can be too small for some big tests.
1039 these_tests.stack_size = 2 * 1024 * 1024;
1040 }
1041
10371042 const qualified_name = b.fmt("{s}-{s}-{s}{s}{s}{s}", .{
10381043 options.name,
10391044 triple_txt,