Skip to content

Commit 378d341

Browse files
authored
Merge pull request #27111 from xymus/fix-index-deser-5.1-08-28
Serialization: recover from missing modules when reading SubstitutionMaps [5.1 08-28]
2 parents 8c71f89 + dcaf945 commit 378d341

File tree

4 files changed

+192
-30
lines changed

4 files changed

+192
-30
lines changed

include/swift/Serialization/ModuleFile.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,12 @@ class ModuleFile
592592
void readGenericRequirements(SmallVectorImpl<Requirement> &requirements,
593593
llvm::BitstreamCursor &Cursor);
594594

595+
/// Reads a set of requirements from \c DeclTypeCursor, returns the first
596+
/// error, if any.
597+
llvm::Error
598+
readGenericRequirementsChecked(SmallVectorImpl<Requirement> &requirements,
599+
llvm::BitstreamCursor &Cursor);
600+
595601
/// Set up a (potentially lazy) generic environment for the given type,
596602
/// function or extension.
597603
void configureGenericEnvironment(
@@ -884,7 +890,6 @@ class ModuleFile
884890
/// Returns the decl with the given ID, deserializing it if needed.
885891
///
886892
/// \param DID The ID for the decl within this module.
887-
888893
/// \sa getDeclChecked
889894
Decl *getDecl(serialization::DeclID DID);
890895

@@ -912,6 +917,10 @@ class ModuleFile
912917
/// Returns the generic signature for the given ID.
913918
GenericSignature *getGenericSignature(serialization::GenericSignatureID ID);
914919

920+
/// Returns the generic signature for the given ID or the first error.
921+
llvm::Expected<GenericSignature *>
922+
getGenericSignatureChecked(serialization::GenericSignatureID ID);
923+
915924
/// Returns the generic signature or environment for the given ID,
916925
/// deserializing it if needed.
917926
///
@@ -931,11 +940,22 @@ class ModuleFile
931940
/// needed.
932941
SubstitutionMap getSubstitutionMap(serialization::SubstitutionMapID id);
933942

943+
/// Returns the substitution map for the given ID, deserializing it if
944+
/// needed, or the first error.
945+
llvm::Expected<SubstitutionMap>
946+
getSubstitutionMapChecked(serialization::SubstitutionMapID id);
947+
934948
/// Recursively reads a protocol conformance from the given cursor.
935949
ProtocolConformanceRef readConformance(llvm::BitstreamCursor &Cursor,
936950
GenericEnvironment *genericEnv =
937951
nullptr);
938-
952+
953+
/// Recursively reads a protocol conformance from the given cursor,
954+
/// returns the conformance or the first error.
955+
llvm::Expected<ProtocolConformanceRef>
956+
readConformanceChecked(llvm::BitstreamCursor &Cursor,
957+
GenericEnvironment *genericEnv = nullptr);
958+
939959
/// Read a SILLayout from the given cursor.
940960
SILLayout *readSILLayout(llvm::BitstreamCursor &Cursor);
941961

lib/Serialization/Deserialization.cpp

Lines changed: 110 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,15 @@ SILLayout *ModuleFile::readSILLayout(llvm::BitstreamCursor &Cursor) {
458458
ProtocolConformanceRef ModuleFile::readConformance(
459459
llvm::BitstreamCursor &Cursor,
460460
GenericEnvironment *genericEnv) {
461+
auto conformance = readConformanceChecked(Cursor, genericEnv);
462+
if (!conformance)
463+
fatal(conformance.takeError());
464+
return conformance.get();
465+
}
466+
467+
Expected<ProtocolConformanceRef>
468+
ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor,
469+
GenericEnvironment *genericEnv) {
461470
using namespace decls_block;
462471

463472
SmallVector<uint64_t, 16> scratch;
@@ -477,14 +486,24 @@ ProtocolConformanceRef ModuleFile::readConformance(
477486
case ABSTRACT_PROTOCOL_CONFORMANCE: {
478487
DeclID protoID;
479488
AbstractProtocolConformanceLayout::readRecord(scratch, protoID);
480-
auto proto = cast<ProtocolDecl>(getDecl(protoID));
489+
490+
auto decl = getDeclChecked(protoID);
491+
if (!decl)
492+
return decl.takeError();
493+
494+
auto proto = cast<ProtocolDecl>(decl.get());
481495
return ProtocolConformanceRef(proto);
482496
}
483497

484498
case SELF_PROTOCOL_CONFORMANCE: {
485499
DeclID protoID;
486500
SelfProtocolConformanceLayout::readRecord(scratch, protoID);
487-
auto proto = cast<ProtocolDecl>(getDecl(protoID));
501+
502+
auto decl = getDeclChecked(protoID);
503+
if (!decl)
504+
return decl.takeError();
505+
506+
auto proto = cast<ProtocolDecl>(decl.get());
488507
auto conformance = getContext().getSelfConformance(proto);
489508
return ProtocolConformanceRef(conformance);
490509
}
@@ -696,6 +715,14 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
696715
void ModuleFile::readGenericRequirements(
697716
SmallVectorImpl<Requirement> &requirements,
698717
llvm::BitstreamCursor &Cursor) {
718+
auto error = readGenericRequirementsChecked(requirements, Cursor);
719+
if (error)
720+
fatal(std::move(error));
721+
}
722+
723+
llvm::Error ModuleFile::readGenericRequirementsChecked(
724+
SmallVectorImpl<Requirement> &requirements,
725+
llvm::BitstreamCursor &Cursor) {
699726
using namespace decls_block;
700727

701728
BCOffsetRAII lastRecordOffset(Cursor);
@@ -721,27 +748,42 @@ void ModuleFile::readGenericRequirements(
721748

722749
switch (rawKind) {
723750
case GenericRequirementKind::Conformance: {
724-
auto subject = getType(rawTypeIDs[0]);
725-
auto constraint = getType(rawTypeIDs[1]);
751+
auto subject = getTypeChecked(rawTypeIDs[0]);
752+
if (!subject)
753+
return subject.takeError();
754+
755+
auto constraint = getTypeChecked(rawTypeIDs[1]);
756+
if (!constraint)
757+
return constraint.takeError();
726758

727759
requirements.push_back(Requirement(RequirementKind::Conformance,
728-
subject, constraint));
760+
subject.get(), constraint.get()));
729761
break;
730762
}
731763
case GenericRequirementKind::Superclass: {
732-
auto subject = getType(rawTypeIDs[0]);
733-
auto constraint = getType(rawTypeIDs[1]);
764+
auto subject = getTypeChecked(rawTypeIDs[0]);
765+
if (!subject)
766+
return subject.takeError();
767+
768+
auto constraint = getTypeChecked(rawTypeIDs[1]);
769+
if (!constraint)
770+
return constraint.takeError();
734771

735772
requirements.push_back(Requirement(RequirementKind::Superclass,
736-
subject, constraint));
773+
subject.get(), constraint.get()));
737774
break;
738775
}
739776
case GenericRequirementKind::SameType: {
740-
auto first = getType(rawTypeIDs[0]);
741-
auto second = getType(rawTypeIDs[1]);
777+
auto first = getTypeChecked(rawTypeIDs[0]);
778+
if (!first)
779+
return first.takeError();
780+
781+
auto second = getTypeChecked(rawTypeIDs[1]);
782+
if (!second)
783+
return second.takeError();
742784

743785
requirements.push_back(Requirement(RequirementKind::SameType,
744-
first, second));
786+
first.get(), second.get()));
745787
break;
746788
}
747789
default:
@@ -759,7 +801,10 @@ void ModuleFile::readGenericRequirements(
759801
LayoutRequirementLayout::readRecord(scratch, rawKind, rawTypeID,
760802
size, alignment);
761803

762-
auto first = getType(rawTypeID);
804+
auto first = getTypeChecked(rawTypeID);
805+
if (!first)
806+
return first.takeError();
807+
763808
LayoutConstraint layout;
764809
LayoutConstraintKind kind = LayoutConstraintKind::UnknownLayout;
765810
switch (rawKind) {
@@ -803,7 +848,7 @@ void ModuleFile::readGenericRequirements(
803848
LayoutConstraint::getLayoutConstraint(kind, size, alignment, ctx);
804849

805850
requirements.push_back(
806-
Requirement(RequirementKind::Layout, first, layout));
851+
Requirement(RequirementKind::Layout, first.get(), layout));
807852
break;
808853
}
809854
default:
@@ -815,6 +860,8 @@ void ModuleFile::readGenericRequirements(
815860
if (!shouldContinue)
816861
break;
817862
}
863+
864+
return llvm::Error::success();
818865
}
819866

