Merge pull request #65267 from xymus/serial-indirect-conformances

[Serialization] Keep indirect conformances knowledge with safety
This commit is contained in:
Alexis Laferrière
2023-04-19 10:52:20 -07:00
committed by GitHub
4 changed files with 66 additions and 14 deletions

View File

@@ -3128,10 +3128,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
// conformances.
auto protocols = ext->getLocalProtocols(
ConformanceLookupKind::OnlyExplicit);
bool hasSafeConformances = std::any_of(protocols.begin(),
protocols.end(),
isDeserializationSafe);
if (hasSafeConformances)
if (!protocols.empty())
return true;
// Truly empty extensions are safe, it may happen in swiftinterfaces.
@@ -3141,6 +3138,9 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
return false;
}
if (isa<ProtocolDecl>(decl))
return true;
auto value = cast<ValueDecl>(decl);
// A decl is safe if formally accessible publicly.

View File

@@ -0,0 +1,52 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// REQUIRES: asserts
//--- Lib.swift
// RUN: %target-swift-frontend -emit-module %t/Lib.swift \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -emit-module-path %t/Lib.swiftmodule \
// RUN: -emit-module-interface-path %t/Lib.swiftinterface
// RUN: cat %t/Lib.swiftinterface | %FileCheck %t/Lib.swift
public protocol PublicProtocol : AnyObject {}
// CHECK: public protocol PublicProtocol : AnyObject
protocol InternalProtocol: PublicProtocol {}
// CHECK-NOT: InternalProtocol
public class IndirectConformant {
public init() {}
}
extension IndirectConformant: InternalProtocol {}
// CHECK: extension Lib.IndirectConformant : Lib.PublicProtocol {}
//--- Client.swift
/// Works without safety.
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t
/// Works with safety.
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \
// RUN: -enable-deserialization-safety \
// RUN: -Xllvm -debug-only=Serialization 2>&1 \
// RUN: | %FileCheck %t/Client.swift
/// Works with swiftinterface.
// RUN: rm %t/Lib.swiftmodule
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t
import Lib
func requireConformanceToPublicProtocol(_ a: PublicProtocol) {}
requireConformanceToPublicProtocol(IndirectConformant())
/// Deserialization safety should keep the original chain. We're mostly
/// documenting the current safety implementation details here, if we can get
/// without deserializing 'InternalProtocol' it would be even better.
// CHECK: Deserialized: 'IndirectConformant'
// CHECK: Deserialized: 'PublicProtocol'
// CHECK: Deserialized: 'InternalProtocol'

View File

@@ -34,12 +34,12 @@
public protocol PublicProto {}
// SAFETY-PRIVATE: Serialization safety, safe: 'PublicProto'
internal protocol InternalProto {}
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalProto'
// SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
private protocol PrivateProto {}
// SAFETY-PRIVATE: Serialization safety, unsafe: 'PrivateProto'
// SAFETY-PRIVATE: Serialization safety, safe: 'PrivateProto'
fileprivate protocol FileprivateProto {}
// SAFETY-PRIVATE: Serialization safety, unsafe: 'FileprivateProto'
// SAFETY-PRIVATE: Serialization safety, safe: 'FileprivateProto'
internal struct InternalStruct : PublicProto {
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalStruct'

View File

@@ -47,7 +47,7 @@ extension ExtendedPublic : PublicProto {
/// Internal
internal protocol InternalProto {}
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalProto'
// SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
internal struct ExtendedInternal {}
// SAFETY-INTERNAL: Serialization safety, unsafe: 'ExtendedInternal'
@@ -63,7 +63,7 @@ extension ExtendedInternal : InternalProto {}
/// Private
private protocol PrivateProto {}
// SAFETY-PRIVATE: Serialization safety, unsafe: 'PrivateProto'
// SAFETY-PRIVATE: Serialization safety, safe: 'PrivateProto'
private struct ExtendedPrivate {}
// SAFETY-PRIVATE: Serialization safety, unsafe: 'ExtendedPrivate'
extension ExtendedPrivate {
@@ -75,7 +75,7 @@ extension ExtendedPrivate : PrivateProto {}
/// Fileprivate
private protocol FileprivateProto {}
// SAFETY-PRIVATE: Serialization safety, unsafe: 'FileprivateProto'
// SAFETY-PRIVATE: Serialization safety, safe: 'FileprivateProto'
private struct ExtendedFileprivate {}
// SAFETY-PRIVATE: Serialization safety, unsafe: 'ExtendedFileprivate'
extension ExtendedFileprivate {
@@ -87,14 +87,14 @@ extension ExtendedFileprivate : FileprivateProto {}
/// Back to public
extension ExtendedPublic : InternalProto {
// SAFETY-INTERNAL: Serialization safety, unsafe: 'extension ExtendedPublic'
// SAFETY-INTERNAL: Serialization safety, safe: 'extension ExtendedPublic'
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'extension ExtendedPublic'
}
extension ExtendedPublic : PrivateProto {
// SAFETY-PRIVATE: Serialization safety, unsafe: 'extension ExtendedPublic'
// SAFETY-PRIVATE: Serialization safety, safe: 'extension ExtendedPublic'
}
extension ExtendedPublic : FileprivateProto {
// SAFETY-PRIVATE: Serialization safety, unsafe: 'extension ExtendedPublic'
// SAFETY-PRIVATE: Serialization safety, safe: 'extension ExtendedPublic'
}
extension ExtendedPublic {