mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #65267 from xymus/serial-indirect-conformances
[Serialization] Keep indirect conformances knowledge with safety
This commit is contained in:
@@ -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.
|
||||
|
||||
52
test/Serialization/Safety/indirect-conformance.swift
Normal file
52
test/Serialization/Safety/indirect-conformance.swift
Normal 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'
|
||||
@@ -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'
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user