@@ -3524,9 +3524,11 @@ pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPo
35243524 return ty .abiAlignment (zcu );
35253525}
35263526
3527- /// Given a container type requiring resolution, ensures that it is up-to-date.
3528- /// If not, the type is recreated at a new `InternPool.Index`.
3529- /// The new index is returned. This is the same as the old index if the fields were up-to-date.
3527+ /// `ty` is a container type requiring resolution (struct, union, or enum).
3528+ /// If `ty` is outdated, it is recreated at a new `InternPool.Index`, which is returned.
3529+ /// If the type cannot be recreated because it has been lost, `error.AnalysisFail` is returned.
3530+ /// If `ty` is not outdated, that same `InternPool.Index` is returned.
3531+ /// If `ty` has already been replaced by this function, the new index will not be returned again.
35303532pub fn ensureTypeUpToDate (pt : Zcu.PerThread , ty : InternPool.Index ) Zcu.SemaError ! InternPool.Index {
35313533 const zcu = pt .zcu ;
35323534 const gpa = zcu .gpa ;
@@ -3536,13 +3538,30 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError
35363538 const outdated = zcu .outdated .swapRemove (anal_unit ) or
35373539 zcu .potentially_outdated .swapRemove (anal_unit );
35383540
3541+ if (outdated ) {
3542+ _ = zcu .outdated_ready .swapRemove (anal_unit );
3543+ try zcu .markDependeeOutdated (.marked_po , .{ .interned = ty });
3544+ }
3545+
3546+ const ty_key = switch (ip .indexToKey (ty )) {
3547+ .struct_type , .union_type , .enum_type = > | key | key ,
3548+ else = > unreachable ,
3549+ };
3550+ const declared_ty_key = switch (ty_key ) {
3551+ .reified = > unreachable , // never outdated
3552+ .generated_tag = > unreachable , // never outdated
3553+ .declared = > | d | d ,
3554+ };
3555+
3556+ if (declared_ty_key .zir_index .resolve (ip ) == null ) {
3557+ // The instruction has been lost -- this type is dead.
3558+ return error .AnalysisFail ;
3559+ }
3560+
35393561 if (! outdated ) return ty ;
35403562
35413563 // We will recreate the type at a new `InternPool.Index`.
35423564
3543- _ = zcu .outdated_ready .swapRemove (anal_unit );
3544- try zcu .markDependeeOutdated (.marked_po , .{ .interned = ty });
3545-
35463565 // Delete old state which is no longer in use. Technically, this is not necessary: these exports,
35473566 // references, etc, will be ignored because the type itself is unreferenced. However, it allows
35483567 // reusing the memory which is currently being used to track this state.
@@ -3555,31 +3574,25 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError
35553574 zcu .intern_pool .removeDependenciesForDepender (gpa , anal_unit );
35563575
35573576 switch (ip .indexToKey (ty )) {
3558- .struct_type = > | key | return pt .recreateStructType (ty , key ),
3559- .union_type = > | key | return pt .recreateUnionType (ty , key ),
3560- .enum_type = > | key | return pt .recreateEnumType (ty , key ),
3577+ .struct_type = > return pt .recreateStructType (ty , declared_ty_key ),
3578+ .union_type = > return pt .recreateUnionType (ty , declared_ty_key ),
3579+ .enum_type = > return pt .recreateEnumType (ty , declared_ty_key ),
35613580 else = > unreachable ,
35623581 }
35633582}
35643583
35653584fn recreateStructType (
35663585 pt : Zcu.PerThread ,
35673586 old_ty : InternPool.Index ,
3568- full_key : InternPool.Key.NamespaceType ,
3569- ) Zcu.SemaError ! InternPool.Index {
3587+ key : InternPool.Key.NamespaceType.Declared ,
3588+ ) Allocator.Error ! InternPool.Index {
35703589 const zcu = pt .zcu ;
35713590 const gpa = zcu .gpa ;
35723591 const ip = & zcu .intern_pool ;
35733592
3574- const key = switch (full_key ) {
3575- .reified = > unreachable , // never outdated
3576- .generated_tag = > unreachable , // not a struct
3577- .declared = > | d | d ,
3578- };
3579-
3580- const inst_info = key .zir_index .resolveFull (ip ) orelse return error .AnalysisFail ;
3593+ const inst_info = key .zir_index .resolveFull (ip ).? ;
35813594 const file = zcu .fileByIndex (inst_info .file );
3582- if (file .status != .success_zir ) return error . AnalysisFail ;
3595+ assert (file .status == .success_zir ); // otherwise inst tracking failed
35833596 const zir = file .zir ;
35843597
35853598 assert (zir .instructions .items (.tag )[@intFromEnum (inst_info .inst )] == .extended );
@@ -3600,7 +3613,7 @@ fn recreateStructType(
36003613 break :blk fields_len ;
36013614 } else 0 ;
36023615
3603- if (captures_len != key .captures .owned .len ) return error . AnalysisFail ;
3616+ assert (captures_len == key .captures .owned .len ); // synchronises with logic in `Zcu.mapOldZirToNew`
36043617
36053618 const struct_obj = ip .loadStructType (old_ty );
36063619
@@ -3644,21 +3657,15 @@ fn recreateStructType(
36443657fn recreateUnionType (
36453658 pt : Zcu.PerThread ,
36463659 old_ty : InternPool.Index ,
3647- full_key : InternPool.Key.NamespaceType ,
3648- ) Zcu.SemaError ! InternPool.Index {
3660+ key : InternPool.Key.NamespaceType.Declared ,
3661+ ) Allocator.Error ! InternPool.Index {
36493662 const zcu = pt .zcu ;
36503663 const gpa = zcu .gpa ;
36513664 const ip = & zcu .intern_pool ;
36523665
3653- const key = switch (full_key ) {
3654- .reified = > unreachable , // never outdated
3655- .generated_tag = > unreachable , // not a union
3656- .declared = > | d | d ,
3657- };
3658-
3659- const inst_info = key .zir_index .resolveFull (ip ) orelse return error .AnalysisFail ;
3666+ const inst_info = key .zir_index .resolveFull (ip ).? ;
36603667 const file = zcu .fileByIndex (inst_info .file );
3661- if (file .status != .success_zir ) return error . AnalysisFail ;
3668+ assert (file .status == .success_zir ); // otherwise inst tracking failed
36623669 const zir = file .zir ;
36633670
36643671 assert (zir .instructions .items (.tag )[@intFromEnum (inst_info .inst )] == .extended );
@@ -3681,7 +3688,7 @@ fn recreateUnionType(
36813688 break :blk fields_len ;
36823689 } else 0 ;
36833690
3684- if (captures_len != key .captures .owned .len ) return error . AnalysisFail ;
3691+ assert (captures_len == key .captures .owned .len ); // synchronises with logic in `Zcu.mapOldZirToNew`
36853692
36863693 const union_obj = ip .loadUnionType (old_ty );
36873694
@@ -3731,23 +3738,19 @@ fn recreateUnionType(
37313738 return wip_ty .finish (ip , namespace_index );
37323739}
37333740
3741+ // TODO: is it safe for this to return `SemaError`? enum type resolution is a bit weird...
37343742fn recreateEnumType (
37353743 pt : Zcu.PerThread ,
37363744 old_ty : InternPool.Index ,
3737- full_key : InternPool.Key.NamespaceType ,
3745+ key : InternPool.Key.NamespaceType.Declared ,
37383746) Zcu.SemaError ! InternPool.Index {
37393747 const zcu = pt .zcu ;
37403748 const gpa = zcu .gpa ;
37413749 const ip = & zcu .intern_pool ;
37423750
3743- const key = switch (full_key ) {
3744- .reified , .generated_tag = > unreachable , // never outdated
3745- .declared = > | d | d ,
3746- };
3747-
3748- const inst_info = key .zir_index .resolveFull (ip ) orelse return error .AnalysisFail ;
3751+ const inst_info = key .zir_index .resolveFull (ip ).? ;
37493752 const file = zcu .fileByIndex (inst_info .file );
3750- if (file .status != .success_zir ) return error . AnalysisFail ;
3753+ assert (file .status == .success_zir ); // otherwise inst tracking failed
37513754 const zir = file .zir ;
37523755
37533756 assert (zir .instructions .items (.tag )[@intFromEnum (inst_info .inst )] == .extended );
@@ -3787,7 +3790,7 @@ fn recreateEnumType(
37873790 break :blk decls_len ;
37883791 } else 0 ;
37893792
3790- if (captures_len != key .captures .owned .len ) return error . AnalysisFail ;
3793+ assert (captures_len == key .captures .owned .len ); // synchronises with logic in `Zcu.mapOldZirToNew`
37913794
37923795 extra_index += captures_len ;
37933796 extra_index += decls_len ;
0 commit comments