authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-08-09 11:38:47-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-08-09 11:38:47-07:00
log72c68f698ed2153f2a9e3b2c7166fa03bb03ae1a
tree68d5adadb029c03beb65a70aaf8ed35bd2620fea
parent9676a43a5d36693c884cda53220cbee1ad9de4d5
parent57470e833e4ac545a75ad7b3dd6830fa666cd325
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16752 from jacobly0/generic-srclocs

Sema: fix issues with source locations of generic arguments

6 files changed, 147 insertions(+), 52 deletions(-)

src/Module.zig+40-16
...@@ -2133,10 +2133,40 @@ pub const SrcLoc = struct {...@@ -2133,10 +2133,40 @@ pub const SrcLoc = struct {
2133 .call_arg => |call_arg| {2133 .call_arg => |call_arg| {
2134 const tree = try src_loc.file_scope.getTree(gpa);2134 const tree = try src_loc.file_scope.getTree(gpa);
2135 const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset);2135 const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset);
2136 var buf: [1]Ast.Node.Index = undefined;2136 var buf: [2]Ast.Node.Index = undefined;
2137 const call_full = tree.fullCall(&buf, node).?;2137 const call_full = tree.fullCall(buf[0..1], node) orelse {
2138 const src_node = call_full.ast.params[call_arg.arg_index];2138 const node_tags = tree.nodes.items(.tag);
2139 return nodeToSpan(tree, src_node);2139 assert(node_tags[node] == .builtin_call);
2140 const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];
2141 switch (node_tags[call_args_node]) {
2142 .array_init_one,
2143 .array_init_one_comma,
2144 .array_init_dot_two,
2145 .array_init_dot_two_comma,
2146 .array_init_dot,
2147 .array_init_dot_comma,
2148 .array_init,
2149 .array_init_comma,
2150 => {
2151 const full = tree.fullArrayInit(&buf, call_args_node).?.ast.elements;
2152 return nodeToSpan(tree, full[call_arg.arg_index]);
2153 },
2154 .struct_init_one,
2155 .struct_init_one_comma,
2156 .struct_init_dot_two,
2157 .struct_init_dot_two_comma,
2158 .struct_init_dot,
2159 .struct_init_dot_comma,
2160 .struct_init,
2161 .struct_init_comma,
2162 => {
2163 const full = tree.fullStructInit(&buf, call_args_node).?.ast.fields;
2164 return nodeToSpan(tree, full[call_arg.arg_index]);
2165 },
2166 else => return nodeToSpan(tree, call_args_node),
2167 }
2168 };
2169 return nodeToSpan(tree, call_full.ast.params[call_arg.arg_index]);
2140 },2170 },
2141 .fn_proto_param => |fn_proto_param| {2171 .fn_proto_param => |fn_proto_param| {
2142 const tree = try src_loc.file_scope.getTree(gpa);2172 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -5926,21 +5956,15 @@ pub fn argSrc(...@@ -5926,21 +5956,15 @@ pub fn argSrc(
5926 });5956 });
5927 return LazySrcLoc.nodeOffset(0);5957 return LazySrcLoc.nodeOffset(0);
5928 };5958 };
5929 const node_tags = tree.nodes.items(.tag);
5930 const node = decl.relativeToNodeIndex(call_node_offset);5959 const node = decl.relativeToNodeIndex(call_node_offset);
5931 var args: [1]Ast.Node.Index = undefined;5960 var args: [1]Ast.Node.Index = undefined;
5932 const full = switch (node_tags[node]) {5961 const call_full = tree.fullCall(&args, node) orelse {
5933 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&args, node),5962 assert(tree.nodes.items(.tag)[node] == .builtin_call);
5934 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),5963 const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];
5935 .builtin_call => {5964 const call_args_offset = decl.nodeIndexToRelative(call_args_node);
5936 const node_datas = tree.nodes.items(.data);5965 return mod.initSrc(call_args_offset, decl, arg_i);
5937 const call_args_node = tree.extra_data[node_datas[node].rhs - 1];
5938 const call_args_offset = decl.nodeIndexToRelative(call_args_node);
5939 return mod.initSrc(call_args_offset, decl, arg_i);
5940 },
5941 else => unreachable,
5942 };5966 };
5943 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full.ast.params[arg_i]));5967 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(call_full.ast.params[arg_i]));
5944}5968}
59455969
5946pub fn initSrc(5970pub fn initSrc(
src/Sema.zig+29-15
...@@ -70,6 +70,7 @@ generic_owner: InternPool.Index = .none,...@@ -70,6 +70,7 @@ generic_owner: InternPool.Index = .none,
70/// instantiation can point back to the instantiation site in addition to the70/// instantiation can point back to the instantiation site in addition to the
71/// declaration site.71/// declaration site.
72generic_call_src: LazySrcLoc = .unneeded,72generic_call_src: LazySrcLoc = .unneeded,
73generic_bound_arg_src: ?LazySrcLoc = null,
73/// Corresponds to `generic_call_src`.74/// Corresponds to `generic_call_src`.
74generic_call_decl: Decl.OptionalIndex = .none,75generic_call_decl: Decl.OptionalIndex = .none,
75/// The key is types that must be fully resolved prior to machine code76/// The key is types that must be fully resolved prior to machine code
...@@ -7077,16 +7078,19 @@ fn analyzeCall(...@@ -7077,16 +7078,19 @@ fn analyzeCall(
7077 const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies;7078 const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies;
7078 const parent_generic_owner = sema.generic_owner;7079 const parent_generic_owner = sema.generic_owner;
7079 const parent_generic_call_src = sema.generic_call_src;7080 const parent_generic_call_src = sema.generic_call_src;
7081 const parent_generic_bound_arg_src = sema.generic_bound_arg_src;
7080 const parent_generic_call_decl = sema.generic_call_decl;7082 const parent_generic_call_decl = sema.generic_call_decl;
7081 sema.fn_ret_ty = bare_return_type;7083 sema.fn_ret_ty = bare_return_type;
7082 sema.fn_ret_ty_ies = null;7084 sema.fn_ret_ty_ies = null;
7083 sema.generic_owner = .none;7085 sema.generic_owner = .none;
7084 sema.generic_call_src = .unneeded;7086 sema.generic_call_src = .unneeded;
7087 sema.generic_bound_arg_src = null;
7085 sema.generic_call_decl = .none;7088 sema.generic_call_decl = .none;
7086 defer sema.fn_ret_ty = parent_fn_ret_ty;7089 defer sema.fn_ret_ty = parent_fn_ret_ty;
7087 defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies;7090 defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies;
7088 defer sema.generic_owner = parent_generic_owner;7091 defer sema.generic_owner = parent_generic_owner;
7089 defer sema.generic_call_src = parent_generic_call_src;7092 defer sema.generic_call_src = parent_generic_call_src;
7093 defer sema.generic_bound_arg_src = parent_generic_bound_arg_src;
7090 defer sema.generic_call_decl = parent_generic_call_decl;7094 defer sema.generic_call_decl = parent_generic_call_decl;
70917095
7092 if (module_fn.analysis(ip).inferred_error_set) {7096 if (module_fn.analysis(ip).inferred_error_set) {
...@@ -7545,6 +7549,7 @@ fn instantiateGenericCall(...@@ -7545,6 +7549,7 @@ fn instantiateGenericCall(
7545 .comptime_args = comptime_args,7549 .comptime_args = comptime_args,
7546 .generic_owner = generic_owner,7550 .generic_owner = generic_owner,
7547 .generic_call_src = call_src,7551 .generic_call_src = call_src,
7552 .generic_bound_arg_src = bound_arg_src,
7548 .generic_call_decl = block.src_decl.toOptional(),7553 .generic_call_decl = block.src_decl.toOptional(),
7549 .branch_quota = sema.branch_quota,7554 .branch_quota = sema.branch_quota,
7550 .branch_count = sema.branch_count,7555 .branch_count = sema.branch_count,
...@@ -8583,17 +8588,20 @@ fn resolveGenericBody(...@@ -8583,17 +8588,20 @@ fn resolveGenericBody(
8583 const prev_no_partial_func_type = sema.no_partial_func_ty;8588 const prev_no_partial_func_type = sema.no_partial_func_ty;
8584 const prev_generic_owner = sema.generic_owner;8589 const prev_generic_owner = sema.generic_owner;
8585 const prev_generic_call_src = sema.generic_call_src;8590 const prev_generic_call_src = sema.generic_call_src;
8591 const prev_generic_bound_arg_src = sema.generic_bound_arg_src;
8586 const prev_generic_call_decl = sema.generic_call_decl;8592 const prev_generic_call_decl = sema.generic_call_decl;
8587 block.params = .{};8593 block.params = .{};
8588 sema.no_partial_func_ty = true;8594 sema.no_partial_func_ty = true;
8589 sema.generic_owner = .none;8595 sema.generic_owner = .none;
8590 sema.generic_call_src = .unneeded;8596 sema.generic_call_src = .unneeded;
8597 sema.generic_bound_arg_src = null;
8591 sema.generic_call_decl = .none;8598 sema.generic_call_decl = .none;
8592 defer {8599 defer {
8593 block.params = prev_params;8600 block.params = prev_params;
8594 sema.no_partial_func_ty = prev_no_partial_func_type;8601 sema.no_partial_func_ty = prev_no_partial_func_type;
8595 sema.generic_owner = prev_generic_owner;8602 sema.generic_owner = prev_generic_owner;
8596 sema.generic_call_src = prev_generic_call_src;8603 sema.generic_call_src = prev_generic_call_src;
8604 sema.generic_bound_arg_src = prev_generic_bound_arg_src;
8597 sema.generic_call_decl = prev_generic_call_decl;8605 sema.generic_call_decl = prev_generic_call_decl;
8598 }8606 }
85998607
...@@ -9211,6 +9219,21 @@ fn finishFunc(...@@ -9211,6 +9219,21 @@ fn finishFunc(
9211 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);9219 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);
9212}9220}
92139221
9222fn genericArgSrcLoc(sema: *Sema, block: *Block, param_index: u32, param_src: LazySrcLoc) Module.SrcLoc {
9223 const mod = sema.mod;
9224 if (sema.generic_owner == .none) return param_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
9225 const arg_decl = sema.generic_call_decl.unwrap().?;
9226 const arg_src: LazySrcLoc = if (param_index == 0 and sema.generic_bound_arg_src != null)
9227 sema.generic_bound_arg_src.?
9228 else
9229 .{ .call_arg = .{
9230 .decl = arg_decl,
9231 .call_node_offset = sema.generic_call_src.node_offset.x,
9232 .arg_index = param_index - @intFromBool(sema.generic_bound_arg_src != null),
9233 } };
9234 return arg_src.toSrcLoc(mod.declPtr(arg_decl), mod);
9235}
9236
9214fn zirParam(9237fn zirParam(
9215 sema: *Sema,9238 sema: *Sema,
9216 block: *Block,9239 block: *Block,
...@@ -9218,7 +9241,6 @@ fn zirParam(...@@ -9218,7 +9241,6 @@ fn zirParam(
9218 param_index: u32,9241 param_index: u32,
9219 comptime_syntax: bool,9242 comptime_syntax: bool,
9220) CompileError!void {9243) CompileError!void {
9221 const mod = sema.mod;
9222 const gpa = sema.gpa;9244 const gpa = sema.gpa;
9223 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;9245 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
9224 const src = inst_data.src();9246 const src = inst_data.src();
...@@ -9235,17 +9257,20 @@ fn zirParam(...@@ -9235,17 +9257,20 @@ fn zirParam(
9235 const prev_no_partial_func_type = sema.no_partial_func_ty;9257 const prev_no_partial_func_type = sema.no_partial_func_ty;
9236 const prev_generic_owner = sema.generic_owner;9258 const prev_generic_owner = sema.generic_owner;
9237 const prev_generic_call_src = sema.generic_call_src;9259 const prev_generic_call_src = sema.generic_call_src;
9260 const prev_generic_bound_arg_src = sema.generic_bound_arg_src;
9238 const prev_generic_call_decl = sema.generic_call_decl;9261 const prev_generic_call_decl = sema.generic_call_decl;
9239 block.params = .{};9262 block.params = .{};
9240 sema.no_partial_func_ty = true;9263 sema.no_partial_func_ty = true;
9241 sema.generic_owner = .none;9264 sema.generic_owner = .none;
9242 sema.generic_call_src = .unneeded;9265 sema.generic_call_src = .unneeded;
9266 sema.generic_bound_arg_src = null;
9243 sema.generic_call_decl = .none;9267 sema.generic_call_decl = .none;
9244 defer {9268 defer {
9245 block.params = prev_params;9269 block.params = prev_params;
9246 sema.no_partial_func_ty = prev_no_partial_func_type;9270 sema.no_partial_func_ty = prev_no_partial_func_type;
9247 sema.generic_owner = prev_generic_owner;9271 sema.generic_owner = prev_generic_owner;
9248 sema.generic_call_src = prev_generic_call_src;9272 sema.generic_call_src = prev_generic_call_src;
9273 sema.generic_bound_arg_src = prev_generic_bound_arg_src;
9249 sema.generic_call_decl = prev_generic_call_decl;9274 sema.generic_call_decl = prev_generic_call_decl;
9250 }9275 }
92519276
...@@ -9319,13 +9344,8 @@ fn zirParam(...@@ -9319,13 +9344,8 @@ fn zirParam(
9319 sema.comptime_args[param_index] = val.toIntern();9344 sema.comptime_args[param_index] = val.toIntern();
9320 return;9345 return;
9321 }9346 }
9322 const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{
9323 .decl = sema.generic_call_decl.unwrap().?,
9324 .call_node_offset = sema.generic_call_src.node_offset.x,
9325 .arg_index = param_index,
9326 } } else src;
9327 const msg = msg: {9347 const msg = msg: {
9328 const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);9348 const src_loc = sema.genericArgSrcLoc(block, param_index, src);
9329 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{9349 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9330 @as([]const u8, "runtime-known argument passed to comptime parameter"),9350 @as([]const u8, "runtime-known argument passed to comptime parameter"),
9331 });9351 });
...@@ -9371,7 +9391,6 @@ fn zirParamAnytype(...@@ -9371,7 +9391,6 @@ fn zirParamAnytype(
9371 param_index: u32,9391 param_index: u32,
9372 comptime_syntax: bool,9392 comptime_syntax: bool,
9373) CompileError!void {9393) CompileError!void {
9374 const mod = sema.mod;
9375 const gpa = sema.gpa;9394 const gpa = sema.gpa;
9376 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;9395 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
9377 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);9396 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);
...@@ -9385,11 +9404,6 @@ fn zirParamAnytype(...@@ -9385,11 +9404,6 @@ fn zirParamAnytype(
9385 sema.comptime_args[param_index] = opv.toIntern();9404 sema.comptime_args[param_index] = opv.toIntern();
9386 return;9405 return;
9387 }9406 }
9388 const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{
9389 .decl = sema.generic_call_decl.unwrap().?,
9390 .call_node_offset = sema.generic_call_src.node_offset.x,
9391 .arg_index = param_index,
9392 } } else src;
93939407
9394 if (comptime_syntax) {9408 if (comptime_syntax) {
9395 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {9409 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
...@@ -9397,7 +9411,7 @@ fn zirParamAnytype(...@@ -9397,7 +9411,7 @@ fn zirParamAnytype(
9397 return;9411 return;
9398 }9412 }
9399 const msg = msg: {9413 const msg = msg: {
9400 const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);9414 const src_loc = sema.genericArgSrcLoc(block, param_index, src);
9401 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{9415 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9402 @as([]const u8, "runtime-known argument passed to comptime parameter"),9416 @as([]const u8, "runtime-known argument passed to comptime parameter"),
9403 });9417 });
...@@ -9417,7 +9431,7 @@ fn zirParamAnytype(...@@ -9417,7 +9431,7 @@ fn zirParamAnytype(
9417 return;9431 return;
9418 }9432 }
9419 const msg = msg: {9433 const msg = msg: {
9420 const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);9434 const src_loc = sema.genericArgSrcLoc(block, param_index, src);
9421 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{9435 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9422 @as([]const u8, "runtime-known argument passed to comptime-only type parameter"),9436 @as([]const u8, "runtime-known argument passed to comptime-only type parameter"),
9423 });9437 });
test/cases/compile_errors/builtin_call_with_invalid_param.zig created+12
...@@ -0,0 +1,12 @@
1export fn builtinCallBoolFunctionInlineWithVoid() void {
2 @call(.always_inline, boolFunction, .{{}});
3}
4
5fn boolFunction(_: bool) void {}
6
7// error
8// backend=stage2
9// target=native
10//
11// :2:43: error: expected type 'bool', found 'void'
12// :5:20: note: parameter type declared here
test/cases/compile_errors/generic_method_call_invalid_coercion.zig deleted-21
...@@ -1,21 +0,0 @@
1export fn callBoolMethod() void {
2 const s = S{};
3 s.boolMethod({});
4}
5
6export fn callVoidMethod() void {
7 const s = S{};
8 s.voidMethod(false);
9}
10
11const S = struct {
12 fn boolMethod(comptime _: @This(), _: bool) void {}
13 fn voidMethod(comptime _: @This(), _: void) void {}
14};
15
16// error
17// backend=stage2
18// target=native
19//
20// :3:18: error: expected type 'bool', found 'void'
21// :8:18: error: expected type 'void', found 'bool'
test/cases/compile_errors/generic_method_call_with_invalid_param.zig created+30
...@@ -0,0 +1,30 @@
1export fn callBoolMethodWithVoid() void {
2 const s = S{};
3 s.boolMethod({});
4}
5
6export fn callVoidMethodWithBool() void {
7 const s = S{};
8 s.voidMethod(false);
9}
10
11export fn callComptimeBoolMethodWithRuntimeBool() void {
12 const s = S{};
13 var arg = true;
14 s.comptimeBoolMethod(arg);
15}
16
17const S = struct {
18 fn boolMethod(comptime _: @This(), _: bool) void {}
19 fn voidMethod(comptime _: @This(), _: void) void {}
20 fn comptimeBoolMethod(comptime _: @This(), comptime _: bool) void {}
21};
22
23// error
24// backend=stage2
25// target=native
26//
27// :3:18: error: expected type 'bool', found 'void'
28// :8:18: error: expected type 'void', found 'bool'
29// :14:26: error: runtime-known argument passed to comptime parameter
30// :20:57: note: declared comptime here
test/compile_errors.zig+36
...@@ -183,4 +183,40 @@ pub fn addCases(ctx: *Cases) !void {...@@ -183,4 +183,40 @@ pub fn addCases(ctx: *Cases) !void {
183 ":1:1: note: invalid byte: '\\xff'",183 ":1:1: note: invalid byte: '\\xff'",
184 });184 });
185 }185 }
186
187 {
188 const case = ctx.obj("imported generic method call with invalid param", .{});
189
190 case.addError(
191 \\pub const import = @import("import.zig");
192 \\
193 \\export fn callComptimeBoolFunctionWithRuntimeBool(x: bool) void {
194 \\ import.comptimeBoolFunction(x);
195 \\}
196 \\
197 \\export fn callComptimeAnytypeFunctionWithRuntimeBool(x: bool) void {
198 \\ import.comptimeAnytypeFunction(x);
199 \\}
200 \\
201 \\export fn callAnytypeFunctionWithRuntimeComptimeOnlyType(x: u32) void {
202 \\ const S = struct { x: u32, y: type };
203 \\ import.anytypeFunction(S{ .x = x, .y = u32 });
204 \\}
205 , &[_][]const u8{
206 ":4:33: error: runtime-known argument passed to comptime parameter",
207 ":1:38: note: declared comptime here",
208 ":8:36: error: runtime-known argument passed to comptime parameter",
209 ":2:41: note: declared comptime here",
210 ":13:29: error: runtime-known argument passed to comptime-only type parameter",
211 ":3:24: note: declared here",
212 ":12:35: note: struct requires comptime because of this field",
213 ":12:35: note: types are not available at runtime",
214 });
215
216 case.addSourceFile("import.zig",
217 \\pub fn comptimeBoolFunction(comptime _: bool) void {}
218 \\pub fn comptimeAnytypeFunction(comptime _: anytype) void {}
219 \\pub fn anytypeFunction(_: anytype) void {}
220 );
221 }
186}222}