Merge pull request #17589 from eeckstein/disable-static-strings-macos

Temporarily disable generation of static long Strings for macos.
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index e92dd07..e970e58 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -1176,6 +1176,12 @@
     ///
     /// Meaningful for all type-descriptor kinds.
     IsReflectable = 2,
+    
+    /// Set if the type is a Clang-importer-synthesized related entity. After
+    /// the null terminator for the type name is another null-terminated string
+    /// containing the tag that discriminates the entity from other synthesized
+    /// declarations associated with the same declaration.
+    IsSynthesizedRelatedEntity = 3,
 
     /// Set if the context descriptor is includes metadata for dynamically
     /// constructing a class's vtables at metadata instantiation time.
@@ -1208,6 +1214,10 @@
   FLAGSET_DEFINE_FLAG_ACCESSORS(IsCTypedef, isCTypedef, setIsCTypedef)
   FLAGSET_DEFINE_FLAG_ACCESSORS(IsReflectable, isReflectable, setIsReflectable)
 
+  FLAGSET_DEFINE_FLAG_ACCESSORS(IsSynthesizedRelatedEntity,
+                                isSynthesizedRelatedEntity,
+                                setIsSynthesizedRelatedEntity)
+
   FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasVTable,
                                 class_hasVTable,
                                 class_setHasVTable)
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index 83670b5..27cb3be 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -36,7 +36,6 @@
 NODE(BoundGenericEnum)
 NODE(BoundGenericStructure)
 NODE(BoundGenericOtherNominalType)
-NODE(BoundGenericTypeAlias)
 NODE(BuiltinTypeName)
 NODE(CFunctionPointer)
 CONTEXT_NODE(Class)
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index 9d64ea2..55ecb4c 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -1136,12 +1136,13 @@
   Demangle::NodePointer
   buildNominalTypeMangling(ContextDescriptorRef descriptor,
                            Demangle::NodeFactory &nodeFactory) {
-    std::vector<std::pair<Demangle::Node::Kind, std::string>>
+    std::vector<std::pair<Demangle::Node::Kind, Demangle::NodePointer>>
       nameComponents;
     ContextDescriptorRef parent = descriptor;
     
     while (parent) {
       std::string nodeName;
+      std::string relatedTag;
       Demangle::Node::Kind nodeKind;
       
       auto getTypeName = [&]() -> bool {
@@ -1149,7 +1150,16 @@
           reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
             (parent.getLocalBuffer());
         auto nameAddress = resolveRelativeField(parent, typeBuffer->Name);
-        return Reader->readString(RemoteAddress(nameAddress), nodeName);
+        if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
+          return false;
+        
+        if (typeBuffer->isSynthesizedRelatedEntity()) {
+          nameAddress += nodeName.size() + 1;
+          if (!Reader->readString(RemoteAddress(nameAddress), relatedTag))
+            return false;
+        }
+        
+        return true;
       };
       
       bool isTypeContext = false;
@@ -1208,8 +1218,17 @@
         else if (typeFlags.isCTypedef())
           nodeKind = Demangle::Node::Kind::TypeAlias;
       }
+      
+      auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
+                                             nodeName);
+      if (!relatedTag.empty()) {
+        auto relatedNode =
+          nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
+        relatedNode->addChild(nameNode, nodeFactory);
+        nameNode = relatedNode;
+      }
 
-      nameComponents.emplace_back(nodeKind, nodeName);
+      nameComponents.emplace_back(nodeKind, nameNode);
       
       parent = readParentContextDescriptor(parent);
     }
@@ -1222,13 +1241,11 @@
     auto moduleInfo = std::move(nameComponents.back());
     nameComponents.pop_back();
     auto demangling =
-      nodeFactory.createNode(Node::Kind::Module, moduleInfo.second);
+      nodeFactory.createNode(Node::Kind::Module, moduleInfo.second->getText());
     for (auto &component : reversed(nameComponents)) {
-      auto name = nodeFactory.createNode(Node::Kind::Identifier,
-                                         component.second);
       auto parent = nodeFactory.createNode(component.first);
       parent->addChild(demangling, nodeFactory);
-      parent->addChild(name, nodeFactory);
+      parent->addChild(component.second, nodeFactory);
       demangling = parent;
     }
     
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 9689c29..e473285 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -3511,6 +3511,21 @@
 
   llvm::ArrayRef<GenericParamDescriptor> getGenericParams() const;
 
+  bool isSynthesizedRelatedEntity() const {
+    return getTypeContextDescriptorFlags().isSynthesizedRelatedEntity();
+  }
+
+  /// Return the tag used to discriminate declarations synthesized by the
+  /// Clang importer and give them stable identities.
+  StringRef getSynthesizedDeclRelatedEntityTag() const {
+    if (!isSynthesizedRelatedEntity())
+      return {};
+    // The tag name comes after the null terminator for the name.
+    const char *nameBegin = Name.get();
+    auto *nameEnd = nameBegin + strlen(nameBegin) + 1;
+    return nameEnd;
+  }
+
   /// Return the offset of the start of generic arguments in the nominal
   /// type's metadata. The returned value is measured in sizeof(void*).
   int32_t getGenericArgumentOffset() const;
diff --git a/include/swift/SILOptimizer/Analysis/ARCAnalysis.h b/include/swift/SILOptimizer/Analysis/ARCAnalysis.h
index 31e508f..f98e4ba 100644
--- a/include/swift/SILOptimizer/Analysis/ARCAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/ARCAnalysis.h
@@ -13,16 +13,17 @@
 #ifndef SWIFT_SILOPTIMIZER_ANALYSIS_ARCANALYSIS_H
 #define SWIFT_SILOPTIMIZER_ANALYSIS_ARCANALYSIS_H
 
+#include "swift/Basic/LLVM.h"
 #include "swift/SIL/SILArgument.h"
-#include "swift/SIL/SILValue.h"
 #include "swift/SIL/SILBasicBlock.h"
