They are and they aren’t. The usual term for this kind of thing is a “fat pointer”, there are a few kinds of those but a slice is definitely one.
But also, a slice is basically this:
fn Slice(T: type) type {
return struct {
.ptr: *T,
.len: usize,
};
}
fn MaybeSlice(T: type) type {
return struct {
.ptr: ?*T,
.len: usize,
};
}
With some essential syntax sugar to make it easy to use.
Currently Zig special-cases what Rust calls “niche optimization” for pointers only, but there are plans afoot to expand this. For instance, right now, a ?u21 has @sizeOf 8, but clearly it could be 4, because there are unused bits in the backing u32.
Another one would generalize what the MaybeSlice does, and say that, if you have a struct type with an unused niche in its value, you can use that field for an optional. So for something like this:
const SomeStruct = struct {
fee: u64,
fie: u32,
foe: u21,
};
Since there’s room in the u21 for bits which aren’t legal for the type, those could be used to tag a ?SomeStruct null type. Making the special niche value std.math.maxInt(u32) would make testing for it as fast, or nearly so, as testing for 0.
Since it doesn’t affect the correctness of programs, there’s no special hurry to add things like this. But it would make a meaningful difference in data size, particularly when arrays of structs start to enter the picture, so it will be nice to have when we do.