authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-02 19:40:18-07:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-05 10:37:08+02:00
log6d3586e0edf3278862a3a969debaa842014f8110
treebcfd155cf39aebb455c36df4dbdae43a3d499baa
parent00720c52f6333c314aee68de31ef505b2665e44e

explicit "_ptr" variants of ZIR try instruction

* Introduce "_ptr" variants of ZIR try instruction to disallow constructs such as `try` on a pointer value instead of an error union value. * Disable the "_inline" variants of the ZIR try instruction for now because we are out of ZIR tags. I will free up some space in an independent commit. * AstGen: fix tryExpr calling rvalue() on ResultLoc.ref

5 files changed, 104 insertions(+), 43 deletions(-)

src/Air.zig+1-1
......@@ -1018,6 +1018,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
10181018 .shl_with_overflow,
10191019 .ptr_add,
10201020 .ptr_sub,
1021 .try_ptr,
10211022 => return air.getRefType(datas[inst].ty_pl.ty),
10221023
10231024 .not,
......@@ -1055,7 +1056,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
10551056 .popcount,
10561057 .byte_swap,
10571058 .bit_reverse,
1058 .try_ptr,
10591059 => return air.getRefType(datas[inst].ty_op.ty),
10601060
10611061 .loop,
src/AstGen.zig+17-3
......@@ -2426,7 +2426,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
24262426 .ret_ptr,
24272427 .ret_type,
24282428 .@"try",
2429 .try_inline,
2429 .try_ptr,
2430 //.try_inline,
2431 //.try_ptr_inline,
24302432 => break :b false,
24312433
24322434 .extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) {
......@@ -4880,7 +4882,16 @@ fn tryExpr(
48804882 // This could be a pointer or value depending on the `rl` parameter.
48814883 const operand = try expr(parent_gz, scope, operand_rl, operand_node);
48824884 const is_inline = parent_gz.force_comptime;
4883 const block_tag: Zir.Inst.Tag = if (is_inline) .try_inline else .@"try";
4885 const is_inline_bit = @as(u2, @boolToInt(is_inline));
4886 const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref)) << 1;
4887 const block_tag: Zir.Inst.Tag = switch (is_inline_bit | is_ptr_bit) {
4888 0b00 => .@"try",
4889 0b01 => .@"try",
4890 //0b01 => .try_inline,
4891 0b10 => .try_ptr,
4892 0b11 => .try_ptr,
4893 //0b11 => .try_ptr_inline,
4894 };
48844895 const try_inst = try parent_gz.makeBlockInst(block_tag, node);
48854896 try parent_gz.instructions.append(astgen.gpa, try_inst);
48864897
......@@ -4897,7 +4908,10 @@ fn tryExpr(
48974908
48984909 try else_scope.setTryBody(try_inst, operand);
48994910 const result = indexToRef(try_inst);
4900 return rvalue(parent_gz, rl, result, node);
4911 switch (rl) {
4912 .ref => return result,
4913 else => return rvalue(parent_gz, rl, result, node),
4914 }
49014915}
49024916
49034917fn orelseCatchExpr(
src/Sema.zig+67-30
......@@ -1323,28 +1323,18 @@ fn analyzeBodyInner(
13231323 }
13241324 },
13251325 .@"try" => blk: {
1326 if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
1326 if (!block.is_comptime) break :blk try sema.zirTry(block, inst, false);
13271327 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13281328 const src = inst_data.src();
13291329 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
13301330 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
13311331 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
1332 const operand = try sema.resolveInst(extra.data.operand);
1333 const operand_ty = sema.typeOf(operand);
1334 const is_ptr = operand_ty.zigTypeTag() == .Pointer;
1335 const err_union = if (is_ptr)
1336 try sema.analyzeLoad(block, src, operand, operand_src)
1337 else
1338 operand;
1332 const err_union = try sema.resolveInst(extra.data.operand);
13391333 const is_non_err = try sema.analyzeIsNonErr(block, operand_src, err_union);
13401334 const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
13411335 if (is_non_err_tv.val.toBool()) {
1342 if (is_ptr) {
1343 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1344 } else {
1345 const err_union_ty = sema.typeOf(err_union);
1346 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
1347 }
1336 const err_union_ty = sema.typeOf(err_union);
1337 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
13481338 }
13491339 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
13501340 break always_noreturn;
......@@ -1354,28 +1344,50 @@ fn analyzeBodyInner(
13541344 break break_data.inst;
13551345 }
13561346 },
1357 .try_inline => blk: {
1347 //.try_inline => blk: {
1348 // const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1349 // const src = inst_data.src();
1350 // const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
1351 // const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1352 // const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
1353 // const operand = try sema.resolveInst(extra.data.operand);
1354 // const operand_ty = sema.typeOf(operand);
1355 // const is_ptr = operand_ty.zigTypeTag() == .Pointer;
1356 // const err_union = if (is_ptr)
1357 // try sema.analyzeLoad(block, src, operand, operand_src)
1358 // else
1359 // operand;
1360 // const is_non_err = try sema.analyzeIsNonErr(block, operand_src, err_union);
1361 // const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
1362 // if (is_non_err_tv.val.toBool()) {
1363 // if (is_ptr) {
1364 // break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1365 // } else {
1366 // const err_union_ty = sema.typeOf(err_union);
1367 // break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
1368 // }
1369 // }
1370 // const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1371 // break always_noreturn;
1372 // if (inst == break_data.block_inst) {
1373 // break :blk try sema.resolveInst(break_data.operand);
1374 // } else {
1375 // break break_data.inst;
1376 // }
1377 //},
1378 .try_ptr => blk: {
1379 if (!block.is_comptime) break :blk try sema.zirTry(block, inst, true);
13581380 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13591381 const src = inst_data.src();
13601382 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
13611383 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
13621384 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
13631385 const operand = try sema.resolveInst(extra.data.operand);
1364 const operand_ty = sema.typeOf(operand);
1365 const is_ptr = operand_ty.zigTypeTag() == .Pointer;
1366 const err_union = if (is_ptr)
1367 try sema.analyzeLoad(block, src, operand, operand_src)
1368 else
1369 operand;
1386 const err_union = try sema.analyzeLoad(block, src, operand, operand_src);
13701387 const is_non_err = try sema.analyzeIsNonErr(block, operand_src, err_union);
13711388 const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
13721389 if (is_non_err_tv.val.toBool()) {
1373 if (is_ptr) {
1374 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1375 } else {
1376 const err_union_ty = sema.typeOf(err_union);
1377 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
1378 }
1390 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
13791391 }
13801392 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
13811393 break always_noreturn;
......@@ -1385,6 +1397,27 @@ fn analyzeBodyInner(
13851397 break break_data.inst;
13861398 }
13871399 },
1400 //.try_ptr_inline => blk: {
1401 // const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1402 // const src = inst_data.src();
1403 // const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
1404 // const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1405 // const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
1406 // const operand = try sema.resolveInst(extra.data.operand);
1407 // const err_union = try sema.analyzeLoad(block, src, operand, operand_src);
1408 // const is_non_err = try sema.analyzeIsNonErr(block, operand_src, err_union);
1409 // const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
1410 // if (is_non_err_tv.val.toBool()) {
1411 // break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1412 // }
1413 // const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1414 // break always_noreturn;
1415 // if (inst == break_data.block_inst) {
1416 // break :blk try sema.resolveInst(break_data.operand);
1417 // } else {
1418 // break break_data.inst;
1419 // }
1420 //},
13881421 };
13891422 if (sema.typeOf(air_inst).isNoReturn())
13901423 break always_noreturn;
......@@ -13032,15 +13065,18 @@ fn zirCondbr(
1303213065 return always_noreturn;
1303313066}
1303413067
13035fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref {
13068fn zirTry(
13069 sema: *Sema,
13070 parent_block: *Block,
13071 inst: Zir.Inst.Index,
13072 is_ptr: bool,
13073) CompileError!Zir.Inst.Ref {
1303613074 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1303713075 const src = inst_data.src();
1303813076 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
1303913077 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1304013078 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
1304113079 const operand = try sema.resolveInst(extra.data.operand);
13042 const operand_ty = sema.typeOf(operand);
13043 const is_ptr = operand_ty.zigTypeTag() == .Pointer;
1304413080 const err_union = if (is_ptr)
1304513081 try sema.analyzeLoad(parent_block, src, operand, operand_src)
1304613082 else
......@@ -13073,6 +13109,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1307313109 _ = try sema.analyzeBodyInner(&sub_block, body);
1307413110
1307513111 if (is_ptr) {
13112 const operand_ty = sema.typeOf(operand);
1307613113 const ptr_info = operand_ty.ptrInfo().data;
1307713114 const res_ty = try Type.ptr(sema.arena, sema.mod, .{
1307813115 .pointee_type = err_union_ty.errorUnionPayload(),
src/Zir.zig+18-8
......@@ -328,10 +328,14 @@ pub const Inst = struct {
328328 /// payload value, as if `err_union_payload_unsafe` was executed on the operand.
329329 /// Uses the `pl_node` union field. Payload is `Try`.
330330 @"try",
331 /// Same as `try` except the operand is coerced to a comptime value, and
332 /// only the taken branch is analyzed. The block must terminate with an "inline"
333 /// variant of a noreturn instruction.
334 try_inline,
331 ///// Same as `try` except the operand is coerced to a comptime value, and
332 ///// only the taken branch is analyzed. The block must terminate with an "inline"
333 ///// variant of a noreturn instruction.
334 //try_inline,
335 /// Same as `try` except the operand is a pointer and the result is a pointer.
336 try_ptr,
337 ///// Same as `try_inline` except the operand is a pointer and the result is a pointer.
338 //try_ptr_inline,
335339 /// An error set type definition. Contains a list of field names.
336340 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
337341 error_set_decl,
......@@ -1245,7 +1249,9 @@ pub const Inst = struct {
12451249 .ret_ptr,
12461250 .ret_type,
12471251 .@"try",
1248 .try_inline,
1252 .try_ptr,
1253 //.try_inline,
1254 //.try_ptr_inline,
12491255 => false,
12501256
12511257 .@"break",
......@@ -1525,7 +1531,9 @@ pub const Inst = struct {
15251531 .repeat_inline,
15261532 .panic,
15271533 .@"try",
1528 .try_inline,
1534 .try_ptr,
1535 //.try_inline,
1536 //.try_ptr_inline,
15291537 => false,
15301538
15311539 .extended => switch (data.extended.opcode) {
......@@ -1587,7 +1595,9 @@ pub const Inst = struct {
15871595 .condbr = .pl_node,
15881596 .condbr_inline = .pl_node,
15891597 .@"try" = .pl_node,
1590 .try_inline = .pl_node,
1598 .try_ptr = .pl_node,
1599 //.try_inline = .pl_node,
1600 //.try_ptr_inline = .pl_node,
15911601 .error_set_decl = .pl_node,
15921602 .error_set_decl_anon = .pl_node,
15931603 .error_set_decl_func = .pl_node,
......@@ -3766,7 +3776,7 @@ fn findDeclsInner(
37663776 try zir.findDeclsBody(list, then_body);
37673777 try zir.findDeclsBody(list, else_body);
37683778 },
3769 .@"try", .try_inline => {
3779 .@"try", .try_ptr => {
37703780 const inst_data = datas[inst].pl_node;
37713781 const extra = zir.extraData(Inst.Try, inst_data.payload_index);
37723782 const body = zir.extra[extra.end..][0..extra.data.body_len];
src/print_zir.zig+1-1
......@@ -381,7 +381,7 @@ const Writer = struct {
381381 => try self.writeCondBr(stream, inst),
382382
383383 .@"try",
384 .try_inline,
384 .try_ptr,
385385 => try self.writeTry(stream, inst),
386386
387387 .error_set_decl => try self.writeErrorSetDecl(stream, inst, .parent),