Merge pull request #19389 from mikeash/patch-bundleforclass

[Runtime][Foundation] Supplement the class_getImageName patch with a patch to +[NSBundle bundleForClass:] on older "embedded" targets
diff --git a/README.md b/README.md
index 1ebe13d..e7add90 100644
--- a/README.md
+++ b/README.md
@@ -71,7 +71,7 @@
 
 #### macOS
 
-To build for macOS, you need [Xcode 10 beta 6](https://developer.apple.com/xcode/downloads/).
+To build for macOS, you need [Xcode 10.0](https://developer.apple.com/xcode/downloads/).
 The required version of Xcode changes frequently, and is often a beta release.
 Check this document or the host information on <https://ci.swift.org> for the
 current required version.
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index 71a8090..cf33184 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -141,7 +141,8 @@
   global ::= protocol 'TL'               // protocol requirements base descriptor
   global ::= assoc-type-name 'Tl'        // associated type descriptor
   global ::= assoc-type-name 'TM'        // default associated type witness accessor
-
+  global ::= type assoc-type-path protocol 'Tn' // associated conformance descriptor
+  global ::= type assoc-type-path protocol 'TN' // default associated conformance witness accessor
 
   REABSTRACT-THUNK-TYPE ::= 'R'          // reabstraction thunk helper function
   REABSTRACT-THUNK-TYPE ::= 'r'          // reabstraction thunk
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index ff0ee4a..370dcf8 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -3979,6 +3979,19 @@
   /// Record the default witness for a requirement.
   void setDefaultWitness(ValueDecl *requirement, Witness witness);
 
+  /// Returns the default associated conformance witness for an associated
+  /// type, or \c None if there is no default.
+  Optional<ProtocolConformanceRef> getDefaultAssociatedConformanceWitness(
+                                              CanType association,
+                                              ProtocolDecl *requirement) const;
+
+  /// Set the default associated conformance witness for the given
+  /// associated conformance.
+  void setDefaultAssociatedConformanceWitness(
+                                            CanType association,
+                                            ProtocolDecl *requirement,
+                                            ProtocolConformanceRef conformance);
+
   /// Retrieve the name to use for this protocol when interoperating
   /// with the Objective-C runtime.
   StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;
diff --git a/include/swift/AST/DiagnosticsModuleDiffer.def b/include/swift/AST/DiagnosticsModuleDiffer.def
index c5b0a7d..24adcfb 100644
--- a/include/swift/AST/DiagnosticsModuleDiffer.def
+++ b/include/swift/AST/DiagnosticsModuleDiffer.def
@@ -52,6 +52,12 @@
 
 ERROR(decl_new_attr,none,"%0 is now %1", (StringRef, StringRef))
 
+ERROR(decl_reorder,none,"%0 in a non-resilient type changes position from %1 to %2", (StringRef, unsigned, unsigned))
+
+ERROR(decl_added,none,"%0 is added to a non-resilient type", (StringRef))
+
+ERROR(default_arg_removed,none,"%0 has removed default argument from %1", (StringRef, StringRef))
+
 #ifndef DIAG_NO_UNDEF
 # if defined(DIAG)
 #  undef DIAG
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index e8653c3..d85dd41 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1696,6 +1696,11 @@
 NOTE(witness_fix_access,none,
      "mark the %0 as '%select{%error|fileprivate|internal|public|%error}1' to "
      "satisfy the requirement", (DescriptiveDeclKind, AccessLevel))
+WARNING(assoc_type_default_conformance_failed,none,
+        "default type %0 for associated type %1 does not satisfy constraint "
+        "%2: %3", (Type, DeclName, Type, Type))
+NOTE(assoc_type_default_here,none,
+     "associated type %0 has default type %1 written here", (DeclName, Type))
 
 ERROR(protocol_access,none,
       "%select{protocol must be declared %select{"
diff --git a/include/swift/AST/LazyResolver.h b/include/swift/AST/LazyResolver.h
index a600fdf..b2911aa 100644
--- a/include/swift/AST/LazyResolver.h
+++ b/include/swift/AST/LazyResolver.h
@@ -63,9 +63,6 @@
   /// Resolve the generic environment of the given protocol.
   virtual void resolveProtocolEnvironment(ProtocolDecl *proto) = 0;
 
-  /// Bind an extension to its extended type.
-  virtual void bindExtension(ExtensionDecl *ext) = 0;
-
   /// Resolve the type of an extension.
   ///
   /// This can be called to ensure that the members of an extension can be
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index cb1d6f3..ed283d6 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -211,6 +211,7 @@
 NODE(MethodDescriptor)
 NODE(ProtocolRequirementsBaseDescriptor)
 NODE(AssociatedConformanceDescriptor)
+NODE(DefaultAssociatedConformanceAccessor)
 NODE(AssociatedTypeDescriptor)
 NODE(ThrowsAnnotation)
 NODE(EmptyList)
diff --git a/include/swift/IDE/DigesterEnums.def b/include/swift/IDE/DigesterEnums.def
index 0092af8..f730523 100644
--- a/include/swift/IDE/DigesterEnums.def
+++ b/include/swift/IDE/DigesterEnums.def
@@ -100,6 +100,7 @@
 KEY(mutating)
 KEY(static)
 KEY(deprecated)
+KEY(implicit)
 KEY(typeAttributes)
 KEY(declAttributes)
 KEY(declKind)
@@ -109,6 +110,7 @@
 KEY(conformingProtocols)
 KEY(enumRawTypeName)
 KEY(genericSig)
+KEY(fixedbinaryorder)
 
 KNOWN_TYPE(Optional)
 KNOWN_TYPE(ImplicitlyUnwrappedOptional)
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index e5d486f..2e99868 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -213,6 +213,11 @@
     /// is stored in the data.
     AssociatedConformanceDescriptor,
 
+    /// A default accessor for an associated conformance of a protocol.
+    /// The pointer is a ProtocolDecl*; the index of the associated conformance
+    /// is stored in the data.
+    DefaultAssociatedConformanceAccessor,
+
     /// A function which returns the default type metadata for the associated
     /// type of a protocol.  The secondary pointer is a ProtocolDecl*.
     /// The index of the associated type declaration is stored in the data.
@@ -795,14 +800,13 @@
   }
 
   static LinkEntity
-  forAssociatedConformanceDescriptor(ProtocolDecl *proto,
-                                     CanType associatedType,
-                                     ProtocolDecl *associatedProtocol) {
+  forAssociatedConformanceDescriptor(AssociatedConformance conformance) {
     LinkEntity entity;
     entity.setForProtocolAndAssociatedConformance(
         Kind::AssociatedConformanceDescriptor,
-        proto, associatedType,
-        associatedProtocol);
+        conformance.getSourceProtocol(),
+        conformance.getAssociation(),
+        conformance.getAssociatedRequirement());
     return entity;
   }
 
@@ -835,6 +839,17 @@
     return entity;
   }
 
+  static LinkEntity
+  forDefaultAssociatedConformanceAccessor(AssociatedConformance conformance) {
+    LinkEntity entity;
+    entity.setForProtocolAndAssociatedConformance(
+        Kind::DefaultAssociatedConformanceAccessor,
+        conformance.getSourceProtocol(),
+        conformance.getAssociation(),
+        conformance.getAssociatedRequirement());
+    return entity;
+  }
+
   static LinkEntity forReflectionBuiltinDescriptor(CanType type) {
     LinkEntity entity;
     entity.setForType(Kind::ReflectionBuiltinDescriptor, type);
@@ -925,7 +940,8 @@
                        LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex));
     }
 
-    assert(getKind() == Kind::AssociatedConformanceDescriptor);
+    assert(getKind() == Kind::AssociatedConformanceDescriptor ||
+           getKind() == Kind::DefaultAssociatedConformanceAccessor);
     return getAssociatedConformanceByIndex(
              cast<ProtocolDecl>(getDecl()),
              LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex));
diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h
index 1942d5e..723bbb9 100644
--- a/include/swift/Serialization/Validation.h
+++ b/include/swift/Serialization/Validation.h
@@ -20,6 +20,7 @@
 
 namespace swift {
 
+class ModuleFile;
 enum class ResilienceStrategy : unsigned;
 
 namespace serialization {
@@ -147,6 +148,24 @@
 validateSerializedAST(StringRef data,
                       ExtendedValidationInfo *extendedInfo = nullptr);
 
+/// Emit diagnostics explaining a failure to load a serialized AST.
+///
+/// - \p Ctx is an AST context through which any diagnostics are surfaced.
+/// - \p diagLoc is the (possibly invalid) location used in the diagnostics.
+/// - \p loadInfo and \p extendedInfo describe the attempt to load an AST
+///   (\ref validateSerializedAST). Note that loadInfo.Status must not be
+///   Status::Valid.
+/// - \p moduleBufferID and \p moduleDocBufferID are the buffer identifiers
+///   of the module input and doc input buffers respectively (\ref 
+///   SerializedModuleLoader::loadAST, \ref ModuleFile::load).
+/// - \p loadedModuleFile is an invalid loaded module.
+/// - \p ModuleName is the name used to refer to the module in diagnostics.
+void diagnoseSerializedASTLoadFailure(
+    ASTContext &Ctx, SourceLoc diagLoc, const ValidationInfo &loadInfo,
+    const ExtendedValidationInfo &extendedInfo, StringRef moduleBufferID,
+    StringRef moduleDocBufferID, ModuleFile *loadedModuleFile,
+    Identifier ModuleName);
+
 } // end namespace serialization
 } // end namespace swift
 
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index ea0de37..b0cea9a 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -285,6 +285,11 @@
   llvm::DenseMap<std::pair<const ProtocolDecl *, AssociatedTypeDecl *>, Type>
     DefaultTypeWitnesses;
 
+  /// Default associated conformance witnesses for protocols.
+  llvm::DenseMap<std::tuple<const ProtocolDecl *, CanType, ProtocolDecl *>,
+                 ProtocolConformanceRef>
+    DefaultAssociatedConformanceWitnesses;
+
   /// \brief Structure that captures data that is segregated into different
   /// arenas.
   struct Arena {
@@ -1709,6 +1714,32 @@
   (void)pair;
 }
 
+Optional<ProtocolConformanceRef>
+ProtocolDecl::getDefaultAssociatedConformanceWitness(
+                                             CanType association,
+                                             ProtocolDecl *requirement) const {
+  auto &ctx = getASTContext();
+  auto found =
+    ctx.getImpl().DefaultAssociatedConformanceWitnesses.find(
+      std::make_tuple(this, association, requirement));
+  if (found == ctx.getImpl().DefaultAssociatedConformanceWitnesses.end())
+    return None;
+
+  return found->second;
+}
+
+void ProtocolDecl::setDefaultAssociatedConformanceWitness(
+                                          CanType association,
+                                          ProtocolDecl *requirement,
+                                          ProtocolConformanceRef conformance) {
+  auto &ctx = getASTContext();
+  auto pair = ctx.getImpl().DefaultAssociatedConformanceWitnesses.insert(
+                std::make_pair(std::make_tuple(this, association, requirement),
+                               conformance));
+  assert(pair.second && "Already have a default associated conformance");
+  (void)pair;
+}
+
 bool ASTContext::canImportModule(std::pair<Identifier, SourceLoc> ModulePath) {
   // If this module has already been successfully imported, it is importable.
   if (getLoadedModule(ModulePath) != nullptr)
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 99b3928..635bb09 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -821,6 +821,11 @@
     Options.ExcludeAttrList.push_back(DAK_Final);
   }
 
+  // Don't print 'final' on accessors.
+  if (Options.PrintImplicitAttrs && isa<AccessorDecl>(D)) {
+    Options.ExcludeAttrList.push_back(DAK_Final);
+  }
+
   // If the declaration is implicitly @objc, print the attribute now.
   if (Options.PrintImplicitAttrs) {
     if (auto VD = dyn_cast<ValueDecl>(D)) {
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index 925e667..55bbda3 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -92,7 +92,11 @@
     const_cast<ProtocolDecl *>(proto)->createGenericParamsIfMissing();
   }
 
-  return getGenericParamsOfContext()->getParams().front()
+  auto *genericParams = getGenericParamsOfContext();
+  if (genericParams == nullptr)
+    return nullptr;
+
+  return genericParams->getParams().front()
       ->getDeclaredInterfaceType()
       ->castTo<GenericTypeParamType>();
 }
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index 1ef30d5..699a8b7 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -564,6 +564,9 @@
 
   ASTContext &ctx = proto->getASTContext();
   TinyPtrVector<NominalTypeDecl *> result;
+  if (!ext->getGenericParams())
+    return result;
+
   for (const auto &req : ext->getGenericParams()->getTrailingRequirements()) {
     // We only care about type constraints.
     if (req.getKind() != RequirementReprKind::TypeConstraint)
@@ -709,6 +712,7 @@
   };
 
   if (Loc.isValid() &&
+      DC->getParentSourceFile() &&
       DC->getParentSourceFile()->Kind != SourceFileKind::REPL &&
       Ctx.LangOpts.EnableASTScopeLookup) {
     // Find the source file in which we are performing the lookup.
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index eafed55..cb3a04c 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -56,7 +56,7 @@
 
 bool ClangImporter::Implementation::isOverAligned(clang::QualType type) {
   auto align = getClangASTContext().getTypeAlignInChars(type);
-  return align.getQuantity() > MaximumAlignment;
+  return align > clang::CharUnits::fromQuantity(MaximumAlignment);
 }
 
 namespace {
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index a41f978..9048834 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -1841,6 +1841,15 @@
                                 protoTy, assocTypePath, requirementTy);
     }
 
+    case 'N': {
+      NodePointer requirementTy = popProtocol();
+      auto assocTypePath = popAssocTypePath();
+      NodePointer protoTy = popNode(Node::Kind::Type);
+      return createWithChildren(
+                            Node::Kind::DefaultAssociatedConformanceAccessor,
+                            protoTy, assocTypePath, requirementTy);
+    }
+
     case 'H':
     case 'h': {
       auto nodeKind = c == 'H' ? Node::Kind::KeyPathEqualsThunkHelper
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index 50e451b..363d552 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -323,6 +323,7 @@
     case Node::Kind::DeclContext:
     case Node::Kind::DefaultArgumentInitializer:
     case Node::Kind::DefaultAssociatedTypeMetadataAccessor:
+    case Node::Kind::DefaultAssociatedConformanceAccessor:
     case Node::Kind::DependentAssociatedTypeRef:
     case Node::Kind::DependentGenericSignature:
     case Node::Kind::DependentGenericParamCount:
@@ -1564,6 +1565,14 @@
     Printer << ": ";
     print(Node->getChild(2));
     return nullptr;
+  case Node::Kind::DefaultAssociatedConformanceAccessor:
+    Printer << "default associated conformance accessor for ";
+    print(Node->getChild(0));
+    Printer << ".";
+    print(Node->getChild(1));
+    Printer << ": ";
+    print(Node->getChild(2));
+    return nullptr;
   case Node::Kind::AssociatedTypeDescriptor:
     Printer << "associated type descriptor for ";
     print(Node->getChild(0));
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index 2549d1a..e4f08ee 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -888,6 +888,10 @@
   Out << "<associated-conformance-descriptor>";
 }
 
+void Remangler::mangleDefaultAssociatedConformanceAccessor(Node *node) {
+  Out << "<default-associated-conformance-descriptor>";
+}
+
 void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
   Out << "Wt";
   mangleChildNodes(node); // protocol conformance, identifier
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index f7ffe88..348b288 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -579,6 +579,11 @@
   Buffer << "Tn";
 }
 
+void Remangler::mangleDefaultAssociatedConformanceAccessor(Node *node) {
+  mangleChildNodes(node);
+  Buffer << "TN";
+}
+
 void Remangler::mangleAssociatedTypeMetadataAccessor(Node *node) {
   mangleChildNodes(node); // protocol conformance, identifier
   Buffer << "Wt";
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index ec487ba..23048cd 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -517,7 +517,9 @@
   }
 
   FrontendStatsTracer tracer(Context->Stats, "perform-sema");
-  Context->LoadedModules[MainModule->getName()] = getMainModule();
+
+  ModuleDecl *mainModule = getMainModule();
+  Context->LoadedModules[mainModule->getName()] = mainModule;
 
   if (Invocation.getInputKind() == InputFileKind::SIL) {
     assert(!InputSourceCodeBufferIDs.empty());
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index d48d029..0cc89af 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -3389,21 +3389,15 @@
 
 llvm::Constant *IRGenModule::getAddrOfAssociatedConformanceDescriptor(
                                           AssociatedConformance conformance) {
-  auto entity = LinkEntity::forAssociatedConformanceDescriptor(
-                  conformance.getSourceProtocol(),
-                  conformance.getAssociation(),
-                  conformance.getAssociatedRequirement());
+  auto entity = LinkEntity::forAssociatedConformanceDescriptor(conformance);
   return getAddrOfLLVMVariable(entity, getPointerAlignment(), ConstantInit(),
                                ProtocolRequirementStructTy, DebugTypeInfo());
 }
 
 llvm::GlobalValue *IRGenModule::defineAssociatedConformanceDescriptor(
-                                                ProtocolDecl *proto,
-                                                CanType subject,
-                                                ProtocolDecl *requirement,
-                                                llvm::Constant *definition) {
-  auto entity = LinkEntity::forAssociatedConformanceDescriptor(proto, subject,
-                                                               requirement);
+                                            AssociatedConformance conformance,
+                                            llvm::Constant *definition) {
+  auto entity = LinkEntity::forAssociatedConformanceDescriptor(conformance);
   return defineAlias(entity, definition);
 }
 
@@ -3989,6 +3983,25 @@
 }
 
 llvm::Function *
+IRGenModule::getAddrOfDefaultAssociatedConformanceAccessor(
+                                         AssociatedConformance requirement) {
+  auto forDefinition = ForDefinition;
+
+  LinkEntity entity =
+    LinkEntity::forDefaultAssociatedConformanceAccessor(requirement);
+  llvm::Function *&entry = GlobalFuncs[entity];
+  if (entry) {
+    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
+    return entry;
+  }
+
+  auto signature = getAssociatedTypeWitnessTableAccessFunctionSignature();
+  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
+  entry = createFunction(*this, link, signature);
+  return entry;
+}
+
+llvm::Function *
 IRGenModule::getAddrOfContinuationPrototype(CanSILFunctionType fnType) {
   LinkEntity entity = LinkEntity::forCoroutineContinuationPrototype(fnType);
 
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index f0198cf..a75abe0 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -647,7 +647,14 @@
 
       if (entry.isAssociatedConformance()) {
         auto flags = Flags(Flags::Kind::AssociatedConformanceAccessFunction);
-        return { flags, nullptr };
+
+        // Look for a default witness.
+        llvm::Constant *defaultImpl =
+          findDefaultAssociatedConformanceWitness(
+            entry.getAssociatedConformancePath(),
+            entry.getAssociatedConformanceRequirement());
+
+        return { flags, defaultImpl };
       }
 
       assert(entry.isFunction());
@@ -712,10 +719,12 @@
         if (entry.isAssociatedConformance()) {
           // Define the associated conformance descriptor to point to the
           // current position in the protocol descriptor.
+          AssociatedConformance conformance(
+                                  Proto,
+                                  entry.getAssociatedConformancePath(),
+                                  entry.getAssociatedConformanceRequirement());
           IGM.defineAssociatedConformanceDescriptor(
-              Proto,
-              entry.getAssociatedConformancePath(),
-              entry.getAssociatedConformanceRequirement(),
+              conformance,
               B.getAddrOfCurrentPosition(IGM.ProtocolRequirementStructTy));
         }
 
@@ -800,6 +809,89 @@
       IGF.Builder.CreateRet(returnValue);
       return accessor;
     }
+
+    llvm::Constant *findDefaultAssociatedConformanceWitness(
+                                                  CanType association,
+                                                  ProtocolDecl *requirement) {
+      if (!DefaultWitnesses) return nullptr;
+
+      for (auto &entry : DefaultWitnesses->getEntries()) {
+        if (!entry.isValid() ||
+            entry.getKind() != SILWitnessTable::AssociatedTypeProtocol ||
+            entry.getAssociatedTypeProtocolWitness().Protocol != requirement ||
+            entry.getAssociatedTypeProtocolWitness().Requirement != association)
+          continue;
+
+        auto witness = entry.getAssociatedTypeProtocolWitness().Witness;
+        return getDefaultAssociatedConformanceAccessFunction(
+                 AssociatedConformance(Proto, association, requirement),
+                 witness);
+      }
+
+      return nullptr;
+    }
+
+    llvm::Constant *getDefaultAssociatedConformanceAccessFunction(
+                      AssociatedConformance requirement,
+                      ProtocolConformanceRef conformance) {
+      auto accessor =
+        IGM.getAddrOfDefaultAssociatedConformanceAccessor(requirement);
+
+      IRGenFunction IGF(IGM, accessor);
+      if (IGM.DebugInfo)
+        IGM.DebugInfo->emitArtificialFunction(IGF, accessor);
+
+      Explosion parameters = IGF.collectParameters();
+
+      llvm::Value *associatedTypeMetadata = parameters.claimNext();
+      llvm::Value *self = parameters.claimNext();
+      llvm::Value *wtable = parameters.claimNext();
+
+      bool hasArchetype =
+        !conformance.isConcrete() ||
+        conformance.getConcrete()->getType()->hasArchetype();
+      if (hasArchetype) {
+        // Bind local Self type data from the metadata argument.
+        CanType selfInContext =
+            Proto->mapTypeIntoContext(Proto->getProtocolSelfType())
+              ->getCanonicalType();
+        IGF.bindLocalTypeDataFromTypeMetadata(selfInContext, IsExact, self,
+                                              MetadataState::Abstract);
+        IGF.setUnscopedLocalTypeData(
+            selfInContext,
+            LocalTypeDataKind::forAbstractProtocolWitnessTable(Proto),
+            wtable);
+
+        // Bind the associated type metadata.
+        IGF.bindLocalTypeDataFromTypeMetadata(requirement.getAssociation(),
+                                              IsExact,
+                                              associatedTypeMetadata,
+                                              MetadataState::Abstract);
+      }
+
+      // For a concrete witness table, call it.
+      ProtocolDecl *associatedProtocol = requirement.getAssociatedRequirement();
+      if (conformance.isConcrete()) {
+        auto conformanceI = &IGM.getConformanceInfo(associatedProtocol,
+                                                    conformance.getConcrete());
+        auto returnValue = conformanceI->getTable(IGF, &associatedTypeMetadata);
+        IGF.Builder.CreateRet(returnValue);
+        return accessor;
+      }
+
+      // For an abstract table, emit a reference to the witness table.
+      CanType associatedTypeInContext
+        = Proto->mapTypeIntoContext(requirement.getAssociation())
+            ->getCanonicalType();
+      auto returnValue =
+          emitArchetypeWitnessTableRef(
+            IGF,
+            cast<ArchetypeType>(associatedTypeInContext),
+            associatedProtocol);
+      IGF.Builder.CreateRet(returnValue);
+      return accessor;
+    }
+
     void addAssociatedTypeNames() {
       std::string AssociatedTypeNames;
 
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 0cf4f02..a04e8ae 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -1385,6 +1385,13 @@
     void addAssociatedConformance(AssociatedConformance requirement) {
       // FIXME: Add static witness tables for type conformances.
 
+      auto &entry = SILEntries.front();
+      (void)entry;
+      SILEntries = SILEntries.slice(1);
+
+      if (ResilientConformance)
+        return;
+
       auto associate =
         ConformanceInContext.getAssociatedType(
           requirement.getAssociation())->getCanonicalType();
@@ -1394,9 +1401,8 @@
           requirement.getAssociation(),
           requirement.getAssociatedRequirement());
 
+
 #ifndef NDEBUG
-      auto &entry = SILEntries.front();
-      (void)entry;
       assert(entry.getKind() == SILWitnessTable::AssociatedTypeProtocol
              && "sil witness table does not match protocol");
       auto associatedWitness = entry.getAssociatedTypeProtocolWitness();
@@ -1411,8 +1417,6 @@
              "offset doesn't match ProtocolInfo layout");
 #endif
 
