Skip to content

Commit 58cc2a4

Browse files
Merge pull request #73794 from aschwaighofer/package_cmo_opaque_type_subst
Fix opaque type substitution in the package cmo resilience domain
2 parents c64a95b + 9cc6723 commit 58cc2a4

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-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
@@ -10093,6 +10093,11 @@ bool OpaqueTypeDecl::exportUnderlyingType() const {
1009310093
if (mod->getResilienceStrategy() != ResilienceStrategy::Resilient)
1009410094
return true;
1009510095

10096+
// If we perform package CMO, in-package clients must have access to the
10097+
// underlying type.
10098+
if (mod->serializePackageEnabled())
10099+
return true;
10100+
1009610101
ValueDecl *namingDecl = getNamingDecl();
1009710102
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(namingDecl))
1009810103
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() &&
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-build-swift %t/Lib.swift \
5+
// RUN: -module-name=Lib -package-name Pkg \
6+
// RUN: -parse-as-library -emit-module -emit-module-path %t/Lib.swiftmodule -I%t \
7+
// RUN: -Xfrontend -experimental-package-cmo -Xfrontend -experimental-allow-non-resilient-access \
8+
// RUN: -O -wmo -enable-library-evolution -Xfrontend -disable-availability-checking
9+
10+
// RUN: %target-build-swift -module-name=Main -package-name Pkg -I%t -emit-sil -O %t/main.swift -o %t/Main-res.sil
11+
// RUN: %FileCheck %s --check-prefixes=CHECK-OPAQUE < %t/Main-res.sil
12+
13+
// REQUIRES: swift_in_compiler
14+
15+
//--- main.swift
16+
17+
import Lib
18+
19+
// CHECK-OPAQUE: sil @$s4Main023testPackageInSerializedC4FuncyyF : $@convention(thin) () -> ()
20+
// CHECK-OPAQUE: struct $Thing
21+
// CHECK-OPAQUE: struct $Thing1
22+
// CHECK-OPAQUE: function_ref @$s3Lib13getSomeProto2QryF
23+
// CHECK-OPAQUE: function_ref @$s3Lib13getSomeProto3QryF
24+
// CHECK-OPAQUE: } // end sil function '$s4Main023testPackageInSerializedC4FuncyyF'
25+
26+
public func testPackageInSerializedPackageFunc() {
27+
print(getSomeProto())
28+
print(getSomeProto1())
29+
print(getSomeProto2())
30+
print(getSomeProto3())
31+
}
32+
33+
//--- Lib.swift
34+
35+
public protocol SomeProto {}
36+
37+
public struct Thing : SomeProto {}
38+
package struct Thing1 : SomeProto {}
39+
internal struct Thing2 : SomeProto {}
40+
private struct Thing3 : SomeProto {}
41+
42+
// Don't crash on this example.
43+
public func getSomeProto() -> some SomeProto {
44+
return Thing()
45+
}
46+
public func getSomeProto1() -> some SomeProto {
47+
return Thing1()
48+
}
49+
public func getSomeProto2() -> some SomeProto {
50+
return Thing2()
51+
}
52+
public func getSomeProto3() -> some SomeProto {
53+
return Thing3()
54+
}

0 commit comments

Comments
 (0)