Segfaults on implementing an interface

const std = @import("std");

const VTab = struct {
    areaFn: *const fn (ptr: *anyopaque) f32,
};

const Circle = struct {
    radius: f32,
    fn area(self: *anyopaque) f32 {
        const s: *const Circle = @ptrCast(@alignCast(self));
        return std.math.pi * s.radius * s.radius;
    }
    pub fn vtable() *const VTab {
        return &VTab{ .areaFn = Circle.area };
    }
};

const Square = struct {
    side: f32,
    fn area(self: *anyopaque) f32 {
        const s: *const Square = @ptrCast(@alignCast(self));
        return s.side * s.side;
    }
    pub fn vtable() *const VTab {
        return &VTab{ .areaFn = Square.area };
    }
};

const Shape1 = struct {
    ptr: *anyopaque,
    vtab: *const VTab,

    fn area(self: *Shape1) f32 {
        return self.vtab.areaFn(self.ptr);
    }

    fn init(ptr: *anyopaque, vtab: *const VTab) Shape1 {
        return .{
            .ptr = ptr,
            .vtab = vtab,
        };
    }
};

pub fn main() !void {
    var sq = Square{ .side = 2 };
    var cr = Circle{ .radius = 2 };
    var shapes = [_]Shape1{
        Shape1.init(&sq, Square.vtable()),
        Shape1.init(&cr, Circle.vtable()),
    };
    for (&shapes) |*shape| {
        std.log.debug("{d}", .{shape.area()});
    }
}

EDIT:
Why this works?

pub fn vtable() *const VTab {
        return &VTab{ .areaFn = Square.area };
}

Since the members of VTab are all constant, allocation is static. We get a VTab pointer to the static space that does not change.

Why this does not work?

fn init(ptr: *anyopaque, f: *const fn (ptr: *anyopaque) f32) Shape1 {
    return .{
        .ptr = ptr,
        .vtab = &VTab{ .areaFn = f },
    };
}

Here VTab is not constant, f comes in runtime. Since VTab is allocated locally, it is allocated in stack.
When init finishes the stack space is reused by other functions and its value becomes corrupted.

Discussion: Feel confused with lifetime of anonymous struct