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 = &.{},...@@ -63,6 +63,13 @@ comptime_args: []InternPool.Index = &.{},
63/// Used to communicate from a generic function instantiation to the logic that63/// Used to communicate from a generic function instantiation to the logic that
64/// creates a generic function instantiation value in `funcCommon`.64/// creates a generic function instantiation value in `funcCommon`.
65generic_owner: InternPool.Index = .none,65generic_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,
66/// The key is types that must be fully resolved prior to machine code73/// The key is types that must be fully resolved prior to machine code
67/// generation pass. Types are added to this set when resolving them74/// generation pass. Types are added to this set when resolving them
68/// immediately could cause a dependency loop, but they do need to be resolved75/// immediately could cause a dependency loop, but they do need to be resolved
...@@ -2055,10 +2062,7 @@ fn resolveDefinedValue(...@@ -2055,10 +2062,7 @@ fn resolveDefinedValue(
2055/// Value Tag `variable` causes this function to return `null`.2062/// Value Tag `variable` causes this function to return `null`.
2056/// Value Tag `undef` causes this function to return the Value.2063/// Value Tag `undef` causes this function to return the Value.
2057/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.2064/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2058fn resolveMaybeUndefVal(2065fn resolveMaybeUndefVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2059 sema: *Sema,
2060 inst: Air.Inst.Ref,
2061) CompileError!?Value {
2062 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;2066 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
2063 if (val.isGenericPoison()) return error.GenericPoison;2067 if (val.isGenericPoison()) return error.GenericPoison;
2064 if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null;2068 if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null;
...@@ -2069,10 +2073,7 @@ fn resolveMaybeUndefVal(...@@ -2069,10 +2073,7 @@ fn resolveMaybeUndefVal(
2069/// Value Tag `undef` causes this function to return the Value.2073/// Value Tag `undef` causes this function to return the Value.
2070/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.2074/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2071/// Lazy values are recursively resolved.2075/// Lazy values are recursively resolved.
2072fn resolveMaybeUndefLazyVal(2076fn resolveMaybeUndefLazyVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2073 sema: *Sema,
2074 inst: Air.Inst.Ref,
2075) CompileError!?Value {
2076 return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null);2077 return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null);
2077}2078}
20782079
...@@ -2081,10 +2082,7 @@ fn resolveMaybeUndefLazyVal(...@@ -2081,10 +2082,7 @@ fn resolveMaybeUndefLazyVal(
2081/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.2082/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2082/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.2083/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.
2083/// Lazy values are recursively resolved.2084/// Lazy values are recursively resolved.
2084fn resolveMaybeUndefValIntable(2085fn resolveMaybeUndefValIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2085 sema: *Sema,
2086 inst: Air.Inst.Ref,
2087) CompileError!?Value {
2088 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;2086 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
2089 if (val.isGenericPoison()) return error.GenericPoison;2087 if (val.isGenericPoison()) return error.GenericPoison;
2090 if (val.ip_index == .none) return val;2088 if (val.ip_index == .none) return val;
...@@ -7047,12 +7045,18 @@ fn analyzeCall(...@@ -7047,12 +7045,18 @@ fn analyzeCall(
7047 const parent_fn_ret_ty = sema.fn_ret_ty;7045 const parent_fn_ret_ty = sema.fn_ret_ty;
7048 const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies;7046 const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies;
7049 const parent_generic_owner = sema.generic_owner;7047 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;
7050 sema.fn_ret_ty = bare_return_type;7050 sema.fn_ret_ty = bare_return_type;
7051 sema.fn_ret_ty_ies = null;7051 sema.fn_ret_ty_ies = null;
7052 sema.generic_owner = .none;7052 sema.generic_owner = .none;
7053 sema.generic_call_src = .unneeded;
7054 sema.generic_call_decl = .none;
7053 defer sema.fn_ret_ty = parent_fn_ret_ty;7055 defer sema.fn_ret_ty = parent_fn_ret_ty;
7054 defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies;7056 defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies;
7055 defer sema.generic_owner = parent_generic_owner;7057 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
7057 if (module_fn.analysis(ip).inferred_error_set) {7061 if (module_fn.analysis(ip).inferred_error_set) {
7058 // Create a fresh inferred error set type for inline/comptime calls.7062 // Create a fresh inferred error set type for inline/comptime calls.
...@@ -7506,6 +7510,8 @@ fn instantiateGenericCall(...@@ -7506,6 +7510,8 @@ fn instantiateGenericCall(
7506 .owner_func_index = .none,7510 .owner_func_index = .none,
7507 .comptime_args = comptime_args,7511 .comptime_args = comptime_args,
7508 .generic_owner = generic_owner,7512 .generic_owner = generic_owner,
7513 .generic_call_src = call_src,
7514 .generic_call_decl = block.src_decl.toOptional(),
7509 .branch_quota = sema.branch_quota,7515 .branch_quota = sema.branch_quota,
7510 .branch_count = sema.branch_count,7516 .branch_count = sema.branch_count,
7511 .comptime_mutable_decls = sema.comptime_mutable_decls,7517 .comptime_mutable_decls = sema.comptime_mutable_decls,
...@@ -9167,13 +9173,19 @@ fn zirParam(...@@ -9167,13 +9173,19 @@ fn zirParam(
9167 const prev_params = block.params;9173 const prev_params = block.params;
9168 const prev_no_partial_func_type = sema.no_partial_func_ty;9174 const prev_no_partial_func_type = sema.no_partial_func_ty;
9169 const prev_generic_owner = sema.generic_owner;9175 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;
9170 block.params = .{};9178 block.params = .{};
9171 sema.no_partial_func_ty = true;9179 sema.no_partial_func_ty = true;
9172 sema.generic_owner = .none;9180 sema.generic_owner = .none;
9181 sema.generic_call_src = .unneeded;
9182 sema.generic_call_decl = .none;
9173 defer {9183 defer {
9174 block.params = prev_params;9184 block.params = prev_params;
9175 sema.no_partial_func_ty = prev_no_partial_func_type;9185 sema.no_partial_func_ty = prev_no_partial_func_type;
9176 sema.generic_owner = prev_generic_owner;9186 sema.generic_owner = prev_generic_owner;
9187 sema.generic_call_src = prev_generic_call_src;
9188 sema.generic_call_decl = prev_generic_call_decl;
9177 }9189 }
91789190
9179 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {9191 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
...@@ -9289,6 +9301,8 @@ fn zirParamAnytype(...@@ -9289,6 +9301,8 @@ fn zirParamAnytype(
9289 param_index: u32,9301 param_index: u32,
9290 comptime_syntax: bool,9302 comptime_syntax: bool,
9291) CompileError!void {9303) CompileError!void {
9304 const mod = sema.mod;
9305 const gpa = sema.gpa;
9292 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;9306 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
9293 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);9307 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);
9294 const src = inst_data.src();9308 const src = inst_data.src();
...@@ -9301,13 +9315,68 @@ fn zirParamAnytype(...@@ -9301,13 +9315,68 @@ fn zirParamAnytype(
9301 sema.comptime_args[param_index] = opv.toIntern();9315 sema.comptime_args[param_index] = opv.toIntern();
9302 return;9316 return;
9303 }9317 }
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
9304 if (comptime_syntax) {9323 if (comptime_syntax) {
9305 sema.comptime_args[param_index] = (try sema.resolveConstMaybeUndefVal(block, src, air_ref, "parameter is declared comptime")).toIntern();9324 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
9306 return;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);
9307 }9349 }
9350
9308 if (try sema.typeRequiresComptime(param_ty)) {9351 if (try sema.typeRequiresComptime(param_ty)) {
9309 sema.comptime_args[param_index] = (try sema.resolveConstMaybeUndefVal(block, src, air_ref, "parameter type requires comptime")).toIntern();9352 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
9310 return;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);
9311 }9380 }
93129381
9313 // The parameter is runtime-known.9382 // 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 {...@@ -16,5 +16,7 @@ pub export fn entry() void {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
19// :7:14: error: unable to resolve comptime value19// :7:14: error: runtime-known argument passed to comptime-only type parameter
20// :7:14: note: argument to parameter with comptime-only type must be comptime-known20// :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