authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-04 16:04:31+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-09 13:48:34-07:00
logb511231f9552d7c1de1574eda19dc6cf657e906e
tree41cfb8c26ff8aaf654930b7c282829e146d5d3d2
parent8d95b713c54d9dcd13d7a0afa743254ddc224a5e

Merge pull request #13338 from Vexu/stage2-compile-errors

Improve some error messages

13 files changed, 181 insertions(+), 31 deletions(-)

ci/azure/pipelines.yml+1-1
......@@ -16,7 +16,7 @@ jobs:
1616 vmImage: 'windows-2019'
1717 variables:
1818 TARGET: 'x86_64-windows-gnu'
19 ZIG_LLVM_CLANG_LLD_NAME: 'zig+llvm+lld+clang-${{ variables.TARGET }}-0.10.0-dev.4560+828735ac0'
19 ZIG_LLVM_CLANG_LLD_NAME: 'zig+llvm+lld+clang-${{ variables.TARGET }}-0.11.0-dev.25+499dddb4c'
2020 ZIG_LLVM_CLANG_LLD_URL: 'https://ziglang.org/deps/${{ variables.ZIG_LLVM_CLANG_LLD_NAME }}.zip'
2121 steps:
2222 - pwsh: |
lib/std/meta.zig+3-3
......@@ -304,7 +304,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
304304 .Array = .{
305305 .len = array_info.len,
306306 .child = array_info.child,
307 .sentinel = &sentinel_val,
307 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
308308 },
309309 }),
310310 .is_allowzero = info.is_allowzero,
......@@ -322,7 +322,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
322322 .address_space = info.address_space,
323323 .child = info.child,
324324 .is_allowzero = info.is_allowzero,
325 .sentinel = &sentinel_val,
325 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
326326 },
327327 }),
328328 else => {},
......@@ -340,7 +340,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
340340 .address_space = ptr_info.address_space,
341341 .child = ptr_info.child,
342342 .is_allowzero = ptr_info.is_allowzero,
343 .sentinel = &sentinel_val,
343 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
344344 },
345345 }),
346346 },
lib/std/start_windows_tls.zig+1-1
......@@ -42,7 +42,7 @@ export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{
4242 .StartAddressOfRawData = &_tls_start,
4343 .EndAddressOfRawData = &_tls_end,
4444 .AddressOfIndex = &_tls_index,
45 .AddressOfCallBacks = &__xl_a,
45 .AddressOfCallBacks = @ptrCast(*anyopaque, &__xl_a),
4646 .SizeOfZeroFill = 0,
4747 .Characteristics = 0,
4848};
lib/std/zig/Ast.zig+9-1
......@@ -197,7 +197,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
197197 });
198198 },
199199 .expected_labelable => {
200 return stream.print("expected 'while', 'for', 'inline', 'suspend', or '{{', found '{s}'", .{
200 return stream.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{
201201 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
202202 });
203203 },
......@@ -356,6 +356,12 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
356356 .next_field => {
357357 return stream.writeAll("field after declarations here");
358358 },
359 .expected_var_const => {
360 return stream.writeAll("expected 'var' or 'const' before variable declaration");
361 },
362 .wrong_equal_var_decl => {
363 return stream.writeAll("variable initialized with '==' instead of '='");
364 },
359365
360366 .expected_token => {
361367 const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];
......@@ -2579,6 +2585,8 @@ pub const Error = struct {
25792585 mismatched_binary_op_whitespace,
25802586 invalid_ampersand_ampersand,
25812587 c_style_container,
2588 expected_var_const,
2589 wrong_equal_var_decl,
25822590
25832591 zig_style_container,
25842592 previous_field,
lib/std/zig/parse.zig+24-2
......@@ -812,7 +812,18 @@ const Parser = struct {
812812 const align_node = try p.parseByteAlign();
813813 const addrspace_node = try p.parseAddrSpace();
814814 const section_node = try p.parseLinkSection();
815 const init_node: Node.Index = if (p.eatToken(.equal) == null) 0 else try p.expectExpr();
815 const init_node: Node.Index = switch (p.token_tags[p.tok_i]) {
816 .equal_equal => blk: {
817 try p.warn(.wrong_equal_var_decl);
818 p.tok_i += 1;
819 break :blk try p.expectExpr();
820 },
821 .equal => blk: {
822 p.tok_i += 1;
823 break :blk try p.expectExpr();
824 },
825 else => 0,
826 };
816827 if (section_node == 0 and addrspace_node == 0) {
817828 if (align_node == 0) {
818829 return p.addNode(.{
......@@ -1118,7 +1129,18 @@ const Parser = struct {
11181129 if (loop_stmt != 0) return loop_stmt;
11191130
11201131 if (label_token != 0) {
1121 return p.fail(.expected_labelable);
1132 const after_colon = p.tok_i;
1133 const node = try p.parseTypeExpr();
1134 if (node != 0) {
1135 const a = try p.parseByteAlign();
1136 const b = try p.parseAddrSpace();
1137 const c = try p.parseLinkSection();
1138 const d = if (p.eatToken(.equal) == null) 0 else try p.expectExpr();
1139 if (a != 0 or b != 0 or c != 0 or d != 0) {
1140 return p.failMsg(.{ .tag = .expected_var_const, .token = label_token });
1141 }
1142 }
1143 return p.failMsg(.{ .tag = .expected_labelable, .token = after_colon });
11221144 }
11231145
11241146 return null_node;
lib/std/zig/parser_test.zig+34
......@@ -5145,6 +5145,40 @@ test "zig fmt: make single-line if no trailing comma" {
51455145 );
51465146}
51475147
5148test "zig fmt: variable initialized with ==" {
5149 try testError(
5150 \\comptime {
5151 \\ var z: u32 == 12 + 1;
5152 \\}
5153 , &.{.wrong_equal_var_decl});
5154}
5155
5156test "zig fmt: missing const/var before local variable" {
5157 try testError(
5158 \\comptime {
5159 \\ z: u32;
5160 \\}
5161 \\comptime {
5162 \\ z: u32 align(1);
5163 \\}
5164 \\comptime {
5165 \\ z: u32 addrspace(.generic);
5166 \\}
5167 \\comptime {
5168 \\ z: u32 linksection("foo");
5169 \\}
5170 \\comptime {
5171 \\ z: u32 = 1;
5172 \\}
5173 , &.{
5174 .expected_labelable,
5175 .expected_var_const,
5176 .expected_var_const,
5177 .expected_var_const,
5178 .expected_var_const,
5179 });
5180}
5181
51485182test "zig fmt: while continue expr" {
51495183 try testCanonical(
51505184 \\test {
src/AstGen.zig+5
......@@ -6500,9 +6500,14 @@ fn switchExpr(
65006500 }
65016501
65026502 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
6503 astgen.advanceSourceCursorToNode(operand_node);
6504 const operand_line = astgen.source_line - parent_gz.decl_line;
6505 const operand_column = astgen.source_column;
65036506 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
65046507 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;
65056508 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);
6509 // Sema expects a dbg_stmt immediately after switch_cond(_ref)
6510 try emitDbgStmt(parent_gz, operand_line, operand_column);
65066511 // We need the type of the operand to use as the result location for all the prong items.
65076512 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
65086513 const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } };
src/Sema.zig+57-6
......@@ -9662,6 +9662,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
96629662 const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);
96639663
96649664 const operand = try sema.resolveInst(extra.data.operand);
9665 // AstGen guarantees that the instruction immediately following
9666 // switch_cond(_ref) is a dbg_stmt
9667 const cond_dbg_node_index = Zir.refToIndex(extra.data.operand).? + 1;
96659668
96669669 var header_extra_index: usize = extra.end;
96679670
......@@ -10358,6 +10361,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1035810361 if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and
1035910362 (!operand_ty.isNonexhaustiveEnum() or union_originally))
1036010363 {
10364 try sema.zirDbgStmt(block, cond_dbg_node_index);
1036110365 const ok = try block.addUnOp(.is_named_enum_value, operand);
1036210366 try sema.addSafetyCheck(block, ok, .corrupt_switch);
1036310367 }
......@@ -10827,6 +10831,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1082710831 if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and
1082810832 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))
1082910833 {
10834 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
1083010835 const ok = try case_block.addUnOp(.is_named_enum_value, operand);
1083110836 try sema.addSafetyCheck(&case_block, ok, .corrupt_switch);
1083210837 }
......@@ -10850,6 +10855,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1085010855 // We still need a terminator in this block, but we have proven
1085110856 // that it is unreachable.
1085210857 if (case_block.wantSafety()) {
10858 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
1085310859 _ = try sema.safetyPanic(&case_block, src, .corrupt_switch);
1085410860 } else {
1085510861 _ = try case_block.addNoOp(.unreach);
......@@ -16620,7 +16626,17 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1662016626 const bitoffset_src: LazySrcLoc = .{ .node_offset_ptr_bitoffset = extra.data.src_node };
1662116627 const hostsize_src: LazySrcLoc = .{ .node_offset_ptr_hostsize = extra.data.src_node };
1662216628
16623 const unresolved_elem_ty = try sema.resolveType(block, elem_ty_src, extra.data.elem_type);
16629 const unresolved_elem_ty = blk: {
16630 const air_inst = try sema.resolveInst(extra.data.elem_type);
16631 const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| {
16632 if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer()) {
16633 try sema.errNote(block, elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});
16634 }
16635 return err;
16636 };
16637 if (ty.tag() == .generic_poison) return error.GenericPoison;
16638 break :blk ty;
16639 };
1662416640 const target = sema.mod.getTarget();
1662516641
1662616642 var extra_i = extra.end;
......@@ -18666,6 +18682,13 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1866618682 }
1866718683
1866818684 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
18685 if (dest_ty.intInfo(sema.mod.getTarget()).bits == 0) {
18686 if (block.wantSafety()) {
18687 const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, try sema.addConstant(operand_ty, Value.zero));
18688 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
18689 }
18690 return sema.addConstant(dest_ty, Value.zero);
18691 }
1866918692 const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);
1867018693 if (block.wantSafety()) {
1867118694 const back = try block.addTyOp(.int_to_float, operand_ty, result);
......@@ -18932,6 +18955,9 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1893218955 if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) {
1893318956 return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)});
1893418957 }
18958 if (dest_ty.zigTypeTag() == .Optional and sema.typeOf(ptr).zigTypeTag() != .Optional) {
18959 return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, operand_val));
18960 }
1893518961 return sema.addConstant(aligned_dest_ty, operand_val);
1893618962 }
1893718963
......@@ -23919,9 +23945,20 @@ fn coerceExtra(
2391923945 // cast from ?*T and ?[*]T to ?*anyopaque
2392023946 // but don't do it if the source type is a double pointer
2392123947 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and
23922 inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer)
23923 {
23948 inst_ty.isPtrAtRuntime())
23949 anyopaque_check: {
2392423950 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;
23951 const elem_ty = inst_ty.elemType2();
23952 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {
23953 in_memory_result = .{ .double_ptr_to_anyopaque = .{
23954 .actual = inst_ty,
23955 .wanted = dest_ty,
23956 } };
23957 break :optional;
23958 }
23959 // Let the logic below handle wrapping the optional now that
23960 // it has been checked to correctly coerce.
23961 if (!inst_ty.isPtrLikeOptional()) break :anyopaque_check;
2392523962 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2392623963 }
2392723964
......@@ -24044,9 +24081,16 @@ fn coerceExtra(
2404424081
2404524082 // cast from *T and [*]T to *anyopaque
2404624083 // but don't do it if the source type is a double pointer
24047 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and
24048 inst_ty.childType().zigTypeTag() != .Pointer and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
24049 {
24084 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) {
24085 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
24086 const elem_ty = inst_ty.elemType2();
24087 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {
24088 in_memory_result = .{ .double_ptr_to_anyopaque = .{
24089 .actual = inst_ty,
24090 .wanted = dest_ty,
24091 } };
24092 break :pointer;
24093 }
2405024094 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2405124095 }
2405224096
......@@ -24528,6 +24572,7 @@ const InMemoryCoercionResult = union(enum) {
2452824572 ptr_allowzero: Pair,
2452924573 ptr_bit_range: BitRange,
2453024574 ptr_alignment: IntPair,
24575 double_ptr_to_anyopaque: Pair,
2453124576
2453224577 const Pair = struct {
2453324578 actual: Type,
......@@ -24820,6 +24865,12 @@ const InMemoryCoercionResult = union(enum) {
2482024865 });
2482124866 break;
2482224867 },
24868 .double_ptr_to_anyopaque => |pair| {
24869 try sema.errNote(block, src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{
24870 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
24871 });
24872 break;
24873 },
2482324874 };
2482424875 }
2482524876};
src/type.zig-3
......@@ -3944,10 +3944,7 @@ pub const Type = extern union {
39443944 .optional => {
39453945 var buf: Payload.ElemType = undefined;
39463946 const child_type = self.optionalChild(&buf);
3947 // optionals of zero sized pointers behave like bools
3948 if (!child_type.hasRuntimeBits()) return false;
39493947 if (child_type.zigTypeTag() != .Pointer) return false;
3950
39513948 const info = child_type.ptrInfo().data;
39523949 switch (info.size) {
39533950 .Slice, .C => return false,
test/behavior/cast.zig+8
......@@ -1411,3 +1411,11 @@ test "peer type resolution of const and non-const pointer to array" {
14111411 try std.testing.expect(@TypeOf(a, b) == *const [1024]u8);
14121412 try std.testing.expect(a == b);
14131413}
1414
1415test "floatToInt to zero-bit int" {
1416 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1417 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1418
1419 var a: f32 = 0.0;
1420 comptime try std.testing.expect(@floatToInt(u0, a) == 0);
1421}
test/cases/compile_errors/dont_implicit_cast_double_pointer_to_anyopaque.zig deleted-14
......@@ -1,14 +0,0 @@
1export fn entry() void {
2 var a: u32 = 1;
3 var ptr: *align(@alignOf(u32)) anyopaque = &a;
4 var b: *u32 = @ptrCast(*u32, ptr);
5 var ptr2: *anyopaque = &b;
6 _ = ptr2;
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :5:28: error: expected type '*anyopaque', found '**u32'
14// :5:28: note: pointer type child '*u32' cannot cast into pointer type child 'anyopaque'
test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig created+28
......@@ -0,0 +1,28 @@
1pub export fn entry1() void {
2 const x: usize = 5;
3
4 const ptr: *const anyopaque = &(&x);
5 _ = ptr;
6}
7pub export fn entry2() void {
8 var val: [*:0]u8 = undefined;
9 func(&val);
10}
11fn func(_: ?*anyopaque) void {}
12pub export fn entry3() void {
13 var x: *?*usize = undefined;
14
15 const ptr: *const anyopaque = x;
16 _ = ptr;
17}
18
19// error
20// backend=stage2
21// target=native
22//
23// :4:35: error: expected type '*const anyopaque', found '*const *const usize'
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'
26// :9:10: note: cannot implicitly cast double pointer '*[*:0]u8' to anyopaque pointer '?*anyopaque'
27// :15:35: error: expected type '*const anyopaque', found '*?*usize'
28// :15:35: note: cannot implicitly cast double pointer '*?*usize' to anyopaque pointer '*const anyopaque'
test/cases/compile_errors/incorrect_pointer_dereference_syntax.zig created+11
......@@ -0,0 +1,11 @@
1pub export fn entry() void {
2 var a: *u32 = undefined;
3 _ = *a;
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :3:10: error: expected type 'type', found '*u32'
11// :3:10: note: use '.*' to dereference pointer