| ... | @@ -1967,7 +1967,9 @@ pub const Type = extern union { | ... | @@ -1967,7 +1967,9 @@ pub const Type = extern union { |
| 1967 | /// There are two reasons a type will return false: | 1967 | /// There are two reasons a type will return false: |
| 1968 | /// * the type is a comptime-only type. For example, the type `type` itself. | 1968 | /// * the type is a comptime-only type. For example, the type `type` itself. |
| 1969 | /// * the type has only one possible value, making its ABI size 0. | 1969 | /// * the type has only one possible value, making its ABI size 0. |
| 1970 | pub fn hasRuntimeBits(ty: Type) bool { | 1970 | /// When `ignore_comptime_only` is true, then types that are comptime only |
| | 1971 | /// may return false positives. |
| | 1972 | pub fn hasRuntimeBitsAdvanced(ty: Type, ignore_comptime_only: bool) bool { |
| 1971 | return switch (ty.tag()) { | 1973 | return switch (ty.tag()) { |
| 1972 | .u1, | 1974 | .u1, |
| 1973 | .u8, | 1975 | .u8, |
| ... | @@ -2063,7 +2065,7 @@ pub const Type = extern union { | ... | @@ -2063,7 +2065,7 @@ pub const Type = extern union { |
| 2063 | .const_slice, | 2065 | .const_slice, |
| 2064 | .mut_slice, | 2066 | .mut_slice, |
| 2065 | .pointer, | 2067 | .pointer, |
| 2066 | => !ty.comptimeOnly(), | 2068 | => if (ignore_comptime_only) true else !comptimeOnly(ty), |
| 2067 | | 2069 | |
| 2068 | .@"struct" => { | 2070 | .@"struct" => { |
| 2069 | const struct_obj = ty.castTag(.@"struct").?.data; | 2071 | const struct_obj = ty.castTag(.@"struct").?.data; |
| ... | @@ -2075,7 +2077,7 @@ pub const Type = extern union { | ... | @@ -2075,7 +2077,7 @@ pub const Type = extern union { |
| 2075 | } | 2077 | } |
| 2076 | assert(struct_obj.haveFieldTypes()); | 2078 | assert(struct_obj.haveFieldTypes()); |
| 2077 | for (struct_obj.fields.values()) |value| { | 2079 | for (struct_obj.fields.values()) |value| { |
| 2078 | if (value.ty.hasRuntimeBits()) | 2080 | if (value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only)) |
| 2079 | return true; | 2081 | return true; |
| 2080 | } else { | 2082 | } else { |
| 2081 | return false; | 2083 | return false; |
| ... | @@ -2093,14 +2095,14 @@ pub const Type = extern union { | ... | @@ -2093,14 +2095,14 @@ pub const Type = extern union { |
| 2093 | .enum_numbered, .enum_nonexhaustive => { | 2095 | .enum_numbered, .enum_nonexhaustive => { |
| 2094 | var buffer: Payload.Bits = undefined; | 2096 | var buffer: Payload.Bits = undefined; |
| 2095 | const int_tag_ty = ty.intTagType(&buffer); | 2097 | const int_tag_ty = ty.intTagType(&buffer); |
| 2096 | return int_tag_ty.hasRuntimeBits(); | 2098 | return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only); |
| 2097 | }, | 2099 | }, |
| 2098 | | 2100 | |
| 2099 | .@"union" => { | 2101 | .@"union" => { |
| 2100 | const union_obj = ty.castTag(.@"union").?.data; | 2102 | const union_obj = ty.castTag(.@"union").?.data; |
| 2101 | assert(union_obj.haveFieldTypes()); | 2103 | assert(union_obj.haveFieldTypes()); |
| 2102 | for (union_obj.fields.values()) |value| { | 2104 | for (union_obj.fields.values()) |value| { |
| 2103 | if (value.ty.hasRuntimeBits()) | 2105 | if (value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only)) |
| 2104 | return true; | 2106 | return true; |
| 2105 | } else { | 2107 | } else { |
| 2106 | return false; | 2108 | return false; |
| ... | @@ -2108,27 +2110,29 @@ pub const Type = extern union { | ... | @@ -2108,27 +2110,29 @@ pub const Type = extern union { |
| 2108 | }, | 2110 | }, |
| 2109 | .union_tagged => { | 2111 | .union_tagged => { |
| 2110 | const union_obj = ty.castTag(.union_tagged).?.data; | 2112 | const union_obj = ty.castTag(.union_tagged).?.data; |
| 2111 | if (union_obj.tag_ty.hasRuntimeBits()) { | 2113 | if (union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only)) { |
| 2112 | return true; | 2114 | return true; |
| 2113 | } | 2115 | } |
| 2114 | assert(union_obj.haveFieldTypes()); | 2116 | assert(union_obj.haveFieldTypes()); |
| 2115 | for (union_obj.fields.values()) |value| { | 2117 | for (union_obj.fields.values()) |value| { |
| 2116 | if (value.ty.hasRuntimeBits()) | 2118 | if (value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only)) |
| 2117 | return true; | 2119 | return true; |
| 2118 | } else { | 2120 | } else { |
| 2119 | return false; | 2121 | return false; |
| 2120 | } | 2122 | } |
| 2121 | }, | 2123 | }, |
| 2122 | | 2124 | |
| 2123 | .array, .vector => ty.arrayLen() != 0 and ty.elemType().hasRuntimeBits(), | 2125 | .array, .vector => ty.arrayLen() != 0 and |
| | 2126 | ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only), |
| 2124 | .array_u8 => ty.arrayLen() != 0, | 2127 | .array_u8 => ty.arrayLen() != 0, |
| 2125 | .array_sentinel => ty.childType().hasRuntimeBits(), | 2128 | .array_sentinel => ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only), |
| 2126 | | 2129 | |
| 2127 | .int_signed, .int_unsigned => ty.cast(Payload.Bits).?.data != 0, | 2130 | .int_signed, .int_unsigned => ty.cast(Payload.Bits).?.data != 0, |
| 2128 | | 2131 | |
| 2129 | .error_union => { | 2132 | .error_union => { |
| 2130 | const payload = ty.castTag(.error_union).?.data; | 2133 | const payload = ty.castTag(.error_union).?.data; |
| 2131 | return payload.error_set.hasRuntimeBits() or payload.payload.hasRuntimeBits(); | 2134 | return payload.error_set.hasRuntimeBitsAdvanced(ignore_comptime_only) or |
| | 2135 | payload.payload.hasRuntimeBitsAdvanced(ignore_comptime_only); |
| 2132 | }, | 2136 | }, |
| 2133 | | 2137 | |
| 2134 | .tuple, .anon_struct => { | 2138 | .tuple, .anon_struct => { |
| ... | @@ -2136,7 +2140,7 @@ pub const Type = extern union { | ... | @@ -2136,7 +2140,7 @@ pub const Type = extern union { |
| 2136 | for (tuple.types) |field_ty, i| { | 2140 | for (tuple.types) |field_ty, i| { |
| 2137 | const val = tuple.values[i]; | 2141 | const val = tuple.values[i]; |
| 2138 | if (val.tag() != .unreachable_value) continue; // comptime field | 2142 | if (val.tag() != .unreachable_value) continue; // comptime field |
| 2139 | if (field_ty.hasRuntimeBits()) return true; | 2143 | if (field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only)) return true; |
| 2140 | } | 2144 | } |
| 2141 | return false; | 2145 | return false; |
| 2142 | }, | 2146 | }, |
| ... | @@ -2148,6 +2152,14 @@ pub const Type = extern union { | ... | @@ -2148,6 +2152,14 @@ pub const Type = extern union { |
| 2148 | }; | 2152 | }; |
| 2149 | } | 2153 | } |
| 2150 | | 2154 | |
| | 2155 | pub fn hasRuntimeBits(ty: Type) bool { |
| | 2156 | return hasRuntimeBitsAdvanced(ty, false); |
| | 2157 | } |
| | 2158 | |
| | 2159 | pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool { |
| | 2160 | return hasRuntimeBitsAdvanced(ty, true); |
| | 2161 | } |
| | 2162 | |
| 2151 | pub fn isFnOrHasRuntimeBits(ty: Type) bool { | 2163 | pub fn isFnOrHasRuntimeBits(ty: Type) bool { |
| 2152 | switch (ty.zigTypeTag()) { | 2164 | switch (ty.zigTypeTag()) { |
| 2153 | .Fn => { | 2165 | .Fn => { |