| ... | ... | @@ -4135,23 +4135,24 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 4135 | 4135 | const ptr = try sema.resolveInst(extra.lhs); |
| 4136 | 4136 | const operand = try sema.resolveInst(extra.rhs); |
| 4137 | 4137 | |
| 4138 | const is_ret = if (Zir.refToIndex(extra.lhs)) |ptr_index| |
| 4139 | zir_tags[ptr_index] == .ret_ptr |
| 4140 | else |
| 4141 | false; |
| 4142 | |
| 4138 | 4143 | // Check for the possibility of this pattern: |
| 4139 | 4144 | // %a = ret_ptr |
| 4140 | 4145 | // %b = store(%a, %c) |
| 4141 | 4146 | // Where %c is an error union or error set. In such case we need to add |
| 4142 | 4147 | // to the current function's inferred error set, if any. |
| 4143 | | if ((sema.typeOf(operand).zigTypeTag() == .ErrorUnion or |
| 4148 | if (is_ret and (sema.typeOf(operand).zigTypeTag() == .ErrorUnion or |
| 4144 | 4149 | sema.typeOf(operand).zigTypeTag() == .ErrorSet) and |
| 4145 | 4150 | sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) |
| 4146 | 4151 | { |
| 4147 | | if (Zir.refToIndex(extra.lhs)) |ptr_index| { |
| 4148 | | if (zir_tags[ptr_index] == .ret_ptr) { |
| 4149 | | try sema.addToInferredErrorSet(operand); |
| 4150 | | } |
| 4151 | | } |
| 4152 | try sema.addToInferredErrorSet(operand); |
| 4152 | 4153 | } |
| 4153 | 4154 | |
| 4154 | | return sema.storePtr(block, src, ptr, operand); |
| 4155 | return sema.storePtr2(block, src, ptr, src, operand, src, if (is_ret) .ret_ptr else .store); |
| 4155 | 4156 | } |
| 4156 | 4157 | |
| 4157 | 4158 | fn zirParamType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5543,7 +5544,7 @@ fn analyzeCall( |
| 5543 | 5544 | try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst) |
| 5544 | 5545 | else |
| 5545 | 5546 | try sema.resolveInst(fn_info.ret_ty_ref); |
| 5546 | | const ret_ty_src = func_src; // TODO better source location |
| 5547 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 5547 | 5548 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); |
| 5548 | 5549 | // Create a fresh inferred error set type for inline/comptime calls. |
| 5549 | 5550 | const fn_ret_ty = blk: { |
| ... | ... | @@ -6885,7 +6886,7 @@ fn zirFunc( |
| 6885 | 6886 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 6886 | 6887 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 6887 | 6888 | const target = sema.mod.getTarget(); |
| 6888 | | const ret_ty_src = inst_data.src(); // TODO better source location |
| 6889 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = inst_data.src_node }; |
| 6889 | 6890 | |
| 6890 | 6891 | var extra_index = extra.end; |
| 6891 | 6892 | |
| ... | ... | @@ -7467,13 +7468,20 @@ fn analyzeAs( |
| 7467 | 7468 | zir_dest_type: Zir.Inst.Ref, |
| 7468 | 7469 | zir_operand: Zir.Inst.Ref, |
| 7469 | 7470 | ) CompileError!Air.Inst.Ref { |
| 7471 | const is_ret = if (Zir.refToIndex(zir_dest_type)) |ptr_index| |
| 7472 | sema.code.instructions.items(.tag)[ptr_index] == .ret_type |
| 7473 | else |
| 7474 | false; |
| 7470 | 7475 | const dest_ty = try sema.resolveType(block, src, zir_dest_type); |
| 7471 | 7476 | const operand = try sema.resolveInst(zir_operand); |
| 7472 | 7477 | if (dest_ty.tag() == .var_args_param) return operand; |
| 7473 | 7478 | if (dest_ty.zigTypeTag() == .NoReturn) { |
| 7474 | 7479 | return sema.fail(block, src, "cannot cast to noreturn", .{}); |
| 7475 | 7480 | } |
| 7476 | | return sema.coerce(block, dest_ty, operand, src); |
| 7481 | return sema.coerceExtra(block, dest_ty, operand, src, true, is_ret) catch |err| switch (err) { |
| 7482 | error.NotCoercible => unreachable, |
| 7483 | else => |e| return e, |
| 7484 | }; |
| 7477 | 7485 | } |
| 7478 | 7486 | |
| 7479 | 7487 | fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -13656,7 +13664,10 @@ fn analyzeRet( |
| 13656 | 13664 | if (sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) { |
| 13657 | 13665 | try sema.addToInferredErrorSet(uncasted_operand); |
| 13658 | 13666 | } |
| 13659 | | const operand = try sema.coerce(block, sema.fn_ret_ty, uncasted_operand, src); |
| 13667 | const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, true, true) catch |err| switch (err) { |
| 13668 | error.NotCoercible => unreachable, |
| 13669 | else => |e| return e, |
| 13670 | }; |
| 13660 | 13671 | |
| 13661 | 13672 | if (block.inlining) |inlining| { |
| 13662 | 13673 | if (block.is_comptime) { |
| ... | ... | @@ -19869,7 +19880,7 @@ fn coerce( |
| 19869 | 19880 | inst: Air.Inst.Ref, |
| 19870 | 19881 | inst_src: LazySrcLoc, |
| 19871 | 19882 | ) CompileError!Air.Inst.Ref { |
| 19872 | | return sema.coerceExtra(block, dest_ty_unresolved, inst, inst_src, true) catch |err| switch (err) { |
| 19883 | return sema.coerceExtra(block, dest_ty_unresolved, inst, inst_src, true, false) catch |err| switch (err) { |
| 19873 | 19884 | error.NotCoercible => unreachable, |
| 19874 | 19885 | else => |e| return e, |
| 19875 | 19886 | }; |
| ... | ... | @@ -19888,6 +19899,7 @@ fn coerceExtra( |
| 19888 | 19899 | inst: Air.Inst.Ref, |
| 19889 | 19900 | inst_src: LazySrcLoc, |
| 19890 | 19901 | report_err: bool, |
| 19902 | is_ret: bool, |
| 19891 | 19903 | ) CoersionError!Air.Inst.Ref { |
| 19892 | 19904 | switch (dest_ty_unresolved.tag()) { |
| 19893 | 19905 | .var_args_param => return sema.coerceVarArgParam(block, inst, inst_src), |
| ... | ... | @@ -19939,7 +19951,7 @@ fn coerceExtra( |
| 19939 | 19951 | |
| 19940 | 19952 | // T to ?T |
| 19941 | 19953 | const child_type = try dest_ty.optionalChildAlloc(sema.arena); |
| 19942 | | const intermediate = sema.coerceExtra(block, child_type, inst, inst_src, false) catch |err| switch (err) { |
| 19954 | const intermediate = sema.coerceExtra(block, child_type, inst, inst_src, false, is_ret) catch |err| switch (err) { |
| 19943 | 19955 | error.NotCoercible => { |
| 19944 | 19956 | if (in_memory_result == .no_match) { |
| 19945 | 19957 | // Try to give more useful notes |
| ... | ... | @@ -20056,7 +20068,7 @@ fn coerceExtra( |
| 20056 | 20068 | return sema.addConstant(dest_ty, Value.@"null"); |
| 20057 | 20069 | }, |
| 20058 | 20070 | .ComptimeInt => { |
| 20059 | | const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, false) catch |err| switch (err) { |
| 20071 | const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, false, is_ret) catch |err| switch (err) { |
| 20060 | 20072 | error.NotCoercible => break :pointer, |
| 20061 | 20073 | else => |e| return e, |
| 20062 | 20074 | }; |
| ... | ... | @@ -20067,7 +20079,7 @@ fn coerceExtra( |
| 20067 | 20079 | .signed => Type.isize, |
| 20068 | 20080 | .unsigned => Type.usize, |
| 20069 | 20081 | }; |
| 20070 | | const addr = sema.coerceExtra(block, ptr_size_ty, inst, inst_src, false) catch |err| switch (err) { |
| 20082 | const addr = sema.coerceExtra(block, ptr_size_ty, inst, inst_src, false, is_ret) catch |err| switch (err) { |
| 20071 | 20083 | error.NotCoercible => { |
| 20072 | 20084 | // Try to give more useful notes |
| 20073 | 20085 | in_memory_result = try sema.coerceInMemoryAllowed(block, ptr_size_ty, inst_ty, false, target, dest_ty_src, inst_src); |
| ... | ... | @@ -20414,6 +20426,19 @@ fn coerceExtra( |
| 20414 | 20426 | |
| 20415 | 20427 | if (!report_err) return error.NotCoercible; |
| 20416 | 20428 | |
| 20429 | if (is_ret and dest_ty.zigTypeTag() == .NoReturn) { |
| 20430 | const msg = msg: { |
| 20431 | const msg = try sema.errMsg(block, inst_src, "function declared 'noreturn' returns", .{}); |
| 20432 | errdefer msg.destroy(sema.gpa); |
| 20433 | |
| 20434 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 20435 | const src_decl = sema.mod.declPtr(sema.func.?.owner_decl); |
| 20436 | try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "'noreturn' declared here", .{}); |
| 20437 | break :msg msg; |
| 20438 | }; |
| 20439 | return sema.failWithOwnedErrorMsg(block, msg); |
| 20440 | } |
| 20441 | |
| 20417 | 20442 | const msg = msg: { |
| 20418 | 20443 | const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) }); |
| 20419 | 20444 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -20436,6 +20461,20 @@ fn coerceExtra( |
| 20436 | 20461 | } |
| 20437 | 20462 | |
| 20438 | 20463 | try in_memory_result.report(sema, block, inst_src, msg); |
| 20464 | |
| 20465 | // Add notes about function return type |
| 20466 | if (is_ret and sema.mod.test_functions.get(sema.func.?.owner_decl) == null) { |
| 20467 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 20468 | const src_decl = sema.mod.declPtr(sema.func.?.owner_decl); |
| 20469 | if (inst_ty.isError() and !dest_ty.isError()) { |
| 20470 | try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function cannot return an error", .{}); |
| 20471 | } else { |
| 20472 | try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function return type declared here", .{}); |
| 20473 | } |
| 20474 | } |
| 20475 | |
| 20476 | // TODO maybe add "cannot store an error in type '{}'" note |
| 20477 | |
| 20439 | 20478 | break :msg msg; |
| 20440 | 20479 | }; |
| 20441 | 20480 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | ... | @@ -21372,6 +21411,8 @@ fn storePtr2( |
| 21372 | 21411 | // TODO do the same thing for anon structs as for tuples above. |
| 21373 | 21412 | // However, beware of the need to handle missing/extra fields. |
| 21374 | 21413 | |
| 21414 | const is_ret = air_tag == .ret_ptr; |
| 21415 | |
| 21375 | 21416 | // Detect if we are storing an array operand to a bitcasted vector pointer. |
| 21376 | 21417 | // If so, we instead reach through the bitcasted pointer to the vector pointer, |
| 21377 | 21418 | // bitcast the array operand to a vector, and then lower this as a store of |
| ... | ... | @@ -21380,12 +21421,18 @@ fn storePtr2( |
| 21380 | 21421 | // https://github.com/ziglang/zig/issues/11154 |
| 21381 | 21422 | if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| { |
| 21382 | 21423 | const vector_ty = sema.typeOf(vector_ptr).childType(); |
| 21383 | | const vector = try sema.coerce(block, vector_ty, uncasted_operand, operand_src); |
| 21424 | const vector = sema.coerceExtra(block, vector_ty, uncasted_operand, operand_src, true, is_ret) catch |err| switch (err) { |
| 21425 | error.NotCoercible => unreachable, |
| 21426 | else => |e| return e, |
| 21427 | }; |
| 21384 | 21428 | try sema.storePtr2(block, src, vector_ptr, ptr_src, vector, operand_src, .store); |
| 21385 | 21429 | return; |
| 21386 | 21430 | } |
| 21387 | 21431 | |
| 21388 | | const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src); |
| 21432 | const operand = sema.coerceExtra(block, elem_ty, uncasted_operand, operand_src, true, is_ret) catch |err| switch (err) { |
| 21433 | error.NotCoercible => unreachable, |
| 21434 | else => |e| return e, |
| 21435 | }; |
| 21389 | 21436 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); |
| 21390 | 21437 | |
| 21391 | 21438 | const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { |
| ... | ... | @@ -21415,7 +21462,11 @@ fn storePtr2( |
| 21415 | 21462 | |
| 21416 | 21463 | try sema.requireRuntimeBlock(block, runtime_src); |
| 21417 | 21464 | try sema.queueFullTypeResolution(elem_ty); |
| 21418 | | _ = try block.addBinOp(air_tag, ptr, operand); |
| 21465 | if (is_ret) { |
| 21466 | _ = try block.addBinOp(.store, ptr, operand); |
| 21467 | } else { |
| 21468 | _ = try block.addBinOp(air_tag, ptr, operand); |
| 21469 | } |
| 21419 | 21470 | } |
| 21420 | 21471 | |
| 21421 | 21472 | /// Traverse an arbitrary number of bitcasted pointers and return the underyling vector |