-      SILEntries = SILEntries.slice(1);
-
       llvm::Constant *wtableAccessFunction =
         getAssociatedTypeWitnessTableAccessFunction(requirement,
                                                     associate,
@@ -1644,7 +1648,8 @@
 getAssociatedTypeWitnessTableAccessFunction(AssociatedConformance requirement,
                                             CanType associatedType,
                                 ProtocolConformanceRef associatedConformance) {
-  if (!associatedType->hasArchetype()) {
+  bool hasArchetype = associatedType->hasArchetype();
+  if (!hasArchetype && !ResilientConformance) {
     assert(associatedConformance.isConcrete() &&
            "no concrete conformance for non-dependent type");
     return getOrCreateWitnessTableAccessFunction(IGM,
@@ -1682,13 +1687,6 @@
   Address destTable(parameters.claimNext(), IGM.getPointerAlignment());
   setProtocolWitnessTableName(IGM, destTable.getAddress(), ConcreteType,
                               Conformance.getProtocol());
-  IGF.bindLocalTypeDataFromSelfWitnessTable(
-          &Conformance,
-          destTable.getAddress(),
-          [&](CanType type) {
-            return Conformance.getDeclContext()->mapTypeIntoContext(type)
-                     ->getCanonicalType();
-          });
 
   ProtocolDecl *associatedProtocol = requirement.getAssociatedRequirement();
 
@@ -1710,6 +1708,24 @@
     }
   }
 
+  // If there are no archetypes, return a reference to the table. There is
+  // no need for a cache.
+  if (!hasArchetype) {
+    auto wtable = MetadataResponse::forComplete(
+                    conformanceI->getTable(IGF, &associatedTypeMetadata))
+        .getMetadata();
+    IGF.Builder.CreateRet(wtable);
+    return accessor;
+  }
+
+  IGF.bindLocalTypeDataFromSelfWitnessTable(
+        &Conformance,
+        destTable.getAddress(),
+        [&](CanType type) {
+          return Conformance.getDeclContext()->mapTypeIntoContext(type)
+                   ->getCanonicalType();
+        });
+
   // If the witness table is directly fulfillable from the type,
   // we don't need a cache entry.
   // TODO: maybe we should have a cache entry anyway if the fulfillment
@@ -1869,7 +1885,8 @@
   unsigned count = 0;
   for (auto &entry : SILWT->getEntries()) {
     if (entry.getKind() != SILWitnessTable::Method &&
-        entry.getKind() != SILWitnessTable::AssociatedType)
+        entry.getKind() != SILWitnessTable::AssociatedType &&
+        entry.getKind() != SILWitnessTable::AssociatedTypeProtocol)
       continue;
 
     count++;
@@ -1907,6 +1924,36 @@
       continue;
     }
 
+    // Associated conformance access function.
+    if (entry.getKind() == SILWitnessTable::AssociatedTypeProtocol) {
+      const auto &witness = entry.getAssociatedTypeProtocolWitness();
+
+      // Associated type descriptor.
+      AssociatedConformance requirement(SILWT->getConformance()->getProtocol(),
+                                        witness.Requirement,
+                                        witness.Protocol);
+      auto assocConformanceDescriptor =
+        IGM.getAddrOfLLVMVariableOrGOTEquivalent(
+          LinkEntity::forAssociatedConformanceDescriptor(requirement),
+          Alignment(4), IGM.ProtocolRequirementStructTy);
+      table.addRelativeAddress(assocConformanceDescriptor);
+
+      auto associate =
+        ConformanceInContext.getAssociatedType(
+          witness.Requirement)->getCanonicalType();
+
+      ProtocolConformanceRef associatedConformance =
+        ConformanceInContext.getAssociatedConformance(witness.Requirement,
+                                                      witness.Protocol);
+
+      llvm::Constant *wtableAccessFunction =
+        getAssociatedTypeWitnessTableAccessFunction(requirement,
+                                                    associate,
+                                                    associatedConformance);
+      table.addRelativeAddress(wtableAccessFunction);
+      continue;
+    }
+
     if (entry.getKind() != SILWitnessTable::Method)
       continue;
 
diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h
index edd7713..37c5b95 100644
--- a/lib/IRGen/IRGenMangler.h
+++ b/lib/IRGen/IRGenMangler.h
@@ -197,6 +197,19 @@
     return finalize();
   }
 
+  std::string mangleDefaultAssociatedConformanceAccessor(
+      const ProtocolDecl *proto,
+      CanType subject,
+      const ProtocolDecl *requirement) {
+    beginMangling();
+    appendAnyGenericType(proto);
+    bool isFirstAssociatedTypeIdentifier = true;
+    appendAssociatedTypePath(subject, isFirstAssociatedTypeIdentifier);
+    appendProtocolName(requirement);
+    appendOperator("TN");
+    return finalize();
+  }
+
   std::string mangleProtocolConformanceDescriptor(
                                  const ProtocolConformance *Conformance) {
     beginMangling();
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index fb33001..0c98b82 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -1237,10 +1237,8 @@
   llvm::Constant *getAddrOfAssociatedConformanceDescriptor(
                                             AssociatedConformance conformance);
   llvm::GlobalValue *defineAssociatedConformanceDescriptor(
-                                                  ProtocolDecl *proto,
-                                                  CanType subject,
-                                                  ProtocolDecl *requirement,
-                                                  llvm::Constant *definition);
+                                              AssociatedConformance conformance,
+                                              llvm::Constant *definition);
 
   llvm::Constant *getAddrOfProtocolDescriptor(ProtocolDecl *D,
                                       ConstantInit definition = ConstantInit());
@@ -1293,6 +1291,8 @@
                                      const AssociatedConformance &association);
   llvm::Function *getAddrOfDefaultAssociatedTypeMetadataAccessFunction(
                                            AssociatedType association);
+  llvm::Function *getAddrOfDefaultAssociatedConformanceAccessor(
+                                           AssociatedConformance requirement);
 
   Address getAddrOfObjCISAMask();
 
diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp
index 6562b50..b24a247 100644
--- a/lib/IRGen/Linking.cpp
+++ b/lib/IRGen/Linking.cpp
@@ -187,6 +187,14 @@
              assocConformance.second);
   }
 
+  case Kind::DefaultAssociatedConformanceAccessor: {
+    auto assocConformance = getAssociatedConformance();
+    return mangler.mangleDefaultAssociatedConformanceAccessor(
+             cast<ProtocolDecl>(getDecl()),
+             assocConformance.first,
+             assocConformance.second);
+  }
+
   case Kind::ProtocolConformanceDescriptor:
     return mangler.mangleProtocolConformanceDescriptor(
                    cast<NormalProtocolConformance>(getProtocolConformance()));
@@ -498,6 +506,7 @@
   case Kind::AssociatedTypeMetadataAccessFunction:
   case Kind::DefaultAssociatedTypeMetadataAccessFunction:
   case Kind::AssociatedTypeWitnessTableAccessFunction:
+  case Kind::DefaultAssociatedConformanceAccessor:
   case Kind::GenericProtocolWitnessTableCache:
   case Kind::GenericProtocolWitnessTableInstantiationFunction:
     return SILLinkage::Private;
@@ -629,6 +638,7 @@
   case Kind::TypeMetadataCompletionFunction:
   case Kind::TypeMetadataPattern:
   case Kind::DefaultAssociatedTypeMetadataAccessFunction:
+  case Kind::DefaultAssociatedConformanceAccessor:
     return false;
 
   case Kind::ValueWitness:
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index e655e14..75d0bc7 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -181,7 +181,8 @@
     ProtocolConformance *
     parseProtocolConformanceHelper(ProtocolDecl *&proto,
                                    GenericEnvironment *GenericEnv,
-                                   bool localScope);
+                                   bool localScope,
+                                   ProtocolDecl *defaultForProto);
   public:
     SILParser(Parser &P)
         : P(P), SILMod(static_cast<SILParserTUState *>(P.SIL)->M),
@@ -391,15 +392,18 @@
     bool isStartOfSILInstruction();
 
     bool parseSubstitutions(SmallVectorImpl<ParsedSubstitution> &parsed,
-                            GenericEnvironment *GenericEnv=nullptr);
+                            GenericEnvironment *GenericEnv=nullptr,
+                            ProtocolDecl *defaultForProto = nullptr);
 
     ProtocolConformance *parseProtocolConformance(ProtocolDecl *&proto,
                              GenericEnvironment *&genericEnv,
-                             bool localScope);
-    ProtocolConformance *parseProtocolConformance() {
+                             bool localScope,
+                             ProtocolDecl *defaultForProto);
+    ProtocolConformance *parseProtocolConformance(
+                                              ProtocolDecl *defaultForProto) {
       ProtocolDecl *dummy;
       GenericEnvironment *env;
-      return parseProtocolConformance(dummy, env, true);
+      return parseProtocolConformance(dummy, env, true, defaultForProto);
     }
 
     Optional<llvm::coverage::Counter>
@@ -1012,6 +1016,8 @@
 
   if (!DC)
     DC = &P.SF;
+  else if (!GenericEnv)
+    GenericEnv = DC->getGenericEnvironmentOfContext();
 
   return swift::performTypeLocChecking(P.Context, T,
                                        /*isSILMode=*/true, IsSILType,
@@ -1510,10 +1516,46 @@
   return false;
 }
 
+/// Bind any unqualified 'Self' references to the given protocol's 'Self'
+/// generic parameter.
+///
+/// FIXME: This is a hack to work around the lack of a DeclContext for
+/// witness tables.
+static void bindProtocolSelfInTypeRepr(TypeLoc &TL, ProtocolDecl *proto) {
+  if (auto typeRepr = TL.getTypeRepr()) {
+    // AST walker to update 'Self' references.
+    class BindProtocolSelf : public ASTWalker {
+      ProtocolDecl *proto;
+      GenericTypeParamDecl *selfParam;
+      Identifier selfId;
+
+    public:
+      BindProtocolSelf(ProtocolDecl *proto)
+        : proto(proto),
+          selfParam(proto->getProtocolSelfType()->getDecl()),
+          selfId(proto->getASTContext().Id_Self) {
+      }
+
+      virtual bool walkToTypeReprPre(TypeRepr *T) override {
+        if (auto ident = dyn_cast<IdentTypeRepr>(T)) {
+          auto firstComponent = ident->getComponentRange().front();
+          if (firstComponent->getIdentifier() == selfId)
+            firstComponent->setValue(selfParam, proto);
+        }
+
+        return true;
+      }
+    };
+
+    typeRepr->walk(BindProtocolSelf(proto));
+  }
+}
+
 /// Parse the substitution list for an apply instruction or
 /// specialized protocol conformance.
 bool SILParser::parseSubstitutions(SmallVectorImpl<ParsedSubstitution> &parsed,
-                                   GenericEnvironment *GenericEnv) {
+                                   GenericEnvironment *GenericEnv,
+                                   ProtocolDecl *defaultForProto) {
   // Check for an opening '<' bracket.
   if (!P.Tok.isContextualPunctuator("<"))
     return false;
@@ -1529,7 +1571,10 @@
     if (TyR.isNull())
       return true;
     TypeLoc Ty = TyR.get();
-    if (performTypeLocChecking(Ty, /*IsSILType=*/ false, GenericEnv))
+    if (defaultForProto)
+      bindProtocolSelfInTypeRepr(Ty, defaultForProto);
+    if (performTypeLocChecking(Ty, /*IsSILType=*/ false, GenericEnv,
+                               defaultForProto))
       return true;
     parsed.push_back({Loc, Ty.getType()});
   } while (P.consumeIf(tok::comma));
@@ -5725,7 +5770,8 @@
 ProtocolConformance *SILParser::parseProtocolConformance(
            ProtocolDecl *&proto,
            GenericEnvironment *&genericEnv,
-           bool localScope) {
+           bool localScope,
+           ProtocolDecl *defaultForProto) {
   // Parse generic params for the protocol conformance. We need to make sure
   // they have the right scope.
   Optional<Scope> GenericsScope;
@@ -5741,7 +5787,8 @@
   }
 
   ProtocolConformance *retVal =
-      parseProtocolConformanceHelper(proto, genericEnv, localScope);
+      parseProtocolConformanceHelper(proto, genericEnv, localScope,
+                                     defaultForProto);
 
   if (localScope) {
     GenericsScope.reset();
@@ -5752,13 +5799,19 @@
 ProtocolConformance *SILParser::parseProtocolConformanceHelper(
                                     ProtocolDecl *&proto,
                                     GenericEnvironment *witnessEnv,
-                                    bool localScope) {
+                                    bool localScope,
+                                    ProtocolDecl *defaultForProto) {
   // Parse AST type.
   ParserResult<TypeRepr> TyR = P.parseType();
   if (TyR.isNull())
     return nullptr;
   TypeLoc Ty = TyR.get();
-  if (performTypeLocChecking(Ty, /*IsSILType=*/ false, witnessEnv))
+  if (defaultForProto) {
+    bindProtocolSelfInTypeRepr(Ty, defaultForProto);
+  }
+
+  if (performTypeLocChecking(Ty, /*IsSILType=*/ false, witnessEnv,
+                             defaultForProto))
     return nullptr;
   auto ConformingTy = Ty.getType();
 
@@ -5770,7 +5823,7 @@
 
     // Parse substitutions for specialized conformance.
     SmallVector<ParsedSubstitution, 4> parsedSubs;
-    if (parseSubstitutions(parsedSubs, witnessEnv))
+    if (parseSubstitutions(parsedSubs, witnessEnv, defaultForProto))
       return nullptr;
 
     if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
@@ -5778,7 +5831,8 @@
     ProtocolDecl *dummy;
     GenericEnvironment *specializedEnv;
     auto genericConform =
-        parseProtocolConformance(dummy, specializedEnv, localScope);
+        parseProtocolConformance(dummy, specializedEnv, localScope,
+                                 defaultForProto);
     if (!genericConform)
       return nullptr;
     if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen))
@@ -5799,7 +5853,7 @@
 
     if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
       return nullptr;
-    auto baseConform = parseProtocolConformance();
+    auto baseConform = parseProtocolConformance(defaultForProto);
     if (!baseConform)
       return nullptr;
     if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen))
@@ -5812,41 +5866,6 @@
   return retVal;
 }
 
