-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use case: comptime allocator #1291
Comments
Perhaps related to #130 |
We probably don't need |
I had a second pass at this, and it almost all worked, except for:
Which is a legitimate problem. Because this is trying to, at comptime, do a Related - I had a conversation with @cavedweller about this the other evening, and he pointed out an important use case: freeing the memory. With a pure userland solution to this, as you can see, there is no freeing memory. All comptime-allocated memory escapes, because
My proposal for this builtin would be: @comptimeRealloc(old_mem: []u8, new_size: usize, new_align: u29) []u8 Notably, comptime allocation doesn't fail - that would be a compile error! To allocate fresh memory, pass a zero-length slice for The returned byte slice would point to memory that is comptime-mutable within the current comptime scope. Outside that scope, the memory would be either runtime-mutable or runtime-const, depending on where the memory escaped to outside the comptime scope. One problem to solve with this proposal would be the lingering reference to a comptime allocator. As an example: const std = @import("std");
const foo = comptime blk: {
var comptime_alloc_state = ComptimeAllocator.init();
const allocator = &comptime_alloc_state.allocator;
var list = std.ArrayList(i32).init(allocator);
list.append(10) catch unreachable;
list.append(20) catch unreachable;
break :blk list;
};
pub fn main() void {
std.debug.warn("list[0]={}\n", foo.at(0));
std.debug.warn("list[1]={}\n", foo.at(1));
}
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const ComptimeAllocator = struct {
allocator: Allocator,
fn init() ComptimeAllocator {
return ComptimeAllocator{
.allocator = Allocator{
.reallocFn = realloc,
.shrinkFn = shrink,
},
};
}
fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) Allocator.Error![]u8 {
return @comptimeRealloc(old_mem, new_size, new_align);
}
fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
return @comptimeRealloc(old_mem, new_size, new_align);
}
}; Clearly the example wouldn't work if we made |
First off, the solution with the smallest-footprint change could look like this: @comptimeRealloc(old_mem: []u8, new_size: usize, new_align: u29) ?[]u8 //returns null if evaluated at runtime For a more thorough and "optimal" concept, maybe I'm just stating the obvious here, I'll try to keep it short; this is how my mind completes/solves the last comment's perspective:
If this design is accepted, the implementation of comptime variants can use the same interface as a runtime variant - in the case of allocators, the allocate function would unconditionally contain
For the purpose of code-deduplication, maybe something like #868 could also help in usage: if(@weAreInComptime())
return comptime_allocator.allocate(T);
else
return error.OnlySupportedAtComptime; |
EDIT2: Looks like I commented without doing proper research/testing again. Sorry for the noise. |
@rohlem: I don't think we want to draw a hard line between comptime and runtime code here. After all, a key feature of comptime is the ability to integrate with runtime program flow (see: Also, #5675 could be helpful here in any case. |
I've proposed a reworking of comptime semantics (#5895) to accommodate this use case. |
I run into this when trying to port ctregex to zig 0.13, what is the status of this issue? Is this abandoned or implemented? |
I updated the OP with a fresh writeup. In summary:
|
Additionally, one of the biggest thing blocking any There is a plan for this, discussed in a compiler meeting a while back -- the comptime pointer access rules should be relaxed, so that instead of emitting an error, accessing this kind of reinterpreted pointer works fine, but always spits out |
Here's an attempt at implementing the
Allocator
interface at compile-time:After #4298 is solved:
I believe there is only one problem left:
I think this would have already been working if we hadn't changed the Allocator interface from good ol'
@fieldParentPtr
to vtables.But anyway, I think the language rules can be relaxed. This coercion can be allowed as long as it makes the value a comptime-only value. In other words, function pointers are allowed to point to inline functions as long as the function pointer value is comptime-known. Attempt to coerce the function pointer to a runtime-known value would yield a compile error.
And then everything should work fine.
The text was updated successfully, but these errors were encountered: