//===--- Deserialization.cpp - Loading a serialized AST -------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "BCReadingExtras.h"
#include "DeserializationErrors.h"
#include "ModuleFile.h"
#include "ModuleFormat.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/Expr.h"
#include "swift/AST/ForeignErrorConvention.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/PropertyWrappers.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "Serialization"

STATISTIC(NumDeclsLoaded, "# of decls deserialized");
STATISTIC(NumMemberListsLoaded,
          "# of nominals/extensions whose members were loaded");
STATISTIC(NumNormalProtocolConformancesLoaded,
          "# of normal protocol conformances deserialized");
STATISTIC(NumNormalProtocolConformancesCompleted,
          "# of normal protocol conformances completed");
STATISTIC(NumNestedTypeShortcuts,
          "# of nested types resolved without full lookup");

using namespace swift;
using namespace swift::serialization;
using llvm::Expected;

StringRef swift::getNameOfModule(const ModuleFile *MF) {
  return MF->Name;
}

namespace {
  struct DeclAndOffset {
    const Decl *D;
    uint64_t offset;
  };

  static raw_ostream &operator<<(raw_ostream &os, DeclAndOffset &&pair) {
    return os << Decl::getKindName(pair.D->getKind())
              << "Decl @ " << pair.offset;
  }

  class PrettyDeclDeserialization : public llvm::PrettyStackTraceEntry {
    const ModuleFile *MF;
    const ModuleFile::Serialized<Decl*> &DeclOrOffset;
    uint64_t offset;
    decls_block::RecordKind Kind;
  public:
    PrettyDeclDeserialization(ModuleFile *module,
                              const ModuleFile::Serialized<Decl*> &declOrOffset,
                              decls_block::RecordKind kind)
      : MF(module), DeclOrOffset(declOrOffset), offset(declOrOffset),
        Kind(kind) {
    }

    static const char *getRecordKindString(decls_block::RecordKind Kind) {
      switch (Kind) {
#define RECORD(Id) case decls_block::Id: return #Id;
#include "DeclTypeRecordNodes.def"
      }

      llvm_unreachable("Unhandled RecordKind in switch.");
    }

    void print(raw_ostream &os) const override {
      if (!DeclOrOffset.isComplete()) {
        os << "While deserializing decl @ " << offset << " ("
           << getRecordKindString(Kind) << ")";
      } else {
        os << "While deserializing ";

        if (auto VD = dyn_cast<ValueDecl>(DeclOrOffset.get())) {
          os << "'" << VD->getBaseName() << "' (" << DeclAndOffset{VD, offset}
             << ")";
        } else if (auto ED = dyn_cast<ExtensionDecl>(DeclOrOffset.get())) {
          os << "extension of '" << ED->getExtendedType() << "' ("
             << DeclAndOffset{ED, offset} << ")";
        } else {
          os << DeclAndOffset{DeclOrOffset.get(), offset};
        }
      }
      os << " in '" << getNameOfModule(MF) << "'\n";
    }
  };

  class PrettyXRefTrace :
      public llvm::PrettyStackTraceEntry,
      public XRefTracePath {
  public:
    explicit PrettyXRefTrace(ModuleDecl &M) : XRefTracePath(M) {}

    void print(raw_ostream &os) const override {
      XRefTracePath::print(os, "\t");
    }
  };
} // end anonymous namespace

const char DeclDeserializationError::ID = '\0';
void DeclDeserializationError::anchor() {}
const char XRefError::ID = '\0';
void XRefError::anchor() {}
const char XRefNonLoadedModuleError::ID = '\0';
void XRefNonLoadedModuleError::anchor() {}
const char OverrideError::ID = '\0';
void OverrideError::anchor() {}
const char TypeError::ID = '\0';
void TypeError::anchor() {}
const char ExtensionError::ID = '\0';
void ExtensionError::anchor() {}

/// Skips a single record in the bitstream.
///
/// Returns true if the next entry is a record of type \p recordKind.
/// Destroys the stream position if the next entry is not a record.
static void skipRecord(llvm::BitstreamCursor &cursor, unsigned recordKind) {
  auto next = cursor.advance(AF_DontPopBlockAtEnd);
  assert(next.Kind == llvm::BitstreamEntry::Record);

  unsigned kind = cursor.skipRecord(next.ID);
  assert(kind == recordKind);
  (void)kind;
}

void ModuleFile::fatal(llvm::Error error) {
  if (FileContext) {
    getContext().Diags.diagnose(SourceLoc(), diag::serialization_fatal, Name);

    if (!CompatibilityVersion.empty()) {
      if (getContext().LangOpts.EffectiveLanguageVersion
            != CompatibilityVersion) {
        SmallString<16> effectiveVersionBuffer, compatVersionBuffer;
        {
          llvm::raw_svector_ostream out(effectiveVersionBuffer);
          out << getContext().LangOpts.EffectiveLanguageVersion;
        }
        {
          llvm::raw_svector_ostream out(compatVersionBuffer);
          out << CompatibilityVersion;
        }
        getContext().Diags.diagnose(
            SourceLoc(), diag::serialization_compatibility_version_mismatch,
            effectiveVersionBuffer, Name, compatVersionBuffer);
      }
    }
  }

  logAllUnhandledErrors(std::move(error), llvm::errs(),
                        "\n*** DESERIALIZATION FAILURE (please include this "
                        "section in any bug report) ***\n");
  abort();
}

static Optional<swift::AccessorKind>
getActualAccessorKind(uint8_t raw) {
  switch (serialization::AccessorKind(raw)) {
#define ACCESSOR(ID) \
  case serialization::AccessorKind::ID: return swift::AccessorKind::ID;
#include "swift/AST/AccessorKinds.def"
  }

  return None;
}

/// Translate from the serialization DefaultArgumentKind enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<swift::DefaultArgumentKind>
getActualDefaultArgKind(uint8_t raw) {
  switch (static_cast<serialization::DefaultArgumentKind>(raw)) {
  case serialization::DefaultArgumentKind::None:
    return swift::DefaultArgumentKind::None;
  case serialization::DefaultArgumentKind::Normal:
    return swift::DefaultArgumentKind::Normal;
  case serialization::DefaultArgumentKind::Inherited:
    return swift::DefaultArgumentKind::Inherited;
  case serialization::DefaultArgumentKind::Column:
    return swift::DefaultArgumentKind::Column;
  case serialization::DefaultArgumentKind::File:
    return swift::DefaultArgumentKind::File;
  case serialization::DefaultArgumentKind::Line:
    return swift::DefaultArgumentKind::Line;
  case serialization::DefaultArgumentKind::Function:
    return swift::DefaultArgumentKind::Function;
  case serialization::DefaultArgumentKind::DSOHandle:
    return swift::DefaultArgumentKind::DSOHandle;
  case serialization::DefaultArgumentKind::NilLiteral:
    return swift::DefaultArgumentKind::NilLiteral;
  case serialization::DefaultArgumentKind::EmptyArray:
    return swift::DefaultArgumentKind::EmptyArray;
  case serialization::DefaultArgumentKind::EmptyDictionary:
    return swift::DefaultArgumentKind::EmptyDictionary;
  case serialization::DefaultArgumentKind::StoredProperty:
    return swift::DefaultArgumentKind::StoredProperty;
  }
  return None;
}

ParameterList *ModuleFile::readParameterList() {
  using namespace decls_block;

  SmallVector<uint64_t, 8> scratch;
  auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
  unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch);
  assert(recordID == PARAMETERLIST);
  (void) recordID;

  ArrayRef<uint64_t> rawMemberIDs;
  decls_block::ParameterListLayout::readRecord(scratch, rawMemberIDs);

  SmallVector<ParamDecl *, 8> params;
  for (DeclID paramID : rawMemberIDs)
    params.push_back(cast<ParamDecl>(getDecl(paramID)));

  return ParameterList::create(getContext(), params);
}

Expected<Pattern *> ModuleFile::readPattern(DeclContext *owningDC) {
  // Currently, the only case in which this function can fail (return an error)
  // is when reading a pattern for a single variable declaration.

  using namespace decls_block;

  auto readPatternUnchecked = [this](DeclContext *owningDC) -> Pattern * {
    Expected<Pattern *> deserialized = readPattern(owningDC);
    if (!deserialized) {
      fatal(deserialized.takeError());
    }
    assert(deserialized.get());
    return deserialized.get();
  };

  SmallVector<uint64_t, 8> scratch;

  BCOffsetRAII restoreOffset(DeclTypeCursor);
  auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
  if (next.Kind != llvm::BitstreamEntry::Record)
    fatal();

  /// Local function to record the type of this pattern.
  auto recordPatternType = [&](Pattern *pattern, Type type) {
    if (type->hasTypeParameter())
      pattern->setDelayedInterfaceType(type, owningDC);
    else
      pattern->setType(type);
  };

  unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch);
  switch (kind) {
  case decls_block::PAREN_PATTERN: {
    bool isImplicit;
    ParenPatternLayout::readRecord(scratch, isImplicit);

    Pattern *subPattern = readPatternUnchecked(owningDC);

    auto result = new (getContext()) ParenPattern(SourceLoc(),
                                                  subPattern,
                                                  SourceLoc(),
                                                  isImplicit);

    if (Type interfaceType = subPattern->getDelayedInterfaceType())
      result->setDelayedInterfaceType(ParenType::get(getContext(),
                                                     interfaceType), owningDC);
    else
      result->setType(ParenType::get(getContext(), subPattern->getType()));
    restoreOffset.reset();
    return result;
  }
  case decls_block::TUPLE_PATTERN: {
    TypeID tupleTypeID;
    unsigned count;
    bool isImplicit;

    TuplePatternLayout::readRecord(scratch, tupleTypeID, count, isImplicit);

    SmallVector<TuplePatternElt, 8> elements;
    for ( ; count > 0; --count) {
      scratch.clear();
      next = DeclTypeCursor.advance();
      assert(next.Kind == llvm::BitstreamEntry::Record);

      kind = DeclTypeCursor.readRecord(next.ID, scratch);
      assert(kind == decls_block::TUPLE_PATTERN_ELT);

      // FIXME: Add something for this record or remove it.
      IdentifierID labelID;
      TuplePatternEltLayout::readRecord(scratch, labelID);
      Identifier label = getIdentifier(labelID);

      Pattern *subPattern = readPatternUnchecked(owningDC);
      elements.push_back(TuplePatternElt(label, SourceLoc(), subPattern));
    }

    auto result = TuplePattern::create(getContext(), SourceLoc(),
                                       elements, SourceLoc(), isImplicit);
    recordPatternType(result, getType(tupleTypeID));
    restoreOffset.reset();
    return result;
  }
  case decls_block::NAMED_PATTERN: {
    DeclID varID;
    TypeID typeID;
    bool isImplicit;
    NamedPatternLayout::readRecord(scratch, varID, typeID, isImplicit);

    auto deserialized = getDeclChecked(varID);
    if (!deserialized) {
      // Pass through the error. It's too bad that it affects the whole pattern,
      // but that's what we get.
      return deserialized.takeError();
    }

    auto var = cast<VarDecl>(deserialized.get());
    auto result = new (getContext()) NamedPattern(var, isImplicit);
    recordPatternType(result, getType(typeID));
    restoreOffset.reset();
    return result;
  }
  case decls_block::ANY_PATTERN: {
    TypeID typeID;
    bool isImplicit;

    AnyPatternLayout::readRecord(scratch, typeID, isImplicit);
    auto result = new (getContext()) AnyPattern(SourceLoc(), isImplicit);
    recordPatternType(result, getType(typeID));
    restoreOffset.reset();
    return result;
  }
  case decls_block::TYPED_PATTERN: {
    TypeID typeID;
    bool isImplicit;
    TypedPatternLayout::readRecord(scratch, typeID, isImplicit);

    Expected<Pattern *> subPattern = readPattern(owningDC);
    if (!subPattern) {
      // Pass through any errors.
      return subPattern;
    }

    auto type = getType(typeID);
    auto result = new (getContext()) TypedPattern(subPattern.get(),
                                                  /*typeRepr*/nullptr,
                                                  isImplicit);
    recordPatternType(result, type);
    restoreOffset.reset();
    return result;
  }
  case decls_block::VAR_PATTERN: {
    bool isImplicit, isLet;
    VarPatternLayout::readRecord(scratch, isLet, isImplicit);

    Pattern *subPattern = readPatternUnchecked(owningDC);

    auto result = new (getContext()) VarPattern(SourceLoc(), isLet, subPattern,
                                                isImplicit);
    if (Type interfaceType = subPattern->getDelayedInterfaceType())
      result->setDelayedInterfaceType(interfaceType, owningDC);
    else
      result->setType(subPattern->getType());
    restoreOffset.reset();
    return result;
  }

  default:
    return nullptr;
  }
}

SILLayout *ModuleFile::readSILLayout(llvm::BitstreamCursor &Cursor) {
  using namespace decls_block;

  SmallVector<uint64_t, 16> scratch;

  auto next = Cursor.advance(AF_DontPopBlockAtEnd);
  assert(next.Kind == llvm::BitstreamEntry::Record);

  unsigned kind = Cursor.readRecord(next.ID, scratch);
  switch (kind) {
  case decls_block::SIL_LAYOUT: {
    GenericSignatureID rawGenericSig;
    unsigned numFields;
    ArrayRef<uint64_t> types;
    decls_block::SILLayoutLayout::readRecord(scratch, rawGenericSig,
                                             numFields, types);
    
    SmallVector<SILField, 4> fields;
    for (auto fieldInfo : types.slice(0, numFields)) {
      bool isMutable = fieldInfo & 0x80000000U;
      auto typeId = fieldInfo & 0x7FFFFFFFU;
      fields.push_back(
        SILField(getType(typeId)->getCanonicalType(),
                 isMutable));
    }
    
    CanGenericSignature canSig;
    if (auto sig = getGenericSignature(rawGenericSig))
      canSig = sig->getCanonicalSignature();
    return SILLayout::get(getContext(), canSig, fields);
  }
  default:
    fatal();
  }
}

ProtocolConformanceRef ModuleFile::readConformance(
                                             llvm::BitstreamCursor &Cursor,
                                             GenericEnvironment *genericEnv) {
  auto conformance = readConformanceChecked(Cursor, genericEnv);
  if (!conformance)
    fatal(conformance.takeError());
  return conformance.get();
}

Expected<ProtocolConformanceRef>
ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor,
                                   GenericEnvironment *genericEnv) {
  using namespace decls_block;

  SmallVector<uint64_t, 16> scratch;

  auto next = Cursor.advance(AF_DontPopBlockAtEnd);
  assert(next.Kind == llvm::BitstreamEntry::Record);

  if (getContext().Stats)
    getContext().Stats->getFrontendCounters().NumConformancesDeserialized++;

  unsigned kind = Cursor.readRecord(next.ID, scratch);
  switch (kind) {
  case INVALID_PROTOCOL_CONFORMANCE: {
    return ProtocolConformanceRef::forInvalid();
  }

  case ABSTRACT_PROTOCOL_CONFORMANCE: {
    DeclID protoID;
    AbstractProtocolConformanceLayout::readRecord(scratch, protoID);

    auto decl = getDeclChecked(protoID);
    if (!decl)
      return decl.takeError();

    auto proto = cast<ProtocolDecl>(decl.get());
    return ProtocolConformanceRef(proto);
  }

  case SELF_PROTOCOL_CONFORMANCE: {
    DeclID protoID;
    SelfProtocolConformanceLayout::readRecord(scratch, protoID);

    auto decl = getDeclChecked(protoID);
    if (!decl)
      return decl.takeError();

    auto proto = cast<ProtocolDecl>(decl.get());
    auto conformance = getContext().getSelfConformance(proto);
    return ProtocolConformanceRef(conformance);
  }

  case SPECIALIZED_PROTOCOL_CONFORMANCE: {
    TypeID conformingTypeID;
    SubstitutionMapID substitutionMapID;
    SpecializedProtocolConformanceLayout::readRecord(scratch, conformingTypeID,
                                                     substitutionMapID);

    ASTContext &ctx = getContext();
    Type conformingType = getType(conformingTypeID);
    if (genericEnv) {
      conformingType = genericEnv->mapTypeIntoContext(conformingType);
    }

    PrettyStackTraceType trace(getAssociatedModule()->getASTContext(),
                               "reading specialized conformance for",
                               conformingType);

    auto subMap = getSubstitutionMap(substitutionMapID);

    ProtocolConformanceRef genericConformance =
      readConformance(Cursor, genericEnv);
    PrettyStackTraceDecl traceTo("... to", genericConformance.getRequirement());

    assert(genericConformance.isConcrete() && "Abstract generic conformance?");
    auto conformance =
           ctx.getSpecializedConformance(conformingType,
                                         genericConformance.getConcrete(),
                                         subMap);
    return ProtocolConformanceRef(conformance);
  }

  case INHERITED_PROTOCOL_CONFORMANCE: {
    TypeID conformingTypeID;
    InheritedProtocolConformanceLayout::readRecord(scratch, conformingTypeID);

    ASTContext &ctx = getContext();
    Type conformingType = getType(conformingTypeID);
    if (genericEnv) {
      conformingType = genericEnv->mapTypeIntoContext(conformingType);
    }

    PrettyStackTraceType trace(getAssociatedModule()->getASTContext(),
                               "reading inherited conformance for",
                               conformingType);

    ProtocolConformanceRef inheritedConformance =
      readConformance(Cursor, genericEnv);
    PrettyStackTraceDecl traceTo("... to",
                                 inheritedConformance.getRequirement());

    assert(inheritedConformance.isConcrete() &&
           "Abstract inherited conformance?");
    auto conformance =
      ctx.getInheritedConformance(conformingType,
                                  inheritedConformance.getConcrete());
    return ProtocolConformanceRef(conformance);
  }

  case NORMAL_PROTOCOL_CONFORMANCE_ID: {
    NormalConformanceID conformanceID;
    NormalProtocolConformanceIdLayout::readRecord(scratch, conformanceID);
    return ProtocolConformanceRef(readNormalConformance(conformanceID));
  }

  case PROTOCOL_CONFORMANCE_XREF: {
    DeclID protoID;
    DeclID nominalID;
    ModuleID moduleID;
    ProtocolConformanceXrefLayout::readRecord(scratch, protoID, nominalID,
                                              moduleID);

    auto nominal = cast<NominalTypeDecl>(getDecl(nominalID));
    PrettyStackTraceDecl trace("cross-referencing conformance for", nominal);
    auto proto = cast<ProtocolDecl>(getDecl(protoID));
    PrettyStackTraceDecl traceTo("... to", proto);
    auto module = getModule(moduleID);

    // FIXME: If the module hasn't been loaded, we probably don't want to fall
    // back to the current module like this.
    if (!module)
      module = getAssociatedModule();

    SmallVector<ProtocolConformance *, 2> conformances;
    nominal->lookupConformance(module, proto, conformances);
    PrettyStackTraceModuleFile traceMsg(
        "If you're seeing a crash here, check that your SDK and dependencies "
        "are at least as new as the versions used to build", *this);
    // This would normally be an assertion but it's more useful to print the
    // PrettyStackTrace here even in no-asserts builds.
    if (conformances.empty())
      abort();
    return ProtocolConformanceRef(conformances.front());
  }

  // Not a protocol conformance.
  default:
    fatal();
  }
}

NormalProtocolConformance *ModuleFile::readNormalConformance(
                             NormalConformanceID conformanceID) {
  auto &conformanceEntry = NormalConformances[conformanceID-1];
  if (conformanceEntry.isComplete()) {
    return conformanceEntry.get();
  }

  using namespace decls_block;

  // Find the conformance record.
  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(conformanceEntry);
  auto entry = DeclTypeCursor.advance();
  if (entry.Kind != llvm::BitstreamEntry::Record)
    fatal();

  DeclID protoID;
  DeclContextID contextID;
  unsigned valueCount, typeCount, conformanceCount;
  ArrayRef<uint64_t> rawIDs;
  SmallVector<uint64_t, 16> scratch;

  unsigned kind = DeclTypeCursor.readRecord(entry.ID, scratch);
  if (kind != NORMAL_PROTOCOL_CONFORMANCE)
    fatal();
  NormalProtocolConformanceLayout::readRecord(scratch, protoID,
                                              contextID, typeCount,
                                              valueCount, conformanceCount,
                                              rawIDs);

  ASTContext &ctx = getContext();
  DeclContext *dc = getDeclContext(contextID);
  assert(!isa<ClangModuleUnit>(dc->getModuleScopeContext())
         && "should not have serialized a conformance from a clang module");
  Type conformingType = dc->getDeclaredInterfaceType();
  PrettyStackTraceType trace(ctx, "reading conformance for", conformingType);

  auto proto = cast<ProtocolDecl>(getDecl(protoID));
  PrettyStackTraceDecl traceTo("... to", proto);
  ++NumNormalProtocolConformancesLoaded;

  auto conformance = ctx.getConformance(conformingType, proto, SourceLoc(), dc,
                                        ProtocolConformanceState::Incomplete);

  // Record this conformance.
  if (conformanceEntry.isComplete())
    return conformance;

  uint64_t offset = conformanceEntry;
  conformanceEntry = conformance;

  dc->getSelfNominalTypeDecl()->registerProtocolConformance(conformance);

  // If the conformance is complete, we're done.
  if (conformance->isComplete())
    return conformance;

  conformance->setState(ProtocolConformanceState::Complete);
  conformance->setLazyLoader(this, offset);
  return conformance;
}

GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
  using namespace decls_block;

  assert(DC && "need a context for the decls in the list");

  BCOffsetRAII lastRecordOffset(DeclTypeCursor);
  SmallVector<uint64_t, 8> scratch;
  StringRef blobData;

  auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
  if (next.Kind != llvm::BitstreamEntry::Record)
    return nullptr;

  unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch, &blobData);
  if (kind != GENERIC_PARAM_LIST)
    return nullptr;
  lastRecordOffset.reset();

  SmallVector<GenericTypeParamDecl *, 8> params;

  ArrayRef<uint64_t> paramIDs;
  GenericParamListLayout::readRecord(scratch, paramIDs);
  for (DeclID nextParamID : paramIDs) {
    auto genericParam = cast<GenericTypeParamDecl>(getDecl(nextParamID));
    params.push_back(genericParam);
  }

  // Don't create empty generic parameter lists. (This should never happen in
  // practice, but it doesn't hurt to be defensive.)
  if (params.empty())
    return nullptr;

  return GenericParamList::create(getContext(), SourceLoc(),
                                  params, SourceLoc(), { },
                                  SourceLoc());
}

void ModuleFile::readGenericRequirements(
                   SmallVectorImpl<Requirement> &requirements,
                   llvm::BitstreamCursor &Cursor) {
  auto error = readGenericRequirementsChecked(requirements, Cursor);
  if (error)
    fatal(std::move(error));
}

