authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-01-19 00:35:45-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-19 15:31:18-08:00
log46d592e485cf8ee4d85854040acd1b05271591b5
tree3c6de775a40405360f3ca216e2e4c205851404c4
parentd7b6d637df5b94ec07cf017fa742e8c34a4b9433

do not enforce function parameters to be marked comptime if only called at comptime


5 files changed, 36 insertions(+), 51 deletions(-)

lib/std/comptime_string_map.zig+19
...@@ -299,3 +299,22 @@ test "ComptimeStringMap redundant insensitive" {...@@ -299,3 +299,22 @@ test "ComptimeStringMap redundant insensitive" {
299299
300 try std.testing.expectEqual(TestEnum.A, map.get("theNeedle").?);300 try std.testing.expectEqual(TestEnum.A, map.get("theNeedle").?);
301}301}
302
303test "ComptimeStringMap comptime-only value" {
304 const map = std.ComptimeStringMap(type, .{
305 .{ "a", struct {
306 pub const foo = 1;
307 } },
308 .{ "b", struct {
309 pub const foo = 2;
310 } },
311 .{ "c", struct {
312 pub const foo = 3;
313 } },
314 });
315
316 try std.testing.expect(map.get("a").?.foo == 1);
317 try std.testing.expect(map.get("b").?.foo == 2);
318 try std.testing.expect(map.get("c").?.foo == 3);
319 try std.testing.expect(map.get("d") == null);
320}
src/Sema.zig+2-2
...@@ -9302,7 +9302,7 @@ fn funcCommon(...@@ -9302,7 +9302,7 @@ fn funcCommon(
9302 };9302 };
9303 return sema.failWithOwnedErrorMsg(block, msg);9303 return sema.failWithOwnedErrorMsg(block, msg);
9304 }9304 }
9305 if (is_source_decl and requires_comptime and !param_is_comptime and has_body) {9305 if (is_source_decl and requires_comptime and !param_is_comptime and has_body and !block.is_comptime) {
9306 const msg = msg: {9306 const msg = msg: {
9307 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{9307 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{
9308 param_ty.fmt(mod),9308 param_ty.fmt(mod),
...@@ -9597,7 +9597,7 @@ fn finishFunc(...@@ -9597,7 +9597,7 @@ fn finishFunc(
95979597
9598 // If the return type is comptime-only but not dependent on parameters then9598 // If the return type is comptime-only but not dependent on parameters then
9599 // all parameter types also need to be comptime.9599 // all parameter types also need to be comptime.
9600 if (is_source_decl and opt_func_index != .none and ret_ty_requires_comptime) comptime_check: {9600 if (is_source_decl and opt_func_index != .none and ret_ty_requires_comptime and !block.is_comptime) comptime_check: {
9601 for (block.params.items(.is_comptime)) |is_comptime| {9601 for (block.params.items(.is_comptime)) |is_comptime| {
9602 if (!is_comptime) break;9602 if (!is_comptime) break;
9603 } else break :comptime_check;9603 } else break :comptime_check;
test/behavior/fn.zig+9
...@@ -596,3 +596,12 @@ test "pointer to alias behaves same as pointer to function" {...@@ -596,3 +596,12 @@ test "pointer to alias behaves same as pointer to function" {
596 _ = &a;596 _ = &a;
597 try std.testing.expect(S.foo() == a());597 try std.testing.expect(S.foo() == a());
598}598}
599
600test "comptime parameters don't have to be marked comptime if only called at comptime" {
601 const S = struct {
602 fn foo(x: comptime_int, y: comptime_int) u32 {
603 return x + y;
604 }
605 };
606 comptime std.debug.assert(S.foo(5, 6) == 11);
607}
test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig deleted-25
...@@ -1,25 +0,0 @@
1fn f(_: anytype) void {}
2const T = *const fn (anytype) void;
3fn g(h: T) void {
4 h({});
5}
6pub export fn entry() void {
7 g(f);
8}
9
10pub fn comptimeMod(num: anytype, denom: comptime_int) void {
11 _ = num;
12 _ = denom;
13}
14
15pub export fn entry1() void {
16 _ = comptimeMod(1, 2);
17}
18
19// error
20// backend=stage2
21// target=native
22//
23// :3:6: error: parameter of type '*const fn (anytype) void' must be declared comptime
24// :3:6: note: function is generic
25// :10:34: error: parameter of type 'comptime_int' must be declared comptime
test/cases/compile_errors/non_comptime_param_in_comptime_function.zig+6-24
...@@ -3,34 +3,16 @@ fn F(val: anytype) type {...@@ -3,34 +3,16 @@ fn F(val: anytype) type {
3 return struct {};3 return struct {};
4}4}
5export fn entry() void {5export fn entry() void {
6 _ = F(void{});6 var x: u32 = 0;
7}7 _ = &x;
8const S = struct {8 _ = F(x);
9 foo: fn () void,
10};
11fn bar(_: u32) S {
12 return undefined;
13}
14export fn entry1() void {
15 _ = bar();
16}
17// prioritize other return type errors
18fn foo(a: u32) callconv(.C) comptime_int {
19 return a;
20}
21export fn entry2() void {
22 _ = foo(1);
23}9}
2410
25// error11// error
26// backend=stage212// backend=stage2
27// target=native13// target=native
28//14//
29// :1:20: error: function with comptime-only return type 'type' requires all parameters to be comptime15// :8:11: error: unable to resolve comptime value
16// :8:11: note: argument to function being called at comptime must be comptime-known
17// :1:20: note: expression is evaluated at comptime because the function returns a comptime-only type 'type'
30// :1:20: note: types are not available at runtime18// :1:20: note: types are not available at runtime
31// :1:6: note: param 'val' is required to be comptime
32// :11:16: error: function with comptime-only return type 'tmp.S' requires all parameters to be comptime
33// :9:10: note: struct requires comptime because of this field
34// :9:10: note: use '*const fn () void' for a function pointer type
35// :11:8: note: param is required to be comptime
36// :18:29: error: return type 'comptime_int' not allowed in function with calling convention 'C'