| author | |
| committer | |
| log | af958e95cc0a78404e604400f509ea0c219614d1 |
| tree | 899f3b4d0a2de3c89b9fb5d66fd4934a38cdad9f |
| parent | fd57487e3593dfd0bc9c62a945bcf57f16ff6fae |
Improve error messages, fix dependency loops40 files changed, 377 insertions(+), 94 deletions(-)
lib/std/fs.zig-2| ... | ... | @@ -809,8 +809,6 @@ pub const IterableDir = struct { |
| 809 | 809 | // and we avoid the code complexity here. |
| 810 | 810 | const w = os.wasi; |
| 811 | 811 | start_over: while (true) { |
| 812 | // TODO https://github.com/ziglang/zig/issues/12498 | |
| 813 | _ = @sizeOf(w.dirent_t) + 1; | |
| 814 | 812 | // According to the WASI spec, the last entry might be truncated, |
| 815 | 813 | // so we need to check if the left buffer contains the whole dirent. |
| 816 | 814 | if (self.end_index - self.index < @sizeOf(w.dirent_t)) { |
src/AstGen.zig+41-7| ... | ... | @@ -2625,7 +2625,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2625 | 2625 | .compile_error, |
| 2626 | 2626 | .ret_node, |
| 2627 | 2627 | .ret_load, |
| 2628 | .ret_tok, | |
| 2628 | .ret_implicit, | |
| 2629 | 2629 | .ret_err_value, |
| 2630 | 2630 | .@"unreachable", |
| 2631 | 2631 | .repeat, |
| ... | ... | @@ -3689,6 +3689,29 @@ fn fnDecl( |
| 3689 | 3689 | if (param.anytype_ellipsis3) |tok| { |
| 3690 | 3690 | return astgen.failTok(tok, "missing parameter name", .{}); |
| 3691 | 3691 | } else { |
| 3692 | ambiguous: { | |
| 3693 | if (tree.nodes.items(.tag)[param.type_expr] != .identifier) break :ambiguous; | |
| 3694 | const main_token = tree.nodes.items(.main_token)[param.type_expr]; | |
| 3695 | const identifier_str = tree.tokenSlice(main_token); | |
| 3696 | if (isPrimitive(identifier_str)) break :ambiguous; | |
| 3697 | return astgen.failNodeNotes( | |
| 3698 | param.type_expr, | |
| 3699 | "missing parameter name or type", | |
| 3700 | .{}, | |
| 3701 | &[_]u32{ | |
| 3702 | try astgen.errNoteNode( | |
| 3703 | param.type_expr, | |
| 3704 | "if this is a name, annotate its type '{s}: T'", | |
| 3705 | .{identifier_str}, | |
| 3706 | ), | |
| 3707 | try astgen.errNoteNode( | |
| 3708 | param.type_expr, | |
| 3709 | "if this is a type, give it a name '<name>: {s}'", | |
| 3710 | .{identifier_str}, | |
| 3711 | ), | |
| 3712 | }, | |
| 3713 | ); | |
| 3714 | } | |
| 3692 | 3715 | return astgen.failNode(param.type_expr, "missing parameter name", .{}); |
| 3693 | 3716 | } |
| 3694 | 3717 | } else 0; |
| ... | ... | @@ -3884,9 +3907,8 @@ fn fnDecl( |
| 3884 | 3907 | // As our last action before the return, "pop" the error trace if needed |
| 3885 | 3908 | _ = try gz.addRestoreErrRetIndex(.ret, .always); |
| 3886 | 3909 | |
| 3887 | // Since we are adding the return instruction here, we must handle the coercion. | |
| 3888 | // We do this by using the `ret_tok` instruction. | |
| 3889 | _ = try fn_gz.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node)); | |
| 3910 | // Add implicit return at end of function. | |
| 3911 | _ = try fn_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node)); | |
| 3890 | 3912 | } |
| 3891 | 3913 | |
| 3892 | 3914 | break :func try decl_gz.addFunc(.{ |
| ... | ... | @@ -4330,9 +4352,8 @@ fn testDecl( |
| 4330 | 4352 | // As our last action before the return, "pop" the error trace if needed |
| 4331 | 4353 | _ = try gz.addRestoreErrRetIndex(.ret, .always); |
| 4332 | 4354 | |
| 4333 | // Since we are adding the return instruction here, we must handle the coercion. | |
| 4334 | // We do this by using the `ret_tok` instruction. | |
| 4335 | _ = try fn_block.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node)); | |
| 4355 | // Add implicit return at end of function. | |
| 4356 | _ = try fn_block.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node)); | |
| 4336 | 4357 | } |
| 4337 | 4358 | |
| 4338 | 4359 | const func_inst = try decl_block.addFunc(.{ |
| ... | ... | @@ -5580,6 +5601,14 @@ fn simpleBinOp( |
| 5580 | 5601 | const tree = astgen.tree; |
| 5581 | 5602 | const node_datas = tree.nodes.items(.data); |
| 5582 | 5603 | |
| 5604 | if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) { | |
| 5605 | const node_tags = tree.nodes.items(.tag); | |
| 5606 | const str = if (op_inst_tag == .cmp_eq) "==" else "!="; | |
| 5607 | if (node_tags[node_datas[node].lhs] == .string_literal or | |
| 5608 | node_tags[node_datas[node].rhs] == .string_literal) | |
| 5609 | return astgen.failNode(node, "cannot compare strings with {s}", .{str}); | |
| 5610 | } | |
| 5611 | ||
| 5583 | 5612 | const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node); |
| 5584 | 5613 | var line: u32 = undefined; |
| 5585 | 5614 | var column: u32 = undefined; |
| ... | ... | @@ -6577,6 +6606,11 @@ fn switchExpr( |
| 6577 | 6606 | continue; |
| 6578 | 6607 | } |
| 6579 | 6608 | |
| 6609 | for (case.ast.values) |val| { | |
| 6610 | if (node_tags[val] == .string_literal) | |
| 6611 | return astgen.failNode(val, "cannot switch on strings", .{}); | |
| 6612 | } | |
| 6613 | ||
| 6580 | 6614 | if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) { |
| 6581 | 6615 | scalar_cases_len += 1; |
| 6582 | 6616 | } else { |
src/Module.zig+2| ... | ... | @@ -938,6 +938,7 @@ pub const Struct = struct { |
| 938 | 938 | known_non_opv: bool, |
| 939 | 939 | requires_comptime: PropertyBoolean = .unknown, |
| 940 | 940 | have_field_inits: bool = false, |
| 941 | assumed_runtime_bits: bool = false, | |
| 941 | 942 | |
| 942 | 943 | pub const Fields = std.StringArrayHashMapUnmanaged(Field); |
| 943 | 944 | |
| ... | ... | @@ -1203,6 +1204,7 @@ pub const Union = struct { |
| 1203 | 1204 | fully_resolved, |
| 1204 | 1205 | }, |
| 1205 | 1206 | requires_comptime: PropertyBoolean = .unknown, |
| 1207 | assumed_runtime_bits: bool = false, | |
| 1206 | 1208 | |
| 1207 | 1209 | pub const Field = struct { |
| 1208 | 1210 | /// undefined until `status` is `have_field_types` or `have_layout`. |
src/Sema.zig+106-27| ... | ... | @@ -195,8 +195,8 @@ pub const Block = struct { |
| 195 | 195 | try sema.errNote(ci.block, ci.src, parent, prefix ++ "it is inside a @cImport", .{}); |
| 196 | 196 | }, |
| 197 | 197 | .comptime_ret_ty => |rt| { |
| 198 | const src_loc = if (try sema.funcDeclSrc(rt.func)) |capture| blk: { | |
| 199 | var src_loc = capture; | |
| 198 | const src_loc = if (try sema.funcDeclSrc(rt.func)) |fn_decl| blk: { | |
| 199 | var src_loc = fn_decl.srcLoc(); | |
| 200 | 200 | src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 201 | 201 | break :blk src_loc; |
| 202 | 202 | } else blk: { |
| ... | ... | @@ -1000,7 +1000,7 @@ fn analyzeBodyInner( |
| 1000 | 1000 | // These functions match the return type of analyzeBody so that we can |
| 1001 | 1001 | // tail call them here. |
| 1002 | 1002 | .compile_error => break sema.zirCompileError(block, inst), |
| 1003 | .ret_tok => break sema.zirRetTok(block, inst), | |
| 1003 | .ret_implicit => break sema.zirRetImplicit(block, inst), | |
| 1004 | 1004 | .ret_node => break sema.zirRetNode(block, inst), |
| 1005 | 1005 | .ret_load => break sema.zirRetLoad(block, inst), |
| 1006 | 1006 | .ret_err_value => break sema.zirRetErrValue(block, inst), |
| ... | ... | @@ -5745,7 +5745,7 @@ fn lookupInNamespace( |
| 5745 | 5745 | return null; |
| 5746 | 5746 | } |
| 5747 | 5747 | |
| 5748 | fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?Module.SrcLoc { | |
| 5748 | fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl { | |
| 5749 | 5749 | const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null; |
| 5750 | 5750 | if (func_val.isUndef()) return null; |
| 5751 | 5751 | const owner_decl_index = switch (func_val.tag()) { |
| ... | ... | @@ -5754,8 +5754,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?Module.SrcLoc { |
| 5754 | 5754 | .decl_ref => sema.mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl, |
| 5755 | 5755 | else => return null, |
| 5756 | 5756 | }; |
| 5757 | const owner_decl = sema.mod.declPtr(owner_decl_index); | |
| 5758 | return owner_decl.srcLoc(); | |
| 5757 | return sema.mod.declPtr(owner_decl_index); | |
| 5759 | 5758 | } |
| 5760 | 5759 | |
| 5761 | 5760 | pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref { |
| ... | ... | @@ -5933,7 +5932,7 @@ fn zirCall( |
| 5933 | 5932 | break :check_args; |
| 5934 | 5933 | } |
| 5935 | 5934 | |
| 5936 | const decl_src = try sema.funcDeclSrc(func); | |
| 5935 | const maybe_decl = try sema.funcDeclSrc(func); | |
| 5937 | 5936 | const member_str = if (bound_arg_src != null) "member function " else ""; |
| 5938 | 5937 | const variadic_str = if (func_ty_info.is_var_args) "at least " else ""; |
| 5939 | 5938 | const msg = msg: { |
| ... | ... | @@ -5950,7 +5949,7 @@ fn zirCall( |
| 5950 | 5949 | ); |
| 5951 | 5950 | errdefer msg.destroy(sema.gpa); |
| 5952 | 5951 | |
| 5953 | if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{}); | |
| 5952 | if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{}); | |
| 5954 | 5953 | break :msg msg; |
| 5955 | 5954 | }; |
| 5956 | 5955 | return sema.failWithOwnedErrorMsg(msg); |
| ... | ... | @@ -6144,7 +6143,7 @@ fn analyzeCall( |
| 6144 | 6143 | const func_ty_info = func_ty.fnInfo(); |
| 6145 | 6144 | const cc = func_ty_info.cc; |
| 6146 | 6145 | if (cc == .Naked) { |
| 6147 | const decl_src = try sema.funcDeclSrc(func); | |
| 6146 | const maybe_decl = try sema.funcDeclSrc(func); | |
| 6148 | 6147 | const msg = msg: { |
| 6149 | 6148 | const msg = try sema.errMsg( |
| 6150 | 6149 | block, |
| ... | ... | @@ -6154,7 +6153,7 @@ fn analyzeCall( |
| 6154 | 6153 | ); |
| 6155 | 6154 | errdefer msg.destroy(sema.gpa); |
| 6156 | 6155 | |
| 6157 | if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{}); | |
| 6156 | if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{}); | |
| 6158 | 6157 | break :msg msg; |
| 6159 | 6158 | }; |
| 6160 | 6159 | return sema.failWithOwnedErrorMsg(msg); |
| ... | ... | @@ -6388,6 +6387,7 @@ fn analyzeCall( |
| 6388 | 6387 | &should_memoize, |
| 6389 | 6388 | memoized_call_key, |
| 6390 | 6389 | func_ty_info.param_types, |
| 6390 | func, | |
| 6391 | 6391 | ) catch |err| switch (err) { |
| 6392 | 6392 | error.NeededSourceLocation => { |
| 6393 | 6393 | _ = sema.inst_map.remove(inst); |
| ... | ... | @@ -6404,6 +6404,7 @@ fn analyzeCall( |
| 6404 | 6404 | &should_memoize, |
| 6405 | 6405 | memoized_call_key, |
| 6406 | 6406 | func_ty_info.param_types, |
| 6407 | func, | |
| 6407 | 6408 | ); |
| 6408 | 6409 | return error.AnalysisFail; |
| 6409 | 6410 | }, |
| ... | ... | @@ -6546,12 +6547,17 @@ fn analyzeCall( |
| 6546 | 6547 | const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len); |
| 6547 | 6548 | for (uncasted_args) |uncasted_arg, i| { |
| 6548 | 6549 | if (i < fn_params_len) { |
| 6550 | const opts: CoerceOpts = .{ .param_src = .{ | |
| 6551 | .func_inst = func, | |
| 6552 | .param_i = @intCast(u32, i), | |
| 6553 | } }; | |
| 6549 | 6554 | const param_ty = func_ty.fnParamType(i); |
| 6550 | 6555 | args[i] = sema.analyzeCallArg( |
| 6551 | 6556 | block, |
| 6552 | 6557 | .unneeded, |
| 6553 | 6558 | param_ty, |
| 6554 | 6559 | uncasted_arg, |
| 6560 | opts, | |
| 6555 | 6561 | ) catch |err| switch (err) { |
| 6556 | 6562 | error.NeededSourceLocation => { |
| 6557 | 6563 | const decl = sema.mod.declPtr(block.src_decl); |
| ... | ... | @@ -6560,6 +6566,7 @@ fn analyzeCall( |
| 6560 | 6566 | Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src), |
| 6561 | 6567 | param_ty, |
| 6562 | 6568 | uncasted_arg, |
| 6569 | opts, | |
| 6563 | 6570 | ); |
| 6564 | 6571 | return error.AnalysisFail; |
| 6565 | 6572 | }, |
| ... | ... | @@ -6641,6 +6648,7 @@ fn analyzeInlineCallArg( |
| 6641 | 6648 | should_memoize: *bool, |
| 6642 | 6649 | memoized_call_key: Module.MemoizedCall.Key, |
| 6643 | 6650 | raw_param_types: []const Type, |
| 6651 | func_inst: Air.Inst.Ref, | |
| 6644 | 6652 | ) !void { |
| 6645 | 6653 | const zir_tags = sema.code.instructions.items(.tag); |
| 6646 | 6654 | switch (zir_tags[inst]) { |
| ... | ... | @@ -6665,7 +6673,13 @@ fn analyzeInlineCallArg( |
| 6665 | 6673 | return err; |
| 6666 | 6674 | }; |
| 6667 | 6675 | } |
| 6668 | const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src); | |
| 6676 | const casted_arg = sema.coerceExtra(arg_block, param_ty, uncasted_arg, arg_src, .{ .param_src = .{ | |
| 6677 | .func_inst = func_inst, | |
| 6678 | .param_i = @intCast(u32, arg_i.*), | |
| 6679 | } }) catch |err| switch (err) { | |
| 6680 | error.NotCoercible => unreachable, | |
| 6681 | else => |e| return e, | |
| 6682 | }; | |
| 6669 | 6683 | |
| 6670 | 6684 | if (is_comptime_call) { |
| 6671 | 6685 | try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); |
| ... | ... | @@ -6755,9 +6769,13 @@ fn analyzeCallArg( |
| 6755 | 6769 | arg_src: LazySrcLoc, |
| 6756 | 6770 | param_ty: Type, |
| 6757 | 6771 | uncasted_arg: Air.Inst.Ref, |
| 6772 | opts: CoerceOpts, | |
| 6758 | 6773 | ) !Air.Inst.Ref { |
| 6759 | 6774 | try sema.resolveTypeFully(param_ty); |
| 6760 | return sema.coerce(block, param_ty, uncasted_arg, arg_src); | |
| 6775 | return sema.coerceExtra(block, param_ty, uncasted_arg, arg_src, opts) catch |err| switch (err) { | |
| 6776 | error.NotCoercible => unreachable, | |
| 6777 | else => |e| return e, | |
| 6778 | }; | |
| 6761 | 6779 | } |
| 6762 | 6780 | |
| 6763 | 6781 | fn analyzeGenericCallArg( |
| ... | ... | @@ -16398,7 +16416,7 @@ fn zirRetErrValue( |
| 16398 | 16416 | return sema.analyzeRet(block, result_inst, src); |
| 16399 | 16417 | } |
| 16400 | 16418 | |
| 16401 | fn zirRetTok( | |
| 16419 | fn zirRetImplicit( | |
| 16402 | 16420 | sema: *Sema, |
| 16403 | 16421 | block: *Block, |
| 16404 | 16422 | inst: Zir.Inst.Index, |
| ... | ... | @@ -16408,9 +16426,33 @@ fn zirRetTok( |
| 16408 | 16426 | |
| 16409 | 16427 | const inst_data = sema.code.instructions.items(.data)[inst].un_tok; |
| 16410 | 16428 | const operand = try sema.resolveInst(inst_data.operand); |
| 16411 | const src = inst_data.src(); | |
| 16412 | 16429 | |
| 16413 | return sema.analyzeRet(block, operand, src); | |
| 16430 | const r_brace_src = inst_data.src(); | |
| 16431 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | |
| 16432 | const base_tag = sema.fn_ret_ty.baseZigTypeTag(); | |
| 16433 | if (base_tag == .NoReturn) { | |
| 16434 | const msg = msg: { | |
| 16435 | const msg = try sema.errMsg(block, ret_ty_src, "function declared '{}' implicitly returns", .{ | |
| 16436 | sema.fn_ret_ty.fmt(sema.mod), | |
| 16437 | }); | |
| 16438 | errdefer msg.destroy(sema.gpa); | |
| 16439 | try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); | |
| 16440 | break :msg msg; | |
| 16441 | }; | |
| 16442 | return sema.failWithOwnedErrorMsg(msg); | |
| 16443 | } else if (base_tag != .Void) { | |
| 16444 | const msg = msg: { | |
| 16445 | const msg = try sema.errMsg(block, ret_ty_src, "function with non-void return type '{}' implicitly returns", .{ | |
| 16446 | sema.fn_ret_ty.fmt(sema.mod), | |
| 16447 | }); | |
| 16448 | errdefer msg.destroy(sema.gpa); | |
| 16449 | try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{}); | |
| 16450 | break :msg msg; | |
| 16451 | }; | |
| 16452 | return sema.failWithOwnedErrorMsg(msg); | |
| 16453 | } | |
| 16454 | ||
| 16455 | return sema.analyzeRet(block, operand, .unneeded); | |
| 16414 | 16456 | } |
| 16415 | 16457 | |
| 16416 | 16458 | fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { |
| ... | ... | @@ -16677,7 +16719,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 16677 | 16719 | const bitoffset_src: LazySrcLoc = .{ .node_offset_ptr_bitoffset = extra.data.src_node }; |
| 16678 | 16720 | const hostsize_src: LazySrcLoc = .{ .node_offset_ptr_hostsize = extra.data.src_node }; |
| 16679 | 16721 | |
| 16680 | const unresolved_elem_ty = blk: { | |
| 16722 | const elem_ty = blk: { | |
| 16681 | 16723 | const air_inst = try sema.resolveInst(extra.data.elem_type); |
| 16682 | 16724 | const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| { |
| 16683 | 16725 | if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer()) { |
| ... | ... | @@ -16706,7 +16748,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 16706 | 16748 | // Check if this happens to be the lazy alignment of our element type, in |
| 16707 | 16749 | // which case we can make this 0 without resolving it. |
| 16708 | 16750 | if (val.castTag(.lazy_align)) |payload| { |
| 16709 | if (payload.data.eql(unresolved_elem_ty, sema.mod)) { | |
| 16751 | if (payload.data.eql(elem_ty, sema.mod)) { | |
| 16710 | 16752 | break :blk 0; |
| 16711 | 16753 | } |
| 16712 | 16754 | } |
| ... | ... | @@ -16739,14 +16781,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 16739 | 16781 | return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{}); |
| 16740 | 16782 | } |
| 16741 | 16783 | |
| 16742 | const elem_ty = if (abi_align == 0) | |
| 16743 | unresolved_elem_ty | |
| 16744 | else t: { | |
| 16745 | const elem_ty = try sema.resolveTypeFields(unresolved_elem_ty); | |
| 16746 | try sema.resolveTypeLayout(elem_ty); | |
| 16747 | break :t elem_ty; | |
| 16748 | }; | |
| 16749 | ||
| 16750 | 16784 | if (elem_ty.zigTypeTag() == .NoReturn) { |
| 16751 | 16785 | return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{}); |
| 16752 | 16786 | } else if (elem_ty.zigTypeTag() == .Fn) { |
| ... | ... | @@ -20173,7 +20207,7 @@ fn analyzeShuffle( |
| 20173 | 20207 | var buf: Value.ElemValueBuffer = undefined; |
| 20174 | 20208 | const elem = mask.elemValueBuffer(sema.mod, i, &buf); |
| 20175 | 20209 | if (elem.isUndef()) continue; |
| 20176 | const int = elem.toSignedInt(); | |
| 20210 | const int = elem.toSignedInt(sema.mod.getTarget()); | |
| 20177 | 20211 | var unsigned: u32 = undefined; |
| 20178 | 20212 | var chosen: u32 = undefined; |
| 20179 | 20213 | if (int >= 0) { |
| ... | ... | @@ -20215,7 +20249,7 @@ fn analyzeShuffle( |
| 20215 | 20249 | values[i] = Value.undef; |
| 20216 | 20250 | continue; |
| 20217 | 20251 | } |
| 20218 | const int = mask_elem_val.toSignedInt(); | |
| 20252 | const int = mask_elem_val.toSignedInt(sema.mod.getTarget()); | |
| 20219 | 20253 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int); |
| 20220 | 20254 | if (int >= 0) { |
| 20221 | 20255 | values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned); |
| ... | ... | @@ -23957,6 +23991,25 @@ const CoerceOpts = struct { |
| 23957 | 23991 | is_ret: bool = false, |
| 23958 | 23992 | /// Should coercion to comptime_int ermit an error message. |
| 23959 | 23993 | no_cast_to_comptime_int: bool = false, |
| 23994 | ||
| 23995 | param_src: struct { | |
| 23996 | func_inst: Air.Inst.Ref = .none, | |
| 23997 | param_i: u32 = undefined, | |
| 23998 | ||
| 23999 | fn get(info: @This(), sema: *Sema) !?Module.SrcLoc { | |
| 24000 | if (info.func_inst == .none) return null; | |
| 24001 | const fn_decl = (try sema.funcDeclSrc(info.func_inst)) orelse return null; | |
| 24002 | const param_src = Module.paramSrc(0, sema.gpa, fn_decl, info.param_i); | |
| 24003 | if (param_src == .node_offset_param) { | |
| 24004 | return Module.SrcLoc{ | |
| 24005 | .file_scope = fn_decl.getFileScope(), | |
| 24006 | .parent_decl_node = fn_decl.src_node, | |
| 24007 | .lazy = LazySrcLoc.nodeOffset(param_src.node_offset_param), | |
| 24008 | }; | |
| 24009 | } | |
| 24010 | return param_src.toSrcLoc(fn_decl); | |
| 24011 | } | |
| 24012 | } = .{}, | |
| 23960 | 24013 | }; |
| 23961 | 24014 | |
| 23962 | 24015 | fn coerceExtra( |
| ... | ... | @@ -24610,6 +24663,10 @@ fn coerceExtra( |
| 24610 | 24663 | } |
| 24611 | 24664 | } |
| 24612 | 24665 | |
| 24666 | if (try opts.param_src.get(sema)) |param_src| { | |
| 24667 | try sema.mod.errNoteNonLazy(param_src, msg, "parameter type declared here", .{}); | |
| 24668 | } | |
| 24669 | ||
| 24613 | 24670 | // TODO maybe add "cannot store an error in type '{}'" note |
| 24614 | 24671 | |
| 24615 | 24672 | break :msg msg; |
| ... | ... | @@ -28212,6 +28269,7 @@ fn cmpNumeric( |
| 28212 | 28269 | |
| 28213 | 28270 | var lhs_bits: usize = undefined; |
| 28214 | 28271 | if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| { |
| 28272 | try sema.resolveLazyValue(lhs_val); | |
| 28215 | 28273 | if (lhs_val.isUndef()) |
| 28216 | 28274 | return sema.addConstUndef(Type.bool); |
| 28217 | 28275 | if (lhs_val.isNan()) switch (op) { |
| ... | ... | @@ -28265,6 +28323,7 @@ fn cmpNumeric( |
| 28265 | 28323 | |
| 28266 | 28324 | var rhs_bits: usize = undefined; |
| 28267 | 28325 | if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| { |
| 28326 | try sema.resolveLazyValue(rhs_val); | |
| 28268 | 28327 | if (rhs_val.isUndef()) |
| 28269 | 28328 | return sema.addConstUndef(Type.bool); |
| 28270 | 28329 | if (rhs_val.isNan()) switch (op) { |
| ... | ... | @@ -29132,6 +29191,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 29132 | 29191 | |
| 29133 | 29192 | struct_obj.status = .have_layout; |
| 29134 | 29193 | _ = try sema.resolveTypeRequiresComptime(resolved_ty); |
| 29194 | ||
| 29195 | if (struct_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) { | |
| 29196 | const msg = try Module.ErrorMsg.create( | |
| 29197 | sema.gpa, | |
| 29198 | struct_obj.srcLoc(sema.mod), | |
| 29199 | "struct layout depends on it having runtime bits", | |
| 29200 | .{}, | |
| 29201 | ); | |
| 29202 | return sema.failWithOwnedErrorMsg(msg); | |
| 29203 | } | |
| 29135 | 29204 | } |
| 29136 | 29205 | // otherwise it's a tuple; no need to resolve anything |
| 29137 | 29206 | } |
| ... | ... | @@ -29296,6 +29365,16 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 29296 | 29365 | } |
| 29297 | 29366 | union_obj.status = .have_layout; |
| 29298 | 29367 | _ = try sema.resolveTypeRequiresComptime(resolved_ty); |
| 29368 | ||
| 29369 | if (union_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) { | |
| 29370 | const msg = try Module.ErrorMsg.create( | |
| 29371 | sema.gpa, | |
| 29372 | union_obj.srcLoc(sema.mod), | |
| 29373 | "union layout depends on it having runtime bits", | |
| 29374 | .{}, | |
| 29375 | ); | |
| 29376 | return sema.failWithOwnedErrorMsg(msg); | |
| 29377 | } | |
| 29299 | 29378 | } |
| 29300 | 29379 | |
| 29301 | 29380 | // 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 | 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/arch/aarch64/CodeGen.zig+1-1| ... | ... | @@ -6083,7 +6083,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 6083 | 6083 | if (info.bits <= 64) { |
| 6084 | 6084 | const unsigned = switch (info.signedness) { |
| 6085 | 6085 | .signed => blk: { |
| 6086 | const signed = typed_value.val.toSignedInt(); | |
| 6086 | const signed = typed_value.val.toSignedInt(target); | |
| 6087 | 6087 | break :blk @bitCast(u64, signed); |
| 6088 | 6088 | }, |
| 6089 | 6089 | .unsigned => typed_value.val.toUnsignedInt(target), |
src/arch/arm/CodeGen.zig+1-1| ... | ... | @@ -6121,7 +6121,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 6121 | 6121 | if (info.bits <= ptr_bits) { |
| 6122 | 6122 | const unsigned = switch (info.signedness) { |
| 6123 | 6123 | .signed => blk: { |
| 6124 | const signed = @intCast(i32, typed_value.val.toSignedInt()); | |
| 6124 | const signed = @intCast(i32, typed_value.val.toSignedInt(target)); | |
| 6125 | 6125 | break :blk @bitCast(u32, signed); |
| 6126 | 6126 | }, |
| 6127 | 6127 | .unsigned => @intCast(u32, typed_value.val.toUnsignedInt(target)), |
src/arch/sparc64/CodeGen.zig+1-1| ... | ... | @@ -3786,7 +3786,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3786 | 3786 | if (info.bits <= 64) { |
| 3787 | 3787 | const unsigned = switch (info.signedness) { |
| 3788 | 3788 | .signed => blk: { |
| 3789 | const signed = typed_value.val.toSignedInt(); | |
| 3789 | const signed = typed_value.val.toSignedInt(target); | |
| 3790 | 3790 | break :blk @bitCast(u64, signed); |
| 3791 | 3791 | }, |
| 3792 | 3792 | .unsigned => typed_value.val.toUnsignedInt(target), |
src/arch/wasm/CodeGen.zig+5-5| ... | ... | @@ -2604,11 +2604,11 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 2604 | 2604 | switch (int_info.signedness) { |
| 2605 | 2605 | .signed => switch (int_info.bits) { |
| 2606 | 2606 | 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement( |
| 2607 | val.toSignedInt(), | |
| 2607 | val.toSignedInt(target), | |
| 2608 | 2608 | @intCast(u6, int_info.bits), |
| 2609 | 2609 | )) }, |
| 2610 | 2610 | 33...64 => return WValue{ .imm64 = toTwosComplement( |
| 2611 | val.toSignedInt(), | |
| 2611 | val.toSignedInt(target), | |
| 2612 | 2612 | @intCast(u7, int_info.bits), |
| 2613 | 2613 | ) }, |
| 2614 | 2614 | else => unreachable, |
| ... | ... | @@ -2758,15 +2758,15 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 { |
| 2758 | 2758 | } |
| 2759 | 2759 | }, |
| 2760 | 2760 | .Int => switch (ty.intInfo(func.target).signedness) { |
| 2761 | .signed => return @truncate(i32, val.toSignedInt()), | |
| 2761 | .signed => return @truncate(i32, val.toSignedInt(target)), | |
| 2762 | 2762 | .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(target))), |
| 2763 | 2763 | }, |
| 2764 | 2764 | .ErrorSet => { |
| 2765 | 2765 | const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function |
| 2766 | 2766 | return @bitCast(i32, kv.value); |
| 2767 | 2767 | }, |
| 2768 | .Bool => return @intCast(i32, val.toSignedInt()), | |
| 2769 | .Pointer => return @intCast(i32, val.toSignedInt()), | |
| 2768 | .Bool => return @intCast(i32, val.toSignedInt(target)), | |
| 2769 | .Pointer => return @intCast(i32, val.toSignedInt(target)), | |
| 2770 | 2770 | else => unreachable, // Programmer called this function for an illegal type |
| 2771 | 2771 | } |
| 2772 | 2772 | } |
src/arch/x86_64/CodeGen.zig+1-1| ... | ... | @@ -7007,7 +7007,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 7007 | 7007 | .Int => { |
| 7008 | 7008 | const info = typed_value.ty.intInfo(self.target.*); |
| 7009 | 7009 | if (info.bits <= ptr_bits and info.signedness == .signed) { |
| 7010 | return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) }; | |
| 7010 | return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt(target)) }; | |
| 7011 | 7011 | } |
| 7012 | 7012 | if (!(info.bits > ptr_bits or info.signedness == .signed)) { |
| 7013 | 7013 | return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) }; |
src/codegen.zig+7-7| ... | ... | @@ -459,7 +459,7 @@ pub fn generateSymbol( |
| 459 | 459 | if (info.bits <= 8) { |
| 460 | 460 | const x: u8 = switch (info.signedness) { |
| 461 | 461 | .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)), |
| 462 | .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt())), | |
| 462 | .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt(target))), | |
| 463 | 463 | }; |
| 464 | 464 | try code.append(x); |
| 465 | 465 | return Result{ .appended = {} }; |
| ... | ... | @@ -488,13 +488,13 @@ pub fn generateSymbol( |
| 488 | 488 | }, |
| 489 | 489 | .signed => { |
| 490 | 490 | if (info.bits <= 16) { |
| 491 | const x = @intCast(i16, typed_value.val.toSignedInt()); | |
| 491 | const x = @intCast(i16, typed_value.val.toSignedInt(target)); | |
| 492 | 492 | mem.writeInt(i16, try code.addManyAsArray(2), x, endian); |
| 493 | 493 | } else if (info.bits <= 32) { |
| 494 | const x = @intCast(i32, typed_value.val.toSignedInt()); | |
| 494 | const x = @intCast(i32, typed_value.val.toSignedInt(target)); | |
| 495 | 495 | mem.writeInt(i32, try code.addManyAsArray(4), x, endian); |
| 496 | 496 | } else { |
| 497 | const x = typed_value.val.toSignedInt(); | |
| 497 | const x = typed_value.val.toSignedInt(target); | |
| 498 | 498 | mem.writeInt(i64, try code.addManyAsArray(8), x, endian); |
| 499 | 499 | } |
| 500 | 500 | }, |
| ... | ... | @@ -536,13 +536,13 @@ pub fn generateSymbol( |
| 536 | 536 | }, |
| 537 | 537 | .signed => { |
| 538 | 538 | if (info.bits <= 16) { |
| 539 | const x = @intCast(i16, int_val.toSignedInt()); | |
| 539 | const x = @intCast(i16, int_val.toSignedInt(target)); | |
| 540 | 540 | mem.writeInt(i16, try code.addManyAsArray(2), x, endian); |
| 541 | 541 | } else if (info.bits <= 32) { |
| 542 | const x = @intCast(i32, int_val.toSignedInt()); | |
| 542 | const x = @intCast(i32, int_val.toSignedInt(target)); | |
| 543 | 543 | mem.writeInt(i32, try code.addManyAsArray(4), x, endian); |
| 544 | 544 | } else { |
| 545 | const x = int_val.toSignedInt(); | |
| 545 | const x = int_val.toSignedInt(target); | |
| 546 | 546 | mem.writeInt(i64, try code.addManyAsArray(8), x, endian); |
| 547 | 547 | } |
| 548 | 548 | }, |
src/codegen/llvm.zig+1-1| ... | ... | @@ -8934,7 +8934,7 @@ pub const FuncGen = struct { |
| 8934 | 8934 | if (elem.isUndef()) { |
| 8935 | 8935 | val.* = llvm_i32.getUndef(); |
| 8936 | 8936 | } else { |
| 8937 | const int = elem.toSignedInt(); | |
| 8937 | const int = elem.toSignedInt(self.dg.module.getTarget()); | |
| 8938 | 8938 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len); |
| 8939 | 8939 | val.* = llvm_i32.constInt(unsigned, .False); |
| 8940 | 8940 | } |
src/codegen/spirv.zig+1-1| ... | ... | @@ -345,7 +345,7 @@ pub const DeclGen = struct { |
| 345 | 345 | |
| 346 | 346 | // Note, value is required to be sign-extended, so we don't need to mask off the upper bits. |
| 347 | 347 | // See https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Literal |
| 348 | var int_bits = if (ty.isSignedInt()) @bitCast(u64, val.toSignedInt()) else val.toUnsignedInt(target); | |
| 348 | var int_bits = if (ty.isSignedInt()) @bitCast(u64, val.toSignedInt(target)) else val.toUnsignedInt(target); | |
| 349 | 349 | |
| 350 | 350 | const value: spec.LiteralContextDependentNumber = switch (backing_bits) { |
| 351 | 351 | 1...32 => .{ .uint32 = @truncate(u32, int_bits) }, |
src/link/Dwarf.zig+1-1| ... | ... | @@ -409,7 +409,7 @@ pub const DeclState = struct { |
| 409 | 409 | // See https://github.com/ziglang/zig/issues/645 |
| 410 | 410 | var int_buffer: Value.Payload.U64 = undefined; |
| 411 | 411 | const field_int_val = value.enumToInt(ty, &int_buffer); |
| 412 | break :value @bitCast(u64, field_int_val.toSignedInt()); | |
| 412 | break :value @bitCast(u64, field_int_val.toSignedInt(target)); | |
| 413 | 413 | } else @intCast(u64, field_i); |
| 414 | 414 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian); |
| 415 | 415 | } |
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+46-8| ... | ... | @@ -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, |
| ... | ... | @@ -2459,6 +2470,7 @@ pub const Type = extern union { |
| 2459 | 2470 | if (struct_obj.status == .field_types_wip) { |
| 2460 | 2471 | // In this case, we guess that hasRuntimeBits() for this type is true, |
| 2461 | 2472 | // and then later if our guess was incorrect, we emit a compile error. |
| 2473 | struct_obj.assumed_runtime_bits = true; | |
| 2462 | 2474 | return true; |
| 2463 | 2475 | } |
| 2464 | 2476 | switch (strat) { |
| ... | ... | @@ -2491,6 +2503,12 @@ pub const Type = extern union { |
| 2491 | 2503 | |
| 2492 | 2504 | .@"union" => { |
| 2493 | 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 | 2512 | switch (strat) { |
| 2495 | 2513 | .sema => |sema| _ = try sema.resolveTypeFields(ty), |
| 2496 | 2514 | .eager => assert(union_obj.haveFieldTypes()), |
| ... | ... | @@ -3027,8 +3045,9 @@ pub const Type = extern union { |
| 3027 | 3045 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 3028 | 3046 | if (opt_sema) |sema| { |
| 3029 | 3047 | if (struct_obj.status == .field_types_wip) { |
| 3030 | // We'll guess "pointer-aligned" and if we guess wrong, emit | |
| 3031 | // a compile error later. | |
| 3048 | // We'll guess "pointer-aligned", if the struct has an | |
| 3049 | // underaligned pointer field then some allocations | |
| 3050 | // might require explicit alignment. | |
| 3032 | 3051 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) }; |
| 3033 | 3052 | } |
| 3034 | 3053 | _ = try sema.resolveTypeFields(ty); |
| ... | ... | @@ -3153,8 +3172,9 @@ pub const Type = extern union { |
| 3153 | 3172 | }; |
| 3154 | 3173 | if (opt_sema) |sema| { |
| 3155 | 3174 | if (union_obj.status == .field_types_wip) { |
| 3156 | // We'll guess "pointer-aligned" and if we guess wrong, emit | |
| 3157 | // a compile error later. | |
| 3175 | // We'll guess "pointer-aligned", if the union has an | |
| 3176 | // underaligned pointer field then some allocations | |
| 3177 | // might require explicit alignment. | |
| 3158 | 3178 | return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) }; |
| 3159 | 3179 | } |
| 3160 | 3180 | _ = try sema.resolveTypeFields(ty); |
| ... | ... | @@ -5233,7 +5253,12 @@ pub const Type = extern union { |
| 5233 | 5253 | .@"struct" => { |
| 5234 | 5254 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 5235 | 5255 | switch (struct_obj.requires_comptime) { |
| 5236 | .wip, .unknown => unreachable, // This function asserts types already resolved. | |
| 5256 | .wip, .unknown => { | |
| 5257 | // Return false to avoid incorrect dependency loops. | |
| 5258 | // This will be handled correctly once merged with | |
| 5259 | // `Sema.typeRequiresComptime`. | |
| 5260 | return false; | |
| 5261 | }, | |
| 5237 | 5262 | .no => return false, |
| 5238 | 5263 | .yes => return true, |
| 5239 | 5264 | } |
| ... | ... | @@ -5242,7 +5267,12 @@ pub const Type = extern union { |
| 5242 | 5267 | .@"union", .union_safety_tagged, .union_tagged => { |
| 5243 | 5268 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 5244 | 5269 | switch (union_obj.requires_comptime) { |
| 5245 | .wip, .unknown => unreachable, // This function asserts types already resolved. | |
| 5270 | .wip, .unknown => { | |
| 5271 | // Return false to avoid incorrect dependency loops. | |
| 5272 | // This will be handled correctly once merged with | |
| 5273 | // `Sema.typeRequiresComptime`. | |
| 5274 | return false; | |
| 5275 | }, | |
| 5246 | 5276 | .no => return false, |
| 5247 | 5277 | .yes => return true, |
| 5248 | 5278 | } |
| ... | ... | @@ -6454,8 +6484,16 @@ pub const Type = extern union { |
| 6454 | 6484 | // type, we change it to 0 here. If this causes an assertion trip because the |
| 6455 | 6485 | // pointee type needs to be resolved more, that needs to be done before calling |
| 6456 | 6486 | // this ptr() function. |
| 6457 | if (d.@"align" != 0 and d.@"align" == d.pointee_type.abiAlignment(target)) { | |
| 6458 | d.@"align" = 0; | |
| 6487 | if (d.@"align" != 0) canonicalize: { | |
| 6488 | if (d.pointee_type.castTag(.@"struct")) |struct_ty| { | |
| 6489 | if (!struct_ty.data.haveLayout()) break :canonicalize; | |
| 6490 | } | |
| 6491 | if (d.pointee_type.cast(Payload.Union)) |union_ty| { | |
| 6492 | if (!union_ty.data.haveLayout()) break :canonicalize; | |
| 6493 | } | |
| 6494 | if (d.@"align" == d.pointee_type.abiAlignment(target)) { | |
| 6495 | d.@"align" = 0; | |
| 6496 | } | |
| 6459 | 6497 | } |
| 6460 | 6498 | |
| 6461 | 6499 | // 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 | 187 | bound_fn, |
| 188 | 188 | /// The ABI alignment of the payload type. |
| 189 | 189 | lazy_align, |
| 190 | /// The ABI alignment of the payload type. | |
| 190 | /// The ABI size of the payload type. | |
| 191 | 191 | lazy_size, |
| 192 | 192 | |
| 193 | 193 | pub const last_no_payload_tag = Tag.empty_array; |
| ... | ... | @@ -1201,8 +1201,8 @@ pub const Value = extern union { |
| 1201 | 1201 | } |
| 1202 | 1202 | |
| 1203 | 1203 | /// Asserts the value is an integer and it fits in a i64 |
| 1204 | pub fn toSignedInt(self: Value) i64 { | |
| 1205 | switch (self.tag()) { | |
| 1204 | pub fn toSignedInt(val: Value, target: Target) i64 { | |
| 1205 | switch (val.tag()) { | |
| 1206 | 1206 | .zero, |
| 1207 | 1207 | .bool_false, |
| 1208 | 1208 | .the_only_possible_value, // i0, u0 |
| ... | ... | @@ -1212,10 +1212,19 @@ pub const Value = extern union { |
| 1212 | 1212 | .bool_true, |
| 1213 | 1213 | => return 1, |
| 1214 | 1214 | |
| 1215 | .int_u64 => return @intCast(i64, self.castTag(.int_u64).?.data), | |
| 1216 | .int_i64 => return self.castTag(.int_i64).?.data, | |
| 1217 | .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable, | |
| 1218 | .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable, | |
| 1215 | .int_u64 => return @intCast(i64, val.castTag(.int_u64).?.data), | |
| 1216 | .int_i64 => return val.castTag(.int_i64).?.data, | |
| 1217 | .int_big_positive => return val.castTag(.int_big_positive).?.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 | }, | |
| 1219 | 1228 | |
| 1220 | 1229 | .undef => unreachable, |
| 1221 | 1230 | else => unreachable, |
test/behavior.zig+1| ... | ... | @@ -90,6 +90,7 @@ test { |
| 90 | 90 | _ = @import("behavior/bugs/12430.zig"); |
| 91 | 91 | _ = @import("behavior/bugs/12486.zig"); |
| 92 | 92 | _ = @import("behavior/bugs/12488.zig"); |
| 93 | _ = @import("behavior/bugs/12498.zig"); | |
| 93 | 94 | _ = @import("behavior/bugs/12551.zig"); |
| 94 | 95 | _ = @import("behavior/bugs/12644.zig"); |
| 95 | 96 | _ = @import("behavior/bugs/12680.zig"); |
test/behavior/bugs/12498.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | ||
| 4 | const S = struct { a: usize }; | |
| 5 | test "lazy abi size used in comparison" { | |
| 6 | var rhs: i32 = 100; | |
| 7 | try expect(@sizeOf(S) < rhs); | |
| 8 | } |
test/behavior/struct.zig+12| ... | ... | @@ -1418,3 +1418,15 @@ test "address of zero-bit field is equal to address of only field" { |
| 1418 | 1418 | try std.testing.expectEqual(&a, a_ptr); |
| 1419 | 1419 | } |
| 1420 | 1420 | } |
| 1421 | ||
| 1422 | test "struct field has a pointer to an aligned version of itself" { | |
| 1423 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 1424 | ||
| 1425 | const E = struct { | |
| 1426 | next: *align(1) @This(), | |
| 1427 | }; | |
| 1428 | var e: E = undefined; | |
| 1429 | e = .{ .next = &e }; | |
| 1430 | ||
| 1431 | try expect(&e == e.next); | |
| 1432 | } |
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/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 | 8 | // target=native |
| 9 | 9 | // |
| 10 | 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 | 21 | // :8:16: error: expected type '*const u3', found '*align(0:3:1) const u3' |
| 22 | 22 | // :8:16: note: pointer host size '1' cannot cast into pointer host size '0' |
| 23 | 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 | 22 | // target=native |
| 23 | 23 | // |
| 24 | 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 @@ |
| 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/disallow_coercion_from_non-null-terminated_pointer_to_null-terminated_pointer.zig+1| ... | ... | @@ -11,3 +11,4 @@ pub export fn entry() void { |
| 11 | 11 | // |
| 12 | 12 | // :5:14: error: expected type '[*:0]const u8', found '[*]const u8' |
| 13 | 13 | // :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 | 24 | // :4:35: note: cannot implicitly cast double pointer '*const *const usize' to anyopaque pointer '*const anyopaque' |
| 25 | 25 | // :9:10: error: expected type '?*anyopaque', found '*[*:0]u8' |
| 26 | 26 | // :9:10: note: cannot implicitly cast double pointer '*[*:0]u8' to anyopaque pointer '?*anyopaque' |
| 27 | // :11:12: note: parameter type declared here | |
| 27 | 28 | // :15:35: error: expected type '*const anyopaque', found '*?*usize' |
| 28 | 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 | 18 | // |
| 19 | 19 | // :8:9: error: expected type '*u32', found '*align(1) u32' |
| 20 | 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 @@ |
| 1 | comptime { | |
| 2 | var a = "foo"; | |
| 3 | if (a == "foo") unreachable; | |
| 4 | } | |
| 5 | comptime { | |
| 6 | var a = "foo"; | |
| 7 | if (a == ("foo")) unreachable; // intentionally allow | |
| 8 | } | |
| 9 | comptime { | |
| 10 | var a = "foo"; | |
| 11 | switch (a) { | |
| 12 | "foo" => unreachable, | |
| 13 | else => {}, | |
| 14 | } | |
| 15 | } | |
| 16 | comptime { | |
| 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 @@ |
| 1 | comptime { | |
| 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 @@ |
| 1 | fn f2(u64) u64 { | |
| 2 | return x; | |
| 3 | } | |
| 4 | fn f3(*x) u64 { | |
| 5 | return x; | |
| 6 | } | |
| 7 | fn 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 | 16 | // |
| 17 | 17 | // :4:19: error: expected type '*[]const u8', found '*const []const u8' |
| 18 | 18 | // :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 | 12 | // |
| 13 | 13 | // :7:33: error: expected type 'type', found 'tmp.MyStruct' |
| 14 | 14 | // :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 @@ |
| 1 | const Foo = struct { i: i32 }; | |
| 2 | const Bar = struct { j: i32 }; | |
| 3 | ||
| 4 | pub fn helper(_: Foo, _: Bar) void { } | |
| 5 | ||
| 6 | comptime { | |
| 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 | 1 | pub export fn entry() void { |
| 2 | 2 | var a: [:0]const u8 = "foo"; |
| 3 | 3 | switch (a) { |
| 4 | "--version", "version" => unreachable, | |
| 4 | ("--version"), ("version") => unreachable, | |
| 5 | 5 | else => {}, |
| 6 | 6 | } |
| 7 | 7 | } |
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/compile_errors/wrong_pointer_coerced_to_pointer_to_opaque_{}.zig+1| ... | ... | @@ -12,3 +12,4 @@ export fn foo() void { |
| 12 | 12 | // :5:9: error: expected type '*tmp.Derp', found '*anyopaque' |
| 13 | 13 | // :5:9: note: pointer type child 'anyopaque' cannot cast into pointer type child 'tmp.Derp' |
| 14 | 14 | // :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 | 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 |