llvm::Error ModuleFile::readGenericRequirementsChecked(
                   SmallVectorImpl<Requirement> &requirements,
                   llvm::BitstreamCursor &Cursor) {
  using namespace decls_block;

  BCOffsetRAII lastRecordOffset(Cursor);
  SmallVector<uint64_t, 8> scratch;
  StringRef blobData;

  while (true) {
    lastRecordOffset.reset();
    bool shouldContinue = true;

    auto entry = Cursor.advance(AF_DontPopBlockAtEnd);
    if (entry.Kind != llvm::BitstreamEntry::Record)
      break;

    scratch.clear();
    unsigned recordID = Cursor.readRecord(entry.ID, scratch, &blobData);
    switch (recordID) {
    case GENERIC_REQUIREMENT: {
      uint8_t rawKind;
      uint64_t rawTypeIDs[2];
      GenericRequirementLayout::readRecord(scratch, rawKind,
                                           rawTypeIDs[0], rawTypeIDs[1]);

      switch (rawKind) {
      case GenericRequirementKind::Conformance: {
        auto subject = getTypeChecked(rawTypeIDs[0]);
        if (!subject)
          return subject.takeError();

        auto constraint = getTypeChecked(rawTypeIDs[1]);
        if (!constraint)
          return constraint.takeError();

        requirements.push_back(Requirement(RequirementKind::Conformance,
                                           subject.get(), constraint.get()));
        break;
      }
      case GenericRequirementKind::Superclass: {
        auto subject = getTypeChecked(rawTypeIDs[0]);
        if (!subject)
          return subject.takeError();

        auto constraint = getTypeChecked(rawTypeIDs[1]);
        if (!constraint)
          return constraint.takeError();

        requirements.push_back(Requirement(RequirementKind::Superclass,
                                           subject.get(), constraint.get()));
        break;
      }
      case GenericRequirementKind::SameType: {
        auto first = getTypeChecked(rawTypeIDs[0]);
        if (!first)
          return first.takeError();

        auto second = getTypeChecked(rawTypeIDs[1]);
        if (!second)
          return second.takeError();

        requirements.push_back(Requirement(RequirementKind::SameType,
                                           first.get(), second.get()));
        break;
      }
      default:
        // Unknown requirement kind.
        fatal();
      }
      break;
      }
    case LAYOUT_REQUIREMENT: {
      uint8_t rawKind;
      uint64_t rawTypeID;
      uint32_t size;
      uint32_t alignment;
      LayoutRequirementLayout::readRecord(scratch, rawKind, rawTypeID,
                                          size, alignment);

      auto first = getTypeChecked(rawTypeID);
      if (!first)
        return first.takeError();

      LayoutConstraint layout;
      LayoutConstraintKind kind = LayoutConstraintKind::UnknownLayout;
      switch (rawKind) {
      default:
        // Unknown layout requirement kind.
        fatal();
      case LayoutRequirementKind::NativeRefCountedObject:
        kind = LayoutConstraintKind::NativeRefCountedObject;
        break;
      case LayoutRequirementKind::RefCountedObject:
        kind = LayoutConstraintKind::RefCountedObject;
        break;
      case LayoutRequirementKind::Trivial:
        kind = LayoutConstraintKind::Trivial;
        break;
      case LayoutRequirementKind::TrivialOfExactSize:
        kind = LayoutConstraintKind::TrivialOfExactSize;
        break;
      case LayoutRequirementKind::TrivialOfAtMostSize:
        kind = LayoutConstraintKind::TrivialOfAtMostSize;
        break;
      case LayoutRequirementKind::Class:
        kind = LayoutConstraintKind::Class;
        break;
      case LayoutRequirementKind::NativeClass:
        kind = LayoutConstraintKind::NativeClass;
        break;
      case LayoutRequirementKind::UnknownLayout:
        kind = LayoutConstraintKind::UnknownLayout;
        break;
      }

      ASTContext &ctx = getContext();
      if (kind != LayoutConstraintKind::TrivialOfAtMostSize &&
          kind != LayoutConstraintKind::TrivialOfExactSize)
        layout = LayoutConstraint::getLayoutConstraint(kind, ctx);
      else
        layout =
            LayoutConstraint::getLayoutConstraint(kind, size, alignment, ctx);

      requirements.push_back(
          Requirement(RequirementKind::Layout, first.get(), layout));
      break;
      }
    default:
      // This record is not part of the GenericParamList.
      shouldContinue = false;
      break;
    }

    if (!shouldContinue)
      break;
  }

  return llvm::Error::success();
}

/// Advances past any records that might be part of a requirement signature.
static void skipGenericRequirements(llvm::BitstreamCursor &Cursor) {
  using namespace decls_block;

  BCOffsetRAII lastRecordOffset(Cursor);

  while (true) {
    auto entry = Cursor.advance(AF_DontPopBlockAtEnd);
    if (entry.Kind != llvm::BitstreamEntry::Record)
      break;

    unsigned recordID = Cursor.skipRecord(entry.ID);
    switch (recordID) {
    case GENERIC_REQUIREMENT:
    case LAYOUT_REQUIREMENT:
      break;

    default:
      // This record is not a generic requirement.
      return;
    }

    lastRecordOffset.reset();
  }
}

GenericSignature ModuleFile::getGenericSignature(
    serialization::GenericSignatureID ID) {
  auto signature = getGenericSignatureChecked(ID);
  if (!signature)
    fatal(signature.takeError());
  return signature.get();
}

Expected<GenericSignature>
ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) {
  using namespace decls_block;

  // Zero is a sentinel for having no generic signature.
  if (ID == 0) return nullptr;

  assert(ID <= GenericSignatures.size() &&
         "invalid GenericSignature ID");
  auto &sigOffset = GenericSignatures[ID-1];

  // If we've already deserialized this generic signature, return it.
  if (sigOffset.isComplete())
    return sigOffset.get();

  // Read the generic signature.
  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(sigOffset);

  // Read the parameter types.
  SmallVector<GenericTypeParamType *, 4> paramTypes;
  StringRef blobData;
  SmallVector<uint64_t, 8> scratch;

  auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
  if (entry.Kind != llvm::BitstreamEntry::Record)
    fatal();

  unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
  switch (recordID) {
  case GENERIC_SIGNATURE: {
    ArrayRef<uint64_t> rawParamIDs;
    GenericSignatureLayout::readRecord(scratch, rawParamIDs);

    for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) {
      auto paramTy = getType(rawParamIDs[i])->castTo<GenericTypeParamType>();
      paramTypes.push_back(paramTy);
    }
    break;
  }
  case SIL_GENERIC_SIGNATURE: {
    ArrayRef<uint64_t> rawParamIDs;
    SILGenericSignatureLayout::readRecord(scratch, rawParamIDs);

    if (rawParamIDs.size() % 2 != 0)
      fatal();

    for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) {
      Identifier name = getIdentifier(rawParamIDs[i]);
      auto paramTy = getType(rawParamIDs[i+1])->castTo<GenericTypeParamType>();

      if (!name.empty()) {
        auto paramDecl =
          createDecl<GenericTypeParamDecl>(getAssociatedModule(),
                                           name,
                                           SourceLoc(),
                                           paramTy->getDepth(),
                                           paramTy->getIndex());
        paramTy = paramDecl->getDeclaredInterfaceType()
                   ->castTo<GenericTypeParamType>();
      }

      paramTypes.push_back(paramTy);
    }
    break;
  }
  default:
    // Not a generic signature; no way to recover.
    fatal();
  }

  // Read the generic requirements.
  SmallVector<Requirement, 4> requirements;
  auto error = readGenericRequirementsChecked(requirements, DeclTypeCursor);
  if (error)
    return std::move(error);

  // If we've already deserialized this generic signature, start over to return
  // it directly.
  // FIXME: Is this kind of re-entrancy actually possible?
  if (sigOffset.isComplete())
    return getGenericSignature(ID);

  // Construct the generic signature from the loaded parameters and
  // requirements.
  auto signature = GenericSignature::get(paramTypes, requirements);
  sigOffset = signature;
  return signature;
}

SubstitutionMap ModuleFile::getSubstitutionMap(
                                        serialization::SubstitutionMapID id) {
  auto map = getSubstitutionMapChecked(id);
  if (!map)
    fatal(map.takeError());
  return map.get();
}

Expected<SubstitutionMap>
ModuleFile::getSubstitutionMapChecked(serialization::SubstitutionMapID id) {
  using namespace decls_block;

  // Zero is a sentinel for having an empty substitution map.
  if (id == 0) return SubstitutionMap();

  assert(id <= SubstitutionMaps.size() && "invalid SubstitutionMap ID");
  auto &substitutionsOrOffset = SubstitutionMaps[id-1];

  // If we've already deserialized this substitution map, return it.
  if (substitutionsOrOffset.isComplete()) {
    return substitutionsOrOffset.get();
  }

  // Read the substitution map.
  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(substitutionsOrOffset);

  // Read the substitution map.
  auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
  if (entry.Kind != llvm::BitstreamEntry::Record)
    fatal();

  StringRef blobData;
  SmallVector<uint64_t, 8> scratch;
  unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
  if (recordID != SUBSTITUTION_MAP)
    fatal();

  GenericSignatureID genericSigID;
  uint64_t numConformances;
  ArrayRef<uint64_t> replacementTypeIDs;
  SubstitutionMapLayout::readRecord(scratch, genericSigID, numConformances,
                                    replacementTypeIDs);

  // Generic signature.
  auto genericSigOrError = getGenericSignatureChecked(genericSigID);
  if (!genericSigOrError)
    return genericSigOrError.takeError();

  auto genericSig = genericSigOrError.get();
  if (!genericSig)
    fatal();

  // Load the replacement types.
  SmallVector<Type, 4> replacementTypes;
  replacementTypes.reserve(replacementTypeIDs.size());
  for (auto typeID : replacementTypeIDs) {
    replacementTypes.push_back(getType(typeID));
  }

  // Read the conformances.
  SmallVector<ProtocolConformanceRef, 4> conformances;
  conformances.reserve(numConformances);
  for (unsigned i : range(numConformances)) {
    (void)i;
    conformances.push_back(readConformance(DeclTypeCursor));
  }

  // Form the substitution map and record it.
  auto substitutions =
    SubstitutionMap::get(genericSig, ArrayRef<Type>(replacementTypes),
                         ArrayRef<ProtocolConformanceRef>(conformances));
  substitutionsOrOffset = substitutions;
  return substitutions;
}

bool ModuleFile::readDefaultWitnessTable(ProtocolDecl *proto) {
  using namespace decls_block;

  auto entry = DeclTypeCursor.advance();
  if (entry.Kind != llvm::BitstreamEntry::Record)
    return true;

  SmallVector<uint64_t, 16> witnessIDBuffer;

  unsigned kind = DeclTypeCursor.readRecord(entry.ID, witnessIDBuffer);
  assert(kind == DEFAULT_WITNESS_TABLE);
  (void)kind;

  ArrayRef<uint64_t> rawWitnessIDs;
  decls_block::DefaultWitnessTableLayout::readRecord(
      witnessIDBuffer, rawWitnessIDs);

  if (rawWitnessIDs.empty())
    return false;

  unsigned e = rawWitnessIDs.size();
  assert(e % 2 == 0 && "malformed default witness table");
  (void) e;

  for (unsigned i = 0, e = rawWitnessIDs.size(); i < e; i += 2) {
    ValueDecl *requirement = cast<ValueDecl>(getDecl(rawWitnessIDs[i]));
    assert(requirement && "unable to deserialize next requirement");
    ValueDecl *witness = cast<ValueDecl>(getDecl(rawWitnessIDs[i + 1]));
    assert(witness && "unable to deserialize next witness");
    assert(requirement->getDeclContext() == proto);

    proto->setDefaultWitness(requirement, witness);
  }

  return false;
}

static Optional<swift::CtorInitializerKind>
getActualCtorInitializerKind(uint8_t raw) {
  switch (serialization::CtorInitializerKind(raw)) {
#define CASE(NAME) \
  case serialization::CtorInitializerKind::NAME: \
    return swift::CtorInitializerKind::NAME;
  CASE(Designated)
  CASE(Convenience)
  CASE(Factory)
  CASE(ConvenienceFactory)
#undef CASE
  }
  return None;
}

static bool isReExportedToModule(const ValueDecl *value,
                                 const ModuleDecl *expectedModule) {
  const DeclContext *valueDC = value->getDeclContext();
  auto fromClangModule
      = dyn_cast<ClangModuleUnit>(valueDC->getModuleScopeContext());
  if (!fromClangModule)
    return false;
  StringRef exportedName = fromClangModule->getExportedModuleName();

  auto toClangModule
      = dyn_cast<ClangModuleUnit>(expectedModule->getFiles().front());
  if (toClangModule)
    return exportedName == toClangModule->getExportedModuleName();
  return exportedName == expectedModule->getName().str();
}

/// Remove values from \p values that don't match the expected type or module.
///
/// Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be
/// omitted, in which case any type or module is accepted. Values imported
/// from Clang can also appear in any module.
static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
                         CanGenericSignature expectedGenericSig, bool isType,
                         bool inProtocolExt, bool importedFromClang,
                         bool isStatic,
                         Optional<swift::CtorInitializerKind> ctorInit,
                         SmallVectorImpl<ValueDecl *> &values) {
  CanType canTy;
  if (expectedTy)
    canTy = expectedTy->getCanonicalType();

  auto newEnd = std::remove_if(values.begin(), values.end(),
                               [=](ValueDecl *value) {
    // Ignore anything that was parsed (vs. deserialized), because a serialized
    // module cannot refer to it.
    if (value->getDeclContext()->getParentSourceFile())
      return true;

    if (isType != isa<TypeDecl>(value))
      return true;

    // If we're expecting a type, make sure this decl has the expected type.
    if (canTy)  {
      auto ifaceTy = value->getInterfaceType();
      if (!ifaceTy || !ifaceTy->isEqual(canTy))
        return true;
    }

    if (value->isStatic() != isStatic)
      return true;
    if (value->hasClangNode() != importedFromClang)
      return true;

    if (value->getAttrs().hasAttribute<ForbidSerializingReferenceAttr>())
      return true;

    // FIXME: Should be able to move a value from an extension in a derived
    // module to the original definition in a base module.
    if (expectedModule && !value->hasClangNode() &&
        value->getModuleContext() != expectedModule &&
        !isReExportedToModule(value, expectedModule))
      return true;

    // If we're expecting a member within a constrained extension with a
    // particular generic signature, match that signature.
    if (expectedGenericSig &&
        value->getDeclContext()->getGenericSignatureOfContext()
          ->getCanonicalSignature() != expectedGenericSig)
      return true;

    // If we don't expect a specific generic signature, ignore anything from a
    // constrained extension.
    if (!expectedGenericSig &&
        isa<ExtensionDecl>(value->getDeclContext()) &&
        cast<ExtensionDecl>(value->getDeclContext())->isConstrainedExtension())
      return true;

    // If we're looking at members of a protocol or protocol extension,
    // filter by whether we expect to find something in a protocol extension or
    // not. This lets us distinguish between a protocol member and a protocol
    // extension member that have the same type.
    if (value->getDeclContext()->getSelfProtocolDecl() &&
        (bool)value->getDeclContext()->getExtendedProtocolDecl()
          != inProtocolExt)
      return true;

    // If we're expecting an initializer with a specific kind, and this is not
    // an initializer with that kind, remove it.
    if (ctorInit) {
      if (!isa<ConstructorDecl>(value) ||
          cast<ConstructorDecl>(value)->getInitKind() != *ctorInit)
        return true;
    }
    return false;
  });
  values.erase(newEnd, values.end());
}

Expected<Decl *>
ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
  using namespace decls_block;

  ModuleDecl *baseModule = getModule(MID);
  if (!baseModule) {
    return llvm::make_error<XRefNonLoadedModuleError>(getIdentifier(MID));
  }

  assert(baseModule && "missing dependency");
  PrettyXRefTrace pathTrace(*baseModule);

  auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
  if (entry.Kind != llvm::BitstreamEntry::Record)
    fatal();

  SmallVector<ValueDecl *, 8> values;
  SmallVector<uint64_t, 8> scratch;
  StringRef blobData;

  // Read the first path piece. This one is special because lookup is performed
  // against the base module, rather than against the previous link in the path.
  // In particular, operator path pieces represent actual operators here, but
  // filters on operator functions when they appear later on.
  scratch.clear();
  unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch,
                                                &blobData);
  switch (recordID) {
  case XREF_TYPE_PATH_PIECE:
  case XREF_VALUE_PATH_PIECE: {
    IdentifierID IID;
    IdentifierID privateDiscriminator = 0;
    TypeID TID = 0;
    bool isType = (recordID == XREF_TYPE_PATH_PIECE);
    bool inProtocolExt = false;
    bool importedFromClang = false;
    bool isStatic = false;
    if (isType)
      XRefTypePathPieceLayout::readRecord(scratch, IID, privateDiscriminator,
                                          inProtocolExt, importedFromClang);
    else
      XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
                                           importedFromClang, isStatic);

    DeclBaseName name = getDeclBaseName(IID);
    pathTrace.addValue(name);
    if (privateDiscriminator)
      pathTrace.addValue(getIdentifier(privateDiscriminator));

    Type filterTy;
    if (!isType) {
      auto maybeType = getTypeChecked(TID);
      if (!maybeType) {
        // FIXME: Don't throw away the inner error's information.
        llvm::consumeError(maybeType.takeError());
        return llvm::make_error<XRefError>("couldn't decode type",
                                           pathTrace, name);
      }
      filterTy = maybeType.get();
      pathTrace.addType(filterTy);
    }

    if (privateDiscriminator) {
      baseModule->lookupMember(values, baseModule, name,
                               getIdentifier(privateDiscriminator));
    } else {
      baseModule->lookupQualified(baseModule, name,
                                  NL_QualifiedDefault | NL_KnownNoDependency,
                                  values);
    }
    filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt,
                 importedFromClang, isStatic, None, values);
    break;
  }
      
  case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
    IdentifierID DefiningDeclNameID;
    
    XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, DefiningDeclNameID);
    
    auto name = getIdentifier(DefiningDeclNameID);
    pathTrace.addOpaqueReturnType(name);
    
    if (auto opaque = baseModule->lookupOpaqueResultType(name.str())) {
      values.push_back(opaque);
    }
    break;
  }

  case XREF_EXTENSION_PATH_PIECE:
    llvm_unreachable("can only extend a nominal");

  case XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE: {
    IdentifierID IID;
    uint8_t rawOpKind;
    XRefOperatorOrAccessorPathPieceLayout::readRecord(scratch, IID, rawOpKind);

    Identifier opName = getIdentifier(IID);
    pathTrace.addOperator(opName);

    switch (rawOpKind) {
    case OperatorKind::Infix:
      return baseModule->lookupInfixOperator(opName);
    case OperatorKind::Prefix:
      return baseModule->lookupPrefixOperator(opName);
    case OperatorKind::Postfix:
      return baseModule->lookupPostfixOperator(opName);
    case OperatorKind::PrecedenceGroup:
      return baseModule->lookupPrecedenceGroup(opName);
    default:
      // Unknown operator kind.
      fatal();
    }
  }

  case XREF_GENERIC_PARAM_PATH_PIECE:
  case XREF_INITIALIZER_PATH_PIECE:
    llvm_unreachable("only in a nominal or function");

  default:
    // Unknown xref kind.
    pathTrace.addUnknown(recordID);
    fatal();
  }

  auto getXRefDeclNameForError = [&]() -> DeclName {
    DeclName result = pathTrace.getLastName();
    while (--pathLen) {
      auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
      if (entry.Kind != llvm::BitstreamEntry::Record)
        return Identifier();

      scratch.clear();
      unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch,
                                                    &blobData);
      switch (recordID) {
      case XREF_TYPE_PATH_PIECE: {
        IdentifierID IID;
        XRefTypePathPieceLayout::readRecord(scratch, IID, None, None, None);
        result = getIdentifier(IID);
        break;
      }
      case XREF_VALUE_PATH_PIECE: {
        IdentifierID IID;
        XRefValuePathPieceLayout::readRecord(scratch, None, IID, None, None,
                                             None);
        result = getIdentifier(IID);
        break;
      }
      case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
        IdentifierID IID;
        XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, IID);
        auto mangledName = getIdentifier(IID);
        
        SmallString<64> buf;
        {
          llvm::raw_svector_ostream os(buf);
          os << "<<opaque return type of ";
          os << mangledName.str();
          os << ">>";
        }
        
        result = getContext().getIdentifier(buf);
        break;
      }
      case XREF_INITIALIZER_PATH_PIECE:
        result = DeclBaseName::createConstructor();
        break;

      case XREF_EXTENSION_PATH_PIECE:
      case XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE:
        break;

      case XREF_GENERIC_PARAM_PATH_PIECE:
        // Can't get the name without deserializing.
        result = Identifier();
        break;

      default:
        // Unknown encoding.
        return Identifier();
      }
    }
    return result;
  };

  if (values.empty()) {
    return llvm::make_error<XRefError>("top-level value not found", pathTrace,
                                       getXRefDeclNameForError());
  }

  // Filters for values discovered in the remaining path pieces.
  ModuleDecl *M = nullptr;
  CanGenericSignature genericSig = CanGenericSignature();

  // For remaining path pieces, filter or drill down into the results we have.
  while (--pathLen) {
    auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
    if (entry.Kind != llvm::BitstreamEntry::Record)
      fatal();

    scratch.clear();
    unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch,
                                                  &blobData);
    switch (recordID) {
    case XREF_TYPE_PATH_PIECE: {
      if (values.size() == 1 && isa<NominalTypeDecl>(values.front())) {
        // Fast path for nested types that avoids deserializing all
        // members of the parent type.
        IdentifierID IID;
        IdentifierID privateDiscriminator;
        bool importedFromClang = false;
        bool inProtocolExt = false;
        XRefTypePathPieceLayout::readRecord(scratch, IID, privateDiscriminator,
                                            inProtocolExt, importedFromClang);
        if (privateDiscriminator)
          goto giveUpFastPath;

        Identifier memberName = getIdentifier(IID);
        pathTrace.addValue(memberName);

        llvm::PrettyStackTraceString message{
          "If you're seeing a crash here, try passing "
            "-Xfrontend -disable-serialization-nested-type-lookup-table"};

        auto *baseType = cast<NominalTypeDecl>(values.front());
        ModuleDecl *extensionModule = M;
        if (!extensionModule)
          extensionModule = baseType->getModuleContext();

        // Fault in extensions, then ask every file in the module.
        (void)baseType->getExtensions();
        TypeDecl *nestedType = nullptr;
        for (FileUnit *file : extensionModule->getFiles()) {
          if (file == getFile())
            continue;
          nestedType = file->lookupNestedType(memberName, baseType);
          if (nestedType)
            break;
        }

        if (nestedType) {
          SmallVector<ValueDecl *, 1> singleValueBuffer{nestedType};
          filterValues(/*expectedTy*/Type(), extensionModule, genericSig,
                       /*isType*/true, inProtocolExt, importedFromClang,
                       /*isStatic*/false, /*ctorInit*/None, singleValueBuffer);
          if (!singleValueBuffer.empty()) {
            values.assign({nestedType});
            ++NumNestedTypeShortcuts;
            break;
          }
        }

        pathTrace.removeLast();
      }
giveUpFastPath:
      LLVM_FALLTHROUGH;
    }
    case XREF_VALUE_PATH_PIECE:
    case XREF_INITIALIZER_PATH_PIECE: {
      TypeID TID = 0;
      DeclBaseName memberName;
      Identifier privateDiscriminator;
      Optional<swift::CtorInitializerKind> ctorInit;
      bool isType = false;
      bool inProtocolExt = false;
      bool importedFromClang = false;
      bool isStatic = false;
      switch (recordID) {
      case XREF_TYPE_PATH_PIECE: {
        IdentifierID IID, discriminatorID;
        XRefTypePathPieceLayout::readRecord(scratch, IID, discriminatorID,
                                            inProtocolExt, importedFromClang);
        memberName = getDeclBaseName(IID);
        privateDiscriminator = getIdentifier(discriminatorID);
        isType = true;
        break;
      }

      case XREF_VALUE_PATH_PIECE: {
        IdentifierID IID;
        XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
                                             importedFromClang, isStatic);
        memberName = getDeclBaseName(IID);
        break;
      }

      case XREF_INITIALIZER_PATH_PIECE: {
        uint8_t kind;
        XRefInitializerPathPieceLayout::readRecord(scratch, TID, inProtocolExt,
                                                   importedFromClang, kind);
        memberName = DeclBaseName::createConstructor();
        ctorInit = getActualCtorInitializerKind(kind);
        break;
      }
        
      default:
        llvm_unreachable("Unhandled path piece");
      }

      pathTrace.addValue(memberName);
      if (!privateDiscriminator.empty())
        pathTrace.addPrivateDiscriminator(privateDiscriminator);

      Type filterTy;
      if (!isType) {
        auto maybeType = getTypeChecked(TID);
        if (!maybeType) {
          // FIXME: Don't throw away the inner error's information.
          llvm::consumeError(maybeType.takeError());
          return llvm::make_error<XRefError>("couldn't decode type",
                                             pathTrace, memberName);
        }
        filterTy = maybeType.get();
        pathTrace.addType(filterTy);
      }

      if (values.size() != 1) {
        return llvm::make_error<XRefError>("multiple matching base values",
                                           pathTrace,
                                           getXRefDeclNameForError());
      }

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

      if (!nominal) {
        return llvm::make_error<XRefError>("base is not a nominal type",
                                           pathTrace,
                                           getXRefDeclNameForError());
      }

      if (!privateDiscriminator.empty()) {
        ModuleDecl *searchModule = M;
        if (!searchModule)
          searchModule = nominal->getModuleContext();
        searchModule->lookupMember(values, nominal, memberName,
                                   privateDiscriminator);

      } else {
        auto members = nominal->lookupDirect(memberName);
        values.append(members.begin(), members.end());
      }
      filterValues(filterTy, M, genericSig, isType, inProtocolExt,
                   importedFromClang, isStatic, ctorInit, values);
      break;
    }

    case XREF_EXTENSION_PATH_PIECE: {
      ModuleID ownerID;
      GenericSignatureID rawGenericSig;
      XRefExtensionPathPieceLayout::readRecord(scratch, ownerID, rawGenericSig);
      M = getModule(ownerID);
      if (!M) {
        return llvm::make_error<XRefError>("module is not loaded",
                                           pathTrace, getIdentifier(ownerID));
      }
      pathTrace.addExtension(M);

      // Read the generic signature, if we have one.
      genericSig = CanGenericSignature(getGenericSignature(rawGenericSig));

      continue;
    }

    case XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE: {
      uint8_t rawKind;
      XRefOperatorOrAccessorPathPieceLayout::readRecord(scratch, None,
                                                        rawKind);
      if (values.empty())
        break;

      if (!values.front()->getBaseName().isOperator()) {
        pathTrace.addAccessor(rawKind);
        if (auto storage = dyn_cast<AbstractStorageDecl>(values.front())) {
          auto actualKind = getActualAccessorKind(rawKind);
          if (!actualKind) {
            // Unknown accessor kind.
            fatal();
          }
          values.front() = storage->getAccessor(*actualKind);
          if (!values.front()) {
            return llvm::make_error<XRefError>("missing accessor",
                                               pathTrace,
                                               getXRefDeclNameForError());

          }
        }
        break;
      }

      pathTrace.addOperatorFilter(rawKind);

      auto newEnd = std::remove_if(values.begin(), values.end(),
                                   [=](ValueDecl *value) {
        auto fn = dyn_cast<FuncDecl>(value);
        if (!fn)
          return true;
        if (!fn->getOperatorDecl())
          return true;
        if (getStableFixity(fn->getOperatorDecl()->getKind()) != rawKind)
          return true;
        return false;
      });
      values.erase(newEnd, values.end());
      break;
    }

    case XREF_GENERIC_PARAM_PATH_PIECE: {
      if (values.size() != 1) {
        return llvm::make_error<XRefError>("multiple matching base values",
                                           pathTrace,
                                           getXRefDeclNameForError());
      }

      uint32_t depth, paramIndex;
      XRefGenericParamPathPieceLayout::readRecord(scratch, depth, paramIndex);

      pathTrace.addGenericParam(paramIndex);

      ValueDecl *base = values.front();

      GenericSignature currentSig = GenericSignature();
      if (auto nominal = dyn_cast<NominalTypeDecl>(base)) {
        if (genericSig) {
          // Find an extension in the requested module that has the
          // correct generic signature.
          for (auto ext : nominal->getExtensions()) {
            if (ext->getModuleContext() == M &&
                ext->getGenericSignature()->getCanonicalSignature()
                  == genericSig) {
              currentSig = ext->getGenericSignature();
              break;
            }
          }
          assert(currentSig && "Couldn't find constrained extension");
        } else {
          // Simple case: use the nominal type's generic parameters.
          currentSig = nominal->getGenericSignature();
        }
      } else if (auto alias = dyn_cast<TypeAliasDecl>(base)) {
        currentSig = alias->getGenericSignature();
      } else if (auto fn = dyn_cast<AbstractFunctionDecl>(base)) {
        currentSig = fn->getGenericSignature();
      } else if (auto subscript = dyn_cast<SubscriptDecl>(base)) {
        currentSig = subscript->getGenericSignature();
      } else if (auto opaque = dyn_cast<OpaqueTypeDecl>(base)) {
        currentSig = opaque->getGenericSignature();
      }

      if (!currentSig) {
        return llvm::make_error<XRefError>(
            "cross-reference to generic param for non-generic type",
            pathTrace, getXRefDeclNameForError());
      }

      bool found = false;
      for (auto paramTy : currentSig->getGenericParams()) {
        if (paramTy->getIndex() == paramIndex &&
            paramTy->getDepth() == depth) {
          values.clear();
          values.push_back(paramTy->getDecl());
          found = true;
          break;
        }
      }

      if (!found) {
        return llvm::make_error<XRefError>(
            "invalid generic argument index or depth",
            pathTrace, getXRefDeclNameForError());
      }

      break;
    }
        
    case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
      values.clear();
      IdentifierID DefiningDeclNameID;
      
      XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, DefiningDeclNameID);
      
      auto name = getIdentifier(DefiningDeclNameID);
      pathTrace.addOpaqueReturnType(name);
    
      auto lookupModule = M ? M : baseModule;
      if (auto opaqueTy = lookupModule->lookupOpaqueResultType(name.str())) {
        values.push_back(opaqueTy);
      }
      break;
    }

    default:
      // Unknown xref path piece.
      pathTrace.addUnknown(recordID);
      fatal();
    }

    Optional<PrettyStackTraceModuleFile> traceMsg;
    if (M != getAssociatedModule()) {
      traceMsg.emplace("If you're seeing a crash here, check that your SDK "
                         "and dependencies match the versions used to build",
                       *this);
    }

    if (values.empty()) {
      return llvm::make_error<XRefError>("result not found", pathTrace,
                                         getXRefDeclNameForError());
    }

    // Reset the module filter.
    M = nullptr;
    genericSig = nullptr;
  }

  // Make sure we /used/ the last module filter we got.
  // This catches the case where the last path piece we saw was an Extension
  // path piece, which is not a valid way to end a path. (Cross-references to
  // extensions are not allowed because they cannot be uniquely named.)
  if (M)
    fatal();

  // When all is said and done, we should have a single value here to return.
  if (values.size() != 1) {
    return llvm::make_error<XRefError>("result is ambiguous", pathTrace,
                                       getXRefDeclNameForError());
  }

  assert(values.front() != nullptr);
  return values.front();
}

