diff --git a/src/ir.cpp b/src/ir.cpp index 4b39f736a..14600bbc6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -183,6 +183,7 @@ struct ConstCastBadCV { struct ConstCastPtrSentinel { ZigType *wanted_type; + ZigType *actual_type; }; static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); @@ -9898,7 +9899,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted if (!ok_null_term_ptrs) { result.id = ConstCastResultIdPtrSentinel; result.data.bad_ptr_sentinel = allocate_nonzero(1); - result.data.bad_ptr_sentinel->wanted_type = wanted_type; + result.data.bad_ptr_sentinel->wanted_type = wanted_ptr_type; + result.data.bad_ptr_sentinel->actual_type = actual_ptr_type; return result; } bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len; @@ -12653,19 +12655,27 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa break; } case ConstCastResultIdPtrSentinel: { + ZigType *actual_type = cast_result->data.bad_ptr_sentinel->actual_type; ZigType *wanted_type = cast_result->data.bad_ptr_sentinel->wanted_type; - Buf *msg = buf_sprintf("destination pointer requires a terminating '"); - render_const_value(ira->codegen, msg, wanted_type->data.pointer.sentinel); - buf_appendf(msg, "' sentinel value"); - add_error_note(ira->codegen, parent_msg, source_node, msg); + { + Buf *txt_msg = buf_sprintf("destination pointer requires a terminating '"); + render_const_value(ira->codegen, txt_msg, wanted_type->data.pointer.sentinel); + buf_appendf(txt_msg, "' sentinel value"); + if (actual_type->data.pointer.sentinel != nullptr) { + buf_appendf(txt_msg, ", but source pointer has a terminating '"); + render_const_value(ira->codegen, txt_msg, actual_type->data.pointer.sentinel); + buf_appendf(txt_msg, "' sentinel value"); + } + add_error_note(ira->codegen, parent_msg, source_node, txt_msg); + } break; } case ConstCastResultIdSentinelArrays: { ZigType *wanted_type = cast_result->data.sentinel_arrays->wanted_type; - Buf *msg = buf_sprintf("destination array requires a terminating '"); - render_const_value(ira->codegen, msg, wanted_type->data.pointer.sentinel); - buf_appendf(msg, "' sentinel value"); - add_error_note(ira->codegen, parent_msg, source_node, msg); + Buf *txt_msg = buf_sprintf("destination array requires a terminating '"); + render_const_value(ira->codegen, txt_msg, wanted_type->data.pointer.sentinel); + buf_appendf(txt_msg, "' sentinel value"); + add_error_note(ira->codegen, parent_msg, source_node, txt_msg); break; } case ConstCastResultIdCV: { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index d92808858..ef6593a61 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,21 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "incompatible pointer sentinels", + \\export fn entry1(ptr: [*:255]u8) [*:0]u8 { + \\ return ptr; + \\} + \\export fn entry2(ptr: [*]u8) [*:0]u8 { + \\ return ptr; + \\} + , + "tmp.zig:2:5: error: expected type '[*:0]u8', found '[*:255]u8'", + "tmp.zig:2:5: note: destination pointer requires a terminating '0' sentinel value, but source pointer has a terminating '255' sentinel value", + "tmp.zig:5:5: error: expected type '[*:0]u8', found '[*]u8'", + "tmp.zig:5:5: note: destination pointer requires a terminating '0' sentinel value", + ); + cases.add( "regression test #2980: base type u32 is not type checked properly when assigning a value within a struct", \\const Foo = struct {