-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
compiler: add error for unnecessary use of 'var' #18017
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! I'm very happy about this change. I've been letting contributions slide that make this mistake knowing that the compiler would solve the problem eventually. Thanks for going through and making the fixes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops forgot to mark as approved
e3db2d7
to
3b27815
Compare
10fc9a9
to
8756fbf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More tautological cases you missed in math/big_int_test.zig
0393df6
to
ea8dc83
Compare
When a local variable is never used as an lvalue, we can determine that `const` would be sufficient for this variable, so emit an error in this case. More sophisticated checking is unfortunately not possible with Zig's current analysis model, since whether an lvalue is actually mutated depends on semantic analysis, in which some code paths may not be analyzed, so attempting to determine this would result in false positive compile errors. It's worth noting that an unfortunate consequence of this is that any field call `a.b()` will allow `a` to be `var`, even if `b` does not take a pointer as its first parameter - this is again a necessary compromise because the parameter type is not known until semantic analysis. Also update `translate-c` to not trigger these errors. This is done by replacing the `_ = @typeof(x)` emitted with `_ = &x` - the reference there means that the local is permitted to be `var`. A similar strategy will be used to prevent compile errors in the behavior tests, where we sometimes want to force a value to be runtime-known. Resolves: ziglang#224
85ad5a3
to
9cf6c1a
Compare
guess you really do need a machine to enforce these things
A small issue I've just encountered with this change is that unlike with |
In my opinion |
The official way is to fix your code. Don't work around the error. |
The workaround has the following uses:
This means that outside of the compiler codebase, there is pretty much no use in it. Also note: currently, |
This no longer builds with the latest version of Zig. See: ziglang/zig#18017
This no longer builds with the latest version of Zig. See: ziglang/zig#18017
This has a limitation that I'd assume to be quite common as it applies to built-ins like fn foo(ptr: *usize) void {
ptr.* = 42;
}
fn main() void {
const s: struct { i: usize = 0 } = .{};
var i = &s.i; // error: local variable is never mutated
foo(i);
} |
The compiler is correct; the code is wrong. It should be |
That doesn't build either (
|
You mean to write fn foo(ptr: *usize) void {
ptr.* = 42;
}
fn main() void {
var s: struct { i: usize = 0 } = .{};
const i = &s.i;
foo(i);
} |
This no longer builds with the latest version of Zig. See: ziglang/zig#18017
This no longer builds with the latest version of Zig. See: ziglang/zig#18017
* Update var to const in build.zig where applicable This no longer builds with the latest version of Zig. See: ziglang/zig#18017 * Update zig-wcwidth This includes fixes to make build.zig build again. * Add now-required paths field to build.zig.zon
Fixes these errors (introduced in ziglang/zig#18017 and ziglang/zig@6b1a823 ): ``` src/main.zig:290:13: error: local variable is never mutated var line_ = line_fbs.getWritten(); ^~~~~ src/main.zig:290:13: note: consider using 'const' src/main.zig:450:17: error: local variable is never mutated var path = std.fs.path.joinZ(allocator, &.{p, "ncdu", "config"}) catch unreachable; ^~~~ src/main.zig:450:17: note: consider using 'const' ... ``` Will be included in future Zig 0.12, this fix is backward compatible: ncdu still builds and runs fine on Zig 0.11.0. Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>
Depends on #18006, which corrects some unnecessary uses of
var
in Aro.This PR implements #224. The compile error is emitted when a
var
is never used as an lvalue - more detailed analysis is unfortunately not possible under Zig's current analysis model, as whether avar
is actually mutated may depend on semantic analysis where conditional compilation may incorrect affect the answer.Despite how limited this analysis is, the change identified around 1000 incorrect uses across the standard library and compiler, which have been manually corrected. It also led to me catching a few bugs in
std
, and one in the compiler - these have been fixed, aside from one instd
which I wasn't sure of the correct solution for, so a temporary@compileError
has been put in place to point out the issue. (This shows the usefulness of the error!)Since the analysis is simply based on whether a variable is ever used as an lvalue, there is a quite convenient way to silence this error when needed:
_ = &x
. This is kind of a dirty secret, and should ideally never be used in user code, but it's useful in the test cases and behavior tests, where we sometimes want to force values to be semantically runtime-known.The actual implementation of this change is fairly trivial - the bulk of this PR is spent fixing the entire codebase to not trigger this error.