DeclBaseName ModuleFile::getDeclBaseName(IdentifierID IID) {
  if (IID == 0)
    return Identifier();

  if (IID < NUM_SPECIAL_IDS) {
    switch (static_cast<SpecialIdentifierID>(static_cast<uint8_t>(IID))) {
    case BUILTIN_MODULE_ID:
    case CURRENT_MODULE_ID:
    case OBJC_HEADER_MODULE_ID:
        llvm_unreachable("Cannot get DeclBaseName of special module id");
    case SUBSCRIPT_ID:
      return DeclBaseName::createSubscript();
    case serialization::CONSTRUCTOR_ID:
      return DeclBaseName::createConstructor();
    case serialization::DESTRUCTOR_ID:
      return DeclBaseName::createDestructor();
    case NUM_SPECIAL_IDS:
      llvm_unreachable("implementation detail only");
    }
  }

  size_t rawID = IID - NUM_SPECIAL_IDS;
  assert(rawID < Identifiers.size() && "invalid identifier ID");
  auto &identRecord = Identifiers[rawID];

  if (identRecord.Ident.empty()) {
    StringRef text = getIdentifierText(IID);
    identRecord.Ident = getContext().getIdentifier(text);
  }
  return identRecord.Ident;
}

Identifier ModuleFile::getIdentifier(IdentifierID IID) {
  auto name = getDeclBaseName(IID);
  assert(!name.isSpecial());
  return name.getIdentifier();
}

StringRef ModuleFile::getIdentifierText(IdentifierID IID) {
  if (IID == 0)
    return StringRef();

  assert(IID >= NUM_SPECIAL_IDS);

  size_t rawID = IID - NUM_SPECIAL_IDS;
  assert(rawID < Identifiers.size() && "invalid identifier ID");
  auto identRecord = Identifiers[rawID];

  if (!identRecord.Ident.empty())
    return identRecord.Ident.str();

  assert(!IdentifierData.empty() && "no identifier data in module");

  StringRef rawStrPtr = IdentifierData.substr(identRecord.Offset);
  size_t terminatorOffset = rawStrPtr.find('\0');
  assert(terminatorOffset != StringRef::npos &&
         "unterminated identifier string data");
  return rawStrPtr.slice(0, terminatorOffset);
}

DeclContext *ModuleFile::getLocalDeclContext(LocalDeclContextID DCID) {
  assert(DCID != 0 && "invalid local DeclContext ID 0");
  auto &declContextOrOffset = LocalDeclContexts[DCID-1];

  if (declContextOrOffset.isComplete())
    return declContextOrOffset;

  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(declContextOrOffset);
  auto entry = DeclTypeCursor.advance();

  if (entry.Kind != llvm::BitstreamEntry::Record)
    fatal();

  ASTContext &ctx = getContext();
  SmallVector<uint64_t, 64> scratch;
  StringRef blobData;

  unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch,
                                                &blobData);
  switch(recordID) {
  case decls_block::ABSTRACT_CLOSURE_EXPR_CONTEXT: {
    TypeID closureTypeID;
    unsigned discriminator = 0;
    bool implicit = false;
    DeclContextID parentID;

    decls_block::AbstractClosureExprLayout::readRecord(scratch,
                                                       closureTypeID,
                                                       implicit,
                                                       discriminator,
                                                       parentID);
    DeclContext *parent = getDeclContext(parentID);
    auto type = getType(closureTypeID);

    declContextOrOffset = new (ctx)
      SerializedAbstractClosureExpr(type, implicit, discriminator, parent);
    break;
  }

  case decls_block::TOP_LEVEL_CODE_DECL_CONTEXT: {
    DeclContextID parentID;
    decls_block::TopLevelCodeDeclContextLayout::readRecord(scratch,
                                                           parentID);
    DeclContext *parent = getDeclContext(parentID);

    declContextOrOffset = new (ctx) SerializedTopLevelCodeDeclContext(parent);
    break;
  }

  case decls_block::PATTERN_BINDING_INITIALIZER_CONTEXT: {
    DeclID bindingID;
    uint32_t bindingIndex;
    decls_block::PatternBindingInitializerLayout::readRecord(scratch,
                                                             bindingID,
                                                             bindingIndex);
    auto decl = getDecl(bindingID);
    PatternBindingDecl *binding = cast<PatternBindingDecl>(decl);

    if (!declContextOrOffset.isComplete())
      declContextOrOffset = new (ctx)
        SerializedPatternBindingInitializer(binding, bindingIndex);

    if (!blobData.empty())
      binding->setInitStringRepresentation(bindingIndex, blobData);
    break;
  }

  case decls_block::DEFAULT_ARGUMENT_INITIALIZER_CONTEXT: {
    DeclContextID parentID;
    unsigned index = 0;
    decls_block::DefaultArgumentInitializerLayout::readRecord(scratch,
                                                              parentID,
                                                              index);
    DeclContext *parent = getDeclContext(parentID);

    declContextOrOffset = new (ctx)
      SerializedDefaultArgumentInitializer(index, parent);
    break;
  }

  default:
    llvm_unreachable("Unknown record ID found when reading local DeclContext.");
  }
  return declContextOrOffset;
}

DeclContext *ModuleFile::getDeclContext(DeclContextID DCID) {
  if (!DCID)
    return FileContext;

  if (Optional<LocalDeclContextID> contextID = DCID.getAsLocalDeclContextID())
    return getLocalDeclContext(contextID.getValue());

  auto D = getDecl(DCID.getAsDeclID().getValue());

  if (auto GTD = dyn_cast<GenericTypeDecl>(D))
    return GTD;
  if (auto ED = dyn_cast<ExtensionDecl>(D))
    return ED;
  if (auto AFD = dyn_cast<AbstractFunctionDecl>(D))
    return AFD;
  if (auto SD = dyn_cast<SubscriptDecl>(D))
    return SD;
  if (auto EED = dyn_cast<EnumElementDecl>(D))
    return EED;

  llvm_unreachable("Unknown Decl : DeclContext kind");
}

ModuleDecl *ModuleFile::getModule(ModuleID MID) {
  if (MID < NUM_SPECIAL_IDS) {
    switch (static_cast<SpecialIdentifierID>(static_cast<uint8_t>(MID))) {
    case BUILTIN_MODULE_ID:
      return getContext().TheBuiltinModule;
    case CURRENT_MODULE_ID:
      return FileContext->getParentModule();
    case OBJC_HEADER_MODULE_ID: {
      auto clangImporter =
        static_cast<ClangImporter *>(getContext().getClangModuleLoader());
      return clangImporter->getImportedHeaderModule();
    }
    case SUBSCRIPT_ID:
    case CONSTRUCTOR_ID:
    case DESTRUCTOR_ID:
      llvm_unreachable("Modules cannot be named with special names");
    case NUM_SPECIAL_IDS:
      llvm_unreachable("implementation detail only");
    }
  }
  return getModule(getIdentifier(MID));
}

ModuleDecl *ModuleFile::getModule(ArrayRef<Identifier> name,
                                  bool allowLoading) {
  if (name.empty() || name.front().empty())
    return getContext().TheBuiltinModule;

  // FIXME: duplicated from NameBinder::getModule
  if (name.size() == 1 &&
      name.front() == FileContext->getParentModule()->getName()) {
    if (!UnderlyingModule && allowLoading) {
      auto importer = getContext().getClangModuleLoader();
      assert(importer && "no way to import shadowed module");
      UnderlyingModule = importer->loadModule(SourceLoc(),
                                              {{name.front(), SourceLoc()}});
    }

    return UnderlyingModule;
  }

  SmallVector<ImportDecl::AccessPathElement, 4> importPath;
  for (auto pathElem : name)
    importPath.push_back({ pathElem, SourceLoc() });

  if (allowLoading)
    return getContext().getModule(importPath);
  return getContext().getLoadedModule(importPath);
}


/// Translate from the Serialization associativity enum values to the AST
/// strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<swift::Associativity> getActualAssociativity(uint8_t assoc) {
  switch (assoc) {
  case serialization::Associativity::LeftAssociative:
    return swift::Associativity::Left;
  case serialization::Associativity::RightAssociative:
    return swift::Associativity::Right;
  case serialization::Associativity::NonAssociative:
    return swift::Associativity::None;
  default:
    return None;
  }
}

static Optional<swift::StaticSpellingKind>
getActualStaticSpellingKind(uint8_t raw) {
  switch (serialization::StaticSpellingKind(raw)) {
  case serialization::StaticSpellingKind::None:
    return swift::StaticSpellingKind::None;
  case serialization::StaticSpellingKind::KeywordStatic:
    return swift::StaticSpellingKind::KeywordStatic;
  case serialization::StaticSpellingKind::KeywordClass:
    return swift::StaticSpellingKind::KeywordClass;
  }
  return None;
}

static bool isDeclAttrRecord(unsigned ID) {
  using namespace decls_block;
  switch (ID) {
#define DECL_ATTR(NAME, CLASS, ...) case CLASS##_DECL_ATTR: return true;
#include "DeclTypeRecordNodes.def"
  default: return false;
  }
}

static Optional<swift::AccessLevel> getActualAccessLevel(uint8_t raw) {
  switch (serialization::AccessLevel(raw)) {
#define CASE(NAME) \
  case serialization::AccessLevel::NAME: \
    return swift::AccessLevel::NAME;
  CASE(Private)
  CASE(FilePrivate)
  CASE(Internal)
  CASE(Public)
  CASE(Open)
#undef CASE
  }
  return None;
}

static Optional<swift::SelfAccessKind>
getActualSelfAccessKind(uint8_t raw) {
  switch (serialization::SelfAccessKind(raw)) {
  case serialization::SelfAccessKind::NonMutating:
    return swift::SelfAccessKind::NonMutating;
  case serialization::SelfAccessKind::Mutating:
    return swift::SelfAccessKind::Mutating;
  case serialization::SelfAccessKind::Consuming:
    return swift::SelfAccessKind::Consuming;
  }
  return None;
}

/// Translate from the serialization VarDeclSpecifier enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<swift::ParamDecl::Specifier>
getActualParamDeclSpecifier(serialization::ParamDeclSpecifier raw) {
  switch (raw) {
#define CASE(ID) \
  case serialization::ParamDeclSpecifier::ID: \
    return swift::ParamDecl::Specifier::ID;
  CASE(Default)
  CASE(InOut)
  CASE(Shared)
  CASE(Owned)
  }
#undef CASE
  return None;
}

static Optional<swift::VarDecl::Introducer>
getActualVarDeclIntroducer(serialization::VarDeclIntroducer raw) {
  switch (raw) {
#define CASE(ID) \
  case serialization::VarDeclIntroducer::ID: \
    return swift::VarDecl::Introducer::ID;
  CASE(Let)
  CASE(Var)
  }
#undef CASE
  return None;
}

static Optional<swift::OpaqueReadOwnership>
getActualOpaqueReadOwnership(unsigned rawKind) {
  switch (serialization::OpaqueReadOwnership(rawKind)) {
#define CASE(KIND)                               \
  case serialization::OpaqueReadOwnership::KIND: \
    return swift::OpaqueReadOwnership::KIND;
  CASE(Owned)
  CASE(Borrowed)
  CASE(OwnedOrBorrowed)
#undef CASE
  }
  return None;
}

static Optional<swift::ReadImplKind>
getActualReadImplKind(unsigned rawKind) {
  switch (serialization::ReadImplKind(rawKind)) {
#define CASE(KIND)                        \
  case serialization::ReadImplKind::KIND: \
    return swift::ReadImplKind::KIND;
  CASE(Stored)
  CASE(Get)
  CASE(Inherited)
  CASE(Address)
  CASE(Read)
#undef CASE
  }
  return None;
}

static Optional<swift::WriteImplKind>
getActualWriteImplKind(unsigned rawKind) {
  switch (serialization::WriteImplKind(rawKind)) {
#define CASE(KIND)                         \
  case serialization::WriteImplKind::KIND: \
    return swift::WriteImplKind::KIND;
  CASE(Immutable)
  CASE(Stored)
  CASE(Set)
  CASE(StoredWithObservers)
  CASE(InheritedWithObservers)
  CASE(MutableAddress)
  CASE(Modify)
#undef CASE
  }
  return None;
}

static Optional<swift::ReadWriteImplKind>
getActualReadWriteImplKind(unsigned rawKind) {
  switch (serialization::ReadWriteImplKind(rawKind)) {
#define CASE(KIND)                             \
  case serialization::ReadWriteImplKind::KIND: \
    return swift::ReadWriteImplKind::KIND;
  CASE(Immutable)
  CASE(Stored)
  CASE(MutableAddress)
  CASE(MaterializeToTemporary)
  CASE(Modify)
#undef CASE
  }
  return None;
}

void ModuleFile::configureStorage(AbstractStorageDecl *decl,
                                  uint8_t rawOpaqueReadOwnership,
                                  uint8_t rawReadImplKind,
                                  uint8_t rawWriteImplKind,
                                  uint8_t rawReadWriteImplKind,
                                  AccessorRecord &rawIDs) {
  auto opaqueReadOwnership =
    getActualOpaqueReadOwnership(rawOpaqueReadOwnership);
  if (!opaqueReadOwnership)
    return;
  decl->setOpaqueReadOwnership(*opaqueReadOwnership);

  auto readImpl = getActualReadImplKind(rawReadImplKind);
  if (!readImpl) return;

  auto writeImpl = getActualWriteImplKind(rawWriteImplKind);
  if (!writeImpl) return;

  auto readWriteImpl = getActualReadWriteImplKind(rawReadWriteImplKind);
  if (!readWriteImpl) return;

  SmallVector<AccessorDecl*, 8> accessors;
  for (DeclID id : rawIDs.IDs) {
    auto accessor = dyn_cast_or_null<AccessorDecl>(getDecl(id));
    if (!accessor) return;
    accessors.push_back(accessor);
  }

  auto implInfo = StorageImplInfo(*readImpl, *writeImpl, *readWriteImpl);
  decl->setImplInfo(implInfo);

  if (implInfo.isSimpleStored() && accessors.empty())
    return;

  // We currently don't serialize these locations.
  SourceLoc beginLoc, endLoc;

  decl->setAccessors(beginLoc, accessors, endLoc);
}

template <typename T, typename ...Args>
T *ModuleFile::createDecl(Args &&... args) {
  // Note that this method is not used for all decl kinds.
  static_assert(std::is_base_of<Decl, T>::value, "not a Decl");
  return new (getContext()) T(std::forward<Args>(args)...);
}

static const uint64_t lazyConformanceContextDataPositionMask = 0xFFFFFFFFFFFF;

/// Decode the context data for lazily-loaded conformances.
static std::pair<uint64_t, uint64_t> decodeLazyConformanceContextData(
                                       uint64_t contextData) {
  return std::make_pair(contextData >> 48,
                        contextData & lazyConformanceContextDataPositionMask);
}

/// Encode the context data for lazily-loaded conformances.
static uint64_t encodeLazyConformanceContextData(uint64_t numProtocols,
                                                 uint64_t bitPosition) {
  assert(numProtocols < 0xFFFF);
  assert(bitPosition < lazyConformanceContextDataPositionMask);
  return (numProtocols << 48) | bitPosition;
}

template <typename DERIVED>
static bool attributeChainContains(DeclAttribute *attr) {
  DeclAttributes tempAttrs;
  tempAttrs.setRawAttributeChain(attr);
  static_assert(std::is_trivially_destructible<DeclAttributes>::value,
                "must not try to destroy the attribute chain");
  return tempAttrs.hasAttribute<DERIVED>();
}

Decl *ModuleFile::getDecl(DeclID DID) {
  Expected<Decl *> deserialized = getDeclChecked(DID);
  if (!deserialized) {
    fatal(deserialized.takeError());
  }
  return deserialized.get();
}

/// Used to split up methods that would otherwise live in ModuleFile.
class swift::DeclDeserializer {
  template <typename T>
  using Serialized = ModuleFile::Serialized<T>;
  using TypeID = serialization::TypeID;

  ModuleFile &MF;
  ASTContext &ctx;
  Serialized<Decl *> &declOrOffset;

  DeclAttribute *DAttrs = nullptr;
  DeclAttribute **AttrsNext = &DAttrs;

  Identifier privateDiscriminator;
  unsigned localDiscriminator = 0;
  StringRef filenameForPrivate;

  void AddAttribute(DeclAttribute *Attr) {
    // Advance the linked list.
    // This isn't just using DeclAttributes because that would result in the
    // attributes getting reversed.
    // FIXME: If we reverse them at serialization time we could get rid of this.
    *AttrsNext = Attr;
    AttrsNext = Attr->getMutableNext();
  };

  void handleInherited(llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
                       ArrayRef<uint64_t> rawInheritedIDs) {
    SmallVector<TypeLoc, 2> inheritedTypes;
    for (auto rawID : rawInheritedIDs) {
      auto maybeType = MF.getTypeChecked(rawID);
      if (!maybeType) {
        llvm::consumeError(maybeType.takeError());
        continue;
      }
      inheritedTypes.push_back(TypeLoc::withoutLoc(MF.getType(rawID)));
    }

    auto inherited = ctx.AllocateCopy(inheritedTypes);
    if (auto *typeDecl = decl.dyn_cast<TypeDecl *>())
      typeDecl->setInherited(inherited);
    else
      decl.get<ExtensionDecl *>()->setInherited(inherited);
  }

public:
  DeclDeserializer(ModuleFile &MF, Serialized<Decl *> &declOrOffset)
      : MF(MF), ctx(MF.getContext()), declOrOffset(declOrOffset) {}

  ~DeclDeserializer() {
    if (!declOrOffset.isComplete()) {
      // We failed to deserialize this declaration.
      return;
    }

    Decl *decl = declOrOffset.get();
    if (!decl)
      return;

    if (DAttrs)
      decl->getAttrs().setRawAttributeChain(DAttrs);

    if (auto value = dyn_cast<ValueDecl>(decl)) {
      if (!privateDiscriminator.empty())
        MF.PrivateDiscriminatorsByValue[value] = privateDiscriminator;

      if (localDiscriminator != 0)
        value->setLocalDiscriminator(localDiscriminator);

      if (!filenameForPrivate.empty())
        MF.FilenamesForPrivateValues[value] = filenameForPrivate;
    }
  }

  /// Deserializes decl attribute and attribute-like records from
  /// \c MF.DeclTypesCursor until a non-attribute record is found,
  /// passing each one to AddAttribute.
  llvm::Error deserializeDeclAttributes();

  Expected<Decl *> getDeclCheckedImpl();

