authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-03 00:42:11-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-03 00:42:11-05:00
logfdbb0fb7b9c08ebff1b7e45ef89f7160f350d44c
tree714f2766c64ace45df1f7d67ca70be0c88193184
parentc43ac67f82cb5a022df67729aa1e6bebc22cfff2
parentb500e0eb179218f5eb03408c09b5e5a928f0c46e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13744 from Vexu/stage2-fixes

Improve error messages, fix dependency loops

40 files changed, 378 insertions(+), 95 deletions(-)

lib/std/fs.zig-2
...@@ -809,8 +809,6 @@ pub const IterableDir = struct {...@@ -809,8 +809,6 @@ pub const IterableDir = struct {
809 // and we avoid the code complexity here.809 // and we avoid the code complexity here.
810 const w = os.wasi;810 const w = os.wasi;
811 start_over: while (true) {811 start_over: while (true) {
812 // TODO https://github.com/ziglang/zig/issues/12498
813 _ = @sizeOf(w.dirent_t) + 1;
814 // According to the WASI spec, the last entry might be truncated,812 // According to the WASI spec, the last entry might be truncated,
815 // so we need to check if the left buffer contains the whole dirent.813 // so we need to check if the left buffer contains the whole dirent.
816 if (self.end_index - self.index < @sizeOf(w.dirent_t)) {814 if (self.end_index - self.index < @sizeOf(w.dirent_t)) {
src/AstGen.zig+41-7
...@@ -2632,7 +2632,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2632,7 +2632,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2632 .compile_error,2632 .compile_error,
2633 .ret_node,2633 .ret_node,
2634 .ret_load,2634 .ret_load,
2635 .ret_tok,2635 .ret_implicit,
2636 .ret_err_value,2636 .ret_err_value,
2637 .@"unreachable",2637 .@"unreachable",
2638 .repeat,2638 .repeat,
...@@ -3696,6 +3696,29 @@ fn fnDecl(...@@ -3696,6 +3696,29 @@ fn fnDecl(
3696 if (param.anytype_ellipsis3) |tok| {3696 if (param.anytype_ellipsis3) |tok| {
3697 return astgen.failTok(tok, "missing parameter name", .{});3697 return astgen.failTok(tok, "missing parameter name", .{});
3698 } else {3698 } else {
3699 ambiguous: {
3700 if (tree.nodes.items(.tag)[param.type_expr] != .identifier) break :ambiguous;
3701 const main_token = tree.nodes.items(.main_token)[param.type_expr];
3702 const identifier_str = tree.tokenSlice(main_token);
3703 if (isPrimitive(identifier_str)) break :ambiguous;
3704 return astgen.failNodeNotes(
3705 param.type_expr,
3706 "missing parameter name or type",
3707 .{},
3708 &[_]u32{
3709 try astgen.errNoteNode(
3710 param.type_expr,
3711 "if this is a name, annotate its type '{s}: T'",
3712 .{identifier_str},
3713 ),
3714 try astgen.errNoteNode(
3715 param.type_expr,
3716 "if this is a type, give it a name '<name>: {s}'",
3717 .{identifier_str},
3718 ),
3719 },
3720 );
3721 }
3699 return astgen.failNode(param.type_expr, "missing parameter name", .{});3722 return astgen.failNode(param.type_expr, "missing parameter name", .{});
3700 }3723 }
3701 } else 0;3724 } else 0;
...@@ -3891,9 +3914,8 @@ fn fnDecl(...@@ -3891,9 +3914,8 @@ fn fnDecl(
3891 // As our last action before the return, "pop" the error trace if needed3914 // As our last action before the return, "pop" the error trace if needed
3892 _ = try gz.addRestoreErrRetIndex(.ret, .always);3915 _ = try gz.addRestoreErrRetIndex(.ret, .always);
38933916
3894 // Since we are adding the return instruction here, we must handle the coercion.3917 // Add implicit return at end of function.
3895 // We do this by using the `ret_tok` instruction.3918 _ = try fn_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node));
3896 _ = try fn_gz.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node));
3897 }3919 }
38983920
3899 break :func try decl_gz.addFunc(.{3921 break :func try decl_gz.addFunc(.{
...@@ -4311,9 +4333,8 @@ fn testDecl(...@@ -4311,9 +4333,8 @@ fn testDecl(
4311 // As our last action before the return, "pop" the error trace if needed4333 // As our last action before the return, "pop" the error trace if needed
4312 _ = try gz.addRestoreErrRetIndex(.ret, .always);4334 _ = try gz.addRestoreErrRetIndex(.ret, .always);
43134335
4314 // Since we are adding the return instruction here, we must handle the coercion.4336 // Add implicit return at end of function.
4315 // We do this by using the `ret_tok` instruction.4337 _ = try fn_block.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node));
4316 _ = try fn_block.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node));
4317 }4338 }
43184339
4319 const func_inst = try decl_block.addFunc(.{4340 const func_inst = try decl_block.addFunc(.{
...@@ -5605,6 +5626,14 @@ fn simpleBinOp(...@@ -5605,6 +5626,14 @@ fn simpleBinOp(
5605 const tree = astgen.tree;5626 const tree = astgen.tree;
5606 const node_datas = tree.nodes.items(.data);5627 const node_datas = tree.nodes.items(.data);
56075628
5629 if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) {
5630 const node_tags = tree.nodes.items(.tag);
5631 const str = if (op_inst_tag == .cmp_eq) "==" else "!=";
5632 if (node_tags[node_datas[node].lhs] == .string_literal or
5633 node_tags[node_datas[node].rhs] == .string_literal)
5634 return astgen.failNode(node, "cannot compare strings with {s}", .{str});
5635 }
5636
5608 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);5637 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);
5609 var line: u32 = undefined;5638 var line: u32 = undefined;
5610 var column: u32 = undefined;5639 var column: u32 = undefined;
...@@ -6602,6 +6631,11 @@ fn switchExpr(...@@ -6602,6 +6631,11 @@ fn switchExpr(
6602 continue;6631 continue;
6603 }6632 }
66046633
6634 for (case.ast.values) |val| {
6635 if (node_tags[val] == .string_literal)
6636 return astgen.failNode(val, "cannot switch on strings", .{});
6637 }
6638
6605 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {6639 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
6606 scalar_cases_len += 1;6640 scalar_cases_len += 1;
6607 } else {6641 } else {
src/Module.zig+2
...@@ -940,6 +940,7 @@ pub const Struct = struct {...@@ -940,6 +940,7 @@ pub const Struct = struct {
940 requires_comptime: PropertyBoolean = .unknown,940 requires_comptime: PropertyBoolean = .unknown,
941 have_field_inits: bool = false,941 have_field_inits: bool = false,
942 is_tuple: bool,942 is_tuple: bool,
943 assumed_runtime_bits: bool = false,
943944
944 pub const Fields = std.StringArrayHashMapUnmanaged(Field);945 pub const Fields = std.StringArrayHashMapUnmanaged(Field);
945946
...@@ -1205,6 +1206,7 @@ pub const Union = struct {...@@ -1205,6 +1206,7 @@ pub const Union = struct {
1205 fully_resolved,1206 fully_resolved,
1206 },1207 },
1207 requires_comptime: PropertyBoolean = .unknown,1208 requires_comptime: PropertyBoolean = .unknown,
1209 assumed_runtime_bits: bool = false,
12081210
1209 pub const Field = struct {1211 pub const Field = struct {
1210 /// undefined until `status` is `have_field_types` or `have_layout`.1212 /// undefined until `status` is `have_field_types` or `have_layout`.
src/Sema.zig+106-27
...@@ -291,8 +291,8 @@ pub const Block = struct {...@@ -291,8 +291,8 @@ pub const Block = struct {
291 try sema.errNote(ci.block, ci.src, parent, prefix ++ "it is inside a @cImport", .{});291 try sema.errNote(ci.block, ci.src, parent, prefix ++ "it is inside a @cImport", .{});
292 },292 },
293 .comptime_ret_ty => |rt| {293 .comptime_ret_ty => |rt| {
294 const src_loc = if (try sema.funcDeclSrc(rt.func)) |capture| blk: {294 const src_loc = if (try sema.funcDeclSrc(rt.func)) |fn_decl| blk: {
295 var src_loc = capture;295 var src_loc = fn_decl.srcLoc();
296 src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 };296 src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 };
297 break :blk src_loc;297 break :blk src_loc;
298 } else blk: {298 } else blk: {
...@@ -1098,7 +1098,7 @@ fn analyzeBodyInner(...@@ -1098,7 +1098,7 @@ fn analyzeBodyInner(
1098 // These functions match the return type of analyzeBody so that we can1098 // These functions match the return type of analyzeBody so that we can
1099 // tail call them here.1099 // tail call them here.
1100 .compile_error => break sema.zirCompileError(block, inst),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 .ret_node => break sema.zirRetNode(block, inst),1102 .ret_node => break sema.zirRetNode(block, inst),
1103 .ret_load => break sema.zirRetLoad(block, inst),1103 .ret_load => break sema.zirRetLoad(block, inst),
1104 .ret_err_value => break sema.zirRetErrValue(block, inst),1104 .ret_err_value => break sema.zirRetErrValue(block, inst),
...@@ -5843,7 +5843,7 @@ fn lookupInNamespace(...@@ -5843,7 +5843,7 @@ fn lookupInNamespace(
5843 return null;5843 return null;
5844}5844}
58455845
5846fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?Module.SrcLoc {5846fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
5847 const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;5847 const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;
5848 if (func_val.isUndef()) return null;5848 if (func_val.isUndef()) return null;
5849 const owner_decl_index = switch (func_val.tag()) {5849 const owner_decl_index = switch (func_val.tag()) {
...@@ -5852,8 +5852,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?Module.SrcLoc {...@@ -5852,8 +5852,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?Module.SrcLoc {
5852 .decl_ref => sema.mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,5852 .decl_ref => sema.mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,
5853 else => return null,5853 else => return null,
5854 };5854 };
5855 const owner_decl = sema.mod.declPtr(owner_decl_index);5855 return sema.mod.declPtr(owner_decl_index);
5856 return owner_decl.srcLoc();
5857}5856}
58585857
5859pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {5858pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {
...@@ -6031,7 +6030,7 @@ fn zirCall(...@@ -6031,7 +6030,7 @@ fn zirCall(
6031 break :check_args;6030 break :check_args;
6032 }6031 }
60336032
6034 const decl_src = try sema.funcDeclSrc(func);6033 const maybe_decl = try sema.funcDeclSrc(func);
6035 const member_str = if (bound_arg_src != null) "member function " else "";6034 const member_str = if (bound_arg_src != null) "member function " else "";
6036 const variadic_str = if (func_ty_info.is_var_args) "at least " else "";6035 const variadic_str = if (func_ty_info.is_var_args) "at least " else "";
6037 const msg = msg: {6036 const msg = msg: {
...@@ -6048,7 +6047,7 @@ fn zirCall(...@@ -6048,7 +6047,7 @@ fn zirCall(
6048 );6047 );
6049 errdefer msg.destroy(sema.gpa);6048 errdefer msg.destroy(sema.gpa);
60506049
6051 if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{});6050 if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{});
6052 break :msg msg;6051 break :msg msg;
6053 };6052 };
6054 return sema.failWithOwnedErrorMsg(msg);6053 return sema.failWithOwnedErrorMsg(msg);
...@@ -6242,7 +6241,7 @@ fn analyzeCall(...@@ -6242,7 +6241,7 @@ fn analyzeCall(
6242 const func_ty_info = func_ty.fnInfo();6241 const func_ty_info = func_ty.fnInfo();
6243 const cc = func_ty_info.cc;6242 const cc = func_ty_info.cc;
6244 if (cc == .Naked) {6243 if (cc == .Naked) {
6245 const decl_src = try sema.funcDeclSrc(func);6244 const maybe_decl = try sema.funcDeclSrc(func);
6246 const msg = msg: {6245 const msg = msg: {
6247 const msg = try sema.errMsg(6246 const msg = try sema.errMsg(
6248 block,6247 block,
...@@ -6252,7 +6251,7 @@ fn analyzeCall(...@@ -6252,7 +6251,7 @@ fn analyzeCall(
6252 );6251 );
6253 errdefer msg.destroy(sema.gpa);6252 errdefer msg.destroy(sema.gpa);
62546253
6255 if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{});6254 if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{});
6256 break :msg msg;6255 break :msg msg;
6257 };6256 };
6258 return sema.failWithOwnedErrorMsg(msg);6257 return sema.failWithOwnedErrorMsg(msg);
...@@ -6488,6 +6487,7 @@ fn analyzeCall(...@@ -6488,6 +6487,7 @@ fn analyzeCall(
6488 &should_memoize,6487 &should_memoize,
6489 memoized_call_key,6488 memoized_call_key,
6490 func_ty_info.param_types,6489 func_ty_info.param_types,
6490 func,
6491 ) catch |err| switch (err) {6491 ) catch |err| switch (err) {
6492 error.NeededSourceLocation => {6492 error.NeededSourceLocation => {
6493 _ = sema.inst_map.remove(inst);6493 _ = sema.inst_map.remove(inst);
...@@ -6504,6 +6504,7 @@ fn analyzeCall(...@@ -6504,6 +6504,7 @@ fn analyzeCall(
6504 &should_memoize,6504 &should_memoize,
6505 memoized_call_key,6505 memoized_call_key,
6506 func_ty_info.param_types,6506 func_ty_info.param_types,
6507 func,
6507 );6508 );
6508 return error.AnalysisFail;6509 return error.AnalysisFail;
6509 },6510 },
...@@ -6646,12 +6647,17 @@ fn analyzeCall(...@@ -6646,12 +6647,17 @@ fn analyzeCall(
6646 const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);6647 const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);
6647 for (uncasted_args) |uncasted_arg, i| {6648 for (uncasted_args) |uncasted_arg, i| {
6648 if (i < fn_params_len) {6649 if (i < fn_params_len) {
6650 const opts: CoerceOpts = .{ .param_src = .{
6651 .func_inst = func,
6652 .param_i = @intCast(u32, i),
6653 } };
6649 const param_ty = func_ty.fnParamType(i);6654 const param_ty = func_ty.fnParamType(i);
6650 args[i] = sema.analyzeCallArg(6655 args[i] = sema.analyzeCallArg(
6651 block,6656 block,
6652 .unneeded,6657 .unneeded,
6653 param_ty,6658 param_ty,
6654 uncasted_arg,6659 uncasted_arg,
6660 opts,
6655 ) catch |err| switch (err) {6661 ) catch |err| switch (err) {
6656 error.NeededSourceLocation => {6662 error.NeededSourceLocation => {
6657 const decl = sema.mod.declPtr(block.src_decl);6663 const decl = sema.mod.declPtr(block.src_decl);
...@@ -6660,6 +6666,7 @@ fn analyzeCall(...@@ -6660,6 +6666,7 @@ fn analyzeCall(
6660 Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src),6666 Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src),
6661 param_ty,6667 param_ty,
6662 uncasted_arg,6668 uncasted_arg,
6669 opts,
6663 );6670 );
6664 return error.AnalysisFail;6671 return error.AnalysisFail;
6665 },6672 },
...@@ -6741,6 +6748,7 @@ fn analyzeInlineCallArg(...@@ -6741,6 +6748,7 @@ fn analyzeInlineCallArg(
6741 should_memoize: *bool,6748 should_memoize: *bool,
6742 memoized_call_key: Module.MemoizedCall.Key,6749 memoized_call_key: Module.MemoizedCall.Key,
6743 raw_param_types: []const Type,6750 raw_param_types: []const Type,
6751 func_inst: Air.Inst.Ref,
6744) !void {6752) !void {
6745 const zir_tags = sema.code.instructions.items(.tag);6753 const zir_tags = sema.code.instructions.items(.tag);
6746 switch (zir_tags[inst]) {6754 switch (zir_tags[inst]) {
...@@ -6765,7 +6773,13 @@ fn analyzeInlineCallArg(...@@ -6765,7 +6773,13 @@ fn analyzeInlineCallArg(
6765 return err;6773 return err;
6766 };6774 };
6767 }6775 }
6768 const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src);6776 const casted_arg = sema.coerceExtra(arg_block, param_ty, uncasted_arg, arg_src, .{ .param_src = .{
6777 .func_inst = func_inst,
6778 .param_i = @intCast(u32, arg_i.*),
6779 } }) catch |err| switch (err) {
6780 error.NotCoercible => unreachable,
6781 else => |e| return e,
6782 };
67696783
6770 if (is_comptime_call) {6784 if (is_comptime_call) {
6771 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);6785 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
...@@ -6855,9 +6869,13 @@ fn analyzeCallArg(...@@ -6855,9 +6869,13 @@ fn analyzeCallArg(
6855 arg_src: LazySrcLoc,6869 arg_src: LazySrcLoc,
6856 param_ty: Type,6870 param_ty: Type,
6857 uncasted_arg: Air.Inst.Ref,6871 uncasted_arg: Air.Inst.Ref,
6872 opts: CoerceOpts,
6858) !Air.Inst.Ref {6873) !Air.Inst.Ref {
6859 try sema.resolveTypeFully(param_ty);6874 try sema.resolveTypeFully(param_ty);
6860 return sema.coerce(block, param_ty, uncasted_arg, arg_src);6875 return sema.coerceExtra(block, param_ty, uncasted_arg, arg_src, opts) catch |err| switch (err) {
6876 error.NotCoercible => unreachable,
6877 else => |e| return e,
6878 };
6861}6879}
68626880
6863fn analyzeGenericCallArg(6881fn analyzeGenericCallArg(
...@@ -16546,7 +16564,7 @@ fn zirRetErrValue(...@@ -16546,7 +16564,7 @@ fn zirRetErrValue(
16546 return sema.analyzeRet(block, result_inst, src);16564 return sema.analyzeRet(block, result_inst, src);
16547}16565}
1654816566
16549fn zirRetTok(16567fn zirRetImplicit(
16550 sema: *Sema,16568 sema: *Sema,
16551 block: *Block,16569 block: *Block,
16552 inst: Zir.Inst.Index,16570 inst: Zir.Inst.Index,
...@@ -16556,9 +16574,33 @@ fn zirRetTok(...@@ -16556,9 +16574,33 @@ fn zirRetTok(
1655616574
16557 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;16575 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
16558 const operand = try sema.resolveInst(inst_data.operand);16576 const operand = try sema.resolveInst(inst_data.operand);
16559 const src = inst_data.src();
1656016577
16561 return sema.analyzeRet(block, operand, src);16578 const r_brace_src = inst_data.src();
16579 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
16580 const base_tag = sema.fn_ret_ty.baseZigTypeTag();
16581 if (base_tag == .NoReturn) {
16582 const msg = msg: {
16583 const msg = try sema.errMsg(block, ret_ty_src, "function declared '{}' implicitly returns", .{
16584 sema.fn_ret_ty.fmt(sema.mod),
16585 });
16586 errdefer msg.destroy(sema.gpa);
16587 try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{});
16588 break :msg msg;
16589 };
16590 return sema.failWithOwnedErrorMsg(msg);
16591 } else if (base_tag != .Void) {
16592 const msg = msg: {
16593 const msg = try sema.errMsg(block, ret_ty_src, "function with non-void return type '{}' implicitly returns", .{
16594 sema.fn_ret_ty.fmt(sema.mod),
16595 });
16596 errdefer msg.destroy(sema.gpa);
16597 try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{});
16598 break :msg msg;
16599 };
16600 return sema.failWithOwnedErrorMsg(msg);
16601 }
16602
16603 return sema.analyzeRet(block, operand, .unneeded);
16562}16604}
1656316605
16564fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {16606fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
...@@ -16825,7 +16867,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -16825,7 +16867,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
16825 const bitoffset_src: LazySrcLoc = .{ .node_offset_ptr_bitoffset = extra.data.src_node };16867 const bitoffset_src: LazySrcLoc = .{ .node_offset_ptr_bitoffset = extra.data.src_node };
16826 const hostsize_src: LazySrcLoc = .{ .node_offset_ptr_hostsize = extra.data.src_node };16868 const hostsize_src: LazySrcLoc = .{ .node_offset_ptr_hostsize = extra.data.src_node };
1682716869
16828 const unresolved_elem_ty = blk: {16870 const elem_ty = blk: {
16829 const air_inst = try sema.resolveInst(extra.data.elem_type);16871 const air_inst = try sema.resolveInst(extra.data.elem_type);
16830 const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| {16872 const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| {
16831 if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer()) {16873 if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer()) {
...@@ -16854,7 +16896,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -16854,7 +16896,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
16854 // Check if this happens to be the lazy alignment of our element type, in16896 // Check if this happens to be the lazy alignment of our element type, in
16855 // which case we can make this 0 without resolving it.16897 // which case we can make this 0 without resolving it.
16856 if (val.castTag(.lazy_align)) |payload| {16898 if (val.castTag(.lazy_align)) |payload| {
16857 if (payload.data.eql(unresolved_elem_ty, sema.mod)) {16899 if (payload.data.eql(elem_ty, sema.mod)) {
16858 break :blk 0;16900 break :blk 0;
16859 }16901 }
16860 }16902 }
...@@ -16887,14 +16929,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -16887,14 +16929,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
16887 return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{});16929 return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{});
16888 }16930 }
1688916931
16890 const elem_ty = if (abi_align == 0)
16891 unresolved_elem_ty
16892 else t: {
16893 const elem_ty = try sema.resolveTypeFields(unresolved_elem_ty);
16894 try sema.resolveTypeLayout(elem_ty);
16895 break :t elem_ty;
16896 };
16897
16898 if (elem_ty.zigTypeTag() == .NoReturn) {16932 if (elem_ty.zigTypeTag() == .NoReturn) {
16899 return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{});16933 return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{});
16900 } else if (elem_ty.zigTypeTag() == .Fn) {16934 } else if (elem_ty.zigTypeTag() == .Fn) {
...@@ -20270,7 +20304,7 @@ fn analyzeShuffle(...@@ -20270,7 +20304,7 @@ fn analyzeShuffle(
20270 var buf: Value.ElemValueBuffer = undefined;20304 var buf: Value.ElemValueBuffer = undefined;
20271 const elem = mask.elemValueBuffer(sema.mod, i, &buf);20305 const elem = mask.elemValueBuffer(sema.mod, i, &buf);
20272 if (elem.isUndef()) continue;20306 if (elem.isUndef()) continue;
20273 const int = elem.toSignedInt();20307 const int = elem.toSignedInt(sema.mod.getTarget());
20274 var unsigned: u32 = undefined;20308 var unsigned: u32 = undefined;
20275 var chosen: u32 = undefined;20309 var chosen: u32 = undefined;
20276 if (int >= 0) {20310 if (int >= 0) {
...@@ -20312,7 +20346,7 @@ fn analyzeShuffle(...@@ -20312,7 +20346,7 @@ fn analyzeShuffle(
20312 values[i] = Value.undef;20346 values[i] = Value.undef;
20313 continue;20347 continue;
20314 }20348 }
20315 const int = mask_elem_val.toSignedInt();20349 const int = mask_elem_val.toSignedInt(sema.mod.getTarget());
20316 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int);20350 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int);
20317 if (int >= 0) {20351 if (int >= 0) {
20318 values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned);20352 values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned);
...@@ -24040,6 +24074,25 @@ const CoerceOpts = struct {...@@ -24040,6 +24074,25 @@ const CoerceOpts = struct {
24040 is_ret: bool = false,24074 is_ret: bool = false,
24041 /// Should coercion to comptime_int ermit an error message.24075 /// Should coercion to comptime_int ermit an error message.
24042 no_cast_to_comptime_int: bool = false,24076 no_cast_to_comptime_int: bool = false,
24077
24078 param_src: struct {
24079 func_inst: Air.Inst.Ref = .none,
24080 param_i: u32 = undefined,
24081
24082 fn get(info: @This(), sema: *Sema) !?Module.SrcLoc {
24083 if (info.func_inst == .none) return null;
24084 const fn_decl = (try sema.funcDeclSrc(info.func_inst)) orelse return null;
24085 const param_src = Module.paramSrc(0, sema.gpa, fn_decl, info.param_i);
24086 if (param_src == .node_offset_param) {
24087 return Module.SrcLoc{
24088 .file_scope = fn_decl.getFileScope(),
24089 .parent_decl_node = fn_decl.src_node,
24090 .lazy = LazySrcLoc.nodeOffset(param_src.node_offset_param),
24091 };
24092 }
24093 return param_src.toSrcLoc(fn_decl);
24094 }
24095 } = .{},
24043};24096};
2404424097
24045fn coerceExtra(24098fn coerceExtra(
...@@ -24699,6 +24752,10 @@ fn coerceExtra(...@@ -24699,6 +24752,10 @@ fn coerceExtra(
24699 }24752 }
24700 }24753 }
2470124754
24755 if (try opts.param_src.get(sema)) |param_src| {
24756 try sema.mod.errNoteNonLazy(param_src, msg, "parameter type declared here", .{});
24757 }
24758
24702 // TODO maybe add "cannot store an error in type '{}'" note24759 // TODO maybe add "cannot store an error in type '{}'" note
2470324760
24704 break :msg msg;24761 break :msg msg;
...@@ -28307,6 +28364,7 @@ fn cmpNumeric(...@@ -28307,6 +28364,7 @@ fn cmpNumeric(
2830728364
28308 var lhs_bits: usize = undefined;28365 var lhs_bits: usize = undefined;
28309 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {28366 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {
28367 try sema.resolveLazyValue(lhs_val);
28310 if (lhs_val.isUndef())28368 if (lhs_val.isUndef())
28311 return sema.addConstUndef(Type.bool);28369 return sema.addConstUndef(Type.bool);
28312 if (lhs_val.isNan()) switch (op) {28370 if (lhs_val.isNan()) switch (op) {
...@@ -28365,6 +28423,7 @@ fn cmpNumeric(...@@ -28365,6 +28423,7 @@ fn cmpNumeric(
2836528423
28366 var rhs_bits: usize = undefined;28424 var rhs_bits: usize = undefined;
28367 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {28425 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
28426 try sema.resolveLazyValue(rhs_val);
28368 if (rhs_val.isUndef())28427 if (rhs_val.isUndef())
28369 return sema.addConstUndef(Type.bool);28428 return sema.addConstUndef(Type.bool);
28370 if (rhs_val.isNan()) switch (op) {28429 if (rhs_val.isNan()) switch (op) {
...@@ -29237,6 +29296,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -29237,6 +29296,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
2923729296
29238 struct_obj.status = .have_layout;29297 struct_obj.status = .have_layout;
29239 _ = try sema.resolveTypeRequiresComptime(resolved_ty);29298 _ = try sema.resolveTypeRequiresComptime(resolved_ty);
29299
29300 if (struct_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) {
29301 const msg = try Module.ErrorMsg.create(
29302 sema.gpa,
29303 struct_obj.srcLoc(sema.mod),
29304 "struct layout depends on it having runtime bits",
29305 .{},
29306 );
29307 return sema.failWithOwnedErrorMsg(msg);
29308 }
29240 }29309 }
29241 // otherwise it's a tuple; no need to resolve anything29310 // otherwise it's a tuple; no need to resolve anything
29242}29311}
...@@ -29401,6 +29470,16 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -29401,6 +29470,16 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
29401 }29470 }
29402 union_obj.status = .have_layout;29471 union_obj.status = .have_layout;
29403 _ = try sema.resolveTypeRequiresComptime(resolved_ty);29472 _ = try sema.resolveTypeRequiresComptime(resolved_ty);
29473
29474 if (union_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) {
29475 const msg = try Module.ErrorMsg.create(
29476 sema.gpa,
29477 union_obj.srcLoc(sema.mod),
29478 "union layout depends on it having runtime bits",
29479 .{},
29480 );
29481 return sema.failWithOwnedErrorMsg(msg);
29482 }
29404}29483}
2940529484
29406// In case of querying the ABI alignment of this struct, we will ask29485// In case of querying the ABI alignment of this struct, we will ask
src/Zir.zig+4-4
...@@ -519,7 +519,7 @@ pub const Inst = struct {...@@ -519,7 +519,7 @@ pub const Inst = struct {
519 /// Includes an operand as the return value.519 /// Includes an operand as the return value.
520 /// Includes a token source location.520 /// Includes a token source location.
521 /// Uses the `un_tok` union field.521 /// Uses the `un_tok` union field.
522 ret_tok,522 ret_implicit,
523 /// Sends control flow back to the function's callee.523 /// Sends control flow back to the function's callee.
524 /// The return operand is `error.foo` where `foo` is given by the string.524 /// The return operand is `error.foo` where `foo` is given by the string.
525 /// If the current function has an inferred error set, the error given by the525 /// If the current function has an inferred error set, the error given by the
...@@ -1256,7 +1256,7 @@ pub const Inst = struct {...@@ -1256,7 +1256,7 @@ pub const Inst = struct {
1256 .compile_error,1256 .compile_error,
1257 .ret_node,1257 .ret_node,
1258 .ret_load,1258 .ret_load,
1259 .ret_tok,1259 .ret_implicit,
1260 .ret_err_value,1260 .ret_err_value,
1261 .@"unreachable",1261 .@"unreachable",
1262 .repeat,1262 .repeat,
...@@ -1530,7 +1530,7 @@ pub const Inst = struct {...@@ -1530,7 +1530,7 @@ pub const Inst = struct {
1530 .compile_error,1530 .compile_error,
1531 .ret_node,1531 .ret_node,
1532 .ret_load,1532 .ret_load,
1533 .ret_tok,1533 .ret_implicit,
1534 .ret_err_value,1534 .ret_err_value,
1535 .ret_ptr,1535 .ret_ptr,
1536 .ret_type,1536 .ret_type,
...@@ -1659,7 +1659,7 @@ pub const Inst = struct {...@@ -1659,7 +1659,7 @@ pub const Inst = struct {
1659 .ref = .un_tok,1659 .ref = .un_tok,
1660 .ret_node = .un_node,1660 .ret_node = .un_node,
1661 .ret_load = .un_node,1661 .ret_load = .un_node,
1662 .ret_tok = .un_tok,1662 .ret_implicit = .un_tok,
1663 .ret_err_value = .str_tok,1663 .ret_err_value = .str_tok,
1664 .ret_err_value_code = .str_tok,1664 .ret_err_value_code = .str_tok,
1665 .ret_ptr = .node,1665 .ret_ptr = .node,
src/arch/aarch64/CodeGen.zig+1-1
...@@ -6113,7 +6113,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6113,7 +6113,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6113 if (info.bits <= 64) {6113 if (info.bits <= 64) {
6114 const unsigned = switch (info.signedness) {6114 const unsigned = switch (info.signedness) {
6115 .signed => blk: {6115 .signed => blk: {
6116 const signed = typed_value.val.toSignedInt();6116 const signed = typed_value.val.toSignedInt(target);
6117 break :blk @bitCast(u64, signed);6117 break :blk @bitCast(u64, signed);
6118 },6118 },
6119 .unsigned => typed_value.val.toUnsignedInt(target),6119 .unsigned => typed_value.val.toUnsignedInt(target),
src/arch/arm/CodeGen.zig+1-1
...@@ -6070,7 +6070,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6070,7 +6070,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6070 if (info.bits <= ptr_bits) {6070 if (info.bits <= ptr_bits) {
6071 const unsigned = switch (info.signedness) {6071 const unsigned = switch (info.signedness) {
6072 .signed => blk: {6072 .signed => blk: {
6073 const signed = @intCast(i32, typed_value.val.toSignedInt());6073 const signed = @intCast(i32, typed_value.val.toSignedInt(target));
6074 break :blk @bitCast(u32, signed);6074 break :blk @bitCast(u32, signed);
6075 },6075 },
6076 .unsigned => @intCast(u32, typed_value.val.toUnsignedInt(target)),6076 .unsigned => @intCast(u32, typed_value.val.toUnsignedInt(target)),
src/arch/sparc64/CodeGen.zig+1-1
...@@ -3751,7 +3751,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -3751,7 +3751,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
3751 if (info.bits <= 64) {3751 if (info.bits <= 64) {
3752 const unsigned = switch (info.signedness) {3752 const unsigned = switch (info.signedness) {
3753 .signed => blk: {3753 .signed => blk: {
3754 const signed = typed_value.val.toSignedInt();3754 const signed = typed_value.val.toSignedInt(target);
3755 break :blk @bitCast(u64, signed);3755 break :blk @bitCast(u64, signed);
3756 },3756 },
3757 .unsigned => typed_value.val.toUnsignedInt(target),3757 .unsigned => typed_value.val.toUnsignedInt(target),
src/arch/wasm/CodeGen.zig+5-5
...@@ -2670,11 +2670,11 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -2670,11 +2670,11 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
2670 switch (int_info.signedness) {2670 switch (int_info.signedness) {
2671 .signed => switch (int_info.bits) {2671 .signed => switch (int_info.bits) {
2672 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement(2672 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement(
2673 val.toSignedInt(),2673 val.toSignedInt(target),
2674 @intCast(u6, int_info.bits),2674 @intCast(u6, int_info.bits),
2675 )) },2675 )) },
2676 33...64 => return WValue{ .imm64 = toTwosComplement(2676 33...64 => return WValue{ .imm64 = toTwosComplement(
2677 val.toSignedInt(),2677 val.toSignedInt(target),
2678 @intCast(u7, int_info.bits),2678 @intCast(u7, int_info.bits),
2679 ) },2679 ) },
2680 else => unreachable,2680 else => unreachable,
...@@ -2841,15 +2841,15 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {...@@ -2841,15 +2841,15 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {
2841 }2841 }
2842 },2842 },
2843 .Int => switch (ty.intInfo(func.target).signedness) {2843 .Int => switch (ty.intInfo(func.target).signedness) {
2844 .signed => return @truncate(i32, val.toSignedInt()),2844 .signed => return @truncate(i32, val.toSignedInt(target)),
2845 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(target))),2845 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(target))),
2846 },2846 },
2847 .ErrorSet => {2847 .ErrorSet => {
2848 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function2848 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
2849 return @bitCast(i32, kv.value);2849 return @bitCast(i32, kv.value);
2850 },2850 },
2851 .Bool => return @intCast(i32, val.toSignedInt()),2851 .Bool => return @intCast(i32, val.toSignedInt(target)),
2852 .Pointer => return @intCast(i32, val.toSignedInt()),2852 .Pointer => return @intCast(i32, val.toSignedInt(target)),
2853 else => unreachable, // Programmer called this function for an illegal type2853 else => unreachable, // Programmer called this function for an illegal type
2854 }2854 }
2855}2855}
src/arch/x86_64/CodeGen.zig+1-1
...@@ -6862,7 +6862,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6862,7 +6862,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6862 .Int => {6862 .Int => {
6863 const info = typed_value.ty.intInfo(self.target.*);6863 const info = typed_value.ty.intInfo(self.target.*);
6864 if (info.bits <= ptr_bits and info.signedness == .signed) {6864 if (info.bits <= ptr_bits and info.signedness == .signed) {
6865 return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) };6865 return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt(target)) };
6866 }6866 }
6867 if (!(info.bits > ptr_bits or info.signedness == .signed)) {6867 if (!(info.bits > ptr_bits or info.signedness == .signed)) {
6868 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };6868 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
src/codegen.zig+7-7
...@@ -472,7 +472,7 @@ pub fn generateSymbol(...@@ -472,7 +472,7 @@ pub fn generateSymbol(
472 if (info.bits <= 8) {472 if (info.bits <= 8) {
473 const x: u8 = switch (info.signedness) {473 const x: u8 = switch (info.signedness) {
474 .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)),474 .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)),
475 .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt())),475 .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt(target))),
476 };476 };
477 try code.append(x);477 try code.append(x);
478 return Result{ .appended = {} };478 return Result{ .appended = {} };
...@@ -501,13 +501,13 @@ pub fn generateSymbol(...@@ -501,13 +501,13 @@ pub fn generateSymbol(
501 },501 },
502 .signed => {502 .signed => {
503 if (info.bits <= 16) {503 if (info.bits <= 16) {
504 const x = @intCast(i16, typed_value.val.toSignedInt());504 const x = @intCast(i16, typed_value.val.toSignedInt(target));
505 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);505 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
506 } else if (info.bits <= 32) {506 } else if (info.bits <= 32) {
507 const x = @intCast(i32, typed_value.val.toSignedInt());507 const x = @intCast(i32, typed_value.val.toSignedInt(target));
508 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);508 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
509 } else {509 } else {
510 const x = typed_value.val.toSignedInt();510 const x = typed_value.val.toSignedInt(target);
511 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);511 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
512 }512 }
513 },513 },
...@@ -549,13 +549,13 @@ pub fn generateSymbol(...@@ -549,13 +549,13 @@ pub fn generateSymbol(
549 },549 },
550 .signed => {550 .signed => {
551 if (info.bits <= 16) {551 if (info.bits <= 16) {
552 const x = @intCast(i16, int_val.toSignedInt());552 const x = @intCast(i16, int_val.toSignedInt(target));
553 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);553 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
554 } else if (info.bits <= 32) {554 } else if (info.bits <= 32) {
555 const x = @intCast(i32, int_val.toSignedInt());555 const x = @intCast(i32, int_val.toSignedInt(target));
556 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);556 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
557 } else {557 } else {
558 const x = int_val.toSignedInt();558 const x = int_val.toSignedInt(target);
559 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);559 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
560 }560 }
561 },561 },
src/codegen/llvm.zig+1-1
...@@ -8932,7 +8932,7 @@ pub const FuncGen = struct {...@@ -8932,7 +8932,7 @@ pub const FuncGen = struct {
8932 if (elem.isUndef()) {8932 if (elem.isUndef()) {
8933 val.* = llvm_i32.getUndef();8933 val.* = llvm_i32.getUndef();
8934 } else {8934 } else {
8935 const int = elem.toSignedInt();8935 const int = elem.toSignedInt(self.dg.module.getTarget());
8936 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);8936 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
8937 val.* = llvm_i32.constInt(unsigned, .False);8937 val.* = llvm_i32.constInt(unsigned, .False);
8938 }8938 }
src/codegen/spirv.zig+2-2
...@@ -360,7 +360,7 @@ pub const DeclGen = struct {...@@ -360,7 +360,7 @@ pub const DeclGen = struct {
360360
361 // Note, value is required to be sign-extended, so we don't need to mask off the upper bits.361 // Note, value is required to be sign-extended, so we don't need to mask off the upper bits.
362 // See https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Literal362 // See https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Literal
363 var int_bits = if (ty.isSignedInt()) @bitCast(u64, val.toSignedInt()) else val.toUnsignedInt(target);363 var int_bits = if (ty.isSignedInt()) @bitCast(u64, val.toSignedInt(target)) else val.toUnsignedInt(target);
364364
365 const value: spec.LiteralContextDependentNumber = switch (backing_bits) {365 const value: spec.LiteralContextDependentNumber = switch (backing_bits) {
366 1...32 => .{ .uint32 = @truncate(u32, int_bits) },366 1...32 => .{ .uint32 = @truncate(u32, int_bits) },
...@@ -763,7 +763,7 @@ pub const DeclGen = struct {...@@ -763,7 +763,7 @@ pub const DeclGen = struct {
763 if (elem.isUndef()) {763 if (elem.isUndef()) {
764 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);764 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);
765 } else {765 } else {
766 const int = elem.toSignedInt();766 const int = elem.toSignedInt(self.getTarget());
767 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);767 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
768 self.func.body.writeOperand(spec.LiteralInteger, unsigned);768 self.func.body.writeOperand(spec.LiteralInteger, unsigned);
769 }769 }
src/link/Dwarf.zig+1-1
...@@ -410,7 +410,7 @@ pub const DeclState = struct {...@@ -410,7 +410,7 @@ pub const DeclState = struct {
410 // See https://github.com/ziglang/zig/issues/645410 // See https://github.com/ziglang/zig/issues/645
411 var int_buffer: Value.Payload.U64 = undefined;411 var int_buffer: Value.Payload.U64 = undefined;
412 const field_int_val = value.enumToInt(ty, &int_buffer);412 const field_int_val = value.enumToInt(ty, &int_buffer);
413 break :value @bitCast(u64, field_int_val.toSignedInt());413 break :value @bitCast(u64, field_int_val.toSignedInt(target));
414 } else @intCast(u64, field_i);414 } else @intCast(u64, field_i);
415 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);415 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);
416 }416 }
src/print_zir.zig+1-1
...@@ -235,7 +235,7 @@ const Writer = struct {...@@ -235,7 +235,7 @@ const Writer = struct {
235 => try self.writeUnNode(stream, inst),235 => try self.writeUnNode(stream, inst),
236236
237 .ref,237 .ref,
238 .ret_tok,238 .ret_implicit,
239 .closure_capture,239 .closure_capture,
240 .switch_capture_tag,240 .switch_capture_tag,
241 => try self.writeUnTok(stream, inst),241 => try self.writeUnTok(stream, inst),
src/type.zig+46-8
...@@ -160,6 +160,17 @@ pub const Type = extern union {...@@ -160,6 +160,17 @@ pub const Type = extern union {
160 }160 }
161 }161 }
162162
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 pub fn isSelfComparable(ty: Type, is_equality_cmp: bool) bool {174 pub fn isSelfComparable(ty: Type, is_equality_cmp: bool) bool {
164 return switch (ty.zigTypeTag()) {175 return switch (ty.zigTypeTag()) {
165 .Int,176 .Int,
...@@ -2459,6 +2470,7 @@ pub const Type = extern union {...@@ -2459,6 +2470,7 @@ pub const Type = extern union {
2459 if (struct_obj.status == .field_types_wip) {2470 if (struct_obj.status == .field_types_wip) {
2460 // In this case, we guess that hasRuntimeBits() for this type is true,2471 // In this case, we guess that hasRuntimeBits() for this type is true,
2461 // and then later if our guess was incorrect, we emit a compile error.2472 // and then later if our guess was incorrect, we emit a compile error.
2473 struct_obj.assumed_runtime_bits = true;
2462 return true;2474 return true;
2463 }2475 }
2464 switch (strat) {2476 switch (strat) {
...@@ -2491,6 +2503,12 @@ pub const Type = extern union {...@@ -2491,6 +2503,12 @@ pub const Type = extern union {
24912503
2492 .@"union" => {2504 .@"union" => {
2493 const union_obj = ty.castTag(.@"union").?.data;2505 const union_obj = ty.castTag(.@"union").?.data;
2506 if (union_obj.status == .field_types_wip) {
2507 // In this case, we guess that hasRuntimeBits() for this type is true,
2508 // and then later if our guess was incorrect, we emit a compile error.
2509 union_obj.assumed_runtime_bits = true;
2510 return true;
2511 }
2494 switch (strat) {2512 switch (strat) {
2495 .sema => |sema| _ = try sema.resolveTypeFields(ty),2513 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2496 .eager => assert(union_obj.haveFieldTypes()),2514 .eager => assert(union_obj.haveFieldTypes()),
...@@ -3027,8 +3045,9 @@ pub const Type = extern union {...@@ -3027,8 +3045,9 @@ pub const Type = extern union {
3027 const struct_obj = ty.castTag(.@"struct").?.data;3045 const struct_obj = ty.castTag(.@"struct").?.data;
3028 if (opt_sema) |sema| {3046 if (opt_sema) |sema| {
3029 if (struct_obj.status == .field_types_wip) {3047 if (struct_obj.status == .field_types_wip) {
3030 // We'll guess "pointer-aligned" and if we guess wrong, emit3048 // We'll guess "pointer-aligned", if the struct has an
3031 // a compile error later.3049 // underaligned pointer field then some allocations
3050 // might require explicit alignment.
3032 return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };3051 return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };
3033 }3052 }
3034 _ = try sema.resolveTypeFields(ty);3053 _ = try sema.resolveTypeFields(ty);
...@@ -3153,8 +3172,9 @@ pub const Type = extern union {...@@ -3153,8 +3172,9 @@ pub const Type = extern union {
3153 };3172 };
3154 if (opt_sema) |sema| {3173 if (opt_sema) |sema| {
3155 if (union_obj.status == .field_types_wip) {3174 if (union_obj.status == .field_types_wip) {
3156 // We'll guess "pointer-aligned" and if we guess wrong, emit3175 // We'll guess "pointer-aligned", if the union has an
3157 // a compile error later.3176 // underaligned pointer field then some allocations
3177 // might require explicit alignment.
3158 return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };3178 return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };
3159 }3179 }
3160 _ = try sema.resolveTypeFields(ty);3180 _ = try sema.resolveTypeFields(ty);
...@@ -5234,7 +5254,12 @@ pub const Type = extern union {...@@ -5234,7 +5254,12 @@ pub const Type = extern union {
5234 .@"struct" => {5254 .@"struct" => {
5235 const struct_obj = ty.castTag(.@"struct").?.data;5255 const struct_obj = ty.castTag(.@"struct").?.data;
5236 switch (struct_obj.requires_comptime) {5256 switch (struct_obj.requires_comptime) {
5237 .wip, .unknown => unreachable, // This function asserts types already resolved.5257 .wip, .unknown => {
5258 // Return false to avoid incorrect dependency loops.
5259 // This will be handled correctly once merged with
5260 // `Sema.typeRequiresComptime`.
5261 return false;
5262 },
5238 .no => return false,5263 .no => return false,
5239 .yes => return true,5264 .yes => return true,
5240 }5265 }
...@@ -5243,7 +5268,12 @@ pub const Type = extern union {...@@ -5243,7 +5268,12 @@ pub const Type = extern union {
5243 .@"union", .union_safety_tagged, .union_tagged => {5268 .@"union", .union_safety_tagged, .union_tagged => {
5244 const union_obj = ty.cast(Type.Payload.Union).?.data;5269 const union_obj = ty.cast(Type.Payload.Union).?.data;
5245 switch (union_obj.requires_comptime) {5270 switch (union_obj.requires_comptime) {
5246 .wip, .unknown => unreachable, // This function asserts types already resolved.5271 .wip, .unknown => {
5272 // Return false to avoid incorrect dependency loops.
5273 // This will be handled correctly once merged with
5274 // `Sema.typeRequiresComptime`.
5275 return false;
5276 },
5247 .no => return false,5277 .no => return false,
5248 .yes => return true,5278 .yes => return true,
5249 }5279 }
...@@ -6472,8 +6502,16 @@ pub const Type = extern union {...@@ -6472,8 +6502,16 @@ pub const Type = extern union {
6472 // type, we change it to 0 here. If this causes an assertion trip because the6502 // type, we change it to 0 here. If this causes an assertion trip because the
6473 // pointee type needs to be resolved more, that needs to be done before calling6503 // pointee type needs to be resolved more, that needs to be done before calling
6474 // this ptr() function.6504 // this ptr() function.
6475 if (d.@"align" != 0 and d.@"align" == d.pointee_type.abiAlignment(target)) {6505 if (d.@"align" != 0) canonicalize: {
6476 d.@"align" = 0;6506 if (d.pointee_type.castTag(.@"struct")) |struct_ty| {
6507 if (!struct_ty.data.haveLayout()) break :canonicalize;
6508 }
6509 if (d.pointee_type.cast(Payload.Union)) |union_ty| {
6510 if (!union_ty.data.haveLayout()) break :canonicalize;
6511 }
6512 if (d.@"align" == d.pointee_type.abiAlignment(target)) {
6513 d.@"align" = 0;
6514 }
6477 }6515 }
64786516
6479 // Canonicalize host_size. If it matches the bit size of the pointee type,6517 // Canonicalize host_size. If it matches the bit size of the pointee type,
src/value.zig+16-7
...@@ -187,7 +187,7 @@ pub const Value = extern union {...@@ -187,7 +187,7 @@ pub const Value = extern union {
187 bound_fn,187 bound_fn,
188 /// The ABI alignment of the payload type.188 /// The ABI alignment of the payload type.
189 lazy_align,189 lazy_align,
190 /// The ABI alignment of the payload type.190 /// The ABI size of the payload type.
191 lazy_size,191 lazy_size,
192192
193 pub const last_no_payload_tag = Tag.empty_array;193 pub const last_no_payload_tag = Tag.empty_array;
...@@ -1201,8 +1201,8 @@ pub const Value = extern union {...@@ -1201,8 +1201,8 @@ pub const Value = extern union {
1201 }1201 }
12021202
1203 /// Asserts the value is an integer and it fits in a i641203 /// Asserts the value is an integer and it fits in a i64
1204 pub fn toSignedInt(self: Value) i64 {1204 pub fn toSignedInt(val: Value, target: Target) i64 {
1205 switch (self.tag()) {1205 switch (val.tag()) {
1206 .zero,1206 .zero,
1207 .bool_false,1207 .bool_false,
1208 .the_only_possible_value, // i0, u01208 .the_only_possible_value, // i0, u0
...@@ -1212,10 +1212,19 @@ pub const Value = extern union {...@@ -1212,10 +1212,19 @@ pub const Value = extern union {
1212 .bool_true,1212 .bool_true,
1213 => return 1,1213 => return 1,
12141214
1215 .int_u64 => return @intCast(i64, self.castTag(.int_u64).?.data),1215 .int_u64 => return @intCast(i64, val.castTag(.int_u64).?.data),
1216 .int_i64 => return self.castTag(.int_i64).?.data,1216 .int_i64 => return val.castTag(.int_i64).?.data,
1217 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,1217 .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,
1218 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,1218 .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,
1219
1220 .lazy_align => {
1221 const ty = val.castTag(.lazy_align).?.data;
1222 return @intCast(i64, ty.abiAlignment(target));
1223 },
1224 .lazy_size => {
1225 const ty = val.castTag(.lazy_size).?.data;
1226 return @intCast(i64, ty.abiSize(target));
1227 },
12191228
1220 .undef => unreachable,1229 .undef => unreachable,
1221 else => unreachable,1230 else => unreachable,
test/behavior.zig+1
...@@ -90,6 +90,7 @@ test {...@@ -90,6 +90,7 @@ test {
90 _ = @import("behavior/bugs/12430.zig");90 _ = @import("behavior/bugs/12430.zig");
91 _ = @import("behavior/bugs/12486.zig");91 _ = @import("behavior/bugs/12486.zig");
92 _ = @import("behavior/bugs/12488.zig");92 _ = @import("behavior/bugs/12488.zig");
93 _ = @import("behavior/bugs/12498.zig");
93 _ = @import("behavior/bugs/12551.zig");94 _ = @import("behavior/bugs/12551.zig");
94 _ = @import("behavior/bugs/12644.zig");95 _ = @import("behavior/bugs/12644.zig");
95 _ = @import("behavior/bugs/12680.zig");96 _ = @import("behavior/bugs/12680.zig");
test/behavior/bugs/12498.zig created+8
...@@ -0,0 +1,8 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const S = struct { a: usize };
5test "lazy abi size used in comparison" {
6 var rhs: i32 = 100;
7 try expect(@sizeOf(S) < rhs);
8}
test/behavior/struct.zig+12
...@@ -1406,3 +1406,15 @@ test "address of zero-bit field is equal to address of only field" {...@@ -1406,3 +1406,15 @@ test "address of zero-bit field is equal to address of only field" {
1406 try std.testing.expectEqual(&a, a_ptr);1406 try std.testing.expectEqual(&a, a_ptr);
1407 }1407 }
1408}1408}
1409
1410test "struct field has a pointer to an aligned version of itself" {
1411 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1412
1413 const E = struct {
1414 next: *align(1) @This(),
1415 };
1416 var e: E = undefined;
1417 e = .{ .next = &e };
1418
1419 try expect(&e == e.next);
1420}
test/cases/aarch64-macos/hello_world_with_updates.1.zig+2-2
...@@ -2,5 +2,5 @@ pub export fn main() noreturn {}...@@ -2,5 +2,5 @@ pub export fn main() noreturn {}
22
3// error3// error
4//4//
5// :1:32: error: function declared 'noreturn' returns5// :1:22: error: function declared 'noreturn' implicitly returns
6// :1:22: note: 'noreturn' declared here6// :1:32: note: control flow reaches end of body here
test/cases/compile_errors/calling_var_args_extern_function_passing_array_instead_of_pointer.zig+1
...@@ -8,3 +8,4 @@ pub extern fn foo(format: *const u8, ...) void;...@@ -8,3 +8,4 @@ pub extern fn foo(format: *const u8, ...) void;
8// target=native8// target=native
9//9//
10// :2:16: error: expected type '*const u8', found '[5:0]u8'10// :2:16: error: expected type '*const u8', found '[5:0]u8'
11// :4:27: note: parameter type declared here
test/cases/compile_errors/casting_bit_offset_pointer_to_regular_pointer.zig+1
...@@ -21,3 +21,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }...@@ -21,3 +21,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }
21// :8:16: error: expected type '*const u3', found '*align(0:3:1) const u3'21// :8:16: error: expected type '*const u3', found '*align(0:3:1) const u3'
22// :8:16: note: pointer host size '1' cannot cast into pointer host size '0'22// :8:16: note: pointer host size '1' cannot cast into pointer host size '0'
23// :8:16: note: pointer bit offset '3' cannot cast into pointer bit offset '0'23// :8:16: note: pointer bit offset '3' cannot cast into pointer bit offset '0'
24// :11:11: note: parameter type declared here
test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig+1
...@@ -22,3 +22,4 @@ pub export fn entry() void {...@@ -22,3 +22,4 @@ pub export fn entry() void {
22// target=native22// target=native
23//23//
24// :17:25: error: expected type 'u32', found 'type'24// :17:25: error: expected type 'u32', found 'type'
25// :3:21: note: parameter type declared here
test/cases/compile_errors/control_reaches_end_of_non-void_function.zig deleted-9
...@@ -1,9 +0,0 @@
1fn a() i32 {}
2export 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/disallow_coercion_from_non-null-terminated_pointer_to_null-terminated_pointer.zig+1
...@@ -11,3 +11,4 @@ pub export fn entry() void {...@@ -11,3 +11,4 @@ pub export fn entry() void {
11//11//
12// :5:14: error: expected type '[*:0]const u8', found '[*]const u8'12// :5:14: error: expected type '[*:0]const u8', found '[*]const u8'
13// :5:14: note: destination pointer requires '0' sentinel13// :5:14: note: destination pointer requires '0' sentinel
14// :1:20: note: parameter type declared here
test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig+1
...@@ -24,5 +24,6 @@ pub export fn entry3() void {...@@ -24,5 +24,6 @@ pub export fn entry3() void {
24// :4:35: note: cannot implicitly cast double pointer '*const *const usize' to anyopaque pointer '*const anyopaque'24// :4:35: note: cannot implicitly cast double pointer '*const *const usize' to anyopaque pointer '*const anyopaque'
25// :9:10: error: expected type '?*anyopaque', found '*[*:0]u8'25// :9:10: error: expected type '?*anyopaque', found '*[*:0]u8'
26// :9:10: note: cannot implicitly cast double pointer '*[*:0]u8' to anyopaque pointer '?*anyopaque'26// :9:10: note: cannot implicitly cast double pointer '*[*:0]u8' to anyopaque pointer '?*anyopaque'
27// :11:12: note: parameter type declared here
27// :15:35: error: expected type '*const anyopaque', found '*?*usize'28// :15:35: error: expected type '*const anyopaque', found '*?*usize'
28// :15:35: note: cannot implicitly cast double pointer '*?*usize' to anyopaque pointer '*const anyopaque'29// :15:35: note: cannot implicitly cast double pointer '*?*usize' to anyopaque pointer '*const anyopaque'
test/cases/compile_errors/implicitly_increasing_pointer_alignment.zig+1
...@@ -18,3 +18,4 @@ fn bar(x: *u32) void {...@@ -18,3 +18,4 @@ fn bar(x: *u32) void {
18//18//
19// :8:9: error: expected type '*u32', found '*align(1) u32'19// :8:9: error: expected type '*u32', found '*align(1) u32'
20// :8:9: note: pointer alignment '1' cannot cast into pointer alignment '4'20// :8:9: note: pointer alignment '1' cannot cast into pointer alignment '4'
21// :11:11: note: parameter type declared here
test/cases/compile_errors/invalid_compare_string.zig created+29
...@@ -0,0 +1,29 @@
1comptime {
2 var a = "foo";
3 if (a == "foo") unreachable;
4}
5comptime {
6 var a = "foo";
7 if (a == ("foo")) unreachable; // intentionally allow
8}
9comptime {
10 var a = "foo";
11 switch (a) {
12 "foo" => unreachable,
13 else => {},
14 }
15}
16comptime {
17 var a = "foo";
18 switch (a) {
19 ("foo") => unreachable, // intentionally allow
20 else => {},
21 }
22}
23
24// error
25// backend=stage2
26// target=native
27//
28// :3:11: error: cannot compare strings with ==
29// :12:9: error: cannot switch on strings
test/cases/compile_errors/invalid_dependency_on_struct_size.zig created+19
...@@ -0,0 +1,19 @@
1comptime {
2 const S = struct {
3 const Foo = struct {
4 y: Bar,
5 };
6 const Bar = struct {
7 y: if (@sizeOf(Foo) == 0) u64 else void,
8 };
9 };
10
11 _ = @sizeOf(S.Foo) + 1;
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :6:21: error: struct layout depends on it having runtime bits
19// :4:13: note: while checking this field
test/cases/compile_errors/missing_parameter_name.zig created+19
...@@ -0,0 +1,19 @@
1fn f2(u64) u64 {
2 return x;
3}
4fn f3(*x) u64 {
5 return x;
6}
7fn f1(x) u64 {
8 return x;
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :1:7: error: missing parameter name
16// :4:7: error: missing parameter name
17// :7:7: error: missing parameter name or type
18// :7:7: note: if this is a name, annotate its type 'x: T'
19// :7:7: note: if this is a type, give it a name '<name>: x'
test/cases/compile_errors/pass_const_ptr_to_mutable_ptr_fn.zig+1
...@@ -16,3 +16,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }...@@ -16,3 +16,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }
16//16//
17// :4:19: error: expected type '*[]const u8', found '*const []const u8'17// :4:19: error: expected type '*[]const u8', found '*const []const u8'
18// :4:19: note: cast discards const qualifier18// :4:19: note: cast discards const qualifier
19// :6:14: note: parameter type declared here
test/cases/compile_errors/struct_init_passed_to_type_param.zig+1
...@@ -12,3 +12,4 @@ export const value = hi(MyStruct{ .x = 12 });...@@ -12,3 +12,4 @@ export const value = hi(MyStruct{ .x = 12 });
12//12//
13// :7:33: error: expected type 'type', found 'tmp.MyStruct'13// :7:33: error: expected type 'type', found 'tmp.MyStruct'
14// :1:18: note: struct declared here14// :1:18: note: struct declared here
15// :3:19: note: parameter type declared here
test/cases/compile_errors/struct_type_mismatch_in_arg.zig created+18
...@@ -0,0 +1,18 @@
1const Foo = struct { i: i32 };
2const Bar = struct { j: i32 };
3
4pub fn helper(_: Foo, _: Bar) void { }
5
6comptime {
7 helper(Bar { .j = 10 }, Bar { .j = 10 });
8 helper(Bar { .i = 10 }, Bar { .j = 10 });
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :7:16: error: expected type 'tmp.Foo', found 'tmp.Bar'
16// :1:13: note: struct declared here
17// :2:13: note: struct declared here
18// :4:18: note: parameter type declared here
test/cases/compile_errors/switch_on_slice.zig+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1pub export fn entry() void {1pub export fn entry() void {
2 var a: [:0]const u8 = "foo";2 var a: [:0]const u8 = "foo";
3 switch (a) {3 switch (a) {
4 "--version", "version" => unreachable,4 ("--version"), ("version") => unreachable,
5 else => {},5 else => {},
6 }6 }
7}7}
test/cases/compile_errors/type_error_in_implicit_return.zig created+17
...@@ -0,0 +1,17 @@
1fn f1(x: bool) u32 {
2 if (x) return 1;
3}
4fn f2() noreturn {}
5pub 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/compile_errors/wrong_pointer_coerced_to_pointer_to_opaque_{}.zig+1
...@@ -12,3 +12,4 @@ export fn foo() void {...@@ -12,3 +12,4 @@ export fn foo() void {
12// :5:9: error: expected type '*tmp.Derp', found '*anyopaque'12// :5:9: error: expected type '*tmp.Derp', found '*anyopaque'
13// :5:9: note: pointer type child 'anyopaque' cannot cast into pointer type child 'tmp.Derp'13// :5:9: note: pointer type child 'anyopaque' cannot cast into pointer type child 'tmp.Derp'
14// :1:14: note: opaque declared here14// :1:14: note: opaque declared here
15// :2:18: note: parameter type declared here
test/cases/x86_64-linux/hello_world_with_updates.1.zig+3-3
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1pub export fn _start() noreturn {}1pub export fn main() noreturn {}
22
3// error3// error
4//4//
5// :1:34: error: function declared 'noreturn' returns5// :1:22: error: function declared 'noreturn' implicitly returns
6// :1:24: note: 'noreturn' declared here6// :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,5 +2,5 @@ pub export fn main() noreturn {}
22
3// error3// error
4//4//
5// :1:32: error: function declared 'noreturn' returns5// :1:22: error: function declared 'noreturn' implicitly returns
6// :1:22: note: 'noreturn' declared here6// :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,5 +2,5 @@ pub export fn main() noreturn {}
22
3// error3// error
4//4//
5// :1:32: error: function declared 'noreturn' returns5// :1:22: error: function declared 'noreturn' implicitly returns
6// :1:22: note: 'noreturn' declared here6// :1:32: note: control flow reaches end of body here