+#include "swift/SIL/SILValue.h"
 #include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
 #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
 #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h"
 #include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/TinyPtrVector.h"
 
 namespace swift {
@@ -147,7 +148,8 @@
 
   /// Return true if all the successors of the EpilogueRetainInsts do not have
   /// a retain. 
-  bool isTransitiveSuccessorsRetainFree(llvm::DenseSet<SILBasicBlock *> BBs);
+  bool
+  isTransitiveSuccessorsRetainFree(const llvm::DenseSet<SILBasicBlock *> &BBs);
 
   /// Finds matching releases in the provided block \p BB.
   RetainKindValue findMatchingRetainsInBasicBlock(SILBasicBlock *BB, SILValue V);
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index cc88090..0e6cc67 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -739,31 +739,18 @@
       auto aliasTy = cast<NameAliasType>(tybase);
 
       // It's not possible to mangle the context of the builtin module.
-      // For the DWARF output we want to mangle the type alias + context,
-      // unless the type alias references a builtin type.
       TypeAliasDecl *decl = aliasTy->getDecl();
       if (decl->getModuleContext() == decl->getASTContext().TheBuiltinModule) {
         return appendType(aliasTy->getSinglyDesugaredType());
       }
 
-      if (type->isSpecialized()) {
-        // Try to mangle the entire name as a substitution.
-        if (tryMangleSubstitution(tybase))
-          return;
+      // FIXME: We also cannot yet mangle references to typealiases that
+      // involve generics.
+      if (decl->getGenericSignature())
+        return appendSugaredType<NameAliasType>(type);
 
-        appendAnyGenericType(decl);
-        bool isFirstArgList = true;
-        if (auto *nominalType = type->getAs<NominalType>()) {
-          if (nominalType->getParent())
-            type = nominalType->getParent();
-        }
-        appendBoundGenericArgs(type, isFirstArgList);
-        appendRetroactiveConformances(type);
-        appendOperator("G");
-        addSubstitution(type.getPointer());
-        return;
-      }
-
+      // For the DWARF output we want to mangle the type alias + context,
+      // unless the type alias references a builtin type.
       return appendAnyGenericType(decl);
     }
 
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index 7d21b60..9d2fa8d 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -1335,9 +1335,6 @@
     case Node::Kind::OtherNominalType:
       kind = Node::Kind::BoundGenericOtherNominalType;
       break;
-    case Node::Kind::TypeAlias:
-      kind = Node::Kind::BoundGenericTypeAlias;
-      break;
     default:
       return nullptr;
   }
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index 866318b..7703600 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -267,7 +267,6 @@
     case Node::Kind::BoundGenericEnum:
     case Node::Kind::BoundGenericStructure:
     case Node::Kind::BoundGenericOtherNominalType:
-    case Node::Kind::BoundGenericTypeAlias:
     case Node::Kind::BuiltinTypeName:
     case Node::Kind::Class:
     case Node::Kind::DependentGenericType:
@@ -1541,7 +1540,6 @@
   case Node::Kind::BoundGenericStructure:
   case Node::Kind::BoundGenericEnum:
   case Node::Kind::BoundGenericOtherNominalType:
-  case Node::Kind::BoundGenericTypeAlias:
     printBoundGeneric(Node);
     return nullptr;
   case Node::Kind::DynamicSelf:
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index 30cad13..4c8562a 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -1875,11 +1875,6 @@
   mangleAnyNominalType(node, ctx);
 }
 
-void Remangler::mangleBoundGenericTypeAlias(Node *node) {
-  EntityContext ctx;
-  mangleAnyNominalType(node, ctx);
-}
-
 void Remangler::mangleTypeList(Node *node) {
   mangleChildNodes(node); // all types
   Out << '_';
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index ee3807f..8219f88 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -463,7 +463,6 @@
     case Node::Kind::Enum: return mangleAnyGenericType(node, "O");
     case Node::Kind::Class: return mangleAnyGenericType(node, "C");
     case Node::Kind::OtherNominalType: return mangleAnyGenericType(node, "XY");
-    case Node::Kind::TypeAlias: return mangleAnyGenericType(node, "a");
     default:
       unreachable("bad nominal type kind");
   }
@@ -482,8 +481,7 @@
     case Node::Kind::BoundGenericOtherNominalType:
     case Node::Kind::BoundGenericStructure:
     case Node::Kind::BoundGenericEnum:
