Skip to content

Commit 93293c7

Browse files
authored
Merge pull request #24912 from slavapestov/drop-inherited-clause-entries
Serialization: Recover from failure to deserialize inheritance clause entries
2 parents deea9b1 + 5b2211d commit 93293c7

File tree

2 files changed

+84
-18
lines changed

2 files changed

+84
-18
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,13 +2301,23 @@ class swift::DeclDeserializer {
23012301
AttrsNext = Attr->getMutableNext();
23022302
};
23032303

2304-
void handleInherited(TypeDecl *nominal, ArrayRef<uint64_t> rawInheritedIDs) {
2305-
auto inheritedTypes = ctx.Allocate<TypeLoc>(rawInheritedIDs.size());
2306-
for_each(inheritedTypes, rawInheritedIDs,
2307-
[this](TypeLoc &tl, uint64_t rawID) {
2308-
tl = TypeLoc::withoutLoc(MF.getType(rawID));
2309-
});
2310-
nominal->setInherited(inheritedTypes);
2304+
void handleInherited(llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
2305+
ArrayRef<uint64_t> rawInheritedIDs) {
2306+
SmallVector<TypeLoc, 2> inheritedTypes;
2307+
for (auto rawID : rawInheritedIDs) {
2308+
auto maybeType = MF.getTypeChecked(rawID);
2309+
if (!maybeType) {
2310+
llvm::consumeError(maybeType.takeError());
2311+
continue;
2312+
}
2313+
inheritedTypes.push_back(TypeLoc::withoutLoc(MF.getType(rawID)));
2314+
}
2315+
2316+
auto inherited = ctx.AllocateCopy(inheritedTypes);
2317+
if (auto *typeDecl = decl.dyn_cast<TypeDecl *>())
2318+
typeDecl->setInherited(inherited);
2319+
else
2320+
decl.get<ExtensionDecl *>()->setInherited(inherited);
23112321
}
23122322

23132323
public:
@@ -3507,13 +3517,13 @@ class swift::DeclDeserializer {
35073517
GenericEnvironmentID genericEnvID;
35083518
TypeID rawTypeID;
35093519
uint8_t rawAccessLevel;
3510-
unsigned numConformances, numInheritedTypes;
3520+
unsigned numConformances, numInherited;
35113521
ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
35123522

35133523
decls_block::EnumLayout::readRecord(scratch, nameID, contextID,
35143524
isImplicit, isObjC, genericEnvID,
35153525
rawTypeID, rawAccessLevel,
3516-
numConformances, numInheritedTypes,
3526+
numConformances, numInherited,
35173527
rawInheritedAndDependencyIDs);
35183528

35193529
auto DC = MF.getDeclContext(contextID);
@@ -3522,7 +3532,7 @@ class swift::DeclDeserializer {
35223532

35233533
Identifier name = MF.getIdentifier(nameID);
35243534
for (TypeID dependencyID :
3525-
rawInheritedAndDependencyIDs.slice(numInheritedTypes)) {
3535+
rawInheritedAndDependencyIDs.slice(numInherited)) {
35263536
auto dependency = MF.getTypeChecked(dependencyID);
35273537
if (!dependency) {
35283538
return llvm::make_error<TypeError>(
@@ -3557,8 +3567,8 @@ class swift::DeclDeserializer {
35573567

35583568
theEnum->computeType();
35593569

3560-
handleInherited(theEnum,
3561-
rawInheritedAndDependencyIDs.slice(0, numInheritedTypes));
3570+
auto rawInheritedIDs = rawInheritedAndDependencyIDs.slice(0, numInherited);
3571+
handleInherited(theEnum, rawInheritedIDs);
35623572

35633573
theEnum->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
35643574
skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
@@ -3816,12 +3826,8 @@ class swift::DeclDeserializer {
38163826
if (isImplicit)
38173827
extension->setImplicit();
38183828

3819-
auto inheritedTypes = ctx.Allocate<TypeLoc>(numInherited);
3820-
for_each(inheritedTypes, inheritedAndDependencyIDs.slice(0, numInherited),
3821-
[this](TypeLoc &tl, uint64_t rawID) {
3822-
tl = TypeLoc::withoutLoc(MF.getType(rawID));
3823-
});
3824-
extension->setInherited(inheritedTypes);
3829+
auto rawInheritedIDs = inheritedAndDependencyIDs.slice(0, numInherited);
3830+
handleInherited(extension, rawInheritedIDs);
38253831

38263832
extension->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
38273833
skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// Build the protocol library and conforming library to include PrivateProtocol.
4+
// RUN: %target-swift-frontend -emit-module -DPROTOCOL_LIB -DBEFORE %s -module-name protocol_lib -emit-module-path %t/protocol_lib.swiftmodule
5+
// RUN: %target-swift-frontend -emit-module -DCONFORMS_LIB %s -module-name conforms_lib -emit-module-path %t/conforms_lib.swiftmodule -I %t
6+
// RUN: %target-swift-frontend -emit-module -DINHERITS_LIB %s -module-name inherits_lib -emit-module-path %t/inherits_lib.swiftmodule -I %t
7+
8+
// Rebuild the protocol library to omit PrivateProtocol.
9+
// RUN: %target-swift-frontend -emit-module -DPROTOCOL_LIB -DAFTER %s -module-name protocol_lib -emit-module-path %t/protocol_lib.swiftmodule
10+
11+
// The conforming library's types should still deserialize.
12+
// RUN: %target-swift-ide-test -print-module -source-filename %s -D CONFORMS_LIB -module-to-print conforms_lib -I %t | %FileCheck %s
13+
14+
// Make sure we *cannot* recover from a missing inherited protocol.
15+
// RUN: not --crash %target-swift-ide-test -print-module -source-filename %s -D INHERITS_LIB -module-to-print inherits_lib -I %t
16+
17+
#if PROTOCOL_LIB
18+
19+
#if BEFORE
20+
public protocol PrivateProtocol {}
21+
#endif
22+
23+
#elseif CONFORMS_LIB
24+
import protocol_lib
25+
26+
public protocol PublicProtocol {}
27+
28+
// CHECK: class C1 : PublicProtocol {
29+
public class C1 : PrivateProtocol, PublicProtocol {}
30+
31+
// CHECK: class C2 {
32+
public class C2 {}
33+
34+
// CHECK: extension C2 : PublicProtocol {
35+
extension C2 : PrivateProtocol, PublicProtocol {}
36+
37+
// CHECK: enum E1 : PublicProtocol {
38+
public enum E1 : PrivateProtocol, PublicProtocol {}
39+
40+
// CHECK: enum E2 {
41+
public enum E2 {}
42+
43+
// CHECK: extension E2 : PublicProtocol {
44+
extension E2 : PrivateProtocol, PublicProtocol {}
45+
46+
// CHECK: struct S1 : PublicProtocol {
47+
public struct S1 : PrivateProtocol, PublicProtocol {}
48+
49+
// CHECK: struct S2 {
50+
public struct S2 {}
51+
52+
// CHECK: extension S2 : PublicProtocol {
53+
extension S2 : PrivateProtocol, PublicProtocol {}
54+
55+
#elseif INHERITS_LIB
56+
import protocol_lib
57+
58+
public protocol InheritsPrivateProtocol : PrivateProtocol {}
59+
60+
#endif

0 commit comments

Comments
 (0)