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:
@@ -3124,14 +3124,11 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
|
|||||||
if (hasSafeMembers)
|
if (hasSafeMembers)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// We can mark the extension unsafe only if it has no public
|
// We can mark the extension unsafe only if it has no public
|
||||||
// conformances.
|
// conformances.
|
||||||
auto protocols = ext->getLocalProtocols(
|
auto protocols = ext->getLocalProtocols(
|
||||||
ConformanceLookupKind::OnlyExplicit);
|
ConformanceLookupKind::OnlyExplicit);
|
||||||
bool hasSafeConformances = std::any_of(protocols.begin(),
|
if (!protocols.empty())
|
||||||
protocols.end(),
|
|
||||||
isDeserializationSafe);
|
|
||||||
if (hasSafeConformances)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Truly empty extensions are safe, it may happen in swiftinterfaces.
|
// Truly empty extensions are safe, it may happen in swiftinterfaces.
|
||||||
@@ -3141,6 +3138,9 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isa<ProtocolDecl>(decl))
|
||||||
|
return true;
|
||||||
|
|
||||||
auto value = cast<ValueDecl>(decl);
|
auto value = cast<ValueDecl>(decl);
|
||||||
|
|
||||||
// A decl is safe if formally accessible publicly.
|
// 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 {}
|
public protocol PublicProto {}
|
||||||
// SAFETY-PRIVATE: Serialization safety, safe: 'PublicProto'
|
// SAFETY-PRIVATE: Serialization safety, safe: 'PublicProto'
|
||||||
internal protocol InternalProto {}
|
internal protocol InternalProto {}
|
||||||
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalProto'
|
// SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
|
||||||
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
|
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
|
||||||
private protocol PrivateProto {}
|
private protocol PrivateProto {}
|
||||||
// SAFETY-PRIVATE: Serialization safety, unsafe: 'PrivateProto'
|
// SAFETY-PRIVATE: Serialization safety, safe: 'PrivateProto'
|
||||||
fileprivate protocol FileprivateProto {}
|
fileprivate protocol FileprivateProto {}
|
||||||
// SAFETY-PRIVATE: Serialization safety, unsafe: 'FileprivateProto'
|
// SAFETY-PRIVATE: Serialization safety, safe: 'FileprivateProto'
|
||||||
|
|
||||||
internal struct InternalStruct : PublicProto {
|
internal struct InternalStruct : PublicProto {
|
||||||
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalStruct'
|
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalStruct'
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ extension ExtendedPublic : PublicProto {
|
|||||||
|
|
||||||
/// Internal
|
/// Internal
|
||||||
internal protocol InternalProto {}
|
internal protocol InternalProto {}
|
||||||
// SAFETY-INTERNAL: Serialization safety, unsafe: 'InternalProto'
|
// SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
|
||||||
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
|
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'InternalProto'
|
||||||
internal struct ExtendedInternal {}
|
internal struct ExtendedInternal {}
|
||||||
// SAFETY-INTERNAL: Serialization safety, unsafe: 'ExtendedInternal'
|
// SAFETY-INTERNAL: Serialization safety, unsafe: 'ExtendedInternal'
|
||||||
@@ -63,7 +63,7 @@ extension ExtendedInternal : InternalProto {}
|
|||||||
|
|
||||||
/// Private
|
/// Private
|
||||||
private protocol PrivateProto {}
|
private protocol PrivateProto {}
|
||||||
// SAFETY-PRIVATE: Serialization safety, unsafe: 'PrivateProto'
|
// SAFETY-PRIVATE: Serialization safety, safe: 'PrivateProto'
|
||||||
private struct ExtendedPrivate {}
|
private struct ExtendedPrivate {}
|
||||||
// SAFETY-PRIVATE: Serialization safety, unsafe: 'ExtendedPrivate'
|
// SAFETY-PRIVATE: Serialization safety, unsafe: 'ExtendedPrivate'
|
||||||
extension ExtendedPrivate {
|
extension ExtendedPrivate {
|
||||||
@@ -75,7 +75,7 @@ extension ExtendedPrivate : PrivateProto {}
|
|||||||
|
|
||||||
/// Fileprivate
|
/// Fileprivate
|
||||||
private protocol FileprivateProto {}
|
private protocol FileprivateProto {}
|
||||||
// SAFETY-PRIVATE: Serialization safety, unsafe: 'FileprivateProto'
|
// SAFETY-PRIVATE: Serialization safety, safe: 'FileprivateProto'
|
||||||
private struct ExtendedFileprivate {}
|
private struct ExtendedFileprivate {}
|
||||||
// SAFETY-PRIVATE: Serialization safety, unsafe: 'ExtendedFileprivate'
|
// SAFETY-PRIVATE: Serialization safety, unsafe: 'ExtendedFileprivate'
|
||||||
extension ExtendedFileprivate {
|
extension ExtendedFileprivate {
|
||||||
@@ -87,14 +87,14 @@ extension ExtendedFileprivate : FileprivateProto {}
|
|||||||
|
|
||||||
/// Back to public
|
/// Back to public
|
||||||
extension ExtendedPublic : InternalProto {
|
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'
|
// NO-SAFETY-INTERNAL: Serialization safety, safe: 'extension ExtendedPublic'
|
||||||
}
|
}
|
||||||
extension ExtendedPublic : PrivateProto {
|
extension ExtendedPublic : PrivateProto {
|
||||||
// SAFETY-PRIVATE: Serialization safety, unsafe: 'extension ExtendedPublic'
|
// SAFETY-PRIVATE: Serialization safety, safe: 'extension ExtendedPublic'
|
||||||
}
|
}
|
||||||
extension ExtendedPublic : FileprivateProto {
|
extension ExtendedPublic : FileprivateProto {
|
||||||
// SAFETY-PRIVATE: Serialization safety, unsafe: 'extension ExtendedPublic'
|
// SAFETY-PRIVATE: Serialization safety, safe: 'extension ExtendedPublic'
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ExtendedPublic {
|
extension ExtendedPublic {
|
||||||
|
|||||||
Reference in New Issue
Block a user