Skip to content

Commit f7fec02

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 434fb4b commit f7fec02

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
@@ -3888,7 +3888,16 @@ class DeclDeserializer {
38883888
opaqueDecl->setGenericSignature(genericSig);
38893889
else
38903890
opaqueDecl->setGenericSignature(GenericSignature());
3891-
if (underlyingTypeSubsID) {
3891+
3892+
auto *AFD = dyn_cast<AbstractFunctionDecl>(namingDecl);
3893+
if (MF.getResilienceStrategy() == ResilienceStrategy::Resilient &&
3894+
AFD && AFD->getResilienceExpansion() != ResilienceExpansion::Minimal) {
3895+
// Do not try to read the underlying type information if the function
3896+
// is not inlinable in clients. This reflects the swiftinterface behavior
3897+
// in where clients are only aware of the underlying type when the body
3898+
// of the function is public.
3899+
3900+
} else if (underlyingTypeSubsID) {
38923901
auto subMapOrError = MF.getSubstitutionMapChecked(underlyingTypeSubsID);
38933902
if (!subMapOrError) {
38943903
// 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)