Commit e77dede87e
src/Sema.zig
@@ -1898,10 +1898,14 @@ fn resolveMaybeUndefVal(
inst: Air.Inst.Ref,
) CompileError!?Value {
const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
- switch (val.tag()) {
- .variable => return null,
+ switch (val.ip_index) {
.generic_poison => return error.GenericPoison,
else => return val,
+ .none => switch (val.tag()) {
+ .variable => return null,
+ .generic_poison => return error.GenericPoison,
+ else => return val,
+ },
}
}
@@ -33497,6 +33501,33 @@ fn typePtrOrOptionalPtrTy(
buf: *Type.Payload.ElemType,
) !?Type {
const mod = sema.mod;
+
+ if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
+ .ptr_type => |ptr_type| switch (ptr_type.size) {
+ .Slice => return null,
+ .C => return ptr_type.elem_type.toType(),
+ .One, .Many => return ty,
+ },
+ .optional_type => |o| switch (mod.intern_pool.indexToKey(o.payload_type)) {
+ .ptr_type => |ptr_type| switch (ptr_type.size) {
+ .Slice, .C => return null,
+ .Many, .One => {
+ if (ptr_type.is_allowzero) return null;
+
+ // optionals of zero sized types behave like bools, not pointers
+ const payload_ty = o.payload_type.toType();
+ if ((try sema.typeHasOnePossibleValue(payload_ty)) != null) {
+ return null;
+ }
+
+ return payload_ty;
+ },
+ },
+ else => return null,
+ },
+ else => return null,
+ };
+
switch (ty.tag()) {
.optional_single_const_pointer,
.optional_single_mut_pointer,
src/type.zig
@@ -4319,8 +4319,20 @@ pub const Type = struct {
/// Returns true if the type is optional and would be lowered to a single pointer
/// address value, using 0 for null. Note that this returns true for C pointers.
- pub fn isPtrLikeOptional(self: Type, mod: *const Module) bool {
- switch (self.tag()) {
+ /// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
+ pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {
+ if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
+ .ptr_type => |ptr_type| ptr_type.size == .C,
+ .optional_type => |o| switch (mod.intern_pool.indexToKey(o.payload_type)) {
+ .ptr_type => |ptr_type| switch (ptr_type.size) {
+ .Slice, .C => false,
+ .Many, .One => !ptr_type.is_allowzero,
+ },
+ else => false,
+ },
+ else => false,
+ };
+ switch (ty.tag()) {
.optional_single_const_pointer,
.optional_single_mut_pointer,
.c_const_pointer,
@@ -4328,7 +4340,7 @@ pub const Type = struct {
=> return true,
.optional => {
- const child_ty = self.castTag(.optional).?.data;
+ const child_ty = ty.castTag(.optional).?.data;
if (child_ty.zigTypeTag(mod) != .Pointer) return false;
const info = child_ty.ptrInfo().data;
switch (info.size) {
@@ -4337,7 +4349,7 @@ pub const Type = struct {
}
},
- .pointer => return self.castTag(.pointer).?.data.size == .C,
+ .pointer => return ty.castTag(.pointer).?.data.size == .C,
else => return false,
}
src/value.zig
@@ -117,6 +117,8 @@ pub const Value = struct {
int_big_negative,
function,
extern_fn,
+ /// A comptime-known pointer can point to the address of a global
+ /// variable. The child element value in this case will have this tag.
variable,
/// A wrapper for values which are comptime-known but should
/// semantically be runtime-known.