Skip to content

Commit f5ad014

Browse files
authored
Merge pull request swiftlang#27074 from xymus/fix-index-deser
serialization: recover from missing modules when reading SubstitutionMaps
2 parents 94c7d04 + 7ce8614 commit f5ad014

File tree

4 files changed

+184
-28
lines changed

4 files changed

+184
-28
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 103 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,15 @@ SILLayout *ModuleFile::readSILLayout(llvm::BitstreamCursor &Cursor) {
431431
ProtocolConformanceRef ModuleFile::readConformance(
432432
llvm::BitstreamCursor &Cursor,
433433
GenericEnvironment *genericEnv) {
434+
auto conformance = readConformanceChecked(Cursor, genericEnv);
435+
if (!conformance)
436+
fatal(conformance.takeError());
437+
return conformance.get();
438+
}
439+
440+
Expected<ProtocolConformanceRef>
441+
ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor,
442+
GenericEnvironment *genericEnv) {
434443
using namespace decls_block;
435444

436445
SmallVector<uint64_t, 16> scratch;
@@ -450,14 +459,24 @@ ProtocolConformanceRef ModuleFile::readConformance(
450459
case ABSTRACT_PROTOCOL_CONFORMANCE: {
451460
DeclID protoID;
452461
AbstractProtocolConformanceLayout::readRecord(scratch, protoID);
453-
auto proto = cast<ProtocolDecl>(getDecl(protoID));
462+
463+
auto decl = getDeclChecked(protoID);
464+
if (!decl)
465+
return decl.takeError();
466+
467+
auto proto = cast<ProtocolDecl>(decl.get());
454468
return ProtocolConformanceRef(proto);
455469
}
456470

457471
case SELF_PROTOCOL_CONFORMANCE: {
458472
DeclID protoID;
459473
SelfProtocolConformanceLayout::readRecord(scratch, protoID);
460-
auto proto = cast<ProtocolDecl>(getDecl(protoID));
474+
475+
auto decl = getDeclChecked(protoID);
476+
if (!decl)
477+
return decl.takeError();
478+
479+
auto proto = cast<ProtocolDecl>(decl.get());
461480
auto conformance = getContext().getSelfConformance(proto);
462481
return ProtocolConformanceRef(conformance);
463482
}
@@ -663,6 +682,14 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
663682
void ModuleFile::readGenericRequirements(
664683
SmallVectorImpl<Requirement> &requirements,
665684
llvm::BitstreamCursor &Cursor) {
685+
auto error = readGenericRequirementsChecked(requirements, Cursor);
686+
if (error)
687+
fatal(std::move(error));
688+
}
689+
690+
llvm::Error ModuleFile::readGenericRequirementsChecked(
691+
SmallVectorImpl<Requirement> &requirements,
692+
llvm::BitstreamCursor &Cursor) {
666693
using namespace decls_block;
667694

668695
BCOffsetRAII lastRecordOffset(Cursor);
@@ -688,27 +715,42 @@ void ModuleFile::readGenericRequirements(
688715

689716
switch (rawKind) {
690717
case GenericRequirementKind::Conformance: {
691-
auto subject = getType(rawTypeIDs[0]);
692-
auto constraint = getType(rawTypeIDs[1]);
718+
auto subject = getTypeChecked(rawTypeIDs[0]);
719+
if (!subject)
720+
return subject.takeError();
721+
722+
auto constraint = getTypeChecked(rawTypeIDs[1]);
723+
if (!constraint)
724+
return constraint.takeError();
693725

694726
requirements.push_back(Requirement(RequirementKind::Conformance,
695-
subject, constraint));
727+
subject.get(), constraint.get()));
696728
break;
697729
}
698730
case GenericRequirementKind::Superclass: {
699-
auto subject = getType(rawTypeIDs[0]);
700-
auto constraint = getType(rawTypeIDs[1]);
731+
auto subject = getTypeChecked(rawTypeIDs[0]);
732+
if (!subject)
733+
return subject.takeError();
734+
735+
auto constraint = getTypeChecked(rawTypeIDs[1]);
736+
if (!constraint)
737+
return constraint.takeError();
701738

702739
requirements.push_back(Requirement(RequirementKind::Superclass,
703-
subject, constraint));
740+
subject.get(), constraint.get()));
704741
break;
705742
}
706743
case GenericRequirementKind::SameType: {
707-
auto first = getType(rawTypeIDs[0]);
708-
auto second = getType(rawTypeIDs[1]);
744+
auto first = getTypeChecked(rawTypeIDs[0]);
745+
if (!first)
746+
return first.takeError();
747+
748+
auto second = getTypeChecked(rawTypeIDs[1]);
749+
if (!second)
750+
return second.takeError();
709751

710752
requirements.push_back(Requirement(RequirementKind::SameType,
711-
first, second));
753+
first.get(), second.get()));
712754
break;
713755
}
714756
default:
@@ -725,7 +767,10 @@ void ModuleFile::readGenericRequirements(
725767
LayoutRequirementLayout::readRecord(scratch, rawKind, rawTypeID,
726768
size, alignment);
727769

728-
auto first = getType(rawTypeID);
770+
auto first = getTypeChecked(rawTypeID);
771+
if (!first)
772+
return first.takeError();
773+
729774
LayoutConstraint layout;
730775
LayoutConstraintKind kind = LayoutConstraintKind::UnknownLayout;
731776
switch (rawKind) {
@@ -767,7 +812,7 @@ void ModuleFile::readGenericRequirements(
767812
LayoutConstraint::getLayoutConstraint(kind, size, alignment, ctx);
768813

769814
requirements.push_back(
770-
Requirement(RequirementKind::Layout, first, layout));
815+
Requirement(RequirementKind::Layout, first.get(), layout));
771816
break;
772817
}
773818
default:
@@ -779,6 +824,8 @@ void ModuleFile::readGenericRequirements(
779824
if (!shouldContinue)
780825
break;
781826
}
827+
828+
return llvm::Error::success();
782829
}
783830

