Created
August 2, 2022 16:42
-
-
Save tauoverpi/e8fc90d44659d86a0ac25dc7fb1081bc to your computer and use it in GitHub Desktop.
.Pointer needs to go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/ziglang/zig/issues/10710#issue-1116978295 | |
const std = @import("std"); | |
const assert = std.debug.assert; | |
const TypeInfo = std.builtin.TypeInfo; | |
pub fn Type(comptime T: TypeInfo) type { | |
return comptime switch (T) { | |
// but what is the type of type? | |
.Type => type, | |
// won't work as the result is memoized :( | |
.Opaque => opaque {}, | |
// the awkward | |
.Struct => @Type(T), | |
.Union => @Type(T), | |
.Enum => @Type(T), | |
.Int => @Type(T), | |
.Fn => @Type(T), | |
.Frame => |info| @Frame(info.function), // ??? | |
.ErrorSet => @Type(T), // sad: | |
.BoundFn => @compileError("not loved anymore"), | |
// the good stuff | |
.Optional => |info| ?info.child, | |
.AnyFrame => anyframe, | |
.ComptimeFloat => comptime_float, | |
.ComptimeInt => comptime_int, | |
.Void => void, | |
.Bool => bool, | |
.NoReturn => noreturn, | |
.Undefined => @TypeOf(undefined), | |
.Null => @TypeOf(null), | |
.EnumLiteral => @TypeOf(.magic), | |
.Vector => |info| @Vector(info.len, info.child), | |
.ErrorUnion => |info| info.error_set!info.payload, | |
// :sad .ErrorSet => |info| @typeInfo(@TypeOf(hack(info orelse return error{}))).ErrorUnion.error_set, | |
// cute | |
.Array => |info| if (info.sentinel) |sentinel| | |
[info.len:@ptrCast(*const info.child, sentinel).*]info.child | |
else | |
[info.len]info.child, | |
.Float => |info| switch (info.bits) { | |
16 => f16, | |
32 => f32, | |
64 => f64, | |
80 => f80, | |
128 => f128, | |
else => @compileError("mate"), | |
}, | |
// well, it's not that bad | |
.Pointer => |info| { | |
const pattern = // | |
@as(u3, @boolToInt(info.is_volatile)) << 2 | | |
@as(u3, @boolToInt(info.is_allowzero)) << 1 | | |
@as(u3, @boolToInt(info.is_const)); | |
switch (info.size) { | |
.One => return switch (pattern) { | |
0b111 => *allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b011 => *allowzero align(info.alignment) addrspace(info.address_space) const info.child, | |
0b101 => *align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b001 => *align(info.alignment) addrspace(info.address_space) const info.child, | |
0b110 => *allowzero align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b010 => *allowzero align(info.alignment) addrspace(info.address_space) info.child, | |
0b100 => *align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b000 => *align(info.alignment) addrspace(info.address_space) info.child, | |
}, | |
.Many => { | |
if (info.sentinel) |tmp| { | |
const sentinel = @ptrCast(*const info.child, tmp).*; | |
return switch (pattern) { | |
0b111 => [*:sentinel]allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b011 => [*:sentinel]allowzero align(info.alignment) addrspace(info.address_space) const info.child, | |
0b101 => [*:sentinel]align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b001 => [*:sentinel]align(info.alignment) addrspace(info.address_space) const info.child, | |
0b110 => [*:sentinel]allowzero align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b010 => [*:sentinel]allowzero align(info.alignment) addrspace(info.address_space) info.child, | |
0b100 => [*:sentinel]align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b000 => [*:sentinel]align(info.alignment) addrspace(info.address_space) info.child, | |
}; | |
} else { | |
return switch (pattern) { | |
0b111 => [*]allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b011 => [*]allowzero align(info.alignment) addrspace(info.address_space) const info.child, | |
0b101 => [*]align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b001 => [*]align(info.alignment) addrspace(info.address_space) const info.child, | |
0b110 => [*]allowzero align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b010 => [*]allowzero align(info.alignment) addrspace(info.address_space) info.child, | |
0b100 => [*]align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b000 => [*]align(info.alignment) addrspace(info.address_space) info.child, | |
}; | |
} | |
}, | |
.Slice => { | |
if (info.sentinel) |tmp| { | |
const sentinel = @ptrCast(*const info.child, tmp).*; | |
return switch (pattern) { | |
0b111 => [:sentinel]allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b011 => [:sentinel]allowzero align(info.alignment) addrspace(info.address_space) const info.child, | |
0b101 => [:sentinel]align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b001 => [:sentinel]align(info.alignment) addrspace(info.address_space) const info.child, | |
0b110 => [:sentinel]allowzero align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b010 => [:sentinel]allowzero align(info.alignment) addrspace(info.address_space) info.child, | |
0b100 => [:sentinel]align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b000 => [:sentinel]align(info.alignment) addrspace(info.address_space) info.child, | |
}; | |
} else { | |
return switch (pattern) { | |
0b111 => []allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b011 => []allowzero align(info.alignment) addrspace(info.address_space) const info.child, | |
0b101 => []align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b001 => []align(info.alignment) addrspace(info.address_space) const info.child, | |
0b110 => []allowzero align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b010 => []allowzero align(info.alignment) addrspace(info.address_space) info.child, | |
0b100 => []align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b000 => []align(info.alignment) addrspace(info.address_space) info.child, | |
}; | |
} | |
}, | |
.C => return switch (pattern) { | |
0b101 => [*c]align(info.alignment) addrspace(info.address_space) const volatile info.child, | |
0b001 => [*c]align(info.alignment) addrspace(info.address_space) const info.child, | |
0b100 => [*c]align(info.alignment) addrspace(info.address_space) volatile info.child, | |
0b000 => [*c]align(info.alignment) addrspace(info.address_space) info.child, | |
else => unreachable, // I can't be bothered to fix this | |
}, | |
} | |
}, | |
}; | |
} | |
fn hack(comptime errors: []const TypeInfo.Error) !void { | |
var x = false; | |
inline for (errors) |err| { | |
if (x) return @field(anyerror, err.name); // sue me | |
} | |
} | |
test { | |
const everything = *allowzero align(32) addrspace(.generic) const volatile u8; | |
const shorttype = [*:32]allowzero align(32) addrspace(.generic) const volatile u32; | |
comptime assert(Type(@typeInfo(everything)) == everything); | |
comptime assert(Type(@typeInfo(shorttype)) == shorttype); | |
comptime assert(*const u8 == Type(@typeInfo(*const u8))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment