Skip to content

Commit ce91d77

Browse files
authored
Merge pull request #63068 from xymus/serial-pub-override
[Serialization] Public overrides of internal decls are ignorable by clients
2 parents ffac122 + 6c6cd41 commit ce91d77

File tree

2 files changed

+83
-4
lines changed

2 files changed

+83
-4
lines changed

lib/Serialization/Serialization.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3368,15 +3368,27 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
33683368
///
33693369
/// This should be kept conservative. Compiler crashes are still better than
33703370
/// miscompiles.
3371-
static bool overriddenDeclAffectsABI(const ValueDecl *overridden) {
3371+
static bool overriddenDeclAffectsABI(const ValueDecl *override,
3372+
const ValueDecl *overridden) {
33723373
if (!overridden)
33733374
return false;
3374-
// There's one case where we know a declaration doesn't affect the ABI of
3375+
// There's a few cases where we know a declaration doesn't affect the ABI of
33753376
// its overrides after they've been compiled: if the declaration is '@objc'
33763377
// and 'dynamic'. In that case, all accesses to the method or property will
33773378
// go through the Objective-C method tables anyway.
33783379
if (overridden->hasClangNode() || overridden->shouldUseObjCDispatch())
33793380
return false;
3381+
3382+
// In a public-override-internal case, the override doesn't have ABI
3383+
// implications.
3384+
auto isPublic = [](const ValueDecl *VD) {
3385+
return VD->getFormalAccessScope(VD->getDeclContext(),
3386+
/*treatUsableFromInlineAsPublic*/true)
3387+
.isPublic();
3388+
};
3389+
if (isPublic(override) && !isPublic(overridden))
3390+
return false;
3391+
33803392
return true;
33813393
}
33823394

@@ -4067,7 +4079,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
40674079
fn->isImplicitlyUnwrappedOptional(),
40684080
S.addDeclRef(fn->getOperatorDecl()),
40694081
S.addDeclRef(fn->getOverriddenDecl()),
4070-
overriddenDeclAffectsABI(fn->getOverriddenDecl()),
4082+
overriddenDeclAffectsABI(fn, fn->getOverriddenDecl()),
40714083
fn->getName().getArgumentNames().size() +
40724084
fn->getName().isCompoundName(),
40734085
rawAccessLevel,
@@ -4159,7 +4171,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
41594171
uint8_t(getStableAccessorKind(fn->getAccessorKind()));
41604172

41614173
bool overriddenAffectsABI =
4162-
overriddenDeclAffectsABI(fn->getOverriddenDecl());
4174+
overriddenDeclAffectsABI(fn, fn->getOverriddenDecl());
41634175

41644176
Type ty = fn->getInterfaceType();
41654177
SmallVector<IdentifierID, 4> dependencies;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/// Deserialization can ignore public overrides to internal methods.
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: split-file %s %t
5+
6+
/// Build the library.
7+
// RUN: %target-swift-frontend -emit-module %t/Lib.swift -I %t \
8+
// RUN: -enable-library-evolution -swift-version 5 \
9+
// RUN: -emit-module-path %t/Lib.swiftmodule \
10+
// RUN: -emit-module-interface-path %t/Lib.swiftinterface
11+
12+
/// Build against the swiftmodule.
13+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \
14+
// RUN: -enable-deserialization-safety
15+
16+
/// Build against the swiftinterface.
17+
// RUN: rm %t/Lib.swiftmodule
18+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \
19+
// RUN: -enable-deserialization-safety
20+
21+
//--- Lib.swift
22+
23+
open class Base {
24+
public func publicMethod() -> Int {
25+
return 1
26+
}
27+
28+
fileprivate func fileprivateMethod() -> Int {
29+
return 1
30+
}
31+
32+
internal func internalMethod() -> Int {
33+
return 1
34+
}
35+
}
36+
37+
open class Derived : Base {
38+
open override func publicMethod() -> Int {
39+
return super.publicMethod() + 1
40+
}
41+
42+
open override func fileprivateMethod() -> Int {
43+
return super.fileprivateMethod() + 1
44+
}
45+
46+
open override func internalMethod() -> Int {
47+
return super.internalMethod() + 1
48+
}
49+
}
50+
51+
//--- Client.swift
52+
53+
import Lib
54+
55+
public class OtherFinalDerived : Derived {
56+
public override func publicMethod() -> Int {
57+
return super.publicMethod() + 1
58+
}
59+
60+
public override func fileprivateMethod() -> Int {
61+
return super.fileprivateMethod() + 1
62+
}
63+
64+
public override func internalMethod() -> Int {
65+
return super.internalMethod() + 1
66+
}
67+
}

0 commit comments

Comments
 (0)