authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-04-01 18:30:40+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-01 15:56:38-04:00
log6695fa4f326e807256b9afc6321e63a90b08e1ba
treee5a6d7aa12dce2d9ac468e5c15431058f1578699
parent212e2354b8ab631995b0c25f7cf1d9a3e01fac57

ir: Fix comparison of ?T values

The code assumed that every ?T had a pointer child type T, add some more checks to make sure the type is effectively a pointer. Closes #4789

2 files changed, 15 insertions(+), 4 deletions(-)

src/ir.cpp+2-4
...@@ -11454,10 +11454,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -11454,10 +11454,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
11454 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);11454 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
11455 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;11455 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
11456 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;11456 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
11457 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&11457 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr && wanted_ptr_type->id == ZigTypeIdPointer;
11458 (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);11458 bool actual_opt_or_ptr = actual_ptr_type != nullptr && actual_ptr_type->id == ZigTypeIdPointer;
11459 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
11460 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
11461 if (wanted_opt_or_ptr && actual_opt_or_ptr) {11459 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
11462 bool ok_null_term_ptrs =11460 bool ok_null_term_ptrs =
11463 wanted_ptr_type->data.pointer.sentinel == nullptr ||11461 wanted_ptr_type->data.pointer.sentinel == nullptr ||
test/compile_errors.zig+13
...@@ -2,6 +2,19 @@ const tests = @import("tests.zig");...@@ -2,6 +2,19 @@ const tests = @import("tests.zig");
2const std = @import("std");2const std = @import("std");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.addTest("cast between ?T where T is not a pointer",
6 \\pub const fnty1 = ?fn (i8) void;
7 \\pub const fnty2 = ?fn (u64) void;
8 \\export fn entry() void {
9 \\ var a: fnty1 = undefined;
10 \\ var b: fnty2 = undefined;
11 \\ a = b;
12 \\}
13 , &[_][]const u8{
14 "tmp.zig:6:9: error: expected type '?fn(i8) void', found '?fn(u64) void'",
15 "tmp.zig:6:9: note: optional type child 'fn(u64) void' cannot cast into optional type child 'fn(i8) void'",
16 });
17
5 cases.addTest("unused variable error on errdefer",18 cases.addTest("unused variable error on errdefer",
6 \\fn foo() !void {19 \\fn foo() !void {
7 \\ errdefer |a| unreachable;20 \\ errdefer |a| unreachable;