more hinting for array arguments not being const being the reason that a literal cannot be passed to a function
Zig Version
0.11.0-dev.3395+1e7dcaa3a
Steps to Reproduce and Observed Output
const std = @import("std");
fn sum(
// note: should be []const i32 to act the way I want
my_arg: []i32
) i32
{
var result:i32 = 0;
for (my_arg) |val| {
result += val;
}
return result;
}
test "array literal function argument" {
try std.testing.expectEqual(@as(i32, 9), sum(&.{ 1, 3, 5 }));
}
Message you get:
/var/tmp/test.zig:18:50: error: expected type '[]i32', found '*const tuple{comptime comptime_int = 1, comptime comptime_int = 3, comptime comptime_int = 5}'
try std.testing.expectEqual(@as(i32, 9), sum(&.{ 1, 3, 5 }));
^~~~~~~~~~~~~
/var/tmp/test.zig:18:50: note: cast discards const qualifier
/var/tmp/test.zig:5:13: note: parameter type declared here
my_arg: []i32
Expected Output
I keep bumping into this. The issue is that the error message is trying to tell me that because the parameter is missing a const, and a literal is const, I can't pass the literal into the parameter, I need to fix the signature on the parameter. However, the way that my brain reads this is that there is a problem with the declaration of the literal. Only after googling/searching discord do I remember what is going on and fix it. 99% of the time I meant for the parameter to be const anyway and forgot to mark it as const.
I think the gotcha is that typically, for non-reference types, you don't need to worry about using the const qualifier for parameters - parameters are const. And even for reference types ([]i32), you only hit this if you try and pass in a literal or other []const i32 array.
To be specific about the error message, I think I'm reading the "discards const qualifier" line as a problem with the literal instead of a problem with the parameter.
I wonder if something as simple as adding a "to parameter type" to the "cast discards const qualifier" message would help point at the right thing, so the message reads more like:
/var/tmp/test.zig:18:50: error: expected type '[]i32', found '*const tuple{comptime comptime_int = 1, comptime comptime_int = 3, comptime comptime_int = 5}'
try std.testing.expectEqual(@as(i32, 9), sum(&.{ 1, 3, 5 }));
^~~~~~~~~~~~~
/var/tmp/test.zig:18:50: note: cast to parameter type of discards const qualifier from literal
/var/tmp/test.zig:5:13: note: parameter type declared here
my_arg: []i32
Thanks! I appreciate the hard work you do in making zig as readable as it is!
For reference swift has a pretty clear message:
Cannot pass immutable value as inout argument: literals are not mutable
To repro:
func test(i : inout Int) {
print(i);
}
func foo() {
test(i: 3)
}
I don't see what the words "to parameter type of" would be adding to the message here, especially considering that the directly following line tells you the type is of a parameter. Swift special-cases this stuff because its inout modifier is a semantically a special thing of parameters, but this is a regular old type error as far as Zig is concerned.
I'm reading the "discards const qualifier" line as a problem with the literal
What part of the existing message would imply this interpretation?
You're right, this is a regular type error for zig. But to contrast the two errors, I think the swift error says in one line, very succintly and clearly what the problem is: you can't pass a by definition const literal to a parameter whose type is not const. The zig error has all of that information split up across several different lines... as a beginner, you have to carefully read the three lines and put it together.
With another year of experience with zig behind me, I'd probably want to write the error in this way:
/var/tmp/test.zig:18:50: error: cannot pass literal to non const parameter
/var/tmp/test.zig:18:50: note: cast discards const qualifier from literal
/var/tmp/test.zig:18:50: error: expected type '[]i32', found '*const tuple{comptime comptime_int = 1, comptime comptime_int = 3, comptime comptime_int = 5}'
try std.testing.expectEqual(@as(i32, 9), sum(&.{ 1, 3, 5 }));
^~~~~~~~~~~~~
/var/tmp/test.zig:5:13: note: parameter type declared here
my_arg: []i32
I don't hit this as often any more, since I've internalized this rule, but I tripped over this error while learning the language.
This stuff is super subjective and the compiler needs to succinctly communicate to expert users and help guide beginners at the same time, so I know this is a tough problem. I appreciate you engaging with it and discussing further!
THERE IS ISSUE IN ZIGZIG
Because the fact that the assignee is a parameter has no relation to the nature of this error (it is neither the cause nor related to the fix), mentioning it at all could only serve to mislead beginners. There is no such thing as a "const parameter".