# Why Slice(T).new(cap) only support for primitive type?

**URL:** <https://forum.crystal-lang.org/t/why-slice-t-new-cap-only-support-for-primitive-type/6926>\
**Category:** Help & Support\
**Created:** [June 13, 2024, 12:54am UTC](https://forum.crystal-lang.org/t/why-slice-t-new-cap-only-support-for-primitive-type/6926 "2024-06-13T00:54:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![aiac](https://avatars.discourse-cdn.com/v4/letter/a/db5fbb/32.png) [@aiac](https://forum.crystal-lang.org/u/aiac)\
**Post date:** [June 13, 2024, 12:54am UTC](https://forum.crystal-lang.org/t/why-slice-t-new-cap-only-support-for-primitive-type/6926/1 "2024-06-13T00:54:36Z")

</div>

- Slice(T).new(cap)

```auto
 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

```

but

- `Pointer(T).malloc(cap)` is working for any type

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [June 13, 2024, 8:48am UTC](https://forum.crystal-lang.org/t/why-slice-t-new-cap-only-support-for-primitive-type/6926/3 "2024-06-13T08:48:36Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![HertzDevil](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hertzdevil/32/1023_2.png) [@HertzDevil](https://forum.crystal-lang.org/u/HertzDevil)\
**Post date:** [June 19, 2024, 3:02am UTC](https://forum.crystal-lang.org/t/why-slice-t-new-cap-only-support-for-primitive-type/6926/4 "2024-06-19T03:02:55Z")

</div>

For the record, the exact list of zero-initializable types, whose all-zero-bytes representation is a valid object, are:

- All primitive integers and floats, including [the other floats in LLVM](https://llvm.org/docs/LangRef.html#floating-point-types) not available in Crystal;
- `Pointer`;
- `Char`;
- `Bool`;
- All nilable types, including just `Nil`;
- 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 `StaticArray`s, `Tuple`s, and `NamedTuple`s containing only other zero-initializable types;
- All LLVM vector types (their member type is required to be integer, boolean, float, or pointer);
- The LLVM [x86\_mmx](https://llvm.org/docs/LangRef.html#x86-mmx-type) and [x86\_amx](https://llvm.org/docs/LangRef.html#x86-amx-type) register types.

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.

---

<div class="post-metadata">

**Author:** ![aiac](https://avatars.discourse-cdn.com/v4/letter/a/db5fbb/32.png) [@aiac](https://forum.crystal-lang.org/u/aiac)\
**Post date:** [June 20, 2024, 6:13am UTC](https://forum.crystal-lang.org/t/why-slice-t-new-cap-only-support-for-primitive-type/6926/5 "2024-06-20T06:13:14Z")

</div>

Would be better that It is clearly stated in the documentation that Slice items are non-undefined values ​​compared to Pointers.

 ![Screenshot 2024-06-20 140837](https://canada1.discourse-cdn.com/flex036/uploads/crystal_lang/original/2X/f/f69ca81f29eb22ff65a7d96690a0460207b0e42f.png)

---

<div class="post-metadata">

**Author:** ![ysbaddaden](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/ysbaddaden/32/2252_2.png) [@ysbaddaden](https://forum.crystal-lang.org/u/ysbaddaden)\
**Post date:** [June 26, 2024, 10:05am UTC](https://forum.crystal-lang.org/t/why-slice-t-new-cap-only-support-for-primitive-type/6926/6 "2024-06-26T10:05:30Z")

</div>

Maybe the error could direct to the block veraion of the initializer?
