aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-05-24 15:10:18 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-05-24 15:34:52 -0700
commitc711c788f0a840f45d0d7423efe2f946b47caafb (patch)
tree48f57fc696e485937a7b96477657bdd8cdaff534 /src/type.zig
parentc847a462ae11e0d483ad877b3ecc9ec291c29bb3 (diff)
downloadzig-c711c788f0a840f45d0d7423efe2f946b47caafb.tar.gz
zig-c711c788f0a840f45d0d7423efe2f946b47caafb.zip
stage2: fixes for error unions, optionals, errors
* `?E` where E is an error set with only one field now lowers the same as `bool`. * Fix implementation of errUnionErrOffset and errUnionPayloadOffset to properly compute the offset of each field. Also name them the same as the corresponding LLVM functions and have the same function signature, to avoid confusion. This fixes a bug where wasm was passing the error union type instead of the payload type. * Fix C backend handling of optionals with zero-bit payload types. * C backend: separate out airOptionalPayload and airOptionalPayloadPtr which reduces branching and cleans up control flow. * Make Type.isNoReturn return true for error sets with no fields. * Make `?error{}` have only one possible value (null).
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig64
1 files changed, 54 insertions, 10 deletions
diff --git a/src/type.zig b/src/type.zig
index 1c59cf9e59..4325d6d772 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -2375,7 +2375,6 @@ pub const Type = extern union {
// These types have more than one possible value, so the result is the same as
// asking whether they are comptime-only types.
.anyframe_T,
- .optional,
.optional_single_mut_pointer,
.optional_single_const_pointer,
.single_const_pointer,
@@ -2397,6 +2396,22 @@ pub const Type = extern union {
}
},
+ .optional => {
+ var buf: Payload.ElemType = undefined;
+ const child_ty = ty.optionalChild(&buf);
+ if (child_ty.isNoReturn()) {
+ // Then the optional is comptime-known to be null.
+ return false;
+ }
+ if (ignore_comptime_only) {
+ return true;
+ } else if (sema_kit) |sk| {
+ return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, child_ty));
+ } else {
+ return !comptimeOnly(child_ty);
+ }
+ },
+
.error_union => {
// This code needs to be kept in sync with the equivalent switch prong
// in abiSizeAdvanced.
@@ -2665,13 +2680,22 @@ pub const Type = extern union {
};
}
- pub fn isNoReturn(self: Type) bool {
- const definitely_correct_result =
- self.tag_if_small_enough != .bound_fn and
- self.zigTypeTag() == .NoReturn;
- const fast_result = self.tag_if_small_enough == Tag.noreturn;
- assert(fast_result == definitely_correct_result);
- return fast_result;
+ /// TODO add enums with no fields here
+ pub fn isNoReturn(ty: Type) bool {
+ switch (ty.tag()) {
+ .noreturn => return true,
+ .error_set => {
+ const err_set_obj = ty.castTag(.error_set).?.data;
+ const names = err_set_obj.names.keys();
+ return names.len == 0;
+ },
+ .error_set_merged => {
+ const name_map = ty.castTag(.error_set_merged).?.data;
+ const names = name_map.keys();
+ return names.len == 0;
+ },
+ else => return false,
+ }
}
/// Returns 0 if the pointer is naturally aligned and the element type is 0-bit.
@@ -2918,7 +2942,13 @@ pub const Type = extern union {
switch (child_type.zigTypeTag()) {
.Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
- .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, target, strat),
+ .ErrorSet => switch (child_type.errorSetCardinality()) {
+ // `?error{}` is comptime-known to be null.
+ .zero => return AbiAlignmentAdvanced{ .scalar = 0 },
+ .one => return AbiAlignmentAdvanced{ .scalar = 1 },
+ .many => return abiAlignmentAdvanced(Type.anyerror, target, strat),
+ },
+ .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 },
else => {},
}
@@ -3365,6 +3395,11 @@ pub const Type = extern union {
.optional => {
var buf: Payload.ElemType = undefined;
const child_type = ty.optionalChild(&buf);
+
+ if (child_type.isNoReturn()) {
+ return AbiSizeAdvanced{ .scalar = 0 };
+ }
+
if (!child_type.hasRuntimeBits()) return AbiSizeAdvanced{ .scalar = 1 };
switch (child_type.zigTypeTag()) {
@@ -4804,7 +4839,6 @@ pub const Type = extern union {
.const_slice,
.mut_slice,
.anyopaque,
- .optional,
.optional_single_mut_pointer,
.optional_single_const_pointer,
.enum_literal,
@@ -4839,6 +4873,16 @@ pub const Type = extern union {
.bound_fn,
=> return null,
+ .optional => {
+ var buf: Payload.ElemType = undefined;
+ const child_ty = ty.optionalChild(&buf);
+ if (child_ty.isNoReturn()) {
+ return Value.@"null";
+ } else {
+ return null;
+ }
+ },
+
.error_set_single => return Value.initTag(.the_only_possible_value),
.error_set => {
const err_set_obj = ty.castTag(.error_set).?.data;