820867
/// Advances past any records that might be part of a requirement signature.
@@ -866,7 +913,15 @@ void ModuleFile::configureGenericEnvironment(
866913
}
867914

868915
GenericSignature *ModuleFile::getGenericSignature(
869-
serialization::GenericSignatureID ID) {
916+
serialization::GenericSignatureID ID) {
917+
auto signature = getGenericSignatureChecked(ID);
918+
if (!signature)
919+
fatal(signature.takeError());
920+
return signature.get();
921+
}
922+
923+
Expected<GenericSignature *>
924+
ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) {
870925
using namespace decls_block;
871926

872927
// Zero is a sentinel for having no generic signature.
@@ -912,7 +967,9 @@ GenericSignature *ModuleFile::getGenericSignature(
912967

913968
// Read the generic requirements.
914969
SmallVector<Requirement, 4> requirements;
915-
readGenericRequirements(requirements, DeclTypeCursor);
970+
auto error = readGenericRequirementsChecked(requirements, DeclTypeCursor);
971+
if (error)
972+
return std::move(error);
916973

917974
// Construct the generic signature from the loaded parameters and
918975
// requirements.
@@ -1040,6 +1097,12 @@ ModuleFile::getGenericSignatureOrEnvironment(
10401097
auto genericEnv = signature->createGenericEnvironment();
10411098
envOrOffset = genericEnv;
10421099

1100+
//// Read the generic requirements.
1101+
//SmallVector<Requirement, 4> requirements;
1102+
//auto error = readGenericRequirementsChecked(requirements, DeclTypeCursor);
1103+
//if (error)
1104+
// return std::move(error);
1105+
10431106
return genericEnv;
10441107
}
10451108

@@ -1051,6 +1114,14 @@ GenericEnvironment *ModuleFile::getGenericEnvironment(
10511114

10521115
SubstitutionMap ModuleFile::getSubstitutionMap(
10531116
serialization::SubstitutionMapID id) {
1117+
auto map = getSubstitutionMapChecked(id);
1118+
if (!map)
1119+
fatal(map.takeError());
1120+
return map.get();
1121+
}
1122+
1123+
Expected<SubstitutionMap>
1124+
ModuleFile::getSubstitutionMapChecked(serialization::SubstitutionMapID id) {
10541125
using namespace decls_block;
10551126

10561127
// Zero is a sentinel for having an empty substitution map.
@@ -1091,7 +1162,11 @@ SubstitutionMap ModuleFile::getSubstitutionMap(
10911162
replacementTypeIDs);
10921163

10931164
// Generic signature.
1094-
auto genericSig = getGenericSignature(genericSigID);
1165+
auto genericSigOrError = getGenericSignatureChecked(genericSigID);
1166+
if (!genericSigOrError)
1167+
return genericSigOrError.takeError();
1168+
1169+
auto genericSig = genericSigOrError.get();
10951170
if (!genericSig) {
10961171
error();
10971172
return SubstitutionMap();
@@ -5021,9 +5096,13 @@ class swift::TypeDeserializer {
50215096

50225097
decls_block::DependentMemberTypeLayout::readRecord(scratch, baseID,
50235098
assocTypeID);
5099+
auto assocType = MF.getDeclChecked(assocTypeID);
5100+
if (!assocType)
5101+
return assocType.takeError();
5102+
50245103
return DependentMemberType::get(
50255104
MF.getType(baseID),
5026-
cast<AssociatedTypeDecl>(MF.getDecl(assocTypeID)));
5105+
cast<AssociatedTypeDecl>(assocType.get()));
50275106
}
50285107

50295108
Expected<Type> deserializeBoundGenericType(ArrayRef<uint64_t> scratch,
@@ -5733,23 +5812,26 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
57335812
continue;
57345813
}
57355814

5736-
// Generic environment.
5737-
GenericEnvironment *syntheticEnv = nullptr;
5738-
57395815
auto trySetOpaqueWitness = [&]{
57405816
if (!req)
57415817
return;
5742-
5743-
// We shouldn't yet need to worry about generic requirements, since
5744-
// an imported ObjC method should never be generic.
5745-
assert(syntheticEnv == nullptr &&
5746-
"opaque witness shouldn't be generic yet. when this is "
5747-
"possible, it should use forwarding substitutions");
5818+
57485819
conformance->setWitness(req, Witness::forOpaque(req));
57495820
};
57505821

57515822
// Witness substitutions.
5752-
SubstitutionMap witnessSubstitutions = getSubstitutionMap(*rawIDIter++);
5823+
auto witnessSubstitutions = getSubstitutionMapChecked(*rawIDIter++);
5824+
if (!witnessSubstitutions) {
5825+
// Missing module errors are most likely caused by an
5826+
// implementation-only import hiding types and decls.
5827+
// rdar://problem/52837313
5828+
if (witnessSubstitutions.errorIsA<XRefNonLoadedModuleError>()) {
5829+
consumeError(witnessSubstitutions.takeError());
5830+
isOpaque = true;
5831+
}
5832+
else
5833+
fatal(witnessSubstitutions.takeError());
5834+
}
57535835

57545836
// Handle opaque witnesses that couldn't be deserialized.
57555837
if (isOpaque) {
@@ -5758,7 +5840,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
57585840
}
57595841

57605842
// Set the witness.
5761-
trySetWitness(Witness::forDeserialized(witness, witnessSubstitutions));
5843+
trySetWitness(Witness::forDeserialized(witness, witnessSubstitutions.get()));
57625844
}
57635845
assert(rawIDIter <= rawIDs.end() && "read too much");
57645846

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module public_lib [system] {}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Recover from missing types hidden behind an importation-only when indexing
2+
// a system module.
3+
// rdar://problem/52837313
4+
5+
// RUN: %empty-directory(%t)
6+
7+
//// Build the private module, the public module and the client app normally.
8+
//// Force the public module to be system with an underlying Clang module.
9+
// RUN: %target-swift-frontend -emit-module -DPRIVATE_LIB %s -module-name private_lib -emit-module-path %t/private_lib.swiftmodule
10+
// RUN: %target-swift-frontend -emit-module -DPUBLIC_LIB %s -module-name public_lib -emit-module-path %t/public_lib.swiftmodule -I %t -I %S/Inputs/implementation-only-missing -import-underlying-module
11+
12+
//// The client app should build OK without the private module. Removing the
13+
//// private module is superfluous but makes sure that it's not somehow loaded.
14+
// RUN: rm %t/private_lib.swiftmodule
15+
// RUN: %target-swift-frontend -typecheck -DCLIENT_APP -primary-file %s -I %t -index-system-modules -index-store-path %t
16+
17+
#if PRIVATE_LIB
18+
19+
public struct HiddenGenStruct<A: HiddenProtocol> {
20+
public init() {}
21+
}
22+
23+
public protocol HiddenProtocol {
24+
associatedtype Value
25+
}
26+
27+
#elseif PUBLIC_LIB
28+
29+
@_implementationOnly import private_lib
30+
31+
struct LibProtocolContraint { }
32+
33+
protocol LibProtocolTABound { }
34+
struct LibProtocolTA: LibProtocolTABound { }
35+
36+
protocol LibProtocol {
37+
associatedtype TA: LibProtocolTABound = LibProtocolTA
38+
39+
func hiddenRequirement<A>(
40+
param: HiddenGenStruct<A>
41+
) where A.Value == LibProtocolContraint
42+
}
43+
44+
extension LibProtocol where TA == LibProtocolTA {
45+
func hiddenRequirement<A>(
46+
param: HiddenGenStruct<A>
47+
) where A.Value == LibProtocolContraint { }
48+
}
49+
50+
public struct PublicStruct: LibProtocol {
51+
typealias TA = LibProtocolTA
52+
public init() { }
53+
}
54+
55+
#elseif CLIENT_APP
56+
57+
import public_lib
58+
59+
#endif

0 commit comments

Comments
 (0)