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
This is a consequence of removing anonymous struct types (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:
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.