Allocator VTable creation in standard library

in GeneralPurposeAllocator.allocator(), the following code is used to create an Allocator:

        pub fn allocator(self: *Self) Allocator {
            return .{
                .ptr = self,
                .vtable = &.{
                    .alloc = alloc,
                    .resize = resize,
                    .free = free,
                },
            };
        }

I have a very basic question about this: what language mechanism ensures that the vtable pointed to here has global lifetime, rather than being created on the stack during the allocator() function (so no longer valid when the function returns)?

I would have expected something like the following to ensure that returned allocator points to a VTable with long enough lifetime:

        const vtable: Allocator.VTable = .{
            .alloc = alloc,
            .resize = resize,
            .free = free,
        };

        pub fn allocator(self: *Self) Allocator {
            return .{
                .ptr = self,
                .vtable = &vtable,
            };
        }

Why is the above not necessary in this case? Thanks!

1 Like

It is static allocated because all the members are constant.
See: Diving deep into anonymous struct literals

2 Likes

Ah so this is expected behaviour of anonymous struct literals, thanks for the links.

As an aside: it seems a bit brittle that any non-const field would (silently) reduce the lifetime to local? Hopefully future zig gets some lifetime checks that would catch this kind of case at compile time though!

3 Likes