-/// Bind any unqualified 'Self' references to the given protocol's 'Self'
-/// generic parameter.
-///
-/// FIXME: This is a hack to work around the lack of a DeclContext for
-/// witness tables.
-static void bindProtocolSelfInTypeRepr(TypeLoc &TL, ProtocolDecl *proto) {
-  if (auto typeRepr = TL.getTypeRepr()) {
-    // AST walker to update 'Self' references.
-    class BindProtocolSelf : public ASTWalker {
-      ProtocolDecl *proto;
-      GenericTypeParamDecl *selfParam;
-      Identifier selfId;
-
-    public:
-      BindProtocolSelf(ProtocolDecl *proto)
-        : proto(proto),
-          selfParam(proto->getProtocolSelfType()->getDecl()),
-          selfId(proto->getASTContext().Id_Self) {
-      }
-
-      virtual bool walkToTypeReprPre(TypeRepr *T) override {
-        if (auto ident = dyn_cast<IdentTypeRepr>(T)) {
-          auto firstComponent = ident->getComponentRange().front();
-          if (firstComponent->getIdentifier() == selfId)
-            firstComponent->setValue(selfParam, proto);
-        }
-
-        return true;
-      }
-    };
-
-    typeRepr->walk(BindProtocolSelf(proto));
-  }
-}
-
 /// Parser a single SIL vtable entry and add it to either \p witnessEntries
 /// or \c conditionalConformances.
 static bool parseSILVTableEntry(
@@ -5859,6 +5878,7 @@
          std::vector<SILWitnessTable::Entry> &witnessEntries,
          std::vector<SILWitnessTable::ConditionalConformance>
            &conditionalConformances) {
+  ProtocolDecl *defaultForProto = isDefaultWitnessTable ? proto : nullptr;
   Identifier EntryKeyword;
   SourceLoc KeywordLoc;
   if (P.parseIdentifier(EntryKeyword, KeywordLoc,
@@ -5878,7 +5898,8 @@
       return true;
     if (P.parseToken(tok::colon, diag::expected_sil_witness_colon))
       return true;
-    ProtocolConformance *conform = witnessState.parseProtocolConformance();
+    ProtocolConformance *conform =
+      witnessState.parseProtocolConformance(defaultForProto);
     if (!conform) // Ignore this witness entry for now.
       return false;
 
@@ -5925,7 +5946,7 @@
 
     ProtocolConformanceRef conformance(proto);
     if (P.Tok.getText() != "dependent") {
-      auto concrete = witnessState.parseProtocolConformance();
+      auto concrete = witnessState.parseProtocolConformance(defaultForProto);
       if (!concrete) // Ignore this witness entry for now.
         return false;
       conformance = ProtocolConformanceRef(concrete);
@@ -6045,7 +6066,8 @@
   GenericEnvironment *witnessEnv;
   auto conf = WitnessState.parseProtocolConformance(proto,
                                                     witnessEnv,
-                                                    false/*localScope*/);
+                                                    false/*localScope*/,
+                                                    nullptr);
   WitnessState.ContextGenericEnv = witnessEnv;
 
   NormalProtocolConformance *theConformance = conf ?
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index 1350026..4182f48 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -769,7 +769,19 @@
   }
 
   void addAssociatedConformance(const AssociatedConformance &req) {
-    addMissingDefault();
+    auto witness =
+        Proto->getDefaultAssociatedConformanceWitness(
+          req.getAssociation(),
+          req.getAssociatedRequirement());
+    if (!witness)
+      return addMissingDefault();
+
+    auto entry =
+        SILWitnessTable::AssociatedTypeProtocolWitness{
+          req.getAssociation(),
+          req.getAssociatedRequirement(),
+          *witness};
+    DefaultWitnesses.push_back(entry);
   }
 };
 
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 564da3e..dcd7e17 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -19,6 +19,7 @@
 #include "TypeCheckType.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/TypeWalker.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Compiler.h"
@@ -1226,15 +1227,9 @@
 void ConstraintSystem::solve(SmallVectorImpl<Solution> &solutions) {
   assert(solverState);
 
-  SmallVector<SolverStep *, 16> workList;
+  SmallVector<std::unique_ptr<SolverStep>, 16> workList;
   // First step is always wraps whole constraint system.
-  workList.push_back(SplitterStep::create(*this, solutions));
-
-  SWIFT_DEFER {
-    // Delete all of the leftover steps from the work list.
-    while (!workList.empty())
-      delete workList.pop_back_val();
-  };
+  workList.push_back(llvm::make_unique<SplitterStep>(*this, solutions));
 
   // Indicate whether previous step in the stack has failed
   // (returned StepResult::Kind = Error), this is useful to
@@ -1251,9 +1246,6 @@
     }
 
     currentState = step->getState();
-    assert(currentState == StepState::Ready ||
-           currentState == StepState::Suspended);
-
     step->transitionTo(StepState::Running);
     return currentState == StepState::Ready ? step->take(prevFailed)
                                             : step->resume(prevFailed);
@@ -1264,17 +1256,13 @@
   // a solution, or producing another set of mergeable
   // steps to take before arriving to solution.
   while (!workList.empty()) {
-    auto *step = workList.back();
+    auto &step = workList.back();
 
     // Now let's try to advance to the next step or re-take previous,
     // which should produce another steps to follow,
     // or error, which means that current path is inconsistent.
     {
-      assert(!(step->getState() == StepState::Running ||
-               step->getState() == StepState::Done) &&
-             "Cannot re-take already running/done step.");
-
-      auto result = advance(step, prevFailed);
+      auto result = advance(step.get(), prevFailed);
       switch (result.getKind()) {
       // It was impossible to solve this step, let's note that
       // for followup steps, to propogate the error.
@@ -1286,7 +1274,6 @@
       // toward that solution.
       case SolutionKind::Solved: {
         workList.pop_back();
-        delete step;
         break;
       }
 
diff --git a/lib/Sema/CSStep.cpp b/lib/Sema/CSStep.cpp
index a2c0512..aa48e66 100644
--- a/lib/Sema/CSStep.cpp
+++ b/lib/Sema/CSStep.cpp
@@ -49,7 +49,7 @@
   if (prevFailed || CS.failedConstraint || CS.simplify())
     return done(/*isSuccess=*/false);
 
-  SmallVector<ComponentStep *, 4> components;
+  SmallVector<std::unique_ptr<ComponentStep>, 4> components;
   // Try to run "connected components" algorithm and split
   // type variables and their constraints into independent
   // sub-systems to solve.
@@ -59,10 +59,14 @@
   // try to merge solutions, "split" step should be considered
   // done and replaced by a single component step.
   if (components.size() < 2)
-    return replaceWith(components.front());
+    return replaceWith(std::move(components.front()));
+
+  SmallVector<std::unique_ptr<SolverStep>, 4> followup;
+  for (auto &step : components)
+    followup.push_back(std::move(step));
 
   /// Wait until all of the component steps are done.
-  return suspend<ComponentStep>(components);
+  return suspend(followup);
 }
 
 StepResult SplitterStep::resume(bool prevFailed) {
@@ -83,7 +87,7 @@
 }
 
 void SplitterStep::computeFollowupSteps(
-    SmallVectorImpl<ComponentStep *> &componentSteps) {
+    SmallVectorImpl<std::unique_ptr<ComponentStep>> &componentSteps) {
   // Compute next steps based on that connected components
   // algorithm tells us is splittable.
 
@@ -99,7 +103,7 @@
   SmallVector<unsigned, 16> components;
   unsigned numComponents = CG.computeConnectedComponents(typeVars, components);
   if (numComponents < 2) {
-    componentSteps.push_back(ComponentStep::create(
+    componentSteps.push_back(llvm::make_unique<ComponentStep>(
         CS, 0, /*single=*/true, &CS.InactiveConstraints, Solutions));
     return;
   }
@@ -109,7 +113,7 @@
       new SmallVector<Solution, 4>[numComponents]);
 
   for (unsigned i = 0, n = numComponents; i != n; ++i) {
-    componentSteps.push_back(ComponentStep::create(
+    componentSteps.push_back(llvm::make_unique<ComponentStep>(
         CS, i, /*single=*/false, &Components[i], PartialSolutions[i]));
   }
 
@@ -186,7 +190,8 @@
   // since components are going to be executed in LIFO order, we'd
   // want to have smaller/faster components at the back of the list.
   std::sort(componentSteps.begin(), componentSteps.end(),
-            [](const ComponentStep *lhs, const ComponentStep *rhs) {
+            [](const std::unique_ptr<ComponentStep> &lhs,
+               const std::unique_ptr<ComponentStep> &rhs) {
               return lhs->disjunctionCount() > rhs->disjunctionCount();
             });
 }
@@ -256,10 +261,12 @@
   if (bestBindings && (!disjunction || (!bestBindings->InvolvesTypeVariables &&
                                         !bestBindings->FullyBound))) {
     // Produce a type variable step.
-    return suspend(TypeVariableStep::create(CS, *bestBindings, Solutions));
+    return suspend(
+        llvm::make_unique<TypeVariableStep>(CS, *bestBindings, Solutions));
   } else if (disjunction) {
     // Produce a disjunction step.
-    return suspend(DisjunctionStep::create(CS, disjunction, Solutions));
+    return suspend(
+        llvm::make_unique<DisjunctionStep>(CS, disjunction, Solutions));
   }
 
   // If there are no disjunctions or type variables to bind
@@ -353,24 +360,11 @@
 bool TypeVariableStep::attempt(const TypeVariableBinding &choice) {
   ++CS.solverState->NumTypeVariableBindings;
 
-  if (isDebugMode()) {
-    auto &log = getDebugLogger();
-    log << "(trying ";
-    choice.print(log, &CS.getASTContext().SourceMgr);
-    log << '\n';
-  }
-
   if (choice.hasDefaultedProtocol())
     SawFirstLiteralConstraint = true;
 
   // Try to solve the system with typeVar := type
-  if (!choice.attempt(CS)) {
-    if (isDebugMode())
-      getDebugLogger() << ")\n";
-    return false;
-  }
-
-  return true;
+  return choice.attempt(CS);
 }
 
 StepResult TypeVariableStep::resume(bool prevFailed) {
@@ -380,16 +374,16 @@
   // that active binding has a solution.
   AnySolved |= !prevFailed;
 
-  if (isDebugMode())
-    getDebugLogger() << ")\n";
-
-  const auto choice = ActiveChoice->second;
+  bool shouldStop = shouldStopAfter(ActiveChoice->second);
   // Rewind back all of the changes made to constraint system.
   ActiveChoice.reset();
 
+  if (isDebugMode())
+    getDebugLogger() << ")\n";
+
   // Let's check if we should stop right before
   // attempting any new bindings.
-  if (shouldStopAfter(choice))
+  if (shouldStop)
     return done(/*isSuccess=*/AnySolved);
 
   // Attempt next type variable binding.
@@ -560,11 +554,5 @@
     }
   }
 
-  if (!choice.attempt(CS)) {
-    if (isDebugMode())
-      getDebugLogger() << ")\n";
-    return false;
-  }
-
-  return true;
+  return choice.attempt(CS);
 }
diff --git a/lib/Sema/CSStep.h b/lib/Sema/CSStep.h
index 3fd6495..38dfa4f 100644
--- a/lib/Sema/CSStep.h
+++ b/lib/Sema/CSStep.h
@@ -49,15 +49,15 @@
 
 private:
   Kind ResultKind;
-  SmallVector<SolverStep *, 4> NextSteps;
+  SmallVector<std::unique_ptr<SolverStep>, 4> NextSteps;
 
   StepResult(Kind kind) : ResultKind(kind) {}
 
-  StepResult(Kind kind, SolverStep *step) : ResultKind(kind) {
-    NextSteps.push_back(step);
+  StepResult(Kind kind, std::unique_ptr<SolverStep> step) : ResultKind(kind) {
+    NextSteps.push_back(std::move(step));
   }
 
-  StepResult(Kind kind, SmallVectorImpl<SolverStep *> &followup)
+  StepResult(Kind kind, SmallVectorImpl<std::unique_ptr<SolverStep>> &followup)
       : ResultKind(kind), NextSteps(std::move(followup)) {}
 
 public:
@@ -65,29 +65,24 @@
 
   Kind getKind() const { return ResultKind; }
 
-  void transfer(SmallVectorImpl<SolverStep *> &workList) {
+  void transfer(SmallVectorImpl<std::unique_ptr<SolverStep>> &workList) {
     workList.reserve(NextSteps.size());
-    workList.append(NextSteps.begin(), NextSteps.end());
+    for (auto &step : NextSteps)
+      workList.push_back(std::move(step));
   }
 
 private:
   static StepResult success() { return StepResult(Kind::Solved); }
   static StepResult failure() { return StepResult(Kind::Error); }
 
-  static StepResult unsolved(SolverStep *singleStep) {
-    return StepResult(Kind::Unsolved, singleStep);
+  static StepResult unsolved(std::unique_ptr<SolverStep> singleStep) {
+    return StepResult(Kind::Unsolved, std::move(singleStep));
   }
 
-  static StepResult unsolved(SmallVectorImpl<SolverStep *> &followup) {
+  static StepResult
+  unsolved(SmallVectorImpl<std::unique_ptr<SolverStep>> &followup) {
     return StepResult(Kind::Unsolved, followup);
   }
-
-  template <typename T> static StepResult unsolved(ArrayRef<T *> followup) {
-    auto result = StepResult(Kind::Unsolved);
-    for (auto *step : followup)
-      result.NextSteps.push_back(static_cast<SolverStep *>(step));
-    return result;
-  }
 };
 
 /// Represents a single independently solvable part of
@@ -156,9 +151,32 @@
   ///
   /// \param newState The new state this step should be in.
   void transitionTo(StepState newState) {
-    // TODO: Make sure that ordering of the state transitions is correct,
-    //       because `setup -> ready -> running [-> suspended]* -> done`
-    //       is the only reasonable state transition path.
+#ifndef NDEBUG
+    // Make sure that ordering of the state transitions is correct,
+    // because `setup -> ready -> running [-> suspended]* -> done`
+    // is the only reasonable state transition path.
+    switch (State) {
+    case StepState::Setup:
+      assert(newState == StepState::Ready);
+      break;
+
+    case StepState::Ready:
+      assert(newState == StepState::Running);
+      break;
+
+    case StepState::Running:
+      assert(newState == StepState::Suspended || newState == StepState::Done);
+      break;
+
+    case StepState::Suspended:
+      assert(newState == StepState::Running);
+      break;
+
+    case StepState::Done:
+      llvm_unreachable("step is already done.");
+    }
+#endif
+
     State = newState;
   }
 
@@ -167,22 +185,17 @@
     return isSuccess ? StepResult::success() : StepResult::failure();
   }
 
-  StepResult replaceWith(SolverStep *replacement) {
+  StepResult replaceWith(std::unique_ptr<SolverStep> replacement) {
     transitionTo(StepState::Done);
-    return StepResult(StepResult::Kind::Solved, replacement);
+    return StepResult(StepResult::Kind::Solved, std::move(replacement));
   }
 
-  StepResult suspend(SolverStep *followup) {
+  StepResult suspend(std::unique_ptr<SolverStep> followup) {
     transitionTo(StepState::Suspended);
-    return StepResult::unsolved(followup);
+    return StepResult::unsolved(std::move(followup));
   }
 
-  StepResult suspend(SmallVectorImpl<SolverStep *> &followup) {
-    transitionTo(StepState::Suspended);
-    return StepResult::unsolved(followup);
-  }
-
-  template <typename T> StepResult suspend(ArrayRef<T *> followup) {
+  StepResult suspend(SmallVectorImpl<std::unique_ptr<SolverStep>> &followup) {
     transitionTo(StepState::Suspended);
     return StepResult::unsolved(followup);
   }
@@ -244,10 +257,10 @@
 
   SmallVector<Constraint *, 4> OrphanedConstraints;
 
+public:
   SplitterStep(ConstraintSystem &cs, SmallVectorImpl<Solution> &solutions)
       : SolverStep(cs, solutions) {}
 
-public:
   StepResult take(bool prevFailed) override;
   StepResult resume(bool prevFailed) override;
 
@@ -255,15 +268,11 @@
     Out << "SplitterStep with #" << Components.size() << " components\n";
   }
 
-  static SplitterStep *create(ConstraintSystem &cs,
-                              SmallVectorImpl<Solution> &solutions) {
-    return new SplitterStep(cs, solutions);
-  }
-
 private:
   /// If current step needs follow-up steps to get completely solved,
   /// let's compute them using connected components algorithm.
-  void computeFollowupSteps(SmallVectorImpl<ComponentStep *> &componentSteps);
+  void computeFollowupSteps(
+      SmallVectorImpl<std::unique_ptr<ComponentStep>> &componentSteps);
 
   /// Once all of the follow-up steps are complete, let's try
   /// to merge resulting solutions together, to form final solution(s)
@@ -339,6 +348,7 @@
   /// with it, which makes it disconnected in the graph.
   Constraint *OrphanedConstraint = nullptr;
 
+public:
   ComponentStep(ConstraintSystem &cs, unsigned index, bool single,
                 ConstraintList *constraints,
                 SmallVectorImpl<Solution> &solutions)
@@ -346,7 +356,6 @@
         OriginalScore(getCurrentScore()), OriginalBestScore(getBestScore()),
         Constraints(constraints) {}
 
-public:
   /// Record a type variable as associated with this step.
   void record(TypeVariableType *typeVar) { TypeVars.push_back(typeVar); }
 
@@ -388,12 +397,6 @@
   void print(llvm::raw_ostream &Out) override {
     Out << "ComponentStep with at #" << Index << '\n';
   }
-
-  static ComponentStep *create(ConstraintSystem &cs, unsigned index,
-                               bool single, ConstraintList *constraints,
-                               SmallVectorImpl<Solution> &solutions) {
-    return new ComponentStep(cs, index, single, constraints, solutions);
-  }
 };
 
 template <typename P> class BindingStep : public SolverStep {
@@ -425,14 +428,24 @@
       if (shouldStopAt(*choice))
         break;
 
+      if (isDebugMode()) {
+        auto &log = getDebugLogger();
+        log << "(attempting ";
+        choice->print(log, &CS.getASTContext().SourceMgr);
+        log << '\n';
+      }
+
       {
         auto scope = llvm::make_unique<Scope>(CS);
         if (attempt(*choice)) {
           ActiveChoice.emplace(std::move(scope), *choice);
-          return suspend(SplitterStep::create(CS, Solutions));
+          return suspend(llvm::make_unique<SplitterStep>(CS, Solutions));
         }
       }
 
+      if (isDebugMode())
+        getDebugLogger() << ")\n";
+
       // If this binding didn't match, let's check if we've attempted
       // enough bindings to stop, because some producers might need
       // to compute next step of bindings to try, which we'd want to avoid.
@@ -490,12 +503,12 @@
   /// attempting other bindings in certain conditions.
   bool SawFirstLiteralConstraint = false;
 
+public:
   TypeVariableStep(ConstraintSystem &cs, BindingContainer &bindings,
                    SmallVectorImpl<Solution> &solutions)
       : BindingStep(cs, {cs, bindings}, solutions), TypeVar(bindings.TypeVar),
         InitialBindings(bindings.Bindings.begin(), bindings.Bindings.end()) {}
 
-public:
   void setup() override;
 
   StepResult resume(bool prevFailed) override;
@@ -505,12 +518,6 @@
         << InitialBindings.size() << " initial bindings\n";
   }
 
-  static TypeVariableStep *create(ConstraintSystem &cs,
-                                  BindingContainer &bindings,
-                                  SmallVectorImpl<Solution> &solutions) {
-    return new TypeVariableStep(cs, bindings, solutions);
-  }
-
 protected:
   bool attempt(const TypeVariableBinding &choice) override;
 
@@ -574,11 +581,6 @@
     Out << '\n';
   }
 
-  static DisjunctionStep *create(ConstraintSystem &cs, Constraint *disjunction,
-                                 SmallVectorImpl<Solution> &solutions) {
-    return new DisjunctionStep(cs, disjunction, solutions);
-  }
-
 private:
   bool shouldSkip(const DisjunctionChoice &choice) const override;
 
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index eef1a1f..35b3ddb 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -3373,6 +3373,7 @@
   bool isSymmetricOperator() const;
 
   void print(llvm::raw_ostream &Out, SourceManager *SM) const {
+    Out << "disjunction choice ";
     Choice->print(Out, SM);
   }
 
@@ -3420,7 +3421,8 @@
   bool attempt(ConstraintSystem &cs) const;
 
   void print(llvm::raw_ostream &Out, SourceManager *) const {
-    Out << TypeVar->getString() << " := " << Binding.BindingType->getString();
+    Out << "type variable " << TypeVar->getString()
+        << " := " << Binding.BindingType->getString();
   }
 };
 
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index bf1f963..194f65b 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -4689,7 +4689,25 @@
   (void)decl->isDynamic();
 }
 
-bool swift::isPassThroughTypealias(TypeAliasDecl *typealias) {
+/// Determine whether this is a "pass-through" typealias, which has the
+/// same type parameters as the nominal type it references and specializes
+/// the underlying nominal type with exactly those type parameters.
+/// For example, the following typealias \c GX is a pass-through typealias:
+///
+/// \code
+/// struct X<T, U> { }
+/// typealias GX<A, B> = X<A, B>
+/// \endcode
+///
+/// whereas \c GX2 and \c GX3 are not pass-through because \c GX2 has
+/// different type parameters and \c GX3 doesn't pass its type parameters
+/// directly through.
+///
+/// \code
+/// typealias GX2<A> = X<A, A>
+/// typealias GX3<A, B> = X<B, A>
+/// \endcode
+static bool isPassThroughTypealias(TypeAliasDecl *typealias) {
   // Pass-through only makes sense when the typealias refers to a nominal
   // type.
   Type underlyingType = typealias->getUnderlyingTypeLoc().getType();
@@ -4877,31 +4895,78 @@
   if (ext->hasValidationStarted())
     return;
 
-  bindExtension(ext);
-
   DeclValidationRAII IBV(ext);
 
-  // If the extension is already known to be invalid, we're done.
-  if (ext->isInvalid())
-    return;
+  auto dc = ext->getDeclContext();
 
-  // FIXME: We need to check whether anything is specialized, because
-  // the innermost extended type might itself be a non-generic type
-  // within a generic type.
+  // If we didn't parse a type, fill in an error type and bail out.
+  if (!ext->getExtendedTypeLoc().getTypeRepr()) {
+    ext->setInvalid();
+    ext->getExtendedTypeLoc().setInvalidType(Context);
+    return;
+  }
+
+  // Validate the extended type.
+  TypeResolutionOptions options(TypeResolverContext::ExtensionBinding);
+  options |= TypeResolutionFlags::AllowUnboundGenerics;
+  if (validateType(ext->getExtendedTypeLoc(),
+                   TypeResolution::forContextual(dc), options)) {
+    ext->setInvalid();
+    ext->getExtendedTypeLoc().setInvalidType(Context);
+    return;
+  }
+
+  // Dig out the extended type.
   auto extendedType = ext->getExtendedType();
 
-  if (extendedType.isNull() || extendedType->hasError())
+  // Hack to allow extending a generic typealias.
+  if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
+    if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
+      auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
+      if (extendedNominal) {
+        extendedType = extendedNominal->getDeclaredType();
+        if (!isPassThroughTypealias(aliasDecl))
+          ext->getExtendedTypeLoc().setType(extendedType);
+      }
+    }
+  }
+
+  // Cannot extend a metatype.
+  if (extendedType->is<AnyMetatypeType>()) {
+    diagnose(ext->getLoc(), diag::extension_metatype, extendedType)
+      .highlight(ext->getExtendedTypeLoc().getSourceRange());
+    ext->setInvalid();
+    ext->getExtendedTypeLoc().setInvalidType(Context);
+    return;
+  }
+
+  // Cannot extend a bound generic type.
+  if (extendedType->isSpecialized()) {
+    diagnose(ext->getLoc(), diag::extension_specialization,
+             extendedType->getAnyNominal()->getName())
+      .highlight(ext->getExtendedTypeLoc().getSourceRange());
+    ext->setInvalid();
+    ext->getExtendedTypeLoc().setInvalidType(Context);
+    return;
+  }
+
+  auto *nominal = extendedType->getAnyNominal();
+
+  // Cannot extend function types, tuple types, etc.
+  if (nominal == nullptr) {
+    diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType)
+      .highlight(ext->getExtendedTypeLoc().getSourceRange());
+    ext->setInvalid();
+    ext->getExtendedTypeLoc().setInvalidType(Context);
+    return;
+  }
+
+  // Extensions nested inside other declarations are invalid and we
+  // do not bind them.
+  if (!isa<SourceFile>(dc))
     return;
 
   // Validate the nominal type declaration being extended.
-  NominalTypeDecl *nominal = extendedType->getAnyNominal();
-  if (!nominal) {
-    auto unbound = cast<UnboundGenericType>(extendedType.getPointer());
-    auto typealias = cast<TypeAliasDecl>(unbound->getDecl());
-    validateDecl(typealias);
-
-    nominal = typealias->getUnderlyingTypeLoc().getType()->getAnyNominal();
-  }
   validateDecl(nominal);
 
   if (nominal->getGenericParamsOfContext()) {
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 9cc6860..4b1f7a5 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -5252,6 +5252,30 @@
 void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
   DefaultWitnessChecker checker(*this, proto);
 
+  // Find the default for the given associated type.
+  auto findAssociatedTypeDefault =
+      [&](AssociatedTypeDecl *assocType,
+      AssociatedTypeDecl **defaultedAssocTypeOut = nullptr) -> Type {
+    auto defaultedAssocType =
+      AssociatedTypeInference::findDefaultedAssociatedType(*this, assocType);
+    if (!defaultedAssocType)
+      return nullptr;;
+
+    Type defaultType = defaultedAssocType->getDefaultDefinitionLoc().getType();
+    if (!defaultType)
+      return nullptr;
+
+    // Map out of its protocol context...
+    defaultType = defaultType->mapTypeOutOfContext();
+    if (defaultType->hasError())
+      return nullptr;
+
+    if (defaultedAssocTypeOut)
+      *defaultedAssocTypeOut = defaultedAssocType;
+
+    return defaultType;
+  };
+
   for (auto *requirement : proto->getMembers()) {
     if (requirement->isInvalid())
       continue;
@@ -5262,19 +5286,8 @@
 
     if (auto assocType = dyn_cast<AssociatedTypeDecl>(valueDecl)) {
       if (assocType->getOverriddenDecls().empty()) {
-        if (auto defaultedAssocType =
-                AssociatedTypeInference::findDefaultedAssociatedType(
-                  *this, assocType)) {
-          Type defaultType =
-            defaultedAssocType->getDefaultDefinitionLoc().getType();
-
-          // Map out of its protocol context...
-          defaultType = defaultType->mapTypeOutOfContext();
-
-          if (!defaultType->hasError()) {
-            proto->setDefaultTypeWitness(assocType, defaultType);
-          }
-        }
+        if (Type defaultType = findAssociatedTypeDefault(assocType))
+          proto->setDefaultTypeWitness(assocType, defaultType);
       }
 
       continue;
@@ -5288,6 +5301,77 @@
 
     checker.resolveWitnessViaLookup(valueDecl);
   }
+
+  // Find defaults for any associated conformances rooted on defaulted
+  // associated types.
+  for (const auto &req : proto->getRequirementSignature()) {
+    if (req.getKind() != RequirementKind::Conformance)
+      continue;
+    if (req.getFirstType()->isEqual(proto->getProtocolSelfType()))
+      continue;
+
+    // Find the innermost dependent member type (e.g., Self.AssocType), so
+    // we can look at the associated type.
+    auto depMemTy = req.getFirstType()->getAs<DependentMemberType>();
+    if (!depMemTy)
+      continue;
+
+    while (auto innerDepMemTy =
+             depMemTy->getBase()->getAs<DependentMemberType>())
+      depMemTy = innerDepMemTy;
+
+    if (!depMemTy->getBase()->isEqual(proto->getProtocolSelfType()))
+      continue;
+
+    auto assocType = depMemTy->getAssocType();
+    if (!assocType)
+      continue;
+
+    // Find the associated type nearest our own protocol, which might have
+    // a default not available in the associated type referenced by the
+    // (canonicalized) requirement.
+    if (assocType->getProtocol() != proto) {
+      SmallVector<ValueDecl *, 2> found;
+      proto->getModuleContext()->lookupQualified(
+                           proto, assocType->getFullName(),
+                           NL_QualifiedDefault|NL_ProtocolMembers|NL_OnlyTypes,
+                           found);
+      if (found.size() == 1 && isa<AssociatedTypeDecl>(found[0]))
+        assocType = cast<AssociatedTypeDecl>(found[0]);
+    }
+
+    // Dig out the default associated type definition.
+    AssociatedTypeDecl *defaultedAssocType = nullptr;
+    Type defaultAssocType = findAssociatedTypeDefault(assocType,
+                                                      &defaultedAssocType);
+    if (!defaultAssocType)
+      continue;
+
+    Type defaultAssocTypeInContext =
+      proto->mapTypeIntoContext(defaultAssocType);
+    auto requirementProto =
+      req.getSecondType()->castTo<ProtocolType>()->getDecl();
+    auto conformance = conformsToProtocol(defaultAssocTypeInContext,
+                                          requirementProto, proto,
+                                          ConformanceCheckFlags::Used);
+    if (!conformance) {
+      // Diagnose the lack of a conformance. This is potentially an ABI
+      // incompatibility.
+      diagnose(proto, diag::assoc_type_default_conformance_failed,
+               defaultAssocType, assocType->getFullName(), req.getFirstType(),
+               req.getSecondType());
+      diagnose(defaultedAssocType, diag::assoc_type_default_here,
+               assocType->getFullName(), defaultAssocType)
+        .highlight(
+          defaultedAssocType->getDefaultDefinitionLoc().getSourceRange());
+
+      continue;
+    }
+
+    // Record the default associated conformance.
+    proto->setDefaultAssociatedConformanceWitness(
+        req.getFirstType()->getCanonicalType(), requirementProto, *conformance);
+  }
 }
 
 void TypeChecker::recordKnownWitness(NormalProtocolConformance *conformance,
diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp
index 8f441ac..615cb50 100644
--- a/lib/Sema/TypeCheckProtocolInference.cpp
+++ b/lib/Sema/TypeCheckProtocolInference.cpp
@@ -183,15 +183,19 @@
     if (extension == conformanceExtension)
       return true;
 
-    tc.bindExtension(extension);
+    auto *extendedNominal = extension->getExtendedNominal();
+
+    // Invalid case.
+    if (extendedNominal == nullptr)
+      return true;
 
     // Assume unconstrained concrete extensions we found witnesses in are
     // always viable.
-    if (!extension->getExtendedType()->isAnyExistentialType()) {
-      // TODO: When constrained extensions are a thing, we'll need an "is
-      // as specialized as" kind of check here.
+    if (!isa<ProtocolDecl>(extendedNominal))
       return !extension->isConstrainedExtension();
-    }
+
+    // Build a generic signature.
+    tc.validateExtension(extension);
 
     // The extension may not have a generic signature set up yet, as a
     // recursion breaker, in which case we can't yet confidently reject its
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index 07fe209..90ab00d 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -346,80 +346,6 @@
   nominal->addExtension(ext);
 }
 
-static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) {
-  if (ED->getExtendedType())
-    return;
-
-  // If we didn't parse a type, fill in an error type and bail out.
-  if (!ED->getExtendedTypeLoc().getTypeRepr()) {
-    ED->setInvalid();
-    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
-    return;
-  }
-
-  auto dc = ED->getDeclContext();
-
-  // Validate the representation.
-  // FIXME: Perform some kind of "shallow" validation here?
-  TypeResolutionOptions options(TypeResolverContext::ExtensionBinding);
-  options |= TypeResolutionFlags::AllowUnboundGenerics;
-  if (TC.validateType(ED->getExtendedTypeLoc(),
-                      TypeResolution::forContextual(dc), options)) {
-    ED->setInvalid();
-    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
-    return;
-  }
-
-  // Dig out the extended type.
-  auto extendedType = ED->getExtendedType();
-
-  // Hack to allow extending a generic typealias.
-  if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
-    if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
-      auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
-      if (extendedNominal) {
-        extendedType = extendedNominal->getDeclaredType();
-        if (!isPassThroughTypealias(aliasDecl))
-          ED->getExtendedTypeLoc().setType(extendedType);
-      }
-    }
-  }
-
-  // Handle easy cases.
-
-  // Cannot extend a metatype.
-  if (extendedType->is<AnyMetatypeType>()) {
-    TC.diagnose(ED->getLoc(), diag::extension_metatype, extendedType)
-      .highlight(ED->getExtendedTypeLoc().getSourceRange());
-    ED->setInvalid();
-    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
-    return;
-  }
-
-  // Cannot extend a bound generic type.
-  if (extendedType->isSpecialized()) {
-    TC.diagnose(ED->getLoc(), diag::extension_specialization,
-                extendedType->getAnyNominal()->getName())
-      .highlight(ED->getExtendedTypeLoc().getSourceRange());
-    ED->setInvalid();
-    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
-    return;
-  }
-
-  // Dig out the nominal type being extended.
-  NominalTypeDecl *extendedNominal = extendedType->getAnyNominal();
-  if (!extendedNominal) {
-    TC.diagnose(ED->getLoc(), diag::non_nominal_extension, extendedType)
-      .highlight(ED->getExtendedTypeLoc().getSourceRange());
-    ED->setInvalid();
-    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
-    return;
-  }
-  assert(extendedNominal && "Should have the nominal type being extended");
-
-  bindExtensionToNominal(ED, extendedNominal);
-}
-
 static void bindExtensions(SourceFile &SF, TypeChecker &TC) {
   // Utility function to try and resolve the extended type without diagnosing.
   // If we succeed, we go ahead and bind the extension. Otherwise, return false.
@@ -467,14 +393,8 @@
     }
   } while(changed);
 
-  // Phase 3 - anything that remains on the worklist cannot be resolved, which
-  // means its invalid. Diagnose.
-  for (auto *ext : worklist)
-    bindExtensionDecl(ext, TC);
-}
-
-void TypeChecker::bindExtension(ExtensionDecl *ext) {
-  ::bindExtensionDecl(ext, *this);
+  // Any remaining extensions are invalid. They will be diagnosed later by
+  // typeCheckDecl().
 }
 
 static void typeCheckFunctionsAndExternalDecls(SourceFile &SF, TypeChecker &TC) {
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 6dc3db3..6d13959 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1106,8 +1106,6 @@
     validateDecl(proto);
   }
 
-  virtual void bindExtension(ExtensionDecl *ext) override;
-
   virtual void resolveExtension(ExtensionDecl *ext) override {
     validateExtension(ext);
   }
@@ -2173,26 +2171,6 @@
                                               DeclContext *DC,
                                               TypeChecker &TC);
 
-/// Determine whether this is a "pass-through" typealias, which has the
-/// same type parameters as the nominal type it references and specializes
-/// the underlying nominal type with exactly those type parameters.
-/// For example, the following typealias \c GX is a pass-through typealias:
-///
-/// \code
-/// struct X<T, U> { }
-/// typealias GX<A, B> = X<A, B>
-/// \endcode
-///
-/// whereas \c GX2 and \c GX3 are not pass-through because \c GX2 has
-/// different type parameters and \c GX3 doesn't pass its type parameters
-/// directly through.
-///
-/// \code
-/// typealias GX2<A> = X<A, A>
-/// typealias GX3<A, B> = X<B, A>
-/// \endcode
-bool isPassThroughTypealias(TypeAliasDecl *typealias);
-
 /// Whether an overriding declaration requires the 'override' keyword.
 enum class OverrideRequiresKeyword {
   /// The keyword is never required.
diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp
index 09b95d2..a97621d 100644
--- a/lib/Serialization/SerializedModuleLoader.cpp
+++ b/lib/Serialization/SerializedModuleLoader.cpp
@@ -326,9 +326,19 @@
   if (auto orphanedBuffer = loadedModuleFile->takeBufferForDiagnostics())
     OrphanedMemoryBuffers.push_back(std::move(orphanedBuffer));
 
-  if (!diagLoc)
-    return nullptr;
+  if (diagLoc)
+    serialization::diagnoseSerializedASTLoadFailure(
+        Ctx, *diagLoc, loadInfo, extendedInfo, moduleBufferID,
+        moduleDocBufferID, loadedModuleFile.get(), M.getName());
+  return nullptr;
+}
 
