How a basic usage of, for example, an ArrayList would look like with inlining? For example, imagine a function that creates an ArrayList, resizes it, fills it in a loop and returns it.
pub export fn foo1() *anyopaque {
const size: u8 = 32;
var buffer: [size]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator();
var arr = @call(.always_inline, std.ArrayList(u8).init, .{ allocator });
@call(.always_inline, std.ArrayList(u8).resize, .{ &arr, size }) catch unreachable;
for (0..size) |i| {
arr.items[i] = @intCast(i);
}
// ensure that arr is not optimized away
return &arr;
}
It does not look great, imagine there are more ArrayList functions and all of them have to be wrapped into @call. And if you forgot to do it, you won’t be notified by the compiler.
But what if a function foo2 takes an Allocator as a parameter? What the author of this function should do? @call(.always_inline) every ArrayList function? It would help only if foo2 itself is inlined. But the author of the function can’t control that.
Personally, I don’t want to specify inlining frequently, because it may hurt perfromance. I want to rely on compiler for that.
That’s why I believe that the approach of @LucasSantos91 is better. Static polymorphism is a more basic building block than dynamic polymorhphism, because you can get latter from the former (by passing std.mem.Allocator as a comptime Allocator argument), but not vice versa. Advantages:
- you don’t have to remember to wrap function calls with
@call(.always_inline); - you let the compiler to decide what functions should be inlined;
- it gives more possibilities to the user (the user may decide whether they want to pass a concrete allocator or the interface
std.mem.Allocator).
Disadvantages stem from the fact that it is harder to use.
- The user has to understand whether to pass their
ConcreteAllocatoror*ConcreteAllocator. I don’t know how to improve it properly. - It may lead to code bloat if used extensively. It may be fixed by passing
std.mem.Allocatoron call sites (the user decides where exactly they want to do that). - Duck typing with
anytype. I believe it should be solved by something likeconcepts from C++.