| ... | @@ -1579,8 +1579,6 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -1579,8 +1579,6 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1579 | const target = sema.mod.getTarget(); | 1579 | const target = sema.mod.getTarget(); |
| 1580 | const addr_space = target_util.defaultAddressSpace(target, .local); | 1580 | const addr_space = target_util.defaultAddressSpace(target, .local); |
| 1581 | | 1581 | |
| 1582 | try sema.resolveTypeLayout(block, src, pointee_ty); | | |
| 1583 | | | |
| 1584 | if (Air.refToIndex(ptr)) |ptr_inst| { | 1582 | if (Air.refToIndex(ptr)) |ptr_inst| { |
| 1585 | if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) { | 1583 | if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) { |
| 1586 | const air_datas = sema.air_instructions.items(.data); | 1584 | const air_datas = sema.air_instructions.items(.data); |
| ... | @@ -1617,6 +1615,9 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -1617,6 +1615,9 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1617 | try pointee_ty.copy(anon_decl.arena()), | 1615 | try pointee_ty.copy(anon_decl.arena()), |
| 1618 | Value.undef, | 1616 | Value.undef, |
| 1619 | ); | 1617 | ); |
| | 1618 | if (iac.data.alignment != 0) { |
| | 1619 | try sema.resolveTypeLayout(block, src, pointee_ty); |
| | 1620 | } |
| 1620 | const ptr_ty = try Type.ptr(sema.arena, target, .{ | 1621 | const ptr_ty = try Type.ptr(sema.arena, target, .{ |
| 1621 | .pointee_type = pointee_ty, | 1622 | .pointee_type = pointee_ty, |
| 1622 | .@"align" = iac.data.alignment, | 1623 | .@"align" = iac.data.alignment, |
| ... | @@ -1886,7 +1887,7 @@ fn zirEnumDecl( | ... | @@ -1886,7 +1887,7 @@ fn zirEnumDecl( |
| 1886 | | 1887 | |
| 1887 | enum_obj.* = .{ | 1888 | enum_obj.* = .{ |
| 1888 | .owner_decl = new_decl, | 1889 | .owner_decl = new_decl, |
| 1889 | .tag_ty = Type.initTag(.@"null"), | 1890 | .tag_ty = Type.@"null", |
| 1890 | .tag_ty_inferred = true, | 1891 | .tag_ty_inferred = true, |
| 1891 | .fields = .{}, | 1892 | .fields = .{}, |
| 1892 | .values = .{}, | 1893 | .values = .{}, |
| ... | @@ -17867,13 +17868,13 @@ const TypedValueAndOffset = struct { | ... | @@ -17867,13 +17868,13 @@ const TypedValueAndOffset = struct { |
| 17867 | }; | 17868 | }; |
| 17868 | | 17869 | |
| 17869 | const ComptimePtrLoadKit = struct { | 17870 | const ComptimePtrLoadKit = struct { |
| 17870 | /// The Value and Type corresponding to the target of the provided pointer. | 17871 | /// The Value and Type corresponding to the pointee of the provided pointer. |
| 17871 | /// If a direct dereference is not possible, this is null. | 17872 | /// If a direct dereference is not possible, this is null. |
| 17872 | target: ?TypedValue, | 17873 | pointee: ?TypedValue, |
| 17873 | /// The largest parent Value containing `target` and having a well-defined memory layout. | 17874 | /// The largest parent Value containing `pointee` and having a well-defined memory layout. |
| 17874 | /// This is used for bitcasting, if direct dereferencing failed (i.e. `target` is null). | 17875 | /// This is used for bitcasting, if direct dereferencing failed (i.e. `pointee` is null). |
| 17875 | parent: ?TypedValueAndOffset, | 17876 | parent: ?TypedValueAndOffset, |
| 17876 | /// Whether the `target` could be mutated by further | 17877 | /// Whether the `pointee` could be mutated by further |
| 17877 | /// semantic analysis and a copy must be performed. | 17878 | /// semantic analysis and a copy must be performed. |
| 17878 | is_mutable: bool, | 17879 | is_mutable: bool, |
| 17879 | /// If the root decl could not be used as `parent`, this is the type that | 17880 | /// If the root decl could not be used as `parent`, this is the type that |
| ... | @@ -17885,7 +17886,7 @@ const ComptimePtrLoadError = CompileError || error{ | ... | @@ -17885,7 +17886,7 @@ const ComptimePtrLoadError = CompileError || error{ |
| 17885 | RuntimeLoad, | 17886 | RuntimeLoad, |
| 17886 | }; | 17887 | }; |
| 17887 | | 17888 | |
| 17888 | /// If `maybe_array_ty` is provided, it will be used to directly dereference an | 17889 | /// If `maybe_array_ty` is provided, it will be used to directly dereference an |
| 17889 | /// .elem_ptr of type T to a value of [N]T, if necessary. | 17890 | /// .elem_ptr of type T to a value of [N]T, if necessary. |
| 17890 | fn beginComptimePtrLoad( | 17891 | fn beginComptimePtrLoad( |
| 17891 | sema: *Sema, | 17892 | sema: *Sema, |
| ... | @@ -17908,10 +17909,10 @@ fn beginComptimePtrLoad( | ... | @@ -17908,10 +17909,10 @@ fn beginComptimePtrLoad( |
| 17908 | const decl_tv = try decl.typedValue(); | 17909 | const decl_tv = try decl.typedValue(); |
| 17909 | if (decl_tv.val.tag() == .variable) return error.RuntimeLoad; | 17910 | if (decl_tv.val.tag() == .variable) return error.RuntimeLoad; |
| 17910 | | 17911 | |
| 17911 | const layout_defined = try sema.typeHasWellDefinedLayout(block, src, decl.ty); | 17912 | const layout_defined = decl.ty.hasWellDefinedLayout(); |
| 17912 | break :blk ComptimePtrLoadKit{ | 17913 | break :blk ComptimePtrLoadKit{ |
| 17913 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | 17914 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, |
| 17914 | .target = decl_tv, | 17915 | .pointee = decl_tv, |
| 17915 | .is_mutable = is_mutable, | 17916 | .is_mutable = is_mutable, |
| 17916 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, | 17917 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, |
| 17917 | }; | 17918 | }; |
| ... | @@ -17923,7 +17924,7 @@ fn beginComptimePtrLoad( | ... | @@ -17923,7 +17924,7 @@ fn beginComptimePtrLoad( |
| 17923 | var deref = try beginComptimePtrLoad(sema, block, src, elem_ptr.array_ptr, null); | 17924 | var deref = try beginComptimePtrLoad(sema, block, src, elem_ptr.array_ptr, null); |
| 17924 | | 17925 | |
| 17925 | if (elem_ptr.index != 0) { | 17926 | if (elem_ptr.index != 0) { |
| 17926 | if (try sema.typeHasWellDefinedLayout(block, src, elem_ty)) { | 17927 | if (elem_ty.hasWellDefinedLayout()) { |
| 17927 | if (deref.parent) |*parent| { | 17928 | if (deref.parent) |*parent| { |
| 17928 | // Update the byte offset (in-place) | 17929 | // Update the byte offset (in-place) |
| 17929 | const elem_size = try sema.typeAbiSize(block, src, elem_ty); | 17930 | const elem_size = try sema.typeAbiSize(block, src, elem_ty); |
| ... | @@ -17938,17 +17939,17 @@ fn beginComptimePtrLoad( | ... | @@ -17938,17 +17939,17 @@ fn beginComptimePtrLoad( |
| 17938 | | 17939 | |
| 17939 | // If we're loading an elem_ptr that was derived from a different type | 17940 | // If we're loading an elem_ptr that was derived from a different type |
| 17940 | // than the true type of the underlying decl, we cannot deref directly | 17941 | // than the true type of the underlying decl, we cannot deref directly |
| 17941 | const ty_matches = if (deref.target != null and deref.target.?.ty.isArrayLike()) x: { | 17942 | const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayLike()) x: { |
| 17942 | const deref_elem_ty = deref.target.?.ty.childType(); | 17943 | const deref_elem_ty = deref.pointee.?.ty.childType(); |
| 17943 | break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or | 17944 | break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or |
| 17944 | (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; | 17945 | (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; |
| 17945 | } else false; | 17946 | } else false; |
| 17946 | if (!ty_matches) { | 17947 | if (!ty_matches) { |
| 17947 | deref.target = null; | 17948 | deref.pointee = null; |
| 17948 | break :blk deref; | 17949 | break :blk deref; |
| 17949 | } | 17950 | } |
| 17950 | | 17951 | |
| 17951 | var array_tv = deref.target.?; | 17952 | var array_tv = deref.pointee.?; |
| 17952 | const check_len = array_tv.ty.arrayLenIncludingSentinel(); | 17953 | const check_len = array_tv.ty.arrayLenIncludingSentinel(); |
| 17953 | if (elem_ptr.index >= check_len) { | 17954 | if (elem_ptr.index >= check_len) { |
| 17954 | // TODO have the deref include the decl so we can say "declared here" | 17955 | // TODO have the deref include the decl so we can say "declared here" |
| ... | @@ -17959,10 +17960,10 @@ fn beginComptimePtrLoad( | ... | @@ -17959,10 +17960,10 @@ fn beginComptimePtrLoad( |
| 17959 | | 17960 | |
| 17960 | if (maybe_array_ty) |load_ty| { | 17961 | if (maybe_array_ty) |load_ty| { |
| 17961 | // It's possible that we're loading a [N]T, in which case we'd like to slice | 17962 | // It's possible that we're loading a [N]T, in which case we'd like to slice |
| 17962 | // the target array directly from our parent array. | 17963 | // the pointee array directly from our parent array. |
| 17963 | if (load_ty.isArrayLike() and load_ty.childType().eql(elem_ty)) { | 17964 | if (load_ty.isArrayLike() and load_ty.childType().eql(elem_ty)) { |
| 17964 | const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel()); | 17965 | const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel()); |
| 17965 | deref.target = if (elem_ptr.index + N <= check_len) TypedValue{ | 17966 | deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{ |
| 17966 | .ty = try Type.array(sema.arena, N, null, elem_ty), | 17967 | .ty = try Type.array(sema.arena, N, null, elem_ty), |
| 17967 | .val = try array_tv.val.sliceArray(sema.arena, elem_ptr.index, elem_ptr.index + N), | 17968 | .val = try array_tv.val.sliceArray(sema.arena, elem_ptr.index, elem_ptr.index + N), |
| 17968 | } else null; | 17969 | } else null; |
| ... | @@ -17970,7 +17971,7 @@ fn beginComptimePtrLoad( | ... | @@ -17970,7 +17971,7 @@ fn beginComptimePtrLoad( |
| 17970 | } | 17971 | } |
| 17971 | } | 17972 | } |
| 17972 | | 17973 | |
| 17973 | deref.target = .{ | 17974 | deref.pointee = .{ |
| 17974 | .ty = elem_ty, | 17975 | .ty = elem_ty, |
| 17975 | .val = try array_tv.val.elemValue(sema.arena, elem_ptr.index), | 17976 | .val = try array_tv.val.elemValue(sema.arena, elem_ptr.index), |
| 17976 | }; | 17977 | }; |
| ... | @@ -17983,7 +17984,7 @@ fn beginComptimePtrLoad( | ... | @@ -17983,7 +17984,7 @@ fn beginComptimePtrLoad( |
| 17983 | const field_ty = field_ptr.container_ty.structFieldType(field_index); | 17984 | const field_ty = field_ptr.container_ty.structFieldType(field_index); |
| 17984 | var deref = try beginComptimePtrLoad(sema, block, src, field_ptr.container_ptr, field_ptr.container_ty); | 17985 | var deref = try beginComptimePtrLoad(sema, block, src, field_ptr.container_ptr, field_ptr.container_ty); |
| 17985 | | 17986 | |
| 17986 | if (try sema.typeHasWellDefinedLayout(block, src, field_ptr.container_ty)) { | 17987 | if (field_ptr.container_ty.hasWellDefinedLayout()) { |
| 17987 | if (deref.parent) |*parent| { | 17988 | if (deref.parent) |*parent| { |
| 17988 | // Update the byte offset (in-place) | 17989 | // Update the byte offset (in-place) |
| 17989 | try sema.resolveTypeLayout(block, src, field_ptr.container_ty); | 17990 | try sema.resolveTypeLayout(block, src, field_ptr.container_ty); |
| ... | @@ -17995,19 +17996,19 @@ fn beginComptimePtrLoad( | ... | @@ -17995,19 +17996,19 @@ fn beginComptimePtrLoad( |
| 17995 | deref.ty_without_well_defined_layout = field_ptr.container_ty; | 17996 | deref.ty_without_well_defined_layout = field_ptr.container_ty; |
| 17996 | } | 17997 | } |
| 17997 | | 17998 | |
| 17998 | if (deref.target) |*tv| { | 17999 | if (deref.pointee) |*tv| { |
| 17999 | const coerce_in_mem_ok = | 18000 | const coerce_in_mem_ok = |
| 18000 | (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or | 18001 | (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or |
| 18001 | (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok; | 18002 | (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok; |
| 18002 | if (coerce_in_mem_ok) { | 18003 | if (coerce_in_mem_ok) { |
| 18003 | deref.target = TypedValue{ | 18004 | deref.pointee = TypedValue{ |
| 18004 | .ty = field_ty, | 18005 | .ty = field_ty, |
| 18005 | .val = try tv.val.fieldValue(sema.arena, field_index), | 18006 | .val = try tv.val.fieldValue(sema.arena, field_index), |
| 18006 | }; | 18007 | }; |
| 18007 | break :blk deref; | 18008 | break :blk deref; |
| 18008 | } | 18009 | } |
| 18009 | } | 18010 | } |
| 18010 | deref.target = null; | 18011 | deref.pointee = null; |
| 18011 | break :blk deref; | 18012 | break :blk deref; |
| 18012 | }, | 18013 | }, |
| 18013 | | 18014 | |
| ... | @@ -18028,7 +18029,7 @@ fn beginComptimePtrLoad( | ... | @@ -18028,7 +18029,7 @@ fn beginComptimePtrLoad( |
| 18028 | deref.ty_without_well_defined_layout = payload_ptr.container_ty; | 18029 | deref.ty_without_well_defined_layout = payload_ptr.container_ty; |
| 18029 | } | 18030 | } |
| 18030 | | 18031 | |
| 18031 | if (deref.target) |*tv| { | 18032 | if (deref.pointee) |*tv| { |
| 18032 | const coerce_in_mem_ok = | 18033 | const coerce_in_mem_ok = |
| 18033 | (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or | 18034 | (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or |
| 18034 | (try sema.coerceInMemoryAllowed(block, tv.ty, payload_ptr.container_ty, false, target, src, src)) == .ok; | 18035 | (try sema.coerceInMemoryAllowed(block, tv.ty, payload_ptr.container_ty, false, target, src, src)) == .ok; |
| ... | @@ -18042,7 +18043,7 @@ fn beginComptimePtrLoad( | ... | @@ -18042,7 +18043,7 @@ fn beginComptimePtrLoad( |
| 18042 | break :blk deref; | 18043 | break :blk deref; |
| 18043 | } | 18044 | } |
| 18044 | } | 18045 | } |
| 18045 | deref.target = null; | 18046 | deref.pointee = null; |
| 18046 | break :blk deref; | 18047 | break :blk deref; |
| 18047 | }, | 18048 | }, |
| 18048 | | 18049 | |
| ... | @@ -18060,7 +18061,7 @@ fn beginComptimePtrLoad( | ... | @@ -18060,7 +18061,7 @@ fn beginComptimePtrLoad( |
| 18060 | else => unreachable, | 18061 | else => unreachable, |
| 18061 | }; | 18062 | }; |
| 18062 | | 18063 | |
| 18063 | if (deref.target) |tv| { | 18064 | if (deref.pointee) |tv| { |
| 18064 | if (deref.parent == null and tv.ty.hasWellDefinedLayout()) { | 18065 | if (deref.parent == null and tv.ty.hasWellDefinedLayout()) { |
| 18065 | deref.parent = .{ .tv = tv, .byte_offset = 0 }; | 18066 | deref.parent = .{ .tv = tv, .byte_offset = 0 }; |
| 18066 | } | 18067 | } |
| ... | @@ -21157,7 +21158,7 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr | ... | @@ -21157,7 +21158,7 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 21157 | else => |e| return e, | 21158 | else => |e| return e, |
| 21158 | }; | 21159 | }; |
| 21159 | | 21160 | |
| 21160 | if (deref.target) |tv| { | 21161 | if (deref.pointee) |tv| { |
| 21161 | const coerce_in_mem_ok = | 21162 | const coerce_in_mem_ok = |
| 21162 | (try sema.coerceInMemoryAllowed(block, load_ty, tv.ty, false, target, src, src)) == .ok or | 21163 | (try sema.coerceInMemoryAllowed(block, load_ty, tv.ty, false, target, src, src)) == .ok or |
| 21163 | (try sema.coerceInMemoryAllowed(block, tv.ty, load_ty, false, target, src, src)) == .ok; | 21164 | (try sema.coerceInMemoryAllowed(block, tv.ty, load_ty, false, target, src, src)) == .ok; |
| ... | @@ -21176,13 +21177,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr | ... | @@ -21176,13 +21177,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 21176 | | 21177 | |
| 21177 | // The type is not in-memory coercible or the direct dereference failed, so it must | 21178 | // The type is not in-memory coercible or the direct dereference failed, so it must |
| 21178 | // be bitcast according to the pointer type we are performing the load through. | 21179 | // be bitcast according to the pointer type we are performing the load through. |
| 21179 | if (!(try sema.typeHasWellDefinedLayout(block, src, load_ty))) | 21180 | if (!load_ty.hasWellDefinedLayout()) |
| 21180 | return sema.fail(block, src, "comptime dereference requires {} to have a well-defined layout, but it does not.", .{load_ty}); | 21181 | return sema.fail(block, src, "comptime dereference requires {} to have a well-defined layout, but it does not.", .{load_ty}); |
| 21181 | | 21182 | |
| 21182 | const load_sz = try sema.typeAbiSize(block, src, load_ty); | 21183 | const load_sz = try sema.typeAbiSize(block, src, load_ty); |
| 21183 | | 21184 | |
| 21184 | // Try the smaller bit-cast first, since that's more efficient than using the larger `parent` | 21185 | // Try the smaller bit-cast first, since that's more efficient than using the larger `parent` |
| 21185 | if (deref.target) |tv| if (load_sz <= try sema.typeAbiSize(block, src, tv.ty)) | 21186 | if (deref.pointee) |tv| if (load_sz <= try sema.typeAbiSize(block, src, tv.ty)) |
| 21186 | return try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0); | 21187 | return try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0); |
| 21187 | | 21188 | |
| 21188 | // If that fails, try to bit-cast from the largest parent value with a well-defined layout | 21189 | // If that fails, try to bit-cast from the largest parent value with a well-defined layout |
| ... | @@ -21271,182 +21272,6 @@ fn typePtrOrOptionalPtrTy( | ... | @@ -21271,182 +21272,6 @@ fn typePtrOrOptionalPtrTy( |
| 21271 | } | 21272 | } |
| 21272 | } | 21273 | } |
| 21273 | | 21274 | |
| 21274 | fn typeHasWellDefinedLayout(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { | | |
| 21275 | return switch (ty.tag()) { | | |
| 21276 | .u1, | | |
| 21277 | .u8, | | |
| 21278 | .i8, | | |
| 21279 | .u16, | | |
| 21280 | .i16, | | |
| 21281 | .u32, | | |
| 21282 | .i32, | | |
| 21283 | .u64, | | |
| 21284 | .i64, | | |
| 21285 | .u128, | | |
| 21286 | .i128, | | |
| 21287 | .usize, | | |
| 21288 | .isize, | | |
| 21289 | .c_short, | | |
| 21290 | .c_ushort, | | |
| 21291 | .c_int, | | |
| 21292 | .c_uint, | | |
| 21293 | .c_long, | | |
| 21294 | .c_ulong, | | |
| 21295 | .c_longlong, | | |
| 21296 | .c_ulonglong, | | |
| 21297 | .c_longdouble, | | |
| 21298 | .f16, | | |
| 21299 | .f32, | | |
| 21300 | .f64, | | |
| 21301 | .f80, | | |
| 21302 | .f128, | | |
| 21303 | .bool, | | |
| 21304 | .void, | | |
| 21305 | .manyptr_u8, | | |
| 21306 | .manyptr_const_u8, | | |
| 21307 | .manyptr_const_u8_sentinel_0, | | |
| 21308 | .anyerror_void_error_union, | | |
| 21309 | .empty_struct_literal, | | |
| 21310 | .empty_struct, | | |
| 21311 | .array_u8, | | |
| 21312 | .array_u8_sentinel_0, | | |
| 21313 | .int_signed, | | |
| 21314 | .int_unsigned, | | |
| 21315 | .pointer, | | |
| 21316 | .single_const_pointer, | | |
| 21317 | .single_mut_pointer, | | |
| 21318 | .many_const_pointer, | | |
| 21319 | .many_mut_pointer, | | |
| 21320 | .c_const_pointer, | | |
| 21321 | .c_mut_pointer, | | |
| 21322 | .single_const_pointer_to_comptime_int, | | |
| 21323 | .enum_numbered, | | |
| 21324 | => true, | | |
| 21325 | | | |
| 21326 | .anyopaque, | | |
| 21327 | .anyerror, | | |
| 21328 | .noreturn, | | |
| 21329 | .@"null", | | |
| 21330 | .@"anyframe", | | |
| 21331 | .@"undefined", | | |
| 21332 | .atomic_order, | | |
| 21333 | .atomic_rmw_op, | | |
| 21334 | .calling_convention, | | |
| 21335 | .address_space, | | |
| 21336 | .float_mode, | | |
| 21337 | .reduce_op, | | |
| 21338 | .call_options, | | |
| 21339 | .prefetch_options, | | |
| 21340 | .export_options, | | |
| 21341 | .extern_options, | | |
| 21342 | .error_set, | | |
| 21343 | .error_set_single, | | |
| 21344 | .error_set_inferred, | | |
| 21345 | .error_set_merged, | | |
| 21346 | .@"opaque", | | |
| 21347 | .generic_poison, | | |
| 21348 | .type, | | |
| 21349 | .comptime_int, | | |
| 21350 | .comptime_float, | | |
| 21351 | .enum_literal, | | |
| 21352 | .type_info, | | |
| 21353 | // These are function bodies, not function pointers. | | |
| 21354 | .fn_noreturn_no_args, | | |
| 21355 | .fn_void_no_args, | | |
| 21356 | .fn_naked_noreturn_no_args, | | |
| 21357 | .fn_ccc_void_no_args, | | |
| 21358 | .function, | | |
| 21359 | .const_slice_u8, | | |
| 21360 | .const_slice_u8_sentinel_0, | | |
| 21361 | .const_slice, | | |
| 21362 | .mut_slice, | | |
| 21363 | .enum_simple, | | |
| 21364 | .error_union, | | |
| 21365 | .anyframe_T, | | |
| 21366 | .tuple, | | |
| 21367 | .anon_struct, | | |
| 21368 | => false, | | |
| 21369 | | | |
| 21370 | .enum_full, | | |
| 21371 | .enum_nonexhaustive, | | |
| 21372 | => !ty.cast(Type.Payload.EnumFull).?.data.tag_ty_inferred, | | |
| 21373 | | | |
| 21374 | .var_args_param => unreachable, | | |
| 21375 | .inferred_alloc_mut => unreachable, | | |
| 21376 | .inferred_alloc_const => unreachable, | | |
| 21377 | .bound_fn => unreachable, | | |
| 21378 | | | |
| 21379 | .array, | | |
| 21380 | .array_sentinel, | | |
| 21381 | .vector, | | |
| 21382 | => sema.typeHasWellDefinedLayout(block, src, ty.childType()), | | |
| 21383 | | | |
| 21384 | .optional, | | |
| 21385 | .optional_single_mut_pointer, | | |
| 21386 | .optional_single_const_pointer, | | |
| 21387 | => blk: { | | |
| 21388 | var buf: Type.Payload.ElemType = undefined; | | |
| 21389 | break :blk sema.typeHasWellDefinedLayout(block, src, ty.optionalChild(&buf)); | | |
| 21390 | }, | | |
| 21391 | | | |
| 21392 | .@"struct" => { | | |
| 21393 | const struct_obj = ty.castTag(.@"struct").?.data; | | |
| 21394 | if (struct_obj.layout == .Auto) { | | |
| 21395 | struct_obj.has_well_defined_layout = .no; | | |
| 21396 | return false; | | |
| 21397 | } | | |
| 21398 | switch (struct_obj.has_well_defined_layout) { | | |
| 21399 | .no => return false, | | |
| 21400 | .yes, .wip => return true, | | |
| 21401 | .unknown => { | | |
| 21402 | if (struct_obj.status == .field_types_wip) | | |
| 21403 | return true; | | |
| 21404 | | | |
| 21405 | try sema.resolveTypeFieldsStruct(block, src, ty, struct_obj); | | |
| 21406 | | | |
| 21407 | struct_obj.has_well_defined_layout = .wip; | | |
| 21408 | for (struct_obj.fields.values()) |field| { | | |
| 21409 | if (!(try sema.typeHasWellDefinedLayout(block, src, field.ty))) { | | |
| 21410 | struct_obj.has_well_defined_layout = .no; | | |
| 21411 | return false; | | |
| 21412 | } | | |
| 21413 | } | | |
| 21414 | struct_obj.has_well_defined_layout = .yes; | | |
| 21415 | return true; | | |
| 21416 | }, | | |
| 21417 | } | | |
| 21418 | }, | | |
| 21419 | | | |
| 21420 | .@"union", .union_tagged => { | | |
| 21421 | const union_obj = ty.cast(Type.Payload.Union).?.data; | | |
| 21422 | if (union_obj.layout == .Auto) { | | |
| 21423 | union_obj.has_well_defined_layout = .no; | | |
| 21424 | return false; | | |
| 21425 | } | | |
| 21426 | switch (union_obj.has_well_defined_layout) { | | |
| 21427 | .no => return false, | | |
| 21428 | .yes, .wip => return true, | | |
| 21429 | .unknown => { | | |
| 21430 | if (union_obj.status == .field_types_wip) | | |
| 21431 | return true; | | |
| 21432 | | | |
| 21433 | try sema.resolveTypeFieldsUnion(block, src, ty, union_obj); | | |
| 21434 | | | |
| 21435 | union_obj.has_well_defined_layout = .wip; | | |
| 21436 | for (union_obj.fields.values()) |field| { | | |
| 21437 | if (!(try sema.typeHasWellDefinedLayout(block, src, field.ty))) { | | |
| 21438 | union_obj.has_well_defined_layout = .no; | | |
| 21439 | return false; | | |
| 21440 | } | | |
| 21441 | } | | |
| 21442 | union_obj.has_well_defined_layout = .yes; | | |
| 21443 | return true; | | |
| 21444 | }, | | |
| 21445 | } | | |
| 21446 | }, | | |
| 21447 | }; | | |
| 21448 | } | | |
| 21449 | | | |
| 21450 | /// `generic_poison` will return false. | 21275 | /// `generic_poison` will return false. |
| 21451 | /// This function returns false negatives when structs and unions are having their | 21276 | /// This function returns false negatives when structs and unions are having their |
| 21452 | /// field types resolved. | 21277 | /// field types resolved. |