mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
Merge pull request #16752 from jacobly0/generic-srclocs
Sema: fix issues with source locations of generic arguments
This commit is contained in:
commit
72c68f698e
@ -2133,10 +2133,40 @@ pub const SrcLoc = struct {
|
||||
.call_arg => |call_arg| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset);
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
const call_full = tree.fullCall(&buf, node).?;
|
||||
const src_node = call_full.ast.params[call_arg.arg_index];
|
||||
return nodeToSpan(tree, src_node);
|
||||
var buf: [2]Ast.Node.Index = undefined;
|
||||
const call_full = tree.fullCall(buf[0..1], node) orelse {
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
assert(node_tags[node] == .builtin_call);
|
||||
const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];
|
||||
switch (node_tags[call_args_node]) {
|
||||
.array_init_one,
|
||||
.array_init_one_comma,
|
||||
.array_init_dot_two,
|
||||
.array_init_dot_two_comma,
|
||||
.array_init_dot,
|
||||
.array_init_dot_comma,
|
||||
.array_init,
|
||||
.array_init_comma,
|
||||
=> {
|
||||
const full = tree.fullArrayInit(&buf, call_args_node).?.ast.elements;
|
||||
return nodeToSpan(tree, full[call_arg.arg_index]);
|
||||
},
|
||||
.struct_init_one,
|
||||
.struct_init_one_comma,
|
||||
.struct_init_dot_two,
|
||||
.struct_init_dot_two_comma,
|
||||
.struct_init_dot,
|
||||
.struct_init_dot_comma,
|
||||
.struct_init,
|
||||
.struct_init_comma,
|
||||
=> {
|
||||
const full = tree.fullStructInit(&buf, call_args_node).?.ast.fields;
|
||||
return nodeToSpan(tree, full[call_arg.arg_index]);
|
||||
},
|
||||
else => return nodeToSpan(tree, call_args_node),
|
||||
}
|
||||
};
|
||||
return nodeToSpan(tree, call_full.ast.params[call_arg.arg_index]);
|
||||
},
|
||||
.fn_proto_param => |fn_proto_param| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
@ -5926,21 +5956,15 @@ pub fn argSrc(
|
||||
});
|
||||
return LazySrcLoc.nodeOffset(0);
|
||||
};
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node = decl.relativeToNodeIndex(call_node_offset);
|
||||
var args: [1]Ast.Node.Index = undefined;
|
||||
const full = switch (node_tags[node]) {
|
||||
.call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&args, node),
|
||||
.call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
|
||||
.builtin_call => {
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const call_args_node = tree.extra_data[node_datas[node].rhs - 1];
|
||||
const call_args_offset = decl.nodeIndexToRelative(call_args_node);
|
||||
return mod.initSrc(call_args_offset, decl, arg_i);
|
||||
},
|
||||
else => unreachable,
|
||||
const call_full = tree.fullCall(&args, node) orelse {
|
||||
assert(tree.nodes.items(.tag)[node] == .builtin_call);
|
||||
const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];
|
||||
const call_args_offset = decl.nodeIndexToRelative(call_args_node);
|
||||
return mod.initSrc(call_args_offset, decl, arg_i);
|
||||
};
|
||||
return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full.ast.params[arg_i]));
|
||||
return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(call_full.ast.params[arg_i]));
|
||||
}
|
||||
|
||||
pub fn initSrc(
|
||||
|
||||
44
src/Sema.zig
44
src/Sema.zig
@ -70,6 +70,7 @@ generic_owner: InternPool.Index = .none,
|
||||
/// instantiation can point back to the instantiation site in addition to the
|
||||
/// declaration site.
|
||||
generic_call_src: LazySrcLoc = .unneeded,
|
||||
generic_bound_arg_src: ?LazySrcLoc = null,
|
||||
/// Corresponds to `generic_call_src`.
|
||||
generic_call_decl: Decl.OptionalIndex = .none,
|
||||
/// The key is types that must be fully resolved prior to machine code
|
||||
@ -7077,16 +7078,19 @@ fn analyzeCall(
|
||||
const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies;
|
||||
const parent_generic_owner = sema.generic_owner;
|
||||
const parent_generic_call_src = sema.generic_call_src;
|
||||
const parent_generic_bound_arg_src = sema.generic_bound_arg_src;
|
||||
const parent_generic_call_decl = sema.generic_call_decl;
|
||||
sema.fn_ret_ty = bare_return_type;
|
||||
sema.fn_ret_ty_ies = null;
|
||||
sema.generic_owner = .none;
|
||||
sema.generic_call_src = .unneeded;
|
||||
sema.generic_bound_arg_src = null;
|
||||
sema.generic_call_decl = .none;
|
||||
defer sema.fn_ret_ty = parent_fn_ret_ty;
|
||||
defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies;
|
||||
defer sema.generic_owner = parent_generic_owner;
|
||||
defer sema.generic_call_src = parent_generic_call_src;
|
||||
defer sema.generic_bound_arg_src = parent_generic_bound_arg_src;
|
||||
defer sema.generic_call_decl = parent_generic_call_decl;
|
||||
|
||||
if (module_fn.analysis(ip).inferred_error_set) {
|
||||
@ -7545,6 +7549,7 @@ fn instantiateGenericCall(
|
||||
.comptime_args = comptime_args,
|
||||
.generic_owner = generic_owner,
|
||||
.generic_call_src = call_src,
|
||||
.generic_bound_arg_src = bound_arg_src,
|
||||
.generic_call_decl = block.src_decl.toOptional(),
|
||||
.branch_quota = sema.branch_quota,
|
||||
.branch_count = sema.branch_count,
|
||||
@ -8583,17 +8588,20 @@ fn resolveGenericBody(
|
||||
const prev_no_partial_func_type = sema.no_partial_func_ty;
|
||||
const prev_generic_owner = sema.generic_owner;
|
||||
const prev_generic_call_src = sema.generic_call_src;
|
||||
const prev_generic_bound_arg_src = sema.generic_bound_arg_src;
|
||||
const prev_generic_call_decl = sema.generic_call_decl;
|
||||
block.params = .{};
|
||||
sema.no_partial_func_ty = true;
|
||||
sema.generic_owner = .none;
|
||||
sema.generic_call_src = .unneeded;
|
||||
sema.generic_bound_arg_src = null;
|
||||
sema.generic_call_decl = .none;
|
||||
defer {
|
||||
block.params = prev_params;
|
||||
sema.no_partial_func_ty = prev_no_partial_func_type;
|
||||
sema.generic_owner = prev_generic_owner;
|
||||
sema.generic_call_src = prev_generic_call_src;
|
||||
sema.generic_bound_arg_src = prev_generic_bound_arg_src;
|
||||
sema.generic_call_decl = prev_generic_call_decl;
|
||||
}
|
||||
|
||||
@ -9211,6 +9219,21 @@ fn finishFunc(
|
||||
return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);
|
||||
}
|
||||
|
||||
fn genericArgSrcLoc(sema: *Sema, block: *Block, param_index: u32, param_src: LazySrcLoc) Module.SrcLoc {
|
||||
const mod = sema.mod;
|
||||
if (sema.generic_owner == .none) return param_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
|
||||
const arg_decl = sema.generic_call_decl.unwrap().?;
|
||||
const arg_src: LazySrcLoc = if (param_index == 0 and sema.generic_bound_arg_src != null)
|
||||
sema.generic_bound_arg_src.?
|
||||
else
|
||||
.{ .call_arg = .{
|
||||
.decl = arg_decl,
|
||||
.call_node_offset = sema.generic_call_src.node_offset.x,
|
||||
.arg_index = param_index - @intFromBool(sema.generic_bound_arg_src != null),
|
||||
} };
|
||||
return arg_src.toSrcLoc(mod.declPtr(arg_decl), mod);
|
||||
}
|
||||
|
||||
fn zirParam(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
@ -9218,7 +9241,6 @@ fn zirParam(
|
||||
param_index: u32,
|
||||
comptime_syntax: bool,
|
||||
) CompileError!void {
|
||||
const mod = sema.mod;
|
||||
const gpa = sema.gpa;
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
|
||||
const src = inst_data.src();
|
||||
@ -9235,17 +9257,20 @@ fn zirParam(
|
||||
const prev_no_partial_func_type = sema.no_partial_func_ty;
|
||||
const prev_generic_owner = sema.generic_owner;
|
||||
const prev_generic_call_src = sema.generic_call_src;
|
||||
const prev_generic_bound_arg_src = sema.generic_bound_arg_src;
|
||||
const prev_generic_call_decl = sema.generic_call_decl;
|
||||
block.params = .{};
|
||||
sema.no_partial_func_ty = true;
|
||||
sema.generic_owner = .none;
|
||||
sema.generic_call_src = .unneeded;
|
||||
sema.generic_bound_arg_src = null;
|
||||
sema.generic_call_decl = .none;
|
||||
defer {
|
||||
block.params = prev_params;
|
||||
sema.no_partial_func_ty = prev_no_partial_func_type;
|
||||
sema.generic_owner = prev_generic_owner;
|
||||
sema.generic_call_src = prev_generic_call_src;
|
||||
sema.generic_bound_arg_src = prev_generic_bound_arg_src;
|
||||
sema.generic_call_decl = prev_generic_call_decl;
|
||||
}
|
||||
|
||||
@ -9319,13 +9344,8 @@ fn zirParam(
|
||||
sema.comptime_args[param_index] = val.toIntern();
|
||||
return;
|
||||
}
|
||||
const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{
|
||||
.decl = sema.generic_call_decl.unwrap().?,
|
||||
.call_node_offset = sema.generic_call_src.node_offset.x,
|
||||
.arg_index = param_index,
|
||||
} } else src;
|
||||
const msg = msg: {
|
||||
const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
|
||||
const src_loc = sema.genericArgSrcLoc(block, param_index, src);
|
||||
const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
|
||||
@as([]const u8, "runtime-known argument passed to comptime parameter"),
|
||||
});
|
||||
@ -9371,7 +9391,6 @@ fn zirParamAnytype(
|
||||
param_index: u32,
|
||||
comptime_syntax: bool,
|
||||
) CompileError!void {
|
||||
const mod = sema.mod;
|
||||
const gpa = sema.gpa;
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
|
||||
const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);
|
||||
@ -9385,11 +9404,6 @@ fn zirParamAnytype(
|
||||
sema.comptime_args[param_index] = opv.toIntern();
|
||||
return;
|
||||
}
|
||||
const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{
|
||||
.decl = sema.generic_call_decl.unwrap().?,
|
||||
.call_node_offset = sema.generic_call_src.node_offset.x,
|
||||
.arg_index = param_index,
|
||||
} } else src;
|
||||
|
||||
if (comptime_syntax) {
|
||||
if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
|
||||
@ -9397,7 +9411,7 @@ fn zirParamAnytype(
|
||||
return;
|
||||
}
|
||||
const msg = msg: {
|
||||
const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
|
||||
const src_loc = sema.genericArgSrcLoc(block, param_index, src);
|
||||
const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
|
||||
@as([]const u8, "runtime-known argument passed to comptime parameter"),
|
||||
});
|
||||
@ -9417,7 +9431,7 @@ fn zirParamAnytype(
|
||||
return;
|
||||
}
|
||||
const msg = msg: {
|
||||
const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
|
||||
const src_loc = sema.genericArgSrcLoc(block, param_index, src);
|
||||
const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
|
||||
@as([]const u8, "runtime-known argument passed to comptime-only type parameter"),
|
||||
});
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
export fn builtinCallBoolFunctionInlineWithVoid() void {
|
||||
@call(.always_inline, boolFunction, .{{}});
|
||||
}
|
||||
|
||||
fn boolFunction(_: bool) void {}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:43: error: expected type 'bool', found 'void'
|
||||
// :5:20: note: parameter type declared here
|
||||
@ -1,21 +0,0 @@
|
||||
export fn callBoolMethod() void {
|
||||
const s = S{};
|
||||
s.boolMethod({});
|
||||
}
|
||||
|
||||
export fn callVoidMethod() void {
|
||||
const s = S{};
|
||||
s.voidMethod(false);
|
||||
}
|
||||
|
||||
const S = struct {
|
||||
fn boolMethod(comptime _: @This(), _: bool) void {}
|
||||
fn voidMethod(comptime _: @This(), _: void) void {}
|
||||
};
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:18: error: expected type 'bool', found 'void'
|
||||
// :8:18: error: expected type 'void', found 'bool'
|
||||
@ -0,0 +1,30 @@
|
||||
export fn callBoolMethodWithVoid() void {
|
||||
const s = S{};
|
||||
s.boolMethod({});
|
||||
}
|
||||
|
||||
export fn callVoidMethodWithBool() void {
|
||||
const s = S{};
|
||||
s.voidMethod(false);
|
||||
}
|
||||
|
||||
export fn callComptimeBoolMethodWithRuntimeBool() void {
|
||||
const s = S{};
|
||||
var arg = true;
|
||||
s.comptimeBoolMethod(arg);
|
||||
}
|
||||
|
||||
const S = struct {
|
||||
fn boolMethod(comptime _: @This(), _: bool) void {}
|
||||
fn voidMethod(comptime _: @This(), _: void) void {}
|
||||
fn comptimeBoolMethod(comptime _: @This(), comptime _: bool) void {}
|
||||
};
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:18: error: expected type 'bool', found 'void'
|
||||
// :8:18: error: expected type 'void', found 'bool'
|
||||
// :14:26: error: runtime-known argument passed to comptime parameter
|
||||
// :20:57: note: declared comptime here
|
||||
@ -183,4 +183,40 @@ pub fn addCases(ctx: *Cases) !void {
|
||||
":1:1: note: invalid byte: '\\xff'",
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const case = ctx.obj("imported generic method call with invalid param", .{});
|
||||
|
||||
case.addError(
|
||||
\\pub const import = @import("import.zig");
|
||||
\\
|
||||
\\export fn callComptimeBoolFunctionWithRuntimeBool(x: bool) void {
|
||||
\\ import.comptimeBoolFunction(x);
|
||||
\\}
|
||||
\\
|
||||
\\export fn callComptimeAnytypeFunctionWithRuntimeBool(x: bool) void {
|
||||
\\ import.comptimeAnytypeFunction(x);
|
||||
\\}
|
||||
\\
|
||||
\\export fn callAnytypeFunctionWithRuntimeComptimeOnlyType(x: u32) void {
|
||||
\\ const S = struct { x: u32, y: type };
|
||||
\\ import.anytypeFunction(S{ .x = x, .y = u32 });
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
":4:33: error: runtime-known argument passed to comptime parameter",
|
||||
":1:38: note: declared comptime here",
|
||||
":8:36: error: runtime-known argument passed to comptime parameter",
|
||||
":2:41: note: declared comptime here",
|
||||
":13:29: error: runtime-known argument passed to comptime-only type parameter",
|
||||
":3:24: note: declared here",
|
||||
":12:35: note: struct requires comptime because of this field",
|
||||
":12:35: note: types are not available at runtime",
|
||||
});
|
||||
|
||||
case.addSourceFile("import.zig",
|
||||
\\pub fn comptimeBoolFunction(comptime _: bool) void {}
|
||||
\\pub fn comptimeAnytypeFunction(comptime _: anytype) void {}
|
||||
\\pub fn anytypeFunction(_: anytype) void {}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user