Merge pull request #9407 from slavapestov/use-objc-msgsend-for-overrides-of-imported-methods

Use objc_msgSend() for overrides of imported methods [4.0]
diff --git a/include/swift/AST/Witness.h b/include/swift/AST/Witness.h
index 738e2f1..e81c5ea 100644
--- a/include/swift/AST/Witness.h
+++ b/include/swift/AST/Witness.h
@@ -108,6 +108,16 @@
   /// not generic (excepting \c Self)  and the conforming type is non-generic.
   Witness(ValueDecl *witness) : storage(witness) { assert(witness != nullptr); }
 
+  /// Create an opaque witness for the given requirement.
+  ///
+  /// This indicates that a witness exists, but is not visible to the current
+  /// module.
+  static Witness forOpaque(ValueDecl *requirement) {
+    // TODO: It's probably a good idea to have a separate 'opaque' bit.
+    // Making req == witness is kind of a hack.
+    return Witness(requirement);
+  }
+
   /// Create a witness that requires substitutions.
   ///
   /// \param decl The declaration for the witness.
diff --git a/include/swift/Basic/Version.h b/include/swift/Basic/Version.h
index 9c36999..9d157dc 100644
--- a/include/swift/Basic/Version.h
+++ b/include/swift/Basic/Version.h
@@ -144,6 +144,9 @@
 
 bool operator>=(const Version &lhs, const Version &rhs);
 bool operator==(const Version &lhs, const Version &rhs);
+inline bool operator!=(const Version &lhs, const Version &rhs) {
+  return !(lhs == rhs);
+}
 
 raw_ostream &operator<<(raw_ostream &os, const Version &version);
 
diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h
index 263941a..6401709 100644
--- a/include/swift/ClangImporter/ClangImporter.h
+++ b/include/swift/ClangImporter/ClangImporter.h
@@ -308,10 +308,12 @@
 
   Optional<std::string>
   getOrCreatePCH(const ClangImporterOptions &ImporterOptions,
-                 const std::string &SwiftPCHHash);
+                 StringRef SwiftPCHHash);
   Optional<std::string>
+  /// \param isExplicit true if the PCH filename was passed directly
+  /// with -import-objc-header option.
   getPCHFilename(const ClangImporterOptions &ImporterOptions,
-                 const std::string &SwiftPCHHash);
+                 StringRef SwiftPCHHash, bool &isExplicit);
 };
 
 ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,
diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h
index d7106e6..0904510 100644
--- a/include/swift/Demangling/Demangle.h
+++ b/include/swift/Demangling/Demangle.h
@@ -409,6 +409,12 @@
 /// This should always round-trip perfectly with demangleSymbolAsNode.
 std::string mangleNode(const NodePointer &root);
 
+/// Remangle in the old mangling scheme.
+///
+/// This is only used for objc-runtime names and should be removed as soon as
+/// we switch to the new mangling for those names as well.
+std::string mangleNodeOld(const NodePointer &root);
+
 /// \brief Transform the node structure to a string.
 ///
 /// Typical usage:
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index d53c555..a3293e7 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -13,6 +13,7 @@
 #ifndef SWIFT_IDE_UTILS_H
 #define SWIFT_IDE_UTILS_H
 
+#include "llvm/ADT/PointerIntPair.h"
 #include "swift/Basic/LLVM.h"
 #include "swift/AST/ASTNode.h"
 #include "swift/AST/Module.h"
@@ -243,9 +244,12 @@
   Break,
   Continue,
 };
+
+typedef llvm::PointerIntPair<TypeBase*, 1, bool> ReturnTyAndWhetherExit;
+
 struct ResolvedRangeInfo {
   RangeKind Kind;
-  Type Ty;
+  ReturnTyAndWhetherExit ExitInfo;
   StringRef Content;
   bool HasSingleEntry;
   bool ThrowingUnhandledError;
@@ -256,23 +260,26 @@
   ArrayRef<DeclaredDecl> DeclaredDecls;
   ArrayRef<ReferencedDecl> ReferencedDecls;
   DeclContext* RangeContext;
-  ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content,
+  ResolvedRangeInfo(RangeKind Kind, ReturnTyAndWhetherExit ExitInfo, StringRef Content,
                     DeclContext* RangeContext,
                     bool HasSingleEntry, bool ThrowingUnhandledError,
                     OrphanKind Orphan, ArrayRef<ASTNode> ContainedNodes,
                     ArrayRef<DeclaredDecl> DeclaredDecls,
                     ArrayRef<ReferencedDecl> ReferencedDecls): Kind(Kind),
-                      Ty(Ty), Content(Content), HasSingleEntry(HasSingleEntry),
+                      ExitInfo(ExitInfo), Content(Content),
+                      HasSingleEntry(HasSingleEntry),
                       ThrowingUnhandledError(ThrowingUnhandledError),
                       Orphan(Orphan), ContainedNodes(ContainedNodes),
                       DeclaredDecls(DeclaredDecls),
                       ReferencedDecls(ReferencedDecls),
                       RangeContext(RangeContext) {}
   ResolvedRangeInfo(StringRef Content) :
-  ResolvedRangeInfo(RangeKind::Invalid, Type(), Content, nullptr,
+  ResolvedRangeInfo(RangeKind::Invalid, {nullptr, false}, Content, nullptr,
                     /*Single entry*/true, /*unhandled error*/false,
                     OrphanKind::None, {}, {}, {}) {}
   void print(llvm::raw_ostream &OS);
+  bool exit() const { return ExitInfo.getInt(); }
+  Type getType() const { return ExitInfo.getPointer(); }
 };
 
 class RangeResolver : public SourceEntityWalker {
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 429aec1..6c4c320 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -73,7 +73,7 @@
   StringRef TargetTriple;
 
   /// The Swift compatibility version in use when this module was built.
-  StringRef CompatibilityVersion;
+  version::Version CompatibilityVersion;
 
   /// The data blob containing all of the module's identifiers.
   StringRef IdentifierData;
diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h
index 76b279b..dbd86e1 100644
--- a/include/swift/Serialization/Validation.h
+++ b/include/swift/Serialization/Validation.h
@@ -71,7 +71,7 @@
   StringRef name = {};
   StringRef targetTriple = {};
   StringRef shortVersion = {};
-  StringRef compatibilityVersion = {};
+  version::Version compatibilityVersion = {};
   size_t bytes = 0;
   Status status = Status::Malformed;
 };
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index 93d5a07..fa9a543 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -24,6 +24,7 @@
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/ProtocolConformance.h"
 #include "swift/Demangling/ManglingUtils.h"
+#include "swift/Demangling/Demangler.h"
 #include "swift/Strings.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/AST/Attr.h"
@@ -301,12 +302,18 @@
   return finalize();
 }
 
+#ifdef USE_NEW_MANGLING_FOR_OBJC_RUNTIME_NAMES
 static bool isPrivate(const NominalTypeDecl *Nominal) {
   return Nominal->hasAccessibility() &&
          Nominal->getFormalAccess() <= Accessibility::FilePrivate;
 }
