diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-01-05 05:27:48 +0000 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2025-01-09 06:46:47 +0000 |
| commit | e9bd2d45d4bbaf7eff7e95bc3ef7a0123b66a103 (patch) | |
| tree | da18bc40935c7dd9698d792eae3d102fa0ad67ae /test/cases/compile_errors | |
| parent | 3f95003d4c57650f9b4779f55c8d7368b137337c (diff) | |
| download | zig-e9bd2d45d4bbaf7eff7e95bc3ef7a0123b66a103.tar.gz zig-e9bd2d45d4bbaf7eff7e95bc3ef7a0123b66a103.zip | |
Sema: rewrite semantic analysis of function calls
This rewrite improves some error messages, hugely simplifies the logic,
and fixes several bugs. One of these bugs is technically a new rule
which Andrew and I agreed on: if a parameter has a comptime-only type
but is not declared `comptime`, then the corresponding call argument
should not be *evaluated* at comptime; only resolved. Implementing this
required changing how function types work a little, which in turn
required allowing a new kind of function coercion for some generic use
cases: function coercions are now allowed to implicitly *remove*
`comptime` annotations from parameters with comptime-only types. This is
okay because removing the annotation affects only the call site.
Resolves: #22262
Diffstat (limited to 'test/cases/compile_errors')
21 files changed, 77 insertions, 92 deletions
diff --git a/test/cases/compile_errors/arg_to_non_comptime_param_with_comptime_only_type_is_not_evaluated_at_comptime.zig b/test/cases/compile_errors/arg_to_non_comptime_param_with_comptime_only_type_is_not_evaluated_at_comptime.zig new file mode 100644 index 0000000000..02a6464339 --- /dev/null +++ b/test/cases/compile_errors/arg_to_non_comptime_param_with_comptime_only_type_is_not_evaluated_at_comptime.zig @@ -0,0 +1,36 @@ +//! Whew, that filename is a bit of a mouthful! +//! To maximise consistency with other parts of the language, function arguments expressions are +//! only *evaluated* at comptime if the parameter is declared `comptime`. If the parameter type is +//! comptime-only, but the parameter is not declared `comptime`, the evaluation happens at runtime, +//! and the value is just comptime-resolved. + +export fn foo() void { + // This function is itself generic, with the comptime-only parameter being generic. + simpleGeneric(type, if (cond()) u8 else u16); +} + +export fn bar() void { + // This function is not generic; once `Wrapper` is called, its parameter type is immediately known. + Wrapper(type).inner(if (cond()) u8 else u16); +} + +fn simpleGeneric(comptime T: type, _: T) void {} + +fn Wrapper(comptime T: type) type { + return struct { + fn inner(_: T) void {} + }; +} + +fn cond() bool { + return true; +} + +// error +// +// :9:25: error: value with comptime-only type 'type' depends on runtime control flow +// :9:33: note: runtime control flow here +// :9:25: note: types are not available at runtime +// :14:25: error: value with comptime-only type 'type' depends on runtime control flow +// :14:33: note: runtime control flow here +// :14:25: note: types are not available at runtime diff --git a/test/cases/compile_errors/bad_usage_of_call.zig b/test/cases/compile_errors/bad_usage_of_call.zig index 3b7abe53f6..6eca5d7e3d 100644 --- a/test/cases/compile_errors/bad_usage_of_call.zig +++ b/test/cases/compile_errors/bad_usage_of_call.zig @@ -42,8 +42,8 @@ noinline fn dummy2() void {} // :2:23: error: expected a tuple, found 'void' // :5:21: error: unable to perform 'never_inline' call at compile-time // :8:21: error: unable to perform 'never_tail' call at compile-time -// :11:5: error: 'never_inline' call of inline function +// :11:5: error: cannot perform inline call with 'never_inline' modifier // :15:26: error: modifier 'compile_time' requires a comptime-known function -// :18:9: error: 'always_inline' call of noinline function -// :21:9: error: 'always_inline' call of noinline function +// :18:9: error: inline call of noinline function +// :21:9: error: inline call of noinline function // :26:27: error: modifier 'always_inline' requires a comptime-known function diff --git a/test/cases/compile_errors/comptime_call_of_function_pointer.zig b/test/cases/compile_errors/comptime_call_of_function_pointer.zig index 574f55e9f3..a73f541b5e 100644 --- a/test/cases/compile_errors/comptime_call_of_function_pointer.zig +++ b/test/cases/compile_errors/comptime_call_of_function_pointer.zig @@ -4,7 +4,6 @@ export fn entry() void { } // error -// backend=stage2 -// target=native // -// :3:20: error: comptime call of function pointer +// :3:14: error: unable to resolve comptime value +// :3:14: note: function being called at comptime must be comptime-known diff --git a/test/cases/compile_errors/condition_comptime_reason_explained.zig b/test/cases/compile_errors/condition_comptime_reason_explained.zig index d641b6176b..4cd12d039b 100644 --- a/test/cases/compile_errors/condition_comptime_reason_explained.zig +++ b/test/cases/compile_errors/condition_comptime_reason_explained.zig @@ -36,11 +36,13 @@ pub export fn entry2() void { // // :8:9: error: unable to resolve comptime value // :19:15: note: called at comptime from here -// :7:13: note: function with comptime-only return type 'tmp.S' is evaluated at comptime +// :19:15: note: call to function with comptime-only return type 'tmp.S' is evaluated at comptime +// :7:13: note: return type declared here // :2:12: note: struct requires comptime because of this field // :2:12: note: use '*const fn () void' for a function pointer type // :22:13: error: unable to resolve comptime value // :32:19: note: called at comptime from here -// :21:17: note: function with comptime-only return type 'tmp.S' is evaluated at comptime +// :32:19: note: call to function with comptime-only return type 'tmp.S' is evaluated at comptime +// :21:17: note: return type declared here // :2:12: note: struct requires comptime because of this field // :2:12: note: use '*const fn () void' for a function pointer type diff --git a/test/cases/compile_errors/dereference_anyopaque.zig b/test/cases/compile_errors/dereference_anyopaque.zig index c4e4649892..f4ce9efdd8 100644 --- a/test/cases/compile_errors/dereference_anyopaque.zig +++ b/test/cases/compile_errors/dereference_anyopaque.zig @@ -1,54 +1,7 @@ -const std = @import("std"); - -const Error = error{Something}; - -fn next() Error!void { - return; -} - -fn parse(comptime T: type, allocator: std.mem.Allocator) !void { - parseFree(T, undefined, allocator); - _ = (try next()) != null; -} - -fn parseFree(comptime T: type, value: T, allocator: std.mem.Allocator) void { - switch (@typeInfo(T)) { - .@"struct" => |structInfo| { - inline for (structInfo.fields) |field| { - if (!field.is_comptime) - parseFree(field.type, undefined, allocator); - } - }, - .pointer => |ptrInfo| { - switch (ptrInfo.size) { - .One => { - parseFree(ptrInfo.child, value.*, allocator); - }, - .Slice => { - for (value) |v| - parseFree(ptrInfo.child, v, allocator); - }, - else => unreachable, - } - }, - else => unreachable, - } -} - -pub export fn entry() void { - const allocator = std.testing.failing_allocator; - _ = parse(std.StringArrayHashMap(bool), allocator) catch return; +export fn foo(ptr: *anyopaque) void { + _ = ptr.*; } // error -// target=native -// backend=llvm // -// :11:22: error: comparison of 'void' with null -// :25:51: error: cannot load opaque type 'anyopaque' -// :25:51: error: values of type 'fn (*anyopaque, usize, u8, usize) ?[*]u8' must be comptime-known, but operand value is runtime-known -// :25:51: note: use '*const fn (*anyopaque, usize, u8, usize) ?[*]u8' for a function pointer type -// :25:51: error: values of type 'fn (*anyopaque, []u8, u8, usize, usize) bool' must be comptime-known, but operand value is runtime-known -// :25:51: note: use '*const fn (*anyopaque, []u8, u8, usize, usize) bool' for a function pointer type -// :25:51: error: values of type 'fn (*anyopaque, []u8, u8, usize) void' must be comptime-known, but operand value is runtime-known -// :25:51: note: use '*const fn (*anyopaque, []u8, u8, usize) void' for a function pointer type +// :2:12: error: cannot load opaque type 'anyopaque' diff --git a/test/cases/compile_errors/explain_why_fn_is_called_at_comptime.zig b/test/cases/compile_errors/explain_why_fn_is_called_at_comptime.zig index 7901808f3c..d1f6599f36 100644 --- a/test/cases/compile_errors/explain_why_fn_is_called_at_comptime.zig +++ b/test/cases/compile_errors/explain_why_fn_is_called_at_comptime.zig @@ -15,6 +15,7 @@ pub export fn entry() void { // error // // :12:13: error: unable to resolve comptime value -// :7:16: note: function with comptime-only return type 'tmp.S' is evaluated at comptime +// :12:12: note: call to function with comptime-only return type 'tmp.S' is evaluated at comptime +// :7:16: note: return type declared here // :2:12: note: struct requires comptime because of this field // :2:12: note: use '*const fn () void' for a function pointer type diff --git a/test/cases/compile_errors/explain_why_generic_fn_is_called_at_comptime.zig b/test/cases/compile_errors/explain_why_generic_fn_is_called_at_comptime.zig index cfec89d5a7..f57bd44f88 100644 --- a/test/cases/compile_errors/explain_why_generic_fn_is_called_at_comptime.zig +++ b/test/cases/compile_errors/explain_why_generic_fn_is_called_at_comptime.zig @@ -17,6 +17,7 @@ pub export fn entry() void { // error // // :15:13: error: unable to resolve comptime value -// :9:38: note: generic function instantiated with comptime-only return type 'tmp.S(fn () void)' is evaluated at comptime +// :15:12: note: call to generic function instantiated with comptime-only return type 'tmp.S(fn () void)' is evaluated at comptime +// :9:38: note: return type declared here // :3:16: note: struct requires comptime because of this field // :3:16: note: use '*const fn () void' for a function pointer type diff --git a/test/cases/compile_errors/generic_function_instance_with_non-constant_expression.zig b/test/cases/compile_errors/generic_function_instance_with_non-constant_expression.zig index 829db19d87..ebef24d293 100644 --- a/test/cases/compile_errors/generic_function_instance_with_non-constant_expression.zig +++ b/test/cases/compile_errors/generic_function_instance_with_non-constant_expression.zig @@ -10,8 +10,7 @@ export fn entry() usize { } // error -// backend=stage2 -// target=native // -// :5:16: error: runtime-known argument passed to comptime parameter -// :1:17: note: declared comptime here +// :5:16: error: unable to resolve comptime value +// :5:16: note: argument to comptime parameter must be comptime-known +// :1:8: note: parameter declared comptime here diff --git a/test/cases/compile_errors/generic_function_instantiation_inherits_parent_branch_quota.zig b/test/cases/compile_errors/generic_function_instantiation_inherits_parent_branch_quota.zig index 1d45ce86db..4db27f0620 100644 --- a/test/cases/compile_errors/generic_function_instantiation_inherits_parent_branch_quota.zig +++ b/test/cases/compile_errors/generic_function_instantiation_inherits_parent_branch_quota.zig @@ -22,9 +22,8 @@ fn Type(comptime n: usize) type { } // error -// backend=stage2 -// target=native // // :21:16: error: evaluation exceeded 1001 backwards branches // :21:16: note: use @setEvalBranchQuota() to raise the branch limit from 1001 // :16:34: note: called from here +// :8:15: note: called from here diff --git a/test/cases/compile_errors/generic_instantiation_failure_in_generic_function_return_type.zig b/test/cases/compile_errors/generic_instantiation_failure_in_generic_function_return_type.zig index a4aaf8eb91..1be4360317 100644 --- a/test/cases/compile_errors/generic_instantiation_failure_in_generic_function_return_type.zig +++ b/test/cases/compile_errors/generic_instantiation_failure_in_generic_function_return_type.zig @@ -40,3 +40,4 @@ pub fn is(comptime id: std.builtin.TypeId) TraitFn { // target=native // // :8:48: error: expected type 'type', found 'bool' +// :5:21: note: called from here diff --git a/test/cases/compile_errors/generic_method_call_with_invalid_param.zig b/test/cases/compile_errors/generic_method_call_with_invalid_param.zig index 6ce431461b..04eba6e99e 100644 --- a/test/cases/compile_errors/generic_method_call_with_invalid_param.zig +++ b/test/cases/compile_errors/generic_method_call_with_invalid_param.zig @@ -22,12 +22,11 @@ const S = struct { }; // error -// backend=stage2 -// target=native // // :3:18: error: expected type 'bool', found 'void' // :19:43: note: parameter type declared here // :8:18: error: expected type 'void', found 'bool' // :20:43: note: parameter type declared here -// :15:26: error: runtime-known argument passed to comptime parameter -// :21:57: note: declared comptime here +// :15:26: error: unable to resolve comptime value +// :15:26: note: argument to comptime parameter must be comptime-known +// :21:48: note: parameter declared comptime here diff --git a/test/cases/compile_errors/global_variable_initializer_must_be_constant_expression.zig b/test/cases/compile_errors/global_variable_initializer_must_be_constant_expression.zig index a87f628396..b06767111d 100644 --- a/test/cases/compile_errors/global_variable_initializer_must_be_constant_expression.zig +++ b/test/cases/compile_errors/global_variable_initializer_must_be_constant_expression.zig @@ -5,7 +5,5 @@ export fn entry() i32 { } // error -// backend=stage2 -// target=native // // :2:14: error: comptime call of extern function diff --git a/test/cases/compile_errors/inline_call_runtime_value_to_comptime_param.zig b/test/cases/compile_errors/inline_call_runtime_value_to_comptime_param.zig index 67079c8a2d..abeb4bcaae 100644 --- a/test/cases/compile_errors/inline_call_runtime_value_to_comptime_param.zig +++ b/test/cases/compile_errors/inline_call_runtime_value_to_comptime_param.zig @@ -10,8 +10,7 @@ pub export fn entry() void { } // error -// backend=stage2 -// target=native // // :5:18: error: unable to resolve comptime value // :5:18: note: argument to comptime parameter must be comptime-known +// :1:24: note: parameter declared comptime here diff --git a/test/cases/compile_errors/invalid_extern_function_call.zig b/test/cases/compile_errors/invalid_extern_function_call.zig index c270c3bf48..36a8ac3fd7 100644 --- a/test/cases/compile_errors/invalid_extern_function_call.zig +++ b/test/cases/compile_errors/invalid_extern_function_call.zig @@ -9,8 +9,6 @@ export fn entry1() void { } // error -// backend=stage2 -// target=native // -// :4:15: error: comptime call of extern function pointer -// :8:5: error: inline call of extern function pointer +// :4:15: error: comptime call of extern function +// :8:5: error: inline call of extern function diff --git a/test/cases/compile_errors/invalid_pointer_for_var_type.zig b/test/cases/compile_errors/invalid_pointer_for_var_type.zig index d94c7bd3b8..2d80718b4f 100644 --- a/test/cases/compile_errors/invalid_pointer_for_var_type.zig +++ b/test/cases/compile_errors/invalid_pointer_for_var_type.zig @@ -7,7 +7,5 @@ export fn f() void { } // error -// backend=stage2 -// target=native // // :2:16: error: comptime call of extern function diff --git a/test/cases/compile_errors/nested_generic_function_param_type_mismatch.zig b/test/cases/compile_errors/nested_generic_function_param_type_mismatch.zig index 99f4b7a193..93718771b4 100644 --- a/test/cases/compile_errors/nested_generic_function_param_type_mismatch.zig +++ b/test/cases/compile_errors/nested_generic_function_param_type_mismatch.zig @@ -19,6 +19,6 @@ pub export fn entry() void { // backend=llvm // target=native // -// :15:28: error: expected type '*const fn (comptime type, u8, u8) u32', found '*const fn (void, u8, u8) u32' -// :15:28: note: pointer type child 'fn (void, u8, u8) u32' cannot cast into pointer type child 'fn (comptime type, u8, u8) u32' +// :15:28: error: expected type '*const fn (type, u8, u8) u32', found '*const fn (void, u8, u8) u32' +// :15:28: note: pointer type child 'fn (void, u8, u8) u32' cannot cast into pointer type child 'fn (type, u8, u8) u32' // :15:28: note: non-generic function cannot cast into a generic function diff --git a/test/cases/compile_errors/never_inline_call_of_inline_fn_with_comptime_param.zig b/test/cases/compile_errors/never_inline_call_of_inline_fn_with_comptime_param.zig index f1eadb7625..20556f1cf5 100644 --- a/test/cases/compile_errors/never_inline_call_of_inline_fn_with_comptime_param.zig +++ b/test/cases/compile_errors/never_inline_call_of_inline_fn_with_comptime_param.zig @@ -19,5 +19,5 @@ export fn entry2() void { // error // -// :14:5: error: 'never_inline' call of inline function -// :17:5: error: 'never_inline' call of inline function +// :14:5: error: cannot perform inline call with 'never_inline' modifier +// :17:5: error: cannot perform inline call with 'never_inline' modifier diff --git a/test/cases/compile_errors/non-const_expression_in_struct_literal_outside_function.zig b/test/cases/compile_errors/non-const_expression_in_struct_literal_outside_function.zig index c6d4e04fc1..808f94d9bf 100644 --- a/test/cases/compile_errors/non-const_expression_in_struct_literal_outside_function.zig +++ b/test/cases/compile_errors/non-const_expression_in_struct_literal_outside_function.zig @@ -9,7 +9,5 @@ export fn entry() usize { } // error -// backend=stage2 -// target=native // // :4:27: error: comptime call of extern function 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 cfb68bbcf6..3f913991a6 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 @@ -11,5 +11,6 @@ export fn entry() void { // error // // :8:11: error: unable to resolve comptime value -// :1:20: note: function with comptime-only return type 'type' is evaluated at comptime -// :1:20: note: types are not available at runtime +// :8:10: note: call to function with comptime-only return type 'type' is evaluated at comptime +// :1:20: note: return type declared here +// :8:10: note: types are not available at runtime diff --git a/test/cases/compile_errors/recursive_inline_fn.zig b/test/cases/compile_errors/recursive_inline_fn.zig index 1cecfdbada..7f96ad6709 100644 --- a/test/cases/compile_errors/recursive_inline_fn.zig +++ b/test/cases/compile_errors/recursive_inline_fn.zig @@ -29,8 +29,10 @@ pub export fn entry2() void { } // error -// backend=stage2 -// target=native // // :5:27: error: inline call is recursive +// :12:12: note: called from here // :24:10: error: inline call is recursive +// :20:10: note: called from here +// :16:11: note: called from here +// :28:10: note: called from here diff --git a/test/cases/compile_errors/runtime_operation_in_comptime_scope.zig b/test/cases/compile_errors/runtime_operation_in_comptime_scope.zig index 8c1d31adf2..e3576c179b 100644 --- a/test/cases/compile_errors/runtime_operation_in_comptime_scope.zig +++ b/test/cases/compile_errors/runtime_operation_in_comptime_scope.zig @@ -27,8 +27,9 @@ var rt: u32 = undefined; // :19:5: note: operation is runtime due to this operand // :14:8: note: called at comptime from here // :10:12: note: called at comptime from here -// :13:10: note: function with comptime-only return type 'type' is evaluated at comptime -// :13:10: note: types are not available at runtime +// :10:12: note: call to function with comptime-only return type 'type' is evaluated at comptime +// :13:10: note: return type declared here +// :10:12: note: types are not available at runtime // :2:8: note: called from here // :19:8: error: unable to evaluate comptime expression // :19:5: note: operation is runtime due to this operand |