-    case Node::Kind::BoundGenericClass:
-    case Node::Kind::BoundGenericTypeAlias: {
+    case Node::Kind::BoundGenericClass: {
       NodePointer unboundType = node->getChild(0);
       assert(unboundType->getKind() == Node::Kind::Type);
       NodePointer nominalType = unboundType->getChild(0);
@@ -595,10 +593,6 @@
   mangleAnyNominalType(node);
 }
 
-void Remangler::mangleBoundGenericTypeAlias(Node *node) {
-  mangleAnyNominalType(node);
-}
-
 void Remangler::mangleBuiltinTypeName(Node *node) {
   Buffer << 'B';
   StringRef text = node->getText();
@@ -2037,7 +2031,6 @@
     case Node::Kind::BoundGenericEnum:
     case Node::Kind::BoundGenericClass:
     case Node::Kind::BoundGenericOtherNominalType:
-    case Node::Kind::BoundGenericTypeAlias:
       return true;
 
     case Node::Kind::Structure:
@@ -2073,8 +2066,7 @@
     case Node::Kind::BoundGenericStructure:
     case Node::Kind::BoundGenericEnum:
     case Node::Kind::BoundGenericClass:
-    case Node::Kind::BoundGenericOtherNominalType:
-    case Node::Kind::BoundGenericTypeAlias: {
+    case Node::Kind::BoundGenericOtherNominalType: {
       NodePointer unboundType = node->getChild(0);
       assert(unboundType->getKind() == Node::Kind::Type);
       NodePointer nominalType = unboundType->getChild(0);
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 975276f..1b9b982 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -4115,6 +4115,9 @@
 // layout. Calling isResilient() with this scope will always return false.
 ResilienceExpansion
 IRGenModule::getResilienceExpansionForLayout(NominalTypeDecl *decl) {
+  if (Types.isCompletelyFragile())
+    return ResilienceExpansion::Minimal;
+
   if (isResilient(decl, ResilienceExpansion::Minimal))
     return ResilienceExpansion::Maximal;
 
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index f247427..485a93a 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -481,11 +481,21 @@
     }
     
     void addName() {
+      SmallString<32> nameBuf;
       StringRef name;
-      
+
+      // Use the original name with tag for synthesized decls. The tag comes
+      // after the null terminator for the name.
+      if (auto *synthesizedTypeAttr =
+            Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+        nameBuf.append(synthesizedTypeAttr->originalTypeName);
+        nameBuf.push_back('\0');
+        nameBuf.append(synthesizedTypeAttr->getManglingName());
+        
+        name = nameBuf;
       // Try to use the Clang name if there is one.
-      if (auto namedClangDecl =
-                             Mangle::ASTMangler::getClangDeclForMangling(Type)) {
+      } else if (auto namedClangDecl =
+                            Mangle::ASTMangler::getClangDeclForMangling(Type)) {
         name = namedClangDecl->getName();
       } else {
         name = Type->getName().str();
@@ -565,22 +575,18 @@
     /// Flags to indicate Clang-imported declarations so we mangle them
     /// consistently at runtime.
     void getClangImportedFlags(TypeContextDescriptorFlags &flags) const {
-      auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type);
-      if (!clangDecl)
-        return;
-      
-      if (isa<clang::TagDecl>(clangDecl)) {
-        flags.setIsCTag(true);
-        return;
+      if (Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+        flags.setIsSynthesizedRelatedEntity(true);
       }
       
-      if (isa<clang::TypedefNameDecl>(clangDecl)
-          || isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
-        flags.setIsCTypedef(true);
-        return;
+      if (auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type)) {
+        if (isa<clang::TagDecl>(clangDecl)) {
+          flags.setIsCTag(true);
+        } else if (isa<clang::TypedefNameDecl>(clangDecl)
+                   || isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
+          flags.setIsCTypedef(true);
+        }
       }
-      
-      return;
     }
 
     // Subclasses should provide:
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index cdeda25..29c67fc 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -753,7 +753,17 @@
       if (HadError) return;
       if (decl == Result) return;
       if (!Result) {
-        Result = cast<NominalTypeDecl>(decl);
+        // A synthesized type from the Clang importer may resolve to a
+        // compatibility alias.
+        if (auto resultAlias = dyn_cast<TypeAliasDecl>(decl)) {
+          if (resultAlias->isCompatibilityAlias()) {
+            Result = resultAlias->getUnderlyingTypeLoc().getType()
+                                ->getAnyNominal();
+          }
+        } else {
+          Result = dyn_cast<NominalTypeDecl>(decl);
+        }
+        HadError |= !Result;
       } else {
         HadError = true;
         Result = nullptr;
diff --git a/lib/SIL/Projection.cpp b/lib/SIL/Projection.cpp
index e6c774a..a29f259 100644
--- a/lib/SIL/Projection.cpp
+++ b/lib/SIL/Projection.cpp
@@ -840,6 +840,24 @@
   return Proj->createProjection(B, Loc, Arg);
 }
 
+// Projection tree only supports structs and tuples today.
+static bool isSupportedProjection(const Projection &p) {
+  switch (p.getKind()) {
+  case ProjectionKind::Struct:
+  case ProjectionKind::Tuple:
+    return true;
+  case ProjectionKind::Class:
+  case ProjectionKind::Enum:
+  case ProjectionKind::Box:
+  case ProjectionKind::Upcast:
+  case ProjectionKind::RefCast:
+  case ProjectionKind::BitwiseCast:
+  case ProjectionKind::TailElems:
+  case ProjectionKind::Index:
+    return false;
+  }
+}
+
 void
 ProjectionTreeNode::
 processUsersOfValue(ProjectionTree &Tree,
@@ -863,12 +881,11 @@
       continue;
     }
 
-    // Check whether the user is such a projection.
     auto P = Projection(projectionInst);
 
-    // If we fail to create a projection, add User as a user to this node and
-    // continue.
-    if (!P.isValid()) {
+    // If we fail to create a projection or this is a type of projection that we
+    // do not support, add User as a user to this node and continue.
+    if (!P.isValid() || !isSupportedProjection(P)) {
       DEBUG(llvm::dbgs() << "            Failed to create projection. Adding "
             "to non projection user!\n");
       addNonProjectionUser(Op);
diff --git a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
index c9a3ea2..93e0553 100644
--- a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
@@ -498,22 +498,24 @@
   findMatchingRetains(&*BB);
 }
 
-bool
-ConsumedResultToEpilogueRetainMatcher::
-isTransitiveSuccessorsRetainFree(llvm::DenseSet<SILBasicBlock *> BBs) {
+bool ConsumedResultToEpilogueRetainMatcher::isTransitiveSuccessorsRetainFree(
+    const llvm::DenseSet<SILBasicBlock *> &BBs) {
   // For every block with retain, we need to check the transitive
   // closure of its successors are retain-free.
   for (auto &I : EpilogueRetainInsts) {
-    auto *CBB = I->getParent();
-    for (auto &Succ : CBB->getSuccessors()) {
-      if (BBs.find(Succ) != BBs.end())
+    for (auto &Succ : I->getParent()->getSuccessors()) {
+      if (BBs.count(Succ))
         continue;
       return false;
     }
   }
+
+  // FIXME: We are iterating over a DenseSet. That can lead to non-determinism
+  // and is in general pretty inefficient since we are iterating over a hash
+  // table.
   for (auto CBB : BBs) {
     for (auto &Succ : CBB->getSuccessors()) {
-      if (BBs.find(Succ) != BBs.end())
+      if (BBs.count(Succ))
         continue;
       return false;
     }
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index decc345..c877936 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -129,17 +129,6 @@
 const char ExtensionError::ID = '\0';
 void ExtensionError::anchor() {}
 
-LLVM_NODISCARD
-static std::unique_ptr<llvm::ErrorInfoBase> takeErrorInfo(llvm::Error error) {
-  std::unique_ptr<llvm::ErrorInfoBase> result;
-  llvm::handleAllErrors(std::move(error),
-                        [&](std::unique_ptr<llvm::ErrorInfoBase> info) {
-    result = std::move(info);
-  });
-  return result;
-}
-
-
 /// Skips a single record in the bitstream.
 ///
 /// Returns true if the next entry is a record of type \p recordKind.
@@ -4816,27 +4805,42 @@
     }
 
     auto processParameter = [&](TypeID typeID, uint64_t rawConvention)
-                                  -> Optional<SILParameterInfo> {
+                                  -> llvm::Expected<SILParameterInfo> {
       auto convention = getActualParameterConvention(rawConvention);
-      auto type = getType(typeID);
-      if (!convention || !type) return None;
-      return SILParameterInfo(type->getCanonicalType(), *convention);
+      if (!convention) {
+        error();
+        llvm_unreachable("an error is a fatal exit at this point");
+      }
+      auto type = getTypeChecked(typeID);
+      if (!type)
+        return type.takeError();
+      return SILParameterInfo(type.get()->getCanonicalType(), *convention);
     };
 
     auto processYield = [&](TypeID typeID, uint64_t rawConvention)
-                                  -> Optional<SILYieldInfo> {
+                                  -> llvm::Expected<SILYieldInfo> {
       auto convention = getActualParameterConvention(rawConvention);
-      auto type = getType(typeID);
-      if (!convention || !type) return None;
-      return SILYieldInfo(type->getCanonicalType(), *convention);
+      if (!convention) {
+        error();
+        llvm_unreachable("an error is a fatal exit at this point");
+      }
+      auto type = getTypeChecked(typeID);
+      if (!type)
+        return type.takeError();
+      return SILYieldInfo(type.get()->getCanonicalType(), *convention);
     };
 
     auto processResult = [&](TypeID typeID, uint64_t rawConvention)
-                               -> Optional<SILResultInfo> {
+                               -> llvm::Expected<SILResultInfo> {
       auto convention = getActualResultConvention(rawConvention);
-      auto type = getType(typeID);
-      if (!convention || !type) return None;
-      return SILResultInfo(type->getCanonicalType(), *convention);
+      if (!convention) {
+        error();
+        llvm_unreachable("an error is a fatal exit at this point");
+      }
+      auto type = getTypeChecked(typeID);
+      if (!type)
+        return type.takeError();
+      return SILResultInfo(type.get()->getCanonicalType(), *convention);
     };
 
     // Bounds check.  FIXME: overflow
@@ -4855,11 +4859,9 @@
       auto typeID = variableData[nextVariableDataIndex++];
       auto rawConvention = variableData[nextVariableDataIndex++];
       auto param = processParameter(typeID, rawConvention);
-      if (!param) {
-        error();
-        return nullptr;
-      }
-      allParams.push_back(*param);
+      if (!param)
+        return param.takeError();
+      allParams.push_back(param.get());
     }
 
     // Process the yields.
@@ -4869,11 +4871,9 @@
       auto typeID = variableData[nextVariableDataIndex++];
       auto rawConvention = variableData[nextVariableDataIndex++];
       auto yield = processYield(typeID, rawConvention);
-      if (!yield) {
-        error();
-        return nullptr;
-      }
-      allYields.push_back(*yield);
+      if (!yield)
+        return yield.takeError();
+      allYields.push_back(yield.get());
     }
 
     // Process the results.
@@ -4883,11 +4883,9 @@
       auto typeID = variableData[nextVariableDataIndex++];
       auto rawConvention = variableData[nextVariableDataIndex++];
       auto result = processResult(typeID, rawConvention);
-      if (!result) {
-        error();
-        return nullptr;
-      }
-      allResults.push_back(*result);
+      if (!result)
+        return result.takeError();
+      allResults.push_back(result.get());
     }
 
     // Process the error result.
@@ -4895,11 +4893,10 @@
     if (hasErrorResult) {
       auto typeID = variableData[nextVariableDataIndex++];
       auto rawConvention = variableData[nextVariableDataIndex++];
-      errorResult = processResult(typeID, rawConvention);
-      if (!errorResult) {
-        error();
-        return nullptr;
-      }
+      auto maybeErrorResult = processResult(typeID, rawConvention);
+      if (!maybeErrorResult)
+        return maybeErrorResult.takeError();
+      errorResult = maybeErrorResult.get();
     }
 
     Optional<ProtocolConformanceRef> witnessMethodConformance;
diff --git a/lib/Serialization/DeserializationErrors.h b/lib/Serialization/DeserializationErrors.h
index 0703ea4..dc0e952 100644
--- a/lib/Serialization/DeserializationErrors.h
+++ b/lib/Serialization/DeserializationErrors.h
@@ -355,6 +355,41 @@
   }
 };
 
+class SILEntityError : public llvm::ErrorInfo<SILEntityError> {
+  friend ErrorInfo;
+  static const char ID;
+  void anchor() override;
+
+  std::unique_ptr<ErrorInfoBase> underlyingReason;
+  StringRef name;
+public:
+  SILEntityError(StringRef name, std::unique_ptr<ErrorInfoBase> reason)
+      : underlyingReason(std::move(reason)), name(name) {}
+
+  void log(raw_ostream &OS) const override {
+    OS << "could not deserialize SIL entity '" << name << "'";
+    if (underlyingReason) {
+      OS << ": ";
+      underlyingReason->log(OS);
+    }
+  }
+
+  std::error_code convertToErrorCode() const override {
+    return llvm::inconvertibleErrorCode();
+  }
+};
+
+LLVM_NODISCARD
+static inline std::unique_ptr<llvm::ErrorInfoBase>
+takeErrorInfo(llvm::Error error) {
+  std::unique_ptr<llvm::ErrorInfoBase> result;
+  llvm::handleAllErrors(std::move(error),
+                        [&](std::unique_ptr<llvm::ErrorInfoBase> info) {
+    result = std::move(info);
+  });
+  return result;
+}
+
 class PrettyStackTraceModuleFile : public llvm::PrettyStackTraceEntry {
   const char *Action;
   const ModuleFile &MF;
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 1c2ad04..75b8a45 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -12,13 +12,16 @@
 
 #define DEBUG_TYPE "deserialize"
 #include "DeserializeSIL.h"
+
+#include "DeserializationErrors.h"
+#include "SILFormat.h"
+
 #include "swift/Basic/Defer.h"
 #include "swift/Basic/PrettyStackTrace.h"
 #include "swift/AST/GenericSignature.h"
 #include "swift/AST/ProtocolConformance.h"
 #include "swift/AST/PrettyStackTrace.h"
 #include "swift/Serialization/ModuleFile.h"
-#include "SILFormat.h"
 #include "swift/SIL/SILArgument.h"
 #include "swift/SIL/SILBuilder.h"
 #include "swift/SIL/SILDebugScope.h"
@@ -38,6 +41,9 @@
 using namespace swift::serialization::sil_block;
 using namespace llvm::support;
 
+const char SILEntityError::ID = '\0';
+void SILEntityError::anchor() {}
+
 STATISTIC(NumDeserializedFunc, "Number of deserialized SIL functions");
 
 static Optional<StringLiteralInst::Encoding>
@@ -340,7 +346,14 @@
     // Otherwise, look for a function with this name in the module.
     auto iter = FuncTable->find(name);
     if (iter != FuncTable->end()) {
-      fn = readSILFunction(*iter, nullptr, name, /*declarationOnly*/ true);
+      auto maybeFn = readSILFunctionChecked(*iter, nullptr, name,
+                                            /*declarationOnly*/ true);
+      if (maybeFn) {
+        fn = maybeFn.get();
+      } else {
+        // Ignore the failure; we'll synthesize a bogus function instead.
+        llvm::consumeError(maybeFn.takeError());
+      }
     }
   }
 
@@ -363,7 +376,15 @@
   if (iter == FuncTable->end())
     return nullptr;
 
-  return readSILFunction(*iter, nullptr, name, /*declarationOnly*/ true);
+  auto maybeFn = readSILFunctionChecked(*iter, nullptr, name,
+                                        /*declarationOnly*/ true);
+  if (!maybeFn) {
+    // Ignore the failure and just pretend the function doesn't exist
+    llvm::consumeError(maybeFn.takeError());
+    return nullptr;
+  }
+
+  return maybeFn.get();
 }
 
 /// Helper function to find a SILGlobalVariable given its name. It first checks
@@ -387,6 +408,19 @@
                                               StringRef name,
                                               bool declarationOnly,
                                               bool errorIfEmptyBody) {
+  llvm::Expected<SILFunction *> deserialized =
+      readSILFunctionChecked(FID, existingFn, name, declarationOnly,
+                             errorIfEmptyBody);
+  if (!deserialized) {
+    MF->fatal(deserialized.takeError());
+  }
+  return deserialized.get();
+}
+
+llvm::Expected<SILFunction *>
+SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
+                                        StringRef name, bool declarationOnly,
+                                        bool errorIfEmptyBody) {
   // We can't deserialize function bodies after IRGen lowering passes have
   // happened since other definitions in the module will no longer be in
   // canonical SIL form.
@@ -445,7 +479,16 @@
     MF->error();
     return nullptr;
   }
-  auto ty = getSILType(MF->getType(funcTyID), SILValueCategory::Object);
+  auto astType = MF->getTypeChecked(funcTyID);
+  if (!astType) {
+    if (!existingFn || errorIfEmptyBody) {
+      return llvm::make_error<SILEntityError>(
+          name, takeErrorInfo(astType.takeError()));
+    }
+    llvm::consumeError(astType.takeError());
+    return existingFn;
+  }
+  auto ty = getSILType(astType.get(), SILValueCategory::Object);
   if (!ty.is<SILFunctionType>()) {
     DEBUG(llvm::dbgs() << "not a function type for SILFunction\n");
     MF->error();
@@ -2433,14 +2476,21 @@
   if (iter == FuncTable->end())
     return nullptr;
 
-  auto Func = readSILFunction(*iter, InFunc, name, /*declarationOnly*/ false);
-  if (Func) {
-    DEBUG(llvm::dbgs() << "Deserialize SIL:\n";
-          Func->dump());
-    assert(InFunc->getName() == Func->getName());
+  auto maybeFunc = readSILFunctionChecked(*iter, InFunc, name,
+                                          /*declarationOnly*/ false);
+  if (!maybeFunc) {
+    // Ignore the error; treat it as if we didn't have a definition.
+    llvm::consumeError(maybeFunc.takeError());
+    return nullptr;
   }
 
-  return Func;
+  if (maybeFunc.get()) {
+    DEBUG(llvm::dbgs() << "Deserialize SIL:\n";
+          maybeFunc.get()->dump());
+    assert(InFunc->getName() == maybeFunc.get()->getName());
+  }
+
+  return maybeFunc.get();
 }
 
 /// Check for existence of a function with a given name and required linkage.
@@ -2517,11 +2567,20 @@
   if (iter == FuncTable->end())
     return nullptr;
 
-  auto Func = readSILFunction(*iter, nullptr, name, declarationOnly);
-  if (Func)
+  auto maybeFunc = readSILFunctionChecked(*iter, nullptr, name,
+                                          declarationOnly);
+
+  if (!maybeFunc) {
+    // Ignore the error; treat it as if we didn't have a definition.
+    llvm::consumeError(maybeFunc.takeError());
+    return nullptr;
+  }
+
+  if (maybeFunc.get()) {
     DEBUG(llvm::dbgs() << "Deserialize SIL:\n";
-          Func->dump());
-  return Func;
+          maybeFunc.get()->dump());
+  }
+  return maybeFunc.get();
 }
 
 SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
@@ -2617,8 +2676,12 @@
     auto DI = FuncTable->find(*KI);
     assert(DI != FuncTable->end() && "There should never be a key without data.");
 
-    readSILFunction(*DI, nullptr, *KI, false,
-                    false/*errorIfEmptyBody*/);
+    auto maybeFunc = readSILFunctionChecked(*DI, nullptr, *KI, false,
+                                            false/*errorIfEmptyBody*/);
+    if (!maybeFunc) {
+      // Ignore the error; treat it as if we didn't have a definition.
+      llvm::consumeError(maybeFunc.takeError());
+    }
   }
 }
 
diff --git a/lib/Serialization/DeserializeSIL.h b/lib/Serialization/DeserializeSIL.h
index 15ea040..b4a4f30 100644
--- a/lib/Serialization/DeserializeSIL.h
+++ b/lib/Serialization/DeserializeSIL.h
@@ -79,6 +79,12 @@
     SILFunction *readSILFunction(serialization::DeclID, SILFunction *InFunc,
                                  StringRef Name, bool declarationOnly,
                                  bool errorIfEmptyBody = true);
+    /// Read a SIL function.
+    llvm::Expected<SILFunction *>
+    readSILFunctionChecked(serialization::DeclID, SILFunction *InFunc,
+                           StringRef Name, bool declarationOnly,
+                           bool errorIfEmptyBody = true);
+
     /// Read a SIL basic block within a given SIL function.
     SILBasicBlock *readSILBasicBlock(SILFunction *Fn,
                                      SILBasicBlock *Prev,
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 4a3f522..21547d7 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -160,8 +160,14 @@
         
         auto typeNode = Dem.createNode(nodeKind);
         typeNode->addChild(node, Dem);
-        auto identifier = Dem.createNode(Node::Kind::Identifier, name);
-        typeNode->addChild(identifier, Dem);
+        auto nameNode = Dem.createNode(Node::Kind::Identifier, name);
+        if (type->isSynthesizedRelatedEntity()) {
+          auto relatedName = Dem.createNode(Node::Kind::RelatedEntityDeclName,
+                                    type->getSynthesizedDeclRelatedEntityTag());
+          relatedName->addChild(nameNode, Dem);
+          nameNode = relatedName;
+        }
+        typeNode->addChild(nameNode, Dem);
         node = typeNode;
         
         // Apply generic arguments if the context is generic.
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 66be4c1..47c174e 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -1488,7 +1488,20 @@
         && kind <= ContextDescriptorKind::Type_Last) {
       auto typeA = cast<TypeContextDescriptor>(a);
       auto typeB = cast<TypeContextDescriptor>(b);
-      return strcmp(typeA->Name.get(), typeB->Name.get()) == 0;
+      if (strcmp(typeA->Name.get(), typeB->Name.get()) != 0)
+        return false;
+      
+      // A synthesized entity has to match the related entity tag too.
+      if (typeA->isSynthesizedRelatedEntity()) {
+        if (!typeB->isSynthesizedRelatedEntity())
+          return false;
+        
+        if (typeA->getSynthesizedDeclRelatedEntityTag()
+            != typeB->getSynthesizedDeclRelatedEntityTag())
+          return false;
+      }
+      
+      return true;
     }
     
     // Otherwise, this runtime doesn't know anything about this context kind.
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index a239b0b..be28b62 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -264,14 +264,31 @@
         }
 
         auto nameNode = node->getChild(1);
-        if (nameNode->getKind() == Demangle::Node::Kind::PrivateDeclName)
-          return false;
-
-        if (nameNode->getText() != type->Name.get())
-          return false;
         
-        node = node->getChild(0);
-        break;
+        // Declarations synthesized by the Clang importer get a small tag
+        // string in addition to their name.
+        if (nameNode->getKind() == Demangle::Node::Kind::RelatedEntityDeclName){
+          if (nameNode->getText() != type->getSynthesizedDeclRelatedEntityTag())
+            return false;
+          
+          nameNode = nameNode->getChild(0);
+        } else if (type->isSynthesizedRelatedEntity()) {
+          return false;
+        }
+        
+        // We should only match public or internal declarations with stable
+        // names. The runtime metadata for private declarations would be
+        // anonymized.
+        if (nameNode->getKind() == Demangle::Node::Kind::Identifier) {
+          if (nameNode->getText() != type->Name.get())
+            return false;
+          
+          node = node->getChild(0);
+          break;
+        }
+        
+        return false;
+
       }
       
       // We don't know about this kind of context, or it doesn't have a stable
@@ -1166,7 +1183,7 @@
     if (typeInfo == nullptr) {
       typeInfo = TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {});
       warning(0, "SWIFT RUNTIME BUG: unable to demangle type of field '%*s'. "
-                 "mangled type name is '%*s'",
+                 "mangled type name is '%*s'\n",
                  (int)name.size(), name.data(),
                  (int)typeName.size(), typeName.data());
     }
