88 | {% raise "Can only use primitive integers and floats with Slice.new(size), not #{T}" %}
^----
Error: Can only use primitive integers and floats with Slice.new(size), not S
The difference between Pointer and Slice is that the latter provides more safety. Attaching a size to a Pointer creates a slice, and that makes it safe to access elements in the slice. So Slice is generally considered “safe”.
When allocating a Slice instance, the allocated items need a valid value. Otherwise they would be uninitialized and code that accesses it could break when the memory layout is invalid.
For primitive number types we can be sure that the uninitialized memory is a valid value (and actually for a few more, so this restriction could theoretically be a bit more lenient).
This might not be the case for other, more complex types. Hence this operation is not allowed in order to ensure memory consistency.
In this case you can use one of the other overloads of Slice.new to provide an explicit initialization for the allocated items.
Or, if you’re sure it’s fine to leave the memory uninitialized, you can allocate via Pointer.malloc and create a slice from that. This extra step should make it more explicit what’s going on and that this might have dangerous consequences.
The allocating variants of Slice.new are just convenience short cuts. But unsafe code should not be convenient.
All flag enums, and all non-flag enums containing a zero member;
Symbol, if at least 1 symbol is defined (although we don’t really want the ability to implicitly create symbols this way without an actual symbol literal);
Void and NoReturn (not meaningful in this context);
All StaticArrays, Tuples, and NamedTuples containing only other zero-initializable types;
All LLVM vector types (their member type is required to be integer, boolean, float, or pointer);
In theory, structs containing only zero-initializable instance variables are also themselves zero-initializable, but they are almost always endowed with domain-specific invariants where the all-zero-bytes representation isn’t semantically valid (e.g. a LibGMP::MPZ with a null limb pointer).
Non-null references are never zero-initializable. Neither is ReferenceStorage, as the type ID cannot be zero for any reference object.