authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-18 15:07:15-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-18 19:02:06-07:00
log47499bf47ba73ab49503298a87123b9e873e3693
tree096ebcfc06afe8f85612c9f70d866d276aeebeca
parentabe71b40c54c98badd4b18328ae22c8425add4b3

Sema: enhance generic call error message

when the type of an anytype parameter is a comptime-only type but the argument at the callsite is runtime-known.

2 files changed, 89 insertions(+), 18 deletions(-)

src/Sema.zig+85-16
......@@ -63,6 +63,13 @@ comptime_args: []InternPool.Index = &.{},
6363/// Used to communicate from a generic function instantiation to the logic that
6464/// creates a generic function instantiation value in `funcCommon`.
6565generic_owner: InternPool.Index = .none,
66/// When `generic_owner` is not none, this contains the generic function
67/// instantiation callsite so that compile errors on the parameter types of the
68/// instantiation can point back to the instantiation site in addition to the
69/// declaration site.
70generic_call_src: LazySrcLoc = .unneeded,
71/// Corresponds to `generic_call_src`.
72generic_call_decl: Decl.OptionalIndex = .none,
6673/// The key is types that must be fully resolved prior to machine code
6774/// generation pass. Types are added to this set when resolving them
6875/// immediately could cause a dependency loop, but they do need to be resolved
......@@ -2055,10 +2062,7 @@ fn resolveDefinedValue(
20552062/// Value Tag `variable` causes this function to return `null`.
20562063/// Value Tag `undef` causes this function to return the Value.
20572064/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2058fn resolveMaybeUndefVal(
2059 sema: *Sema,
2060 inst: Air.Inst.Ref,
2061) CompileError!?Value {
2065fn resolveMaybeUndefVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
20622066 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
20632067 if (val.isGenericPoison()) return error.GenericPoison;
20642068 if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null;
......@@ -2069,10 +2073,7 @@ fn resolveMaybeUndefVal(
20692073/// Value Tag `undef` causes this function to return the Value.
20702074/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
20712075/// Lazy values are recursively resolved.
2072fn resolveMaybeUndefLazyVal(
2073 sema: *Sema,
2074 inst: Air.Inst.Ref,
2075) CompileError!?Value {
2076fn resolveMaybeUndefLazyVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
20762077 return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null);
20772078}
20782079
......@@ -2081,10 +2082,7 @@ fn resolveMaybeUndefLazyVal(
20812082/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
20822083/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.
20832084/// Lazy values are recursively resolved.
2084fn resolveMaybeUndefValIntable(
2085 sema: *Sema,
2086 inst: Air.Inst.Ref,
2087) CompileError!?Value {
2085fn resolveMaybeUndefValIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
20882086 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
20892087 if (val.isGenericPoison()) return error.GenericPoison;
20902088 if (val.ip_index == .none) return val;
......@@ -7047,12 +7045,18 @@ fn analyzeCall(
70477045 const parent_fn_ret_ty = sema.fn_ret_ty;
70487046 const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies;
70497047 const parent_generic_owner = sema.generic_owner;
7048 const parent_generic_call_src = sema.generic_call_src;
7049 const parent_generic_call_decl = sema.generic_call_decl;
70507050 sema.fn_ret_ty = bare_return_type;
70517051 sema.fn_ret_ty_ies = null;
70527052 sema.generic_owner = .none;
7053 sema.generic_call_src = .unneeded;
7054 sema.generic_call_decl = .none;
70537055 defer sema.fn_ret_ty = parent_fn_ret_ty;
70547056 defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies;
70557057 defer sema.generic_owner = parent_generic_owner;
7058 defer sema.generic_call_src = parent_generic_call_src;
7059 defer sema.generic_call_decl = parent_generic_call_decl;
70567060
70577061 if (module_fn.analysis(ip).inferred_error_set) {
70587062 // Create a fresh inferred error set type for inline/comptime calls.
......@@ -7506,6 +7510,8 @@ fn instantiateGenericCall(
75067510 .owner_func_index = .none,
75077511 .comptime_args = comptime_args,
75087512 .generic_owner = generic_owner,
7513 .generic_call_src = call_src,
7514 .generic_call_decl = block.src_decl.toOptional(),
75097515 .branch_quota = sema.branch_quota,
75107516 .branch_count = sema.branch_count,
75117517 .comptime_mutable_decls = sema.comptime_mutable_decls,
......@@ -9167,13 +9173,19 @@ fn zirParam(
91679173 const prev_params = block.params;
91689174 const prev_no_partial_func_type = sema.no_partial_func_ty;
91699175 const prev_generic_owner = sema.generic_owner;
9176 const prev_generic_call_src = sema.generic_call_src;
9177 const prev_generic_call_decl = sema.generic_call_decl;
91709178 block.params = .{};
91719179 sema.no_partial_func_ty = true;
91729180 sema.generic_owner = .none;
9181 sema.generic_call_src = .unneeded;
9182 sema.generic_call_decl = .none;
91739183 defer {
91749184 block.params = prev_params;
91759185 sema.no_partial_func_ty = prev_no_partial_func_type;
91769186 sema.generic_owner = prev_generic_owner;
9187 sema.generic_call_src = prev_generic_call_src;
9188 sema.generic_call_decl = prev_generic_call_decl;
91779189 }
91789190
91799191 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
......@@ -9289,6 +9301,8 @@ fn zirParamAnytype(
92899301 param_index: u32,
92909302 comptime_syntax: bool,
92919303) CompileError!void {
9304 const mod = sema.mod;
9305 const gpa = sema.gpa;
92929306 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
92939307 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);
92949308 const src = inst_data.src();
......@@ -9301,13 +9315,68 @@ fn zirParamAnytype(
93019315 sema.comptime_args[param_index] = opv.toIntern();
93029316 return;
93039317 }
9318 const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{
9319 .call_node_offset = sema.generic_call_src.node_offset.x,
9320 .arg_index = param_index,
9321 } } else .unneeded;
9322
93049323 if (comptime_syntax) {
9305 sema.comptime_args[param_index] = (try sema.resolveConstMaybeUndefVal(block, src, air_ref, "parameter is declared comptime")).toIntern();
9306 return;
9324 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
9325 sema.comptime_args[param_index] = val.toIntern();
9326 return;
9327 }
9328 const msg = msg: {
9329 const fallback_src = src.toSrcLoc(mod.declPtr(block.src_decl), mod);
9330 const src_loc = if (sema.generic_call_decl.unwrap()) |decl|
9331 if (arg_src != .unneeded)
9332 arg_src.toSrcLoc(mod.declPtr(decl), mod)
9333 else
9334 fallback_src
9335 else
9336 fallback_src;
9337
9338 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9339 @as([]const u8, "runtime-known argument passed to comptime parameter"),
9340 });
9341 errdefer msg.destroy(gpa);
9342
9343 if (sema.generic_call_decl != .none) {
9344 try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared here")});
9345 }
9346 break :msg msg;
9347 };
9348 return sema.failWithOwnedErrorMsg(msg);
93079349 }
9350
93089351 if (try sema.typeRequiresComptime(param_ty)) {
9309 sema.comptime_args[param_index] = (try sema.resolveConstMaybeUndefVal(block, src, air_ref, "parameter type requires comptime")).toIntern();
9310 return;
9352 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
9353 sema.comptime_args[param_index] = val.toIntern();
9354 return;
9355 }
9356 const msg = msg: {
9357 const fallback_src = src.toSrcLoc(mod.declPtr(block.src_decl), mod);
9358 const src_loc = if (sema.generic_call_decl.unwrap()) |decl|
9359 if (arg_src != .unneeded)
9360 arg_src.toSrcLoc(mod.declPtr(decl), mod)
9361 else
9362 fallback_src
9363 else
9364 fallback_src;
9365
9366 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9367 @as([]const u8, "runtime-known argument passed to comptime-only type parameter"),
9368 });
9369 errdefer msg.destroy(gpa);
9370
9371 if (sema.generic_call_decl != .none) {
9372 try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared here")});
9373 }
9374
9375 try sema.explainWhyTypeIsComptime(msg, src_loc, param_ty);
9376
9377 break :msg msg;
9378 };
9379 return sema.failWithOwnedErrorMsg(msg);
93119380 }
93129381
93139382 // The parameter is runtime-known.
test/cases/compile_errors/anytype_param_requires_comptime.zig+4-2
......@@ -16,5 +16,7 @@ pub export fn entry() void {
1616// backend=stage2
1717// target=native
1818//
19// :7:14: error: unable to resolve comptime value
20// :7:14: note: argument to parameter with comptime-only type must be comptime-known
19// :7:14: error: runtime-known argument passed to comptime-only type parameter
20// :9:12: note: declared here
21// :4:16: note: struct requires comptime because of this field
22// :4:16: note: types are not available at runtime