Skip to content

Commit 8ba60da

Browse files
committed
[Serialization] Only write the underlying type of an opaque type if inlinable
Clients of a resilient module using opaque types don't need access to the underlying type unless it's used in an inlinable context. Plus, the underlying type can reference internal details which can lead to crashes when they reference implementation-only dependencies. To clean up this behavior, let's only serialize the underlying type if used by an inlinable function. rdar://105128784
1 parent b4e2969 commit 8ba60da

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3886,7 +3886,16 @@ class DeclDeserializer {
38863886
opaqueDecl->setGenericSignature(genericSig);
38873887
else
38883888
opaqueDecl->setGenericSignature(GenericSignature());
3889-
if (underlyingTypeSubsID) {
3889+
3890+
auto *AFD = dyn_cast<AbstractFunctionDecl>(namingDecl);
3891+
if (MF.getResilienceStrategy() == ResilienceStrategy::Resilient &&
3892+
AFD && AFD->getResilienceExpansion() != ResilienceExpansion::Minimal) {
3893+
// Do not try to read the underlying type information if the function
3894+
// is not inlinable in clients. This reflects the swiftinterface behavior
3895+
// in where clients are only aware of the underlying type when the body
3896+
// of the function is public.
3897+
3898+
} else if (underlyingTypeSubsID) {
38903899
auto subMapOrError = MF.getSubstitutionMapChecked(underlyingTypeSubsID);
38913900
if (!subMapOrError) {
38923901
// If the underlying type references internal details, ignore it.

test/Serialization/Safety/skip-reading-internal-details.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ public struct PublicStruct {
8686
}
8787
}
8888

89+
// resultBuilder scenario
90+
public protocol V {}
91+
92+
@resultBuilder
93+
public struct VB {
94+
public static func buildExpression<Content>(_ content: Content) -> Content where Content : V { fatalError() }
95+
public static func buildBlock() -> V { fatalError() }
96+
public static func buildBlock<Content>(_ content: Content) -> Content where Content : V { fatalError() }
97+
}
98+
99+
public struct EV : V {
100+
public init () {}
101+
}
102+
103+
@available(SwiftStdlib 5.1, *)
104+
public extension V {
105+
@VB
106+
func opaqueReferencingPrivate() -> some V {
107+
referencedPrivateFunc(v: EV())
108+
}
109+
110+
private func referencedPrivateFunc(v: some V) -> some V { return v }
111+
}
112+
89113
//--- Client.swift
90114

91115
import Lib
@@ -94,3 +118,8 @@ var x = PublicStruct()
94118

95119
// Trigger a typo correction that reads all members.
96120
x.notAMember() // expected-error {{value of type 'PublicStruct' has no member 'notAMember'}}
121+
122+
if #available(SwiftStdlib 5.1, *) {
123+
let v = EV()
124+
let _ = v.opaqueReferencingPrivate()
125+
}

0 commit comments

Comments
 (0)