  Expected<Decl *> deserializeTypeAlias(ArrayRef<uint64_t> scratch,
                                        StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    TypeID underlyingTypeID, interfaceTypeID;
    bool isImplicit;
    GenericSignatureID genericSigID;
    uint8_t rawAccessLevel;
    ArrayRef<uint64_t> dependencyIDs;

    decls_block::TypeAliasLayout::readRecord(scratch, nameID, contextID,
                                             underlyingTypeID, interfaceTypeID,
                                             isImplicit, genericSigID,
                                             rawAccessLevel, dependencyIDs);

    Identifier name = MF.getIdentifier(nameID);

    for (TypeID dependencyID : dependencyIDs) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()));
      }
    }

    auto DC = MF.getDeclContext(contextID);

    auto genericParams = MF.maybeReadGenericParams(DC);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto alias = MF.createDecl<TypeAliasDecl>(SourceLoc(), SourceLoc(), name,
                                              SourceLoc(), genericParams, DC);
    declOrOffset = alias;

    auto genericSig = MF.getGenericSignature(genericSigID);
    alias->setGenericSignature(genericSig);

    auto underlying = MF.getType(underlyingTypeID);
    alias->setUnderlyingType(underlying);
    
    if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
      alias->setAccess(*accessLevel);
    else
      MF.fatal();

    if (isImplicit)
      alias->setImplicit();

    return alias;
  }

  Expected<Decl *>
  deserializeGenericTypeParamDecl(ArrayRef<uint64_t> scratch,
                                  StringRef blobData) {
    IdentifierID nameID;
    bool isImplicit;
    unsigned depth;
    unsigned index;

    decls_block::GenericTypeParamDeclLayout::readRecord(scratch, nameID,
                                                        isImplicit,
                                                        depth,
                                                        index);

    // Always create GenericTypeParamDecls in the associated module;
    // the real context will reparent them.
    auto DC = MF.getAssociatedModule();
    auto genericParam = MF.createDecl<GenericTypeParamDecl>(
        DC, MF.getIdentifier(nameID), SourceLoc(), depth, index);
    declOrOffset = genericParam;

    if (isImplicit)
      genericParam->setImplicit();

    return genericParam;
  }

  Expected<Decl *>
  deserializeAssociatedTypeDecl(ArrayRef<uint64_t> scratch,
                                StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    TypeID defaultDefinitionID;
    bool isImplicit;
    ArrayRef<uint64_t> rawOverriddenIDs;

    decls_block::AssociatedTypeDeclLayout::readRecord(scratch, nameID,
                                                      contextID,
                                                      defaultDefinitionID,
                                                      isImplicit,
                                                      rawOverriddenIDs);

    auto DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    // The where-clause information is pushed up into the protocol
    // (specifically, into its requirement signature) and
    // serialized/deserialized there, so the actual Decl doesn't need to store
    // it.
    TrailingWhereClause *trailingWhere = nullptr;
    auto assocType = MF.createDecl<AssociatedTypeDecl>(
        DC, SourceLoc(), MF.getIdentifier(nameID), SourceLoc(), trailingWhere,
        &MF, defaultDefinitionID);
    declOrOffset = assocType;

    assert(!assocType->getDeclaredInterfaceType()->hasError() &&
           "erroneous associated type");

    AccessLevel parentAccess = cast<ProtocolDecl>(DC)->getFormalAccess();
    assocType->setAccess(std::max(parentAccess, AccessLevel::Internal));
    if (isImplicit)
      assocType->setImplicit();

    // Overridden associated types.
    SmallVector<ValueDecl *, 2> overriddenAssocTypes;
    for (auto overriddenID : rawOverriddenIDs) {
      if (auto overriddenAssocType =
              dyn_cast_or_null<AssociatedTypeDecl>(MF.getDecl(overriddenID))) {
        overriddenAssocTypes.push_back(overriddenAssocType);
      }
    }
    assocType->setOverriddenDecls(overriddenAssocTypes);

    return assocType;
  }

  Expected<Decl *> deserializeStruct(ArrayRef<uint64_t> scratch,
                                     StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    bool isImplicit;
    bool isObjC;
    GenericSignatureID genericSigID;
    uint8_t rawAccessLevel;
    unsigned numConformances, numInheritedTypes;
    ArrayRef<uint64_t> rawInheritedAndDependencyIDs;

    decls_block::StructLayout::readRecord(scratch, nameID, contextID,
                                          isImplicit, isObjC, genericSigID,
                                          rawAccessLevel,
                                          numConformances, numInheritedTypes,
                                          rawInheritedAndDependencyIDs);

    Identifier name = MF.getIdentifier(nameID);

    for (TypeID dependencyID :
           rawInheritedAndDependencyIDs.slice(numInheritedTypes)) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()));
      }
    }

    auto DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto genericParams = MF.maybeReadGenericParams(DC);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto theStruct = MF.createDecl<StructDecl>(SourceLoc(), name, SourceLoc(),
                                               None, genericParams, DC);
    declOrOffset = theStruct;

    // Read the generic environment.
    theStruct->setGenericSignature(MF.getGenericSignature(genericSigID));

    if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
      theStruct->setAccess(*accessLevel);
    else
      MF.fatal();

    theStruct->setAddedImplicitInitializers();
    if (isImplicit)
      theStruct->setImplicit();
    theStruct->setIsObjC(isObjC);

    handleInherited(theStruct,
                    rawInheritedAndDependencyIDs.slice(0, numInheritedTypes));

    theStruct->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
    skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
    theStruct->setConformanceLoader(
      &MF,
      encodeLazyConformanceContextData(numConformances,
                                       MF.DeclTypeCursor.GetCurrentBitNo()));

    return theStruct;
  }

  Expected<Decl *> deserializeConstructor(ArrayRef<uint64_t> scratch,
                                          StringRef blobData) {
    DeclContextID contextID;
    bool isIUO, isFailable;
    bool isImplicit, isObjC, hasStubImplementation, throws;
    GenericSignatureID genericSigID;
    uint8_t storedInitKind, rawAccessLevel;
    DeclID overriddenID;
    bool needsNewVTableEntry, firstTimeRequired;
    unsigned numArgNames;
    ArrayRef<uint64_t> argNameAndDependencyIDs;

    decls_block::ConstructorLayout::readRecord(scratch, contextID,
                                               isFailable, isIUO, isImplicit,
                                               isObjC, hasStubImplementation,
                                               throws, storedInitKind,
                                               genericSigID,
                                               overriddenID,
                                               rawAccessLevel,
                                               needsNewVTableEntry,
                                               firstTimeRequired,
                                               numArgNames,
                                               argNameAndDependencyIDs);

    // Resolve the name ids.
    SmallVector<Identifier, 2> argNames;
    for (auto argNameID : argNameAndDependencyIDs.slice(0, numArgNames))
      argNames.push_back(MF.getIdentifier(argNameID));
    DeclName name(ctx, DeclBaseName::createConstructor(), argNames);

    Optional<swift::CtorInitializerKind> initKind =
        getActualCtorInitializerKind(storedInitKind);

    DeclDeserializationError::Flags errorFlags;
    unsigned numVTableEntries = 0;
    if (initKind == CtorInitializerKind::Designated)
      errorFlags |= DeclDeserializationError::DesignatedInitializer;
    if (needsNewVTableEntry) {
      numVTableEntries = 1;
      DeclAttributes attrs;
      attrs.setRawAttributeChain(DAttrs);
    }

    auto overridden = MF.getDeclChecked(overriddenID);
    if (!overridden) {
      llvm::consumeError(overridden.takeError());
      return llvm::make_error<OverrideError>(
          name, errorFlags, numVTableEntries);
    }

    for (auto dependencyID : argNameAndDependencyIDs.slice(numArgNames)) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()),
            errorFlags, numVTableEntries);
      }
    }

    auto parent = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto *genericParams = MF.maybeReadGenericParams(parent);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto ctor = MF.createDecl<ConstructorDecl>(name, SourceLoc(), isFailable,
                                               /*FailabilityLoc=*/SourceLoc(),
                                               /*Throws=*/throws,
                                               /*ThrowsLoc=*/SourceLoc(),
                                               /*BodyParams=*/nullptr,
                                               genericParams, parent);
    declOrOffset = ctor;

    ctor->setGenericSignature(MF.getGenericSignature(genericSigID));

    if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
      ctor->setAccess(*accessLevel);
    else
      MF.fatal();

    auto *bodyParams = MF.readParameterList();
    assert(bodyParams && "missing parameters for constructor");
    ctor->setParameters(bodyParams);

    if (auto errorConvention = MF.maybeReadForeignErrorConvention())
      ctor->setForeignErrorConvention(*errorConvention);

    if (auto bodyText = MF.maybeReadInlinableBodyText())
      ctor->setBodyStringRepresentation(*bodyText);

    if (isImplicit)
      ctor->setImplicit();
    ctor->setIsObjC(isObjC);
    if (hasStubImplementation)
      ctor->setStubImplementation(true);
    if (initKind.hasValue())
      ctx.evaluator.cacheOutput(InitKindRequest{ctor},
                                std::move(initKind.getValue()));
    ctx.evaluator.cacheOutput(NeedsNewVTableEntryRequest{ctor},
                              std::move(needsNewVTableEntry));

    ctor->setOverriddenDecl(cast_or_null<ConstructorDecl>(overridden.get()));
    if (auto *overridden = ctor->getOverriddenDecl()) {
      if (!attributeChainContains<RequiredAttr>(DAttrs) ||
          !overridden->isRequired()) {
        // FIXME: why is a convenience init considered overridden when the
        // overriding init can't be marked overriding in source?
        if (!overridden->isConvenienceInit())
          AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
      }
    }

    ctor->setImplicitlyUnwrappedOptional(isIUO);
    ctor->computeType();

    return ctor;
  }

  Expected<Decl *> deserializeVar(ArrayRef<uint64_t> scratch,
                                  StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    bool isImplicit, isObjC, isStatic, hasNonPatternBindingInit;
    uint8_t rawIntroducer;
    bool isGetterMutating, isSetterMutating;
    bool isLazyStorageProperty;
    DeclID lazyStorageID;
    unsigned numAccessors, numBackingProperties;
    uint8_t readImpl, writeImpl, readWriteImpl, opaqueReadOwnership;
    uint8_t rawAccessLevel, rawSetterAccessLevel;
    TypeID interfaceTypeID;
    bool isIUO;
    ModuleFile::AccessorRecord accessors;
    DeclID overriddenID, opaqueReturnTypeID;
    unsigned numVTableEntries;
    ArrayRef<uint64_t> arrayFieldIDs;

    decls_block::VarLayout::readRecord(scratch, nameID, contextID,
                                       isImplicit, isObjC, isStatic, rawIntroducer,
                                       hasNonPatternBindingInit,
                                       isGetterMutating, isSetterMutating,
                                       isLazyStorageProperty,
                                       lazyStorageID,
                                       opaqueReadOwnership,
                                       readImpl, writeImpl, readWriteImpl,
                                       numAccessors,
                                       interfaceTypeID,
                                       isIUO,
                                       overriddenID,
                                       rawAccessLevel, rawSetterAccessLevel,
                                       opaqueReturnTypeID,
                                       numBackingProperties,
                                       numVTableEntries,
                                       arrayFieldIDs);

    Identifier name = MF.getIdentifier(nameID);

    auto getErrorFlags = [&]() {
      // Stored properties in classes still impact class object layout because
      // their offset is computed and stored in the field offset vector.
      DeclDeserializationError::Flags errorFlags;

      if (!isStatic) {
        auto actualReadImpl = getActualReadImplKind(readImpl);
        if (actualReadImpl && *actualReadImpl == ReadImplKind::Stored) {
          errorFlags |= DeclDeserializationError::Flag::NeedsFieldOffsetVectorEntry;
        }
      }

      return errorFlags;
    };

    Expected<Decl *> overridden = MF.getDeclChecked(overriddenID);
    if (!overridden) {
      llvm::consumeError(overridden.takeError());

      return llvm::make_error<OverrideError>(
          name, getErrorFlags(), numVTableEntries);
    }

    // Extract the accessor IDs.
    for (DeclID accessorID : arrayFieldIDs.slice(0, numAccessors)) {
      accessors.IDs.push_back(accessorID);
    }
    arrayFieldIDs = arrayFieldIDs.slice(numAccessors);

    // Extract the backing property IDs.
    auto backingPropertyIDs = arrayFieldIDs.slice(0, numBackingProperties);
    arrayFieldIDs = arrayFieldIDs.slice(numBackingProperties);

    for (TypeID dependencyID : arrayFieldIDs) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()),
            getErrorFlags(), numVTableEntries);
      }
    }

    auto DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto introducer = getActualVarDeclIntroducer(
        (serialization::VarDeclIntroducer) rawIntroducer);
    if (!introducer)
      MF.fatal();

    auto var = MF.createDecl<VarDecl>(/*IsStatic*/ isStatic, *introducer,
                                      /*IsCaptureList*/ false, SourceLoc(),
                                      name, DC);
    var->setHasNonPatternBindingInit(hasNonPatternBindingInit);
    var->setIsGetterMutating(isGetterMutating);
    var->setIsSetterMutating(isSetterMutating);
    declOrOffset = var;

    Type interfaceType = MF.getType(interfaceTypeID);
    var->setInterfaceType(interfaceType);
    var->setImplicitlyUnwrappedOptional(isIUO);

    if (auto referenceStorage = interfaceType->getAs<ReferenceStorageType>())
      AddAttribute(
          new (ctx) ReferenceOwnershipAttr(referenceStorage->getOwnership()));

    MF.configureStorage(var, opaqueReadOwnership,
                        readImpl, writeImpl, readWriteImpl, accessors);
    auto accessLevel = getActualAccessLevel(rawAccessLevel);
    if (!accessLevel)
      MF.fatal();

    var->setAccess(*accessLevel);

    if (var->isSettable(nullptr)) {
      auto setterAccess = getActualAccessLevel(rawSetterAccessLevel);
      if (!setterAccess)
        MF.fatal();
      var->setSetterAccess(*setterAccess);

      // If we have a less-accessible setter, honor that by adding the
      // setter access attribute.
      if (*setterAccess < *accessLevel) {
        AddAttribute(
          new (ctx) SetterAccessAttr(SourceLoc(), SourceLoc(),
                                     *setterAccess, /*implicit*/true));
      }
    }

    if (isImplicit)
      var->setImplicit();
    var->setIsObjC(isObjC);

    var->setOverriddenDecl(cast_or_null<VarDecl>(overridden.get()));
    if (var->getOverriddenDecl())
      AddAttribute(new (ctx) OverrideAttr(SourceLoc()));

    // Add the @_hasStorage attribute if this var has storage.
    if (var->hasStorage())
      AddAttribute(new (ctx) HasStorageAttr(/*isImplicit:*/true));

    if (opaqueReturnTypeID) {
      ctx.evaluator.cacheOutput(
          OpaqueResultTypeRequest{var},
          cast<OpaqueTypeDecl>(MF.getDecl(opaqueReturnTypeID)));
    }

    // If this is a lazy property, record its backing storage.
    if (lazyStorageID) {
      VarDecl *storage = cast<VarDecl>(MF.getDecl(lazyStorageID));
      ctx.evaluator.cacheOutput(
          LazyStoragePropertyRequest{var}, std::move(storage));
    }

    var->setLazyStorageProperty(isLazyStorageProperty);

    // If there are any backing properties, record them.
    if (numBackingProperties > 0) {
      VarDecl *backingVar = cast<VarDecl>(MF.getDecl(backingPropertyIDs[0]));
      VarDecl *storageWrapperVar = nullptr;
      if (numBackingProperties > 1) {
        storageWrapperVar = cast<VarDecl>(MF.getDecl(backingPropertyIDs[1]));
      }

      PropertyWrapperBackingPropertyInfo info(
          backingVar, storageWrapperVar, nullptr, nullptr, nullptr);
      ctx.evaluator.cacheOutput(
          PropertyWrapperBackingPropertyInfoRequest{var}, std::move(info));
      ctx.evaluator.cacheOutput(
          PropertyWrapperBackingPropertyTypeRequest{var},
          backingVar->getInterfaceType());
      backingVar->setOriginalWrappedProperty(var);

      if (storageWrapperVar)
        storageWrapperVar->setOriginalWrappedProperty(var);
    }

    return var;
  }

  Expected<Decl *> deserializeParam(ArrayRef<uint64_t> scratch,
                                    StringRef blobData) {
    IdentifierID argNameID, paramNameID;
    DeclContextID contextID;
    unsigned rawSpecifier;
    TypeID interfaceTypeID;
    bool isIUO;
    bool isVariadic;
    bool isAutoClosure;
    uint8_t rawDefaultArg;

    decls_block::ParamLayout::readRecord(scratch, argNameID, paramNameID,
                                         contextID, rawSpecifier,
                                         interfaceTypeID, isIUO, isVariadic,
                                         isAutoClosure, rawDefaultArg);

    auto DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto specifier = getActualParamDeclSpecifier(
                              (serialization::ParamDeclSpecifier)rawSpecifier);
    if (!specifier)
      MF.fatal();

    auto param = MF.createDecl<ParamDecl>(SourceLoc(), SourceLoc(),
                                          MF.getIdentifier(argNameID),
                                          SourceLoc(),
                                          MF.getIdentifier(paramNameID), DC);
    param->setSpecifier(*specifier);

    declOrOffset = param;

    auto paramTy = MF.getType(interfaceTypeID);
    if (paramTy->hasError()) {
      // FIXME: This should never happen, because we don't serialize
      // error types.
      DC->dumpContext();
      paramTy->dump();
      MF.fatal();
    }

    param->setInterfaceType(paramTy);
    param->setImplicitlyUnwrappedOptional(isIUO);
    param->setVariadic(isVariadic);
    param->setAutoClosure(isAutoClosure);

    // Decode the default argument kind.
    // FIXME: Default argument expression, if available.
    if (auto defaultArg = getActualDefaultArgKind(rawDefaultArg)) {
      param->setDefaultArgumentKind(*defaultArg);
      if (!blobData.empty())
        param->setDefaultValueStringRepresentation(blobData);
    }
    return param;
  }

  Expected<Decl *> deserializeAnyFunc(ArrayRef<uint64_t> scratch,
                                      StringRef blobData,
                                      bool isAccessor) {
    DeclContextID contextID;
    bool isImplicit;
    bool isStatic;
    uint8_t rawStaticSpelling, rawAccessLevel, rawMutModifier;
    uint8_t rawAccessorKind;
    bool isObjC, hasForcedStaticDispatch, throws;
    unsigned numNameComponentsBiased;
    GenericSignatureID genericSigID;
    TypeID resultInterfaceTypeID;
    bool isIUO;
    DeclID associatedDeclID;
    DeclID overriddenID;
    DeclID accessorStorageDeclID;
    bool needsNewVTableEntry, isTransparent;
    DeclID opaqueReturnTypeID;
    ArrayRef<uint64_t> nameAndDependencyIDs;

    if (!isAccessor) {
      decls_block::FuncLayout::readRecord(scratch, contextID, isImplicit,
                                          isStatic, rawStaticSpelling, isObjC,
                                          rawMutModifier,
                                          hasForcedStaticDispatch, throws,
                                          genericSigID,
                                          resultInterfaceTypeID,
                                          isIUO,
                                          associatedDeclID, overriddenID,
                                          numNameComponentsBiased,
                                          rawAccessLevel,
                                          needsNewVTableEntry,
                                          opaqueReturnTypeID,
                                          nameAndDependencyIDs);
    } else {
      decls_block::AccessorLayout::readRecord(scratch, contextID, isImplicit,
                                              isStatic, rawStaticSpelling, isObjC,
                                              rawMutModifier,
                                              hasForcedStaticDispatch, throws,
                                              genericSigID,
                                              resultInterfaceTypeID,
                                              isIUO,
                                              overriddenID,
                                              accessorStorageDeclID,
                                              rawAccessorKind,
                                              rawAccessLevel,
                                              needsNewVTableEntry,
                                              isTransparent,
                                              nameAndDependencyIDs);
    }

    DeclDeserializationError::Flags errorFlags;
    unsigned numVTableEntries = needsNewVTableEntry ? 1 : 0;

    // Parse the accessor-specific fields.
    AbstractStorageDecl *storage = nullptr;
    AccessorKind accessorKind;
    if (isAccessor) {
      auto storageResult = MF.getDeclChecked(accessorStorageDeclID);
      if (!storageResult ||
          !(storage =
              dyn_cast_or_null<AbstractStorageDecl>(storageResult.get()))) {
        // FIXME: "TypeError" isn't exactly correct for this.
        return llvm::make_error<TypeError>(
            DeclName(), takeErrorInfo(storageResult.takeError()),
            errorFlags, numVTableEntries);
      }

      if (auto accessorKindResult = getActualAccessorKind(rawAccessorKind))
        accessorKind = *accessorKindResult;
      else
        MF.fatal();

      // Deserializing the storage declaration will cause a recurrence
      // into this code.  When we come out, don't create the accessor twice.
      // TODO: find some better way of breaking this cycle, like lazily
      // deserializing the accessors.
      if (auto accessor = storage->getAccessor(accessorKind))
        return accessor;
    }

    // Resolve the name ids.
    DeclName name;
    ArrayRef<uint64_t> dependencyIDs;
    if (isAccessor) {
      dependencyIDs = nameAndDependencyIDs;
    } else {
      Identifier baseName = MF.getIdentifier(nameAndDependencyIDs.front());
      if (numNameComponentsBiased != 0) {
        SmallVector<Identifier, 2> names;
        for (auto nameID : nameAndDependencyIDs.slice(1,
                                                      numNameComponentsBiased-1)){
          names.push_back(MF.getIdentifier(nameID));
        }
        name = DeclName(ctx, baseName, names);
        dependencyIDs = nameAndDependencyIDs.slice(numNameComponentsBiased);
      } else {
        name = baseName;
        dependencyIDs = nameAndDependencyIDs.drop_front();
      }
    }

    Expected<Decl *> overriddenOrError = MF.getDeclChecked(overriddenID);
    Decl *overridden;
    if (overriddenOrError) {
      overridden = overriddenOrError.get();
    } else {
      llvm::consumeError(overriddenOrError.takeError());
      // There's one case where we know it's safe to ignore a missing override:
      // if this declaration is '@objc' and 'dynamic'.
      bool canIgnoreMissingOverriddenDecl = false;
      if (isObjC && ctx.LangOpts.EnableDeserializationRecovery) {
        canIgnoreMissingOverriddenDecl =
            std::any_of(DeclAttributes::iterator(DAttrs),
                        DeclAttributes::iterator(nullptr),
                        [](const DeclAttribute *attr) -> bool {
          return isa<DynamicAttr>(attr);
        });
      }
      if (!canIgnoreMissingOverriddenDecl)
        return llvm::make_error<OverrideError>(
            name, errorFlags, numVTableEntries);

      overridden = nullptr;
    }

    for (TypeID dependencyID : dependencyIDs) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()),
            errorFlags, numVTableEntries);
      }
    }

    auto DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    // Read generic params before reading the type, because the type may
    // reference generic parameters, and we want them to have a dummy
    // DeclContext for now.
    GenericParamList *genericParams = MF.maybeReadGenericParams(DC);

    auto staticSpelling = getActualStaticSpellingKind(rawStaticSpelling);
    if (!staticSpelling.hasValue())
      MF.fatal();

    if (declOrOffset.isComplete())
      return declOrOffset;

    FuncDecl *fn;
    if (!isAccessor) {
      fn = FuncDecl::createDeserialized(
        ctx, /*StaticLoc=*/SourceLoc(), staticSpelling.getValue(),
        /*FuncLoc=*/SourceLoc(), name, /*NameLoc=*/SourceLoc(),
        /*Throws=*/throws, /*ThrowsLoc=*/SourceLoc(),
        genericParams, DC);
    } else {
      auto *accessor = AccessorDecl::createDeserialized(
        ctx, /*FuncLoc=*/SourceLoc(), /*AccessorKeywordLoc=*/SourceLoc(),
        accessorKind, storage,
        /*StaticLoc=*/SourceLoc(), staticSpelling.getValue(),
        /*Throws=*/throws, /*ThrowsLoc=*/SourceLoc(),
        genericParams, DC);
      accessor->setIsTransparent(isTransparent);

      fn = accessor;
    }
    declOrOffset = fn;

    fn->setGenericSignature(MF.getGenericSignature(genericSigID));

    if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
      fn->setAccess(*accessLevel);
    else
      MF.fatal();

    if (auto SelfAccessKind = getActualSelfAccessKind(rawMutModifier))
      fn->setSelfAccessKind(*SelfAccessKind);
    else
      MF.fatal();

    if (!isAccessor) {
      if (Decl *associated = MF.getDecl(associatedDeclID)) {
        if (auto op = dyn_cast<OperatorDecl>(associated)) {
          ctx.evaluator.cacheOutput(FunctionOperatorRequest{fn},
                                    std::move(op));

          if (isa<PrefixOperatorDecl>(op))
            fn->getAttrs().add(new (ctx) PrefixAttr(/*implicit*/false));
          else if (isa<PostfixOperatorDecl>(op))
            fn->getAttrs().add(new (ctx) PostfixAttr(/*implicit*/false));
          // Note that an explicit 'infix' is not required.
        }
        // Otherwise, unknown associated decl kind.
      }
    }

    fn->setStatic(isStatic);

    fn->getBodyResultTypeLoc().setType(MF.getType(resultInterfaceTypeID));
    fn->setImplicitlyUnwrappedOptional(isIUO);

    ParameterList *paramList = MF.readParameterList();
    fn->setParameters(paramList);

    if (auto errorConvention = MF.maybeReadForeignErrorConvention())
      fn->setForeignErrorConvention(*errorConvention);

    if (auto bodyText = MF.maybeReadInlinableBodyText())
      fn->setBodyStringRepresentation(*bodyText);

    fn->setOverriddenDecl(cast_or_null<FuncDecl>(overridden));
    if (fn->getOverriddenDecl())
      AddAttribute(new (ctx) OverrideAttr(SourceLoc()));

    if (isImplicit)
      fn->setImplicit();
    fn->setIsObjC(isObjC);
    fn->setForcedStaticDispatch(hasForcedStaticDispatch);
    ctx.evaluator.cacheOutput(NeedsNewVTableEntryRequest{fn},
                              std::move(needsNewVTableEntry));

    if (opaqueReturnTypeID) {
      ctx.evaluator.cacheOutput(
          OpaqueResultTypeRequest{fn},
          cast<OpaqueTypeDecl>(MF.getDecl(opaqueReturnTypeID)));
    }

    // Set the interface type.
    fn->computeType();

    return fn;
  }

  Expected<Decl *> deserializeFunc(ArrayRef<uint64_t> scratch,
                                   StringRef blobData) {
    return deserializeAnyFunc(scratch, blobData, /*isAccessor*/false);
  }
  Expected<Decl *> deserializeAccessor(ArrayRef<uint64_t> scratch,
                                       StringRef blobData) {
    return deserializeAnyFunc(scratch, blobData, /*isAccessor*/true);
  }
      
  Expected<Decl *> deserializeOpaqueType(ArrayRef<uint64_t> scratch,
                                         StringRef blobData) {
    DeclID namingDeclID;
    DeclContextID contextID;
    GenericSignatureID interfaceSigID;
    TypeID interfaceTypeID;
    GenericSignatureID genericSigID;
    SubstitutionMapID underlyingTypeID;
    
    decls_block::OpaqueTypeLayout::readRecord(scratch, contextID,
                                              namingDeclID, interfaceSigID,
                                              interfaceTypeID, genericSigID,
                                              underlyingTypeID);
    
    auto declContext = MF.getDeclContext(contextID);
    auto interfaceSig = MF.getGenericSignature(interfaceSigID);
    auto interfaceType = MF.getType(interfaceTypeID)
                            ->castTo<GenericTypeParamType>();
    
    // Check for reentrancy.
    if (declOrOffset.isComplete())
      return cast<OpaqueTypeDecl>(declOrOffset.get());
      
    // Create the decl.
    auto opaqueDecl =
      new (ctx) OpaqueTypeDecl(nullptr, nullptr, declContext,
                               interfaceSig, interfaceType);
    declOrOffset = opaqueDecl;

    auto namingDecl = cast<ValueDecl>(MF.getDecl(namingDeclID));
    opaqueDecl->setNamingDecl(namingDecl);

    if (auto genericParams = MF.maybeReadGenericParams(opaqueDecl)) {
      ctx.evaluator.cacheOutput(GenericParamListRequest{opaqueDecl},
                                std::move(genericParams));
    }

    auto genericSig = MF.getGenericSignature(genericSigID);
    if (genericSig)
      opaqueDecl->setGenericSignature(genericSig);
    if (underlyingTypeID)
      opaqueDecl->setUnderlyingTypeSubstitutions(
                                       MF.getSubstitutionMap(underlyingTypeID));
    SubstitutionMap subs;
    if (genericSig) {
      subs = genericSig->getIdentitySubstitutionMap();
    }
    auto opaqueTy = OpaqueTypeArchetypeType::get(opaqueDecl, subs);
    auto metatype = MetatypeType::get(opaqueTy);
    opaqueDecl->setInterfaceType(metatype);
    return opaqueDecl;
  }

  Expected<Decl *> deserializePatternBinding(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
    DeclContextID contextID;
    bool isImplicit;
    bool isStatic;
    uint8_t RawStaticSpelling;
    unsigned numPatterns;
    ArrayRef<uint64_t> initContextIDs;

    decls_block::PatternBindingLayout::readRecord(scratch, contextID,
                                                  isImplicit,
                                                  isStatic,
                                                  RawStaticSpelling,
                                                  numPatterns,
                                                  initContextIDs);
    auto StaticSpelling = getActualStaticSpellingKind(RawStaticSpelling);
    if (!StaticSpelling.hasValue())
      MF.fatal();

    auto dc = MF.getDeclContext(contextID);

    SmallVector<std::pair<Pattern *, DeclContextID>, 4> patterns;
    for (unsigned i = 0; i != numPatterns; ++i) {
      auto pattern = MF.readPattern(dc);
      if (!pattern) {
        // Silently drop the pattern...
        llvm::consumeError(pattern.takeError());
        // ...but continue to read any further patterns we're expecting.
        continue;
      }

      patterns.emplace_back(pattern.get(), DeclContextID());
      if (!initContextIDs.empty()) {
        patterns.back().second =
            DeclContextID::getFromOpaqueValue(initContextIDs[i]);
      }
    }

    auto binding =
      PatternBindingDecl::createDeserialized(ctx, SourceLoc(),
                                             StaticSpelling.getValue(),
                                             SourceLoc(), patterns.size(), dc);
    declOrOffset = binding;

    binding->setStatic(isStatic);

    if (isImplicit)
      binding->setImplicit();

    for (unsigned i = 0; i != patterns.size(); ++i) {
      DeclContext *initContext = MF.getDeclContext(patterns[i].second);
      binding->setPattern(i, patterns[i].first, initContext);
    }

    return binding;
  }

  Expected<Decl *> deserializeProtocol(ArrayRef<uint64_t> scratch,
                                       StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    bool isImplicit, isClassBounded, isObjC, existentialTypeSupported;
    uint8_t rawAccessLevel;
    unsigned numInheritedTypes;
    ArrayRef<uint64_t> rawInheritedAndDependencyIDs;

    decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
                                            isImplicit, isClassBounded, isObjC,
                                            existentialTypeSupported,
                                            rawAccessLevel, numInheritedTypes,
                                            rawInheritedAndDependencyIDs);

    Identifier name = MF.getIdentifier(nameID);

    for (TypeID dependencyID :
           rawInheritedAndDependencyIDs.slice(numInheritedTypes)) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()));
      }
    }

    auto DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto proto = MF.createDecl<ProtocolDecl>(DC, SourceLoc(), SourceLoc(), name,
                                             None, /*TrailingWhere=*/nullptr);
    declOrOffset = proto;

    ctx.evaluator.cacheOutput(ProtocolRequiresClassRequest{proto},
                              std::move(isClassBounded));
    ctx.evaluator.cacheOutput(ExistentialTypeSupportedRequest{proto},
                              std::move(existentialTypeSupported));

    if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
      proto->setAccess(*accessLevel);
    else
      MF.fatal();

    auto genericParams = MF.maybeReadGenericParams(DC);
    assert(genericParams && "protocol with no generic parameters?");
    ctx.evaluator.cacheOutput(GenericParamListRequest{proto},
                              std::move(genericParams));

    handleInherited(proto,
                    rawInheritedAndDependencyIDs.slice(0, numInheritedTypes));

    if (isImplicit)
      proto->setImplicit();
    proto->setIsObjC(isObjC);

    proto->setCircularityCheck(CircularityCheck::Checked);

    proto->setLazyRequirementSignature(&MF,
                                       MF.DeclTypeCursor.GetCurrentBitNo());
    skipGenericRequirements(MF.DeclTypeCursor);

    proto->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());

    return proto;
  }

  template <typename OperatorLayout, typename OperatorDecl>
  Expected<Decl *> deserializeUnaryOperator(ArrayRef<uint64_t> scratch,
                                            StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    ArrayRef<uint64_t> designatedNominalTypeDeclIDs;

    OperatorLayout::readRecord(scratch, nameID, contextID,
                               designatedNominalTypeDeclIDs);
    auto DC = MF.getDeclContext(contextID);

    SmallVector<NominalTypeDecl *, 1> designatedNominalTypes;
    for (auto id : designatedNominalTypeDeclIDs) {
      Expected<Decl *> nominal = MF.getDeclChecked(id);
      if (!nominal)
        return nominal.takeError();
      designatedNominalTypes.push_back(cast<NominalTypeDecl>(nominal.get()));
    }

    auto result = MF.createDecl<OperatorDecl>(
        DC, SourceLoc(), MF.getIdentifier(nameID), SourceLoc(),
        ctx.AllocateCopy(designatedNominalTypes));

    declOrOffset = result;
    return result;
  }

  Expected<Decl *> deserializePrefixOperator(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
    return deserializeUnaryOperator<decls_block::PrefixOperatorLayout,
                                    PrefixOperatorDecl>(scratch, blobData);
  }

  Expected<Decl *> deserializePostfixOperator(ArrayRef<uint64_t> scratch,
                                              StringRef blobData) {
    return deserializeUnaryOperator<decls_block::PostfixOperatorLayout,
                                    PostfixOperatorDecl>(scratch, blobData);
  }

  Expected<Decl *> deserializeInfixOperator(ArrayRef<uint64_t> scratch,
                                            StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    DeclID precedenceGroupID;
    ArrayRef<uint64_t> designatedNominalTypeDeclIDs;

    decls_block::InfixOperatorLayout::readRecord(scratch, nameID, contextID,
                                                 precedenceGroupID,
                                                 designatedNominalTypeDeclIDs);

    Expected<Decl *> precedenceGroup = MF.getDeclChecked(precedenceGroupID);
    if (!precedenceGroup)
      return precedenceGroup.takeError();

    auto DC = MF.getDeclContext(contextID);

    SmallVector<NominalTypeDecl *, 1> designatedNominalTypes;
    for (auto id : designatedNominalTypeDeclIDs) {
      Expected<Decl *> nominal = MF.getDeclChecked(id);
      if (!nominal)
        return nominal.takeError();
      designatedNominalTypes.push_back(cast<NominalTypeDecl>(nominal.get()));
    }

    auto result = MF.createDecl<InfixOperatorDecl>(
        DC, SourceLoc(), MF.getIdentifier(nameID), SourceLoc(), SourceLoc(),
        ArrayRef<Identifier>{}, ArrayRef<SourceLoc>{});
    result->setDesignatedNominalTypes(ctx.AllocateCopy(designatedNominalTypes));
    ctx.evaluator.cacheOutput(
        OperatorPrecedenceGroupRequest{result},
        std::move(cast_or_null<PrecedenceGroupDecl>(precedenceGroup.get())));
    
    declOrOffset = result;
    return result;
  }

  Expected<Decl *> deserializePrecedenceGroup(ArrayRef<uint64_t> scratch,
                                              StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    uint8_t rawAssociativity;
    bool assignment;
    unsigned numHigherThan;
    ArrayRef<uint64_t> rawRelations;

    decls_block::PrecedenceGroupLayout::readRecord(scratch, nameID, contextID,
                                                   rawAssociativity,
                                                   assignment, numHigherThan,
                                                   rawRelations);

    auto DC = MF.getDeclContext(contextID);

    auto associativity = getActualAssociativity(rawAssociativity);
    if (!associativity.hasValue())
      MF.fatal();

    if (numHigherThan > rawRelations.size())
      MF.fatal();

    SmallVector<PrecedenceGroupDecl::Relation, 4> higherThan;
    for (auto relID : rawRelations.slice(0, numHigherThan)) {
      PrecedenceGroupDecl *rel = nullptr;
      if (relID)
        rel = dyn_cast_or_null<PrecedenceGroupDecl>(MF.getDecl(relID));
      if (!rel)
        MF.fatal();

      higherThan.push_back({SourceLoc(), rel->getName(), rel});
    }

    SmallVector<PrecedenceGroupDecl::Relation, 4> lowerThan;
    for (auto relID : rawRelations.slice(numHigherThan)) {
      PrecedenceGroupDecl *rel = nullptr;
      if (relID)
        rel = dyn_cast_or_null<PrecedenceGroupDecl>(MF.getDecl(relID));
      if (!rel)
        MF.fatal();

      lowerThan.push_back({SourceLoc(), rel->getName(), rel});
    }

    declOrOffset = PrecedenceGroupDecl::create(DC, SourceLoc(), SourceLoc(),
                                               MF.getIdentifier(nameID),
                                               SourceLoc(),
                                               SourceLoc(), SourceLoc(),
                                               *associativity,
                                               SourceLoc(), SourceLoc(),
                                               assignment,
                                               SourceLoc(), higherThan,
                                               SourceLoc(), lowerThan,
                                               SourceLoc());
    return declOrOffset.get();
  }

  Expected<Decl *> deserializeClass(ArrayRef<uint64_t> scratch,
                                    StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    bool isImplicit, isObjC;
    bool inheritsSuperclassInitializers;
    GenericSignatureID genericSigID;
    TypeID superclassID;
    uint8_t rawAccessLevel;
    unsigned numConformances, numInheritedTypes;
    ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
    decls_block::ClassLayout::readRecord(scratch, nameID, contextID,
                                         isImplicit, isObjC,
                                         inheritsSuperclassInitializers,
                                         genericSigID, superclassID,
                                         rawAccessLevel, numConformances,
                                         numInheritedTypes,
                                         rawInheritedAndDependencyIDs);

    Identifier name = MF.getIdentifier(nameID);

    for (TypeID dependencyID :
           rawInheritedAndDependencyIDs.slice(numInheritedTypes)) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()));
      }
    }

    auto DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto genericParams = MF.maybeReadGenericParams(DC);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto theClass = MF.createDecl<ClassDecl>(SourceLoc(), name, SourceLoc(),
                                             None, genericParams, DC);
    declOrOffset = theClass;

    theClass->setGenericSignature(MF.getGenericSignature(genericSigID));

    if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
      theClass->setAccess(*accessLevel);
    else
      MF.fatal();

    theClass->setAddedImplicitInitializers();
    if (isImplicit)
      theClass->setImplicit();
    theClass->setIsObjC(isObjC);
    theClass->setSuperclass(MF.getType(superclassID));
    if (inheritsSuperclassInitializers)
      theClass->setInheritsSuperclassInitializers();

    handleInherited(theClass,
                    rawInheritedAndDependencyIDs.slice(0, numInheritedTypes));

    theClass->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
    skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
    theClass->setConformanceLoader(
      &MF,
      encodeLazyConformanceContextData(numConformances,
                                       MF.DeclTypeCursor.GetCurrentBitNo()));

    theClass->setCircularityCheck(CircularityCheck::Checked);
    return theClass;
  }

  Expected<Decl *> deserializeEnum(ArrayRef<uint64_t> scratch,
                                   StringRef blobData) {
    IdentifierID nameID;
    DeclContextID contextID;
    bool isImplicit;
    bool isObjC;
    GenericSignatureID genericSigID;
    TypeID rawTypeID;
    uint8_t rawAccessLevel;
    unsigned numConformances, numInherited;
    ArrayRef<uint64_t> rawInheritedAndDependencyIDs;

    decls_block::EnumLayout::readRecord(scratch, nameID, contextID,
                                        isImplicit, isObjC, genericSigID,
                                        rawTypeID, rawAccessLevel,
                                        numConformances, numInherited,
                                        rawInheritedAndDependencyIDs);

    auto DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    Identifier name = MF.getIdentifier(nameID);
    for (TypeID dependencyID :
           rawInheritedAndDependencyIDs.slice(numInherited)) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()));
      }
    }

    auto genericParams = MF.maybeReadGenericParams(DC);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto theEnum = MF.createDecl<EnumDecl>(SourceLoc(), name, SourceLoc(), None,
                                           genericParams, DC);

    declOrOffset = theEnum;

    theEnum->setGenericSignature(MF.getGenericSignature(genericSigID));

    if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
      theEnum->setAccess(*accessLevel);
    else
      MF.fatal();

    theEnum->setAddedImplicitInitializers();
    // @objc enums have all their raw values checked.
    if (isObjC) {
      theEnum->setHasFixedRawValues();
    }
    
    if (isImplicit)
      theEnum->setImplicit();
    theEnum->setIsObjC(isObjC);

    theEnum->setRawType(MF.getType(rawTypeID));

    auto rawInheritedIDs = rawInheritedAndDependencyIDs.slice(0, numInherited);
    handleInherited(theEnum, rawInheritedIDs);

    theEnum->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
    skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
    theEnum->setConformanceLoader(
      &MF,
      encodeLazyConformanceContextData(numConformances,
                                       MF.DeclTypeCursor.GetCurrentBitNo()));
    return theEnum;
  }

  Expected<Decl *> deserializeEnumElement(ArrayRef<uint64_t> scratch,
                                          StringRef blobData) {
    DeclContextID contextID;
    bool isImplicit, hasPayload, isRawValueImplicit, isNegative;
    unsigned rawValueKindID;
    IdentifierID rawValueData;
    unsigned numArgNames;
    ArrayRef<uint64_t> argNameAndDependencyIDs;

    decls_block::EnumElementLayout::readRecord(scratch, contextID,
                                               isImplicit, hasPayload,
                                               rawValueKindID,
                                               isRawValueImplicit, isNegative,
                                               rawValueData,
                                               numArgNames,
                                               argNameAndDependencyIDs);

    // Resolve the name ids.
    Identifier baseName = MF.getIdentifier(argNameAndDependencyIDs.front());
    SmallVector<Identifier, 2> argNames;
    for (auto argNameID : argNameAndDependencyIDs.slice(1, numArgNames-1))
      argNames.push_back(MF.getIdentifier(argNameID));
    DeclName compoundName(ctx, baseName, argNames);
    DeclName name = argNames.empty() ? baseName : compoundName;

    for (TypeID dependencyID : argNameAndDependencyIDs.slice(numArgNames)) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        // Enum elements never introduce missing members in their parent enum.
        //
        // A frozen enum cannot be laid out if its missing cases anyway,
        // so the dependency mechanism ensures the entire enum fails to
        // deserialize.
        //
        // For a resilient enum, we don't care and just drop the element
        // and continue.
        return llvm::make_error<TypeError>(
          name, takeErrorInfo(dependency.takeError()));
      }
    }

    DeclContext *DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto elem = MF.createDecl<EnumElementDecl>(SourceLoc(),
                                               name,
                                               nullptr,
                                               SourceLoc(),
                                               nullptr,
                                               DC);
    declOrOffset = elem;

    // Read payload parameter list, if it exists.
    if (hasPayload) {
      auto *paramList = MF.readParameterList();
      elem->setParameterList(paramList);
    }

    // Deserialize the literal raw value, if any.
    switch ((EnumElementRawValueKind)rawValueKindID) {
    case EnumElementRawValueKind::None:
      break;
    case EnumElementRawValueKind::IntegerLiteral: {
      auto literalText = MF.getIdentifierText(rawValueData);
      auto literal = new (ctx) IntegerLiteralExpr(literalText, SourceLoc(),
                                                  isRawValueImplicit);
      if (isNegative)
        literal->setNegative(SourceLoc());
      elem->setRawValueExpr(literal);
    }
    }

    if (isImplicit)
      elem->setImplicit();
    elem->setAccess(std::max(cast<EnumDecl>(DC)->getFormalAccess(),
                             AccessLevel::Internal));

    return elem;
  }

  Expected<Decl *> deserializeSubscript(ArrayRef<uint64_t> scratch,
                                        StringRef blobData) {
    DeclContextID contextID;
    bool isImplicit, isObjC, isGetterMutating, isSetterMutating;
    GenericSignatureID genericSigID;
    TypeID elemInterfaceTypeID;
    bool isIUO;
    ModuleFile::AccessorRecord accessors;
    DeclID overriddenID, opaqueReturnTypeID;
    uint8_t rawAccessLevel, rawSetterAccessLevel, rawStaticSpelling;
    uint8_t opaqueReadOwnership, readImpl, writeImpl, readWriteImpl;
    unsigned numArgNames, numAccessors;
    unsigned numVTableEntries;
    ArrayRef<uint64_t> argNameAndDependencyIDs;

    decls_block::SubscriptLayout::readRecord(scratch, contextID,
                                             isImplicit, isObjC,
                                             isGetterMutating, isSetterMutating,
                                             opaqueReadOwnership,
                                             readImpl, writeImpl, readWriteImpl,
                                             numAccessors,
                                             genericSigID,
                                             elemInterfaceTypeID,
                                             isIUO,
                                             overriddenID, rawAccessLevel,
                                             rawSetterAccessLevel,
                                             rawStaticSpelling, numArgNames,
                                             opaqueReturnTypeID,
                                             numVTableEntries,
                                             argNameAndDependencyIDs);
    // Resolve the name ids.
    SmallVector<Identifier, 2> argNames;
    for (auto argNameID : argNameAndDependencyIDs.slice(0, numArgNames))
      argNames.push_back(MF.getIdentifier(argNameID));
    DeclName name(ctx, DeclBaseName::createSubscript(), argNames);
    argNameAndDependencyIDs = argNameAndDependencyIDs.slice(numArgNames);

    // Exctract the accessor IDs.
    for (DeclID accessorID : argNameAndDependencyIDs.slice(0, numAccessors)) {
      accessors.IDs.push_back(accessorID);
    }
    argNameAndDependencyIDs = argNameAndDependencyIDs.slice(numAccessors);

    Expected<Decl *> overridden = MF.getDeclChecked(overriddenID);
    if (!overridden) {
      llvm::consumeError(overridden.takeError());

      DeclDeserializationError::Flags errorFlags;
      return llvm::make_error<OverrideError>(
          name, errorFlags, numVTableEntries);
    }

    for (TypeID dependencyID : argNameAndDependencyIDs) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        DeclDeserializationError::Flags errorFlags;
        return llvm::make_error<TypeError>(
            name, takeErrorInfo(dependency.takeError()),
            errorFlags, numVTableEntries);
      }
    }

    auto parent = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto *genericParams = MF.maybeReadGenericParams(parent);
    if (declOrOffset.isComplete())
      return declOrOffset;
    
    auto staticSpelling = getActualStaticSpellingKind(rawStaticSpelling);
    if (!staticSpelling.hasValue())
      MF.fatal();

    auto subscript = MF.createDecl<SubscriptDecl>(name,
                                                  SourceLoc(), *staticSpelling,
                                                  SourceLoc(), nullptr,
                                                  SourceLoc(), TypeLoc(),
                                                  parent, genericParams);
    subscript->setIsGetterMutating(isGetterMutating);
    subscript->setIsSetterMutating(isSetterMutating);
    declOrOffset = subscript;

    subscript->setGenericSignature(MF.getGenericSignature(genericSigID));

    subscript->setIndices(MF.readParameterList());

    MF.configureStorage(subscript, opaqueReadOwnership,
                        readImpl, writeImpl, readWriteImpl, accessors);

    if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
      subscript->setAccess(*accessLevel);
    else
      MF.fatal();

    if (subscript->supportsMutation()) {
      if (auto setterAccess = getActualAccessLevel(rawSetterAccessLevel))
        subscript->setSetterAccess(*setterAccess);
      else
        MF.fatal();
    }

    auto elemInterfaceType = MF.getType(elemInterfaceTypeID);
    subscript->getElementTypeLoc().setType(elemInterfaceType);
    subscript->setImplicitlyUnwrappedOptional(isIUO);

    if (isImplicit)
      subscript->setImplicit();
    subscript->setIsObjC(isObjC);
    subscript->setOverriddenDecl(cast_or_null<SubscriptDecl>(overridden.get()));
    if (subscript->getOverriddenDecl())
      AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
    
    if (opaqueReturnTypeID) {
      ctx.evaluator.cacheOutput(
          OpaqueResultTypeRequest{subscript},
          cast<OpaqueTypeDecl>(MF.getDecl(opaqueReturnTypeID)));
    }
    
    return subscript;
  }

  Expected<Decl *> deserializeExtension(ArrayRef<uint64_t> scratch,
                                        StringRef blobData) {
    TypeID extendedTypeID;
    DeclID extendedNominalID;
    DeclContextID contextID;
    bool isImplicit;
    GenericSignatureID genericSigID;
    unsigned numConformances, numInherited;
    ArrayRef<uint64_t> inheritedAndDependencyIDs;

    decls_block::ExtensionLayout::readRecord(scratch, extendedTypeID,
                                             extendedNominalID, contextID,
                                             isImplicit, genericSigID,
                                             numConformances, numInherited,
                                             inheritedAndDependencyIDs);

    auto DC = MF.getDeclContext(contextID);

    for (TypeID dependencyID : inheritedAndDependencyIDs.slice(numInherited)) {
      auto dependency = MF.getTypeChecked(dependencyID);
      if (!dependency) {
        return llvm::make_error<ExtensionError>(
            takeErrorInfo(dependency.takeError()));
      }
    }

    if (declOrOffset.isComplete())
      return declOrOffset;

    auto extension = ExtensionDecl::create(ctx, SourceLoc(), nullptr, { },
                                           DC, nullptr);
    declOrOffset = extension;

    // Generic parameter lists are written from outermost to innermost.
    // Keep reading until we run out of generic parameter lists.
    GenericParamList *outerParams = nullptr;
    while (auto *genericParams = MF.maybeReadGenericParams(DC)) {
      genericParams->setOuterParameters(outerParams);

      // Set up the DeclContexts for the GenericTypeParamDecls in the list.
      for (auto param : *genericParams)
        param->setDeclContext(extension);

      outerParams = genericParams;
    }
    ctx.evaluator.cacheOutput(GenericParamListRequest{extension},
                              std::move(outerParams));

    extension->setGenericSignature(MF.getGenericSignature(genericSigID));

    auto extendedType = MF.getType(extendedTypeID);
    ctx.evaluator.cacheOutput(ExtendedTypeRequest{extension},
                              std::move(extendedType));
    auto nominal = dyn_cast<NominalTypeDecl>(MF.getDecl(extendedNominalID));
    ctx.evaluator.cacheOutput(ExtendedNominalRequest{extension},
                              std::move(nominal));

    if (isImplicit)
      extension->setImplicit();

    auto rawInheritedIDs = inheritedAndDependencyIDs.slice(0, numInherited);
    handleInherited(extension, rawInheritedIDs);

    extension->setMemberLoader(&MF, MF.DeclTypeCursor.GetCurrentBitNo());
    skipRecord(MF.DeclTypeCursor, decls_block::MEMBERS);
    extension->setConformanceLoader(
      &MF,
      encodeLazyConformanceContextData(numConformances,
                                       MF.DeclTypeCursor.GetCurrentBitNo()));

    nominal->addExtension(extension);

#ifndef NDEBUG
    if (outerParams) {
      unsigned paramCount = 0;
      for (auto *paramList = outerParams;
           paramList != nullptr;
           paramList = paramList->getOuterParameters()) {
        paramCount += paramList->size();
      }
      assert(paramCount ==
             extension->getGenericSignature()->getGenericParams().size());
    }
#endif

    return extension;
  }

  Expected<Decl *> deserializeDestructor(ArrayRef<uint64_t> scratch,
                                         StringRef blobData) {
    DeclContextID contextID;
    bool isImplicit, isObjC;
    GenericSignatureID genericSigID;

    decls_block::DestructorLayout::readRecord(scratch, contextID,
                                              isImplicit, isObjC,
                                              genericSigID);

    DeclContext *DC = MF.getDeclContext(contextID);
    if (declOrOffset.isComplete())
      return declOrOffset;

    auto dtor = MF.createDecl<DestructorDecl>(SourceLoc(), DC);
    declOrOffset = dtor;

    if (auto bodyText = MF.maybeReadInlinableBodyText())
      dtor->setBodyStringRepresentation(*bodyText);

    dtor->setGenericSignature(MF.getGenericSignature(genericSigID));

    dtor->setAccess(std::max(cast<ClassDecl>(DC)->getFormalAccess(),
                             AccessLevel::Internal));
    dtor->computeType();

    if (isImplicit)
      dtor->setImplicit();
    dtor->setIsObjC(isObjC);

    return dtor;
  }
};

