| author | |
| committer | |
| log | 72c68f698ed2153f2a9e3b2c7166fa03bb03ae1a |
| tree | 68d5adadb029c03beb65a70aaf8ed35bd2620fea |
| parent | 9676a43a5d36693c884cda53220cbee1ad9de4d5 |
| parent | 57470e833e4ac545a75ad7b3dd6830fa666cd325 |
| signature |
Sema: fix issues with source locations of generic arguments6 files changed, 147 insertions(+), 52 deletions(-)
src/Module.zig+40-16| ... | ... | @@ -2133,10 +2133,40 @@ pub const SrcLoc = struct { |
| 2133 | 2133 | .call_arg => |call_arg| { |
| 2134 | 2134 | const tree = try src_loc.file_scope.getTree(gpa); |
| 2135 | 2135 | const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset); |
| 2136 | var buf: [1]Ast.Node.Index = undefined; | |
| 2137 | const call_full = tree.fullCall(&buf, node).?; | |
| 2138 | const src_node = call_full.ast.params[call_arg.arg_index]; | |
| 2139 | return nodeToSpan(tree, src_node); | |
| 2136 | var buf: [2]Ast.Node.Index = undefined; | |
| 2137 | const call_full = tree.fullCall(buf[0..1], node) orelse { | |
| 2138 | const node_tags = tree.nodes.items(.tag); | |
| 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 | 2171 | .fn_proto_param => |fn_proto_param| { |
| 2142 | 2172 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | ... | @@ -5926,21 +5956,15 @@ pub fn argSrc( |
| 5926 | 5956 | }); |
| 5927 | 5957 | return LazySrcLoc.nodeOffset(0); |
| 5928 | 5958 | }; |
| 5929 | const node_tags = tree.nodes.items(.tag); | |
| 5930 | 5959 | const node = decl.relativeToNodeIndex(call_node_offset); |
| 5931 | 5960 | var args: [1]Ast.Node.Index = undefined; |
| 5932 | const full = switch (node_tags[node]) { | |
| 5933 | .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&args, node), | |
| 5934 | .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node), | |
| 5935 | .builtin_call => { | |
| 5936 | const node_datas = tree.nodes.items(.data); | |
| 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, | |
| 5961 | const call_full = tree.fullCall(&args, node) orelse { | |
| 5962 | assert(tree.nodes.items(.tag)[node] == .builtin_call); | |
| 5963 | const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1]; | |
| 5964 | const call_args_offset = decl.nodeIndexToRelative(call_args_node); | |
| 5965 | return mod.initSrc(call_args_offset, decl, arg_i); | |
| 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 | } |
| 5945 | 5969 | |
| 5946 | 5970 | pub fn initSrc( |
src/Sema.zig+29-15| ... | ... | @@ -70,6 +70,7 @@ generic_owner: InternPool.Index = .none, |
| 70 | 70 | /// instantiation can point back to the instantiation site in addition to the |
| 71 | 71 | /// declaration site. |
| 72 | 72 | generic_call_src: LazySrcLoc = .unneeded, |
| 73 | generic_bound_arg_src: ?LazySrcLoc = null, | |
| 73 | 74 | /// Corresponds to `generic_call_src`. |
| 74 | 75 | generic_call_decl: Decl.OptionalIndex = .none, |
| 75 | 76 | /// The key is types that must be fully resolved prior to machine code |
| ... | ... | @@ -7077,16 +7078,19 @@ fn analyzeCall( |
| 7077 | 7078 | const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies; |
| 7078 | 7079 | const parent_generic_owner = sema.generic_owner; |
| 7079 | 7080 | const parent_generic_call_src = sema.generic_call_src; |
| 7081 | const parent_generic_bound_arg_src = sema.generic_bound_arg_src; | |
| 7080 | 7082 | const parent_generic_call_decl = sema.generic_call_decl; |
| 7081 | 7083 | sema.fn_ret_ty = bare_return_type; |
| 7082 | 7084 | sema.fn_ret_ty_ies = null; |
| 7083 | 7085 | sema.generic_owner = .none; |
| 7084 | 7086 | sema.generic_call_src = .unneeded; |
| 7087 | sema.generic_bound_arg_src = null; | |
| 7085 | 7088 | sema.generic_call_decl = .none; |
| 7086 | 7089 | defer sema.fn_ret_ty = parent_fn_ret_ty; |
| 7087 | 7090 | defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies; |
| 7088 | 7091 | defer sema.generic_owner = parent_generic_owner; |
| 7089 | 7092 | defer sema.generic_call_src = parent_generic_call_src; |
| 7093 | defer sema.generic_bound_arg_src = parent_generic_bound_arg_src; | |
| 7090 | 7094 | defer sema.generic_call_decl = parent_generic_call_decl; |
| 7091 | 7095 | |
| 7092 | 7096 | if (module_fn.analysis(ip).inferred_error_set) { |
| ... | ... | @@ -7545,6 +7549,7 @@ fn instantiateGenericCall( |
| 7545 | 7549 | .comptime_args = comptime_args, |
| 7546 | 7550 | .generic_owner = generic_owner, |
| 7547 | 7551 | .generic_call_src = call_src, |
| 7552 | .generic_bound_arg_src = bound_arg_src, | |
| 7548 | 7553 | .generic_call_decl = block.src_decl.toOptional(), |
| 7549 | 7554 | .branch_quota = sema.branch_quota, |
| 7550 | 7555 | .branch_count = sema.branch_count, |
| ... | ... | @@ -8583,17 +8588,20 @@ fn resolveGenericBody( |
| 8583 | 8588 | const prev_no_partial_func_type = sema.no_partial_func_ty; |
| 8584 | 8589 | const prev_generic_owner = sema.generic_owner; |
| 8585 | 8590 | const prev_generic_call_src = sema.generic_call_src; |
| 8591 | const prev_generic_bound_arg_src = sema.generic_bound_arg_src; | |
| 8586 | 8592 | const prev_generic_call_decl = sema.generic_call_decl; |
| 8587 | 8593 | block.params = .{}; |
| 8588 | 8594 | sema.no_partial_func_ty = true; |
| 8589 | 8595 | sema.generic_owner = .none; |
| 8590 | 8596 | sema.generic_call_src = .unneeded; |
| 8597 | sema.generic_bound_arg_src = null; | |
| 8591 | 8598 | sema.generic_call_decl = .none; |
| 8592 | 8599 | defer { |
| 8593 | 8600 | block.params = prev_params; |
| 8594 | 8601 | sema.no_partial_func_ty = prev_no_partial_func_type; |
| 8595 | 8602 | sema.generic_owner = prev_generic_owner; |
| 8596 | 8603 | sema.generic_call_src = prev_generic_call_src; |
| 8604 | sema.generic_bound_arg_src = prev_generic_bound_arg_src; | |
| 8597 | 8605 | sema.generic_call_decl = prev_generic_call_decl; |
| 8598 | 8606 | } |
| 8599 | 8607 | |
| ... | ... | @@ -9211,6 +9219,21 @@ fn finishFunc( |
| 9211 | 9219 | return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty); |
| 9212 | 9220 | } |
| 9213 | 9221 | |
| 9222 | fn 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 | ||
| 9214 | 9237 | fn zirParam( |
| 9215 | 9238 | sema: *Sema, |
| 9216 | 9239 | block: *Block, |
| ... | ... | @@ -9218,7 +9241,6 @@ fn zirParam( |
| 9218 | 9241 | param_index: u32, |
| 9219 | 9242 | comptime_syntax: bool, |
| 9220 | 9243 | ) CompileError!void { |
| 9221 | const mod = sema.mod; | |
| 9222 | 9244 | const gpa = sema.gpa; |
| 9223 | 9245 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; |
| 9224 | 9246 | const src = inst_data.src(); |
| ... | ... | @@ -9235,17 +9257,20 @@ fn zirParam( |
| 9235 | 9257 | const prev_no_partial_func_type = sema.no_partial_func_ty; |
| 9236 | 9258 | const prev_generic_owner = sema.generic_owner; |
| 9237 | 9259 | const prev_generic_call_src = sema.generic_call_src; |
| 9260 | const prev_generic_bound_arg_src = sema.generic_bound_arg_src; | |
| 9238 | 9261 | const prev_generic_call_decl = sema.generic_call_decl; |
| 9239 | 9262 | block.params = .{}; |
| 9240 | 9263 | sema.no_partial_func_ty = true; |
| 9241 | 9264 | sema.generic_owner = .none; |
| 9242 | 9265 | sema.generic_call_src = .unneeded; |
| 9266 | sema.generic_bound_arg_src = null; | |
| 9243 | 9267 | sema.generic_call_decl = .none; |
| 9244 | 9268 | defer { |
| 9245 | 9269 | block.params = prev_params; |
| 9246 | 9270 | sema.no_partial_func_ty = prev_no_partial_func_type; |
| 9247 | 9271 | sema.generic_owner = prev_generic_owner; |
| 9248 | 9272 | sema.generic_call_src = prev_generic_call_src; |
| 9273 | sema.generic_bound_arg_src = prev_generic_bound_arg_src; | |
| 9249 | 9274 | sema.generic_call_decl = prev_generic_call_decl; |
| 9250 | 9275 | } |
| 9251 | 9276 | |
| ... | ... | @@ -9319,13 +9344,8 @@ fn zirParam( |
| 9319 | 9344 | sema.comptime_args[param_index] = val.toIntern(); |
| 9320 | 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 | 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 | 9349 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ |
| 9330 | 9350 | @as([]const u8, "runtime-known argument passed to comptime parameter"), |
| 9331 | 9351 | }); |
| ... | ... | @@ -9371,7 +9391,6 @@ fn zirParamAnytype( |
| 9371 | 9391 | param_index: u32, |
| 9372 | 9392 | comptime_syntax: bool, |
| 9373 | 9393 | ) CompileError!void { |
| 9374 | const mod = sema.mod; | |
| 9375 | 9394 | const gpa = sema.gpa; |
| 9376 | 9395 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; |
| 9377 | 9396 | const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start); |
| ... | ... | @@ -9385,11 +9404,6 @@ fn zirParamAnytype( |
| 9385 | 9404 | sema.comptime_args[param_index] = opv.toIntern(); |
| 9386 | 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; | |
| 9393 | 9407 | |
| 9394 | 9408 | if (comptime_syntax) { |
| 9395 | 9409 | if (try sema.resolveMaybeUndefVal(air_ref)) |val| { |
| ... | ... | @@ -9397,7 +9411,7 @@ fn zirParamAnytype( |
| 9397 | 9411 | return; |
| 9398 | 9412 | } |
| 9399 | 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 | 9415 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ |
| 9402 | 9416 | @as([]const u8, "runtime-known argument passed to comptime parameter"), |
| 9403 | 9417 | }); |
| ... | ... | @@ -9417,7 +9431,7 @@ fn zirParamAnytype( |
| 9417 | 9431 | return; |
| 9418 | 9432 | } |
| 9419 | 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 | 9435 | const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{ |
| 9422 | 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 @@ |
| 1 | export fn builtinCallBoolFunctionInlineWithVoid() void { | |
| 2 | @call(.always_inline, boolFunction, .{{}}); | |
| 3 | } | |
| 4 | ||
| 5 | fn 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 @@ |
| 1 | export fn callBoolMethod() void { | |
| 2 | const s = S{}; | |
| 3 | s.boolMethod({}); | |
| 4 | } | |
| 5 | ||
| 6 | export fn callVoidMethod() void { | |
| 7 | const s = S{}; | |
| 8 | s.voidMethod(false); | |
| 9 | } | |
| 10 | ||
| 11 | const 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 @@ |
| 1 | export fn callBoolMethodWithVoid() void { | |
| 2 | const s = S{}; | |
| 3 | s.boolMethod({}); | |
| 4 | } | |
| 5 | ||
| 6 | export fn callVoidMethodWithBool() void { | |
| 7 | const s = S{}; | |
| 8 | s.voidMethod(false); | |
| 9 | } | |
| 10 | ||
| 11 | export fn callComptimeBoolMethodWithRuntimeBool() void { | |
| 12 | const s = S{}; | |
| 13 | var arg = true; | |
| 14 | s.comptimeBoolMethod(arg); | |
| 15 | } | |
| 16 | ||
| 17 | const 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 | 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 | } |