From 9a0f0b20668724e93025cf58f5061eef4f58409c Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Fri, 19 Jan 2024 00:35:45 -0800 Subject: [PATCH] do not enforce function parameters to be marked comptime if only called at comptime --- lib/std/comptime_string_map.zig | 19 ++++++++++++ src/Sema.zig | 4 +-- test/behavior/fn.zig | 9 ++++++ ...omptime_parameter_not_declared_as_such.zig | 25 ---------------- ...on_comptime_param_in_comptime_function.zig | 30 ++++--------------- 5 files changed, 36 insertions(+), 51 deletions(-) delete mode 100644 test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig diff --git a/lib/std/comptime_string_map.zig b/lib/std/comptime_string_map.zig index f4da1490b7ad..6a81bb7f3ca2 100644 --- a/lib/std/comptime_string_map.zig +++ b/lib/std/comptime_string_map.zig @@ -299,3 +299,22 @@ test "ComptimeStringMap redundant insensitive" { try std.testing.expectEqual(TestEnum.A, map.get("theNeedle").?); } + +test "ComptimeStringMap comptime-only value" { + const map = std.ComptimeStringMap(type, .{ + .{ "a", struct { + pub const foo = 1; + } }, + .{ "b", struct { + pub const foo = 2; + } }, + .{ "c", struct { + pub const foo = 3; + } }, + }); + + try std.testing.expect(map.get("a").?.foo == 1); + try std.testing.expect(map.get("b").?.foo == 2); + try std.testing.expect(map.get("c").?.foo == 3); + try std.testing.expect(map.get("d") == null); +} diff --git a/src/Sema.zig b/src/Sema.zig index dfb71e08b105..6adfde673432 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9302,7 +9302,7 @@ fn funcCommon( }; return sema.failWithOwnedErrorMsg(block, msg); } - if (is_source_decl and requires_comptime and !param_is_comptime and has_body) { + if (is_source_decl and requires_comptime and !param_is_comptime and has_body and !block.is_comptime) { const msg = msg: { const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{ param_ty.fmt(mod), @@ -9597,7 +9597,7 @@ fn finishFunc( // If the return type is comptime-only but not dependent on parameters then // all parameter types also need to be comptime. - if (is_source_decl and opt_func_index != .none and ret_ty_requires_comptime) comptime_check: { + if (is_source_decl and opt_func_index != .none and ret_ty_requires_comptime and !block.is_comptime) comptime_check: { for (block.params.items(.is_comptime)) |is_comptime| { if (!is_comptime) break; } else break :comptime_check; diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index 2f0d9fbe72a9..d575c99992ed 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -596,3 +596,12 @@ test "pointer to alias behaves same as pointer to function" { _ = &a; try std.testing.expect(S.foo() == a()); } + +test "comptime parameters don't have to be marked comptime if only called at comptime" { + const S = struct { + fn foo(x: comptime_int, y: comptime_int) u32 { + return x + y; + } + }; + comptime std.debug.assert(S.foo(5, 6) == 11); +} diff --git a/test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig b/test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig deleted file mode 100644 index 33d273ab3f2b..000000000000 --- a/test/cases/compile_errors/comptime_parameter_not_declared_as_such.zig +++ /dev/null @@ -1,25 +0,0 @@ -fn f(_: anytype) void {} -const T = *const fn (anytype) void; -fn g(h: T) void { - h({}); -} -pub export fn entry() void { - g(f); -} - -pub fn comptimeMod(num: anytype, denom: comptime_int) void { - _ = num; - _ = denom; -} - -pub export fn entry1() void { - _ = comptimeMod(1, 2); -} - -// error -// backend=stage2 -// target=native -// -// :3:6: error: parameter of type '*const fn (anytype) void' must be declared comptime -// :3:6: note: function is generic -// :10:34: error: parameter of type 'comptime_int' must be declared comptime diff --git a/test/cases/compile_errors/non_comptime_param_in_comptime_function.zig b/test/cases/compile_errors/non_comptime_param_in_comptime_function.zig index 8449afa1b654..a902ffe9399a 100644 --- a/test/cases/compile_errors/non_comptime_param_in_comptime_function.zig +++ b/test/cases/compile_errors/non_comptime_param_in_comptime_function.zig @@ -3,34 +3,16 @@ fn F(val: anytype) type { return struct {}; } export fn entry() void { - _ = F(void{}); -} -const S = struct { - foo: fn () void, -}; -fn bar(_: u32) S { - return undefined; -} -export fn entry1() void { - _ = bar(); -} -// prioritize other return type errors -fn foo(a: u32) callconv(.C) comptime_int { - return a; -} -export fn entry2() void { - _ = foo(1); + var x: u32 = 0; + _ = &x; + _ = F(x); } // error // backend=stage2 // target=native // -// :1:20: error: function with comptime-only return type 'type' requires all parameters to be comptime +// :8:11: error: unable to resolve comptime value +// :8:11: note: argument to function being called at comptime must be comptime-known +// :1:20: note: expression is evaluated at comptime because the function returns a comptime-only type 'type' // :1:20: note: types are not available at runtime -// :1:6: note: param 'val' is required to be comptime -// :11:16: error: function with comptime-only return type 'tmp.S' requires all parameters to be comptime -// :9:10: note: struct requires comptime because of this field -// :9:10: note: use '*const fn () void' for a function pointer type -// :11:8: note: param is required to be comptime -// :18:29: error: return type 'comptime_int' not allowed in function with calling convention 'C'