| author | |
| committer | |
| log | f20e449fd6ad63c58e76670f230783d0dd399b93 |
| tree | 80090a8144b0a05cf3df5a09867a0b609a592d93 |
| parent | e2509ddbe69a56bb1f4a56b46946b2a706d5aabe |
Closes #265311 files changed, 75 insertions(+), 34 deletions(-)
src/AstGen.zig+5-7| ... | ... | @@ -2632,7 +2632,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2632 | 2632 | .compile_error, |
| 2633 | 2633 | .ret_node, |
| 2634 | 2634 | .ret_load, |
| 2635 | .ret_tok, | |
| 2635 | .ret_implicit, | |
| 2636 | 2636 | .ret_err_value, |
| 2637 | 2637 | .@"unreachable", |
| 2638 | 2638 | .repeat, |
| ... | ... | @@ -3914,9 +3914,8 @@ fn fnDecl( |
| 3914 | 3914 | // As our last action before the return, "pop" the error trace if needed |
| 3915 | 3915 | _ = try gz.addRestoreErrRetIndex(.ret, .always); |
| 3916 | 3916 | |
| 3917 | // Since we are adding the return instruction here, we must handle the coercion. | |
| 3918 | // We do this by using the `ret_tok` instruction. | |
| 3919 | _ = try fn_gz.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node)); | |
| 3917 | // Add implicit return at end of function. | |
| 3918 | _ = try fn_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node)); | |
| 3920 | 3919 | } |
| 3921 | 3920 | |
| 3922 | 3921 | break :func try decl_gz.addFunc(.{ |
| ... | ... | @@ -4334,9 +4333,8 @@ fn testDecl( |
| 4334 | 4333 | // As our last action before the return, "pop" the error trace if needed |
| 4335 | 4334 | _ = try gz.addRestoreErrRetIndex(.ret, .always); |
| 4336 | 4335 | |
| 4337 | // Since we are adding the return instruction here, we must handle the coercion. | |
| 4338 | // We do this by using the `ret_tok` instruction. | |
| 4339 | _ = try fn_block.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node)); | |
| 4336 | // Add implicit return at end of function. | |
| 4337 | _ = try fn_block.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node)); | |
| 4340 | 4338 | } |
| 4341 | 4339 | |
| 4342 | 4340 | const func_inst = try decl_block.addFunc(.{ |
src/Sema.zig+28-4| ... | ... | @@ -1098,7 +1098,7 @@ fn analyzeBodyInner( |
| 1098 | 1098 | // These functions match the return type of analyzeBody so that we can |
| 1099 | 1099 | // tail call them here. |
| 1100 | 1100 | .compile_error => break sema.zirCompileError(block, inst), |
| 1101 | .ret_tok => break sema.zirRetTok(block, inst), | |
| 1101 | .ret_implicit => break sema.zirRetImplicit(block, inst), | |
| 1102 | 1102 | .ret_node => break sema.zirRetNode(block, inst), |
| 1103 | 1103 | .ret_load => break sema.zirRetLoad(block, inst), |
| 1104 | 1104 | .ret_err_value => break sema.zirRetErrValue(block, inst), |
| ... | ... | @@ -16546,7 +16546,7 @@ fn zirRetErrValue( |
| 16546 | 16546 | return sema.analyzeRet(block, result_inst, src); |
| 16547 | 16547 | } |
| 16548 | 16548 | |
| 16549 | fn zirRetTok( | |
| 16549 | fn zirRetImplicit( | |
| 16550 | 16550 | sema: *Sema, |
| 16551 | 16551 | block: *Block, |
| 16552 | 16552 | inst: Zir.Inst.Index, |
| ... | ... | @@ -16556,9 +16556,33 @@ fn zirRetTok( |
| 16556 | 16556 | |
| 16557 | 16557 | const inst_data = sema.code.instructions.items(.data)[inst].un_tok; |
| 16558 | 16558 | const operand = try sema.resolveInst(inst_data.operand); |
| 16559 | const src = inst_data.src(); | |
| 16560 | 16559 | |
| 16561 | return sema.analyzeRet(block, operand, src); | |
| 16560 | const r_brace_src = inst_data.src(); | |
| 16561 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | |
| 16562 | const base_tag = sema.fn_ret_ty.baseZigTypeTag(); | |
| 16563 | if (base_tag == .NoReturn) { | |
| 16564 | const msg = msg: { | |
| 16565 | const msg = try sema.errMsg(block, ret_ty_src, "function declared '{}' implicitly returns", .{ | |
| 16566 | sema.fn_ret_ty.fmt(sema.mod), | |
| 16567 | }); | |
| 16568 | errdefer msg.destroy(sema.gpa); | |
| 16569 | try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); | |
| 16570 | break :msg msg; | |
| 16571 | }; | |
| 16572 | return sema.failWithOwnedErrorMsg(msg); | |
| 16573 | } else if (base_tag != .Void) { | |
| 16574 | const msg = msg: { | |
| 16575 | const msg = try sema.errMsg(block, ret_ty_src, "function with non-void return type '{}' implicitly returns", .{ | |
| 16576 | sema.fn_ret_ty.fmt(sema.mod), | |
| 16577 | }); | |
| 16578 | errdefer msg.destroy(sema.gpa); | |
| 16579 | try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); | |
| 16580 | break :msg msg; | |
| 16581 | }; | |
| 16582 | return sema.failWithOwnedErrorMsg(msg); | |
| 16583 | } | |
| 16584 | ||
| 16585 | return sema.analyzeRet(block, operand, .unneeded); | |
| 16562 | 16586 | } |
| 16563 | 16587 | |
| 16564 | 16588 | fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { |
src/Zir.zig+4-4| ... | ... | @@ -519,7 +519,7 @@ pub const Inst = struct { |
| 519 | 519 | /// Includes an operand as the return value. |
| 520 | 520 | /// Includes a token source location. |
| 521 | 521 | /// Uses the `un_tok` union field. |
| 522 | ret_tok, | |
| 522 | ret_implicit, | |
| 523 | 523 | /// Sends control flow back to the function's callee. |
| 524 | 524 | /// The return operand is `error.foo` where `foo` is given by the string. |
| 525 | 525 | /// If the current function has an inferred error set, the error given by the |
| ... | ... | @@ -1256,7 +1256,7 @@ pub const Inst = struct { |
| 1256 | 1256 | .compile_error, |
| 1257 | 1257 | .ret_node, |
| 1258 | 1258 | .ret_load, |
| 1259 | .ret_tok, | |
| 1259 | .ret_implicit, | |
| 1260 | 1260 | .ret_err_value, |
| 1261 | 1261 | .@"unreachable", |
| 1262 | 1262 | .repeat, |
| ... | ... | @@ -1530,7 +1530,7 @@ pub const Inst = struct { |
| 1530 | 1530 | .compile_error, |
| 1531 | 1531 | .ret_node, |
| 1532 | 1532 | .ret_load, |
| 1533 | .ret_tok, | |
| 1533 | .ret_implicit, | |
| 1534 | 1534 | .ret_err_value, |
| 1535 | 1535 | .ret_ptr, |
| 1536 | 1536 | .ret_type, |
| ... | ... | @@ -1659,7 +1659,7 @@ pub const Inst = struct { |
| 1659 | 1659 | .ref = .un_tok, |
| 1660 | 1660 | .ret_node = .un_node, |
| 1661 | 1661 | .ret_load = .un_node, |
| 1662 | .ret_tok = .un_tok, | |
| 1662 | .ret_implicit = .un_tok, | |
| 1663 | 1663 | .ret_err_value = .str_tok, |
| 1664 | 1664 | .ret_err_value_code = .str_tok, |
| 1665 | 1665 | .ret_ptr = .node, |
src/print_zir.zig+1-1| ... | ... | @@ -235,7 +235,7 @@ const Writer = struct { |
| 235 | 235 | => try self.writeUnNode(stream, inst), |
| 236 | 236 | |
| 237 | 237 | .ref, |
| 238 | .ret_tok, | |
| 238 | .ret_implicit, | |
| 239 | 239 | .closure_capture, |
| 240 | 240 | .switch_capture_tag, |
| 241 | 241 | => try self.writeUnTok(stream, inst), |
src/type.zig+11| ... | ... | @@ -160,6 +160,17 @@ pub const Type = extern union { |
| 160 | 160 | } |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | pub fn baseZigTypeTag(self: Type) std.builtin.TypeId { | |
| 164 | return switch (self.zigTypeTag()) { | |
| 165 | .ErrorUnion => self.errorUnionPayload().baseZigTypeTag(), | |
| 166 | .Optional => { | |
| 167 | var buf: Payload.ElemType = undefined; | |
| 168 | return self.optionalChild(&buf).baseZigTypeTag(); | |
| 169 | }, | |
| 170 | else => |t| t, | |
| 171 | }; | |
| 172 | } | |
| 173 | ||
| 163 | 174 | pub fn isSelfComparable(ty: Type, is_equality_cmp: bool) bool { |
| 164 | 175 | return switch (ty.zigTypeTag()) { |
| 165 | 176 | .Int, |
test/cases/aarch64-macos/hello_world_with_updates.1.zig+2-2| ... | ... | @@ -2,5 +2,5 @@ pub export fn main() noreturn {} |
| 2 | 2 | |
| 3 | 3 | // error |
| 4 | 4 | // |
| 5 | // :1:32: error: function declared 'noreturn' returns | |
| 6 | // :1:22: note: 'noreturn' declared here | |
| 5 | // :1:22: error: function declared 'noreturn' implicitly returns | |
| 6 | // :1:32: note: control flow reaches end of body here |
test/cases/compile_errors/control_reaches_end_of_non-void_function.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | fn a() i32 {} | |
| 2 | export fn entry() void { _ = a(); } | |
| 3 | ||
| 4 | // error | |
| 5 | // backend=stage2 | |
| 6 | // target=native | |
| 7 | // | |
| 8 | // :1:13: error: expected type 'i32', found 'void' | |
| 9 | // :1:8: note: function return type declared here |
test/cases/compile_errors/type_error_in_implicit_return.zig created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | fn f1(x: bool) u32 { | |
| 2 | if (x) return 1; | |
| 3 | } | |
| 4 | fn f2() noreturn {} | |
| 5 | pub export fn entry() void { | |
| 6 | _ = f1(true); | |
| 7 | _ = f2(); | |
| 8 | } | |
| 9 | ||
| 10 | // error | |
| 11 | // backend=stage2 | |
| 12 | // target=native | |
| 13 | // | |
| 14 | // :1:16: error: function with non-void return type 'u32' implicitly returns | |
| 15 | // :3:1: note: control flow reaches end of body here | |
| 16 | // :4:9: error: function declared 'noreturn' implicitly returns | |
| 17 | // :4:19: note: control flow reaches end of body here |
test/cases/x86_64-linux/hello_world_with_updates.1.zig+3-3| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | pub export fn _start() noreturn {} | |
| 1 | pub export fn main() noreturn {} | |
| 2 | 2 | |
| 3 | 3 | // error |
| 4 | 4 | // |
| 5 | // :1:34: error: function declared 'noreturn' returns | |
| 6 | // :1:24: note: 'noreturn' declared here | |
| 5 | // :1:22: error: function declared 'noreturn' implicitly returns | |
| 6 | // :1:32: note: control flow reaches end of body here |
test/cases/x86_64-macos/hello_world_with_updates.1.zig+2-2| ... | ... | @@ -2,5 +2,5 @@ pub export fn main() noreturn {} |
| 2 | 2 | |
| 3 | 3 | // error |
| 4 | 4 | // |
| 5 | // :1:32: error: function declared 'noreturn' returns | |
| 6 | // :1:22: note: 'noreturn' declared here | |
| 5 | // :1:22: error: function declared 'noreturn' implicitly returns | |
| 6 | // :1:32: note: control flow reaches end of body here |
test/cases/x86_64-windows/hello_world_with_updates.1.zig+2-2| ... | ... | @@ -2,5 +2,5 @@ pub export fn main() noreturn {} |
| 2 | 2 | |
| 3 | 3 | // error |
| 4 | 4 | // |
| 5 | // :1:32: error: function declared 'noreturn' returns | |
| 6 | // :1:22: note: 'noreturn' declared here | |
| 5 | // :1:22: error: function declared 'noreturn' implicitly returns | |
| 6 | // :1:32: note: control flow reaches end of body here |