+void swift::serialization::diagnoseSerializedASTLoadFailure(
+    ASTContext &Ctx, SourceLoc diagLoc,
+    const serialization::ValidationInfo &loadInfo,
+    const serialization::ExtendedValidationInfo &extendedInfo,
+    StringRef moduleBufferID, StringRef moduleDocBufferID,
+    ModuleFile *loadedModuleFile, Identifier ModuleName) {
   auto diagnoseDifferentLanguageVersion = [&](StringRef shortVersion) -> bool {
     if (shortVersion.empty())
       return false;
@@ -339,10 +349,9 @@
     if (versionString.str() == shortVersion)
       return false;
 
-    Ctx.Diags.diagnose(*diagLoc,
-                       diag::serialization_module_language_version_mismatch,
-                       loadInfo.shortVersion, versionString.str(),
-                       moduleBufferID);
+    Ctx.Diags.diagnose(
+        diagLoc, diag::serialization_module_language_version_mismatch,
+        loadInfo.shortVersion, versionString.str(), moduleBufferID);
     return true;
   };
 
@@ -353,23 +362,23 @@
   case serialization::Status::FormatTooNew:
     if (diagnoseDifferentLanguageVersion(loadInfo.shortVersion))
       break;
-    Ctx.Diags.diagnose(*diagLoc, diag::serialization_module_too_new,
+    Ctx.Diags.diagnose(diagLoc, diag::serialization_module_too_new,
                        moduleBufferID);
     break;
   case serialization::Status::FormatTooOld:
     if (diagnoseDifferentLanguageVersion(loadInfo.shortVersion))
       break;
-    Ctx.Diags.diagnose(*diagLoc, diag::serialization_module_too_old,
-                       M.getName(), moduleBufferID);
+    Ctx.Diags.diagnose(diagLoc, diag::serialization_module_too_old, ModuleName,
+                       moduleBufferID);
     break;
   case serialization::Status::Malformed:
-    Ctx.Diags.diagnose(*diagLoc, diag::serialization_malformed_module,
+    Ctx.Diags.diagnose(diagLoc, diag::serialization_malformed_module,
                        moduleBufferID);
     break;
 
   case serialization::Status::MalformedDocumentation:
     assert(!moduleDocBufferID.empty());
-    Ctx.Diags.diagnose(*diagLoc, diag::serialization_malformed_module,
+    Ctx.Diags.diagnose(diagLoc, diag::serialization_malformed_module,
                        moduleDocBufferID);
     break;
 
@@ -379,19 +388,19 @@
     // not now.
     llvm::StringSet<> duplicates;
     llvm::SmallVector<ModuleFile::Dependency, 4> missing;
-    std::copy_if(loadedModuleFile->getDependencies().begin(),
-                 loadedModuleFile->getDependencies().end(),
-                 std::back_inserter(missing),
-                 [&duplicates](const ModuleFile::Dependency &dependency)->bool {
-      if (dependency.isLoaded() || dependency.isHeader())
-        return false;
-      return duplicates.insert(dependency.RawPath).second;
-    });
+    std::copy_if(
+        loadedModuleFile->getDependencies().begin(),
+        loadedModuleFile->getDependencies().end(), std::back_inserter(missing),
+        [&duplicates](const ModuleFile::Dependency &dependency) -> bool {
+          if (dependency.isLoaded() || dependency.isHeader())
+            return false;
+          return duplicates.insert(dependency.RawPath).second;
+        });
 
     // FIXME: only show module part of RawAccessPath
     assert(!missing.empty() && "unknown missing dependency?");
     if (missing.size() == 1) {
-      Ctx.Diags.diagnose(*diagLoc,diag::serialization_missing_single_dependency,
+      Ctx.Diags.diagnose(diagLoc, diag::serialization_missing_single_dependency,
                          missing.front().getPrettyPrintedPath());
     } else {
       llvm::SmallString<64> missingNames;
@@ -403,7 +412,7 @@
                  [&] { missingNames += "', '"; });
       missingNames += '\'';
 
-      Ctx.Diags.diagnose(*diagLoc, diag::serialization_missing_dependencies,
+      Ctx.Diags.diagnose(diagLoc, diag::serialization_missing_dependencies,
                          missingNames);
     }
 
@@ -419,24 +428,25 @@
     auto circularDependencyIter =
         llvm::find_if(loadedModuleFile->getDependencies(),
                       [](const ModuleFile::Dependency &next) {
-      return !next.Import.second->hasResolvedImports();
-    });
-    assert(circularDependencyIter != loadedModuleFile->getDependencies().end()
-           && "circular dependency reported, but no module with unresolved "
-              "imports found");
+                        return !next.Import.second->hasResolvedImports();
+                      });
+    assert(circularDependencyIter !=
+               loadedModuleFile->getDependencies().end() &&
+           "circular dependency reported, but no module with unresolved "
+           "imports found");
 
     // FIXME: We should include the path of the circularity as well, but that's
     // hard because we're discovering this /while/ resolving imports, which
     // means the problematic modules haven't been recorded yet.
-    Ctx.Diags.diagnose(*diagLoc, diag::serialization_circular_dependency,
+    Ctx.Diags.diagnose(diagLoc, diag::serialization_circular_dependency,
                        circularDependencyIter->getPrettyPrintedPath(),
-                       M.getName());
+                       ModuleName);
     break;
   }
 
   case serialization::Status::MissingShadowedModule: {
-    Ctx.Diags.diagnose(*diagLoc, diag::serialization_missing_shadowed_module,
-                       M.getName());
+    Ctx.Diags.diagnose(diagLoc, diag::serialization_missing_shadowed_module,
+                       ModuleName);
     if (Ctx.SearchPathOpts.SDKPath.empty() &&
         llvm::Triple(llvm::sys::getProcessTriple()).isMacOSX()) {
       Ctx.Diags.diagnose(SourceLoc(), diag::sema_no_import_no_sdk);
@@ -448,7 +458,7 @@
   case serialization::Status::FailedToLoadBridgingHeader:
     // We already emitted a diagnostic about the bridging header. Just emit
     // a generic message here.
-    Ctx.Diags.diagnose(*diagLoc, diag::serialization_load_failed, M.getName());
+    Ctx.Diags.diagnose(diagLoc, diag::serialization_load_failed, ModuleName);
     break;
 
   case serialization::Status::NameMismatch: {
@@ -457,8 +467,7 @@
     auto diagKind = diag::serialization_name_mismatch;
     if (Ctx.LangOpts.DebuggerSupport)
       diagKind = diag::serialization_name_mismatch_repl;
-    Ctx.Diags.diagnose(*diagLoc, diagKind,
-                       loadInfo.name, M.getName());
+    Ctx.Diags.diagnose(diagLoc, diagKind, loadInfo.name, ModuleName);
     break;
   }
 
@@ -468,8 +477,8 @@
     auto diagKind = diag::serialization_target_incompatible;
     if (Ctx.LangOpts.DebuggerSupport)
       diagKind = diag::serialization_target_incompatible_repl;
-    Ctx.Diags.diagnose(*diagLoc, diagKind,
-                       M.getName(), loadInfo.targetTriple, moduleBufferID);
+    Ctx.Diags.diagnose(diagLoc, diagKind, ModuleName, loadInfo.targetTriple,
+                       moduleBufferID);
     break;
   }
 
@@ -486,14 +495,12 @@
     auto diagKind = diag::serialization_target_too_new;
     if (Ctx.LangOpts.DebuggerSupport)
       diagKind = diag::serialization_target_too_new_repl;
-    Ctx.Diags.diagnose(*diagLoc, diagKind,
-                       compilationOSInfo.first, compilationOSInfo.second,
-                       M.getName(), moduleOSInfo.second, moduleBufferID);
+    Ctx.Diags.diagnose(diagLoc, diagKind, compilationOSInfo.first,
+                       compilationOSInfo.second, ModuleName,
+                       moduleOSInfo.second, moduleBufferID);
     break;
   }
   }
-
-  return nullptr;
 }
 
 bool
diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp
index 68e0d42..384cd05 100644
--- a/lib/TBDGen/TBDGen.cpp
+++ b/lib/TBDGen/TBDGen.cpp
@@ -100,11 +100,8 @@
 }
 
 void TBDGenVisitor::addAssociatedConformanceDescriptor(
-                                                 ProtocolDecl *proto,
-                                                 CanType subject,
-                                                 ProtocolDecl *requirement) {
-  auto entity = LinkEntity::forAssociatedConformanceDescriptor(proto, subject,
-                                                               requirement);
+                                           AssociatedConformance conformance) {
+  auto entity = LinkEntity::forAssociatedConformanceDescriptor(conformance);
   addSymbol(entity);
 }
 
@@ -426,10 +423,11 @@
       if (req.getFirstType()->isEqual(PD->getProtocolSelfType()))
         continue;
 
-      addAssociatedConformanceDescriptor(
-          PD,
-          req.getFirstType()->getCanonicalType(),
-          req.getSecondType()->castTo<ProtocolType>()->getDecl());
+      AssociatedConformance conformance(
+        PD,
+        req.getFirstType()->getCanonicalType(),
+        req.getSecondType()->castTo<ProtocolType>()->getDecl());
+      addAssociatedConformanceDescriptor(conformance);
     }
 
     for (auto *member : PD->getMembers()) {
@@ -442,7 +440,8 @@
         }
       }
 