784831
/// Advances past any records that might be part of a requirement signature.
@@ -809,6 +856,14 @@ static void skipGenericRequirements(llvm::BitstreamCursor &Cursor) {
809856

810857
GenericSignature *ModuleFile::getGenericSignature(
811858
serialization::GenericSignatureID ID) {
859+
auto signature = getGenericSignatureChecked(ID);
860+
if (!signature)
861+
fatal(signature.takeError());
862+
return signature.get();
863+
}
864+
865+
Expected<GenericSignature *>
866+
ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) {
812867
using namespace decls_block;
813868

814869
// Zero is a sentinel for having no generic signature.
@@ -880,7 +935,9 @@ GenericSignature *ModuleFile::getGenericSignature(
880935

881936
// Read the generic requirements.
882937
SmallVector<Requirement, 4> requirements;
883-
readGenericRequirements(requirements, DeclTypeCursor);
938+
auto error = readGenericRequirementsChecked(requirements, DeclTypeCursor);
939+
if (error)
940+
return std::move(error);
884941

885942
// If we've already deserialized this generic signature, start over to return
886943
// it directly.
@@ -897,6 +954,14 @@ GenericSignature *ModuleFile::getGenericSignature(
897954

898955
SubstitutionMap ModuleFile::getSubstitutionMap(
899956
serialization::SubstitutionMapID id) {
957+
auto map = getSubstitutionMapChecked(id);
958+
if (!map)
959+
fatal(map.takeError());
960+
return map.get();
961+
}
962+
963+
Expected<SubstitutionMap>
964+
ModuleFile::getSubstitutionMapChecked(serialization::SubstitutionMapID id) {
900965
using namespace decls_block;
901966

902967
// Zero is a sentinel for having an empty substitution map.
@@ -932,7 +997,11 @@ SubstitutionMap ModuleFile::getSubstitutionMap(
932997
replacementTypeIDs);
933998

934999
// Generic signature.
935-
auto genericSig = getGenericSignature(genericSigID);
1000+
auto genericSigOrError = getGenericSignatureChecked(genericSigID);
1001+
if (!genericSigOrError)
1002+
return genericSigOrError.takeError();
1003+
1004+
auto genericSig = genericSigOrError.get();
9361005
if (!genericSig)
9371006
fatal();
9381007

@@ -4759,9 +4828,13 @@ class swift::TypeDeserializer {
47594828

47604829
decls_block::DependentMemberTypeLayout::readRecord(scratch, baseID,
47614830
assocTypeID);
4831+
auto assocType = MF.getDeclChecked(assocTypeID);
4832+
if (!assocType)
4833+
return assocType.takeError();
4834+
47624835
return DependentMemberType::get(
47634836
MF.getType(baseID),
4764-
cast<AssociatedTypeDecl>(MF.getDecl(assocTypeID)));
4837+
cast<AssociatedTypeDecl>(assocType.get()));
47654838
}
47664839

47674840
Expected<Type> deserializeBoundGenericType(ArrayRef<uint64_t> scratch,
@@ -5436,23 +5509,26 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
54365509
continue;
54375510
}
54385511

5439-
// Generic environment.
5440-
GenericEnvironment *syntheticEnv = nullptr;
5441-
54425512
auto trySetOpaqueWitness = [&]{
54435513
if (!req)
54445514
return;
5445-
5446-
// We shouldn't yet need to worry about generic requirements, since
5447-
// an imported ObjC method should never be generic.
5448-
assert(syntheticEnv == nullptr &&
5449-
"opaque witness shouldn't be generic yet. when this is "
5450-
"possible, it should use forwarding substitutions");
5515+
54515516
conformance->setWitness(req, Witness::forOpaque(req));
54525517
};
54535518

54545519
// Witness substitutions.
5455-
SubstitutionMap witnessSubstitutions = getSubstitutionMap(*rawIDIter++);
5520+
auto witnessSubstitutions = getSubstitutionMapChecked(*rawIDIter++);
5521+
if (!witnessSubstitutions) {
5522+
// Missing module errors are most likely caused by an
5523+
// implementation-only import hiding types and decls.
5524+
// rdar://problem/52837313
5525+
if (witnessSubstitutions.errorIsA<XRefNonLoadedModuleError>()) {
5526+
consumeError(witnessSubstitutions.takeError());
5527+
isOpaque = true;
5528+
}
5529+
else
5530+
fatal(witnessSubstitutions.takeError());
5531+
}
54565532

54575533
// Handle opaque witnesses that couldn't be deserialized.
54585534
if (isOpaque) {
@@ -5461,7 +5537,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
54615537
}
54625538

54635539
// Set the witness.
5464-
trySetWitness(Witness::forDeserialized(witness, witnessSubstitutions));
5540+
trySetWitness(Witness::forDeserialized(witness, witnessSubstitutions.get()));
54655541
}
54665542
assert(rawIDIter <= rawIDs.end() && "read too much");
54675543

lib/Serialization/ModuleFile.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,12 @@ class ModuleFile
554554
void readGenericRequirements(SmallVectorImpl<Requirement> &requirements,
555555
llvm::BitstreamCursor &Cursor);
556556

557+
/// Reads a set of requirements from \c DeclTypeCursor, returns the first
558+
/// error, if any.
559+
llvm::Error
560+
readGenericRequirementsChecked(SmallVectorImpl<Requirement> &requirements,
561+
llvm::BitstreamCursor &Cursor);
562+
557563
/// Populates the protocol's default witness table.
558564
///
559565
/// Returns true if there is an error.
@@ -832,7 +838,6 @@ class ModuleFile
832838
/// Returns the decl with the given ID, deserializing it if needed.
833839
///
834840
/// \param DID The ID for the decl within this module.
835-
836841
/// \sa getDeclChecked
837842
Decl *getDecl(serialization::DeclID DID);
838843

@@ -860,14 +865,29 @@ class ModuleFile
860865
/// Returns the generic signature for the given ID.
861866
GenericSignature *getGenericSignature(serialization::GenericSignatureID ID);
862867

868+
/// Returns the generic signature for the given ID or the first error.
869+
llvm::Expected<GenericSignature *>
870+
getGenericSignatureChecked(serialization::GenericSignatureID ID);
871+
863872
/// Returns the substitution map for the given ID, deserializing it if
864873
/// needed.
865874
SubstitutionMap getSubstitutionMap(serialization::SubstitutionMapID id);
866875

876+
/// Returns the substitution map for the given ID, deserializing it if
877+
/// needed, or the first error.
878+
llvm::Expected<SubstitutionMap>
879+
getSubstitutionMapChecked(serialization::SubstitutionMapID id);
880+
867881
/// Recursively reads a protocol conformance from the given cursor.
868882
ProtocolConformanceRef readConformance(llvm::BitstreamCursor &Cursor,
869883
GenericEnvironment *genericEnv =
870884
nullptr);
885+
886+
/// Recursively reads a protocol conformance from the given cursor,
887+
/// returns the conformance or the first error.
888+
llvm::Expected<ProtocolConformanceRef>
889+
readConformanceChecked(llvm::BitstreamCursor &Cursor,
890+
GenericEnvironment *genericEnv = nullptr);
871891

872892
/// Read a SILLayout from the given cursor.
873893
SILLayout *readSILLayout(llvm::BitstreamCursor &Cursor);
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)