Expected<Decl *>
ModuleFile::getDeclChecked(DeclID DID) {
  if (DID == 0)
    return nullptr;

  assert(DID <= Decls.size() && "invalid decl ID");
  auto &declOrOffset = Decls[DID-1];

  if (!declOrOffset.isComplete()) {
    ++NumDeclsLoaded;
    BCOffsetRAII restoreOffset(DeclTypeCursor);
    DeclTypeCursor.JumpToBit(declOrOffset);

    Expected<Decl *> deserialized =
      DeclDeserializer(*this, declOrOffset).getDeclCheckedImpl();
    if (!deserialized)
      return deserialized;
  }

  // Tag every deserialized ValueDecl coming out of getDeclChecked with its ID.
  assert(declOrOffset.isComplete());
  if (auto *IDC = dyn_cast_or_null<IterableDeclContext>(declOrOffset.get())) {
    // Only set the DeclID on the returned Decl if it's one that was loaded
    // and _wasn't_ one that had its DeclID set elsewhere (a followed XREF).
    if (IDC->wasDeserialized() &&
        static_cast<uint32_t>(IDC->getDeclID()) == 0) {
      IDC->setDeclID(DID);
    }
  }
  return declOrOffset;
}

llvm::Error DeclDeserializer::deserializeDeclAttributes() {
  using namespace decls_block;

  SmallVector<uint64_t, 64> scratch;
  StringRef blobData;
  while (true) {
    BCOffsetRAII restoreOffset(MF.DeclTypeCursor);
    auto entry = MF.DeclTypeCursor.advance();
    if (entry.Kind != llvm::BitstreamEntry::Record) {
      // We don't know how to serialize decls represented by sub-blocks.
      MF.fatal();
    }

    unsigned recordID = MF.DeclTypeCursor.readRecord(entry.ID, scratch,
                                                     &blobData);

    if (isDeclAttrRecord(recordID)) {
      DeclAttribute *Attr = nullptr;
      switch (recordID) {
      case decls_block::SILGenName_DECL_ATTR: {
        bool isImplicit;
        serialization::decls_block::SILGenNameDeclAttrLayout::readRecord(
            scratch, isImplicit);
        Attr = new (ctx) SILGenNameAttr(blobData, isImplicit);
        break;
      }

      case decls_block::CDecl_DECL_ATTR: {
        bool isImplicit;
        serialization::decls_block::CDeclDeclAttrLayout::readRecord(
            scratch, isImplicit);
        Attr = new (ctx) CDeclAttr(blobData, isImplicit);
        break;
      }

      case decls_block::Alignment_DECL_ATTR: {
        bool isImplicit;
        unsigned alignment;
        serialization::decls_block::AlignmentDeclAttrLayout::readRecord(
            scratch, isImplicit, alignment);
        Attr = new (ctx) AlignmentAttr(alignment, SourceLoc(), SourceRange(),
                                       isImplicit);
        break;
      }

      case decls_block::SwiftNativeObjCRuntimeBase_DECL_ATTR: {
        bool isImplicit;
        IdentifierID nameID;
        serialization::decls_block::SwiftNativeObjCRuntimeBaseDeclAttrLayout
          ::readRecord(scratch, isImplicit, nameID);

        auto name = MF.getIdentifier(nameID);
        Attr = new (ctx) SwiftNativeObjCRuntimeBaseAttr(name, SourceLoc(),
                                                        SourceRange(),
                                                        isImplicit);
        break;
      }

      case decls_block::Semantics_DECL_ATTR: {
        bool isImplicit;
        serialization::decls_block::SemanticsDeclAttrLayout::readRecord(
            scratch, isImplicit);
        Attr = new (ctx) SemanticsAttr(blobData, isImplicit);
        break;
      }

      case decls_block::Inline_DECL_ATTR: {
        unsigned kind;
        serialization::decls_block::InlineDeclAttrLayout::readRecord(
            scratch, kind);
        Attr = new (ctx) InlineAttr((InlineKind)kind);
        break;
      }

      case decls_block::Optimize_DECL_ATTR: {
        unsigned kind;
        serialization::decls_block::OptimizeDeclAttrLayout::readRecord(
            scratch, kind);
        Attr = new (ctx) OptimizeAttr((OptimizationMode)kind);
        break;
      }

      case decls_block::Effects_DECL_ATTR: {
        unsigned kind;
        serialization::decls_block::EffectsDeclAttrLayout::readRecord(scratch,
                                                                      kind);
        Attr = new (ctx) EffectsAttr((EffectsKind)kind);
        break;
      }

      case decls_block::Available_DECL_ATTR: {
        bool isImplicit;
        bool isUnavailable;
        bool isDeprecated;
        bool isPackageDescriptionVersionSpecific;
        DEF_VER_TUPLE_PIECES(Introduced);
        DEF_VER_TUPLE_PIECES(Deprecated);
        DEF_VER_TUPLE_PIECES(Obsoleted);
        unsigned platform, messageSize, renameSize;
        // Decode the record, pulling the version tuple information.
        serialization::decls_block::AvailableDeclAttrLayout::readRecord(
            scratch, isImplicit, isUnavailable, isDeprecated,
            isPackageDescriptionVersionSpecific,
            LIST_VER_TUPLE_PIECES(Introduced),
            LIST_VER_TUPLE_PIECES(Deprecated),
            LIST_VER_TUPLE_PIECES(Obsoleted),
            platform, messageSize, renameSize);

        StringRef message = blobData.substr(0, messageSize);
        blobData = blobData.substr(messageSize);
        StringRef rename = blobData.substr(0, renameSize);
        llvm::VersionTuple Introduced, Deprecated, Obsoleted;
        DECODE_VER_TUPLE(Introduced)
        DECODE_VER_TUPLE(Deprecated)
        DECODE_VER_TUPLE(Obsoleted)

        PlatformAgnosticAvailabilityKind platformAgnostic;
        if (isUnavailable)
          platformAgnostic = PlatformAgnosticAvailabilityKind::Unavailable;
        else if (isDeprecated)
          platformAgnostic = PlatformAgnosticAvailabilityKind::Deprecated;
        else if (((PlatformKind)platform) == PlatformKind::none &&
                 (!Introduced.empty() ||
                  !Deprecated.empty() ||
                  !Obsoleted.empty()))
          platformAgnostic = isPackageDescriptionVersionSpecific ?
            PlatformAgnosticAvailabilityKind::PackageDescriptionVersionSpecific:
            PlatformAgnosticAvailabilityKind::SwiftVersionSpecific;
        else
          platformAgnostic = PlatformAgnosticAvailabilityKind::None;

        Attr = new (ctx) AvailableAttr(
          SourceLoc(), SourceRange(),
          (PlatformKind)platform, message, rename,
          Introduced, SourceRange(),
          Deprecated, SourceRange(),
          Obsoleted, SourceRange(),
          platformAgnostic, isImplicit);
        break;
      }

      case decls_block::ObjC_DECL_ATTR: {
        bool isImplicit;
        bool isImplicitName;
        bool isSwift3Inferred;
        uint64_t numArgs;
        ArrayRef<uint64_t> rawPieceIDs;
        serialization::decls_block::ObjCDeclAttrLayout::readRecord(
          scratch, isImplicit, isSwift3Inferred, isImplicitName, numArgs,
          rawPieceIDs);

        SmallVector<Identifier, 4> pieces;
        for (auto pieceID : rawPieceIDs)
          pieces.push_back(MF.getIdentifier(pieceID));

        if (numArgs == 0)
          Attr = ObjCAttr::create(ctx, None, isImplicitName);
        else
          Attr = ObjCAttr::create(ctx, ObjCSelector(ctx, numArgs-1, pieces),
                                  isImplicitName);
        Attr->setImplicit(isImplicit);
        cast<ObjCAttr>(Attr)->setSwift3Inferred(isSwift3Inferred);
        break;
      }

      case decls_block::Specialize_DECL_ATTR: {
        unsigned exported;
        SpecializeAttr::SpecializationKind specializationKind;
        unsigned specializationKindVal;
        GenericSignatureID specializedSigID;

        serialization::decls_block::SpecializeDeclAttrLayout::readRecord(
          scratch, exported, specializationKindVal, specializedSigID);

        specializationKind = specializationKindVal
                                 ? SpecializeAttr::SpecializationKind::Partial
                                 : SpecializeAttr::SpecializationKind::Full;

        auto specializedSig = MF.getGenericSignature(specializedSigID);
        Attr = SpecializeAttr::create(ctx, SourceLoc(), SourceRange(),
                                      nullptr, exported != 0,
                                      specializationKind,
                                      specializedSig);
        break;
      }

      // SWIFT_ENABLE_TENSORFLOW
      case decls_block::Differentiable_DECL_ATTR: {
        bool isImplicit;
        bool linear;
        uint64_t jvpNameId;
        DeclID jvpDeclId;
        uint64_t vjpNameId;
        DeclID vjpDeclId;
        GenericSignatureID derivativeGenSigId;
        ArrayRef<uint64_t> parameters;

        serialization::decls_block::DifferentiableDeclAttrLayout::readRecord(
            scratch, isImplicit, linear, jvpNameId, jvpDeclId, vjpNameId,
            vjpDeclId, derivativeGenSigId, parameters);

        Optional<DeclNameWithLoc> jvp;
        FuncDecl *jvpDecl = nullptr;
        if (jvpNameId != 0)
          jvp = { MF.getIdentifier(jvpNameId), DeclNameLoc() };
        if (jvpDeclId != 0)
          jvpDecl = cast<FuncDecl>(MF.getDecl(jvpDeclId));

        Optional<DeclNameWithLoc> vjp;
        FuncDecl *vjpDecl = nullptr;
        if (vjpNameId != 0)
          vjp = { MF.getIdentifier(vjpNameId), DeclNameLoc() };
        if (vjpDeclId != 0)
          vjpDecl = cast<FuncDecl>(MF.getDecl(vjpDeclId));

        auto derivativeGenSig = MF.getGenericSignature(derivativeGenSigId);

        llvm::SmallBitVector parametersBitVector(parameters.size());
        for (unsigned i : indices(parameters))
          parametersBitVector[i] = parameters[i];
        auto *indices = IndexSubset::get(ctx, parametersBitVector);

        auto diffAttr =
            DifferentiableAttr::create(ctx, isImplicit, SourceLoc(),
                                       SourceRange(), linear, indices, jvp, vjp,
                                       derivativeGenSig);
        diffAttr->setJVPFunction(jvpDecl);
        diffAttr->setVJPFunction(vjpDecl);
        Attr = diffAttr;
        break;
      }

      case decls_block::DynamicReplacement_DECL_ATTR: {
        bool isImplicit;
        uint64_t numArgs;
        ArrayRef<uint64_t> rawPieceIDs;
        DeclID replacedFunID;
        serialization::decls_block::DynamicReplacementDeclAttrLayout::
            readRecord(scratch, isImplicit, replacedFunID, numArgs, rawPieceIDs);

        auto replacedFunDecl = MF.getDeclChecked(replacedFunID);
        if (!replacedFunDecl)
          return replacedFunDecl.takeError();
        auto baseName = MF.getDeclBaseName(rawPieceIDs[0]);
        SmallVector<Identifier, 4> pieces;
        for (auto pieceID : rawPieceIDs.slice(1))
          pieces.push_back(MF.getIdentifier(pieceID));

        assert(numArgs != 0);
        assert(!isImplicit && "Need to update for implicit");
        Attr = DynamicReplacementAttr::create(
            ctx, DeclName(ctx, baseName, ArrayRef<Identifier>(pieces)),
            cast<AbstractFunctionDecl>(*replacedFunDecl));
        break;
      }

      case decls_block::Custom_DECL_ATTR: {
        bool isImplicit;
        TypeID typeID;
        serialization::decls_block::CustomDeclAttrLayout::readRecord(
          scratch, isImplicit, typeID);

        Expected<Type> deserialized = MF.getTypeChecked(typeID);
        if (!deserialized) {
          MF.fatal(deserialized.takeError());
          break;
        }

        Attr = CustomAttr::create(ctx, SourceLoc(),
                                  TypeLoc::withoutLoc(deserialized.get()),
                                  isImplicit);
        break;
      }

      case decls_block::ProjectedValueProperty_DECL_ATTR: {
        bool isImplicit;
        IdentifierID nameID;
        serialization::decls_block::ProjectedValuePropertyDeclAttrLayout
            ::readRecord(scratch, isImplicit, nameID);

        auto name = MF.getIdentifier(nameID);
        Attr = new (ctx) ProjectedValuePropertyAttr(
            name, SourceLoc(), SourceRange(), isImplicit);
        break;
      }

      case decls_block::Quoted_DECL_ATTR: {
        bool isImplicit;
        DeclID quoteDeclID;
        serialization::decls_block::QuotedDeclAttrLayout::readRecord(
            scratch, isImplicit, quoteDeclID);

        auto quoteDecl = MF.getDeclChecked(quoteDeclID);
        if (!quoteDecl)
          return quoteDecl.takeError();

        Attr = QuotedAttr::create(ctx, cast<FuncDecl>(*quoteDecl), SourceLoc(),
                                  SourceRange(), isImplicit);
        break;
      }

#define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \
      case decls_block::CLASS##_DECL_ATTR: { \
        bool isImplicit; \
        serialization::decls_block::CLASS##DeclAttrLayout::readRecord( \
            scratch, isImplicit); \
        Attr = new (ctx) CLASS##Attr(isImplicit); \
        break; \
      }
#include "swift/AST/Attr.def"

      default:
        // We don't know how to deserialize this kind of attribute.
        MF.fatal();
      }

      if (!Attr)
        return llvm::Error::success();

      AddAttribute(Attr);

    } else if (recordID == decls_block::PRIVATE_DISCRIMINATOR) {
      IdentifierID discriminatorID;
      decls_block::PrivateDiscriminatorLayout::readRecord(scratch,
                                                          discriminatorID);
      privateDiscriminator = MF.getIdentifier(discriminatorID);

    } else if (recordID == decls_block::LOCAL_DISCRIMINATOR) {
      unsigned discriminator;
      decls_block::LocalDiscriminatorLayout::readRecord(scratch, discriminator);
      localDiscriminator = discriminator;
    } else if (recordID == decls_block::FILENAME_FOR_PRIVATE) {
      IdentifierID filenameID;
      decls_block::FilenameForPrivateLayout::readRecord(scratch, filenameID);
      filenameForPrivate = MF.getIdentifierText(filenameID);
    } else {
      return llvm::Error::success();
    }

    // Prepare to read the next record.
    restoreOffset.cancel();
    scratch.clear();
  }
}

