Skip to content

Commit 3dbc9de

Browse files
committed
[Serialization] Use llvm::Expected for deserialization failures.
...but don't actually try to handle any of them yet. In fact, don't even bother to /produce/ them yet, except for resolving cross-references.
1 parent 3e28874 commit 3dbc9de

File tree

2 files changed

+75
-20
lines changed

2 files changed

+75
-20
lines changed

include/swift/Serialization/ModuleFile.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/ADT/DenseMap.h"
2727
#include "llvm/ADT/TinyPtrVector.h"
2828
#include "llvm/Bitcode/BitstreamReader.h"
29+
#include "llvm/Support/Error.h"
2930
#include "llvm/Support/MemoryBuffer.h"
3031

3132
namespace llvm {
@@ -542,12 +543,14 @@ class ModuleFile : public LazyMemberLoader {
542543
/// because it reads from the cursor, it is not possible to reset the cursor
543544
/// after reading. Nothing should ever follow an XREF record except
544545
/// XREF_PATH_PIECE records.
545-
Decl *resolveCrossReference(ModuleDecl *M, uint32_t pathLen);
546+
llvm::Expected<Decl *> resolveCrossReference(ModuleDecl *M, uint32_t pathLen);
546547

547548
/// Populates TopLevelIDs for name lookup.
548549
void buildTopLevelDeclMap();
549550

550-
void configureStorage(AbstractStorageDecl *storage, unsigned rawStorageKind,
551+
/// Sets the accessors for \p storage based on \p rawStorageKind.
552+
void configureStorage(AbstractStorageDecl *storage,
553+
unsigned rawStorageKind,
551554
serialization::DeclID getter,
552555
serialization::DeclID setter,
553556
serialization::DeclID materializeForSet,
@@ -743,8 +746,13 @@ class ModuleFile : public LazyMemberLoader {
743746
}
744747

745748
/// Returns the type with the given ID, deserializing it if needed.
749+
///
750+
/// \sa getTypeChecked
746751
Type getType(serialization::TypeID TID);
747752

753+
/// Returns the type with the given ID, deserializing it if needed.
754+
llvm::Expected<Type> getTypeChecked(serialization::TypeID TID);
755+
748756
/// Returns the identifier with the given ID, deserializing it if needed.
749757
Identifier getIdentifier(serialization::IdentifierID IID);
750758

@@ -754,9 +762,21 @@ class ModuleFile : public LazyMemberLoader {
754762
/// \param ForcedContext Optional override for the decl context of certain
755763
/// kinds of decls, used to avoid re-entrant
756764
/// deserialization.
765+
///
766+
/// \sa getDeclChecked
757767
Decl *getDecl(serialization::DeclID DID,
758768
Optional<DeclContext *> ForcedContext = None);
759769

770+
/// Returns the decl with the given ID, deserializing it if needed.
771+
///
772+
/// \param DID The ID for the decl within this module.
773+
/// \param ForcedContext Optional override for the decl context of certain
774+
/// kinds of decls, used to avoid re-entrant
775+
/// deserialization.
776+
llvm::Expected<Decl *>
777+
getDeclChecked(serialization::DeclID DID,
778+
Optional<DeclContext *> ForcedContext = None);
779+
760780
/// Returns the decl context with the given ID, deserializing it if needed.
761781
DeclContext *getDeclContext(serialization::DeclContextID DID);
762782

lib/Serialization/Deserialization.cpp

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ STATISTIC(NumNestedTypeShortcuts,
3737

3838
using namespace swift;
3939
using namespace swift::serialization;
40+
using llvm::Expected;
4041

4142
StringRef swift::getNameOfModule(const ModuleFile *MF) {
4243
return MF->Name;
@@ -1298,8 +1299,8 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
12981299
values.erase(newEnd, values.end());
12991300
}
13001301

1301-
Decl *ModuleFile::resolveCrossReference(ModuleDecl *baseModule,
1302-
uint32_t pathLen) {
1302+
Expected<Decl *>
1303+
ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
13031304
using namespace decls_block;
13041305
assert(baseModule && "missing dependency");
13051306
PrettyXRefTrace pathTrace(*baseModule);
@@ -1420,8 +1421,9 @@ Decl *ModuleFile::resolveCrossReference(ModuleDecl *baseModule,
14201421
}
14211422

14221423
if (values.empty()) {
1423-
error();
1424-
return nullptr;
1424+
return llvm::make_error<llvm::StringError>(
1425+
"top-level value not found",
1426+
std::error_code(EINVAL, std::generic_category()));
14251427
}
14261428

14271429
// Filters for values discovered in the remaining path pieces.
@@ -1540,16 +1542,18 @@ Decl *ModuleFile::resolveCrossReference(ModuleDecl *baseModule,
15401542
pathTrace.addType(filterTy);
15411543

15421544
if (values.size() != 1) {
1543-
error();
1544-
return nullptr;
1545+
return llvm::make_error<llvm::StringError>(
1546+
"multiple matching base values",
1547+
std::error_code(EINVAL, std::generic_category()));
15451548
}
15461549

15471550
auto nominal = dyn_cast<NominalTypeDecl>(values.front());
15481551
values.clear();
15491552

15501553
if (!nominal) {
1551-
error();
1552-
return nullptr;
1554+
return llvm::make_error<llvm::StringError>(
1555+
"base is not a nominal type",
1556+
std::error_code(EINVAL, std::generic_category()));
15531557
}
15541558

15551559
auto members = nominal->lookupDirect(memberName);
@@ -1638,8 +1642,9 @@ Decl *ModuleFile::resolveCrossReference(ModuleDecl *baseModule,
16381642

16391643
case XREF_GENERIC_PARAM_PATH_PIECE: {
16401644
if (values.size() != 1) {
1641-
error();
1642-
return nullptr;
1645+
return llvm::make_error<llvm::StringError>(
1646+
"multiple matching base values",
1647+
std::error_code(EINVAL, std::generic_category()));
16431648
}
16441649

16451650
uint32_t paramIndex;
@@ -1672,9 +1677,15 @@ Decl *ModuleFile::resolveCrossReference(ModuleDecl *baseModule,
16721677
} else if (auto fn = dyn_cast<AbstractFunctionDecl>(base))
16731678
paramList = fn->getGenericParams();
16741679

1675-
if (!paramList || paramIndex >= paramList->size()) {
1676-
error();
1677-
return nullptr;
1680+
if (!paramList) {
1681+
return llvm::make_error<llvm::StringError>(
1682+
"cross-reference to generic param for non-generic type",
1683+
std::error_code(EINVAL, std::generic_category()));
1684+
}
1685+
if (paramIndex >= paramList->size()) {
1686+
return llvm::make_error<llvm::StringError>(
1687+
"generic argument index out of bounds",
1688+
std::error_code(EINVAL, std::generic_category()));
16781689
}
16791690

16801691
values.clear();
@@ -1698,8 +1709,9 @@ Decl *ModuleFile::resolveCrossReference(ModuleDecl *baseModule,
16981709
}
16991710

17001711
if (values.empty()) {
1701-
error();
1702-
return nullptr;
1712+
return llvm::make_error<llvm::StringError>(
1713+
"result not found",
1714+
std::error_code(EINVAL, std::generic_category()));
17031715
}
17041716

17051717
// Reset the module filter.
@@ -1718,8 +1730,9 @@ Decl *ModuleFile::resolveCrossReference(ModuleDecl *baseModule,
17181730

17191731
// When all is said and done, we should have a single value here to return.
17201732
if (values.size() != 1) {
1721-
error();
1722-
return nullptr;
1733+
return llvm::make_error<llvm::StringError>(
1734+
"result is ambiguous",
1735+
std::error_code(EINVAL, std::generic_category()));
17231736
}
17241737

17251738
return values.front();
@@ -2141,6 +2154,16 @@ static uint64_t encodeLazyConformanceContextData(uint64_t numProtocols,
21412154
}
21422155

21432156
Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
2157+
Expected<Decl *> deserialized = getDeclChecked(DID, ForcedContext);
2158+
if (!deserialized) {
2159+
error();
2160+
return nullptr;
2161+
}
2162+
return deserialized.get();
2163+
}
2164+
2165+
Expected<Decl *>
2166+
ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
21442167
if (DID == 0)
21452168
return nullptr;
21462169

@@ -3542,7 +3565,10 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
35423565
ModuleID baseModuleID;
35433566
uint32_t pathLen;
35443567
decls_block::XRefLayout::readRecord(scratch, baseModuleID, pathLen);
3545-
declOrOffset = resolveCrossReference(getModule(baseModuleID), pathLen);
3568+
auto resolved = resolveCrossReference(getModule(baseModuleID), pathLen);
3569+
if (!resolved)
3570+
return resolved;
3571+
declOrOffset = resolved.get();
35463572
break;
35473573
}
35483574

@@ -3657,6 +3683,15 @@ Optional<swift::ResultConvention> getActualResultConvention(uint8_t raw) {
36573683
}
36583684

36593685
Type ModuleFile::getType(TypeID TID) {
3686+
Expected<Type> deserialized = getTypeChecked(TID);
3687+
if (!deserialized) {
3688+
error();
3689+
return Type();
3690+
}
3691+
return deserialized.get();
3692+
}
3693+
3694+
Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
36603695
if (TID == 0)
36613696
return Type();
36623697

0 commit comments

Comments
 (0)