The const
modifier occurs in the context of pointers, to indicate that the pointed to memory is constant. This is different from the mutability of the variable: for example,
const a: u8 = 111;
const b: u8 = 222;
var ptr: *const u8 = &a;
// This is legal:
ptr = &b; // Now the ptr variable points to b instead of a
// This is not legal:
// ptr.* = 123; // You cannot mutate the value pointed to by the pointer, since the pointer is const (this would be changing the value of b)
This is relevant to your situation because slices are fundamentally pointers: a slice is a pointer to some data (e.g. a [*]u8
) along with the length of the data. If you have a slice s
, you can access these parts using s.ptr
and s.len
, respectively. Returning to your example, the type []const []const u8
involves two levels of pointers, so const
is specified in two places to indicate that both the outer pointer and inner pointer point to constant memory.
Now, arrays on the other hand are values, not pointers. When you use [_][]const u8
, that is an array (with inferred length, _
) of []const u8
. Since arrays are not pointers, you can’t put const
after the [_]
, since the mutability of the array contents is determined by whether the variable is declared var
or const
:
var a = [_]u8{0};
// This is legal:
a[0] = 1;
const b = [_]u8{0};
// This is not:
// b[0] = 1;
And the compiler knows this, so in the above example, the type of &a
is *[1]u8
(pointer to a mutable array, since a
is a var
), and the type of &b
is *const [1]u8
(pointer to a constant array, since b
is a const
).
Hopefully this makes sense and helps clarify what’s going on.