Expected<Decl *>
DeclDeserializer::getDeclCheckedImpl() {
  if (auto s = ctx.Stats)
    s->getFrontendCounters().NumDeclsDeserialized++;

  auto attrError = deserializeDeclAttributes();
  if (attrError)
    return std::move(attrError);

  // FIXME: @_dynamicReplacement(for:) includes a reference to another decl,
  // usually in the same type, and that can result in this decl being
  // re-entrantly deserialized. If that happens, don't fail here.
  if (declOrOffset.isComplete())
    return declOrOffset;

  auto entry = MF.DeclTypeCursor.advance();
  if (entry.Kind != llvm::BitstreamEntry::Record) {
    // We don't know how to serialize decls represented by sub-blocks.
    MF.fatal();
  }

  SmallVector<uint64_t, 64> scratch;
  StringRef blobData;
  unsigned recordID = MF.DeclTypeCursor.readRecord(entry.ID, scratch,
                                                   &blobData);

  PrettyDeclDeserialization stackTraceEntry(
     &MF, declOrOffset, static_cast<decls_block::RecordKind>(recordID));

  switch (recordID) {
#define CASE(RECORD_NAME) \
  case decls_block::RECORD_NAME##Layout::Code: \
    return deserialize##RECORD_NAME(scratch, blobData);

  CASE(TypeAlias)
  CASE(GenericTypeParamDecl)
  CASE(AssociatedTypeDecl)
  CASE(Struct)
  CASE(Constructor)
  CASE(Var)
  CASE(Param)
  CASE(Func)
  CASE(OpaqueType)
  CASE(Accessor)
  CASE(PatternBinding)
  CASE(Protocol)
  CASE(PrefixOperator)
  CASE(PostfixOperator)
  CASE(InfixOperator)
  CASE(PrecedenceGroup)
  CASE(Class)
  CASE(Enum)
  CASE(EnumElement)
  CASE(Subscript)
  CASE(Extension)
  CASE(Destructor)
#undef CASE

  case decls_block::XREF: {
    assert(DAttrs == nullptr);
    ModuleID baseModuleID;
    uint32_t pathLen;
    decls_block::XRefLayout::readRecord(scratch, baseModuleID, pathLen);
    auto resolved = MF.resolveCrossReference(baseModuleID, pathLen);
    if (resolved)
      declOrOffset = resolved.get();
    return resolved;
  }
  
  default:
    // We don't know how to deserialize this kind of decl.
    MF.fatal();
  }
}

/// Translate from the Serialization function type repr enum values to the AST
/// strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<swift::FunctionType::Representation>
getActualFunctionTypeRepresentation(uint8_t rep) {
  switch (rep) {
#define CASE(THE_CC) \
  case (uint8_t)serialization::FunctionTypeRepresentation::THE_CC: \
    return swift::FunctionType::Representation::THE_CC;
  CASE(Swift)
  CASE(Block)
  CASE(Thin)
  CASE(CFunctionPointer)
#undef CASE
  default:
    return None;
  }
}

/// Translate from the Serialization function type repr enum values to the AST
/// strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<swift::SILFunctionType::Representation>
getActualSILFunctionTypeRepresentation(uint8_t rep) {
  switch (rep) {
#define CASE(THE_CC) \
  case (uint8_t)serialization::SILFunctionTypeRepresentation::THE_CC: \
    return swift::SILFunctionType::Representation::THE_CC;
  CASE(Thick)
  CASE(Block)
  CASE(Thin)
  CASE(CFunctionPointer)
  CASE(Method)
  CASE(ObjCMethod)
  CASE(WitnessMethod)
#undef CASE
  default:
    return None;
  }
}

/// Translate from the Serialization coroutine kind enum values to the AST
/// strongly-typed enum.
///
/// The former is guaranteed to be stable, but may not reflect this version of
/// the AST.
static Optional<swift::SILCoroutineKind>
getActualSILCoroutineKind(uint8_t rep) {
  switch (rep) {
#define CASE(KIND) \
  case (uint8_t)serialization::SILCoroutineKind::KIND: \
    return swift::SILCoroutineKind::KIND;
  CASE(None)
  CASE(YieldOnce)
  CASE(YieldMany)
#undef CASE
  default:
    return None;
  }
}

/// Translate from the serialization ReferenceOwnership enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<swift::ReferenceOwnership>
getActualReferenceOwnership(serialization::ReferenceOwnership raw) {
  switch (raw) {
  case serialization::ReferenceOwnership::Strong:
    return swift::ReferenceOwnership::Strong;
#define REF_STORAGE(Name, ...) \
  case serialization::ReferenceOwnership::Name: \
    return swift::ReferenceOwnership::Name;
#include "swift/AST/ReferenceStorage.def"
  }
  return None;
}

/// Translate from the serialization ValueOwnership enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<swift::ValueOwnership>
getActualValueOwnership(serialization::ValueOwnership raw) {
  switch (raw) {
#define CASE(ID) \
  case serialization::ValueOwnership::ID: \
    return swift::ValueOwnership::ID;
  CASE(Default)
  CASE(InOut)
  CASE(Shared)
  CASE(Owned)
#undef CASE
  }
  return None;
}

/// Translate from the serialization ParameterConvention enumerators,
/// which are guaranteed to be stable, to the AST ones.
static
Optional<swift::ParameterConvention> getActualParameterConvention(uint8_t raw) {
  switch (serialization::ParameterConvention(raw)) {
#define CASE(ID) \
  case serialization::ParameterConvention::ID: \
    return swift::ParameterConvention::ID;
  CASE(Indirect_In)
  CASE(Indirect_Inout)
  CASE(Indirect_InoutAliasable)
  CASE(Indirect_In_Guaranteed)
  CASE(Indirect_In_Constant)
  CASE(Direct_Owned)
  CASE(Direct_Unowned)
  CASE(Direct_Guaranteed)
#undef CASE
  }
  return None;
}

// SWIFT_ENABLE_TENSORFLOW
/// Translate from the serialization DifferentiabilityKind enumerators,
/// which are guaranteed to be stable, to the AST ones.
static Optional<swift::DifferentiabilityKind>
getActualDifferentiabilityKind(uint8_t raw) {
  switch (serialization::DifferentiabilityKind(raw)) {
#define CASE(ID)                                                               \
  case serialization::DifferentiabilityKind::ID:                               \
    return swift::DifferentiabilityKind::ID;
  CASE(NonDifferentiable)
  CASE(Normal)
  CASE(Linear)
#undef CASE
  }
  return None;
}

/// Translate from the serialization SILParameterDifferentiability enumerators,
/// which are guaranteed to be stable, to the AST ones.
static Optional<swift::SILParameterDifferentiability>
getActualSILParameterDifferentiability(uint8_t raw) {
  switch (serialization::SILParameterDifferentiability(raw)) {
#define CASE(ID)                                                               \
  case serialization::SILParameterDifferentiability::ID:                       \
    return swift::SILParameterDifferentiability::ID;
  CASE(DifferentiableOrNotApplicable)
  CASE(NotDifferentiable)
#undef CASE
  }
  return None;
}

/// Translate from the serialization ResultConvention enumerators,
/// which are guaranteed to be stable, to the AST ones.
static
Optional<swift::ResultConvention> getActualResultConvention(uint8_t raw) {
  switch (serialization::ResultConvention(raw)) {
#define CASE(ID) \
  case serialization::ResultConvention::ID: return swift::ResultConvention::ID;
  CASE(Indirect)
  CASE(Owned)
  CASE(Unowned)
  CASE(UnownedInnerPointer)
  CASE(Autoreleased)
#undef CASE
  }
  return None;
}

