Sema: add "parameter type declared here" note to type coercion
This commit is contained in:
63
src/Sema.zig
63
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user