// edit: this test is to illustrate incorrect behavior
test "var slice is never mutated but does not trigger error" {
var array = [_]f32{ 1.2, 3.4, 5.6 };
var slice = array[0..3];
// mutate array referenced by slice not slice itself
slice[0] = 3.1415;
try std.testing.expectEqual(3.1415, slice[0]);
}
// edit: no bug here. this test is to illustrate correct behavior
test "compile error variable is never mutated" {
var array = [_]f32{ 1.2, 3.4, 5.6 };
var slice = array[0..3];
try std.testing.expectEqual(3.1415, slice[0]);
}
zig version
0.15.2
Any other place requires me to carefully choose either const or var. Here the compiler accepts both of them. Is it a bug?
My guess is that the const-ness only affects the object itself, but not ‘external’ data that is referenced through a pointer (e.g. you can write to data that’s referenced by a non-const pointer inside a const object).
A slice is a ‘fat pointer’, and the array data that’s referenced by the slice isn’t part of the slice itself.
The same is true for structs with pointers btw:
const Bla = struct { x: *i32 };
// ...
var i: i32 = 123;
const blub: Bla = .{ .x = &i };
blub.x.* = 234;
PS: case in point, variable data referenced by a const slice is actually mutable:
Can you try to zig run bla.zig this code with 0.15.2? Because that fails for me with the expected error, while your post reads like the compiler accepts the var.
When I put your code into a bla.zig and compile as test I still get the error with zig 0.15.2:
const std = @import("std");
test "var slice is never mutated but does not trigger error" {
var array = [_]f32{ 1.2, 3.4, 5.6 };
var slice = array[0..3];
// mutate array referenced by slice not slice itself
slice[0] = 3.1415;
try std.testing.expectEqual(3.1415, slice[0]);
}
test "compile error variable is never mutated" {
var array = [_]f32{ 1.2, 3.4, 5.6 };
var slice = array[0..3];
try std.testing.expectEqual(3.1415, slice[0]);
}
scratch ➤ zig test bla.zig
bla.zig:13:9: error: local variable is never mutated
var slice = array[0..3];
^~~~~
bla.zig:13:9: note: consider using 'const'
scratch ➤ zig version
0.15.2
…but on the current zig master it builds (and then fails the test):
scratch ➤ zig test bla.zig
expected 3.1415, found 1.2
2/2 bla.test.compile error variable is never mutated...FAIL (TestExpectedEqual)
/Users/floh/.zvm/master/lib/std/testing.zig:113:17: 0x10219c7ff in expectEqualInner__anon_633 (test)
return error.TestExpectedEqual;
^
/Users/floh/scratch/bla.zig:14:5: 0x1022495df in test.compile error variable is never mutated (test)
try std.testing.expectEqual(3.1415, slice[0]);
^
1 passed; 0 skipped; 1 failed.
error: the following test command failed with exit code 1:
/Users/floh/.cache/zig/o/3c98c5988f8ba1782cf07d247059e509/test --seed=0xa8e5d06d
…but strangely enough, my original code also fails in master:
scratch ➤ zig run bla.zig
bla.zig:5:9: error: local variable is never mutated
var slice = array[0..3];
^~~~~
bla.zig:5:9: note: consider using 'const'
scratch ➤ zig version
0.16.0-dev.1484+d0ba6642b
…so it seems to be a regression in master but it only triggers in some situations…(?)