Type ModuleFile::getType(TypeID TID) {
  Expected<Type> deserialized = getTypeChecked(TID);
  if (!deserialized) {
    fatal(deserialized.takeError());
  }
  return deserialized.get();
}

class swift::TypeDeserializer {
  using TypeID = serialization::TypeID;

  ModuleFile &MF;
  ASTContext &ctx;
public:
  explicit TypeDeserializer(ModuleFile &MF)
      : MF(MF), ctx(MF.getContext()) {}

  Expected<Type> getTypeCheckedImpl();

  Expected<Type> deserializeBuiltinAliasType(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
    DeclID underlyingID;
    TypeID canonicalTypeID;
    decls_block::BuiltinAliasTypeLayout::readRecord(scratch, underlyingID,
                                                    canonicalTypeID);
    auto aliasOrError = MF.getDeclChecked(underlyingID);
    if (!aliasOrError)
      return aliasOrError.takeError();
    auto alias = dyn_cast<TypeAliasDecl>(aliasOrError.get());

    if (ctx.LangOpts.EnableDeserializationRecovery) {
      Expected<Type> expectedType = MF.getTypeChecked(canonicalTypeID);
      if (!expectedType)
        return expectedType.takeError();
      if (expectedType.get()) {
        if (!alias ||
            !alias->getDeclaredInterfaceType()->isEqual(expectedType.get())) {
          // Fall back to the canonical type.
          return expectedType.get();
        }
      }
    }

    // Look through compatibility aliases that are now unavailable.
    if (alias->getAttrs().isUnavailable(ctx) &&
        alias->isCompatibilityAlias()) {
      return alias->getUnderlyingType();
    }

    return alias->getDeclaredInterfaceType();
  }

  Expected<Type> deserializeTypeAliasType(ArrayRef<uint64_t> scratch,
                                          StringRef blobData) {
    DeclID typealiasID;
    TypeID parentTypeID;
    TypeID underlyingTypeID;
    TypeID substitutedTypeID;
    SubstitutionMapID substitutionsID;
    decls_block::TypeAliasTypeLayout::readRecord(scratch, typealiasID,
                                                 parentTypeID,
                                                 underlyingTypeID,
                                                 substitutedTypeID,
                                                 substitutionsID);

    TypeAliasDecl *alias = nullptr;
    Type underlyingType;
    if (ctx.LangOpts.EnableDeserializationRecovery) {
      auto underlyingTypeOrError = MF.getTypeChecked(underlyingTypeID);
      if (!underlyingTypeOrError) {
        // If we can't deserialize the underlying type, we can't be sure the
        // actual typealias hasn't changed.
        return underlyingTypeOrError.takeError();
      }

      underlyingType = underlyingTypeOrError.get();

      if (auto aliasOrError = MF.getDeclChecked(typealiasID)) {
        alias = dyn_cast<TypeAliasDecl>(aliasOrError.get());
      } else {
        // We're going to recover by falling back to the underlying type, so
        // just ignore the error.
        llvm::consumeError(aliasOrError.takeError());
      }

      if (!alias ||
          !alias->getDeclaredInterfaceType()->isEqual(underlyingType)) {
        // Fall back to the canonical type.
        return underlyingType;
      }

    } else {
      alias = dyn_cast<TypeAliasDecl>(MF.getDecl(typealiasID));
      underlyingType = MF.getType(underlyingTypeID);
    }

    // Read the substituted type.
    auto substitutedTypeOrError = MF.getTypeChecked(substitutedTypeID);
    if (!substitutedTypeOrError)
      return substitutedTypeOrError.takeError();

    auto substitutedType = substitutedTypeOrError.get();

    // Read the substitutions.
    auto subMap = MF.getSubstitutionMap(substitutionsID);

    auto parentTypeOrError = MF.getTypeChecked(parentTypeID);
    if (!parentTypeOrError)
      return underlyingType;

    // Look through compatibility aliases that are now unavailable.
    if (alias &&
        alias->getAttrs().isUnavailable(ctx) &&
        alias->isCompatibilityAlias()) {
      return alias->getUnderlyingType().subst(subMap);
    }

    auto parentType = parentTypeOrError.get();
    return TypeAliasType::get(alias, parentType, subMap, substitutedType);
  }

  Expected<Type> deserializeNominalType(ArrayRef<uint64_t> scratch,
                                        StringRef blobData) {
    DeclID declID;
    TypeID parentID;
    decls_block::NominalTypeLayout::readRecord(scratch, declID, parentID);

    Expected<Type> parentTy = MF.getTypeChecked(parentID);
    if (!parentTy)
      return parentTy.takeError();

    auto nominalOrError = MF.getDeclChecked(declID);
    if (!nominalOrError)
      return nominalOrError.takeError();

    // Look through compatibility aliases.
    if (auto *alias = dyn_cast<TypeAliasDecl>(nominalOrError.get())) {
      // Reminder: TypeBase::getAs will look through sugar. But we don't want to
      // do that here, so we do isa<> checks on the TypeBase itself instead of
      // using the Type wrapper.
      const TypeBase *underlyingTy = nullptr;
      while (alias->isCompatibilityAlias()) {
        underlyingTy = alias->getUnderlyingType().getPointer();

        // If the underlying type is itself a typealias, it might be another
        // compatibility alias, meaning we need to go around the loop again.
        auto aliasTy = dyn_cast<TypeAliasType>(underlyingTy);
        if (!aliasTy)
          break;
        alias = aliasTy->getDecl();
      }

      // We only want to use the type we found if it's a simple non-generic
      // nominal type.
      if (auto simpleNominalTy = dyn_cast_or_null<NominalType>(underlyingTy)) {
        nominalOrError = simpleNominalTy->getDecl();
        (void)!nominalOrError; // "Check" the llvm::Expected<> value.
      }
    }

    auto nominal = dyn_cast<NominalTypeDecl>(nominalOrError.get());
    if (!nominal) {
      XRefTracePath tinyTrace{*nominalOrError.get()->getModuleContext()};
      DeclName fullName = cast<ValueDecl>(nominalOrError.get())->getFullName();
      tinyTrace.addValue(fullName.getBaseIdentifier());
      return llvm::make_error<XRefError>("declaration is not a nominal type",
                                         tinyTrace, fullName);
    }
    return NominalType::get(nominal, parentTy.get(), ctx);
  }

  Expected<Type> deserializeParenType(ArrayRef<uint64_t> scratch,
                                      StringRef blobData) {
    TypeID underlyingID;
    decls_block::ParenTypeLayout::readRecord(scratch, underlyingID);

    auto underlyingTy = MF.getTypeChecked(underlyingID);
    if (!underlyingTy)
      return underlyingTy.takeError();

    return ParenType::get(ctx, underlyingTy.get());
  }

  Expected<Type> deserializeTupleType(SmallVectorImpl<uint64_t> &scratch,
                                      StringRef blobData) {
    // The tuple record itself is empty. Read all trailing elements.
    SmallVector<TupleTypeElt, 8> elements;
    while (true) {
      auto entry = MF.DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
      if (entry.Kind != llvm::BitstreamEntry::Record)
        break;

      scratch.clear();
      unsigned recordID = MF.DeclTypeCursor.readRecord(entry.ID, scratch,
                                                       &blobData);
      if (recordID != decls_block::TUPLE_TYPE_ELT)
        break;

      IdentifierID nameID;
      TypeID typeID;
      decls_block::TupleTypeEltLayout::readRecord(scratch, nameID, typeID);

      auto elementTy = MF.getTypeChecked(typeID);
      if (!elementTy)
        return elementTy.takeError();

      elements.emplace_back(elementTy.get(), MF.getIdentifier(nameID));
    }

    return TupleType::get(elements, ctx);
  }

  Expected<Type> deserializeAnyFunctionType(SmallVectorImpl<uint64_t> &scratch,
                                            StringRef blobData,
                                            bool isGeneric) {
    TypeID resultID;
    uint8_t rawRepresentation;

    // SWIFT_ENABLE_TENSORFLOW
    bool noescape = false, throws = false;
    uint8_t rawDiffKind = 0;
    auto diffKind = DifferentiabilityKind::NonDifferentiable;
    GenericSignature genericSig = GenericSignature();

    if (!isGeneric) {
      decls_block::FunctionTypeLayout::readRecord(scratch, resultID,
                                                  rawRepresentation,
                                                  noescape,
                                                  // SWIFT_ENABLE_TENSORFLOW
                                                  throws,
                                                  rawDiffKind);
      diffKind = DifferentiabilityKind(rawDiffKind);
    } else {
      GenericSignatureID rawGenericSig;
      decls_block::GenericFunctionTypeLayout::readRecord(scratch,
                                                         resultID,
                                                         rawRepresentation,
                                                         throws,
                                                         // SWIFT_ENABLE_TENSORFLOW
                                                         rawDiffKind,
                                                         rawGenericSig);
      diffKind = DifferentiabilityKind(rawDiffKind);
      genericSig = MF.getGenericSignature(rawGenericSig);
    }

    auto representation = getActualFunctionTypeRepresentation(rawRepresentation);
    if (!representation.hasValue())
      MF.fatal();

    auto info = FunctionType::ExtInfo(*representation, noescape,
                                      // SWIFT_ENABLE_TENSORFLOW
                                      throws, diffKind);

    auto resultTy = MF.getTypeChecked(resultID);
    if (!resultTy)
      return resultTy.takeError();

    SmallVector<AnyFunctionType::Param, 8> params;
    while (true) {
      auto entry = MF.DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
      if (entry.Kind != llvm::BitstreamEntry::Record)
        break;

      scratch.clear();
      unsigned recordID = MF.DeclTypeCursor.readRecord(entry.ID, scratch,
                                                    &blobData);
      if (recordID != decls_block::FUNCTION_PARAM)
        break;

      IdentifierID labelID;
      TypeID typeID;
      bool isVariadic, isAutoClosure, isNonDifferentiable;
      unsigned rawOwnership;
      decls_block::FunctionParamLayout::readRecord(scratch, labelID, typeID,
                                                   isVariadic, isAutoClosure,
                                                   rawOwnership, isNonDifferentiable);

      auto ownership =
          getActualValueOwnership((serialization::ValueOwnership)rawOwnership);
      if (!ownership)
        MF.fatal();

      auto paramTy = MF.getTypeChecked(typeID);
      if (!paramTy)
        return paramTy.takeError();

      params.emplace_back(paramTy.get(),
                          MF.getIdentifier(labelID),
                          ParameterTypeFlags(isVariadic, isAutoClosure,
                                             *ownership, isNonDifferentiable));
    }

    if (!isGeneric) {
      assert(genericSig.isNull());
      return FunctionType::get(params, resultTy.get(), info);
    }

    assert(!genericSig.isNull());
    return GenericFunctionType::get(genericSig, params, resultTy.get(), info);
  }

  Expected<Type> deserializeFunctionType(SmallVectorImpl<uint64_t> &scratch,
                                         StringRef blobData) {
    return deserializeAnyFunctionType(scratch, blobData, /*isGeneric*/false);
  }

  Expected<Type>
  deserializeGenericFunctionType(SmallVectorImpl<uint64_t> &scratch,
                                 StringRef blobData) {
    return deserializeAnyFunctionType(scratch, blobData, /*isGeneric*/true);
  }

  template <typename Layout, typename ASTType, bool CanBeThin>
  Expected<Type> deserializeAnyMetatypeType(ArrayRef<uint64_t> scratch,
                                            StringRef blobData) {
    TypeID instanceID;
    uint8_t repr;
    Layout::readRecord(scratch, instanceID, repr);

    auto instanceType = MF.getTypeChecked(instanceID);
    if (!instanceType)
      return instanceType.takeError();

    switch (repr) {
    case serialization::MetatypeRepresentation::MR_None:
      return ASTType::get(instanceType.get());

    case serialization::MetatypeRepresentation::MR_Thin:
      if (!CanBeThin)
        MF.fatal();
      return ASTType::get(instanceType.get(),
                          MetatypeRepresentation::Thin);

    case serialization::MetatypeRepresentation::MR_Thick:
      return ASTType::get(instanceType.get(),
                          MetatypeRepresentation::Thick);

    case serialization::MetatypeRepresentation::MR_ObjC:
      return ASTType::get(instanceType.get(),
                          MetatypeRepresentation::ObjC);

    default:
      MF.fatal();
    }
  }

  Expected<Type>
  deserializeExistentialMetatypeType(ArrayRef<uint64_t> scratch,
                                     StringRef blobData) {
    return
        deserializeAnyMetatypeType<decls_block::ExistentialMetatypeTypeLayout,
                                   ExistentialMetatypeType, /*CanBeThin*/false>(
        scratch, blobData);
  }

  Expected<Type> deserializeMetatypeType(ArrayRef<uint64_t> scratch,
                                         StringRef blobData) {
    return deserializeAnyMetatypeType<decls_block::MetatypeTypeLayout,
                                      MetatypeType, /*CanBeThin*/true>(
        scratch, blobData);
  }

  Expected<Type> deserializeDynamicSelfType(ArrayRef<uint64_t> scratch,
                                            StringRef blobData) {
    TypeID selfID;
    decls_block::DynamicSelfTypeLayout::readRecord(scratch, selfID);
    return DynamicSelfType::get(MF.getType(selfID), ctx);
  }

  Expected<Type> deserializeReferenceStorageType(ArrayRef<uint64_t> scratch,
                                                 StringRef blobData) {
    uint8_t rawOwnership;
    TypeID objectTypeID;
    decls_block::ReferenceStorageTypeLayout::readRecord(scratch, rawOwnership,
                                                        objectTypeID);

    auto ownership = getActualReferenceOwnership(
        (serialization::ReferenceOwnership)rawOwnership);
    if (!ownership.hasValue())
      MF.fatal();

    auto objectTy = MF.getTypeChecked(objectTypeID);
    if (!objectTy)
      return objectTy.takeError();

    return ReferenceStorageType::get(objectTy.get(), ownership.getValue(), ctx);
  }

  Expected<Type> deserializePrimaryArchetypeType(ArrayRef<uint64_t> scratch,
                                                 StringRef blobData) {
    GenericSignatureID sigID;
    unsigned depth, index;

    decls_block::PrimaryArchetypeTypeLayout::readRecord(scratch, sigID,
                                                        depth, index);

    auto sig = MF.getGenericSignature(sigID);
    if (!sig)
      MF.fatal();

    Type interfaceType = GenericTypeParamType::get(depth, index, ctx);
    Type contextType = sig->getGenericEnvironment()
        ->mapTypeIntoContext(interfaceType);

    if (contextType->hasError())
      MF.fatal();

    return contextType;
  }

  Expected<Type> deserializeOpenedArchetypeType(ArrayRef<uint64_t> scratch,
                                                StringRef blobData) {
    TypeID existentialID;

    decls_block::OpenedArchetypeTypeLayout::readRecord(scratch,
                                                       existentialID);

    return OpenedArchetypeType::get(MF.getType(existentialID));
  }
      
  Expected<Type> deserializeOpaqueArchetypeType(ArrayRef<uint64_t> scratch,
                                                StringRef blobData) {
    DeclID opaqueDeclID;
    SubstitutionMapID subsID;
    decls_block::OpaqueArchetypeTypeLayout::readRecord(scratch,
                                                       opaqueDeclID, subsID);

    auto opaqueDecl = cast<OpaqueTypeDecl>(MF.getDecl(opaqueDeclID));
    auto subs = MF.getSubstitutionMap(subsID);

    return OpaqueTypeArchetypeType::get(opaqueDecl, subs);
  }
      
  Expected<Type> deserializeNestedArchetypeType(ArrayRef<uint64_t> scratch,
                                                StringRef blobData) {
    TypeID rootID, interfaceTyID;
    decls_block::NestedArchetypeTypeLayout::readRecord(scratch,
                                                       rootID, interfaceTyID);
    
    auto rootTy = MF.getType(rootID)->castTo<ArchetypeType>();
    auto interfaceTy = MF.getType(interfaceTyID)->castTo<DependentMemberType>();
    return rootTy->getGenericEnvironment()->mapTypeIntoContext(interfaceTy);
  }

  Expected<Type> deserializeGenericTypeParamType(ArrayRef<uint64_t> scratch,
                                                 StringRef blobData) {
    DeclID declIDOrDepth;
    unsigned indexPlusOne;

    decls_block::GenericTypeParamTypeLayout::readRecord(scratch, declIDOrDepth,
                                                        indexPlusOne);

    if (indexPlusOne == 0) {
      auto genericParam
        = dyn_cast_or_null<GenericTypeParamDecl>(MF.getDecl(declIDOrDepth));

      if (!genericParam)
        MF.fatal();

      return genericParam->getDeclaredInterfaceType();
    }

    return GenericTypeParamType::get(declIDOrDepth,indexPlusOne-1,ctx);
  }

  Expected<Type> deserializeProtocolCompositionType(ArrayRef<uint64_t> scratch,
                                                    StringRef blobData) {
    bool hasExplicitAnyObject;
    ArrayRef<uint64_t> rawProtocolIDs;

    decls_block::ProtocolCompositionTypeLayout::readRecord(scratch,
                                                           hasExplicitAnyObject,
                                                           rawProtocolIDs);
    SmallVector<Type, 4> protocols;
    for (TypeID protoID : rawProtocolIDs) {
      auto protoTy = MF.getTypeChecked(protoID);
      if (!protoTy)
        return protoTy.takeError();
      protocols.push_back(protoTy.get());
    }

    return ProtocolCompositionType::get(ctx, protocols, hasExplicitAnyObject);
  }

  Expected<Type> deserializeDependentMemberType(ArrayRef<uint64_t> scratch,
                                                StringRef blobData) {
    TypeID baseID;
    DeclID assocTypeID;

    decls_block::DependentMemberTypeLayout::readRecord(scratch, baseID,
                                                       assocTypeID);
    auto assocType = MF.getDeclChecked(assocTypeID);
    if (!assocType)
      return assocType.takeError();

    return DependentMemberType::get(
        MF.getType(baseID),
        cast<AssociatedTypeDecl>(assocType.get()));
  }

  Expected<Type> deserializeBoundGenericType(ArrayRef<uint64_t> scratch,
                                             StringRef blobData) {
    DeclID declID;
    TypeID parentID;
    ArrayRef<uint64_t> rawArgumentIDs;

    decls_block::BoundGenericTypeLayout::readRecord(scratch, declID, parentID,
                                                    rawArgumentIDs);

    auto nominalOrError = MF.getDeclChecked(declID);
    if (!nominalOrError)
      return nominalOrError.takeError();
    auto nominal = cast<NominalTypeDecl>(nominalOrError.get());

    // FIXME: Check this?
    auto parentTy = MF.getType(parentID);

    SmallVector<Type, 8> genericArgs;
    for (TypeID ID : rawArgumentIDs) {
      auto argTy = MF.getTypeChecked(ID);
      if (!argTy)
        return argTy.takeError();

      genericArgs.push_back(argTy.get());
    }

    return BoundGenericType::get(nominal, parentTy, genericArgs);
  }

  Expected<Type> deserializeSILBlockStorageType(ArrayRef<uint64_t> scratch,
                                                StringRef blobData) {
    TypeID captureID;
    decls_block::SILBlockStorageTypeLayout::readRecord(scratch, captureID);
    return SILBlockStorageType::get(MF.getType(captureID)->getCanonicalType());
  }

  Expected<Type> deserializeSILBoxType(ArrayRef<uint64_t> scratch,
                                       StringRef blobData) {
    SILLayoutID layoutID;
    SubstitutionMapID subMapID;
    decls_block::SILBoxTypeLayout::readRecord(scratch, layoutID, subMapID);

    // Get the layout.
    auto getLayout = [this](SILLayoutID layoutID) -> SILLayout * {
      assert(layoutID > 0 && layoutID <= MF.SILLayouts.size()
             && "invalid layout ID");

      auto &layoutOrOffset = MF.SILLayouts[layoutID - 1];
      if (layoutOrOffset.isComplete()) {
        return layoutOrOffset;
      }

      BCOffsetRAII saveOffset(MF.DeclTypeCursor);
      MF.DeclTypeCursor.JumpToBit(layoutOrOffset);
      auto layout = MF.readSILLayout(MF.DeclTypeCursor);
      if (!layout)
        MF.fatal();
      layoutOrOffset = layout;
      return layout;
    };

    auto layout = getLayout(layoutID);
    if (!layout)
      return nullptr;

    auto subMap = MF.getSubstitutionMap(subMapID);
    return SILBoxType::get(ctx, layout, subMap);
  }

  Expected<Type> deserializeSILFunctionType(ArrayRef<uint64_t> scratch,
                                            StringRef blobData) {
    uint8_t rawCoroutineKind;
    uint8_t rawCalleeConvention;
    uint8_t rawRepresentation;
    bool pseudogeneric = false;
    bool noescape;
    // SWIFT_ENABLE_TENSORFLOW
    uint8_t rawDifferentiabilityKind;
    bool hasErrorResult;
    unsigned numParams;
    unsigned numYields;
    unsigned numResults;
    GenericSignatureID rawGenericSig;
    ArrayRef<uint64_t> variableData;

    decls_block::SILFunctionTypeLayout::readRecord(scratch,
                                             rawCoroutineKind,
                                             rawCalleeConvention,
                                             rawRepresentation,
                                             pseudogeneric,
                                             noescape,
                                             // SWIFT_ENABLE_TENSORFLOW
                                             rawDifferentiabilityKind,
                                             hasErrorResult,
                                             numParams,
                                             numYields,
                                             numResults,
                                             rawGenericSig,
                                             variableData);

    // Process the ExtInfo.
    auto representation
      = getActualSILFunctionTypeRepresentation(rawRepresentation);
    if (!representation.hasValue())
      MF.fatal();
    auto differentiabilityKind =
        getActualDifferentiabilityKind(rawDifferentiabilityKind);
    if (!differentiabilityKind.hasValue())
      MF.fatal();
    SILFunctionType::ExtInfo extInfo(*representation, pseudogeneric,
                                     noescape, *differentiabilityKind);

    // Process the coroutine kind.
    auto coroutineKind = getActualSILCoroutineKind(rawCoroutineKind);
    if (!coroutineKind.hasValue())
      MF.fatal();

    // Process the callee convention.
    auto calleeConvention = getActualParameterConvention(rawCalleeConvention);
    if (!calleeConvention.hasValue())
      MF.fatal();

    // SWIFT_ENABLE_TENSORFLOW
    auto processParameter =
        [&](TypeID typeID, uint64_t rawConvention,
            uint64_t rawParamDiff) -> llvm::Expected<SILParameterInfo> {
      auto convention = getActualParameterConvention(rawConvention);
      if (!convention)
        MF.fatal();
      auto type = MF.getTypeChecked(typeID);
      if (!type)
        return type.takeError();
      // SWIFT_ENABLE_TENSORFLOW
      auto paramDiff =
          swift::SILParameterDifferentiability::DifferentiableOrNotApplicable;
      if (differentiabilityKind != DifferentiabilityKind::NonDifferentiable) {
        auto paramDiffOpt =
            getActualSILParameterDifferentiability(rawParamDiff);
        if (!paramDiffOpt) {
          MF.fatal();
          llvm_unreachable("an error is a fatal exit at this point");
        }
        paramDiff = *paramDiffOpt;
      }
      return SILParameterInfo(type.get()->getCanonicalType(), *convention,
                              paramDiff);
    };

    auto processYield = [&](TypeID typeID, uint64_t rawConvention)
                                  -> llvm::Expected<SILYieldInfo> {
      auto convention = getActualParameterConvention(rawConvention);
      if (!convention)
        MF.fatal();
      auto type = MF.getTypeChecked(typeID);
      if (!type)
        return type.takeError();
      return SILYieldInfo(type.get()->getCanonicalType(), *convention);
    };

    auto processResult = [&](TypeID typeID, uint64_t rawConvention)
                               -> llvm::Expected<SILResultInfo> {
      auto convention = getActualResultConvention(rawConvention);
      if (!convention)
        MF.fatal();
      auto type = MF.getTypeChecked(typeID);
      if (!type)
        return type.takeError();
      return SILResultInfo(type.get()->getCanonicalType(), *convention);
    };

    // Bounds check.  FIXME: overflow
    // SWIFT_ENABLE_TENSORFLOW
    unsigned entriesPerParam =
        differentiabilityKind != DifferentiabilityKind::NonDifferentiable
            ? 3 : 2;
    if (entriesPerParam * numParams + 2 * numResults +
            2 * unsigned(hasErrorResult) >
        variableData.size()) {
      MF.fatal();
    }

    unsigned nextVariableDataIndex = 0;

    // Process the parameters.
    SmallVector<SILParameterInfo, 8> allParams;
    allParams.reserve(numParams);
    for (unsigned i = 0; i != numParams; ++i) {
      auto typeID = variableData[nextVariableDataIndex++];
      auto rawConvention = variableData[nextVariableDataIndex++];
      // SWIFT_ENABLE_TENSORFLOW
      uint64_t paramDiff = 0;
      if (differentiabilityKind != DifferentiabilityKind::NonDifferentiable)
        paramDiff = variableData[nextVariableDataIndex++];
      auto param = processParameter(typeID, rawConvention, paramDiff);
      if (!param)
        return param.takeError();
      allParams.push_back(param.get());
    }

    // Process the yields.
    SmallVector<SILYieldInfo, 8> allYields;
    allYields.reserve(numYields);
    for (unsigned i = 0; i != numYields; ++i) {
      auto typeID = variableData[nextVariableDataIndex++];
      auto rawConvention = variableData[nextVariableDataIndex++];
      auto yield = processYield(typeID, rawConvention);
      if (!yield)
        return yield.takeError();
      allYields.push_back(yield.get());
    }

    // Process the results.
    SmallVector<SILResultInfo, 8> allResults;
    allParams.reserve(numResults);
    for (unsigned i = 0; i != numResults; ++i) {
      auto typeID = variableData[nextVariableDataIndex++];
      auto rawConvention = variableData[nextVariableDataIndex++];
      auto result = processResult(typeID, rawConvention);
      if (!result)
        return result.takeError();
      allResults.push_back(result.get());
    }

    // Process the error result.
    Optional<SILResultInfo> errorResult;
    if (hasErrorResult) {
      auto typeID = variableData[nextVariableDataIndex++];
      auto rawConvention = variableData[nextVariableDataIndex++];
      auto maybeErrorResult = processResult(typeID, rawConvention);
      if (!maybeErrorResult)
        return maybeErrorResult.takeError();
      errorResult = maybeErrorResult.get();
    }

    Optional<ProtocolConformanceRef> witnessMethodConformance;
    if (*representation == SILFunctionTypeRepresentation::WitnessMethod) {
      witnessMethodConformance = MF.readConformance(MF.DeclTypeCursor);
    }

    GenericSignature genericSig = MF.getGenericSignature(rawGenericSig);

    return SILFunctionType::get(genericSig, extInfo, coroutineKind.getValue(),
                                calleeConvention.getValue(),
                                allParams, allYields, allResults,
                                errorResult, ctx, witnessMethodConformance);
  }