@@ -1214,6 +1231,17 @@
         return;
     }
   }
+
+  // If we failed to find the field descriptor metadata for the type, fall
+  // back to returning an empty tuple as a standin.
+  auto typeName = swift_getTypeName(base, /*qualified*/ true);
+  warning(0, "SWIFT RUNTIME BUG: unable to find field metadata for type '%*s'\n",
+             (int)typeName.length, typeName.data);
+  callback("unknown",
+           FieldType()
+             .withType(TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {}))
+             .withIndirect(false)
+             .withWeak(false));
 }
 
 #define OVERRIDE_METADATALOOKUP COMPATIBILITY_OVERRIDE
diff --git a/test/ClangImporter/objc_ir.swift b/test/ClangImporter/objc_ir.swift
index ca3a76e..812b8eb 100644
--- a/test/ClangImporter/objc_ir.swift
+++ b/test/ClangImporter/objc_ir.swift
@@ -363,7 +363,5 @@
 // CHECK: ![[SWIFT_NAME_ALIAS_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$SSo14SwiftNameAliasaD", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, baseType: !{{[0-9]+}})
 
 // CHECK: ![[SWIFT_GENERIC_NAME_ALIAS_VAR]] = !DILocalVariable(name: "generic_obj", arg: 1, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[SWIFT_GENERIC_NAME_ALIAS_TYPE:[0-9]+]])
