| ... | ... | @@ -3187,12 +3187,32 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 3187 | 3187 | const tracy = trace(@src()); |
| 3188 | 3188 | defer tracy.end(); |
| 3189 | 3189 | |
| 3190 | | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 3190 | const zir_tags = sema.code.instructions.items(.tag); |
| 3191 | const zir_datas = sema.code.instructions.items(.data); |
| 3192 | const inst_data = zir_datas[inst].pl_node; |
| 3191 | 3193 | const src = inst_data.src(); |
| 3192 | 3194 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 3193 | 3195 | const ptr = sema.resolveInst(extra.lhs); |
| 3194 | | const value = sema.resolveInst(extra.rhs); |
| 3195 | | return sema.storePtr(block, src, ptr, value); |
| 3196 | const operand = sema.resolveInst(extra.rhs); |
| 3197 | |
| 3198 | // Check for the possibility of this pattern: |
| 3199 | // %a = ret_ptr |
| 3200 | // %b = store(%a, %c) |
| 3201 | // Where %c is an error union. In such case we need to add to the current function's |
| 3202 | // inferred error set, if any. |
| 3203 | if (sema.typeOf(operand).zigTypeTag() == .ErrorUnion and |
| 3204 | sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) |
| 3205 | { |
| 3206 | if (Zir.refToIndex(extra.lhs)) |ptr_index| { |
| 3207 | if (zir_tags[ptr_index] == .extended and |
| 3208 | zir_datas[ptr_index].extended.opcode == .ret_ptr) |
| 3209 | { |
| 3210 | try sema.addToInferredErrorSet(operand); |
| 3211 | } |
| 3212 | } |
| 3213 | } |
| 3214 | |
| 3215 | return sema.storePtr(block, src, ptr, operand); |
| 3196 | 3216 | } |
| 3197 | 3217 | |
| 3198 | 3218 | fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -10400,6 +10420,23 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir |
| 10400 | 10420 | return always_noreturn; |
| 10401 | 10421 | } |
| 10402 | 10422 | |
| 10423 | fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void { |
| 10424 | assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion); |
| 10425 | |
| 10426 | if (sema.fn_ret_ty.errorUnionSet().castTag(.error_set_inferred)) |payload| { |
| 10427 | const op_ty = sema.typeOf(uncasted_operand); |
| 10428 | switch (op_ty.zigTypeTag()) { |
| 10429 | .ErrorSet => { |
| 10430 | try payload.data.addErrorSet(sema.gpa, op_ty); |
| 10431 | }, |
| 10432 | .ErrorUnion => { |
| 10433 | try payload.data.addErrorSet(sema.gpa, op_ty.errorUnionSet()); |
| 10434 | }, |
| 10435 | else => {}, |
| 10436 | } |
| 10437 | } |
| 10438 | } |
| 10439 | |
| 10403 | 10440 | fn analyzeRet( |
| 10404 | 10441 | sema: *Sema, |
| 10405 | 10442 | block: *Block, |
| ... | ... | @@ -10410,18 +10447,7 @@ fn analyzeRet( |
| 10410 | 10447 | // add the error tag to the inferred error set of the in-scope function, so |
| 10411 | 10448 | // that the coercion below works correctly. |
| 10412 | 10449 | if (sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) { |
| 10413 | | if (sema.fn_ret_ty.errorUnionSet().castTag(.error_set_inferred)) |payload| { |
| 10414 | | const op_ty = sema.typeOf(uncasted_operand); |
| 10415 | | switch (op_ty.zigTypeTag()) { |
| 10416 | | .ErrorSet => { |
| 10417 | | try payload.data.addErrorSet(sema.gpa, op_ty); |
| 10418 | | }, |
| 10419 | | .ErrorUnion => { |
| 10420 | | try payload.data.addErrorSet(sema.gpa, op_ty.errorUnionSet()); |
| 10421 | | }, |
| 10422 | | else => {}, |
| 10423 | | } |
| 10424 | | } |
| 10450 | try sema.addToInferredErrorSet(uncasted_operand); |
| 10425 | 10451 | } |
| 10426 | 10452 | const operand = try sema.coerce(block, sema.fn_ret_ty, uncasted_operand, src); |
| 10427 | 10453 | |
| ... | ... | @@ -14355,9 +14381,32 @@ fn coerce( |
| 14355 | 14381 | }, |
| 14356 | 14382 | else => {}, |
| 14357 | 14383 | }, |
| 14358 | | .ErrorUnion => { |
| 14359 | | // T to E!T or E to E!T |
| 14360 | | return sema.wrapErrorUnion(block, dest_ty, inst, inst_src); |
| 14384 | .ErrorUnion => switch (inst_ty.zigTypeTag()) { |
| 14385 | .ErrorUnion => { |
| 14386 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |inst_val| { |
| 14387 | switch (inst_val.tag()) { |
| 14388 | .undef => return sema.addConstUndef(dest_ty), |
| 14389 | .eu_payload => { |
| 14390 | const payload = try sema.addConstant( |
| 14391 | inst_ty.errorUnionPayload(), |
| 14392 | inst_val.castTag(.eu_payload).?.data, |
| 14393 | ); |
| 14394 | return sema.wrapErrorUnion(block, dest_ty, payload, inst_src); |
| 14395 | }, |
| 14396 | else => { |
| 14397 | const error_set = try sema.addConstant( |
| 14398 | inst_ty.errorUnionSet(), |
| 14399 | inst_val, |
| 14400 | ); |
| 14401 | return sema.wrapErrorUnion(block, dest_ty, error_set, inst_src); |
| 14402 | }, |
| 14403 | } |
| 14404 | } |
| 14405 | }, |
| 14406 | else => { |
| 14407 | // T to E!T or E to E!T |
| 14408 | return sema.wrapErrorUnion(block, dest_ty, inst, inst_src); |
| 14409 | }, |
| 14361 | 14410 | }, |
| 14362 | 14411 | .Union => switch (inst_ty.zigTypeTag()) { |
| 14363 | 14412 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), |