Skip to content

Commit bcd6f26

Browse files
committed
Fix opaque type substitution in the package cmo resilience domain
We need to serialize the underlying type if we want to see the underlying type accross the package resilience domain. rdar://128482863
1 parent 231f5b5 commit bcd6f26

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

include/swift/AST/Types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6621,6 +6621,8 @@ enum class OpaqueSubstitutionKind {
66216621
// Can be done if the underlying type is accessible from the context we
66226622
// substitute into. Private types cannot be accessed from a different TU.
66236623
SubstituteSameModuleMaximalResilience,
6624+
// Same as previous but with package and above visibility.
6625+
SubstituteSamePackageMaximalResilience,
66246626
// Substitute in a different module from the opaque defining decl. Can only
66256627
// be done if the underlying type is public.
66266628
SubstituteNonResilientModule

lib/AST/Decl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10078,6 +10078,11 @@ bool OpaqueTypeDecl::exportUnderlyingType() const {
1007810078
if (mod->getResilienceStrategy() != ResilienceStrategy::Resilient)
1007910079
return true;
1008010080

10081+
// If we perform package CMO, in-package clients must have access to the
10082+
// underlying type.
10083+
if (mod->serializePackageEnabled())
10084+
return true;
10085+
1008110086
ValueDecl *namingDecl = getNamingDecl();
1008210087
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(namingDecl))
1008310088
return AFD->getResilienceExpansion() == ResilienceExpansion::Minimal;

lib/AST/TypeSubstitution.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,14 @@ ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
982982
module == contextModule)
983983
return OpaqueSubstitutionKind::SubstituteSameModuleMaximalResilience;
984984

985+
// Allow replacement of opaque result types in the context of maximal
986+
// resilient expansion if the context's and the opaque type's module are in
987+
// the same package.
988+
if (contextExpansion == ResilienceExpansion::Maximal &&
989+
module->isResilient() && module->serializePackageEnabled() &&
990+
module->inSamePackage(contextModule))
991+
return OpaqueSubstitutionKind::SubstituteSamePackageMaximalResilience;
992+
985993
// Allow general replacement from non resilient modules. Otherwise, disallow.
986994
if (module->isResilient())
987995
return OpaqueSubstitutionKind::DontSubstitute;
@@ -1047,6 +1055,10 @@ static bool canSubstituteTypeInto(Type ty, const DeclContext *dc,
10471055

10481056
return typeDecl->getEffectiveAccess() > AccessLevel::FilePrivate;
10491057

1058+
case OpaqueSubstitutionKind::SubstituteSamePackageMaximalResilience: {
1059+
return typeDecl->getEffectiveAccess() >= AccessLevel::Package;
1060+
}
1061+
10501062
case OpaqueSubstitutionKind::SubstituteNonResilientModule:
10511063
// Can't access types that are not public from a different module.
10521064
if (dc->getParentModule() == typeDecl->getDeclContext()->getParentModule() &&

test/SILOptimizer/package-cmo-resilient-mode.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
// RUN: %target-build-swift -module-name=Main -package-name Pkg -I%t -emit-sil -O %t/main.swift -o %t/Main-res.sil
2828
// RUN: %FileCheck %s --check-prefixes=CHECK-MAIN-COMMON,CHECK-MAIN-RES < %t/Main-res.sil
29+
// RUN: %FileCheck %s --check-prefixes=CHECK-OPAQUE < %t/Main-res.sil
2930

3031
// RUN: llvm-bcanalyzer --dump %t/Lib.swiftmodule | %FileCheck %s --check-prefix=CHECK-BC
3132
// CHECK-BC: SERIALIZE_PACKAGE_ENABLED
@@ -188,6 +189,20 @@ public func mainPubArgRetInlinable(_ arg: PubKlass) -> PubStruct {
188189
return PubStruct(arg.data)
189190
}
190191

192+
// CHECK-OPAQUE: sil @$s4Main023testPackageInSerializedC4FuncyyF : $@convention(thin) () -> ()
193+
// CHECK-OPAQUE: struct $Thing
194+
// CHECK-OPAQUE: struct $Thing1
195+
// CHECK-OPAQUE: function_ref @$s3Lib13getSomeProto2QryF
196+
// CHECK-OPAQUE: function_ref @$s3Lib13getSomeProto3QryF
197+
// CHECK-OPAQUE: } // end sil function '$s4Main023testPackageInSerializedC4FuncyyF'
198+
199+
public func testPackageInSerializedPackageFunc() {
200+
print(getSomeProto())
201+
print(getSomeProto1())
202+
print(getSomeProto2())
203+
print(getSomeProto3())
204+
}
205+
191206
//--- Lib.swift
192207

193208
public struct PubStruct {
@@ -504,3 +519,24 @@ public func reproduce(_ e: Something) {
504519
return e.f()
505520
}
506521
}
522+
523+
public protocol SomeProto {}
524+
525+
public struct Thing : SomeProto {}
526+
package struct Thing1 : SomeProto {}
527+
internal struct Thing2 : SomeProto {}
528+
private struct Thing3 : SomeProto {}
529+
530+
// Don't crash on this example.
531+
public func getSomeProto() -> some SomeProto {
532+
return Thing()
533+
}
534+
public func getSomeProto1() -> some SomeProto {
535+
return Thing1()
536+
}
537+
public func getSomeProto2() -> some SomeProto {
538+
return Thing2()
539+
}
540+
public func getSomeProto3() -> some SomeProto {
541+
return Thing3()
542+
}

0 commit comments

Comments
 (0)