aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorantlilja <liljaanton2001@gmail.com>2022-08-06 22:32:00 +0200
committerVeikka Tuominen <git@vexu.eu>2022-08-27 11:17:48 +0300
commitae8d26a6a00a528bdf555689c2a93cb35a3287f2 (patch)
treed72b651523e62b81d0b1733cf2f1a4eced7265db /src
parentda95da438ed5c934a9f42811651f5ffa524e48a8 (diff)
downloadzig-ae8d26a6a00a528bdf555689c2a93cb35a3287f2.tar.gz
zig-ae8d26a6a00a528bdf555689c2a93cb35a3287f2.zip
Sema: add error for non-comptime param in comptime func
Adds error for taking a non comptime parameter in a function returning a comptime-only type but not when that type is dependent on a parameter. Co-authored-by: Veikka Tuominen <git@vexu.eu>
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig61
1 files changed, 47 insertions, 14 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 2907999c25..047d3f84c2 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -7816,19 +7816,17 @@ fn funcCommon(
};
}
- var is_comptime_ret = false;
- const ret_poison = if (!is_generic) rp: {
- if (sema.typeRequiresComptime(block, ret_ty_src, bare_return_type)) |ret_comptime| {
- is_comptime_ret = ret_comptime;
- break :rp bare_return_type.tag() == .generic_poison;
- } else |err| switch (err) {
- error.GenericPoison => {
- is_generic = true;
- break :rp true;
- },
- else => |e| return e,
- }
- } else bare_return_type.tag() == .generic_poison;
+ var ret_ty_requires_comptime = false;
+ const ret_poison = if (sema.typeRequiresComptime(block, ret_ty_src, bare_return_type)) |ret_comptime| rp: {
+ ret_ty_requires_comptime = ret_comptime;
+ break :rp bare_return_type.tag() == .generic_poison;
+ } else |err| switch (err) {
+ error.GenericPoison => rp: {
+ is_generic = true;
+ break :rp true;
+ },
+ else => |e| return e,
+ };
const return_type = if (!inferred_error_set or ret_poison)
bare_return_type
@@ -7873,6 +7871,41 @@ fn funcCommon(
return sema.failWithOwnedErrorMsg(msg);
}
+ // If the return type is comptime only but not dependent on parameters then all parameter types also need to be comptime
+ if (!sema.is_generic_instantiation and has_body and ret_ty_requires_comptime) comptime_check: {
+ for (block.params.items) |param| {
+ if (!param.is_comptime) break;
+ } else break :comptime_check;
+
+ const msg = try sema.errMsg(
+ block,
+ ret_ty_src,
+ "function with comptime only return type '{}' requires all parameters to be comptime",
+ .{return_type.fmt(sema.mod)},
+ );
+ try sema.explainWhyTypeIsComptime(block, ret_ty_src, msg, ret_ty_src.toSrcLoc(sema.owner_decl), return_type);
+
+ const tags = sema.code.instructions.items(.tag);
+ const data = sema.code.instructions.items(.data);
+ const param_body = sema.code.getParamBody(func_inst);
+ for (block.params.items) |param, i| {
+ if (!param.is_comptime) {
+ const param_index = param_body[i];
+ const param_src = switch (tags[param_index]) {
+ .param => data[param_index].pl_tok.src(),
+ .param_anytype => data[param_index].str_tok.src(),
+ else => unreachable,
+ };
+ if (param.name.len != 0) {
+ try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{param.name});
+ } else {
+ try sema.errNote(block, param_src, msg, "param is required to be comptime", .{});
+ }
+ }
+ }
+ return sema.failWithOwnedErrorMsg(msg);
+ }
+
const arch = sema.mod.getTarget().cpu.arch;
if (switch (cc_workaround) {
.Unspecified, .C, .Naked, .Async, .Inline => null,
@@ -7917,7 +7950,7 @@ fn funcCommon(
}
if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
for (comptime_params) |ct| is_generic = is_generic or ct;
- is_generic = is_generic or is_comptime_ret;
+ is_generic = is_generic or ret_ty_requires_comptime;
break :fn_ty try Type.Tag.function.create(sema.arena, .{
.param_types = param_types,