| ... | @@ -4135,23 +4135,24 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v | ... | @@ -4135,23 +4135,24 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 4135 | const ptr = try sema.resolveInst(extra.lhs); | 4135 | const ptr = try sema.resolveInst(extra.lhs); |
| 4136 | const operand = try sema.resolveInst(extra.rhs); | 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 | // Check for the possibility of this pattern: | 4143 | // Check for the possibility of this pattern: |
| 4139 | // %a = ret_ptr | 4144 | // %a = ret_ptr |
| 4140 | // %b = store(%a, %c) | 4145 | // %b = store(%a, %c) |
| 4141 | // Where %c is an error union or error set. In such case we need to add | 4146 | // Where %c is an error union or error set. In such case we need to add |
| 4142 | // to the current function's inferred error set, if any. | 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 | sema.typeOf(operand).zigTypeTag() == .ErrorSet) and | 4149 | sema.typeOf(operand).zigTypeTag() == .ErrorSet) and |
| 4145 | sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) | 4150 | sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) |
| 4146 | { | 4151 | { |
| 4147 | if (Zir.refToIndex(extra.lhs)) |ptr_index| { | 4152 | try sema.addToInferredErrorSet(operand); |
| 4148 | if (zir_tags[ptr_index] == .ret_ptr) { | | |
| 4149 | try sema.addToInferredErrorSet(operand); | | |
| 4150 | } | | |
| 4151 | } | | |
| 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 | fn zirParamType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 4158 | fn zirParamType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -5543,7 +5544,7 @@ fn analyzeCall( | ... | @@ -5543,7 +5544,7 @@ fn analyzeCall( |
| 5543 | try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst) | 5544 | try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst) |
| 5544 | else | 5545 | else |
| 5545 | try sema.resolveInst(fn_info.ret_ty_ref); | 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 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); | 5548 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); |
| 5548 | // Create a fresh inferred error set type for inline/comptime calls. | 5549 | // Create a fresh inferred error set type for inline/comptime calls. |
| 5549 | const fn_ret_ty = blk: { | 5550 | const fn_ret_ty = blk: { |
| ... | @@ -6885,7 +6886,7 @@ fn zirFunc( | ... | @@ -6885,7 +6886,7 @@ fn zirFunc( |
| 6885 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 6886 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 6886 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); | 6887 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 6887 | const target = sema.mod.getTarget(); | 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 | var extra_index = extra.end; | 6891 | var extra_index = extra.end; |
| 6891 | | 6892 | |
| ... | @@ -7467,13 +7468,20 @@ fn analyzeAs( | ... | @@ -7467,13 +7468,20 @@ fn analyzeAs( |
| 7467 | zir_dest_type: Zir.Inst.Ref, | 7468 | zir_dest_type: Zir.Inst.Ref, |
| 7468 | zir_operand: Zir.Inst.Ref, | 7469 | zir_operand: Zir.Inst.Ref, |
| 7469 | ) CompileError!Air.Inst.Ref { | 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 | const dest_ty = try sema.resolveType(block, src, zir_dest_type); | 7475 | const dest_ty = try sema.resolveType(block, src, zir_dest_type); |
| 7471 | const operand = try sema.resolveInst(zir_operand); | 7476 | const operand = try sema.resolveInst(zir_operand); |
| 7472 | if (dest_ty.tag() == .var_args_param) return operand; | 7477 | if (dest_ty.tag() == .var_args_param) return operand; |
| 7473 | if (dest_ty.zigTypeTag() == .NoReturn) { | 7478 | if (dest_ty.zigTypeTag() == .NoReturn) { |
| 7474 | return sema.fail(block, src, "cannot cast to noreturn", .{}); | 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 | fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 7487 | fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -13656,7 +13664,10 @@ fn analyzeRet( | ... | @@ -13656,7 +13664,10 @@ fn analyzeRet( |
| 13656 | if (sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) { | 13664 | if (sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) { |
| 13657 | try sema.addToInferredErrorSet(uncasted_operand); | 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 | if (block.inlining) |inlining| { | 13672 | if (block.inlining) |inlining| { |
| 13662 | if (block.is_comptime) { | 13673 | if (block.is_comptime) { |
| ... | @@ -19869,7 +19880,7 @@ fn coerce( | ... | @@ -19869,7 +19880,7 @@ fn coerce( |
| 19869 | inst: Air.Inst.Ref, | 19880 | inst: Air.Inst.Ref, |
| 19870 | inst_src: LazySrcLoc, | 19881 | inst_src: LazySrcLoc, |
| 19871 | ) CompileError!Air.Inst.Ref { | 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 | error.NotCoercible => unreachable, | 19884 | error.NotCoercible => unreachable, |
| 19874 | else => |e| return e, | 19885 | else => |e| return e, |
| 19875 | }; | 19886 | }; |
| ... | @@ -19888,6 +19899,7 @@ fn coerceExtra( | ... | @@ -19888,6 +19899,7 @@ fn coerceExtra( |
| 19888 | inst: Air.Inst.Ref, | 19899 | inst: Air.Inst.Ref, |
| 19889 | inst_src: LazySrcLoc, | 19900 | inst_src: LazySrcLoc, |
| 19890 | report_err: bool, | 19901 | report_err: bool, |
| | 19902 | is_ret: bool, |
| 19891 | ) CoersionError!Air.Inst.Ref { | 19903 | ) CoersionError!Air.Inst.Ref { |
| 19892 | switch (dest_ty_unresolved.tag()) { | 19904 | switch (dest_ty_unresolved.tag()) { |
| 19893 | .var_args_param => return sema.coerceVarArgParam(block, inst, inst_src), | 19905 | .var_args_param => return sema.coerceVarArgParam(block, inst, inst_src), |
| ... | @@ -19939,7 +19951,7 @@ fn coerceExtra( | ... | @@ -19939,7 +19951,7 @@ fn coerceExtra( |
| 19939 | | 19951 | |
| 19940 | // T to ?T | 19952 | // T to ?T |
| 19941 | const child_type = try dest_ty.optionalChildAlloc(sema.arena); | 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 | error.NotCoercible => { | 19955 | error.NotCoercible => { |
| 19944 | if (in_memory_result == .no_match) { | 19956 | if (in_memory_result == .no_match) { |
| 19945 | // Try to give more useful notes | 19957 | // Try to give more useful notes |
| ... | @@ -20056,7 +20068,7 @@ fn coerceExtra( | ... | @@ -20056,7 +20068,7 @@ fn coerceExtra( |
| 20056 | return sema.addConstant(dest_ty, Value.@"null"); | 20068 | return sema.addConstant(dest_ty, Value.@"null"); |
| 20057 | }, | 20069 | }, |
| 20058 | .ComptimeInt => { | 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 | error.NotCoercible => break :pointer, | 20072 | error.NotCoercible => break :pointer, |
| 20061 | else => |e| return e, | 20073 | else => |e| return e, |
| 20062 | }; | 20074 | }; |
| ... | @@ -20067,7 +20079,7 @@ fn coerceExtra( | ... | @@ -20067,7 +20079,7 @@ fn coerceExtra( |
| 20067 | .signed => Type.isize, | 20079 | .signed => Type.isize, |
| 20068 | .unsigned => Type.usize, | 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 | error.NotCoercible => { | 20083 | error.NotCoercible => { |
| 20072 | // Try to give more useful notes | 20084 | // Try to give more useful notes |
| 20073 | in_memory_result = try sema.coerceInMemoryAllowed(block, ptr_size_ty, inst_ty, false, target, dest_ty_src, inst_src); | 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,6 +20426,19 @@ fn coerceExtra( |
| 20414 | | 20426 | |
| 20415 | if (!report_err) return error.NotCoercible; | 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 | const msg = msg: { | 20442 | const msg = msg: { |
| 20418 | const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) }); | 20443 | const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) }); |
| 20419 | errdefer msg.destroy(sema.gpa); | 20444 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -20436,6 +20461,20 @@ fn coerceExtra( | ... | @@ -20436,6 +20461,20 @@ fn coerceExtra( |
| 20436 | } | 20461 | } |
| 20437 | | 20462 | |
| 20438 | try in_memory_result.report(sema, block, inst_src, msg); | 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 | break :msg msg; | 20478 | break :msg msg; |
| 20440 | }; | 20479 | }; |
| 20441 | return sema.failWithOwnedErrorMsg(block, msg); | 20480 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | @@ -21372,6 +21411,8 @@ fn storePtr2( | ... | @@ -21372,6 +21411,8 @@ fn storePtr2( |
| 21372 | // TODO do the same thing for anon structs as for tuples above. | 21411 | // TODO do the same thing for anon structs as for tuples above. |
| 21373 | // However, beware of the need to handle missing/extra fields. | 21412 | // However, beware of the need to handle missing/extra fields. |
| 21374 | | 21413 | |
| | 21414 | const is_ret = air_tag == .ret_ptr; |
| | 21415 | |
| 21375 | // Detect if we are storing an array operand to a bitcasted vector pointer. | 21416 | // Detect if we are storing an array operand to a bitcasted vector pointer. |
| 21376 | // If so, we instead reach through the bitcasted pointer to the vector pointer, | 21417 | // If so, we instead reach through the bitcasted pointer to the vector pointer, |
| 21377 | // bitcast the array operand to a vector, and then lower this as a store of | 21418 | // bitcast the array operand to a vector, and then lower this as a store of |
| ... | @@ -21380,12 +21421,18 @@ fn storePtr2( | ... | @@ -21380,12 +21421,18 @@ fn storePtr2( |
| 21380 | // https://github.com/ziglang/zig/issues/11154 | 21421 | // https://github.com/ziglang/zig/issues/11154 |
| 21381 | if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| { | 21422 | if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| { |
| 21382 | const vector_ty = sema.typeOf(vector_ptr).childType(); | 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 | try sema.storePtr2(block, src, vector_ptr, ptr_src, vector, operand_src, .store); | 21428 | try sema.storePtr2(block, src, vector_ptr, ptr_src, vector, operand_src, .store); |
| 21385 | return; | 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 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); | 21436 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); |
| 21390 | | 21437 | |
| 21391 | const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { | 21438 | const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { |
| ... | @@ -21415,7 +21462,11 @@ fn storePtr2( | ... | @@ -21415,7 +21462,11 @@ fn storePtr2( |
| 21415 | | 21462 | |
| 21416 | try sema.requireRuntimeBlock(block, runtime_src); | 21463 | try sema.requireRuntimeBlock(block, runtime_src); |
| 21417 | try sema.queueFullTypeResolution(elem_ty); | 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 | /// Traverse an arbitrary number of bitcasted pointers and return the underyling vector | 21472 | /// Traverse an arbitrary number of bitcasted pointers and return the underyling vector |