| ... | @@ -1323,7 +1323,7 @@ fn analyzeBodyInner( | ... | @@ -1323,7 +1323,7 @@ fn analyzeBodyInner( |
| 1323 | } | 1323 | } |
| 1324 | }, | 1324 | }, |
| 1325 | .@"try" => blk: { | 1325 | .@"try" => blk: { |
| 1326 | if (!block.is_comptime) break :blk try sema.zirTry(block, inst, false); | 1326 | if (!block.is_comptime) break :blk try sema.zirTry(block, inst); |
| 1327 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 1327 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 1328 | const src = inst_data.src(); | 1328 | const src = inst_data.src(); |
| 1329 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 1329 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| ... | @@ -1376,7 +1376,7 @@ fn analyzeBodyInner( | ... | @@ -1376,7 +1376,7 @@ fn analyzeBodyInner( |
| 1376 | // } | 1376 | // } |
| 1377 | //}, | 1377 | //}, |
| 1378 | .try_ptr => blk: { | 1378 | .try_ptr => blk: { |
| 1379 | if (!block.is_comptime) break :blk try sema.zirTry(block, inst, true); | 1379 | if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst); |
| 1380 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 1380 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 1381 | const src = inst_data.src(); | 1381 | const src = inst_data.src(); |
| 1382 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 1382 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| ... | @@ -13065,22 +13065,13 @@ fn zirCondbr( | ... | @@ -13065,22 +13065,13 @@ fn zirCondbr( |
| 13065 | return always_noreturn; | 13065 | return always_noreturn; |
| 13066 | } | 13066 | } |
| 13067 | | 13067 | |
| 13068 | fn zirTry( | 13068 | fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref { |
| 13069 | sema: *Sema, | | |
| 13070 | parent_block: *Block, | | |
| 13071 | inst: Zir.Inst.Index, | | |
| 13072 | is_ptr: bool, | | |
| 13073 | ) CompileError!Zir.Inst.Ref { | | |
| 13074 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 13069 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 13075 | const src = inst_data.src(); | 13070 | const src = inst_data.src(); |
| 13076 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 13071 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 13077 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); | 13072 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 13078 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; | 13073 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| 13079 | const operand = try sema.resolveInst(extra.data.operand); | 13074 | const err_union = try sema.resolveInst(extra.data.operand); |
| 13080 | const err_union = if (is_ptr) | | |
| 13081 | try sema.analyzeLoad(parent_block, src, operand, operand_src) | | |
| 13082 | else | | |
| 13083 | operand; | | |
| 13084 | const err_union_ty = sema.typeOf(err_union); | 13075 | const err_union_ty = sema.typeOf(err_union); |
| 13085 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { | 13076 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { |
| 13086 | return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ | 13077 | return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ |
| ... | @@ -13091,11 +13082,7 @@ fn zirTry( | ... | @@ -13091,11 +13082,7 @@ fn zirTry( |
| 13091 | | 13082 | |
| 13092 | if (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)) |is_non_err_val| { | 13083 | if (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)) |is_non_err_val| { |
| 13093 | if (is_non_err_val.toBool()) { | 13084 | if (is_non_err_val.toBool()) { |
| 13094 | if (is_ptr) { | 13085 | return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, err_union, operand_src, false); |
| 13095 | return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false); | | |
| 13096 | } else { | | |
| 13097 | return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, operand, operand_src, false); | | |
| 13098 | } | | |
| 13099 | } | 13086 | } |
| 13100 | // We can analyze the body directly in the parent block because we know there are | 13087 | // We can analyze the body directly in the parent block because we know there are |
| 13101 | // no breaks from the body possible, and that the body is noreturn. | 13088 | // no breaks from the body possible, and that the body is noreturn. |
| ... | @@ -13108,39 +13095,12 @@ fn zirTry( | ... | @@ -13108,39 +13095,12 @@ fn zirTry( |
| 13108 | // This body is guaranteed to end with noreturn and has no breaks. | 13095 | // This body is guaranteed to end with noreturn and has no breaks. |
| 13109 | _ = try sema.analyzeBodyInner(&sub_block, body); | 13096 | _ = try sema.analyzeBodyInner(&sub_block, body); |
| 13110 | | 13097 | |
| 13111 | if (is_ptr) { | | |
| 13112 | const operand_ty = sema.typeOf(operand); | | |
| 13113 | const ptr_info = operand_ty.ptrInfo().data; | | |
| 13114 | const res_ty = try Type.ptr(sema.arena, sema.mod, .{ | | |
| 13115 | .pointee_type = err_union_ty.errorUnionPayload(), | | |
| 13116 | .@"addrspace" = ptr_info.@"addrspace", | | |
| 13117 | .mutable = ptr_info.mutable, | | |
| 13118 | .@"allowzero" = ptr_info.@"allowzero", | | |
| 13119 | .@"volatile" = ptr_info.@"volatile", | | |
| 13120 | }); | | |
| 13121 | const res_ty_ref = try sema.addType(res_ty); | | |
| 13122 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len + | | |
| 13123 | sub_block.instructions.items.len); | | |
| 13124 | const try_inst = try parent_block.addInst(.{ | | |
| 13125 | .tag = .try_ptr, | | |
| 13126 | .data = .{ .ty_pl = .{ | | |
| 13127 | .ty = res_ty_ref, | | |
| 13128 | .payload = sema.addExtraAssumeCapacity(Air.TryPtr{ | | |
| 13129 | .ptr = operand, | | |
| 13130 | .body_len = @intCast(u32, sub_block.instructions.items.len), | | |
| 13131 | }), | | |
| 13132 | } }, | | |
| 13133 | }); | | |
| 13134 | sema.air_extra.appendSliceAssumeCapacity(sub_block.instructions.items); | | |
| 13135 | return try_inst; | | |
| 13136 | } | | |
| 13137 | | | |
| 13138 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len + | 13098 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len + |
| 13139 | sub_block.instructions.items.len); | 13099 | sub_block.instructions.items.len); |
| 13140 | const try_inst = try parent_block.addInst(.{ | 13100 | const try_inst = try parent_block.addInst(.{ |
| 13141 | .tag = .@"try", | 13101 | .tag = .@"try", |
| 13142 | .data = .{ .pl_op = .{ | 13102 | .data = .{ .pl_op = .{ |
| 13143 | .operand = operand, | 13103 | .operand = err_union, |
| 13144 | .payload = sema.addExtraAssumeCapacity(Air.Try{ | 13104 | .payload = sema.addExtraAssumeCapacity(Air.Try{ |
| 13145 | .body_len = @intCast(u32, sub_block.instructions.items.len), | 13105 | .body_len = @intCast(u32, sub_block.instructions.items.len), |
| 13146 | }), | 13106 | }), |
| ... | @@ -13150,6 +13110,63 @@ fn zirTry( | ... | @@ -13150,6 +13110,63 @@ fn zirTry( |
| 13150 | return try_inst; | 13110 | return try_inst; |
| 13151 | } | 13111 | } |
| 13152 | | 13112 | |
| | 13113 | fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref { |
| | 13114 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| | 13115 | const src = inst_data.src(); |
| | 13116 | const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| | 13117 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| | 13118 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| | 13119 | const operand = try sema.resolveInst(extra.data.operand); |
| | 13120 | const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src); |
| | 13121 | const err_union_ty = sema.typeOf(err_union); |
| | 13122 | if (err_union_ty.zigTypeTag() != .ErrorUnion) { |
| | 13123 | return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{ |
| | 13124 | err_union_ty.fmt(sema.mod), |
| | 13125 | }); |
| | 13126 | } |
| | 13127 | const is_non_err = try sema.analyzeIsNonErr(parent_block, operand_src, err_union); |
| | 13128 | |
| | 13129 | if (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)) |is_non_err_val| { |
| | 13130 | if (is_non_err_val.toBool()) { |
| | 13131 | return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false); |
| | 13132 | } |
| | 13133 | // We can analyze the body directly in the parent block because we know there are |
| | 13134 | // no breaks from the body possible, and that the body is noreturn. |
| | 13135 | return sema.resolveBody(parent_block, body, inst); |
| | 13136 | } |
| | 13137 | |
| | 13138 | var sub_block = parent_block.makeSubBlock(); |
| | 13139 | defer sub_block.instructions.deinit(sema.gpa); |
| | 13140 | |
| | 13141 | // This body is guaranteed to end with noreturn and has no breaks. |
| | 13142 | _ = try sema.analyzeBodyInner(&sub_block, body); |
| | 13143 | |
| | 13144 | const operand_ty = sema.typeOf(operand); |
| | 13145 | const ptr_info = operand_ty.ptrInfo().data; |
| | 13146 | const res_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| | 13147 | .pointee_type = err_union_ty.errorUnionPayload(), |
| | 13148 | .@"addrspace" = ptr_info.@"addrspace", |
| | 13149 | .mutable = ptr_info.mutable, |
| | 13150 | .@"allowzero" = ptr_info.@"allowzero", |
| | 13151 | .@"volatile" = ptr_info.@"volatile", |
| | 13152 | }); |
| | 13153 | const res_ty_ref = try sema.addType(res_ty); |
| | 13154 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.TryPtr).Struct.fields.len + |
| | 13155 | sub_block.instructions.items.len); |
| | 13156 | const try_inst = try parent_block.addInst(.{ |
| | 13157 | .tag = .try_ptr, |
| | 13158 | .data = .{ .ty_pl = .{ |
| | 13159 | .ty = res_ty_ref, |
| | 13160 | .payload = sema.addExtraAssumeCapacity(Air.TryPtr{ |
| | 13161 | .ptr = operand, |
| | 13162 | .body_len = @intCast(u32, sub_block.instructions.items.len), |
| | 13163 | }), |
| | 13164 | } }, |
| | 13165 | }); |
| | 13166 | sema.air_extra.appendSliceAssumeCapacity(sub_block.instructions.items); |
| | 13167 | return try_inst; |
| | 13168 | } |
| | 13169 | |
| 13153 | // A `break` statement is inside a runtime condition, but trying to | 13170 | // A `break` statement is inside a runtime condition, but trying to |
| 13154 | // break from an inline loop. In such case we must convert it to | 13171 | // break from an inline loop. In such case we must convert it to |
| 13155 | // a runtime break. | 13172 | // a runtime break. |