aboutsummaryrefslogtreecommitdiff
path: root/test/cases/compile_errors
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2025-01-05 05:27:48 +0000
committermlugg <mlugg@mlugg.co.uk>2025-01-09 06:46:47 +0000
commite9bd2d45d4bbaf7eff7e95bc3ef7a0123b66a103 (patch)
treeda18bc40935c7dd9698d792eae3d102fa0ad67ae /test/cases/compile_errors
parent3f95003d4c57650f9b4779f55c8d7368b137337c (diff)
downloadzig-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')
-rw-r--r--test/cases/compile_errors/arg_to_non_comptime_param_with_comptime_only_type_is_not_evaluated_at_comptime.zig36
-rw-r--r--test/cases/compile_errors/bad_usage_of_call.zig6
-rw-r--r--test/cases/compile_errors/comptime_call_of_function_pointer.zig5
-rw-r--r--test/cases/compile_errors/condition_comptime_reason_explained.zig6
-rw-r--r--test/cases/compile_errors/dereference_anyopaque.zig53
-rw-r--r--test/cases/compile_errors/explain_why_fn_is_called_at_comptime.zig3
-rw-r--r--test/cases/compile_errors/explain_why_generic_fn_is_called_at_comptime.zig3
-rw-r--r--test/cases/compile_errors/generic_function_instance_with_non-constant_expression.zig7
-rw-r--r--test/cases/compile_errors/generic_function_instantiation_inherits_parent_branch_quota.zig3
-rw-r--r--test/cases/compile_errors/generic_instantiation_failure_in_generic_function_return_type.zig1
-rw-r--r--test/cases/compile_errors/generic_method_call_with_invalid_param.zig7
-rw-r--r--test/cases/compile_errors/global_variable_initializer_must_be_constant_expression.zig2
-rw-r--r--test/cases/compile_errors/inline_call_runtime_value_to_comptime_param.zig3
-rw-r--r--test/cases/compile_errors/invalid_extern_function_call.zig6
-rw-r--r--test/cases/compile_errors/invalid_pointer_for_var_type.zig2
-rw-r--r--test/cases/compile_errors/nested_generic_function_param_type_mismatch.zig4
-rw-r--r--test/cases/compile_errors/never_inline_call_of_inline_fn_with_comptime_param.zig4
-rw-r--r--test/cases/compile_errors/non-const_expression_in_struct_literal_outside_function.zig2
-rw-r--r--test/cases/compile_errors/non_comptime_param_in_comptime_function.zig5
-rw-r--r--test/cases/compile_errors/recursive_inline_fn.zig6
-rw-r--r--test/cases/compile_errors/runtime_operation_in_comptime_scope.zig5
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