authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-04 16:04:31+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-11-04 16:04:31+02:00
log8c4faa5f3f63cfbcfdc12cda7c37be1da642d2f6
tree2a90fb00f39cb5eae5f8083e2b8462a2e198f918
parentea54c9a375ef8f419694b39b9f14f181fa0b82ee
parent577daab08cd2119604b5ee501e4bd8aeb2619668
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

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:...@@ -16,7 +16,7 @@ jobs:
16 vmImage: 'windows-2019'16 vmImage: 'windows-2019'
17 variables:17 variables:
18 TARGET: 'x86_64-windows-gnu'18 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'
20 ZIG_LLVM_CLANG_LLD_URL: 'https://ziglang.org/deps/${{ variables.ZIG_LLVM_CLANG_LLD_NAME }}.zip'20 ZIG_LLVM_CLANG_LLD_URL: 'https://ziglang.org/deps/${{ variables.ZIG_LLVM_CLANG_LLD_NAME }}.zip'
21 steps:21 steps:
22 - pwsh: |22 - pwsh: |
lib/std/meta.zig+3-3
...@@ -304,7 +304,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {...@@ -304,7 +304,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
304 .Array = .{304 .Array = .{
305 .len = array_info.len,305 .len = array_info.len,
306 .child = array_info.child,306 .child = array_info.child,
307 .sentinel = &sentinel_val,307 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
308 },308 },
309 }),309 }),
310 .is_allowzero = info.is_allowzero,310 .is_allowzero = info.is_allowzero,
...@@ -322,7 +322,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {...@@ -322,7 +322,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
322 .address_space = info.address_space,322 .address_space = info.address_space,
323 .child = info.child,323 .child = info.child,
324 .is_allowzero = info.is_allowzero,324 .is_allowzero = info.is_allowzero,
325 .sentinel = &sentinel_val,325 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
326 },326 },
327 }),327 }),
328 else => {},328 else => {},
...@@ -340,7 +340,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {...@@ -340,7 +340,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
340 .address_space = ptr_info.address_space,340 .address_space = ptr_info.address_space,
341 .child = ptr_info.child,341 .child = ptr_info.child,
342 .is_allowzero = ptr_info.is_allowzero,342 .is_allowzero = ptr_info.is_allowzero,
343 .sentinel = &sentinel_val,343 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
344 },344 },
345 }),345 }),
346 },346 },
lib/std/start_windows_tls.zig+1-1
...@@ -42,7 +42,7 @@ export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{...@@ -42,7 +42,7 @@ export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{
42 .StartAddressOfRawData = &_tls_start,42 .StartAddressOfRawData = &_tls_start,
43 .EndAddressOfRawData = &_tls_end,43 .EndAddressOfRawData = &_tls_end,
44 .AddressOfIndex = &_tls_index,44 .AddressOfIndex = &_tls_index,
45 .AddressOfCallBacks = &__xl_a,45 .AddressOfCallBacks = @ptrCast(*anyopaque, &__xl_a),
46 .SizeOfZeroFill = 0,46 .SizeOfZeroFill = 0,
47 .Characteristics = 0,47 .Characteristics = 0,
48};48};
lib/std/zig/Ast.zig+9-1
...@@ -197,7 +197,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -197,7 +197,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
197 });197 });
198 },198 },
199 .expected_labelable => {199 .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}'", .{
201 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),201 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
202 });202 });
203 },203 },
...@@ -356,6 +356,12 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -356,6 +356,12 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
356 .next_field => {356 .next_field => {
357 return stream.writeAll("field after declarations here");357 return stream.writeAll("field after declarations here");
358 },358 },
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
360 .expected_token => {366 .expected_token => {
361 const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];367 const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];
...@@ -2579,6 +2585,8 @@ pub const Error = struct {...@@ -2579,6 +2585,8 @@ pub const Error = struct {
2579 mismatched_binary_op_whitespace,2585 mismatched_binary_op_whitespace,
2580 invalid_ampersand_ampersand,2586 invalid_ampersand_ampersand,
2581 c_style_container,2587 c_style_container,
2588 expected_var_const,
2589 wrong_equal_var_decl,
25822590
2583 zig_style_container,2591 zig_style_container,
2584 previous_field,2592 previous_field,
lib/std/zig/parse.zig+24-2
...@@ -812,7 +812,18 @@ const Parser = struct {...@@ -812,7 +812,18 @@ const Parser = struct {
812 const align_node = try p.parseByteAlign();812 const align_node = try p.parseByteAlign();
813 const addrspace_node = try p.parseAddrSpace();813 const addrspace_node = try p.parseAddrSpace();
814 const section_node = try p.parseLinkSection();814 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 };
816 if (section_node == 0 and addrspace_node == 0) {827 if (section_node == 0 and addrspace_node == 0) {
817 if (align_node == 0) {828 if (align_node == 0) {
818 return p.addNode(.{829 return p.addNode(.{
...@@ -1118,7 +1129,18 @@ const Parser = struct {...@@ -1118,7 +1129,18 @@ const Parser = struct {
1118 if (loop_stmt != 0) return loop_stmt;1129 if (loop_stmt != 0) return loop_stmt;
11191130
1120 if (label_token != 0) {1131 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 });
1122 }1144 }
11231145
1124 return null_node;1146 return null_node;
lib/std/zig/parser_test.zig+34
...@@ -5145,6 +5145,40 @@ test "zig fmt: make single-line if no trailing comma" {...@@ -5145,6 +5145,40 @@ test "zig fmt: make single-line if no trailing comma" {
5145 );5145 );
5146}5146}
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
5148test "zig fmt: while continue expr" {5182test "zig fmt: while continue expr" {
5149 try testCanonical(5183 try testCanonical(
5150 \\test {5184 \\test {
src/AstGen.zig+5
...@@ -6500,9 +6500,14 @@ fn switchExpr(...@@ -6500,9 +6500,14 @@ fn switchExpr(
6500 }6500 }
65016501
6502 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };6502 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;
6503 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);6506 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
6504 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;6507 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;
6505 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);6508 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);
6506 // We need the type of the operand to use as the result location for all the prong items.6511 // We need the type of the operand to use as the result location for all the prong items.
6507 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);6512 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
6508 const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } };6513 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...@@ -9662,6 +9662,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9662 const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);9662 const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);
96639663
9664 const operand = try sema.resolveInst(extra.data.operand);9664 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
9666 var header_extra_index: usize = extra.end;9669 var header_extra_index: usize = extra.end;
96679670
...@@ -10358,6 +10361,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10358,6 +10361,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10358 if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and10361 if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and
10359 (!operand_ty.isNonexhaustiveEnum() or union_originally))10362 (!operand_ty.isNonexhaustiveEnum() or union_originally))
10360 {10363 {
10364 try sema.zirDbgStmt(block, cond_dbg_node_index);
10361 const ok = try block.addUnOp(.is_named_enum_value, operand);10365 const ok = try block.addUnOp(.is_named_enum_value, operand);
10362 try sema.addSafetyCheck(block, ok, .corrupt_switch);10366 try sema.addSafetyCheck(block, ok, .corrupt_switch);
10363 }10367 }
...@@ -10827,6 +10831,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10827,6 +10831,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10827 if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and10831 if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and
10828 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))10832 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))
10829 {10833 {
10834 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
10830 const ok = try case_block.addUnOp(.is_named_enum_value, operand);10835 const ok = try case_block.addUnOp(.is_named_enum_value, operand);
10831 try sema.addSafetyCheck(&case_block, ok, .corrupt_switch);10836 try sema.addSafetyCheck(&case_block, ok, .corrupt_switch);
10832 }10837 }
...@@ -10850,6 +10855,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10850,6 +10855,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10850 // We still need a terminator in this block, but we have proven10855 // We still need a terminator in this block, but we have proven
10851 // that it is unreachable.10856 // that it is unreachable.
10852 if (case_block.wantSafety()) {10857 if (case_block.wantSafety()) {
10858 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
10853 _ = try sema.safetyPanic(&case_block, src, .corrupt_switch);10859 _ = try sema.safetyPanic(&case_block, src, .corrupt_switch);
10854 } else {10860 } else {
10855 _ = try case_block.addNoOp(.unreach);10861 _ = try case_block.addNoOp(.unreach);
...@@ -16620,7 +16626,17 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -16620,7 +16626,17 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
16620 const bitoffset_src: LazySrcLoc = .{ .node_offset_ptr_bitoffset = extra.data.src_node };16626 const bitoffset_src: LazySrcLoc = .{ .node_offset_ptr_bitoffset = extra.data.src_node };
16621 const hostsize_src: LazySrcLoc = .{ .node_offset_ptr_hostsize = extra.data.src_node };16627 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 };
16624 const target = sema.mod.getTarget();16640 const target = sema.mod.getTarget();
1662516641
16626 var extra_i = extra.end;16642 var extra_i = extra.end;
...@@ -18666,6 +18682,13 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -18666,6 +18682,13 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
18666 }18682 }
1866718683
18668 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);18684 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 }
18669 const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);18692 const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);
18670 if (block.wantSafety()) {18693 if (block.wantSafety()) {
18671 const back = try block.addTyOp(.int_to_float, operand_ty, result);18694 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...@@ -18932,6 +18955,9 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
18932 if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) {18955 if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) {
18933 return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)});18956 return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)});
18934 }18957 }
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 }
18935 return sema.addConstant(aligned_dest_ty, operand_val);18961 return sema.addConstant(aligned_dest_ty, operand_val);
18936 }18962 }
1893718963
...@@ -23919,9 +23945,20 @@ fn coerceExtra(...@@ -23919,9 +23945,20 @@ fn coerceExtra(
23919 // cast from ?*T and ?[*]T to ?*anyopaque23945 // cast from ?*T and ?[*]T to ?*anyopaque
23920 // but don't do it if the source type is a double pointer23946 // but don't do it if the source type is a double pointer
23921 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and23947 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and
23922 inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer)23948 inst_ty.isPtrAtRuntime())
23923 {23949 anyopaque_check: {
23924 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;23950 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;
23925 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);23962 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
23926 }23963 }
2392723964
...@@ -24044,9 +24081,16 @@ fn coerceExtra(...@@ -24044,9 +24081,16 @@ fn coerceExtra(
2404424081
24045 // cast from *T and [*]T to *anyopaque24082 // cast from *T and [*]T to *anyopaque
24046 // but don't do it if the source type is a double pointer24083 // 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 and24084 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) {
24048 inst_ty.childType().zigTypeTag() != .Pointer and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))24085 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
24049 {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 }
24050 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);24094 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
24051 }24095 }
2405224096
...@@ -24528,6 +24572,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -24528,6 +24572,7 @@ const InMemoryCoercionResult = union(enum) {
24528 ptr_allowzero: Pair,24572 ptr_allowzero: Pair,
24529 ptr_bit_range: BitRange,24573 ptr_bit_range: BitRange,
24530 ptr_alignment: IntPair,24574 ptr_alignment: IntPair,
24575 double_ptr_to_anyopaque: Pair,
2453124576
24532 const Pair = struct {24577 const Pair = struct {
24533 actual: Type,24578 actual: Type,
...@@ -24820,6 +24865,12 @@ const InMemoryCoercionResult = union(enum) {...@@ -24820,6 +24865,12 @@ const InMemoryCoercionResult = union(enum) {
24820 });24865 });
24821 break;24866 break;
24822 },24867 },
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 },
24823 };24874 };
24824 }24875 }
24825};24876};
src/type.zig-3
...@@ -3944,10 +3944,7 @@ pub const Type = extern union {...@@ -3944,10 +3944,7 @@ pub const Type = extern union {
3944 .optional => {3944 .optional => {
3945 var buf: Payload.ElemType = undefined;3945 var buf: Payload.ElemType = undefined;
3946 const child_type = self.optionalChild(&buf);3946 const child_type = self.optionalChild(&buf);
3947 // optionals of zero sized pointers behave like bools
3948 if (!child_type.hasRuntimeBits()) return false;
3949 if (child_type.zigTypeTag() != .Pointer) return false;3947 if (child_type.zigTypeTag() != .Pointer) return false;
3950
3951 const info = child_type.ptrInfo().data;3948 const info = child_type.ptrInfo().data;
3952 switch (info.size) {3949 switch (info.size) {
3953 .Slice, .C => return false,3950 .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" {...@@ -1411,3 +1411,11 @@ test "peer type resolution of const and non-const pointer to array" {
1411 try std.testing.expect(@TypeOf(a, b) == *const [1024]u8);1411 try std.testing.expect(@TypeOf(a, b) == *const [1024]u8);
1412 try std.testing.expect(a == b);1412 try std.testing.expect(a == b);
1413}1413}
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