-
-
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
Generic way to specify a non-null value for optional pointers to zero-bit types? #4537
Comments
Is there an actual use case for this? As I understand it, zero-length pointers exist as an optimization of generic code that is compatible with a non-zero-length type. If you know that the type is zero-length, why use an optional pointer instead of a bool?
|
The following probably should work: const std = @import("std");
const assert = std.debug.assert;
pub fn notNull(comptime T: type) ?*T {
comptime assert(@sizeOf(T) == 0);
return @intToPtr(?*T, 0xdeadbeef);
}
test "notNull" {
var ptr = notNull(u0);
assert(ptr != null);
}
Although it seems both assert(ptr != null) and assert(ptr == null) pass (returning a null pointer works as expected) |
var ptr: ?*T = // what goes here? how about: var ptr: ?*T = @as(*T, undefined); I guess you kind of answered that above. Maybe it would be helpful to understand the real world motivation? |
There's no generic way to specify a non-null For each of the 0 bit types you listed, there is a specific way to get a value, then you could take the pointer to that value. const x = {};
return &x;
const x = @as(u0, 0);
return &x; I'm having trouble imagining a generic use case for generating a value of T separated from the code that is specifying what T is. |
the |
I'm not sure what the official stance is here, but I was under the impression that zero-sized types could not actually take on the value |
I can't remember my use case but I think I did come by it honestly. I think it was something like: I had a generic function providing a typed API over a u8-array backing. There was some logic that I had that did not work on 0 bytes type so I had have a special case with Something like this hackneyed example: fn Things(comptime T: type) type {
return struct {
memory: []const u8,
num_items: usize,
fn getFirst(self: *@This()) ?T {
if (@sizeOf(T) == 0) {
if (self.num_items > 0) {
const nothing: T = undefined;
return nothing;
} else {
return null;
}
}
// some logic that doesn't work on 0 byte types
const items = std.mem.bytesAsSlice(T, &self.memory);
if (self.num_items > 0) {
return items[0];
} else {
return null;
}
}
};
} But there are no pointers in this example, so maybe the problem wasn't about pointers specifically? Or it's possible this recreation has nothing to do with my original use case. Again I can't remember. I should have got around to replying back in February when I was doing this. |
At the core of this issue is the question "can a zero-sized value actually contain undefined?". After some discussion with @thejoshwolfe and @andrewrk , we've decided that they cannot. So saying var x: T = undefined;
return &x; You could alternatively use |
Background: optional pointers to zero-bit types are basically booleans. It's easy to set them to null, but not so easy to set them to "not-null".
I want to do this:
Maybe add a new function in
std.meta
, which does something like this? -Is there a better way to do this that I'm not aware of?
Examples of zero-bit types:
void
u0
struct {}
struct { nothing: u0 }
union { nothing: u0 }
enum { one }
*u0
[8]u0
[0]u8
@Vector(8, u0)
@Vector(0, u8)
Some more exotic ones (it's legal to make pointers to these):
@TypeOf(null)
@TypeOf(undefined)
The text was updated successfully, but these errors were encountered: