| author | |
| committer | |
| log | 46d592e485cf8ee4d85854040acd1b05271591b5 |
| tree | 3c6de775a40405360f3ca216e2e4c205851404c4 |
| parent | d7b6d637df5b94ec07cf017fa742e8c34a4b9433 |
5 files changed, 36 insertions(+), 51 deletions(-)
lib/std/comptime_string_map.zig+19| ... | ... | @@ -299,3 +299,22 @@ test "ComptimeStringMap redundant insensitive" { |
| 299 | 299 | |
| 300 | 300 | try std.testing.expectEqual(TestEnum.A, map.get("theNeedle").?); |
| 301 | 301 | } |
| 302 | ||
| 303 | test "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 | 9302 | }; |
| 9303 | 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 | 9306 | const msg = msg: { |
| 9307 | 9307 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{ |
| 9308 | 9308 | param_ty.fmt(mod), |
| ... | ... | @@ -9597,7 +9597,7 @@ fn finishFunc( |
| 9597 | 9597 | |
| 9598 | 9598 | // If the return type is comptime-only but not dependent on parameters then |
| 9599 | 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 | 9601 | for (block.params.items(.is_comptime)) |is_comptime| { |
| 9602 | 9602 | if (!is_comptime) break; |
| 9603 | 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 | 596 | _ = &a; |
| 597 | 597 | try std.testing.expect(S.foo() == a()); |
| 598 | 598 | } |
| 599 | ||
| 600 | test "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 @@ |
| 1 | fn f(_: anytype) void {} | |
| 2 | const T = *const fn (anytype) void; | |
| 3 | fn g(h: T) void { | |
| 4 | h({}); | |
| 5 | } | |
| 6 | pub export fn entry() void { | |
| 7 | g(f); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn comptimeMod(num: anytype, denom: comptime_int) void { | |
| 11 | _ = num; | |
| 12 | _ = denom; | |
| 13 | } | |
| 14 | ||
| 15 | pub 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 | 3 | return struct {}; |
| 4 | 4 | } |
| 5 | 5 | export fn entry() void { |
| 6 | _ = F(void{}); | |
| 7 | } | |
| 8 | const S = struct { | |
| 9 | foo: fn () void, | |
| 10 | }; | |
| 11 | fn bar(_: u32) S { | |
| 12 | return undefined; | |
| 13 | } | |
| 14 | export fn entry1() void { | |
| 15 | _ = bar(); | |
| 16 | } | |
| 17 | // prioritize other return type errors | |
| 18 | fn foo(a: u32) callconv(.C) comptime_int { | |
| 19 | return a; | |
| 20 | } | |
| 21 | export fn entry2() void { | |
| 22 | _ = foo(1); | |
| 6 | var x: u32 = 0; | |
| 7 | _ = &x; | |
| 8 | _ = F(x); | |
| 23 | 9 | } |
| 24 | 10 | |
| 25 | 11 | // error |
| 26 | 12 | // backend=stage2 |
| 27 | 13 | // target=native |
| 28 | 14 | // |
| 29 | // :1:20: error: function with comptime-only return type 'type' requires all parameters to be comptime | |
| 15 | // :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 | 18 | // :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' |