mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
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
This commit is contained in:
parent
00720c52f6
commit
6d3586e0ed
@ -1018,6 +1018,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||
.shl_with_overflow,
|
||||
.ptr_add,
|
||||
.ptr_sub,
|
||||
.try_ptr,
|
||||
=> return air.getRefType(datas[inst].ty_pl.ty),
|
||||
|
||||
.not,
|
||||
@ -1055,7 +1056,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||
.popcount,
|
||||
.byte_swap,
|
||||
.bit_reverse,
|
||||
.try_ptr,
|
||||
=> return air.getRefType(datas[inst].ty_op.ty),
|
||||
|
||||
.loop,
|
||||
|
||||
@ -2426,7 +2426,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
|
||||
.ret_ptr,
|
||||
.ret_type,
|
||||
.@"try",
|
||||
.try_inline,
|
||||
.try_ptr,
|
||||
//.try_inline,
|
||||
//.try_ptr_inline,
|
||||
=> break :b false,
|
||||
|
||||
.extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) {
|
||||
@ -4880,7 +4882,16 @@ fn tryExpr(
|
||||
// This could be a pointer or value depending on the `rl` parameter.
|
||||
const operand = try expr(parent_gz, scope, operand_rl, operand_node);
|
||||
const is_inline = parent_gz.force_comptime;
|
||||
const block_tag: Zir.Inst.Tag = if (is_inline) .try_inline else .@"try";
|
||||
const is_inline_bit = @as(u2, @boolToInt(is_inline));
|
||||
const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref)) << 1;
|
||||
const block_tag: Zir.Inst.Tag = switch (is_inline_bit | is_ptr_bit) {
|
||||
0b00 => .@"try",
|
||||
0b01 => .@"try",
|
||||
//0b01 => .try_inline,
|
||||
0b10 => .try_ptr,
|
||||
0b11 => .try_ptr,
|
||||
//0b11 => .try_ptr_inline,
|
||||
};
|
||||
const try_inst = try parent_gz.makeBlockInst(block_tag, node);
|
||||
try parent_gz.instructions.append(astgen.gpa, try_inst);
|
||||
|
||||
@ -4897,7 +4908,10 @@ fn tryExpr(
|
||||
|
||||
try else_scope.setTryBody(try_inst, operand);
|
||||
const result = indexToRef(try_inst);
|
||||
return rvalue(parent_gz, rl, result, node);
|
||||
switch (rl) {
|
||||
.ref => return result,
|
||||
else => return rvalue(parent_gz, rl, result, node),
|
||||
}
|
||||
}
|
||||
|
||||
fn orelseCatchExpr(
|
||||
|
||||
97
src/Sema.zig
97
src/Sema.zig
@ -1323,28 +1323,18 @@ fn analyzeBodyInner(
|
||||
}
|
||||
},
|
||||
.@"try" => blk: {
|
||||
if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
|
||||
if (!block.is_comptime) break :blk try sema.zirTry(block, inst, false);
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
|
||||
const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
|
||||
const operand = try sema.resolveInst(extra.data.operand);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
const is_ptr = operand_ty.zigTypeTag() == .Pointer;
|
||||
const err_union = if (is_ptr)
|
||||
try sema.analyzeLoad(block, src, operand, operand_src)
|
||||
else
|
||||
operand;
|
||||
const err_union = try sema.resolveInst(extra.data.operand);
|
||||
const is_non_err = try sema.analyzeIsNonErr(block, operand_src, err_union);
|
||||
const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
|
||||
if (is_non_err_tv.val.toBool()) {
|
||||
if (is_ptr) {
|
||||
break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
|
||||
} else {
|
||||
const err_union_ty = sema.typeOf(err_union);
|
||||
break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
|
||||
}
|
||||
const err_union_ty = sema.typeOf(err_union);
|
||||
break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
|
||||
}
|
||||
const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
|
||||
break always_noreturn;
|
||||
@ -1354,28 +1344,50 @@ fn analyzeBodyInner(
|
||||
break break_data.inst;
|
||||
}
|
||||
},
|
||||
.try_inline => blk: {
|
||||
//.try_inline => blk: {
|
||||
// const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
// const src = inst_data.src();
|
||||
// const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
|
||||
// const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
|
||||
// const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
|
||||
// const operand = try sema.resolveInst(extra.data.operand);
|
||||
// const operand_ty = sema.typeOf(operand);
|
||||
// const is_ptr = operand_ty.zigTypeTag() == .Pointer;
|
||||
// const err_union = if (is_ptr)
|
||||
// try sema.analyzeLoad(block, src, operand, operand_src)
|
||||
// else
|
||||
// operand;
|
||||
// const is_non_err = try sema.analyzeIsNonErr(block, operand_src, err_union);
|
||||
// const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
|
||||
// if (is_non_err_tv.val.toBool()) {
|
||||
// if (is_ptr) {
|
||||
// break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
|
||||
// } else {
|
||||
// const err_union_ty = sema.typeOf(err_union);
|
||||
// break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
|
||||
// }
|
||||
// }
|
||||
// const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
|
||||
// break always_noreturn;
|
||||
// if (inst == break_data.block_inst) {
|
||||
// break :blk try sema.resolveInst(break_data.operand);
|
||||
// } else {
|
||||
// break break_data.inst;
|
||||
// }
|
||||
//},
|
||||
.try_ptr => blk: {
|
||||
if (!block.is_comptime) break :blk try sema.zirTry(block, inst, true);
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
|
||||
const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
|
||||
const operand = try sema.resolveInst(extra.data.operand);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
const is_ptr = operand_ty.zigTypeTag() == .Pointer;
|
||||
const err_union = if (is_ptr)
|
||||
try sema.analyzeLoad(block, src, operand, operand_src)
|
||||
else
|
||||
operand;
|
||||
const err_union = try sema.analyzeLoad(block, src, operand, operand_src);
|
||||
const is_non_err = try sema.analyzeIsNonErr(block, operand_src, err_union);
|
||||
const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
|
||||
if (is_non_err_tv.val.toBool()) {
|
||||
if (is_ptr) {
|
||||
break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
|
||||
} else {
|
||||
const err_union_ty = sema.typeOf(err_union);
|
||||
break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
|
||||
}
|
||||
break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
|
||||
}
|
||||
const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
|
||||
break always_noreturn;
|
||||
@ -1385,6 +1397,27 @@ fn analyzeBodyInner(
|
||||
break break_data.inst;
|
||||
}
|
||||
},
|
||||
//.try_ptr_inline => blk: {
|
||||
// const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
// const src = inst_data.src();
|
||||
// const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
|
||||
// const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
|
||||
// const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
|
||||
// const operand = try sema.resolveInst(extra.data.operand);
|
||||
// const err_union = try sema.analyzeLoad(block, src, operand, operand_src);
|
||||
// const is_non_err = try sema.analyzeIsNonErr(block, operand_src, err_union);
|
||||
// const is_non_err_tv = try sema.resolveInstConst(block, operand_src, is_non_err);
|
||||
// if (is_non_err_tv.val.toBool()) {
|
||||
// break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
|
||||
// }
|
||||
// const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
|
||||
// break always_noreturn;
|
||||
// if (inst == break_data.block_inst) {
|
||||
// break :blk try sema.resolveInst(break_data.operand);
|
||||
// } else {
|
||||
// break break_data.inst;
|
||||
// }
|
||||
//},
|
||||
};
|
||||
if (sema.typeOf(air_inst).isNoReturn())
|
||||
break always_noreturn;
|
||||
@ -13032,15 +13065,18 @@ fn zirCondbr(
|
||||
return always_noreturn;
|
||||
}
|
||||
|
||||
fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref {
|
||||
fn zirTry(
|
||||
sema: *Sema,
|
||||
parent_block: *Block,
|
||||
inst: Zir.Inst.Index,
|
||||
is_ptr: bool,
|
||||
) CompileError!Zir.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
|
||||
const body = sema.code.extra[extra.end..][0..extra.data.body_len];
|
||||
const operand = try sema.resolveInst(extra.data.operand);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
const is_ptr = operand_ty.zigTypeTag() == .Pointer;
|
||||
const err_union = if (is_ptr)
|
||||
try sema.analyzeLoad(parent_block, src, operand, operand_src)
|
||||
else
|
||||
@ -13073,6 +13109,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
|
||||
_ = try sema.analyzeBodyInner(&sub_block, body);
|
||||
|
||||
if (is_ptr) {
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
const ptr_info = operand_ty.ptrInfo().data;
|
||||
const res_ty = try Type.ptr(sema.arena, sema.mod, .{
|
||||
.pointee_type = err_union_ty.errorUnionPayload(),
|
||||
|
||||
26
src/Zir.zig
26
src/Zir.zig
@ -328,10 +328,14 @@ pub const Inst = struct {
|
||||
/// payload value, as if `err_union_payload_unsafe` was executed on the operand.
|
||||
/// Uses the `pl_node` union field. Payload is `Try`.
|
||||
@"try",
|
||||
/// Same as `try` except the operand is coerced to a comptime value, and
|
||||
/// only the taken branch is analyzed. The block must terminate with an "inline"
|
||||
/// variant of a noreturn instruction.
|
||||
try_inline,
|
||||
///// Same as `try` except the operand is coerced to a comptime value, and
|
||||
///// only the taken branch is analyzed. The block must terminate with an "inline"
|
||||
///// variant of a noreturn instruction.
|
||||
//try_inline,
|
||||
/// Same as `try` except the operand is a pointer and the result is a pointer.
|
||||
try_ptr,
|
||||
///// Same as `try_inline` except the operand is a pointer and the result is a pointer.
|
||||
//try_ptr_inline,
|
||||
/// An error set type definition. Contains a list of field names.
|
||||
/// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
|
||||
error_set_decl,
|
||||
@ -1245,7 +1249,9 @@ pub const Inst = struct {
|
||||
.ret_ptr,
|
||||
.ret_type,
|
||||
.@"try",
|
||||
.try_inline,
|
||||
.try_ptr,
|
||||
//.try_inline,
|
||||
//.try_ptr_inline,
|
||||
=> false,
|
||||
|
||||
.@"break",
|
||||
@ -1525,7 +1531,9 @@ pub const Inst = struct {
|
||||
.repeat_inline,
|
||||
.panic,
|
||||
.@"try",
|
||||
.try_inline,
|
||||
.try_ptr,
|
||||
//.try_inline,
|
||||
//.try_ptr_inline,
|
||||
=> false,
|
||||
|
||||
.extended => switch (data.extended.opcode) {
|
||||
@ -1587,7 +1595,9 @@ pub const Inst = struct {
|
||||
.condbr = .pl_node,
|
||||
.condbr_inline = .pl_node,
|
||||
.@"try" = .pl_node,
|
||||
.try_inline = .pl_node,
|
||||
.try_ptr = .pl_node,
|
||||
//.try_inline = .pl_node,
|
||||
//.try_ptr_inline = .pl_node,
|
||||
.error_set_decl = .pl_node,
|
||||
.error_set_decl_anon = .pl_node,
|
||||
.error_set_decl_func = .pl_node,
|
||||
@ -3766,7 +3776,7 @@ fn findDeclsInner(
|
||||
try zir.findDeclsBody(list, then_body);
|
||||
try zir.findDeclsBody(list, else_body);
|
||||
},
|
||||
.@"try", .try_inline => {
|
||||
.@"try", .try_ptr => {
|
||||
const inst_data = datas[inst].pl_node;
|
||||
const extra = zir.extraData(Inst.Try, inst_data.payload_index);
|
||||
const body = zir.extra[extra.end..][0..extra.data.body_len];
|
||||
|
||||
@ -381,7 +381,7 @@ const Writer = struct {
|
||||
=> try self.writeCondBr(stream, inst),
|
||||
|
||||
.@"try",
|
||||
.try_inline,
|
||||
.try_ptr,
|
||||
=> try self.writeTry(stream, inst),
|
||||
|
||||
.error_set_decl => try self.writeErrorSetDecl(stream, inst, .parent),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user