  Expected<Type> deserializeArraySliceType(ArrayRef<uint64_t> scratch,
                                           StringRef blobData) {
    TypeID baseID;
    decls_block::ArraySliceTypeLayout::readRecord(scratch, baseID);

    auto baseTy = MF.getTypeChecked(baseID);
    if (!baseTy)
      return baseTy.takeError();

    return ArraySliceType::get(baseTy.get());
  }

  Expected<Type> deserializeDictionaryType(ArrayRef<uint64_t> scratch,
                                           StringRef blobData) {
    TypeID keyID, valueID;
    decls_block::DictionaryTypeLayout::readRecord(scratch, keyID, valueID);

    auto keyTy = MF.getTypeChecked(keyID);
    if (!keyTy)
      return keyTy.takeError();

    auto valueTy = MF.getTypeChecked(valueID);
    if (!valueTy)
      return valueTy.takeError();

    return DictionaryType::get(keyTy.get(), valueTy.get());
  }

  Expected<Type> deserializeOptionalType(ArrayRef<uint64_t> scratch,
                                         StringRef blobData) {
    TypeID baseID;
    decls_block::OptionalTypeLayout::readRecord(scratch, baseID);

    auto baseTy = MF.getTypeChecked(baseID);
    if (!baseTy)
      return baseTy.takeError();

    return OptionalType::get(baseTy.get());
  }

  Expected<Type> deserializeUnboundGenericType(ArrayRef<uint64_t> scratch,
                                               StringRef blobData) {
    DeclID genericID;
    TypeID parentID;
    decls_block::UnboundGenericTypeLayout::readRecord(scratch,
                                                      genericID, parentID);

    auto nominalOrError = MF.getDeclChecked(genericID);
    if (!nominalOrError)
      return nominalOrError.takeError();
    auto genericDecl = cast<GenericTypeDecl>(nominalOrError.get());

    // FIXME: Check this?
    auto parentTy = MF.getType(parentID);

    return UnboundGenericType::get(genericDecl, parentTy, ctx);
  }
};

Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
  if (TID == 0)
    return Type();

  assert(TID <= Types.size() && "invalid type ID");
  auto &typeOrOffset = Types[TID-1];

  if (typeOrOffset.isComplete())
    return typeOrOffset;

  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(typeOrOffset);

  auto result = TypeDeserializer(*this).getTypeCheckedImpl();
  if (!result)
    return result;
  typeOrOffset = result.get();

#ifndef NDEBUG
  PrettyStackTraceType trace(getContext(), "deserializing", typeOrOffset.get());
  if (typeOrOffset.get()->hasError()) {
    typeOrOffset.get()->dump();
    llvm_unreachable("deserialization produced an invalid type "
                     "(rdar://problem/30382791)");
  }
#endif

  // Invoke the callback on the deserialized type.
  DeserializedTypeCallback(typeOrOffset.get());
  return typeOrOffset.get();
}

Expected<Type> TypeDeserializer::getTypeCheckedImpl() {
  if (auto s = ctx.Stats)
    s->getFrontendCounters().NumTypesDeserialized++;

  auto entry = MF.DeclTypeCursor.advance();

  if (entry.Kind != llvm::BitstreamEntry::Record) {
    // We don't know how to serialize types represented by sub-blocks.
    MF.fatal();
  }

  SmallVector<uint64_t, 64> scratch;
  StringRef blobData;
  unsigned recordID = MF.DeclTypeCursor.readRecord(entry.ID, scratch,
                                                   &blobData);

  switch (recordID) {
#define CASE(RECORD_NAME) \
  case decls_block::RECORD_NAME##TypeLayout::Code: \
    return deserialize##RECORD_NAME##Type(scratch, blobData);

  CASE(BuiltinAlias)
  CASE(TypeAlias)
  CASE(Nominal)
  CASE(Paren)
  CASE(Tuple)
  CASE(Function)
  CASE(GenericFunction)
  CASE(ExistentialMetatype)
  CASE(Metatype)
  CASE(DynamicSelf)
  CASE(ReferenceStorage)
  CASE(PrimaryArchetype)
  CASE(OpaqueArchetype)
  CASE(OpenedArchetype)
  CASE(NestedArchetype)
  CASE(GenericTypeParam)
  CASE(ProtocolComposition)
  CASE(DependentMember)
  CASE(BoundGeneric)
  CASE(SILBlockStorage)
  CASE(SILBox)
  CASE(SILFunction)
  CASE(ArraySlice)
  CASE(Dictionary)
  CASE(Optional)
  CASE(UnboundGeneric)

#undef CASE

  default:
    // We don't know how to deserialize this kind of type.
    MF.fatal();
  }
}

Decl *handleErrorAndSupplyMissingClassMember(ASTContext &context,
                                             llvm::Error &&error,
                                             ClassDecl *containingClass) {
  Decl *suppliedMissingMember = nullptr;
  auto handleMissingClassMember = [&](const DeclDeserializationError &error) {
    if (error.isDesignatedInitializer())
      containingClass->setHasMissingDesignatedInitializers();
    if (error.getNumberOfVTableEntries() > 0)
      containingClass->setHasMissingVTableEntries();

    suppliedMissingMember = MissingMemberDecl::create(
        context, containingClass, error.getName(),
        error.getNumberOfVTableEntries(),
        error.needsFieldOffsetVectorEntry());
  };
  llvm::handleAllErrors(std::move(error), handleMissingClassMember);
  return suppliedMissingMember;
}

Decl *handleErrorAndSupplyMissingProtoMember(ASTContext &context,
                                             llvm::Error &&error,
                                             ProtocolDecl *containingProto) {
  Decl *suppliedMissingMember = nullptr;

  auto handleMissingProtocolMember =
      [&](const DeclDeserializationError &error) {
        assert(error.needsFieldOffsetVectorEntry() == 0);

        if (error.getNumberOfVTableEntries() > 0)
          containingProto->setHasMissingRequirements(true);

        suppliedMissingMember = MissingMemberDecl::create(
            context, containingProto, error.getName(),
            error.getNumberOfVTableEntries(), 0);
      };
  llvm::handleAllErrors(std::move(error), handleMissingProtocolMember);
  return suppliedMissingMember;
}

Decl *handleErrorAndSupplyMissingMiscMember(llvm::Error &&error) {
  llvm::consumeError(std::move(error));
  return nullptr;
}

Decl *handleErrorAndSupplyMissingMember(ASTContext &context, Decl *container,
                                        llvm::Error &&error) {
  // Drop the member if it had a problem.
  // FIXME: Handle overridable members in class extensions too, someday.
  if (auto *containingClass = dyn_cast<ClassDecl>(container)) {
    return handleErrorAndSupplyMissingClassMember(context, std::move(error),
                                                  containingClass);
  }
  if (auto *containingProto = dyn_cast<ProtocolDecl>(container)) {
    return handleErrorAndSupplyMissingProtoMember(context, std::move(error),
                                                  containingProto);
  }
  return handleErrorAndSupplyMissingMiscMember(std::move(error));
}

void ModuleFile::loadAllMembers(Decl *container, uint64_t contextData) {
  PrettyStackTraceDecl trace("loading members for", container);
  ++NumMemberListsLoaded;

  IterableDeclContext *IDC;
  if (auto *nominal = dyn_cast<NominalTypeDecl>(container))
    IDC = nominal;
  else
    IDC = cast<ExtensionDecl>(container);

  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(contextData);
  auto entry = DeclTypeCursor.advance();
  if (entry.Kind != llvm::BitstreamEntry::Record)
    fatal();

  SmallVector<uint64_t, 16> memberIDBuffer;

  unsigned kind = DeclTypeCursor.readRecord(entry.ID, memberIDBuffer);
  assert(kind == decls_block::MEMBERS);
  (void)kind;

  ArrayRef<uint64_t> rawMemberIDs;
  decls_block::MembersLayout::readRecord(memberIDBuffer, rawMemberIDs);

  if (rawMemberIDs.empty())
    return;

  SmallVector<Decl *, 16> members;
  members.reserve(rawMemberIDs.size());
  for (DeclID rawID : rawMemberIDs) {
    Expected<Decl *> next = getDeclChecked(rawID);
    if (next) {
      assert(next.get() && "unchecked error deserializing next member");
      members.push_back(next.get());
    } else {
      if (!getContext().LangOpts.EnableDeserializationRecovery)
        fatal(next.takeError());

      Decl *suppliedMissingMember = handleErrorAndSupplyMissingMember(
          getContext(), container, next.takeError());
      if (suppliedMissingMember)
        members.push_back(suppliedMissingMember);
    }
  }

  for (auto member : members)
    IDC->addMember(member);

  if (auto *proto = dyn_cast<ProtocolDecl>(container)) {
    PrettyStackTraceDecl trace("reading default witness table for", proto);
    bool Err = readDefaultWitnessTable(proto);
    assert(!Err && "unable to read default witness table");
    (void)Err;
  }
}

void
ModuleFile::loadAllConformances(const Decl *D, uint64_t contextData,
                          SmallVectorImpl<ProtocolConformance*> &conformances) {
  PrettyStackTraceDecl trace("loading conformances for", D);

  uint64_t numConformances;
  uint64_t bitPosition;
  std::tie(numConformances, bitPosition)
    = decodeLazyConformanceContextData(contextData);

  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(bitPosition);

  while (numConformances--) {
    auto conf = readConformance(DeclTypeCursor);
    if (conf.isConcrete())
      conformances.push_back(conf.getConcrete());
  }
}

Type
ModuleFile::loadAssociatedTypeDefault(const swift::AssociatedTypeDecl *ATD,
                                      uint64_t contextData) {
  return getType(contextData);
}

void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
                                         uint64_t contextData) {
  using namespace decls_block;

  PrettyStackTraceModuleFile traceModule("While reading from", *this);
  PrettyStackTraceConformance trace(getAssociatedModule()->getASTContext(),
                                    "finishing conformance for",
                                    conformance);
  ++NumNormalProtocolConformancesCompleted;

  assert(conformance->isComplete());

  conformance->setState(ProtocolConformanceState::Incomplete);
  SWIFT_DEFER { conformance->setState(ProtocolConformanceState::Complete); };

  // Find the conformance record.
  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(contextData);
  auto entry = DeclTypeCursor.advance();
  assert(entry.Kind == llvm::BitstreamEntry::Record &&
         "registered lazy loader incorrectly");

  DeclID protoID;
  DeclContextID contextID;
  unsigned valueCount, typeCount, conformanceCount;
  ArrayRef<uint64_t> rawIDs;
  SmallVector<uint64_t, 16> scratch;

  unsigned kind = DeclTypeCursor.readRecord(entry.ID, scratch);
  (void) kind;
  assert(kind == NORMAL_PROTOCOL_CONFORMANCE &&
         "registered lazy loader incorrectly");
  NormalProtocolConformanceLayout::readRecord(scratch, protoID,
                                              contextID, typeCount,
                                              valueCount, conformanceCount,
                                              rawIDs);

  // Read requirement signature conformances.
  const ProtocolDecl *proto = conformance->getProtocol();
  SmallVector<ProtocolConformanceRef, 4> reqConformances;

  if (proto->isObjC() && getContext().LangOpts.EnableDeserializationRecovery) {
    // Don't crash if inherited protocols are added or removed.
    // This is limited to Objective-C protocols because we know their only
    // conformance requirements are on Self. This isn't actually a /safe/ change
    // even in Objective-C, but we mostly just don't want to crash.

    // FIXME: DenseMap requires that its value type be default-constructible,
    // which ProtocolConformanceRef is not, hence the extra Optional.
    llvm::SmallDenseMap<ProtocolDecl *, Optional<ProtocolConformanceRef>, 16>
        conformancesForProtocols;
    while (conformanceCount--) {
      ProtocolConformanceRef nextConformance = readConformance(DeclTypeCursor);
      ProtocolDecl *confProto = nextConformance.getRequirement();
      conformancesForProtocols[confProto] = nextConformance;
    }

    for (const auto &req : proto->getRequirementSignature()) {
      if (req.getKind() != RequirementKind::Conformance)
        continue;
      ProtocolDecl *proto =
          req.getSecondType()->castTo<ProtocolType>()->getDecl();
      auto iter = conformancesForProtocols.find(proto);
      if (iter != conformancesForProtocols.end()) {
        reqConformances.push_back(iter->getSecond().getValue());
      } else {
        // Put in an abstract conformance as a placeholder. This is a lie, but
        // there's not much better we can do. We're relying on the fact that
        // the rest of the compiler doesn't actually need to check the
        // conformance to an Objective-C protocol for anything important.
        // There are no associated types and we don't emit a Swift conformance
        // record.
        reqConformances.push_back(ProtocolConformanceRef(proto));
      }
    }

  } else {
    auto isConformanceReq = [](const Requirement &req) {
      return req.getKind() == RequirementKind::Conformance;
    };
    if (conformanceCount != llvm::count_if(proto->getRequirementSignature(),
                                           isConformanceReq)) {
      fatal(llvm::make_error<llvm::StringError>(
          "serialized conformances do not match requirement signature",
          llvm::inconvertibleErrorCode()));
    }
    while (conformanceCount--)
      reqConformances.push_back(readConformance(DeclTypeCursor));
  }
  conformance->setSignatureConformances(reqConformances);

  ArrayRef<uint64_t>::iterator rawIDIter = rawIDs.begin();

  TypeWitnessMap typeWitnesses;
  while (typeCount--) {
    // FIXME: We don't actually want to allocate an archetype here; we just
    // want to get an access path within the protocol.
    auto first = cast<AssociatedTypeDecl>(getDecl(*rawIDIter++));
    auto second = getType(*rawIDIter++);
    auto third = cast_or_null<TypeDecl>(getDecl(*rawIDIter++));
    if (third &&
        isa<TypeAliasDecl>(third) &&
        third->getModuleContext() != getAssociatedModule() &&
        !third->getDeclaredInterfaceType()->isEqual(second)) {
      // Conservatively drop references to typealiases in other modules
      // that may have changed. This may also drop references to typealiases
      // that /haven't/ changed but just happen to have generics in them, but
      // in practice having a declaration here isn't actually required by the
      // rest of the compiler.
      third = nullptr;
    }
    typeWitnesses[first] = std::make_pair(second, third);
  }
  assert(rawIDIter <= rawIDs.end() && "read too much");

  // Set type witnesses.
  for (auto typeWitness : typeWitnesses) {
    conformance->setTypeWitness(typeWitness.first, typeWitness.second.first,
                                typeWitness.second.second);
  }

  // An imported requirement may have changed type between Swift versions.
  // In this situation we need to do a post-pass to fill in missing
  // requirements with opaque witnesses.
  bool needToFillInOpaqueValueWitnesses = false;
  while (valueCount--) {
    ValueDecl *req;
    
    auto trySetWitness = [&](Witness w) {
      if (req)
        conformance->setWitness(req, w);
    };
    
    auto deserializedReq = getDeclChecked(*rawIDIter++);
    if (deserializedReq) {
      req = cast_or_null<ValueDecl>(*deserializedReq);
    } else if (getContext().LangOpts.EnableDeserializationRecovery) {
      consumeError(deserializedReq.takeError());
      req = nullptr;
      needToFillInOpaqueValueWitnesses = true;
    } else {
      fatal(deserializedReq.takeError());
    }
    
    bool isOpaque = false;
    ValueDecl *witness;
    auto deserializedWitness = getDeclChecked(*rawIDIter++);
    if (deserializedWitness) {
      witness = cast_or_null<ValueDecl>(*deserializedWitness);
    // Across language compatibility versions, the witnessing decl may have
    // changed its signature as seen by the current compatibility version.
    // In that case, we want the conformance to still be available, but
    // we can't make use of the relationship to the underlying decl.
    } else if (getContext().LangOpts.EnableDeserializationRecovery) {
      consumeError(deserializedWitness.takeError());
      isOpaque = true;
      witness = nullptr;
    } else {
      fatal(deserializedWitness.takeError());
    }
    
    assert(!req || isOpaque || witness ||
           req->getAttrs().hasAttribute<OptionalAttr>() ||
           req->getAttrs().isUnavailable(getContext()));
    if (!witness && !isOpaque) {
      trySetWitness(Witness());
      continue;
    }

    auto trySetOpaqueWitness = [&]{
      if (!req)
        return;

      conformance->setWitness(req, Witness::forOpaque(req));
    };

    // Witness substitutions.
    auto witnessSubstitutions = getSubstitutionMapChecked(*rawIDIter++);
    if (!witnessSubstitutions) {
      // Missing module errors are most likely caused by an
      // implementation-only import hiding types and decls.
      // rdar://problem/52837313
      if (witnessSubstitutions.errorIsA<XRefNonLoadedModuleError>()) {
        consumeError(witnessSubstitutions.takeError());
        isOpaque = true;
      }
      else
        fatal(witnessSubstitutions.takeError());
    }

    // Handle opaque witnesses that couldn't be deserialized.
    if (isOpaque) {
      trySetOpaqueWitness();
      continue;
    }

    // Set the witness.
    trySetWitness(Witness::forDeserialized(witness, witnessSubstitutions.get()));
  }
  assert(rawIDIter <= rawIDs.end() && "read too much");
  
  // Fill in opaque value witnesses if we need to.
  if (needToFillInOpaqueValueWitnesses) {
    for (auto member : proto->getMembers()) {
      // We only care about non-associated-type requirements.
      auto valueMember = dyn_cast<ValueDecl>(member);
      if (!valueMember || !valueMember->isProtocolRequirement()
          || isa<AssociatedTypeDecl>(valueMember))
        continue;
      
      if (!conformance->hasWitness(valueMember))
        conformance->setWitness(valueMember, Witness::forOpaque(valueMember));
    }
  }
}

void ModuleFile::loadRequirementSignature(const ProtocolDecl *decl,
                                          uint64_t contextData,
                                          SmallVectorImpl<Requirement> &reqs) {
  BCOffsetRAII restoreOffset(DeclTypeCursor);
  DeclTypeCursor.JumpToBit(contextData);
  readGenericRequirements(reqs, DeclTypeCursor);
}

static Optional<ForeignErrorConvention::Kind>
decodeRawStableForeignErrorConventionKind(uint8_t kind) {
  switch (kind) {
  case static_cast<uint8_t>(ForeignErrorConventionKind::ZeroResult):
    return ForeignErrorConvention::ZeroResult;
  case static_cast<uint8_t>(ForeignErrorConventionKind::NonZeroResult):
    return ForeignErrorConvention::NonZeroResult;
  case static_cast<uint8_t>(ForeignErrorConventionKind::ZeroPreservedResult):
    return ForeignErrorConvention::ZeroPreservedResult;
  case static_cast<uint8_t>(ForeignErrorConventionKind::NilResult):
    return ForeignErrorConvention::NilResult;
  case static_cast<uint8_t>(ForeignErrorConventionKind::NonNilError):
    return ForeignErrorConvention::NonNilError;
  default:
    return None;
  }
}

Optional<StringRef> ModuleFile::maybeReadInlinableBodyText() {
  using namespace decls_block;

  SmallVector<uint64_t, 8> scratch;
  BCOffsetRAII restoreOffset(DeclTypeCursor);
  StringRef blobData;

  auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
  if (next.Kind != llvm::BitstreamEntry::Record)
    return None;

  unsigned recKind = DeclTypeCursor.readRecord(next.ID, scratch, &blobData);
  if (recKind != INLINABLE_BODY_TEXT)
    return None;

  restoreOffset.reset();
  return blobData;
}

Optional<ForeignErrorConvention> ModuleFile::maybeReadForeignErrorConvention() {
  using namespace decls_block;

  SmallVector<uint64_t, 8> scratch;

  BCOffsetRAII restoreOffset(DeclTypeCursor);

  auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
  if (next.Kind != llvm::BitstreamEntry::Record)
    return None;

  unsigned recKind = DeclTypeCursor.readRecord(next.ID, scratch);
  switch (recKind) {
  case FOREIGN_ERROR_CONVENTION:
    restoreOffset.reset();
    break;

  default:
    return None;
  }

  uint8_t rawKind;
  bool isOwned;
  bool isReplaced;
  unsigned errorParameterIndex;
  TypeID errorParameterTypeID;
  TypeID resultTypeID;
  ForeignErrorConventionLayout::readRecord(scratch, rawKind,
                                           isOwned, isReplaced,
                                           errorParameterIndex,
                                           errorParameterTypeID,
                                           resultTypeID);

  ForeignErrorConvention::Kind kind;
  if (auto optKind = decodeRawStableForeignErrorConventionKind(rawKind))
    kind = *optKind;
  else
    fatal();

  Type errorParameterType = getType(errorParameterTypeID);
  CanType canErrorParameterType;
  if (errorParameterType)
    canErrorParameterType = errorParameterType->getCanonicalType();

  Type resultType = getType(resultTypeID);
  CanType canResultType;
  if (resultType)
    canResultType = resultType->getCanonicalType();

  auto owned = isOwned ? ForeignErrorConvention::IsOwned
                       : ForeignErrorConvention::IsNotOwned;
  auto replaced = ForeignErrorConvention::IsReplaced_t(isOwned);
  switch (kind) {
  case ForeignErrorConvention::ZeroResult:
    return ForeignErrorConvention::getZeroResult(errorParameterIndex,
                                                 owned, replaced,
                                                 canErrorParameterType,
                                                 canResultType);

  case ForeignErrorConvention::NonZeroResult:
    return ForeignErrorConvention::getNonZeroResult(errorParameterIndex,
                                                    owned, replaced,
                                                    canErrorParameterType,
                                                    canResultType);

  case ForeignErrorConvention::ZeroPreservedResult:
    return ForeignErrorConvention::getZeroPreservedResult(errorParameterIndex,
                                                          owned, replaced,
                                                       canErrorParameterType);

  case ForeignErrorConvention::NilResult:
    return ForeignErrorConvention::getNilResult(errorParameterIndex,
                                                owned, replaced,
                                                canErrorParameterType);

  case ForeignErrorConvention::NonNilError:
    return ForeignErrorConvention::getNonNilError(errorParameterIndex,
                                                  owned, replaced,
                                                  canErrorParameterType);
  }

  llvm_unreachable("Unhandled ForeignErrorConvention in switch.");
}