+#endif
 
 std::string ASTMangler::mangleObjCRuntimeName(const NominalTypeDecl *Nominal) {
+#ifdef USE_NEW_MANGLING_FOR_OBJC_RUNTIME_NAMES
+  // Using the new mangling for ObjC runtime names (except for top-level
+  // classes). This is currently disabled to support old archives.
+  // TODO: re-enable this as we switch to the new mangling for ObjC names.
   DeclContext *Ctx = Nominal->getDeclContext();
 
   if (Ctx->isModuleScopeContext() && !isPrivate(Nominal)) {
@@ -338,6 +345,34 @@
   beginMangling();
   appendAnyGenericType(Nominal);
   return finalize();
+#else
+  // Use the old mangling for ObjC runtime names.
+  beginMangling();
+  appendAnyGenericType(Nominal);
+  std::string NewName = finalize();
+  Demangle::Demangler Dem;
+  Demangle::Node *Root = Dem.demangleSymbol(NewName);
+  assert(Root->getKind() == Node::Kind::Global);
+  Node *NomTy = Root->getFirstChild();
+  if (NomTy->getKind() == Node::Kind::Protocol) {
+    // Protocols are actually mangled as protocol lists.
+    Node *PTy = Dem.createNode(Node::Kind::Type);
+    PTy->addChild(NomTy, Dem);
+    Node *TList = Dem.createNode(Node::Kind::TypeList);
+    TList->addChild(PTy, Dem);
+    NomTy = Dem.createNode(Node::Kind::ProtocolList);
+    NomTy->addChild(TList, Dem);
+  }
+  // Add a TypeMangling node at the top
+  Node *Ty = Dem.createNode(Node::Kind::Type);
+  Ty->addChild(NomTy, Dem);
+  Node *TyMangling = Dem.createNode(Node::Kind::TypeMangling);
+  TyMangling->addChild(Ty, Dem);
+  Node *NewGlobal = Dem.createNode(Node::Kind::Global);
+  NewGlobal->addChild(TyMangling, Dem);
+  std::string OldName = mangleNodeOld(NewGlobal);
+  return OldName;
+#endif
 }
 
 std::string ASTMangler::mangleTypeAsContextUSR(const NominalTypeDecl *type) {
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index aebcb27..9ca9f7c 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -226,6 +226,11 @@
   return isValidVersion ? Optional<Version>(TheVersion) : None;
 }
 
+Version::Version(StringRef VersionString,
+                 SourceLoc Loc,
+                 DiagnosticEngine *Diags)
+  : Version(*parseVersionString(VersionString, Loc, Diags))
+{}
 
 Version Version::getCurrentCompilerVersion() {
 #ifdef SWIFT_COMPILER_VERSION
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 5847118..236f4e0 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -711,22 +711,73 @@
 }
 
 bool ClangImporter::canReadPCH(StringRef PCHFilename) {
-  return clang::ASTReader::isAcceptableASTFile(PCHFilename,
-    Impl.Instance->getFileManager(),
-    Impl.Instance->getPCHContainerReader(),
-    Impl.Instance->getLangOpts(),
-    Impl.Instance->getTargetOpts(),
-    Impl.Instance->getPreprocessorOpts(),
-    Impl.Instance->getSpecificModuleCachePath());
+  if (!llvm::sys::fs::exists(PCHFilename))
+    return false;
+
+  // FIXME: The following attempts to do an initial ReadAST invocation to verify
+  // the PCH, without affecting the existing CompilerInstance.
+  // Look into combining creating the ASTReader along with verification + update
+  // if necesary, so that we can create and use one ASTReader in the common case
+  // when there is no need for update.
+
+  CompilerInstance &CI = *Impl.Instance;
+  auto clangDiags = CompilerInstance::createDiagnostics(
+                                              new clang::DiagnosticOptions());
+  clang::SourceManager clangSrcMgr(*clangDiags, CI.getFileManager());
+  auto FID = clangSrcMgr.createFileID(
+                        llvm::make_unique<ZeroFilledMemoryBuffer>(1, "<main>"));
+  clangSrcMgr.setMainFileID(FID);
+  clang::Preprocessor PP(CI.getInvocation().getPreprocessorOptsPtr(),
+                         *clangDiags,
+                         CI.getLangOpts(),
+                         clangSrcMgr,
+                         CI.getPCMCache(),
+                         CI.getPreprocessor().getHeaderSearchInfo(), CI,
+                         /*IILookup=*/nullptr,
+                         /*OwnsHeaderSearch=*/false);
+  PP.Initialize(CI.getTarget());
+  clang::ASTContext ctx(CI.getLangOpts(), clangSrcMgr,
+                        PP.getIdentifierTable(), PP.getSelectorTable(),
+                        PP.getBuiltinInfo());
+
+  std::unique_ptr<clang::ASTReader> Reader(new clang::ASTReader(
+      PP, ctx, CI.getPCHContainerReader(),
+      CI.getFrontendOpts().ModuleFileExtensions,
+      CI.getHeaderSearchOpts().Sysroot,
+      /*DisableValidation*/ false,
+      /*AllowPCHWithCompilerErrors*/ false,
+      /*AllowConfigurationMismatch*/ false,
+      /*ValidateSystemInputs*/ true));
+  ctx.InitBuiltinTypes(CI.getTarget());
+
+  auto result = Reader->ReadAST(PCHFilename,
+                  clang::serialization::MK_PCH,
+                  clang::SourceLocation(),
+                  clang::ASTReader::ARR_None);
+  switch (result) {
+  case clang::ASTReader::Success:
+    return true;
+  case clang::ASTReader::Failure:
+  case clang::ASTReader::Missing:
+  case clang::ASTReader::OutOfDate:
+  case clang::ASTReader::VersionMismatch:
+    return false;
+  case clang::ASTReader::ConfigurationMismatch:
+  case clang::ASTReader::HadErrors:
+    assert(0 && "unexpected ASTReader failure for PCH validation");
+    return false;
+  }
 }
 
 Optional<std::string>
 ClangImporter::getPCHFilename(const ClangImporterOptions &ImporterOptions,
-                              const std::string &SwiftPCHHash) {
+                              StringRef SwiftPCHHash, bool &isExplicit) {
   if (llvm::sys::path::extension(ImporterOptions.BridgingHeader)
         .endswith(PCH_EXTENSION)) {
+    isExplicit = true;
     return ImporterOptions.BridgingHeader;
   }
+  isExplicit = false;
 
   const auto &BridgingHeader = ImporterOptions.BridgingHeader;
   const auto &PCHOutputDir = ImporterOptions.PrecompiledHeaderOutputDir;
@@ -749,18 +800,27 @@
 
 Optional<std::string>
 ClangImporter::getOrCreatePCH(const ClangImporterOptions &ImporterOptions,
-                              const std::string &SwiftPCHHash) {
-  auto PCHFilename = getPCHFilename(ImporterOptions, SwiftPCHHash);
+                              StringRef SwiftPCHHash) {
+  bool isExplicit;
+  auto PCHFilename = getPCHFilename(ImporterOptions, SwiftPCHHash,
+                                    isExplicit);
   if (!PCHFilename.hasValue()) {
     return None;
   }
-  if (!canReadPCH(PCHFilename.getValue())) {
+  if (!isExplicit && !canReadPCH(PCHFilename.getValue())) {
     SmallString<256> Message;
     llvm::raw_svector_ostream OS(Message);
     auto Diags = new clang::TextDiagnosticPrinter {
       llvm::errs(),
       &Impl.Instance->getDiagnosticOpts()
     };
+    StringRef parentDir = llvm::sys::path::parent_path(PCHFilename.getValue());
+    std::error_code EC = llvm::sys::fs::create_directories(parentDir);
+    if (EC) {
+      llvm::errs() << "failed to create directory '" << parentDir << "': "
+        << EC.message();
+      return None;
+    }
     auto FailedToEmit = emitBridgingPCH(ImporterOptions.BridgingHeader,
                                         PCHFilename.getValue(),
                                         Diags);
diff --git a/lib/Demangling/CMakeLists.txt b/lib/Demangling/CMakeLists.txt
index d92b3e0..8f83b92 100644
--- a/lib/Demangling/CMakeLists.txt
+++ b/lib/Demangling/CMakeLists.txt
@@ -5,6 +5,7 @@
   NodeDumper.cpp
   NodePrinter.cpp
   OldDemangler.cpp
+  OldRemangler.cpp
   Punycode.cpp
   Remangler.cpp
   )
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
new file mode 100644
index 0000000..fc4be9c
--- /dev/null
+++ b/lib/Demangling/OldRemangler.cpp
@@ -0,0 +1,1753 @@
+//===--- OldRemangler.cpp - Old Swift Re-mangler --------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 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
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the remangler, which turns a demangling parse
+//  tree back into a mangled string.  This is useful for tools which
+//  want to extract subtrees from mangled strings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Demangling/Demangler.h"
+#include "swift/Demangling/Punycode.h"
+#include "swift/Strings.h"
+#include <vector>
+#include <cstdio>
+#include <cstdlib>
+#include <unordered_map>
+
+using namespace swift;
+using namespace Demangle;
+
+[[noreturn]]
+static void unreachable(const char *Message) {
+  fprintf(stderr, "fatal error: %s\n", Message);
+  std::abort();
+}
+
+/// Translate the given operator character into its mangled form.
+///
+/// Current operator characters:   @/=-+*%<>!&|^~ and the special operator '..'
+static char mangleOperatorChar(char op) {
+  switch (op) {
+  case '&': return 'a'; // 'and'
+  case '@': return 'c'; // 'commercial at sign'
+  case '/': return 'd'; // 'divide'
+  case '=': return 'e'; // 'equal'
+  case '>': return 'g'; // 'greater'
+  case '<': return 'l'; // 'less'
+  case '*': return 'm'; // 'multiply'
+  case '!': return 'n'; // 'negate'
+  case '|': return 'o'; // 'or'
+  case '+': return 'p'; // 'plus'
+  case '?': return 'q'; // 'question'
+  case '%': return 'r'; // 'remainder'
+  case '-': return 's'; // 'subtract'
+  case '~': return 't'; // 'tilde'
+  case '^': return 'x'; // 'xor'
+  case '.': return 'z'; // 'zperiod' (the z is silent)
+  default:
+    return op;
+  }
+}
+
+static bool isNonAscii(StringRef str) {
+  for (unsigned char c : str) {
+    if (c >= 0x80)
+      return true;
+  }
+  return false;
+}
+
+static char mangleOperatorKind(OperatorKind operatorKind) {
+  switch (operatorKind) {
+  case OperatorKind::NotOperator: unreachable("invalid");
+  case OperatorKind::Infix: return 'i';
+  case OperatorKind::Prefix: return 'p';
+  case OperatorKind::Postfix: return 'P';
+  }
+  unreachable("invalid");
+}
+
+static void mangleIdentifier(StringRef ident, OperatorKind operatorKind,
+                             bool usePunycode, DemanglerPrinter &out) {
+  std::string punycodeBuf;
+  if (usePunycode) {
+    // If the identifier contains non-ASCII character, we mangle 
+    // with an initial X and Punycode the identifier string.
+    if (isNonAscii(ident)) {
+      out << 'X';
+      Punycode::encodePunycodeUTF8(ident, punycodeBuf);
+      ident = punycodeBuf;
+    }
+  }
+
+  // Mangle normal identifiers as
+  //   count identifier-char+
+  // where the count is the number of characters in the identifier,
+  // and where individual identifier characters represent themselves.
+  if (operatorKind == OperatorKind::NotOperator) {
+    out << ident.size() << ident;
+    return;
+  }
+
+  // Mangle operator identifiers as
+  //   operator ::= 'o' operator-fixity count operator-char+
+  //   operator-fixity ::= 'p' // prefix
+  //   operator-fixity ::= 'P' // postfix
+  //   operator-fixity ::= 'i' // infix
+  // where the count is the number of characters in the operator,
+  // and where the individual operator characters are translated.
+  out << 'o' << mangleOperatorKind(operatorKind);
+
+  // Mangle ASCII operators directly.
+  out << ident.size();
+  for (char ch : ident) {
+    out << mangleOperatorChar(ch);
+  }
+}
+
+void Demangle::mangleIdentifier(const char *data, size_t length,
+                                OperatorKind operatorKind,
+                                std::string &out, bool usePunycode) {
+  DemanglerPrinter printer;
+  ::mangleIdentifier(StringRef(data, length), operatorKind,
+                     usePunycode, printer);
+  out = std::move(printer).str();
+}
+
+namespace {
+  struct DeepHasher {
+    size_t value = 0;
+
+    void combine(size_t newValue) {
+      value = 33 * value + newValue;
+    }
+
+    void hash(Node *node) {
+      combine((size_t) node->getKind());
+      if (node->hasIndex()) {
+        combine(node->getIndex());
+      } else if (node->hasText()) {
+        StringRef text = node->getText();
+        for (char c : text) {
+          combine((unsigned char) c);
+        }
+      }
+      for (const auto &child : *node) {
+        hash(child);
+      }
+    }
+  };
+} // end anonymous namespace
+
+static size_t deepHash(Node *node) {
+  DeepHasher hasher;
+  hasher.hash(node);
+  return hasher.value;  
+}
+
+static bool deepEquals(Node *lhs, Node *rhs) {
+  if (lhs->getKind() != rhs->getKind())
+    return false;
+  if (lhs->hasIndex()) {
+    if (!rhs->hasIndex())
+      return false;
+    if (lhs->getIndex() != rhs->getIndex())
+      return false;
+  } else if (lhs->hasText()) {
+    if (!rhs->hasText())
+      return false;
+    if (lhs->getText() != rhs->getText())
+      return false;
+  } else if (rhs->hasIndex() || rhs->hasText()) {
+    return false;
+  }
+
+  if (lhs->getNumChildren() != rhs->getNumChildren())
+    return false;
+
+  for (auto li = lhs->begin(), ri = lhs->begin(), le = lhs->end();
+       li != le; ++li, ++ri) {
+    if (!deepEquals(*li, *ri))
+      return false;
+  }
+
+  return true;
+}
+
+namespace {
+  struct SubstitutionEntry {
+    Node *TheNode;
+    size_t StoredHash;
+
+    // Note that the constructor leaves this uninitialized.
+
+    struct Hasher {
+      size_t operator()(const SubstitutionEntry &entry) const {
+        return entry.StoredHash;
+      }
+    };
+    friend bool operator==(const SubstitutionEntry &lhs,
+                           const SubstitutionEntry &rhs) {
+      return (lhs.StoredHash == rhs.StoredHash &&
+              deepEquals(lhs.TheNode, lhs.TheNode));
+    }
+  };
+
+  class Remangler {
+    DemanglerPrinter &Out;
+
+    // We have to cons up temporary nodes sometimes when remangling
+    // nested generics. This factory owns them.
+    NodeFactory Factory;
+
+    std::unordered_map<SubstitutionEntry, unsigned,
+                       SubstitutionEntry::Hasher> Substitutions;
+  public:
+    Remangler(DemanglerPrinter &out) : Out(out) {}
+
+    class EntityContext {
+      bool AsContext = false;
+    public:
+      bool isAsContext() const {
+        return AsContext;
+      }
+
+      class ManglingContextRAII {
+        EntityContext &Ctx;
+        bool SavedValue;
+      public:
+        ManglingContextRAII(EntityContext &ctx)
+          : Ctx(ctx), SavedValue(ctx.AsContext) {
+          ctx.AsContext = true;
+        }
+
+        ~ManglingContextRAII() {
+          Ctx.AsContext = SavedValue;
+        }
+      };
+    };
+
+    void mangle(Node *node) {
+      switch (node->getKind()) {
+#define NODE(ID) case Node::Kind::ID: return mangle##ID(node);
+#include "swift/Demangling/DemangleNodes.def"
+      }
+      unreachable("bad demangling tree node");
+    }
+
+    void mangleGenericArgs(Node *node, EntityContext &ctx);
+    void mangleAnyNominalType(Node *node, EntityContext &ctx);
+
+#define NODE(ID)                                                        \
+    void mangle##ID(Node *node);
+#define CONTEXT_NODE(ID)                                                \
+    void mangle##ID(Node *node);                                        \
+    void mangle##ID(Node *node, EntityContext &ctx);
+#include "swift/Demangling/DemangleNodes.def"
+
+    void mangleIndex(Node::IndexType index);
+    void mangleIdentifier(StringRef name, OperatorKind operatorKind);
+
+    void mangleChildNodes(Node *node) { mangleNodes(node->begin(), node->end()); }
+    void mangleNodes(Node::iterator i, Node::iterator e) {
+      for (; i != e; ++i) {
+        mangle(*i);
+      }
+    }
+    void mangleSingleChildNode(Node *node) {
+      assert(node->getNumChildren() == 1);
+      mangle(*node->begin());
+    }
+    void mangleChildNode(Node *node, unsigned index) {
+      assert(index < node->getNumChildren());
+      mangle(node->begin()[index]);
+    }
+
+    void mangleSimpleEntity(Node *node, char basicKind, StringRef entityKind,
+                            EntityContext &ctx);
+    void mangleNamedEntity(Node *node, char basicKind, StringRef entityKind,
+                           EntityContext &ctx);
+    void mangleTypedEntity(Node *node, char basicKind, StringRef entityKind,
+                           EntityContext &ctx);
+    void mangleNamedAndTypedEntity(Node *node, char basicKind,
+                                   StringRef entityKind,
+                                   EntityContext &ctx);
+    void mangleNominalType(Node *node, char basicKind, EntityContext &ctx);
+
+    void mangleProtocolWithoutPrefix(Node *node);
+    void mangleProtocolListWithoutPrefix(Node *node,
+                                         Node *additionalProto = nullptr);
+
+    void mangleEntityContext(Node *node, EntityContext &ctx);
+    void mangleEntityType(Node *node, EntityContext &ctx);
+    void mangleEntityGenericType(Node *node, EntityContext &ctx);
+
+    bool trySubstitution(Node *node, SubstitutionEntry &entry);
+    bool mangleStandardSubstitution(Node *node);
+    void addSubstitution(const SubstitutionEntry &entry);
+    void resetSubstitutions();
+
+    void mangleDependentGenericParamIndex(Node *node);
+    void mangleConstrainedType(Node *node);
+  };
+} // end anonymous namespace
+
+#define NODE(ID)
+#define CONTEXT_NODE(ID)                        \
+void Remangler::mangle##ID(Node *node) {        \
+  EntityContext ctx;                            \
+  mangle##ID(node, ctx);                        \
+}
+#include "swift/Demangling/DemangleNodes.def"
+
+/// Reset the currently-active set of substitutions.  This is useful
+/// when part of the mangling is done independently, e.g. when an
+/// optimization pass modifies a pass.
+void Remangler::resetSubstitutions() {
+  Substitutions.clear();
+}
+
+bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry) {
+  if (mangleStandardSubstitution(node))
+    return true;
+
+  // Go ahead and initialize the substitution entry.
+  entry.TheNode = node;
+  entry.StoredHash = deepHash(node);
+
+  auto it = Substitutions.find(entry);
+  if (it == Substitutions.end())
+    return false;
+
+  Out << 'S';
+  mangleIndex(it->second);
+  return true;
+}
+
+static bool isInSwiftModule(Node *node) {
+  Node *context = node->getFirstChild();
+  return (context->getKind() == Node::Kind::Module &&
+          context->getText() == STDLIB_NAME);
+};
+
+bool Remangler::mangleStandardSubstitution(Node *node) {
+  // Look for known substitutions.
+  switch (node->getKind()) {
+#define SUCCESS_IF_IS(VALUE, EXPECTED, SUBSTITUTION)            \
+    do {                                                        \
+      if ((VALUE) == (EXPECTED)) {                              \
+        Out << SUBSTITUTION;                                    \
+        return true;                                            \
+      }                                                         \
+    } while (0)
+#define SUCCESS_IF_TEXT_IS(EXPECTED, SUBSTITUTION)              \
+    SUCCESS_IF_IS(node->getText(), EXPECTED, SUBSTITUTION)
+#define SUCCESS_IF_DECLNAME_IS(EXPECTED, SUBSTITUTION)          \
+    SUCCESS_IF_IS(node->getChild(1)->getText(), EXPECTED, SUBSTITUTION)
+
+    case Node::Kind::Module:
+      SUCCESS_IF_TEXT_IS(STDLIB_NAME, "s");
+      SUCCESS_IF_TEXT_IS(MANGLING_MODULE_OBJC, "So");
+      SUCCESS_IF_TEXT_IS(MANGLING_MODULE_CLANG_IMPORTER, "SC");
+      break;
+    case Node::Kind::Structure:
+      if (isInSwiftModule(node)) {
+        SUCCESS_IF_DECLNAME_IS("Array", "Sa");
+        SUCCESS_IF_DECLNAME_IS("Bool", "Sb");
+        SUCCESS_IF_DECLNAME_IS("UnicodeScalar", "Sc");
+        SUCCESS_IF_DECLNAME_IS("Double", "Sd");
+        SUCCESS_IF_DECLNAME_IS("Float", "Sf");
+        SUCCESS_IF_DECLNAME_IS("Int", "Si");
+        SUCCESS_IF_DECLNAME_IS("UnsafeRawPointer", "SV");
+        SUCCESS_IF_DECLNAME_IS("UnsafeMutableRawPointer", "Sv");
+        SUCCESS_IF_DECLNAME_IS("UnsafePointer", "SP");
+        SUCCESS_IF_DECLNAME_IS("UnsafeMutablePointer", "Sp");
+        SUCCESS_IF_DECLNAME_IS("UnsafeBufferPointer", "SR");
+        SUCCESS_IF_DECLNAME_IS("UnsafeMutableBufferPointer", "Sr");
+        SUCCESS_IF_DECLNAME_IS("String", "SS");
+        SUCCESS_IF_DECLNAME_IS("UInt", "Su");
+      }
+      break;
+    case Node::Kind::Enum:
+      if (isInSwiftModule(node)) {
+        SUCCESS_IF_DECLNAME_IS("Optional", "Sq");
+        SUCCESS_IF_DECLNAME_IS("ImplicitlyUnwrappedOptional", "SQ");
+      }
+      break;
+
+    default:
+      break;
+
+#undef SUCCESS_IF_DECLNAME_IS
+#undef SUCCESS_IF_TEXT_IS
+#undef SUCCESS_IF_IS
+  }
+  return false;
+}
+
+void Remangler::addSubstitution(const SubstitutionEntry &entry) {
+  auto result = Substitutions.insert({entry, Substitutions.size()});
+  assert(result.second);
+  (void) result;
+}
+
+void Remangler::mangleIdentifier(Node *node) {
+  mangleIdentifier(node->getText(), OperatorKind::NotOperator);
+}
+void Remangler::manglePrefixOperator(Node *node) {
+  mangleIdentifier(node->getText(), OperatorKind::Prefix);
+}
+void Remangler::manglePostfixOperator(Node *node) {
+  mangleIdentifier(node->getText(), OperatorKind::Postfix);
+}
+void Remangler::mangleInfixOperator(Node *node) {
+  mangleIdentifier(node->getText(), OperatorKind::Infix);
+}
+void Remangler::mangleIdentifier(StringRef ident, OperatorKind operatorKind) {
+  ::mangleIdentifier(ident, operatorKind, /*usePunycode*/ false, Out);
+}
+
+void Remangler::mangleNumber(Node *node) {
+  mangleIndex(node->getIndex());
+}
+void Remangler::mangleIndex(Node::IndexType value) {
+  if (value == 0) {
+    Out << '_';
+  } else {
+    Out << (value - 1) << '_';
+  }
+}
+
+void Remangler::mangleGlobal(Node *node) {
+  Out << "_T";
+  mangleChildNodes(node);
+}
+
+void Remangler::mangleSuffix(Node *node) {
+  // Just add the suffix back on.
+  Out << node->getText();
+}
+
+void Remangler::mangleGenericSpecialization(Node *node) {
+  Out << "TSg";
+  mangleChildNodes(node); // GenericSpecializationParams
+
+  // Specializations are just prepended to already-mangled names.
+  resetSubstitutions();
+
+  // Start another mangled name.
+  Out << "__T";
+}
+void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) {
+  Out << "TSr";
+  mangleChildNodes(node); // GenericSpecializationParams
+
+  // Specializations are just prepended to already-mangled names.
+  resetSubstitutions();
+
+  // Start another mangled name.
+  Out << "__T";
+}
+
+void Remangler::mangleGenericPartialSpecialization(Node *node) {
+  unreachable("todo");
+}
+
+void Remangler::mangleGenericPartialSpecializationNotReAbstracted(Node *node) {
+  unreachable("todo");
+}
+
+void Remangler::mangleGenericSpecializationParam(Node *node) {
+  // Should be a type followed by a series of protocol conformances.
+  mangleChildNodes(node);
+  Out << '_';
+}
+
+void Remangler::mangleFunctionSignatureSpecialization(Node *node) {
+  Out << "TSf";
+  mangleChildNodes(node); // FunctionSignatureSpecializationParams
+
+  // Specializations are just prepended to already-mangled names.
+  resetSubstitutions();
+
+  // Start another mangled name.
+  Out << "__T";
+}
+
+void Remangler::mangleSpecializationPassID(Node *node) {
+  Out << node->getIndex();
+}
+
+void Remangler::mangleSpecializationIsFragile(Node *node) {
+  Out << "q";
+}
+
+void Remangler::mangleFunctionSignatureSpecializationParam(Node *node) {
+  if (!node->hasChildren()) {
+    Out << "n_";
+    return;
+  }
+
+  // The first child is always a kind that specifies the type of param that we
+  // have.
+  NodePointer firstChild = node->getChild(0);
+  unsigned kindValue = firstChild->getIndex();
+  auto kind = FunctionSigSpecializationParamKind(kindValue);
+
+  switch (kind) {
+  case FunctionSigSpecializationParamKind::ConstantPropFunction:
+    Out << "cpfr";
+    mangleIdentifier(node->getChild(1));
+    Out << '_';
+    return;
+  case FunctionSigSpecializationParamKind::ConstantPropGlobal:
+    Out << "cpg";
+    mangleIdentifier(node->getChild(1));
+    Out << '_';
+    return;
+  case FunctionSigSpecializationParamKind::ConstantPropInteger:
+    Out << "cpi" << node->getChild(1)->getText() << '_';
+    return;
+  case FunctionSigSpecializationParamKind::ConstantPropFloat:
+    Out << "cpfl" << node->getChild(1)->getText() << '_';
+    return;
+  case FunctionSigSpecializationParamKind::ConstantPropString: {
+    Out << "cpse";
+    StringRef encodingStr = node->getChild(1)->getText();
+    if (encodingStr == "u8")
+      Out << '0';
+    else if (encodingStr == "u16")
+      Out << '1';
+    else
+      unreachable("Unknown encoding");
+    Out << 'v';
+    mangleIdentifier(node->getChild(2));
+    Out << '_';
+    return;
+  }
+  case FunctionSigSpecializationParamKind::ClosureProp:
+    Out << "cl";
+    mangleIdentifier(node->getChild(1));
+    for (unsigned i = 2, e = node->getNumChildren(); i != e; ++i) {
+      mangleType(node->getChild(i));
+    }
+    Out << '_';
+    return;
+  case FunctionSigSpecializationParamKind::BoxToValue:
+    Out << "i_";
+    return;
+  case FunctionSigSpecializationParamKind::BoxToStack:
+    Out << "k_";
+    return;
+  default:
+    if (kindValue &
+        unsigned(FunctionSigSpecializationParamKind::Dead))
+      Out << 'd';
+    if (kindValue &
+        unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed))
+      Out << 'g';
+    if (kindValue & unsigned(FunctionSigSpecializationParamKind::SROA))
+      Out << 's';
+    Out << '_';
+    return;
+  }
+}
+
+void Remangler::mangleFunctionSignatureSpecializationParamPayload(Node *node) {
+  // This should never be called since mangling parameter payloads require
+  // knowing what the parameter kind is.
+  unreachable("This should never be called");
+}
+
+void Remangler::mangleFunctionSignatureSpecializationParamKind(Node *node) {
+  // This should never be called since mangling parameter kinds have influence
+  // on the payloads.
+  unreachable("This should never be called");
+}
+
+void Remangler::mangleProtocolConformance(Node *node) {
+  // type, protocol name, context
+  assert(node->getNumChildren() == 3);
+  mangleChildNode(node, 0);
+  mangleProtocolWithoutPrefix(node->begin()[1]);
+  mangleChildNode(node, 2);
+}
+
+void Remangler::mangleObjCAttribute(Node *node) {
+  Out << "To";
+}
+
+void Remangler::mangleNonObjCAttribute(Node *node) {
+  Out << "TO";
+}
+
+void Remangler::mangleDirectMethodReferenceAttribute(Node *node) {
+  Out << "Td";
+}
+
+void Remangler::mangleDynamicAttribute(Node *node) {
+  Out << "TD";
+}
+
+void Remangler::mangleVTableAttribute(Node *node) {
+  Out << "TV";
+}
+
+void Remangler::mangleGenericTypeMetadataPattern(Node *node) {
+  Out << "MP";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleTypeMetadataAccessFunction(Node *node) {
+  Out << "Ma";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleTypeMetadataLazyCache(Node *node) {
+  Out << "ML";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleMetaclass(Node *node) {
+  Out << "Mm";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleNominalTypeDescriptor(Node *node) {
+  Out << "Mn";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleTypeMetadata(Node *node) {
+  Out << "M";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleFullTypeMetadata(Node *node) {
+  Out << "Mf";
+  mangleChildNodes(node); // type
+}
+
+void Remangler::mangleProtocolDescriptor(Node *node) {
+  Out << "Mp";
+  mangleProtocolWithoutPrefix(node->begin()[0]);
+}
+
+void Remangler::manglePartialApplyForwarder(Node *node) {
+  Out << "PA__T";
+  mangleSingleChildNode(node); // global
+}
+
+void Remangler::manglePartialApplyObjCForwarder(Node *node) {
+  Out << "PAo__T";
+  mangleSingleChildNode(node); // global
+}
+
+void Remangler::mangleDirectness(Node *node) {
+  auto getChar = [](Directness d) -> char {
+    switch (d) {
+    case Directness::Direct: return 'd';
+    case Directness::Indirect: return 'i';
+    }
+    unreachable("bad directness kind");
+  };
+  Out << getChar(Directness(node->getIndex()));
+}
+
+void Remangler::mangleValueWitness(Node *node) {
+  const char *Code = nullptr;
+  switch (ValueWitnessKind(node->getIndex())) {
+#define VALUE_WITNESS(MANGLING, NAME) \
+    case ValueWitnessKind::NAME: Code = #MANGLING; break;
+#include "swift/Demangling/ValueWitnessMangling.def"
+  }
+  Out << 'w' << Code;
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleValueWitnessTable(Node *node) {
+  Out << "WV";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleThrowsAnnotation(Node *node) {
+  Out << "z";
+}
+
+void Remangler::mangleFieldOffset(Node *node) {
+  Out << "Wv";
+  mangleChildNodes(node); // directness, entity
+}
+
+void Remangler::mangleProtocolWitnessTable(Node *node) {
+  Out << "WP";
+  mangleSingleChildNode(node); // protocol conformance
+}
+
+void Remangler::mangleGenericProtocolWitnessTable(Node *node) {
+  Out << "WG";
+  mangleSingleChildNode(node); // protocol conformance
+}
+
+void Remangler::mangleGenericProtocolWitnessTableInstantiationFunction(
+                                                                  Node *node) {
+  Out << "WI";
+  mangleSingleChildNode(node); // protocol conformance
+}
+
+void Remangler::mangleProtocolWitnessTableAccessor(Node *node) {
+  Out << "Wa";
+  mangleSingleChildNode(node); // protocol conformance
+}
+
+void Remangler::mangleLazyProtocolWitnessTableAccessor(Node *node) {
+  Out << "Wl";
+  mangleChildNodes(node); // type, protocol conformance
+}
+
+void Remangler::mangleLazyProtocolWitnessTableCacheVariable(Node *node) {
+  Out << "WL";
+  mangleChildNodes(node); // type, protocol conformance
+}
+
+void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
+  Out << "Wt";
+  mangleChildNodes(node); // protocol conformance, identifier
+}
+
+void Remangler::mangleAssociatedTypeWitnessTableAccessor(Node *node) {
+  Out << "WT";
+  assert(node->getNumChildren() == 3);
+  mangleChildNode(node, 0); // protocol conformance
+  mangleChildNode(node, 1); // identifier
+  mangleProtocolWithoutPrefix(node->begin()[2]); // type
+}
+
+void Remangler::mangleReabstractionThunkHelper(Node *node) {
+  Out << "TR";
+  if (node->getNumChildren() == 3) Out << 'G';
+  mangleChildNodes(node); // generic signature?, type, type
+}
+
+void Remangler::mangleReabstractionThunk(Node *node) {
+  Out << "Tr";
+  if (node->getNumChildren() == 3) Out << 'G';
+  mangleChildNodes(node); // generic signature?, type, type
+}
+
+void Remangler::mangleProtocolWitness(Node *node) {
+  Out << "TW";
+  mangleChildNodes(node); // protocol conformance, entity
+}
+
+void Remangler::mangleFunction(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "", ctx);
+}
+
+void Remangler::mangleVariable(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'v', "", ctx);
+}
+
+void Remangler::mangleSubscript(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'i', "", ctx);
+}
+
+void Remangler::mangleInitializer(Node *node, EntityContext &ctx) {
+  mangleSimpleEntity(node, 'I', "i", ctx);
+}
+
+void Remangler::mangleDefaultArgumentInitializer(Node *node,
+                                                 EntityContext &ctx) {
+  mangleNamedEntity(node, 'I', "A", ctx);
+}
+
+void Remangler::mangleDeallocator(Node *node, EntityContext &ctx) {
+  mangleSimpleEntity(node, 'F', "D", ctx);
+}
+
+void Remangler::mangleDestructor(Node *node, EntityContext &ctx) {
+  mangleSimpleEntity(node, 'F', "d", ctx);
+}
+
+void Remangler::mangleAllocator(Node *node, EntityContext &ctx) {
+  mangleTypedEntity(node, 'F', "C", ctx);
+}
+
+void Remangler::mangleConstructor(Node *node, EntityContext &ctx) {
+  mangleTypedEntity(node, 'F', "c", ctx);
+}
+
+void Remangler::mangleIVarInitializer(Node *node, EntityContext &ctx) {
+  mangleSimpleEntity(node, 'F', "e", ctx);
+}
+
+void Remangler::mangleIVarDestroyer(Node *node, EntityContext &ctx) {
+  mangleSimpleEntity(node, 'F', "E", ctx);
+}
+
+void Remangler::mangleGetter(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "g", ctx);
+}
+
+void Remangler::mangleGlobalGetter(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "G", ctx);
+}
+
+void Remangler::mangleSetter(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "s", ctx);
+}
+
+void Remangler::mangleMaterializeForSet(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "m", ctx);
+}
+
+void Remangler::mangleWillSet(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "w", ctx);
+}
+
+void Remangler::mangleDidSet(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "W", ctx);
+}
+
+void Remangler::mangleOwningMutableAddressor(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "aO", ctx);
+}
+
+void Remangler::mangleNativeOwningMutableAddressor(Node *node,
+                                                   EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "ao", ctx);
+}
+
+void Remangler::mangleNativePinningMutableAddressor(Node *node,
+                                                    EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "ap", ctx);
+}
+
+void Remangler::mangleUnsafeMutableAddressor(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "au", ctx);
+}
+
+void Remangler::mangleOwningAddressor(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "lO", ctx);
+}
+
+void Remangler::mangleNativeOwningAddressor(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "lo", ctx);
+}
+
+void Remangler::mangleNativePinningAddressor(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "lp", ctx);
+}
+
+void Remangler::mangleUnsafeAddressor(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "lu", ctx);
+}
+
+void Remangler::mangleExplicitClosure(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "U", ctx); // name is index
+}
+
+void Remangler::mangleImplicitClosure(Node *node, EntityContext &ctx) {
+  mangleNamedAndTypedEntity(node, 'F', "u", ctx); // name is index
+}
+
+void Remangler::mangleStatic(Node *node, EntityContext &ctx) {
+  Out << 'Z';
+  mangleEntityContext(node->getChild(0), ctx);
+}
+
+void Remangler::mangleSimpleEntity(Node *node, char basicKind,
+                                   StringRef entityKind,
+                                   EntityContext &ctx) {
+  assert(node->getNumChildren() == 1);
+  Out << basicKind;
+  mangleEntityContext(node->begin()[0], ctx);
+  Out << entityKind;
+}
+
+void Remangler::mangleNamedEntity(Node *node, char basicKind,
+                                  StringRef entityKind,
+                                  EntityContext &ctx) {
+  assert(node->getNumChildren() == 2);
+  if (basicKind != '\0') Out << basicKind;
+  mangleEntityContext(node->begin()[0], ctx);
+  Out << entityKind;
+  mangleChildNode(node, 1); // decl name / index
+}
+
+void Remangler::mangleTypedEntity(Node *node, char basicKind,
+                                  StringRef entityKind,
+                                  EntityContext &ctx) {
+  assert(node->getNumChildren() == 2);
+  Out << basicKind;
+  mangleEntityContext(node->begin()[0], ctx);
+  Out << entityKind;
+  mangleEntityType(node->begin()[1], ctx);
+}
+
+void Remangler::mangleNamedAndTypedEntity(Node *node, char basicKind,
+                                          StringRef entityKind,
+                                          EntityContext &ctx) {
+  assert(node->getNumChildren() == 3);
+  Out << basicKind;
+  mangleEntityContext(node->begin()[0], ctx);
+  Out << entityKind;
+  mangleChildNode(node, 1); // decl name / index
+  mangleEntityType(node->begin()[2], ctx);
+}
+
+void Remangler::mangleEntityContext(Node *node, EntityContext &ctx) {
+  // Remember that we're mangling a context.
+  EntityContext::ManglingContextRAII raii(ctx);
+
+  switch (node->getKind()) {
+#define NODE(ID)                                \
+  case Node::Kind::ID:
+#define CONTEXT_NODE(ID)
+#include "swift/Demangling/DemangleNodes.def"
+    unreachable("not a context node");
+
+#define NODE(ID)
+#define CONTEXT_NODE(ID)                        \
+  case Node::Kind::ID:                          \
+    return mangle##ID(node, ctx);
+#include "swift/Demangling/DemangleNodes.def"
+  }
+  unreachable("bad node kind");
+}
+
+void Remangler::mangleEntityType(Node *node, EntityContext &ctx) {
+  assert(node->getKind() == Node::Kind::Type);
+  assert(node->getNumChildren() == 1);
+  node = node->begin()[0];
+
+  // Expand certain kinds of type within the entity context.
+  switch (node->getKind()) {
+  case Node::Kind::FunctionType:
+  case Node::Kind::UncurriedFunctionType: {
+    Out << (node->getKind() == Node::Kind::FunctionType ? 'F' : 'f');
+    unsigned inputIndex = node->getNumChildren() - 2;
+    assert(inputIndex <= 1);
+    for (unsigned i = 0; i <= inputIndex; ++i)
+      mangle(node->begin()[i]);
+    auto returnType = node->begin()[inputIndex+1];
+    assert(returnType->getKind() == Node::Kind::ReturnType);
+    assert(returnType->getNumChildren() == 1);
+    mangleEntityType(returnType->begin()[0], ctx);
+    return;
+  }
+  default:
+    mangle(node);
+    return;
+  }
+}
+
+void Remangler::mangleLocalDeclName(Node *node) {
+  Out << 'L';
+  mangleChildNodes(node); // index, identifier
+}
+
+void Remangler::manglePrivateDeclName(Node *node) {
+  Out << 'P';
+  mangleChildNodes(node); // identifier, identifier
+}
+
+void Remangler::mangleTypeMangling(Node *node) {
+  Out << 't';
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleType(Node *node) {
+  mangleSingleChildNode(node);
+}
+
+template <size_t N> 
+static bool stripPrefix(StringRef &string, const char (&data)[N]) {
+  constexpr size_t prefixLength = N - 1;
+  if (!string.startswith(StringRef(data, prefixLength)))
+    return false;
+  string = string.drop_front(prefixLength);
+  return true;
+}
+
+void Remangler::mangleBuiltinTypeName(Node *node) {
+  Out << 'B';
+  StringRef text = node->getText();
+
+  if (text == "Builtin.BridgeObject") {
+    Out << 'b';
+  } else if (text == "Builtin.UnsafeValueBuffer") {
+    Out << 'B';
+  } else if (text == "Builtin.UnknownObject") {
+    Out << 'O';
+  } else if (text == "Builtin.NativeObject") {
+    Out << 'o';
+  } else if (text == "Builtin.RawPointer") {
+    Out << 'p';
+  } else if (text == "Builtin.Word") {
+    Out << 'w';
+  } else if (stripPrefix(text, "Builtin.Int")) {
+    Out << 'i' << text << '_';
+  } else if (stripPrefix(text, "Builtin.Float")) {
+    Out << 'f' << text << '_';
+  } else if (stripPrefix(text, "Builtin.Vec")) {
+    auto split = text.split('x');
+    Out << 'v' << split.first << 'B';
+    if (split.second == "RawPointer") {
+      Out << 'p';
+    } else if (stripPrefix(split.second, "Float")) {
+      Out << 'f' << split.second << '_';
+    } else if (stripPrefix(split.second, "Int")) {
+      Out << 'i' << split.second << '_';
+    } else {
+      unreachable("unexpected builtin vector type");
+    }
+  } else {
+    unreachable("unexpected builtin type");
+  }
+}
+
+void Remangler::mangleTypeAlias(Node *node, EntityContext &ctx) {
+  SubstitutionEntry entry;
+  if (trySubstitution(node, entry)) return;
+  Out << 'a';
+  mangleChildNodes(node); // context, identifier
+  addSubstitution(entry);
+}
+
+void Remangler::mangleFunctionType(Node *node) {
+  Out << 'F';
+  mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleUncurriedFunctionType(Node *node) {
+  Out << 'f';
+  mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleObjCBlock(Node *node) {
+  Out << 'b';
+  mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleCFunctionPointer(Node *node) {
+  Out << 'c';
+  mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleAutoClosureType(Node *node) {
+  Out << 'K';
+  mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleThinFunctionType(Node *node) {
+  Out << "Xf";
+  mangleChildNodes(node); // argument tuple, result type
+}
+
+void Remangler::mangleArgumentTuple(Node *node) {
+  mangleSingleChildNode(node);
+}
+
+void Remangler::mangleReturnType(Node *node) {
+  mangleSingleChildNode(node);
+}
+
+void Remangler::mangleImplFunctionType(Node *node) {
+  Out << "XF";
+  auto i = node->begin(), e = node->end();
+  if (i != e && (*i)->getKind() == Node::Kind::ImplConvention) {
+    StringRef text = (*i)->getText();
+    i++;
+    if (text == "@callee_unowned") {
+      Out << 'd';
+    } else if (text == "@callee_guaranteed") {
+      Out << 'g';
+    } else if (text == "@callee_owned") {
+      Out << 'o';
+    } else {
+      unreachable("bad callee convention");
+    }
+  } else {
+    Out << 't';
+  }
+  for (; i != e &&
+         (*i)->getKind() == Node::Kind::ImplFunctionAttribute; ++i) {
+    mangle(*i); // impl function attribute
+  }
+  if (i != e &&
+      ((*i)->getKind() == Node::Kind::DependentGenericSignature ||
+       (*i)->getKind() == Node::Kind::DependentPseudogenericSignature)) {
+    Out << ((*i)->getKind() == Node::Kind::DependentGenericSignature
+              ? 'G' : 'g');
+    mangleDependentGenericSignature((*i));
+    i++;
+  }
+  Out << '_';
+  for (; i != e && (*i)->getKind() == Node::Kind::ImplParameter; ++i) {
+    mangleImplParameter(*i);
+  }
+  Out << '_';
+  mangleNodes(i, e); // impl results
+  Out << '_';
+}
+
+void Remangler::mangleImplFunctionAttribute(Node *node) {
+  StringRef text = node->getText();
+  if (text == "@convention(block)") {
+    Out << "Cb";
+  } else if (text == "@convention(c)") {
+    Out << "Cc";
+  } else if (text == "@convention(method)") {
+    Out << "Cm";
+  } else if (text == "@convention(objc_method)") {
+    Out << "CO";
+  } else if (text == "@convention(witness_method)") {
+    Out << "Cw";
+  } else {
+    unreachable("bad impl-function-attribute");
+  }
+}
+
+void Remangler::mangleImplParameter(Node *node) {
+  assert(node->getNumChildren() == 2);
+  mangleChildNodes(node); // impl convention, type
+}
+
+void Remangler::mangleImplErrorResult(Node *node) {
+  assert(node->getNumChildren() == 2);
+  Out << 'z';
+  mangleChildNodes(node); // impl convention, type
+}
+
+void Remangler::mangleImplResult(Node *node) {
+  assert(node->getNumChildren() == 2);
+  mangleChildNodes(node); // impl convention, type
+}
+
+void Remangler::mangleImplConvention(Node *node) {
+  assert(node->getKind() == Node::Kind::ImplConvention);
+  StringRef text = node->getText();
+  if (text == "@autoreleased") {
+    Out << 'a';
+  } else if (text == "@unowned") {
+    Out << 'd';
+  } else if (text == "@unowned_inner_pointer") {
+    Out << 'D'; // only in results
+  } else if (text == "@guaranteed") {
+    Out << 'g';
+  } else if (text == "@deallocating") {
+    Out << 'e';
+  } else if (text == "@in") {
+    Out << 'i'; // only in parameters
+  } else if (text == "@out") {
+    Out << 'i'; // only in results
+  } else if (text == "@inout") {
+    Out << 'l';
+  } else if (text == "@owned") {
+    Out << 'o';
+  } else {
+    unreachable("invalid impl convention");
+  }
+}
+
+void Remangler::mangleDynamicSelf(Node *node) {
+  Out << 'D';
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleErrorType(Node *node) {
+  Out << "ERR";
+}
+
+void Remangler::mangleSILBoxType(Node *node) {
+  Out << 'X' << 'b';
+  mangleSingleChildNode(node);
+}
+
+void Remangler::mangleMetatype(Node *node) {
+  if (node->getNumChildren() == 1) {
+    Out << 'M';
+    mangleSingleChildNode(node); // type
+  } else {
+    assert(node->getNumChildren() == 2);
+    Out << "XM";
+    mangleChildNodes(node); // metatype representation, type
+  }
+}
+
+void Remangler::mangleExistentialMetatype(Node *node) {
+  if (node->getNumChildren() == 1) {
+    Out << "PM";
+    mangleSingleChildNode(node); // type
+  } else {
+    assert(node->getNumChildren() == 2);
+    Out << "XPM";
+    mangleChildNodes(node); // metatype representation, type
+  }
+}
+
+void Remangler::mangleMetatypeRepresentation(Node *node) {
+  StringRef text = node->getText();
+  if (text == "@thin") {
+    Out << 't';
+  } else if (text == "@thick") {
+    Out << 'T';
+  } else if (text == "@objc_metatype") {
+    Out << 'o';
+  } else {
+    unreachable("bad metatype representation");
+  }
+}
+
+void Remangler::mangleProtocolList(Node *node) {
+  // In its usual use as a type, this gets a prefix 'P'.
+  Out << 'P';
+  mangleProtocolListWithoutPrefix(node);
+}
+
+void Remangler::mangleProtocolListWithoutPrefix(Node *node,
+                                                Node *additionalProto) {
+  assert(node->getKind() == Node::Kind::ProtocolList);
+  assert(node->getNumChildren() == 1);
+  auto typeList = node->begin()[0];
+  assert(typeList->getKind() == Node::Kind::TypeList);
+  for (auto &child : *typeList) {
+    mangleProtocolWithoutPrefix(child);
+  }
+  if (additionalProto) {
+    mangleProtocolWithoutPrefix(additionalProto);
+  }
+  Out << '_';
+}
+
+void Remangler::mangleUnowned(Node *node) {
+  Out << "Xo";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleUnmanaged(Node *node) {
+  Out << "Xu";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleWeak(Node *node) {
+  Out << "Xw";
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleInOut(Node *node) {
+  Out << 'R';
+  mangleSingleChildNode(node); // type
+}
+
+void Remangler::mangleTuple(Node *node) {
+  size_t NumElems = node->getNumChildren();
+  if (NumElems > 0 &&
+      node->getChild(NumElems - 1)->getFirstChild()->getKind() ==
+      Node::Kind::VariadicMarker) {
+    Out << 't';
+  } else {
+    Out << 'T';
+  }
+  mangleChildNodes(node); // tuple elements
+  Out << '_';
+}
+
+void Remangler::mangleTupleElement(Node *node) {
+  mangleChildNodes(node); // tuple element name?, type
+}
+
+void Remangler::mangleTupleElementName(Node *node) {
+  mangleIdentifier(node->getText(), OperatorKind::NotOperator);
+}
+
+void Remangler::mangleDependentGenericType(Node *node) {
+  Out << 'u';
+  mangleChildNodes(node); // generic signature, type
+}
+
+void Remangler::mangleDependentPseudogenericSignature(Node *node) {
+  mangleDependentGenericSignature(node);
+}
+
+void Remangler::mangleDependentGenericSignature(Node *node) {
+  auto i = node->begin(), e = node->end();
+  
+  // If there's only one generic param, mangle nothing.
+  if (node->getNumChildren() >= 1
+      && node->getChild(0)->getKind() == Node::Kind::DependentGenericParamCount
+      && node->getChild(0)->getIndex() == 1
+      && (node->getNumChildren() == 1
+          || node->getChild(1)->getKind() != Node::Kind::DependentGenericParamCount))
+  {
+    ++i;
+    goto mangle_requirements;
+  }
+  
+  // Remangle generic params.
+  for (; i != e &&
+         (*i)->getKind() == Node::Kind::DependentGenericParamCount; ++i) {
+    auto count = *i;
+    if (count->getIndex() > 0)
+      mangleIndex(count->getIndex() - 1);
+    else
+      Out << 'z';
+  }
+  
+mangle_requirements:
+  if (i == e) { // no generic requirements
+    Out << 'r';
+    return;
+  }
+  
+  Out << 'R';
+  mangleNodes(i, e); // generic requirements
+  Out << 'r';
+}
+
+void Remangler::mangleDependentGenericParamCount(Node *node) {
+  unreachable("handled inline in DependentGenericSignature");
+}
+
+void Remangler::mangleDependentGenericConformanceRequirement(Node *node) {
+  mangleConstrainedType(node->getChild(0));
+  // If the constraint represents a protocol, use the shorter mangling.
+  if (node->getNumChildren() == 2
+      && node->getChild(1)->getKind() == Node::Kind::Type
+      && node->getChild(1)->getNumChildren() == 1
+      && node->getChild(1)->getChild(0)->getKind() == Node::Kind::Protocol) {
+    mangleProtocolWithoutPrefix(node->getChild(1)->getChild(0));
+    return;
+  }
+
+  mangle(node->getChild(1));
+}
+
+void Remangler::mangleDependentGenericSameTypeRequirement(Node *node) {
+  mangleConstrainedType(node->getChild(0));
+  Out << 'z';
+  mangle(node->getChild(1));
+}
+
+void Remangler::mangleDependentGenericLayoutRequirement(Node *node) {
+  mangleConstrainedType(node->getChild(0));
+  Out << 'l';
+  auto id =  node->getChild(1)->getText();
+  auto size = -1;
+  if (node->getNumChildren() > 2) {
+    size = node->getChild(2)->getIndex();
+  }
+  int alignment = -1;
+  if (node->getNumChildren() > 3) {
+    alignment = node->getChild(3)->getIndex();
+  }
+  Out << id;
+  if (size >= 0)
+    Out << size;
+  if (alignment >= 0) {
+    Out << "_" << alignment;
+  }
+}
+
+void Remangler::mangleConstrainedType(Node *node) {
+  if (node->getFirstChild()->getKind()
+        == Node::Kind::DependentGenericParamType) {
+    // Can be mangled without an introducer.
+    mangleDependentGenericParamIndex(node->getFirstChild());
+  } else {
+    mangle(node);
+  }
+}
+
+void Remangler::mangleAssociatedType(Node *node) {
+  if (node->hasChildren()) {
+    assert(node->getNumChildren() == 1);
+    mangleProtocolListWithoutPrefix(*node->begin());
+  } else {
+    Out << '_';
+  }
+}
+
+void Remangler::mangleQualifiedArchetype(Node *node) {
+  Out << "Qq";
+  mangleChildNodes(node); // index, declcontext
+}
+
+void Remangler::mangleDeclContext(Node *node) {
+  mangleSingleChildNode(node);
+}
+
+void Remangler::mangleExtension(Node *node, EntityContext &ctx) {
+  assert(node->getNumChildren() == 2 || node->getNumChildren() == 3);
+  if (node->getNumChildren() == 3) {
+    Out << 'e';
+  } else {
+    Out << 'E';
+  }
+  mangleEntityContext(node->begin()[0], ctx); // module
+  if (node->getNumChildren() == 3) {
+    mangleDependentGenericSignature(node->begin()[2]); // generic sig
+  }
+  mangleEntityContext(node->begin()[1], ctx); // context
+}
+
+void Remangler::mangleModule(Node *node, EntityContext &ctx) {
+  SubstitutionEntry entry;
+  if (trySubstitution(node, entry)) return;
+
+  // Module types get an M prefix, but module contexts don't.
+  if (!ctx.isAsContext()) Out << 'M';
+  mangleIdentifier(node->getText(), OperatorKind::NotOperator);
+  addSubstitution(entry);
+}
+
+void Remangler::mangleAssociatedTypeRef(Node *node) {
+  SubstitutionEntry entry;
+  if (trySubstitution(node, entry)) return;
+  Out << "Q";
+  mangleChildNodes(node); // type, identifier
+  addSubstitution(entry);
+}
+
+void Remangler::mangleDependentMemberType(Node *node) {
+  std::vector<Node *> members;
+  Node *base = node;
+  do {
+    members.push_back(base);
+    base = base->getFirstChild()->getFirstChild();
+  } while (base->getKind() == Node::Kind::DependentMemberType);
+
+  assert(base->getKind() == Node::Kind::DependentGenericParamType
+         && "dependent members not based on a generic param are non-canonical"
+            " and shouldn't need remangling");
+  assert(members.size() >= 1);
+  if (members.size() == 1) {
+    Out << 'w';
+    mangleDependentGenericParamIndex(base);
+    mangle(members[0]->getChild(1));
+  } else {
+    Out << 'W';
+    mangleDependentGenericParamIndex(base);
+
+    for (unsigned i = 1, n = members.size(); i <= n; ++i) {
+      Node *member = members[n - i];
+      mangle(member->getChild(1));
+    }
+    Out << '_';
+  }
+}
+
+void Remangler::mangleDependentAssociatedTypeRef(Node *node) {
+  SubstitutionEntry entry;
+  if (trySubstitution(node, entry)) return;
+
+  if (node->getNumChildren() > 0) {
+    Out << 'P';
+    mangleProtocolWithoutPrefix(node->getFirstChild());
+  }
+  mangleIdentifier(node);
+
+  addSubstitution(entry);
+}
+
+void Remangler::mangleDependentGenericParamIndex(Node *node) {
+  auto depth = node->getChild(0)->getIndex();
+  auto index = node->getChild(1)->getIndex();
+
+  if (depth != 0) {
+    Out << 'd';
+    mangleIndex(depth - 1);
+    mangleIndex(index);
+    return;
+  }
+  if (index != 0) {
+    mangleIndex(index - 1);
+    return;
+  }
+
+  // depth == index == 0
+  Out << 'x';
+}
+
+void Remangler::mangleDependentGenericParamType(Node *node) {
+  if (node->getChild(0)->getIndex() == 0
+      && node->getChild(1)->getIndex() == 0) {
+    Out << 'x';
+    return;
+  }
+
+  Out << 'q';
+  mangleDependentGenericParamIndex(node);
+}
+
+void Remangler::mangleIndex(Node *node) {
+  mangleIndex(node->getIndex());
+}
+
+void Remangler::mangleProtocol(Node *node, EntityContext &ctx) {
+  mangleNominalType(node, 'P', ctx);
+}
+
+void Remangler::mangleProtocolWithoutPrefix(Node *node) {
+  if (node->getKind() == Node::Kind::Type) {
+    assert(node->getNumChildren() == 1);
+    node = node->begin()[0];
+  }
+
+  assert(node->getKind() == Node::Kind::Protocol);
+  EntityContext ctx;
+  mangleNominalType(node, '\0', ctx);
+}
+
+void Remangler::mangleGenericArgs(Node *node, EntityContext &ctx) {
+  switch (node->getKind()) {
+  case Node::Kind::Structure:
+  case Node::Kind::Enum:
+  case Node::Kind::Class: {
+    NodePointer parentOrModule = node->getChild(0);
+    mangleGenericArgs(parentOrModule, ctx);
+
+    // No generic arguments at this level
+    Out << '_';
+    break;
+  }
+
+  case Node::Kind::BoundGenericStructure:
+  case Node::Kind::BoundGenericEnum:
+  case Node::Kind::BoundGenericClass: {
+    NodePointer unboundType = node->getChild(0);
+    assert(unboundType->getKind() == Node::Kind::Type);
+    NodePointer nominalType = unboundType->getChild(0);
+    NodePointer parentOrModule = nominalType->getChild(0);
+    mangleGenericArgs(parentOrModule, ctx);
+
+    mangleTypeList(node->getChild(1));
+    break;
+  }
+
+  default:
+    break;
+  }
+}
+
+void Remangler::mangleAnyNominalType(Node *node, EntityContext &ctx) {
+  if (isSpecialized(node)) {
+    Out << 'G';
+
+    NodePointer unboundType = getUnspecialized(node, Factory);
+
+    mangleAnyNominalType(unboundType, ctx);
+    mangleGenericArgs(node, ctx);
+    return;
+  }
+
+  switch (node->getKind()) {
+  case Node::Kind::Structure:
+    mangleNominalType(node, 'V', ctx);
+    break;
+  case Node::Kind::Enum:
+    mangleNominalType(node, 'O', ctx);
+    break;
+  case Node::Kind::Class:
+    mangleNominalType(node, 'C', ctx);
+    break;
+  default:
+    unreachable("bad nominal type kind");
+  }
+}
+
+void Remangler::mangleStructure(Node *node, EntityContext &ctx) {
+  mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleEnum(Node *node, EntityContext &ctx) {
+  mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleClass(Node *node, EntityContext &ctx) {
+  mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleNominalType(Node *node, char kind, EntityContext &ctx) {
+  SubstitutionEntry entry;
+  if (trySubstitution(node, entry)) return;
+  mangleNamedEntity(node, kind, "", ctx);
+  addSubstitution(entry);
+}
+
+void Remangler::mangleBoundGenericClass(Node *node) {
+  EntityContext ctx;
+  mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleBoundGenericStructure(Node *node) {
+  EntityContext ctx;
+  mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleBoundGenericEnum(Node *node) {
+  EntityContext ctx;
+  mangleAnyNominalType(node, ctx);
+}
+
+void Remangler::mangleTypeList(Node *node) {
+  mangleChildNodes(node); // all types
+  Out << '_';
+}
+
+void Remangler::mangleReflectionMetadataBuiltinDescriptor(Node *node) {
+  Out << "MRb";
+}
+
+void Remangler::mangleReflectionMetadataFieldDescriptor(Node *node) {
+  Out << "MRf";
+}
+
+void Remangler::mangleReflectionMetadataAssocTypeDescriptor(Node *node) {
+  Out << "MRa";
+}
+
+void Remangler::mangleReflectionMetadataSuperclassDescriptor(Node *node) {
+  Out << "MRc";
+}
+
+void Remangler::mangleGenericTypeParamDecl(Node *node) {
+  unreachable("todo");
+}
+
+void Remangler::mangleCurryThunk(Node *node, EntityContext &ctx) {
+  Out << "<curry-thunk>";
+}
+
+void Remangler::mangleEmptyList(Node *node) {
+  Out << "<empty>";
+}
+
+void Remangler::mangleFirstElementMarker(Node *node) {
+  Out << "<first>";
+}
+
+void Remangler::mangleVariadicMarker(Node *node) {
+  // Handled in mangleTuple
+}
+
+void Remangler::mangleOutlinedCopy(Node *node) {
+  Out << "Wy";
+  mangleChildNodes(node);
+}
+
+void Remangler::mangleOutlinedConsume(Node *node) {
+  Out << "We";
+  mangleChildNodes(node);
+}
+
+void Remangler::mangleOutlinedRetain(Node *node) {
+  Out << "Wr";
+  mangleSingleChildNode(node);
+}
+
+void Remangler::mangleOutlinedRelease(Node *node) {
+  Out << "Ws";
+  mangleSingleChildNode(node);
+}
+
+void Remangler::mangleKeyPathGetterThunkHelper(Node *node) {
+  Out << "TK";
+  mangleChildNodes(node);
+}
+
+void Remangler::mangleKeyPathSetterThunkHelper(Node *node) {
+  Out << "Tk";
+  mangleChildNodes(node);
+}
+
+void Remangler::mangleProtocolListWithClass(Node *node) {
+  Out << "Xc";
+  mangleChildNode(node, 1);
+  mangleProtocolListWithoutPrefix(node->getChild(0));
+}
+
+void Remangler::mangleProtocolListWithAnyObject(Node *node) {
+  Node *P = Factory.createNode(Node::Kind::Protocol);
+  P->addChild(Factory.createNode(Node::Kind::Module, "Swift"), Factory);
+  P->addChild(Factory.createNode(Node::Kind::Identifier, "AnyObject"), Factory);
+  Out << "P";
+  mangleProtocolListWithoutPrefix(node->getChild(0), /*additionalProto*/ P);
+}
+
+void Remangler::mangleVTableThunk(Node *node) {
+  Out << "TV";
+  mangleChildNodes(node);
+}
+
+void Remangler::mangleSILBoxTypeWithLayout(Node *node) {
+  assert(node->getKind() == Node::Kind::SILBoxTypeWithLayout);
+  assert(node->getNumChildren() == 1 || node->getNumChildren() == 3);
+  Out << "XB";
+  auto layout = node->getChild(0);
+  assert(layout->getKind() == Node::Kind::SILBoxLayout);
+  NodePointer genericArgs = nullptr;
+  if (node->getNumChildren() == 3) {
+    NodePointer signature = node->getChild(1);
+    assert(signature->getKind() == Node::Kind::DependentGenericSignature);
+    genericArgs = node->getChild(2);
+    assert(genericArgs->getKind() == Node::Kind::TypeList);
+    
+    Out << 'G';
+    mangleDependentGenericSignature(signature);
+  }
+  mangleSILBoxLayout(layout);
+  if (genericArgs) {
+    for (unsigned i = 0; i < genericArgs->getNumChildren(); ++i) {
+      auto type = genericArgs->getChild(i);
+      assert(genericArgs->getKind() == Node::Kind::Type);
+      mangleType(type);
+    }
+    Out << '_';  
+  }
+}
+
+void Remangler::mangleSILBoxLayout(Node *node) {
+  assert(node->getKind() == Node::Kind::SILBoxLayout);
+  for (unsigned i = 0; i < node->getNumChildren(); ++i) {
+    assert(node->getKind() == Node::Kind::SILBoxImmutableField
+           || node->getKind() == Node::Kind::SILBoxMutableField);
+    mangle(node->getChild(i));
+    
+  }
+  Out << '_';
+}
+
+void Remangler::mangleSILBoxMutableField(Node *node) {
+  Out << 'm';
+  assert(node->getNumChildren() == 1
+         && node->getChild(0)->getKind() == Node::Kind::Type);
+  mangleType(node->getChild(0));
+}
+
+void Remangler::mangleSILBoxImmutableField(Node *node) {
+  Out << 'i';
+  assert(node->getNumChildren() == 1
+         && node->getChild(0)->getKind() == Node::Kind::Type);
+  mangleType(node->getChild(0));
+}
+
+/// The top-level interface to the remangler.
+std::string Demangle::mangleNodeOld(const NodePointer &node) {
+  if (!node) return "";
+
+  DemanglerPrinter printer;
+  Remangler(printer).mangle(node);
+  return std::move(printer).str();
+}
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index d47d801..d5a2adb 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -227,10 +227,15 @@
   OS << "</Kind>\n";
 
   OS << "<Content>" << Content << "</Content>\n";
-  if (Ty) {
+
+  if (auto Ty = ExitInfo.getPointer()) {
     OS << "<Type>";
     Ty->print(OS);
-    OS << "</Type>\n";
+    OS << "</Type>";
+    if (ExitInfo.getInt()) {
+      OS << "<Exit>true</Exit>";
+    }
+    OS << "\n";
   }
 
   if (RangeContext) {
@@ -382,7 +387,10 @@
   std::vector<ASTNode> ContainedASTNodes;
 
   /// Collect the type that an ASTNode should be evaluated to.
-  Type resolveNodeType(ASTNode N, RangeKind Kind) {
+  ReturnTyAndWhetherExit resolveNodeType(ASTNode N, RangeKind Kind) {
+    auto *VoidTy = Ctx.getVoidDecl()->getDeclaredInterfaceType().getPointer();
+    if (N.isNull())
+      return {VoidTy, false};
     switch(Kind) {
     case RangeKind::Invalid:
     case RangeKind::SingleDecl:
@@ -390,14 +398,18 @@
 
     // For a single expression, its type is apparent.
     case RangeKind::SingleExpression:
-      return N.get<Expr*>()->getType();
+      return {N.get<Expr*>()->getType().getPointer(), false};
 
     // For statements, we either resolve to the returning type or Void.
     case RangeKind::SingleStatement:
     case RangeKind::MultiStatement: {
       if (N.is<Stmt*>()) {
         if (auto RS = dyn_cast<ReturnStmt>(N.get<Stmt*>())) {
-          return resolveNodeType(RS->getResult(), RangeKind::SingleExpression);
+          return {
+            resolveNodeType(RS->hasResult() ? RS->getResult() : nullptr,
+              RangeKind::SingleExpression).getPointer(),
+            true
+          };
         }
 
         // Unbox the brace statement to find its type.
@@ -407,9 +419,25 @@
                                    RangeKind::SingleStatement);
           }
         }
+
+        // Unbox the if statement to find its type.
+        if (auto *IS = dyn_cast<IfStmt>(N.get<Stmt*>())) {
+          auto ThenTy = resolveNodeType(IS->getThenStmt(),
+                                        RangeKind::SingleStatement);
+          auto ElseTy = resolveNodeType(IS->getElseStmt(),
+                                        RangeKind::SingleStatement);
+
+          // If two branches agree on the return type, return that type.
+          if (ThenTy.getPointer()->isEqual(ElseTy.getPointer()) &&
+              ThenTy.getInt() == ElseTy.getInt())
+            return ThenTy;
+
+          // Otherwise, return the error type.
+          return {Ctx.TheErrorType.getPointer(), false};
+        }
       }
       // For other statements, the type should be void.
-      return Ctx.getVoidDecl()->getDeclaredInterfaceType();
+      return {VoidTy, false};
     }
     }
   }
@@ -440,7 +468,7 @@
                                llvm::makeArrayRef(ReferencedDecls));
     else {
       assert(Node.is<Decl*>());
-      return ResolvedRangeInfo(RangeKind::SingleDecl, Type(), Content,
+      return ResolvedRangeInfo(RangeKind::SingleDecl, {nullptr, false}, Content,
                                getImmediateContext(), SingleEntry,
                                UnhandledError, Kind,
                                llvm::makeArrayRef(ContainedASTNodes),
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 1a8f4e2..0c849fd 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -3266,6 +3266,12 @@
 }
 
 Type TypeChecker::getSuperClassOf(Type type) {
+  if (auto *parenTy = dyn_cast<ParenType>(type.getPointer())) {
+    auto superclassTy = getSuperClassOf(parenTy->getUnderlyingType());
+    if (!superclassTy)
+      return Type();
+    return ParenType::get(Context, superclassTy);
+  }
   return type->getSuperclass();
 }
 
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 940b9d1..d2c8caf 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -165,13 +165,20 @@
     getContext().Diags.diagnose(SourceLoc(), diag::serialization_fatal, Name);
 
     if (!CompatibilityVersion.empty()) {
-      SmallString<16> buffer;
-      llvm::raw_svector_ostream out(buffer);
-      out << getContext().LangOpts.EffectiveLanguageVersion;
-      if (out.str() != CompatibilityVersion) {
+      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,
-            out.str(), Name, CompatibilityVersion);
+            effectiveVersionBuffer, Name, compatVersionBuffer);
       }
     }
   }
@@ -4464,20 +4471,69 @@
 
   ArrayRef<uint64_t>::iterator rawIDIter = rawIDs.begin();
 
+  // 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--) {
-    auto req = cast<ValueDecl>(getDecl(*rawIDIter++));
-    auto witness = cast_or_null<ValueDecl>(getDecl(*rawIDIter++));
-    assert(witness ||
+    ValueDecl *req;
+    
+    auto trySetWitness = [&](Witness w) {
+      if (req)
+        conformance->setWitness(req, w);
+    };
+    
+    auto deserializedReq = getDeclChecked(*rawIDIter++);
+    if (deserializedReq) {
+      req = cast<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<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) {
-      conformance->setWitness(req, Witness());
+    if (!witness && !isOpaque) {
+      trySetWitness(Witness());
       continue;
     }
 
     // Generic signature and environment.
     GenericSignature *syntheticSig = nullptr;
     GenericEnvironment *syntheticEnv = nullptr;
+    
+    auto trySetOpaqueWitness = [&]{
+      if (!req)
+        return;
+      
+      // We shouldn't yet need to worry about generic requirements, since
+      // an imported ObjC method should never be generic.
+      assert(syntheticSig == nullptr && syntheticEnv == nullptr &&
+             "opaque witness shouldn't be generic yet. when this is "
+             "possible, it should use forwarding substitutions");
+      conformance->setWitness(req, Witness::forOpaque(req));
+    };
 
     // Requirement -> synthetic map.
     SmallVector<Substitution, 4> reqToSyntheticSubs;
@@ -4518,16 +4574,22 @@
       }
     }
 
+    // Handle opaque witnesses that couldn't be deserialized.
+    if (isOpaque) {
+      trySetOpaqueWitness();
+      continue;
+    }
+
     // Handle simple witnesses.
     if (witnessSubstitutions.empty() && !syntheticSig && !syntheticEnv &&
         reqToSyntheticSubs.empty()) {
-      conformance->setWitness(req, Witness(witness));
+      trySetWitness(Witness(witness));
       continue;
     }
 
     // Set the witness.
-    conformance->setWitness(req, Witness(witness, witnessSubstitutions,
-                                         syntheticEnv, reqToSyntheticSubs));
+    trySetWitness(Witness(witness, witnessSubstitutions,
+                          syntheticEnv, reqToSyntheticSubs));
   }
   assert(rawIDIter <= rawIDs.end() && "read too much");
 
@@ -4558,6 +4620,20 @@
     conformance->setTypeWitness(typeWitness.first, typeWitness.second.first,
                                 typeWitness.second.second);
   }
+  
+  // 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));
+    }
+  }
 }
 
 GenericEnvironment *ModuleFile::loadGenericEnvironment(const DeclContext *decl,
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index 02bc030..d5cf782 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -200,7 +200,9 @@
       default:
         // Add new cases here, in descending order.
       case 4:
-        result.compatibilityVersion = blobData.substr(scratch[2]+1, scratch[3]);
+        result.compatibilityVersion =
+          version::Version(blobData.substr(scratch[2]+1, scratch[3]),
+                           SourceLoc(), nullptr);
         LLVM_FALLTHROUGH;
       case 3:
         result.shortVersion = blobData.slice(0, scratch[2]);
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
index 3bb4871..f4dea7b 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
@@ -257,8 +257,7 @@
   ${TRACE},
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
   sameValue: (${Element}, ${Element}) -> Bool
-) where C.Iterator.Element == ${Element},
-  C.SubSequence : Collection {
+) where C.Iterator.Element == ${Element} {
 
   checkForwardCollection(expected, collection, message(),
     stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
@@ -278,7 +277,6 @@
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all
 ) where
   C.Iterator.Element == ${Element},
-  C.SubSequence : ${TraversalCollection},
   ${Element} : Equatable {
 
   check${Traversal}Collection(
@@ -298,8 +296,7 @@
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
   sameValue: (${Element}, ${Element}) -> Bool
 ) where
-  C.Iterator.Element == ${Element},
-  C.SubSequence : ${TraversalCollection} {
+  C.Iterator.Element == ${Element} {
 
   checkOneLevelOf${Traversal}Collection(expected, collection, ${trace},
     resiliencyChecks: resiliencyChecks, sameValue: sameValue)
@@ -504,8 +501,7 @@
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
   sameValue: (${Element}, ${Element}) -> Bool
 ) where
-  S.Iterator.Element == ${Element},
-  S.SubSequence : ${TraversalCollection} {
+  S.Iterator.Element == ${Element} {
 
   let expectedArray = Array(expected)
 
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
index 8ce2040..a550216 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
@@ -471,16 +471,9 @@
 %{
   from gyb_stdlib_support import collectionForTraversal
   def testConstraints(protocol):
-    if protocol == 'Collection':
-      subseq_as_collection = 'CollectionWithEquatableElement.SubSequence : Collection,'
-    else:
-      subseq_as_collection=''
     return '''
     C : %(protocol)s,
     CollectionWithEquatableElement : %(protocol)s,
-    %(subseq_as_collection)s
-    C.SubSequence : %(protocol)s,
-    C.Indices : %(protocol)s,
     CollectionWithEquatableElement.Iterator.Element : Equatable
   ''' % locals()
 
@@ -494,6 +487,7 @@
       [CollectionWithEquatableElement.Iterator.Element]
     ) -> CollectionWithEquatableElement,
 
+
     wrapValueIntoEquatable: @escaping (
       MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
 
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
index c20f755..fb13a1a 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
@@ -121,8 +121,6 @@
     isFixedLengthCollection: Bool,
     collectionIsBidirectional: Bool = false
   ) where
-    C.SubSequence : MutableCollection,
-    C.Indices : Collection,
     CollectionWithEquatableElement.Iterator.Element : Equatable,
     CollectionWithComparableElement.Iterator.Element : Comparable {
 
@@ -783,8 +781,6 @@
     withUnsafeMutableBufferPointerIsSupported: Bool,
     isFixedLengthCollection: Bool
   ) where
-    C.SubSequence : BidirectionalCollection & MutableCollection,
-    C.Indices : BidirectionalCollection,
     CollectionWithEquatableElement.Iterator.Element : Equatable,
     CollectionWithComparableElement.Iterator.Element : Comparable {
 
@@ -929,8 +925,6 @@
     withUnsafeMutableBufferPointerIsSupported: Bool,
     isFixedLengthCollection: Bool
   ) where
-    C.SubSequence : RandomAccessCollection & MutableCollection,
-    C.Indices : RandomAccessCollection,
     CollectionWithEquatableElement.Iterator.Element : Equatable,
     CollectionWithComparableElement.Iterator.Element : Comparable {
 
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift
index 14363c6..245f486 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift
+++ b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift
@@ -462,10 +462,7 @@
     outOfBoundsIndexOffset: Int = 1,
     collectionIsBidirectional: Bool = false
   ) where
-    C.SubSequence : Collection,
-    C.Indices : Collection,
-    CollectionWithEquatableElement.Iterator.Element : Equatable,
-    CollectionWithEquatableElement.SubSequence : Collection {
+    CollectionWithEquatableElement.Iterator.Element : Equatable {
 
     var testNamePrefix = testNamePrefix
 
@@ -1180,8 +1177,6 @@
     resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
     outOfBoundsIndexOffset: Int = 1
   ) where
-    C.SubSequence : BidirectionalCollection & RangeReplaceableCollection,
-    C.Indices : BidirectionalCollection,
     CollectionWithEquatableElement.Iterator.Element : Equatable {
 
     var testNamePrefix = testNamePrefix
@@ -1302,8 +1297,6 @@
     resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
     outOfBoundsIndexOffset: Int = 1
   ) where
-    C.SubSequence : RandomAccessCollection & RangeReplaceableCollection,
-    C.Indices : RandomAccessCollection,
     CollectionWithEquatableElement.Iterator.Element : Equatable {
 
     var testNamePrefix = testNamePrefix
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift
index fb10e30..28a802e 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift
+++ b/stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift
@@ -33,7 +33,6 @@
     collectionIsBidirectional: Bool = false
   ) where
     C.SubSequence == C,
-    C.Indices : Collection,
     CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
     CollectionWithEquatableElement.Iterator.Element : Equatable {
 
@@ -165,7 +164,6 @@
     outOfBoundsIndexOffset: Int = 1
   ) where
     C.SubSequence == C,
-    C.Indices : BidirectionalCollection,
     CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
     CollectionWithEquatableElement.Iterator.Element : Equatable {
 
@@ -310,7 +308,6 @@
     outOfBoundsIndexOffset: Int = 1
   ) where
     C.SubSequence == C,
-    C.Indices : RandomAccessCollection,
     CollectionWithEquatableElement.SubSequence == CollectionWithEquatableElement,
     CollectionWithEquatableElement.Iterator.Element : Equatable {
 
diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
index 2d61bee..02b1df0 100644
--- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
+++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
@@ -376,14 +376,7 @@
 % for Mutable in ['', 'Mutable']:
 public func expect${Mutable}CollectionType<X : ${Mutable}Collection>(
   _ x: X.Type
-) where
-  // FIXME(ABI)#2 (Associated Types with where clauses): there should be no constraints in
-  // the 'where' clause, all of these should be required by the protocol.
-%   if Mutable == '':
-  X.SubSequence : Collection,
-%   end
-  // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#3 (Recursive Protocol Constraints): can't have this constraint now.
-  X.Indices : Collection {}
+) { }
 % end
 
 /// A slice is a `Collection` that when sliced returns an instance of
@@ -421,12 +414,7 @@
   indexType: X.Index.Type,
   indexDistanceType: X.IndexDistance.Type,
   indicesType: X.Indices.Type
-) where
-  // FIXME(ABI)#6 (Associated Types with where clauses): there should be no constraints in
-  // the 'where' clause, all of these should be required by the protocol.
-  X.SubSequence : Collection,
-  // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#7 (Recursive Protocol Constraints): can't have this constraint now.
-  X.Indices : Collection {}
+) { }
 
 /// Check that all associated types of a `BidirectionalCollection` are what we
 /// expect them to be.
@@ -437,12 +425,7 @@
   indexType: X.Index.Type,
   indexDistanceType: X.IndexDistance.Type,
   indicesType: X.Indices.Type
-) where
-  // FIXME(ABI)#8 (Associated Types with where clauses): there should be no constraints in
-  // the 'where' clause, all of these should be required by the protocol.
-  X.SubSequence : BidirectionalCollection,
-  // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#9 (Recursive Protocol Constraints): can't have this constraint now.
-  X.Indices : BidirectionalCollection {}
+) { }
 
 /// Check that all associated types of a `RandomAccessCollection` are what we
 /// expect them to be.
@@ -453,12 +436,7 @@
   indexType: X.Index.Type,
   indexDistanceType: X.IndexDistance.Type,
   indicesType: X.Indices.Type
-) where
-  // FIXME(ABI)#10 (Associated Types with where clauses): there should be no constraints in
-  // the 'where' clause, all of these should be required by the protocol.
-  X.SubSequence : RandomAccessCollection,
-  // X.SubSequence.Indices == X.Indices, // FIXME(ABI)#11 (Recursive Protocol Constraints): can't have this constraint now.
-  X.Indices : RandomAccessCollection {}
+) { }
 
 public struct AssertionResult : CustomStringConvertible {
   init(isPass: Bool) {
diff --git a/stdlib/public/core/ArrayBufferProtocol.swift b/stdlib/public/core/ArrayBufferProtocol.swift
index 2748e6d..c5a248c 100644
--- a/stdlib/public/core/ArrayBufferProtocol.swift
+++ b/stdlib/public/core/ArrayBufferProtocol.swift
@@ -16,7 +16,7 @@
 internal protocol _ArrayBufferProtocol
   : MutableCollection, RandomAccessCollection {
 
-  associatedtype Indices : RandomAccessCollection = CountableRange<Int>
+  associatedtype Indices = CountableRange<Int>
 
   /// The type of elements stored in the buffer.
   associatedtype Element
diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift
index f7349e2..0668e05 100644
--- a/stdlib/public/core/BidirectionalCollection.swift
+++ b/stdlib/public/core/BidirectionalCollection.swift
@@ -65,8 +65,8 @@
 ///   `c.index(before: c.index(after: i)) == i`.
 /// - If `i > c.startIndex && i <= c.endIndex`
 ///   `c.index(after: c.index(before: i)) == i`.
-public protocol BidirectionalCollection
-  : _BidirectionalIndexable, Collection {
+public protocol BidirectionalCollection : _BidirectionalIndexable, Collection 
+where SubSequence: BidirectionalCollection, Indices: BidirectionalCollection {
 
 // TODO: swift-3-indexing-model - replaces functionality in BidirectionalIndex
   /// Returns the position immediately before the given index.
@@ -84,17 +84,11 @@
 
   /// A sequence that can represent a contiguous subrange of the collection's
   /// elements.
-  associatedtype SubSequence : _BidirectionalIndexable, Collection
-    = BidirectionalSlice<Self>
-  // FIXME(ABI)#93 (Recursive Protocol Constraints):
-  // associatedtype SubSequence : BidirectionalCollection
+  associatedtype SubSequence = BidirectionalSlice<Self>
 
   /// A type that represents the indices that are valid for subscripting the
   /// collection, in ascending order.
-  associatedtype Indices : _BidirectionalIndexable, Collection
-    = DefaultBidirectionalIndices<Self>
-  // FIXME(ABI)#95 (Recursive Protocol Constraints):
-  // associatedtype Indices : BidirectionalCollection
+  associatedtype Indices = DefaultBidirectionalIndices<Self>
 
   /// The indices that are valid for subscripting the collection, in ascending
   /// order.
diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift
index f7a8175..fb8f0f9 100644
--- a/stdlib/public/core/Collection.swift
+++ b/stdlib/public/core/Collection.swift
@@ -642,7 +642,10 @@
 /// forward or bidirectional collection must traverse the entire collection to
 /// count the number of contained elements, accessing its `count` property is
 /// an O(*n*) operation.
-public protocol Collection : _Indexable, Sequence {
+public protocol Collection : _Indexable, Sequence 
+where SubSequence: Collection, Indices: Collection,
+      SubSequence.Index == Index
+{
   /// A type that represents the number of steps between a pair of
   /// indices.
   associatedtype IndexDistance = Int
@@ -668,10 +671,10 @@
   /// This associated type appears as a requirement in the `Sequence`
   /// protocol, but it is restated here with stricter constraints. In a
   /// collection, the subsequence should also conform to `Collection`.
-  associatedtype SubSequence : _IndexableBase, Sequence = Slice<Self>
-      where Self.SubSequence.Index == Index,
-            Self.Iterator.Element == Self.SubSequence.Iterator.Element,
+  associatedtype SubSequence = Slice<Self>
+      where Iterator.Element == SubSequence.Iterator.Element,
             SubSequence.SubSequence == SubSequence
+
   // FIXME(ABI)#98 (Recursive Protocol Constraints):
   // FIXME(ABI)#99 (Associated Types with where clauses):
   // associatedtype SubSequence : Collection
@@ -732,10 +735,9 @@
 
   /// A type that represents the indices that are valid for subscripting the
   /// collection, in ascending order.
-  associatedtype Indices : _Indexable, Sequence = DefaultIndices<Self>
+  associatedtype Indices = DefaultIndices<Self>
     where Indices.Iterator.Element == Index,
-          Indices.Index == Index,
-          Indices.SubSequence == Indices
+          Indices.Index == Index
 
   // FIXME(ABI)#100 (Recursive Protocol Constraints):
   // associatedtype Indices : Collection
diff --git a/stdlib/public/core/ExistentialCollection.swift.gyb b/stdlib/public/core/ExistentialCollection.swift.gyb
index 6cdb79d..204ca5c 100644
--- a/stdlib/public/core/ExistentialCollection.swift.gyb
+++ b/stdlib/public/core/ExistentialCollection.swift.gyb
@@ -426,14 +426,11 @@
 @_fixed_layout
 @_versioned
 internal final class _${Kind}Box<S : ${Kind}> : _Any${Kind}Box<S.Iterator.Element>
+%  if Kind == 'Sequence':
   where
   S.SubSequence : ${Kind},
-%  if Kind == 'Sequence':
   S.SubSequence.Iterator.Element == S.Iterator.Element,
   S.SubSequence.SubSequence == S.SubSequence
-%  else:
-  S.SubSequence.Indices : ${Kind},
-  S.Indices : ${Kind}
 %  end
 {
   internal typealias Element = S.Iterator.Element
@@ -1040,10 +1037,7 @@
     where
     // FIXME(ABI)#101 (Associated Types with where clauses): these constraints should be applied to
     // associated types of Collection.
-    C.SubSequence : ${SubProtocol},
-    C.SubSequence.Iterator.Element == Element,
-    C.SubSequence.Indices : ${SubProtocol},
-    C.Indices : ${SubProtocol}
+    C.SubSequence.Iterator.Element == Element
      {
     // Traversal: ${Traversal}
     // SubTraversal: ${SubTraversal}
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index c2d319e..37d95d8 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -214,13 +214,7 @@
     children: C,
     displayStyle: DisplayStyle? = nil,
     ancestorRepresentation: AncestorRepresentation = .generated
-  ) where
-    C.Iterator.Element == Child,
-    // FIXME(ABI)#47 (Associated Types with where clauses): these constraints should be applied to
-    // associated types of Collection.
-    C.SubSequence : Collection,
-    C.SubSequence.Indices : Collection,
-    C.Indices : Collection {
+  ) where C.Iterator.Element == Child {
 
     self.subjectType = Subject.self
     self._makeSuperclassMirror = Mirror._superclassIterator(
@@ -267,11 +261,7 @@
     unlabeledChildren: C,
     displayStyle: DisplayStyle? = nil,
     ancestorRepresentation: AncestorRepresentation = .generated
-  ) where
-    // FIXME(ABI)#48 (Associated Types with where clauses): these constraints should be applied to
-    // associated types of Collection.
-    C.SubSequence : Collection,
-    C.Indices : Collection {
+  ) {
 
     self.subjectType = Subject.self
     self._makeSuperclassMirror = Mirror._superclassIterator(
diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift
index 4c424d8..14c47eb 100644
--- a/stdlib/public/core/MutableCollection.swift
+++ b/stdlib/public/core/MutableCollection.swift
@@ -217,14 +217,9 @@
 ///     // Must be equivalent to:
 ///     a[i] = x
 ///     let y = x
-public protocol MutableCollection : _MutableIndexable, Collection {
-  // FIXME(ABI)#181: should be constrained to MutableCollection
-  // (<rdar://problem/20715009> Implement recursive protocol
-  // constraints)
-  /// A collection that represents a contiguous subrange of the collection's
-  /// elements.
-  associatedtype SubSequence : Collection /*: MutableCollection*/
-    = MutableSlice<Self>
+public protocol MutableCollection : _MutableIndexable, Collection
+where SubSequence: MutableCollection {
+  associatedtype SubSequence = MutableSlice<Self>
 
   /// Accesses the element at the specified position.
   ///
diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift
index 88f4253..8a4dec0 100644
--- a/stdlib/public/core/RandomAccessCollection.swift
+++ b/stdlib/public/core/RandomAccessCollection.swift
@@ -48,20 +48,15 @@
 /// `distance(from:to:)` methods with O(1) efficiency.
 public protocol RandomAccessCollection :
   _RandomAccessIndexable, BidirectionalCollection
+  where SubSequence: RandomAccessCollection, Indices: RandomAccessCollection
 {
   /// A collection that represents a contiguous subrange of the collection's
   /// elements.
-  associatedtype SubSequence : _RandomAccessIndexable, BidirectionalCollection
-    = RandomAccessSlice<Self>
-  // FIXME(ABI)#102 (Recursive Protocol Constraints):
-  // associatedtype SubSequence : RandomAccessCollection
+  associatedtype SubSequence = RandomAccessSlice<Self>
 
   /// A type that represents the indices that are valid for subscripting the
   /// collection, in ascending order.
-  associatedtype Indices : _RandomAccessIndexable, BidirectionalCollection
-    = DefaultRandomAccessIndices<Self>
-  // FIXME(ABI)#103 (Recursive Protocol Constraints):
-  // associatedtype Indices : RandomAccessCollection
+  associatedtype Indices = DefaultRandomAccessIndices<Self>
 
   /// The indices that are valid for subscripting the collection, in ascending
   /// order.
diff --git a/stdlib/public/core/SequenceAlgorithms.swift.gyb b/stdlib/public/core/SequenceAlgorithms.swift.gyb
index a5b99de..5be151b 100644
--- a/stdlib/public/core/SequenceAlgorithms.swift.gyb
+++ b/stdlib/public/core/SequenceAlgorithms.swift.gyb
@@ -729,13 +729,6 @@
     }
     return result
   }
-
-  @available(*, deprecated, message: "This call uses implicit promotion to optional. Please use map instead.")
-  public func flatMap<T>(
-    _ transform: (${GElement}) throws -> T
-  ) rethrows -> [T] {
-    return try map(transform)
-  }
 }
 
 extension Sequence {
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index d06cb92..1201400 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -445,7 +445,14 @@
       let relativeOffset = i._base._position - _coreOffset
       if _core.isASCII {
         let asciiBuffer = _core.asciiBuffer._unsafelyUnwrappedUnchecked
-        return Character(UnicodeScalar(asciiBuffer[relativeOffset]))
+        // Bounds checks in an UnsafeBufferPointer (asciiBuffer) are only
+        // performed in Debug mode, so they need to be duplicated here.
+        // Falling back to the non-optimal behavior in the case they don't
+        // pass.
+        if relativeOffset >= asciiBuffer.startIndex &&
+          relativeOffset < asciiBuffer.endIndex {
+          return Character(UnicodeScalar(asciiBuffer[relativeOffset]))
+        }
       } else if _core._baseAddress != nil {
         let cu = _core._nthContiguous(relativeOffset)
         // Only constructible if sub-surrogate
diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt
index a471e5f..5263c15 100644
--- a/stdlib/public/runtime/CMakeLists.txt
+++ b/stdlib/public/runtime/CMakeLists.txt
@@ -49,6 +49,7 @@
     SwiftObject.mm
     SwiftValue.mm
     Reflection.mm
+    "${SWIFT_SOURCE_DIR}/lib/Demangling/OldRemangler.cpp"
     "${SWIFT_SOURCE_DIR}/lib/Demangling/Remangler.cpp")
 
 set(swift_runtime_sources
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 583178f..b7ee950 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -1532,7 +1532,7 @@
   auto globalNode = Dem.createNode(Demangle::Node::Kind::Global);
   globalNode->addChild(typeNode, Dem);
 
-  auto string = Demangle::mangleNode(globalNode);
+  auto string = Demangle::mangleNodeOld(globalNode);
 
   auto fullNameBuf = (char*)swift_slowAlloc(string.size() + 1, 0);
   memcpy(fullNameBuf, string.c_str(), string.size() + 1);
diff --git a/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.apinotes b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.apinotes
new file mode 100644
index 0000000..adad67b
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.apinotes
@@ -0,0 +1,9 @@
+Name: SomeObjCModule
+Classes:
+- Name: NSRuncibleSpoon
+  SwiftBridge: RuncibleSpoon
+SwiftVersions:
+- Version: 3
+  Classes:
+  - Name: NSRuncibleSpoon
+    SwiftBridge: ""
diff --git a/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.h b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.h
new file mode 100644
index 0000000..a12b1af
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModule.h
@@ -0,0 +1,24 @@
+// Swift 3 sees the ObjC class NSRuncibleSpoon as the class, and uses methods
+// with type signatures involving NSRuncibleSpoon to conform to protocols
+// across the language boundary. Swift 4 sees the type as bridged to
+// a RuncibleSpoon value type, but still needs to be able to use conformances
+// declared by Swift 3.
+
+@import Foundation;
+
+@interface NSRuncibleSpoon: NSObject
+@end
+
+@interface SomeObjCClass: NSObject
+- (instancetype _Nonnull)initWithSomeSwiftInitRequirement:(NSRuncibleSpoon* _Nonnull)s;
+- (void)someSwiftMethodRequirement:(NSRuncibleSpoon* _Nonnull)s;
+@property NSRuncibleSpoon * _Nonnull someSwiftPropertyRequirement;
+@end
+
+@protocol SomeObjCProtocol
+- (instancetype _Nonnull)initWithSomeObjCInitRequirement:(NSRuncibleSpoon * _Nonnull)string;
+- (void)someObjCMethodRequirement:(NSRuncibleSpoon * _Nonnull)string;
+@property NSRuncibleSpoon * _Nonnull someObjCPropertyRequirement;
+@end
+
+
diff --git a/test/Compatibility/MixAndMatch/Inputs/SomeObjCModuleX.swift b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModuleX.swift
new file mode 100644
index 0000000..2abcabe
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/SomeObjCModuleX.swift
@@ -0,0 +1,22 @@
+// NB: This file is not named SomeObjCModule.swift to avoid getting picked up
+// by -enable-source-import
+
+@_exported import SomeObjCModule
+
+public struct RuncibleSpoon: _ObjectiveCBridgeable {
+  public init() {}
+
+  public func _bridgeToObjectiveC() -> NSRuncibleSpoon {
+    fatalError()
+  }
+  public static func _forceBridgeFromObjectiveC(_: NSRuncibleSpoon, result: inout RuncibleSpoon?) {
+    fatalError()
+  }
+  public static func _conditionallyBridgeFromObjectiveC(_: NSRuncibleSpoon, result: inout RuncibleSpoon?) -> Bool {
+    fatalError()
+  }
+  public static func _unconditionallyBridgeFromObjectiveC(_: NSRuncibleSpoon?) -> RuncibleSpoon {
+    fatalError()
+  }
+}
+
diff --git a/test/Compatibility/MixAndMatch/Inputs/module.modulemap b/test/Compatibility/MixAndMatch/Inputs/module.modulemap
new file mode 100644
index 0000000..154dc37
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/module.modulemap
@@ -0,0 +1,4 @@
+module SomeObjCModule {
+  header "SomeObjCModule.h"
+  export *
+}
diff --git a/test/Compatibility/MixAndMatch/Inputs/witness_change_swift3_leaf.swift b/test/Compatibility/MixAndMatch/Inputs/witness_change_swift3_leaf.swift
new file mode 100644
index 0000000..89a5a70
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/witness_change_swift3_leaf.swift
@@ -0,0 +1,71 @@
+
+// Swift 3 sees the ObjC class NSRuncibleSpoon as the class, and uses methods
+// with type signatures involving NSRuncibleSpoon to conform to protocols
+// across the language boundary. Swift 4 sees the type as bridged to
+// a RuncibleSpoon value type, but still needs to be able to use conformances
+// declared by Swift 3.
+
+// Swift 3, importing Swift 3 and Swift 4 code
+
+import SomeObjCModule
+import SomeSwift3Module
+import SomeSwift4Module
+
+func testMatchAndMix(bridged: RuncibleSpoon, unbridged: NSRuncibleSpoon) {
+  let objcInstanceViaClass
+    = SomeObjCClass(someSwiftInitRequirement: unbridged)
+
+  let objcClassAsS3Protocol: SomeSwift3Protocol.Type = SomeObjCClass.self
+  let objcInstanceViaS3Protocol
+    = objcClassAsS3Protocol.init(someSwiftInitRequirement: unbridged)
+
+  let objcClassAsS4Protocol: SomeSwift4Protocol.Type = SomeObjCClass.self
+  let objcInstanceViaS4Protocol
+    = objcClassAsS4Protocol.init(someSwiftInitRequirement: bridged)
+
+  var bridgedSink: RuncibleSpoon
+  var unbridgedSink: NSRuncibleSpoon
+
+  let swiftPropertyViaClass = objcInstanceViaClass.someSwiftPropertyRequirement
+  unbridgedSink = swiftPropertyViaClass
+  let swiftPropertyViaS3Protocol = objcInstanceViaS3Protocol.someSwiftPropertyRequirement
+  unbridgedSink = swiftPropertyViaS3Protocol
+  let swiftPropertyViaS4Protocol = objcInstanceViaS4Protocol.someSwiftPropertyRequirement
+  bridgedSink = swiftPropertyViaS4Protocol
+
+  objcInstanceViaClass.someSwiftMethodRequirement(unbridged)
+  objcInstanceViaS3Protocol.someSwiftMethodRequirement(unbridged)
+  objcInstanceViaS4Protocol.someSwiftMethodRequirement(bridged)
+
+  let swift3InstanceViaClass
+    = SomeSwift3Class(someObjCInitRequirement: unbridged)
+  let swift3ClassAsProtocol: SomeObjCProtocol.Type = SomeSwift3Class.self
+  let swift3InstanceViaProtocol
+    = swift3ClassAsProtocol.init(someObjCInitRequirement: unbridged)
+  
+  let objcPropertyViaClassS3 = swift3InstanceViaClass.someObjCPropertyRequirement
+  unbridgedSink = objcPropertyViaClassS3
+  let objcPropertyViaProtocolS3 = swift3InstanceViaProtocol.someObjCPropertyRequirement
+  unbridgedSink = objcPropertyViaProtocolS3
+
+  swift3InstanceViaClass.someObjCMethodRequirement(unbridged)
+  swift3InstanceViaProtocol.someObjCMethodRequirement(unbridged)
+
+  let swift4InstanceViaClass
+    = SomeSwift4Class(someObjCInitRequirement: bridged)
+  let swift4ClassAsProtocol: SomeObjCProtocol.Type = SomeSwift4Class.self
+  let swift4InstanceViaProtocol
+    = swift4ClassAsProtocol.init(someObjCInitRequirement: unbridged)
+  
+  let objcPropertyViaClassS4 = swift4InstanceViaClass.someObjCPropertyRequirement
+  bridgedSink = objcPropertyViaClassS4
+  let objcPropertyViaProtocolS4 = swift4InstanceViaProtocol.someObjCPropertyRequirement
+  unbridgedSink = objcPropertyViaProtocolS4
+
+  swift4InstanceViaClass.someObjCMethodRequirement(bridged)
+  swift4InstanceViaProtocol.someObjCMethodRequirement(unbridged)
+
+  _ = bridgedSink
+  _ = unbridgedSink
+}
+
diff --git a/test/Compatibility/MixAndMatch/Inputs/witness_change_swift4.swift b/test/Compatibility/MixAndMatch/Inputs/witness_change_swift4.swift
new file mode 100644
index 0000000..0ebad72
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/Inputs/witness_change_swift4.swift
@@ -0,0 +1,65 @@
+
+// Swift 3 sees the ObjC class NSRuncibleSpoon as the class, and uses methods
+// with type signatures involving NSRuncibleSpoon to conform to protocols
+// across the language boundary. Swift 4 sees the type as bridged to
+// a RuncibleSpoon value type, but still needs to be able to use conformances
+// declared by Swift 3.
+
+// Swift 4
+
+import SomeObjCModule
+import SomeSwift3Module
+
+public func testMixAndMatch(bridged: RuncibleSpoon, unbridged: NSRuncibleSpoon) {
+  let objcInstanceViaClass
+    = SomeObjCClass(someSwiftInitRequirement: bridged)
+  let objcClassAsProtocol: SomeSwift3Protocol.Type = SomeObjCClass.self
+  let objcInstanceViaProtocol
+    = objcClassAsProtocol.init(someSwiftInitRequirement: unbridged)
+
+  var bridgedSink: RuncibleSpoon
+  var unbridgedSink: NSRuncibleSpoon
+
+  let swiftPropertyViaClass = objcInstanceViaClass.someSwiftPropertyRequirement
+  bridgedSink = swiftPropertyViaClass
+  let swiftPropertyViaProtocol = objcInstanceViaProtocol.someSwiftPropertyRequirement
+  unbridgedSink = swiftPropertyViaProtocol
+
+  objcInstanceViaClass.someSwiftMethodRequirement(bridged)
+  objcInstanceViaProtocol.someSwiftMethodRequirement(unbridged)
+
+  let swiftInstanceViaClass
+    = SomeSwift3Class(someObjCInitRequirement: unbridged)
+  let swiftClassAsProtocol: SomeObjCProtocol.Type = SomeSwift3Class.self
+  let swiftInstanceViaProtocol
+    = swiftClassAsProtocol.init(someObjCInitRequirement: bridged)
+  
+  let objcPropertyViaClass = swiftInstanceViaClass.someObjCPropertyRequirement
+  unbridgedSink = objcPropertyViaClass
+  let objcPropertyViaProtocol = swiftInstanceViaProtocol.someObjCPropertyRequirement
+  bridgedSink = objcPropertyViaProtocol
+
+  swiftInstanceViaClass.someObjCMethodRequirement(unbridged)
+  swiftInstanceViaProtocol.someObjCMethodRequirement(bridged)
+
+  _ = bridgedSink
+  _ = unbridgedSink
+}
+
+public protocol SomeSwift4Protocol {
+  init(someSwiftInitRequirement: RuncibleSpoon)
+  func someSwiftMethodRequirement(_: RuncibleSpoon)
+  var someSwiftPropertyRequirement: RuncibleSpoon { get }
+}
+
+extension SomeObjCClass: SomeSwift4Protocol {}
+
+public class SomeSwift4Class: NSObject {
+  public required init(someObjCInitRequirement x: RuncibleSpoon) {
+    someObjCPropertyRequirement = x
+  }
+  public func someObjCMethodRequirement(_: RuncibleSpoon) {}
+  public var someObjCPropertyRequirement: RuncibleSpoon
+}
+
+extension SomeSwift4Class: SomeObjCProtocol {}
diff --git a/test/Compatibility/MixAndMatch/witness_change.swift b/test/Compatibility/MixAndMatch/witness_change.swift
new file mode 100644
index 0000000..f384cd8
--- /dev/null
+++ b/test/Compatibility/MixAndMatch/witness_change.swift
@@ -0,0 +1,37 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-deserialization-recovery -emit-module -o %t/SomeObjCModule.swiftmodule -module-name SomeObjCModule -I %t -I %S/Inputs -swift-version 3 %S/Inputs/SomeObjCModuleX.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-deserialization-recovery -emit-module -o %t/SomeSwift3Module.swiftmodule -module-name SomeSwift3Module -I %t -I %S/Inputs -swift-version 3 %s
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-deserialization-recovery -emit-module -o %t/SomeSwift4Module.swiftmodule -module-name SomeSwift4Module -I %t -I %S/Inputs -swift-version 4 %S/Inputs/witness_change_swift4.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-deserialization-recovery -c -I %t -I %S/Inputs -swift-version 3 %S/Inputs/witness_change_swift3_leaf.swift
+
+// REQUIRES: objc_interop
+
+// Swift 3 sees the ObjC class NSRuncibleSpoon as the class, and uses methods
+// with type signatures involving NSRuncibleSpoon to conform to protocols
+// across the language boundary. Swift 4 sees the type as bridged to
+// a RuncibleSpoon value type, but still needs to be able to use conformances
+// declared by Swift 3.
+
+// Swift 3
+
+import SomeObjCModule
+
+_ = RuncibleSpoon()
+
+public class SomeSwift3Class: NSObject {
+  public required init(someObjCInitRequirement x: NSRuncibleSpoon) {
+    someObjCPropertyRequirement = x
+  }
+  public func someObjCMethodRequirement(_: NSRuncibleSpoon) {}
+  public var someObjCPropertyRequirement: NSRuncibleSpoon
+}
+extension SomeSwift3Class: SomeObjCProtocol {}
+
+public protocol SomeSwift3Protocol {
+  init(someSwiftInitRequirement: NSRuncibleSpoon)
+  func someSwiftMethodRequirement(_: NSRuncibleSpoon)
+  var someSwiftPropertyRequirement: NSRuncibleSpoon { get }
+}
+extension SomeObjCClass: SomeSwift3Protocol {}
+
diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift
index a78ab61..8bd3650 100644
--- a/test/Constraints/closures.swift
+++ b/test/Constraints/closures.swift
@@ -512,8 +512,7 @@
 
 returnsArray().flatMap { $0 }.flatMap { }
 // expected-warning@-1 {{expression of type 'Int' is unused}}
-// expected-warning@-2 {{Please use map instead.}}
-// expected-warning@-3 {{result of call to 'flatMap' is unused}}
+// expected-warning@-2 {{result of call to 'flatMap' is unused}}
 
 // rdar://problem/30271695
 _ = ["hi"].flatMap { $0.isEmpty ? nil : $0 }
diff --git a/test/Constraints/function_conversion.swift b/test/Constraints/function_conversion.swift
new file mode 100644
index 0000000..58375e5
--- /dev/null
+++ b/test/Constraints/function_conversion.swift
@@ -0,0 +1,23 @@
+// RUN: %target-typecheck-verify-swift -swift-version 3
+// RUN: %target-typecheck-verify-swift -swift-version 4
+
+// rdar://problem/31969605
+
+class Base {}
+class Derived : Base {}
+
+protocol Refined {}
+protocol Proto : Refined {}
+extension Base : Refined {}
+
+func baseFn(_: Base) {}
+
+func superclassConversion(fn: @escaping (Base) -> ()) {
+  let _: (Derived) -> () = fn
+}
+
+func existentialConversion(fn: @escaping (Refined) -> ()) {
+  let _: (Proto) -> () = fn
+  let _: (Base) -> () = fn
+  let _: (Derived) -> () = fn
+}
diff --git a/test/IDE/complete_with_header_import.swift b/test/IDE/complete_with_header_import.swift
index 2da9189..3ba7ab9 100644
--- a/test/IDE/complete_with_header_import.swift
+++ b/test/IDE/complete_with_header_import.swift
@@ -4,6 +4,11 @@
 // RUN: %target-swift-ide-test -code-completion -pch-output-dir %t -source-filename %s -code-completion-token=TOP -import-objc-header %S/Inputs/header.h | %FileCheck %s -check-prefix=CHECK-TOP
 // RUN: %target-swift-ide-test -code-completion -pch-output-dir %t -source-filename %s -code-completion-token=TYPE -import-objc-header %S/Inputs/header.h | %FileCheck %s -check-prefix=CHECK-TYPE
 // RUN: stat %t/*.pch
+// RUN: cp %S/Inputs/header.h %t
+// RUN: %target-swift-ide-test -code-completion -pch-output-dir %t/pch -source-filename %s -code-completion-token=TOP -import-objc-header %t/header.h | %FileCheck %s -check-prefix=CHECK-TOP
+// RUN: stat %t/pch/*.pch
+// RUN: echo '// new stuff' >> %t/header.h
+// RUN: %target-swift-ide-test -code-completion -pch-output-dir %t/pch -source-filename %s -code-completion-token=TOP -import-objc-header %t/header.h | %FileCheck %s -check-prefix=CHECK-TOP
 
 // REQUIRES: objc_interop
 
diff --git a/test/IDE/range_info_branches.swift b/test/IDE/range_info_branches.swift
new file mode 100644
index 0000000..049eea8
--- /dev/null
+++ b/test/IDE/range_info_branches.swift
@@ -0,0 +1,40 @@
+func foo(_ a: Bool) -> Int{
+  if a {
+    return 1
+  } else {
+  }
+  if a {
+    return 0
+  } else {
+    return 1
+  }
+}
+
+func foo1(_ a: Bool) {
+  if a {}
+  if a {}
+  else {}
+  if a {
+    return
+  } else {
+    return
+  }
+}
+
+// RUN: %target-swift-ide-test -range -pos=2:1 -end-pos 5:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-ERR
+// RUN: %target-swift-ide-test -range -pos=6:1 -end-pos 10:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-INT
+// RUN: %target-swift-ide-test -range -pos=14:1 -end-pos 14:10 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-NO-RETURN
+// RUN: %target-swift-ide-test -range -pos=15:1 -end-pos 16:10 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-NO-RETURN
+// RUN: %target-swift-ide-test -range -pos=17:1 -end-pos 21:4 -source-filename %s | %FileCheck %s -check-prefix=CHECK-VOID-RETURN
+
+// CHECK-ERR: <Type><<error type>></Type>
+// CHECK-ERR-NOT: <Exit>true</Exit>
+
+// CHECK-INT: <Type>Int</Type>
+// CHECK-INT: <Exit>true</Exit>
+
+// CHECK-VOID-NO-RETURN: <Type>Void</Type>
+// CHECK-VOID-NO-RETURN-NOT: <Exit>true</Exit>
+
+// CHECK-VOID-RETURN: <Type>Void</Type>
+// CHECK-VOID-RETURN: <Exit>true</Exit>
diff --git a/test/Interpreter/SDK/Inputs/test.arc b/test/Interpreter/SDK/Inputs/test.arc
new file mode 100644
index 0000000..780fd62
--- /dev/null
+++ b/test/Interpreter/SDK/Inputs/test.arc
Binary files differ
diff --git a/test/Interpreter/SDK/archive_compatibility.swift b/test/Interpreter/SDK/archive_compatibility.swift
new file mode 100644
index 0000000..19875d2
--- /dev/null
+++ b/test/Interpreter/SDK/archive_compatibility.swift
@@ -0,0 +1,131 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %target-build-swift %s -module-name=test -o %t/a.out
+// RUN: %target-run %t/a.out %S/Inputs/test.arc | %FileCheck %s
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+// UNSUPPORTED: OS=tvos
+// UNSUPPORTED: OS=watchos
+
+// This test checks if an archive, produced with the swift 3.1 compiler, can
+// still be read with the current compiler.
+
+import Foundation
+
+struct ABC {
+  class NestedClass : NSObject, NSCoding {
+    var i : Int
+
+    init(_ ii: Int) {
+      i = ii
+    }
+
+    required init(coder aDecoder: NSCoder) {
+      i = aDecoder.decodeInteger(forKey: "i")
+    }
+
+    func encode(with aCoder: NSCoder) {
+      aCoder.encode(i, forKey: "i")
+    }
+  }
+}
+
+private class PrivateClass : NSObject, NSCoding {
+  var pi : Int
+
+  init(_ ii: Int) {
+    pi = ii
+  }
+
+  required init(coder aDecoder: NSCoder) {
+    pi = aDecoder.decodeInteger(forKey: "pi")
+  }
+
+  func encode(with aCoder: NSCoder) {
+    aCoder.encode(pi, forKey: "pi")
+  }
+}
+
+class GenericClass<T> : NSObject, NSCoding {
+  var gi : Int
+
+  init(_ ii: Int) {
+    gi = ii
+  }
+
+  required init(coder aDecoder: NSCoder) {
+    gi = aDecoder.decodeInteger(forKey: "gi")
+  }
+
+  func encode(with aCoder: NSCoder) {
+    aCoder.encode(gi, forKey: "gi")
+  }
+}
+
+class TopLevel : NSObject, NSCoding {
+  var tli : Int
+
+  var nested: ABC.NestedClass?
+  fileprivate var priv: PrivateClass?
+  var generic : GenericClass<Int>?
+
+  init(_ ii: Int) {
+    tli = ii
+  }
+
+  required init(coder aDecoder: NSCoder) {
+    tli = aDecoder.decodeInteger(forKey: "tli")
+    nested = aDecoder.decodeObject(forKey: "nested") as? ABC.NestedClass
+    priv = aDecoder.decodeObject(forKey: "priv") as? PrivateClass
+    generic = aDecoder.decodeObject(forKey: "generic") as? GenericClass<Int>
+  }
+
+  func encode(with aCoder: NSCoder) {
+    aCoder.encode(tli, forKey: "tli")
+    aCoder.encode(nested, forKey: "nested")
+    aCoder.encode(priv, forKey: "priv")
+    aCoder.encode(generic, forKey: "generic")
+  }
+}
+
+func main() {
+
+  let args = CommandLine.arguments
+
+  let g = GenericClass<Int>(42)
+#if ENCODE
+  // This is how the archive was created with the swift 3.1 compiler.
+  let c = TopLevel(27)
+  c.nested = ABC.NestedClass(28)
+  c.priv = PrivateClass(29)
+  c.generic = g
+
+  NSKeyedArchiver.archiveRootObject(c, toFile: args[1])
+#else
+  if let u = NSKeyedUnarchiver.unarchiveObject(withFile: args[1]) {
+    if let x = u as? TopLevel {
+      // CHECK: top-level: 27
+      print("top-level: \(x.tli)")
+      if let n = x.nested {
+        // CHECK: nested: 28
+        print("nested: \(n.i)")
+      }
+      if let p = x.priv {
+        // CHECK: private: 29
+        print("private: \(p.pi)")
+      }
+      if let g = x.generic {
+        // CHECK: generic: 42
+        print("generic: \(g.gi)")
+      }
+    } else {
+      print(u)
+    }
+  } else {
+    print("nil")
+  }
+#endif
+}
+
+main()
+
diff --git a/test/Interpreter/SDK/archiving_generic_swift_class.swift b/test/Interpreter/SDK/archiving_generic_swift_class.swift
index 52c3bd6..b862e60 100644
--- a/test/Interpreter/SDK/archiving_generic_swift_class.swift
+++ b/test/Interpreter/SDK/archiving_generic_swift_class.swift
@@ -190,10 +190,10 @@
     fatalError("unable to unarchive Foo<NSNumber>")
   }
 
-  // CHECK-LABEL: <_T04main3FooCySo8NSStringCGD: {{0x[0-9a-f]+}}> #0
+  // CHECK-LABEL: <_TtGC4main3FooCSo8NSString_: {{0x[0-9a-f]+}}> #0
   // CHECK:         one: one
   // CHECK:         two: two
-  // CHECK-LABEL: <_T04main3FooCySo8NSNumberCGD: {{0x[0-9a-f]+}}> #0
+  // CHECK-LABEL: <_TtGC4main3FooCSo8NSNumber_: {{0x[0-9a-f]+}}> #0
   // CHECK:         one: 1
   // CHECK:         two: 2
   dump(strings)
diff --git a/test/stdlib/FlatMapDiagnostics.swift.gyb b/test/stdlib/FlatMapDiagnostics.swift.gyb
deleted file mode 100644
index 0183eda..0000000
--- a/test/stdlib/FlatMapDiagnostics.swift.gyb
+++ /dev/null
@@ -1,39 +0,0 @@
-//===--- FlatMapDiagnostics.swift -----------------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 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
-//
-//===----------------------------------------------------------------------===//
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: %gyb %s -o %t/FlatMapDiagnostics.swift
-// RUN: %target-swift-frontend -typecheck -verify %t/FlatMapDiagnostics.swift
-
-
-% for Type in [
-%   'Sequence',
-%   'Collection',
-%   'LazySequenceProtocol',
-%   'LazyCollectionProtocol']:
-
-func testGeneric${Type}<T : ${Type}>(xs: T) {
-  _ = xs.flatMap { $0 } // expected-warning {{Please use map instead.}}
-}
-
-% end
-
-func testArray(xs: [Int]) {
- _ = xs.flatMap { $0 } // expected-warning {{Please use map instead.}}
- _ = xs.lazy.flatMap { $0 } // expected-warning {{Please use map instead.}}
-}
-
-func testGenericLazyBidirectionalCollection<
-  T : LazyCollectionProtocol & BidirectionalCollection
->(xs: T) where T.Elements : BidirectionalCollection {
-  _ = xs.flatMap { $0 } // expected-warning {{Please use map instead.}}
-}
-
diff --git a/test/stdlib/RuntimeObjC.swift b/test/stdlib/RuntimeObjC.swift
index 055b937..78c3d1a 100644
--- a/test/stdlib/RuntimeObjC.swift
+++ b/test/stdlib/RuntimeObjC.swift
@@ -334,47 +334,54 @@
 protocol ProtocolB {}
 
 Runtime.test("Generic class ObjC runtime names") {
-  expectEqual("_T01a12GenericClassCySiGD",
+  expectEqual("_TtGC1a12GenericClassSi_",
               NSStringFromClass(GenericClass<Int>.self))
-  expectEqual("_T01a12GenericClassCyAA11PlainStructVGD",
+  expectEqual("_TtGC1a12GenericClassVS_11PlainStruct_",
               NSStringFromClass(GenericClass<PlainStruct>.self))
-  expectEqual("_T01a12GenericClassCyAA9PlainEnumOGD",
+  expectEqual("_TtGC1a12GenericClassOS_9PlainEnum_",
               NSStringFromClass(GenericClass<PlainEnum>.self))
-  expectEqual("_T01a12GenericClassCyAA11PlainStructV_AA0C4EnumOAEtGD",
+  expectEqual("_TtGC1a12GenericClassTVS_11PlainStructOS_9PlainEnumS1___",
               NSStringFromClass(GenericClass<(PlainStruct, PlainEnum, PlainStruct)>.self))
-  expectEqual("_T01a12GenericClassCyAA11PlainStructVmGD",
+  expectEqual("_TtGC1a12GenericClassMVS_11PlainStruct_",
               NSStringFromClass(GenericClass<PlainStruct.Type>.self))
-  expectEqual("_T01a12GenericClassCyAA11PlainStructVAEmcGD",
+  expectEqual("_TtGC1a12GenericClassFMVS_11PlainStructS1__",
               NSStringFromClass(GenericClass<(PlainStruct.Type) -> PlainStruct>.self))
 
-  expectEqual("_T01a12GenericClassCyAA11PlainStructVAEmKcGD",
+  expectEqual("_TtGC1a12GenericClassFzMVS_11PlainStructS1__",
               NSStringFromClass(GenericClass<(PlainStruct.Type) throws -> PlainStruct>.self))
-  expectEqual("_T01a12GenericClassCySiAA11PlainStructV_AA0C4EnumOztcGD",
+  expectEqual("_TtGC1a12GenericClassFTVS_11PlainStructROS_9PlainEnum_Si_",
               NSStringFromClass(GenericClass<(PlainStruct, inout PlainEnum) -> Int>.self))
 
-  expectEqual("_T01a12GenericClassCyAA9ProtocolA_pGD",
+  expectEqual("_TtGC1a12GenericClassPS_9ProtocolA__",
               NSStringFromClass(GenericClass<ProtocolA>.self))
-  expectEqual("_T01a12GenericClassCyAA9ProtocolA_AA0C1BpGD",
+  expectEqual("_TtGC1a12GenericClassPS_9ProtocolAS_9ProtocolB__",
               NSStringFromClass(GenericClass<ProtocolA & ProtocolB>.self))
-  expectEqual("_T01a12GenericClassCyAA9ProtocolA_AA0C1BpXpGD",
+  expectEqual("_TtGC1a12GenericClassPMPS_9ProtocolAS_9ProtocolB__",
               NSStringFromClass(GenericClass<(ProtocolA & ProtocolB).Type>.self))
-  expectEqual("_T01a12GenericClassCyAA9ProtocolA_AA0C1BpmGD",
+  expectEqual("_TtGC1a12GenericClassMPS_9ProtocolAS_9ProtocolB__",
               NSStringFromClass(GenericClass<(ProtocolB & ProtocolA).Protocol>.self))
 
-  expectEqual("_T01a12GenericClassCySo7CFArrayCGD",
+  expectEqual("_TtGC1a12GenericClassCSo7CFArray_",
               NSStringFromClass(GenericClass<CFArray>.self))
-  expectEqual("_T01a12GenericClassCySo7DecimalVGD",
+  expectEqual("_TtGC1a12GenericClassVSo7Decimal_",
               NSStringFromClass(GenericClass<Decimal>.self))
-  expectEqual("_T01a12GenericClassCySo8NSObjectCGD",
+  expectEqual("_TtGC1a12GenericClassCSo8NSObject_",
               NSStringFromClass(GenericClass<NSObject>.self))
-  expectEqual("_T01a12GenericClassCySo8NSObjectCGD",
+  expectEqual("_TtGC1a12GenericClassCSo8NSObject_",
               NSStringFromClass(GenericClass<NSObject>.self))
-  expectEqual("_T01a12GenericClassCySo9NSCopying_pGD",
+  expectEqual("_TtGC1a12GenericClassPSo9NSCopying__",
               NSStringFromClass(GenericClass<NSCopying>.self))
-  expectEqual("_T01a12GenericClassCySo9NSCopying_AA9ProtocolAAA0D1BpGD",
+  expectEqual("_TtGC1a12GenericClassPSo9NSCopyingS_9ProtocolAS_9ProtocolB__",
               NSStringFromClass(GenericClass<ProtocolB & NSCopying & ProtocolA>.self))
 
-  expectEqual("_T01a17MultiGenericClassCyAA0B6StructVySiGAA0B4EnumOyAHySiGGGD",
+  expectEqual("_TtGC1a12GenericClassXcCS_9SomeClassS_9ProtocolA__",
+              NSStringFromClass(GenericClass<ProtocolA & SomeClass>.self))
+  expectEqual("_TtGC1a12GenericClassPS_9ProtocolAs9AnyObject__",
+              NSStringFromClass(GenericClass<ProtocolA & AnyObject>.self))
+  expectEqual("_TtGC1a12GenericClassPs9AnyObject__",
+              NSStringFromClass(GenericClass<AnyObject>.self))
+
+  expectEqual("_TtGC1a17MultiGenericClassGVS_13GenericStructSi_GOS_11GenericEnumGS2_Si___",
               NSStringFromClass(MultiGenericClass<GenericStruct<Int>,
                                                   GenericEnum<GenericEnum<Int>>>.self))
 }
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index cea03ff..e4f3c86 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
@@ -1337,7 +1337,7 @@
       case RangeKind::SingleExpression: {
         SmallString<64> SS;
         llvm::raw_svector_ostream OS(SS);
-        Info.Ty.print(OS);
+        Info.ExitInfo.getPointer()->print(OS);
         Result.ExprType = OS.str();
         Receiver(Result);
         return;
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index d295197..355bda1 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -960,6 +960,8 @@
 
 dash-dash
 
+skip-test-lldb
+
 swift-install-components=compiler;clang-builtin-headers;stdlib;sdk-overlay;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers
 llvm-install-components=libclang;libclang-headers
 
diff --git a/validation-test/stdlib/CollectionDiagnostics.swift b/validation-test/stdlib/CollectionDiagnostics.swift
index 775fcee..f83e8b4 100644
--- a/validation-test/stdlib/CollectionDiagnostics.swift
+++ b/validation-test/stdlib/CollectionDiagnostics.swift
@@ -23,7 +23,7 @@
     fatalError("unreachable")
   }
 
-  // expected-note@+3 {{possibly intended match 'CollectionWithBadSubSequence.SubSequence' (aka 'OpaqueValue<Int8>') does not conform to 'Sequence'}}
+  // expected-note@+3 {{possibly intended match}}
   // expected-note@+2 {{possibly intended match}}
   // expected-note@+1 {{possibly intended match}}
   typealias SubSequence = OpaqueValue<Int8>
diff --git a/validation-test/stdlib/String.swift b/validation-test/stdlib/String.swift
index 5ca97e8..a0a8a5b 100644
--- a/validation-test/stdlib/String.swift
+++ b/validation-test/stdlib/String.swift
@@ -192,9 +192,7 @@
   expectEqual("a", acceptor[donor.startIndex])
 }
 
-StringTests.test("ForeignIndexes/subscript(Index)/OutOfBoundsTrap")
-  .skip(.always("<rdar://problem/31992473>"))
-  .code {
+StringTests.test("ForeignIndexes/subscript(Index)/OutOfBoundsTrap") {
   let donor = "abcdef"
   let acceptor = "uvw"