Skip to content

Commit cc0f42f

Browse files
authored
Merge pull request #65267 from xymus/serial-indirect-conformances
[Serialization] Keep indirect conformances knowledge with safety
2 parents b9f9eeb + 9602df1 commit cc0f42f

File tree

4 files changed

+66
-14
lines changed

4 files changed

+66
-14
lines changed

lib/Serialization/Serialization.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3124,14 +3124,11 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
31243124
if (hasSafeMembers)
31253125
return true;
31263126

3127-
// We can mark the extension unsafe only if it has no public
3127+
// We can mark the extension unsafe only if it has no public
31283128
// conformances.
31293129
auto protocols = ext->getLocalProtocols(
31303130
ConformanceLookupKind::OnlyExplicit);
3131-
bool hasSafeConformances = std::any_of(protocols.begin(),
3132-
protocols.end(),
3133-
isDeserializationSafe);
3134-
if (hasSafeConformances)
3131+
if (!protocols.empty())
31353132
return true;
31363133

31373134
// Truly empty extensions are safe, it may happen in swiftinterfaces.
@@ -3141,6 +3138,9 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
31413138
return false;
31423139
}
31433140

3141+
if (isa<ProtocolDecl>(decl))
3142+
return true;
3143+
31443144
auto value = cast<ValueDecl>(decl);
31453145

31463146
// A decl is safe if formally accessible publicly.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// REQUIRES: asserts
5+
6+
//--- Lib.swift
7+
8+
// RUN: %target-swift-frontend -emit-module %t/Lib.swift \
9+
// RUN: -enable-library-evolution -swift-version 5 \
10+
// RUN: -emit-module-path %t/Lib.swiftmodule \
11+
// RUN: -emit-module-interface-path %t/Lib.swiftinterface
12+
13+
// RUN: cat %t/Lib.swiftinterface | %FileCheck %t/Lib.swift
14+
15+
public protocol PublicProtocol : AnyObject {}
16+
// CHECK: public protocol PublicProtocol : AnyObject
17+
18+
protocol InternalProtocol: PublicProtocol {}
19+
// CHECK-NOT: InternalProtocol
20+
21+
public class IndirectConformant {
22+
public init() {}
23+
}
24+
extension IndirectConformant: InternalProtocol {}
25+
// CHECK: extension Lib.IndirectConformant : Lib.PublicProtocol {}
26+
27+
//--- Client.swift
28+
29+
/// Works without safety.
30+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t
31+
32+
/// Works with safety.
33+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \
34+
// RUN: -enable-deserialization-safety \
35+
// RUN: -Xllvm -debug-only=Serialization 2>&1 \
36+
// RUN: | %FileCheck %t/Client.swift
37+
38+
/// Works with swiftinterface.
39+
// RUN: rm %t/Lib.swiftmodule
40+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t
41+
42+
import Lib
43+
44+
func requireConformanceToPublicProtocol(_ a: PublicProtocol) {}
45+
requireConformanceToPublicProtocol(IndirectConformant())
46+
47+
/// Deserialization safety should keep the original chain. We're mostly
48+
/// documenting the current safety implementation details here, if we can get
49+
/// without deserializing 'InternalProtocol' it would be even better.
50+
// CHECK: Deserialized: 'IndirectConformant'
51+
// CHECK: Deserialized: 'PublicProtocol'
52+
// CHECK: Deserialized: 'InternalProtocol'

test/Serialization/Safety/unsafe-decls.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
public protocol PublicProto {}
3535
// SAFETY-PRIVATE: Serialization safety, safe: 'PublicProto'
3636
internal protocol InternalProto {}
37-
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalProto'
37+
// SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
3838
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
3939
private protocol PrivateProto {}
40-
// SAFETY-PRIVATE: Serialization safety, unsafe: 'PrivateProto'
40+
// SAFETY-PRIVATE: Serialization safety, safe: 'PrivateProto'
4141
fileprivate protocol FileprivateProto {}
42-
// SAFETY-PRIVATE: Serialization safety, unsafe: 'FileprivateProto'
42+
// SAFETY-PRIVATE: Serialization safety, safe: 'FileprivateProto'
4343

4444
internal struct InternalStruct : PublicProto {
4545
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalStruct'

test/Serialization/Safety/unsafe-extensions.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ extension ExtendedPublic : PublicProto {
4747

4848
/// Internal
4949
internal protocol InternalProto {}
50-
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalProto'
50+
// SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
5151
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
5252
internal struct ExtendedInternal {}
5353
// SAFETY-INTERNAL: Serialization safety, unsafe: 'ExtendedInternal'
@@ -63,7 +63,7 @@ extension ExtendedInternal : InternalProto {}
6363

6464
/// Private
6565
private protocol PrivateProto {}
66-
// SAFETY-PRIVATE: Serialization safety, unsafe: 'PrivateProto'
66+
// SAFETY-PRIVATE: Serialization safety, safe: 'PrivateProto'
6767
private struct ExtendedPrivate {}
6868
// SAFETY-PRIVATE: Serialization safety, unsafe: 'ExtendedPrivate'
6969
extension ExtendedPrivate {
@@ -75,7 +75,7 @@ extension ExtendedPrivate : PrivateProto {}
7575

7676
/// Fileprivate
7777
private protocol FileprivateProto {}
78-
// SAFETY-PRIVATE: Serialization safety, unsafe: 'FileprivateProto'
78+
// SAFETY-PRIVATE: Serialization safety, safe: 'FileprivateProto'
7979
private struct ExtendedFileprivate {}
8080
// SAFETY-PRIVATE: Serialization safety, unsafe: 'ExtendedFileprivate'
8181
extension ExtendedFileprivate {
@@ -87,14 +87,14 @@ extension ExtendedFileprivate : FileprivateProto {}
8787

8888
/// Back to public
8989
extension ExtendedPublic : InternalProto {
90-
// SAFETY-INTERNAL: Serialization safety, unsafe: 'extension ExtendedPublic'
90+
// SAFETY-INTERNAL: Serialization safety, safe: 'extension ExtendedPublic'
9191
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'extension ExtendedPublic'
9292
}
9393
extension ExtendedPublic : PrivateProto {
94-
// SAFETY-PRIVATE: Serialization safety, unsafe: 'extension ExtendedPublic'
94+
// SAFETY-PRIVATE: Serialization safety, safe: 'extension ExtendedPublic'
9595
}
9696
extension ExtendedPublic : FileprivateProto {
97-
// SAFETY-PRIVATE: Serialization safety, unsafe: 'extension ExtendedPublic'
97+
// SAFETY-PRIVATE: Serialization safety, safe: 'extension ExtendedPublic'
9898
}
9999

100100
extension ExtendedPublic {

0 commit comments

Comments
 (0)