From b500e0eb179218f5eb03408c09b5e5a928f0c46e Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 2 Dec 2022 21:36:41 +0200 Subject: [PATCH] Sema: add "parameter type declared here" note to type coercion --- src/Sema.zig | 63 +++++++++++++++---- ...ction_passing_array_instead_of_pointer.zig | 1 + ..._bit_offset_pointer_to_regular_pointer.zig | 1 + ...et_in_param_ty_instantiate_incorrectly.zig | 1 + ...ted_pointer_to_null-terminated_pointer.zig | 1 + .../double_pointer_to_anyopaque_pointer.zig | 1 + ...mplicitly_increasing_pointer_alignment.zig | 1 + .../pass_const_ptr_to_mutable_ptr_fn.zig | 1 + .../struct_init_passed_to_type_param.zig | 1 + .../struct_type_mismatch_in_arg.zig | 1 + ...ointer_coerced_to_pointer_to_opaque_{}.zig | 1 + 11 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index bd7bdb48cb356dbd974ef79d8d166715df58be52..09fd184320004259529dc59fab391b4e277eb219 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -291,8 +291,8 @@ pub const Block = struct { try sema.errNote(ci.block, ci.src, parent, prefix ++ "it is inside a @cImport", .{}); }, .comptime_ret_ty => |rt| { - const src_loc = if (try sema.funcDeclSrc(rt.func)) |capture| blk: { - var src_loc = capture; + const src_loc = if (try sema.funcDeclSrc(rt.func)) |fn_decl| blk: { + var src_loc = fn_decl.srcLoc(); src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 }; break :blk src_loc; } else blk: { @@ -5843,7 +5843,7 @@ fn lookupInNamespace( return null; } -fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?Module.SrcLoc { +fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl { const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null; if (func_val.isUndef()) return null; const owner_decl_index = switch (func_val.tag()) { @@ -5852,8 +5852,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?Module.SrcLoc { .decl_ref => sema.mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl, else => return null, }; - const owner_decl = sema.mod.declPtr(owner_decl_index); - return owner_decl.srcLoc(); + return sema.mod.declPtr(owner_decl_index); } pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref { @@ -6031,7 +6030,7 @@ fn zirCall( break :check_args; } - const decl_src = try sema.funcDeclSrc(func); + const maybe_decl = try sema.funcDeclSrc(func); const member_str = if (bound_arg_src != null) "member function " else ""; const variadic_str = if (func_ty_info.is_var_args) "at least " else ""; const msg = msg: { @@ -6048,7 +6047,7 @@ fn zirCall( ); errdefer msg.destroy(sema.gpa); - if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{}); + if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(msg); @@ -6242,7 +6241,7 @@ fn analyzeCall( const func_ty_info = func_ty.fnInfo(); const cc = func_ty_info.cc; if (cc == .Naked) { - const decl_src = try sema.funcDeclSrc(func); + const maybe_decl = try sema.funcDeclSrc(func); const msg = msg: { const msg = try sema.errMsg( block, @@ -6252,7 +6251,7 @@ fn analyzeCall( ); errdefer msg.destroy(sema.gpa); - if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{}); + if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(msg); @@ -6488,6 +6487,7 @@ fn analyzeCall( &should_memoize, memoized_call_key, func_ty_info.param_types, + func, ) catch |err| switch (err) { error.NeededSourceLocation => { _ = sema.inst_map.remove(inst); @@ -6504,6 +6504,7 @@ fn analyzeCall( &should_memoize, memoized_call_key, func_ty_info.param_types, + func, ); return error.AnalysisFail; }, @@ -6646,12 +6647,17 @@ fn analyzeCall( const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len); for (uncasted_args) |uncasted_arg, i| { if (i < fn_params_len) { + const opts: CoerceOpts = .{ .param_src = .{ + .func_inst = func, + .param_i = @intCast(u32, i), + } }; const param_ty = func_ty.fnParamType(i); args[i] = sema.analyzeCallArg( block, .unneeded, param_ty, uncasted_arg, + opts, ) catch |err| switch (err) { error.NeededSourceLocation => { const decl = sema.mod.declPtr(block.src_decl); @@ -6660,6 +6666,7 @@ fn analyzeCall( Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src), param_ty, uncasted_arg, + opts, ); return error.AnalysisFail; }, @@ -6741,6 +6748,7 @@ fn analyzeInlineCallArg( should_memoize: *bool, memoized_call_key: Module.MemoizedCall.Key, raw_param_types: []const Type, + func_inst: Air.Inst.Ref, ) !void { const zir_tags = sema.code.instructions.items(.tag); switch (zir_tags[inst]) { @@ -6765,7 +6773,13 @@ fn analyzeInlineCallArg( return err; }; } - const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src); + const casted_arg = sema.coerceExtra(arg_block, param_ty, uncasted_arg, arg_src, .{ .param_src = .{ + .func_inst = func_inst, + .param_i = @intCast(u32, arg_i.*), + } }) catch |err| switch (err) { + error.NotCoercible => unreachable, + else => |e| return e, + }; if (is_comptime_call) { sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg); @@ -6855,9 +6869,13 @@ fn analyzeCallArg( arg_src: LazySrcLoc, param_ty: Type, uncasted_arg: Air.Inst.Ref, + opts: CoerceOpts, ) !Air.Inst.Ref { try sema.resolveTypeFully(param_ty); - return sema.coerce(block, param_ty, uncasted_arg, arg_src); + return sema.coerceExtra(block, param_ty, uncasted_arg, arg_src, opts) catch |err| switch (err) { + error.NotCoercible => unreachable, + else => |e| return e, + }; } fn analyzeGenericCallArg( @@ -24056,6 +24074,25 @@ const CoerceOpts = struct { is_ret: bool = false, /// Should coercion to comptime_int ermit an error message. no_cast_to_comptime_int: bool = false, + + param_src: struct { + func_inst: Air.Inst.Ref = .none, + param_i: u32 = undefined, + + fn get(info: @This(), sema: *Sema) !?Module.SrcLoc { + if (info.func_inst == .none) return null; + const fn_decl = (try sema.funcDeclSrc(info.func_inst)) orelse return null; + const param_src = Module.paramSrc(0, sema.gpa, fn_decl, info.param_i); + if (param_src == .node_offset_param) { + return Module.SrcLoc{ + .file_scope = fn_decl.getFileScope(), + .parent_decl_node = fn_decl.src_node, + .lazy = LazySrcLoc.nodeOffset(param_src.node_offset_param), + }; + } + return param_src.toSrcLoc(fn_decl); + } + } = .{}, }; fn coerceExtra( @@ -24715,6 +24752,10 @@ fn coerceExtra( } } + if (try opts.param_src.get(sema)) |param_src| { + try sema.mod.errNoteNonLazy(param_src, msg, "parameter type declared here", .{}); + } + // TODO maybe add "cannot store an error in type '{}'" note break :msg msg; diff --git a/test/cases/compile_errors/calling_var_args_extern_function_passing_array_instead_of_pointer.zig b/test/cases/compile_errors/calling_var_args_extern_function_passing_array_instead_of_pointer.zig index 846a5ff81a3686fb7370c5e570315c4cab6533d6..c9e2e2e5eb820250efcb4c319346656a880ad0f2 100644 --- a/test/cases/compile_errors/calling_var_args_extern_function_passing_array_instead_of_pointer.zig +++ b/test/cases/compile_errors/calling_var_args_extern_function_passing_array_instead_of_pointer.zig @@ -8,3 +8,4 @@ pub extern fn foo(format: *const u8, ...) void; // target=native // // :2:16: error: expected type '*const u8', found '[5:0]u8' +// :4:27: note: parameter type declared here diff --git a/test/cases/compile_errors/casting_bit_offset_pointer_to_regular_pointer.zig b/test/cases/compile_errors/casting_bit_offset_pointer_to_regular_pointer.zig index 132627557e0493ac39a3b381d0d0f660507fd386..7fd38280c6dc10afe23e3be708b9acdb47d66ba3 100644 --- a/test/cases/compile_errors/casting_bit_offset_pointer_to_regular_pointer.zig +++ b/test/cases/compile_errors/casting_bit_offset_pointer_to_regular_pointer.zig @@ -21,3 +21,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); } // :8:16: error: expected type '*const u3', found '*align(0:3:1) const u3' // :8:16: note: pointer host size '1' cannot cast into pointer host size '0' // :8:16: note: pointer bit offset '3' cannot cast into pointer bit offset '0' +// :11:11: note: parameter type declared here diff --git a/test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig b/test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig index dc533442fb5d206b99d330ddb56514764d36c31f..8855755ec1b7cc4d2c456e5e94b540f7b0ca8af7 100644 --- a/test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig +++ b/test/cases/compile_errors/closure_get_in_param_ty_instantiate_incorrectly.zig @@ -22,3 +22,4 @@ pub export fn entry() void { // target=native // // :17:25: error: expected type 'u32', found 'type' +// :3:21: note: parameter type declared here diff --git a/test/cases/compile_errors/disallow_coercion_from_non-null-terminated_pointer_to_null-terminated_pointer.zig b/test/cases/compile_errors/disallow_coercion_from_non-null-terminated_pointer_to_null-terminated_pointer.zig index 0074c26de7344806ce4310c1ea7c35519df854ba..3670def4eec86c8cdcfbbe65c2ac4cb876a1c10b 100644 --- a/test/cases/compile_errors/disallow_coercion_from_non-null-terminated_pointer_to_null-terminated_pointer.zig +++ b/test/cases/compile_errors/disallow_coercion_from_non-null-terminated_pointer_to_null-terminated_pointer.zig @@ -11,3 +11,4 @@ pub export fn entry() void { // // :5:14: error: expected type '[*:0]const u8', found '[*]const u8' // :5:14: note: destination pointer requires '0' sentinel +// :1:20: note: parameter type declared here diff --git a/test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig b/test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig index 6aa9618dbd2e389a2c3fc232f11694fc2ba542dd..c7e54738d15614173edbe5c2a2f3a9c7d5ace3a1 100644 --- a/test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig +++ b/test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig @@ -24,5 +24,6 @@ pub export fn entry3() void { // :4:35: note: cannot implicitly cast double pointer '*const *const usize' to anyopaque pointer '*const anyopaque' // :9:10: error: expected type '?*anyopaque', found '*[*:0]u8' // :9:10: note: cannot implicitly cast double pointer '*[*:0]u8' to anyopaque pointer '?*anyopaque' +// :11:12: note: parameter type declared here // :15:35: error: expected type '*const anyopaque', found '*?*usize' // :15:35: note: cannot implicitly cast double pointer '*?*usize' to anyopaque pointer '*const anyopaque' diff --git a/test/cases/compile_errors/implicitly_increasing_pointer_alignment.zig b/test/cases/compile_errors/implicitly_increasing_pointer_alignment.zig index b9a9fb2faf3fd15334b0bae5c73b42cf368843b4..13adba1b9140bd21d762e8b1a9114afd4efa1b2a 100644 --- a/test/cases/compile_errors/implicitly_increasing_pointer_alignment.zig +++ b/test/cases/compile_errors/implicitly_increasing_pointer_alignment.zig @@ -18,3 +18,4 @@ fn bar(x: *u32) void { // // :8:9: error: expected type '*u32', found '*align(1) u32' // :8:9: note: pointer alignment '1' cannot cast into pointer alignment '4' +// :11:11: note: parameter type declared here diff --git a/test/cases/compile_errors/pass_const_ptr_to_mutable_ptr_fn.zig b/test/cases/compile_errors/pass_const_ptr_to_mutable_ptr_fn.zig index 39c55870f16d4b4ee4a19c4e2af76555f0230087..fd24b58f55637d91f58f5894ba7a0bc681f4fdfc 100644 --- a/test/cases/compile_errors/pass_const_ptr_to_mutable_ptr_fn.zig +++ b/test/cases/compile_errors/pass_const_ptr_to_mutable_ptr_fn.zig @@ -16,3 +16,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); } // // :4:19: error: expected type '*[]const u8', found '*const []const u8' // :4:19: note: cast discards const qualifier +// :6:14: note: parameter type declared here diff --git a/test/cases/compile_errors/struct_init_passed_to_type_param.zig b/test/cases/compile_errors/struct_init_passed_to_type_param.zig index b00c27986fd3fe59a1957a60596c368b7cf8ec0e..01906ac6137c554ae20f4bf6d135e88bb67c8136 100644 --- a/test/cases/compile_errors/struct_init_passed_to_type_param.zig +++ b/test/cases/compile_errors/struct_init_passed_to_type_param.zig @@ -12,3 +12,4 @@ export const value = hi(MyStruct{ .x = 12 }); // // :7:33: error: expected type 'type', found 'tmp.MyStruct' // :1:18: note: struct declared here +// :3:19: note: parameter type declared here diff --git a/test/cases/compile_errors/struct_type_mismatch_in_arg.zig b/test/cases/compile_errors/struct_type_mismatch_in_arg.zig index 3e53189f2f8b6d9cdae8b7a9be6ce7abbe064c09..a52bdfab6c59ce12313c261da4a3750e0868a859 100644 --- a/test/cases/compile_errors/struct_type_mismatch_in_arg.zig +++ b/test/cases/compile_errors/struct_type_mismatch_in_arg.zig @@ -15,3 +15,4 @@ comptime { // :7:16: error: expected type 'tmp.Foo', found 'tmp.Bar' // :1:13: note: struct declared here // :2:13: note: struct declared here +// :4:18: note: parameter type declared here diff --git a/test/cases/compile_errors/wrong_pointer_coerced_to_pointer_to_opaque_{}.zig b/test/cases/compile_errors/wrong_pointer_coerced_to_pointer_to_opaque_{}.zig index e22c285cb0d0f1895e05fbdca59cdd9b49190616..a050eb6a4c1ec83b61966fc5b5ef90b25fd40bdf 100644 --- a/test/cases/compile_errors/wrong_pointer_coerced_to_pointer_to_opaque_{}.zig +++ b/test/cases/compile_errors/wrong_pointer_coerced_to_pointer_to_opaque_{}.zig @@ -12,3 +12,4 @@ export fn foo() void { // :5:9: error: expected type '*tmp.Derp', found '*anyopaque' // :5:9: note: pointer type child 'anyopaque' cannot cast into pointer type child 'tmp.Derp' // :1:14: note: opaque declared here +// :2:18: note: parameter type declared here -- 2.54.0