authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-25 12:38:56-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-06-25 12:38:56-07:00
logdf389b62de4430434a6518580e27208101ae2fc8
treed6acb3165d8475643acba4bd7942f4bd5d285b52
parentd07149c56d202c3503c4f5505e8b003b3e161145
parentfec7565da6e27334de63c3635dd2e32325c39c98
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16192 from mlugg/builtins-infer-dest-ty-fixes

Follow-up to cast builtin result type inference

10 files changed, 318 insertions(+), 28 deletions(-)

doc/langref.html.in+1-1
...@@ -10267,7 +10267,7 @@ pub fn main() void {...@@ -10267,7 +10267,7 @@ pub fn main() void {
10267 foo(Set1.B);10267 foo(Set1.B);
10268}10268}
10269fn foo(set1: Set1) void {10269fn foo(set1: Set1) void {
10270 const x = @as(Set2, @errSetCast(set1));10270 const x: Set2 = @errSetCast(set1);
10271 std.debug.print("value: {}\n", .{x});10271 std.debug.print("value: {}\n", .{x});
10272}10272}
10273 {#code_end#}10273 {#code_end#}
src/AstGen.zig+3-11
...@@ -6483,11 +6483,11 @@ fn forExpr(...@@ -6483,11 +6483,11 @@ fn forExpr(
6483 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});6483 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});
6484 }6484 }
6485 const start_node = node_data[input].lhs;6485 const start_node = node_data[input].lhs;
6486 const start_val = try expr(parent_gz, scope, .{ .rl = .none }, start_node);6486 const start_val = try expr(parent_gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, start_node);
64876487
6488 const end_node = node_data[input].rhs;6488 const end_node = node_data[input].rhs;
6489 const end_val = if (end_node != 0)6489 const end_val = if (end_node != 0)
6490 try expr(parent_gz, scope, .{ .rl = .none }, node_data[input].rhs)6490 try expr(parent_gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_data[input].rhs)
6491 else6491 else
6492 .none;6492 .none;
64936493
...@@ -8053,17 +8053,9 @@ fn ptrCast(...@@ -8053,17 +8053,9 @@ fn ptrCast(
8053 }8053 }
80548054
8055 // Full cast including result type8055 // Full cast including result type
8056 const need_result_type_builtin = if (flags.ptr_cast)
8057 "@ptrCast"
8058 else if (flags.align_cast)
8059 "@alignCast"
8060 else if (flags.addrspace_cast)
8061 "@addrSpaceCast"
8062 else
8063 unreachable;
80648056
8065 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);8057 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
8066 const result_type = try ri.rl.resultType(gz, root_node, need_result_type_builtin);8058 const result_type = try ri.rl.resultType(gz, root_node, flags.needResultTypeBuiltinName());
8067 const operand = try expr(gz, scope, .{ .rl = .none }, node);8059 const operand = try expr(gz, scope, .{ .rl = .none }, node);
8068 try emitDbgStmt(gz, cursor);8060 try emitDbgStmt(gz, cursor);
8069 const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_i, Zir.Inst.BinNode{8061 const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_i, Zir.Inst.BinNode{
src/Module.zig+40
...@@ -34,6 +34,7 @@ const isUpDir = @import("introspect.zig").isUpDir;...@@ -34,6 +34,7 @@ const isUpDir = @import("introspect.zig").isUpDir;
34const clang = @import("clang.zig");34const clang = @import("clang.zig");
35const InternPool = @import("InternPool.zig");35const InternPool = @import("InternPool.zig");
36const Alignment = InternPool.Alignment;36const Alignment = InternPool.Alignment;
37const BuiltinFn = @import("BuiltinFn.zig");
3738
38comptime {39comptime {
39 @setEvalBranchQuota(4000);40 @setEvalBranchQuota(4000);
...@@ -2273,6 +2274,41 @@ pub const SrcLoc = struct {...@@ -2273,6 +2274,41 @@ pub const SrcLoc = struct {
2273 .node_offset_builtin_call_arg3 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 3),2274 .node_offset_builtin_call_arg3 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 3),
2274 .node_offset_builtin_call_arg4 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 4),2275 .node_offset_builtin_call_arg4 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 4),
2275 .node_offset_builtin_call_arg5 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 5),2276 .node_offset_builtin_call_arg5 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 5),
2277 .node_offset_ptrcast_operand => |node_off| {
2278 const tree = try src_loc.file_scope.getTree(gpa);
2279 const main_tokens = tree.nodes.items(.main_token);
2280 const node_datas = tree.nodes.items(.data);
2281 const node_tags = tree.nodes.items(.tag);
2282
2283 var node = src_loc.declRelativeToNodeIndex(node_off);
2284 while (true) {
2285 switch (node_tags[node]) {
2286 .builtin_call_two, .builtin_call_two_comma => {},
2287 else => break,
2288 }
2289
2290 if (node_datas[node].lhs == 0) break; // 0 args
2291 if (node_datas[node].rhs != 0) break; // 2 args
2292
2293 const builtin_token = main_tokens[node];
2294 const builtin_name = tree.tokenSlice(builtin_token);
2295 const info = BuiltinFn.list.get(builtin_name) orelse break;
2296
2297 switch (info.tag) {
2298 else => break,
2299 .ptr_cast,
2300 .align_cast,
2301 .addrspace_cast,
2302 .const_cast,
2303 .volatile_cast,
2304 => {},
2305 }
2306
2307 node = node_datas[node].lhs;
2308 }
2309
2310 return nodeToSpan(tree, node);
2311 },
2276 .node_offset_array_access_index => |node_off| {2312 .node_offset_array_access_index => |node_off| {
2277 const tree = try src_loc.file_scope.getTree(gpa);2313 const tree = try src_loc.file_scope.getTree(gpa);
2278 const node_datas = tree.nodes.items(.data);2314 const node_datas = tree.nodes.items(.data);
...@@ -2887,6 +2923,9 @@ pub const LazySrcLoc = union(enum) {...@@ -2887,6 +2923,9 @@ pub const LazySrcLoc = union(enum) {
2887 node_offset_builtin_call_arg3: i32,2923 node_offset_builtin_call_arg3: i32,
2888 node_offset_builtin_call_arg4: i32,2924 node_offset_builtin_call_arg4: i32,
2889 node_offset_builtin_call_arg5: i32,2925 node_offset_builtin_call_arg5: i32,
2926 /// Like `node_offset_builtin_call_arg0` but recurses through arbitrarily many calls
2927 /// to pointer cast builtins.
2928 node_offset_ptrcast_operand: i32,
2890 /// The source location points to the index expression of an array access2929 /// The source location points to the index expression of an array access
2891 /// expression, found by taking this AST node index offset from the containing2930 /// expression, found by taking this AST node index offset from the containing
2892 /// Decl AST node, which points to an array access AST node. Next, navigate2931 /// Decl AST node, which points to an array access AST node. Next, navigate
...@@ -3145,6 +3184,7 @@ pub const LazySrcLoc = union(enum) {...@@ -3145,6 +3184,7 @@ pub const LazySrcLoc = union(enum) {
3145 .node_offset_builtin_call_arg3,3184 .node_offset_builtin_call_arg3,
3146 .node_offset_builtin_call_arg4,3185 .node_offset_builtin_call_arg4,
3147 .node_offset_builtin_call_arg5,3186 .node_offset_builtin_call_arg5,
3187 .node_offset_ptrcast_operand,
3148 .node_offset_array_access_index,3188 .node_offset_array_access_index,
3149 .node_offset_slice_ptr,3189 .node_offset_slice_ptr,
3150 .node_offset_slice_start,3190 .node_offset_slice_start,
src/Sema.zig+45-16
...@@ -1820,8 +1820,25 @@ pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Ins...@@ -1820,8 +1820,25 @@ pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Ins
1820 return ty;1820 return ty;
1821}1821}
18221822
1823fn resolveCastDestType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, builtin_name: []const u8) !Type {1823fn resolveCastDestType(
1824 return sema.resolveType(block, src, zir_ref) catch |err| switch (err) {1824 sema: *Sema,
1825 block: *Block,
1826 src: LazySrcLoc,
1827 zir_ref: Zir.Inst.Ref,
1828 strat: enum { remove_eu_opt, remove_eu, remove_opt },
1829 builtin_name: []const u8,
1830) !Type {
1831 const mod = sema.mod;
1832 const remove_eu = switch (strat) {
1833 .remove_eu_opt, .remove_eu => true,
1834 .remove_opt => false,
1835 };
1836 const remove_opt = switch (strat) {
1837 .remove_eu_opt, .remove_opt => true,
1838 .remove_eu => false,
1839 };
1840
1841 const raw_ty = sema.resolveType(block, src, zir_ref) catch |err| switch (err) {
1825 error.GenericPoison => {1842 error.GenericPoison => {
1826 // Cast builtins use their result type as the destination type, but1843 // Cast builtins use their result type as the destination type, but
1827 // it could be an anytype argument, which we can't catch in AstGen.1844 // it could be an anytype argument, which we can't catch in AstGen.
...@@ -1836,6 +1853,18 @@ fn resolveCastDestType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir...@@ -1836,6 +1853,18 @@ fn resolveCastDestType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir
1836 },1853 },
1837 else => |e| return e,1854 else => |e| return e,
1838 };1855 };
1856
1857 if (remove_eu and raw_ty.zigTypeTag(mod) == .ErrorUnion) {
1858 const eu_child = raw_ty.errorUnionPayload(mod);
1859 if (remove_opt and eu_child.zigTypeTag(mod) == .Optional) {
1860 return eu_child.childType(mod);
1861 }
1862 return eu_child;
1863 }
1864 if (remove_opt and raw_ty.zigTypeTag(mod) == .Optional) {
1865 return raw_ty.childType(mod);
1866 }
1867 return raw_ty;
1839}1868}
18401869
1841fn analyzeAsType(1870fn analyzeAsType(
...@@ -8304,7 +8333,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8304,7 +8333,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8304 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;8333 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
8305 const src = inst_data.src();8334 const src = inst_data.src();
8306 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };8335 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
8307 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@enumFromInt");8336 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt");
8308 const operand = try sema.resolveInst(extra.rhs);8337 const operand = try sema.resolveInst(extra.rhs);
83098338
8310 if (dest_ty.zigTypeTag(mod) != .Enum) {8339 if (dest_ty.zigTypeTag(mod) != .Enum) {
...@@ -9600,7 +9629,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9600,7 +9629,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9600 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };9629 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
9601 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;9630 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
96029631
9603 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@intCast");9632 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast");
9604 const operand = try sema.resolveInst(extra.rhs);9633 const operand = try sema.resolveInst(extra.rhs);
96059634
9606 return sema.intCast(block, inst_data.src(), dest_ty, src, operand, operand_src, true);9635 return sema.intCast(block, inst_data.src(), dest_ty, src, operand, operand_src, true);
...@@ -9761,7 +9790,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9761,7 +9790,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9761 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };9790 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
9762 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;9791 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
97639792
9764 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@bitCast");9793 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast");
9765 const operand = try sema.resolveInst(extra.rhs);9794 const operand = try sema.resolveInst(extra.rhs);
9766 const operand_ty = sema.typeOf(operand);9795 const operand_ty = sema.typeOf(operand);
9767 switch (dest_ty.zigTypeTag(mod)) {9796 switch (dest_ty.zigTypeTag(mod)) {
...@@ -9904,7 +9933,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -9904,7 +9933,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
9904 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };9933 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
9905 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;9934 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
99069935
9907 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@floatCast");9936 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast");
9908 const operand = try sema.resolveInst(extra.rhs);9937 const operand = try sema.resolveInst(extra.rhs);
99099938
9910 const target = mod.getTarget();9939 const target = mod.getTarget();
...@@ -20706,7 +20735,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -20706,7 +20735,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
20706 const src = inst_data.src();20735 const src = inst_data.src();
20707 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;20736 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
20708 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20737 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
20709 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@intFromFloat");20738 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat");
20710 const operand = try sema.resolveInst(extra.rhs);20739 const operand = try sema.resolveInst(extra.rhs);
20711 const operand_ty = sema.typeOf(operand);20740 const operand_ty = sema.typeOf(operand);
2071220741
...@@ -20746,7 +20775,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -20746,7 +20775,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
20746 const src = inst_data.src();20775 const src = inst_data.src();
20747 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;20776 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
20748 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20777 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
20749 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@floatFromInt");20778 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt");
20750 const operand = try sema.resolveInst(extra.rhs);20779 const operand = try sema.resolveInst(extra.rhs);
20751 const operand_ty = sema.typeOf(operand);20780 const operand_ty = sema.typeOf(operand);
2075220781
...@@ -20775,7 +20804,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -20775,7 +20804,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
20775 const operand_res = try sema.resolveInst(extra.rhs);20804 const operand_res = try sema.resolveInst(extra.rhs);
20776 const operand_coerced = try sema.coerce(block, Type.usize, operand_res, operand_src);20805 const operand_coerced = try sema.coerce(block, Type.usize, operand_res, operand_src);
2077720806
20778 const ptr_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@ptrFromInt");20807 const ptr_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt");
20779 try sema.checkPtrType(block, src, ptr_ty);20808 try sema.checkPtrType(block, src, ptr_ty);
20780 const elem_ty = ptr_ty.elemType2(mod);20809 const elem_ty = ptr_ty.elemType2(mod);
20781 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);20810 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);
...@@ -20833,7 +20862,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -20833,7 +20862,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
20833 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;20862 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
20834 const src = LazySrcLoc.nodeOffset(extra.node);20863 const src = LazySrcLoc.nodeOffset(extra.node);
20835 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };20864 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
20836 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@errSetCast");20865 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@errSetCast");
20837 const operand = try sema.resolveInst(extra.rhs);20866 const operand = try sema.resolveInst(extra.rhs);
20838 const operand_ty = sema.typeOf(operand);20867 const operand_ty = sema.typeOf(operand);
20839 try sema.checkErrorSetType(block, src, dest_ty);20868 try sema.checkErrorSetType(block, src, dest_ty);
...@@ -20915,12 +20944,12 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -20915,12 +20944,12 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
20915}20944}
2091620945
20917fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {20946fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20918 const flags = @as(Zir.Inst.FullPtrCastFlags, @bitCast(@as(u5, @truncate(extended.small))));20947 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(u5, @truncate(extended.small)));
20919 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;20948 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
20920 const src = LazySrcLoc.nodeOffset(extra.node);20949 const src = LazySrcLoc.nodeOffset(extra.node);
20921 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };20950 const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node };
20922 const operand = try sema.resolveInst(extra.rhs);20951 const operand = try sema.resolveInst(extra.rhs);
20923 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@ptrCast"); // TODO: better error message (builtin name)20952 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, flags.needResultTypeBuiltinName());
20924 return sema.ptrCastFull(20953 return sema.ptrCastFull(
20925 block,20954 block,
20926 flags,20955 flags,
...@@ -20936,7 +20965,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20936,7 +20965,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20936 const src = inst_data.src();20965 const src = inst_data.src();
20937 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };20966 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
20938 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;20967 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
20939 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@ptrCast");20968 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu, "@ptrCast");
20940 const operand = try sema.resolveInst(extra.rhs);20969 const operand = try sema.resolveInst(extra.rhs);
2094120970
20942 return sema.ptrCastFull(20971 return sema.ptrCastFull(
...@@ -21325,7 +21354,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -21325,7 +21354,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
21325 const flags = @as(Zir.Inst.FullPtrCastFlags, @bitCast(@as(u5, @truncate(extended.small))));21354 const flags = @as(Zir.Inst.FullPtrCastFlags, @bitCast(@as(u5, @truncate(extended.small))));
21326 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;21355 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
21327 const src = LazySrcLoc.nodeOffset(extra.node);21356 const src = LazySrcLoc.nodeOffset(extra.node);
21328 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };21357 const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node };
21329 const operand = try sema.resolveInst(extra.operand);21358 const operand = try sema.resolveInst(extra.operand);
21330 const operand_ty = sema.typeOf(operand);21359 const operand_ty = sema.typeOf(operand);
21331 try sema.checkPtrOperand(block, operand_src, operand_ty);21360 try sema.checkPtrOperand(block, operand_src, operand_ty);
...@@ -21349,7 +21378,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -21349,7 +21378,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
21349 const src = inst_data.src();21378 const src = inst_data.src();
21350 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };21379 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
21351 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;21380 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
21352 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@truncate");21381 const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, .remove_eu_opt, "@truncate");
21353 const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, src);21382 const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, src);
21354 const operand = try sema.resolveInst(extra.rhs);21383 const operand = try sema.resolveInst(extra.rhs);
21355 const operand_ty = sema.typeOf(operand);21384 const operand_ty = sema.typeOf(operand);
src/Zir.zig+7
...@@ -2820,6 +2820,13 @@ pub const Inst = struct {...@@ -2820,6 +2820,13 @@ pub const Inst = struct {
2820 addrspace_cast: bool = false,2820 addrspace_cast: bool = false,
2821 const_cast: bool = false,2821 const_cast: bool = false,
2822 volatile_cast: bool = false,2822 volatile_cast: bool = false,
2823
2824 pub inline fn needResultTypeBuiltinName(flags: FullPtrCastFlags) []const u8 {
2825 if (flags.ptr_cast) return "@ptrCast";
2826 if (flags.align_cast) return "@alignCast";
2827 if (flags.addrspace_cast) return "@addrSpaceCast";
2828 unreachable;
2829 }
2823 };2830 };
28242831
2825 /// Trailing:2832 /// Trailing:
test/behavior/cast.zig+122
...@@ -2219,3 +2219,125 @@ test "peer type resolution: pointer attributes are combined correctly" {...@@ -2219,3 +2219,125 @@ test "peer type resolution: pointer attributes are combined correctly" {
2219 try expectEqualSlices(u8, std.mem.span(@volatileCast(r2)), "bar");2219 try expectEqualSlices(u8, std.mem.span(@volatileCast(r2)), "bar");
2220 try expectEqualSlices(u8, std.mem.span(@volatileCast(r3)), "baz");2220 try expectEqualSlices(u8, std.mem.span(@volatileCast(r3)), "baz");
2221}2221}
2222
2223test "cast builtins can wrap result in optional" {
2224 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2225 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2226 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2227 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2228 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2229 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
2230
2231 const S = struct {
2232 const MyEnum = enum(u32) { _ };
2233 fn a() ?MyEnum {
2234 return @enumFromInt(123);
2235 }
2236 fn b() ?u32 {
2237 return @intFromFloat(42.50);
2238 }
2239 fn c() ?*const f32 {
2240 const x: u32 = 1;
2241 return @ptrCast(&x);
2242 }
2243
2244 fn doTheTest() !void {
2245 const ra = a() orelse return error.ImpossibleError;
2246 const rb = b() orelse return error.ImpossibleError;
2247 const rc = c() orelse return error.ImpossibleError;
2248
2249 comptime assert(@TypeOf(ra) == MyEnum);
2250 comptime assert(@TypeOf(rb) == u32);
2251 comptime assert(@TypeOf(rc) == *const f32);
2252
2253 try expect(@intFromEnum(ra) == 123);
2254 try expect(rb == 42);
2255 try expect(@as(*const u32, @ptrCast(rc)).* == 1);
2256 }
2257 };
2258
2259 try S.doTheTest();
2260 try comptime S.doTheTest();
2261}
2262
2263test "cast builtins can wrap result in error union" {
2264 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2266 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2267 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2269 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
2270
2271 const S = struct {
2272 const MyEnum = enum(u32) { _ };
2273 const E = error{ImpossibleError};
2274 fn a() E!MyEnum {
2275 return @enumFromInt(123);
2276 }
2277 fn b() E!u32 {
2278 return @intFromFloat(42.50);
2279 }
2280 fn c() E!*const f32 {
2281 const x: u32 = 1;
2282 return @ptrCast(&x);
2283 }
2284
2285 fn doTheTest() !void {
2286 const ra = try a();
2287 const rb = try b();
2288 const rc = try c();
2289
2290 comptime assert(@TypeOf(ra) == MyEnum);
2291 comptime assert(@TypeOf(rb) == u32);
2292 comptime assert(@TypeOf(rc) == *const f32);
2293
2294 try expect(@intFromEnum(ra) == 123);
2295 try expect(rb == 42);
2296 try expect(@as(*const u32, @ptrCast(rc)).* == 1);
2297 }
2298 };
2299
2300 try S.doTheTest();
2301 try comptime S.doTheTest();
2302}
2303
2304test "cast builtins can wrap result in error union and optional" {
2305 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2306 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2307 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2308 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2309 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2310 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
2311
2312 const S = struct {
2313 const MyEnum = enum(u32) { _ };
2314 const E = error{ImpossibleError};
2315 fn a() E!?MyEnum {
2316 return @enumFromInt(123);
2317 }
2318 fn b() E!?u32 {
2319 return @intFromFloat(42.50);
2320 }
2321 fn c() E!?*const f32 {
2322 const x: u32 = 1;
2323 return @ptrCast(&x);
2324 }
2325
2326 fn doTheTest() !void {
2327 const ra = try a() orelse return error.ImpossibleError;
2328 const rb = try b() orelse return error.ImpossibleError;
2329 const rc = try c() orelse return error.ImpossibleError;
2330
2331 comptime assert(@TypeOf(ra) == MyEnum);
2332 comptime assert(@TypeOf(rb) == u32);
2333 comptime assert(@TypeOf(rc) == *const f32);
2334
2335 try expect(@intFromEnum(ra) == 123);
2336 try expect(rb == 42);
2337 try expect(@as(*const u32, @ptrCast(rc)).* == 1);
2338 }
2339 };
2340
2341 try S.doTheTest();
2342 try comptime S.doTheTest();
2343}
test/cases/compile_errors/cast_without_result_type.zig created+28
...@@ -0,0 +1,28 @@
1export fn a() void {
2 _ = @ptrFromInt(123);
3}
4export fn b() void {
5 const x = @ptrCast(@alignCast(@as(*u8, undefined)));
6 _ = x;
7}
8export fn c() void {
9 _ = &@intCast(@as(u64, 123));
10 _ = S;
11}
12export fn d() void {
13 var x: f32 = 0;
14 _ = x + @floatFromInt(123);
15}
16
17// error
18// backend=stage2
19// target=native
20//
21// :2:9: error: @ptrFromInt must have a known result type
22// :2:9: note: use @as to provide explicit result type
23// :5:15: error: @ptrCast must have a known result type
24// :5:15: note: use @as to provide explicit result type
25// :9:10: error: @intCast must have a known result type
26// :9:10: note: use @as to provide explicit result type
27// :14:13: error: @floatFromInt must have a known result type
28// :14:13: note: use @as to provide explicit result type
test/cases/compile_errors/cast_without_result_type_due_to_generic_parameter.zig created+31
...@@ -0,0 +1,31 @@
1export fn a() void {
2 bar(@ptrFromInt(123));
3}
4export fn b() void {
5 bar(@ptrCast(@alignCast(@as(*u8, undefined))));
6}
7export fn c() void {
8 bar(@intCast(@as(u64, 123)));
9}
10export fn d() void {
11 bar(@floatFromInt(123));
12}
13
14fn bar(_: anytype) void {}
15
16// error
17// backend=stage2
18// target=native
19//
20// :2:9: error: @ptrFromInt must have a known result type
21// :2:9: note: result type is unknown due to anytype parameter
22// :2:9: note: use @as to provide explicit result type
23// :5:9: error: @ptrCast must have a known result type
24// :5:9: note: result type is unknown due to anytype parameter
25// :5:9: note: use @as to provide explicit result type
26// :8:9: error: @intCast must have a known result type
27// :8:9: note: result type is unknown due to anytype parameter
28// :8:9: note: use @as to provide explicit result type
29// :11:9: error: @floatFromInt must have a known result type
30// :11:9: note: result type is unknown due to anytype parameter
31// :11:9: note: use @as to provide explicit result type
test/cases/compile_errors/nested_ptr_cast_bad_operand.zig created+22
...@@ -0,0 +1,22 @@
1const p: ?*const u8 = null;
2export fn a() void {
3 _ = @as(*const u32, @ptrCast(@alignCast(p)));
4}
5export fn b() void {
6 _ = @constCast(@volatileCast(123));
7}
8export fn c() void {
9 const x: ?*f32 = @constCast(@ptrCast(@addrSpaceCast(@volatileCast(p))));
10 _ = x;
11}
12
13// error
14// backend=stage2
15// target=native
16//
17// :3:45: error: null pointer casted to type '*const u32'
18// :6:34: error: expected pointer type, found 'comptime_int'
19// :9:22: error: cast increases pointer alignment
20// :9:71: note: '?*const u8' has alignment '1'
21// :9:22: note: '?*f32' has alignment '4'
22// :9:22: note: use @alignCast to assert pointer alignment
test/cases/compile_errors/redundant_ptr_cast.zig created+19
...@@ -0,0 +1,19 @@
1const p: *anyopaque = undefined;
2export fn a() void {
3 _ = @ptrCast(@ptrCast(p));
4}
5export fn b() void {
6 const ptr1: *u32 = @alignCast(@ptrCast(@alignCast(p)));
7 _ = ptr1;
8}
9export fn c() void {
10 _ = @constCast(@alignCast(@ptrCast(@constCast(@volatileCast(p)))));
11}
12
13// error
14// backend=stage2
15// target=native
16//
17// :3:18: error: redundant @ptrCast
18// :6:44: error: redundant @alignCast
19// :10:40: error: redundant @constCast