The relationship between arrays and slices takes awhile to click for new Zig enjoyers, so I’m going to explain in depth why this works, I suspect you know all this.
Why this works is that you’re returning an array: [1024]u8, and not a slice: []u8. Aliasing it to Buf is just a convenience.
A slice [] is a pointer with a length, so the result location is two words in size. An array [1024] is the memory a slice can point to, in this case 1024 bytes in size.
The original inline function was creating the array inside the function body and returning a pointer to it. This could be legal, because inline is semantic in Zig, it’s not a hint the compiler can overlook, it has effects on (in particular) comptime analysis. We had a long discussion about this awhile ago. It wouldn’t result in a dangling stack pointer because the stack is not permitted to be pushed and popped for an inline fn call.
But I think this is the correct decision. It means that the mental model of the function’s call stack is everything visible in the function definition. An inline function is not so-marked at the call site, and we want reasoning about code to be as local as possible.
This is a good illustration of why that’s fine the way it is, because your inline function can just return an array, [1024]u8, and it should do that, since that’s the type you want.
Say 1024 isn’t always the number, no problem!
pub inline fn buf(len: comptime_int) [len]u8 {
var b: [len]u8 = undefined;
return b;
}
Now it’s buf(1024), buf(4096), whatever.
Last note: inline is not needed for correctness of this function. I would use it, personally, because I don’t want to rely on result location analysis to ensure one buf rather than two are created. But in Zig, the length of an array is part of the type itself, the result location has room for it, you can always return an array.
Zig doesn’t (and shouldn’t) allow runtime-variable amounts of stack space to be created, and how inline functions deal with dangling memory wouldn’t change that. Therefore there’s never any need: just return the memory, not a pointer to it. If and when variable amounts of memory are needed, we use the heap for that.