-// CHECK: ![[SWIFT_GENERIC_NAME_ALIAS_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$SSo21SwiftGenericNameAliasaySo8NSNumberCGD", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, baseType: !{{[0-9]+}})
 
 // CHECK: ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_VAR]] = !DILocalVariable(name: "constr_generic_obj", arg: 1, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_TYPE:[0-9]+]])
-// CHECK: ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$SSo27SwiftConstrGenericNameAliasaySo8NSNumberCGD", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, baseType: !{{[0-9]+}})
diff --git a/test/DebugInfo/DumpDeclFromMangledName.swift b/test/DebugInfo/DumpDeclFromMangledName.swift
index 4b8bcef..a81abe3 100644
--- a/test/DebugInfo/DumpDeclFromMangledName.swift
+++ b/test/DebugInfo/DumpDeclFromMangledName.swift
@@ -39,3 +39,56 @@
 }
 
 patatino()
+
+class Foo<T> {
+  var x : T
+  init(_ x : T) {
+    self.x = x
+  }
+}
+
+typealias Patatino<T> = Foo<T>
+
+public struct Outer<T> {
+  public struct Inner { }
+  public struct GenericInner<U> { }
+
+  public typealias Foo<U> = Outer<U>.Inner
+
+  public func blah() {
+    let foo: Foo<Int> = Outer<Int>.Inner()
+  }
+}
+
+extension Outer.GenericInner {
+  public typealias Bar = Int
+
+  public func useBar() {
+    let bar: Bar = 7
+  }
+}
+
+protocol P {
+  associatedtype A
+}
+
+protocol Q {
+  associatedtype B: P
+  typealias ProtocolTypeAliasThing = B.A
+}
+
+struct ConformsToP: P {
+  typealias A = Int
+}
+
+struct ConformsToQ: Q {
+  typealias B = ConformsToP
+}
+
+struct Blah {
+  typealias SomeQ = ConformsToQ
+
+  func foo() {
+    let bar: SomeQ.ProtocolTypeAliasThing? = nil
+  }
+}
diff --git a/test/DebugInfo/guard-let.swift b/test/DebugInfo/guard-let.swift
index 2db51a4..ddf4ee3 100644
--- a/test/DebugInfo/guard-let.swift
+++ b/test/DebugInfo/guard-let.swift
@@ -21,9 +21,13 @@
   use(val)
 }
 
