@@ -1177,6 +1177,8 @@ fn analyzeBodyInner(
1177
1177
.validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst),
1178
1178
.opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst),
1179
1179
.coerce_ptr_elem_ty => try sema.zirCoercePtrElemTy(block, inst),
1180
+ .try_operand_ty => try sema.zirTryOperandTy(block, inst, false),
1181
+ .try_ref_operand_ty => try sema.zirTryOperandTy(block, inst, true),
1180
1182
1181
1183
.clz => try sema.zirBitCount(block, inst, .clz, Value.clz),
1182
1184
.ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),
@@ -2024,6 +2026,22 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi
2024
2026
const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2025
2027
cur = un_node.operand;
2026
2028
},
2029
+ .try_operand_ty => {
2030
+ // Either the input type was itself poison, or it was a slice, which we cannot translate
2031
+ // to an overall result type.
2032
+ const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2033
+ const operand_ref = sema.resolveInst(un_node.operand) catch |err| switch (err) {
2034
+ error.GenericPoison => unreachable, // this is a type, not a value
2035
+ };
2036
+ if (operand_ref == .generic_poison_type) {
2037
+ // The input was poison -- keep looking.
2038
+ cur = un_node.operand;
2039
+ continue;
2040
+ }
2041
+ // We got a poison because the result type was a slice. This is a tricky case -- let's just
2042
+ // not bother explaining it to the user for now...
2043
+ return .unknown;
2044
+ },
2027
2045
.struct_init_field_type => {
2028
2046
const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2029
2047
const extra = sema.code.extraData(Zir.Inst.FieldType, pl_node.payload_index).data;
@@ -4423,6 +4441,59 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
4423
4441
}
4424
4442
}
4425
4443
4444
+ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref {
4445
+ const pt = sema.pt;
4446
+ const zcu = pt.zcu;
4447
+ const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
4448
+ const src = block.nodeOffset(un_node.src_node);
4449
+
4450
+ const operand_ty = sema.resolveType(block, src, un_node.operand) catch |err| switch (err) {
4451
+ error.GenericPoison => return .generic_poison_type,
4452
+ else => |e| return e,
4453
+ };
4454
+
4455
+ const payload_ty = if (is_ref) ty: {
4456
+ if (!operand_ty.isSinglePointer(zcu)) {
4457
+ return .generic_poison_type; // we can't get a meaningful result type here, since it will be `*E![n]T`, and we don't know `n`.
4458
+ }
4459
+ break :ty operand_ty.childType(zcu);
4460
+ } else operand_ty;
4461
+
4462
+ const err_set_ty = err_set: {
4463
+ // There are awkward cases, like `?E`. Our strategy is to repeatedly unwrap optionals
4464
+ // until we hit an error union or set.
4465
+ var cur_ty = sema.fn_ret_ty;
4466
+ while (true) {
4467
+ switch (cur_ty.zigTypeTag(zcu)) {
4468
+ .error_set => break :err_set cur_ty,
4469
+ .error_union => break :err_set cur_ty.errorUnionSet(zcu),
4470
+ .optional => cur_ty = cur_ty.optionalChild(zcu),
4471
+ else => return sema.failWithOwnedErrorMsg(block, msg: {
4472
+ const msg = try sema.errMsg(src, "expected '{}', found error set", .{sema.fn_ret_ty.fmt(pt)});
4473
+ errdefer msg.destroy(sema.gpa);
4474
+ const ret_ty_src: LazySrcLoc = .{
4475
+ .base_node_inst = sema.getOwnerFuncDeclInst(),
4476
+ .offset = .{ .node_offset_fn_type_ret_ty = 0 },
4477
+ };
4478
+ try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{});
4479
+ break :msg msg;
4480
+ }),
4481
+ }
4482
+ }
4483
+ };
4484
+
4485
+ const eu_ty = try pt.errorUnionType(err_set_ty, payload_ty);
4486
+
4487
+ if (is_ref) {
4488
+ var ptr_info = operand_ty.ptrInfo(zcu);
4489
+ ptr_info.child = eu_ty.toIntern();
4490
+ const eu_ptr_ty = try pt.ptrTypeSema(ptr_info);
4491
+ return Air.internedToRef(eu_ptr_ty.toIntern());
4492
+ } else {
4493
+ return Air.internedToRef(eu_ty.toIntern());
4494
+ }
4495
+ }
4496
+
4426
4497
fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
4427
4498
const pt = sema.pt;
4428
4499
const zcu = pt.zcu;
0 commit comments