-      // Always produce associated type descriptors.
+      // Always produce associated type descriptors, because they can
+      // be referenced by generic signatures.
       if (auto *assocType = dyn_cast<AssociatedTypeDecl>(member)) {
         if (assocType->getOverriddenDecls().empty())
           addAssociatedTypeDescriptor(assocType);
diff --git a/lib/TBDGen/TBDGenVisitor.h b/lib/TBDGen/TBDGenVisitor.h
index 9db482e..e468265 100644
--- a/lib/TBDGen/TBDGenVisitor.h
+++ b/lib/TBDGen/TBDGenVisitor.h
@@ -66,9 +66,7 @@
 
   void addProtocolRequirementsBaseDescriptor(ProtocolDecl *proto);
   void addAssociatedTypeDescriptor(AssociatedTypeDecl *assocType);
-  void addAssociatedConformanceDescriptor(ProtocolDecl *proto,
-                                          CanType subject,
-                                          ProtocolDecl *requirement);
+  void addAssociatedConformanceDescriptor(AssociatedConformance conformance);
 
 public:
   TBDGenVisitor(tapi::internal::InterfaceFile &symbols,
diff --git a/stdlib/public/SwiftOnoneSupport/SwiftOnoneSupport.swift b/stdlib/public/SwiftOnoneSupport/SwiftOnoneSupport.swift
index f9dc7fa..79c5d88 100644
--- a/stdlib/public/SwiftOnoneSupport/SwiftOnoneSupport.swift
+++ b/stdlib/public/SwiftOnoneSupport/SwiftOnoneSupport.swift
@@ -13,8 +13,6 @@
 //===----------------------------------------------------------------------===//
 import Swift
 
-@_frozen // FIXME(sil-serialize-all)
-@usableFromInline // FIXME(sil-serialize-all)
 internal enum _Prespecialize {
   // Create specializations for the arrays of most
   // popular builtin integer and floating point types.
diff --git a/stdlib/public/core/DropWhile.swift b/stdlib/public/core/DropWhile.swift
index 8c78847..d8ce1d9 100644
--- a/stdlib/public/core/DropWhile.swift
+++ b/stdlib/public/core/DropWhile.swift
@@ -12,21 +12,21 @@
 
 /// A sequence whose elements consist of the elements that follow the initial
 /// consecutive elements of some base sequence that satisfy a given predicate.
-@_fixed_layout // FIXME(sil-serialize-all)
+@_fixed_layout // lazy-performance
 public struct LazyDropWhileSequence<Base: Sequence> {
   public typealias Element = Base.Element
   
   /// Create an instance with elements `transform(x)` for each element
   /// `x` of base.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   internal init(_base: Base, predicate: @escaping (Element) -> Bool) {
     self._base = _base
     self._predicate = predicate
   }
 
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal var _base: Base
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal let _predicate: (Element) -> Bool
 }
 
@@ -37,27 +37,27 @@
   /// This is the associated iterator for the `LazyDropWhileSequence`,
   /// `LazyDropWhileCollection`, and `LazyDropWhileBidirectionalCollection`
   /// types.
-  @_fixed_layout // FIXME(sil-serialize-all)
+  @_fixed_layout // lazy-performance
   public struct Iterator {
     public typealias Element = Base.Element
     
-    @inlinable // FIXME(sil-serialize-all)
+    @inlinable // lazy-performance
     internal init(_base: Base.Iterator, predicate: @escaping (Element) -> Bool) {
       self._base = _base
       self._predicate = predicate
     }
 
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // lazy-performance
     internal var _predicateHasFailed = false
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // lazy-performance
     internal var _base: Base.Iterator
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // lazy-performance
     internal let _predicate: (Element) -> Bool
   }
 }
 
 extension LazyDropWhileSequence.Iterator: IteratorProtocol {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public mutating func next() -> Element? {
     // Once the predicate has failed for the first time, the base iterator
     // can be used for the rest of the elements.
@@ -83,7 +83,7 @@
   /// Returns an iterator over the elements of this sequence.
   ///
   /// - Complexity: O(1).
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func makeIterator() -> Iterator {
     return Iterator(_base: _base.makeIterator(), predicate: _predicate)
   }
@@ -101,7 +101,7 @@
   ///   its argument and returns `true` if the element should be skipped or
   ///   `false` otherwise. Once `predicate` returns `false` it will not be
   ///   called again.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func drop(
     while predicate: @escaping (Elements.Element) -> Bool
   ) -> LazyDropWhileSequence<Self.Elements> {
@@ -119,19 +119,19 @@
 ///   performance given by the `Collection` protocol. Be aware, therefore,
 ///   that general operations on lazy collections may not have the
 ///   documented complexity.
-@_fixed_layout // FIXME(sil-serialize-all)
+@_fixed_layout // lazy-performance
 public struct LazyDropWhileCollection<Base: Collection> {
   public typealias Element = Base.Element
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   internal init(_base: Base, predicate: @escaping (Element) -> Bool) {
     self._base = _base
     self._predicate = predicate
   }
 
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal var _base: Base
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal let _predicate: (Element) -> Bool
 }
 
@@ -141,7 +141,7 @@
   /// Returns an iterator over the elements of this sequence.
   ///
   /// - Complexity: O(1).
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func makeIterator() -> Iterator {
     return Iterator(_base: _base.makeIterator(), predicate: _predicate)
   }
@@ -152,12 +152,12 @@
 
   /// A position in a `LazyDropWhileCollection` or
   /// `LazyDropWhileBidirectionalCollection` instance.
-  @_fixed_layout // FIXME(sil-serialize-all)
+  @_fixed_layout // lazy-performance
   public struct Index {
     /// The position corresponding to `self` in the underlying collection.
     public let base: Base.Index
 
-    @inlinable // FIXME(sil-serialize-all)
+    @inlinable // lazy-performance
     internal init(_base: Base.Index) {
       self.base = _base
     }
@@ -165,7 +165,7 @@
 }
 
 extension LazyDropWhileCollection.Index: Equatable, Comparable {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public static func == (
     lhs: LazyDropWhileCollection<Base>.Index,
     rhs: LazyDropWhileCollection<Base>.Index
@@ -173,7 +173,7 @@
     return lhs.base == rhs.base
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public static func < (
     lhs: LazyDropWhileCollection<Base>.Index,
     rhs: LazyDropWhileCollection<Base>.Index
@@ -201,7 +201,7 @@
 }
 
 extension LazyDropWhileCollection: Collection {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public var startIndex: Index {
     var index = _base.startIndex
     while index != _base.endIndex && _predicate(_base[index]) {
@@ -210,19 +210,19 @@
     return Index(_base: index)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public var endIndex: Index {
     return Index(_base: _base.endIndex)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func index(after i: Index) -> Index {
     _precondition(i.base < _base.endIndex, "Can't advance past endIndex")
     return Index(_base: _base.index(after: i.base))
   }
 
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public subscript(position: Index) -> Element {
     return _base[position.base]
   }
@@ -232,7 +232,7 @@
 
 extension LazyDropWhileCollection: BidirectionalCollection 
 where Base: BidirectionalCollection {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func index(before i: Index) -> Index {
     _precondition(i > startIndex, "Can't move before startIndex")
     return Index(_base: _base.index(before: i.base))
@@ -247,7 +247,7 @@
   ///   as its argument and returns `true` if the element should be skipped or
   ///   `false` otherwise. Once `predicate` returns `false` it will not be
   ///   called again.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func drop(
     while predicate: @escaping (Elements.Element) -> Bool
   ) -> LazyDropWhileCollection<Self.Elements> {
diff --git a/stdlib/public/core/Filter.swift b/stdlib/public/core/Filter.swift
index 9b13baa..c630af2 100644
--- a/stdlib/public/core/Filter.swift
+++ b/stdlib/public/core/Filter.swift
@@ -18,17 +18,17 @@
 ///   is a `LazyFilterSequence`.
 @_fixed_layout // lazy-performance
 public struct LazyFilterSequence<Base: Sequence> {
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal var _base: Base
 
   /// The predicate used to determine which elements produced by
   /// `base` are also produced by `self`.
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal let _predicate: (Base.Element) -> Bool
 
   /// Creates an instance consisting of the elements `x` of `base` for
   /// which `isIncluded(x) == true`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public // @testable
   init(_base base: Base, _ isIncluded: @escaping (Base.Element) -> Bool) {
     self._base = base
diff --git a/stdlib/public/core/Integers.swift b/stdlib/public/core/Integers.swift
index 0418e5a..2c00e90 100644
--- a/stdlib/public/core/Integers.swift
+++ b/stdlib/public/core/Integers.swift
@@ -303,7 +303,7 @@
 ///
 /// - Parameter x: A signed number.
 /// - Returns: The absolute value of `x`.
-@_transparent
+@inlinable
 public func abs<T : SignedNumeric>(_ x: T) -> T
   where T.Magnitude == T {
   return x.magnitude
@@ -322,9 +322,9 @@
 ///
 /// - Parameter x: A signed number.
 /// - Returns: The absolute value of `x`.
-@inlinable // FIXME(sil-serialize-all)
+@inlinable
 public func abs<T : SignedNumeric & Comparable>(_ x: T) -> T {
-  return x < 0 ? -x : x
+  return x < (0 as T) ? -x : x
 }
 
 extension Numeric {
@@ -1185,7 +1185,7 @@
   ///
   /// - Returns: The sign of this number, expressed as an integer of the same
   ///   type.
-  @_transparent
+  @inlinable
   public func signum() -> Self {
     return (self > (0 as Self) ? 1 : 0) - (self < (0 as Self) ? 1 : 0)
   }
@@ -1196,7 +1196,7 @@
     return it.next() ?? 0
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   public func _binaryLogarithm() -> Int {
     _precondition(self > (0 as Self))
     var (quotient, remainder) =
@@ -1233,7 +1233,7 @@
   /// - Parameter rhs: The value to divide this value by.
   /// - Returns: A tuple containing the quotient and remainder of this value
   ///   divided by `rhs`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   public func quotientAndRemainder(dividingBy rhs: Self)
     -> (quotient: Self, remainder: Self) {
     return (self / rhs, self % rhs)
@@ -1370,7 +1370,7 @@
   ///   - lhs: The value to shift.
   ///   - rhs: The number of bits to shift `lhs` to the right.
   @_semantics("optimize.sil.specialize.generic.partial.never")
-  @inlinable
+  @_transparent
   public static func >> <RHS: BinaryInteger>(lhs: Self, rhs: RHS) -> Self {
     var r = lhs
     r >>= rhs
@@ -1416,7 +1416,7 @@
   ///   - lhs: The value to shift.
   ///   - rhs: The number of bits to shift `lhs` to the left.
   @_semantics("optimize.sil.specialize.generic.partial.never")
-  @inlinable
+  @_transparent
   public static func << <RHS: BinaryInteger>(lhs: Self, rhs: RHS) -> Self {
     var r = lhs
     r <<= rhs
@@ -1493,7 +1493,6 @@
   }
 
   /// A textual representation of this value.
-  @inlinable // FIXME(sil-serialize-all)
   public var description: String {
     return _description(radix: 10, uppercase: false)
   }
@@ -1505,7 +1504,6 @@
 //===----------------------------------------------------------------------===//
 
 extension BinaryInteger {
-  // FIXME(ABI): using Int as the return type is wrong.
   /// Returns the distance from this value to the given value, expressed as a
   /// stride.
   ///
@@ -1514,7 +1512,7 @@
   ///
   /// - Parameter other: The value to calculate the distance to.
   /// - Returns: The distance from this value to `other`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @inline(__always)
   public func distance(to other: Self) -> Int {
     if !Self.isSigned {
@@ -1542,7 +1540,6 @@
     _preconditionFailure("Distance is not representable in Int")
   }
 
-  // FIXME(ABI): using Int as the parameter type is wrong.
   /// Returns a value that is offset the specified distance from this value.
   ///
   /// Use the `advanced(by:)` method in generic code to offset a value by a
@@ -1554,7 +1551,7 @@
   ///
   /// - Parameter n: The distance to advance this value.
   /// - Returns: A value that is offset from this value by `n`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @inline(__always)
   public func advanced(by n: Int) -> Self {
     if !Self.isSigned {
@@ -1594,8 +1591,7 @@
   /// - Parameters:
   ///   - lhs: An integer to compare.
   ///   - rhs: Another integer to compare.
-  @inlinable // FIXME(sil-serialize-all)
-  @inline(__always)
+  @_transparent
   public static func == <
     Other : BinaryInteger
   >(lhs: Self, rhs: Other) -> Bool {
@@ -1669,8 +1665,7 @@
   /// - Parameters:
   ///   - lhs: An integer to compare.
   ///   - rhs: Another integer to compare.
-  @inlinable // FIXME(sil-serialize-all)
-  @inline(__always)
+  @_transparent
   public static func < <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool {
     let lhsNegative = Self.isSigned && lhs < (0 as Self)
     let rhsNegative = Other.isSigned && rhs < (0 as Other)
@@ -1713,7 +1708,6 @@
   ///   - lhs: An integer to compare.
   ///   - rhs: Another integer to compare.
   @_transparent
-  //@inline(__always)
   public static func <= <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool {
     return !(rhs < lhs)
   }
@@ -1729,7 +1723,6 @@
   ///   - lhs: An integer to compare.
   ///   - rhs: Another integer to compare.
   @_transparent
-  //@inline(__always)
   public static func >= <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool {
     return !(lhs < rhs)
   }
@@ -1745,7 +1738,6 @@
   ///   - lhs: An integer to compare.
   ///   - rhs: Another integer to compare.
   @_transparent
-  //@inline(__always)
   public static func > <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool {
     return rhs < lhs
   }
@@ -1773,20 +1765,17 @@
     return !(lhs == rhs)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
-  @inline(__always)
+  @_transparent
   public static func <= (lhs: Self, rhs: Self) -> Bool {
     return !(rhs < lhs)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
-  @inline(__always)
+  @_transparent
   public static func >= (lhs: Self, rhs: Self) -> Bool {
     return !(lhs < rhs)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
-  @inline(__always)
+  @_transparent
   public static func > (lhs: Self, rhs: Self) -> Bool {
     return rhs < lhs
   }
@@ -2214,7 +2203,7 @@
   @inlinable
   public var bitWidth: Int { return Self.bitWidth }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   public func _binaryLogarithm() -> Int {
     _precondition(self > (0 as Self))
     return Self.bitWidth &- (leadingZeroBitCount &+ 1)
@@ -2225,7 +2214,7 @@
   ///
   /// - Parameter value: A value to use as the little-endian representation of
   ///   the new integer.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   public init(littleEndian value: Self) {
 #if _endian(little)
     self = value
@@ -2239,7 +2228,7 @@
   ///
   /// - Parameter value: A value to use as the big-endian representation of the
   ///   new integer.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   public init(bigEndian value: Self) {
 #if _endian(big)
     self = value
@@ -2253,7 +2242,7 @@
   /// If necessary, the byte order of this value is reversed from the typical
   /// byte order of this integer type. On a little-endian platform, for any
   /// integer `x`, `x == x.littleEndian`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   public var littleEndian: Self {
 #if _endian(little)
     return self
@@ -2267,7 +2256,7 @@
   /// If necessary, the byte order of this value is reversed from the typical
   /// byte order of this integer type. On a big-endian platform, for any
   /// integer `x`, `x == x.bigEndian`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   public var bigEndian: Self {
 #if _endian(big)
     return self
@@ -2310,7 +2299,6 @@
   ///   - rhs: The number of bits to shift `lhs` to the right. If `rhs` is
   ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
   ///     value within that range.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
   public static func &>> (lhs: Self, rhs: Self) -> Self {
@@ -2354,7 +2342,7 @@
   ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
   ///     value within that range.
   @_semantics("optimize.sil.specialize.generic.partial.never")
-  @inlinable
+  @_transparent
   public static func &>> <
     Other : BinaryInteger
   >(lhs: Self, rhs: Other) -> Self {
@@ -2389,7 +2377,6 @@
   ///   - rhs: The number of bits to shift `lhs` to the right. If `rhs` is
   ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
   ///     value within that range.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
   public static func &>>= <
@@ -2432,7 +2419,6 @@
   ///   - rhs: The number of bits to shift `lhs` to the left. If `rhs` is
   ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
   ///     value within that range.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
   public static func &<< (lhs: Self, rhs: Self) -> Self {
@@ -2476,7 +2462,7 @@
   ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
   ///     value within that range.
   @_semantics("optimize.sil.specialize.generic.partial.never")
-  @inlinable
+  @_transparent
   public static func &<< <
     Other : BinaryInteger
   >(lhs: Self, rhs: Other) -> Self {
@@ -2511,7 +2497,6 @@
   ///   - rhs: The number of bits to shift `lhs` to the left. If `rhs` is
   ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
   ///     value within that range.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
   public static func &<<= <
@@ -2756,7 +2741,6 @@
   /// - Parameters:
   ///   - lhs: The value to shift.
   ///   - rhs: The number of bits to shift `lhs` to the right.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
   public static func >> <
@@ -2785,8 +2769,7 @@
     lhs = _nonMaskingRightShift(lhs, shift)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
-  @inline(__always)
+  @_transparent
   public static func _nonMaskingRightShift(_ lhs: Self, _ rhs: Int) -> Self {
     let overshiftR = Self.isSigned ? lhs &>> (Self.bitWidth - 1) : 0
     let overshiftL: Self = 0
@@ -2845,7 +2828,6 @@
   /// - Parameters:
   ///   - lhs: The value to shift.
   ///   - rhs: The number of bits to shift `lhs` to the left.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
   public static func << <
@@ -2874,8 +2856,7 @@
     lhs = _nonMaskingLeftShift(lhs, shift)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
-  @inline(__always)
+  @_transparent
   public static func _nonMaskingLeftShift(_ lhs: Self, _ rhs: Int) -> Self {
     let overshiftR = Self.isSigned ? lhs &>> (Self.bitWidth - 1) : 0
     let overshiftL: Self = 0
@@ -2972,9 +2953,8 @@
   ///     // y == nil
   ///
   /// - Parameter source: A floating-point value to convert to an integer.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
-  @inline(__always)
+  @inlinable
   public init?<T : BinaryFloatingPoint>(exactly source: T) {
     let (temporary, exact) = Self._convert(from: source)
     guard exact, let value = temporary else {
@@ -3003,7 +2983,7 @@
   ///     // y == 0
   ///
   /// - Parameter source: An integer to convert to this type.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @_semantics("optimize.sil.specialize.generic.partial.never")
   public init<Other : BinaryInteger>(clamping source: Other) {
     if _slowPath(source < Self.min) {
@@ -3033,7 +3013,7 @@
   ///
   /// - Parameter rhs: The value to add to this value.
   /// - Returns: The sum of this value and `rhs`.
-  @_transparent
+  @inline(__always)
   public func unsafeAdding(_ other: Self) -> Self {
     let (result, overflow) = self.addingReportingOverflow(other)
 
@@ -3066,7 +3046,7 @@
   ///
   /// - Parameter rhs: The value to subtract from this value.
   /// - Returns: The result of subtracting `rhs` from this value.
-  @_transparent
+  @inline(__always)
   public func unsafeSubtracting(_ other: Self) -> Self {
     let (result, overflow) = self.subtractingReportingOverflow(other)
 
@@ -3099,7 +3079,7 @@
   ///
   /// - Parameter rhs: The value to multiply by this value.
   /// - Returns: The product of this value and `rhs`.
-  @_transparent
+  @inline(__always)
   public func unsafeMultiplied(by other: Self) -> Self {
     let (result, overflow) = self.multipliedReportingOverflow(by: other)
 
@@ -3128,7 +3108,7 @@
   ///
   /// - Parameter rhs: The value to divide this value by.
   /// - Returns: The result of dividing this value by `rhs`.
-  @_transparent
+  @inline(__always)
   public func unsafeDivided(by other: Self) -> Self {
     let (result, overflow) = self.dividedReportingOverflow(by: other)
 
@@ -3179,7 +3159,6 @@
   ///     // 'y' has a binary representation of 11111111_11101011
   ///
   /// - Parameter source: An integer to convert to this type.
-  @inlinable // FIXME(sil-serialize-all)
   @inline(__always)
   public init<T : BinaryInteger>(truncatingIfNeeded source: T) {
     if Self.bitWidth <= Int.bitWidth {
@@ -3421,14 +3400,18 @@
   /// to find an absolute value. In addition, because `abs(_:)` always returns
   /// a value of the same type, even in a generic context, using the function
   /// instead of the `magnitude` property is encouraged.
-  @_transparent
-  public var magnitude: Self { return self }
+  public var magnitude: Self {
+    @inline(__always)
+    get { return self }
+  }
 
   /// A Boolean value indicating whether this type is a signed integer type.
   ///
   /// This property is always `false` for unsigned integer types.
-  @_transparent
-  public static var isSigned: Bool { return false }
+  public static var isSigned: Bool {
+    @inline(__always)
+    get { return false }
+  }
 }
 
 extension UnsignedInteger where Self : FixedWidthInteger {
@@ -3451,7 +3434,6 @@
   ///
   /// - Parameter source: A value to convert to this type of integer. The value
   ///   passed as `source` must be representable in this type.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @inline(__always)
   public init<T : BinaryInteger>(_ source: T) {
@@ -3482,7 +3464,6 @@
   ///     // y == nil
   ///
   /// - Parameter source: A value to convert to this type of integer.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @inline(__always)
   public init?<T : BinaryInteger>(exactly source: T) {
@@ -3503,17 +3484,13 @@
   /// For unsigned integer types, this value is `(2 ** bitWidth) - 1`, where
   /// `**` is exponentiation.
   @_transparent
-  public static var max: Self {
-    return ~0
-  }
+  public static var max: Self { return ~0 }
 
   /// The minimum representable integer in this type.
   ///
   /// For unsigned integer types, this value is always `0`.
   @_transparent
-  public static var min: Self {
-    return 0
-  }
+  public static var min: Self { return 0 }
 }
 
 
@@ -3532,8 +3509,10 @@
   /// A Boolean value indicating whether this type is a signed integer type.
   ///
   /// This property is always `true` for signed integer types.
-  @_transparent
-  public static var isSigned: Bool { return true }
+  public static var isSigned: Bool {
+    @inline(__always)
+    get { return true }
+  }
 }
 
 extension SignedInteger where Self : FixedWidthInteger {
@@ -3556,7 +3535,6 @@
   ///
   /// - Parameter source: A value to convert to this type of integer. The value
   ///   passed as `source` must be representable in this type.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @inline(__always)
   public init<T : BinaryInteger>(_ source: T) {
@@ -3589,7 +3567,6 @@
   ///     // y == nil
   ///
   /// - Parameter source: A value to convert to this type of integer.
-  @inlinable // FIXME(sil-serialize-all)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @inline(__always)
   public init?<T : BinaryInteger>(exactly source: T) {
@@ -3611,9 +3588,7 @@
   /// For signed integer types, this value is `(2 ** (bitWidth - 1)) - 1`,
   /// where `**` is exponentiation.
   @_transparent
-  public static var max: Self {
-    return ~min
-  }
+  public static var max: Self { return ~min }
 
   /// The minimum representable integer in this type.
   ///
@@ -3657,7 +3632,7 @@
 ///
 /// - Parameter x: The integer to convert, and instance of type `T`.
 /// - Returns: The value of `x` converted to type `U`.
-@_transparent
+@inlinable
 public func numericCast<T : BinaryInteger, U : BinaryInteger>(_ x: T) -> U {
   return U(x)
 }
@@ -3669,7 +3644,6 @@
 // At the same time, since they are obsolete in Swift 4, this will not cause
 // `u8 << -1` to fail due to an overflow in an unsigned value.
 extension FixedWidthInteger {
-  @inlinable // FIXME(sil-serialize-all)
   @available(swift, obsoleted: 4)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
@@ -3679,7 +3653,6 @@
     return lhs
   }
 
-  @inlinable // FIXME(sil-serialize-all)
   @available(swift, obsoleted: 4)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
@@ -3687,7 +3660,6 @@
     _nonMaskingRightShiftGeneric(&lhs, rhs)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
   @available(swift, obsoleted: 4)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
@@ -3697,7 +3669,6 @@
     return lhs
   }
 
-  @inlinable // FIXME(sil-serialize-all)
   @available(swift, obsoleted: 4)
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @_transparent
@@ -3707,9 +3678,8 @@
 }
 
 extension FixedWidthInteger {
-  @inlinable // FIXME(sil-serialize-all)
   @available(swift, obsoleted: 4, message: "Use addingReportingOverflow(_:) instead.")
-  @_transparent
+  @inlinable
   public static func addWithOverflow(
     _ lhs: Self, _ rhs: Self
   ) -> (Self, overflow: Bool) {
@@ -3718,9 +3688,8 @@
     return (partialValue, overflow: overflow)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
   @available(swift, obsoleted: 4, message: "Use subtractingReportingOverflow(_:) instead.")
-  @_transparent
+  @inlinable
   public static func subtractWithOverflow(
     _ lhs: Self, _ rhs: Self
   ) -> (Self, overflow: Bool) {
@@ -3729,9 +3698,8 @@
     return (partialValue, overflow: overflow)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @available(swift, obsoleted: 4, message: "Use multipliedReportingOverflow(by:) instead.")
-  @_transparent
   public static func multiplyWithOverflow(
     _ lhs: Self, _ rhs: Self
   ) -> (Self, overflow: Bool) {
@@ -3740,9 +3708,8 @@
     return (partialValue, overflow: overflow)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @available(swift, obsoleted: 4, message: "Use dividedReportingOverflow(by:) instead.")
-  @_transparent
   public static func divideWithOverflow(
     _ lhs: Self, _ rhs: Self
   ) -> (Self, overflow: Bool) {
@@ -3751,9 +3718,8 @@
     return (partialValue, overflow: overflow)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @available(swift, obsoleted: 4, message: "Use remainderReportingOverflow(dividingBy:) instead.")
-  @_transparent
   public static func remainderWithOverflow(
     _ lhs: Self, _ rhs: Self
   ) -> (Self, overflow: Bool) {
@@ -3764,7 +3730,7 @@
 }
 
 extension BinaryInteger {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @available(swift, obsoleted: 3.2,
     message: "Please use FixedWidthInteger protocol as a generic constraint and addingReportingOverflow(_:) method instead.")
   public static func addWithOverflow(
@@ -3773,7 +3739,7 @@
     fatalError("Unavailable")
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @available(swift, obsoleted: 3.2,
     message: "Please use FixedWidthInteger protocol as a generic constraint and subtractingReportingOverflow(_:) method instead.")
   public static func subtractWithOverflow(
@@ -3782,7 +3748,7 @@
     fatalError("Unavailable")
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @available(swift, obsoleted: 3.2,
     message: "Please use FixedWidthInteger protocol as a generic constraint and multipliedReportingOverflow(by:) method instead.")
   public static func multiplyWithOverflow(
@@ -3791,7 +3757,7 @@
     fatalError("Unavailable")
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @available(swift, obsoleted: 3.2,
     message: "Please use FixedWidthInteger protocol as a generic constraint and dividedReportingOverflow(by:) method instead.")
   public static func divideWithOverflow(
@@ -3800,7 +3766,7 @@
     fatalError("Unavailable")
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   @available(swift, obsoleted: 3.2,
     message: "Please use FixedWidthInteger protocol as a generic constraint and remainderReportingOverflow(dividingBy:) method instead.")
   public static func remainderWithOverflow(
@@ -3820,24 +3786,24 @@
 //    var _  = (x &+ (y - 1)) < x
 //                      ^
 extension SignedInteger {
-  @inlinable // FIXME(sil-serialize-all)
+  @_transparent
   public static func _maskingAdd(_ lhs: Self, _ rhs: Self) -> Self {
     fatalError("Should be overridden in a more specific type")
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @_transparent
   @available(swift, obsoleted: 4.0,
       message: "Please use 'FixedWidthInteger' instead of 'SignedInteger' to get '&+' in generic code.")
   public static func &+ (lhs: Self, rhs: Self) -> Self {
     return _maskingAdd(lhs, rhs)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @_transparent
   public static func _maskingSubtract(_ lhs: Self, _ rhs: Self) -> Self {
     fatalError("Should be overridden in a more specific type")
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @_transparent
   @available(swift, obsoleted: 4.0,
       message: "Please use 'FixedWidthInteger' instead of 'SignedInteger' to get '&-' in generic code.")
   public static func &- (lhs: Self, rhs: Self) -> Self {
@@ -3848,7 +3814,7 @@
 extension SignedInteger where Self : FixedWidthInteger {
   // This overload is supposed to break the ambiguity between the
   // implementations on SignedInteger and FixedWidthInteger
-  @inlinable // FIXME(sil-serialize-all)
+  @_transparent
   public static func &+ (lhs: Self, rhs: Self) -> Self {
     return _maskingAdd(lhs, rhs)
   }
@@ -3860,7 +3826,7 @@
 
   // This overload is supposed to break the ambiguity between the
   // implementations on SignedInteger and FixedWidthInteger
-  @inlinable // FIXME(sil-serialize-all)
+  @_transparent
   public static func &- (lhs: Self, rhs: Self) -> Self {
     return _maskingSubtract(lhs, rhs)
   }
diff --git a/stdlib/public/core/Join.swift b/stdlib/public/core/Join.swift
index 44e5399..f6001c0 100644
--- a/stdlib/public/core/Join.swift
+++ b/stdlib/public/core/Join.swift
@@ -17,16 +17,16 @@
 
   public typealias Element = Base.Element.Element
   
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal var _base: Base
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal var _separator: ContiguousArray<Element>
 
   /// Creates an iterator that presents the elements of the sequences
   /// traversed by `base`, concatenated using `separator`.
   ///
   /// - Complexity: O(`separator.count`).
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public init<Separator : Sequence>(base: Base, separator: Separator)
     where Separator.Element == Element {
     self._base = base
diff --git a/stdlib/public/core/MigrationSupport.swift b/stdlib/public/core/MigrationSupport.swift
index f2cfa39..b11e7c4 100644
--- a/stdlib/public/core/MigrationSupport.swift
+++ b/stdlib/public/core/MigrationSupport.swift
@@ -330,6 +330,9 @@
   }
 }
 
+@available(swift, deprecated: 5.0, renamed: "KeyValuePairs")
+public typealias DictionaryLiteral<Key, Value> = KeyValuePairs<Key, Value>
+
 extension LazySequenceProtocol {
   /// Returns the non-`nil` results of mapping the given transformation over
   /// this sequence.
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index a3cd3db..6f5271d 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -524,7 +524,6 @@
 ///     let pairs = IntPairs([1: 2, 1: 1, 3: 4, 2: 1])
 ///     print(pairs.elements)
 ///     // Prints "[(1, 2), (1, 1), (3, 4), (2, 1)]"
-@_fixed_layout // FIXME(sil-serialize-all)
 public struct KeyValuePairs<Key, Value> : ExpressibleByDictionaryLiteral {
   /// Creates a new `KeyValuePairs` instance from the given dictionary
   /// literal.
@@ -534,13 +533,9 @@
   public init(dictionaryLiteral elements: (Key, Value)...) {
     self._elements = elements
   }
-  @usableFromInline // FIXME(sil-serialize-all)
   internal let _elements: [(Key, Value)]
 }
 
-@available(swift, deprecated: 5.0, renamed: "KeyValuePairs")
-public typealias DictionaryLiteral<Key, Value> = KeyValuePairs<Key, Value>
-
 /// `Collection` conformance that allows `KeyValuePairs` to
 /// interoperate with the rest of the standard library.
 extension KeyValuePairs : RandomAccessCollection {
@@ -550,7 +545,6 @@
   ///
   /// If the `KeyValuePairs` instance is empty, `startIndex` is equal to
   /// `endIndex`.
-  @inlinable // FIXME(sil-serialize-all)
   public var startIndex: Int { return 0 }
 
   /// The collection's "past the end" position---that is, the position one
@@ -558,7 +552,6 @@
   ///
   /// If the `KeyValuePairs` instance is empty, `endIndex` is equal to
   /// `startIndex`.
-  @inlinable // FIXME(sil-serialize-all)
   public var endIndex: Int { return _elements.endIndex }
 
   // FIXME(ABI)#174 (Type checker): a typealias is needed to prevent <rdar://20248032>
@@ -572,7 +565,6 @@
   ///   must be a valid index of the collection that is not equal to the
   ///   `endIndex` property.
   /// - Returns: The key-value pair at position `position`.
-  @inlinable // FIXME(sil-serialize-all)
   public subscript(position: Int) -> Element {
     return _elements[position]
   }
@@ -618,7 +610,6 @@
   ///
   ///     print(String(describing: p))
   ///     // Prints "(21, 30)"
-  @inlinable // FIXME(sil-serialize-all)
   public init<Subject>(describing instance: Subject) {
     self.init()
     _print_unlocked(instance, &self)
@@ -668,7 +659,6 @@
   ///
   ///     print(String(reflecting: p))
   ///     // Prints "Point(x: 21, y: 30)"
-  @inlinable // FIXME(sil-serialize-all)
   public init<Subject>(reflecting subject: Subject) {
     self.init()
     _debugPrint_unlocked(subject, &self)
diff --git a/stdlib/public/core/OptionSet.swift b/stdlib/public/core/OptionSet.swift
index c551fce..f8c6b75 100644
--- a/stdlib/public/core/OptionSet.swift
+++ b/stdlib/public/core/OptionSet.swift
@@ -142,7 +142,7 @@
   /// - Parameter other: An option set.
   /// - Returns: A new option set made up of the elements contained in this
   ///   set, in `other`, or in both.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func union(_ other: Self) -> Self {
     var r: Self = Self(rawValue: self.rawValue)
     r.formUnion(other)
@@ -169,7 +169,7 @@
   /// - Parameter other: An option set.
   /// - Returns: A new option set with only the elements contained in both this
   ///   set and `other`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func intersection(_ other: Self) -> Self {
     var r = Self(rawValue: self.rawValue)
     r.formIntersection(other)
@@ -182,7 +182,7 @@
   /// - Parameter other: An option set.
   /// - Returns: A new option set with only the elements contained in either
   ///   this set or `other`, but not in both.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func symmetricDifference(_ other: Self) -> Self {
     var r = Self(rawValue: self.rawValue)
     r.formSymmetricDifference(other)
@@ -212,7 +212,7 @@
   /// - Parameter member: The element to look for in the option set.
   /// - Returns: `true` if the option set contains `member`; otherwise,
   ///   `false`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func contains(_ member: Self) -> Bool {
     return self.isSuperset(of: member)
   }
@@ -237,7 +237,7 @@
   /// - Returns: `(true, newMember)` if `newMember` was not contained in
   ///   `self`. Otherwise, returns `(false, oldMember)`, where `oldMember` is
   ///   the member of the set equal to `newMember`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   @discardableResult
   public mutating func insert(
     _ newMember: Element
@@ -283,7 +283,7 @@
   /// - Parameter member: The element of the set to remove.
   /// - Returns: The intersection of `[member]` and the set, if the
   ///   intersection was nonempty; otherwise, `nil`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   @discardableResult
   public mutating func remove(_ member: Element) -> Element? {
     let r = isSuperset(of: member) ? Optional(member) : nil
@@ -303,7 +303,7 @@
   ///
   /// - Returns: The intersection of `[newMember]` and the set if the
   ///   intersection was nonempty; otherwise, `nil`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   @discardableResult
   public mutating func update(with newMember: Element) -> Element? {
     let r = self.intersection(newMember)
@@ -330,7 +330,7 @@
   /// Creates an empty option set.
   ///
   /// This initializer creates an option set with a raw value of zero.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public init() {
     self.init(rawValue: 0)
   }
@@ -341,7 +341,7 @@
   /// two sets' raw values.
   ///
   /// - Parameter other: An option set.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func formUnion(_ other: Self) {
     self = Self(rawValue: self.rawValue | other.rawValue)
   }
@@ -353,7 +353,7 @@
   /// two sets' raw values.
   ///
   /// - Parameter other: An option set.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func formIntersection(_ other: Self) {
     self = Self(rawValue: self.rawValue & other.rawValue)
   }
@@ -365,7 +365,7 @@
   /// sets' raw values.
   ///
   /// - Parameter other: An option set.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func formSymmetricDifference(_ other: Self) {
     self = Self(rawValue: self.rawValue ^ other.rawValue)
   }
diff --git a/stdlib/public/core/OutputStream.swift b/stdlib/public/core/OutputStream.swift
index e6c33d3..346bd43 100644
--- a/stdlib/public/core/OutputStream.swift
+++ b/stdlib/public/core/OutputStream.swift
@@ -75,9 +75,7 @@
 }
 
 extension TextOutputStream {
-  @inlinable // FIXME(sil-serialize-all)
   public mutating func _lock() {}
-  @inlinable // FIXME(sil-serialize-all)
   public mutating func _unlock() {}
 }
 
@@ -278,7 +276,6 @@
 internal func _opaqueSummary(_ metadata: Any.Type) -> UnsafePointer<CChar>?
 
 /// Do our best to print a value that cannot be printed directly.
-@inlinable // FIXME(sil-serialize-all)
 @_semantics("optimize.sil.specialize.generic.never")
 internal func _adHocPrint_unlocked<T, TargetStream : TextOutputStream>(
     _ value: T, _ mirror: Mirror, _ target: inout TargetStream,
@@ -460,7 +457,6 @@
   _adHocPrint_unlocked(value, mirror, &target, isDebugPrint: true)
 }
 
-@inlinable // FIXME(sil-serialize-all)
 @_semantics("optimize.sil.specialize.generic.never")
 internal func _dumpPrint_unlocked<T, TargetStream : TextOutputStream>(
     _ value: T, _ mirror: Mirror, _ target: inout TargetStream
diff --git a/stdlib/public/core/PrefixWhile.swift b/stdlib/public/core/PrefixWhile.swift
index 4c80aac..3304c60 100644
--- a/stdlib/public/core/PrefixWhile.swift
+++ b/stdlib/public/core/PrefixWhile.swift
@@ -13,19 +13,19 @@
 
 /// A sequence whose elements consist of the initial consecutive elements of
 /// some base sequence that satisfy a given predicate.
-@_fixed_layout // FIXME(sil-serialize-all)
+@_fixed_layout // lazy-performance
 public struct LazyPrefixWhileSequence<Base: Sequence> {
   public typealias Element = Base.Element
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   internal init(_base: Base, predicate: @escaping (Element) -> Bool) {
     self._base = _base
     self._predicate = predicate
   }
 
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal var _base: Base
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal let _predicate: (Element) -> Bool
 }
 
@@ -37,18 +37,18 @@
   /// This is the associated iterator for the `LazyPrefixWhileSequence`,
   /// `LazyPrefixWhileCollection`, and `LazyPrefixWhileBidirectionalCollection`
   /// types.
-  @_fixed_layout // FIXME(sil-serialize-all)
+  @_fixed_layout // lazy-performance
   public struct Iterator {
     public typealias Element = Base.Element
 
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // lazy-performance
     internal var _predicateHasFailed = false
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // lazy-performance
     internal var _base: Base.Iterator
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // lazy-performance
     internal let _predicate: (Element) -> Bool
 
-    @inlinable // FIXME(sil-serialize-all)
+    @inlinable // lazy-performance
     internal init(_base: Base.Iterator, predicate: @escaping (Element) -> Bool) {
       self._base = _base
       self._predicate = predicate
@@ -57,7 +57,7 @@
 }
 
 extension LazyPrefixWhileSequence.Iterator: IteratorProtocol, Sequence {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public mutating func next() -> Element? {
     // Return elements from the base iterator until one fails the predicate.
     if !_predicateHasFailed, let nextElement = _base.next() {
@@ -74,7 +74,7 @@
 extension LazyPrefixWhileSequence: Sequence {
   public typealias SubSequence = AnySequence<Element> // >:(
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func makeIterator() -> Iterator {
     return Iterator(_base: _base.makeIterator(), predicate: _predicate)
   }
@@ -92,7 +92,7 @@
   ///   its argument and returns `true` if the element should be included or
   ///   `false` otherwise. Once `predicate` returns `false` it will not be
   ///   called again.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func prefix(
     while predicate: @escaping (Elements.Element) -> Bool
   ) -> LazyPrefixWhileSequence<Self.Elements> {
@@ -109,27 +109,27 @@
 ///   the usual performance given by the `Collection` protocol. Be aware,
 ///   therefore, that general operations on `${Self}` instances may not have
 ///   the documented complexity.
-@_fixed_layout // FIXME(sil-serialize-all)
+@_fixed_layout // lazy-performance
 public struct LazyPrefixWhileCollection<Base: Collection> {
   public typealias Element = Base.Element
   public typealias SubSequence = Slice<LazyPrefixWhileCollection<Base>>
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   internal init(_base: Base, predicate: @escaping (Element) -> Bool) {
     self._base = _base
     self._predicate = predicate
   }
 
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal var _base: Base
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // lazy-performance
   internal let _predicate: (Element) -> Bool
 }
 
 extension LazyPrefixWhileCollection: Sequence {
   public typealias Iterator = LazyPrefixWhileSequence<Base>.Iterator
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func makeIterator() -> Iterator {
     return Iterator(_base: _base.makeIterator(), predicate: _predicate)
   }
@@ -138,7 +138,7 @@
 extension LazyPrefixWhileCollection {
   /// A position in the base collection of a `LazyPrefixWhileCollection` or the
   /// end of that collection.
-  @_frozen // FIXME(sil-serialize-all)
+  @_frozen // lazy-performance
   @usableFromInline
   internal enum _IndexRepresentation {
     case index(Base.Index)
@@ -147,14 +147,14 @@
   
   /// A position in a `LazyPrefixWhileCollection` or
   /// `LazyPrefixWhileBidirectionalCollection` instance.
-  @_fixed_layout // FIXME(sil-serialize-all)
+  @_fixed_layout // lazy-performance
   public struct Index {
     /// The position corresponding to `self` in the underlying collection.
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // lazy-performance
     internal let _value: _IndexRepresentation
 
     /// Creates a new index wrapper for `i`.
-    @inlinable // FIXME(sil-serialize-all)
+    @inlinable // lazy-performance
     internal init(_ i: Base.Index) {
       self._value = .index(i)
     }
@@ -162,7 +162,7 @@
     /// Creates a new index that can represent the `endIndex` of a
     /// `LazyPrefixWhileCollection<Base>`. This is not the same as a wrapper
     /// around `Base.endIndex`.
-    @inlinable // FIXME(sil-serialize-all)
+    @inlinable // lazy-performance
     internal init(endOf: Base) {
       self._value = .pastEnd
     }
@@ -170,7 +170,7 @@
 }
 
 extension LazyPrefixWhileCollection.Index: Comparable {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public static func == (
     lhs: LazyPrefixWhileCollection<Base>.Index, 
     rhs: LazyPrefixWhileCollection<Base>.Index
@@ -185,7 +185,7 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public static func < (
     lhs: LazyPrefixWhileCollection<Base>.Index, 
     rhs: LazyPrefixWhileCollection<Base>.Index
@@ -219,12 +219,12 @@
 }
 
 extension LazyPrefixWhileCollection: Collection {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public var startIndex: Index {
     return Index(_base.startIndex)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public var endIndex: Index {
     // If the first element of `_base` satisfies the predicate, there is at
     // least one element in the lazy collection: Use the explicit `.pastEnd` index.
@@ -237,7 +237,7 @@
     return startIndex
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func index(after i: Index) -> Index {
     _precondition(i != endIndex, "Can't advance past endIndex")
     guard case .index(let i) = i._value else {
@@ -250,7 +250,7 @@
     return Index(nextIndex)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public subscript(position: Index) -> Element {
     switch position._value {
     case .index(let i):
@@ -263,7 +263,7 @@
 
 extension LazyPrefixWhileCollection: BidirectionalCollection
 where Base: BidirectionalCollection {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func index(before i: Index) -> Index {
     switch i._value {
     case .index(let i):
@@ -303,7 +303,7 @@
   ///   as its argument and returns `true` if the element should be included
   ///   or `false` otherwise. Once `predicate` returns `false` it will not be
   ///   called again.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // lazy-performance
   public func prefix(
     while predicate: @escaping (Element) -> Bool
   ) -> LazyPrefixWhileCollection<Elements> {
diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift
index 935b680..0643af6 100644
--- a/stdlib/public/core/Range.swift
+++ b/stdlib/public/core/Range.swift
@@ -762,7 +762,7 @@
 ///     let word2 = "grisly"
 ///     let changes = countLetterChanges(word1[...], word2[...])
 ///     // changes == 2
-@_frozen // FIXME(sil-serialize-all)
+@_frozen // namespace
 public enum UnboundedRange_ {
   // FIXME: replace this with a computed var named `...` when the language makes
   // that possible.
@@ -771,7 +771,6 @@
   ///
   /// The unbounded range operator (`...`) is valid only within a collection's
   /// subscript.
-  @inlinable // FIXME(sil-serialize-all)
   public static postfix func ... (_: UnboundedRange_) -> () {
     fatalError("uncallable")
   }
@@ -844,7 +843,7 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable
   public subscript(x: UnboundedRange) -> SubSequence {
     get {
       return self[startIndex...]
diff --git a/stdlib/public/core/SequenceWrapper.swift b/stdlib/public/core/SequenceWrapper.swift
index cb9bf68..85833b2 100644
--- a/stdlib/public/core/SequenceWrapper.swift
+++ b/stdlib/public/core/SequenceWrapper.swift
@@ -27,12 +27,12 @@
 }
 
 extension _SequenceWrapper  {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public var underestimatedCount: Int {
     return _base.underestimatedCount
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func _preprocessingPass<R>(
     _ preprocess: () throws -> R
   ) rethrows -> R? {
@@ -41,12 +41,12 @@
 }
 
 extension _SequenceWrapper where Iterator == Base.Iterator {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func makeIterator() -> Iterator {
     return self._base.makeIterator()
   }
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   @discardableResult
   public func _copyContents(
     initializing buf: UnsafeMutableBufferPointer<Element>
@@ -56,33 +56,33 @@
 }
 
 extension _SequenceWrapper {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func map<T>(
     _ transform: (Element) throws -> T
 ) rethrows -> [T] {
     return try _base.map(transform)
   }
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func filter(
     _ isIncluded: (Element) throws -> Bool
   ) rethrows -> [Element] {
     return try _base.filter(isIncluded)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func forEach(_ body: (Element) throws -> Void) rethrows {
     return try _base.forEach(body)
   }
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func _customContainsEquatableElement(
     _ element: Element
   ) -> Bool? { 
     return _base._customContainsEquatableElement(element)
   }
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func _copyToContiguousArray()
     -> ContiguousArray<Element> {
     return _base._copyToContiguousArray()
@@ -90,38 +90,38 @@
 }
 
 extension _SequenceWrapper where SubSequence == Base.SubSequence {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func dropFirst(_ n: Int) -> SubSequence {
     return _base.dropFirst(n)
   }
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func dropLast(_ n: Int) -> SubSequence {
     return _base.dropLast(n)
   }
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func prefix(_ maxLength: Int) -> SubSequence {
     return _base.prefix(maxLength)
   }
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func suffix(_ maxLength: Int) -> SubSequence {
     return _base.suffix(maxLength)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func drop(
     while predicate: (Element) throws -> Bool
   ) rethrows -> SubSequence {
     return try _base.drop(while: predicate)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func prefix(
     while predicate: (Element) throws -> Bool
   ) rethrows -> SubSequence {
     return try _base.prefix(while: predicate)
   }
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func split(
     maxSplits: Int, omittingEmptySubsequences: Bool,
     whereSeparator isSeparator: (Element) throws -> Bool
diff --git a/stdlib/public/core/Slice.swift b/stdlib/public/core/Slice.swift
index 139a52b..01cf1d6 100644
--- a/stdlib/public/core/Slice.swift
+++ b/stdlib/public/core/Slice.swift
@@ -79,12 +79,12 @@
 ///   collection type, don't use `Slice` as its subsequence type. Instead,
 ///   define your own subsequence type that takes your index invalidation
 ///   requirements into account.
-@_fixed_layout // FIXME(sil-serialize-all)
+@_fixed_layout // generic-performance
 public struct Slice<Base: Collection> {
   public var _startIndex: Base.Index
   public var _endIndex: Base.Index
 
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // generic-performance
   internal var _base: Base
 
   /// Creates a view into the given collection that allows access to elements
@@ -106,7 +106,7 @@
   /// - Parameters:
   ///   - base: The collection to create a view into.
   ///   - bounds: The range of indices to allow access to in the new slice.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public init(base: Base, bounds: Range<Base.Index>) {
     self._base = base
     self._startIndex = bounds.lowerBound
@@ -131,7 +131,7 @@
   ///     // Prints "10"
   ///     print(singleDigits == singleNonZeroDigits.base)
   ///     // Prints "true"
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public var base: Base {
     return _base
   }
@@ -144,17 +144,17 @@
   public typealias SubSequence = Slice<Base>
   public typealias Iterator = IndexingIterator<Slice<Base>>
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public var startIndex: Index {
     return _startIndex
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public var endIndex: Index {
     return _endIndex
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public subscript(index: Index) -> Base.Element {
     get {
       _failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
@@ -162,7 +162,7 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public subscript(bounds: Range<Index>) -> Slice<Base> {
     get {
       _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
@@ -174,25 +174,25 @@
     return _base.indices[_startIndex..<_endIndex]
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func index(after i: Index) -> Index {
     // FIXME: swift-3-indexing-model: range check.
     return _base.index(after: i)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func formIndex(after i: inout Index) {
     // FIXME: swift-3-indexing-model: range check.
     _base.formIndex(after: &i)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func index(_ i: Index, offsetBy n: Int) -> Index {
     // FIXME: swift-3-indexing-model: range check.
     return _base.index(i, offsetBy: n)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func index(
     _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
@@ -200,31 +200,31 @@
     return _base.index(i, offsetBy: n, limitedBy: limit)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func distance(from start: Index, to end: Index) -> Int {
     // FIXME: swift-3-indexing-model: range check.
     return _base.distance(from: start, to: end)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
     _base._failEarlyRangeCheck(index, bounds: bounds)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
     _base._failEarlyRangeCheck(range, bounds: bounds)
   }
 }
 
 extension Slice: BidirectionalCollection where Base: BidirectionalCollection {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func index(before i: Index) -> Index {
     // FIXME: swift-3-indexing-model: range check.
     return _base.index(before: i)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func formIndex(before i: inout Index) {
     // FIXME: swift-3-indexing-model: range check.
     _base.formIndex(before: &i)
@@ -233,7 +233,7 @@
 
 
 extension Slice: MutableCollection where Base: MutableCollection {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public subscript(index: Index) -> Base.Element {
     get {
       _failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
@@ -248,7 +248,7 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public subscript(bounds: Range<Index>) -> Slice<Base> {
     get {
       _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
@@ -265,28 +265,28 @@
 
 extension Slice: RangeReplaceableCollection
   where Base: RangeReplaceableCollection {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public init() {
     self._base = Base()
     self._startIndex = _base.startIndex
     self._endIndex = _base.endIndex
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public init(repeating repeatedValue: Base.Element, count: Int) {
     self._base = Base(repeating: repeatedValue, count: count)
     self._startIndex = _base.startIndex
     self._endIndex = _base.endIndex
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public init<S>(_ elements: S) where S: Sequence, S.Element == Base.Element {
     self._base = Base(elements)
     self._startIndex = _base.startIndex
     self._endIndex = _base.endIndex
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func replaceSubrange<C>(
     _ subRange: Range<Index>, with newElements: C
   ) where C : Collection, C.Element == Base.Element {
@@ -303,7 +303,7 @@
     _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func insert(_ newElement: Base.Element, at i: Index) {
     // FIXME: swift-3-indexing-model: range check.
     let sliceOffset = _base.distance(from: _base.startIndex, to: _startIndex)
@@ -313,7 +313,7 @@
     _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func insert<S>(contentsOf newElements: S, at i: Index)
   where S: Collection, S.Element == Base.Element {
 
@@ -325,7 +325,7 @@
     _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func remove(at i: Index) -> Base.Element {
     // FIXME: swift-3-indexing-model: range check.
     let sliceOffset = _base.distance(from: _base.startIndex, to: _startIndex)
@@ -336,7 +336,7 @@
     return result
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func removeSubrange(_ bounds: Range<Index>) {
     // FIXME: swift-3-indexing-model: range check.
     let sliceOffset = _base.distance(from: _base.startIndex, to: _startIndex)
@@ -351,7 +351,7 @@
 extension Slice
   where Base: RangeReplaceableCollection, Base: BidirectionalCollection {
   
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func replaceSubrange<C>(
     _ subRange: Range<Index>, with newElements: C
   ) where C : Collection, C.Element == Base.Element {
@@ -378,7 +378,7 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func insert(_ newElement: Base.Element, at i: Index) {
     // FIXME: swift-3-indexing-model: range check.
     if i == _base.startIndex {
@@ -398,7 +398,7 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func insert<S>(contentsOf newElements: S, at i: Index)
   where S : Collection, S.Element == Base.Element {
     // FIXME: swift-3-indexing-model: range check.
@@ -421,7 +421,7 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func remove(at i: Index) -> Base.Element {
     // FIXME: swift-3-indexing-model: range check.
     if i == _base.startIndex {
@@ -443,7 +443,7 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func removeSubrange(_ bounds: Range<Index>) {
     // FIXME: swift-3-indexing-model: range check.
     if bounds.lowerBound == _base.startIndex {
diff --git a/stdlib/public/core/StaticString.swift b/stdlib/public/core/StaticString.swift
index b7d17c2..16c4402 100644
--- a/stdlib/public/core/StaticString.swift
+++ b/stdlib/public/core/StaticString.swift
@@ -130,7 +130,7 @@
   ///   `withUTF8Buffer(invoke:)` method. The pointer argument is valid only
   ///   for the duration of the method's execution.
   /// - Returns: The return value, if any, of the `body` closure.
-  @inlinable // FIXME(sil-serialize-all)
+  @_transparent
   public func withUTF8Buffer<R>(
     _ body: (UnsafeBufferPointer<UInt8>) -> R) -> R {
     if hasPointerRepresentation {
@@ -187,7 +187,6 @@
       : (0x1 as UInt8)._value
   }
 
-  @inlinable // FIXME(sil-serialize-all)
   @_effects(readonly)
   @_transparent
   public init(_builtinUnicodeScalarLiteral value: Builtin.Int32) {
@@ -198,14 +197,12 @@
   ///
   /// Do not call this initializer directly. It may be used by the compiler
   /// when you initialize a static string with a Unicode scalar.
-  @inlinable // FIXME(sil-serialize-all)
   @_effects(readonly)
   @_transparent
   public init(unicodeScalarLiteral value: StaticString) {
     self = value
   }
 
-  @inlinable // FIXME(sil-serialize-all)
   @_effects(readonly)
   @_transparent
   public init(
@@ -225,14 +222,12 @@
   ///
   /// Do not call this initializer directly. It may be used by the compiler
   /// when you initialize a static string using an extended grapheme cluster.
-  @inlinable // FIXME(sil-serialize-all)
   @_effects(readonly)
   @_transparent
   public init(extendedGraphemeClusterLiteral value: StaticString) {
     self = value
   }
 
-  @inlinable // FIXME(sil-serialize-all)
   @_effects(readonly)
   @_transparent
   public init(
@@ -250,7 +245,6 @@
   ///
   /// Do not call this initializer directly. It may be used by the compiler
   /// when you initialize a static string using a string literal.
-  @inlinable // FIXME(sil-serialize-all)
   @_effects(readonly)
   @_transparent
   public init(stringLiteral value: StaticString) {
@@ -258,7 +252,6 @@
   }
 
   /// A string representation of the static string.
-  @inlinable // FIXME(sil-serialize-all)
   public var description: String {
     return withUTF8Buffer { (buffer) in
       if isASCII {
diff --git a/stdlib/public/core/StringProtocol.swift b/stdlib/public/core/StringProtocol.swift
index 8842115..09ef393 100644
--- a/stdlib/public/core/StringProtocol.swift
+++ b/stdlib/public/core/StringProtocol.swift
@@ -29,6 +29,8 @@
 
   associatedtype UnicodeScalarView : BidirectionalCollection
   where UnicodeScalarView.Element == Unicode.Scalar
+  
+  associatedtype SubSequence = Substring
 
   var utf8: UTF8View { get }
   var utf16: UTF16View { get }
diff --git a/stdlib/public/core/UnfoldSequence.swift b/stdlib/public/core/UnfoldSequence.swift
index 9d9a8fe..bc4e82c 100644
--- a/stdlib/public/core/UnfoldSequence.swift
+++ b/stdlib/public/core/UnfoldSequence.swift
@@ -38,7 +38,7 @@
 ///   returns the next element.
 /// - Returns: A sequence that starts with `first` and continues with every
 ///   value returned by passing the previous element to `next`.
-@inlinable // FIXME(sil-serialize-all)
+@inlinable // generic-performance
 public func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldFirstSequence<T> {
   // The trivial implementation where the state is the next value to return
   // has the downside of being unnecessarily eager (it evaluates `next` one
@@ -83,7 +83,7 @@
 /// - Parameter next: A closure that accepts an `inout` state and returns the
 ///   next element of the sequence.
 /// - Returns: A sequence that yields each successive value from `next`.
-@inlinable // FIXME(sil-serialize-all)
+@inlinable // generic-performance
 public func sequence<T, State>(state: State, next: @escaping (inout State) -> T?)
   -> UnfoldSequence<T, State> {
   return UnfoldSequence(_state: state, _next: next)
@@ -100,9 +100,9 @@
 ///
 /// Instances of `UnfoldSequence` are created with the functions
 /// `sequence(first:next:)` and `sequence(state:next:)`.
-@_fixed_layout // FIXME(sil-serialize-all)
+@_fixed_layout // generic-performance
 public struct UnfoldSequence<Element, State> : Sequence, IteratorProtocol {
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func next() -> Element? {
     guard !_done else { return nil }
     if let elt = _next(&_state) {
@@ -113,16 +113,16 @@
     }
   }
 
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   internal init(_state: State, _next: @escaping (inout State) -> Element?) {
     self._state = _state
     self._next = _next
   }
 
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // generic-performance
   internal var _state: State
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // generic-performance
   internal let _next: (inout State) -> Element?
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // generic-performance
   internal var _done = false
 }
diff --git a/stdlib/public/core/Unmanaged.swift b/stdlib/public/core/Unmanaged.swift
index 08e0b0e..24d97a5 100644
--- a/stdlib/public/core/Unmanaged.swift
+++ b/stdlib/public/core/Unmanaged.swift
@@ -89,7 +89,7 @@
   /// and you know that you're not responsible for releasing the result.
   ///
   /// - Returns: The object referenced by this `Unmanaged` instance.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // unsafe-performance
   public func takeUnretainedValue() -> Instance {
     return _value
   }
@@ -101,7 +101,7 @@
   /// and you know that you're responsible for releasing the result.
   ///
   /// - Returns: The object referenced by this `Unmanaged` instance.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // unsafe-performance
   public func takeRetainedValue() -> Instance {
     let result = _value
     release()
@@ -200,7 +200,7 @@
   ///      }
   ///    }
   ///  }
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // unsafe-performance
   public func _withUnsafeGuaranteedRef<Result>(
     _ body: (Instance) throws -> Result
   ) rethrows -> Result {
diff --git a/stdlib/public/core/Zip.swift b/stdlib/public/core/Zip.swift
index 5bb3dc5..b97fe84 100644
--- a/stdlib/public/core/Zip.swift
+++ b/stdlib/public/core/Zip.swift
@@ -41,7 +41,7 @@
 ///   - sequence2: The second sequence or collection to zip.
 /// - Returns: A sequence of tuple pairs, where the elements of each pair are
 ///   corresponding elements of `sequence1` and `sequence2`.
-@inlinable // FIXME(sil-serialize-all)
+@inlinable // generic-performance
 public func zip<Sequence1, Sequence2>(
   _ sequence1: Sequence1, _ sequence2: Sequence2
 ) -> Zip2Sequence<Sequence1, Sequence2> {
@@ -67,16 +67,16 @@
 ///     // Prints "two: 2
 ///     // Prints "three: 3"
 ///     // Prints "four: 4"
-@_fixed_layout // FIXME(sil-serialize-all)
+@_fixed_layout // generic-performance
 public struct Zip2Sequence<Sequence1 : Sequence, Sequence2 : Sequence> {
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // generic-performance
   internal let _sequence1: Sequence1
-  @usableFromInline // FIXME(sil-serialize-all)
+  @usableFromInline // generic-performance
   internal let _sequence2: Sequence2
 
   /// Creates an instance that makes pairs of elements from `sequence1` and
   /// `sequence2`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public // @testable
   init(_sequence1 sequence1: Sequence1, _sequence2 sequence2: Sequence2) {
     (_sequence1, _sequence2) = (sequence1, sequence2)
@@ -85,17 +85,17 @@
 
 extension Zip2Sequence {
   /// An iterator for `Zip2Sequence`.
-  @_fixed_layout // FIXME(sil-serialize-all)
+  @_fixed_layout // generic-performance
   public struct Iterator {
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // generic-performance
     internal var _baseStream1: Sequence1.Iterator
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // generic-performance
     internal var _baseStream2: Sequence2.Iterator
-    @usableFromInline // FIXME(sil-serialize-all)
+    @usableFromInline // generic-performance
     internal var _reachedEnd: Bool = false
 
     /// Creates an instance around a pair of underlying iterators.
-    @inlinable // FIXME(sil-serialize-all)
+    @inlinable // generic-performance
     internal init(
     _ iterator1: Sequence1.Iterator, 
     _ iterator2: Sequence2.Iterator
@@ -113,7 +113,7 @@
   /// exists.
   ///
   /// Once `nil` has been returned, all subsequent calls return `nil`.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public mutating func next() -> Element? {
     // The next() function needs to track if it has reached the end.  If we
     // didn't, and the first sequence is longer than the second, then when we
@@ -139,7 +139,7 @@
   public typealias Element = (Sequence1.Element, Sequence2.Element)
 
   /// Returns an iterator over the elements of this sequence.
-  @inlinable // FIXME(sil-serialize-all)
+  @inlinable // generic-performance
   public func makeIterator() -> Iterator {
     return Iterator(
       _sequence1.makeIterator(),
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 993c5d7..ecdffda 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -3620,11 +3620,13 @@
     return false;
   }
 
-  // If we don't have resilient witnesses, the template must provide
-  // everything.
-  assert (genericTable->WitnessTableSizeInWords ==
+  // If we don't have the exact number of witnesses expected, we require
+  // instantiation.
+  if (genericTable->WitnessTableSizeInWords !=
           (genericTable->Protocol->NumRequirements +
-           WitnessTableFirstRequirementOffset));
+           WitnessTableFirstRequirementOffset)) {
+    return false;
+  }
 
   // If we have an instantiation function or private data, we require
   // instantiation.
@@ -3643,39 +3645,46 @@
   auto protocol = genericTable->Protocol.get();
 
   auto requirements = protocol->getRequirements();
-  auto witnesses = genericTable->ResilientWitnesses->getWitnesses();
+  llvm::ArrayRef<TargetResilientWitness<InProcess>> witnesses;
+  if (auto resilientWitnesses = genericTable->ResilientWitnesses.get())
+    witnesses = resilientWitnesses->getWitnesses();
 
+  // Loop over the provided witnesses, filling in appropriate entry.
+  for (const auto &witness : witnesses) {
+    // Retrieve the requirement descriptor.
+    auto reqDescriptor = witness.Requirement.get();
+
+    // The requirement descriptor may be NULL, in which case this is a
+    // requirement introduced in a later version of the protocol./
+    if (!reqDescriptor) continue;
+
+    // If the requirement descriptor doesn't land within the bounds of the
+    // requirements, abort.
+    if (reqDescriptor < requirements.begin() ||
+        reqDescriptor >= requirements.end()) {
+      fatalError(0, "generic witness table at %p contains out-of-bounds "
+                 "requirement descriptor %p\n",
+                 genericTable, reqDescriptor);
+    }
+
+    unsigned witnessIndex = (reqDescriptor - requirements.data()) +
+      WitnessTableFirstRequirementOffset;
+
+    table[witnessIndex] = witness.Witness.get();
+  }
+
+  // Loop over the requirements, filling in default implementations where
+  // needed.
   for (size_t i = 0, e = protocol->NumRequirements; i < e; ++i) {
-    auto &reqt = requirements[i];
-
-    // Only certain requirements are filled in from the resilient witness table.
-    switch (reqt.Flags.getKind()) {
-    case ProtocolRequirementFlags::Kind::Method:
-    case ProtocolRequirementFlags::Kind::Init:
-    case ProtocolRequirementFlags::Kind::Getter:
-    case ProtocolRequirementFlags::Kind::Setter:
-    case ProtocolRequirementFlags::Kind::ReadCoroutine:
-    case ProtocolRequirementFlags::Kind::ModifyCoroutine:
-    case ProtocolRequirementFlags::Kind::AssociatedTypeAccessFunction:
-      break;
-    case ProtocolRequirementFlags::Kind::BaseProtocol:
-    case ProtocolRequirementFlags::Kind::AssociatedConformanceAccessFunction:
-      continue;
-    }
-
-    void *impl = reqt.DefaultImplementation.get();
-
-    // Find the witness if there is one, otherwise we use the default.
-    for (auto &witness : witnesses) {
-      if (witness.Requirement.get() == &reqt) {
-        impl = witness.Witness.get();
-        break;
-      }
-    }
-
-    assert(impl != nullptr && "no implementation for witness");
-
     unsigned witnessIndex = WitnessTableFirstRequirementOffset + i;
+
+    // If we already have a witness, there's nothing to do.
+    if (table[witnessIndex])
+      continue;
+
+    // Otherwise, fill in a default implementation.
+    auto &reqt = requirements[i];
+    void *impl = reqt.DefaultImplementation.get();
     table[witnessIndex] = impl;
   }
 }
@@ -3716,8 +3725,7 @@
   }
 
   // Fill in any default requirements.
-  if (genericTable->ResilientWitnesses)
-    initializeResilientWitnessTable(genericTable, table);
+  initializeResilientWitnessTable(genericTable, table);
 
   auto castTable = reinterpret_cast<WitnessTable*>(table);
 
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index 35fe8a3..57244a9 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -332,3 +332,4 @@
 $S1T19protocol_resilience17ResilientProtocolPTl --> associated type descriptor for T
 $S18resilient_protocol21ResilientBaseProtocolTL --> protocol requirements base descriptor for resilient_protocol.ResilientBaseProtocol
 $S1t1PP10AssocType2_AA1QTn --> associated conformance descriptor for t.P.AssocType2: t.Q
+$S1t1PP10AssocType2_AA1QTN --> default associated conformance accessor for t.P.AssocType2: t.Q
diff --git a/test/IRGen/abi_v7k.swift b/test/IRGen/abi_v7k.swift
index 2bb0163..d4b1af0 100644
--- a/test/IRGen/abi_v7k.swift
+++ b/test/IRGen/abi_v7k.swift
@@ -270,10 +270,10 @@
 // double in d0, i32 in r0, return in d0,...,d3
 // V7K: vmov [[ID:s[0-9]+]], r0
 // V7K: vcvt.f64.s32 [[ID2:d[0-9]+]], [[ID]]
-// V7K: vstr d0, [sp]
+// V7K: vstr d0, [sp, #8]
 // V7K: vmov.f64 d0, [[ID2]]
 // V7K: bl
-// V7K: vldr [[ID3:d[0-9]+]], [sp]
+// V7K: vldr [[ID3:d[0-9]+]], [sp, #8]
 // V7K: vmov.f64 d2, [[ID3]]
 func testRet2(w : Double, i : Int) -> MyRect {
   var r = MyRect(x : Double(i), y : 2.0, w : 3.0, h : 4.0)
diff --git a/test/IRGen/protocol_resilience_descriptors.swift b/test/IRGen/protocol_resilience_descriptors.swift
index 7dd512e..5f6c8ca 100644
--- a/test/IRGen/protocol_resilience_descriptors.swift
+++ b/test/IRGen/protocol_resilience_descriptors.swift
@@ -14,6 +14,7 @@
 
 // Protocol descriptor
 // CHECK-DEFINITION-LABEL: @"$S18resilient_protocol29ProtocolWithAssocTypeDefaultsMp" ={{( protected)?}} constant
+// CHECK-DEFINITION-SAME: @"$S18resilient_protocol29ProtocolWithAssocTypeDefaultsP2T2_AA014OtherResilientC0TN"
 // CHECK-DEFINITION-SAME: $S2T118resilient_protocol29ProtocolWithAssocTypeDefaultsPTM
 // CHECK-DEFINITION-SAME: $S2T218resilient_protocol29ProtocolWithAssocTypeDefaultsPTM
 
@@ -25,6 +26,9 @@
 // CHECK-DEFINITION: @"$S1T18resilient_protocol24ProtocolWithRequirementsPTl" ={{( dllexport)?}}{{( protected)?}} alias
 // CHECK-DEFINITION: @"$S18resilient_protocol29ProtocolWithAssocTypeDefaultsP2T2_AA014OtherResilientC0Tn" ={{( dllexport)?}}{{( protected)?}} alias
 
+// Default associated conformance witnesses
+// CHECK-DEFINITION-LABEL: define internal swiftcc i8** @"$S18resilient_protocol29ProtocolWithAssocTypeDefaultsP2T2_AA014OtherResilientC0TN"
+
 // Default associated type witnesses
 // CHECK-DEFINITION-LABEL: define internal swiftcc %swift.metadata_response @"$S2T118resilient_protocol29ProtocolWithAssocTypeDefaultsPTM"
 
@@ -32,6 +36,8 @@
 // CHECK-DEFINITION: getelementptr inbounds i8*, i8** [[WTABLE:%.*]], i32 2
 // CHECK-DEFINITION: call{{.*}}S18resilient_protocol7WrapperVMa
 
+// CHECK-DEFINITION-LABEL: define internal swiftcc %swift.metadata_response @"$S9AssocType18resilient_protocol20ResilientSelfDefaultPTM
+
 import resilient_protocol
 
 // ----------------------------------------------------------------------------
@@ -51,6 +57,12 @@
 public struct ConditionallyConforms<Element> { }
 public struct Y { }
 
+// CHECK-USAGE: @"$S31protocol_resilience_descriptors29ConformsWithAssocRequirementsV010resilient_A008ProtocoleF12TypeDefaultsAAWr" = internal
+// CHECK-USAGE-SAME: $S18resilient_protocol29ProtocolWithAssocTypeDefaultsP2T2_AA014OtherResilientC0Tn
+// CHECK-USAGE-SAME: $S31protocol_resilience_descriptors29ConformsWithAssocRequirementsV010resilient_A008ProtocoleF12TypeDefaultsAA2T2_AD014OtherResilientI0PWT
+public struct ConformsWithAssocRequirements : ProtocolWithAssocTypeDefaults {
+}
+
 // CHECK-USAGE: @"$Sx1T_MXA" =
 // CHECK-USAGE-SAME: i32 0
 // CHECK-USAGE-SAME: @"{{got.|__imp_}}$S18resilient_protocol24ProtocolWithRequirementsMp"
diff --git a/test/Inputs/resilient_protocol.swift b/test/Inputs/resilient_protocol.swift
index e6dfcb8..9a93674 100644
--- a/test/Inputs/resilient_protocol.swift
+++ b/test/Inputs/resilient_protocol.swift
@@ -34,3 +34,7 @@
   associatedtype T1 = Self
   associatedtype T2: OtherResilientProtocol = Wrapper<T1>
 }
+
+public protocol ResilientSelfDefault : ResilientBaseProtocol {
+  associatedtype AssocType: ResilientBaseProtocol = Self
+}
diff --git a/test/ModuleInterface/final.swift b/test/ModuleInterface/final.swift
new file mode 100644
index 0000000..a3ff6b1
--- /dev/null
+++ b/test/ModuleInterface/final.swift
@@ -0,0 +1,41 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule -emit-interface-path %t/Test.swiftinterface -module-name Test %s
+// RUN: %FileCheck %s < %t/Test.swiftinterface
+// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -disable-objc-attr-requires-foundation-module -emit-interface-path - -module-name Test | %FileCheck %s
+
+// CHECK: final public class FinalClass {
+public final class FinalClass {
+  // CHECK: @inlinable final public class var a: [[INT:(Swift.)?Int]] {
+  // CHECK-NEXT: return 3
+  // CHECK-NEXT: }
+  @inlinable
+  public final class var a: Int {
+    return 3
+  }
+
+  // CHECK: final public class var b: [[INT]] {
+  // CHECK-NEXT:   {{^}} @inlinable get {
+  // CHECK-NEXT:     return 3
+  // CHECK-NEXT:   }
+  // CHECK-NEXT:   set[[NEWVALUE:(\(newValue\))?]]{{$}}
+  // CHECK-NEXT: }
+  public final class var b: Int {
+    @inlinable get {
+      return 3
+    }
+    set {
+      print("x")
+    }
+  }
+
+  // CHECK: public static var c: [[INT]] {
+  // CHECK-NEXT: {{^}} get
+  // CHECK-NEXT:   @inlinable set[[NEWVALUE]] {}
+  // CHECK-NEXT: }
+  public static var c: Int {
+    get {
+      return 0
+    }
+    @inlinable set {}
+  }
+}
diff --git a/test/SIL/Parser/default_witness_tables.sil b/test/SIL/Parser/default_witness_tables.sil
index bb1b8e9..8153e21 100644
--- a/test/SIL/Parser/default_witness_tables.sil
+++ b/test/SIL/Parser/default_witness_tables.sil
@@ -48,7 +48,7 @@
 
 
 // CHECK-LABEL: sil_default_witness_table ResilientProtocol {
-// CHECK: no_default
+// CHECK: associated_type_protocol (T: Proto): Wrapper<Self>: specialize <Self> (<T> Wrapper<T>: Proto module witness_tables)
 // CHECK: associated_type T: Wrapper<Self>
 // CHECK: no_default
 // CHECK: no_default
@@ -58,7 +58,7 @@
 // CHECK: }
 
 sil_default_witness_table ResilientProtocol {
-  no_default
+  associated_type_protocol (T: Proto): Wrapper<Self>: specialize <Self> (<T> Wrapper<T>: Proto module witness_tables)
   associated_type T: Wrapper<Self>
   no_default
   no_default
diff --git a/test/SILGen/protocol_resilience.swift b/test/SILGen/protocol_resilience.swift
index e930bfb..e75df7e 100644
--- a/test/SILGen/protocol_resilience.swift
+++ b/test/SILGen/protocol_resilience.swift
@@ -251,6 +251,13 @@
   inoutFunc(&OtherConformingType.staticPropertyInExtension)
 }
 
+// Protocol is public -- needs resilient witness table
+public struct ConformsToP: P { }
+
+public protocol ResilientAssocTypes {
+  associatedtype AssocType: P = ConformsToP
+}
+
 // CHECK-LABEL: sil_default_witness_table P {
 // CHECK-NEXT: }
 
@@ -312,3 +319,8 @@
 // CHECK-NEXT:   method #ReabstractSelfRefined.callback!setter.1: {{.*}} : @$S19protocol_resilience21ReabstractSelfRefinedP8callbackyxxcvs
 // CHECK-NEXT:   method #ReabstractSelfRefined.callback!modify.1: {{.*}} : @$S19protocol_resilience21ReabstractSelfRefinedP8callbackyxxcvM
 // CHECK-NEXT: }
+
+// CHECK-LABEL: sil_default_witness_table ResilientAssocTypes {
+// CHECK-NEXT:   associated_type_protocol (AssocType: P): ConformsToP: P module protocol_resilience
+// CHECK-NEXT:   associated_type AssocType: ConformsToP
+// CHECK-NEXT: }
diff --git a/test/api-digester/Inputs/cake.swift b/test/api-digester/Inputs/cake.swift
index 34e9637..5ae49f9 100644
--- a/test/api-digester/Inputs/cake.swift
+++ b/test/api-digester/Inputs/cake.swift
@@ -40,4 +40,11 @@
 
 public extension Int {
   public func foo() {}
-}
\ No newline at end of file
+}
+
+@_fixed_layout
+public struct fixedLayoutStruct {
+  public var a = 1
+  private var b = 2
+  var c = 3
+}
diff --git a/test/api-digester/Inputs/cake1.swift b/test/api-digester/Inputs/cake1.swift
index 7ec7e43..f0df08f 100644
--- a/test/api-digester/Inputs/cake1.swift
+++ b/test/api-digester/Inputs/cake1.swift
@@ -47,3 +47,21 @@
 public extension P1 where Self: P2 {
   func P1Constraint() {}
 }
+
+@_fixed_layout
+public struct fixedLayoutStruct {
+  public var b = 2
+  public func foo() {}
+  public var a = 1
+}
+
+@_frozen
+public enum FrozenKind {
+  case Unchanged
+  case Fixed
+  case Rigid
+}
+
+public class C7 {
+  public func foo(_ a: Int = 1, _ b: Int = 2) {}
+}
\ No newline at end of file
diff --git a/test/api-digester/Inputs/cake2.swift b/test/api-digester/Inputs/cake2.swift
index 651ac79..921982f 100644
--- a/test/api-digester/Inputs/cake2.swift
+++ b/test/api-digester/Inputs/cake2.swift
@@ -47,3 +47,26 @@
 public extension P1 {
   func P1Constraint() {}
 }
+
+@_fixed_layout
+public struct fixedLayoutStruct {
+  public var a = 1
+  public func OKChange() {}
+  private static let constant = 0
+  public var b = 2
+  public func foo() {}
+  private var c = 3
+  private lazy var lazy_d = 4
+}
+
+@_frozen
+public enum FrozenKind {
+  case Unchanged
+  case Rigid
+  case Fixed
+  case AddedCase
+}
+
+public class C7 {
+  public func foo(_ a: Int, _ b: Int) {}
+}
\ No newline at end of file
diff --git a/test/api-digester/Outputs/Cake-abi.txt b/test/api-digester/Outputs/Cake-abi.txt
index 093eff1..fb58af1 100644
--- a/test/api-digester/Outputs/Cake-abi.txt
+++ b/test/api-digester/Outputs/Cake-abi.txt
@@ -6,6 +6,7 @@
 
 /* Removed Decls */
 cake1: Constructor Somestruct2.init(_:) has been removed
+cake1: Constructor fixedLayoutStruct.init(b:a:) has been removed
 cake1: Func C4.foo() has been removed
 
 /* Moved Decls */
@@ -17,6 +18,8 @@
 /* Type Changes */
 cake1: Constructor S1.init(_:) has parameter 0 type change from Int to Double
 cake1: Func C1.foo2(_:) has parameter 0 type change from Int to () -> ()
+cake1: Func C7.foo(_:_:) has removed default argument from parameter 0
+cake1: Func C7.foo(_:_:) has removed default argument from parameter 1
 cake1: Func Somestruct2.foo1(_:) has parameter 0 type change from C3 to C1
 
 /* Decl Attribute changes */
@@ -29,3 +32,12 @@
 cake1: Struct C6 is now with @_fixed_layout
 cake1: Var C1.CIIns1 changes from weak to strong
 cake1: Var C1.CIIns2 changes from strong to weak
+
+/* Fixed-layout Type changes */
+cake1: EnumElement FrozenKind.Fixed in a non-resilient type changes position from 1 to 2
+cake1: EnumElement FrozenKind.Rigid in a non-resilient type changes position from 2 to 1
+cake1: Var fixedLayoutStruct.a in a non-resilient type changes position from 1 to 0
+cake1: Var fixedLayoutStruct.b in a non-resilient type changes position from 0 to 1
+cake2: EnumElement FrozenKind.AddedCase is added to a non-resilient type
+cake2: Var fixedLayoutStruct.c is added to a non-resilient type
+cake2: Var fixedLayoutStruct.lazy_d.storage is added to a non-resilient type
\ No newline at end of file
diff --git a/test/api-digester/Outputs/Cake.txt b/test/api-digester/Outputs/Cake.txt
index e46efe9..0727459 100644
--- a/test/api-digester/Outputs/Cake.txt
+++ b/test/api-digester/Outputs/Cake.txt
@@ -6,6 +6,7 @@
 
 /* Removed Decls */
 cake1: Constructor Somestruct2.init(_:) has been removed
+cake1: Constructor fixedLayoutStruct.init(b:a:) has been removed
 cake1: Func C4.foo() has been removed
 
 /* Moved Decls */
@@ -17,6 +18,8 @@
 /* Type Changes */
 cake1: Constructor S1.init(_:) has parameter 0 type change from Int to Double
 cake1: Func C1.foo2(_:) has parameter 0 type change from Int to () -> ()
+cake1: Func C7.foo(_:_:) has removed default argument from parameter 0
+cake1: Func C7.foo(_:_:) has removed default argument from parameter 1
 
 /* Decl Attribute changes */
 cake1: Func C1.foo1() is now not static
diff --git a/test/api-digester/Outputs/cake-abi.json b/test/api-digester/Outputs/cake-abi.json
index 3a068eb..b980795 100644
--- a/test/api-digester/Outputs/cake-abi.json
+++ b/test/api-digester/Outputs/cake-abi.json
@@ -95,6 +95,7 @@
           "usr": "s:4cake2S1VACycfc",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -125,6 +126,7 @@
           "location": "",
           "moduleName": "cake",
           "genericSig": "<τ_0_0, τ_0_1, τ_0_2>",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -241,6 +243,7 @@
               "usr": "s:4cake2C1C3InsACSgXwvg",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Transparent"
               ],
@@ -269,6 +272,7 @@
               "usr": "s:4cake2C1C3InsACSgXwvs",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Transparent"
               ],
@@ -323,6 +327,7 @@
               "usr": "s:4cake2C1C4Ins2ACXovg",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Transparent"
               ],
@@ -343,6 +348,7 @@
               "usr": "s:4cake2C1C4Ins2ACXovs",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Transparent"
               ],
@@ -370,6 +376,7 @@
           "usr": "s:4cake2C1CACycfc",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -462,6 +469,7 @@
           "usr": "s:4cake6NumberO3oneyA2CmF",
           "location": "",
           "moduleName": "cake",
+          "fixedbinaryorder": 0,
           "children": [
             {
               "kind": "TypeFunc",
@@ -499,6 +507,7 @@
           "usr": "s:4cake6NumberO8RawValuea",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -516,6 +525,7 @@
           "usr": "s:4cake6NumberO9hashValueSivp",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -531,6 +541,7 @@
               "usr": "s:4cake6NumberO9hashValueSivg",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "children": [
                 {
                   "kind": "TypeNominal",
@@ -550,6 +561,7 @@
           "usr": "s:4cake6NumberO4hash4intoys6HasherVz_tF",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -572,6 +584,7 @@
           "usr": "s:4cake6NumberO8rawValueACSgSi_tcfc",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "declAttributes": [
             "Inlinable"
           ],
@@ -606,6 +619,7 @@
           "usr": "s:4cake6NumberO8rawValueSivp",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -621,6 +635,7 @@
               "usr": "s:4cake6NumberO8rawValueSivg",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Inlinable"
               ],
@@ -675,6 +690,281 @@
     },
     {
       "kind": "TypeDecl",
+      "name": "fixedLayoutStruct",
+      "printedName": "fixedLayoutStruct",
+      "declKind": "Struct",
+      "usr": "s:4cake17fixedLayoutStructV",
+      "location": "",
+      "moduleName": "cake",
+      "declAttributes": [
+        "FixedLayout"
+      ],
+      "children": [
+        {
+          "kind": "Var",
+          "name": "a",
+          "printedName": "a",
+          "declKind": "Var",
+          "usr": "s:4cake17fixedLayoutStructV1aSivp",
+          "location": "",
+          "moduleName": "cake",
+          "fixedbinaryorder": 0,
+          "declAttributes": [
+            "HasInitialValue"
+          ],
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "Getter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake17fixedLayoutStructV1aSivg",
+              "location": "",
+              "moduleName": "cake",
+              "implicit": true,
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            },
+            {
+              "kind": "Setter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake17fixedLayoutStructV1aSivs",
+              "location": "",
+              "moduleName": "cake",
+              "implicit": true,
+              "mutating": true,
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Void",
+                  "printedName": "()"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "Var",
+          "name": "b",
+          "printedName": "b",
+          "declKind": "Var",
+          "usr": "s:4cake17fixedLayoutStructV1b33_3D8926C30F7417F2EF9A277D0C73FBDBLLSivp",
+          "location": "",
+          "moduleName": "cake",
+          "fixedbinaryorder": 1,
+          "declAttributes": [
+            "HasInitialValue"
+          ],
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "Getter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake17fixedLayoutStructV1b33_3D8926C30F7417F2EF9A277D0C73FBDBLLSivg",
+              "location": "",
+              "moduleName": "cake",
+              "implicit": true,
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            },
+            {
+              "kind": "Setter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake17fixedLayoutStructV1b33_3D8926C30F7417F2EF9A277D0C73FBDBLLSivs",
+              "location": "",
+              "moduleName": "cake",
+              "implicit": true,
+              "mutating": true,
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Void",
+                  "printedName": "()"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "Var",
+          "name": "c",
+          "printedName": "c",
+          "declKind": "Var",
+          "usr": "s:4cake17fixedLayoutStructV1cSivp",
+          "location": "",
+          "moduleName": "cake",
+          "fixedbinaryorder": 2,
+          "declAttributes": [
+            "HasInitialValue"
+          ],
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "Getter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake17fixedLayoutStructV1cSivg",
+              "location": "",
+              "moduleName": "cake",
+              "implicit": true,
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            },
+            {
+              "kind": "Setter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake17fixedLayoutStructV1cSivs",
+              "location": "",
+              "moduleName": "cake",
+              "implicit": true,
+              "mutating": true,
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Void",
+                  "printedName": "()"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "Constructor",
+          "name": "init",
+          "printedName": "init(a:b:c:)",
+          "declKind": "Constructor",
+          "usr": "s:4cake17fixedLayoutStructV1a1b1cACSi_S2itc33_3D8926C30F7417F2EF9A277D0C73FBDBLlfc",
+          "location": "",
+          "moduleName": "cake",
+          "implicit": true,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "fixedLayoutStruct",
+              "printedName": "fixedLayoutStruct",
+              "usr": "s:4cake17fixedLayoutStructV"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            }
+          ]
+        },
+        {
+          "kind": "Constructor",
+          "name": "init",
+          "printedName": "init()",
+          "declKind": "Constructor",
+          "usr": "s:4cake17fixedLayoutStructVACycfc",
+          "location": "",
+          "moduleName": "cake",
+          "implicit": true,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "fixedLayoutStruct",
+              "printedName": "fixedLayoutStruct",
+              "usr": "s:4cake17fixedLayoutStructV"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "kind": "TypeDecl",
       "name": "Int",
       "printedName": "Int",
       "declKind": "Struct",
diff --git a/test/api-digester/Outputs/cake.json b/test/api-digester/Outputs/cake.json
index 56af1b7..994ab4e 100644
--- a/test/api-digester/Outputs/cake.json
+++ b/test/api-digester/Outputs/cake.json
@@ -102,6 +102,7 @@
           "usr": "s:4cake2S1VACycfc",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -132,6 +133,7 @@
           "location": "",
           "moduleName": "cake",
           "genericSig": "<T1, T2, T3>",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -248,6 +250,7 @@
               "usr": "s:4cake2C1C3InsACSgXwvg",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Transparent"
               ],
@@ -276,6 +279,7 @@
               "usr": "s:4cake2C1C3InsACSgXwvs",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Transparent"
               ],
@@ -330,6 +334,7 @@
               "usr": "s:4cake2C1C4Ins2ACXovg",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Transparent"
               ],
@@ -350,6 +355,7 @@
               "usr": "s:4cake2C1C4Ins2ACXovs",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Transparent"
               ],
@@ -377,6 +383,7 @@
           "usr": "s:4cake2C1CACycfc",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -469,6 +476,7 @@
           "usr": "s:4cake6NumberO3oneyA2CmF",
           "location": "",
           "moduleName": "cake",
+          "fixedbinaryorder": 0,
           "children": [
             {
               "kind": "TypeFunc",
@@ -513,6 +521,7 @@
           "usr": "s:4cake6NumberO8RawValuea",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -530,6 +539,7 @@
           "usr": "s:4cake6NumberO9hashValueSivp",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -545,6 +555,7 @@
               "usr": "s:4cake6NumberO9hashValueSivg",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "children": [
                 {
                   "kind": "TypeNominal",
@@ -564,6 +575,7 @@
           "usr": "s:4cake6NumberO4hash4intoys6HasherVz_tF",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -586,6 +598,7 @@
           "usr": "s:4cake6NumberO8rawValueACSgSi_tcfc",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "declAttributes": [
             "Inlinable"
           ],
@@ -620,6 +633,7 @@
           "usr": "s:4cake6NumberO8rawValueSivp",
           "location": "",
           "moduleName": "cake",
+          "implicit": true,
           "children": [
             {
               "kind": "TypeNominal",
@@ -635,6 +649,7 @@
               "usr": "s:4cake6NumberO8rawValueSivg",
               "location": "",
               "moduleName": "cake",
+              "implicit": true,
               "declAttributes": [
                 "Inlinable"
               ],
@@ -689,6 +704,143 @@
     },
     {
       "kind": "TypeDecl",
+      "name": "fixedLayoutStruct",
+      "printedName": "fixedLayoutStruct",
+      "declKind": "Struct",
+      "usr": "s:4cake17fixedLayoutStructV",
+      "location": "",
+      "moduleName": "cake",
+      "declAttributes": [
+        "FixedLayout"
+      ],
+      "children": [
+        {
+          "kind": "Var",
+          "name": "a",
+          "printedName": "a",
+          "declKind": "Var",
+          "usr": "s:4cake17fixedLayoutStructV1aSivp",
+          "location": "",
+          "moduleName": "cake",
+          "fixedbinaryorder": 0,
+          "declAttributes": [
+            "HasInitialValue"
+          ],
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "Getter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake17fixedLayoutStructV1aSivg",
+              "location": "",
+              "moduleName": "cake",
+              "implicit": true,
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            },
+            {
+              "kind": "Setter",
+              "name": "_",
+              "printedName": "_()",
+              "declKind": "Accessor",
+              "usr": "s:4cake17fixedLayoutStructV1aSivs",
+              "location": "",
+              "moduleName": "cake",
+              "implicit": true,
+              "mutating": true,
+              "declAttributes": [
+                "Transparent"
+              ],
+              "children": [
+                {
+                  "kind": "TypeNominal",
+                  "name": "Void",
+                  "printedName": "()"
+                },
+                {
+                  "kind": "TypeNominal",
+                  "name": "Int",
+                  "printedName": "Int",
+                  "usr": "s:Si"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "kind": "Constructor",
+          "name": "init",
+          "printedName": "init(a:b:c:)",
+          "declKind": "Constructor",
+          "usr": "s:4cake17fixedLayoutStructV1a1b1cACSi_S2itc33_3D8926C30F7417F2EF9A277D0C73FBDBLlfc",
+          "location": "",
+          "moduleName": "cake",
+          "implicit": true,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "fixedLayoutStruct",
+              "printedName": "fixedLayoutStruct",
+              "usr": "s:4cake17fixedLayoutStructV"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            }
+          ]
+        },
+        {
+          "kind": "Constructor",
+          "name": "init",
+          "printedName": "init()",
+          "declKind": "Constructor",
+          "usr": "s:4cake17fixedLayoutStructVACycfc",
+          "location": "",
+          "moduleName": "cake",
+          "implicit": true,
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "fixedLayoutStruct",
+              "printedName": "fixedLayoutStruct",
+              "usr": "s:4cake17fixedLayoutStructV"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "kind": "TypeDecl",
       "name": "Int",
       "printedName": "Int",
       "declKind": "Struct",
diff --git a/test/api-digester/Outputs/clang-module-dump.txt b/test/api-digester/Outputs/clang-module-dump.txt
index c26a73a..46c293e 100644
--- a/test/api-digester/Outputs/clang-module-dump.txt
+++ b/test/api-digester/Outputs/clang-module-dump.txt
@@ -54,6 +54,7 @@
           "usr": "c:objc(cs)NSObject(im)init",
           "location": "",
           "moduleName": "Foo",
+          "implicit": true,
           "declAttributes": [
             "Override",
             "ObjC"
diff --git a/test/api-digester/apinotes-diags.swift b/test/api-digester/apinotes-diags.swift
index 4e64c05..6a7b06d 100644
--- a/test/api-digester/apinotes-diags.swift
+++ b/test/api-digester/apinotes-diags.swift
@@ -6,6 +6,12 @@
 // RUN: %api-digester %clang-importer-sdk-nosource -dump-sdk -module APINotesTest -o %t.dump2.json -module-cache-path %t.module-cache -swift-version 3 -I %S/Inputs/APINotesRight
 // RUN: %api-digester %clang-importer-sdk-nosource -dump-sdk -module APINotesTest -o %t.dump3.json -module-cache-path %t.module-cache -swift-version 4 -I %S/Inputs/APINotesRight
 // RUN: %api-digester -diagnose-sdk -print-module -input-paths %t.dump1.json -input-paths %t.dump3.json > %t.result
-// RUN: diff -u %S/Outputs/apinotes-diags.txt %t.result
+
+// RUN: %clang -E -P -x c %S/Outputs/apinotes-diags.txt -o - | sed '/^\s*$/d' > %t.expected
+// RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp
+// RUN: diff -u %t.expected %t.result.tmp
+
 // RUN: %api-digester -diagnose-sdk -print-module -input-paths %t.dump2.json -input-paths %t.dump3.json > %t.result
-// RUN: diff -u %S/Outputs/apinotes-diags-3-4.txt %t.result
+// RUN: %clang -E -P -x c %S/Outputs/apinotes-diags-3-4.txt -o - | sed '/^\s*$/d' > %t.expected
+// RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp
+// RUN: diff -u %t.expected %t.result.tmp
diff --git a/test/api-digester/compare-dump.swift b/test/api-digester/compare-dump.swift
index 3a8b92a..e70f166 100644
--- a/test/api-digester/compare-dump.swift
+++ b/test/api-digester/compare-dump.swift
@@ -6,9 +6,15 @@
 // RUN: %api-digester -dump-sdk -module cake1 -o %t.dump1.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %t.mod -I %S/Inputs/APINotesLeft
 // RUN: %api-digester -dump-sdk -module cake2 -o %t.dump2.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %t.mod -I %S/Inputs/APINotesRight
 // RUN: %api-digester -diagnose-sdk -print-module --input-paths %t.dump1.json -input-paths %t.dump2.json > %t.result
-// RUN: diff -u %S/Outputs/Cake.txt %t.result
+
+// RUN: %clang -E -P -x c %S/Outputs/Cake.txt -o - | sed '/^\s*$/d' > %t.expected
+// RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp
+// RUN: diff -u %t.expected %t.result.tmp
 
 // RUN: %api-digester -dump-sdk -module cake1 -o %t.dump1.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %t.mod -I %S/Inputs/APINotesLeft -abi
 // RUN: %api-digester -dump-sdk -module cake2 -o %t.dump2.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %t.mod -I %S/Inputs/APINotesRight -abi
 // RUN: %api-digester -diagnose-sdk -print-module --input-paths %t.dump1.json -input-paths %t.dump2.json -abi > %t.result
-// RUN: diff -u %S/Outputs/Cake-abi.txt %t.result
+
+// RUN: %clang -E -P -x c %S/Outputs/Cake-abi.txt -o - | sed '/^\s*$/d' > %t.expected
+// RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp
+// RUN: diff -u %t.expected %t.result.tmp
diff --git a/test/attr/attr_dynamic_infer.swift b/test/attr/attr_dynamic_infer.swift
index e4686df..dd95065 100644
--- a/test/attr/attr_dynamic_infer.swift
+++ b/test/attr/attr_dynamic_infer.swift
@@ -65,17 +65,17 @@
 
   // CHECK: @objc final var prop: Super
   @objc final var prop: Super {
-    // CHECK: final get
+    // CHECK: get
     get { return Super() }
-    // CHECK: final set
+    // CHECK: set
     set { }
   }
 
   // CHECK: @objc final subscript(sup: Super) -> Super
   @objc final subscript(sup: Super) -> Super {
-    // CHECK: final get
+    // CHECK: get
     get { return sup }
-    // CHECK: final set
+    // CHECK: set
     set { }
   }
 
diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift
index 09ac36a..11bef3f 100644
--- a/test/attr/attr_objc.swift
+++ b/test/attr/attr_objc.swift
@@ -841,17 +841,17 @@
   var observingAccessorsVar1: Int {
   // CHECK: @objc var observingAccessorsVar1: Int {
     willSet {}
-    // CHECK-NEXT: {{^}} final willSet {}
+    // CHECK-NEXT: {{^}} willSet {}
     didSet {}
-    // CHECK-NEXT: {{^}} final didSet {}
+    // CHECK-NEXT: {{^}} didSet {}
   }
 
   @objc var observingAccessorsVar1_: Int {
   // CHECK: {{^}} @objc var observingAccessorsVar1_: Int {
     willSet {}
-    // CHECK-NEXT: {{^}} final willSet {}
+    // CHECK-NEXT: {{^}} willSet {}
     didSet {}
-    // CHECK-NEXT: {{^}} final didSet {}
+    // CHECK-NEXT: {{^}} didSet {}
   }
 
 
diff --git a/test/decl/protocol/resilient_defaults.swift b/test/decl/protocol/resilient_defaults.swift
new file mode 100644
index 0000000..b959241
--- /dev/null
+++ b/test/decl/protocol/resilient_defaults.swift
@@ -0,0 +1,18 @@
+// RUN: %target-typecheck-verify-swift -enable-resilience
+
+public struct Wrapper<T: P>: P { }
+extension Wrapper: Q where T: Q { }
+
+public protocol PBase {
+  associatedtype AssocType
+}
+
+public protocol P: PBase {
+  override associatedtype AssocType: P = Wrapper<Self>
+  // expected-note@-1{{associated type 'AssocType' has default type 'Wrapper<Self>' written here}}
+}
+
+public protocol Q: P where Self.AssocType: Q { }
+
+public protocol R: Q where Self.AssocType: R { }
+// expected-warning@-1{{default type 'Wrapper<Self>' for associated type 'AssocType' does not satisfy constraint 'Self.AssocType': 'R'}}
diff --git a/tools/swift-api-digester/ModuleAnalyzerNodes.cpp b/tools/swift-api-digester/ModuleAnalyzerNodes.cpp
index 396f6bd..08b5f5b 100644
--- a/tools/swift-api-digester/ModuleAnalyzerNodes.cpp
+++ b/tools/swift-api-digester/ModuleAnalyzerNodes.cpp
@@ -42,11 +42,13 @@
   StringRef USR;
   StringRef Location;
   StringRef ModuleName;
+  bool IsImplicit = false;
   bool IsThrowing = false;
   bool IsMutating = false;
   bool IsStatic = false;
   bool IsDeprecated = false;
   Optional<uint8_t> SelfIndex;
+  Optional<unsigned> FixedBinaryOrder;
   ReferenceOwnership ReferenceOwnership = ReferenceOwnership::Strong;
   std::vector<DeclAttrKind> DeclAttrs;
   std::vector<TypeAttrKind> TypeAttrs;
@@ -81,8 +83,8 @@
 SDKNodeDecl::SDKNodeDecl(SDKNodeInitInfo Info, SDKNodeKind Kind)
       : SDKNode(Info, Kind), DKind(Info.DKind), Usr(Info.USR),
         Location(Info.Location), ModuleName(Info.ModuleName),
-        DeclAttributes(Info.DeclAttrs), IsStatic(Info.IsStatic),
-        IsDeprecated(Info.IsDeprecated),
+        DeclAttributes(Info.DeclAttrs), IsImplicit(Info.IsImplicit),
+        IsStatic(Info.IsStatic), IsDeprecated(Info.IsDeprecated),
         ReferenceOwnership(uint8_t(Info.ReferenceOwnership)),
         GenericSig(Info.GenericSig) {}
 
@@ -108,7 +110,8 @@
   SDKNodeDecl(Info, SDKNodeKind::DeclTypeAlias) {}
 
 SDKNodeDeclVar::SDKNodeDeclVar(SDKNodeInitInfo Info): 
-  SDKNodeDecl(Info, SDKNodeKind::DeclVar) {}
+  SDKNodeDecl(Info, SDKNodeKind::DeclVar),
+  FixedBinaryOrder(Info.FixedBinaryOrder) {}
 
 SDKNodeDeclAbstractFunc::SDKNodeDeclAbstractFunc(SDKNodeInitInfo Info,
   SDKNodeKind Kind): SDKNodeDecl(Info, Kind), IsThrowing(Info.IsThrowing),
@@ -153,8 +156,10 @@
   }
 }
 
-unsigned SDKNode::getChildIndex(NodePtr Child) const {
-  return std::find(Children.begin(), Children.end(), Child) - Children.begin();
+unsigned SDKNode::getChildIndex(const SDKNode* Child) const {
+  auto It = std::find(Children.begin(), Children.end(), Child);
+  assert(It != Children.end() && "cannot find the child");
+  return It - Children.begin();
 }
 
 SDKNode* SDKNode::getOnlyChild() const {
@@ -503,6 +508,9 @@
       case KeyKind::KK_selfIndex:
         Info.SelfIndex = getAsInt(Pair.getValue());
         break;
+      case KeyKind::KK_fixedbinaryorder:
+        Info.FixedBinaryOrder = getAsInt(Pair.getValue());
+        break;
       case KeyKind::KK_usr:
         Info.USR = GetScalarString(Pair.getValue());
         break;
@@ -555,6 +563,9 @@
       case KeyKind::KK_deprecated:
         Info.IsDeprecated = true;
         break;
+      case KeyKind::KK_implicit:
+        Info.IsImplicit = true;
+        break;
       case KeyKind::KK_ownership:
         Info.ReferenceOwnership =
             swift::ReferenceOwnership(getAsInt(Pair.getValue()));
@@ -653,6 +664,8 @@
       auto Right = (&Other)->getAs<SDKNodeType>();
       if (!Left->getTypeAttributes().equals(Right->getTypeAttributes()))
         return false;
+      if (Left->hasDefaultArgument() != Right->hasDefaultArgument())
+        return false;
       if (Left->getPrintedName() == Right->getPrintedName())
         return true;
       return Left->getName() == Right->getName() &&
@@ -671,8 +684,24 @@
         return false;
       LLVM_FALLTHROUGH;
     }
+
+    case SDKNodeKind::DeclVar: {
+      if (getSDKContext().checkingABI()) {
+        // If we're checking ABI, the definition order matters.
+        // If they're both members for fixed layout types, we never consider
+        // them equal because we need to check definition orders.
+        if (auto *LV = dyn_cast<SDKNodeDeclVar>(this)) {
+          if (auto *RV = dyn_cast<SDKNodeDeclVar>(&Other)) {
+            if (LV->hasFixedBinaryOrder() && RV->hasFixedBinaryOrder()) {
+              if (LV->getFixedBinaryOrder() != RV->getFixedBinaryOrder())
+                return false;
+            }
+          }
+        }
+      }
+      LLVM_FALLTHROUGH;
+    }
     case SDKNodeKind::DeclType:
-    case SDKNodeKind::DeclVar:
     case SDKNodeKind::DeclTypeAlias: {
       auto Left = this->getAs<SDKNodeDecl>();
       auto Right = (&Other)->getAs<SDKNodeDecl>();
@@ -684,6 +713,7 @@
         return false;
       if (Left->getGenericSignature() != Right->getGenericSignature())
         return false;
+
       LLVM_FALLTHROUGH;
     }
     case SDKNodeKind::Root: {
@@ -902,6 +932,39 @@
   return StringRef();
 }
 
+static Optional<unsigned> getFixedBinaryOrder(ValueDecl *VD) {
+  auto D = VD->getDeclContext()->getAsDecl();
+  if (!D)
+    return None;
+
+  if (auto *ED = dyn_cast<EnumDecl>(D)) {
+    auto Check = [](Decl *M) {
+      return isa<EnumElementDecl>(M);
+    };
+    if (!ED->isResilient() && Check(VD)) {
+      auto Members = ED->getMembers();
+      auto End = std::find(Members.begin(), Members.end(), VD);
+      assert(End != Members.end());
+      return std::count_if(Members.begin(), End, Check);
+    }
+  }
+  if (auto *SD = dyn_cast<StructDecl>(D)) {
+    auto Check = [](Decl *M) {
+      if (auto *STD = dyn_cast<AbstractStorageDecl>(M)) {
+        return STD->hasStorage() && !STD->isStatic();
+      }
+      return false;
+    };
+    if (!SD->isResilient() && Check(VD)) {
+      auto Members = SD->getMembers();
+      auto End = std::find(Members.begin(), Members.end(), VD);
+      assert(End != Members.end());
+      return std::count_if(Members.begin(), End, Check);
+    }
+  }
+  return llvm::None;
+}
+
 SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, Type Ty,
                                  TypeInitInfo TypeInfo) :
     Ctx(Ctx), Name(getTypeName(Ctx, Ty, TypeInfo.IsImplicitlyUnwrappedOptional)),
@@ -921,10 +984,12 @@
       PrintedName(getPrintedName(Ctx, VD)), DKind(VD->getKind()),
       USR(calculateUsr(Ctx, VD)), Location(calculateLocation(Ctx, VD)),
       ModuleName(VD->getModuleContext()->getName().str()),
+      IsImplicit(VD->isImplicit()),
       IsThrowing(isFuncThrowing(VD)), IsMutating(isFuncMutating(VD)),
       IsStatic(VD->isStatic()),
       IsDeprecated(VD->getAttrs().getDeprecated(VD->getASTContext())),
-      SelfIndex(getSelfIndex(VD)), ReferenceOwnership(getReferenceOwnership(VD)),
+      SelfIndex(getSelfIndex(VD)), FixedBinaryOrder(getFixedBinaryOrder(VD)),
+      ReferenceOwnership(getReferenceOwnership(VD)),
       GenericSig(printGenericSignature(Ctx, VD)) {
 
   // Calculate usr for its super class.
@@ -1054,7 +1119,7 @@
   return Func;
 }
 
-static bool shouldIgnore(Decl *D, const Decl* Parent) {
+static bool shouldIgnore(Decl *D, const Decl* Parent, SDKContext &Ctx) {
   if (D->isPrivateStdlibDecl(false))
     return true;
   if (AvailableAttr::isUnavailable(D))
@@ -1072,6 +1137,10 @@
     case AccessLevel::Internal:
     case AccessLevel::Private:
     case AccessLevel::FilePrivate:
+      // Private vars with fixed binary orders can have ABI-impact, so we should
+      // whitelist them if we're checking ABI.
+      if (Ctx.checkingABI() && getFixedBinaryOrder(VD).hasValue())
+        break;
       return true;
     case AccessLevel::Public:
     case AccessLevel::Open:
@@ -1153,7 +1222,7 @@
                              IterableDeclContext *Context,
                              std::set<ExtensionDecl*> &HandledExts) {
   for (auto *Member : Context->getMembers()) {
-    if (shouldIgnore(Member, Context->getDecl()))
+    if (shouldIgnore(Member, Context->getDecl(), Ctx))
       continue;
     if (auto Func = dyn_cast<FuncDecl>(Member)) {
       Root->addChild(constructFunctionNode(Ctx, Func, SDKNodeKind::DeclFunction));
@@ -1182,7 +1251,7 @@
     llvm::SmallVector<Decl*, 512> Decls;
     M->getDisplayDecls(Decls);
     for (auto D : Decls) {
-      if (shouldIgnore(D, nullptr))
+      if (shouldIgnore(D, nullptr, Ctx))
         continue;
       if (KnownDecls.count(D))
         continue;
@@ -1300,6 +1369,16 @@
       if (bool isDeprecated = D->isDeprecated())
         out.mapRequired(getKeyContent(Ctx, KeyKind::KK_deprecated).data(),
                         isDeprecated);
+      if (bool isImplicit = D->isImplicit())
+        out.mapRequired(getKeyContent(Ctx, KeyKind::KK_implicit).data(),
+                        isImplicit);
+      if (auto V = dyn_cast<SDKNodeDeclVar>(value)) {
+        if (V->hasFixedBinaryOrder()) {
+          auto Order = V->getFixedBinaryOrder();
+          out.mapRequired(getKeyContent(Ctx, KeyKind::KK_fixedbinaryorder).data(),
+                          Order);
+        }
+      }
       if (auto F = dyn_cast<SDKNodeDeclAbstractFunc>(value)) {
         if (bool isThrowing = F->isThrowing())
           out.mapRequired(getKeyContent(Ctx, KeyKind::KK_throwing).data(),
diff --git a/tools/swift-api-digester/ModuleAnalyzerNodes.h b/tools/swift-api-digester/ModuleAnalyzerNodes.h
index 11eac7f..660af51 100644
--- a/tools/swift-api-digester/ModuleAnalyzerNodes.h
+++ b/tools/swift-api-digester/ModuleAnalyzerNodes.h
@@ -220,7 +220,6 @@
   std::set<NodeAnnotation> Annotations;
   std::map<NodeAnnotation, StringRef> AnnotateComments;
   NodePtr Parent = nullptr;
-
 protected:
   SDKNode(SDKNodeInitInfo Info, SDKNodeKind Kind);
 
@@ -253,7 +252,7 @@
   void addChild(SDKNode *Child);
   ArrayRef<SDKNode*> getChildren() const;
   bool hasSameChildren(const SDKNode &Other) const;
-  unsigned getChildIndex(NodePtr Child) const;
+  unsigned getChildIndex(const SDKNode *Child) const;
   SDKNode* getOnlyChild() const;
   SDKContext &getSDKContext() const { return Ctx; }
   SDKNodeRoot *getRootNode() const;
@@ -275,6 +274,7 @@
   StringRef Location;
   StringRef ModuleName;
   std::vector<DeclAttrKind> DeclAttributes;
+  bool IsImplicit;
   bool IsStatic;
   bool IsDeprecated;
   uint8_t ReferenceOwnership;
@@ -301,6 +301,7 @@
   bool isSDKPrivate() const;
   bool isDeprecated() const { return IsDeprecated; };
   bool hasDeclAttribute(DeclAttrKind DAKind) const;
+  bool isImplicit() const { return IsImplicit; };
   bool isStatic() const { return IsStatic; };
   StringRef getGenericSignature() const { return GenericSig; }
   StringRef getScreenInfo() const;
@@ -440,9 +441,12 @@
 };
 
 class SDKNodeDeclVar : public SDKNodeDecl {
+  Optional<unsigned> FixedBinaryOrder;
 public:
   SDKNodeDeclVar(SDKNodeInitInfo Info);
   static bool classof(const SDKNode *N);
+  bool hasFixedBinaryOrder() const { return FixedBinaryOrder.hasValue(); }
+  unsigned getFixedBinaryOrder() const { return *FixedBinaryOrder; }
 };
 
 class SDKNodeDeclAbstractFunc : public SDKNodeDecl {
@@ -538,6 +542,7 @@
                        CheckerOptions Opts);
 
 int findDeclUsr(StringRef dumpPath, CheckerOptions Opts);
+
 } // end of abi namespace
 } // end of ide namespace
 } // end of Swift namespace
diff --git a/tools/swift-api-digester/ModuleDiagsConsumer.cpp b/tools/swift-api-digester/ModuleDiagsConsumer.cpp
index c00bad3..8454c31 100644
--- a/tools/swift-api-digester/ModuleDiagsConsumer.cpp
+++ b/tools/swift-api-digester/ModuleDiagsConsumer.cpp
@@ -41,12 +41,16 @@
   case LocalDiagID::decl_attr_change:
   case LocalDiagID::decl_new_attr:
     return "/* Decl Attribute changes */";
+  case LocalDiagID::default_arg_removed:
   case LocalDiagID::decl_type_change:
     return "/* Type Changes */";
   case LocalDiagID::raw_type_change:
     return "/* RawRepresentable Changes */";
   case LocalDiagID::generic_sig_change:
     return "/* Generic Signature Changes */";
+  case LocalDiagID::decl_added:
+  case LocalDiagID::decl_reorder:
+    return "/* Fixed-layout Type Changes */";
   default:
     return StringRef();
   }
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index bc3c9e4..ade1857 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -709,6 +709,17 @@
             Desc);
         }
       }
+      // Detect re-ordering if they're from structs with a fixed layout.
+      auto *LV = dyn_cast<SDKNodeDeclVar>(L);
+      auto *RV = dyn_cast<SDKNodeDeclVar>(R);
+      if (LV && RV &&
+          LV->hasFixedBinaryOrder() && RV->hasFixedBinaryOrder() &&
+          LV->getFixedBinaryOrder() != RV->getFixedBinaryOrder()) {
+        Ctx.getDiags().diagnose(SourceLoc(), diag::decl_reorder,
+                                LV->getScreenInfo(),
+                                LV->getFixedBinaryOrder(),
+                                RV->getFixedBinaryOrder());
+      }
     }
 
     // Diagnose generic signature change
@@ -720,6 +731,21 @@
   }
 }
 
+static void diagnoseTypeChange(SDKNode* L, SDKNode* R) {
+  auto &Ctx = L->getSDKContext();
+  auto &Diags = Ctx.getDiags();
+  auto *LT = dyn_cast<SDKNodeType>(L);
+  auto *RT = dyn_cast<SDKNodeType>(R);
+  if (!LT || !RT)
+    return;
+  if (LT->hasDefaultArgument() && !RT->hasDefaultArgument()) {
+    auto *Func = cast<SDKNodeDeclAbstractFunc>(LT->getClosestParentDecl());
+    Diags.diagnose(SourceLoc(), diag::default_arg_removed, Func->getScreenInfo(),
+                   Func->getTypeRoleDescription(Ctx, Func->getChildIndex(LT)));
+  }
+}
+
+
 // This is first pass on two given SDKNode trees. This pass removes the common part
 // of two versions of SDK, leaving only the changed part.
 class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass {
@@ -751,6 +777,14 @@
     case NodeMatchReason::Added:
       assert(!Left);
       Right->annotate(NodeAnnotation::Added);
+      if (Ctx.checkingABI()) {
+        if (auto *VAD = dyn_cast<SDKNodeDeclVar>(Right)) {
+          if (VAD->hasFixedBinaryOrder()) {
+            Ctx.getDiags().diagnose(SourceLoc(), diag::decl_added,
+                                    VAD->getScreenInfo());
+          }
+        }
+      }
       return;
     case NodeMatchReason::Removed:
       assert(!Right);
@@ -773,6 +807,7 @@
     // Push the updated node to the map for future reference.
     UpdateMap.insert(Left, Right);
 
+    diagnoseTypeChange(Left, Right);
     if (Left->getKind() != Right->getKind()) {
       assert(isa<SDKNodeType>(Left) && isa<SDKNodeType>(Right) &&
         "only type nodes can match across kinds.");
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 25e9ea2..f412f72 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -2665,21 +2665,21 @@
                 set -x
                 pushd "${PLAYGROUNDSUPPORT_SOURCE_DIR}"
                 if [[ $(not ${SKIP_BUILD_OSX}) ]]; then
-                    "xcodebuild" -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-macOS -sdk macosx -arch x86_64 -derivedDataPath "${build_dir}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
+                    call "xcodebuild" -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-macOS -sdk macosx -arch x86_64 -derivedDataPath "${build_dir}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
                     
                     if [[ $(not ${SKIP_TEST_PLAYGROUNDSUPPORT}) ]]; then
                         # If we're going to end up testing PlaygroundLogger/PlaygroundSupport, then we need to build the tests too.
                         # Note that this *always* needs to run in Debug configuration.
-                        "xcodebuild" build-for-testing -configuration Debug -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-Test-PlaygroundLogger-macOS -sdk macosx -arch x86_64 -derivedDataPath "${build_dir}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
+                        call "xcodebuild" build-for-testing -configuration Debug -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-Test-PlaygroundLogger-macOS -sdk macosx -arch x86_64 -derivedDataPath "${build_dir}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
                     fi
                 fi
 
                 if [[ $(not ${SKIP_BUILD_IOS_SIMULATOR}) ]]; then
-                    "xcodebuild" -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-iOS -sdk iphonesimulator -arch x86_64 -derivedDataPath "${build_dir}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
+                    call "xcodebuild" -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-iOS -sdk iphonesimulator -arch x86_64 -derivedDataPath "${build_dir}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
                 fi
 
                 if [[ $(not ${SKIP_BUILD_TVOS_SIMULATOR}) ]]; then
-                    "xcodebuild" -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-tvOS -sdk appletvsimulator -arch x86_64 -derivedDataPath "${build_dir}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
+                    call "xcodebuild" -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-tvOS -sdk appletvsimulator -arch x86_64 -derivedDataPath "${build_dir}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
                 fi
                 popd
                 { set +x; } 2>/dev/null
@@ -2879,7 +2879,7 @@
                 # Watchpoint testing is currently disabled: see rdar://38566150.
                 if [[ "$(true_false ${LLDB_TEST_SWIFT_ONLY})" == "TRUE" ]]; then
                     LLDB_TEST_SUBDIR_CLAUSE="--test-subdir lang/swift"
-                    LLDB_TEST_CATEGORIES="--skip-category=watchpoint --skip-category=dwo --skip-category=dwarf"
+                    LLDB_TEST_CATEGORIES="--skip-category=watchpoint --skip-category=dwo"
                 else
                     LLDB_TEST_SUBDIR_CLAUSE=""
                     LLDB_TEST_CATEGORIES="--skip-category=watchpoint"
@@ -3102,7 +3102,7 @@
 
                 set -x
                 with_pushd "${PLAYGROUNDSUPPORT_SOURCE_DIR}" \
-                    "xcodebuild" test-without-building -configuration Debug -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-Test-PlaygroundLogger-macOS -sdk macosx -arch x86_64 -derivedDataPath "${PLAYGROUNDSUPPORT_BUILD_DIR}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
+                    call "xcodebuild" test-without-building -configuration Debug -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-Test-PlaygroundLogger-macOS -sdk macosx -arch x86_64 -derivedDataPath "${PLAYGROUNDSUPPORT_BUILD_DIR}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO
                 { set +x; } 2>/dev/null
                 continue
                 ;;
@@ -3423,15 +3423,15 @@
                     Darwin)
                         pushd "${PLAYGROUNDSUPPORT_SOURCE_DIR}"
                         if [[ $(not ${SKIP_BUILD_OSX}) ]]; then
-                            "xcodebuild" install -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-macOS -sdk macosx -arch x86_64 -derivedDataPath "${PLAYGROUNDSUPPORT_BUILD_DIR}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO DSTROOT="$(get_host_install_destdir ${host})" TOOLCHAIN_INSTALL_DIR="${TOOLCHAIN_PREFIX}" BUILD_PLAYGROUNDLOGGER_TESTS=NO
+                            call "xcodebuild" install -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-macOS -sdk macosx -arch x86_64 -derivedDataPath "${PLAYGROUNDSUPPORT_BUILD_DIR}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO DSTROOT="$(get_host_install_destdir ${host})" TOOLCHAIN_INSTALL_DIR="${TOOLCHAIN_PREFIX}" BUILD_PLAYGROUNDLOGGER_TESTS=NO
                         fi
 
                         if [[ $(not ${SKIP_BUILD_IOS_SIMULATOR}) ]]; then
-                            "xcodebuild" install -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-iOS -sdk iphonesimulator -arch x86_64 -derivedDataPath "${PLAYGROUNDSUPPORT_BUILD_DIR}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO DSTROOT="$(get_host_install_destdir ${host})" TOOLCHAIN_INSTALL_DIR="${TOOLCHAIN_PREFIX}" BUILD_PLAYGROUNDLOGGER_TESTS=NO
+                            call "xcodebuild" install -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-iOS -sdk iphonesimulator -arch x86_64 -derivedDataPath "${PLAYGROUNDSUPPORT_BUILD_DIR}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO DSTROOT="$(get_host_install_destdir ${host})" TOOLCHAIN_INSTALL_DIR="${TOOLCHAIN_PREFIX}" BUILD_PLAYGROUNDLOGGER_TESTS=NO
                         fi
 
                         if [[ $(not ${SKIP_BUILD_TVOS_SIMULATOR}) ]]; then
-                            "xcodebuild" install -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-tvOS -sdk appletvsimulator -arch x86_64 -derivedDataPath "${PLAYGROUNDSUPPORT_BUILD_DIR}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO DSTROOT="$(get_host_install_destdir ${host})" TOOLCHAIN_INSTALL_DIR="${TOOLCHAIN_PREFIX}" BUILD_PLAYGROUNDLOGGER_TESTS=NO
+                            call "xcodebuild" install -configuration "${PLAYGROUNDSUPPORT_BUILD_TYPE}" -workspace swift-xcode-playground-support.xcworkspace -scheme BuildScript-tvOS -sdk appletvsimulator -arch x86_64 -derivedDataPath "${PLAYGROUNDSUPPORT_BUILD_DIR}"/DerivedData SWIFT_EXEC="${SWIFTC_BIN}" SWIFT_LIBRARY_PATH="${SWIFT_LIB_DIR}/\$(PLATFORM_NAME)" ONLY_ACTIVE_ARCH=NO DSTROOT="$(get_host_install_destdir ${host})" TOOLCHAIN_INSTALL_DIR="${TOOLCHAIN_PREFIX}" BUILD_PLAYGROUNDLOGGER_TESTS=NO
                         fi
                         popd
                         continue
diff --git a/validation-test/Evolution/Inputs/protocol_add_requirements.swift b/validation-test/Evolution/Inputs/protocol_add_requirements.swift
index 6e2eb34..ba05853 100644
--- a/validation-test/Evolution/Inputs/protocol_add_requirements.swift
+++ b/validation-test/Evolution/Inputs/protocol_add_requirements.swift
@@ -176,24 +176,23 @@
 #endif
 }
 
-public struct Wrapper<T> { }
+public protocol SimpleProtocol {
+  static func getString() -> String
+}
+
+public struct Wrapper<T>: SimpleProtocol {
+  public static func getString() -> String {
+    return "I am a wrapper for \(T.self)"
+  }
+}
 
 public protocol AddAssocTypesProtocol {
-  // FIXME: The presence of a single method requirement causes us to
-  // create a resilient witness table, avoiding a runtime assertion.
-  func dummy()
-
 #if AFTER
   associatedtype AssocType = Self
-  associatedtype AssocType2 = Wrapper<AssocType>
+  associatedtype AssocType2: SimpleProtocol = Wrapper<AssocType>
 #endif
 }
 
-extension AddAssocTypesProtocol {
-  public func dummy() { }
-}
-
-
 public func doSomethingWithAssocTypes<T: AddAssocTypesProtocol>(_ value: T)
     -> String {
 #if AFTER
@@ -202,3 +201,17 @@
   return "there are no associated types yet"
 #endif
 }
+
+public func doSomethingWithAssocConformances<T: AddAssocTypesProtocol>(_ value: T)
+    -> String {
+#if AFTER
+  let at2: Any.Type = T.AssocType2.self
+  if let simpleType = at2 as? SimpleProtocol.Type {
+    return simpleType.getString()
+  }
+  
+  return "missing associated conformance"
+#else
+  return "there are no associated conformances yet"
+#endif
+}
diff --git a/validation-test/Evolution/test_protocol_add_requirements.swift b/validation-test/Evolution/test_protocol_add_requirements.swift
index 046b6ee..2acfb7e 100644
--- a/validation-test/Evolution/test_protocol_add_requirements.swift
+++ b/validation-test/Evolution/test_protocol_add_requirements.swift
@@ -154,5 +154,16 @@
   }
 }
 
+ProtocolAddRequirementsTest.test("AddAssociatedConformanceRequirements") {
+  let addString = AddAssociatedType<String>()
+  let stringResult = doSomethingWithAssocConformances(addString)
+
+  if getVersion() == 0 {
+    expectEqual("there are no associated conformances yet", stringResult)
+  } else {
+    expectEqual("I am a wrapper for AddAssociatedType<String>", stringResult)
+  }
+}
+
 runAllTests()