-// With large type optimizations the string is passed indirectly on i386 so
-// there is no shadow copy happening.
+// With large type optimizations the string is passed indirectly on the
+// following architectures so there is no shadow copy happening. As this
+// tests that we're emitting the DI correctly, we can skip running on them.
 // UNSUPPORTED: CPU=i386
+// UNSUPPORTED: CPU=armv7
+// UNSUPPORTED: CPU=armv7s
+// UNSUPPORTED: CPU=armv7k
 
 public func g(_ s : String?)
 {
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index a007915..830e783 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -310,5 +310,4 @@
 _$S3BBBBi0602365061_ ---> _$S3BBBBi0602365061_
 _$S3BBBBv0602365061_ ---> _$S3BBBBv0602365061_
 _T0lxxxmmmTk ---> _T0lxxxmmmTk
-$S4blah8PatatinoaySiGD -> blah.Patatino<Swift.Int>
 
diff --git a/test/IRGen/enum_resilience_objc.swift b/test/IRGen/enum_resilience_objc.swift
new file mode 100644
index 0000000..1a582d4
--- /dev/null
+++ b/test/IRGen/enum_resilience_objc.swift
@@ -0,0 +1,25 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -module-name enum_resilience -I %t -emit-ir -enable-resilience %s | %FileCheck %s -DINT=i%target-ptrsize
+// RUN: %target-swift-frontend -module-name enum_resilience -I %t -emit-ir -enable-resilience -O %s
+
+// REQUIRES: objc_interop
+
+// Because the enum is resilient we cannot pack the tag into the pointer inside of the resilient payload.
+// CHECK: %T15enum_resilience9ContainerC5Multi33_{{.*}}LLO.0 = type <{ [{{(8|4)}} x i8], [1 x i8] }>
+
+import resilient_struct
+
+public class Container {
+  private enum Multi {
+    case none
+    case some(Container)
+    case data(ResilientRef)
+  }
+  private var e: Multi
+  var i: Int
+  init() {
+    e = .none
+    i = 0
+  }
+}
diff --git a/test/Inputs/resilient_struct.swift b/test/Inputs/resilient_struct.swift
index 01982d4..37b52da 100644
--- a/test/Inputs/resilient_struct.swift
+++ b/test/Inputs/resilient_struct.swift
@@ -77,3 +77,17 @@
     self.d = d
   }
 }
