# Surprising(?) zig 0.14.0 incompatibility when initializing arrays of structs

**URL:** <https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917>\
**Category:** Help\
**Tags:** language\
**Created:** [March 6, 2025, 4:41pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917 "2025-03-06T16:41:05Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![floooh](https://ziggit.dev/user_avatar/ziggit.dev/floooh/32/2989_2.png) [@floooh](https://ziggit.dev/u/floooh)\
**Post date:** [March 6, 2025, 4:41pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/1 "2025-03-06T16:41:05Z")

</div>

Just stumbled over this in one of my Zig projects when initializing an array of structs with default values like this:

```ts
ghosts: [NumGhosts]Ghost = .{.{}} ** NumGhosts,

```

In 0.14.0 this now produces the compiler error `expected type 'pacman.Ghost', found '@TypeOf(.{})'`.

Replacing the initialization with `@splat()` works (and tbh is nicer):

```ts
ghosts: [NumGhosts]Ghost = @splat(.{}),

```

…but I’m surprised that the former version isn’t equivalent. Is it a bug, or expected?

---

<div class="post-metadata">

**Author:** ![tensorush](https://ziggit.dev/letter_avatar_proxy/v4/letter/t/6a8cbe/32.png) [@tensorush](https://ziggit.dev/u/tensorush)\
**Post date:** [March 6, 2025, 4:43pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/2 "2025-03-06T16:43:45Z")

</div>

Like this should still work:

```zig
ghosts = [1]Ghost{.{}} ** NumGhosts,

```

---

<div class="post-metadata">

**Author:** ![floooh](https://ziggit.dev/user_avatar/ziggit.dev/floooh/32/2989_2.png) [@floooh](https://ziggit.dev/u/floooh)\
**Post date:** [March 6, 2025, 4:44pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/3 "2025-03-06T16:44:36Z")

</div>

TBH, I would prefer this to work 😉

```ts
ghosts: [NumGhosts]Ghost = .{},

```

---

<div class="post-metadata">

**Author:** ![tensorush](https://ziggit.dev/letter_avatar_proxy/v4/letter/t/6a8cbe/32.png) [@tensorush](https://ziggit.dev/u/tensorush)\
**Post date:** [March 6, 2025, 4:56pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/4 "2025-03-06T16:56:06Z")

</div>

Yea, idk I like how `@splat(.{})` communicates both array initialization as well as array element initialization, while just `.{}` conceals the latter.

Btw, `@splat` virtually rendered the `**` array multiplication syntax redundant, I think. If so, I’d like for there to be one way of doing things.

---

<div class="post-metadata">

**Author:** ![floooh](https://ziggit.dev/user_avatar/ziggit.dev/floooh/32/2989_2.png) [@floooh](https://ziggit.dev/u/floooh)\
**Post date:** [March 6, 2025, 4:58pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/5 "2025-03-06T16:58:43Z")

</div>

Only thing I don’t like about `@splat` is that it looks like a workaround for missing language syntax. E.g. in my mind, every occurance of a `@` builtin is a code smell 🙂

---

<div class="post-metadata">

**Author:** ![castholm](https://ziggit.dev/user_avatar/ziggit.dev/castholm/32/1330_2.png) [@castholm](https://ziggit.dev/u/castholm)\
**Post date:** [March 6, 2025, 5:12pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/6 "2025-03-06T17:12:17Z")

</div>

This is a consequence of [removing anonymous struct types](https://ziglang.org/download/0.14.0/release-notes.html#Remove-Anonymous-Struct-Types-Unify-Tuples) (which confusingly does not refer to anonymous struct inits `.{}` but rather a special struct type with special rules).

Previously, if you assigned a struct or array initializer `.{}` to an _untyped variable or result location_, it was given a special type that allows for coercion to a different structurally compatible struct type, which allowed for code like this:

```zig
var x: i32 = 10;
var y: i32 = 20;
const MyStruct = struct { a: i32, b: i32 };
const a = .{ .a = x, .b = y };
// @TypeOf(a) is a special anonymous struct type
const b: MyStruct = a;

```

After removing this language feature, the last assignment is no longer legal, because `@TypeOf(a)` is now a regular `struct { a: i32, b: i32 }`.

Both before and after removal of anonymous struct types, if you assigned `.{}` to a location with a result type, it takes on that type, so something like `ghosts: [3]Ghost = .{ x, y, z }` is valid and works like how you would expect.

However, the `**` operator does not provide a result type (this is also true for most other operators), so the right hand side of an assignment like `ghosts: [NumGhosts]Ghost = .{.{}}** NumGhosts` yields `[NumGhosts]struct {}` and not `[NumGhosts]Ghost`.

Before 0.14, this yielded `[NumGhosts]<special anonymous struct type>`, which is why the code used to work but no longer does.

---

<div class="post-metadata">

**Author:** ![tensorush](https://ziggit.dev/letter_avatar_proxy/v4/letter/t/6a8cbe/32.png) [@tensorush](https://ziggit.dev/u/tensorush)\
**Post date:** [March 6, 2025, 5:17pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/7 "2025-03-06T17:17:41Z")

</div>

Well, builtins are meant to be used sparingly, so I’d say that rather builtin overuse is a code smell.

---

<div class="post-metadata">

**Author:** ![floooh](https://ziggit.dev/user_avatar/ziggit.dev/floooh/32/2989_2.png) [@floooh](https://ziggit.dev/u/floooh)\
**Post date:** [March 6, 2025, 5:19pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/8 "2025-03-06T17:19:37Z")

</div>

Thanks for the explanation @castholm

---

<div class="post-metadata">

**Author:** ![Luke](https://ziggit.dev/letter_avatar_proxy/v4/letter/l/7ab992/32.png) [@Luke](https://ziggit.dev/u/Luke)\
**Post date:** [March 6, 2025, 7:14pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/9 "2025-03-06T19:14:24Z")

</div>

> [@tensorush](#):
>
> Well, builtins are meant to be used sparingly, so I’d say that rather builtin overuse is a code smell.

Really? Is there documentation about this?

What about all the trigonometry functions, the @min/@max, etc?

---

<div class="post-metadata">

**Author:** ![tensorush](https://ziggit.dev/letter_avatar_proxy/v4/letter/t/6a8cbe/32.png) [@tensorush](https://ziggit.dev/u/tensorush)\
**Post date:** [March 6, 2025, 7:23pm UTC](https://ziggit.dev/t/surprising-zig-0-14-0-incompatibility-when-initializing-arrays-of-structs/8917/10 "2025-03-06T19:23:33Z")

</div>

No, just an opinion. It’s never an overuse when you know what you’re doing. `@branchHint` is a good example.