+
+public class Referent {}
+
+public struct ResilientWeakRef {
+  public weak var ref: Referent?
+
+  public init (_ r: Referent) {
+    ref = r
+  }
+}
+
+public struct ResilientRef {
+  public var r: Referent
+}
diff --git a/test/Interpreter/enum_resilience.swift b/test/Interpreter/enum_resilience.swift
index 3db9e03..9c68d42 100644
--- a/test/Interpreter/enum_resilience.swift
+++ b/test/Interpreter/enum_resilience.swift
@@ -436,4 +436,28 @@
   expectEqual(Base.self, ResilientMultiPayloadGenericEnumFixedSize<Base>.A.getTypeParameter())
 }
 
+public class Container {
+  private enum Multi {
+    case none
+    case some(Container)
+    case other(ResilientRef)
+  }
+  private var m: Multi
+  var i: Int
+  init() {
+    m = .none
+    i = 0
+    switch self.m {
+      case .none:
+        print("success")
+      case .some(_), .other(_):
+        assert(false, "noooo!")
+    }
+  }
+}
+
+ResilientEnumTestSuite.test("ResilientPrivateEnumMember") {
+  _ = Container()
+}
+
 runAllTests()
diff --git a/test/Runtime/Inputs/synthesized_decl_uniqueness.swift b/test/Runtime/Inputs/synthesized_decl_uniqueness.swift
new file mode 100644
index 0000000..5157acc
--- /dev/null
+++ b/test/Runtime/Inputs/synthesized_decl_uniqueness.swift
@@ -0,0 +1,9 @@
+import CoreLocation
+
+public func getCLError() -> Any.Type {
+  return CLError.self
+}
+
+public func getCLErrorCode() -> Any.Type {
+  return CLError.Code.self
+}
diff --git a/test/Runtime/demangleToMetadataObjC.swift b/test/Runtime/demangleToMetadataObjC.swift
index 606f111..11ba20d 100644
--- a/test/Runtime/demangleToMetadataObjC.swift
+++ b/test/Runtime/demangleToMetadataObjC.swift
@@ -5,6 +5,7 @@
 import StdlibUnittest
 import Foundation
 import CoreFoundation
+import CoreLocation
 
 let DemangleToMetadataTests = TestSuite("DemangleToMetadataObjC")
 
@@ -74,5 +75,15 @@
   expectNil(_typeByMangledName("4main3CG4CyAA1DCAA1DCG"))
 }
 
+DemangleToMetadataTests.test("synthesized declarations") {
+  expectEqual(CLError.self, _typeByMangledName("SC7CLErrorLeV")!)
+  expectNil(_typeByMangledName("SC7CLErrorV"))
+  expectEqual(CLError.Code.self, _typeByMangledName("So7CLErrorV")!)
+
+  let error = NSError(domain: NSCocoaErrorDomain, code: 0)
+  let reflectionString = String(reflecting: CLError(_nsError: error))
+  expectTrue(reflectionString.hasPrefix("__C_Synthesized.related decl 'e' for CLError(_nsError:"))
+}
+
 runAllTests()
 
diff --git a/test/Runtime/synthesized_decl_uniqueness.swift b/test/Runtime/synthesized_decl_uniqueness.swift
new file mode 100644
index 0000000..e47aea0
--- /dev/null
+++ b/test/Runtime/synthesized_decl_uniqueness.swift
@@ -0,0 +1,21 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -parse-as-library -force-single-frontend-invocation %S/Inputs/synthesized_decl_uniqueness.swift -emit-object -o %t/A.o -module-name A -emit-module-path %t/A.swiftmodule
+// RUN: %target-build-swift -parse-as-library -force-single-frontend-invocation %S/Inputs/synthesized_decl_uniqueness.swift -emit-object -o %t/B.o -module-name B -emit-module-path %t/B.swiftmodule
+// RUN: %target-build-swift -I %t %s %t/A.o %t/B.o -o %t/a.out
+// RUN: %target-run %t/a.out
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import StdlibUnittest
+import A
+import B
+
+var tests = TestSuite("metadata identity for synthesized types")
+
+tests.test("synthesized type identity across modules") {
+  expectEqual(A.getCLError(), B.getCLError())
+  expectEqual(A.getCLErrorCode(), B.getCLErrorCode())
+}
+
+runAllTests()
diff --git a/test/SIL/Serialization/Recovery/Inputs/bad-modules/Types.h b/test/SIL/Serialization/Recovery/Inputs/bad-modules/Types.h
new file mode 100644
index 0000000..a735ae9
--- /dev/null
+++ b/test/SIL/Serialization/Recovery/Inputs/bad-modules/Types.h
@@ -0,0 +1,3 @@
+// struct SoonToBeMissing {
+//   int value;
+// };
diff --git a/test/SIL/Serialization/Recovery/Inputs/bad-modules/module.modulemap b/test/SIL/Serialization/Recovery/Inputs/bad-modules/module.modulemap
new file mode 100644
index 0000000..b811768
--- /dev/null
+++ b/test/SIL/Serialization/Recovery/Inputs/bad-modules/module.modulemap
@@ -0,0 +1 @@
+module Types { header "Types.h" }
diff --git a/test/SIL/Serialization/Recovery/Inputs/good-modules/Types.h b/test/SIL/Serialization/Recovery/Inputs/good-modules/Types.h
new file mode 100644
index 0000000..4b49807
--- /dev/null
+++ b/test/SIL/Serialization/Recovery/Inputs/good-modules/Types.h
@@ -0,0 +1,3 @@
+struct SoonToBeMissing {
+  int value;
+};
diff --git a/test/SIL/Serialization/Recovery/Inputs/good-modules/module.modulemap b/test/SIL/Serialization/Recovery/Inputs/good-modules/module.modulemap
new file mode 100644
index 0000000..b811768
--- /dev/null
+++ b/test/SIL/Serialization/Recovery/Inputs/good-modules/module.modulemap
@@ -0,0 +1 @@
+module Types { header "Types.h" }
diff --git a/test/SIL/Serialization/Recovery/function.sil b/test/SIL/Serialization/Recovery/function.sil
new file mode 100644
index 0000000..311c1b9
--- /dev/null
+++ b/test/SIL/Serialization/Recovery/function.sil
@@ -0,0 +1,26 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -parse-sil %s -emit-sib -o %t/Library.sib -module-name Library -I %S/Inputs/good-modules -parse-stdlib
+// RUN: %target-sil-opt %t/Library.sib -I %S/Inputs/good-modules | %FileCheck %s
+// RUN: %target-sil-opt %t/Library.sib -I %S/Inputs/bad-modules | %FileCheck -check-prefix=CHECK-RECOVERY %s
+// RUN: %target-sil-opt %t/Library.sib -I %S/Inputs/bad-modules | %FileCheck -check-prefix=CHECK-RECOVERY-NEGATIVE %s
+
+// CHECK-LABEL: sil_stage raw
+// CHECK-RECOVERY-LABEL: sil_stage raw
+
+sil_stage raw
+import Types
+
+// CHECK-LABEL: sil @missingParam : $@convention(thin) (SoonToBeMissing) -> () {
+// CHECK-RECOVERY-NEGATIVE-NOT: sil @missingParam
+sil @missingParam : $@convention(thin) (SoonToBeMissing) -> () {
+entry(%arg: $SoonToBeMissing):
+  %9999 = tuple()
+  return %9999 : $()
+}
+
+// CHECK-LABEL: sil @missingResult : $@convention(thin) () -> SoonToBeMissing {
+// CHECK-RECOVERY-NEGATIVE-NOT: sil @missingResult
+sil @missingResult : $@convention(thin) () -> (SoonToBeMissing) {
+entry:
+  unreachable
+}
diff --git a/validation-test/Serialization/Inputs/custom-modules/module.modulemap b/validation-test/Serialization/Inputs/custom-modules/module.modulemap
new file mode 100644
index 0000000..b8ef16f
--- /dev/null
+++ b/validation-test/Serialization/Inputs/custom-modules/module.modulemap
@@ -0,0 +1 @@
+module rdar40899824Helper { header "rdar40899824Helper.h" }
diff --git a/validation-test/Serialization/Inputs/custom-modules/rdar40899824Helper.h b/validation-test/Serialization/Inputs/custom-modules/rdar40899824Helper.h
new file mode 100644
index 0000000..390ee41
--- /dev/null
+++ b/validation-test/Serialization/Inputs/custom-modules/rdar40899824Helper.h
@@ -0,0 +1,13 @@
+#ifndef BAD
+typedef struct {
+  int value;
+} SoonToBeMissing;
+#endif
+
+@interface Impl
+#ifndef BAD
+- (void)use:(SoonToBeMissing)value;
+#endif
+
+- (void)unrelated;
+@end
diff --git a/validation-test/Serialization/rdar40899824.swift b/validation-test/Serialization/rdar40899824.swift
new file mode 100644
index 0000000..1e793d5
--- /dev/null
+++ b/validation-test/Serialization/rdar40899824.swift
@@ -0,0 +1,38 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift %s -emit-module -o %t/Library.swiftmodule -I %S/Inputs/custom-modules -DLIBRARY -Xfrontend -enable-objc-interop -Xfrontend -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend %s -I %t -I %S/Inputs/custom-modules -enable-objc-interop -emit-ir > /dev/null
+
+// RUN: %target-swift-frontend %s -I %t -I %S/Inputs/custom-modules -enable-objc-interop -emit-ir -Xcc -DBAD > /dev/null
+// RUN: %target-swift-frontend %s -I %t -I %S/Inputs/custom-modules -enable-objc-interop -emit-ir -Xcc -DBAD -O > /dev/null
+
+#if LIBRARY
+
+import rdar40899824Helper
+
+public protocol Proto: class {
+  func use(_: SoonToBeMissing)
+  func unrelated()
+}
+
+extension Impl: Proto {}
+
+#else // LIBRARY
+
+import Library
+import rdar40899824Helper
+
+func testGeneric<T: Proto>(_ obj: T) {
+  obj.unrelated()
+}
+
+func testExistential(_ obj: Proto) {
+  obj.unrelated()
+}
+
+func test(_ proto: Proto, _ impl: Impl) {
+  impl.unrelated()
+  testGeneric(impl)
+  testExistential(impl)
+}
+
+#endif // LIBRARY