Merge pull request #16059 from AnthonyLatsis/unused-result-closure-warning

[DiagnosticsSema] SR-5983
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0f2f72..4c81bc6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -61,6 +61,15 @@
 Swift 4.2
 ---------
 
+* [SR-106][]
+
+  The behavior of `.description` and `.debugDescription` for floating-point
+  numbers has been changed. Previously these unconditionally printed a fixed
+  number of decimal digits (e.g. 15 and 17 for Double, respectively). They now
+  print exactly as many digits as are needed for the resulting string to
+  convert back to the original source value, and no more. For more details,
+  see the original bug report and the linked pull request.
+
 * [SE-0193][]
 
   Various function-like declarations can now be marked as `@inlinable`,
@@ -6981,6 +6990,7 @@
 [SE-0198]: <https://github.com/apple/swift-evolution/blob/master/proposals/0198-playground-quicklook-api-revamp.md>
 [SE-0199]: <https://github.com/apple/swift-evolution/blob/master/proposals/0199-bool-toggle.md>
 
+[SR-106]: <https://bugs.swift.org/browse/SR-106>
 [SR-419]: <https://bugs.swift.org/browse/SR-419>
 [SR-1009]: <https://bugs.swift.org/browse/SR-1009>
 [SR-1446]: <https://bugs.swift.org/browse/SR-1446>
diff --git a/README.md b/README.md
index 3e44e9d..c609454 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@
 
 For Ubuntu, you'll need the following development dependencies:
 
-    sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev autoconf libtool systemtap-sdt-dev tzdata rsync
+    sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev systemtap-sdt-dev tzdata rsync
 
 **Note:** LLDB currently requires at least `swig-1.3.40` but will successfully build
 with version 2 shipped with Ubuntu.
diff --git a/benchmark/single-source/CSVParsing.swift b/benchmark/single-source/CSVParsing.swift
index 62eec0d..03671be 100644
--- a/benchmark/single-source/CSVParsing.swift
+++ b/benchmark/single-source/CSVParsing.swift
@@ -31,7 +31,7 @@
     var result: Substring = "" // we accumulate the result
 
     while !remainder.isEmpty {
-        guard let nextQuoteIndex = remainder.index(of: "\"") else {
+        guard let nextQuoteIndex = remainder.firstIndex(of: "\"") else {
             throw ParseError(message: "Expected a closing \"")
         }
 
diff --git a/benchmark/single-source/RemoveWhere.swift b/benchmark/single-source/RemoveWhere.swift
index b995bf2..81e1287 100644
--- a/benchmark/single-source/RemoveWhere.swift
+++ b/benchmark/single-source/RemoveWhere.swift
@@ -46,7 +46,7 @@
 
 extension RangeReplaceableCollection where Self: MutableCollection {
   mutating func removeWhere_move(where match: (Element) throws -> Bool) rethrows  {
-    guard var i = try index(where: match) else { return }
+    guard var i = try firstIndex(where: match) else { return }
 
     var j = index(after: i)
     while j != endIndex {
@@ -62,7 +62,7 @@
   }
 
   mutating func removeWhere_swap(where match: (Element) throws -> Bool) rethrows {
-    guard var i = try index(where: match) else { return }
+    guard var i = try firstIndex(where: match) else { return }
 
     var j = index(after: i)
     while j != endIndex {
diff --git a/cmake/modules/SwiftHandleGybSources.cmake b/cmake/modules/SwiftHandleGybSources.cmake
index ebf4de9..d96494c 100644
--- a/cmake/modules/SwiftHandleGybSources.cmake
+++ b/cmake/modules/SwiftHandleGybSources.cmake
@@ -111,7 +111,6 @@
       "${SWIFT_SOURCE_DIR}/utils/UnicodeData/GraphemeBreakProperty.txt"
       "${SWIFT_SOURCE_DIR}/utils/UnicodeData/GraphemeBreakTest.txt"
       "${SWIFT_SOURCE_DIR}/utils/gyb_stdlib_support.py"
-      "${SWIFT_SOURCE_DIR}/utils/gyb_stdlib_unittest_support.py"
       "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/__init__.py"
       "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/Child.py"
       "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/kinds.py"
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 750def2..e575382 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -367,7 +367,7 @@
     DefaultArgumentResilienceExpansion : 1
   );
   
-  SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+5+1+1+1+1+1,
+  SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+5+1+1+1+1+1+1,
     /// \see AbstractFunctionDecl::BodyKind
     BodyKind : 3,
 
@@ -390,7 +390,11 @@
     HasComputedNeedsNewVTableEntry : 1,
 
     /// The ResilienceExpansion to use for default arguments.
-    DefaultArgumentResilienceExpansion : 1
+    DefaultArgumentResilienceExpansion : 1,
+
+    /// Whether this member was synthesized as part of a derived
+    /// protocol conformance.
+    Synthesized : 1
   );
 
   SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+2+1+1+2,
@@ -5105,6 +5109,7 @@
     Bits.AbstractFunctionDecl.HasComputedNeedsNewVTableEntry = false;
     Bits.AbstractFunctionDecl.DefaultArgumentResilienceExpansion =
         unsigned(ResilienceExpansion::Maximal);
+    Bits.AbstractFunctionDecl.Synthesized = false;
 
     // Verify no bitfield truncation.
     assert(Bits.AbstractFunctionDecl.NumParameterLists == NumParameterLists);
@@ -5253,6 +5258,14 @@
     return Bits.AbstractFunctionDecl.NeedsNewVTableEntry;
   }
 
+  bool isSynthesized() const {
+    return Bits.AbstractFunctionDecl.Synthesized;
+  }
+
+  void setSynthesized(bool value = true) {
+    Bits.AbstractFunctionDecl.Synthesized = value;
+  }
+
 private:
   void computeNeedsNewVTableEntry();
 
diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h
index 389984d..21fecc9 100644
--- a/include/swift/AST/DiagnosticEngine.h
+++ b/include/swift/AST/DiagnosticEngine.h
@@ -30,6 +30,7 @@
   class ValueDecl;
   
   enum class PatternKind : uint8_t;
+  enum class ReferenceOwnership : uint8_t;
   enum class StaticSpellingKind : uint8_t;
   enum class DescriptiveDeclKind : uint8_t;
   enum DeclAttrKind : unsigned;
@@ -76,6 +77,7 @@
     Type,
     TypeRepr,
     PatternKind,
+    ReferenceOwnership,
     StaticSpellingKind,
     DescriptiveDeclKind,
     DeclAttribute,
@@ -103,6 +105,7 @@
       Type TypeVal;
       TypeRepr *TyR;
       PatternKind PatternKindVal;
+      ReferenceOwnership ReferenceOwnershipVal;
       StaticSpellingKind StaticSpellingKindVal;
       DescriptiveDeclKind DescriptiveDeclKindVal;
       const DeclAttribute *DeclAttributeVal;
@@ -162,6 +165,10 @@
     DiagnosticArgument(PatternKind K)
         : Kind(DiagnosticArgumentKind::PatternKind), PatternKindVal(K) {}
 
+    DiagnosticArgument(ReferenceOwnership RO)
+        : Kind(DiagnosticArgumentKind::ReferenceOwnership),
+          ReferenceOwnershipVal(RO) {}
+
     DiagnosticArgument(StaticSpellingKind SSK)
         : Kind(DiagnosticArgumentKind::StaticSpellingKind),
           StaticSpellingKindVal(SSK) {}
@@ -237,6 +244,11 @@
       return PatternKindVal;
     }
 
+    ReferenceOwnership getAsReferenceOwnership() const {
+      assert(Kind == DiagnosticArgumentKind::ReferenceOwnership);
+      return ReferenceOwnershipVal;
+    }
+
     StaticSpellingKind getAsStaticSpellingKind() const {
       assert(Kind == DiagnosticArgumentKind::StaticSpellingKind);
       return StaticSpellingKindVal;
diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def
index 1f3624d..6486e4a 100644
--- a/include/swift/AST/DiagnosticsDriver.def
+++ b/include/swift/AST/DiagnosticsDriver.def
@@ -126,6 +126,9 @@
 ERROR(error_conflicting_options, none,
       "conflicting options '%0' and '%1'",
       (StringRef, StringRef))
+ERROR(error_option_not_supported, none,
+      "'%0' is not supported with '%1'",
+      (StringRef, StringRef))
 
 WARNING(warn_ignore_embed_bitcode, none,
         "ignoring -embed-bitcode since no object file is being generated", ())
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 897b265..9c6c449 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1960,9 +1960,8 @@
       "of overridden %select{method|initializer}0 %2",
       (bool, DeclName, DeclName))
 ERROR(override_ownership_mismatch,none,
-      "cannot override %select{strong|weak|unowned|unowned(unsafe)}0 property "
-      "with %select{strong|weak|unowned|unowned(unsafe)}1 property",
-      (/*ReferenceOwnership*/unsigned, /*ReferenceOwnership*/unsigned))
+      "cannot override %0 property with %1 property",
+      (ReferenceOwnership, ReferenceOwnership))
 ERROR(override_dynamic_self_mismatch,none,
       "cannot override a Self return type with a non-Self return type",
       ())
@@ -2008,10 +2007,18 @@
 ERROR(override_mutable_covariant_subscript,none,
       "cannot override mutable subscript of type %0 with covariant type %1",
       (Type, Type))
-ERROR(decl_already_final,none,
+ERROR(static_decl_already_final,none,
       "static declarations are already final", ())
 ERROR(open_decl_cannot_be_final,none,
       "%0 cannot be declared both 'final' and 'open'", (DescriptiveDeclKind))
+ERROR(implicitly_final_cannot_be_open,none,
+      "%select{'let' properties|members of 'final' classes|"
+      "static declarations}0 are implicitly 'final'; use 'public' instead of "
+      "'open'", (unsigned))
+WARNING(implicitly_final_cannot_be_open_swift4,none,
+        "%select{'let' properties|members of 'final' classes|"
+        "static declarations}0 are implicitly 'final'; use 'public' instead of "
+        "'open'", (unsigned))
 
 WARNING(override_swift3_objc_inference,none,
         "override of %0 %1 from extension of %2 depends on deprecated "
@@ -2739,6 +2746,15 @@
      "use '%0' to reference the %1 in module %2",
      (StringRef, DescriptiveDeclKind, Identifier))
 
+WARNING(warn_deprecated_conditional_conformance_outer_access,none,
+        "use of %0 as reference to %1 in %2 %3 will change in future versions of Swift to reference %4 in %5 %6 "
+        "which comes via a conditional conformance",
+        (DeclName, DescriptiveDeclKind, DescriptiveDeclKind, DeclName,
+        DescriptiveDeclKind, DescriptiveDeclKind, DeclName))
+NOTE(fix_deprecated_conditional_conformance_outer_access,none,
+     "use '%0' to continue to reference the %1",
+     (StringRef, DescriptiveDeclKind, Identifier))
+
 ERROR(unsupported_special_decl_ref, none,
       "referencing %0 as a function value is not implemented", (Identifier))
 
@@ -3061,10 +3077,9 @@
      "add an explicit type annotation to silence this warning", ())
 
 WARNING(unowned_assignment_immediate_deallocation,none,
-        "instance will be immediately deallocated as %0 is "
-        "%select{a 'strong'|a 'weak'|an 'unowned'|an 'unowned'}1 "
-        "%select{variable|property}2",
-        (Identifier, /*Ownership*/unsigned, /*Is Property*/unsigned))
+        "instance will be immediately deallocated because "
+        "%select{variable|property}2 %0 is %1",
+        (Identifier, ReferenceOwnership, /*Is Property*/unsigned))
 NOTE(unowned_assignment_requires_strong,none,
      "a strong reference is required to prevent the instance from being "
      "deallocated", ())
@@ -3222,24 +3237,25 @@
 
 // Ownership
 ERROR(invalid_ownership_type,none,
-      "'%select{strong|weak|unowned|unowned}0' may only be applied to "
-      "class and class-bound protocol types, not %1",
-      (/*ReferenceOwnership*/unsigned, Type))
+      "%0 may only be applied to class and class-bound protocol types, not %1",
+      (ReferenceOwnership, Type))
 ERROR(invalid_ownership_protocol_type,none,
-      "'%select{strong|weak|unowned|unowned}0' must not be applied to "
-      "non-class-bound %1; consider adding a protocol conformance that has a class bound",
-      (/*ReferenceOwnership*/unsigned, Type))
+      "%0 must not be applied to non-class-bound %1; "
+      "consider adding a protocol conformance that has a class bound",
+      (ReferenceOwnership, Type))
+ERROR(invalid_ownership_with_optional,none,
+      "%0 variable cannot have optional type", (ReferenceOwnership))
 ERROR(invalid_weak_ownership_not_optional,none,
       "'weak' variable should have optional type %0", (Type))
 ERROR(invalid_weak_let,none,
       "'weak' must be a mutable variable, because it may change at runtime", ())
 ERROR(ownership_invalid_in_protocols,none,
-      "'%select{strong|weak|unowned|unowned}0' cannot be applied to a property declaration in a protocol",
-      (/*ReferenceOwnership*/unsigned))
+      "%0 cannot be applied to a property declaration in a protocol",
+      (ReferenceOwnership))
 WARNING(ownership_invalid_in_protocols_compat_warning,none,
-      "'%select{strong|weak|unowned|unowned}0' should not be applied to a property declaration "
+      "%0 should not be applied to a property declaration "
       "in a protocol and will be disallowed in future versions",
-      (/*ReferenceOwnership*/unsigned))
+      (ReferenceOwnership))
 
 // required
 ERROR(required_initializer_nonclass,none,
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index c6be668..c879733 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -2353,11 +2353,16 @@
   SourceLoc DotLoc;
   DeclNameLoc NameLoc;
   DeclName Name;
+  ArrayRef<ValueDecl *> OuterAlternatives;
+
 public:
-  UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, DeclName name,
-                    DeclNameLoc nameloc, bool Implicit)
-    : Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc),
-      NameLoc(nameloc), Name(name) {
+  UnresolvedDotExpr(
+      Expr *subexpr, SourceLoc dotloc, DeclName name, DeclNameLoc nameloc,
+      bool Implicit,
+      ArrayRef<ValueDecl *> outerAlternatives = ArrayRef<ValueDecl *>())
+      : Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr),
+        DotLoc(dotloc), NameLoc(nameloc), Name(name),
+        OuterAlternatives(outerAlternatives) {
     Bits.UnresolvedDotExpr.FunctionRefKind =
       static_cast<unsigned>(NameLoc.isCompound() ? FunctionRefKind::Compound
                                                  : FunctionRefKind::Unapplied);
@@ -2380,6 +2385,10 @@
   DeclName getName() const { return Name; }
   DeclNameLoc getNameLoc() const { return NameLoc; }
 
+  ArrayRef<ValueDecl *> getOuterAlternatives() const {
+    return OuterAlternatives;
+  }
+
   /// Retrieve the kind of function reference.
   FunctionRefKind getFunctionRefKind() const {
     return static_cast<FunctionRefKind>(Bits.UnresolvedDotExpr.FunctionRefKind);
diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h
index 51b6b46..96e100e 100644
--- a/include/swift/AST/NameLookup.h
+++ b/include/swift/AST/NameLookup.h
@@ -86,19 +86,37 @@
 /// unqualified lookup (i.e. lookup for a plain identifier).
 class UnqualifiedLookup {
 public:
+  enum class Flags {
+    /// This lookup is known to not affect downstream files.
+    KnownPrivate = 0x01,
+    /// This lookup should only return types.
+    TypeLookup = 0x02,
+    /// This lookup should consider declarations within protocols to which the
+    /// context type conforms.
+    AllowProtocolMembers = 0x04,
+    /// Don't check access when doing lookup into a type.
+    IgnoreAccessControl = 0x08,
+    /// This lookup should include results from outside the innermost scope with
+    /// results.
+    IncludeOuterResults = 0x10,
+  };
+  using Options = OptionSet<Flags>;
+
   /// \brief Lookup an unqualified identifier \p Name in the context.
   ///
   /// If the current DeclContext is nested in a function body, the SourceLoc
   /// is used to determine which declarations in that body are visible.
-  UnqualifiedLookup(DeclName Name, DeclContext *DC,
-                    LazyResolver *TypeResolver,
-                    bool IsKnownPrivate = false,
-                    SourceLoc Loc = SourceLoc(),
-                    bool IsTypeLookup = false,
-                    bool AllowProtocolMembers = false,
-                    bool IgnoreAccessControl = false);
+  UnqualifiedLookup(DeclName Name, DeclContext *DC, LazyResolver *TypeResolver,
+                    SourceLoc Loc = SourceLoc(), Options options = Options());
 
   SmallVector<LookupResultEntry, 4> Results;
+  /// \brief The index of the first result that isn't from the innermost scope
+  /// with results.
+  ///
+  /// That is, \c makeArrayRef(Results).take_front(IndexOfFirstOuterResults)
+  /// will be Results from the innermost scope that had results, and the
+  /// remaining elements of Results will be from parent scopes of this one.
+  size_t IndexOfFirstOuterResult;
 
   /// \brief Return true if anything was found by the name lookup.
   bool isSuccess() const { return !Results.empty(); }
@@ -107,6 +125,11 @@
   TypeDecl *getSingleTypeResult();
 };
 
+inline UnqualifiedLookup::Options operator|(UnqualifiedLookup::Flags flag1,
+                                            UnqualifiedLookup::Flags flag2) {
+  return UnqualifiedLookup::Options(flag1) | flag2;
+}
+
 /// Describes the reason why a certain declaration is visible.
 enum class DeclVisibilityKind {
   /// Declaration is a local variable or type.
diff --git a/include/swift/AST/Ownership.h b/include/swift/AST/Ownership.h
index ac6599e..d797611 100644
--- a/include/swift/AST/Ownership.h
+++ b/include/swift/AST/Ownership.h
@@ -20,6 +20,7 @@
 #define SWIFT_OWNERSHIP_H
 
 #include "swift/Basic/InlineBitfield.h"
+#include "llvm/Support/raw_ostream.h"
 #include <stdint.h>
 
 namespace swift {
@@ -46,6 +47,9 @@
 enum : unsigned { NumReferenceOwnershipBits =
   countBitsUsed(static_cast<unsigned>(ReferenceOwnership::Last_Kind)) };
 
+/// Diagnostic printing of \c StaticSpellingKind.
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceOwnership RO);
+
 /// Different kinds of value ownership supported by Swift.
 enum class ValueOwnership : uint8_t {
   /// \brief the context-dependent default ownership (sometimes shared,
diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h
index a8eccf4..4b7a77d 100644
--- a/include/swift/AST/Stmt.h
+++ b/include/swift/AST/Stmt.h
@@ -1023,7 +1023,7 @@
   SourceLoc Loc;
   Identifier TargetName; // Named target statement, if specified in the source.
   SourceLoc TargetLoc;
-  LabeledStmt *Target;  // Target stmt, wired up by Sema.
+  LabeledStmt *Target = nullptr;  // Target stmt, wired up by Sema.
 public:
   BreakStmt(SourceLoc Loc, Identifier TargetName, SourceLoc TargetLoc,
             Optional<bool> implicit = None)
@@ -1058,7 +1058,7 @@
   SourceLoc Loc;
   Identifier TargetName; // Named target statement, if specified in the source.
   SourceLoc TargetLoc;
-  LabeledStmt *Target;
+  LabeledStmt *Target = nullptr;
 
 public:
   ContinueStmt(SourceLoc Loc, Identifier TargetName, SourceLoc TargetLoc,
diff --git a/include/swift/AST/TypeMatcher.h b/include/swift/AST/TypeMatcher.h
index 34cedc0..8f092c5 100644
--- a/include/swift/AST/TypeMatcher.h
+++ b/include/swift/AST/TypeMatcher.h
@@ -141,43 +141,25 @@
       return mismatch(firstTuple.getPointer(), secondType, sugaredFirstType);
     }
 
-    template<typename FirstReferenceStorageType>
-    bool handleReferenceStorageType(
-           CanTypeWrapper<FirstReferenceStorageType> firstStorage,
-           Type secondType, Type sugaredFirstType) {
-      if (auto secondStorage = secondType->getAs<FirstReferenceStorageType>()) {
-        return this->visit(
-                 firstStorage.getReferentType(),
-                 secondStorage->getReferentType(),
-                 sugaredFirstType->getAs<FirstReferenceStorageType>()
-                   ->getReferentType());
+    bool visitReferenceStorageType(CanReferenceStorageType firstStorage,
+                                   Type secondType, Type sugaredFirstType) {
+      auto _secondStorage = secondType->getCanonicalType();
+      if (firstStorage->getKind() == _secondStorage->getKind()) {
+        auto secondStorage = cast<ReferenceStorageType>(_secondStorage);
+        return this->visit(firstStorage.getReferentType(),
+                           secondStorage->getReferentType(),
+                           sugaredFirstType->castTo<ReferenceStorageType>()
+                             ->getReferentType());
       }
 
       return mismatch(firstStorage.getPointer(), secondType, sugaredFirstType);
     }
 
-    bool visitUnownedStorageType(CanUnownedStorageType firstStorage,
-                                 Type secondType, Type sugaredFirstType) {
-      return handleReferenceStorageType(firstStorage, secondType,
-                                        sugaredFirstType);
-    }
-
-    bool visitUnmanagedStorageType(CanUnmanagedStorageType firstStorage,
-                                   Type secondType, Type sugaredFirstType) {
-      return handleReferenceStorageType(firstStorage, secondType,
-                                        sugaredFirstType);
-    }
-
-    bool visitWeakStorageType(CanWeakStorageType firstStorage,
-                              Type secondType, Type sugaredFirstType) {
-      return handleReferenceStorageType(firstStorage, secondType,
-                                        sugaredFirstType);
-    }
-
-    template<typename FirstNominalType>
-    bool handleNominalType(CanTypeWrapper<FirstNominalType> firstNominal,
-                           Type secondType, Type sugaredFirstType) {
-      if (auto secondNominal = secondType->getAs<FirstNominalType>()) {
+    bool visitNominalType(CanNominalType firstNominal,
+                          Type secondType, Type sugaredFirstType) {
+      auto _secondNominal = secondType->getCanonicalType();
+      if (firstNominal->getKind() == _secondNominal->getKind()) {
+        auto secondNominal = cast<NominalType>(_secondNominal);
         if (firstNominal->getDecl() != secondNominal->getDecl())
           return mismatch(firstNominal.getPointer(), secondNominal,
                           sugaredFirstType);
@@ -185,7 +167,7 @@
         if (firstNominal.getParent())
           return this->visit(firstNominal.getParent(),
                              secondNominal->getParent(),
-                             sugaredFirstType->castTo<FirstNominalType>()
+                             sugaredFirstType->castTo<NominalType>()
                                ->getParent());
 
         return true;
@@ -194,52 +176,20 @@
       return mismatch(firstNominal.getPointer(), secondType, sugaredFirstType);
     }
 
-    bool visitEnumType(CanEnumType firstEnum, Type secondType,
-                       Type sugaredFirstType) {
-      return handleNominalType(firstEnum, secondType, sugaredFirstType);
-    }
-
-    bool visitStructType(CanStructType firstStruct, Type secondType,
-                         Type sugaredFirstType) {
-      return handleNominalType(firstStruct, secondType, sugaredFirstType);
-    }
-
-    bool visitClassType(CanClassType firstClass, Type secondType,
-                        Type sugaredFirstType) {
-      return handleNominalType(firstClass, secondType, sugaredFirstType);
-    }
-
-    bool visitProtocolType(CanProtocolType firstProtocol, Type secondType,
-                           Type sugaredFirstType) {
-      return handleNominalType(firstProtocol, secondType, sugaredFirstType);
-    }
-
-    template<typename FirstMetatypeType>
-    bool handleAnyMetatypeType(CanTypeWrapper<FirstMetatypeType> firstMeta,
-                               Type secondType, Type sugaredFirstType) {
-      if (auto secondMeta = secondType->getAs<FirstMetatypeType>()) {
-        if (firstMeta->getKind() != secondMeta->getKind())
-          return mismatch(firstMeta.getPointer(), secondMeta, sugaredFirstType);
-
+    bool visitAnyMetatypeType(CanAnyMetatypeType firstMeta,
+                              Type secondType, Type sugaredFirstType) {
+      auto _secondMeta = secondType->getCanonicalType();
+      if (firstMeta->getKind() == _secondMeta->getKind()) {
+        auto secondMeta = cast<AnyMetatypeType>(_secondMeta);
         return this->visit(firstMeta.getInstanceType(),
                            secondMeta->getInstanceType(),
-                           sugaredFirstType->castTo<FirstMetatypeType>()
+                           sugaredFirstType->castTo<AnyMetatypeType>()
                              ->getInstanceType());
       }
 
       return mismatch(firstMeta.getPointer(), secondType, sugaredFirstType);
     }
 
-    bool visitMetatypeType(CanMetatypeType firstMeta, Type secondType,
-                           Type sugaredFirstType) {
-      return handleAnyMetatypeType(firstMeta, secondType, sugaredFirstType);
-    }
-
-    bool visitExistentialMetatypeType(CanExistentialMetatypeType firstMeta,
-                                      Type secondType, Type sugaredFirstType) {
-      return handleAnyMetatypeType(firstMeta, secondType, sugaredFirstType);
-    }
-
     TRIVIAL_CASE(ModuleType)
     TRIVIAL_CASE(DynamicSelfType)
     TRIVIAL_CASE(ArchetypeType)
@@ -332,15 +282,15 @@
       return mismatch(firstUBGT.getPointer(), secondType, sugaredFirstType);
     }
 
-    template<typename FirstBoundGenericType>
-    bool handleBoundGenericType(CanTypeWrapper<FirstBoundGenericType> firstBGT,
-                                Type secondType, Type sugaredFirstType) {
-      if (auto secondBGT = secondType->getAs<FirstBoundGenericType>()) {
+    bool visitBoundGenericType(CanBoundGenericType firstBGT,
+                               Type secondType, Type sugaredFirstType) {
+      auto _secondBGT = secondType->getCanonicalType();
+      if (firstBGT->getKind() == _secondBGT->getKind()) {
+        auto secondBGT = cast<BoundGenericType>(_secondBGT);
         if (firstBGT->getDecl() != secondBGT->getDecl())
           return mismatch(firstBGT.getPointer(), secondBGT, sugaredFirstType);
 
-        auto sugaredFirstBGT
-          = sugaredFirstType->castTo<FirstBoundGenericType>();
+        auto sugaredFirstBGT = sugaredFirstType->castTo<BoundGenericType>();
         if (firstBGT->getParent() &&
             !this->visit(firstBGT.getParent(), secondBGT->getParent(),
                          sugaredFirstBGT->getParent()))
@@ -360,21 +310,6 @@
       return mismatch(firstBGT.getPointer(), secondType, sugaredFirstType);
     }
 
-    bool visitBoundGenericClassType(CanBoundGenericClassType firstBGT,
-                                    Type secondType, Type sugaredFirstType) {
-      return handleBoundGenericType(firstBGT, secondType, sugaredFirstType);
-    }
-
-    bool visitBoundGenericEnumType(CanBoundGenericEnumType firstBGT,
-                                   Type secondType, Type sugaredFirstType) {
-      return handleBoundGenericType(firstBGT, secondType, sugaredFirstType);
-    }
-
-    bool visitBoundGenericStructType(CanBoundGenericStructType firstBGT,
-                                     Type secondType, Type sugaredFirstType) {
-      return handleBoundGenericType(firstBGT, secondType, sugaredFirstType);
-    }
-
     TRIVIAL_CASE(TypeVariableType)
 
 #undef TRIVIAL_CASE
diff --git a/include/swift/AST/Witness.h b/include/swift/AST/Witness.h
index 02b4a1d..8736cce 100644
--- a/include/swift/AST/Witness.h
+++ b/include/swift/AST/Witness.h
@@ -150,9 +150,6 @@
   /// Determines whether there is a witness at all.
   explicit operator bool() const { return !storage.isNull(); }
 
-  /// Determine whether this witness requires any substitutions.
-  bool requiresSubstitution() const { return storage.is<StoredWitness *>(); }
-
   /// Retrieve the substitutions required to use this witness from the
   /// synthetic environment.
   ///
@@ -164,15 +161,17 @@
 
   /// Retrieve the synthetic generic environment.
   GenericEnvironment *getSyntheticEnvironment() const {
-    assert(requiresSubstitution() && "No substitutions required for witness");
-    return storage.get<StoredWitness *>()->syntheticEnvironment;
+    if (auto *storedWitness = storage.dyn_cast<StoredWitness *>())
+      return storedWitness->syntheticEnvironment;
+    return nullptr;
   }
 
   /// Retrieve the substitution map that maps the interface types of the
   /// requirement to the interface types of the synthetic environment.
   SubstitutionList getRequirementToSyntheticSubs() const {
-    assert(requiresSubstitution() && "No substitutions required for witness");
-    return storage.get<StoredWitness *>()->reqToSyntheticEnvSubs;
+    if (auto *storedWitness = storage.dyn_cast<StoredWitness *>())
+      return storedWitness->reqToSyntheticEnvSubs;
+    return {};
   }
 
   LLVM_ATTRIBUTE_DEPRECATED(
diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h
index c4673e4..83a7971 100644
--- a/include/swift/Demangling/Demangle.h
+++ b/include/swift/Demangling/Demangle.h
@@ -466,6 +466,14 @@
 /// This should always round-trip perfectly with demangleSymbolAsNode.
 std::string mangleNode(const NodePointer &root);
 
+using SymbolicResolver = llvm::function_ref<Demangle::NodePointer (const void *)>;
+
+/// \brief Remangle a demangled parse tree, using a callback to resolve
+/// symbolic references.
+///
+/// This should always round-trip perfectly with demangleSymbolAsNode.
+std::string mangleNode(const NodePointer &root, SymbolicResolver resolver);
+
 /// Remangle in the old mangling scheme.
 ///
 /// This is only used for objc-runtime names and should be removed as soon as
diff --git a/include/swift/IDE/APIDigesterData.h b/include/swift/IDE/APIDigesterData.h
index ec6c3ea..abacb15 100644
--- a/include/swift/IDE/APIDigesterData.h
+++ b/include/swift/IDE/APIDigesterData.h
@@ -334,6 +334,21 @@
   }
 };
 
+struct NameCorrectionInfo {
+  StringRef OriginalName;
+  StringRef CorrectedName;
+  StringRef ModuleName;
+  NameCorrectionInfo(StringRef OriginalName, StringRef CorrectedName,
+    StringRef ModuleName): OriginalName(OriginalName),
+    CorrectedName(CorrectedName), ModuleName(ModuleName) {}
+  bool operator<(NameCorrectionInfo Other) const {
+    if (ModuleName != Other.ModuleName)
+      return ModuleName.compare(Other.ModuleName) < 0;
+    else
+      return OriginalName.compare(Other.OriginalName) < 0;
+  }
+};
+
 /// APIDiffItem store is the interface that migrator should communicates with;
 /// Given a key, usually the usr of the system entity under migration, the store
 /// should return a slice of related changes in the same format of
@@ -343,6 +358,7 @@
   struct Implementation;
   Implementation &Impl;
   static void serialize(llvm::raw_ostream &os, ArrayRef<APIDiffItem*> Items);
+  static void serialize(llvm::raw_ostream &os, ArrayRef<NameCorrectionInfo> Items);
   APIDiffItemStore(const APIDiffItemStore& that) = delete;
   APIDiffItemStore();
   ~APIDiffItemStore();
diff --git a/include/swift/IDE/DigesterEnums.def b/include/swift/IDE/DigesterEnums.def
index 20efd72..906e3c1 100644
--- a/include/swift/IDE/DigesterEnums.def
+++ b/include/swift/IDE/DigesterEnums.def
@@ -81,7 +81,12 @@
 NODE_ANNOTATION_CHANGE_KIND(OptionalArrayMemberUpdate)
 NODE_ANNOTATION_CHANGE_KIND(SimpleStringRepresentableUpdate)
 NODE_ANNOTATION_CHANGE_KIND(SimpleOptionalStringRepresentableUpdate)
-
+NODE_ANNOTATION_CHANGE_KIND(RevertDictionaryKeyUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertOptionalDictionaryKeyUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertArrayMemberUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertOptionalArrayMemberUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertSimpleStringRepresentableUpdate)
+NODE_ANNOTATION_CHANGE_KIND(RevertSimpleOptionalStringRepresentableUpdate)
 
 DECL_ATTR(deprecated)
 DECL_ATTR(fixedLayout)
diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h
index a6a36bc..792eb85 100644
--- a/include/swift/Runtime/Debug.h
+++ b/include/swift/Runtime/Debug.h
@@ -46,19 +46,19 @@
 }
 
 LLVM_ATTRIBUTE_ALWAYS_INLINE
-static void CRSetCrashLogMessage(const char *message) {
+static inline void CRSetCrashLogMessage(const char *message) {
   gCRAnnotations.message = reinterpret_cast<uint64_t>(message);
 }
 
 LLVM_ATTRIBUTE_ALWAYS_INLINE
-static const char *CRGetCrashLogMessage() {
+static inline const char *CRGetCrashLogMessage() {
   return reinterpret_cast<const char *>(gCRAnnotations.message);
 }
 
 #else
 
 LLVM_ATTRIBUTE_ALWAYS_INLINE
-static void CRSetCrashLogMessage(const char *) {}
+static inline void CRSetCrashLogMessage(const char *) {}
 
 #endif
 
diff --git a/include/swift/Runtime/Exclusivity.h b/include/swift/Runtime/Exclusivity.h
index aa75a46..d3a4ffc 100644
--- a/include/swift/Runtime/Exclusivity.h
+++ b/include/swift/Runtime/Exclusivity.h
@@ -58,6 +58,19 @@
 SWIFT_RUNTIME_EXPORT
 bool _swift_disableExclusivityChecking;
 
+#ifndef NDEBUG
+
+/// Dump all accesses currently tracked by the runtime.
+///
+/// This is a debug routine that is intended to be used from the debugger and is
+/// compiled out when asserts are disabled. The intention is that it allows one
+/// to dump the access state to easily see if/when exclusivity violations will
+/// happen. This eases debugging.
+SWIFT_RUNTIME_EXPORT
+void swift_dumpTrackedAccesses();
+
+#endif
+
 } // end namespace swift
 
 #endif
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 3e9df39..f55c5f8 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -827,7 +827,7 @@
          ATTRS(NoUnwind))
 
 // MetadataResponse swift_checkMetadataState(MetadataRequest request,
-//                                           cosnt Metadata *type);
+//                                           const Metadata *type);
 FUNCTION(CheckMetadataState, swift_checkMetadataState, SwiftCC,
          RETURNS(TypeMetadataResponseTy),
          ARGS(SizeTy, TypeMetadataPtrTy),
diff --git a/include/swift/SIL/SILVTableVisitor.h b/include/swift/SIL/SILVTableVisitor.h
index abf4f24..9549cfa 100644
--- a/include/swift/SIL/SILVTableVisitor.h
+++ b/include/swift/SIL/SILVTableVisitor.h
@@ -18,11 +18,55 @@
 #ifndef SWIFT_SIL_SILVTABLEVISITOR_H
 #define SWIFT_SIL_SILVTABLEVISITOR_H
 
+#include <string>
+
 #include "swift/AST/Decl.h"
 #include "swift/AST/Types.h"
+#include "swift/AST/ASTMangler.h"
 
 namespace swift {
 
+// Utility class for deterministically ordering vtable entries for
+// synthesized methods.
+struct SortedFuncList {
+  using Entry = std::pair<std::string, AbstractFunctionDecl *>;
+  SmallVector<Entry, 2> elts;
+  bool sorted = false;
+
+  void add(AbstractFunctionDecl *afd) {
+    Mangle::ASTMangler mangler;
+    std::string mangledName;
+    if (auto *cd = dyn_cast<ConstructorDecl>(afd))
+      mangledName = mangler.mangleConstructorEntity(cd, 0, 0);
+    else
+      mangledName = mangler.mangleEntity(afd, 0);
+
+    elts.push_back(std::make_pair(mangledName, afd));
+  }
+
+  bool empty() { return elts.empty(); }
+
+  void sort() {
+    assert(!sorted);
+    sorted = true;
+    std::sort(elts.begin(),
+              elts.end(),
+              [](const Entry &lhs, const Entry &rhs) -> bool {
+                return lhs.first < rhs.first;
+              });
+  }
+
+  decltype(elts)::const_iterator begin() const {
+    assert(sorted);
+    return elts.begin();
+  }
+
+  decltype(elts)::const_iterator end() const {
+    assert(sorted);
+    return elts.end();
+  }
+};
+
 /// A CRTP class for visiting virtually-dispatched methods of a class.
 ///
 /// You must override these two methods in your subclass:
@@ -76,19 +120,47 @@
     }
   }
 
+  void maybeAddMember(Decl *member) {
+    if (auto *fd = dyn_cast<FuncDecl>(member))
+      maybeAddMethod(fd);
+    else if (auto *cd = dyn_cast<ConstructorDecl>(member))
+      maybeAddConstructor(cd);
+    else if (auto *placeholder = dyn_cast<MissingMemberDecl>(member))
+      asDerived().addPlaceholder(placeholder);
+  }
+
 protected:
   void addVTableEntries(ClassDecl *theClass) {
     // Imported classes do not have a vtable.
     if (!theClass->hasKnownSwiftImplementation())
       return;
 
+    // Note that while vtable order is not ABI, we still want it to be
+    // consistent between translation units.
+    //
+    // So, sort synthesized members by their mangled name, since they
+    // are added lazily during type checking, with the remaining ones
+    // forced at the end.
+    SortedFuncList synthesizedMembers;
+
     for (auto member : theClass->getMembers()) {
-      if (auto *fd = dyn_cast<FuncDecl>(member))
-        maybeAddMethod(fd);
-      else if (auto *cd = dyn_cast<ConstructorDecl>(member))
-        maybeAddConstructor(cd);
-      else if (auto *placeholder = dyn_cast<MissingMemberDecl>(member))
-        asDerived().addPlaceholder(placeholder);
+      if (auto *afd = dyn_cast<AbstractFunctionDecl>(member)) {
+        if (afd->isSynthesized()) {
+          synthesizedMembers.add(afd);
+          continue;
+        }
+      }
+
+      maybeAddMember(member);
+    }
+
+    if (synthesizedMembers.empty())
+      return;
+
+    synthesizedMembers.sort();
+
+    for (const auto &pair : synthesizedMembers) {
+      maybeAddMember(pair.second);
     }
   }
 };
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 15e3dc3..d35b753 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
 /// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 408; // Last change: begin_access [nontracking]
+const uint16_t VERSION_MINOR = 409; // Last change: standalone requirement subs
 
 using DeclIDField = BCFixed<31>;
 
diff --git a/include/swift/Strings.h b/include/swift/Strings.h
index 4d02d9d..38a687a 100644
--- a/include/swift/Strings.h
+++ b/include/swift/Strings.h
@@ -13,6 +13,9 @@
 #ifndef SWIFT_STRINGS_H
 #define SWIFT_STRINGS_H
 
+#include "swift/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
 namespace swift {
 
 /// The extension for serialized modules.
@@ -89,6 +92,10 @@
 constexpr static const char BUILTIN_TYPE_NAME_SILTOKEN[] = "Builtin.SILToken";
 /// The name of the Builtin type for Word
 constexpr static const char BUILTIN_TYPE_NAME_WORD[] = "Builtin.Word";
+
+constexpr static StringLiteral OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY =
+    "optimize.sil.preserve_exclusivity";
+
 } // end namespace swift
 
 #endif // SWIFT_STRINGS_H
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d3c0a97..ea83a0c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1430,8 +1430,9 @@
 static void recordKnownProtocol(ModuleDecl *Stdlib, StringRef Name,
                                 KnownProtocolKind Kind) {
   Identifier ID = Stdlib->getASTContext().getIdentifier(Name);
-  UnqualifiedLookup Lookup(ID, Stdlib, nullptr, /*IsKnownPrivate=*/true,
-                           SourceLoc(), /*IsTypeLookup=*/true);
+  UnqualifiedLookup Lookup(ID, Stdlib, nullptr, SourceLoc(),
+                           UnqualifiedLookup::Flags::KnownPrivate |
+                               UnqualifiedLookup::Flags::TypeLookup);
   if (auto Proto
         = dyn_cast_or_null<ProtocolDecl>(Lookup.getSingleTypeResult()))
     Proto->setKnownProtocolKind(Kind);
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 1e49ce1..735a631 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -2115,11 +2115,17 @@
 
     void verifyChecked(ValueDecl *VD) {
       if (VD->hasAccess()) {
-        if (VD->getFormalAccess() == AccessLevel::Open &&
-            !isa<ClassDecl>(VD) && !VD->isPotentiallyOverridable()) {
-          Out << "decl cannot be 'open'\n";
-          VD->dump(Out);
-          abort();
+        if (VD->getFormalAccess() == AccessLevel::Open) {
+          if (!isa<ClassDecl>(VD) && !VD->isPotentiallyOverridable()) {
+            Out << "decl cannot be 'open'\n";
+            VD->dump(Out);
+            abort();
+          }
+          if (VD->isFinal()) {
+            Out << "decl cannot be both 'open' and 'final'\n";
+            VD->dump(Out);
+            abort();
+          }
         }
       } else {
         if (!VD->getDeclContext()->isLocalContext() &&
@@ -2516,13 +2522,18 @@
           // Check the witness substitutions.
           const auto &witness = normal->getWitness(req, nullptr);
 
-          if (witness.requiresSubstitution()) {
-            GenericEnv.push_back({witness.getSyntheticEnvironment()});
-            for (const auto &sub : witness.getSubstitutions()) {
-              verifyChecked(sub.getReplacement());
-            }
+          if (auto *genericEnv = witness.getSyntheticEnvironment())
+            GenericEnv.push_back({genericEnv});
+
+          for (const auto &sub : witness.getRequirementToSyntheticSubs())
+            verifyChecked(sub.getReplacement());
+
+          for (const auto &sub : witness.getSubstitutions())
+            verifyChecked(sub.getReplacement());
+
+          if (auto *genericEnv = witness.getSyntheticEnvironment()) {
             assert(GenericEnv.back().storage.dyn_cast<GenericEnvironment *>()
-                     == witness.getSyntheticEnvironment());
+                     == genericEnv);
             GenericEnv.pop_back();
           }
 
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index ca75410..39b08df 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -296,6 +296,17 @@
   llvm_unreachable("bad StaticSpellingKind");
 }
 
+llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS,
+                                     ReferenceOwnership RO) {
+  switch (RO) {
+  case ReferenceOwnership::Strong: return OS << "'strong'";
+  case ReferenceOwnership::Weak: return OS << "'weak'";
+  case ReferenceOwnership::Unowned: return OS << "'unowned'";
+  case ReferenceOwnership::Unmanaged: return OS << "'unowned(unsafe)'";
+  }
+  llvm_unreachable("bad ReferenceOwnership kind");
+}
+
 DeclContext *Decl::getInnermostDeclContext() const {
   if (auto func = dyn_cast<AbstractFunctionDecl>(this))
     return const_cast<AbstractFunctionDecl*>(func);
diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp
index 95cd868..d0456a7 100644
--- a/lib/AST/DiagnosticEngine.cpp
+++ b/lib/AST/DiagnosticEngine.cpp
@@ -472,6 +472,19 @@
     assert(Modifier.empty() && "Improper modifier for PatternKind argument");
     Out << Arg.getAsPatternKind();
     break;
+
+  case DiagnosticArgumentKind::ReferenceOwnership:
+    if (Modifier == "select") {
+      formatSelectionArgument(ModifierArguments, Args,
+                              unsigned(Arg.getAsReferenceOwnership()),
+                              FormatOpts, Out);
+    } else {
+      assert(Modifier.empty() &&
+             "Improper modifier for ReferenceOwnership argument");
+      Out << Arg.getAsReferenceOwnership();
+    }
+    break;
+
   case DiagnosticArgumentKind::StaticSpellingKind:
     if (Modifier == "select") {
       formatSelectionArgument(ModifierArguments, Args,
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index 2643f71..f93caad 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -453,24 +453,42 @@
 }
 
 UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
-                                     LazyResolver *TypeResolver,
-                                     bool IsKnownNonCascading,
-                                     SourceLoc Loc, bool IsTypeLookup,
-                                     bool AllowProtocolMembers,
-                                     bool IgnoreAccessControl) {
+                                     LazyResolver *TypeResolver, SourceLoc Loc,
+                                     Options options)
+  : IndexOfFirstOuterResult(0)
+{
   ModuleDecl &M = *DC->getParentModule();
   ASTContext &Ctx = M.getASTContext();
   const SourceManager &SM = Ctx.SourceMgr;
   DebuggerClient *DebugClient = M.getDebugClient();
 
-  NamedDeclConsumer Consumer(Name, Results, IsTypeLookup);
+  auto isOriginallyTypeLookup = options.contains(Flags::TypeLookup);
+  NamedDeclConsumer Consumer(Name, Results, isOriginallyTypeLookup);
+
+  NLOptions baseNLOptions = NL_UnqualifiedDefault;
+  if (options.contains(Flags::AllowProtocolMembers))
+    baseNLOptions |= NL_ProtocolMembers;
+  if (isOriginallyTypeLookup)
+    baseNLOptions |= NL_OnlyTypes;
+  if (options.contains(Flags::IgnoreAccessControl))
+    baseNLOptions |= NL_IgnoreAccessControl;
 
   Optional<bool> isCascadingUse;
-  if (IsKnownNonCascading)
+  if (options.contains(Flags::KnownPrivate))
     isCascadingUse = false;
 
   SmallVector<LookupResultEntry, 4> UnavailableInnerResults;
 
+  auto shouldReturnBasedOnResults = [&](bool noMoreOuterResults = false) {
+    if (Results.empty())
+      return false;
+
+    if (IndexOfFirstOuterResult == 0)
+      IndexOfFirstOuterResult = Results.size();
+
+    return !options.contains(Flags::IncludeOuterResults) || noMoreOuterResults;
+  };
+
   if (Loc.isValid() &&
       DC->getParentSourceFile()->Kind != SourceFileKind::REPL &&
       Ctx.LangOpts.EnableASTScopeLookup) {
@@ -506,7 +524,7 @@
       }
 
       // If we found anything, we're done.
-      if (!Results.empty())
+      if (shouldReturnBasedOnResults())
         return;
 
       // When we are in the body of a method, get the 'self' declaration.
@@ -575,22 +593,17 @@
 
         if (lookupType->hasError()) continue;
 
+        NLOptions options = baseNLOptions;
         // Perform lookup into the type.
-        NLOptions options = NL_UnqualifiedDefault;
         if (isCascadingUse.getValue())
           options |= NL_KnownCascadingDependency;
         else
           options |= NL_KnownNonCascadingDependency;
 
-        if (AllowProtocolMembers)
-          options |= NL_ProtocolMembers;
-        if (IsTypeLookup)
-          options |= NL_OnlyTypes;
-        if (IgnoreAccessControl)
-          options |= NL_IgnoreAccessControl;
-
         SmallVector<ValueDecl *, 4> lookup;
         dc->lookupQualified(lookupType, Name, options, TypeResolver, lookup);
+
+        auto startIndex = Results.size();
         for (auto result : lookup) {
           auto *baseDC = dc;
           if (!isa<TypeDecl>(result) && selfDC) baseDC = selfDC;
@@ -607,15 +620,17 @@
                 .isUnavailableInSwiftVersion(effectiveVersion);
           };
 
-          // If all of the results we found are unavailable, keep looking.
-          if (std::all_of(Results.begin(), Results.end(),
-                          unavailableLookupResult)) {
-            UnavailableInnerResults.append(Results.begin(), Results.end());
-            Results.clear();
+          // If all of the results we just found are unavailable, keep looking.
+          auto begin = Results.begin() + startIndex;
+          if (std::all_of(begin, Results.end(), unavailableLookupResult)) {
+            UnavailableInnerResults.append(begin, Results.end());
+            Results.erase(begin, Results.end());
           } else {
             if (DebugClient)
               filterForDiscriminator(Results, DebugClient);
-            return;
+
+            if (shouldReturnBasedOnResults())
+              return;
           }
         }
 
@@ -652,7 +667,7 @@
           if (auto *selfParam = PBI->getImplicitSelfDecl()) {
             Consumer.foundDecl(selfParam,
                                DeclVisibilityKind::FunctionParameter);
-            if (!Results.empty())
+            if (shouldReturnBasedOnResults())
               return;
 
             DC = DC->getParent();
@@ -698,11 +713,11 @@
 
             namelookup::FindLocalVal localVal(SM, Loc, Consumer);
             localVal.visit(AFD->getBody());
-            if (!Results.empty())
+            if (shouldReturnBasedOnResults())
               return;
             for (auto *PL : AFD->getParameterLists())
               localVal.checkParameterList(PL);
-            if (!Results.empty())
+            if (shouldReturnBasedOnResults())
               return;
           }
           if (!isCascadingUse.hasValue() || isCascadingUse.getValue())
@@ -741,10 +756,10 @@
             if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
               namelookup::FindLocalVal localVal(SM, Loc, Consumer);
               localVal.visit(CE->getBody());
-              if (!Results.empty())
+              if (shouldReturnBasedOnResults())
                 return;
               localVal.checkParameterList(CE->getParameters());
-              if (!Results.empty())
+              if (shouldReturnBasedOnResults())
                 return;
             }
           }
@@ -781,27 +796,21 @@
           namelookup::FindLocalVal localVal(SM, Loc, Consumer);
           localVal.checkGenericParams(GenericParams);
 
-          if (!Results.empty())
+          if (shouldReturnBasedOnResults())
             return;
         }
 
         if (BaseDC && !ExtendedType->hasError()) {
-          NLOptions options = NL_UnqualifiedDefault;
+          NLOptions options = baseNLOptions;
           if (isCascadingUse.getValue())
             options |= NL_KnownCascadingDependency;
           else
             options |= NL_KnownNonCascadingDependency;
 
-          if (AllowProtocolMembers)
-            options |= NL_ProtocolMembers;
-          if (IsTypeLookup)
-            options |= NL_OnlyTypes;
-          if (IgnoreAccessControl)
-            options |= NL_IgnoreAccessControl;
-
           SmallVector<ValueDecl *, 4> Lookup;
           DC->lookupQualified(ExtendedType, Name, options, TypeResolver, Lookup);
           bool FoundAny = false;
+          auto startIndex = Results.size();
           for (auto Result : Lookup) {
             // In Swift 3 mode, unqualified lookup skips static methods when
             // performing lookup from instance context.
@@ -846,15 +855,16 @@
             };
 
             // If all of the results we found are unavailable, keep looking.
-            if (std::all_of(Results.begin(), Results.end(),
-                            unavailableLookupResult)) {
-              UnavailableInnerResults.append(Results.begin(), Results.end());
-              Results.clear();
-              FoundAny = false;
+            auto begin = Results.begin() + startIndex;
+            if (std::all_of(begin, Results.end(), unavailableLookupResult)) {
+              UnavailableInnerResults.append(begin, Results.end());
+              Results.erase(begin, Results.end());
             } else {
               if (DebugClient)
                 filterForDiscriminator(Results, DebugClient);
-              return;
+
+              if (shouldReturnBasedOnResults())
+                return;
             }
           }
         }
@@ -873,7 +883,7 @@
           namelookup::FindLocalVal localVal(SM, Loc, Consumer);
           localVal.checkGenericParams(dcGenericParams);
 
-          if (!Results.empty())
+          if (shouldReturnBasedOnResults())
             return;
 
           if (!isa<ExtensionDecl>(DC))
@@ -896,16 +906,16 @@
         // local types.
         namelookup::FindLocalVal localVal(SM, Loc, Consumer);
         localVal.checkSourceFile(*SF);
-        if (!Results.empty())
+        if (shouldReturnBasedOnResults())
           return;
       }
     }
   }
 
   // TODO: Does the debugger client care about compound names?
-  if (Name.isSimpleName()
-      && DebugClient && DebugClient->lookupOverrides(Name.getBaseName(), DC,
-                                                   Loc, IsTypeLookup, Results))
+  if (Name.isSimpleName() && DebugClient &&
+      DebugClient->lookupOverrides(Name.getBaseName(), DC, Loc,
+                                   isOriginallyTypeLookup, Results))
     return;
 
   recordLookupOfTopLevelName(DC, Name, isCascadingUse.getValue());
@@ -917,8 +927,8 @@
 
   using namespace namelookup;
   SmallVector<ValueDecl *, 8> CurModuleResults;
-  auto resolutionKind =
-    IsTypeLookup ? ResolutionKind::TypesOnly : ResolutionKind::Overloadable;
+  auto resolutionKind = isOriginallyTypeLookup ? ResolutionKind::TypesOnly
+                                               : ResolutionKind::Overloadable;
   lookupInModule(&M, {}, Name, CurModuleResults, NLKind::UnqualifiedLookup,
                  resolutionKind, TypeResolver, DC, extraImports);
 
@@ -930,20 +940,19 @@
 
   // Now add any names the DebugClient knows about to the lookup.
   if (Name.isSimpleName() && DebugClient)
-      DebugClient->lookupAdditions(Name.getBaseName(), DC, Loc, IsTypeLookup,
-                                   Results);
+    DebugClient->lookupAdditions(Name.getBaseName(), DC, Loc,
+                                 isOriginallyTypeLookup, Results);
 
   // If we've found something, we're done.
-  if (!Results.empty())
+  if (shouldReturnBasedOnResults(/*noMoreOuterResults=*/true))
     return;
 
   // If we still haven't found anything, but we do have some
   // declarations that are "unavailable in the current Swift", drop
   // those in.
-  if (!UnavailableInnerResults.empty()) {
-    Results = std::move(UnavailableInnerResults);
+  Results = std::move(UnavailableInnerResults);
+  if (shouldReturnBasedOnResults(/*noMoreOuterResults=*/true))
     return;
-  }
 
   if (!Name.isSimpleName())
     return;
@@ -951,7 +960,8 @@
   // Look for a module with the given name.
   if (Name.isSimpleName(M.getName())) {
     Results.push_back(LookupResultEntry(&M));
-    return;
+    if (shouldReturnBasedOnResults(/*noMoreOuterResults=*/true))
+      return;
   }
 
   ModuleDecl *desiredModule = Ctx.getLoadedModule(Name.getBaseIdentifier());
@@ -966,6 +976,8 @@
       return true;
     });
   }
+  // Make sure we've recorded the inner-result-boundary.
+  (void)shouldReturnBasedOnResults(/*noMoreOuterResults=*/true);
 }
 
 TypeDecl* UnqualifiedLookup::getSingleTypeResult() {
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 3325322..e2afc66 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -41,8 +41,13 @@
 Witness::Witness(ValueDecl *decl, SubstitutionList substitutions,
                  GenericEnvironment *syntheticEnv,
                  SubstitutionList reqToSynthesizedEnvSubs) {
-  auto &ctx = decl->getASTContext();
+  if (!syntheticEnv && substitutions.empty() &&
+      reqToSynthesizedEnvSubs.empty()) {
+    storage = decl;
+    return;
+  }
 
+  auto &ctx = decl->getASTContext();
   auto declRef = ConcreteDeclRef(ctx, decl, substitutions);
   auto storedMem = ctx.Allocate(sizeof(StoredWitness), alignof(StoredWitness));
   auto stored = new (storedMem)
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 08e2cbe..063f5f4 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -3412,7 +3412,7 @@
                                    genericMemberType->getExtInfo());
   }
 
-  auto type = memberType.subst(subs);
+  auto type = memberType.subst(subs, SubstFlags::UseErrorType);
 
   if (isa<AbstractFunctionDecl>(baseDecl)) {
     type = type->replaceSelfParameterType(this);
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 1913152..de67729 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -487,6 +487,7 @@
   auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
                                                 { paramRef }, { Identifier() });
   reinterpreted->setType(enumTy);
+  reinterpreted->setThrows(false);
 
   auto assign = new (C) AssignExpr(selfRef, SourceLoc(), reinterpreted,
                                    /*implicit*/ true);
@@ -573,6 +574,7 @@
   auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
                                                 { selfRef }, { Identifier() });
   reinterpreted->setType(rawTy);
+  reinterpreted->setThrows(false);
 
   auto ret = new (C) ReturnStmt(SourceLoc(), reinterpreted);
   auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
@@ -911,6 +913,7 @@
     auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
                                                   { selfRef },
                                                   { Identifier() });
+    reinterpreted->setThrows(false);
     auto ret = new (C) ReturnStmt(SourceLoc(), reinterpreted);
     auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
                                   /*implicit*/ true);
@@ -2639,6 +2642,7 @@
           AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
         structDecl->computeType();
         structDecl->setCheckedInheritanceClause();
+        structDecl->setAddedImplicitInitializers();
 
         auto options = getDefaultMakeStructRawValuedOptions();
         options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
@@ -2689,6 +2693,7 @@
           errorWrapper = new (C) StructDecl(loc, name, loc, None, nullptr, dc);
           errorWrapper->computeType();
           errorWrapper->setValidationStarted();
+          errorWrapper->setAddedImplicitInitializers();
           errorWrapper->setAccess(AccessLevel::Public);
           errorWrapper->getAttrs().add(
             new (Impl.SwiftContext) FixedLayoutAttr(/*IsImplicit*/true));
@@ -3124,6 +3129,7 @@
                                  Impl.importSourceLoc(decl->getLocation()),
                                  None, nullptr, dc);
       result->computeType();
+      result->setAddedImplicitInitializers();
       Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
 
       // FIXME: Figure out what to do with superclasses in C++. One possible
@@ -5300,6 +5306,7 @@
       decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
   structDecl->computeType();
   structDecl->setCheckedInheritanceClause();
+  structDecl->setAddedImplicitInitializers();
 
   // Import the type of the underlying storage
   auto storedUnderlyingType = Impl.importTypeIgnoreIUO(
@@ -5578,6 +5585,7 @@
       decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
   structDecl->computeType();
   structDecl->setCheckedInheritanceClause();
+  structDecl->setAddedImplicitInitializers();
 
   makeStructRawValued(Impl, structDecl, underlyingType,
                       {KnownProtocolKind::OptionSet});
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 28b771e..7b825e1 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -152,6 +152,9 @@
   // nested generics. This factory owns them.
   NodeFactory Factory;
 
+  // A callback for resolving symbolic references.
+  SymbolicResolver Resolver;
+
   StringRef getBufferStr() const { return Buffer.getStringRef(); }
 
   void resetBuffer(size_t toPos) { Buffer.resetSize(toPos); }
@@ -284,7 +287,8 @@
 #include "swift/Demangling/DemangleNodes.def"
 
 public:
-  Remangler(DemanglerPrinter &Buffer) : Buffer(Buffer) {}
+  Remangler(DemanglerPrinter &Buffer,
+            SymbolicResolver Resolver) : Buffer(Buffer), Resolver(Resolver) {}
 
   void mangle(Node *node) {
     switch (node->getKind()) {
@@ -1994,18 +1998,25 @@
 }
 
 void Remangler::mangleSymbolicReference(Node *node) {
-  unreachable("should not try to mangle a symbolic reference; "
-              "resolve it to a non-symbolic demangling tree instead");
+  return mangle(Resolver((const void *)node->getIndex()));
 }
 
 } // anonymous namespace
 
 /// The top-level interface to the remangler.
 std::string Demangle::mangleNode(const NodePointer &node) {
+  return mangleNode(node, [](const void *) -> NodePointer {
+    unreachable("should not try to mangle a symbolic reference; "
+                "resolve it to a non-symbolic demangling tree instead");
+  });
+}
+
+std::string
+Demangle::mangleNode(const NodePointer &node, SymbolicResolver resolver) {
   if (!node) return "";
 
   DemanglerPrinter printer;
-  Remangler(printer).mangle(node);
+  Remangler(printer, resolver).mangle(node);
 
   return std::move(printer).str();
 }
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 4ca40e1..c22cfbf 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -119,88 +119,133 @@
   return Args;
 }
 
-static void validateArgs(DiagnosticEngine &diags, const ArgList &Args) {
-  if (Args.hasArgNoClaim(options::OPT_import_underlying_module) &&
-      Args.hasArgNoClaim(options::OPT_import_objc_header)) {
+static void validateBridgingHeaderArgs(DiagnosticEngine &diags,
+                                       const ArgList &args) {
+  if (args.hasArgNoClaim(options::OPT_import_underlying_module) &&
+      args.hasArgNoClaim(options::OPT_import_objc_header)) {
     diags.diagnose({}, diag::error_framework_bridging_header);
   }
+}
+
+static void validateDeploymentTarget(DiagnosticEngine &diags,
+                                     const ArgList &args) {
+  const Arg *A = args.getLastArg(options::OPT_target);
+  if (!A)
+    return;
 
   // Check minimum supported OS versions.
-  if (const Arg *A = Args.getLastArg(options::OPT_target)) {
-    llvm::Triple triple(llvm::Triple::normalize(A->getValue()));
-    if (triple.isMacOSX()) {
-      if (triple.isMacOSXVersionLT(10, 9))
+  llvm::Triple triple(llvm::Triple::normalize(A->getValue()));
+  if (triple.isMacOSX()) {
+    if (triple.isMacOSXVersionLT(10, 9))
+      diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
+                     "OS X 10.9");
+  } else if (triple.isiOS()) {
+    if (triple.isTvOS()) {
+      if (triple.isOSVersionLT(9, 0)) {
         diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
-                       "OS X 10.9");
-    } else if (triple.isiOS()) {
-      if (triple.isTvOS()) {
-        if (triple.isOSVersionLT(9, 0)) {
-          diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
-                         "tvOS 9.0");
-          return;
-        }
-      }
-      if (triple.isOSVersionLT(7))
-        diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
-                       "iOS 7");
-      if (triple.isArch32Bit() && !triple.isOSVersionLT(11)) {
-        diags.diagnose(SourceLoc(), diag::error_ios_maximum_deployment_32,
-                       triple.getOSMajorVersion());
-      }
-    } else if (triple.isWatchOS()) {
-      if (triple.isOSVersionLT(2, 0)) {
-          diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
-                         "watchOS 2.0");
-          return;
+                       "tvOS 9.0");
+        return;
       }
     }
+    if (triple.isOSVersionLT(7))
+      diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
+                     "iOS 7");
+    if (triple.isArch32Bit() && !triple.isOSVersionLT(11)) {
+      diags.diagnose(SourceLoc(), diag::error_ios_maximum_deployment_32,
+                     triple.getOSMajorVersion());
+    }
+  } else if (triple.isWatchOS()) {
+    if (triple.isOSVersionLT(2, 0)) {
+      diags.diagnose(SourceLoc(), diag::error_os_minimum_deployment,
+                     "watchOS 2.0");
+      return;
+    }
   }
+}
 
-  // Check for conflicting warning control flags
-  if (Args.hasArg(options::OPT_suppress_warnings) &&
-      Args.hasArg(options::OPT_warnings_as_errors)) {
+static void validateWarningControlArgs(DiagnosticEngine &diags,
+                                       const ArgList &args) {
+  if (args.hasArg(options::OPT_suppress_warnings) &&
+      args.hasArg(options::OPT_warnings_as_errors)) {
     diags.diagnose(SourceLoc(), diag::error_conflicting_options,
                    "-warnings-as-errors", "-suppress-warnings");
   }
+}
 
-  // Check for conflicting profiling flags
-  const Arg *ProfileGenerate = Args.getLastArg(options::OPT_profile_generate);
-  const Arg *ProfileUse = Args.getLastArg(options::OPT_profile_use);
-  if (ProfileGenerate && ProfileUse)
+static void validateProfilingArgs(DiagnosticEngine &diags,
+                                  const ArgList &args) {
+  const Arg *ProfileGenerate = args.getLastArg(options::OPT_profile_generate);
+  const Arg *ProfileUse = args.getLastArg(options::OPT_profile_use);
+  if (ProfileGenerate && ProfileUse) {
     diags.diagnose(SourceLoc(), diag::error_conflicting_options,
                    "-profile-generate", "-profile-use");
-
-  // Check if the profdata is missing
-  if (ProfileUse && !llvm::sys::fs::exists(ProfileUse->getValue()))
-    diags.diagnose(SourceLoc(), diag::error_profile_missing,
-                  ProfileUse->getValue());
-
-  // Check for missing debug option when verifying debug info.
-  if (Args.hasArg(options::OPT_verify_debug_info)) {
-    bool hasDebugOption = true;
-    Arg *Arg = Args.getLastArg(swift::options::OPT_g_Group);
-    if (!Arg || Arg->getOption().matches(swift::options::OPT_gnone))
-      hasDebugOption = false;
-    if (!hasDebugOption)
-      diags.diagnose(SourceLoc(),
-                     diag::verify_debug_info_requires_debug_option);
   }
 
-  for (const Arg *A : Args.filtered(options::OPT_D)) {
+  // Check if the profdata is missing
+  if (ProfileUse && !llvm::sys::fs::exists(ProfileUse->getValue())) {
+    diags.diagnose(SourceLoc(), diag::error_profile_missing,
+                   ProfileUse->getValue());
+  }
+}
+
+static void validateDebugInfoArgs(DiagnosticEngine &diags,
+                                  const ArgList &args) {
+  // Check for missing debug option when verifying debug info.
+  if (args.hasArg(options::OPT_verify_debug_info)) {
+    Arg *debugOpt = args.getLastArg(swift::options::OPT_g_Group);
+    if (!debugOpt || debugOpt->getOption().matches(swift::options::OPT_gnone)) {
+      diags.diagnose(SourceLoc(),
+                     diag::verify_debug_info_requires_debug_option);
+    }
+  }
+}
+
+static void validateCompilationConditionArgs(DiagnosticEngine &diags,
+                                             const ArgList &args) {
+  for (const Arg *A : args.filtered(options::OPT_D)) {
     StringRef name = A->getValue();
-    if (name.find('=') != StringRef::npos)
+    if (name.find('=') != StringRef::npos) {
       diags.diagnose(SourceLoc(),
                      diag::cannot_assign_value_to_conditional_compilation_flag,
                      name);
-    else if (name.startswith("-D"))
+    } else if (name.startswith("-D")) {
       diags.diagnose(SourceLoc(), diag::redundant_prefix_compilation_flag,
                      name);
-    else if (!Lexer::isIdentifier(name))
+    } else if (!Lexer::isIdentifier(name)) {
       diags.diagnose(SourceLoc(), diag::invalid_conditional_compilation_flag,
                      name);
+    }
   }
 }
 
+static void validateAutolinkingArgs(DiagnosticEngine &diags,
+                                    const ArgList &args) {
+  auto *forceLoadArg = args.getLastArg(options::OPT_autolink_force_load);
+  if (!forceLoadArg)
+    return;
+  auto *incrementalArg = args.getLastArg(options::OPT_incremental);
+  if (!incrementalArg)
+    return;
+
+  // Note: -incremental can itself be overridden by other arguments later
+  // on, but since -autolink-force-load is a rare and not-really-recommended
+  // option it's not worth modeling that complexity here (or moving the
+  // check somewhere else).
+  diags.diagnose(SourceLoc(), diag::error_option_not_supported,
+                 forceLoadArg->getSpelling(), incrementalArg->getSpelling());
+}
+
+/// Perform miscellaneous early validation of arguments.
+static void validateArgs(DiagnosticEngine &diags, const ArgList &args) {
+  validateBridgingHeaderArgs(diags, args);
+  validateDeploymentTarget(diags, args);
+  validateWarningControlArgs(diags, args);
+  validateProfilingArgs(diags, args);
+  validateDebugInfoArgs(diags, args);
+  validateCompilationConditionArgs(diags, args);
+  validateAutolinkingArgs(diags, args);
+}
+
 std::unique_ptr<ToolChain>
 Driver::buildToolChain(const llvm::opt::InputArgList &ArgList) {
 
diff --git a/lib/Driver/FrontendUtil.cpp b/lib/Driver/FrontendUtil.cpp
index 2727671..f8e663e 100644
--- a/lib/Driver/FrontendUtil.cpp
+++ b/lib/Driver/FrontendUtil.cpp
@@ -34,6 +34,11 @@
   // frontend command.
   Args.push_back("-force-single-frontend-invocation");
 
+  // Explictly disable batch mode to avoid a spurious warning when combining
+  // -enable-batch-mode with -force-single-frontend-invocation.  This is an
+  // implementation detail.
+  Args.push_back("-disable-batch-mode");
+
   // Avoid using filelists
   std::string neverThreshold =
       std::to_string(Compilation::NEVER_USE_FILELIST);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index ccf92e8..8af50c8 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -312,7 +312,7 @@
   Opts.EnableNonFrozenEnumExhaustivityDiagnostics =
     Args.hasFlag(OPT_enable_nonfrozen_enum_exhaustivity_diagnostics,
                  OPT_disable_nonfrozen_enum_exhaustivity_diagnostics,
-                 Opts.EnableNonFrozenEnumExhaustivityDiagnostics);
+                 Opts.isSwiftVersionAtLeast(5));
 
   if (Arg *A = Args.getLastArg(OPT_Rpass_EQ))
     Opts.OptimizationRemarkPassedPattern =
diff --git a/lib/IDE/APIDigesterData.cpp b/lib/IDE/APIDigesterData.cpp
index d998fd3..2714fdf 100644
--- a/lib/IDE/APIDigesterData.cpp
+++ b/lib/IDE/APIDigesterData.cpp
@@ -444,6 +444,25 @@
     return const_cast<APIDiffItem *&>(seq[index]);
   }
 };
+
+template<>
+struct ObjectTraits<NameCorrectionInfo> {
+  static void mapping(Output &out, NameCorrectionInfo &value) {
+    out.mapRequired(getKeyContent(DiffItemKeyKind::KK_OldPrintedName),value.OriginalName);
+    out.mapRequired(getKeyContent(DiffItemKeyKind::KK_NewPrintedName), value.CorrectedName);
+    out.mapRequired(getKeyContent(DiffItemKeyKind::KK_ModuleName), value.ModuleName);
+  }
+};
+template<>
+struct ArrayTraits<ArrayRef<NameCorrectionInfo>> {
+  static size_t size(Output &out, ArrayRef<NameCorrectionInfo> &seq) {
+    return seq.size();
+  }
+  static NameCorrectionInfo &element(Output &, ArrayRef<NameCorrectionInfo> &seq,
+                                     size_t index) {
+    return const_cast<NameCorrectionInfo&>(seq[index]);
+  }
+};
 } // namespace json
 } // namespace swift
 
@@ -453,6 +472,12 @@
   yout << Items;
 }
 
+void swift::ide::api::APIDiffItemStore::
+serialize(llvm::raw_ostream &os, ArrayRef<NameCorrectionInfo> Items) {
+  json::Output yout(os);
+  yout << Items;
+}
+
 struct swift::ide::api::APIDiffItemStore::Implementation {
 private:
   llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 2> AllBuffer;
diff --git a/lib/IDE/TypeReconstruction.cpp b/lib/IDE/TypeReconstruction.cpp
index 0256f66..48b651d 100644
--- a/lib/IDE/TypeReconstruction.cpp
+++ b/lib/IDE/TypeReconstruction.cpp
@@ -596,7 +596,7 @@
         // FIXME: Need a more complete/robust lookup mechanism that can handle
         // declarations in sub-stmts, etc.
         UnqualifiedLookup lookup(name, FD, ast->getLazyResolver(),
-                                 /*IsKnownPrivate=*/false, FD->getEndLoc());
+                                 FD->getEndLoc());
         if (!lookup.isSuccess()) {
           result._error = "no decl found in function";
         } else {
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 47b3c78..59eefc9 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -2310,11 +2310,19 @@
 
   LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
 
-  if (f->getInlineStrategy() == NoInline) {
+  switch (f->getInlineStrategy()) {
+  case NoInline:
     attrs = attrs.addAttribute(signature.getType()->getContext(),
                                llvm::AttributeList::FunctionIndex,
                                llvm::Attribute::NoInline);
+    break;
+  case AlwaysInline:
+    // FIXME: We do not currently transfer AlwaysInline since doing so results
+    // in test failures, which must be investigated first.
+  case InlineDefault:
+    break;
   }
+
   if (isReadOnlyFunction(f)) {
     attrs = attrs.addAttribute(signature.getType()->getContext(),
                                llvm::AttributeList::FunctionIndex,
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index df147e2..353bfe3 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -365,8 +365,8 @@
     }
     
     void addExtendedContext() {
-      auto string = getTypeRef(IGM,
-                               E->getSelfInterfaceType()->getCanonicalType());
+      auto string = IGM.getTypeRef(
+          E->getSelfInterfaceType()->getCanonicalType());
       B.addRelativeAddress(string);
     }
     
@@ -3841,7 +3841,7 @@
 
       auto flags = GenericRequirementFlags(abiKind, false, false);
       auto typeName =
-        getTypeRef(IGM, requirement.getSecondType()->getCanonicalType());
+        IGM.getTypeRef(requirement.getSecondType()->getCanonicalType());
 
       addGenericRequirement(IGM, B, metadata, sig, flags,
                             requirement.getFirstType(),
diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp
index bb61f72..9e08613 100644
--- a/lib/IRGen/GenReflection.cpp
+++ b/lib/IRGen/GenReflection.cpp
@@ -164,6 +164,12 @@
   }
 };
 
+llvm::Constant *IRGenModule::getTypeRef(CanType type) {
+  IRGenMangler Mangler;
+  auto SymbolicName = Mangler.mangleTypeForReflection(*this, type);
+  return getAddrOfStringForTypeRef(SymbolicName);
+}
+
 class ReflectionMetadataBuilder {
 protected:
   IRGenModule &IGM;
@@ -203,46 +209,23 @@
 
   /// Add a 32-bit relative offset to a mangled typeref string
   /// in the typeref reflection section.
-  void addTypeRef(ModuleDecl *ModuleContext, CanType type,
-                  CanGenericSignature Context = {}) {
-    assert(type);
-
-    // Generic parameters should be written in terms of interface types
-    // for the purposes of reflection metadata
-    assert(!type->hasArchetype() && "Forgot to map typeref out of context");
-
-    // TODO: As a compatibility hack, mangle single-field boxes with the legacy
-    // mangling in reflection metadata.
-    bool isSingleFieldOfBox = false;
-    auto boxTy = dyn_cast<SILBoxType>(type);
-    if (boxTy && boxTy->getLayout()->getFields().size() == 1) {
-      GenericContextScope scope(IGM, Context);
-      type = boxTy->getFieldLoweredType(IGM.getSILModule(), 0);
-      isSingleFieldOfBox = true;
-    }
-    IRGenMangler mangler;
-    auto MangledStr = mangler.mangleTypeForReflection(IGM, type,
-                                                      ModuleContext,
-                                                      isSingleFieldOfBox);
-    auto mangledName = IGM.getAddrOfStringForTypeRef(MangledStr);
-    B.addRelativeAddress(mangledName);
+  void addTypeRef(CanType type) {
+    B.addRelativeAddress(IGM.getTypeRef(type));
   }
 
   /// Add a 32-bit relative offset to a mangled nominal type string
   /// in the typeref reflection section.
   void addNominalRef(const NominalTypeDecl *nominal) {
-    IRGenMangler mangler;
-    SymbolicMangling mangledStr;
     if (auto proto = dyn_cast<ProtocolDecl>(nominal)) {
+      IRGenMangler mangler;
+      SymbolicMangling mangledStr;
       mangledStr.String = mangler.mangleBareProtocol(proto);
+      auto mangledName = IGM.getAddrOfStringForTypeRef(mangledStr);
+      B.addRelativeAddress(mangledName);
     } else {
       CanType type = nominal->getDeclaredType()->getCanonicalType();
-      mangledStr =
-        mangler.mangleTypeForReflection(IGM, type, nominal->getModuleContext(),
-                                        /*isSingleFieldOfBox=*/false);
+      B.addRelativeAddress(IGM.getTypeRef(type));
     }
-    auto mangledName = IGM.getAddrOfStringForTypeRef(mangledStr);
-    B.addRelativeAddress(mangledName);
   }
 
   llvm::GlobalVariable *emit(Optional<LinkEntity> entity,
@@ -296,9 +279,7 @@
     PrettyStackTraceDecl DebugStack("emitting associated type metadata",
                                     Nominal);
 
-    auto *M = IGM.getSILModule().getSwiftModule();
-
-    addTypeRef(M, Nominal->getDeclaredType()->getCanonicalType());
+    addTypeRef(Nominal->getDeclaredType()->getCanonicalType());
     addNominalRef(Conformance->getProtocol());
 
     B.addInt32(AssociatedTypes.size());
@@ -308,7 +289,7 @@
       auto NameGlobal = IGM.getAddrOfFieldName(AssocTy.first);
       B.addRelativeAddress(NameGlobal);
       addBuiltinTypeRefs(AssocTy.second);
-      addTypeRef(M, AssocTy.second);
+      addTypeRef(AssocTy.second);
     }
   }
 
@@ -342,7 +323,7 @@
     if (!type) {
       B.addInt32(0);
     } else {
-      addTypeRef(value->getModuleContext(), type);
+      addTypeRef(type);
       addBuiltinTypeRefs(type);
     }
 
@@ -448,8 +429,7 @@
 
     auto *CD = dyn_cast<ClassDecl>(NTD);
     if (CD && CD->getSuperclass()) {
-      addTypeRef(NTD->getModuleContext(),
-                 CD->getSuperclass()->getCanonicalType());
+      addTypeRef(CD->getSuperclass()->getCanonicalType());
     } else {
       B.addInt32(0);
     }
@@ -511,7 +491,7 @@
   }
   
   void layout() override {
-    addTypeRef(module, type);
+    addTypeRef(type);
 
     B.addInt32(ti->getFixedSize().getValue());
     B.addInt32(ti->getFixedAlignment().getValue());
@@ -561,7 +541,7 @@
     B.addInt32(0); // Number of sources
     B.addInt32(0); // Number of generic bindings
 
-    addTypeRef(IGM.getSILModule().getSwiftModule(), BoxedType);
+    addTypeRef(BoxedType);
     addBuiltinTypeRefs(BoxedType);
   }
 
@@ -754,8 +734,7 @@
 
     // Now add typerefs of all of the captures.
     for (auto CaptureType : CaptureTypes) {
-      addTypeRef(IGM.getSILModule().getSwiftModule(), CaptureType,
-                 OrigCalleeType->getGenericSignature());
+      addTypeRef(CaptureType);
       addBuiltinTypeRefs(CaptureType);
     }
 
@@ -765,7 +744,7 @@
       auto GenericParam = GenericAndSource.first->getCanonicalType();
       auto Source = GenericAndSource.second;
 
-      addTypeRef(nullptr, GenericParam);
+      addTypeRef(GenericParam);
       addMetadataSource(Source);
     }
   }
diff --git a/lib/IRGen/IRGenMangler.cpp b/lib/IRGen/IRGenMangler.cpp
index d9fcc0c..40e7679 100644
--- a/lib/IRGen/IRGenMangler.cpp
+++ b/lib/IRGen/IRGenMangler.cpp
@@ -81,10 +81,8 @@
 
 SymbolicMangling
 IRGenMangler::mangleTypeForReflection(IRGenModule &IGM,
-                                      Type Ty,
-                                      ModuleDecl *Module,
-                                      bool isSingleFieldOfBox) {
-  Mod = Module;
+                                      Type Ty) {
+  Mod = IGM.getSwiftModule();
   OptimizeProtocolNames = false;
 
   llvm::SaveAndRestore<std::function<bool (const DeclContext *)>>
@@ -109,8 +107,6 @@
   SymbolicReferences.clear();
   
   appendType(Ty);
-  if (isSingleFieldOfBox)
-    appendOperator("Xb");
   
   return {finalize(), std::move(SymbolicReferences)};
 }
diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h
index a0b25a4..9d342e1 100644
--- a/lib/IRGen/IRGenMangler.h
+++ b/lib/IRGen/IRGenMangler.h
@@ -354,9 +354,7 @@
   }
 
   SymbolicMangling mangleTypeForReflection(IRGenModule &IGM,
-                                           Type Ty,
-                                           ModuleDecl *Module,
-                                           bool isSingleFieldOfBox);
+                                           Type Ty);
 
   std::string mangleTypeForLLVMTypeName(CanType Ty);
 
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 833df22..e2bc7b8 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -970,6 +970,7 @@
   /// reflection metadata.
   llvm::SetVector<const StructDecl *> ImportedStructs;
 
+  llvm::Constant *getTypeRef(CanType type);
   llvm::Constant *getAddrOfStringForTypeRef(StringRef mangling);
   llvm::Constant *getAddrOfStringForTypeRef(const SymbolicMangling &mangling);
   llvm::Constant *getAddrOfFieldName(StringRef Name);
diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp
index aa993fc..158fabb 100644
--- a/lib/IRGen/MetadataRequest.cpp
+++ b/lib/IRGen/MetadataRequest.cpp
@@ -297,18 +297,6 @@
   return addr;
 }
 
-// FIXME: willBeRelativelyAddressed is only needed to work around an ld64 bug
-// resolving relative references to coalesceable symbols.
-// It should be removed when fixed. rdar://problem/22674524
-llvm::Constant *irgen::getTypeRef(IRGenModule &IGM, CanType type) {
-  IRGenMangler Mangler;
-  auto SymbolicName = Mangler.mangleTypeForReflection(IGM, type,
-                                                    IGM.getSwiftModule(),
-                                                    /*single-field box*/ false);
-  
-  return IGM.getAddrOfStringForTypeRef(SymbolicName);
-}
-
 llvm::Value *irgen::emitObjCMetadataRefForMetadata(IRGenFunction &IGF,
                                                    llvm::Value *classPtr) {
   assert(IGF.IGM.Context.LangOpts.EnableObjCInterop);
diff --git a/lib/IRGen/MetadataRequest.h b/lib/IRGen/MetadataRequest.h
index 86ad7a3..ec1beba 100644
--- a/lib/IRGen/MetadataRequest.h
+++ b/lib/IRGen/MetadataRequest.h
@@ -503,8 +503,6 @@
 llvm::Value *uniqueForeignTypeMetadataRef(IRGenFunction &IGF,
                                           llvm::Value *candidate);
 
-llvm::Constant *getTypeRef(IRGenModule &IGM, CanType type);
-
 using LazyCacheEmitter =
   llvm::function_ref<MetadataResponse(IRGenFunction &IGF, Explosion &params)>;
 
diff --git a/lib/Migrator/TypeOfMigratorPass.cpp b/lib/Migrator/TypeOfMigratorPass.cpp
index 3697b9c..965f5b3 100644
--- a/lib/Migrator/TypeOfMigratorPass.cpp
+++ b/lib/Migrator/TypeOfMigratorPass.cpp
@@ -44,7 +44,6 @@
       { SF->getASTContext().getIdentifier("type") },
       ContextStack.empty() ? SF->getModuleScopeContext() : ContextStack.back(),
       /*TypeResolver=*/SF->getASTContext().getLazyResolver(),
-      /*IsKnownPrivate=*/false,
       DTE->getLoc()
     };
     auto isShadowing = [&]() -> bool {
diff --git a/lib/SIL/SILProfiler.cpp b/lib/SIL/SILProfiler.cpp
index b0f3685..91557c4 100644
--- a/lib/SIL/SILProfiler.cpp
+++ b/lib/SIL/SILProfiler.cpp
@@ -93,11 +93,8 @@
   assert(hasASTBeenTypeChecked(N) && "Cannot use this AST for profiling");
 
   if (auto *D = N.dyn_cast<Decl *>()) {
-    // Any mapped function may be profiled. There's an exception for
-    // constructors because all of the constructors for a type share a single
-    // profiler.
     if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D))
-      return !isa<ConstructorDecl>(AFD);
+      return true;
 
     if (isa<TopLevelCodeDecl>(D))
       return true;
@@ -798,7 +795,7 @@
       return visitFunctionDecl(*this, AFD, [&] {
         CounterExpr &funcCounter = assignCounter(AFD->getBody());
 
-        if (isa<ConstructorDecl>(AFD))
+        if (ParentNominalType && isa<ConstructorDecl>(AFD))
           addToCounter(ParentNominalType, funcCounter);
       });
     } else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
@@ -995,16 +992,6 @@
   return {};
 }
 
-static void walkTopLevelNodeForProfiling(ASTNode Root, ASTWalker &Walker) {
-  Root.walk(Walker);
-
-  // Visit extensions when walking through a nominal type.
-  auto *NTD = dyn_cast_or_null<NominalTypeDecl>(Root.dyn_cast<Decl *>());
-  if (NTD)
-    for (ExtensionDecl *ED : NTD->getExtensions())
-      ED->walk(Walker);
-}
-
 void SILProfiler::assignRegionCounters() {
   const auto &SM = M.getASTContext().SourceMgr;
 
@@ -1040,7 +1027,7 @@
       CurrentFuncName, getEquivalentPGOLinkage(CurrentFuncLinkage),
       CurrentFileName);
 
-  walkTopLevelNodeForProfiling(Root, Mapper);
+  Root.walk(Mapper);
 
   NumRegionCounters = Mapper.NextCounter;
   // TODO: Mapper needs to calculate a function hash as it goes.
@@ -1048,7 +1035,7 @@
 
   if (EmitCoverageMapping) {
     CoverageMapping Coverage(SM);
-    walkTopLevelNodeForProfiling(Root, Coverage);
+    Root.walk(Coverage);
     CovMap =
         Coverage.emitSourceRegions(M, CurrentFuncName, PGOFuncName, PGOFuncHash,
                                    RegionCounterMap, CurrentFileName);
@@ -1066,7 +1053,7 @@
     }
     PGOMapping pgoMapper(RegionLoadedCounterMap, LoadedCounts,
                          RegionCondToParentMap);
-    walkTopLevelNodeForProfiling(Root, pgoMapper);
+    Root.walk(pgoMapper);
   }
 }
 
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 0ac3d43..ee30072 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -2000,8 +2000,12 @@
     SILType caseTy =
       UI->getOperand()->getType().getEnumElementType(UI->getElement(),
                                                     F.getModule());
-    requireSameType(caseTy, UI->getType(),
-            "InitEnumDataAddrInst result does not match type of enum case");
+
+    if (UI->getModule().getStage() != SILStage::Lowered) {
+      requireSameType(
+          caseTy, UI->getType(),
+          "InitEnumDataAddrInst result does not match type of enum case");
+    }
   }
 
   void checkUncheckedEnumDataInst(UncheckedEnumDataInst *UI) {
@@ -2019,8 +2023,11 @@
     SILType caseTy =
       UI->getOperand()->getType().getEnumElementType(UI->getElement(),
                                                     F.getModule());
-    require(caseTy == UI->getType(),
-            "UncheckedEnumData result does not match type of enum case");
+
+    if (UI->getModule().getStage() != SILStage::Lowered) {
+      require(caseTy == UI->getType(),
+              "UncheckedEnumData result does not match type of enum case");
+    }
   }
 
   void checkUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *UI) {
@@ -2038,8 +2045,11 @@
     SILType caseTy =
       UI->getOperand()->getType().getEnumElementType(UI->getElement(),
                                                     F.getModule());
-    require(caseTy == UI->getType(),
-            "UncheckedTakeEnumDataAddrInst result does not match type of enum case");
+
+    if (UI->getModule().getStage() != SILStage::Lowered) {
+      require(caseTy == UI->getType(), "UncheckedTakeEnumDataAddrInst result "
+                                       "does not match type of enum case");
+    }
   }
 
   void checkInjectEnumAddrInst(InjectEnumAddrInst *IUAI) {
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index ff77f9c..7dbc069 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -489,13 +489,22 @@
 }
 
 SILProfiler *
-SILGenModule::getOrCreateProfilerForConstructors(NominalTypeDecl *decl) {
-  assert(decl && "No nominal type for constructor lookup");
-
+SILGenModule::getOrCreateProfilerForConstructors(DeclContext *ctx,
+                                                 ConstructorDecl *cd) {
   const auto &Opts = M.getOptions();
   if (!Opts.GenerateProfile && Opts.UseProfile.empty())
     return nullptr;
 
+  // Profile nominal types and extensions separately, as they may live in
+  // distinct files. For extensions, just pass in the constructor, because
+  // there are no stored property initializers to visit.
+  Decl *decl = nullptr;
+  if (ctx->isExtensionContext())
+    decl = cd;
+  else
+    decl = ctx->getAsNominalTypeOrNominalTypeExtensionContext();
+  assert(decl && "No decl available for profiling in this context");
+
   SILProfiler *&profiler = constructorProfilers[decl];
   if (!profiler)
     profiler = SILProfiler::create(M, ForDefinition, decl);
@@ -755,7 +764,7 @@
 
   bool ForCoverageMapping = doesASTRequireProfiling(M, decl);
 
-  if (auto *clsDecl = declCtx->getAsClassOrClassExtensionContext()) {
+  if (declCtx->getAsClassOrClassExtensionContext()) {
     // Class constructors have separate entry points for allocation and
     // initialization.
     emitOrDelayFunction(
@@ -772,11 +781,12 @@
       SILDeclRef initConstant(decl, SILDeclRef::Kind::Initializer);
       emitOrDelayFunction(
           *this, initConstant,
-          [this, initConstant, decl, clsDecl](SILFunction *initF) {
+          [this, initConstant, decl, declCtx](SILFunction *initF) {
             preEmitFunction(initConstant, decl, initF, decl);
             PrettyStackTraceSILFunction X("silgen constructor initializer",
                                           initF);
-            initF->setProfiler(getOrCreateProfilerForConstructors(clsDecl));
+            initF->setProfiler(
+                getOrCreateProfilerForConstructors(declCtx, decl));
             SILGenFunction(*this, *initF).emitClassConstructorInitializer(decl);
             postEmitFunction(initConstant, initF);
           },
@@ -784,12 +794,11 @@
     }
   } else {
     // Struct and enum constructors do everything in a single function.
-    auto *nomDecl = declCtx->getAsNominalTypeOrNominalTypeExtensionContext();
     emitOrDelayFunction(
-        *this, constant, [this, constant, decl, nomDecl](SILFunction *f) {
+        *this, constant, [this, constant, decl, declCtx](SILFunction *f) {
           preEmitFunction(constant, decl, f, decl);
           PrettyStackTraceSILFunction X("silgen emitConstructor", f);
-          f->setProfiler(getOrCreateProfilerForConstructors(nomDecl));
+          f->setProfiler(getOrCreateProfilerForConstructors(declCtx, decl));
           SILGenFunction(*this, *f).emitValueConstructor(decl);
           postEmitFunction(constant, f);
         });
@@ -997,10 +1006,8 @@
     PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
 
     // Inherit a profiler instance from the constructor.
-    auto *nominalDecl =
-        var->getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
-    if (nominalDecl)
-      f->setProfiler(getOrCreateProfilerForConstructors(nominalDecl));
+    f->setProfiler(
+        getOrCreateProfilerForConstructors(var->getDeclContext(), nullptr));
 
     SILGenFunction(*this, *f).emitGeneratorFunction(constant, init);
     postEmitFunction(constant, f);
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index 66ae0b9..8b39f6f 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -96,9 +96,10 @@
   /// The most recent conformance...
   NormalProtocolConformance *lastEmittedConformance = nullptr;
 
-  /// Profiler instances for constructors, grouped by associated nominal type.
+  /// Profiler instances for constructors, grouped by associated decl.
   /// Each profiler is shared by all member initializers for a nominal type.
-  llvm::DenseMap<NominalTypeDecl *, SILProfiler *> constructorProfilers;
+  /// Constructors within extensions are profiled separately.
+  llvm::DenseMap<Decl *, SILProfiler *> constructorProfilers;
 
   SILFunction *emitTopLevelFunction(SILLocation Loc);
 
@@ -440,9 +441,12 @@
   /// Emit a property descriptor for the given storage decl if it needs one.
   void tryEmitPropertyDescriptor(AbstractStorageDecl *decl);
 
-  /// Get or create the profiler instance for a nominal type's constructors.
-  SILProfiler *getOrCreateProfilerForConstructors(NominalTypeDecl *decl);
-  
+  /// Get or create the shared profiler instance for a type's constructors.
+  /// This takes care to create separate profilers for extensions, which may
+  /// reside in a different file than the one where the base type is defined.
+  SILProfiler *getOrCreateProfilerForConstructors(DeclContext *ctx,
+                                                  ConstructorDecl *cd);
+
 private:
   /// Emit the deallocator for a class that uses the objc allocator.
   void emitObjCAllocatorDestructor(ClassDecl *cd, DestructorDecl *dd);
diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp
index c9dfcd2..aa72932 100644
--- a/lib/SILGen/SILGenBuiltin.cpp
+++ b/lib/SILGen/SILGenBuiltin.cpp
@@ -574,10 +574,11 @@
   SILType valueBufferTy =
       SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);
 
-  SILValue buffer = SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
-                                                 valueBufferTy.getAddressType(),
-                                                 /*strict*/ true,
-                                                 /*invariant*/ false);
+  SILValue buffer =
+    SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
+                                 valueBufferTy.getAddressType(),
+                                 /*strict*/ true,
+                                 /*invariant*/ false);
   SGF.B.createBeginUnpairedAccess(loc, addr, buffer, SILAccessKind::Modify,
                                   SILAccessEnforcement::Dynamic,
                                   /*noNestedConflict*/ false);
@@ -586,11 +587,10 @@
 }
 
 /// Specialized emitter for Builtin.performInstantaneousReadAccess
-static ManagedValue emitBuiltinPerformInstantaneousReadAccess(SILGenFunction &SGF,
-                                                       SILLocation loc,
-                                                       SubstitutionList substitutions,
-                                                       ArrayRef<ManagedValue> args,
-                                                       SGFContext C) {
+static ManagedValue emitBuiltinPerformInstantaneousReadAccess(
+  SILGenFunction &SGF, SILLocation loc, SubstitutionList substitutions,
+  ArrayRef<ManagedValue> args, SGFContext C) {
+
   assert(substitutions.size() == 1 &&
          "Builtin.performInstantaneousReadAccess should have one substitution");
   assert(args.size() == 2 &&
@@ -603,13 +603,21 @@
                                                /*strict*/ true,
                                                /*invariant*/ false);
 
-  // Begin and then immediately end a read access. No nested conflict is
-  // possible because there are no instructions between the begin and the
-  // end of the access.
-  SILValue access = SGF.B.createBeginAccess(loc, addr, SILAccessKind::Read,
-                                            SILAccessEnforcement::Dynamic,
-                                            /*noNestedConflict*/ true);
-  SGF.B.createEndAccess(loc, access, /*aborted*/ false);
+  SILType valueBufferTy =
+    SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);
+  SILValue unusedBuffer = SGF.emitTemporaryAllocation(loc, valueBufferTy);
+
+  // Begin an "unscoped" read access. No nested conflict is possible because
+  // the compiler should generate the actual read for the KeyPath expression
+  // immediately after the call to this builtin, which forms the address of
+  // that real access. When noNestedConflict=true, no EndUnpairedAccess should
+  // be emitted.
+  //
+  // Unpaired access is necessary because a BeginAccess/EndAccess pair with no
+  // use will be trivially optimized away.
+  SGF.B.createBeginUnpairedAccess(loc, addr, unusedBuffer, SILAccessKind::Read,
+                                  SILAccessEnforcement::Dynamic,
+                                  /*noNestedConflict*/ true);
 
   return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
 }
diff --git a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
index b6bc09a..60e1797 100644
--- a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
@@ -19,12 +19,19 @@
 /// test cases through the pipeline and exercising SIL verification before all
 /// passes support access markers.
 ///
+/// This must only run before inlining _semantic calls. If we inline and drop
+/// the @_semantics("optimize.sil.preserve_exclusivity") attribute, the inlined
+/// markers will be eliminated, but the noninlined markers will not. This would
+/// result in inconsistent begin/end_unpaired_access resulting in unpredictable,
+/// potentially catastrophic runtime behavior.
+///
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "access-marker-elim"
 #include "swift/Basic/Range.h"
 #include "swift/SIL/SILFunction.h"
 #include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/Strings.h"
 #include "llvm/Support/CommandLine.h"
 
 using namespace swift;
@@ -167,6 +174,12 @@
   void run() override {
     auto &M = *getModule();
     for (auto &F : M) {
+      if (F.hasSemanticsAttr(OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY)) {
+        DEBUG(llvm::dbgs() << "Skipping " << F.getName() << ". Found "
+                           << OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY << " tag!\n");
+        continue;
+      }
+
       bool removedAny = AccessMarkerElimination(&F).stripMarkers();
 
       // Only invalidate analyses if we removed some markers.
diff --git a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp
index ee9f4c3..da15951 100644
--- a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp
+++ b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp
@@ -20,12 +20,14 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "swift/SILOptimizer/PassManager/Passes.h"
+#define DEBUG_TYPE "sil-cleanup"
 #include "swift/SIL/SILFunction.h"
 #include "swift/SIL/SILInstruction.h"
 #include "swift/SIL/SILModule.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/PassManager/Passes.h"
 #include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/Strings.h"
 
 using namespace swift;
 
@@ -68,10 +70,12 @@
 
 class IRGenPrepare : public SILFunctionTransform {
   void run() override {
-    bool shouldInvalidate = cleanFunction(*getFunction());
-    if (!shouldInvalidate)
-      return;
-    invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
+    SILFunction *F = getFunction();
+
+    bool shouldInvalidate = cleanFunction(*F);
+
+    if (shouldInvalidate)
+      invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
   }
 };
 
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 4da4ffa..44bb95c 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -2820,6 +2820,22 @@
       }
 
       auto selected = *selectedElt;
+      if (!selected.choice.getBaseType()) {
+        // This is one of the "outer alternatives", meaning the innermost
+        // methods didn't work out.
+        //
+        // The only way to get here is via an UnresolvedDotExpr with outer
+        // alternatives.
+        auto UDE = cast<UnresolvedDotExpr>(expr);
+        cs.diagnoseDeprecatedConditionalConformanceOuterAccess(
+            UDE, selected.choice.getDecl());
+
+        return buildDeclRef(selected.choice, nameLoc, selected.openedFullType,
+                            memberLocator, implicit,
+                            selected.choice.getFunctionRefKind(),
+                            AccessSemantics::Ordinary);
+      }
+
       switch (selected.choice.getKind()) {
       case OverloadChoiceKind::DeclViaBridge: {
         base = cs.coerceToRValue(base);
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 2165e22..6ad37ae 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -1333,7 +1333,7 @@
 static DeclName
 findCorrectEnumCaseName(Type Ty, TypoCorrectionResults &corrections,
                         DeclName memberName) {
-  if (!memberName.isSimpleName())
+  if (memberName.isSpecial() || !memberName.isSimpleName())
     return DeclName();
   if (!Ty->is<EnumType>() &&
       !Ty->is<BoundGenericEnumType>())
@@ -1630,7 +1630,7 @@
 
   // This happens, for example, with ambiguous OverloadedDeclRefExprs. We should
   // just implement visitOverloadedDeclRefExprs and nuke this.
-  
+
   // If we couldn't resolve an argument, then produce a generic "ambiguity"
   // diagnostic.
   diagnose(anchor->getLoc(), diag::ambiguous_member_overload_set,
@@ -3549,6 +3549,58 @@
       TE->isImplicit(), TT));
 }
 
+static DeclName getBaseName(DeclContext *context) {
+  if (auto generic = context->getAsNominalTypeOrNominalTypeExtensionContext()) {
+    return generic->getName();
+  } else if (context->isModuleScopeContext())
+    return context->getParentModule()->getName();
+  else
+    llvm_unreachable("Unsupported base");
+};
+
+static void emitFixItForExplicitlyQualifiedReference(
+    TypeChecker &tc, UnresolvedDotExpr *UDE,
+    decltype(diag::fix_unqualified_access_top_level) diag, DeclName baseName,
+    DescriptiveDeclKind kind) {
+  auto name = baseName.getBaseIdentifier();
+  SmallString<32> namePlusDot = name.str();
+  namePlusDot.push_back('.');
+
+  tc.diagnose(UDE->getLoc(), diag, namePlusDot, kind, name)
+      .fixItInsert(UDE->getStartLoc(), namePlusDot);
+}
+
+void ConstraintSystem::diagnoseDeprecatedConditionalConformanceOuterAccess(
+    UnresolvedDotExpr *UDE, ValueDecl *choice) {
+  auto result = TC.lookupUnqualified(DC, UDE->getName(), UDE->getLoc());
+  assert(result && "names can't just disappear");
+  // These should all come from the same place.
+  auto exampleInner = result.front();
+  auto innerChoice = exampleInner.getValueDecl();
+  auto innerDC = exampleInner.getDeclContext()->getInnermostTypeContext();
+  auto innerParentDecl =
+      innerDC->getAsNominalTypeOrNominalTypeExtensionContext();
+  auto innerBaseName = getBaseName(innerDC);
+
+  auto choiceKind = choice->getDescriptiveKind();
+  auto choiceDC = choice->getDeclContext();
+  auto choiceBaseName = getBaseName(choiceDC);
+  auto choiceParentDecl = choiceDC->getAsDeclOrDeclExtensionContext();
+  auto choiceParentKind = choiceParentDecl
+                              ? choiceParentDecl->getDescriptiveKind()
+                              : DescriptiveDeclKind::Module;
+
+  TC.diagnose(UDE->getLoc(),
+              diag::warn_deprecated_conditional_conformance_outer_access,
+              UDE->getName(), choiceKind, choiceParentKind, choiceBaseName,
+              innerChoice->getDescriptiveKind(),
+              innerParentDecl->getDescriptiveKind(), innerBaseName);
+
+  emitFixItForExplicitlyQualifiedReference(
+      TC, UDE, diag::fix_deprecated_conditional_conformance_outer_access,
+      choiceBaseName, choiceKind);
+}
+
 static bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
                                        CalleeCandidateInfo &CCI,
                                        ArrayRef<Identifier> argLabels,
@@ -3655,16 +3707,6 @@
     return kind;
   };
 
-  auto getBaseName = [](DeclContext *context) -> DeclName {
-    if (auto generic =
-          context->getAsNominalTypeOrNominalTypeExtensionContext()) {
-      return generic->getName();
-    } else if (context->isModuleScopeContext())
-      return context->getParentModule()->getName();
-    else
-      llvm_unreachable("Unsupported base");
-  };
-
   auto diagnoseShadowing = [&](ValueDecl *base,
                                ArrayRef<OverloadChoice> candidates) -> bool {
     CalleeCandidateInfo calleeInfo(base ? base->getInterfaceType() : nullptr,
@@ -3712,13 +3754,8 @@
     if (baseKind == DescriptiveDeclKind::Module)
       topLevelDiag = diag::fix_unqualified_access_top_level_multi;
 
-    auto name = baseName.getBaseIdentifier();
-    SmallString<32> namePlusDot = name.str();
-    namePlusDot.push_back('.');
-
-    TC.diagnose(UDE->getLoc(), topLevelDiag, namePlusDot,
-                choice->getDescriptiveKind(), name)
-        .fixItInsert(UDE->getStartLoc(), namePlusDot);
+    emitFixItForExplicitlyQualifiedReference(TC, UDE, topLevelDiag, baseName,
+                                             choice->getDescriptiveKind());
 
     for (auto &candidate : calleeInfo.candidates) {
       if (auto decl = candidate.getDecl())
@@ -6857,7 +6894,7 @@
     // If we have more than one result, filter out unavailable or
     // obviously unusable candidates.
     if (lookup.size() > 1) {
-      lookup.filter([&](LookupResultEntry result) -> bool {
+      lookup.filter([&](LookupResultEntry result, bool isOuter) -> bool {
         // Drop unavailable candidates.
         if (result.getValueDecl()->getAttrs().isUnavailable(TC.Context))
           return false;
@@ -7525,18 +7562,23 @@
 
   // If this is a tuple, then the index needs to be valid.
   if (auto tuple = baseObjTy->getAs<TupleType>()) {
-    StringRef nameStr = memberName.getBaseIdentifier().str();
-    int fieldIdx = -1;
-    // Resolve a number reference into the tuple type.
-    unsigned Value = 0;
-    if (!nameStr.getAsInteger(10, Value) && Value < tuple->getNumElements()) {
-      fieldIdx = Value;
-    } else {
-      fieldIdx = tuple->getNamedElementId(memberName.getBaseIdentifier());
-    }
+    auto baseName = memberName.getBaseName();
 
-    if (fieldIdx != -1)
-      return false; // Lookup is valid.
+    if (!baseName.isSpecial()) {
+      StringRef nameStr = baseName.userFacingName();
+
+      int fieldIdx = -1;
+      // Resolve a number reference into the tuple type.
+      unsigned Value = 0;
+      if (!nameStr.getAsInteger(10, Value) && Value < tuple->getNumElements()) {
+        fieldIdx = Value;
+      } else {
+        fieldIdx = tuple->getNamedElementId(memberName.getBaseIdentifier());
+      }
+
+      if (fieldIdx != -1)
+        return false; // Lookup is valid.
+    }
 
     diagnose(BaseLoc, diag::could_not_find_tuple_member, baseObjTy, memberName)
         .highlight(memberRange);
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index a9c8a0c..339018b 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -978,7 +978,8 @@
     /// \brief Add constraints for a reference to a named member of the given
     /// base type, and return the type of such a reference.
     Type addMemberRefConstraints(Expr *expr, Expr *base, DeclName name,
-                                 FunctionRefKind functionRefKind) {
+                                 FunctionRefKind functionRefKind,
+                                 ArrayRef<ValueDecl *> outerAlternatives) {
       // The base must have a member of the given name, such that accessing
       // that member through the base returns a value convertible to the type
       // of this expression.
@@ -986,8 +987,13 @@
       auto tv = CS.createTypeVariable(
                   CS.getConstraintLocator(expr, ConstraintLocator::Member),
                   TVO_CanBindToLValue);
-      CS.addValueMemberConstraint(baseTy, name, tv, CurDC, functionRefKind,
-        CS.getConstraintLocator(expr, ConstraintLocator::Member));
+      SmallVector<OverloadChoice, 4> outerChoices;
+      for (auto decl : outerAlternatives) {
+        outerChoices.push_back(OverloadChoice(Type(), decl, functionRefKind));
+      }
+      CS.addValueMemberConstraint(
+          baseTy, name, tv, CurDC, functionRefKind, outerChoices,
+          CS.getConstraintLocator(expr, ConstraintLocator::Member));
       return tv;
     }
 
@@ -1116,6 +1122,7 @@
       } else {
         CS.addValueMemberConstraint(baseTy, DeclBaseName::createSubscript(),
                                     fnTy, CurDC, FunctionRefKind::DoubleApply,
+                                    /*outerAlternatives=*/{},
                                     memberLocator);
       }
 
@@ -1496,9 +1503,12 @@
                           TVO_PrefersSubtypeBinding);
         auto resultTy = CS.createTypeVariable(CS.getConstraintLocator(expr));
         auto methodTy = FunctionType::get(argsTy, resultTy);
-        CS.addValueMemberConstraint(baseTy, expr->getName(),
-          methodTy, CurDC, expr->getFunctionRefKind(),
-          CS.getConstraintLocator(expr, ConstraintLocator::ConstructorMember));
+        CS.addValueMemberConstraint(
+            baseTy, expr->getName(), methodTy, CurDC,
+            expr->getFunctionRefKind(),
+            /*outerAlternatives=*/{},
+            CS.getConstraintLocator(expr,
+                                    ConstraintLocator::ConstructorMember));
 
         // The result of the expression is the partial application of the
         // constructor to the subexpression.
@@ -1506,7 +1516,8 @@
       }
 
       return addMemberRefConstraints(expr, expr->getBase(), expr->getName(),
-                                     expr->getFunctionRefKind());
+                                     expr->getFunctionRefKind(),
+                                     expr->getOuterAlternatives());
     }
     
     Type visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *expr) {
@@ -1911,7 +1922,8 @@
       Identifier name
         = context.getIdentifier(llvm::utostr(expr->getFieldNumber()));
       return addMemberRefConstraints(expr, expr->getBase(), name,
-                                     FunctionRefKind::Unapplied);
+                                     FunctionRefKind::Unapplied,
+                                     /*outerAlternatives=*/{});
     }
 
     /// Give each parameter in a ClosureExpr a fresh type variable if parameter
@@ -2862,6 +2874,7 @@
                                       memberTy,
                                       CurDC,
                                       refKind,
+                                      /*outerAlternatives=*/{},
                                       memberLocator);
           base = memberTy;
           break;
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 1693c50..0a06bcfd 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -2555,6 +2555,7 @@
                            DeclBaseName::createConstructor(),
                            FunctionType::get(tv, resultType),
                            useDC, functionRefKind,
+                           /*outerAlternatives=*/{},
                            getConstraintLocator(
                              fnLocator, 
                              ConstraintLocator::ConstructorMember));
@@ -3443,14 +3444,11 @@
   return result;
 }
 
-ConstraintSystem::SolutionKind
-ConstraintSystem::simplifyMemberConstraint(ConstraintKind kind,
-                                           Type baseTy, DeclName member,
-                                           Type memberTy,
-                                           DeclContext *useDC,
-                                           FunctionRefKind functionRefKind,
-                                           TypeMatchOptions flags,
-                                           ConstraintLocatorBuilder locatorB) {
+ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
+    ConstraintKind kind, Type baseTy, DeclName member, Type memberTy,
+    DeclContext *useDC, FunctionRefKind functionRefKind,
+    ArrayRef<OverloadChoice> outerAlternatives, TypeMatchOptions flags,
+    ConstraintLocatorBuilder locatorB) {
   // Resolve the base type, if we can. If we can't resolve the base type,
   // then we can't solve this constraint.
   // FIXME: simplifyType() call here could be getFixedTypeRecursive?
@@ -3467,8 +3465,8 @@
     // If requested, generate a constraint.
     if (flags.contains(TMF_GenerateConstraints)) {
       addUnsolvedConstraint(
-        Constraint::createMember(*this, kind, baseTy, memberTy, member, useDC,
-                                 functionRefKind, locator));
+        Constraint::createMemberOrOuterDisjunction(*this, kind, baseTy, memberTy, member, useDC,
+                                                   functionRefKind, outerAlternatives, locator));
       return SolutionKind::Solved;
     }
 
@@ -3485,8 +3483,8 @@
   // If we found viable candidates, then we're done!
   if (!result.ViableCandidates.empty()) {
     addOverloadSet(memberTy, result.ViableCandidates, useDC, locator,
-                   result.getFavoredChoice());
-    
+                   result.getFavoredChoice(), outerAlternatives);
+
     return SolutionKind::Solved;
   }
   
@@ -3522,7 +3520,8 @@
     
     // Look through one level of optional.
     addValueMemberConstraint(baseObjTy->getOptionalObjectType(),
-                             member, memberTy, useDC, functionRefKind, locator);
+                             member, memberTy, useDC, functionRefKind,
+                             outerAlternatives, locator);
     return SolutionKind::Solved;
   }
   return SolutionKind::Error;
@@ -5202,6 +5201,7 @@
                                     constraint.getSecondType(),
                                     constraint.getMemberUseDC(),
                                     constraint.getFunctionRefKind(),
+                                    /*outerAlternatives=*/{},
                                     TMF_GenerateConstraints,
                                     constraint.getLocator());
 
diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp
index adfdfd3..68a7545 100644
--- a/lib/Sema/Constraint.cpp
+++ b/lib/Sema/Constraint.cpp
@@ -642,6 +642,25 @@
                                 locator, typeVars);
 }
 
+Constraint *Constraint::createMemberOrOuterDisjunction(
+    ConstraintSystem &cs, ConstraintKind kind, Type first, Type second,
+    DeclName member, DeclContext *useDC, FunctionRefKind functionRefKind,
+    ArrayRef<OverloadChoice> outerAlternatives, ConstraintLocator *locator) {
+  auto memberConstraint = createMember(cs, kind, first, second, member,
+                             useDC, functionRefKind, locator);
+
+  if (outerAlternatives.empty())
+    return memberConstraint;
+
+  SmallVector<Constraint *, 4> constraints;
+  constraints.push_back(memberConstraint);
+  memberConstraint->setFavored();
+  for (auto choice : outerAlternatives) {
+    constraints.push_back(
+        Constraint::createBindOverload(cs, first, choice, useDC, locator));
+  }
+  return Constraint::createDisjunction(cs, constraints, locator, ForgetChoice);
+}
 
 Constraint *Constraint::createMember(ConstraintSystem &cs, ConstraintKind kind, 
                                      Type first, Type second, DeclName member,
diff --git a/lib/Sema/Constraint.h b/lib/Sema/Constraint.h
index 29f8269..ca09d09 100644
--- a/lib/Sema/Constraint.h
+++ b/lib/Sema/Constraint.h
@@ -435,6 +435,13 @@
                             Type First, Type Second, Type Third,
                             ConstraintLocator *locator);
 
+  /// Create a new member constraint, or a disjunction of that with the outer
+  /// alternatives.
+  static Constraint *createMemberOrOuterDisjunction(
+      ConstraintSystem &cs, ConstraintKind kind, Type first, Type second,
+      DeclName member, DeclContext *useDC, FunctionRefKind functionRefKind,
+      ArrayRef<OverloadChoice> outerAlternatives, ConstraintLocator *locator);
+
   /// Create a new member constraint.
   static Constraint *createMember(ConstraintSystem &cs, ConstraintKind kind,
                                   Type first, Type second, DeclName member,
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 8e9a29b..efee4f3 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -295,12 +295,13 @@
 
   // If there's anything to remove, filter it out now.
   if (anyRemovals) {
-    result->filter([&](LookupResultEntry entry) -> bool {
+    result->filter([&](LookupResultEntry entry, bool isOuter) -> bool {
       auto *decl = entry.getValueDecl();
 
       // Remove invalid declarations so the constraint solver doesn't need to
       // cope with them.
-      if (decl->isInvalid()) return false;
+      if (decl->isInvalid())
+        return false;
 
       return known[getDynamicResultSignature(decl)] == decl;
     });
@@ -1471,11 +1472,12 @@
                                       ArrayRef<OverloadChoice> choices,
                                       DeclContext *useDC,
                                       ConstraintLocator *locator,
-                                      OverloadChoice *favoredChoice) {
+                                      OverloadChoice *favoredChoice,
+                                      ArrayRef<OverloadChoice> outerAlternatives) {
   assert(!choices.empty() && "Empty overload set");
 
   // If there is a single choice, add the bind overload directly.
-  if (choices.size() == 1) {
+  if (choices.size() == 1 && outerAlternatives.empty()) {
     addBindOverloadConstraint(boundType, choices.front(), locator, useDC);
     return;
   }
@@ -1511,7 +1513,26 @@
                                                        useDC, locator));
   }
 
-  addDisjunctionConstraint(overloads, locator, ForgetChoice, favoredChoice);
+  auto innerDisjunction = Constraint::createDisjunction(*this, overloads,
+                                                        locator, ForgetChoice);
+  if (outerAlternatives.empty()) {
+    if (favoredChoice)
+      innerDisjunction->setFavored();
+
+    addUnsolvedConstraint(innerDisjunction);
+    return;
+  }
+
+  SmallVector<Constraint *, 4> outerConstraints;
+  outerConstraints.push_back(innerDisjunction);
+  innerDisjunction->setFavored();
+  for (auto choice : outerAlternatives) {
+    outerConstraints.push_back(Constraint::createBindOverload(
+                                 *this, boundType, choice,
+                                   useDC, locator));
+  }
+
+  addDisjunctionConstraint(outerConstraints, locator, ForgetChoice, favoredChoice);
 }
 
 /// If we're resolving an overload set with a decl that has special type
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 2d524d5..2e1b31b 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -1748,6 +1748,13 @@
   /// emits an error message.
   void diagnoseFailureForExpr(Expr *expr);
 
+  /// \brief Give the deprecation warning for referring to a global function
+  /// when there's a method from a conditional conformance in a smaller/closer
+  /// scope.
+  void
+  diagnoseDeprecatedConditionalConformanceOuterAccess(UnresolvedDotExpr *UDE,
+                                                      ValueDecl *choice);
+
   /// \brief Add a constraint to the constraint system.
   void addConstraint(ConstraintKind kind, Type first, Type second,
                      ConstraintLocatorBuilder locator,
@@ -1784,14 +1791,15 @@
   void addValueMemberConstraint(Type baseTy, DeclName name, Type memberTy,
                                 DeclContext *useDC,
                                 FunctionRefKind functionRefKind,
+                                ArrayRef<OverloadChoice> outerAlternatives,
                                 ConstraintLocatorBuilder locator) {
     assert(baseTy);
     assert(memberTy);
     assert(name);
     assert(useDC);
-    switch (simplifyMemberConstraint(ConstraintKind::ValueMember, baseTy, name,
-                                     memberTy, useDC, functionRefKind,
-                                     TMF_GenerateConstraints, locator)) {
+    switch (simplifyMemberConstraint(
+        ConstraintKind::ValueMember, baseTy, name, memberTy, useDC,
+        functionRefKind, outerAlternatives, TMF_GenerateConstraints, locator)) {
     case SolutionKind::Unsolved:
       llvm_unreachable("Unsolved result when generating constraints!");
 
@@ -1800,10 +1808,9 @@
 
     case SolutionKind::Error:
       if (shouldAddNewFailingConstraint()) {
-        addNewFailingConstraint(
-          Constraint::createMember(*this, ConstraintKind::ValueMember, baseTy,
-                                   memberTy, name, useDC, functionRefKind,
-                                   getConstraintLocator(locator)));
+        addNewFailingConstraint(Constraint::createMemberOrOuterDisjunction(
+            *this, ConstraintKind::ValueMember, baseTy, memberTy, name, useDC,
+            functionRefKind, outerAlternatives, getConstraintLocator(locator)));
       }
       break;
     }
@@ -1822,6 +1829,7 @@
     switch (simplifyMemberConstraint(ConstraintKind::UnresolvedValueMember,
                                      baseTy, name, memberTy,
                                      useDC, functionRefKind,
+                                     /*outerAlternatives=*/{},
                                      TMF_GenerateConstraints, locator)) {
     case SolutionKind::Unsolved:
       llvm_unreachable("Unsolved result when generating constraints!");
@@ -2190,7 +2198,8 @@
   /// sets.
   void addOverloadSet(Type boundType, ArrayRef<OverloadChoice> choices,
                       DeclContext *useDC, ConstraintLocator *locator,
-                      OverloadChoice *favored = nullptr);
+                      OverloadChoice *favored = nullptr,
+                      ArrayRef<OverloadChoice> outerAlternatives = {});
 
   /// \brief Retrieve the allocator used by this constraint system.
   llvm::BumpPtrAllocator &getAllocator() { return Allocator; }
@@ -2561,14 +2570,12 @@
                                              ConstraintLocatorBuilder locator);
 
   /// \brief Attempt to simplify the given member constraint.
-  SolutionKind simplifyMemberConstraint(ConstraintKind kind,
-                                        Type baseType, DeclName member,
-                                        Type memberType, DeclContext *useDC,
-                                        FunctionRefKind functionRefKind,
-                                        TypeMatchOptions flags,
-                                        ConstraintLocatorBuilder locator);
+  SolutionKind simplifyMemberConstraint(
+      ConstraintKind kind, Type baseType, DeclName member, Type memberType,
+      DeclContext *useDC, FunctionRefKind functionRefKind,
+      ArrayRef<OverloadChoice> outerAlternatives, TypeMatchOptions flags,
+      ConstraintLocatorBuilder locator);
 
-  
   /// \brief Attempt to simplify the optional object constraint.
   SolutionKind simplifyOptionalObjectConstraint(
                                           Type first, Type second,
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index 55b329b..ac77bbc 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -750,13 +750,14 @@
                                       TypeLoc::withoutLoc(returnType),
                                       target);
   encodeDecl->setImplicit();
+  encodeDecl->setSynthesized();
   encodeDecl->setBodySynthesizer(deriveBodyEncodable_encode);
 
   // This method should be marked as 'override' for classes inheriting Encodable
   // conformance from a parent class.
   auto *classDecl = dyn_cast<ClassDecl>(target);
   if (classDecl && superclassIsEncodable(classDecl)) {
-    auto *attr = new (C) SimpleDeclAttr<DAK_Override>(/*IsImplicit=*/true);
+    auto *attr = new (C) OverrideAttr(/*IsImplicit=*/true);
     encodeDecl->getAttrs().add(attr);
   }
 
@@ -1084,11 +1085,12 @@
                                            SourceLoc(), selfDecl, paramList,
                                            /*GenericParams=*/nullptr, target);
   initDecl->setImplicit();
+  initDecl->setSynthesized();
   initDecl->setBodySynthesizer(deriveBodyDecodable_init);
 
   // This constructor should be marked as `required` for non-final classes.
   if (isa<ClassDecl>(target) && !target->getAttrs().hasAttribute<FinalAttr>()) {
-    auto *reqAttr = new (C) SimpleDeclAttr<DAK_Required>(/*IsImplicit=*/true);
+    auto *reqAttr = new (C) RequiredAttr(/*IsImplicit=*/true);
     initDecl->getAttrs().add(reqAttr);
   }
 
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index dfdb730..4bc0d96 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -145,6 +145,17 @@
     addGetterToReadOnlyDerivedProperty(tc, propDecl, rawType);
   getterDecl->setBodySynthesizer(&deriveBodyRawRepresentable_raw);
 
+  // If the containing module is not resilient, make sure clients can get at
+  // the raw value without function call overhead.
+  if (parentDC->getParentModule()->getResilienceStrategy() !=
+      ResilienceStrategy::Resilient) {
+    AccessScope access =
+        enumDecl->getFormalAccessScope(nullptr,
+                                       /*treatUsableFromInlineAsPublic*/true);
+    if (access.isPublic())
+      getterDecl->getAttrs().add(new (C) InlinableAttr(/*implicit*/false));
+  }
+
   auto dc = cast<IterableDeclContext>(parentDecl);
   dc->addMember(getterDecl);
   dc->addMember(propDecl);
@@ -343,6 +354,17 @@
   initDecl->copyFormalAccessFrom(enumDecl, /*sourceIsParentContext*/true);
   initDecl->setValidationStarted();
 
+  // If the containing module is not resilient, make sure clients can construct
+  // an instance without function call overhead.
+  if (parentDC->getParentModule()->getResilienceStrategy() !=
+      ResilienceStrategy::Resilient) {
+    AccessScope access =
+        enumDecl->getFormalAccessScope(nullptr,
+                                       /*treatUsableFromInlineAsPublic*/true);
+    if (access.isPublic())
+      initDecl->getAttrs().add(new (C) InlinableAttr(/*implicit*/false));
+  }
+
   tc.Context.addSynthesizedDecl(initDecl);
 
   cast<IterableDeclContext>(parentDecl)->addMember(initDecl);
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index a8bcf50..b13c12c 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -873,7 +873,8 @@
 
       DeclContext *topLevelContext = DC->getModuleScopeContext();
       UnqualifiedLookup lookup(VD->getBaseName(), topLevelContext, &TC,
-                               /*knownPrivate*/true);
+                               /*Loc=*/SourceLoc(),
+                               UnqualifiedLookup::Flags::KnownPrivate);
 
       // Group results by module. Pick an arbitrary result from each module.
       llvm::SmallDenseMap<const ModuleDecl*,const ValueDecl*,4> resultsByModule;
@@ -2128,8 +2129,7 @@
     storageKind = SK_Property;
 
   TC.diagnose(diagLoc, diag::unowned_assignment_immediate_deallocation,
-              varDecl->getName(),
-              (unsigned) ownershipAttr->get(), (unsigned) storageKind)
+              varDecl->getName(), ownershipAttr->get(), unsigned(storageKind))
     .highlight(diagRange);
 
   TC.diagnose(diagLoc, diag::unowned_assignment_requires_strong)
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index e651a99..43e4bc2 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -991,11 +991,11 @@
   
   // If none of the ones we find are acceptable, then reject one.
   auto oneCandidate = candidates.front();
-  candidates.filter([&](LookupResultEntry entry)->bool {
+  candidates.filter([&](LookupResultEntry entry, bool isOuter) -> bool {
     auto cand = cast<SubscriptDecl>(entry.getValueDecl());
     return isAcceptableDynamicMemberLookupSubscript(cand, decl, TC);
   });
-  
+
   if (candidates.empty()) {
     TC.diagnose(oneCandidate.getValueDecl()->getLoc(),
                 diag::type_invalid_dml, type);
@@ -1984,7 +1984,10 @@
 
   // On internal declarations, @inlinable implies @usableFromInline.
   if (VD->getAttrs().hasAttribute<InlinableAttr>()) {
-    diagnoseAndRemoveAttr(attr, diag::inlinable_implies_usable_from_inline);
+    if (attr->isImplicit())
+      attr->setInvalid();
+    else
+      diagnoseAndRemoveAttr(attr, diag::inlinable_implies_usable_from_inline);
     return;
   }
 }
@@ -2143,7 +2146,9 @@
   auto ownershipKind = attr->get();
 
   // A weak variable must have type R? or R! for some ownership-capable type R.
-  Type underlyingType = type;
+  auto underlyingType = type->getOptionalObjectType();
+  auto isOptional = bool(underlyingType);
+  auto allowOptional = false;
   switch (ownershipKind) {
   case ReferenceOwnership::Strong:
     llvm_unreachable("Cannot specify 'strong' in an ownership attribute");
@@ -2151,24 +2156,35 @@
   case ReferenceOwnership::Unmanaged:
     break;
   case ReferenceOwnership::Weak:
+    allowOptional = true;
     if (var->isLet()) {
       diagnose(var->getStartLoc(), diag::invalid_weak_let);
       attr->setInvalid();
     }
 
-    if (Type objType = type->getOptionalObjectType()) {
-      underlyingType = objType;
-    } else {
-      // @IBOutlet must be optional, but not necessarily weak. Let it diagnose.
-      if (!var->getAttrs().hasAttribute<IBOutletAttr>()) {
-        diagnose(var->getStartLoc(), diag::invalid_weak_ownership_not_optional,
-                 OptionalType::get(type));
-      }
-      attr->setInvalid();
+    if (isOptional)
+      break;
+
+    // @IBOutlet must be optional, but not necessarily weak. Let it diagnose.
+    if (!var->getAttrs().hasAttribute<IBOutletAttr>()) {
+      diagnose(var->getStartLoc(), diag::invalid_weak_ownership_not_optional,
+               OptionalType::get(type));
     }
+    attr->setInvalid();
     break;
   }
 
+
+  if (!allowOptional && isOptional) {
+    diagnose(var->getStartLoc(), diag::invalid_ownership_with_optional,
+             ownershipKind)
+      .fixItReplace(attr->getRange(), "weak");
+    attr->setInvalid();
+  }
+
+  if (!underlyingType)
+    underlyingType = type;
+
   if (!underlyingType->allowsOwnership()) {
     auto D = diag::invalid_ownership_type;
 
@@ -2178,23 +2194,19 @@
       D = diag::invalid_ownership_protocol_type;
     }
 
-    diagnose(var->getStartLoc(), D, (unsigned) ownershipKind, underlyingType);
+    diagnose(var->getStartLoc(), D, ownershipKind, underlyingType);
     attr->setInvalid();
-  } else if (isa<ProtocolDecl>(var->getDeclContext()) &&
-             !cast<ProtocolDecl>(var->getDeclContext())->isObjC()) {
+  }
+
+  auto PDC = dyn_cast<ProtocolDecl>((var->getDeclContext()));
+  if (PDC && !PDC->isObjC()) {
     // Ownership does not make sense in protocols, except for "weak" on
     // properties of Objective-C protocols.
-    if (Context.isSwiftVersionAtLeast(5))
-      diagnose(attr->getLocation(),
-        diag::ownership_invalid_in_protocols,
-        (unsigned) ownershipKind)
-        .fixItRemove(attr->getRange());
-    else
-      diagnose(attr->getLocation(),
-        diag::ownership_invalid_in_protocols_compat_warning,
-        (unsigned) ownershipKind)
-        .fixItRemove(attr->getRange());
-
+    auto D = Context.isSwiftVersionAtLeast(5)
+           ? diag::ownership_invalid_in_protocols
+           : diag::ownership_invalid_in_protocols_compat_warning;
+    diagnose(attr->getLocation(), D, ownershipKind)
+      .fixItRemove(attr->getRange());
     attr->setInvalid();
   }
 
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 7b3ae4f..d43aedb 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -397,6 +397,56 @@
   }
 }
 
+static bool findNonMembers(TypeChecker &TC,
+                           ArrayRef<LookupResultEntry> lookupResults,
+                           DeclRefKind refKind, bool breakOnMember,
+                           SmallVectorImpl<ValueDecl *> &ResultValues,
+                           llvm::function_ref<bool(ValueDecl *)> isValid) {
+  bool AllDeclRefs = true;
+  for (auto Result : lookupResults) {
+    // If we find a member, then all of the results aren't non-members.
+    bool IsMember =
+        (Result.getBaseDecl() && !isa<ModuleDecl>(Result.getBaseDecl()));
+    if (IsMember) {
+      AllDeclRefs = false;
+      if (breakOnMember)
+        break;
+      continue;
+    }
+
+    ValueDecl *D = Result.getValueDecl();
+    if (!D->hasInterfaceType())
+      TC.validateDecl(D);
+
+    // FIXME: Circularity hack.
+    if (!D->hasInterfaceType()) {
+      AllDeclRefs = false;
+      continue;
+    }
+
+    if (!isValid(D))
+      return false;
+
+    if (matchesDeclRefKind(D, refKind))
+      ResultValues.push_back(D);
+  }
+
+  return AllDeclRefs;
+}
+
+/// Whether we should be looking at the outer results for a function called \c
+/// name.
+///
+/// This is very restrictive because it's a source compatibility issue (see the
+/// if (AllConditionalConformances) { (void)findNonMembers(...); } below).
+static bool shouldConsiderOuterResultsFor(DeclName name) {
+  const StringRef specialNames[] = {"min", "max"};
+  for (auto specialName : specialNames)
+    if (name.isSimpleName(specialName))
+      return true;
+
+  return false;
+}
 
 /// Bind an UnresolvedDeclRefExpr by performing name lookup and
 /// returning the resultant expression.  Context is the DeclContext used
@@ -411,6 +461,9 @@
   NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
   if (isa<AbstractFunctionDecl>(DC))
     lookupOptions |= NameLookupFlags::KnownPrivate;
+  if (shouldConsiderOuterResultsFor(Name))
+    lookupOptions |= NameLookupFlags::IncludeOuterResults;
+
   auto Lookup = lookupUnqualified(DC, Name, Loc, lookupOptions);
 
   if (!Lookup) {
@@ -526,40 +579,27 @@
                                    UDRE->isImplicit());
   }
 
-  bool AllDeclRefs = true;
   SmallVector<ValueDecl*, 4> ResultValues;
-  for (auto Result : Lookup) {
-    // If we find a member, then all of the results aren't non-members.
-    bool IsMember = (Result.getBaseDecl() &&
-                     !isa<ModuleDecl>(Result.getBaseDecl()));
-    if (IsMember) {
-      AllDeclRefs = false;
-      break;
-    }
+  Expr *error = nullptr;
+  bool AllDeclRefs = findNonMembers(
+      *this, Lookup.innerResults(), UDRE->getRefKind(), /*breakOnMember=*/true,
+      ResultValues, [&](ValueDecl *D) {
+        // FIXME: The source-location checks won't make sense once
+        // EnableASTScopeLookup is the default.
+        if (Loc.isValid() && D->getLoc().isValid() &&
+            D->getDeclContext()->isLocalContext() &&
+            D->getDeclContext() == DC &&
+            Context.SourceMgr.isBeforeInBuffer(Loc, D->getLoc())) {
+          diagnose(Loc, diag::use_local_before_declaration, Name);
+          diagnose(D, diag::decl_declared_here, Name);
+          error = new (Context) ErrorExpr(UDRE->getSourceRange());
+          return false;
+        }
+        return true;
+      });
+  if (error)
+    return error;
 
-    ValueDecl *D = Result.getValueDecl();
-    if (!D->hasInterfaceType()) validateDecl(D);
-
-    // FIXME: Circularity hack.
-    if (!D->hasInterfaceType()) {
-      AllDeclRefs = false;
-      continue;
-    }
-
-    // FIXME: The source-location checks won't make sense once
-    // EnableASTScopeLookup is the default.
-    if (Loc.isValid() && D->getLoc().isValid() &&
-        D->getDeclContext()->isLocalContext() &&
-        D->getDeclContext() == DC &&
-        Context.SourceMgr.isBeforeInBuffer(Loc, D->getLoc())) {
-      diagnose(Loc, diag::use_local_before_declaration, Name);
-      diagnose(D, diag::decl_declared_here, Name);
-      return new (Context) ErrorExpr(UDRE->getSourceRange());
-    }
-    if (matchesDeclRefKind(D, UDRE->getRefKind()))
-      ResultValues.push_back(D);
-  }
-  
   if (AllDeclRefs) {
     // Diagnose uses of operators that found no matching candidates.
     if (ResultValues.empty()) {
@@ -599,20 +639,43 @@
 
   ResultValues.clear();
   bool AllMemberRefs = true;
+  bool AllConditionalConformances = true;
   ValueDecl *Base = nullptr;
   DeclContext *BaseDC = nullptr;
   for (auto Result : Lookup) {
+    auto ThisBase = Result.getBaseDecl();
+
     // Track the base for member declarations.
-    if (Result.getBaseDecl() &&
-        !isa<ModuleDecl>(Result.getBaseDecl())) {
-      ResultValues.push_back(Result.getValueDecl());
-      if (Base && Result.getBaseDecl() != Base) {
+    if (ThisBase && !isa<ModuleDecl>(ThisBase)) {
+      auto Value = Result.getValueDecl();
+      ResultValues.push_back(Value);
+      if (Base && ThisBase != Base) {
         AllMemberRefs = false;
         break;
       }
 
-      Base = Result.getBaseDecl();
+      Base = ThisBase;
       BaseDC = Result.getDeclContext();
+
+      // Check if this result is derived through a conditional conformance,
+      // meaning it comes from a protocol (or extension) where there's a
+      // conditional conformance for the type with the method in question
+      // (NB. that type may not be the type associated with DC, for tested types
+      // with static methods).
+      if (auto Proto = Value->getDeclContext()
+                           ->getAsProtocolOrProtocolExtensionContext()) {
+        auto contextSelfType =
+            BaseDC->getInnermostTypeContext()->getDeclaredInterfaceType();
+        auto conformance = conformsToProtocol(
+            contextSelfType, Proto, DC,
+            ConformanceCheckFlags::InExpression |
+                ConformanceCheckFlags::SkipConditionalRequirements);
+
+        if (!conformance || conformance->getConditionalRequirements().empty()) {
+          AllConditionalConformances = false;
+        }
+      }
+
       continue;
     }
 
@@ -633,13 +696,29 @@
       BaseExpr = new (Context) DeclRefExpr(Base, UDRE->getNameLoc(),
                                            /*Implicit=*/true);
     }
-    
-   
+
+    // We *might* include any non-members that we found in outer contexts in
+    // some special cases, for backwards compatibility: first, we have to be
+    // looking for one of the special names
+    // ('shouldConsiderOuterResultsFor(Name)'), and second, all of the inner
+    // results need to come from conditional conformances. The second condition
+    // is how the problem here was encountered: a type ('Range') was made to
+    // conditionally conform to a new protocol ('Sequence'), which introduced
+    // some extra methods ('min' and 'max') that shadowed global functions that
+    // people regularly called within extensions to that type (usually adding
+    // 'clamp').
+    llvm::SmallVector<ValueDecl *, 4> outerAlternatives;
+    if (AllConditionalConformances) {
+      (void)findNonMembers(*this, Lookup.outerResults(), UDRE->getRefKind(),
+                           /*breakOnMember=*/false, outerAlternatives,
+                           /*isValid=*/[&](ValueDecl *) { return true; });
+    }
+
     // Otherwise, form an UnresolvedDotExpr and sema will resolve it based on
     // type information.
-    return new (Context) UnresolvedDotExpr(BaseExpr, SourceLoc(), Name,
-                                           UDRE->getNameLoc(),
-                                           UDRE->isImplicit());
+    return new (Context) UnresolvedDotExpr(
+        BaseExpr, SourceLoc(), Name, UDRE->getNameLoc(), UDRE->isImplicit(),
+        Context.AllocateCopy(outerAlternatives));
   }
   
   // FIXME: If we reach this point, the program we're being handed is likely
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 3d3aae9..12771d5 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -1213,6 +1213,7 @@
 
 void swift::makeFinal(ASTContext &ctx, ValueDecl *D) {
   if (D && !D->isFinal()) {
+    assert(isa<ClassDecl>(D) || D->isPotentiallyOverridable());
     D->getAttrs().add(new (ctx) FinalAttr(/*IsImplicit=*/true));
   }
 }
@@ -1223,6 +1224,57 @@
   }
 }
 
+namespace {
+// The raw values of this enum must be kept in sync with
+// diag::implicitly_final_cannot_be_open.
+enum class ImplicitlyFinalReason : unsigned {
+  /// A property was declared with 'let'.
+  Let,
+  /// The containing class is final.
+  FinalClass,
+  /// A member was declared as 'static'.
+  Static
+};
+}
+
+static void inferFinalAndDiagnoseIfNeeded(TypeChecker &TC, ValueDecl *D,
+                                          StaticSpellingKind staticSpelling) {
+  auto cls = D->getDeclContext()->getAsClassOrClassExtensionContext();
+  if (!cls)
+    return;
+
+  // Are there any reasons to infer 'final'? Prefer 'static' over the class
+  // being final for the purposes of diagnostics.
+  Optional<ImplicitlyFinalReason> reason;
+  if (staticSpelling == StaticSpellingKind::KeywordStatic) {
+    reason = ImplicitlyFinalReason::Static;
+
+    if (auto finalAttr = D->getAttrs().getAttribute<FinalAttr>()) {
+      auto finalRange = finalAttr->getRange();
+      if (finalRange.isValid()) {
+        TC.diagnose(finalRange.Start, diag::static_decl_already_final)
+        .fixItRemove(finalRange);
+      }
+    }
+  } else if (cls->isFinal()) {
+    reason = ImplicitlyFinalReason::FinalClass;
+  }
+
+  if (!reason)
+    return;
+
+  if (D->getFormalAccess() == AccessLevel::Open) {
+    auto diagID = diag::implicitly_final_cannot_be_open;
+    if (!TC.Context.isSwiftVersionAtLeast(5))
+      diagID = diag::implicitly_final_cannot_be_open_swift4;
+    auto inFlightDiag = TC.diagnose(D, diagID,
+                                    static_cast<unsigned>(reason.getValue()));
+    fixItAccess(inFlightDiag, D, AccessLevel::Public);
+  }
+
+  makeFinal(TC.Context, D);
+}
+
 /// Configure the implicit 'self' parameter of a function, setting its type,
 /// pattern, etc.
 ///
@@ -1498,14 +1550,26 @@
     // decl. A setter attribute can also override this.
     AbstractStorageDecl *storage = accessor->getStorage();
     if (storage->hasAccess()) {
-      if (accessor->getAccessorKind() == AccessorKind::IsSetter ||
-          accessor->getAccessorKind() == AccessorKind::IsMutableAddressor ||
-          accessor->getAccessorKind() == AccessorKind::IsMaterializeForSet)
-        accessor->setAccess(storage->getSetterFormalAccess());
-      else
+      switch (accessor->getAccessorKind()) {
+      case AccessorKind::IsGetter:
+      case AccessorKind::IsAddressor:
         accessor->setAccess(storage->getFormalAccess());
+        break;
+      case AccessorKind::IsSetter:
+      case AccessorKind::IsMutableAddressor:
+      case AccessorKind::IsMaterializeForSet:
+        accessor->setAccess(storage->getSetterFormalAccess());
+        break;
+      case AccessorKind::IsWillSet:
+      case AccessorKind::IsDidSet:
+        // These are only needed to synthesize the setter.
+        accessor->setAccess(AccessLevel::Private);
+        break;
+      }
     } else {
       computeAccessLevel(storage);
+      assert(accessor->hasAccess() &&
+             "if the accessor isn't just the getter/setter this isn't enough");
     }
   }
 
@@ -2571,36 +2635,14 @@
   if (D->isFinal() && !isNSManaged)
     return;
 
-  // Variables declared with 'let' cannot be 'dynamic'.
-  if (auto VD = dyn_cast<VarDecl>(D)) {
-    auto staticSpelling = VD->getParentPatternBinding()->getStaticSpelling();
-
-    // The presence of 'static' blocks the inference of 'dynamic'.
-    if (staticSpelling == StaticSpellingKind::KeywordStatic)
-      return;
-
-    if (VD->isLet() && !isNSManaged)
-      return;
-  }
-
   // Accessors should not infer 'dynamic' on their own; they can get it from
   // their storage decls.
-  if (auto FD = dyn_cast<FuncDecl>(D)) {
-    if (isa<AccessorDecl>(FD))
-      return;
+  if (isa<AccessorDecl>(D))
+    return;
 
-    auto staticSpelling = FD->getStaticSpelling();
-
-    // The presence of 'static' bocks the inference of 'dynamic'.
-    if (staticSpelling == StaticSpellingKind::KeywordStatic)
-      return;
-  }
-
-  // The presence of 'final' on a class prevents 'dynamic'.
+  // Only classes can use 'dynamic'.
   auto classDecl = D->getDeclContext()->getAsClassOrClassExtensionContext();
-  if (!classDecl) return;
-  if (!isNSManaged && classDecl->isFinal() &&
-      !classDecl->requiresStoredPropertyInits())
+  if (!classDecl)
     return;
 
   // Add the 'dynamic' attribute.
@@ -4331,6 +4373,7 @@
 
     TC.validateDecl(ED);
     TC.DeclsToFinalize.remove(ED);
+    ED->setHasValidatedLayout();
 
     {
       // Check for circular inheritance of the raw type.
@@ -4364,6 +4407,7 @@
 
     TC.validateDecl(SD);
     TC.DeclsToFinalize.remove(SD);
+    SD->setHasValidatedLayout();
 
     TC.addImplicitConstructors(SD);
 
@@ -4489,6 +4533,7 @@
     TC.validateDecl(CD);
     TC.requestSuperclassLayout(CD);
     TC.DeclsToFinalize.remove(CD);
+    CD->setHasValidatedLayout();
 
     {
       // Check for circular inheritance.
@@ -5289,6 +5334,7 @@
         // Check whether the types are identical.
         auto parentDeclTy = owningTy->adjustSuperclassMemberDeclType(
             parentDecl, decl, parentDecl->getInterfaceType());
+        if (parentDeclTy->hasError()) continue;
         parentDeclTy = parentDeclTy->getUnlabeledType(TC.Context);
         if (method) {
           // For methods, strip off the 'Self' type.
@@ -5442,8 +5488,7 @@
         parentOwnership = ReferenceOwnership::Strong;
       if (parentOwnership != ownershipAttr->get()) {
         TC.diagnose(decl, diag::override_ownership_mismatch,
-                    (unsigned)parentOwnership,
-                    (unsigned)ownershipAttr->get());
+                    parentOwnership, ownershipAttr->get());
         TC.diagnose(matchDecl, diag::overridden_here);
       }
     }
@@ -6869,7 +6914,7 @@
     }
 
     if (!isa<ClassDecl>(nominal))
-      DeclsToFinalize.insert(nominal);
+      requestNominalLayout(nominal);
 
     break;
   }
@@ -7043,33 +7088,28 @@
         }
       }
 
-      // Infer 'dynamic' before touching accessors.
-      inferDynamic(Context, VD);
-
       // If this variable is a class member, mark it final if the
       // class is final, or if it was declared with 'let'.
-      if (auto cls = dyn_cast<ClassDecl>(nominalDecl)) {
-        if (cls->isFinal() || VD->isLet()) {
-          if (!VD->isFinal()) {
-            makeFinal(Context, VD);
-          }
-        }
-        if (VD->isStatic()) {
-          auto staticSpelling =
-            VD->getParentPatternBinding()->getStaticSpelling();
-          if (staticSpelling == StaticSpellingKind::KeywordStatic) {
-            auto finalAttr = VD->getAttrs().getAttribute<FinalAttr>();
-            if (finalAttr) {
-              auto finalRange = finalAttr->getRange();
-              if (finalRange.isValid())
-                diagnose(finalRange.Start, diag::decl_already_final)
-                .highlight(finalRange)
-                .fixItRemove(finalRange);
-            }
-            makeFinal(Context, VD);
-          }
+      auto staticSpelling =
+          VD->getParentPatternBinding()->getStaticSpelling();
+      inferFinalAndDiagnoseIfNeeded(*this, VD, staticSpelling);
+
+      if (VD->isLet() && isa<ClassDecl>(nominalDecl)) {
+        makeFinal(Context, VD);
+
+        if (VD->getFormalAccess() == AccessLevel::Open) {
+          auto diagID = diag::implicitly_final_cannot_be_open;
+          if (!Context.isSwiftVersionAtLeast(5))
+            diagID = diag::implicitly_final_cannot_be_open_swift4;
+          auto inFlightDiag =
+              diagnose(D, diagID,
+                       static_cast<unsigned>(ImplicitlyFinalReason::Let));
+          fixItAccess(inFlightDiag, D, AccessLevel::Public);
         }
       }
+
+      // Infer 'dynamic' after 'final' but before touching accessors.
+      inferDynamic(Context, VD);
     }
 
     // Perform accessor-related validation.
@@ -7367,6 +7407,9 @@
                                                      errorConvention)))
         isObjC = None;
       markAsObjC(*this, FD, isObjC, errorConvention);
+
+      inferFinalAndDiagnoseIfNeeded(*this, FD, FD->getStaticSpelling());
+      inferDynamic(Context, FD);
     }
 
     // If the function is exported to C, it must be representable in (Obj-)C.
@@ -7381,28 +7424,6 @@
       }
     }
 
-    inferDynamic(Context, FD);
-
-    // If this is a class member, mark it final if the class is final.
-    if (auto cls = FD->getDeclContext()->getAsClassOrClassExtensionContext()) {
-      if (cls->isFinal() && !FD->isFinal()) {
-        makeFinal(Context, FD);
-      }
-      // static func declarations in classes are synonyms
-      // for `class final func` declarations.
-      if (FD->getStaticSpelling() == StaticSpellingKind::KeywordStatic) {
-        auto finalAttr = FD->getAttrs().getAttribute<FinalAttr>();
-        if (finalAttr) {
-          auto finalRange = finalAttr->getRange();
-          if (finalRange.isValid())
-            diagnose(finalRange.Start, diag::decl_already_final)
-              .highlight(finalRange)
-              .fixItRemove(finalRange);
-        }
-        makeFinal(Context, FD);
-      }
-    }
-
     checkDeclAttributes(FD);
 
     break;
@@ -7715,13 +7736,9 @@
     }
 
     // Member subscripts need some special validation logic.
-    if (auto nominalDecl = dc->getAsNominalTypeOrNominalTypeExtensionContext()) {
+    if (dc->isTypeContext()) {
       // If this is a class member, mark it final if the class is final.
-      if (auto cls = dyn_cast<ClassDecl>(nominalDecl)) {
-        if (cls->isFinal() && !SD->isFinal()) {
-          makeFinal(Context, SD);
-        }
-      }
+      inferFinalAndDiagnoseIfNeeded(*this, SD, StaticSpellingKind::None);
 
       // A subscript is ObjC-compatible if it's explicitly @objc, or a
       // member of an ObjC-compatible class or protocol.
@@ -7975,11 +7992,6 @@
   assert(!nominal->hasClangNode());
   assert(isa<SourceFile>(nominal->getModuleScopeContext()));
 
-  Optional<bool> lazyVarsAlreadyHaveImplementation;
-
-  if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
-    TC.requestSuperclassLayout(classDecl);
-
   for (auto *D : nominal->getMembers()) {
     auto VD = dyn_cast<ValueDecl>(D);
     if (!VD)
@@ -7991,40 +8003,44 @@
     TC.validateDecl(VD);
 
     // The only thing left to do is synthesize storage for lazy variables.
-    // We only have to do that if it's a type from another file, though.
-    // In NDEBUG builds, bail out as soon as we can.
-#ifdef NDEBUG
-    if (lazyVarsAlreadyHaveImplementation.hasValue() &&
-        lazyVarsAlreadyHaveImplementation.getValue())
-      continue;
-#endif
     auto *prop = dyn_cast<VarDecl>(D);
     if (!prop)
       continue;
 
     if (prop->getAttrs().hasAttribute<LazyAttr>() && !prop->isStatic()
                                                   && prop->getGetter()) {
-      bool hasImplementation = prop->getGetter()->hasBody();
-
-      if (lazyVarsAlreadyHaveImplementation.hasValue()) {
-        assert(lazyVarsAlreadyHaveImplementation.getValue() ==
-                 hasImplementation &&
-               "only some lazy vars already have implementations");
-      } else {
-        lazyVarsAlreadyHaveImplementation = hasImplementation;
-      }
-
-      if (!hasImplementation)
-        TC.completeLazyVarImplementation(prop);
+      assert(!prop->getGetter()->hasBody());
+      TC.completeLazyVarImplementation(prop);
     }
   }
 
-  // FIXME: We need to add implicit initializers and dtors when a decl is
-  // touched, because it affects vtable layout.  If you're not defining the
-  // class, you shouldn't have to know what the vtable layout is.
   if (auto *CD = dyn_cast<ClassDecl>(nominal)) {
+    // We need to add implicit initializers and dtors because it
+    // affects vtable layout.
     TC.addImplicitConstructors(CD);
     CD->addImplicitDestructor();
+
+    // We need the superclass vtable layout as well.
+    TC.requestSuperclassLayout(CD);
+
+    auto useConformance = [&](ProtocolDecl *protocol) {
+      if (auto ref = TC.conformsToProtocol(
+            CD->getDeclaredInterfaceType(), protocol, CD,
+            ConformanceCheckFlags::SkipConditionalRequirements,
+            SourceLoc())) {
+        if (ref->getConcrete()->getDeclContext() == CD)
+          TC.markConformanceUsed(*ref, CD);
+      }
+    };
+
+    // If the class is Encodable or Decodable, force those
+    // conformances to ensure that the init(from:) and
+    // encode(to:) members appear in the vtable.
+    //
+    // FIXME: Generalize this to other protocols for which
+    // we can derive conformances.
+    useConformance(TC.Context.getProtocol(KnownProtocolKind::Decodable));
+    useConformance(TC.Context.getProtocol(KnownProtocolKind::Encodable));
   }
 
   // validateDeclForNameLookup will not trigger an immediate full
@@ -8575,6 +8591,27 @@
   }
 }
 
+void TypeChecker::maybeDiagnoseClassWithoutInitializers(ClassDecl *classDecl) {
+  // Some heuristics to skip emitting a diagnostic if the class is already
+  // irreperably busted.
+  if (classDecl->isInvalid() ||
+      classDecl->inheritsSuperclassInitializers(nullptr))
+    return;
+
+  auto *superclassDecl = classDecl->getSuperclassDecl();
+  if (superclassDecl &&
+      superclassDecl->hasMissingDesignatedInitializers())
+    return;
+
+  for (auto member : classDecl->lookupDirect(DeclBaseName::createConstructor())) {
+    auto ctor = dyn_cast<ConstructorDecl>(member);
+    if (ctor && ctor->isDesignatedInit())
+      return;
+  }
+
+  diagnoseClassWithoutInitializers(*this, classDecl);
+}
+
 /// Diagnose a missing required initializer.
 static void diagnoseMissingRequiredInitializer(
               TypeChecker &TC,
@@ -8697,16 +8734,13 @@
   // Bail out if we're validating one of our constructors already; we'll
   // revisit the issue later.
   if (isa<ClassDecl>(decl)) {
-    bool alreadyValidatingCtor = false;
     for (auto member : decl->getMembers()) {
       if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
         validateDecl(ctor);
         if (!ctor->hasValidSignature())
-          alreadyValidatingCtor = true;
+          return;
       }
     }
-    if (alreadyValidatingCtor)
-      return;
   }
 
   decl->setAddedImplicitInitializers();
@@ -8716,37 +8750,8 @@
   bool FoundMemberwiseInitializedProperty = false;
   bool SuppressDefaultInitializer = false;
   bool SuppressMemberwiseInitializer = false;
-  bool FoundSynthesizedInit = false;
   bool FoundDesignatedInit = false;
 
-  // Before we look for constructors, we need to make sure that all synthesized
-  // initializers are properly synthesized.
-  //
-  // NOTE: Lookups of synthesized initializers MUST come after
-  //       decl->setAddedImplicitInitializers() in case synthesis requires
-  //       protocol conformance checking, which might be recursive here.
-  // FIXME: Disable this code and prevent _any_ implicit constructors from doing
-  //        this. Investigate why this hasn't worked otherwise.
-  DeclName synthesizedInitializers[1] = {
-    // init(from:) is synthesized by derived conformance to Decodable.
-    DeclName(Context, DeclBaseName::createConstructor(), Context.Id_from)
-  };
-
-  auto initializerIsSynthesized = [=](ConstructorDecl *initializer) {
-    if (!initializer->isImplicit())
-      return false;
-
-    for (auto &name : synthesizedInitializers)
-      if (initializer->getFullName() == name)
-        return true;
-
-    return false;
-  };
-
-  for (auto &name : synthesizedInitializers) {
-    synthesizeMemberForLookup(decl, name);
-  }
-
   SmallPtrSet<CanType, 4> initializerParamTypes;
   llvm::SmallPtrSet<ConstructorDecl *, 4> overriddenInits;
   if (decl->hasClangNode() && isa<ClassDecl>(decl)) {
@@ -8768,13 +8773,10 @@
   } else {
     for (auto member : decl->getMembers()) {
       if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
-        // Synthesized initializers others than the default initializer should
-        // not prevent default initializer synthesis.
-        if (initializerIsSynthesized(ctor)) {
-          FoundSynthesizedInit = true;
-        } else if (ctor->isDesignatedInit()) {
+        // Initializers that were synthesized to fulfill derived conformances
+        // should not prevent default initializer synthesis.
+        if (ctor->isDesignatedInit() && !ctor->isSynthesized())
           FoundDesignatedInit = true;
-        }
 
         if (isa<StructDecl>(decl))
           continue;
@@ -8846,8 +8848,10 @@
   }
 
   if (auto structDecl = dyn_cast<StructDecl>(decl)) {
-    if (!FoundDesignatedInit && !SuppressMemberwiseInitializer
-        && !structDecl->hasUnreferenceableStorage()) {
+    assert(!structDecl->hasUnreferenceableStorage() &&
+           "User-defined structs cannot have unreferenceable storage");
+
+    if (!FoundDesignatedInit && !SuppressMemberwiseInitializer) {
       // For a struct with memberwise initialized properties, we add a
       // memberwise init.
       if (FoundMemberwiseInitializedProperty) {
@@ -8869,13 +8873,13 @@
   // FIXME: Currently skipping generic classes.
   auto classDecl = cast<ClassDecl>(decl);
   if (classDecl->hasSuperclass()) {
-    bool canInheritInitializers = !FoundDesignatedInit;
+    bool canInheritInitializers = (!SuppressDefaultInitializer &&
+                                   !FoundDesignatedInit);
 
     // We can't define these overrides if we have any uninitialized
     // stored properties.
-    if (SuppressDefaultInitializer && !FoundDesignatedInit
-        && !FoundSynthesizedInit && !classDecl->hasClangNode()) {
-      diagnoseClassWithoutInitializers(*this, classDecl);
+    if (SuppressDefaultInitializer && !FoundDesignatedInit &&
+        !classDecl->hasClangNode()) {
       return;
     }
 
@@ -8976,12 +8980,8 @@
     // constructor.
 
     // ... unless there are uninitialized stored properties.
-    if (SuppressDefaultInitializer) {
-      if (!FoundSynthesizedInit)
-        diagnoseClassWithoutInitializers(*this, classDecl);
-
+    if (SuppressDefaultInitializer)
       return;
-    }
 
     defineDefaultConstructor(decl);
   }
@@ -8992,14 +8992,9 @@
   auto baseName = member.getBaseName();
 
   // Checks whether the target conforms to the given protocol. If the
-  // conformance is incomplete, check the conformance to force synthesis, if
-  // possible.
+  // conformance is incomplete, force the conformance.
   //
-  // Swallows diagnostics if conformance checking is already in progress (so we
-  // don't display diagnostics twice).
-  //
-  // Returns whether the target conforms to the protocol and the conformance is
-  // complete.
+  // Returns whether the target conforms to the protocol.
   auto evaluateTargetConformanceTo = [&](ProtocolDecl *protocol) {
     auto targetType = target->getDeclaredInterfaceType();
     if (auto ref = conformsToProtocol(
@@ -9008,26 +9003,12 @@
                          ConformanceCheckFlags::SkipConditionalRequirements),
                          SourceLoc())) {
       if (auto *conformance = ref->getConcrete()->getRootNormalConformance()) {
-        if (conformance->isIncomplete()) {
-          // Check conformance, forcing synthesis.
-          //
-          // If synthesizing conformance fails, this will produce diagnostics.
-          // If conformance checking was already in progress elsewhere, though,
-          // this could produce diagnostics twice.
-          //
-          // To prevent this duplication, we swallow the diagnostics if the
-          // state of the conformance is not Incomplete.
-          DiagnosticTransaction transaction(Context.Diags);
-          auto shouldSwallowDiagnostics =
-            conformance->getState() != ProtocolConformanceState::Incomplete;
-
+        if (conformance->getState() == ProtocolConformanceState::Incomplete) {
           checkConformance(conformance);
-          if (shouldSwallowDiagnostics)
-            transaction.abort();
-
-          return conformance->isComplete();
         }
       }
+
+      return true;
     }
 
     return false;
@@ -9049,13 +9030,6 @@
       auto *encodableProto = Context.getProtocol(KnownProtocolKind::Encodable);
       if (!evaluateTargetConformanceTo(decodableProto))
         (void)evaluateTargetConformanceTo(encodableProto);
-    } else if (baseName.getIdentifier() == Context.Id_allCases ||
-               baseName.getIdentifier() == Context.Id_AllCases) {
-      // If the target should conform to the CaseIterable protocol, check the
-      // conformance here to attempt synthesis.
-      auto *caseIterableProto
-          = Context.getProtocol(KnownProtocolKind::CaseIterable);
-      (void)evaluateTargetConformanceTo(caseIterableProto);
     }
   } else {
     auto argumentNames = member.getArgumentNames();
@@ -9084,32 +9058,6 @@
   }
 }
 
-void TypeChecker::addImplicitStructConformances(StructDecl *SD) {
-  // Type-check the protocol conformances of the struct decl to instantiate its
-  // derived conformances.
-  checkConformancesInContext(SD, SD);
-}
-
-void TypeChecker::addImplicitEnumConformances(EnumDecl *ED) {
-  // Type-check the raw values of the enum.
-  for (auto elt : ED->getAllElements()) {
-    assert(elt->hasRawValueExpr());
-    if (elt->getTypeCheckedRawValueExpr()) continue;
-    Expr *typeChecked = elt->getRawValueExpr();
-    Type rawTy = ED->mapTypeIntoContext(ED->getRawType());
-    auto resultTy = typeCheckExpression(
-        typeChecked, ED, TypeLoc::withoutLoc(rawTy), CTP_EnumCaseRawValue);
-    assert(resultTy);
-    (void)resultTy;
-    elt->setTypeCheckedRawValueExpr(typeChecked);
-    checkEnumElementErrorHandling(elt);
-  }
-  
-  // Type-check the protocol conformances of the enum decl to instantiate its
-  // derived conformances.
-  checkConformancesInContext(ED, ED);
-}
-
 void TypeChecker::defineDefaultConstructor(NominalTypeDecl *decl) {
   PrettyStackTraceDecl stackTrace("defining default constructor for",
                                   decl);
diff --git a/lib/Sema/TypeCheckExprObjC.cpp b/lib/Sema/TypeCheckExprObjC.cpp
index db91929..cb7f3c8 100644
--- a/lib/Sema/TypeCheckExprObjC.cpp
+++ b/lib/Sema/TypeCheckExprObjC.cpp
@@ -277,7 +277,7 @@
     // If we have more than one result, filter out unavailable or
     // obviously unusable candidates.
     if (lookup.size() > 1) {
-      lookup.filter([&](LookupResultEntry result) -> bool {
+      lookup.filter([&](LookupResultEntry result, bool isOuter) -> bool {
           // Drop unavailable candidates.
           if (result.getValueDecl()->getAttrs().isUnavailable(Context))
             return false;
diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp
index a084f88..f680463 100644
--- a/lib/Sema/TypeCheckNameLookup.cpp
+++ b/lib/Sema/TypeCheckNameLookup.cpp
@@ -26,10 +26,23 @@
 
 using namespace swift;
 
-void LookupResult::filter(const std::function<bool(LookupResultEntry)> &pred) {
+void LookupResult::filter(
+    const std::function<bool(LookupResultEntry, bool)> &pred) {
+  size_t index = 0;
+  size_t originalFirstOuter = IndexOfFirstOuterResult;
   Results.erase(std::remove_if(Results.begin(), Results.end(),
                                [&](LookupResultEntry result) -> bool {
-                                 return !pred(result);
+                                 auto isInner = index < originalFirstOuter;
+                                 index++;
+                                 if (pred(result, !isInner))
+                                   return false;
+
+                                 // Need to remove this, which means, if it is
+                                 // an inner result, the outer results need to
+                                 // shift down.
+                                 if (isInner)
+                                   IndexOfFirstOuterResult--;
+                                 return true;
                                }),
                 Results.end());
 }
@@ -46,6 +59,8 @@
 
     /// The vector of found declarations.
     SmallVector<ValueDecl *, 4> FoundDecls;
+    /// The vector of found declarations.
+    SmallVector<ValueDecl *, 4> FoundOuterDecls;
 
     /// The set of known declarations.
     llvm::SmallDenseMap<std::pair<ValueDecl *, DeclContext *>, bool, 4> Known;
@@ -76,25 +91,35 @@
 
       // Remove any overridden declarations from the found-declarations set.
       removeOverriddenDecls(FoundDecls);
+      removeOverriddenDecls(FoundOuterDecls);
 
       // Remove any shadowed declarations from the found-declarations set.
       removeShadowedDecls(FoundDecls, DC->getParentModule(), &TC);
+      removeShadowedDecls(FoundOuterDecls, DC->getParentModule(), &TC);
 
       // Filter out those results that have been removed from the
       // found-declarations set.
-      unsigned foundIdx = 0, foundSize = FoundDecls.size();
-      Result.filter([&](LookupResultEntry result) -> bool {
-          // If the current result matches the remaining found declaration,
-          // keep it and move to the next found declaration.
-          if (foundIdx < foundSize &&
-              result.getValueDecl() == FoundDecls[foundIdx]) {
-            ++foundIdx;
-            return true;
-          }
+      unsigned foundIdx = 0, foundSize = FoundDecls.size(),
+               foundOuterSize = FoundOuterDecls.size();
+      Result.filter([&](LookupResultEntry result, bool isOuter) -> bool {
+        unsigned idx = foundIdx;
+        unsigned limit = foundSize;
+        ArrayRef<ValueDecl *> decls = FoundDecls;
+        if (isOuter) {
+          idx = foundIdx - foundSize;
+          limit = foundOuterSize;
+          decls = FoundOuterDecls;
+        }
+        // If the current result matches the remaining found declaration,
+        // keep it and move to the next found declaration.
+        if (idx < limit && result.getValueDecl() == decls[idx]) {
+          ++foundIdx;
+          return true;
+        }
 
-          // Otherwise, this result should be filtered out.
-          return false;
-        });
+        // Otherwise, this result should be filtered out.
+        return false;
+      });
     }
 
     /// Add a new result.
@@ -106,7 +131,11 @@
     ///
     /// \param foundInType The type through which we found the
     /// declaration.
-    void add(ValueDecl *found, DeclContext *baseDC, Type foundInType) {
+    ///
+    /// \param isOuter Whether this is an outer result (i.e. a result that isn't
+    /// from the innermost scope with results)
+    void add(ValueDecl *found, DeclContext *baseDC, Type foundInType,
+             bool isOuter) {
       ConformanceCheckOptions conformanceOptions;
       if (Options.contains(NameLookupFlags::KnownPrivate))
         conformanceOptions |= ConformanceCheckFlags::InExpression;
@@ -116,8 +145,11 @@
 
       auto addResult = [&](ValueDecl *result) {
         if (Known.insert({{result, baseDC}, false}).second) {
-          Result.add(LookupResultEntry(baseDC, result));
-          FoundDecls.push_back(result);
+          Result.add(LookupResultEntry(baseDC, result), isOuter);
+          if (isOuter)
+            FoundOuterDecls.push_back(result);
+          else
+            FoundDecls.push_back(result);
         }
       };
 
@@ -212,21 +244,32 @@
   };
 } // end anonymous namespace
 
+static UnqualifiedLookup::Options
+convertToUnqualifiedLookupOptions(NameLookupOptions options) {
+  UnqualifiedLookup::Options newOptions;
+  if (options.contains(NameLookupFlags::KnownPrivate))
+    newOptions |= UnqualifiedLookup::Flags::KnownPrivate;
+  if (options.contains(NameLookupFlags::ProtocolMembers))
+    newOptions |= UnqualifiedLookup::Flags::AllowProtocolMembers;
+  if (options.contains(NameLookupFlags::IgnoreAccessControl))
+    newOptions |= UnqualifiedLookup::Flags::IgnoreAccessControl;
+  if (options.contains(NameLookupFlags::IncludeOuterResults))
+    newOptions |= UnqualifiedLookup::Flags::IncludeOuterResults;
+
+  return newOptions;
+}
+
 LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclName name,
                                             SourceLoc loc,
                                             NameLookupOptions options) {
-  UnqualifiedLookup lookup(
-      name, dc, this,
-      options.contains(NameLookupFlags::KnownPrivate),
-      loc,
-      /*IsTypeLookup=*/false,
-      options.contains(NameLookupFlags::ProtocolMembers),
-      options.contains(NameLookupFlags::IgnoreAccessControl));
+  UnqualifiedLookup lookup(name, dc, this, loc,
+                           convertToUnqualifiedLookupOptions(options));
 
   LookupResult result;
   LookupResultBuilder builder(*this, result, dc, options,
                               /*memberLookup*/false);
-  for (const auto &found : lookup.Results) {
+  for (auto idx : indices(lookup.Results)) {
+    const auto &found = lookup.Results[idx];
     // Determine which type we looked through to find this result.
     Type foundInType;
 
@@ -240,7 +283,8 @@
       assert(foundInType && "bogus base declaration?");
     }
 
-    builder.add(found.getValueDecl(), found.getDeclContext(), foundInType);
+    builder.add(found.getValueDecl(), found.getDeclContext(), foundInType,
+                /*isOuter=*/idx >= lookup.IndexOfFirstOuterResult);
   }
   return result;
 }
@@ -249,19 +293,17 @@
 TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclName name,
                                    SourceLoc loc,
                                    NameLookupOptions options) {
+  auto ulOptions = convertToUnqualifiedLookupOptions(options) |
+                   UnqualifiedLookup::Flags::TypeLookup;
   {
     // Try lookup without ProtocolMembers first.
     UnqualifiedLookup lookup(
-      name, dc, this,
-        options.contains(NameLookupFlags::KnownPrivate),
-        loc,
-        /*IsTypeLookup=*/true,
-        /*AllowProtocolMembers=*/false,
-        options.contains(NameLookupFlags::IgnoreAccessControl));
+        name, dc, this, loc,
+        ulOptions - UnqualifiedLookup::Flags::AllowProtocolMembers);
 
     if (!lookup.Results.empty() ||
         !options.contains(NameLookupFlags::ProtocolMembers)) {
-      return LookupResult(lookup.Results);
+      return LookupResult(lookup.Results, lookup.IndexOfFirstOuterResult);
     }
   }
 
@@ -272,14 +314,10 @@
     // is called too early, we start resolving extensions -- even those
     // which do provide not conformances.
     UnqualifiedLookup lookup(
-      name, dc, this,
-        options.contains(NameLookupFlags::KnownPrivate),
-        loc,
-        /*IsTypeLookup=*/true,
-        /*AllowProtocolMembers=*/true,
-        options.contains(NameLookupFlags::IgnoreAccessControl));
+        name, dc, this, loc,
+        ulOptions | UnqualifiedLookup::Flags::AllowProtocolMembers);
 
-    return LookupResult(lookup.Results);
+    return LookupResult(lookup.Results, lookup.IndexOfFirstOuterResult);
   }
 }
 
@@ -310,7 +348,7 @@
   dc->lookupQualified(type, name, subOptions, this, lookupResults);
 
   for (auto found : lookupResults)
-    builder.add(found, nullptr, type);
+    builder.add(found, nullptr, type, /*isOuter=*/false);
 
   return result;
 }
@@ -621,7 +659,7 @@
 void
 TypoCorrectionResults::addAllCandidatesToLookup(LookupResult &lookup) const {
   for (auto candidate : Candidates)
-    lookup.add(LookupResultEntry(candidate));
+    lookup.add(LookupResultEntry(candidate), /*isOuter=*/false);
 }
 
 static Decl *findExplicitParentForImplicitDecl(ValueDecl *decl) {
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index c18ec50..73e85b1 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1495,15 +1495,21 @@
       return conformance;
     }
     // And... even if it isn't conditional, we still don't currently support
-    // @objc protocols in extensions.
+    // @objc protocols in extensions of Swift generic classes, because there's
+    // no stable Objective-C class object to install the protocol conformance
+    // category onto.
     if (isa<ExtensionDecl>(DC)) {
       if (auto genericT = T->getGenericAncestor()) {
-        auto isSubclass = !genericT->isEqual(T);
-        auto genericTIsGeneric = (bool)genericT->getAnyGeneric()->getGenericParams();
-        TC.diagnose(ComplainLoc, diag::objc_protocol_in_generic_extension, T,
-                    ProtoType, isSubclass, genericTIsGeneric);
-        conformance->setInvalid();
-        return conformance;
+        if (!cast<ClassDecl>(genericT->getAnyNominal())
+               ->usesObjCGenericsModel()) {
+          auto isSubclass = !genericT->isEqual(T);
+          auto genericTIsGeneric = (bool)genericT->getAnyGeneric()
+                                                 ->getGenericParams();
+          TC.diagnose(ComplainLoc, diag::objc_protocol_in_generic_extension, T,
+                      ProtoType, isSubclass, genericTIsGeneric);
+          conformance->setInvalid();
+          return conformance;
+        }
       }
     }
   }
@@ -4024,6 +4030,7 @@
   llvm::SetVector<ValueDecl *> globalMissingWitnesses;
   ConformanceChecker checker(*this, conformance, globalMissingWitnesses);
   checker.ensureRequirementsAreSatisfied(/*failUnsubstituted=*/true);
+  checker.diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorFixIt);
 }
 
 /// Determine the score when trying to match two identifiers together.
@@ -4931,6 +4938,7 @@
     checker.resolveTypeWitnesses();
   else
     checker.resolveSingleTypeWitness(assocType);
+  checker.diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorFixIt);
 }
 
 void TypeChecker::resolveWitness(const NormalProtocolConformance *conformance,
@@ -4941,6 +4949,7 @@
                        const_cast<NormalProtocolConformance*>(conformance),
                        MissingWitnesses);
   checker.resolveSingleWitness(requirement);
+  checker.diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorFixIt);
 }
 
 ValueDecl *TypeChecker::deriveProtocolRequirement(DeclContext *DC,
diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp
index d2a448d..439f842 100644
--- a/lib/Sema/TypeCheckSwitchStmt.cpp
+++ b/lib/Sema/TypeCheckSwitchStmt.cpp
@@ -1381,10 +1381,8 @@
           // playgrounds.
           return;
         }
-        if (!TC.Context.isSwiftVersionAtLeast(5)) {
-          // Downgrade missing '@unknown' to a warning in Swift 4 and below.
-          mainDiagType = diag::non_exhaustive_switch_warn;
-        }
+        // Missing '@unknown' is just a warning.
+        mainDiagType = diag::non_exhaustive_switch_warn;
         break;
       }
 
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index 7978707..9151ffb 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -65,18 +65,6 @@
   Context.setLazyResolver(nullptr);
 }
 
-void TypeChecker::handleExternalDecl(Decl *decl) {
-  if (auto SD = dyn_cast<StructDecl>(decl)) {
-    addImplicitStructConformances(SD);
-  }
-  if (auto CD = dyn_cast<ClassDecl>(decl)) {
-    CD->addImplicitDestructor();
-  }
-  if (auto ED = dyn_cast<EnumDecl>(decl)) {
-    addImplicitEnumConformances(ED);
-  }
-}
-
 ProtocolDecl *TypeChecker::getProtocol(SourceLoc loc, KnownProtocolKind kind) {
   auto protocol = Context.getProtocol(kind);
   if (!protocol && loc.isValid()) {
@@ -450,6 +438,10 @@
       else {
         auto *ntd = cast<NominalTypeDecl>(decl);
         TC.checkConformancesInContext(ntd, ntd);
+
+        // Finally, we can check classes for missing initializers.
+        if (auto *classDecl = dyn_cast<ClassDecl>(ntd))
+          TC.maybeDiagnoseClassWithoutInitializers(classDecl);
       }
     }
     TC.ConformanceContexts.clear();
@@ -475,10 +467,8 @@
         TC.checkFunctionErrorHandling(AFD);
         continue;
       }
-      if (isa<NominalTypeDecl>(decl)) {
-        TC.handleExternalDecl(decl);
+      if (isa<NominalTypeDecl>(decl))
         continue;
-      }
       if (isa<VarDecl>(decl))
         continue;
       llvm_unreachable("Unhandled external definition kind");
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 86e2aaf..a1a7169 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -86,35 +86,57 @@
 private:
   /// The set of results found.
   SmallVector<LookupResultEntry, 4> Results;
+  size_t IndexOfFirstOuterResult = 0;
 
 public:
   LookupResult() {}
 
-  explicit
-  LookupResult(const SmallVectorImpl<LookupResultEntry> &Results)
-    : Results(Results.begin(), Results.end()) {}
+  explicit LookupResult(const SmallVectorImpl<LookupResultEntry> &Results,
+                        size_t indexOfFirstOuterResult)
+      : Results(Results.begin(), Results.end()),
+        IndexOfFirstOuterResult(indexOfFirstOuterResult) {}
 
   using iterator = SmallVectorImpl<LookupResultEntry>::iterator;
   iterator begin() { return Results.begin(); }
-  iterator end() { return Results.end(); }
-  unsigned size() const { return Results.size(); }
-  bool empty() const { return Results.empty(); }
+  iterator end() {
+    return Results.begin() + IndexOfFirstOuterResult;
+  }
+  unsigned size() const { return innerResults().size(); }
+  bool empty() const { return innerResults().empty(); }
+
+  ArrayRef<LookupResultEntry> innerResults() const {
+    return llvm::makeArrayRef(Results).take_front(IndexOfFirstOuterResult);
+  }
+
+  ArrayRef<LookupResultEntry> outerResults() const {
+    return llvm::makeArrayRef(Results).drop_front(IndexOfFirstOuterResult);
+  }
 
   const LookupResultEntry& operator[](unsigned index) const {
     return Results[index];
   }
 
-  LookupResultEntry front() const { return Results.front(); }
-  LookupResultEntry back() const { return Results.back(); }
+  LookupResultEntry front() const { return innerResults().front(); }
+  LookupResultEntry back() const { return innerResults().back(); }
 
   /// Add a result to the set of results.
-  void add(LookupResultEntry result) { Results.push_back(result); }
+  void add(LookupResultEntry result, bool isOuter) {
+    Results.push_back(result);
+    if (!isOuter) {
+      IndexOfFirstOuterResult++;
+      assert(IndexOfFirstOuterResult == Results.size() &&
+             "found an outer result before an inner one");
+    } else {
+      assert(IndexOfFirstOuterResult > 0 &&
+             "found outer results without an inner one");
+    }
+  }
 
   void clear() { Results.clear(); }
 
   /// Determine whether the result set is nonempty.
   explicit operator bool() const {
-    return !Results.empty();
+    return !empty();
   }
 
   TypeDecl *getSingleTypeResult() const {
@@ -125,7 +147,8 @@
   }
 
   /// Filter out any results that aren't accepted by the given predicate.
-  void filter(const std::function<bool(LookupResultEntry)> &pred);
+  void
+  filter(const std::function<bool(LookupResultEntry, /*isOuter*/ bool)> &pred);
 };
 
 /// The result of name lookup for types.
@@ -260,6 +283,9 @@
   /// Whether to ignore access control for this lookup, allowing inaccessible
   /// results to be returned.
   IgnoreAccessControl = 0x10,
+  /// Whether to include results from outside the innermost scope that has a
+  /// result.
+  IncludeOuterResults = 0x20,
 };
 
 /// A set of options that control name lookup.
@@ -1535,18 +1561,14 @@
   /// Retrieve the set of inherited protocols for this protocol type.
   llvm::TinyPtrVector<ProtocolDecl *> getDirectConformsTo(ProtocolDecl *proto);
 
+  /// Diagnose if the class has no designated initializers.
+  void maybeDiagnoseClassWithoutInitializers(ClassDecl *classDecl);
+
+  ///
   /// \brief Add any implicitly-defined constructors required for the given
   /// struct or class.
   void addImplicitConstructors(NominalTypeDecl *typeDecl);
 
-  /// \brief Add the RawOptionSet (todo:, Equatable, and Hashable) methods to an
-  /// imported NS_OPTIONS struct.
-  void addImplicitStructConformances(StructDecl *ED);
-
-  /// \brief Add the RawRepresentable, Equatable, and Hashable methods to an
-  /// enum with a raw type.
-  void addImplicitEnumConformances(EnumDecl *ED);
-
   /// Synthesize the member with the given name on the target if applicable,
   /// i.e. if the member is synthesizable and has not yet been added to the
   /// target.
@@ -2269,12 +2291,6 @@
   /// we're parsing the standard library.
   ModuleDecl *getStdlibModule(const DeclContext *dc);
 
-  /// \name AST Mutation Listener Implementation
-  /// @{
-  void handleExternalDecl(Decl *decl);
-
-  /// @}
-
   /// \name Lazy resolution.
   ///
   /// Routines that perform lazy resolution as required for AST operations.
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 896131a..755e38e 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -5309,13 +5309,13 @@
     if (auto syntheticSig = getGenericSignature(*rawIDIter++)) {
       // Create the synthetic environment.
       syntheticEnv = syntheticSig->createGenericEnvironment();
+    }
 
-      // Requirement -> synthetic substitutions.
-      if (unsigned numReqSubstitutions = *rawIDIter++) {
-        while (numReqSubstitutions--) {
-          auto sub = maybeReadSubstitution(DeclTypeCursor, nullptr);
-          reqToSyntheticSubs.push_back(*sub);
-        }
+    // Requirement -> synthetic substitutions.
+    if (unsigned numReqSubstitutions = *rawIDIter++) {
+      while (numReqSubstitutions--) {
+        auto sub = maybeReadSubstitution(DeclTypeCursor, nullptr);
+        reqToSyntheticSubs.push_back(*sub);
       }
     }
 
@@ -5334,13 +5334,6 @@
       continue;
     }
 
-    // Handle simple witnesses.
-    if (witnessSubstitutions.empty() && !syntheticSig && !syntheticEnv &&
-        reqToSyntheticSubs.empty()) {
-      trySetWitness(Witness(witness));
-      continue;
-    }
-
     // Set the witness.
     trySetWitness(Witness(witness, witnessSubstitutions,
                           syntheticEnv, reqToSyntheticSubs));
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 0219e97..ad76558 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1530,19 +1530,17 @@
       // If there is no witness, we're done.
       if (!witness.getDecl()) return;
 
-      if (auto genericEnv = witness.requiresSubstitution() 
-                              ? witness.getSyntheticEnvironment()
-                              : nullptr) {
+      if (auto *genericEnv = witness.getSyntheticEnvironment()) {
         // Generic signature.
         auto *genericSig = genericEnv->getGenericSignature();
         data.push_back(addGenericSignatureRef(genericSig));
-
-        auto reqToSyntheticSubs = witness.getRequirementToSyntheticSubs();
-        data.push_back(reqToSyntheticSubs.size());
       } else {
         data.push_back(/*null generic signature*/0);
       }
 
+      auto reqToSyntheticSubs = witness.getRequirementToSyntheticSubs();
+
+      data.push_back(reqToSyntheticSubs.size());
       data.push_back(witness.getSubstitutions().size());
   });
 
@@ -1568,19 +1566,14 @@
    // Bail out early for simple witnesses.
    if (!witness.getDecl()) return;
 
-   if (witness.requiresSubstitution()) {
-     // Write requirement-to-synthetic substitutions.
-     writeSubstitutions(witness.getRequirementToSyntheticSubs(),
-                        DeclTypeAbbrCodes,
-                        nullptr);
-   }
+   // Write requirement-to-synthetic substitutions.
+   writeSubstitutions(witness.getRequirementToSyntheticSubs(),
+                      DeclTypeAbbrCodes, nullptr);
 
    // Write the witness substitutions.
    writeSubstitutions(witness.getSubstitutions(),
                       DeclTypeAbbrCodes,
-                      witness.requiresSubstitution()
-                        ? witness.getSyntheticEnvironment()
-                        : nullptr);
+                      witness.getSyntheticEnvironment());
   });
 }
 
diff --git a/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt b/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt
index 2776ce4..39e44da 100644
--- a/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt
+++ b/stdlib/private/StdlibCollectionUnittest/CMakeLists.txt
@@ -7,15 +7,15 @@
   # filename.
   StdlibCollectionUnittest.swift
 
-  CheckCollectionInstance.swift.gyb
-  CheckCollectionType.swift.gyb
-  CheckMutableCollectionType.swift.gyb
+  CheckCollectionInstance.swift
+  CheckCollectionType.swift
+  CheckMutableCollectionType.swift
   CheckRangeReplaceableCollectionType.swift
   CheckRangeReplaceableSliceType.swift
-  CheckSequenceInstance.swift.gyb
+  CheckSequenceInstance.swift
   CheckSequenceType.swift
-  LoggingWrappers.swift.gyb
-  MinimalCollections.swift.gyb
+  LoggingWrappers.swift
+  MinimalCollections.swift
   RangeSelection.swift
   ../../public/core/WriteBackMutableSlice.swift
 
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift
new file mode 100644
index 0000000..b6c2876
--- /dev/null
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift
@@ -0,0 +1,1917 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import StdlibUnittest
+
+public struct CollectionMisuseResiliencyChecks {
+  public enum FailureKind {
+    case none
+    case trap
+  }
+
+  public var creatingOutOfBoundsIndicesBehavior: FailureKind = .trap
+  public var subscriptOnOutOfBoundsIndicesBehavior: FailureKind = .trap
+  public var subscriptRangeOnOutOfBoundsRangesBehavior: FailureKind = .trap
+
+  public static var all: CollectionMisuseResiliencyChecks {
+    return CollectionMisuseResiliencyChecks()
+  }
+
+  public static var none: CollectionMisuseResiliencyChecks {
+    return CollectionMisuseResiliencyChecks(
+      creatingOutOfBoundsIndicesBehavior: .none,
+      subscriptOnOutOfBoundsIndicesBehavior: .none,
+      subscriptRangeOnOutOfBoundsRangesBehavior: .none)
+  }
+}
+
+
+/// Test that the elements of `instances` satisfy
+/// the semantic
+/// requirements of `Collection`, using `equalityOracle` to
+/// generate equality expectations from pairs of positions in
+/// `instances`.
+///
+/// - Precondition: `endIndex` is reachable from all
+///   elements of `instances`.
+public func checkIncrementable<Instances, BaseCollection>(
+  _ instances: Instances,
+  of baseCollection: BaseCollection,
+  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+  endIndex: Instances.Element,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  Instances : Collection,
+  BaseCollection : Collection,
+  Instances.Element == BaseCollection.Index {
+
+  checkEquatable(instances, oracle: equalityOracle, message(),
+  stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  for i in instances {
+    if i != endIndex {
+      let next = baseCollection.index(after: i)
+      // index(after:) gets us a new index value
+      expectNotEqual(i, next, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+      // Which is the same as if we apply formIndex(after:)
+      var j = i
+      baseCollection.formIndex(after: &j)
+      expectEqual(j, next, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+    }
+  }
+}
+
+/// Test that the elements of `instances` satisfy
+/// some of the semantic
+/// requirements of `BidirectionalCollection`, using `equalityOracle` to
+/// generate equality expectations from pairs of positions in
+/// `instances`.
+///
+/// - Precondition: all
+///   elements of `instances` are reachable from `startIndex`.
+public func checkDecrementable<Instances, BaseCollection>(
+  _ instances: Instances,
+  of baseCollection: BaseCollection,
+  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+  startIndex: Instances.Element,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  Instances : Collection,
+  BaseCollection : BidirectionalCollection,
+  Instances.Element == BaseCollection.Index {
+
+  checkEquatable(instances, oracle: equalityOracle, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  for i in instances {
+    if i != startIndex {
+      let next = baseCollection.index(before: i)
+      // index(before:) gets us a new index value
+      expectNotEqual(i, next, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+      // Which is the same as if we apply formIndex(before:)
+      var j = i
+      baseCollection.formIndex(before: &j)
+      expectEqual(j, next, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+    }
+  }
+}
+
+internal func _checkIncrementalAdvance<Instances, BaseCollection>(
+  _ instances: Instances,
+  of baseCollection : BaseCollection,
+  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+  limit: Instances.Element,
+  sign: Int, // 1 or -1
+  next: (Instances.Element) -> Instances.Element,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  Instances : Collection,
+  BaseCollection : Collection,
+  Instances.Element == BaseCollection.Index {
+  for i in instances {
+    let d: Int = sign > 0 ?
+      baseCollection.distance(from: i, to: limit) :
+      -baseCollection.distance(from: limit, to: i)
+
+    var offset: Int = 0
+    for _ in 0...Int64(d * sign) {
+      let j = baseCollection.index(i, offsetBy: offset)
+      let k = baseCollection.index(i, offsetBy: offset + sign, limitedBy: limit) ?? limit
+      let jAtLimit = offset == d
+      if jAtLimit {
+        expectEqual(limit, j, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      }
+      expectEqual(jAtLimit ? j : next(j), k, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      offset += sign
+    }
+  }
+}
+
+/// Test that the elements of `instances` satisfy the semantic requirements of
+/// index for `Collection`, using `equalityOracle` to generate equality
+/// expectations from pairs of positions in `instances`.
+///
+/// - Precondition: `endIndex` is reachable from all elements of
+///   `instances`
+public func checkForwardIndex<Instances, BaseCollection>(
+  _ instances: Instances,
+  of baseCollection: BaseCollection,
+  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+  endIndex: Instances.Element,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  Instances : Collection,
+  BaseCollection : Collection,
+  Instances.Element == BaseCollection.Index {
+
+  checkIncrementable(instances, of: baseCollection,
+    equalityOracle: equalityOracle, endIndex: endIndex, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  _checkIncrementalAdvance(instances, of: baseCollection,
+    equalityOracle: equalityOracle, limit: endIndex,
+    sign: 1, next: { baseCollection.index(after: $0) }, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+}
+
+/// Test that the elements of `instances` satisfy the semantic requirements of
+/// index for `BidirectionalCollection`, using `equalityOracle` to generate
+/// equality expectations from pairs of positions in `instances`.
+///
+/// - Precondition:
+///   - all elements of `instances` are reachable from `startIndex`.
+///   - `endIndex` is reachable from all elements of `instances`.
+public func checkBidirectionalIndex<Instances, BaseCollection>(
+  _ instances: Instances,
+  of baseCollection: BaseCollection,
+  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+  startIndex: Instances.Element,
+  endIndex: Instances.Element,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  Instances: Collection,
+  BaseCollection : BidirectionalCollection,
+  Instances.Element == BaseCollection.Index {
+
+  checkForwardIndex(instances, of: baseCollection,
+    equalityOracle: equalityOracle, endIndex: endIndex)
+
+  checkDecrementable(instances, of: baseCollection,
+    equalityOracle: equalityOracle, startIndex: startIndex, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  _checkIncrementalAdvance(instances, of: baseCollection,
+    equalityOracle: equalityOracle, limit: startIndex,
+    sign: -1, next: { baseCollection.index(before: $0) }, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+}
+
+/// Test that the elements of `instances` satisfy the semantic requirements of
+/// index for `RandomAccessCollection`, using `advanceOracle` and
+/// 'distanceOracle' to generate expectations about the results of
+/// `advanced(by:)` and `distance(to:)` from pairs of positions in `instances`
+/// and `distances`.
+///
+/// - Precondition:
+///   - all elements of `instances` are reachable from `startIndex`.
+///   - `endIndex` is reachable from all elements of `instances`.
+public func checkRandomAccessIndex<Instances, Distances, BaseCollection>(
+  _ instances: Instances, distances: Distances,
+  of baseCollection: BaseCollection,
+  distanceOracle:
+    (Instances.Index, Instances.Index) -> Distances.Element,
+  advanceOracle:
+    (Instances.Index, Distances.Index) -> Instances.Element,
+  startIndex: Instances.Iterator.Element,
+  endIndex: Instances.Iterator.Element,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  Instances : Collection,
+  Distances : Collection,
+  BaseCollection : RandomAccessCollection,
+  Instances.Element == BaseCollection.Index,
+  Distances.Element == Int {
+
+  checkBidirectionalIndex(instances, of: baseCollection,
+    equalityOracle: { distanceOracle($0, $1) == 0 },
+    startIndex: startIndex, endIndex: endIndex, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  checkAdvancesAndDistances(
+    instances, distances: distances,
+    of: baseCollection,
+    distanceOracle: distanceOracle,
+    advanceOracle: advanceOracle, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+}
+
+// Copies what checkStrideable is doing, but instead of calling
+// advanced(by:) and distance(to:) on an Strideable's,
+// calls corresponding methods on a base collection.
+public func checkAdvancesAndDistances<Instances, Distances, BaseCollection>(
+  _ instances: Instances, distances: Distances,
+  of baseCollection: BaseCollection,
+  distanceOracle:
+    (Instances.Index, Instances.Index) -> Distances.Element,
+  advanceOracle:
+    (Instances.Index, Distances.Index) -> Instances.Element,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  Instances : Collection,
+  Distances : Collection,
+  BaseCollection : Collection,
+  Instances.Element == BaseCollection.Index,
+  Distances.Element == Int {
+
+  checkComparable(
+    instances,
+    oracle: {
+      let d = distanceOracle($1, $0);
+      return d < 0 ? .lt : d == 0 ? .eq : .gt
+    },
+    message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  for i in instances.indices {
+    let x = instances[i]
+    expectEqual(x, baseCollection.index(x, offsetBy: 0))
+
+    for j in distances.indices {
+      let y = distances[j]
+      expectEqual(advanceOracle(i, j), baseCollection.index(x, offsetBy: y))
+    }
+
+    for j in instances.indices {
+      let y = instances[j]
+      expectEqual(distanceOracle(i, j), baseCollection.distance(from: x, to: y))
+    }
+  }
+}
+
+// Generate two overloads: one for Array (which will get
+// picked up when the caller passes a literal), and another that
+// accepts any appropriate Collection type.
+
+// Top-level check for Collection instances. Alias for checkForwardCollection.
+// Checks all slices: O(n^2).
+public func checkCollection<Expected: Collection, C : Collection>(
+  _ expected: Expected,
+  _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where C.Element == Expected.Element {
+
+  checkForwardCollection(expected, collection, message(),
+    stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
+    resiliencyChecks: resiliencyChecks,
+    sameValue: sameValue)
+}
+
+
+// Calls checkForwardCollection with default `sameValue`.
+public func checkForwardCollection<
+  Expected: Collection, C : Collection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+  C.Element == Expected.Element,
+  Expected.Element : Equatable {
+
+  checkForwardCollection(
+    expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all Collection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkForwardCollection<
+  Expected: Collection, C : Collection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+  C.Element == Expected.Element {
+
+  checkOneLevelOfForwardCollection(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+  // Avoid validation of all possible (n^2) slices on large collection.
+  // Test cases should call checkOneLevelOfForwardCollection instead.
+  expectLT(expected.count, 30)
+
+  _checkSliceableWithForwardIndex(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkForwardCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `Collection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfForwardCollection<
+  Expected: Collection, C : Collection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where C.Element == Expected.Element {
+
+  // A `Collection` is a multi-pass `Sequence`.
+  for _ in 0..<3 {
+    checkSequence(
+      expected, collection, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+      resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+  }
+
+  //===------------------------------------------------------------------===//
+  // Check Index semantics
+  //===------------------------------------------------------------------===//
+
+  let succ = { collection.index(after: $0) }
+  // Advances up to 1 positions without passing endIndex.  Don't use
+  // advanced(by: n) to do this because it's under test here.
+  let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+  // advances up to 5 positions without passing endIndex.  Picking a
+  // small constant to avoid complexity explosion on large input
+  // collections.
+  let next5 = { next(next(next(next(next($0))))) }
+
+  let partWay0 = next5(collection.startIndex)
+  let partWay1 = next5(partWay0)
+
+
+  let instances = _allIndices(into: collection,
+    in: collection.startIndex..<partWay0)
+  checkForwardIndex(instances, of: collection,
+    equalityOracle: { $0 == $1 }, endIndex: partWay1, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+  let expectedArray = Array(expected)
+
+  // Check `count`.
+  expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  //===------------------------------------------------------------------===//
+  // Check Iteration behavior.
+  //===------------------------------------------------------------------===//
+
+  for _ in 0..<3 {
+    do {
+      let startIndex = collection.startIndex
+      let endIndex = collection.endIndex
+
+      for _ in collection.indices {
+        expectEqual(
+          startIndex, collection.startIndex,
+          "Iteration should not change startIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+        expectEqual(
+          endIndex, collection.endIndex,
+          "Iteration should not change endIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      }
+    }
+
+    var allIndices = Array(collection.indices)
+
+    if expectedArray.count >= 2 {
+      for i in 0..<allIndices.count-1 {
+        let successor1 = succ(allIndices[i])
+        var successor2 = allIndices[i]
+        successor2 = succ(successor2)
+        var successor3 = allIndices[i]
+        successor3 = succ(successor3)
+        for s in [ successor1, successor2, successor3 ] {
+          expectEqual(allIndices[i + 1], s, message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+          expectEqualTest(
+            expectedArray[i + 1], collection[s], message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+        }
+      }
+
+
+    } // end of `if expectedArray.count >= 2`
+
+    do {
+      var allIndices2: [C.Index] = []
+      for i in collection.indices {
+        allIndices2.append(i)
+      }
+
+      expectEqualSequence(
+        allIndices, allIndices2, "iteration should not invalidate indices",
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+      expectEqualSequence(
+        expectedArray, allIndices.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+      expectEqualSequence(
+        expectedArray, allIndices2.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+    }
+  } // end of `for _ in 0..<3`
+
+  // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkForwardCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithForwardIndex<
+Expected: Collection, S : Collection
+>(
+  _ expected: Expected, _ sliceable: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+  S.Element == Expected.Element {
+
+  let expectedArray = Array(expected)
+
+  let succ = { sliceable.index(after: $0) }
+
+  var start = sliceable.startIndex
+  for startNumericIndex in 0...expectedArray.count {
+    var end = start
+    for endNumericIndex in startNumericIndex...expectedArray.count {
+      let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+      let slice = sliceable[start..<end]
+      // For every possible slice, verify that the slice's bounds are identical
+      // to the indices used to form the slice.
+      expectEqual(start, slice.startIndex)
+      expectEqual(end, slice.endIndex)
+
+      checkOneLevelOfForwardCollection(expectedSlice, slice, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+        resiliencyChecks: resiliencyChecks,
+        sameValue: sameValue)
+
+      if end != sliceable.endIndex {
+        end = succ(end)
+      }
+    }
+    if start != sliceable.endIndex {
+      start = succ(start)
+    }
+  }
+}
+
+
+// Calls checkBidirectionalCollection with default `sameValue`.
+public func checkBidirectionalCollection<
+  Expected: Collection, C : BidirectionalCollection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+  C.Element == Expected.Element,
+  Expected.Element : Equatable {
+
+  checkBidirectionalCollection(
+    expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all BidirectionalCollection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkBidirectionalCollection<
+  Expected: Collection, C : BidirectionalCollection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+  C.Element == Expected.Element {
+
+  checkOneLevelOfBidirectionalCollection(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+  // Avoid validation of all possible (n^2) slices on large collection.
+  // Test cases should call checkOneLevelOfBidirectionalCollection instead.
+  expectLT(expected.count, 30)
+
+  _checkSliceableWithBidirectionalIndex(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkBidirectionalCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `BidirectionalCollection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfBidirectionalCollection<
+  Expected: Collection, C : BidirectionalCollection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where C.Element == Expected.Element {
+
+  // A `Collection` is a multi-pass `Sequence`.
+  for _ in 0..<3 {
+    checkSequence(
+      expected, collection, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+      resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+  }
+
+  //===------------------------------------------------------------------===//
+  // Check Index semantics
+  //===------------------------------------------------------------------===//
+
+  let succ = { collection.index(after: $0) }
+  let pred = { collection.index(before: $0) }
+  // Advances up to 1 positions without passing endIndex.  Don't use
+  // advanced(by: n) to do this because it's under test here.
+  let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+  // advances up to 5 positions without passing endIndex.  Picking a
+  // small constant to avoid complexity explosion on large input
+  // collections.
+  let next5 = { next(next(next(next(next($0))))) }
+
+  let partWay0 = next5(collection.startIndex)
+  let partWay1 = next5(partWay0)
+
+
+  let instances = _allIndices(into: collection, in: partWay0..<partWay1)
+  checkBidirectionalIndex(instances, of: collection,
+    equalityOracle: { $0 == $1 },
+    startIndex: collection.startIndex,
+    endIndex: next5(partWay1), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+  let expectedArray = Array(expected)
+
+  // Check `count`.
+  expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  //===------------------------------------------------------------------===//
+  // Check Iteration behavior.
+  //===------------------------------------------------------------------===//
+
+  for _ in 0..<3 {
+    do {
+      let startIndex = collection.startIndex
+      let endIndex = collection.endIndex
+
+      for _ in collection.indices {
+        expectEqual(
+          startIndex, collection.startIndex,
+          "Iteration should not change startIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+        expectEqual(
+          endIndex, collection.endIndex,
+          "Iteration should not change endIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      }
+    }
+
+    var allIndices = Array(collection.indices)
+
+    if expectedArray.count >= 2 {
+      for i in 0..<allIndices.count-1 {
+        let successor1 = succ(allIndices[i])
+        var successor2 = allIndices[i]
+        successor2 = succ(successor2)
+        var successor3 = allIndices[i]
+        successor3 = succ(successor3)
+        for s in [ successor1, successor2, successor3 ] {
+          expectEqual(allIndices[i + 1], s, message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+          expectEqualTest(
+            expectedArray[i + 1], collection[s], message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+        }
+      }
+
+
+      for i in 1..<allIndices.count {
+        let predecessor1 = pred(allIndices[i])
+        var predecessor2 = allIndices[i]
+        predecessor2 = pred(predecessor2)
+        var predecessor3 = allIndices[i]
+        predecessor3 = pred(predecessor3)
+        for p in [ predecessor1, predecessor2, predecessor3 ] {
+          expectEqual(allIndices[i - 1], p, message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+          expectEqualTest(
+            expectedArray[i - 1], collection[p], message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+        }
+      }
+      for i in 1..<allIndices.count {
+        let index = succ(pred(allIndices[i]))
+        expectEqual(allIndices[i], index, message(),
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+        expectEqualTest(
+          expectedArray[i], collection[index], message(),
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+      }
+
+
+    } // end of `if expectedArray.count >= 2`
+
+    do {
+      var allIndices2: [C.Index] = []
+      for i in collection.indices {
+        allIndices2.append(i)
+      }
+
+      expectEqualSequence(
+        allIndices, allIndices2, "iteration should not invalidate indices",
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+      expectEqualSequence(
+        expectedArray, allIndices.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+      expectEqualSequence(
+        expectedArray, allIndices2.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+    }
+  } // end of `for _ in 0..<3`
+
+  // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkBidirectionalCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithBidirectionalIndex<
+Expected: Collection, S : BidirectionalCollection
+>(
+  _ expected: Expected, _ sliceable: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+  S.Element == Expected.Element {
+
+  let expectedArray = Array(expected)
+
+  let succ = { sliceable.index(after: $0) }
+  let pred = { sliceable.index(before: $0) }
+
+  var start = sliceable.startIndex
+  for startNumericIndex in 0...expectedArray.count {
+    if start != sliceable.endIndex {
+      start = succ(start)
+      start = pred(start)
+      start = succ(start)
+      start = pred(start)
+    }
+    var end = start
+    for endNumericIndex in startNumericIndex...expectedArray.count {
+      if end != sliceable.endIndex {
+        end = succ(end)
+        end = pred(end)
+        end = succ(end)
+        end = pred(end)
+      }
+      let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+      let slice = sliceable[start..<end]
+      // For every possible slice, verify that the slice's bounds are identical
+      // to the indices used to form the slice.
+      expectEqual(start, slice.startIndex)
+      expectEqual(end, slice.endIndex)
+
+      checkOneLevelOfBidirectionalCollection(expectedSlice, slice, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+        resiliencyChecks: resiliencyChecks,
+        sameValue: sameValue)
+
+      if end != sliceable.endIndex {
+        end = succ(end)
+      }
+    }
+    if start != sliceable.endIndex {
+      start = succ(start)
+    }
+  }
+}
+
+
+// Calls checkRandomAccessCollection with default `sameValue`.
+public func checkRandomAccessCollection<
+  Expected: Collection, C : RandomAccessCollection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+  C.Element == Expected.Element,
+  Expected.Element : Equatable {
+
+  checkRandomAccessCollection(
+    expected, collection, message(),
+  stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all RandomAccessCollection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkRandomAccessCollection<
+  Expected: Collection, C : RandomAccessCollection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+  C.Element == Expected.Element {
+
+  checkOneLevelOfRandomAccessCollection(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+  // Avoid validation of all possible (n^2) slices on large collection.
+  // Test cases should call checkOneLevelOfRandomAccessCollection instead.
+  expectLT(expected.count, 30)
+
+  _checkSliceableWithRandomAccessIndex(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkRandomAccessCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `RandomAccessCollection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfRandomAccessCollection<
+  Expected: Collection, C : RandomAccessCollection
+>(
+  _ expected: Expected, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where C.Element == Expected.Element {
+
+  // A `Collection` is a multi-pass `Sequence`.
+  for _ in 0..<3 {
+    checkSequence(
+      expected, collection, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+      resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+  }
+
+  //===------------------------------------------------------------------===//
+  // Check Index semantics
+  //===------------------------------------------------------------------===//
+
+  let succ = { collection.index(after: $0) }
+  let pred = { collection.index(before: $0) }
+  // Advances up to 1 positions without passing endIndex.  Don't use
+  // advanced(by: n) to do this because it's under test here.
+  let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+  // advances up to 5 positions without passing endIndex.  Picking a
+  // small constant to avoid complexity explosion on large input
+  // collections.
+  let next5 = { next(next(next(next(next($0))))) }
+
+  let partWay0 = next5(collection.startIndex)
+  let partWay1 = next5(partWay0)
+
+  typealias Distance = Int
+
+  let count: Distance  = collection.count
+  let offset0 = min(5, count)
+  let offset1 = min(10, count)
+  let offset2 = min(15, count)
+
+  let distanceCandidates: [Distance] = [
+    -11, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 11]
+
+  let distances = distanceCandidates.filter { (x: Distance) -> Bool in
+    x + offset0 >= 0 && x + offset1 <= count
+  }
+
+  func nextN(_ n: Distance, _ i: C.Index) -> C.Index {
+    return collection.index(i, offsetBy: n)
+  }
+
+  let instances = _allIndices(into: collection, in: partWay0..<partWay1)
+
+  checkRandomAccessIndex(
+    instances,
+    distances: distances,
+    of: collection,
+    distanceOracle: { (x:Int, y:Int) in numericCast(y - x) },
+    advanceOracle: { x, y in nextN(distances[y], instances[x]) },
+    startIndex: collection.startIndex,
+    endIndex: next5(partWay1), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+  let expectedArray = Array(expected)
+
+  // Check `count`.
+  expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  //===------------------------------------------------------------------===//
+  // Check Iteration behavior.
+  //===------------------------------------------------------------------===//
+
+  for _ in 0..<3 {
+    do {
+      let startIndex = collection.startIndex
+      let endIndex = collection.endIndex
+
+      for _ in collection.indices {
+        expectEqual(
+          startIndex, collection.startIndex,
+          "Iteration should not change startIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+        expectEqual(
+          endIndex, collection.endIndex,
+          "Iteration should not change endIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      }
+    }
+
+    var allIndices = Array(collection.indices)
+
+    if expectedArray.count >= 2 {
+      for i in 0..<allIndices.count-1 {
+        let successor1 = succ(allIndices[i])
+        var successor2 = allIndices[i]
+        successor2 = succ(successor2)
+        var successor3 = allIndices[i]
+        successor3 = succ(successor3)
+        for s in [ successor1, successor2, successor3 ] {
+          expectEqual(allIndices[i + 1], s, message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+          expectEqualTest(
+            expectedArray[i + 1], collection[s], message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+        }
+      }
+
+
+    } // end of `if expectedArray.count >= 2`
+
+    do {
+      var allIndices2: [C.Index] = []
+      for i in collection.indices {
+        allIndices2.append(i)
+      }
+
+      expectEqualSequence(
+        allIndices, allIndices2, "iteration should not invalidate indices",
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+      expectEqualSequence(
+        expectedArray, allIndices.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+      expectEqualSequence(
+        expectedArray, allIndices2.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+    }
+  } // end of `for _ in 0..<3`
+
+  // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkRandomAccessCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithRandomAccessIndex<
+Expected: Collection, S : RandomAccessCollection
+>(
+  _ expected: Expected, _ sliceable: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Element, Expected.Element) -> Bool
+) where
+  S.Element == Expected.Element {
+
+  let expectedArray = Array(expected)
+
+  let succ = { sliceable.index(after: $0) }
+  let pred = { sliceable.index(before: $0) }
+
+  var start = sliceable.startIndex
+  for startNumericIndex in 0...expectedArray.count {
+    if start != sliceable.endIndex {
+      start = succ(start)
+      start = pred(start)
+      start = succ(start)
+      start = pred(start)
+    }
+    var end = start
+    for endNumericIndex in startNumericIndex...expectedArray.count {
+      if end != sliceable.endIndex {
+        end = succ(end)
+        end = pred(end)
+        end = succ(end)
+        end = pred(end)
+      }
+      let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+      let slice = sliceable[start..<end]
+      // For every possible slice, verify that the slice's bounds are identical
+      // to the indices used to form the slice.
+      expectEqual(start, slice.startIndex)
+      expectEqual(end, slice.endIndex)
+
+      checkOneLevelOfRandomAccessCollection(expectedSlice, slice, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+        resiliencyChecks: resiliencyChecks,
+        sameValue: sameValue)
+
+      if end != sliceable.endIndex {
+        end = succ(end)
+      }
+    }
+    if start != sliceable.endIndex {
+      start = succ(start)
+    }
+  }
+}
+
+
+
+// Top-level check for Collection instances. Alias for checkForwardCollection.
+// Checks all slices: O(n^2).
+public func checkCollection<Element, C : Collection>(
+  _ expected: Array<Element>,
+  _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where C.Element == Element {
+
+  checkForwardCollection(expected, collection, message(),
+    stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
+    resiliencyChecks: resiliencyChecks,
+    sameValue: sameValue)
+}
+
+
+// Calls checkForwardCollection with default `sameValue`.
+public func checkForwardCollection<
+  Element, C : Collection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+  C.Element == Element,
+  Element : Equatable {
+
+  checkForwardCollection(
+    expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all Collection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkForwardCollection<
+  Element, C : Collection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where
+  C.Element == Element {
+
+  checkOneLevelOfForwardCollection(expected, collection, message(),
+  stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+  // Avoid validation of all possible (n^2) slices on large collection.
+  // Test cases should call checkOneLevelOfForwardCollection instead.
+  expectLT(expected.count, 30)
+
+  _checkSliceableWithForwardIndex(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkForwardCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `Collection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfForwardCollection<
+  Element, C : Collection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where C.Element == Element {
+
+  // A `Collection` is a multi-pass `Sequence`.
+  for _ in 0..<3 {
+    checkSequence(
+      expected, collection, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+      resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+  }
+
+  //===------------------------------------------------------------------===//
+  // Check Index semantics
+  //===------------------------------------------------------------------===//
+
+  let succ = { collection.index(after: $0) }
+  // Advances up to 1 positions without passing endIndex.  Don't use
+  // advanced(by: n) to do this because it's under test here.
+  let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+  // advances up to 5 positions without passing endIndex.  Picking a
+  // small constant to avoid complexity explosion on large input
+  // collections.
+  let next5 = { next(next(next(next(next($0))))) }
+
+  let partWay0 = next5(collection.startIndex)
+  let partWay1 = next5(partWay0)
+
+
+  let instances = _allIndices(into: collection,
+    in: collection.startIndex..<partWay0)
+  checkForwardIndex(instances, of: collection,
+    equalityOracle: { $0 == $1 }, endIndex: partWay1, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+  let expectedArray = Array(expected)
+
+  // Check `count`.
+  expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  //===------------------------------------------------------------------===//
+  // Check Iteration behavior.
+  //===------------------------------------------------------------------===//
+
+  for _ in 0..<3 {
+    do {
+      let startIndex = collection.startIndex
+      let endIndex = collection.endIndex
+
+      for _ in collection.indices {
+        expectEqual(
+          startIndex, collection.startIndex,
+          "Iteration should not change startIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+        expectEqual(
+          endIndex, collection.endIndex,
+          "Iteration should not change endIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      }
+    }
+
+    var allIndices = Array(collection.indices)
+
+    if expectedArray.count >= 2 {
+      for i in 0..<allIndices.count-1 {
+        let successor1 = succ(allIndices[i])
+        var successor2 = allIndices[i]
+        successor2 = succ(successor2)
+        var successor3 = allIndices[i]
+        successor3 = succ(successor3)
+        for s in [ successor1, successor2, successor3 ] {
+          expectEqual(allIndices[i + 1], s, message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+          expectEqualTest(
+            expectedArray[i + 1], collection[s], message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+        }
+      }
+
+
+    } // end of `if expectedArray.count >= 2`
+
+    do {
+      var allIndices2: [C.Index] = []
+      for i in collection.indices {
+        allIndices2.append(i)
+      }
+
+      expectEqualSequence(
+        allIndices, allIndices2, "iteration should not invalidate indices",
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+      expectEqualSequence(
+        expectedArray, allIndices.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+      expectEqualSequence(
+        expectedArray, allIndices2.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+    }
+  } // end of `for _ in 0..<3`
+
+  // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkForwardCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithForwardIndex<
+Element, S : Collection
+>(
+  _ expected: Array<Element>, _ sliceable: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where
+  S.Element == Element {
+
+  let expectedArray = Array(expected)
+
+  let succ = { sliceable.index(after: $0) }
+
+  var start = sliceable.startIndex
+  for startNumericIndex in 0...expectedArray.count {
+    var end = start
+    for endNumericIndex in startNumericIndex...expectedArray.count {
+      let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+      let slice = sliceable[start..<end]
+      // For every possible slice, verify that the slice's bounds are identical
+      // to the indices used to form the slice.
+      expectEqual(start, slice.startIndex)
+      expectEqual(end, slice.endIndex)
+
+      checkOneLevelOfForwardCollection(expectedSlice, slice, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+        resiliencyChecks: resiliencyChecks,
+        sameValue: sameValue)
+
+      if end != sliceable.endIndex {
+        end = succ(end)
+      }
+    }
+    if start != sliceable.endIndex {
+      start = succ(start)
+    }
+  }
+}
+
+
+// Calls checkBidirectionalCollection with default `sameValue`.
+public func checkBidirectionalCollection<
+  Element, C : BidirectionalCollection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+  C.Element == Element,
+  Element : Equatable {
+
+  checkBidirectionalCollection(
+    expected, collection, message(),
+  stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all BidirectionalCollection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkBidirectionalCollection<
+  Element, C : BidirectionalCollection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where
+  C.Element == Element {
+
+  checkOneLevelOfBidirectionalCollection(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+  // Avoid validation of all possible (n^2) slices on large collection.
+  // Test cases should call checkOneLevelOfBidirectionalCollection instead.
+  expectLT(expected.count, 30)
+
+  _checkSliceableWithBidirectionalIndex(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkBidirectionalCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `BidirectionalCollection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfBidirectionalCollection<
+  Element, C : BidirectionalCollection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where C.Element == Element {
+
+  // A `Collection` is a multi-pass `Sequence`.
+  for _ in 0..<3 {
+    checkSequence(
+      expected, collection, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+      resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+  }
+
+  //===------------------------------------------------------------------===//
+  // Check Index semantics
+  //===------------------------------------------------------------------===//
+
+  let succ = { collection.index(after: $0) }
+  let pred = { collection.index(before: $0) }
+  // Advances up to 1 positions without passing endIndex.  Don't use
+  // advanced(by: n) to do this because it's under test here.
+  let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+  // advances up to 5 positions without passing endIndex.  Picking a
+  // small constant to avoid complexity explosion on large input
+  // collections.
+  let next5 = { next(next(next(next(next($0))))) }
+
+  let partWay0 = next5(collection.startIndex)
+  let partWay1 = next5(partWay0)
+
+
+  let instances = _allIndices(into: collection, in: partWay0..<partWay1)
+  checkBidirectionalIndex(instances, of: collection,
+    equalityOracle: { $0 == $1 },
+    startIndex: collection.startIndex,
+    endIndex: next5(partWay1), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+  let expectedArray = Array(expected)
+
+  // Check `count`.
+  expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  //===------------------------------------------------------------------===//
+  // Check Iteration behavior.
+  //===------------------------------------------------------------------===//
+
+  for _ in 0..<3 {
+    do {
+      let startIndex = collection.startIndex
+      let endIndex = collection.endIndex
+
+      for _ in collection.indices {
+        expectEqual(
+          startIndex, collection.startIndex,
+          "Iteration should not change startIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+        expectEqual(
+          endIndex, collection.endIndex,
+          "Iteration should not change endIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      }
+    }
+
+    var allIndices = Array(collection.indices)
+
+    if expectedArray.count >= 2 {
+      for i in 0..<allIndices.count-1 {
+        let successor1 = succ(allIndices[i])
+        var successor2 = allIndices[i]
+        successor2 = succ(successor2)
+        var successor3 = allIndices[i]
+        successor3 = succ(successor3)
+        for s in [ successor1, successor2, successor3 ] {
+          expectEqual(allIndices[i + 1], s, message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+          expectEqualTest(
+            expectedArray[i + 1], collection[s], message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+        }
+      }
+
+
+      for i in 1..<allIndices.count {
+        let predecessor1 = pred(allIndices[i])
+        var predecessor2 = allIndices[i]
+        predecessor2 = pred(predecessor2)
+        var predecessor3 = allIndices[i]
+        predecessor3 = pred(predecessor3)
+        for p in [ predecessor1, predecessor2, predecessor3 ] {
+          expectEqual(allIndices[i - 1], p, message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+          expectEqualTest(
+            expectedArray[i - 1], collection[p], message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+        }
+      }
+      for i in 1..<allIndices.count {
+        let index = succ(pred(allIndices[i]))
+        expectEqual(allIndices[i], index, message(),
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+        expectEqualTest(
+          expectedArray[i], collection[index], message(),
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+      }
+
+
+    } // end of `if expectedArray.count >= 2`
+
+    do {
+      var allIndices2: [C.Index] = []
+      for i in collection.indices {
+        allIndices2.append(i)
+      }
+
+      expectEqualSequence(
+        allIndices, allIndices2, "iteration should not invalidate indices",
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+      expectEqualSequence(
+        expectedArray, allIndices.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+      expectEqualSequence(
+        expectedArray, allIndices2.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+    }
+  } // end of `for _ in 0..<3`
+
+  // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkBidirectionalCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithBidirectionalIndex<
+Element, S : BidirectionalCollection
+>(
+  _ expected: Array<Element>, _ sliceable: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where
+  S.Element == Element {
+
+  let expectedArray = Array(expected)
+
+  let succ = { sliceable.index(after: $0) }
+  let pred = { sliceable.index(before: $0) }
+
+  var start = sliceable.startIndex
+  for startNumericIndex in 0...expectedArray.count {
+    if start != sliceable.endIndex {
+      start = succ(start)
+      start = pred(start)
+      start = succ(start)
+      start = pred(start)
+    }
+    var end = start
+    for endNumericIndex in startNumericIndex...expectedArray.count {
+      if end != sliceable.endIndex {
+        end = succ(end)
+        end = pred(end)
+        end = succ(end)
+        end = pred(end)
+      }
+      let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+      let slice = sliceable[start..<end]
+      // For every possible slice, verify that the slice's bounds are identical
+      // to the indices used to form the slice.
+      expectEqual(start, slice.startIndex)
+      expectEqual(end, slice.endIndex)
+
+      checkOneLevelOfBidirectionalCollection(expectedSlice, slice, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+        resiliencyChecks: resiliencyChecks,
+        sameValue: sameValue)
+
+      if end != sliceable.endIndex {
+        end = succ(end)
+      }
+    }
+    if start != sliceable.endIndex {
+      start = succ(start)
+    }
+  }
+}
+
+
+// Calls checkRandomAccessCollection with default `sameValue`.
+public func checkRandomAccessCollection<
+  Element, C : RandomAccessCollection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+  C.Element == Element,
+  Element : Equatable {
+
+  checkRandomAccessCollection(
+    expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks) { $0 == $1 }
+}
+
+// Top-Level check for all RandomAccessCollection semantics on a single
+// instance. This constrains SubSequence associated types in order to check
+// slice semantics.
+// Checks all slices: O(n^2).
+public func checkRandomAccessCollection<
+  Element, C : RandomAccessCollection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where
+  C.Element == Element {
+
+  checkOneLevelOfRandomAccessCollection(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+
+  // Avoid validation of all possible (n^2) slices on large collection.
+  // Test cases should call checkOneLevelOfRandomAccessCollection instead.
+  expectLT(expected.count, 30)
+
+  _checkSliceableWithRandomAccessIndex(expected, collection, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+}
+
+// Helper for checkRandomAccessCollection. Check that instance of `C`,
+// `collection`, upholds the semantics of `RandomAccessCollection`,
+// non-recursively. This does not check subsequences. It may be called for each
+// subsequence without combinatorial explosion. Also, since recursive protocol
+// constraints are not supported, our second level of checks cannot depend on the
+// associated type properties of SubSequence.
+//
+// Checks all slices: O(n^2).
+public func checkOneLevelOfRandomAccessCollection<
+  Element, C : RandomAccessCollection
+>(
+  _ expected: Array<Element>, _ collection: C,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where C.Element == Element {
+
+  // A `Collection` is a multi-pass `Sequence`.
+  for _ in 0..<3 {
+    checkSequence(
+      expected, collection, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+      resiliencyChecks: resiliencyChecks, sameValue: sameValue)
+  }
+
+  //===------------------------------------------------------------------===//
+  // Check Index semantics
+  //===------------------------------------------------------------------===//
+
+  let succ = { collection.index(after: $0) }
+  let pred = { collection.index(before: $0) }
+  // Advances up to 1 positions without passing endIndex.  Don't use
+  // advanced(by: n) to do this because it's under test here.
+  let next = { $0 == collection.endIndex ? $0 : succ($0) }
+
+  // advances up to 5 positions without passing endIndex.  Picking a
+  // small constant to avoid complexity explosion on large input
+  // collections.
+  let next5 = { next(next(next(next(next($0))))) }
+
+  let partWay0 = next5(collection.startIndex)
+  let partWay1 = next5(partWay0)
+
+  typealias Distance = Int
+
+  let count: Distance  = collection.count
+  let offset0 = min(5, count)
+  let offset1 = min(10, count)
+  let offset2 = min(15, count)
+
+  let distanceCandidates: [Distance] = [
+    -11, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 11]
+
+  let distances = distanceCandidates.filter { (x: Distance) -> Bool in
+    x + offset0 >= 0 && x + offset1 <= count
+  }
+
+  func nextN(_ n: Distance, _ i: C.Index) -> C.Index {
+    return collection.index(i, offsetBy: n)
+  }
+
+  let instances = _allIndices(into: collection, in: partWay0..<partWay1)
+
+  checkRandomAccessIndex(
+    instances,
+    distances: distances,
+    of: collection,
+    distanceOracle: { (x:Int, y:Int) in numericCast(y - x) },
+    advanceOracle: { x, y in nextN(distances[y], instances[x]) },
+    startIndex: collection.startIndex,
+    endIndex: next5(partWay1), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+
+  let expectedArray = Array(expected)
+
+  // Check `count`.
+  expectEqual(Int64(expectedArray.count), Int64(collection.count), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  //===------------------------------------------------------------------===//
+  // Check Iteration behavior.
+  //===------------------------------------------------------------------===//
+
+  for _ in 0..<3 {
+    do {
+      let startIndex = collection.startIndex
+      let endIndex = collection.endIndex
+
+      for _ in collection.indices {
+        expectEqual(
+          startIndex, collection.startIndex,
+          "Iteration should not change startIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+        expectEqual(
+          endIndex, collection.endIndex,
+          "Iteration should not change endIndex",
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      }
+    }
+
+    var allIndices = Array(collection.indices)
+
+    if expectedArray.count >= 2 {
+      for i in 0..<allIndices.count-1 {
+        let successor1 = succ(allIndices[i])
+        var successor2 = allIndices[i]
+        successor2 = succ(successor2)
+        var successor3 = allIndices[i]
+        successor3 = succ(successor3)
+        for s in [ successor1, successor2, successor3 ] {
+          expectEqual(allIndices[i + 1], s, message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+          expectEqualTest(
+            expectedArray[i + 1], collection[s], message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+        }
+      }
+
+
+    } // end of `if expectedArray.count >= 2`
+
+    do {
+      var allIndices2: [C.Index] = []
+      for i in collection.indices {
+        allIndices2.append(i)
+      }
+
+      expectEqualSequence(
+        allIndices, allIndices2, "iteration should not invalidate indices",
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+      expectEqualSequence(
+        expectedArray, allIndices.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+      expectEqualSequence(
+        expectedArray, allIndices2.map { collection[$0] },
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+    }
+  } // end of `for _ in 0..<3`
+
+  // FIXME: more checks for bidirectional and random access collections.
+}
+
+// Helper for checkRandomAccessCollection to check Slices.
+//
+// Checks all slices: O(n^2).
+internal func _checkSliceableWithRandomAccessIndex<
+Element, S : RandomAccessCollection
+>(
+  _ expected: Array<Element>, _ sliceable: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where
+  S.Element == Element {
+
+  let expectedArray = Array(expected)
+
+  let succ = { sliceable.index(after: $0) }
+  let pred = { sliceable.index(before: $0) }
+
+  var start = sliceable.startIndex
+  for startNumericIndex in 0...expectedArray.count {
+    if start != sliceable.endIndex {
+      start = succ(start)
+      start = pred(start)
+      start = succ(start)
+      start = pred(start)
+    }
+    var end = start
+    for endNumericIndex in startNumericIndex...expectedArray.count {
+      if end != sliceable.endIndex {
+        end = succ(end)
+        end = pred(end)
+        end = succ(end)
+        end = pred(end)
+      }
+      let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
+      let slice = sliceable[start..<end]
+      // For every possible slice, verify that the slice's bounds are identical
+      // to the indices used to form the slice.
+      expectEqual(start, slice.startIndex)
+      expectEqual(end, slice.endIndex)
+
+      checkOneLevelOfRandomAccessCollection(expectedSlice, slice, message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+        resiliencyChecks: resiliencyChecks,
+        sameValue: sameValue)
+
+      if end != sliceable.endIndex {
+        end = succ(end)
+      }
+    }
+    if start != sliceable.endIndex {
+      start = succ(start)
+    }
+  }
+}
+
+
+
+// Check RangeReplaceableCollection using a factory.
+//
+// Note: This does not invoke other collection tests.
+public func checkRangeReplaceable<C, N>(
+  _ makeCollection: @escaping () -> C,
+  _ makeNewValues: (Int) -> N
+) where
+  C : RangeReplaceableCollection,
+  N : Collection,
+  C.Element : Equatable,
+  C.Element == N.Element {
+
+  typealias A = C
+
+  // First make an independent copy of the array that we can use for
+  // comparison later.
+  let source = Array<A.Element>(makeCollection())
+
+  for (ix, i) in source.indices.enumerated() {
+    for (jx_, j) in (i..<source.endIndex).enumerated() {
+      let jx = jx_ + ix
+
+      let oldCount = jx - ix
+      for newCount in 0..<(2 * oldCount) {
+        let newValues = makeNewValues(newCount)
+
+        func reportFailure(_ a: inout A, _ message: String) {
+          print("\(message) when replacing indices \(ix)...\(jx)")
+          print("  in \(Array(source)) with \(Array(newValues))")
+          print("  yielding \(Array(a))")
+          print("====================================")
+          expectTrue(false)
+        }
+
+        var a = makeCollection()
+
+        a.replaceSubrange(nthIndex(a, ix)..<nthIndex(a, jx), with: newValues)
+        let growth = newCount - oldCount
+
+        let expectedCount = source.count + growth
+        let actualCount = numericCast(a.count) as Int
+        if actualCount != expectedCount {
+          reportFailure(
+            &a, "\(actualCount) != expected count \(expectedCount)")
+        }
+
+        for (kx, k) in a.indices.enumerated() {
+          let expectedValue = kx < ix ? nth(source, kx)
+          : kx < jx + growth ? nth(newValues, kx - ix)
+          : nth(source, kx - growth)
+
+          if a[k] != expectedValue {
+            reportFailure(
+              &a,
+              // FIXME: why do we need to break this string into two parts?
+              "a[\(kx)] = "
+              + "\(a[k]) != expected value \(expectedValue)")
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
deleted file mode 100644
index 008c400..0000000
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
+++ /dev/null
@@ -1,620 +0,0 @@
-//===--- CheckCollectionInstance.swift.gyb --------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-from gyb_stdlib_support import TRAVERSALS, collectionForTraversal
-}%
-
-import StdlibUnittest
-
-public struct CollectionMisuseResiliencyChecks {
-  public enum FailureKind {
-    case none
-    case trap
-  }
-
-  public var creatingOutOfBoundsIndicesBehavior: FailureKind = .trap
-  public var subscriptOnOutOfBoundsIndicesBehavior: FailureKind = .trap
-  public var subscriptRangeOnOutOfBoundsRangesBehavior: FailureKind = .trap
-
-  public static var all: CollectionMisuseResiliencyChecks {
-    return CollectionMisuseResiliencyChecks()
-  }
-
-  public static var none: CollectionMisuseResiliencyChecks {
-    return CollectionMisuseResiliencyChecks(
-      creatingOutOfBoundsIndicesBehavior: .none,
-      subscriptOnOutOfBoundsIndicesBehavior: .none,
-      subscriptRangeOnOutOfBoundsRangesBehavior: .none)
-  }
-}
-
-% for inc, protocol, direction, end in (
-%  ('inc', 'Collection', 'after', 'end'),
-%  ('dec', 'BidirectionalCollection', 'before', 'start')):
-
-/// Test that the elements of `instances` satisfy
-/// ${'some of ' if inc == 'dec' else ''}the semantic
-/// requirements of `${protocol}`, using `equalityOracle` to
-/// generate equality expectations from pairs of positions in
-/// `instances`.
-///
-/// - Precondition: ${'''`endIndex` is reachable from all
-///   elements of `instances`.''' if inc == 'inc' else '''all
-///   elements of `instances` are reachable from `startIndex`.'''}
-public func check${inc.capitalize()}rementable<Instances, BaseCollection>(
-  _ instances: Instances,
-  of baseCollection: BaseCollection,
-  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
-  ${end}Index: Instances.Element, ${TRACE}
-) where
-  Instances : Collection,
-  BaseCollection : ${protocol},
-  Instances.Element == BaseCollection.Index {
-
-  checkEquatable(instances, oracle: equalityOracle, ${trace})
-  for i in instances {
-    if i != ${end}Index {
-      let next = baseCollection.index(${direction}: i)
-      // index(${direction}:) gets us a new index value
-      expectNotEqual(i, next, ${trace})
-
-      // Which is the same as if we apply formIndex(${direction}:)
-      var j = i
-      baseCollection.formIndex(${direction}: &j)
-      expectEqual(j, next, ${trace})
-    }
-  }
-}
-%end
-
-internal func _checkIncrementalAdvance<Instances, BaseCollection>(
-  _ instances: Instances,
-  of baseCollection : BaseCollection,
-  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
-  limit: Instances.Element,
-  sign: Int, // 1 or -1
-  next: (Instances.Element) -> Instances.Element,
-  ${TRACE}
-) where
-  Instances : Collection,
-  BaseCollection : Collection,
-  Instances.Element == BaseCollection.Index {
-  for i in instances {
-    let d: Int = sign > 0 ?
-      baseCollection.distance(from: i, to: limit) :
-      -baseCollection.distance(from: limit, to: i)
-
-    var offset: Int = 0
-    for _ in 0...Int64(d * sign) {
-      let j = baseCollection.index(i, offsetBy: offset)
-      let k = baseCollection.index(i, offsetBy: offset + sign, limitedBy: limit) ?? limit
-      let jAtLimit = offset == d
-      if jAtLimit {
-        expectEqual(limit, j, ${trace})
-      }
-      expectEqual(jAtLimit ? j : next(j), k, ${trace})
-      offset += sign
-    }
-  }
-}
-
-/// Test that the elements of `instances` satisfy the semantic requirements of
-/// index for `Collection`, using `equalityOracle` to generate equality
-/// expectations from pairs of positions in `instances`.
-///
-/// - Precondition: `endIndex` is reachable from all elements of
-///   `instances`
-public func checkForwardIndex<Instances, BaseCollection>(
-  _ instances: Instances,
-  of baseCollection: BaseCollection,
-  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
-  endIndex: Instances.Element, ${TRACE}
-) where
-  Instances : Collection,
-  BaseCollection : Collection,
-  Instances.Element == BaseCollection.Index {
-
-  checkIncrementable(instances, of: baseCollection,
-    equalityOracle: equalityOracle, endIndex: endIndex, ${trace})
-
-  _checkIncrementalAdvance(instances, of: baseCollection,
-    equalityOracle: equalityOracle, limit: endIndex,
-    sign: 1, next: { baseCollection.index(after: $0) }, ${trace})
-}
-
-/// Test that the elements of `instances` satisfy the semantic requirements of
-/// index for `BidirectionalCollection`, using `equalityOracle` to generate
-/// equality expectations from pairs of positions in `instances`.
-///
-/// - Precondition:
-///   - all elements of `instances` are reachable from `startIndex`.
-///   - `endIndex` is reachable from all elements of `instances`.
-public func checkBidirectionalIndex<Instances, BaseCollection>(
-  _ instances: Instances,
-  of baseCollection: BaseCollection,
-  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
-  startIndex: Instances.Element,
-  endIndex: Instances.Element,
-  ${TRACE}
-) where
-  Instances: Collection,
-  BaseCollection : BidirectionalCollection,
-  Instances.Element == BaseCollection.Index {
-
-  checkForwardIndex(instances, of: baseCollection,
-    equalityOracle: equalityOracle, endIndex: endIndex)
-
-  checkDecrementable(instances, of: baseCollection,
-    equalityOracle: equalityOracle, startIndex: startIndex, ${trace})
-
-  _checkIncrementalAdvance(instances, of: baseCollection,
-    equalityOracle: equalityOracle, limit: startIndex,
-    sign: -1, next: { baseCollection.index(before: $0) }, ${trace})
-}
-
-/// Test that the elements of `instances` satisfy the semantic requirements of
-/// index for `RandomAccessCollection`, using `advanceOracle` and
-/// 'distanceOracle' to generate expectations about the results of
-/// `advanced(by:)` and `distance(to:)` from pairs of positions in `instances`
-/// and `distances`.
-///
-/// - Precondition:
-///   - all elements of `instances` are reachable from `startIndex`.
-///   - `endIndex` is reachable from all elements of `instances`.
-public func checkRandomAccessIndex<Instances, Distances, BaseCollection>(
-  _ instances: Instances, distances: Distances,
-  of baseCollection: BaseCollection,
-  distanceOracle:
-    (Instances.Index, Instances.Index) -> Distances.Element,
-  advanceOracle:
-    (Instances.Index, Distances.Index) -> Instances.Element,
-  startIndex: Instances.Iterator.Element,
-  endIndex: Instances.Iterator.Element,
-  ${TRACE}
-) where
-  Instances : Collection,
-  Distances : Collection,
-  BaseCollection : RandomAccessCollection,
-  Instances.Element == BaseCollection.Index,
-  Distances.Element == Int {
-
-  checkBidirectionalIndex(instances, of: baseCollection,
-    equalityOracle: { distanceOracle($0, $1) == 0 },
-    startIndex: startIndex, endIndex: endIndex, ${trace})
-
-  checkAdvancesAndDistances(
-    instances, distances: distances,
-    of: baseCollection,
-    distanceOracle: distanceOracle,
-    advanceOracle: advanceOracle, ${trace})
-}
-
-// Copies what checkStrideable is doing, but instead of calling
-// advanced(by:) and distance(to:) on an Strideable's,
-// calls corresponding methods on a base collection.
-public func checkAdvancesAndDistances<Instances, Distances, BaseCollection>(
-  _ instances: Instances, distances: Distances,
-  of baseCollection: BaseCollection,
-  distanceOracle:
-    (Instances.Index, Instances.Index) -> Distances.Element,
-  advanceOracle:
-    (Instances.Index, Distances.Index) -> Instances.Element,
-  ${TRACE}
-) where
-  Instances : Collection,
-  Distances : Collection,
-  BaseCollection : Collection,
-  Instances.Element == BaseCollection.Index,
-  Distances.Element == Int {
-
-  checkComparable(
-    instances,
-    oracle: {
-      let d = distanceOracle($1, $0);
-      return d < 0 ? .lt : d == 0 ? .eq : .gt
-    },
-    ${trace})
-
-  for i in instances.indices {
-    let x = instances[i]
-    expectEqual(x, baseCollection.index(x, offsetBy: 0))
-
-    for j in distances.indices {
-      let y = distances[j]
-      expectEqual(advanceOracle(i, j), baseCollection.index(x, offsetBy: y))
-    }
-
-    for j in instances.indices {
-      let y = instances[j]
-      expectEqual(distanceOracle(i, j), baseCollection.distance(from: x, to: y))
-    }
-  }
-}
-
-// Generate two overloads: one for Array (which will get
-// picked up when the caller passes a literal), and another that
-// accepts any appropriate Collection type.
-% for genericParam, Element, Expected in [
-%   ('Expected: Collection',  'Expected.Element',  'Expected'),
-%   ('Element'             ,  'Element'                  ,  'Array<Element>')]:
-
-// Top-level check for Collection instances. Alias for checkForwardCollection.
-// Checks all slices: O(n^2).
-public func checkCollection<${genericParam}, C : Collection>(
-  _ expected: ${Expected},
-  _ collection: C,
-  ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
-  sameValue: (${Element}, ${Element}) -> Bool
-) where C.Element == ${Element} {
-
-  checkForwardCollection(expected, collection, message(),
-    stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
-    resiliencyChecks: resiliencyChecks,
-    sameValue: sameValue)
-}
-
-%   for Traversal in TRAVERSALS:
-%     TraversalCollection = collectionForTraversal(Traversal)
-
-// Calls check${Traversal}Collection with default `sameValue`.
-public func check${Traversal}Collection<
-  ${genericParam}, C : ${TraversalCollection}
->(
-  _ expected: ${Expected}, _ collection: C,
-  ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
-) where
-  C.Element == ${Element},
-  ${Element} : Equatable {
-
-  check${Traversal}Collection(
-    expected, collection, ${trace},
-    resiliencyChecks: resiliencyChecks) { $0 == $1 }
-}
-
-// Top-Level check for all ${TraversalCollection} semantics on a single
-// instance. This constrains SubSequence associated types in order to check
-// slice semantics.
-// Checks all slices: O(n^2).
-public func check${Traversal}Collection<
-  ${genericParam}, C : ${TraversalCollection}
->(
-  _ expected: ${Expected}, _ collection: C,
-  ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
-  sameValue: (${Element}, ${Element}) -> Bool
-) where
-  C.Element == ${Element} {
-
-  checkOneLevelOf${Traversal}Collection(expected, collection, ${trace},
-    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
-
-  // Avoid validation of all possible (n^2) slices on large collection.
-  // Test cases should call checkOneLevelOf${Traversal}Collection instead.
-  expectLT(expected.count, 30)
-
-  _checkSliceableWith${Traversal}Index(expected, collection, ${trace},
-    resiliencyChecks: resiliencyChecks, sameValue: sameValue)
-}
-
-// Helper for check${Traversal}Collection. Check that instance of `C`,
-// `collection`, upholds the semantics of `${TraversalCollection}`,
-// non-recursively. This does not check subsequences. It may be called for each
-// subsequence without combinatorial explosion. Also, since recursive protocol
-// constraints are not supported, our second level of checks cannot depend on the
-// associated type properties of SubSequence.
-//
-// Checks all slices: O(n^2).
-public func checkOneLevelOf${Traversal}Collection<
-  ${genericParam}, C : ${TraversalCollection}
->(
-  _ expected: ${Expected}, _ collection: C,
-  ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
-  sameValue: (${Element}, ${Element}) -> Bool
-) where C.Element == ${Element} {
-
-  // A `Collection` is a multi-pass `Sequence`.
-  for _ in 0..<3 {
-    checkSequence(
-      expected, collection, ${trace},
-      resiliencyChecks: resiliencyChecks, sameValue: sameValue)
-  }
-
-  //===------------------------------------------------------------------===//
-  // Check Index semantics
-  //===------------------------------------------------------------------===//
-
-  let succ = { collection.index(after: $0) }
-%     if Traversal != 'Forward':
-  let pred = { collection.index(before: $0) }
-%     end
-  // Advances up to 1 positions without passing endIndex.  Don't use
-  // advanced(by: n) to do this because it's under test here.
-  let next = { $0 == collection.endIndex ? $0 : succ($0) }
-
-  // advances up to 5 positions without passing endIndex.  Picking a
-  // small constant to avoid complexity explosion on large input
-  // collections.
-  let next5 = { next(next(next(next(next($0))))) }
-
-  let partWay0 = next5(collection.startIndex)
-  let partWay1 = next5(partWay0)
-
-%     if Traversal == 'Forward':
-
-  let instances = _allIndices(into: collection,
-    in: collection.startIndex..<partWay0)
-  checkForwardIndex(instances, of: collection,
-    equalityOracle: { $0 == $1 }, endIndex: partWay1, ${trace})
-
-%     elif Traversal == 'Bidirectional':
-
-  let instances = _allIndices(into: collection, in: partWay0..<partWay1)
-  checkBidirectionalIndex(instances, of: collection,
-    equalityOracle: { $0 == $1 },
-    startIndex: collection.startIndex,
-    endIndex: next5(partWay1), ${trace})
-
-%     else:
-%       assert(Traversal == 'RandomAccess')
-  typealias Distance = Int
-
-  let count: Distance  = collection.count
-  let offset0 = min(5, count)
-  let offset1 = min(10, count)
-  let offset2 = min(15, count)
-
-  let distanceCandidates: [Distance] = [
-    -11, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 11]
-
-  let distances = distanceCandidates.filter { (x: Distance) -> Bool in
-    x + offset0 >= 0 && x + offset1 <= count
-  }
-
-  func nextN(_ n: Distance, _ i: C.Index) -> C.Index {
-    return collection.index(i, offsetBy: n)
-  }
-
-  let instances = _allIndices(into: collection, in: partWay0..<partWay1)
-
-  checkRandomAccessIndex(
-    instances,
-    distances: distances,
-    of: collection,
-    distanceOracle: { (x:Int, y:Int) in numericCast(y - x) },
-    advanceOracle: { x, y in nextN(distances[y], instances[x]) },
-    startIndex: collection.startIndex,
-    endIndex: next5(partWay1), ${trace})
-
-%     end
-
-  let expectedArray = Array(expected)
-
-  // Check `count`.
-  expectEqual(Int64(expectedArray.count), Int64(collection.count), ${trace})
-
-  //===------------------------------------------------------------------===//
-  // Check Iteration behavior.
-  //===------------------------------------------------------------------===//
-
-  for _ in 0..<3 {
-    do {
-      let startIndex = collection.startIndex
-      let endIndex = collection.endIndex
-
-      for _ in collection.indices {
-        expectEqual(
-          startIndex, collection.startIndex,
-          "Iteration should not change startIndex",
-          stackTrace: ${stackTrace})
-
-        expectEqual(
-          endIndex, collection.endIndex,
-          "Iteration should not change endIndex",
-          stackTrace: ${stackTrace})
-      }
-    }
-
-    var allIndices = Array(collection.indices)
-
-    if expectedArray.count >= 2 {
-      for i in 0..<allIndices.count-1 {
-        let successor1 = succ(allIndices[i])
-        var successor2 = allIndices[i]
-        successor2 = succ(successor2)
-        var successor3 = allIndices[i]
-        successor3 = succ(successor3)
-        for s in [ successor1, successor2, successor3 ] {
-          expectEqual(allIndices[i + 1], s, ${trace})
-          expectEqualTest(
-            expectedArray[i + 1], collection[s], ${trace}, sameValue: sameValue)
-        }
-      }
-
-%       if Traversal == "Bidirectional":
-
-      for i in 1..<allIndices.count {
-        let predecessor1 = pred(allIndices[i])
-        var predecessor2 = allIndices[i]
-        predecessor2 = pred(predecessor2)
-        var predecessor3 = allIndices[i]
-        predecessor3 = pred(predecessor3)
-        for p in [ predecessor1, predecessor2, predecessor3 ] {
-          expectEqual(allIndices[i - 1], p, ${trace})
-          expectEqualTest(
-            expectedArray[i - 1], collection[p], ${trace}, sameValue: sameValue)
-        }
-      }
-      for i in 1..<allIndices.count {
-        let index = succ(pred(allIndices[i]))
-        expectEqual(allIndices[i], index, ${trace})
-        expectEqualTest(
-          expectedArray[i], collection[index], ${trace}, sameValue: sameValue)
-      }
-
-%       end # Traversal == "Bidirectional"
-
-    } // end of `if expectedArray.count >= 2`
-
-    do {
-      var allIndices2: [C.Index] = []
-      for i in collection.indices {
-        allIndices2.append(i)
-      }
-
-      expectEqualSequence(
-        allIndices, allIndices2, "iteration should not invalidate indices",
-        stackTrace: ${stackTrace})
-
-      expectEqualSequence(
-        expectedArray, allIndices.map { collection[$0] },
-        stackTrace: ${stackTrace}, sameValue: sameValue)
-      expectEqualSequence(
-        expectedArray, allIndices2.map { collection[$0] },
-        stackTrace: ${stackTrace}, sameValue: sameValue)
-    }
-  } // end of `for _ in 0..<3`
-
-  // FIXME: more checks for bidirectional and random access collections.
-}
-
-// Helper for check${Traversal}Collection to check Slices.
-//
-// Checks all slices: O(n^2).
-internal func _checkSliceableWith${Traversal}Index<
-${genericParam}, S : ${TraversalCollection}
->(
-  _ expected: ${Expected}, _ sliceable: S, ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
-  sameValue: (${Element}, ${Element}) -> Bool
-) where
-  S.Element == ${Element} {
-
-  let expectedArray = Array(expected)
-
-  let succ = { sliceable.index(after: $0) }
-%       if Traversal != "Forward":
-  let pred = { sliceable.index(before: $0) }
-%       end
-
-  var start = sliceable.startIndex
-  for startNumericIndex in 0...expectedArray.count {
-%       if Traversal != "Forward":
-    if start != sliceable.endIndex {
-      start = succ(start)
-      start = pred(start)
-      start = succ(start)
-      start = pred(start)
-    }
-%       end
-    var end = start
-    for endNumericIndex in startNumericIndex...expectedArray.count {
-%       if Traversal != "Forward":
-      if end != sliceable.endIndex {
-        end = succ(end)
-        end = pred(end)
-        end = succ(end)
-        end = pred(end)
-      }
-%       end
-      let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
-      let slice = sliceable[start..<end]
-      // For every possible slice, verify that the slice's bounds are identical
-      // to the indices used to form the slice.
-      expectEqual(start, slice.startIndex)
-      expectEqual(end, slice.endIndex)
-
-      checkOneLevelOf${Traversal}Collection(expectedSlice, slice, ${trace},
-        resiliencyChecks: resiliencyChecks,
-        sameValue: sameValue)
-
-      if end != sliceable.endIndex {
-        end = succ(end)
-      }
-    }
-    if start != sliceable.endIndex {
-      start = succ(start)
-    }
-  }
-}
-
-%   end # Traversal
-
-% end # genericParam, Elements, Expected
-
-// Check RangeReplaceableCollection using a factory.
-//
-// Note: This does not invoke other collection tests.
-public func checkRangeReplaceable<C, N>(
-  _ makeCollection: @escaping () -> C,
-  _ makeNewValues: (Int) -> N
-) where
-  C : RangeReplaceableCollection,
-  N : Collection,
-  C.Element : Equatable,
-  C.Element == N.Element {
-
-  typealias A = C
-
-  // First make an independent copy of the array that we can use for
-  // comparison later.
-  let source = Array<A.Element>(makeCollection())
-
-  for (ix, i) in source.indices.enumerated() {
-    for (jx_, j) in (i..<source.endIndex).enumerated() {
-      let jx = jx_ + ix
-
-      let oldCount = jx - ix
-      for newCount in 0..<(2 * oldCount) {
-        let newValues = makeNewValues(newCount)
-
-        func reportFailure(_ a: inout A, _ message: String) {
-          print("\(message) when replacing indices \(ix)...\(jx)")
-          print("  in \(Array(source)) with \(Array(newValues))")
-          print("  yielding \(Array(a))")
-          print("====================================")
-          expectTrue(false)
-        }
-
-        var a = makeCollection()
-
-        a.replaceSubrange(nthIndex(a, ix)..<nthIndex(a, jx), with: newValues)
-        let growth = newCount - oldCount
-
-        let expectedCount = source.count + growth
-        let actualCount = numericCast(a.count) as Int
-        if actualCount != expectedCount {
-          reportFailure(
-            &a, "\(actualCount) != expected count \(expectedCount)")
-        }
-
-        for (kx, k) in a.indices.enumerated() {
-          let expectedValue = kx < ix ? nth(source, kx)
-          : kx < jx + growth ? nth(newValues, kx - ix)
-          : nth(source, kx - growth)
-
-          if a[k] != expectedValue {
-            reportFailure(
-              &a,
-              // FIXME: why do we need to break this string into two parts?
-              "a[\(kx)] = "
-              + "\(a[k]) != expected value \(expectedValue)")
-          }
-        }
-      }
-    }
-  }
-}
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift
similarity index 69%
rename from stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
rename to stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift
index a15353c..ddd179f 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift
@@ -468,49 +468,36 @@
   }
 }
 
-%{
-  from gyb_stdlib_support import collectionForTraversal
-  def testConstraints(protocol):
-    return '''
-    C : %(protocol)s,
-    CollectionWithEquatableElement : %(protocol)s,
-    CollectionWithEquatableElement.Iterator.Element : Equatable
-  ''' % locals()
-
-  testParams = '''
-    _ testNamePrefix: String = "",
-    makeCollection: @escaping ([C.Iterator.Element]) -> C,
-    wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
-    extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
-
-    makeCollectionOfEquatable: @escaping (
-      [CollectionWithEquatableElement.Iterator.Element]
-    ) -> CollectionWithEquatableElement,
-
-    wrapValueIntoEquatable: @escaping (
-      MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
-
-    extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
-
-    resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
-    outOfBoundsIndexOffset: Int = 1,
-    outOfBoundsSubscriptOffset: Int = 1,
-    collectionIsBidirectional: Bool
-  '''
-
-  import re
-  forwardTestArgs = ',\n    '.join(
-    [ x.group(1) + ': ' + x.group(1)
-      for x in re.finditer(r'([a-zA-Z0-9_]+):', testParams) ]
-  ).replace('testNamePrefix: ', '\n    ')
-}%
 extension TestSuite {
   public func addCollectionTests<
     C, CollectionWithEquatableElement
   >(
-    ${testParams} = false
+
+  _ testNamePrefix: String = "",
+  makeCollection: @escaping ([C.Iterator.Element]) -> C,
+  wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+  extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+  makeCollectionOfEquatable: @escaping (
+    [CollectionWithEquatableElement.Iterator.Element]
+  ) -> CollectionWithEquatableElement,
+
+  wrapValueIntoEquatable: @escaping (
+    MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+  extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  outOfBoundsIndexOffset: Int = 1,
+  outOfBoundsSubscriptOffset: Int = 1,
+  collectionIsBidirectional: Bool
+ = false
   ) where
-    ${testConstraints('Collection')} {
+
+  C : Collection,
+  CollectionWithEquatableElement : Collection,
+  CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
 
     var testNamePrefix = testNamePrefix
 
@@ -827,13 +814,13 @@
     }
 
     //===------------------------------------------------------------------===//
-    // index(of:)/index(where:)
+    // firstIndex(of:)/firstIndex(where:)
     //===------------------------------------------------------------------===//
 
-    self.test("\(testNamePrefix).index(of:)/semantics") {
+    self.test("\(testNamePrefix).firstIndex(of:)/semantics") {
       for test in findTests {
         let c = makeWrappedCollectionWithEquatableElement(test.sequence)
-        var result = c.index(of: wrapValueIntoEquatable(test.element))
+        var result = c.firstIndex(of: wrapValueIntoEquatable(test.element))
         expectType(
           Optional<CollectionWithEquatableElement.Index>.self,
           &result)
@@ -847,12 +834,12 @@
       }
     }
 
-    self.test("\(testNamePrefix).index(where:)/semantics") {
+    self.test("\(testNamePrefix).firstIndex(where:)/semantics") {
       for test in findTests {
         let closureLifetimeTracker = LifetimeTracked(0)
         expectEqual(1, LifetimeTracked.instances)
         let c = makeWrappedCollectionWithEquatableElement(test.sequence)
-        let result = c.index {
+        let result = c.firstIndex {
           (candidate) in
           _blackHole(closureLifetimeTracker)
           return
@@ -1166,15 +1153,49 @@
     }
 
     //===------------------------------------------------------------------===//
-    self.addCommonTests(${forwardTestArgs})
+    self.addCommonTests(
+    testNamePrefix,
+    makeCollection: makeCollection,
+    wrapValue: wrapValue,
+    extractValue: extractValue,
+    makeCollectionOfEquatable: makeCollectionOfEquatable,
+    wrapValueIntoEquatable: wrapValueIntoEquatable,
+    extractValueFromEquatable: extractValueFromEquatable,
+    resiliencyChecks: resiliencyChecks,
+    outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+    outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+    collectionIsBidirectional: collectionIsBidirectional)
   } // addCollectionTests
 
   public func addBidirectionalCollectionTests<
     C, CollectionWithEquatableElement
   >(
-    ${testParams} = true
+
+  _ testNamePrefix: String = "",
+  makeCollection: @escaping ([C.Iterator.Element]) -> C,
+  wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+  extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+  makeCollectionOfEquatable: @escaping (
+    [CollectionWithEquatableElement.Iterator.Element]
+  ) -> CollectionWithEquatableElement,
+
+  wrapValueIntoEquatable: @escaping (
+    MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+  extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  outOfBoundsIndexOffset: Int = 1,
+  outOfBoundsSubscriptOffset: Int = 1,
+  collectionIsBidirectional: Bool
+ = true
   ) where
-    ${testConstraints('BidirectionalCollection')} {
+
+  C : BidirectionalCollection,
+  CollectionWithEquatableElement : BidirectionalCollection,
+  CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
 
     var testNamePrefix = testNamePrefix
 
@@ -1184,7 +1205,18 @@
       return
     }
 
-    addCollectionTests(${forwardTestArgs})
+    addCollectionTests(
+    testNamePrefix,
+    makeCollection: makeCollection,
+    wrapValue: wrapValue,
+    extractValue: extractValue,
+    makeCollectionOfEquatable: makeCollectionOfEquatable,
+    wrapValueIntoEquatable: wrapValueIntoEquatable,
+    extractValueFromEquatable: extractValueFromEquatable,
+    resiliencyChecks: resiliencyChecks,
+    outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+    outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+    collectionIsBidirectional: collectionIsBidirectional)
 
     func makeWrappedCollection(_ elements: [OpaqueValue<Int>]) -> C {
       return makeCollection(elements.map(wrapValue))
@@ -1484,15 +1516,49 @@
 
     //===------------------------------------------------------------------===//
 
-    self.addCommonTests(${forwardTestArgs})
+    self.addCommonTests(
+    testNamePrefix,
+    makeCollection: makeCollection,
+    wrapValue: wrapValue,
+    extractValue: extractValue,
+    makeCollectionOfEquatable: makeCollectionOfEquatable,
+    wrapValueIntoEquatable: wrapValueIntoEquatable,
+    extractValueFromEquatable: extractValueFromEquatable,
+    resiliencyChecks: resiliencyChecks,
+    outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+    outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+    collectionIsBidirectional: collectionIsBidirectional)
   } // addBidirectionalCollectionTests
 
   public func addRandomAccessCollectionTests<
     C, CollectionWithEquatableElement
   >(
-    ${testParams} = true
+
+  _ testNamePrefix: String = "",
+  makeCollection: @escaping ([C.Iterator.Element]) -> C,
+  wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+  extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+  makeCollectionOfEquatable: @escaping (
+    [CollectionWithEquatableElement.Iterator.Element]
+  ) -> CollectionWithEquatableElement,
+
+  wrapValueIntoEquatable: @escaping (
+    MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+  extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  outOfBoundsIndexOffset: Int = 1,
+  outOfBoundsSubscriptOffset: Int = 1,
+  collectionIsBidirectional: Bool
+ = true
   ) where
-    ${testConstraints('RandomAccessCollection')} {
+
+  C : RandomAccessCollection,
+  CollectionWithEquatableElement : RandomAccessCollection,
+  CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
 
     var testNamePrefix = testNamePrefix
 
@@ -1502,7 +1568,18 @@
       return
     }
 
-    addBidirectionalCollectionTests(${forwardTestArgs})
+    addBidirectionalCollectionTests(
+    testNamePrefix,
+    makeCollection: makeCollection,
+    wrapValue: wrapValue,
+    extractValue: extractValue,
+    makeCollectionOfEquatable: makeCollectionOfEquatable,
+    wrapValueIntoEquatable: wrapValueIntoEquatable,
+    extractValueFromEquatable: extractValueFromEquatable,
+    resiliencyChecks: resiliencyChecks,
+    outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+    outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+    collectionIsBidirectional: collectionIsBidirectional)
 
     testNamePrefix += String(describing: C.Type.self)
 
@@ -1539,16 +1616,49 @@
     }
 
     //===------------------------------------------------------------------===//
-    self.addCommonTests(${forwardTestArgs})
+    self.addCommonTests(
+    testNamePrefix,
+    makeCollection: makeCollection,
+    wrapValue: wrapValue,
+    extractValue: extractValue,
+    makeCollectionOfEquatable: makeCollectionOfEquatable,
+    wrapValueIntoEquatable: wrapValueIntoEquatable,
+    extractValueFromEquatable: extractValueFromEquatable,
+    resiliencyChecks: resiliencyChecks,
+    outOfBoundsIndexOffset: outOfBoundsIndexOffset,
+    outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
+    collectionIsBidirectional: collectionIsBidirectional)
   } // addRandomAccessCollectionTests
 
-% for Traversal in ['Forward', 'Bidirectional', 'RandomAccess']:
   func addCommonTests<
     C, CollectionWithEquatableElement
   >(
-    ${testParams}
+
+  _ testNamePrefix: String = "",
+  makeCollection: @escaping ([C.Iterator.Element]) -> C,
+  wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+  extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+  makeCollectionOfEquatable: @escaping (
+    [CollectionWithEquatableElement.Iterator.Element]
+  ) -> CollectionWithEquatableElement,
+
+  wrapValueIntoEquatable: @escaping (
+    MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+  extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  outOfBoundsIndexOffset: Int = 1,
+  outOfBoundsSubscriptOffset: Int = 1,
+  collectionIsBidirectional: Bool
+
   ) where
-    ${testConstraints(collectionForTraversal(Traversal))} {
+
+  C : Collection,
+  CollectionWithEquatableElement : Collection,
+  CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
 
     if !checksAdded.insert(
         "\(testNamePrefix).\(C.self).\(#function)"
@@ -1560,8 +1670,7 @@
       return makeCollection(r.map { wrapValue(OpaqueValue($0)) })
     }
 
-%   for function_name in ['index', 'formIndex']:
-    self.test("\(testNamePrefix).${function_name}(after:)/semantics") {
+    self.test("\(testNamePrefix).index(after:)/semantics") {
       for test in indexAfterTests {
         let c = toCollection(test.start..<test.end)
         var currentIndex = c.startIndex
@@ -1569,16 +1678,24 @@
         repeat {
           expectEqual(counter, extractValue(c[currentIndex]).value,
             stackTrace: SourceLocStack().with(test.loc))
-%     if function_name is 'index':
           currentIndex = c.index(after: currentIndex)
-%     else:
-          c.formIndex(after: &currentIndex)
-%     end
           counter += 1
         } while counter < test.end
       }
     }
-%   end
+    self.test("\(testNamePrefix).formIndex(after:)/semantics") {
+      for test in indexAfterTests {
+        let c = toCollection(test.start..<test.end)
+        var currentIndex = c.startIndex
+        var counter = test.start
+        repeat {
+          expectEqual(counter, extractValue(c[currentIndex]).value,
+            stackTrace: SourceLocStack().with(test.loc))
+          c.formIndex(after: &currentIndex)
+          counter += 1
+        } while counter < test.end
+      }
+    }
 
     self.test("\(testNamePrefix)/distance(from:to:)/semantics")
       .forEach(in: distanceFromToTests) {
@@ -1637,31 +1754,36 @@
         stackTrace: SourceLocStack().with(test.loc))
     }
 
-%   for function_name in ['index', 'formIndex']:
-    self.test("\(testNamePrefix)/${function_name}(_:offsetBy: -n)/semantics")
+    self.test("\(testNamePrefix)/index(_:offsetBy: -n)/semantics")
       .forEach(
         in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
       ) {
       test in
       let c = toCollection(0..<20)
-%     if function_name is 'index':
       let start = c.nthIndex(test.startOffset)
-%     else:
-      var new = c.nthIndex(test.startOffset)
-%     end
 
       if test.expectedOffset! < 0 || !collectionIsBidirectional {
         expectCrashLater()
       }
-%     if function_name is 'index':
       let new = c.index(start, offsetBy: numericCast(test.distance))
-%     else:
-      c.formIndex(&new, offsetBy: numericCast(test.distance))
-%     end
       expectEqual(test.expectedOffset!, extractValue(c[new]).value,
         stackTrace: SourceLocStack().with(test.loc))
     }
-%   end
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      var new = c.nthIndex(test.startOffset)
+
+      if test.expectedOffset! < 0 || !collectionIsBidirectional {
+        expectCrashLater()
+      }
+      c.formIndex(&new, offsetBy: numericCast(test.distance))
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
 
     self.test("\(testNamePrefix)/index(_:offsetBy: n, limitedBy:)/semantics") {
       for test in indexOffsetByTests.filter(
@@ -1757,5 +1879,502 @@
     }
 
   }
-% end
+  func addCommonTests<
+    C, CollectionWithEquatableElement
+  >(
+
+  _ testNamePrefix: String = "",
+  makeCollection: @escaping ([C.Iterator.Element]) -> C,
+  wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+  extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+  makeCollectionOfEquatable: @escaping (
+    [CollectionWithEquatableElement.Iterator.Element]
+  ) -> CollectionWithEquatableElement,
+
+  wrapValueIntoEquatable: @escaping (
+    MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+  extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  outOfBoundsIndexOffset: Int = 1,
+  outOfBoundsSubscriptOffset: Int = 1,
+  collectionIsBidirectional: Bool
+
+  ) where
+
+  C : BidirectionalCollection,
+  CollectionWithEquatableElement : BidirectionalCollection,
+  CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
+
+    if !checksAdded.insert(
+        "\(testNamePrefix).\(C.self).\(#function)"
+      ).inserted {
+      return
+    }
+
+    func toCollection(_ r: Range<Int>) -> C {
+      return makeCollection(r.map { wrapValue(OpaqueValue($0)) })
+    }
+
+    self.test("\(testNamePrefix).index(after:)/semantics") {
+      for test in indexAfterTests {
+        let c = toCollection(test.start..<test.end)
+        var currentIndex = c.startIndex
+        var counter = test.start
+        repeat {
+          expectEqual(counter, extractValue(c[currentIndex]).value,
+            stackTrace: SourceLocStack().with(test.loc))
+          currentIndex = c.index(after: currentIndex)
+          counter += 1
+        } while counter < test.end
+      }
+    }
+    self.test("\(testNamePrefix).formIndex(after:)/semantics") {
+      for test in indexAfterTests {
+        let c = toCollection(test.start..<test.end)
+        var currentIndex = c.startIndex
+        var counter = test.start
+        repeat {
+          expectEqual(counter, extractValue(c[currentIndex]).value,
+            stackTrace: SourceLocStack().with(test.loc))
+          c.formIndex(after: &currentIndex)
+          counter += 1
+        } while counter < test.end
+      }
+    }
+
+    self.test("\(testNamePrefix)/distance(from:to:)/semantics")
+      .forEach(in: distanceFromToTests) {
+      test in
+      let c = toCollection(0..<20)
+      let backwards = (test.startOffset > test.endOffset)
+      if backwards && !collectionIsBidirectional {
+        expectCrashLater()
+      }
+
+      let d = c.distance(
+        from: c.nthIndex(test.startOffset), to: c.nthIndex(test.endOffset))
+      expectEqual(
+        numericCast(test.expectedDistance),
+        d, stackTrace: SourceLocStack().with(test.loc))
+    }
+
+    self.test("\(testNamePrefix)/index(_:offsetBy: n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance >= 0 }
+      ) {
+      test in
+      let max = 10
+      let c = toCollection(0..<max)
+
+      if test.expectedOffset! >= max {
+        expectCrashLater()
+      }
+      let new = c.index(
+        c.nthIndex(test.startOffset),
+        offsetBy: numericCast(test.distance))
+
+      // Since the `nthIndex(offset:)` method performs the same operation
+      // (i.e. advances `c.startIndex` by `test.distance`, it would be
+      // silly to compare index values. Luckily the underlying collection
+      // contains exactly index offsets.
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
+
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance >= 0 }
+      ) {
+      test in
+      let max = 10
+      let c = toCollection(0..<max)
+
+      var new = c.nthIndex(test.startOffset)
+
+      if test.expectedOffset! >= max {
+        expectCrashLater()
+      }
+      c.formIndex(&new, offsetBy: numericCast(test.distance))
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
+
+    self.test("\(testNamePrefix)/index(_:offsetBy: -n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      let start = c.nthIndex(test.startOffset)
+
+      if test.expectedOffset! < 0 || !collectionIsBidirectional {
+        expectCrashLater()
+      }
+      let new = c.index(start, offsetBy: numericCast(test.distance))
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      var new = c.nthIndex(test.startOffset)
+
+      if test.expectedOffset! < 0 || !collectionIsBidirectional {
+        expectCrashLater()
+      }
+      c.formIndex(&new, offsetBy: numericCast(test.distance))
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
+
+    self.test("\(testNamePrefix)/index(_:offsetBy: n, limitedBy:)/semantics") {
+      for test in indexOffsetByTests.filter(
+        {$0.limit != nil && $0.distance >= 0}
+      ) {
+        let c = toCollection(0..<20)
+        let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+        let new = c.index(
+          c.nthIndex(test.startOffset),
+          offsetBy: numericCast(test.distance),
+          limitedBy: limit)
+        if let expectedOffset = test.expectedOffset {
+          expectEqual(c.nthIndex(expectedOffset), new!,
+            stackTrace: SourceLocStack().with(test.loc))
+        } else {
+          expectNil(new)
+        }
+      }
+    }
+
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: n, limitedBy:)/semantics") {
+      for test in indexOffsetByTests.filter(
+        {$0.limit != nil && $0.distance >= 0}
+      ) {
+        let c = toCollection(0..<20)
+        let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+        var new = c.nthIndex(test.startOffset)
+        let exact = c.formIndex(&new, offsetBy: numericCast(test.distance), limitedBy: limit)
+        if let expectedOffset = test.expectedOffset {
+          expectEqual(c.nthIndex(expectedOffset), new,
+            stackTrace: SourceLocStack().with(test.loc))
+          expectTrue(exact, stackTrace: SourceLocStack().with(test.loc))
+        } else {
+          // Clamped to the limit
+          expectEqual(limit, new, stackTrace: SourceLocStack().with(test.loc))
+          expectFalse(exact, stackTrace: SourceLocStack().with(test.loc))
+        }
+      }
+    }
+
+    self.test("\(testNamePrefix)/index(_:offsetBy: -n, limitedBy:)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit != nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+      if collectionIsBidirectional {
+        let new = c.index(
+          c.nthIndex(test.startOffset),
+          offsetBy: numericCast(test.distance),
+          limitedBy: limit)
+        if let expectedOffset = test.expectedOffset {
+          expectEqual(c.nthIndex(expectedOffset), new!,
+            stackTrace: SourceLocStack().with(test.loc))
+        } else {
+          expectNil(new)
+        }
+      } else {
+        expectCrashLater()
+        _ = c.index(
+          c.nthIndex(test.startOffset),
+          offsetBy: numericCast(test.distance),
+          limitedBy: limit)
+      }
+    }
+
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n, limitedBy:)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit != nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+      var new = c.nthIndex(test.startOffset)
+      if collectionIsBidirectional {
+        let exact = c.formIndex(
+          &new,
+          offsetBy: numericCast(test.distance),
+          limitedBy: limit)
+        if let expectedOffset = test.expectedOffset {
+          expectEqual(c.nthIndex(expectedOffset), new,
+            stackTrace: SourceLocStack().with(test.loc))
+          expectTrue(exact, stackTrace: SourceLocStack().with(test.loc))
+        } else {
+          expectEqual(limit, new, stackTrace: SourceLocStack().with(test.loc))
+          expectFalse(exact, stackTrace: SourceLocStack().with(test.loc))
+        }
+      } else {
+        expectCrashLater()
+        _ = c.formIndex(&new, offsetBy: numericCast(test.distance), limitedBy: limit)
+      }
+    }
+
+  }
+  func addCommonTests<
+    C, CollectionWithEquatableElement
+  >(
+
+  _ testNamePrefix: String = "",
+  makeCollection: @escaping ([C.Iterator.Element]) -> C,
+  wrapValue: @escaping (OpaqueValue<Int>) -> C.Iterator.Element,
+  extractValue: @escaping (C.Iterator.Element) -> OpaqueValue<Int>,
+
+  makeCollectionOfEquatable: @escaping (
+    [CollectionWithEquatableElement.Iterator.Element]
+  ) -> CollectionWithEquatableElement,
+
+  wrapValueIntoEquatable: @escaping (
+    MinimalEquatableValue) -> CollectionWithEquatableElement.Iterator.Element,
+
+  extractValueFromEquatable: @escaping ((CollectionWithEquatableElement.Iterator.Element) -> MinimalEquatableValue),
+
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  outOfBoundsIndexOffset: Int = 1,
+  outOfBoundsSubscriptOffset: Int = 1,
+  collectionIsBidirectional: Bool
+
+  ) where
+
+  C : RandomAccessCollection,
+  CollectionWithEquatableElement : RandomAccessCollection,
+  CollectionWithEquatableElement.Iterator.Element : Equatable
+ {
+
+    if !checksAdded.insert(
+        "\(testNamePrefix).\(C.self).\(#function)"
+      ).inserted {
+      return
+    }
+
+    func toCollection(_ r: Range<Int>) -> C {
+      return makeCollection(r.map { wrapValue(OpaqueValue($0)) })
+    }
+
+    self.test("\(testNamePrefix).index(after:)/semantics") {
+      for test in indexAfterTests {
+        let c = toCollection(test.start..<test.end)
+        var currentIndex = c.startIndex
+        var counter = test.start
+        repeat {
+          expectEqual(counter, extractValue(c[currentIndex]).value,
+            stackTrace: SourceLocStack().with(test.loc))
+          currentIndex = c.index(after: currentIndex)
+          counter += 1
+        } while counter < test.end
+      }
+    }
+    self.test("\(testNamePrefix).formIndex(after:)/semantics") {
+      for test in indexAfterTests {
+        let c = toCollection(test.start..<test.end)
+        var currentIndex = c.startIndex
+        var counter = test.start
+        repeat {
+          expectEqual(counter, extractValue(c[currentIndex]).value,
+            stackTrace: SourceLocStack().with(test.loc))
+          c.formIndex(after: &currentIndex)
+          counter += 1
+        } while counter < test.end
+      }
+    }
+
+    self.test("\(testNamePrefix)/distance(from:to:)/semantics")
+      .forEach(in: distanceFromToTests) {
+      test in
+      let c = toCollection(0..<20)
+      let backwards = (test.startOffset > test.endOffset)
+      if backwards && !collectionIsBidirectional {
+        expectCrashLater()
+      }
+
+      let d = c.distance(
+        from: c.nthIndex(test.startOffset), to: c.nthIndex(test.endOffset))
+      expectEqual(
+        numericCast(test.expectedDistance),
+        d, stackTrace: SourceLocStack().with(test.loc))
+    }
+
+    self.test("\(testNamePrefix)/index(_:offsetBy: n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance >= 0 }
+      ) {
+      test in
+      let max = 10
+      let c = toCollection(0..<max)
+
+      if test.expectedOffset! >= max {
+        expectCrashLater()
+      }
+      let new = c.index(
+        c.nthIndex(test.startOffset),
+        offsetBy: numericCast(test.distance))
+
+      // Since the `nthIndex(offset:)` method performs the same operation
+      // (i.e. advances `c.startIndex` by `test.distance`, it would be
+      // silly to compare index values. Luckily the underlying collection
+      // contains exactly index offsets.
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
+
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance >= 0 }
+      ) {
+      test in
+      let max = 10
+      let c = toCollection(0..<max)
+
+      var new = c.nthIndex(test.startOffset)
+
+      if test.expectedOffset! >= max {
+        expectCrashLater()
+      }
+      c.formIndex(&new, offsetBy: numericCast(test.distance))
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
+
+    self.test("\(testNamePrefix)/index(_:offsetBy: -n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      let start = c.nthIndex(test.startOffset)
+
+      if test.expectedOffset! < 0 || !collectionIsBidirectional {
+        expectCrashLater()
+      }
+      let new = c.index(start, offsetBy: numericCast(test.distance))
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit == nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      var new = c.nthIndex(test.startOffset)
+
+      if test.expectedOffset! < 0 || !collectionIsBidirectional {
+        expectCrashLater()
+      }
+      c.formIndex(&new, offsetBy: numericCast(test.distance))
+      expectEqual(test.expectedOffset!, extractValue(c[new]).value,
+        stackTrace: SourceLocStack().with(test.loc))
+    }
+
+    self.test("\(testNamePrefix)/index(_:offsetBy: n, limitedBy:)/semantics") {
+      for test in indexOffsetByTests.filter(
+        {$0.limit != nil && $0.distance >= 0}
+      ) {
+        let c = toCollection(0..<20)
+        let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+        let new = c.index(
+          c.nthIndex(test.startOffset),
+          offsetBy: numericCast(test.distance),
+          limitedBy: limit)
+        if let expectedOffset = test.expectedOffset {
+          expectEqual(c.nthIndex(expectedOffset), new!,
+            stackTrace: SourceLocStack().with(test.loc))
+        } else {
+          expectNil(new)
+        }
+      }
+    }
+
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: n, limitedBy:)/semantics") {
+      for test in indexOffsetByTests.filter(
+        {$0.limit != nil && $0.distance >= 0}
+      ) {
+        let c = toCollection(0..<20)
+        let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+        var new = c.nthIndex(test.startOffset)
+        let exact = c.formIndex(&new, offsetBy: numericCast(test.distance), limitedBy: limit)
+        if let expectedOffset = test.expectedOffset {
+          expectEqual(c.nthIndex(expectedOffset), new,
+            stackTrace: SourceLocStack().with(test.loc))
+          expectTrue(exact, stackTrace: SourceLocStack().with(test.loc))
+        } else {
+          // Clamped to the limit
+          expectEqual(limit, new, stackTrace: SourceLocStack().with(test.loc))
+          expectFalse(exact, stackTrace: SourceLocStack().with(test.loc))
+        }
+      }
+    }
+
+    self.test("\(testNamePrefix)/index(_:offsetBy: -n, limitedBy:)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit != nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+      if collectionIsBidirectional {
+        let new = c.index(
+          c.nthIndex(test.startOffset),
+          offsetBy: numericCast(test.distance),
+          limitedBy: limit)
+        if let expectedOffset = test.expectedOffset {
+          expectEqual(c.nthIndex(expectedOffset), new!,
+            stackTrace: SourceLocStack().with(test.loc))
+        } else {
+          expectNil(new)
+        }
+      } else {
+        expectCrashLater()
+        _ = c.index(
+          c.nthIndex(test.startOffset),
+          offsetBy: numericCast(test.distance),
+          limitedBy: limit)
+      }
+    }
+
+    self.test("\(testNamePrefix)/formIndex(_:offsetBy: -n, limitedBy:)/semantics")
+      .forEach(
+        in: indexOffsetByTests.filter { $0.limit != nil && $0.distance < 0 }
+      ) {
+      test in
+      let c = toCollection(0..<20)
+      let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
+      var new = c.nthIndex(test.startOffset)
+      if collectionIsBidirectional {
+        let exact = c.formIndex(
+          &new,
+          offsetBy: numericCast(test.distance),
+          limitedBy: limit)
+        if let expectedOffset = test.expectedOffset {
+          expectEqual(c.nthIndex(expectedOffset), new,
+            stackTrace: SourceLocStack().with(test.loc))
+          expectTrue(exact, stackTrace: SourceLocStack().with(test.loc))
+        } else {
+          expectEqual(limit, new, stackTrace: SourceLocStack().with(test.loc))
+          expectFalse(exact, stackTrace: SourceLocStack().with(test.loc))
+        }
+      } else {
+        expectCrashLater()
+        _ = c.formIndex(&new, offsetBy: numericCast(test.distance), limitedBy: limit)
+      }
+    }
+
+  }
 }
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift
similarity index 86%
rename from stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
rename to stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift
index b5560d9..2c2bd70 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift
@@ -446,7 +446,8 @@
     var c = makeWrappedCollection(test.collection)
     var result = c._withUnsafeMutableBufferPointerIfSupported {
       (bufferPointer) -> OpaqueValue<Array<OpaqueValue<Int>>> in
-      return OpaqueValue(bufferPointer.map(extractValue))
+      let value = OpaqueValue(bufferPointer.map(extractValue))
+      return value
     }
     expectType(Optional<OpaqueValue<Array<OpaqueValue<Int>>>>.self, &result)
     if withUnsafeMutableBufferPointerIsSupported {
@@ -492,7 +493,7 @@
   expectEqualSequence(
     elements.map { $0.value },
     c.map { extract($0).value })
-   
+
   // If `sorted` throws then result will be empty else
   // returned result must be sorted.
   if thrown {
@@ -511,33 +512,18 @@
   }
 }
 
-% for predicate in [False, True]:
-
-self.test("\(testNamePrefix).sorted/DispatchesThrough_withUnsafeMutableBufferPointerIfSupported/${'Predicate' if predicate else 'WhereElementIsComparable'}") {
+self.test("\(testNamePrefix).sorted/DispatchesThrough_withUnsafeMutableBufferPointerIfSupported/WhereElementIsComparable") {
   let sequence = [ 5, 4, 3, 2, 1 ]
-%   if predicate:
-  let elements: [OpaqueValue<Int>] =
-    zip(sequence, 0..<sequence.count).map {
-      OpaqueValue($0, identity: $1)
-    }
-  let c = makeWrappedCollection(elements)
-%   else:
   let elements: [MinimalComparableValue] =
     zip(sequence, 0..<sequence.count).map {
       MinimalComparableValue($0, identity: $1)
     }
   let c = makeWrappedCollectionWithComparableElement(elements)
-%   end
 
   var lc = LoggingMutableCollection(wrapping: c)
 
-%   if predicate:
-  let result = lc.sorted { extractValue($0).value < extractValue($1).value }
-  let extractedResult = result.map(extractValue)
-%   else:
   let result = lc.sorted()
   let extractedResult = result.map(extractValueFromComparable)
-%   end
 
   // This sort operation is not in-place.
   // The collection is copied into an array before sorting.
@@ -550,26 +536,12 @@
   expectEqualSequence([ 1, 2, 3, 4, 5 ], extractedResult.map { $0.value })
 }
 
-func checkSort_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+func checkSort_WhereElementIsComparable(
   sequence: [Int],
   equalImpl: @escaping ((Int, Int) -> Bool),
   lessImpl: @escaping ((Int, Int) -> Bool),
   verifyOrder: Bool
 ) {
-%   if predicate:
-  let extract = extractValue
-  let elements: [OpaqueValue<Int>] =
-    zip(sequence, 0..<sequence.count).map {
-      OpaqueValue($0, identity: $1)
-    }
-  let c = makeWrappedCollection(elements)
-  let closureLifetimeTracker = LifetimeTracked(0)
-  let result = c.sorted {
-    (lhs, rhs) in
-    _blackHole(closureLifetimeTracker)
-    return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
-  }
-%   else:
   MinimalComparableValue.equalImpl.value = equalImpl
   MinimalComparableValue.lessImpl.value = lessImpl
 
@@ -580,7 +552,6 @@
     }
   let c = makeWrappedCollectionWithComparableElement(elements)
   let result = c.sorted()
-%   end
 
   // Check that the original collection is unchanged.
   expectEqualSequence(
@@ -606,10 +577,10 @@
   }
 }
 
-self.test("\(testNamePrefix).sorted/${'Predicate' if predicate else 'WhereElementIsComparable'}") {
+self.test("\(testNamePrefix).sorted/WhereElementIsComparable") {
   for test in partitionExhaustiveTests {
     forAllPermutations(test.sequence) { (sequence) in
-      checkSort_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+      checkSort_WhereElementIsComparable(
         sequence: sequence,
         equalImpl: { $0 == $1 },
         lessImpl: { $0 < $1 },
@@ -618,11 +589,11 @@
   }
 }
 
-self.test("\(testNamePrefix).sorted/${'Predicate' if predicate else 'WhereElementIsComparable'}/InvalidOrderings") {
+self.test("\(testNamePrefix).sorted/WhereElementIsComparable/InvalidOrderings") {
   withInvalidOrderings { (comparisonPredicate: @escaping (Int, Int) -> Bool) in
     for i in 0..<7 {
       forAllPermutations(i) { (sequence) in
-        checkSort_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+        checkSort_WhereElementIsComparable(
           sequence: sequence,
           equalImpl: {
             !comparisonPredicate($0, $1) &&
@@ -659,7 +630,127 @@
   }
 }
 
-% end
+
+self.test("\(testNamePrefix).sorted/DispatchesThrough_withUnsafeMutableBufferPointerIfSupported/Predicate") {
+  let sequence = [ 5, 4, 3, 2, 1 ]
+  let elements: [OpaqueValue<Int>] =
+    zip(sequence, 0..<sequence.count).map {
+      OpaqueValue($0, identity: $1)
+    }
+  let c = makeWrappedCollection(elements)
+
+  var lc = LoggingMutableCollection(wrapping: c)
+
+  let result = lc.sorted { extractValue($0).value < extractValue($1).value }
+  let extractedResult = result.map(extractValue)
+
+  // This sort operation is not in-place.
+  // The collection is copied into an array before sorting.
+  expectEqual(
+    0, lc.log._withUnsafeMutableBufferPointerIfSupported[type(of: lc)])
+  expectEqual(
+    0,
+    lc.log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[type(of: lc)])
+
+  expectEqualSequence([ 1, 2, 3, 4, 5 ], extractedResult.map { $0.value })
+}
+
+func checkSort_Predicate(
+  sequence: [Int],
+  equalImpl: @escaping ((Int, Int) -> Bool),
+  lessImpl: @escaping ((Int, Int) -> Bool),
+  verifyOrder: Bool
+) {
+  let extract = extractValue
+  let elements: [OpaqueValue<Int>] =
+    zip(sequence, 0..<sequence.count).map {
+      OpaqueValue($0, identity: $1)
+    }
+  let c = makeWrappedCollection(elements)
+  let closureLifetimeTracker = LifetimeTracked(0)
+  let result = c.sorted {
+    (lhs, rhs) in
+    _blackHole(closureLifetimeTracker)
+    return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
+  }
+
+  // Check that the original collection is unchanged.
+  expectEqualSequence(
+    elements.map { $0.value },
+    c.map { extract($0).value })
+
+  let extractedResult = result.map(extract)
+
+  // Check that we didn't lose any elements.
+  expectEqualsUnordered(
+    0..<sequence.count,
+    extractedResult.map { $0.identity })
+
+  // Check that the elements are sorted.
+  if verifyOrder {
+    for i in extractedResult.indices {
+      if i != extractedResult.index(before: extractedResult.endIndex) {
+        let first = extractedResult[i].value
+        let second = extractedResult[extractedResult.index(after: i)].value
+        expectFalse(lessImpl(second, first))
+      }
+    }
+  }
+}
+
+self.test("\(testNamePrefix).sorted/Predicate") {
+  for test in partitionExhaustiveTests {
+    forAllPermutations(test.sequence) { (sequence) in
+      checkSort_Predicate(
+        sequence: sequence,
+        equalImpl: { $0 == $1 },
+        lessImpl: { $0 < $1 },
+        verifyOrder: true)
+    }
+  }
+}
+
+self.test("\(testNamePrefix).sorted/Predicate/InvalidOrderings") {
+  withInvalidOrderings { (comparisonPredicate: @escaping (Int, Int) -> Bool) in
+    for i in 0..<7 {
+      forAllPermutations(i) { (sequence) in
+        checkSort_Predicate(
+          sequence: sequence,
+          equalImpl: {
+            !comparisonPredicate($0, $1) &&
+            !comparisonPredicate($1, $0)
+          },
+          lessImpl: comparisonPredicate,
+          verifyOrder: false)
+      }
+    }
+  }
+}
+
+self.test("\(testNamePrefix).sorted/ThrowingPredicate") {
+  for test in partitionExhaustiveTests {
+    forAllPermutations(test.sequence) { (sequence) in
+      for i in 0..<sequence.count {
+      checkSortedPredicateThrow(
+       sequence: sequence,
+       lessImpl: { $0 < $1 },
+       throwIndex: i)
+      }
+    }
+  }
+}
+
+self.test("\(testNamePrefix).sorted/ThrowingPredicateWithLargeNumberElements") {
+  for sequence in largeElementSortTests {
+      for i in 0..<sequence.count {
+      checkSortedPredicateThrow(
+       sequence: sequence,
+       lessImpl: { $0 < $1 },
+       throwIndex: i)
+    }
+  }
+}
+
 
 //===----------------------------------------------------------------------===//
 // partition(by:)
@@ -993,36 +1084,20 @@
       return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
     }
   } catch {}
-  
+
   //Check no element should lost and added
   expectEqualsUnordered(
     sequence,
     c.map { extract($0).value })
 }
 
-% for predicate in [False, True]:
 
-func checkSortInPlace_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+func checkSortInPlace_WhereElementIsComparable(
   sequence: [Int],
   equalImpl: @escaping ((Int, Int) -> Bool),
   lessImpl: @escaping ((Int, Int) -> Bool),
   verifyOrder: Bool
 ) {
-%   if predicate:
-  let extract = extractValue
-  let elements: [OpaqueValue<Int>] =
-    zip(sequence, 0..<sequence.count).map {
-      OpaqueValue($0, identity: $1)
-    }
-
-  var c = makeWrappedCollection(elements)
-  let closureLifetimeTracker = LifetimeTracked(0)
-  c.sort {
-    (lhs, rhs) in
-    _blackHole(closureLifetimeTracker)
-    return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
-  }
-%   else:
   MinimalComparableValue.equalImpl.value = equalImpl
   MinimalComparableValue.lessImpl.value = lessImpl
 
@@ -1034,7 +1109,6 @@
 
   var c = makeWrappedCollectionWithComparableElement(elements)
   c.sort()
-%   end
 
   let extractedResult = c.map(extract)
 
@@ -1055,10 +1129,10 @@
   }
 }
 
-self.test("\(testNamePrefix).sort/${'Predicate' if predicate else 'WhereElementIsEquatable'}") {
+self.test("\(testNamePrefix).sort/WhereElementIsEquatable") {
   for test in partitionExhaustiveTests {
     forAllPermutations(test.sequence) { (sequence) in
-      checkSortInPlace_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+      checkSortInPlace_WhereElementIsComparable(
         sequence: sequence,
         equalImpl: { $0 == $1 },
         lessImpl: { $0 < $1 },
@@ -1067,11 +1141,11 @@
   }
 }
 
-self.test("\(testNamePrefix).sort/${'Predicate' if predicate else 'WhereElementIsEquatable'}/InvalidOrderings") {
+self.test("\(testNamePrefix).sort/WhereElementIsEquatable/InvalidOrderings") {
   withInvalidOrderings { (comparisonPredicate : @escaping (Int, Int) -> Bool) in
     for i in 0..<7 {
       forAllPermutations(i) { (sequence) in
-        checkSortInPlace_${'Predicate' if predicate else 'WhereElementIsComparable'}(
+        checkSortInPlace_WhereElementIsComparable(
           sequence: sequence,
           equalImpl: {
             !comparisonPredicate($0, $1) &&
@@ -1107,8 +1181,99 @@
     }
   }
 }
- 
-% end
+
+
+func checkSortInPlace_Predicate(
+  sequence: [Int],
+  equalImpl: @escaping ((Int, Int) -> Bool),
+  lessImpl: @escaping ((Int, Int) -> Bool),
+  verifyOrder: Bool
+) {
+  let extract = extractValue
+  let elements: [OpaqueValue<Int>] =
+    zip(sequence, 0..<sequence.count).map {
+      OpaqueValue($0, identity: $1)
+    }
+
+  var c = makeWrappedCollection(elements)
+  let closureLifetimeTracker = LifetimeTracked(0)
+  c.sort {
+    (lhs, rhs) in
+    _blackHole(closureLifetimeTracker)
+    return lessImpl(extractValue(lhs).value, extractValue(rhs).value)
+  }
+
+  let extractedResult = c.map(extract)
+
+  // Check that we didn't lose any elements.
+  expectEqualsUnordered(
+    0..<sequence.count,
+    extractedResult.map { $0.identity })
+
+  // Check that the elements are sorted.
+  if verifyOrder {
+    for i in extractedResult.indices {
+      if i != extractedResult.index(before: extractedResult.endIndex) {
+        let first = extractedResult[i].value
+        let second = extractedResult[extractedResult.index(after: i)].value
+        expectFalse(lessImpl(second, first))
+      }
+    }
+  }
+}
+
+self.test("\(testNamePrefix).sort/Predicate") {
+  for test in partitionExhaustiveTests {
+    forAllPermutations(test.sequence) { (sequence) in
+      checkSortInPlace_Predicate(
+        sequence: sequence,
+        equalImpl: { $0 == $1 },
+        lessImpl: { $0 < $1 },
+        verifyOrder: true)
+    }
+  }
+}
+
+self.test("\(testNamePrefix).sort/Predicate/InvalidOrderings") {
+  withInvalidOrderings { (comparisonPredicate : @escaping (Int, Int) -> Bool) in
+    for i in 0..<7 {
+      forAllPermutations(i) { (sequence) in
+        checkSortInPlace_Predicate(
+          sequence: sequence,
+          equalImpl: {
+            !comparisonPredicate($0, $1) &&
+            !comparisonPredicate($1, $0)
+          },
+          lessImpl: comparisonPredicate,
+          verifyOrder: false)
+      }
+    }
+  }
+}
+
+self.test("\(testNamePrefix).sort/ThrowingPredicate") {
+  for test in partitionExhaustiveTests {
+    forAllPermutations(test.sequence) { (sequence) in
+      for i in 0..<sequence.count {
+        checkSortPredicateThrow(
+         sequence: sequence,
+         lessImpl: { $0 < $1 },
+         throwIndex: i)
+      }
+    }
+  }
+}
+
+self.test("\(testNamePrefix).sort/ThrowingPredicateWithLargeNumberElements") {
+  for sequence in largeElementSortTests {
+    for i in 0..<sequence.count {
+      checkSortPredicateThrow(
+        sequence: sequence,
+        lessImpl: { $0 < $1 },
+        throwIndex: i)
+    }
+  }
+}
 
 //===----------------------------------------------------------------------===//
 
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift b/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift
new file mode 100644
index 0000000..94ba6cf
--- /dev/null
+++ b/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift
@@ -0,0 +1,257 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+
+import StdlibUnittest
+
+// Generate two overloads: one for Array (which will get
+// picked up when the caller passes a literal), and another that
+// accepts any appropriate Collection type.
+
+public func checkIterator<
+  Expected: Collection, I : IteratorProtocol
+>(
+  _ expected: Expected,
+  _ iterator: I,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Iterator.Element, Expected.Iterator.Element) -> Bool
+) where I.Element == Expected.Iterator.Element {
+  // Copying a `IteratorProtocol` is allowed.
+  var mutableGen = iterator
+  var actual: [Expected.Iterator.Element] = []
+  while let e = mutableGen.next() {
+    actual.append(e)
+  }
+  expectEqualSequence(
+    expected, actual, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+
+  // Having returned `.None` once, a `IteratorProtocol` should not generate
+  // more elements.
+  for _ in 0..<10 {
+    expectNil(mutableGen.next(), message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  }
+}
+
+public func checkIterator<
+  Expected: Collection, I : IteratorProtocol
+>(
+  _ expected: Expected,
+  _ iterator: I,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where I.Element == Expected.Iterator.Element, Expected.Iterator.Element : Equatable {
+  checkIterator(
+    expected, iterator, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false,
+    resiliencyChecks: resiliencyChecks
+  ) { $0 == $1 }
+}
+
+public func checkSequence<
+  Expected: Collection, S : Sequence
+>(
+  _ expected: Expected,
+  _ sequence: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Expected.Iterator.Element, Expected.Iterator.Element) -> Bool
+) where S.Iterator.Element == Expected.Iterator.Element {
+  let expectedCount: Int = numericCast(expected.count)
+  checkIterator(
+    expected, sequence.makeIterator(), message(),
+  stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks,
+    sameValue: sameValue)
+
+  expectGE(
+    expectedCount, sequence.underestimatedCount, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  // Test `_copyContents(initializing:)` if we can do so without destroying the
+  // sequence.
+  _ = sequence._preprocessingPass { () -> Void in
+    var count = 0
+    for _ in sequence { count += 1 }
+    let ptr = UnsafeMutablePointer<S.Iterator.Element>.allocate(capacity: count)
+    let buf = UnsafeMutableBufferPointer(start: ptr, count: count)
+    var (remainders,writtenUpTo) = sequence._copyContents(initializing: buf)
+    expectTrue(remainders.next() == nil,
+      "_copyContents returned unwritten elements")
+    expectTrue(writtenUpTo == buf.endIndex,
+      "_copyContents failed to use entire buffer")
+    expectEqualSequence(expected, buf, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+    ptr.deinitialize(count: count)
+    ptr.deallocate()
+  }
+
+  // Test `_copyToContiguousArray()` if we can do so
+  // without destroying the sequence.
+  _ = sequence._preprocessingPass { () -> Void in
+    let copy = sequence._copyToContiguousArray()
+    expectEqualSequence(expected, copy, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+  }
+}
+
+public func checkSequence<
+  Expected: Collection, S : Sequence
+>(
+  _ expected: Expected,
+  _ sequence: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+  S.Iterator.Element == Expected.Iterator.Element,
+  S.Iterator.Element : Equatable {
+
+  checkSequence(
+    expected, sequence, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false,
+    resiliencyChecks: resiliencyChecks
+  ) { $0 == $1 }
+}
+
+public func checkIterator<
+  Element, I : IteratorProtocol
+>(
+  _ expected: Array<Element>,
+  _ iterator: I,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where I.Element == Element {
+  // Copying a `IteratorProtocol` is allowed.
+  var mutableGen = iterator
+  var actual: [Element] = []
+  while let e = mutableGen.next() {
+    actual.append(e)
+  }
+  expectEqualSequence(
+    expected, actual, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+
+  // Having returned `.None` once, a `IteratorProtocol` should not generate
+  // more elements.
+  for _ in 0..<10 {
+    expectNil(mutableGen.next(), message(),
+  stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  }
+}
+
+public func checkIterator<
+  Element, I : IteratorProtocol
+>(
+  _ expected: Array<Element>,
+  _ iterator: I,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where I.Element == Element, Element : Equatable {
+  checkIterator(
+    expected, iterator, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false,
+    resiliencyChecks: resiliencyChecks
+  ) { $0 == $1 }
+}
+
+public func checkSequence<
+  Element, S : Sequence
+>(
+  _ expected: Array<Element>,
+  _ sequence: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
+  sameValue: (Element, Element) -> Bool
+) where S.Iterator.Element == Element {
+  let expectedCount: Int = numericCast(expected.count)
+  checkIterator(
+    expected, sequence.makeIterator(), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    resiliencyChecks: resiliencyChecks,
+    sameValue: sameValue)
+
+  expectGE(
+    expectedCount, sequence.underestimatedCount, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  // Test `_copyContents(initializing:)` if we can do so without destroying the
+  // sequence.
+  _ = sequence._preprocessingPass { () -> Void in
+    var count = 0
+    for _ in sequence { count += 1 }
+    let ptr = UnsafeMutablePointer<S.Iterator.Element>.allocate(capacity: count)
+    let buf = UnsafeMutableBufferPointer(start: ptr, count: count)
+    var (remainders,writtenUpTo) = sequence._copyContents(initializing: buf)
+    expectTrue(remainders.next() == nil,
+      "_copyContents returned unwritten elements")
+    expectTrue(writtenUpTo == buf.endIndex,
+      "_copyContents failed to use entire buffer")
+    expectEqualSequence(expected, buf, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+    ptr.deinitialize(count: count)
+    ptr.deallocate()
+  }
+
+  // Test `_copyToContiguousArray()` if we can do so
+  // without destroying the sequence.
+  _ = sequence._preprocessingPass { () -> Void in
+    let copy = sequence._copyToContiguousArray()
+    expectEqualSequence(expected, copy, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: sameValue)
+  }
+}
+
+public func checkSequence<
+  Element, S : Sequence
+>(
+  _ expected: Array<Element>,
+  _ sequence: S,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
+  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
+) where
+  S.Iterator.Element == Element,
+  S.Iterator.Element : Equatable {
+
+  checkSequence(
+    expected, sequence, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false,
+    resiliencyChecks: resiliencyChecks
+  ) { $0 == $1 }
+}
+
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift.gyb
deleted file mode 100644
index 40fad27..0000000
--- a/stdlib/private/StdlibCollectionUnittest/CheckSequenceInstance.swift.gyb
+++ /dev/null
@@ -1,126 +0,0 @@
-//===--- CheckSequenceInstance.swift.gyb ----------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
-import StdlibUnittest
-
-// Generate two overloads: one for Array (which will get
-// picked up when the caller passes a literal), and another that
-// accepts any appropriate Collection type.
-% for genericParam, Element, Expected in zip(
-%   ('Expected: Collection', 'Element'),
-%   ('Expected.Iterator.Element', 'Element'),
-%   ('Expected', 'Array<Element>')):
-
-public func checkIterator<
-  ${genericParam}, I : IteratorProtocol
->(
-  _ expected: ${Expected},
-  _ iterator: I,
-  ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
-  sameValue: (${Element}, ${Element}) -> Bool
-) where I.Element == ${Element} {
-  // Copying a `IteratorProtocol` is allowed.
-  var mutableGen = iterator
-  var actual: [${Element}] = []
-  while let e = mutableGen.next() {
-    actual.append(e)
-  }
-  expectEqualSequence(
-    expected, actual, ${trace}, sameValue: sameValue)
-
-  // Having returned `.None` once, a `IteratorProtocol` should not generate
-  // more elements.
-  for _ in 0..<10 {
-    expectNil(mutableGen.next(), ${trace})
-  }
-}
-
-public func checkIterator<
-  ${genericParam}, I : IteratorProtocol
->(
-  _ expected: ${Expected},
-  _ iterator: I,
-  ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
-) where I.Element == ${Element}, ${Element} : Equatable {
-  checkIterator(
-    expected, iterator, ${trace}, showFrame: false,
-    resiliencyChecks: resiliencyChecks
-  ) { $0 == $1 }
-}
-
-public func checkSequence<
-  ${genericParam}, S : Sequence
->(
-  _ expected: ${Expected},
-  _ sequence: S,
-  ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
-  sameValue: (${Element}, ${Element}) -> Bool
-) where S.Iterator.Element == ${Element} {
-  let expectedCount: Int = numericCast(expected.count)
-  checkIterator(
-    expected, sequence.makeIterator(), ${trace},
-    resiliencyChecks: resiliencyChecks,
-    sameValue: sameValue)
-
-  expectGE(
-    expectedCount, sequence.underestimatedCount, ${trace})
-
-  // Test `_copyContents(initializing:)` if we can do so without destroying the
-  // sequence.
-  _ = sequence._preprocessingPass { () -> Void in
-    var count = 0
-    for _ in sequence { count += 1 }
-    let ptr = UnsafeMutablePointer<S.Iterator.Element>.allocate(capacity: count)
-    let buf = UnsafeMutableBufferPointer(start: ptr, count: count)
-    var (remainders,writtenUpTo) = sequence._copyContents(initializing: buf)
-    expectTrue(remainders.next() == nil, 
-      "_copyContents returned unwritten elements")
-    expectTrue(writtenUpTo == buf.endIndex, 
-      "_copyContents failed to use entire buffer")
-    expectEqualSequence(expected, buf, ${trace}, sameValue: sameValue)
-    ptr.deinitialize(count: count)
-    ptr.deallocate()
-  }
-
-  // Test `_copyToContiguousArray()` if we can do so
-  // without destroying the sequence.
-  _ = sequence._preprocessingPass { () -> Void in
-    let copy = sequence._copyToContiguousArray()
-    expectEqualSequence(expected, copy, ${trace}, sameValue: sameValue)
-  }
-}
-
-public func checkSequence<
-  ${genericParam}, S : Sequence
->(
-  _ expected: ${Expected},
-  _ sequence: S,
-  ${TRACE},
-  resiliencyChecks: CollectionMisuseResiliencyChecks = .all
-) where
-  S.Iterator.Element == ${Element},
-  S.Iterator.Element : Equatable {
-
-  checkSequence(
-    expected, sequence, ${trace}, showFrame: false,
-    resiliencyChecks: resiliencyChecks
-  ) { $0 == $1 }
-}
-
-% end
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift b/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
index e1551c4..4b6f922 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
+++ b/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
@@ -1935,17 +1935,17 @@
 }
 
 //===----------------------------------------------------------------------===//
-// first()
+// first(where:)
 //===----------------------------------------------------------------------===//
 
-self.test("\(testNamePrefix).first/semantics") {
+self.test("\(testNamePrefix).first(where:)/semantics") {
   for test in findTests {
     let s = makeWrappedSequenceWithEquatableElement(test.sequence)
     let closureLifetimeTracker = LifetimeTracked(0)
-    let found = s.first {
+    let found = s.first(where: {
       _blackHole(closureLifetimeTracker)
       return $0 == wrapValueIntoEquatable(test.element)
-    }
+    })
     expectEqual(
       test.expected == nil ? nil : wrapValueIntoEquatable(test.element),
       found,
diff --git a/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift b/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift
new file mode 100644
index 0000000..0dad559
--- /dev/null
+++ b/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift
@@ -0,0 +1,3169 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import StdlibUnittest
+
+public protocol Wrapper {
+  associatedtype Base
+  init(wrapping base: Base)
+  var base: Base { get set }
+}
+
+public protocol LoggingType : Wrapper {
+  associatedtype Log : AnyObject
+}
+
+extension LoggingType {
+  public var log: Log.Type {
+    return Log.self
+  }
+
+  public var selfType: Any.Type {
+    return type(of: self)
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Iterator
+//===----------------------------------------------------------------------===//
+
+public class IteratorLog {
+  public static func dispatchTester<I>(
+    _ iterator: I
+  ) -> LoggingIterator<LoggingIterator<I>> {
+    return LoggingIterator(wrapping: LoggingIterator(wrapping: iterator))
+  }
+  public static var next = TypeIndexed(0)
+}
+
+public struct LoggingIterator<Base : IteratorProtocol>
+  : IteratorProtocol, LoggingType {
+
+  public typealias Log = IteratorLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public mutating func next() -> Base.Element? {
+    Log.next[selfType] += 1
+    return base.next()
+  }
+
+  public var base: Base
+}
+
+//===----------------------------------------------------------------------===//
+// Sequence and Collection logs
+//===----------------------------------------------------------------------===//
+
+public class SequenceLog {
+  public static func dispatchTester<S>(
+    _ s: S
+  ) -> LoggingSequence<LoggingSequence<S>> {
+    return LoggingSequence(wrapping: LoggingSequence(wrapping: s))
+  }
+  public static var makeIterator = TypeIndexed(0)
+  public static var underestimatedCount = TypeIndexed(0)
+  public static var map = TypeIndexed(0)
+  public static var filter = TypeIndexed(0)
+  public static var forEach = TypeIndexed(0)
+  public static var dropFirst = TypeIndexed(0)
+  public static var dropLast = TypeIndexed(0)
+  public static var dropWhile = TypeIndexed(0)
+  public static var prefixWhile = TypeIndexed(0)
+  public static var prefixMaxLength = TypeIndexed(0)
+  public static var suffixMaxLength = TypeIndexed(0)
+  public static var split = TypeIndexed(0)
+  public static var _customContainsEquatableElement = TypeIndexed(0)
+  public static var _preprocessingPass = TypeIndexed(0)
+  public static var _copyToContiguousArray = TypeIndexed(0)
+  public static var _copyContents = TypeIndexed(0)
+}
+
+public class CollectionLog : SequenceLog {
+  public class func dispatchTester<C>(
+    _ c: C
+  ) -> LoggingCollection<LoggingCollection<C>> {
+    return LoggingCollection(wrapping: LoggingCollection(wrapping: c))
+  }
+  public static var startIndex = TypeIndexed(0)
+  public static var endIndex = TypeIndexed(0)
+  public static var subscriptIndex = TypeIndexed(0)
+  public static var subscriptRange = TypeIndexed(0)
+  public static var _failEarlyRangeCheckIndex = TypeIndexed(0)
+  public static var _failEarlyRangeCheckRange = TypeIndexed(0)
+  public static var successor = TypeIndexed(0)
+  public static var formSuccessor = TypeIndexed(0)
+  public static var indices = TypeIndexed(0)
+  public static var prefixUpTo = TypeIndexed(0)
+  public static var prefixThrough = TypeIndexed(0)
+  public static var suffixFrom = TypeIndexed(0)
+  public static var isEmpty = TypeIndexed(0)
+  public static var count = TypeIndexed(0)
+  public static var _customIndexOfEquatableElement = TypeIndexed(0)
+  public static var first = TypeIndexed(0)
+  public static var advance = TypeIndexed(0)
+  public static var advanceLimit = TypeIndexed(0)
+  public static var distance = TypeIndexed(0)
+}
+
+public class BidirectionalCollectionLog : SequenceLog {
+  public class func dispatchTester<C>(
+    _ c: C
+  ) -> LoggingBidirectionalCollection<LoggingBidirectionalCollection<C>> {
+    return LoggingBidirectionalCollection(
+      wrapping: LoggingBidirectionalCollection(wrapping: c))
+  }
+  public static var predecessor = TypeIndexed(0)
+  public static var formPredecessor = TypeIndexed(0)
+  public static var last = TypeIndexed(0)
+}
+
+public class MutableCollectionLog : CollectionLog {
+  public class func dispatchTester<C>(
+    _ c: C
+  ) -> LoggingMutableCollection<LoggingMutableCollection<C>> {
+    return LoggingMutableCollection(
+      wrapping: LoggingMutableCollection(wrapping: c))
+  }
+  public static var subscriptIndexSet = TypeIndexed(0)
+  public static var subscriptRangeSet = TypeIndexed(0)
+  public static var partitionBy = TypeIndexed(0)
+  public static var _withUnsafeMutableBufferPointerIfSupported = TypeIndexed(0)
+  public static var _withUnsafeMutableBufferPointerIfSupportedNonNilReturns =
+    TypeIndexed(0)
+}
+
+/// Data container to keep track of how many times each `Base` type calls methods
+/// of `RangeReplaceableCollection`.
+///
+/// Each static variable is a mapping of Type -> Number of calls.
+public class RangeReplaceableCollectionLog : CollectionLog {
+  public static var init_ = TypeIndexed(0)
+  public static var initRepeating = TypeIndexed(0)
+  public static var initWithSequence = TypeIndexed(0)
+
+  public static var _customRemoveLast = TypeIndexed(0)
+  public static var _customRemoveLastN = TypeIndexed(0)
+  public static var append = TypeIndexed(0)
+  public static var appendContentsOf = TypeIndexed(0)
+  public static var insert = TypeIndexed(0)
+  public static var insertContentsOf = TypeIndexed(0)
+  public static var removeAll = TypeIndexed(0)
+  public static var removeAt = TypeIndexed(0)
+  public static var removeFirst = TypeIndexed(0)
+  public static var removeFirstN = TypeIndexed(0)
+  public static var removeSubrange = TypeIndexed(0)
+  public static var replaceSubrange = TypeIndexed(0)
+  public static var reserveCapacity = TypeIndexed(0)
+
+  public class func dispatchTester<C>(
+    _ rrc: C
+  ) -> LoggingRangeReplaceableCollection<LoggingRangeReplaceableCollection<C>> {
+    return LoggingRangeReplaceableCollection(
+      wrapping: LoggingRangeReplaceableCollection(wrapping: rrc)
+    )
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Sequence and Collection that count method calls
+//===----------------------------------------------------------------------===//
+
+/// Interposes between `Sequence` method calls to increment each method's
+/// counter.
+public struct LoggingSequence<
+  Base : Sequence
+> : Sequence, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = SequenceLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+
+
+}
+/// Interposes between `Collection` method calls to increment each method's
+/// counter.
+public struct LoggingCollection<
+  Base : Collection & Collection
+> : Collection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = CollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+
+}
+/// Interposes between `Collection` method calls to increment each method's
+/// counter.
+public struct LoggingBidirectionalCollection<
+  Base : Collection & BidirectionalCollection
+> : BidirectionalCollection, Collection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = CollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+
+  public func index(before i: Index) -> Index {
+    BidirectionalCollectionLog.predecessor[selfType] += 1
+    return base.index(before: i)
+  }
+
+  public func formIndex(before i: inout Index) {
+    BidirectionalCollectionLog.formPredecessor[selfType] += 1
+    base.formIndex(before: &i)
+  }
+
+  public var last: Iterator.Element? {
+    BidirectionalCollectionLog.last[selfType] += 1
+    return base.last
+  }
+}
+/// Interposes between `Collection` method calls to increment each method's
+/// counter.
+public struct LoggingRandomAccessCollection<
+  Base : Collection & RandomAccessCollection
+> : RandomAccessCollection, Collection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = CollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+
+  public func index(before i: Index) -> Index {
+    BidirectionalCollectionLog.predecessor[selfType] += 1
+    return base.index(before: i)
+  }
+
+  public func formIndex(before i: inout Index) {
+    BidirectionalCollectionLog.formPredecessor[selfType] += 1
+    base.formIndex(before: &i)
+  }
+
+  public var last: Iterator.Element? {
+    BidirectionalCollectionLog.last[selfType] += 1
+    return base.last
+  }
+}
+/// Interposes between `MutableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingMutableCollection<
+  Base : MutableCollection & Collection
+> : Collection, MutableCollection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = MutableCollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+    set {
+      Log.subscriptIndexSet[selfType] += 1
+      base[position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+    set {
+      Log.subscriptRangeSet[selfType] += 1
+      base[bounds] = newValue
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+  public mutating func partition(
+    by belongsInSecondPartition: (Iterator.Element) throws -> Bool
+  ) rethrows -> Index {
+    Log.partitionBy[selfType] += 1
+    return try base.partition(by: belongsInSecondPartition)
+  }
+
+  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+    _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+  ) rethrows -> R? {
+    Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+    if result != nil {
+      Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+    }
+    return result
+  }
+
+}
+/// Interposes between `MutableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingMutableBidirectionalCollection<
+  Base : MutableCollection & BidirectionalCollection
+> : BidirectionalCollection, MutableCollection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = MutableCollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+    set {
+      Log.subscriptIndexSet[selfType] += 1
+      base[position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+    set {
+      Log.subscriptRangeSet[selfType] += 1
+      base[bounds] = newValue
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+  public mutating func partition(
+    by belongsInSecondPartition: (Iterator.Element) throws -> Bool
+  ) rethrows -> Index {
+    Log.partitionBy[selfType] += 1
+    return try base.partition(by: belongsInSecondPartition)
+  }
+
+  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+    _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+  ) rethrows -> R? {
+    Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+    if result != nil {
+      Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+    }
+    return result
+  }
+
+  public func index(before i: Index) -> Index {
+    BidirectionalCollectionLog.predecessor[selfType] += 1
+    return base.index(before: i)
+  }
+
+  public func formIndex(before i: inout Index) {
+    BidirectionalCollectionLog.formPredecessor[selfType] += 1
+    base.formIndex(before: &i)
+  }
+
+  public var last: Iterator.Element? {
+    BidirectionalCollectionLog.last[selfType] += 1
+    return base.last
+  }
+}
+/// Interposes between `MutableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingMutableRandomAccessCollection<
+  Base : MutableCollection & RandomAccessCollection
+> : RandomAccessCollection, MutableCollection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = MutableCollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+    set {
+      Log.subscriptIndexSet[selfType] += 1
+      base[position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+    set {
+      Log.subscriptRangeSet[selfType] += 1
+      base[bounds] = newValue
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+  public mutating func partition(
+    by belongsInSecondPartition: (Iterator.Element) throws -> Bool
+  ) rethrows -> Index {
+    Log.partitionBy[selfType] += 1
+    return try base.partition(by: belongsInSecondPartition)
+  }
+
+  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+    _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+  ) rethrows -> R? {
+    Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+    if result != nil {
+      Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+    }
+    return result
+  }
+
+  public func index(before i: Index) -> Index {
+    BidirectionalCollectionLog.predecessor[selfType] += 1
+    return base.index(before: i)
+  }
+
+  public func formIndex(before i: inout Index) {
+    BidirectionalCollectionLog.formPredecessor[selfType] += 1
+    base.formIndex(before: &i)
+  }
+
+  public var last: Iterator.Element? {
+    BidirectionalCollectionLog.last[selfType] += 1
+    return base.last
+  }
+}
+/// Interposes between `RangeReplaceableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingRangeReplaceableCollection<
+  Base : RangeReplaceableCollection & Collection
+> : Collection, RangeReplaceableCollection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = RangeReplaceableCollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+
+  public init() {
+    self.base = Base()
+    Log.init_[selfType] += 1
+  }
+
+  public init(repeating repeatedValue: Iterator.Element, count: Int) {
+    self.base = Base(repeating: repeatedValue, count: count)
+    Log.initRepeating[selfType] += 1
+  }
+
+  public init<S : Sequence>(_ elements: S)
+    where S.Iterator.Element == Iterator.Element {
+    self.base = Base(elements)
+    Log.initWithSequence[selfType] += 1
+  }
+
+  public mutating func _customRemoveLast() -> Base.Iterator.Element? {
+    Log._customRemoveLast[selfType] += 1
+    return base._customRemoveLast()
+  }
+
+  public mutating func _customRemoveLast(_ n: Int) -> Bool {
+    Log._customRemoveLastN[selfType] += 1
+    return base._customRemoveLast(n)
+  }
+
+  public mutating func append(_ newElement: Base.Iterator.Element) {
+    Log.append[selfType] += 1
+    base.append(newElement)
+  }
+
+  public mutating func append<S : Sequence>(
+    contentsOf newElements: S
+  ) where S.Iterator.Element == Base.Iterator.Element {
+    Log.appendContentsOf[selfType] += 1
+    base.append(contentsOf: newElements)
+  }
+
+  public mutating func insert(
+    _ newElement: Base.Iterator.Element, at i: Index
+  ) {
+    Log.insert[selfType] += 1
+    base.insert(newElement, at: i)
+  }
+
+  public mutating func insert<C : Collection>(
+    contentsOf newElements: C, at i: Index
+  ) where C.Iterator.Element == Base.Iterator.Element {
+    Log.insertContentsOf[selfType] += 1
+    base.insert(contentsOf: newElements, at: i)
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
+    Log.removeAll[selfType] += 1
+    base.removeAll(keepingCapacity: keepCapacity)
+  }
+
+  @discardableResult
+  public mutating func remove(at index: Index) -> Base.Iterator.Element {
+    Log.removeAt[selfType] += 1
+    return base.remove(at: index)
+  }
+
+  @discardableResult
+  public mutating func removeFirst() -> Base.Iterator.Element {
+    Log.removeFirst[selfType] += 1
+    return base.removeFirst()
+  }
+
+  public mutating func removeFirst(_ n: Int) {
+    Log.removeFirstN[selfType] += 1
+    base.removeFirst(n)
+  }
+
+  public mutating func removeSubrange(_ bounds: Range<Index>) {
+    Log.removeSubrange[selfType] += 1
+    base.removeSubrange(bounds)
+  }
+
+  public mutating func replaceSubrange<C : Collection>(
+    _ bounds: Range<Index>, with newElements: C
+  ) where C.Iterator.Element == Base.Iterator.Element {
+    Log.replaceSubrange[selfType] += 1
+    base.replaceSubrange(bounds, with: newElements)
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    Log.reserveCapacity[selfType] += 1
+    base.reserveCapacity(n)
+  }
+}
+/// Interposes between `RangeReplaceableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingRangeReplaceableBidirectionalCollection<
+  Base : RangeReplaceableCollection & BidirectionalCollection
+> : BidirectionalCollection, RangeReplaceableCollection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = RangeReplaceableCollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+
+  public init() {
+    self.base = Base()
+    Log.init_[selfType] += 1
+  }
+
+  public init(repeating repeatedValue: Iterator.Element, count: Int) {
+    self.base = Base(repeating: repeatedValue, count: count)
+    Log.initRepeating[selfType] += 1
+  }
+
+  public init<S : Sequence>(_ elements: S)
+    where S.Iterator.Element == Iterator.Element {
+    self.base = Base(elements)
+    Log.initWithSequence[selfType] += 1
+  }
+
+  public mutating func _customRemoveLast() -> Base.Iterator.Element? {
+    Log._customRemoveLast[selfType] += 1
+    return base._customRemoveLast()
+  }
+
+  public mutating func _customRemoveLast(_ n: Int) -> Bool {
+    Log._customRemoveLastN[selfType] += 1
+    return base._customRemoveLast(n)
+  }
+
+  public mutating func append(_ newElement: Base.Iterator.Element) {
+    Log.append[selfType] += 1
+    base.append(newElement)
+  }
+
+  public mutating func append<S : Sequence>(
+    contentsOf newElements: S
+  ) where S.Iterator.Element == Base.Iterator.Element {
+    Log.appendContentsOf[selfType] += 1
+    base.append(contentsOf: newElements)
+  }
+
+  public mutating func insert(
+    _ newElement: Base.Iterator.Element, at i: Index
+  ) {
+    Log.insert[selfType] += 1
+    base.insert(newElement, at: i)
+  }
+
+  public mutating func insert<C : Collection>(
+    contentsOf newElements: C, at i: Index
+  ) where C.Iterator.Element == Base.Iterator.Element {
+    Log.insertContentsOf[selfType] += 1
+    base.insert(contentsOf: newElements, at: i)
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
+    Log.removeAll[selfType] += 1
+    base.removeAll(keepingCapacity: keepCapacity)
+  }
+
+  @discardableResult
+  public mutating func remove(at index: Index) -> Base.Iterator.Element {
+    Log.removeAt[selfType] += 1
+    return base.remove(at: index)
+  }
+
+  @discardableResult
+  public mutating func removeFirst() -> Base.Iterator.Element {
+    Log.removeFirst[selfType] += 1
+    return base.removeFirst()
+  }
+
+  public mutating func removeFirst(_ n: Int) {
+    Log.removeFirstN[selfType] += 1
+    base.removeFirst(n)
+  }
+
+  public mutating func removeSubrange(_ bounds: Range<Index>) {
+    Log.removeSubrange[selfType] += 1
+    base.removeSubrange(bounds)
+  }
+
+  public mutating func replaceSubrange<C : Collection>(
+    _ bounds: Range<Index>, with newElements: C
+  ) where C.Iterator.Element == Base.Iterator.Element {
+    Log.replaceSubrange[selfType] += 1
+    base.replaceSubrange(bounds, with: newElements)
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    Log.reserveCapacity[selfType] += 1
+    base.reserveCapacity(n)
+  }
+  public func index(before i: Index) -> Index {
+    BidirectionalCollectionLog.predecessor[selfType] += 1
+    return base.index(before: i)
+  }
+
+  public func formIndex(before i: inout Index) {
+    BidirectionalCollectionLog.formPredecessor[selfType] += 1
+    base.formIndex(before: &i)
+  }
+
+  public var last: Iterator.Element? {
+    BidirectionalCollectionLog.last[selfType] += 1
+    return base.last
+  }
+}
+/// Interposes between `RangeReplaceableCollection` method calls to increment each method's
+/// counter.
+public struct LoggingRangeReplaceableRandomAccessCollection<
+  Base : RangeReplaceableCollection & RandomAccessCollection
+> : RandomAccessCollection, RangeReplaceableCollection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = RangeReplaceableCollectionLog
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public typealias Iterator = LoggingIterator<Base.Iterator>
+
+  public func makeIterator() -> Iterator {
+    Log.makeIterator[selfType] += 1
+    return LoggingIterator(wrapping: base.makeIterator())
+  }
+
+  public var underestimatedCount: Int {
+    Log.underestimatedCount[selfType] += 1
+    return base.underestimatedCount
+  }
+
+  public func map<T>(
+    _ transform: (Base.Iterator.Element) throws -> T
+  ) rethrows -> [T] {
+    Log.map[selfType] += 1
+    return try base.map(transform)
+  }
+
+  public func filter(
+    _ isIncluded: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [Base.Iterator.Element] {
+    Log.filter[selfType] += 1
+    return try base.filter(isIncluded)
+  }
+
+  public func forEach(
+    _ body: (Base.Iterator.Element) throws -> Void
+  ) rethrows {
+    Log.forEach[selfType] += 1
+    try base.forEach(body)
+  }
+
+  public typealias SubSequence = Base.SubSequence
+
+  public func dropFirst(_ n: Int) -> SubSequence {
+    Log.dropFirst[selfType] += 1
+    return base.dropFirst(n)
+  }
+
+  public func dropLast(_ n: Int) -> SubSequence {
+    Log.dropLast[selfType] += 1
+    return base.dropLast(n)
+  }
+
+  public func drop(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.dropWhile[selfType] += 1
+    return try base.drop(while: predicate)
+  }
+
+  public func prefix(_ maxLength: Int) -> SubSequence {
+    Log.prefixMaxLength[selfType] += 1
+    return base.prefix(maxLength)
+  }
+
+  public func prefix(
+    while predicate: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> SubSequence {
+    Log.prefixWhile[selfType] += 1
+    return try base.prefix(while: predicate)
+  }
+
+  public func suffix(_ maxLength: Int) -> SubSequence {
+    Log.suffixMaxLength[selfType] += 1
+    return base.suffix(maxLength)
+  }
+
+  public func split(
+    maxSplits: Int = Int.max,
+    omittingEmptySubsequences: Bool = true,
+    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
+  ) rethrows -> [SubSequence] {
+    Log.split[selfType] += 1
+    return try base.split(
+      maxSplits: maxSplits,
+      omittingEmptySubsequences: omittingEmptySubsequences,
+      whereSeparator: isSeparator)
+  }
+
+  public func _customContainsEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Bool? {
+    Log._customContainsEquatableElement[selfType] += 1
+    return base._customContainsEquatableElement(element)
+  }
+
+  /// If `self` is multi-pass (i.e., a `Collection`), invoke
+  /// `preprocess` on `self` and return its result.  Otherwise, return
+  /// `nil`.
+  public func _preprocessingPass<R>(
+    _ preprocess: () throws -> R
+  ) rethrows -> R? {
+    Log._preprocessingPass[selfType] += 1
+    return try base._preprocessingPass(preprocess)
+  }
+
+  /// Create a native array buffer containing the elements of `self`,
+  /// in the same order.
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+    Log._copyToContiguousArray[selfType] += 1
+    return base._copyToContiguousArray()
+  }
+
+  /// Copy a Sequence into an array.
+  public func _copyContents(
+    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
+  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
+    Log._copyContents[selfType] += 1
+    let (it,idx) = base._copyContents(initializing: buffer)
+    return (Iterator(wrapping: it),idx)
+  }
+
+  public typealias Index = Base.Index
+
+  public var startIndex: Index {
+    Log.startIndex[selfType] += 1
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    Log.endIndex[selfType] += 1
+    return base.endIndex
+  }
+
+  public subscript(position: Index) -> Base.Iterator.Element {
+    get {
+      Log.subscriptIndex[selfType] += 1
+      return base[position]
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      Log.subscriptRange[selfType] += 1
+      return base[bounds]
+    }
+  }
+
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckIndex[selfType] += 1
+    base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    Log._failEarlyRangeCheckRange[selfType] += 1
+    base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    Log.successor[selfType] += 1
+    return base.index(after: i)
+  }
+
+  public func formIndex(after i: inout Index) {
+    Log.formSuccessor[selfType] += 1
+    base.formIndex(after: &i)
+  }
+
+  public typealias Indices = Base.Indices
+
+  public var indices: Indices {
+    Log.indices[selfType] += 1
+    return base.indices
+  }
+
+  public func prefix(upTo end: Index) -> SubSequence {
+    Log.prefixUpTo[selfType] += 1
+    return base.prefix(upTo: end)
+  }
+
+  public func prefix(through position: Index) -> SubSequence {
+    Log.prefixThrough[selfType] += 1
+    return base.prefix(through: position)
+  }
+
+  public func suffix(from start: Index) -> SubSequence {
+    Log.suffixFrom[selfType] += 1
+    return base.suffix(from: start)
+  }
+
+  public var isEmpty: Bool {
+    Log.isEmpty[selfType] += 1
+    return base.isEmpty
+  }
+
+  public var count: Int {
+    Log.count[selfType] += 1
+    return base.count
+  }
+
+  public func _customIndexOfEquatableElement(
+    _ element: Base.Iterator.Element
+  ) -> Index?? {
+    Log._customIndexOfEquatableElement[selfType] += 1
+    return base._customIndexOfEquatableElement(element)
+  }
+
+  public var first: Base.Iterator.Element? {
+    Log.first[selfType] += 1
+    return base.first
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    Log.advance[selfType] += 1
+    return base.index(i, offsetBy: n)
+  }
+
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    Log.advanceLimit[selfType] += 1
+    return base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    Log.distance[selfType] += 1
+    return base.distance(from: start, to: end)
+  }
+
+
+  public init() {
+    self.base = Base()
+    Log.init_[selfType] += 1
+  }
+
+  public init(repeating repeatedValue: Iterator.Element, count: Int) {
+    self.base = Base(repeating: repeatedValue, count: count)
+    Log.initRepeating[selfType] += 1
+  }
+
+  public init<S : Sequence>(_ elements: S)
+    where S.Iterator.Element == Iterator.Element {
+    self.base = Base(elements)
+    Log.initWithSequence[selfType] += 1
+  }
+
+  public mutating func _customRemoveLast() -> Base.Iterator.Element? {
+    Log._customRemoveLast[selfType] += 1
+    return base._customRemoveLast()
+  }
+
+  public mutating func _customRemoveLast(_ n: Int) -> Bool {
+    Log._customRemoveLastN[selfType] += 1
+    return base._customRemoveLast(n)
+  }
+
+  public mutating func append(_ newElement: Base.Iterator.Element) {
+    Log.append[selfType] += 1
+    base.append(newElement)
+  }
+
+  public mutating func append<S : Sequence>(
+    contentsOf newElements: S
+  ) where S.Iterator.Element == Base.Iterator.Element {
+    Log.appendContentsOf[selfType] += 1
+    base.append(contentsOf: newElements)
+  }
+
+  public mutating func insert(
+    _ newElement: Base.Iterator.Element, at i: Index
+  ) {
+    Log.insert[selfType] += 1
+    base.insert(newElement, at: i)
+  }
+
+  public mutating func insert<C : Collection>(
+    contentsOf newElements: C, at i: Index
+  ) where C.Iterator.Element == Base.Iterator.Element {
+    Log.insertContentsOf[selfType] += 1
+    base.insert(contentsOf: newElements, at: i)
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
+    Log.removeAll[selfType] += 1
+    base.removeAll(keepingCapacity: keepCapacity)
+  }
+
+  @discardableResult
+  public mutating func remove(at index: Index) -> Base.Iterator.Element {
+    Log.removeAt[selfType] += 1
+    return base.remove(at: index)
+  }
+
+  @discardableResult
+  public mutating func removeFirst() -> Base.Iterator.Element {
+    Log.removeFirst[selfType] += 1
+    return base.removeFirst()
+  }
+
+  public mutating func removeFirst(_ n: Int) {
+    Log.removeFirstN[selfType] += 1
+    base.removeFirst(n)
+  }
+
+  public mutating func removeSubrange(_ bounds: Range<Index>) {
+    Log.removeSubrange[selfType] += 1
+    base.removeSubrange(bounds)
+  }
+
+  public mutating func replaceSubrange<C : Collection>(
+    _ bounds: Range<Index>, with newElements: C
+  ) where C.Iterator.Element == Base.Iterator.Element {
+    Log.replaceSubrange[selfType] += 1
+    base.replaceSubrange(bounds, with: newElements)
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    Log.reserveCapacity[selfType] += 1
+    base.reserveCapacity(n)
+  }
+  public func index(before i: Index) -> Index {
+    BidirectionalCollectionLog.predecessor[selfType] += 1
+    return base.index(before: i)
+  }
+
+  public func formIndex(before i: inout Index) {
+    BidirectionalCollectionLog.formPredecessor[selfType] += 1
+    base.formIndex(before: &i)
+  }
+
+  public var last: Iterator.Element? {
+    BidirectionalCollectionLog.last[selfType] += 1
+    return base.last
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Collections that count calls to `_withUnsafeMutableBufferPointerIfSupported`
+//===----------------------------------------------------------------------===//
+
+/// Interposes between `_withUnsafeMutableBufferPointerIfSupported` method calls
+/// to increment a counter. Calls to this method from within dispatched methods
+/// are uncounted by the standard logging collection wrapper.
+public struct BufferAccessLoggingMutableCollection<
+  Base : MutableCollection & Collection
+> : MutableCollection, Collection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = MutableCollectionLog
+
+  public typealias SubSequence = Base.SubSequence
+  public typealias Iterator = Base.Iterator
+  public typealias Element = Base.Element
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public func makeIterator() -> Iterator {
+    return base.makeIterator()
+  }
+
+  public typealias Index = Base.Index
+  public typealias Indices = Base.Indices
+
+  public var startIndex: Index {
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    return base.endIndex
+  }
+
+  public var indices: Indices {
+    return base.indices
+  }
+
+  public subscript(position: Index) -> Element {
+    get {
+      return base[position]
+    }
+    set {
+      base[position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      return base[bounds]
+    }
+    set {
+      base[bounds] = newValue
+    }
+  }
+
+  public func index(after i: Index) -> Index {
+    return base.index(after: i)
+  }
+
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    return base.index(i, offsetBy: n)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    return base.distance(from: start, to: end)
+  }
+
+  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+    _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+  ) rethrows -> R? {
+    Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+    if result != nil {
+      Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+    }
+    return result
+  }
+}
+/// Interposes between `_withUnsafeMutableBufferPointerIfSupported` method calls
+/// to increment a counter. Calls to this method from within dispatched methods
+/// are uncounted by the standard logging collection wrapper.
+public struct BufferAccessLoggingMutableBidirectionalCollection<
+  Base : MutableCollection & BidirectionalCollection
+> : MutableCollection, BidirectionalCollection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = MutableCollectionLog
+
+  public typealias SubSequence = Base.SubSequence
+  public typealias Iterator = Base.Iterator
+  public typealias Element = Base.Element
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public func makeIterator() -> Iterator {
+    return base.makeIterator()
+  }
+
+  public typealias Index = Base.Index
+  public typealias Indices = Base.Indices
+
+  public var startIndex: Index {
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    return base.endIndex
+  }
+
+  public var indices: Indices {
+    return base.indices
+  }
+
+  public subscript(position: Index) -> Element {
+    get {
+      return base[position]
+    }
+    set {
+      base[position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      return base[bounds]
+    }
+    set {
+      base[bounds] = newValue
+    }
+  }
+
+  public func index(after i: Index) -> Index {
+    return base.index(after: i)
+  }
+
+  public func index(before i: Index) -> Index {
+    return base.index(before: i)
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    return base.index(i, offsetBy: n)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    return base.distance(from: start, to: end)
+  }
+
+  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+    _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+  ) rethrows -> R? {
+    Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+    if result != nil {
+      Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+    }
+    return result
+  }
+}
+/// Interposes between `_withUnsafeMutableBufferPointerIfSupported` method calls
+/// to increment a counter. Calls to this method from within dispatched methods
+/// are uncounted by the standard logging collection wrapper.
+public struct BufferAccessLoggingMutableRandomAccessCollection<
+  Base : MutableCollection & RandomAccessCollection
+> : MutableCollection, RandomAccessCollection, LoggingType {
+
+  public var base: Base
+
+  public typealias Log = MutableCollectionLog
+
+  public typealias SubSequence = Base.SubSequence
+  public typealias Iterator = Base.Iterator
+  public typealias Element = Base.Element
+
+  public init(wrapping base: Base) {
+    self.base = base
+  }
+
+  public func makeIterator() -> Iterator {
+    return base.makeIterator()
+  }
+
+  public typealias Index = Base.Index
+  public typealias Indices = Base.Indices
+
+  public var startIndex: Index {
+    return base.startIndex
+  }
+
+  public var endIndex: Index {
+    return base.endIndex
+  }
+
+  public var indices: Indices {
+    return base.indices
+  }
+
+  public subscript(position: Index) -> Element {
+    get {
+      return base[position]
+    }
+    set {
+      base[position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    get {
+      return base[bounds]
+    }
+    set {
+      base[bounds] = newValue
+    }
+  }
+
+  public func index(after i: Index) -> Index {
+    return base.index(after: i)
+  }
+
+  public func index(before i: Index) -> Index {
+    return base.index(before: i)
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    return base.index(i, offsetBy: n)
+  }
+
+  public func distance(from start: Index, to end: Index) -> Int {
+    return base.distance(from: start, to: end)
+  }
+
+  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
+    _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
+  ) rethrows -> R? {
+    Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
+    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
+    if result != nil {
+      Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
+    }
+    return result
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Custom assertions
+//===----------------------------------------------------------------------===//
+
+public func expectCustomizable<T : LoggingType>(
+  _: T, _ counters: TypeIndexed<Int>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  T.Base : LoggingType,
+  T.Log == T.Base.Log {
+  let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
+  expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
+  expectEqual(
+    counters[T.self], counters[T.Base.self], message(), stackTrace: newTrace)
+}
+
+public func expectNotCustomizable<T : LoggingType>(
+  _: T, _ counters: TypeIndexed<Int>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where
+  T.Base : LoggingType,
+  T.Log == T.Base.Log {
+  let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
+  expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
+  expectEqual(0, counters[T.Base.self], message(), stackTrace: newTrace)
+}
diff --git a/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb b/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb
deleted file mode 100644
index 1cac3f9..0000000
--- a/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb
+++ /dev/null
@@ -1,700 +0,0 @@
-//===--- LoggingWrappers.swift.gyb ----------------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-%{
-from gyb_stdlib_support import TRAVERSALS, collectionForTraversal
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
-import StdlibUnittest
-
-public protocol Wrapper {
-  associatedtype Base
-  init(wrapping base: Base)
-  var base: Base { get set }
-}
-
-public protocol LoggingType : Wrapper {
-  associatedtype Log : AnyObject
-}
-
-extension LoggingType {
-  public var log: Log.Type {
-    return Log.self
-  }
-
-  public var selfType: Any.Type {
-    return type(of: self)
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Iterator
-//===----------------------------------------------------------------------===//
-
-public class IteratorLog {
-  public static func dispatchTester<I>(
-    _ iterator: I
-  ) -> LoggingIterator<LoggingIterator<I>> {
-    return LoggingIterator(wrapping: LoggingIterator(wrapping: iterator))
-  }
-  public static var next = TypeIndexed(0)
-}
-
-public struct LoggingIterator<Base : IteratorProtocol>
-  : IteratorProtocol, LoggingType {
-
-  public typealias Log = IteratorLog
-
-  public init(wrapping base: Base) {
-    self.base = base
-  }
-
-  public mutating func next() -> Base.Element? {
-    Log.next[selfType] += 1
-    return base.next()
-  }
-
-  public var base: Base
-}
-
-//===----------------------------------------------------------------------===//
-// Sequence and Collection logs
-//===----------------------------------------------------------------------===//
-
-public class SequenceLog {
-  public static func dispatchTester<S>(
-    _ s: S
-  ) -> LoggingSequence<LoggingSequence<S>> {
-    return LoggingSequence(wrapping: LoggingSequence(wrapping: s))
-  }
-  public static var makeIterator = TypeIndexed(0)
-  public static var underestimatedCount = TypeIndexed(0)
-  public static var map = TypeIndexed(0)
-  public static var filter = TypeIndexed(0)
-  public static var forEach = TypeIndexed(0)
-  public static var dropFirst = TypeIndexed(0)
-  public static var dropLast = TypeIndexed(0)
-  public static var dropWhile = TypeIndexed(0)
-  public static var prefixWhile = TypeIndexed(0)
-  public static var prefixMaxLength = TypeIndexed(0)
-  public static var suffixMaxLength = TypeIndexed(0)
-  public static var split = TypeIndexed(0)
-  public static var _customContainsEquatableElement = TypeIndexed(0)
-  public static var _preprocessingPass = TypeIndexed(0)
-  public static var _copyToContiguousArray = TypeIndexed(0)
-  public static var _copyContents = TypeIndexed(0)
-}
-
-public class CollectionLog : SequenceLog {
-  public class func dispatchTester<C>(
-    _ c: C
-  ) -> LoggingCollection<LoggingCollection<C>> {
-    return LoggingCollection(wrapping: LoggingCollection(wrapping: c))
-  }
-  public static var startIndex = TypeIndexed(0)
-  public static var endIndex = TypeIndexed(0)
-  public static var subscriptIndex = TypeIndexed(0)
-  public static var subscriptRange = TypeIndexed(0)
-  public static var _failEarlyRangeCheckIndex = TypeIndexed(0)
-  public static var _failEarlyRangeCheckRange = TypeIndexed(0)
-  public static var successor = TypeIndexed(0)
-  public static var formSuccessor = TypeIndexed(0)
-  public static var indices = TypeIndexed(0)
-  public static var prefixUpTo = TypeIndexed(0)
-  public static var prefixThrough = TypeIndexed(0)
-  public static var suffixFrom = TypeIndexed(0)
-  public static var isEmpty = TypeIndexed(0)
-  public static var count = TypeIndexed(0)
-  public static var _customIndexOfEquatableElement = TypeIndexed(0)
-  public static var first = TypeIndexed(0)
-  public static var advance = TypeIndexed(0)
-  public static var advanceLimit = TypeIndexed(0)
-  public static var distance = TypeIndexed(0)
-}
-
-public class BidirectionalCollectionLog : SequenceLog {
-  public class func dispatchTester<C>(
-    _ c: C
-  ) -> LoggingBidirectionalCollection<LoggingBidirectionalCollection<C>> {
-    return LoggingBidirectionalCollection(
-      wrapping: LoggingBidirectionalCollection(wrapping: c))
-  }
-  public static var predecessor = TypeIndexed(0)
-  public static var formPredecessor = TypeIndexed(0)
-  public static var last = TypeIndexed(0)
-}
-
-public class MutableCollectionLog : CollectionLog {
-  public class func dispatchTester<C>(
-    _ c: C
-  ) -> LoggingMutableCollection<LoggingMutableCollection<C>> {
-    return LoggingMutableCollection(
-      wrapping: LoggingMutableCollection(wrapping: c))
-  }
-  public static var subscriptIndexSet = TypeIndexed(0)
-  public static var subscriptRangeSet = TypeIndexed(0)
-  public static var partitionBy = TypeIndexed(0)
-  public static var _withUnsafeMutableBufferPointerIfSupported = TypeIndexed(0)
-  public static var _withUnsafeMutableBufferPointerIfSupportedNonNilReturns =
-    TypeIndexed(0)
-}
-
-/// Data container to keep track of how many times each `Base` type calls methods
-/// of `RangeReplaceableCollection`.
-///
-/// Each static variable is a mapping of Type -> Number of calls.
-public class RangeReplaceableCollectionLog : CollectionLog {
-  public static var init_ = TypeIndexed(0)
-  public static var initRepeating = TypeIndexed(0)
-  public static var initWithSequence = TypeIndexed(0)
-
-  public static var _customRemoveLast = TypeIndexed(0)
-  public static var _customRemoveLastN = TypeIndexed(0)
-  public static var append = TypeIndexed(0)
-  public static var appendContentsOf = TypeIndexed(0)
-  public static var insert = TypeIndexed(0)
-  public static var insertContentsOf = TypeIndexed(0)
-  public static var removeAll = TypeIndexed(0)
-  public static var removeAt = TypeIndexed(0)
-  public static var removeFirst = TypeIndexed(0)
-  public static var removeFirstN = TypeIndexed(0)
-  public static var removeSubrange = TypeIndexed(0)
-  public static var replaceSubrange = TypeIndexed(0)
-  public static var reserveCapacity = TypeIndexed(0)
-
-  public class func dispatchTester<C>(
-    _ rrc: C
-  ) -> LoggingRangeReplaceableCollection<LoggingRangeReplaceableCollection<C>> {
-    return LoggingRangeReplaceableCollection(
-      wrapping: LoggingRangeReplaceableCollection(wrapping: rrc)
-    )
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Sequence and Collection that count method calls
-//===----------------------------------------------------------------------===//
-
-% for Kind in ['Sequence', 'Collection', 'MutableCollection', 'RangeReplaceableCollection']:
-%   for Traversal in [''] if Kind == 'Sequence' else TRAVERSALS:
-%     if Kind == 'Sequence':
-%       Self = 'LoggingSequence'
-%     else:
-%       Self = 'Logging' + Kind.replace('Collection', collectionForTraversal(Traversal))
-%     end
-%     if Kind == 'Sequence':
-%       Constraints = Kind
-%       Protocols = Kind
-%     else:
-%       Constraints = Kind + ' & ' + collectionForTraversal(Traversal)
-%       Protocols = ', '.join(set([Kind, collectionForTraversal(Traversal)]))
-%     end
-/// Interposes between `${Kind}` method calls to increment each method's
-/// counter.
-public struct ${Self}<
-  Base : ${Constraints}
-> : ${Protocols}, LoggingType {
-
-  public var base: Base
-
-  public typealias Log = ${Kind}Log
-
-  public init(wrapping base: Base) {
-    self.base = base
-  }
-
-  public typealias Iterator = LoggingIterator<Base.Iterator>
-
-  public func makeIterator() -> Iterator {
-    Log.makeIterator[selfType] += 1
-    return LoggingIterator(wrapping: base.makeIterator())
-  }
-
-  public var underestimatedCount: Int {
-    Log.underestimatedCount[selfType] += 1
-    return base.underestimatedCount
-  }
-
-  public func map<T>(
-    _ transform: (Base.Iterator.Element) throws -> T
-  ) rethrows -> [T] {
-    Log.map[selfType] += 1
-    return try base.map(transform)
-  }
-
-  public func filter(
-    _ isIncluded: (Base.Iterator.Element) throws -> Bool
-  ) rethrows -> [Base.Iterator.Element] {
-    Log.filter[selfType] += 1
-    return try base.filter(isIncluded)
-  }
-
-  public func forEach(
-    _ body: (Base.Iterator.Element) throws -> Void
-  ) rethrows {
-    Log.forEach[selfType] += 1
-    try base.forEach(body)
-  }
-
-  public typealias SubSequence = Base.SubSequence
-
-  public func dropFirst(_ n: Int) -> SubSequence {
-    Log.dropFirst[selfType] += 1
-    return base.dropFirst(n)
-  }
-
-  public func dropLast(_ n: Int) -> SubSequence {
-    Log.dropLast[selfType] += 1
-    return base.dropLast(n)
-  }
-
-  public func drop(
-    while predicate: (Base.Iterator.Element) throws -> Bool
-  ) rethrows -> SubSequence {
-    Log.dropWhile[selfType] += 1
-    return try base.drop(while: predicate)
-  }
-
-  public func prefix(_ maxLength: Int) -> SubSequence {
-    Log.prefixMaxLength[selfType] += 1
-    return base.prefix(maxLength)
-  }
-
-  public func prefix(
-    while predicate: (Base.Iterator.Element) throws -> Bool
-  ) rethrows -> SubSequence {
-    Log.prefixWhile[selfType] += 1
-    return try base.prefix(while: predicate)
-  }
-
-  public func suffix(_ maxLength: Int) -> SubSequence {
-    Log.suffixMaxLength[selfType] += 1
-    return base.suffix(maxLength)
-  }
-
-  public func split(
-    maxSplits: Int = Int.max,
-    omittingEmptySubsequences: Bool = true,
-    whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
-  ) rethrows -> [SubSequence] {
-    Log.split[selfType] += 1
-    return try base.split(
-      maxSplits: maxSplits,
-      omittingEmptySubsequences: omittingEmptySubsequences,
-      whereSeparator: isSeparator)
-  }
-
-  public func _customContainsEquatableElement(
-    _ element: Base.Iterator.Element
-  ) -> Bool? {
-    Log._customContainsEquatableElement[selfType] += 1
-    return base._customContainsEquatableElement(element)
-  }
-
-  /// If `self` is multi-pass (i.e., a `Collection`), invoke
-  /// `preprocess` on `self` and return its result.  Otherwise, return
-  /// `nil`.
-  public func _preprocessingPass<R>(
-    _ preprocess: () throws -> R
-  ) rethrows -> R? {
-    Log._preprocessingPass[selfType] += 1
-    return try base._preprocessingPass(preprocess)
-  }
-
-  /// Create a native array buffer containing the elements of `self`,
-  /// in the same order.
-  public func _copyToContiguousArray()
-    -> ContiguousArray<Base.Iterator.Element> {
-    Log._copyToContiguousArray[selfType] += 1
-    return base._copyToContiguousArray()
-  }
-
-  /// Copy a Sequence into an array.
-  public func _copyContents(
-    initializing buffer: UnsafeMutableBufferPointer<Iterator.Element>
-  ) -> (Iterator,UnsafeMutableBufferPointer<Iterator.Element>.Index) {
-    Log._copyContents[selfType] += 1
-    let (it,idx) = base._copyContents(initializing: buffer)
-    return (Iterator(wrapping: it),idx)
-  }
-
-%     if Kind in ['Collection', 'MutableCollection', 'RangeReplaceableCollection']:
-  public typealias Index = Base.Index
-
-  public var startIndex: Index {
-    Log.startIndex[selfType] += 1
-    return base.startIndex
-  }
-
-  public var endIndex: Index {
-    Log.endIndex[selfType] += 1
-    return base.endIndex
-  }
-
-  public subscript(position: Index) -> Base.Iterator.Element {
-    get {
-      Log.subscriptIndex[selfType] += 1
-      return base[position]
-    }
-%       if Kind == 'MutableCollection':
-    set {
-      Log.subscriptIndexSet[selfType] += 1
-      base[position] = newValue
-    }
-%       end
-  }
-
-  public subscript(bounds: Range<Index>) -> SubSequence {
-    get {
-      Log.subscriptRange[selfType] += 1
-      return base[bounds]
-    }
-%       if Kind == 'MutableCollection':
-    set {
-      Log.subscriptRangeSet[selfType] += 1
-      base[bounds] = newValue
-    }
-%       end
-  }
-
-  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
-    Log._failEarlyRangeCheckIndex[selfType] += 1
-    base._failEarlyRangeCheck(index, bounds: bounds)
-  }
-
-  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
-    Log._failEarlyRangeCheckRange[selfType] += 1
-    base._failEarlyRangeCheck(range, bounds: bounds)
-  }
-
-  public func index(after i: Index) -> Index {
-    Log.successor[selfType] += 1
-    return base.index(after: i)
-  }
-
-  public func formIndex(after i: inout Index) {
-    Log.formSuccessor[selfType] += 1
-    base.formIndex(after: &i)
-  }
-
-  public typealias Indices = Base.Indices
-
-  public var indices: Indices {
-    Log.indices[selfType] += 1
-    return base.indices
-  }
-
-  public func prefix(upTo end: Index) -> SubSequence {
-    Log.prefixUpTo[selfType] += 1
-    return base.prefix(upTo: end)
-  }
-
-  public func prefix(through position: Index) -> SubSequence {
-    Log.prefixThrough[selfType] += 1
-    return base.prefix(through: position)
-  }
-
-  public func suffix(from start: Index) -> SubSequence {
-    Log.suffixFrom[selfType] += 1
-    return base.suffix(from: start)
-  }
-
-  public var isEmpty: Bool {
-    Log.isEmpty[selfType] += 1
-    return base.isEmpty
-  }
-
-  public var count: Int {
-    Log.count[selfType] += 1
-    return base.count
-  }
-
-  public func _customIndexOfEquatableElement(
-    _ element: Base.Iterator.Element
-  ) -> Index?? {
-    Log._customIndexOfEquatableElement[selfType] += 1
-    return base._customIndexOfEquatableElement(element)
-  }
-
-  public var first: Base.Iterator.Element? {
-    Log.first[selfType] += 1
-    return base.first
-  }
-
-  public func index(_ i: Index, offsetBy n: Int) -> Index {
-    Log.advance[selfType] += 1
-    return base.index(i, offsetBy: n)
-  }
-
-  public func index(
-    _ i: Index, offsetBy n: Int, limitedBy limit: Index
-  ) -> Index? {
-    Log.advanceLimit[selfType] += 1
-    return base.index(i, offsetBy: n, limitedBy: limit)
-  }
-
-  public func distance(from start: Index, to end: Index) -> Int {
-    Log.distance[selfType] += 1
-    return base.distance(from: start, to: end)
-  }
-%     end
-
-%     if Kind == 'MutableCollection':
-  public mutating func partition(
-    by belongsInSecondPartition: (Iterator.Element) throws -> Bool
-  ) rethrows -> Index {
-    Log.partitionBy[selfType] += 1
-    return try base.partition(by: belongsInSecondPartition)
-  }
-
-  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
-    _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
-  ) rethrows -> R? {
-    Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
-    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
-    if result != nil {
-      Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
-    }
-    return result
-  }
-%     end
-
-%     if Kind == 'RangeReplaceableCollection':
-  public init() {
-    self.base = Base()
-    Log.init_[selfType] += 1
-  }
-
-  public init(repeating repeatedValue: Iterator.Element, count: Int) {
-    self.base = Base(repeating: repeatedValue, count: count)
-    Log.initRepeating[selfType] += 1
-  }
-
-  public init<S : Sequence>(_ elements: S)
-    where S.Iterator.Element == Iterator.Element {
-    self.base = Base(elements)
-    Log.initWithSequence[selfType] += 1
-  }
-
-  public mutating func _customRemoveLast() -> Base.Iterator.Element? {
-    Log._customRemoveLast[selfType] += 1
-    return base._customRemoveLast()
-  }
-
-  public mutating func _customRemoveLast(_ n: Int) -> Bool {
-    Log._customRemoveLastN[selfType] += 1
-    return base._customRemoveLast(n)
-  }
-
-  public mutating func append(_ newElement: Base.Iterator.Element) {
-    Log.append[selfType] += 1
-    base.append(newElement)
-  }
-
-  public mutating func append<S : Sequence>(
-    contentsOf newElements: S
-  ) where S.Iterator.Element == Base.Iterator.Element {
-    Log.appendContentsOf[selfType] += 1
-    base.append(contentsOf: newElements)
-  }
-
-  public mutating func insert(
-    _ newElement: Base.Iterator.Element, at i: Index
-  ) {
-    Log.insert[selfType] += 1
-    base.insert(newElement, at: i)
-  }
-
-  public mutating func insert<C : Collection>(
-    contentsOf newElements: C, at i: Index
-  ) where C.Iterator.Element == Base.Iterator.Element {
-    Log.insertContentsOf[selfType] += 1
-    base.insert(contentsOf: newElements, at: i)
-  }
-
-  public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
-    Log.removeAll[selfType] += 1
-    base.removeAll(keepingCapacity: keepCapacity)
-  }
-
-  @discardableResult
-  public mutating func remove(at index: Index) -> Base.Iterator.Element {
-    Log.removeAt[selfType] += 1
-    return base.remove(at: index)
-  }
-
-  @discardableResult
-  public mutating func removeFirst() -> Base.Iterator.Element {
-    Log.removeFirst[selfType] += 1
-    return base.removeFirst()
-  }
-
-  public mutating func removeFirst(_ n: Int) {
-    Log.removeFirstN[selfType] += 1
-    base.removeFirst(n)
-  }
-
-  public mutating func removeSubrange(_ bounds: Range<Index>) {
-    Log.removeSubrange[selfType] += 1
-    base.removeSubrange(bounds)
-  }
-
-  public mutating func replaceSubrange<C : Collection>(
-    _ bounds: Range<Index>, with newElements: C
-  ) where C.Iterator.Element == Base.Iterator.Element {
-    Log.replaceSubrange[selfType] += 1
-    base.replaceSubrange(bounds, with: newElements)
-  }
-
-  public mutating func reserveCapacity(_ n: Int) {
-    Log.reserveCapacity[selfType] += 1
-    base.reserveCapacity(n)
-  }
-%     end
-%     if Traversal in ['Bidirectional', 'RandomAccess']:
-  public func index(before i: Index) -> Index {
-    BidirectionalCollectionLog.predecessor[selfType] += 1
-    return base.index(before: i)
-  }
-
-  public func formIndex(before i: inout Index) {
-    BidirectionalCollectionLog.formPredecessor[selfType] += 1
-    base.formIndex(before: &i)
-  }
-
-  public var last: Iterator.Element? {
-    BidirectionalCollectionLog.last[selfType] += 1
-    return base.last
-  }
-%     end
-}
-%   end
-% end
-
-//===----------------------------------------------------------------------===//
-// Collections that count calls to `_withUnsafeMutableBufferPointerIfSupported`
-//===----------------------------------------------------------------------===//
-
-% for Traversal in TRAVERSALS:
-%   Self = 'BufferAccessLoggingMutable' + collectionForTraversal(Traversal)
-/// Interposes between `_withUnsafeMutableBufferPointerIfSupported` method calls
-/// to increment a counter. Calls to this method from within dispatched methods
-/// are uncounted by the standard logging collection wrapper.
-public struct ${Self}<
-  Base : MutableCollection & ${collectionForTraversal(Traversal)}
-> : MutableCollection, ${collectionForTraversal(Traversal)}, LoggingType {
-
-  public var base: Base
-
-  public typealias Log = MutableCollectionLog
-
-  public typealias SubSequence = Base.SubSequence
-  public typealias Iterator = Base.Iterator
-  public typealias Element = Base.Element
-
-  public init(wrapping base: Base) {
-    self.base = base
-  }
-
-  public func makeIterator() -> Iterator {
-    return base.makeIterator()
-  }
-
-  public typealias Index = Base.Index
-  public typealias Indices = Base.Indices
-
-  public var startIndex: Index {
-    return base.startIndex
-  }
-
-  public var endIndex: Index {
-    return base.endIndex
-  }
-  
-  public var indices: Indices {
-    return base.indices
-  }
-  
-  public subscript(position: Index) -> Element {
-    get {
-      return base[position]
-    }
-    set {
-      base[position] = newValue
-    }
-  }
-
-  public subscript(bounds: Range<Index>) -> SubSequence {
-    get {
-      return base[bounds]
-    }
-    set {
-      base[bounds] = newValue
-    }
-  }
-
-  public func index(after i: Index) -> Index {
-    return base.index(after: i)
-  }
-
-%     if Traversal in ['Bidirectional', 'RandomAccess']:
-  public func index(before i: Index) -> Index {
-    return base.index(before: i)
-  }
-%     end
-
-  public func index(_ i: Index, offsetBy n: Int) -> Index {
-    return base.index(i, offsetBy: n)
-  }
-
-  public func distance(from start: Index, to end: Index) -> Int {
-    return base.distance(from: start, to: end)
-  }
-
-  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
-    _ body: (inout UnsafeMutableBufferPointer<Iterator.Element>) throws -> R
-  ) rethrows -> R? {
-    Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
-    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
-    if result != nil {
-      Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
-    }
-    return result
-  }
-}
-% end
-
-//===----------------------------------------------------------------------===//
-// Custom assertions
-//===----------------------------------------------------------------------===//
-
-public func expectCustomizable<T : LoggingType>(
-  _: T, _ counters: TypeIndexed<Int>, ${TRACE}
-) where
-  T.Base : LoggingType,
-  T.Log == T.Base.Log {
-  let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
-  expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
-  expectEqual(
-    counters[T.self], counters[T.Base.self], message(), stackTrace: newTrace)
-}
-
-public func expectNotCustomizable<T : LoggingType>(
-  _: T, _ counters: TypeIndexed<Int>, ${TRACE}
-) where
-  T.Base : LoggingType,
-  T.Log == T.Base.Log {
-  let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
-  expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
-  expectEqual(0, counters[T.Base.self], message(), stackTrace: newTrace)
-}
diff --git a/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift b/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift
new file mode 100644
index 0000000..73a3379
--- /dev/null
+++ b/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift
@@ -0,0 +1,6060 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import StdlibUnittest
+
+/// State shared by all generators of a MinimalSequence.
+internal class _MinimalIteratorSharedState<T> {
+  internal init(_ data: [T]) {
+    self.data = data
+  }
+
+  internal let data: [T]
+  internal var i: Int = 0
+  internal var underestimatedCount: Int = 0
+}
+
+//===----------------------------------------------------------------------===//
+// MinimalIterator
+//===----------------------------------------------------------------------===//
+
+/// An IteratorProtocol that implements the protocol contract in the most
+/// narrow way possible.
+///
+/// This generator will return `nil` only once.
+public struct MinimalIterator<T> : IteratorProtocol {
+  public init<S : Sequence>(_ s: S) where S.Iterator.Element == T {
+    self._sharedState = _MinimalIteratorSharedState(Array(s))
+  }
+
+  public init(_ data: [T]) {
+    self._sharedState = _MinimalIteratorSharedState(data)
+  }
+
+  internal init(_ _sharedState: _MinimalIteratorSharedState<T>) {
+    self._sharedState = _sharedState
+  }
+
+  public func next() -> T? {
+    if _sharedState.i == _sharedState.data.count {
+      return nil
+    }
+    defer { _sharedState.i += 1 }
+    return _sharedState.data[_sharedState.i]
+  }
+
+  internal let _sharedState: _MinimalIteratorSharedState<T>
+}
+
+// A protocol to identify MinimalIterator.
+public protocol _MinimalIterator {}
+extension MinimalIterator : _MinimalIterator {}
+
+//===----------------------------------------------------------------------===//
+// MinimalSequence
+//===----------------------------------------------------------------------===//
+
+public enum UnderestimatedCountBehavior {
+  /// Return the actual number of elements.
+  case precise
+
+  /// Return the actual number of elements divided by 2.
+  case half
+
+  /// Return an overestimated count.  Useful to test how algorithms reserve
+  /// memory.
+  case overestimate
+
+  /// Return the provided value.
+  case value(Int)
+}
+
+/// A Sequence that implements the protocol contract in the most
+/// narrow way possible.
+///
+/// This sequence is consumed when its generator is advanced.
+public struct MinimalSequence<T> : Sequence, CustomDebugStringConvertible {
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    let data = Array(elements)
+    self._sharedState = _MinimalIteratorSharedState(data)
+
+    switch underestimatedCount {
+    case .precise:
+      self._sharedState.underestimatedCount = data.count
+
+    case .half:
+      self._sharedState.underestimatedCount = data.count / 2
+
+    case .overestimate:
+      self._sharedState.underestimatedCount = data.count * 3 + 5
+
+    case .value(let count):
+      self._sharedState.underestimatedCount = count
+    }
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_sharedState)
+  }
+
+  public var underestimatedCount: Int {
+    return Swift.max(0, self._sharedState.underestimatedCount - self._sharedState.i)
+  }
+
+  public var debugDescription: String {
+    return "MinimalSequence(\(_sharedState.data[_sharedState.i..<_sharedState.data.count]))"
+  }
+
+  internal let _sharedState: _MinimalIteratorSharedState<T>
+}
+
+//===----------------------------------------------------------------------===//
+// Index invalidation checking
+//===----------------------------------------------------------------------===//
+
+internal enum _CollectionOperation : Equatable {
+  case reserveCapacity(capacity: Int)
+  case append
+  case appendContentsOf(count: Int)
+  case replaceRange(subRange: Range<Int>, replacementCount: Int)
+  case insert(atIndex: Int)
+  case insertContentsOf(atIndex: Int, count: Int)
+  case removeAtIndex(index: Int)
+  case removeLast
+  case removeRange(subRange: Range<Int>)
+  case removeAll(keepCapacity: Bool)
+
+  internal func _applyTo(
+    elementsLastMutatedStateIds: [Int],
+    endIndexLastMutatedStateId: Int,
+    nextStateId: Int
+  ) -> ([Int], Int) {
+    var newElementsIds = elementsLastMutatedStateIds
+    var newEndIndexId = endIndexLastMutatedStateId
+    switch self {
+    case .reserveCapacity:
+      let invalidIndices = newElementsIds.indices
+      newElementsIds.replaceSubrange(
+        invalidIndices,
+        with: repeatElement(nextStateId, count: invalidIndices.count))
+      newEndIndexId = nextStateId
+
+    case .append:
+      newElementsIds.append(nextStateId)
+      newEndIndexId = nextStateId
+
+    case .appendContentsOf(let count):
+      newElementsIds.append(contentsOf:
+        repeatElement(nextStateId, count: count))
+      newEndIndexId = nextStateId
+
+    case .replaceRange(let subRange, let replacementCount):
+      newElementsIds.replaceSubrange(
+        subRange,
+        with: repeatElement(nextStateId, count: replacementCount))
+
+      let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
+      newElementsIds.replaceSubrange(
+        invalidIndices,
+        with: repeatElement(nextStateId, count: invalidIndices.count))
+      newEndIndexId = nextStateId
+
+    case .insert(let atIndex):
+      newElementsIds.insert(nextStateId, at: atIndex)
+
+      let invalidIndices = atIndex..<newElementsIds.endIndex
+      newElementsIds.replaceSubrange(
+        invalidIndices,
+        with: repeatElement(nextStateId, count: invalidIndices.count))
+      newEndIndexId = nextStateId
+
+    case .insertContentsOf(let atIndex, let count):
+      newElementsIds.insert(
+        contentsOf: repeatElement(nextStateId, count: count),
+        at: atIndex)
+
+      let invalidIndices = atIndex..<newElementsIds.endIndex
+      newElementsIds.replaceSubrange(
+        invalidIndices,
+        with: repeatElement(nextStateId, count: invalidIndices.count))
+      newEndIndexId = nextStateId
+
+    case .removeAtIndex(let index):
+      newElementsIds.remove(at: index)
+
+      let invalidIndices = index..<newElementsIds.endIndex
+      newElementsIds.replaceSubrange(
+        invalidIndices,
+        with: repeatElement(nextStateId, count: invalidIndices.count))
+      newEndIndexId = nextStateId
+
+    case .removeLast:
+      newElementsIds.removeLast()
+      newEndIndexId = nextStateId
+
+    case .removeRange(let subRange):
+      newElementsIds.removeSubrange(subRange)
+
+      let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
+      newElementsIds.replaceSubrange(
+        invalidIndices,
+        with: repeatElement(nextStateId, count: invalidIndices.count))
+      newEndIndexId = nextStateId
+
+    case .removeAll(let keepCapacity):
+      newElementsIds.removeAll(keepingCapacity: keepCapacity)
+      newEndIndexId = nextStateId
+    }
+    return (newElementsIds, newEndIndexId)
+  }
+}
+
+internal func == (
+  lhs: _CollectionOperation,
+  rhs: _CollectionOperation
+) -> Bool {
+  switch (lhs, rhs) {
+  case (.reserveCapacity(let lhsCapacity), .reserveCapacity(let rhsCapacity)):
+    return lhsCapacity == rhsCapacity
+
+  case (.append, .append):
+    return true
+
+  case (.appendContentsOf(let lhsCount), .appendContentsOf(let rhsCount)):
+    return lhsCount == rhsCount
+
+  case (
+    .replaceRange(let lhsSubRange, let lhsReplacementCount),
+    .replaceRange(let rhsSubRange, let rhsReplacementCount)):
+
+    return lhsSubRange == rhsSubRange &&
+      lhsReplacementCount == rhsReplacementCount
+
+  case (.insert(let lhsAtIndex), .insert(let rhsAtIndex)):
+    return lhsAtIndex == rhsAtIndex
+
+  case (
+    .insertContentsOf(let lhsAtIndex, let lhsCount),
+    .insertContentsOf(let rhsAtIndex, let rhsCount)):
+
+    return lhsAtIndex == rhsAtIndex && lhsCount == rhsCount
+
+  case (.removeAtIndex(let lhsIndex), .removeAtIndex(let rhsIndex)):
+    return lhsIndex == rhsIndex
+
+  case (.removeLast, .removeLast):
+    return true
+
+  case (.removeRange(let lhsSubRange), .removeRange(let rhsSubRange)):
+    return lhsSubRange == rhsSubRange
+
+  case (.removeAll(let lhsKeepCapacity), .removeAll(let rhsKeepCapacity)):
+    return lhsKeepCapacity == rhsKeepCapacity
+
+  default:
+    return false
+  }
+}
+
+public struct _CollectionState : Equatable, Hashable {
+  internal static var _nextUnusedState: Int = 0
+  internal static var _namedStates: [String : _CollectionState] = [:]
+
+  internal let _id: Int
+  internal let _elementsLastMutatedStateIds: [Int]
+  internal let _endIndexLastMutatedStateId: Int
+
+  internal init(
+    id: Int,
+    elementsLastMutatedStateIds: [Int],
+    endIndexLastMutatedStateId: Int) {
+    self._id = id
+    self._elementsLastMutatedStateIds = elementsLastMutatedStateIds
+    self._endIndexLastMutatedStateId = endIndexLastMutatedStateId
+  }
+
+  public init(newRootStateForElementCount count: Int) {
+    self._id = _CollectionState._nextUnusedState
+    _CollectionState._nextUnusedState += 1
+    self._elementsLastMutatedStateIds =
+      Array(repeatElement(self._id, count: count))
+    self._endIndexLastMutatedStateId = self._id
+  }
+
+  internal init(name: String, elementCount: Int) {
+    if let result = _CollectionState._namedStates[name] {
+      self = result
+    } else {
+      self = _CollectionState(newRootStateForElementCount: elementCount)
+      _CollectionState._namedStates[name] = self
+    }
+  }
+
+  public var hashValue: Int {
+    return _id.hashValue
+  }
+}
+
+public func == (lhs: _CollectionState, rhs: _CollectionState) -> Bool {
+  return lhs._id == rhs._id
+}
+
+internal struct _CollectionStateTransition {
+  internal let _previousState: _CollectionState
+  internal let _operation: _CollectionOperation
+  internal let _nextState: _CollectionState
+
+  internal static var _allTransitions:
+    [_CollectionState : Box<[_CollectionStateTransition]>] = [:]
+
+  internal init(
+    previousState: _CollectionState,
+    operation: _CollectionOperation,
+    nextState: _CollectionState
+  ) {
+    var transitions =
+      _CollectionStateTransition._allTransitions[previousState]
+    if transitions == nil {
+      transitions = Box<[_CollectionStateTransition]>([])
+      _CollectionStateTransition._allTransitions[previousState] = transitions
+    }
+    if let i = transitions!.value.firstIndex(where: { $0._operation == operation }) {
+      self = transitions!.value[i]
+      return
+    }
+    self._previousState = previousState
+    self._operation = operation
+    self._nextState = nextState
+    transitions!.value.append(self)
+  }
+
+  internal init(
+    previousState: _CollectionState,
+    operation: _CollectionOperation
+  ) {
+    let nextStateId = _CollectionState._nextUnusedState
+    _CollectionState._nextUnusedState += 1
+    let (newElementStates, newEndIndexState) = operation._applyTo(
+      elementsLastMutatedStateIds: previousState._elementsLastMutatedStateIds,
+      endIndexLastMutatedStateId: previousState._endIndexLastMutatedStateId,
+      nextStateId: nextStateId)
+    let nextState = _CollectionState(
+      id: nextStateId,
+      elementsLastMutatedStateIds: newElementStates,
+      endIndexLastMutatedStateId: newEndIndexState)
+    self = _CollectionStateTransition(
+      previousState: previousState,
+      operation: operation,
+      nextState: nextState)
+  }
+}
+
+
+//===----------------------------------------------------------------------===//
+// MinimalIndex
+//===----------------------------------------------------------------------===//
+
+/// Asserts that the two indices are allowed to participate in a binary
+/// operation.
+internal func _expectCompatibleIndices(
+  _ first: MinimalIndex,
+  _ second: MinimalIndex,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
+  if first._collectionState._id == second._collectionState._id {
+    // Fast path: the indices are derived from the same state.
+    return
+  }
+
+  // The indices are derived from different states.  Check that they point
+  // to a self-consistent view of the collection.
+  if first._collectionState._id > second._collectionState._id {
+    return _expectCompatibleIndices(second, first)
+  }
+
+  func lastMutatedStateId(
+    of i: MinimalIndex,
+    in state: _CollectionState
+  ) -> Int {
+    let offset = i.position
+    if offset == state._elementsLastMutatedStateIds.endIndex {
+      return state._id
+    }
+    return state._elementsLastMutatedStateIds[offset]
+  }
+
+  let newestCollectionState = second._collectionState
+  let expectedFirstIndexLastMutatedStateId =
+    lastMutatedStateId(of: first, in: newestCollectionState)
+
+  expectEqual(
+    expectedFirstIndexLastMutatedStateId,
+    first._collectionState._id,
+    "Indices are not compatible:\n" +
+    "first: \(first)\n" +
+    "second: \(second)\n" +
+    "first element last mutated in state id: \(first._collectionState._id)\n" +
+    "expected state id: \(expectedFirstIndexLastMutatedStateId)\n" +
+    "newest collection state: \(newestCollectionState)",
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  // To make writing assertions easier, perform a trap.
+  if expectedFirstIndexLastMutatedStateId != first._collectionState._id {
+    fatalError("Indices are not compatible")
+  }
+}
+
+public struct MinimalIndex : Comparable {
+  public init(
+    collectionState: _CollectionState,
+    position: Int,
+    startIndex: Int,
+    endIndex: Int
+  ) {
+    expectTrapping(
+      position,
+      in: startIndex...endIndex)
+    self = MinimalIndex(
+      _collectionState: collectionState,
+      uncheckedPosition: position)
+  }
+
+  internal init(
+    _collectionState: _CollectionState,
+    uncheckedPosition: Int
+  ) {
+    self._collectionState = _collectionState
+    self.position = uncheckedPosition
+  }
+
+  public let _collectionState: _CollectionState
+  public let position: Int
+
+  public static var trapOnRangeCheckFailure = ResettableValue(true)
+
+}
+
+public func == (lhs: MinimalIndex, rhs: MinimalIndex) -> Bool {
+  _expectCompatibleIndices(lhs, rhs)
+  return lhs.position == rhs.position
+}
+
+public func < (lhs: MinimalIndex, rhs: MinimalIndex) -> Bool {
+  _expectCompatibleIndices(lhs, rhs)
+  return lhs.position < rhs.position
+}
+
+
+//===----------------------------------------------------------------------===//
+// MinimalStrideableIndex
+//===----------------------------------------------------------------------===//
+
+/// Asserts that the two indices are allowed to participate in a binary
+/// operation.
+internal func _expectCompatibleIndices(
+  _ first: MinimalStrideableIndex,
+  _ second: MinimalStrideableIndex,
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
+  if first._collectionState._id == second._collectionState._id {
+    // Fast path: the indices are derived from the same state.
+    return
+  }
+
+  // The indices are derived from different states.  Check that they point
+  // to a self-consistent view of the collection.
+  if first._collectionState._id > second._collectionState._id {
+    return _expectCompatibleIndices(second, first)
+  }
+
+  func lastMutatedStateId(
+    of i: MinimalStrideableIndex,
+    in state: _CollectionState
+  ) -> Int {
+    let offset = i.position
+    if offset == state._elementsLastMutatedStateIds.endIndex {
+      return state._id
+    }
+    return state._elementsLastMutatedStateIds[offset]
+  }
+
+  let newestCollectionState = second._collectionState
+  let expectedFirstIndexLastMutatedStateId =
+    lastMutatedStateId(of: first, in: newestCollectionState)
+
+  expectEqual(
+    expectedFirstIndexLastMutatedStateId,
+    first._collectionState._id,
+    "Indices are not compatible:\n" +
+    "first: \(first)\n" +
+    "second: \(second)\n" +
+    "first element last mutated in state id: \(first._collectionState._id)\n" +
+    "expected state id: \(expectedFirstIndexLastMutatedStateId)\n" +
+    "newest collection state: \(newestCollectionState)",
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+
+  // To make writing assertions easier, perform a trap.
+  if expectedFirstIndexLastMutatedStateId != first._collectionState._id {
+    fatalError("Indices are not compatible")
+  }
+}
+
+public struct MinimalStrideableIndex : Comparable {
+  public init(
+    collectionState: _CollectionState,
+    position: Int,
+    startIndex: Int,
+    endIndex: Int
+  ) {
+    expectTrapping(
+      position,
+      in: startIndex...endIndex)
+    self = MinimalStrideableIndex(
+      _collectionState: collectionState,
+      uncheckedPosition: position)
+  }
+
+  internal init(
+    _collectionState: _CollectionState,
+    uncheckedPosition: Int
+  ) {
+    self._collectionState = _collectionState
+    self.position = uncheckedPosition
+  }
+
+  public let _collectionState: _CollectionState
+  public let position: Int
+
+  public static var trapOnRangeCheckFailure = ResettableValue(true)
+
+  public var timesAdvancedCalled = ResettableValue(0)
+  public var timesDistanceCalled = ResettableValue(0)
+}
+
+public func == (lhs: MinimalStrideableIndex, rhs: MinimalStrideableIndex) -> Bool {
+  _expectCompatibleIndices(lhs, rhs)
+  return lhs.position == rhs.position
+}
+
+public func < (lhs: MinimalStrideableIndex, rhs: MinimalStrideableIndex) -> Bool {
+  _expectCompatibleIndices(lhs, rhs)
+  return lhs.position < rhs.position
+}
+
+
+extension MinimalStrideableIndex : Strideable {
+  public typealias Stride = Int
+
+  public func distance(to other: MinimalStrideableIndex) -> Int {
+    timesDistanceCalled.value += 1
+    _expectCompatibleIndices(self, other)
+    return other.position - position
+  }
+
+  public func advanced(by n: Int) -> MinimalStrideableIndex {
+    timesAdvancedCalled.value += 1
+    return MinimalStrideableIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: position + n)
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Minimal***[Mutable]?Collection
+//===----------------------------------------------------------------------===//
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalCollection<T> : Collection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    _precondition(start <= end,
+      "Only BidirectionalCollections can have end come before start")
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    _precondition(n >= 0,
+      "Only BidirectionalCollections can be advanced by a negative amount")
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+
+  public var underestimatedCount: Int
+
+  internal var _elements: [T]
+  internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRangeReplaceableCollection<T> : Collection, RangeReplaceableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+  public init() {
+    self.underestimatedCount = 0
+    self._elements = []
+    self._collectionState =
+      _CollectionState(name: "\(type(of: self))", elementCount: 0)
+  }
+
+  public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+    self.underestimatedCount = 0
+    self._elements = Array(elements)
+    self._collectionState =
+      _CollectionState(newRootStateForElementCount: self._elements.count)
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    _precondition(start <= end,
+      "Only BidirectionalCollections can have end come before start")
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    _precondition(n >= 0,
+      "Only BidirectionalCollections can be advanced by a negative amount")
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    _willMutate(.reserveCapacity(capacity: n))
+    _elements.reserveCapacity(n)
+    reservedCapacity = Swift.max(reservedCapacity, n)
+  }
+
+  public mutating func append(_ x: T) {
+    _willMutate(.append)
+    _elements.append(x)
+  }
+
+  public mutating func append<S : Sequence>(contentsOf newElements: S)
+    where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.append(contentsOf: newElements)
+    let newCount = count
+    _willMutate(.appendContentsOf(count: newCount - oldCount))
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<MinimalIndex>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == T {
+    let oldCount = count
+    _elements.replaceSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position,
+      with: newElements)
+    let newCount = count
+    _willMutate(.replaceRange(
+      subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+      replacementCount:
+        subRange.upperBound.position - subRange.lowerBound.position
+        + newCount - oldCount))
+  }
+
+  public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+    _willMutate(.insert(atIndex: i.position))
+    _elements.insert(newElement, at: i.position)
+  }
+
+  public mutating func insert<S : Collection>(
+    contentsOf newElements: S, at i: MinimalIndex
+  ) where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.insert(contentsOf: newElements, at: i.position)
+    let newCount = count
+
+    if newCount - oldCount != 0 {
+      _willMutate(.insertContentsOf(
+        atIndex: i.position,
+        count: newCount - oldCount))
+    }
+  }
+
+  @discardableResult
+  public mutating func remove(at i: MinimalIndex) -> T {
+    _willMutate(.removeAtIndex(index: i.position))
+    return _elements.remove(at: i.position)
+  }
+
+  @discardableResult
+  public mutating func removeLast() -> T {
+    _willMutate(.removeLast)
+    return _elements.removeLast()
+  }
+
+  public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+    if !subRange.isEmpty {
+      _willMutate(.removeRange(
+        subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+    }
+    _elements.removeSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position
+    )
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+    _willMutate(.removeAll(keepCapacity: keepCapacity))
+    // Ignore the value of `keepCapacity`.
+    _elements.removeAll(keepingCapacity: false)
+  }
+
+  internal mutating func _willMutate(_ operation: _CollectionOperation) {
+    _collectionState = _CollectionStateTransition(
+      previousState: _collectionState,
+      operation: operation)._nextState
+  }
+
+  public var underestimatedCount: Int
+  public var reservedCapacity: Int = 0
+
+  internal var _elements: [T]
+  internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableCollection<T> : Collection, MutableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    _precondition(start <= end,
+      "Only BidirectionalCollections can have end come before start")
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    _precondition(n >= 0,
+      "Only BidirectionalCollections can be advanced by a negative amount")
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+    set {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      _elements[i.position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+
+  public var underestimatedCount: Int
+
+  internal var _elements: [T]
+  internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableRangeReplaceableCollection<T> : Collection, MutableCollection, RangeReplaceableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+  public init() {
+    self.underestimatedCount = 0
+    self._elements = []
+    self._collectionState =
+      _CollectionState(name: "\(type(of: self))", elementCount: 0)
+  }
+
+  public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+    self.underestimatedCount = 0
+    self._elements = Array(elements)
+    self._collectionState =
+      _CollectionState(newRootStateForElementCount: self._elements.count)
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    _precondition(start <= end,
+      "Only BidirectionalCollections can have end come before start")
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    _precondition(n >= 0,
+      "Only BidirectionalCollections can be advanced by a negative amount")
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+    set {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      _elements[i.position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    _willMutate(.reserveCapacity(capacity: n))
+    _elements.reserveCapacity(n)
+    reservedCapacity = Swift.max(reservedCapacity, n)
+  }
+
+  public mutating func append(_ x: T) {
+    _willMutate(.append)
+    _elements.append(x)
+  }
+
+  public mutating func append<S : Sequence>(contentsOf newElements: S)
+    where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.append(contentsOf: newElements)
+    let newCount = count
+    _willMutate(.appendContentsOf(count: newCount - oldCount))
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<MinimalIndex>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == T {
+    let oldCount = count
+    _elements.replaceSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position,
+      with: newElements)
+    let newCount = count
+    _willMutate(.replaceRange(
+      subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+      replacementCount:
+        subRange.upperBound.position - subRange.lowerBound.position
+        + newCount - oldCount))
+  }
+
+  public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+    _willMutate(.insert(atIndex: i.position))
+    _elements.insert(newElement, at: i.position)
+  }
+
+  public mutating func insert<S : Collection>(
+    contentsOf newElements: S, at i: MinimalIndex
+  ) where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.insert(contentsOf: newElements, at: i.position)
+    let newCount = count
+
+    if newCount - oldCount != 0 {
+      _willMutate(.insertContentsOf(
+        atIndex: i.position,
+        count: newCount - oldCount))
+    }
+  }
+
+  @discardableResult
+  public mutating func remove(at i: MinimalIndex) -> T {
+    _willMutate(.removeAtIndex(index: i.position))
+    return _elements.remove(at: i.position)
+  }
+
+  @discardableResult
+  public mutating func removeLast() -> T {
+    _willMutate(.removeLast)
+    return _elements.removeLast()
+  }
+
+  public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+    if !subRange.isEmpty {
+      _willMutate(.removeRange(
+        subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+    }
+    _elements.removeSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position
+    )
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+    _willMutate(.removeAll(keepCapacity: keepCapacity))
+    // Ignore the value of `keepCapacity`.
+    _elements.removeAll(keepingCapacity: false)
+  }
+
+  internal mutating func _willMutate(_ operation: _CollectionOperation) {
+    _collectionState = _CollectionStateTransition(
+      previousState: _collectionState,
+      operation: operation)._nextState
+  }
+
+  public var underestimatedCount: Int
+  public var reservedCapacity: Int = 0
+
+  internal var _elements: [T]
+  internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalBidirectionalCollection<T> : BidirectionalCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalBidirectionalCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+
+  public var underestimatedCount: Int
+
+  internal var _elements: [T]
+  internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRangeReplaceableBidirectionalCollection<T> : BidirectionalCollection, RangeReplaceableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+  public init() {
+    self.underestimatedCount = 0
+    self._elements = []
+    self._collectionState =
+      _CollectionState(name: "\(type(of: self))", elementCount: 0)
+  }
+
+  public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+    self.underestimatedCount = 0
+    self._elements = Array(elements)
+    self._collectionState =
+      _CollectionState(newRootStateForElementCount: self._elements.count)
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableBidirectionalCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    _willMutate(.reserveCapacity(capacity: n))
+    _elements.reserveCapacity(n)
+    reservedCapacity = Swift.max(reservedCapacity, n)
+  }
+
+  public mutating func append(_ x: T) {
+    _willMutate(.append)
+    _elements.append(x)
+  }
+
+  public mutating func append<S : Sequence>(contentsOf newElements: S)
+    where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.append(contentsOf: newElements)
+    let newCount = count
+    _willMutate(.appendContentsOf(count: newCount - oldCount))
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<MinimalIndex>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == T {
+    let oldCount = count
+    _elements.replaceSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position,
+      with: newElements)
+    let newCount = count
+    _willMutate(.replaceRange(
+      subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+      replacementCount:
+        subRange.upperBound.position - subRange.lowerBound.position
+        + newCount - oldCount))
+  }
+
+  public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+    _willMutate(.insert(atIndex: i.position))
+    _elements.insert(newElement, at: i.position)
+  }
+
+  public mutating func insert<S : Collection>(
+    contentsOf newElements: S, at i: MinimalIndex
+  ) where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.insert(contentsOf: newElements, at: i.position)
+    let newCount = count
+
+    if newCount - oldCount != 0 {
+      _willMutate(.insertContentsOf(
+        atIndex: i.position,
+        count: newCount - oldCount))
+    }
+  }
+
+  @discardableResult
+  public mutating func remove(at i: MinimalIndex) -> T {
+    _willMutate(.removeAtIndex(index: i.position))
+    return _elements.remove(at: i.position)
+  }
+
+  @discardableResult
+  public mutating func removeLast() -> T {
+    _willMutate(.removeLast)
+    return _elements.removeLast()
+  }
+
+  public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+    if !subRange.isEmpty {
+      _willMutate(.removeRange(
+        subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+    }
+    _elements.removeSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position
+    )
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+    _willMutate(.removeAll(keepCapacity: keepCapacity))
+    // Ignore the value of `keepCapacity`.
+    _elements.removeAll(keepingCapacity: false)
+  }
+
+  internal mutating func _willMutate(_ operation: _CollectionOperation) {
+    _collectionState = _CollectionStateTransition(
+      previousState: _collectionState,
+      operation: operation)._nextState
+  }
+
+  public var underestimatedCount: Int
+  public var reservedCapacity: Int = 0
+
+  internal var _elements: [T]
+  internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableBidirectionalCollection<T> : BidirectionalCollection, MutableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+    set {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      _elements[i.position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableBidirectionalCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+
+  public var underestimatedCount: Int
+
+  internal var _elements: [T]
+  internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableRangeReplaceableBidirectionalCollection<T> : BidirectionalCollection, MutableCollection, RangeReplaceableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+  public init() {
+    self.underestimatedCount = 0
+    self._elements = []
+    self._collectionState =
+      _CollectionState(name: "\(type(of: self))", elementCount: 0)
+  }
+
+  public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+    self.underestimatedCount = 0
+    self._elements = Array(elements)
+    self._collectionState =
+      _CollectionState(newRootStateForElementCount: self._elements.count)
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+    set {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      _elements[i.position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableBidirectionalCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    _willMutate(.reserveCapacity(capacity: n))
+    _elements.reserveCapacity(n)
+    reservedCapacity = Swift.max(reservedCapacity, n)
+  }
+
+  public mutating func append(_ x: T) {
+    _willMutate(.append)
+    _elements.append(x)
+  }
+
+  public mutating func append<S : Sequence>(contentsOf newElements: S)
+    where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.append(contentsOf: newElements)
+    let newCount = count
+    _willMutate(.appendContentsOf(count: newCount - oldCount))
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<MinimalIndex>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == T {
+    let oldCount = count
+    _elements.replaceSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position,
+      with: newElements)
+    let newCount = count
+    _willMutate(.replaceRange(
+      subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+      replacementCount:
+        subRange.upperBound.position - subRange.lowerBound.position
+        + newCount - oldCount))
+  }
+
+  public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+    _willMutate(.insert(atIndex: i.position))
+    _elements.insert(newElement, at: i.position)
+  }
+
+  public mutating func insert<S : Collection>(
+    contentsOf newElements: S, at i: MinimalIndex
+  ) where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.insert(contentsOf: newElements, at: i.position)
+    let newCount = count
+
+    if newCount - oldCount != 0 {
+      _willMutate(.insertContentsOf(
+        atIndex: i.position,
+        count: newCount - oldCount))
+    }
+  }
+
+  @discardableResult
+  public mutating func remove(at i: MinimalIndex) -> T {
+    _willMutate(.removeAtIndex(index: i.position))
+    return _elements.remove(at: i.position)
+  }
+
+  @discardableResult
+  public mutating func removeLast() -> T {
+    _willMutate(.removeLast)
+    return _elements.removeLast()
+  }
+
+  public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+    if !subRange.isEmpty {
+      _willMutate(.removeRange(
+        subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+    }
+    _elements.removeSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position
+    )
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+    _willMutate(.removeAll(keepCapacity: keepCapacity))
+    // Ignore the value of `keepCapacity`.
+    _elements.removeAll(keepingCapacity: false)
+  }
+
+  internal mutating func _willMutate(_ operation: _CollectionOperation) {
+    _collectionState = _CollectionStateTransition(
+      previousState: _collectionState,
+      operation: operation)._nextState
+  }
+
+  public var underestimatedCount: Int
+  public var reservedCapacity: Int = 0
+
+  internal var _elements: [T]
+  internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRandomAccessCollection<T> : RandomAccessCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultIndices<MinimalRandomAccessCollection<T>>
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRandomAccessCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+
+  public var underestimatedCount: Int
+
+  internal var _elements: [T]
+  internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRandomAccessCollectionWithStrideableIndex<T> : RandomAccessCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalStrideableIndex
+
+  internal func _index(forPosition i: Int) -> MinimalStrideableIndex {
+    return MinimalStrideableIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalStrideableIndex {
+    return MinimalStrideableIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalStrideableIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalStrideableIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+  public typealias Indices = Range<MinimalStrideableIndex>
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalStrideableIndex,
+    bounds: Range<MinimalStrideableIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalStrideableIndex>,
+    bounds: Range<MinimalStrideableIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalStrideableIndex) -> MinimalStrideableIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalStrideableIndex) -> MinimalStrideableIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalStrideableIndex, to end: MinimalStrideableIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalStrideableIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+  }
+
+  public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<MinimalRandomAccessCollectionWithStrideableIndex<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+
+  public var underestimatedCount: Int
+
+  internal var _elements: [T]
+  internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRangeReplaceableRandomAccessCollection<T> : RandomAccessCollection, RangeReplaceableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+  public init() {
+    self.underestimatedCount = 0
+    self._elements = []
+    self._collectionState =
+      _CollectionState(name: "\(type(of: self))", elementCount: 0)
+  }
+
+  public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+    self.underestimatedCount = 0
+    self._elements = Array(elements)
+    self._collectionState =
+      _CollectionState(newRootStateForElementCount: self._elements.count)
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultIndices<MinimalRangeReplaceableRandomAccessCollection<T>>
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableRandomAccessCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    _willMutate(.reserveCapacity(capacity: n))
+    _elements.reserveCapacity(n)
+    reservedCapacity = Swift.max(reservedCapacity, n)
+  }
+
+  public mutating func append(_ x: T) {
+    _willMutate(.append)
+    _elements.append(x)
+  }
+
+  public mutating func append<S : Sequence>(contentsOf newElements: S)
+    where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.append(contentsOf: newElements)
+    let newCount = count
+    _willMutate(.appendContentsOf(count: newCount - oldCount))
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<MinimalIndex>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == T {
+    let oldCount = count
+    _elements.replaceSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position,
+      with: newElements)
+    let newCount = count
+    _willMutate(.replaceRange(
+      subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+      replacementCount:
+        subRange.upperBound.position - subRange.lowerBound.position
+        + newCount - oldCount))
+  }
+
+  public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+    _willMutate(.insert(atIndex: i.position))
+    _elements.insert(newElement, at: i.position)
+  }
+
+  public mutating func insert<S : Collection>(
+    contentsOf newElements: S, at i: MinimalIndex
+  ) where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.insert(contentsOf: newElements, at: i.position)
+    let newCount = count
+
+    if newCount - oldCount != 0 {
+      _willMutate(.insertContentsOf(
+        atIndex: i.position,
+        count: newCount - oldCount))
+    }
+  }
+
+  @discardableResult
+  public mutating func remove(at i: MinimalIndex) -> T {
+    _willMutate(.removeAtIndex(index: i.position))
+    return _elements.remove(at: i.position)
+  }
+
+  @discardableResult
+  public mutating func removeLast() -> T {
+    _willMutate(.removeLast)
+    return _elements.removeLast()
+  }
+
+  public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+    if !subRange.isEmpty {
+      _willMutate(.removeRange(
+        subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+    }
+    _elements.removeSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position
+    )
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+    _willMutate(.removeAll(keepCapacity: keepCapacity))
+    // Ignore the value of `keepCapacity`.
+    _elements.removeAll(keepingCapacity: false)
+  }
+
+  internal mutating func _willMutate(_ operation: _CollectionOperation) {
+    _collectionState = _CollectionStateTransition(
+      previousState: _collectionState,
+      operation: operation)._nextState
+  }
+
+  public var underestimatedCount: Int
+  public var reservedCapacity: Int = 0
+
+  internal var _elements: [T]
+  internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalRangeReplaceableRandomAccessCollectionWithStrideableIndex<T> : RandomAccessCollection, RangeReplaceableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+  public init() {
+    self.underestimatedCount = 0
+    self._elements = []
+    self._collectionState =
+      _CollectionState(name: "\(type(of: self))", elementCount: 0)
+  }
+
+  public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+    self.underestimatedCount = 0
+    self._elements = Array(elements)
+    self._collectionState =
+      _CollectionState(newRootStateForElementCount: self._elements.count)
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalStrideableIndex
+
+  internal func _index(forPosition i: Int) -> MinimalStrideableIndex {
+    return MinimalStrideableIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalStrideableIndex {
+    return MinimalStrideableIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalStrideableIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalStrideableIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+  public typealias Indices = Range<MinimalStrideableIndex>
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalStrideableIndex,
+    bounds: Range<MinimalStrideableIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalStrideableIndex>,
+    bounds: Range<MinimalStrideableIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalStrideableIndex) -> MinimalStrideableIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalStrideableIndex) -> MinimalStrideableIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalStrideableIndex, to end: MinimalStrideableIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalStrideableIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+  }
+
+  public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<MinimalRangeReplaceableRandomAccessCollectionWithStrideableIndex<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    _willMutate(.reserveCapacity(capacity: n))
+    _elements.reserveCapacity(n)
+    reservedCapacity = Swift.max(reservedCapacity, n)
+  }
+
+  public mutating func append(_ x: T) {
+    _willMutate(.append)
+    _elements.append(x)
+  }
+
+  public mutating func append<S : Sequence>(contentsOf newElements: S)
+    where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.append(contentsOf: newElements)
+    let newCount = count
+    _willMutate(.appendContentsOf(count: newCount - oldCount))
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<MinimalStrideableIndex>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == T {
+    let oldCount = count
+    _elements.replaceSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position,
+      with: newElements)
+    let newCount = count
+    _willMutate(.replaceRange(
+      subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+      replacementCount:
+        subRange.upperBound.position - subRange.lowerBound.position
+        + newCount - oldCount))
+  }
+
+  public mutating func insert(_ newElement: T, at i: MinimalStrideableIndex) {
+    _willMutate(.insert(atIndex: i.position))
+    _elements.insert(newElement, at: i.position)
+  }
+
+  public mutating func insert<S : Collection>(
+    contentsOf newElements: S, at i: MinimalStrideableIndex
+  ) where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.insert(contentsOf: newElements, at: i.position)
+    let newCount = count
+
+    if newCount - oldCount != 0 {
+      _willMutate(.insertContentsOf(
+        atIndex: i.position,
+        count: newCount - oldCount))
+    }
+  }
+
+  @discardableResult
+  public mutating func remove(at i: MinimalStrideableIndex) -> T {
+    _willMutate(.removeAtIndex(index: i.position))
+    return _elements.remove(at: i.position)
+  }
+
+  @discardableResult
+  public mutating func removeLast() -> T {
+    _willMutate(.removeLast)
+    return _elements.removeLast()
+  }
+
+  public mutating func removeSubrange(_ subRange: Range<MinimalStrideableIndex>) {
+    if !subRange.isEmpty {
+      _willMutate(.removeRange(
+        subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+    }
+    _elements.removeSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position
+    )
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+    _willMutate(.removeAll(keepCapacity: keepCapacity))
+    // Ignore the value of `keepCapacity`.
+    _elements.removeAll(keepingCapacity: false)
+  }
+
+  internal mutating func _willMutate(_ operation: _CollectionOperation) {
+    _collectionState = _CollectionStateTransition(
+      previousState: _collectionState,
+      operation: operation)._nextState
+  }
+
+  public var underestimatedCount: Int
+  public var reservedCapacity: Int = 0
+
+  internal var _elements: [T]
+  internal var _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableRandomAccessCollection<T> : RandomAccessCollection, MutableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultIndices<MinimalMutableRandomAccessCollection<T>>
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+    set {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      _elements[i.position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRandomAccessCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+
+  public var underestimatedCount: Int
+
+  internal var _elements: [T]
+  internal let _collectionState: _CollectionState
+}
+
+
+/// A minimal implementation of `Collection` with extra checks.
+public struct MinimalMutableRangeReplaceableRandomAccessCollection<T> : RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
+  /// Creates a collection with given contents, but a unique modification
+  /// history.  No other instance has the same modification history.
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == T {
+    self._elements = Array(elements)
+
+    self._collectionState = _CollectionState(
+      newRootStateForElementCount: self._elements.count)
+
+    switch underestimatedCount {
+    case .precise:
+      self.underestimatedCount = _elements.count
+
+    case .half:
+      self.underestimatedCount = _elements.count / 2
+
+    case .overestimate:
+      self.underestimatedCount = _elements.count * 3 + 5
+
+    case .value(let count):
+      self.underestimatedCount = count
+    }
+  }
+
+  public init() {
+    self.underestimatedCount = 0
+    self._elements = []
+    self._collectionState =
+      _CollectionState(name: "\(type(of: self))", elementCount: 0)
+  }
+
+  public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
+    self.underestimatedCount = 0
+    self._elements = Array(elements)
+    self._collectionState =
+      _CollectionState(newRootStateForElementCount: self._elements.count)
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<T> {
+    timesMakeIteratorCalled.value += 1
+    return MinimalIterator(_elements)
+  }
+
+  public typealias Index = MinimalIndex
+
+  internal func _index(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      collectionState: _collectionState,
+      position: i,
+      startIndex: _elements.startIndex,
+      endIndex: _elements.endIndex)
+  }
+
+  internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
+    return MinimalIndex(
+      _collectionState: _collectionState,
+      uncheckedPosition: i)
+  }
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.startIndex)
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return _uncheckedIndex(forPosition: _elements.endIndex)
+  }
+
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultIndices<MinimalMutableRangeReplaceableRandomAccessCollection<T>>
+
+  public func _failEarlyRangeCheck(
+    _ index: MinimalIndex,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: index.position),
+      index)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      index.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func _failEarlyRangeCheck(
+    _ range: Range<MinimalIndex>,
+    bounds: Range<MinimalIndex>
+  ) {
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.lowerBound.position),
+      range.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: range.upperBound.position),
+      range.upperBound)
+
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.lowerBound.position),
+      bounds.lowerBound)
+    _expectCompatibleIndices(
+      _uncheckedIndex(forPosition: bounds.upperBound.position),
+      bounds.upperBound)
+
+    expectTrapping(
+      range.lowerBound.position..<range.upperBound.position,
+      in: bounds.lowerBound.position..<bounds.upperBound.position)
+  }
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    return _uncheckedIndex(forPosition: i.position + 1)
+  }
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    // FIXME: swift-3-indexing-model: perform a range check and use
+    // return _uncheckedIndex(forPosition: i.position - 1)
+    return _index(forPosition: i.position - 1)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if start != endIndex {
+      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
+    }
+    if end != endIndex {
+      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
+    }
+    return end.position - start.position
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: perform a range check properly.
+    if i != endIndex {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+    }
+    return _index(forPosition: i.position + n)
+  }
+
+  public subscript(i: MinimalIndex) -> T {
+    get {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      return _elements[i.position]
+    }
+    set {
+      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
+      _elements[i.position] = newValue
+    }
+  }
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableRandomAccessCollection<T>> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+  public mutating func reserveCapacity(_ n: Int) {
+    _willMutate(.reserveCapacity(capacity: n))
+    _elements.reserveCapacity(n)
+    reservedCapacity = Swift.max(reservedCapacity, n)
+  }
+
+  public mutating func append(_ x: T) {
+    _willMutate(.append)
+    _elements.append(x)
+  }
+
+  public mutating func append<S : Sequence>(contentsOf newElements: S)
+    where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.append(contentsOf: newElements)
+    let newCount = count
+    _willMutate(.appendContentsOf(count: newCount - oldCount))
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<MinimalIndex>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == T {
+    let oldCount = count
+    _elements.replaceSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position,
+      with: newElements)
+    let newCount = count
+    _willMutate(.replaceRange(
+      subRange: subRange.lowerBound.position..<subRange.upperBound.position,
+      replacementCount:
+        subRange.upperBound.position - subRange.lowerBound.position
+        + newCount - oldCount))
+  }
+
+  public mutating func insert(_ newElement: T, at i: MinimalIndex) {
+    _willMutate(.insert(atIndex: i.position))
+    _elements.insert(newElement, at: i.position)
+  }
+
+  public mutating func insert<S : Collection>(
+    contentsOf newElements: S, at i: MinimalIndex
+  ) where S.Iterator.Element == T {
+    let oldCount = count
+    _elements.insert(contentsOf: newElements, at: i.position)
+    let newCount = count
+
+    if newCount - oldCount != 0 {
+      _willMutate(.insertContentsOf(
+        atIndex: i.position,
+        count: newCount - oldCount))
+    }
+  }
+
+  @discardableResult
+  public mutating func remove(at i: MinimalIndex) -> T {
+    _willMutate(.removeAtIndex(index: i.position))
+    return _elements.remove(at: i.position)
+  }
+
+  @discardableResult
+  public mutating func removeLast() -> T {
+    _willMutate(.removeLast)
+    return _elements.removeLast()
+  }
+
+  public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
+    if !subRange.isEmpty {
+      _willMutate(.removeRange(
+        subRange: subRange.lowerBound.position..<subRange.upperBound.position))
+    }
+    _elements.removeSubrange(
+      subRange.lowerBound.position..<subRange.upperBound.position
+    )
+  }
+
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+    _willMutate(.removeAll(keepCapacity: keepCapacity))
+    // Ignore the value of `keepCapacity`.
+    _elements.removeAll(keepingCapacity: false)
+  }
+
+  internal mutating func _willMutate(_ operation: _CollectionOperation) {
+    _collectionState = _CollectionStateTransition(
+      previousState: _collectionState,
+      operation: operation)._nextState
+  }
+
+  public var underestimatedCount: Int
+  public var reservedCapacity: Int = 0
+
+  internal var _elements: [T]
+  internal var _collectionState: _CollectionState
+}
+
+
+/// A Sequence that uses as many default implementations as
+/// `Sequence` can provide.
+public struct DefaultedSequence<Element> : Sequence {
+  public let base: MinimalSequence<Element>
+
+  public init(base: MinimalSequence<Element>) {
+    self.base = base
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base: MinimalSequence(
+      elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return base.makeIterator()
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+}
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedCollection<Element> : Collection {
+  public typealias Base = MinimalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+
+  public let base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedForwardRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
+  public typealias Base = MinimalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedForwardRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedForwardRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedForwardRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRangeReplaceableCollection<Element> : Collection, RangeReplaceableCollection {
+  public typealias Base = MinimalRangeReplaceableCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalRangeReplaceableCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+  public init() {
+    base = Base()
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<DefaultedRangeReplaceableCollection<Element>.Index>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == Element {
+    base.replaceSubrange(subRange, with: newElements)
+  }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedForwardRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
+  public typealias Base = MinimalRangeReplaceableCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedForwardRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedForwardRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedForwardRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableCollection<Element> : Collection, MutableCollection {
+  public typealias Base = MinimalMutableCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalMutableCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+    set {
+      base[i] = newValue
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedForwardRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
+  public typealias Base = MinimalMutableCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedForwardRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedForwardRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedForwardRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableRangeReplaceableCollection<Element> : Collection, MutableCollection, RangeReplaceableCollection {
+  public typealias Base = MinimalMutableRangeReplaceableCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalMutableRangeReplaceableCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+    set {
+      base[i] = newValue
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+  public init() {
+    base = Base()
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<DefaultedMutableRangeReplaceableCollection<Element>.Index>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == Element {
+    base.replaceSubrange(subRange, with: newElements)
+  }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedForwardRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
+  public typealias Base = MinimalMutableRangeReplaceableCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedForwardRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedForwardRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedForwardRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedBidirectionalCollection<Element> : BidirectionalCollection {
+  public typealias Base = MinimalBidirectionalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+
+  public let base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+  public let timesPredecessorCalled = ResettableValue(0)
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    timesPredecessorCalled.value += 1
+    return base.index(before: i)
+  }
+
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedBidirectionalCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
+  public typealias Base = MinimalBidirectionalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedBidirectionalRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedBidirectionalRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedBidirectionalRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRangeReplaceableBidirectionalCollection<Element> : BidirectionalCollection, RangeReplaceableCollection {
+  public typealias Base = MinimalRangeReplaceableBidirectionalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalRangeReplaceableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+  public let timesPredecessorCalled = ResettableValue(0)
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    timesPredecessorCalled.value += 1
+    return base.index(before: i)
+  }
+
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableBidirectionalCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+  public init() {
+    base = Base()
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<DefaultedRangeReplaceableBidirectionalCollection<Element>.Index>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == Element {
+    base.replaceSubrange(subRange, with: newElements)
+  }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
+  public typealias Base = MinimalRangeReplaceableBidirectionalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedBidirectionalRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedBidirectionalRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedBidirectionalRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableBidirectionalCollection<Element> : BidirectionalCollection, MutableCollection {
+  public typealias Base = MinimalMutableBidirectionalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalMutableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+  public let timesPredecessorCalled = ResettableValue(0)
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    timesPredecessorCalled.value += 1
+    return base.index(before: i)
+  }
+
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+    set {
+      base[i] = newValue
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableBidirectionalCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
+  public typealias Base = MinimalMutableBidirectionalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedBidirectionalRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedBidirectionalRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedBidirectionalRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableRangeReplaceableBidirectionalCollection<Element> : BidirectionalCollection, MutableCollection, RangeReplaceableCollection {
+  public typealias Base = MinimalMutableRangeReplaceableBidirectionalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalMutableRangeReplaceableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+  public let timesPredecessorCalled = ResettableValue(0)
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    timesPredecessorCalled.value += 1
+    return base.index(before: i)
+  }
+
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+    set {
+      base[i] = newValue
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableBidirectionalCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+  public init() {
+    base = Base()
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<DefaultedMutableRangeReplaceableBidirectionalCollection<Element>.Index>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == Element {
+    base.replaceSubrange(subRange, with: newElements)
+  }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
+  public typealias Base = MinimalMutableRangeReplaceableBidirectionalCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedBidirectionalRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedBidirectionalRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedBidirectionalRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRandomAccessCollection<Element> : RandomAccessCollection {
+  public typealias Base = MinimalRandomAccessCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultIndices<DefaultedRandomAccessCollection<Element>>
+
+  public let base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+  public let timesPredecessorCalled = ResettableValue(0)
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    timesPredecessorCalled.value += 1
+    return base.index(before: i)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    return base.distance(from: start, to: end)
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    return base.index(i, offsetBy: n)
+  }
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRandomAccessCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+  public typealias Base = MinimalRandomAccessCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedRandomAccessRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRandomAccessCollectionWithStrideableIndex<Element> : RandomAccessCollection {
+  public typealias Base = MinimalRandomAccessCollectionWithStrideableIndex<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalStrideableIndex
+
+  public typealias Indices = Range<MinimalStrideableIndex>
+
+  public let base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalRandomAccessCollectionWithStrideableIndex(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalStrideableIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalStrideableIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalStrideableIndex) -> Element {
+    get {
+      return base[i]
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<DefaultedRandomAccessCollectionWithStrideableIndex<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+  public typealias Base = MinimalRandomAccessCollectionWithStrideableIndex<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalStrideableIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedRandomAccessRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedRangeReplaceableRandomAccessCollection<Element> : RandomAccessCollection, RangeReplaceableCollection {
+  public typealias Base = MinimalRangeReplaceableRandomAccessCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultIndices<DefaultedRangeReplaceableRandomAccessCollection<Element>>
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalRangeReplaceableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+  public let timesPredecessorCalled = ResettableValue(0)
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    timesPredecessorCalled.value += 1
+    return base.index(before: i)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    return base.distance(from: start, to: end)
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    return base.index(i, offsetBy: n)
+  }
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableRandomAccessCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+  }
+
+  public init() {
+    base = Base()
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<DefaultedRangeReplaceableRandomAccessCollection<Element>.Index>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == Element {
+    base.replaceSubrange(subRange, with: newElements)
+  }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+  public typealias Base = MinimalRangeReplaceableRandomAccessCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedRandomAccessRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableRandomAccessCollection<Element> : RandomAccessCollection, MutableCollection {
+  public typealias Base = MinimalMutableRandomAccessCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultIndices<DefaultedMutableRandomAccessCollection<Element>>
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalMutableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+  public let timesPredecessorCalled = ResettableValue(0)
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    timesPredecessorCalled.value += 1
+    return base.index(before: i)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    return base.distance(from: start, to: end)
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    return base.index(i, offsetBy: n)
+  }
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+    set {
+      base[i] = newValue
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRandomAccessCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+  public typealias Base = MinimalMutableRandomAccessCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedRandomAccessRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+/// A Collection that uses as many default implementations as
+/// `Collection` can provide.
+public struct DefaultedMutableRangeReplaceableRandomAccessCollection<Element> : RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
+  public typealias Base = MinimalMutableRangeReplaceableRandomAccessCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultIndices<DefaultedMutableRangeReplaceableRandomAccessCollection<Element>>
+
+  public var base: Base
+
+  public init(base: Base) {
+    self.base = base
+  }
+
+  public init(_ array: [Element]) {
+    self.base = Base(elements: array)
+  }
+
+  public init(elements: [Element]) {
+    self.base = Base(elements: elements)
+  }
+
+  public init<S : Sequence>(
+    elements: S,
+    underestimatedCount: UnderestimatedCountBehavior = .value(0)
+  ) where S.Iterator.Element == Element {
+    self.init(base:
+      MinimalMutableRangeReplaceableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
+  }
+
+  public var underestimatedCount: Int {
+    return base.underestimatedCount
+  }
+
+  public let timesMakeIteratorCalled = ResettableValue(0)
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    timesMakeIteratorCalled.value += 1
+    return base.makeIterator()
+  }
+
+
+  public let timesSuccessorCalled = ResettableValue(0)
+
+  public func index(after i: MinimalIndex) -> MinimalIndex {
+    timesSuccessorCalled.value += 1
+    return base.index(after: i)
+  }
+
+  public let timesPredecessorCalled = ResettableValue(0)
+
+  public func index(before i: MinimalIndex) -> MinimalIndex {
+    timesPredecessorCalled.value += 1
+    return base.index(before: i)
+  }
+
+  public func distance(from start: MinimalIndex, to end: MinimalIndex)
+    -> Int {
+    return base.distance(from: start, to: end)
+  }
+
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    return base.index(i, offsetBy: n)
+  }
+
+
+  public let timesStartIndexCalled = ResettableValue(0)
+
+  public var startIndex: MinimalIndex {
+    timesStartIndexCalled.value += 1
+    return base.startIndex
+  }
+
+  public let timesEndIndexCalled = ResettableValue(0)
+
+  public var endIndex: MinimalIndex {
+    timesEndIndexCalled.value += 1
+    return base.endIndex
+  }
+
+  public subscript(i: MinimalIndex) -> Element {
+    get {
+      return base[i]
+    }
+    set {
+      base[i] = newValue
+    }
+  }
+
+    // FIXME: swift-3-indexing-model: use defaults.
+//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
+
+  public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableRandomAccessCollection<Base.Element>> {
+    get {
+      // FIXME: swift-3-indexing-model: range check.
+      return Slice(base: self, bounds: bounds)
+    }
+    set {
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+
+  public init() {
+    base = Base()
+  }
+
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<DefaultedMutableRangeReplaceableRandomAccessCollection<Element>.Index>,
+    with newElements: C
+  ) where C : Collection, C.Iterator.Element == Element {
+    base.replaceSubrange(subRange, with: newElements)
+  }
+}
+
+/*
+FIXME: swift-3-indexing-model: uncomment this.
+public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
+  : RangeReplaceableCollection {
+
+  public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
+  public typealias Base = MinimalMutableRangeReplaceableRandomAccessCollection<Element>
+  public typealias Iterator = MinimalIterator<Element>
+  public typealias Index = MinimalIndex
+
+  public var base: Base
+  public var startIndex: Index
+  public var endIndex: Index
+
+  public init() {
+    expectSliceType(Self_.self)
+
+    self.base = Base()
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base) {
+    self.base = base
+    self.startIndex = base.startIndex
+    self.endIndex = base.endIndex
+  }
+
+  public init(base: Base, bounds: Range<Index>) {
+    self.base = base
+    self.startIndex = bounds.lowerBound
+    self.endIndex = bounds.upperBound
+  }
+
+  public init(_ array: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: array))
+  }
+
+  public init(elements: [Element]) {
+    self = DefaultedRandomAccessRangeReplaceableSlice(
+      base: Base(elements: elements))
+  }
+
+  public func makeIterator() -> MinimalIterator<Element> {
+    return MinimalIterator(Array(self))
+  }
+
+  public subscript(index: Index) -> Element {
+    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+    return base[index]
+  }
+
+  public subscript(bounds: Range<Index>) -> Self_ {
+    Index._failEarlyRangeCheck2(
+      rangeStart: bounds.lowerBound,
+      rangeEnd: bounds.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    return DefaultedRandomAccessRangeReplaceableSlice(
+      base: base, bounds: bounds)
+  }
+
+  public mutating func replaceSubrange<
+    C : Collection
+  >(
+    _ subRange: Range<Index>,
+    with newElements: C
+  ) where C.Iterator.Element == Element {
+    let startOffset = startIndex.position
+    let endOffset =
+      endIndex.position
+      - subRange.count
+      + numericCast(newElements.count) as Int
+    Index._failEarlyRangeCheck2(
+      rangeStart: subRange.lowerBound,
+      rangeEnd: subRange.upperBound,
+      boundsStart: startIndex,
+      boundsEnd: endIndex)
+    base.replaceSubrange(subRange, with: newElements)
+    startIndex = base.startIndex.advanced(by: startOffset)
+    endIndex = base.startIndex.advanced(by: endOffset)
+  }
+}
+*/
+
+
+// Local Variables:
+// eval: (read-only-mode 1)
+// End:
diff --git a/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb b/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb
deleted file mode 100644
index ddf5a76..0000000
--- a/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb
+++ /dev/null
@@ -1,1091 +0,0 @@
-//===--- MinimalCollections.swift.gyb -------------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-from gyb_stdlib_support import (
-    TRAVERSALS,
-    collectionForTraversal,
-    collectionTypeName,
-    protocolsForCollectionFeatures
-)
-}%
-
-import StdlibUnittest
-
-/// State shared by all generators of a MinimalSequence.
-internal class _MinimalIteratorSharedState<T> {
-  internal init(_ data: [T]) {
-    self.data = data
-  }
-
-  internal let data: [T]
-  internal var i: Int = 0
-  internal var underestimatedCount: Int = 0
-}
-
-//===----------------------------------------------------------------------===//
-// MinimalIterator
-//===----------------------------------------------------------------------===//
-
-/// An IteratorProtocol that implements the protocol contract in the most
-/// narrow way possible.
-///
-/// This generator will return `nil` only once.
-public struct MinimalIterator<T> : IteratorProtocol {
-  public init<S : Sequence>(_ s: S) where S.Iterator.Element == T {
-    self._sharedState = _MinimalIteratorSharedState(Array(s))
-  }
-
-  public init(_ data: [T]) {
-    self._sharedState = _MinimalIteratorSharedState(data)
-  }
-
-  internal init(_ _sharedState: _MinimalIteratorSharedState<T>) {
-    self._sharedState = _sharedState
-  }
-
-  public func next() -> T? {
-    if _sharedState.i == _sharedState.data.count {
-      return nil
-    }
-    defer { _sharedState.i += 1 }
-    return _sharedState.data[_sharedState.i]
-  }
-
-  internal let _sharedState: _MinimalIteratorSharedState<T>
-}
-
-// A protocol to identify MinimalIterator.
-public protocol _MinimalIterator {}
-extension MinimalIterator : _MinimalIterator {}
-
-//===----------------------------------------------------------------------===//
-// MinimalSequence
-//===----------------------------------------------------------------------===//
-
-public enum UnderestimatedCountBehavior {
-  /// Return the actual number of elements.
-  case precise
-
-  /// Return the actual number of elements divided by 2.
-  case half
-
-  /// Return an overestimated count.  Useful to test how algorithms reserve
-  /// memory.
-  case overestimate
-
-  /// Return the provided value.
-  case value(Int)
-}
-
-/// A Sequence that implements the protocol contract in the most
-/// narrow way possible.
-///
-/// This sequence is consumed when its generator is advanced.
-public struct MinimalSequence<T> : Sequence, CustomDebugStringConvertible {
-  public init<S : Sequence>(
-    elements: S,
-    underestimatedCount: UnderestimatedCountBehavior = .value(0)
-  ) where S.Iterator.Element == T {
-    let data = Array(elements)
-    self._sharedState = _MinimalIteratorSharedState(data)
-
-    switch underestimatedCount {
-    case .precise:
-      self._sharedState.underestimatedCount = data.count
-
-    case .half:
-      self._sharedState.underestimatedCount = data.count / 2
-
-    case .overestimate:
-      self._sharedState.underestimatedCount = data.count * 3 + 5
-
-    case .value(let count):
-      self._sharedState.underestimatedCount = count
-    }
-  }
-
-  public let timesMakeIteratorCalled = ResettableValue(0)
-
-  public func makeIterator() -> MinimalIterator<T> {
-    timesMakeIteratorCalled.value += 1
-    return MinimalIterator(_sharedState)
-  }
-
-  public var underestimatedCount: Int {
-    return Swift.max(0, self._sharedState.underestimatedCount - self._sharedState.i)
-  }
-
-  public var debugDescription: String {
-    return "MinimalSequence(\(_sharedState.data[_sharedState.i..<_sharedState.data.count]))"
-  }
-
-  internal let _sharedState: _MinimalIteratorSharedState<T>
-}
-
-//===----------------------------------------------------------------------===//
-// Index invalidation checking
-//===----------------------------------------------------------------------===//
-
-internal enum _CollectionOperation : Equatable {
-  case reserveCapacity(capacity: Int)
-  case append
-  case appendContentsOf(count: Int)
-  case replaceRange(subRange: Range<Int>, replacementCount: Int)
-  case insert(atIndex: Int)
-  case insertContentsOf(atIndex: Int, count: Int)
-  case removeAtIndex(index: Int)
-  case removeLast
-  case removeRange(subRange: Range<Int>)
-  case removeAll(keepCapacity: Bool)
-
-  internal func _applyTo(
-    elementsLastMutatedStateIds: [Int],
-    endIndexLastMutatedStateId: Int,
-    nextStateId: Int
-  ) -> ([Int], Int) {
-    var newElementsIds = elementsLastMutatedStateIds
-    var newEndIndexId = endIndexLastMutatedStateId
-    switch self {
-    case .reserveCapacity:
-      let invalidIndices = newElementsIds.indices
-      newElementsIds.replaceSubrange(
-        invalidIndices,
-        with: repeatElement(nextStateId, count: invalidIndices.count))
-      newEndIndexId = nextStateId
-
-    case .append:
-      newElementsIds.append(nextStateId)
-      newEndIndexId = nextStateId
-
-    case .appendContentsOf(let count):
-      newElementsIds.append(contentsOf:
-        repeatElement(nextStateId, count: count))
-      newEndIndexId = nextStateId
-
-    case .replaceRange(let subRange, let replacementCount):
-      newElementsIds.replaceSubrange(
-        subRange,
-        with: repeatElement(nextStateId, count: replacementCount))
-
-      let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
-      newElementsIds.replaceSubrange(
-        invalidIndices,
-        with: repeatElement(nextStateId, count: invalidIndices.count))
-      newEndIndexId = nextStateId
-
-    case .insert(let atIndex):
-      newElementsIds.insert(nextStateId, at: atIndex)
-
-      let invalidIndices = atIndex..<newElementsIds.endIndex
-      newElementsIds.replaceSubrange(
-        invalidIndices,
-        with: repeatElement(nextStateId, count: invalidIndices.count))
-      newEndIndexId = nextStateId
-
-    case .insertContentsOf(let atIndex, let count):
-      newElementsIds.insert(
-        contentsOf: repeatElement(nextStateId, count: count),
-        at: atIndex)
-
-      let invalidIndices = atIndex..<newElementsIds.endIndex
-      newElementsIds.replaceSubrange(
-        invalidIndices,
-        with: repeatElement(nextStateId, count: invalidIndices.count))
-      newEndIndexId = nextStateId
-
-    case .removeAtIndex(let index):
-      newElementsIds.remove(at: index)
-
-      let invalidIndices = index..<newElementsIds.endIndex
-      newElementsIds.replaceSubrange(
-        invalidIndices,
-        with: repeatElement(nextStateId, count: invalidIndices.count))
-      newEndIndexId = nextStateId
-
-    case .removeLast:
-      newElementsIds.removeLast()
-      newEndIndexId = nextStateId
-
-    case .removeRange(let subRange):
-      newElementsIds.removeSubrange(subRange)
-
-      let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
-      newElementsIds.replaceSubrange(
-        invalidIndices,
-        with: repeatElement(nextStateId, count: invalidIndices.count))
-      newEndIndexId = nextStateId
-
-    case .removeAll(let keepCapacity):
-      newElementsIds.removeAll(keepingCapacity: keepCapacity)
-      newEndIndexId = nextStateId
-    }
-    return (newElementsIds, newEndIndexId)
-  }
-}
-
-internal func == (
-  lhs: _CollectionOperation,
-  rhs: _CollectionOperation
-) -> Bool {
-  switch (lhs, rhs) {
-  case (.reserveCapacity(let lhsCapacity), .reserveCapacity(let rhsCapacity)):
-    return lhsCapacity == rhsCapacity
-
-  case (.append, .append):
-    return true
-
-  case (.appendContentsOf(let lhsCount), .appendContentsOf(let rhsCount)):
-    return lhsCount == rhsCount
-
-  case (
-    .replaceRange(let lhsSubRange, let lhsReplacementCount),
-    .replaceRange(let rhsSubRange, let rhsReplacementCount)):
-
-    return lhsSubRange == rhsSubRange &&
-      lhsReplacementCount == rhsReplacementCount
-
-  case (.insert(let lhsAtIndex), .insert(let rhsAtIndex)):
-    return lhsAtIndex == rhsAtIndex
-
-  case (
-    .insertContentsOf(let lhsAtIndex, let lhsCount),
-    .insertContentsOf(let rhsAtIndex, let rhsCount)):
-
-    return lhsAtIndex == rhsAtIndex && lhsCount == rhsCount
-
-  case (.removeAtIndex(let lhsIndex), .removeAtIndex(let rhsIndex)):
-    return lhsIndex == rhsIndex
-
-  case (.removeLast, .removeLast):
-    return true
-
-  case (.removeRange(let lhsSubRange), .removeRange(let rhsSubRange)):
-    return lhsSubRange == rhsSubRange
-
-  case (.removeAll(let lhsKeepCapacity), .removeAll(let rhsKeepCapacity)):
-    return lhsKeepCapacity == rhsKeepCapacity
-
-  default:
-    return false
-  }
-}
-
-public struct _CollectionState : Equatable, Hashable {
-  internal static var _nextUnusedState: Int = 0
-  internal static var _namedStates: [String : _CollectionState] = [:]
-
-  internal let _id: Int
-  internal let _elementsLastMutatedStateIds: [Int]
-  internal let _endIndexLastMutatedStateId: Int
-
-  internal init(
-    id: Int,
-    elementsLastMutatedStateIds: [Int],
-    endIndexLastMutatedStateId: Int) {
-    self._id = id
-    self._elementsLastMutatedStateIds = elementsLastMutatedStateIds
-    self._endIndexLastMutatedStateId = endIndexLastMutatedStateId
-  }
-
-  public init(newRootStateForElementCount count: Int) {
-    self._id = _CollectionState._nextUnusedState
-    _CollectionState._nextUnusedState += 1
-    self._elementsLastMutatedStateIds =
-      Array(repeatElement(self._id, count: count))
-    self._endIndexLastMutatedStateId = self._id
-  }
-
-  internal init(name: String, elementCount: Int) {
-    if let result = _CollectionState._namedStates[name] {
-      self = result
-    } else {
-      self = _CollectionState(newRootStateForElementCount: elementCount)
-      _CollectionState._namedStates[name] = self
-    }
-  }
-
-  public var hashValue: Int {
-    return _id.hashValue
-  }
-}
-
-public func == (lhs: _CollectionState, rhs: _CollectionState) -> Bool {
-  return lhs._id == rhs._id
-}
-
-internal struct _CollectionStateTransition {
-  internal let _previousState: _CollectionState
-  internal let _operation: _CollectionOperation
-  internal let _nextState: _CollectionState
-
-  internal static var _allTransitions:
-    [_CollectionState : Box<[_CollectionStateTransition]>] = [:]
-
-  internal init(
-    previousState: _CollectionState,
-    operation: _CollectionOperation,
-    nextState: _CollectionState
-  ) {
-    var transitions =
-      _CollectionStateTransition._allTransitions[previousState]
-    if transitions == nil {
-      transitions = Box<[_CollectionStateTransition]>([])
-      _CollectionStateTransition._allTransitions[previousState] = transitions
-    }
-    if let i = transitions!.value.index(where: { $0._operation == operation }) {
-      self = transitions!.value[i]
-      return
-    }
-    self._previousState = previousState
-    self._operation = operation
-    self._nextState = nextState
-    transitions!.value.append(self)
-  }
-
-  internal init(
-    previousState: _CollectionState,
-    operation: _CollectionOperation
-  ) {
-    let nextStateId = _CollectionState._nextUnusedState
-    _CollectionState._nextUnusedState += 1
-    let (newElementStates, newEndIndexState) = operation._applyTo(
-      elementsLastMutatedStateIds: previousState._elementsLastMutatedStateIds,
-      endIndexLastMutatedStateId: previousState._endIndexLastMutatedStateId,
-      nextStateId: nextStateId)
-    let nextState = _CollectionState(
-      id: nextStateId,
-      elementsLastMutatedStateIds: newElementStates,
-      endIndexLastMutatedStateId: newEndIndexState)
-    self = _CollectionStateTransition(
-      previousState: previousState,
-      operation: operation,
-      nextState: nextState)
-  }
-}
-
-% for Index in ['MinimalIndex', 'MinimalStrideableIndex']:
-
-//===----------------------------------------------------------------------===//
-// ${Index}
-//===----------------------------------------------------------------------===//
-
-/// Asserts that the two indices are allowed to participate in a binary
-/// operation.
-internal func _expectCompatibleIndices(
-  _ first: ${Index},
-  _ second: ${Index},
-  ${TRACE}
-) {
-  if first._collectionState._id == second._collectionState._id {
-    // Fast path: the indices are derived from the same state.
-    return
-  }
-
-  // The indices are derived from different states.  Check that they point
-  // to a self-consistent view of the collection.
-  if first._collectionState._id > second._collectionState._id {
-    return _expectCompatibleIndices(second, first)
-  }
-
-  func lastMutatedStateId(
-    of i: ${Index},
-    in state: _CollectionState
-  ) -> Int {
-    let offset = i.position
-    if offset == state._elementsLastMutatedStateIds.endIndex {
-      return state._id
-    }
-    return state._elementsLastMutatedStateIds[offset]
-  }
-
-  let newestCollectionState = second._collectionState
-  let expectedFirstIndexLastMutatedStateId =
-    lastMutatedStateId(of: first, in: newestCollectionState)
-
-  expectEqual(
-    expectedFirstIndexLastMutatedStateId,
-    first._collectionState._id,
-    "Indices are not compatible:\n" +
-    "first: \(first)\n" +
-    "second: \(second)\n" +
-    "first element last mutated in state id: \(first._collectionState._id)\n" +
-    "expected state id: \(expectedFirstIndexLastMutatedStateId)\n" +
-    "newest collection state: \(newestCollectionState)",
-    stackTrace: ${stackTrace})
-
-  // To make writing assertions easier, perform a trap.
-  if expectedFirstIndexLastMutatedStateId != first._collectionState._id {
-    fatalError("Indices are not compatible")
-  }
-}
-
-public struct ${Index} : Comparable {
-  public init(
-    collectionState: _CollectionState,
-    position: Int,
-    startIndex: Int,
-    endIndex: Int
-  ) {
-    expectTrapping(
-      position,
-      in: startIndex...endIndex)
-    self = ${Index}(
-      _collectionState: collectionState,
-      uncheckedPosition: position)
-  }
-
-  internal init(
-    _collectionState: _CollectionState,
-    uncheckedPosition: Int
-  ) {
-    self._collectionState = _collectionState
-    self.position = uncheckedPosition
-  }
-
-  public let _collectionState: _CollectionState
-  public let position: Int
-
-  public static var trapOnRangeCheckFailure = ResettableValue(true)
-
-%   if 'Strideable' in Index:
-  public var timesAdvancedCalled = ResettableValue(0)
-  public var timesDistanceCalled = ResettableValue(0)
-%   end
-}
-
-public func == (lhs: ${Index}, rhs: ${Index}) -> Bool {
-  _expectCompatibleIndices(lhs, rhs)
-  return lhs.position == rhs.position
-}
-
-public func < (lhs: ${Index}, rhs: ${Index}) -> Bool {
-  _expectCompatibleIndices(lhs, rhs)
-  return lhs.position < rhs.position
-}
-
-% end
-
-extension MinimalStrideableIndex : Strideable {
-  public typealias Stride = Int
-
-  public func distance(to other: MinimalStrideableIndex) -> Int {
-    timesDistanceCalled.value += 1
-    _expectCompatibleIndices(self, other)
-    return other.position - position
-  }
-
-  public func advanced(by n: Int) -> MinimalStrideableIndex {
-    timesAdvancedCalled.value += 1
-    return MinimalStrideableIndex(
-      _collectionState: _collectionState,
-      uncheckedPosition: position + n)
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Minimal***[Mutable]?Collection
-//===----------------------------------------------------------------------===//
-
-% for Traversal in TRAVERSALS:
-%   for Mutable in [ False, True ]:
-%     for RangeReplaceable in [ False, True ]:
-%       for StrideableIndex in [ False, True ]:
-%         Self = 'Minimal' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-%         Self += 'WithStrideableIndex' if StrideableIndex else ''
-%         SelfProtocols = ', '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable))
-%         Index = 'MinimalStrideableIndex' if StrideableIndex else 'MinimalIndex'
-%         # Only generating MinimalRandomAccessCollectionWithStrideableIndex
-%         if not StrideableIndex or (
-%           StrideableIndex and Traversal == 'RandomAccess' and
-%           not Mutable):
-
-/// A minimal implementation of `Collection` with extra checks.
-public struct ${Self}<T> : ${SelfProtocols} {
-  /// Creates a collection with given contents, but a unique modification
-  /// history.  No other instance has the same modification history.
-  public init<S : Sequence>(
-    elements: S,
-    underestimatedCount: UnderestimatedCountBehavior = .value(0)
-  ) where S.Iterator.Element == T {
-    self._elements = Array(elements)
-
-    self._collectionState = _CollectionState(
-      newRootStateForElementCount: self._elements.count)
-
-    switch underestimatedCount {
-    case .precise:
-      self.underestimatedCount = _elements.count
-
-    case .half:
-      self.underestimatedCount = _elements.count / 2
-
-    case .overestimate:
-      self.underestimatedCount = _elements.count * 3 + 5
-
-    case .value(let count):
-      self.underestimatedCount = count
-    }
-  }
-
-%     if RangeReplaceable:
-  public init() {
-    self.underestimatedCount = 0
-    self._elements = []
-    self._collectionState =
-      _CollectionState(name: "\(type(of: self))", elementCount: 0)
-  }
-
-  public init<S : Sequence>(_ elements: S) where S.Iterator.Element == T {
-    self.underestimatedCount = 0
-    self._elements = Array(elements)
-    self._collectionState =
-      _CollectionState(newRootStateForElementCount: self._elements.count)
-  }
-%     end
-
-  public let timesMakeIteratorCalled = ResettableValue(0)
-
-  public func makeIterator() -> MinimalIterator<T> {
-    timesMakeIteratorCalled.value += 1
-    return MinimalIterator(_elements)
-  }
-
-  public typealias Index = ${Index}
-
-  internal func _index(forPosition i: Int) -> ${Index} {
-    return ${Index}(
-      collectionState: _collectionState,
-      position: i,
-      startIndex: _elements.startIndex,
-      endIndex: _elements.endIndex)
-  }
-
-  internal func _uncheckedIndex(forPosition i: Int) -> ${Index} {
-    return ${Index}(
-      _collectionState: _collectionState,
-      uncheckedPosition: i)
-  }
-
-  public let timesStartIndexCalled = ResettableValue(0)
-
-  public var startIndex: ${Index} {
-    timesStartIndexCalled.value += 1
-    return _uncheckedIndex(forPosition: _elements.startIndex)
-  }
-
-  public let timesEndIndexCalled = ResettableValue(0)
-
-  public var endIndex: ${Index} {
-    timesEndIndexCalled.value += 1
-    return _uncheckedIndex(forPosition: _elements.endIndex)
-  }
-
-%     if StrideableIndex:
-  public typealias Indices = Range<${Index}>
-%     elif Traversal == 'RandomAccess':
-  // FIXME: this shouldn't be necessary, should come by default
-  public typealias Indices = DefaultIndices<${Self}<T>>
-%     end
-
-  public func _failEarlyRangeCheck(
-    _ index: ${Index},
-    bounds: Range<${Index}>
-  ) {
-    _expectCompatibleIndices(
-      _uncheckedIndex(forPosition: index.position),
-      index)
-
-    _expectCompatibleIndices(
-      _uncheckedIndex(forPosition: bounds.lowerBound.position),
-      bounds.lowerBound)
-    _expectCompatibleIndices(
-      _uncheckedIndex(forPosition: bounds.upperBound.position),
-      bounds.upperBound)
-
-    expectTrapping(
-      index.position,
-      in: bounds.lowerBound.position..<bounds.upperBound.position)
-  }
-
-  public func _failEarlyRangeCheck(
-    _ range: Range<${Index}>,
-    bounds: Range<${Index}>
-  ) {
-    _expectCompatibleIndices(
-      _uncheckedIndex(forPosition: range.lowerBound.position),
-      range.lowerBound)
-    _expectCompatibleIndices(
-      _uncheckedIndex(forPosition: range.upperBound.position),
-      range.upperBound)
-
-    _expectCompatibleIndices(
-      _uncheckedIndex(forPosition: bounds.lowerBound.position),
-      bounds.lowerBound)
-    _expectCompatibleIndices(
-      _uncheckedIndex(forPosition: bounds.upperBound.position),
-      bounds.upperBound)
-
-    expectTrapping(
-      range.lowerBound.position..<range.upperBound.position,
-      in: bounds.lowerBound.position..<bounds.upperBound.position)
-  }
-
-  public func index(after i: ${Index}) -> ${Index} {
-    _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
-    return _uncheckedIndex(forPosition: i.position + 1)
-  }
-
-%     if Traversal in ['Bidirectional', 'RandomAccess']:
-  public func index(before i: ${Index}) -> ${Index} {
-    // FIXME: swift-3-indexing-model: perform a range check and use
-    // return _uncheckedIndex(forPosition: i.position - 1)
-    return _index(forPosition: i.position - 1)
-  }
-%     end
-
-  public func distance(from start: ${Index}, to end: ${Index})
-    -> Int {
-%     if Traversal == 'Forward':
-    _precondition(start <= end,
-      "Only BidirectionalCollections can have end come before start")
-%     end
-    // FIXME: swift-3-indexing-model: perform a range check properly.
-    if start != endIndex {
-      _failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
-    }
-    if end != endIndex {
-      _failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
-    }
-    return end.position - start.position
-  }
-
-  public func index(_ i: Index, offsetBy n: Int) -> Index {
-%     if Traversal == 'Forward':
-    _precondition(n >= 0,
-      "Only BidirectionalCollections can be advanced by a negative amount")
-%     end
-    // FIXME: swift-3-indexing-model: perform a range check properly.
-    if i != endIndex {
-      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
-    }
-    return _index(forPosition: i.position + n)
-  }
-
-  public subscript(i: ${Index}) -> T {
-    get {
-      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
-      return _elements[i.position]
-    }
-%     if Mutable:
-    set {
-      _failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
-      _elements[i.position] = newValue
-    }
-%     end
-  }
-
-  public subscript(bounds: Range<${Index}>) -> Slice<${Self}<T>> {
-    get {
-      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return Slice(base: self, bounds: bounds)
-    }
-%     if Mutable:
-    set {
-      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
-    }
-%     end
-  }
-
-%     if RangeReplaceable:
-  public mutating func reserveCapacity(_ n: Int) {
-    _willMutate(.reserveCapacity(capacity: n))
-    _elements.reserveCapacity(n)
-    reservedCapacity = Swift.max(reservedCapacity, n)
-  }
-
-  public mutating func append(_ x: T) {
-    _willMutate(.append)
-    _elements.append(x)
-  }
-
-  public mutating func append<S : Sequence>(contentsOf newElements: S)
-    where S.Iterator.Element == T {
-    let oldCount = count
-    _elements.append(contentsOf: newElements)
-    let newCount = count
-    _willMutate(.appendContentsOf(count: newCount - oldCount))
-  }
-
-  public mutating func replaceSubrange<C>(
-    _ subRange: Range<${Index}>,
-    with newElements: C
-  ) where C : Collection, C.Iterator.Element == T {
-    let oldCount = count
-    _elements.replaceSubrange(
-      subRange.lowerBound.position..<subRange.upperBound.position,
-      with: newElements)
-    let newCount = count
-    _willMutate(.replaceRange(
-      subRange: subRange.lowerBound.position..<subRange.upperBound.position,
-      replacementCount:
-        subRange.upperBound.position - subRange.lowerBound.position
-        + newCount - oldCount))
-  }
-
-  public mutating func insert(_ newElement: T, at i: ${Index}) {
-    _willMutate(.insert(atIndex: i.position))
-    _elements.insert(newElement, at: i.position)
-  }
-
-  public mutating func insert<S : Collection>(
-    contentsOf newElements: S, at i: ${Index}
-  ) where S.Iterator.Element == T {
-    let oldCount = count
-    _elements.insert(contentsOf: newElements, at: i.position)
-    let newCount = count
-
-    if newCount - oldCount != 0 {
-      _willMutate(.insertContentsOf(
-        atIndex: i.position,
-        count: newCount - oldCount))
-    }
-  }
-
-  @discardableResult
-  public mutating func remove(at i: ${Index}) -> T {
-    _willMutate(.removeAtIndex(index: i.position))
-    return _elements.remove(at: i.position)
-  }
-
-  @discardableResult
-  public mutating func removeLast() -> T {
-    _willMutate(.removeLast)
-    return _elements.removeLast()
-  }
-
-  public mutating func removeSubrange(_ subRange: Range<${Index}>) {
-    if !subRange.isEmpty {
-      _willMutate(.removeRange(
-        subRange: subRange.lowerBound.position..<subRange.upperBound.position))
-    }
-    _elements.removeSubrange(
-      subRange.lowerBound.position..<subRange.upperBound.position
-    )
-  }
-
-  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
-    _willMutate(.removeAll(keepCapacity: keepCapacity))
-    // Ignore the value of `keepCapacity`.
-    _elements.removeAll(keepingCapacity: false)
-  }
-
-  internal mutating func _willMutate(_ operation: _CollectionOperation) {
-    _collectionState = _CollectionStateTransition(
-      previousState: _collectionState,
-      operation: operation)._nextState
-  }
-%     end
-
-  public var underestimatedCount: Int
-%     if RangeReplaceable:
-  public var reservedCapacity: Int = 0
-%     end
-
-  internal var _elements: [T]
-%   if RangeReplaceable:
-  internal var _collectionState: _CollectionState
-%   else:
-  internal let _collectionState: _CollectionState
-%   end
-}
-
-%         end
-%       end
-%     end
-%   end
-% end
-
-/// A Sequence that uses as many default implementations as
-/// `Sequence` can provide.
-public struct DefaultedSequence<Element> : Sequence {
-  public let base: MinimalSequence<Element>
-
-  public init(base: MinimalSequence<Element>) {
-    self.base = base
-  }
-
-  public init<S : Sequence>(
-    elements: S,
-    underestimatedCount: UnderestimatedCountBehavior = .value(0)
-  ) where S.Iterator.Element == Element {
-    self.init(base: MinimalSequence(
-      elements: elements, underestimatedCount: underestimatedCount))
-  }
-
-  public func makeIterator() -> MinimalIterator<Element> {
-    return base.makeIterator()
-  }
-
-  public var underestimatedCount: Int {
-    return base.underestimatedCount
-  }
-}
-
-% for Traversal in TRAVERSALS:
-%   for Mutable in [ False, True ]:
-%     for RangeReplaceable in [ False, True ]:
-%       for StrideableIndex in [ False, True ]:
-%         Self = 'Defaulted' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-%         Self += 'WithStrideableIndex' if StrideableIndex else ''
-%         Base = 'Minimal' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-%         Base += 'WithStrideableIndex' if StrideableIndex else ''
-%         SelfProtocols = ', '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable))
-%         Index = 'MinimalStrideableIndex' if StrideableIndex else 'MinimalIndex'
-%         # Only generating DefaultedRandomAccessCollectionWithStrideableIndex
-%         if not StrideableIndex or (
-%           StrideableIndex and Traversal == 'RandomAccess' and
-%           not Mutable and not RangeReplaceable):
-
-/// A Collection that uses as many default implementations as
-/// `Collection` can provide.
-public struct ${Self}<Element> : ${SelfProtocols} {
-  public typealias Base = ${Base}<Element>
-  public typealias Iterator = MinimalIterator<Element>
-  public typealias Index = ${Index}
-
-%   if StrideableIndex:
-  public typealias Indices = Range<${Index}>
-%  elif Traversal == 'RandomAccess':
-  // FIXME: this shouldn't be necessary, should come by default
-  public typealias Indices = DefaultIndices<${Self}<Element>>
-%   end
-
-%   if Mutable or RangeReplaceable:
-  public var base: Base
-%   else:
-  public let base: Base
-%   end
-
-  public init(base: Base) {
-    self.base = base
-  }
-
-  public init(_ array: [Element]) {
-    self.base = Base(elements: array)
-  }
-
-  public init(elements: [Element]) {
-    self.base = Base(elements: elements)
-  }
-
-  public init<S : Sequence>(
-    elements: S,
-    underestimatedCount: UnderestimatedCountBehavior = .value(0)
-  ) where S.Iterator.Element == Element {
-    self.init(base:
-      ${Base}(elements: elements, underestimatedCount: underestimatedCount))
-  }
-
-  public var underestimatedCount: Int {
-    return base.underestimatedCount
-  }
-
-  public let timesMakeIteratorCalled = ResettableValue(0)
-
-  public func makeIterator() -> MinimalIterator<Element> {
-    timesMakeIteratorCalled.value += 1
-    return base.makeIterator()
-  }
-
-%     if not StrideableIndex:
-
-  public let timesSuccessorCalled = ResettableValue(0)
-
-  public func index(after i: ${Index}) -> ${Index} {
-    timesSuccessorCalled.value += 1
-    return base.index(after: i)
-  }
-
-%       if Traversal in ['Bidirectional', 'RandomAccess']:
-  public let timesPredecessorCalled = ResettableValue(0)
-
-  public func index(before i: ${Index}) -> ${Index} {
-    timesPredecessorCalled.value += 1
-    return base.index(before: i)
-  }
-%       end
-
-%       if Traversal == 'RandomAccess':
-  public func distance(from start: ${Index}, to end: ${Index})
-    -> Int {
-    return base.distance(from: start, to: end)
-  }
-
-  public func index(_ i: Index, offsetBy n: Int) -> Index {
-    return base.index(i, offsetBy: n)
-  }
-%       end
-
-%     end # if not StrideableIndex
-
-  public let timesStartIndexCalled = ResettableValue(0)
-
-  public var startIndex: ${Index} {
-    timesStartIndexCalled.value += 1
-    return base.startIndex
-  }
-
-  public let timesEndIndexCalled = ResettableValue(0)
-
-  public var endIndex: ${Index} {
-    timesEndIndexCalled.value += 1
-    return base.endIndex
-  }
-
-  public subscript(i: ${Index}) -> Element {
-    get {
-      return base[i]
-    }
-%     if Mutable:
-    set {
-      base[i] = newValue
-    }
-%     end
-  }
-
-    // FIXME: swift-3-indexing-model: use defaults.
-//     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
-
-  public subscript(bounds: Range<${Index}>) -> Slice<${Self}<Base.Element>> {
-    get {
-      // FIXME: swift-3-indexing-model: range check.
-      return Slice(base: self, bounds: bounds)
-    }
-%     if Mutable:
-    set {
-      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
-    }
-%     end
-  }
-
-%   if RangeReplaceable:
-  public init() {
-    base = Base()
-  }
-
-  public mutating func replaceSubrange<C>(
-    _ subRange: Range<${Self}<Element>.Index>,
-    with newElements: C
-  ) where C : Collection, C.Iterator.Element == Element {
-    base.replaceSubrange(subRange, with: newElements)
-  }
-%   end
-}
-
-/*
-FIXME: swift-3-indexing-model: uncomment this.
-public struct Defaulted${Traversal}RangeReplaceableSlice<Element>
-  : RangeReplaceableCollection {
-
-  public typealias Self_ = Defaulted${Traversal}RangeReplaceableSlice<Element>
-  public typealias Base = ${Base}<Element>
-  public typealias Iterator = MinimalIterator<Element>
-  public typealias Index = ${Index}
-
-  public var base: Base
-  public var startIndex: Index
-  public var endIndex: Index
-
-  public init() {
-    expectSliceType(Self_.self)
-
-    self.base = Base()
-    self.startIndex = base.startIndex
-    self.endIndex = base.endIndex
-  }
-
-  public init(base: Base) {
-    self.base = base
-    self.startIndex = base.startIndex
-    self.endIndex = base.endIndex
-  }
-
-  public init(base: Base, bounds: Range<Index>) {
-    self.base = base
-    self.startIndex = bounds.lowerBound
-    self.endIndex = bounds.upperBound
-  }
-
-  public init(_ array: [Element]) {
-    self = Defaulted${Traversal}RangeReplaceableSlice(
-      base: Base(elements: array))
-  }
-
-  public init(elements: [Element]) {
-    self = Defaulted${Traversal}RangeReplaceableSlice(
-      base: Base(elements: elements))
-  }
-
-  public func makeIterator() -> MinimalIterator<Element> {
-    return MinimalIterator(Array(self))
-  }
-
-  public subscript(index: Index) -> Element {
-    Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
-    return base[index]
-  }
-
-  public subscript(bounds: Range<Index>) -> Self_ {
-    Index._failEarlyRangeCheck2(
-      rangeStart: bounds.lowerBound,
-      rangeEnd: bounds.upperBound,
-      boundsStart: startIndex,
-      boundsEnd: endIndex)
-    return Defaulted${Traversal}RangeReplaceableSlice(
-      base: base, bounds: bounds)
-  }
-
-  public mutating func replaceSubrange<
-    C : Collection
-  >(
-    _ subRange: Range<Index>,
-    with newElements: C
-  ) where C.Iterator.Element == Element {
-    let startOffset = startIndex.position
-    let endOffset =
-      endIndex.position
-      - subRange.count
-      + numericCast(newElements.count) as Int
-    Index._failEarlyRangeCheck2(
-      rangeStart: subRange.lowerBound,
-      rangeEnd: subRange.upperBound,
-      boundsStart: startIndex,
-      boundsEnd: endIndex)
-    base.replaceSubrange(subRange, with: newElements)
-    startIndex = base.startIndex.advanced(by: startOffset)
-    endIndex = base.startIndex.advanced(by: endOffset)
-  }
-}
-*/
-
-%         end
-%       end
-%     end
-%   end
-% end
-
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
diff --git a/stdlib/private/StdlibUnittest/CMakeLists.txt b/stdlib/private/StdlibUnittest/CMakeLists.txt
index 5729631..699bc5b 100644
--- a/stdlib/private/StdlibUnittest/CMakeLists.txt
+++ b/stdlib/private/StdlibUnittest/CMakeLists.txt
@@ -15,20 +15,20 @@
 add_swift_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
   # This file should be listed the first.  Module name is inferred from the
   # filename.
-  StdlibUnittest.swift.gyb
+  StdlibUnittest.swift
 
-  CheckStrideable.swift.gyb
+  CheckStrideable.swift
   InspectValue.cpp
   InspectValue.swift
   InterceptTraps.cpp
   LifetimeTracked.swift
-  MinimalTypes.swift.gyb
+  MinimalTypes.swift
   OpaqueIdentityFunctions.cpp
   OpaqueIdentityFunctions.swift
   RaceTest.swift
   Statistics.swift
   StdlibCoreExtras.swift
-  StringConvertible.swift.gyb
+  StringConvertible.swift
   TestHelpers.swift
   TypeIndexed.swift
   GetOSVersion.mm
diff --git a/stdlib/private/StdlibUnittest/CheckStrideable.swift.gyb b/stdlib/private/StdlibUnittest/CheckStrideable.swift
similarity index 84%
rename from stdlib/private/StdlibUnittest/CheckStrideable.swift.gyb
rename to stdlib/private/StdlibUnittest/CheckStrideable.swift
index 0f4b7ff..2c15e21 100644
--- a/stdlib/private/StdlibUnittest/CheckStrideable.swift.gyb
+++ b/stdlib/private/StdlibUnittest/CheckStrideable.swift
@@ -10,15 +10,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
 public func checkStrideable<S : Strideable>(
   instances: [S],
   distances: [S.Stride],
   distanceOracle: (Int, Int) -> S.Stride,
-  ${TRACE}
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   for i in instances.indices {
     let first = instances[i]
diff --git a/stdlib/private/StdlibUnittest/MinimalTypes.swift b/stdlib/private/StdlibUnittest/MinimalTypes.swift
new file mode 100644
index 0000000..512a974
--- /dev/null
+++ b/stdlib/private/StdlibUnittest/MinimalTypes.swift
@@ -0,0 +1,388 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+/// A type that does not conform to any protocols.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// conformances.
+public struct OpaqueValue<Underlying> {
+  public var value: Underlying
+  public var identity: Int
+
+  public init(_ value: Underlying) {
+    self.value = value
+    self.identity = 0
+  }
+
+  public init(_ value: Underlying, identity: Int) {
+    self.value = value
+    self.identity = identity
+  }
+}
+
+/// A type that conforms only to `Equatable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct MinimalEquatableValue : Equatable {
+  public static var timesEqualEqualWasCalled: Int = 0
+
+  public static var equalImpl =
+    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+
+  public var value: Int
+  public var identity: Int
+
+  public init(_ value: Int) {
+    self.value = value
+    self.identity = 0
+  }
+
+  public init(_ value: Int, identity: Int) {
+    self.value = value
+    self.identity = identity
+  }
+
+  public static func == (
+    lhs: MinimalEquatableValue,
+    rhs: MinimalEquatableValue
+  ) -> Bool {
+    MinimalEquatableValue.timesEqualEqualWasCalled += 1
+    return MinimalEquatableValue.equalImpl.value(lhs.value, rhs.value)
+  }
+}
+
+/// A type that conforms only to `Equatable` and `Comparable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct MinimalComparableValue : Equatable, Comparable {
+  public static var timesEqualEqualWasCalled = ResettableValue(0)
+  public static var timesLessWasCalled = ResettableValue(0)
+
+  public static var equalImpl =
+    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+  public static var lessImpl =
+    ResettableValue<(Int, Int) -> Bool>({ $0 < $1 })
+
+  public var value: Int
+  public var identity: Int
+
+  public init(_ value: Int) {
+    self.value = value
+    self.identity = 0
+  }
+
+  public init(_ value: Int, identity: Int) {
+    self.value = value
+    self.identity = identity
+  }
+
+  public static func == (
+    lhs: MinimalComparableValue,
+    rhs: MinimalComparableValue
+  ) -> Bool {
+    MinimalComparableValue.timesEqualEqualWasCalled.value += 1
+    return MinimalComparableValue.equalImpl.value(lhs.value, rhs.value)
+  }
+
+  public static func < (
+    lhs: MinimalComparableValue,
+    rhs: MinimalComparableValue
+  ) -> Bool {
+    MinimalComparableValue.timesLessWasCalled.value += 1
+    return MinimalComparableValue.lessImpl.value(lhs.value, rhs.value)
+  }
+}
+
+
+/// A type that conforms only to `Equatable` and `Hashable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct MinimalHashableValue : Equatable, Hashable {
+  public static var timesEqualEqualWasCalled: Int = 0
+  public static var timesHashIntoWasCalled: Int = 0
+
+  public static var equalImpl =
+    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+  public static var hashIntoImpl =
+    ResettableValue<(Int, inout _Hasher) -> Void>({ $1.combine($0) })
+
+  public var value: Int
+  public var identity: Int
+
+  public init(_ value: Int) {
+    self.value = value
+    self.identity = 0
+  }
+
+  public init(_ value: Int, identity: Int) {
+    self.value = value
+    self.identity = identity
+  }
+
+  public static func ==(
+    lhs: MinimalHashableValue,
+    rhs: MinimalHashableValue
+  ) -> Bool {
+    MinimalHashableValue.timesEqualEqualWasCalled += 1
+    return MinimalHashableValue.equalImpl.value(lhs.value, rhs.value)
+  }
+
+  public var hashValue: Int {
+    var hasher = _Hasher()
+    hasher.combine(self)
+    return hasher.finalize()
+  }
+
+  public func _hash(into hasher: inout _Hasher) {
+    MinimalHashableValue.timesHashIntoWasCalled += 1
+    MinimalHashableValue.hashIntoImpl.value(value, &hasher)
+  }
+}
+
+extension MinimalHashableValue: CustomStringConvertible {
+  public var description: String {
+    return "MinimalHashableValue(value: \(value), identity: \(identity))"
+  }
+}
+
+
+/// A type that conforms only to `Equatable` and `Hashable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public class MinimalHashableClass : Equatable, Hashable {
+  public static var timesEqualEqualWasCalled: Int = 0
+  public static var timesHashIntoWasCalled: Int = 0
+
+  public static var equalImpl =
+    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+  public static var hashIntoImpl =
+  ResettableValue<(Int, inout _Hasher) -> Void>({ $1.combine($0) })
+
+  public var value: Int
+  public var identity: Int
+
+  public init(_ value: Int) {
+    self.value = value
+    self.identity = 0
+  }
+
+  public init(_ value: Int, identity: Int) {
+    self.value = value
+    self.identity = identity
+  }
+
+  public static func == (
+    lhs: MinimalHashableClass,
+    rhs: MinimalHashableClass
+  ) -> Bool {
+    MinimalHashableClass.timesEqualEqualWasCalled += 1
+    return MinimalHashableClass.equalImpl.value(lhs.value, rhs.value)
+  }
+
+  public var hashValue: Int {
+    var hasher = _Hasher()
+    hasher.combine(self)
+    return hasher.finalize()
+  }
+
+  public func _hash(into hasher: inout _Hasher) {
+    MinimalHashableClass.timesHashIntoWasCalled += 1
+    MinimalHashableClass.hashIntoImpl.value(value, &hasher)
+  }
+}
+
+extension MinimalHashableClass: CustomStringConvertible {
+  public var description: String {
+    return "MinimalHashableClass(value: \(value), identity: \(identity))"
+  }
+}
+
+
+
+public var GenericMinimalHashableValue_timesEqualEqualWasCalled: Int = 0
+public var GenericMinimalHashableValue_timesHashIntoWasCalled: Int = 0
+
+public var GenericMinimalHashableValue_equalImpl =
+  ResettableValue<(Any, Any) -> Bool>({ _, _ in
+    fatalError("GenericMinimalHashableValue_equalImpl is not set yet")
+  })
+public var GenericMinimalHashableValue_hashIntoImpl =
+  ResettableValue<(Any, inout _Hasher) -> Void>({ _ in
+    fatalError("GenericMinimalHashableValue_hashIntoImpl is not set yet")
+  })
+
+/// A type that conforms only to `Equatable` and `Hashable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct GenericMinimalHashableValue<Wrapped> : Equatable, Hashable {
+  public var value: Wrapped
+  public var identity: Int
+
+  public init(_ value: Wrapped) {
+    self.value = value
+    self.identity = 0
+  }
+
+  public init(_ value: Wrapped, identity: Int) {
+    self.value = value
+    self.identity = identity
+  }
+
+  public static func == <Wrapped>(
+    lhs: GenericMinimalHashableValue<Wrapped>,
+    rhs: GenericMinimalHashableValue<Wrapped>
+  ) -> Bool {
+    GenericMinimalHashableValue_timesEqualEqualWasCalled += 1
+    return GenericMinimalHashableValue_equalImpl.value(lhs.value, rhs.value)
+  }
+
+  public var hashValue: Int {
+    var hasher = _Hasher()
+    hasher.combine(self)
+    return hasher.finalize()
+  }
+
+  public func _hash(into hasher: inout _Hasher) {
+    GenericMinimalHashableValue_timesHashIntoWasCalled += 1
+    GenericMinimalHashableValue_hashIntoImpl.value(value, &hasher)
+  }
+}
+
+extension GenericMinimalHashableValue: CustomStringConvertible {
+  public var description: String {
+    return "GenericMinimalHashableValue(value: \(value), identity: \(identity))"
+  }
+}
+
+public var GenericMinimalHashableClass_timesEqualEqualWasCalled: Int = 0
+public var GenericMinimalHashableClass_timesHashIntoWasCalled: Int = 0
+
+public var GenericMinimalHashableClass_equalImpl =
+  ResettableValue<(Any, Any) -> Bool>({ _, _ in
+    fatalError("GenericMinimalHashableClass_equalImpl is not set yet")
+  })
+public var GenericMinimalHashableClass_hashIntoImpl =
+  ResettableValue<(Any, inout _Hasher) -> Void>({ _ in
+    fatalError("GenericMinimalHashableClass_hashIntoImpl is not set yet")
+  })
+
+/// A type that conforms only to `Equatable` and `Hashable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public class GenericMinimalHashableClass<Wrapped> : Equatable, Hashable {
+  public var value: Wrapped
+  public var identity: Int
+
+  public init(_ value: Wrapped) {
+    self.value = value
+    self.identity = 0
+  }
+
+  public init(_ value: Wrapped, identity: Int) {
+    self.value = value
+    self.identity = identity
+  }
+
+  public static func == <Wrapped>(
+    lhs: GenericMinimalHashableClass<Wrapped>,
+    rhs: GenericMinimalHashableClass<Wrapped>
+  ) -> Bool {
+    GenericMinimalHashableClass_timesEqualEqualWasCalled += 1
+    return GenericMinimalHashableClass_equalImpl.value(lhs.value, rhs.value)
+  }
+
+  public var hashValue: Int {
+    var hasher = _Hasher()
+    hasher.combine(self)
+    return hasher.finalize()
+  }
+
+  public func _hash(into hasher: inout _Hasher) {
+    GenericMinimalHashableClass_timesHashIntoWasCalled += 1
+    GenericMinimalHashableClass_hashIntoImpl.value(value, &hasher)
+  }
+}
+
+extension GenericMinimalHashableClass: CustomStringConvertible {
+  public var description: String {
+    return "GenericMinimalHashableClass(value: \(value), identity: \(identity))"
+  }
+}
+
+
+/// A type that conforms only to `Equatable`, `Comparable`, and `Strideable`.
+///
+/// This type can be used to check that generic functions don't rely on any
+/// other conformances.
+public struct MinimalStrideableValue : Equatable, Comparable, Strideable {
+  public static var timesEqualEqualWasCalled = ResettableValue(0)
+  public static var timesLessWasCalled = ResettableValue(0)
+  public static var timesDistanceWasCalled = ResettableValue(0)
+  public static var timesAdvancedWasCalled = ResettableValue(0)
+
+  public static var equalImpl =
+    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
+  public static var lessImpl =
+    ResettableValue<(Int, Int) -> Bool>({ $0 < $1 })
+
+  public var value: Int
+  public var identity: Int
+
+  public init(_ value: Int) {
+    self.value = value
+    self.identity = 0
+  }
+
+  public init(_ value: Int, identity: Int) {
+    self.value = value
+    self.identity = identity
+  }
+
+  public typealias Stride = Int
+
+  public static func == (
+    lhs: MinimalStrideableValue,
+    rhs: MinimalStrideableValue
+  ) -> Bool {
+    MinimalStrideableValue.timesEqualEqualWasCalled.value += 1
+    return MinimalStrideableValue.equalImpl.value(lhs.value, rhs.value)
+  }
+
+  public static func < (
+    lhs: MinimalStrideableValue,
+    rhs: MinimalStrideableValue
+  ) -> Bool {
+    MinimalStrideableValue.timesLessWasCalled.value += 1
+    return MinimalStrideableValue.lessImpl.value(lhs.value, rhs.value)
+  }
+
+  public func distance(to other: MinimalStrideableValue) -> Stride {
+    MinimalStrideableValue.timesDistanceWasCalled.value += 1
+    return other.value - self.value
+  }
+
+  public func advanced(by n: Stride) -> MinimalStrideableValue {
+    MinimalStrideableValue.timesAdvancedWasCalled.value += 1
+    return MinimalStrideableValue(self.value + n, identity: self.identity)
+  }
+}
+
+
+// Local Variables:
+// eval: (read-only-mode 1)
+// End:
diff --git a/stdlib/private/StdlibUnittest/MinimalTypes.swift.gyb b/stdlib/private/StdlibUnittest/MinimalTypes.swift.gyb
deleted file mode 100644
index 15bb106..0000000
--- a/stdlib/private/StdlibUnittest/MinimalTypes.swift.gyb
+++ /dev/null
@@ -1,255 +0,0 @@
-//===--- MinimalTypes.swift -----------------------------------*- swift -*-===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-/// A type that does not conform to any protocols.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// conformances.
-public struct OpaqueValue<Underlying> {
-  public var value: Underlying
-  public var identity: Int
-
-  public init(_ value: Underlying) {
-    self.value = value
-    self.identity = 0
-  }
-
-  public init(_ value: Underlying, identity: Int) {
-    self.value = value
-    self.identity = identity
-  }
-}
-
-/// A type that conforms only to `Equatable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public struct MinimalEquatableValue : Equatable {
-  public static var timesEqualEqualWasCalled: Int = 0
-
-  public static var equalImpl =
-    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
-
-  public var value: Int
-  public var identity: Int
-
-  public init(_ value: Int) {
-    self.value = value
-    self.identity = 0
-  }
-
-  public init(_ value: Int, identity: Int) {
-    self.value = value
-    self.identity = identity
-  }
-}
-public func == (
-  lhs: MinimalEquatableValue,
-  rhs: MinimalEquatableValue
-) -> Bool {
-  MinimalEquatableValue.timesEqualEqualWasCalled += 1
-  return MinimalEquatableValue.equalImpl.value(lhs.value, rhs.value)
-}
-
-/// A type that conforms only to `Equatable` and `Comparable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public struct MinimalComparableValue : Equatable, Comparable {
-  public static var timesEqualEqualWasCalled = ResettableValue(0)
-  public static var timesLessWasCalled = ResettableValue(0)
-
-  public static var equalImpl =
-    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
-  public static var lessImpl =
-    ResettableValue<(Int, Int) -> Bool>({ $0 < $1 })
-
-  public var value: Int
-  public var identity: Int
-
-  public init(_ value: Int) {
-    self.value = value
-    self.identity = 0
-  }
-
-  public init(_ value: Int, identity: Int) {
-    self.value = value
-    self.identity = identity
-  }
-}
-
-public func == (
-  lhs: MinimalComparableValue,
-  rhs: MinimalComparableValue
-) -> Bool {
-  MinimalComparableValue.timesEqualEqualWasCalled.value += 1
-  return MinimalComparableValue.equalImpl.value(lhs.value, rhs.value)
-}
-
-public func < (
-  lhs: MinimalComparableValue,
-  rhs: MinimalComparableValue
-) -> Bool {
-  MinimalComparableValue.timesLessWasCalled.value += 1
-  return MinimalComparableValue.lessImpl.value(lhs.value, rhs.value)
-}
-
-% for (kind, decl_keyword) in [ ('Value', 'struct'), ('Class', 'class') ]:
-%   Self = 'MinimalHashable%s' % kind
-
-/// A type that conforms only to `Equatable` and `Hashable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public ${decl_keyword} ${Self} : Equatable, Hashable {
-  public static var timesEqualEqualWasCalled: Int = 0
-  public static var timesHashValueWasCalled: Int = 0
-
-  public static var equalImpl =
-    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
-  public static var hashValueImpl =
-    ResettableValue<(Int) -> Int>({ $0.hashValue })
-
-  public var value: Int
-  public var identity: Int
-
-  public init(_ value: Int) {
-    self.value = value
-    self.identity = 0
-  }
-
-  public init(_ value: Int, identity: Int) {
-    self.value = value
-    self.identity = identity
-  }
-
-  public var hashValue: Int {
-    ${Self}.timesHashValueWasCalled += 1
-    return ${Self}.hashValueImpl.value(value)
-  }
-}
-
-public func == (
-  lhs: ${Self},
-  rhs: ${Self}
-) -> Bool {
-  ${Self}.timesEqualEqualWasCalled += 1
-  return ${Self}.equalImpl.value(lhs.value, rhs.value)
-}
-
-% end
-
-% for (kind, decl_keyword) in [ ('Value', 'struct'), ('Class', 'class') ]:
-%   Self = 'GenericMinimalHashable%s' % kind
-
-public var ${Self}_timesEqualEqualWasCalled: Int = 0
-public var ${Self}_timesHashValueWasCalled: Int = 0
-
-public var ${Self}_equalImpl = ResettableValue<(Any, Any) -> Bool>(
-  { _, _ in fatalError("${Self}_equalImpl is not set yet"); () })
-public var ${Self}_hashValueImpl = ResettableValue<(Any) -> Int>(
-  { _ in fatalError("${Self}_hashValueImpl is not set yet"); () })
-
-/// A type that conforms only to `Equatable` and `Hashable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public ${decl_keyword} ${Self}<Wrapped> : Equatable, Hashable {
-  public var value: Wrapped
-  public var identity: Int
-
-  public init(_ value: Wrapped) {
-    self.value = value
-    self.identity = 0
-  }
-
-  public init(_ value: Wrapped, identity: Int) {
-    self.value = value
-    self.identity = identity
-  }
-
-  public var hashValue: Int {
-    ${Self}_timesHashValueWasCalled += 1
-    return ${Self}_hashValueImpl.value(value)
-  }
-}
-
-public func == <Wrapped>(
-  lhs: ${Self}<Wrapped>,
-  rhs: ${Self}<Wrapped>
-) -> Bool {
-  ${Self}_timesEqualEqualWasCalled += 1
-  return ${Self}_equalImpl.value(lhs.value, rhs.value)
-}
-
-% end
-
-/// A type that conforms only to `Equatable`, `Comparable`, and `Strideable`.
-///
-/// This type can be used to check that generic functions don't rely on any
-/// other conformances.
-public struct MinimalStrideableValue : Equatable, Comparable, Strideable {
-  public static var timesEqualEqualWasCalled = ResettableValue(0)
-  public static var timesLessWasCalled = ResettableValue(0)
-  public static var timesDistanceWasCalled = ResettableValue(0)
-  public static var timesAdvancedWasCalled = ResettableValue(0)
-
-  public static var equalImpl =
-    ResettableValue<(Int, Int) -> Bool>({ $0 == $1 })
-  public static var lessImpl =
-    ResettableValue<(Int, Int) -> Bool>({ $0 < $1 })
-
-  public var value: Int
-  public var identity: Int
-
-  public init(_ value: Int) {
-    self.value = value
-    self.identity = 0
-  }
-
-  public init(_ value: Int, identity: Int) {
-    self.value = value
-    self.identity = identity
-  }
-
-  public typealias Stride = Int
-
-  public func distance(to other: MinimalStrideableValue) -> Stride {
-    MinimalStrideableValue.timesDistanceWasCalled.value += 1
-    return other.value - self.value
-  }
-
-  public func advanced(by n: Stride) -> MinimalStrideableValue {
-    MinimalStrideableValue.timesAdvancedWasCalled.value += 1
-    return MinimalStrideableValue(self.value + n, identity: self.identity)
-  }
-}
-
-public func == (
-  lhs: MinimalStrideableValue,
-  rhs: MinimalStrideableValue
-) -> Bool {
-  MinimalStrideableValue.timesEqualEqualWasCalled.value += 1
-  return MinimalStrideableValue.equalImpl.value(lhs.value, rhs.value)
-}
-
-public func < (
-  lhs: MinimalStrideableValue,
-  rhs: MinimalStrideableValue
-) -> Bool {
-  MinimalStrideableValue.timesLessWasCalled.value += 1
-  return MinimalStrideableValue.lessImpl.value(lhs.value, rhs.value)
-}
-
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift
similarity index 71%
rename from stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
rename to stdlib/private/StdlibUnittest/StdlibUnittest.swift
index 98ac5af..d8b2922 100644
--- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
+++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift
@@ -1,4 +1,4 @@
-//===--- StdlibUnittest.swift.gyb -----------------------------*- swift -*-===//
+//===----------------------------------------------------------------------===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -10,9 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
 
 import SwiftPrivate
 import SwiftPrivatePthreadExtras
@@ -120,7 +117,11 @@
 /// Run `body` and expect a failure to happen.
 ///
 /// The check passes iff `body` triggers one or more failures.
-public func expectFailure(${TRACE}, invoking body: () -> Void) {
+public func expectFailure(
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line, invoking body: () -> Void) {
   let startAnyExpectFailed = _anyExpectFailed
   _anyExpectFailed = false
   body()
@@ -128,7 +129,7 @@
   _anyExpectFailed = false
   expectTrue(
     endAnyExpectFailed, "running `body` should produce an expected failure",
-    stackTrace: ${stackTrace}
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
   )
   _anyExpectFailed = _anyExpectFailed || startAnyExpectFailed
 }
@@ -146,49 +147,107 @@
   return element
 }
 
-public func expectEqual<T : Equatable>(_ expected: T, _ actual: T, ${TRACE}) {
-  expectEqualTest(expected, actual, ${trace}, showFrame: false) {$0 == $1}
+public func expectEqual<T : Equatable>(_ expected: T, _ actual: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  expectEqualTest(expected, actual, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
 }
 
 public func expectEqual<T : Equatable, U : Equatable>(
-  _ expected: (T, U), _ actual: (T, U), ${TRACE}) {
-  expectEqualTest(expected.0, actual.0, ${trace}, showFrame: false) {$0 == $1}
-  expectEqualTest(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
+  _ expected: (T, U), _ actual: (T, U),
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  expectEqualTest(expected.0, actual.0, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+  expectEqualTest(expected.1, actual.1, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
 }
 
 public func expectEqual<T : Equatable, U : Equatable, V : Equatable>(
-  _ expected: (T, U, V), _ actual: (T, U, V), ${TRACE}) {
-  expectEqualTest(expected.0, actual.0, ${trace}, showFrame: false) {$0 == $1}
-  expectEqualTest(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
-  expectEqualTest(expected.2, actual.2, ${trace}, showFrame: false) {$0 == $1}
+  _ expected: (T, U, V), _ actual: (T, U, V),
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  expectEqualTest(expected.0, actual.0, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+  expectEqualTest(expected.1, actual.1, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+  expectEqualTest(expected.2, actual.2, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
 }
 
 public func expectEqual<T : Equatable, U : Equatable, V : Equatable, W : Equatable>(
-  _ expected: (T, U, V, W), _ actual: (T, U, V, W), ${TRACE}) {
-  expectEqualTest(expected.0, actual.0, ${trace}, showFrame: false) {$0 == $1}
-  expectEqualTest(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
-  expectEqualTest(expected.2, actual.2, ${trace}, showFrame: false) {$0 == $1}
-  expectEqualTest(expected.3, actual.3, ${trace}, showFrame: false) {$0 == $1}
+  _ expected: (T, U, V, W), _ actual: (T, U, V, W),
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  expectEqualTest(expected.0, actual.0, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+  expectEqualTest(expected.1, actual.1, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+  expectEqualTest(expected.2, actual.2, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
+  expectEqualTest(expected.3, actual.3, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
 }
 
-% for (Lhs, Rhs) in [
-%   ('String', 'Substring'),
-%   ('Substring', 'String'),
-%   ('String', 'String'), # this one is to break ambiguity
-% ]:
-public func expectEqual(_ expected: ${Lhs}, _ actual: ${Rhs}, ${TRACE}) {
+public func expectEqual(_ expected: String, _ actual: Substring,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if !(expected == actual) {
     expectationFailure(
       "expected: \(String(reflecting: expected)) (of type \(String(reflecting: type(of: expected))))\n"
       + "actual: \(String(reflecting: actual)) (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace}
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
     )
   }
 }
-% end
+public func expectEqual(_ expected: Substring, _ actual: String,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  if !(expected == actual) {
+    expectationFailure(
+      "expected: \(String(reflecting: expected)) (of type \(String(reflecting: type(of: expected))))\n"
+      + "actual: \(String(reflecting: actual)) (of type \(String(reflecting: type(of: actual))))",
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
+    )
+  }
+}
+public func expectEqual(_ expected: String, _ actual: String,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  if !(expected == actual) {
+    expectationFailure(
+      "expected: \(String(reflecting: expected)) (of type \(String(reflecting: type(of: expected))))\n"
+      + "actual: \(String(reflecting: actual)) (of type \(String(reflecting: type(of: actual))))",
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
+    )
+  }
+}
 
-public func expectEqualReference(_ expected: AnyObject?, _ actual: AnyObject?, ${TRACE}) {
-  expectEqualTest(expected, actual, ${trace}, showFrame: false) {$0 === $1}
+public func expectEqualReference(_ expected: AnyObject?, _ actual: AnyObject?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  expectEqualTest(expected, actual, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 === $1}
 }
 
 public func expectationFailure(
@@ -205,22 +264,32 @@
 // See <rdar://26058520> Generic type constraints incorrectly applied to
 // functions with the same name
 public func expectEqualTest<T>(
-  _ expected: T, _ actual: T, ${TRACE}, sameValue equal: (T, T) -> Bool
+  _ expected: T, _ actual: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line, sameValue equal: (T, T) -> Bool
 ) {
   if !equal(expected, actual) {
     expectationFailure(
       "expected: \(String(reflecting: expected)) (of type \(String(reflecting: type(of: expected))))\n"
       + "actual: \(String(reflecting: actual)) (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace}
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
     )
   }
 }
 
-public func expectNotEqual<T : Equatable>(_ expected: T, _ actual: T, ${TRACE}) {
+public func expectNotEqual<T : Equatable>(_ expected: T, _ actual: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if expected == actual {
     expectationFailure(
       "unexpected value: \"\(actual)\" (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace}
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)
     )
   }
 }
@@ -228,130 +297,296 @@
 // Cannot write a sane set of overloads using generics because of:
 // <rdar://problem/17015923> Array -> NSArray implicit conversion insanity
 public func expectOptionalEqual<T : Equatable>(
-  _ expected: T, _ actual: T?, ${TRACE}
+  _ expected: T, _ actual: T?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
-  expectOptionalEqual(expected, actual, ${trace}, showFrame: false) {$0 == $1}
+  expectOptionalEqual(expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) {$0 == $1}
 }
 
 public func expectOptionalEqual<T>(
-  _ expected: T, _ actual: T?, ${TRACE}, sameValue equal: (T, T) -> Bool
+  _ expected: T, _ actual: T?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line, sameValue equal: (T, T) -> Bool
 ) {
   if (actual == nil) || !equal(expected, actual!) {
     expectationFailure(
       "expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))\n"
       + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace})
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectEqual<T : Equatable>(_ expected: T?, _ actual: T?, ${TRACE}) {
+public func expectEqual<T : Equatable>(_ expected: T?, _ actual: T?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if expected != actual {
     expectationFailure(
       "expected: \"\(expected.debugDescription)\" (of type \(String(reflecting: type(of: expected))))\n"
       + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace})
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
 public func expectNotEqual<T : Equatable>(
-  _ expected: T?, _ actual: T?, ${TRACE}
+  _ expected: T?, _ actual: T?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   if expected == actual {
     expectationFailure(
       "unexpected value: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace})
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
 // Array<T> is not Equatable if T is.  Provide additional overloads.
 // Same for Dictionary.
-%for (Generic, EquatableType) in [
-%    ('<T : Equatable>', 'ContiguousArray<T>'),
-%    ('<T : Equatable>', 'ArraySlice<T>'),
-%    ('<T : Equatable>', 'Array<T>'),
-%    ('<T, U : Equatable>', 'Dictionary<T, U>')]:
 
-public func expectEqual${Generic}(
-  _ expected: ${EquatableType}, _ actual: ${EquatableType}, ${TRACE}
+public func expectEqual<T : Equatable>(
+  _ expected: ContiguousArray<T>, _ actual: ContiguousArray<T>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
-  expectEqualTest(expected, actual, ${trace}, showFrame: false) { $0 == $1 }
+  expectEqualTest(expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
 }
 
-public func expectOptionalEqual${Generic}(
-    _ expected: ${EquatableType}, _ actual: ${EquatableType}?, ${TRACE}) {
+public func expectOptionalEqual<T : Equatable>(
+    _ expected: ContiguousArray<T>, _ actual: ContiguousArray<T>?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if (actual == nil) || expected != actual! {
     expectationFailure(
       "expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))"
       + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace})
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-%end
+
+public func expectEqual<T : Equatable>(
+  _ expected: ArraySlice<T>, _ actual: ArraySlice<T>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
+  expectEqualTest(expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
+}
+
+public func expectOptionalEqual<T : Equatable>(
+    _ expected: ArraySlice<T>, _ actual: ArraySlice<T>?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  if (actual == nil) || expected != actual! {
+    expectationFailure(
+      "expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))"
+      + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  }
+}
+
+
+public func expectEqual<T : Equatable>(
+  _ expected: Array<T>, _ actual: Array<T>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
+  expectEqualTest(expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
+}
+
+public func expectOptionalEqual<T : Equatable>(
+    _ expected: Array<T>, _ actual: Array<T>?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  if (actual == nil) || expected != actual! {
+    expectationFailure(
+      "expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))"
+      + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  }
+}
+
+
+public func expectEqual<T, U : Equatable>(
+  _ expected: Dictionary<T, U>, _ actual: Dictionary<T, U>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
+  expectEqualTest(expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
+}
+
+public func expectOptionalEqual<T, U : Equatable>(
+    _ expected: Dictionary<T, U>, _ actual: Dictionary<T, U>?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  if (actual == nil) || expected != actual! {
+    expectationFailure(
+      "expected: \"\(expected)\" (of type \(String(reflecting: type(of: expected))))"
+      + "actual: \"\(actual.debugDescription)\" (of type \(String(reflecting: type(of: actual))))",
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  }
+}
+
 
 public func expectEqual(
-  _ expected: Any.Type, _ actual: Any.Type, ${TRACE}
+  _ expected: Any.Type, _ actual: Any.Type,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
-  expectEqualTest(expected, actual, ${trace}, showFrame: false) { $0 == $1 }
+  expectEqualTest(expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), showFrame: false) { $0 == $1 }
 }
 
-public func expectLT<T : Comparable>(_ lhs: T, _ rhs: T, ${TRACE}) {
+public func expectLT<T : Comparable>(_ lhs: T, _ rhs: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if !(lhs < rhs) {
-    expectationFailure("\(lhs) < \(rhs)", trace: ${trace})
+    expectationFailure("\(lhs) < \(rhs)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectLE<T : Comparable>(_ lhs: T, _ rhs: T, ${TRACE}) {
+public func expectLE<T : Comparable>(_ lhs: T, _ rhs: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if !(lhs <= rhs) {
-    expectationFailure("\(lhs) <= \(rhs)", trace: ${trace})
+    expectationFailure("\(lhs) <= \(rhs)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectGT<T : Comparable>(_ lhs: T, _ rhs: T, ${TRACE}) {
+public func expectGT<T : Comparable>(_ lhs: T, _ rhs: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if !(lhs > rhs) {
-    expectationFailure("\(lhs) > \(rhs)", trace: ${trace})
+    expectationFailure("\(lhs) > \(rhs)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectGE<T : Comparable>(_ lhs: T, _ rhs: T, ${TRACE}) {
+public func expectGE<T : Comparable>(_ lhs: T, _ rhs: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if !(lhs >= rhs) {
-    expectationFailure("\(lhs) >= \(rhs)", trace: ${trace})
+    expectationFailure("\(lhs) >= \(rhs)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-% for OtherRange in ['Range', 'ClosedRange']:
 extension Range {
-  internal func _contains(_ other: ${OtherRange}<Bound>) -> Bool {
+  internal func _contains(_ other: Range<Bound>) -> Bool {
     if other.lowerBound < lowerBound { return false }
-%   if 'Closed' in OtherRange:
-    if upperBound <= other.upperBound { return false }
-%   else:
     if upperBound < other.upperBound { return false }
-%   end
     return true
   }
 }
-% end
+extension Range {
+  internal func _contains(_ other: ClosedRange<Bound>) -> Bool {
+    if other.lowerBound < lowerBound { return false }
+    if upperBound <= other.upperBound { return false }
+    return true
+  }
+}
 
-% for Range in ['Range', 'ClosedRange']:
 public func expectTrapping<Bound>(
-  _ point: Bound, in range: ${Range}<Bound>, ${TRACE}
+  _ point: Bound, in range: Range<Bound>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   if !range.contains(point) {
-    expectationFailure("\(point) in \(range)", trace: ${trace})
+    expectationFailure("\(point) in \(range)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
     _trappingExpectationFailedCallback()
   }
 }
 
 public func expectTrapping<Bound>(
-  _ subRange: ${Range}<Bound>, in range: Range<Bound>, ${TRACE}
+  _ subRange: Range<Bound>, in range: Range<Bound>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   if !range._contains(subRange) {
-    expectationFailure("\(subRange) in \(range)", trace: ${trace})
+    expectationFailure("\(subRange) in \(range)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
     _trappingExpectationFailedCallback()
   }
 }
-% end
+public func expectTrapping<Bound>(
+  _ point: Bound, in range: ClosedRange<Bound>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
+  if !range.contains(point) {
+    expectationFailure("\(point) in \(range)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+    _trappingExpectationFailedCallback()
+  }
+}
+
+public func expectTrapping<Bound>(
+  _ subRange: ClosedRange<Bound>, in range: Range<Bound>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
+  if !range._contains(subRange) {
+    expectationFailure("\(subRange) in \(range)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+    _trappingExpectationFailedCallback()
+  }
+}
 
 extension ClosedRange {
   internal func _contains(_ other: ClosedRange<Bound>) -> Bool {
@@ -362,10 +597,15 @@
 }
 
 public func expectTrapping<Bound>(
-  _ subRange: ClosedRange<Bound>, in range: ClosedRange<Bound>, ${TRACE}
+  _ subRange: ClosedRange<Bound>, in range: ClosedRange<Bound>,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   if !range._contains(subRange) {
-    expectationFailure("\(subRange) in \(range)", trace: ${trace})
+    expectationFailure("\(subRange) in \(range)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
     _trappingExpectationFailedCallback()
   }
 }
@@ -377,11 +617,12 @@
   return x
 }
 
-% for Mutable in ['', 'Mutable']:
-public func expect${Mutable}CollectionType<X : ${Mutable}Collection>(
+public func expectCollectionType<X : Collection>(
   _ x: X.Type
 ) {}
-% end
+public func expectMutableCollectionType<X : MutableCollection>(
+  _ x: X.Type
+) {}
 
 /// A slice is a `Collection` that when sliced returns an instance of
 /// itself.
@@ -457,43 +698,77 @@
   return AssertionResult(isPass: false)
 }
 
-public func expectUnreachable(${TRACE}) {
-  expectationFailure("this code should not be executed", trace: ${trace})
+public func expectUnreachable(
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
+  expectationFailure("this code should not be executed", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
-public func expectUnreachableCatch(_ error: Error, ${TRACE}) {
+public func expectUnreachableCatch(_ error: Error,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   expectationFailure(
-    "error should not be thrown: \"\(error)\"", trace: ${trace})
+    "error should not be thrown: \"\(error)\"", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
-public func expectTrue(_ actual: AssertionResult, ${TRACE}) {
+public func expectTrue(_ actual: AssertionResult,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if !actual._isPass {
     expectationFailure(
-      "expected: passed assertion\n\(actual.description)", trace: ${trace})
+      "expected: passed assertion\n\(actual.description)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectFalse(_ actual: AssertionResult, ${TRACE}) {
+public func expectFalse(_ actual: AssertionResult,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if actual._isPass {
     expectationFailure(
-      "expected: failed assertion\n\(actual.description)", trace: ${trace})
+      "expected: failed assertion\n\(actual.description)", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectTrue(_ actual: Bool, ${TRACE}) {
+public func expectTrue(_ actual: Bool,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if !actual {
-    expectationFailure("expected: true", trace: ${trace})
+    expectationFailure("expected: true", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectFalse(_ actual: Bool, ${TRACE}) {
+public func expectFalse(_ actual: Bool,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if actual {
-    expectationFailure("expected: false", trace: ${trace})
+    expectationFailure("expected: false", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
 public func expectThrows<ErrorType: Error & Equatable>(
-  _ expectedError: ErrorType? = nil, _ test: () throws -> Void, ${TRACE}) {
+  _ expectedError: ErrorType? = nil, _ test: () throws -> Void,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   do {
     try test()
   } catch let error as ErrorType {
@@ -501,29 +776,45 @@
       expectEqual(expectedError, error)
     }
   } catch {
-    expectationFailure("unexpected error thrown: \"\(error)\"", trace: ${trace})
+    expectationFailure("unexpected error thrown: \"\(error)\"", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectDoesNotThrow(_ test: () throws -> Void, ${TRACE}) {
+public func expectDoesNotThrow(_ test: () throws -> Void,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   do {
     try test()
   } catch {
-    expectationFailure("unexpected error thrown: \"\(error)\"", trace: ${trace})
+    expectationFailure("unexpected error thrown: \"\(error)\"", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-public func expectNil<T>(_ value: T?, ${TRACE}) {
+public func expectNil<T>(_ value: T?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   if value != nil {
     expectationFailure(
-      "expected optional to be nil\nactual: \"\(value!)\"", trace: ${trace})
+      "expected optional to be nil\nactual: \"\(value!)\"", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
 @discardableResult
-public func expectNotNil<T>(_ value: T?, ${TRACE}) -> T? {
+public func expectNotNil<T>(_ value: T?,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) -> T? {
   if value == nil {
-    expectationFailure("expected optional to be non-nil", trace: ${trace})
+    expectationFailure("expected optional to be non-nil", trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
   return value
 }
@@ -1589,7 +1880,7 @@
   case windowsAny(reason: String)
 
   case windowsCygnusAny(reason: String)
-  
+
   case haikuAny(reason: String)
 
   case objCRuntime(/*reason:*/ String)
@@ -1683,7 +1974,7 @@
 
     case .windowsCygnusAny(reason: let reason):
       return "windowsCygnusAny(*, reason: \(reason))"
-      
+
     case .haikuAny(reason: let reason):
       return "haikuAny(*, reason: \(reason))"
 
@@ -1969,7 +2260,7 @@
       default:
         return false
       }
-  
+
     case .haikuAny:
       switch _getRunningOSVersion() {
       case .haiku:
@@ -2009,7 +2300,11 @@
   _ instances: Instances,
   oracle: (Instances.Index, Instances.Index) -> Bool,
   allowBrokenTransitivity: Bool = false,
-  ${TRACE}
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where
   Instances.Iterator.Element : Equatable
 {
@@ -2018,14 +2313,19 @@
     Array(instances),
     oracle: { oracle(indices[$0], indices[$1]) },
     allowBrokenTransitivity: allowBrokenTransitivity,
-    ${trace})
+    message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
 internal func _checkEquatableImpl<Instance : Equatable>(
   _ instances: [Instance],
   oracle: (Int, Int) -> Bool,
   allowBrokenTransitivity: Bool = false,
-  ${TRACE}
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   // For each index (which corresponds to an instance being tested) track the
   // set of equal instances.
@@ -2044,7 +2344,7 @@
       expectEqual(
         predictedXY, oracle(j, i),
         "bad oracle: broken symmetry between indices \(i), \(j)",
-        stackTrace: ${stackTrace})
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
       let isEqualXY = x == y
       expectEqual(
@@ -2054,13 +2354,13 @@
            : "expected not equal, found equal\n") +
         "lhs (at index \(i)): \(String(reflecting: x))\n" +
         "rhs (at index \(j)): \(String(reflecting: y))",
-        stackTrace: ${stackTrace})
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
       // Not-equal is an inverse of equal.
       expectNotEqual(
         isEqualXY, x != y,
         "lhs (at index \(i)): \(String(reflecting: x))\nrhs (at index \(j)): \(String(reflecting: y))",
-        stackTrace: ${stackTrace})
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
       if !allowBrokenTransitivity {
         // Check transitivity of the predicate represented by the oracle.
@@ -2074,7 +2374,7 @@
             expectTrue(
               oracle(j, k),
               "bad oracle: broken transitivity at indices \(i), \(j), \(k)",
-              stackTrace: ${stackTrace})
+              stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
               // No need to check equality between actual values, we will check
               // them with the checks above.
           }
@@ -2088,49 +2388,135 @@
 
 
 public func checkEquatable<T : Equatable>(
-  _ expectedEqual: Bool, _ lhs: T, _ rhs: T, ${TRACE}
+  _ expectedEqual: Bool, _ lhs: T, _ rhs: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   checkEquatable(
     [lhs, rhs],
-    oracle: { expectedEqual || $0 == $1 }, ${trace}, showFrame: false)
+    oracle: { expectedEqual || $0 == $1 }, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    showFrame: false)
+}
+
+internal func hash<H: Hashable>(_ value: H, seed: Int? = nil) -> Int {
+  var hasher = _Hasher()
+  if let seed = seed {
+    hasher.combine(seed)
+  }
+  hasher.combine(value)
+  return hasher.finalize()
+}
+
+/// Test that the elements of `instances` satisfy the semantic requirements of
+/// `Hashable`, using `equalityOracle` to generate equality and hashing
+/// expectations from pairs of positions in `instances`.
+public func checkHashable<Instances: Collection>(
+  _ instances: Instances,
+  equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+  allowBrokenTransitivity: Bool = false,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where Instances.Iterator.Element: Hashable {
+  checkHashable(
+    instances,
+    equalityOracle: equalityOracle,
+    hashEqualityOracle: equalityOracle,
+    allowBrokenTransitivity: allowBrokenTransitivity,
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    showFrame: false)
 }
 
 /// Test that the elements of `instances` satisfy the semantic
 /// requirements of `Hashable`, using `equalityOracle` to generate
-/// equality expectations from pairs of positions in `instances`.
-public func checkHashable<Instances : Collection>(
+/// equality expectations from pairs of positions in `instances`,
+/// and `hashEqualityOracle` to do the same for hashing.
+public func checkHashable<Instances: Collection>(
   _ instances: Instances,
   equalityOracle: (Instances.Index, Instances.Index) -> Bool,
+  hashEqualityOracle: (Instances.Index, Instances.Index) -> Bool,
   allowBrokenTransitivity: Bool = false,
-  ${TRACE}
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where
   Instances.Iterator.Element : Hashable {
-
   checkEquatable(
     instances,
     oracle: equalityOracle,
     allowBrokenTransitivity: allowBrokenTransitivity,
-    ${trace})
+    message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
   for i in instances.indices {
     let x = instances[i]
     for j in instances.indices {
       let y = instances[j]
+      let predicted = hashEqualityOracle(i, j)
+      expectEqual(
+        predicted, hashEqualityOracle(j, i),
+        "bad hash oracle: broken symmetry between indices \(i), \(j)",
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
       if x == y {
+        expectTrue(
+          predicted,
+          """
+          bad hash oracle: equality must imply hash equality
+          lhs (at index \(i)): \(x)
+          rhs (at index \(j)): \(y)
+          """,
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      }
+      if predicted {
+        expectEqual(
+          hash(x), hash(y),
+          """
+          hash(into:) expected to match, found to differ
+          lhs (at index \(i)): \(x)
+          rhs (at index \(j)): \(y)
+          """,
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
         expectEqual(
           x.hashValue, y.hashValue,
-          "lhs (at index \(i)): \(x)\nrhs (at index \(j)): \(y)",
-          stackTrace: ${stackTrace})
+          """
+          hashValue expected to match, found to differ
+          lhs (at index \(i)): \(x)
+          rhs (at index \(j)): \(y)
+          """,
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+      } else {
+        // Try a few different seeds; at least one of them should discriminate
+        // between the hashes. It is extremely unlikely this check will fail
+        // all ten attempts, unless the type's hash encoding is not unique,
+        // or unless the hash equality oracle is wrong.
+        expectTrue(
+          (0..<10).contains { hash(x, seed: $0) != hash(y, seed: $0) },
+          """
+          _hash(into:) expected to differ, found to match
+          lhs (at index \(i)): \(x)
+          rhs (at index \(j)): \(y)
+          """,
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
       }
     }
   }
 }
 
 public func checkHashable<T : Hashable>(
-  expectedEqual: Bool, _ lhs: T, _ rhs: T, ${TRACE}
+  expectedEqual: Bool, _ lhs: T, _ rhs: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   checkHashable(
-    [lhs, rhs], equalityOracle: { expectedEqual || $0 == $1 }, ${trace})
+    [lhs, rhs], equalityOracle: { expectedEqual || $0 == $1 }, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
 public enum ExpectedComparisonResult {
@@ -2194,13 +2580,18 @@
 public func checkComparable<Instances : Collection>(
   _ instances: Instances,
   oracle: (Instances.Index, Instances.Index) -> ExpectedComparisonResult,
-  ${TRACE}
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where
   Instances.Iterator.Element : Comparable {
 
   // Also checks that equality is consistent with comparison and that
   // the oracle obeys the equality laws
-  checkEquatable(instances, oracle: { oracle($0, $1).isEQ() }, ${trace})
+  checkEquatable(instances, oracle: { oracle($0, $1).isEQ() }, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
   for i in instances.indices {
     let x = instances[i]
@@ -2209,23 +2600,23 @@
       x < x,
       "found 'x < x'\n" +
       "at index \(i): \(String(reflecting: x))",
-      stackTrace: ${stackTrace})
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
     expectFalse(
       x > x,
       "found 'x > x'\n" +
       "at index \(i): \(String(reflecting: x))",
-      stackTrace: ${stackTrace})
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
     expectTrue(x <= x,
       "found 'x <= x' to be false\n" +
       "at index \(i): \(String(reflecting: x))",
-      stackTrace: ${stackTrace})
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
     expectTrue(x >= x,
       "found 'x >= x' to be false\n" +
       "at index \(i): \(String(reflecting: x))",
-      stackTrace: ${stackTrace})
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
     for j in instances.indices where i != j {
       let y = instances[j]
@@ -2236,31 +2627,31 @@
         expected.flip(), oracle(j, i),
         "bad oracle: missing antisymmetry: "
         + "(\(String(reflecting: i)), \(String(reflecting: j)))",
-        stackTrace: ${stackTrace})
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
       expectEqual(expected.isLT(), x < y,
         "x < y\n" +
         "lhs (at index \(i)): \(String(reflecting: x))\n" +
         "rhs (at index \(j)): \(String(reflecting: y))",
-        stackTrace: ${stackTrace})
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
       expectEqual(expected.isLE(), x <= y,
         "x <= y\n" +
         "lhs (at index \(i)): \(String(reflecting: x))\n" +
         "rhs (at index \(j)): \(String(reflecting: y))",
-        stackTrace: ${stackTrace})
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
       expectEqual(expected.isGE(), x >= y,
         "x >= y\n" +
         "lhs (at index \(i)): \(String(reflecting: x))\n" +
         "rhs (at index \(j)): \(String(reflecting: y))",
-        stackTrace: ${stackTrace})
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
       expectEqual(expected.isGT(), x > y,
         "x > y\n" +
         "lhs (at index \(i)): \(String(reflecting: x))\n" +
         "rhs (at index \(j)): \(String(reflecting: y))",
-        stackTrace: ${stackTrace})
+          stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
       for k in instances.indices {
         let expected2 = oracle(j, k)
@@ -2269,7 +2660,7 @@
             expected, oracle(i, k),
             "bad oracle: missing transitivity "
             + "(\(String(reflecting: i)), \(String(reflecting: j)), "
-            + "\(String(reflecting: k)))", stackTrace: ${stackTrace})
+            + "\(String(reflecting: k)))", stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
         }
       }
     }
@@ -2277,12 +2668,17 @@
 }
 
 public func checkComparable<T : Comparable>(
-  _ expected: ExpectedComparisonResult, _ lhs: T, _ rhs: T, ${TRACE}
+  _ expected: ExpectedComparisonResult, _ lhs: T, _ rhs: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   checkComparable(
     [lhs, rhs],
     oracle: { [[ .eq, expected], [ expected.flip(), .eq]][$0][$1] },
-    ${trace})
+    message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
 
@@ -2300,7 +2696,11 @@
     (Instances.Index, Instances.Index) -> Strides.Iterator.Element,
   advanceOracle:
     (Instances.Index, Strides.Index) -> Instances.Iterator.Element,
-  ${TRACE}
+
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where
   Instances.Iterator.Element : Strideable,
   Instances.Iterator.Element.Stride == Strides.Iterator.Element {
@@ -2311,7 +2711,8 @@
       let d = distanceOracle($1, $0);
       return d < 0 ? .lt : d == 0 ? .eq : .gt
     },
-    ${trace})
+    message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
   for i in instances.indices {
     let x = instances[i]
@@ -2347,12 +2748,17 @@
   Expected: Sequence,
   Actual: Sequence
 >(
-  _ expected: Expected, _ actual: Actual, ${TRACE}
+  _ expected: Expected, _ actual: Actual,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where
   Expected.Iterator.Element == Actual.Iterator.Element,
   Expected.Iterator.Element : Equatable {
 
-  expectEqualSequence(expected, actual, ${trace}) { $0 == $1 }
+  expectEqualSequence(expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) { $0 == $1 }
 }
 
 public func expectEqualSequence<
@@ -2361,13 +2767,18 @@
   T : Equatable,
   U : Equatable
 >(
-  _ expected: Expected, _ actual: Actual, ${TRACE}
+  _ expected: Expected, _ actual: Actual,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where
   Expected.Iterator.Element == Actual.Iterator.Element,
   Expected.Iterator.Element == (T, U) {
 
   expectEqualSequence(
-    expected, actual, ${trace}) {
+    expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) {
     (lhs: (T, U), rhs: (T, U)) -> Bool in
     lhs.0 == rhs.0 && lhs.1 == rhs.1
   }
@@ -2377,7 +2788,11 @@
   Expected: Sequence,
   Actual: Sequence
 >(
-  _ expected: Expected, _ actual: Actual, ${TRACE},
+  _ expected: Expected, _ actual: Actual,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
   sameValue: (Expected.Iterator.Element, Expected.Iterator.Element) -> Bool
 ) where
   Expected.Iterator.Element == Actual.Iterator.Element {
@@ -2385,7 +2800,8 @@
   if !expected.elementsEqual(actual, by: sameValue) {
     expectationFailure("expected elements: \"\(expected)\"\n"
       + "actual: \"\(actual)\" (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace})
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
@@ -2393,7 +2809,11 @@
   Expected : Sequence,
   Actual : Sequence
 >(
-  _ expected: Expected, _ actual: Actual, ${TRACE},
+  _ expected: Expected, _ actual: Actual,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line,
   compare: @escaping (Expected.Iterator.Element, Expected.Iterator.Element)
     -> ExpectedComparisonResult
 ) where
@@ -2404,44 +2824,61 @@
   let y: [Actual.Iterator.Element] =
     actual.sorted { compare($0, $1).isLT() }
   expectEqualSequence(
-    x, y, ${trace}, sameValue: { compare($0, $1).isEQ() })
+    x, y, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: { compare($0, $1).isEQ() })
 }
 
 public func expectEqualsUnordered<
   Expected : Sequence,
   Actual : Sequence
 >(
-  _ expected: Expected, _ actual: Actual, ${TRACE}
+  _ expected: Expected, _ actual: Actual,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where
   Expected.Iterator.Element == Actual.Iterator.Element,
   Expected.Iterator.Element : Comparable {
 
-  expectEqualsUnordered(expected, actual, ${trace}) {
+  expectEqualsUnordered(expected, actual, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) {
     $0 < $1 ? .lt : $0 == $1 ? .eq : .gt
   }
 }
 
 public func expectEqualsUnordered<T : Comparable>(
-  _ expected: [T], _ actual: [T], ${TRACE}
+  _ expected: [T], _ actual: [T],
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   let x = expected.sorted()
   let y = actual.sorted()
-  expectEqualSequence(x, y, ${trace})
+  expectEqualSequence(x, y, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
 public func expectEqualsUnordered<T : Strideable>(
-  _ expected: Range<T>, _ actual: [T], ${TRACE}
+  _ expected: Range<T>, _ actual: [T],
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where T.Stride: SignedInteger {
   if expected.count != actual.count {
     expectationFailure("expected elements: \"\(expected)\"\n"
       + "actual: \"\(actual)\" (of type \(String(reflecting: type(of: actual))))",
-      trace: ${trace})
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
   for e in actual {
     if !expected.contains(e) {
       expectationFailure("expected elements: \"\(expected)\"\n"
         + "actual: \"\(actual)\" (of type \(String(reflecting: type(of: actual))))",
-        trace: ${trace})
+        trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
     }
   }
 }
@@ -2474,7 +2911,11 @@
   Actual : Sequence,
   T : Comparable
 >(
-  _ expected: Expected, _ actual: Actual, ${TRACE}
+  _ expected: Expected, _ actual: Actual,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) where
   Actual.Iterator.Element == (key: T, value: T),
   Expected.Iterator.Element == (T, T) {
@@ -2493,7 +2934,8 @@
     return lhs.0 == rhs.0 && lhs.1 == rhs.1
   }
 
-  expectEqualSequence(x, y, ${trace}, sameValue: comparePairEquals)
+  expectEqualSequence(x, y, message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line), sameValue: comparePairEquals)
 }
 
 public func expectEqualFunctionsForDomain<ArgumentType, Result : Equatable>(
@@ -2527,7 +2969,11 @@
 }
 
 public func expectEqualUnicodeScalars(
-  _ expected: [UInt32], _ actual: String, ${TRACE}) {
+  _ expected: [UInt32], _ actual: String,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line) {
   let actualUnicodeScalars = Array(
     actual.unicodeScalars.lazy.map { $0.value })
 
@@ -2535,10 +2981,11 @@
     expectationFailure(
       "expected elements: \"\(asHex(expected))\"\n"
       + "actual: \"\(asHex(actualUnicodeScalars))\"",
-      trace: ${trace})
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
-// ${'Local Variables'}:
+// Local Variables:
 // eval: (read-only-mode 1)
 // End:
diff --git a/stdlib/private/StdlibUnittest/StringConvertible.swift.gyb b/stdlib/private/StdlibUnittest/StringConvertible.swift
similarity index 68%
rename from stdlib/private/StdlibUnittest/StringConvertible.swift.gyb
rename to stdlib/private/StdlibUnittest/StringConvertible.swift
index 2ddbfeb..8252ba2 100644
--- a/stdlib/private/StdlibUnittest/StringConvertible.swift.gyb
+++ b/stdlib/private/StdlibUnittest/StringConvertible.swift
@@ -1,4 +1,4 @@
-//===--- StringConvertible.swift.gyb --------------------------*- swift -*-===//
+//===----------------------------------------------------------------------===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -10,9 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
 
 /// A type that has different `CustomStringConvertible` and
 /// `CustomDebugStringConvertible` representations.
@@ -110,43 +107,68 @@
 }
 
 public func expectPrinted<T>(
-  expectedOneOf patterns: [String], _ object: T, ${TRACE}
+  expectedOneOf patterns: [String], _ object: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   let actual = String(describing: object)
   if !patterns.contains(actual) {
     expectationFailure(
       "expected: any of \(String(reflecting: patterns))\n"
       + "actual: \(String(reflecting: actual))",
-      trace: ${trace})
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
 public func expectPrinted<T>(
-  _ expected: String, _ object: T, ${TRACE}
+  _ expected: String, _ object: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
-  expectPrinted(expectedOneOf: [expected], object, ${trace})
+  expectPrinted(expectedOneOf: [expected], object, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
 public func expectDebugPrinted<T>(
-  expectedOneOf patterns: [String], _ object: T, ${TRACE}
+  expectedOneOf patterns: [String], _ object: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
-  expectPrinted(expectedOneOf: patterns, String(reflecting: object), ${trace})
+  expectPrinted(expectedOneOf: patterns, String(reflecting: object), message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
 public func expectDebugPrinted<T>(
-  _ expected: String, _ object: T, ${TRACE}
+  _ expected: String, _ object: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
-  expectDebugPrinted(expectedOneOf: [expected], object, ${trace})
+  expectDebugPrinted(expectedOneOf: [expected], object, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
 public func expectDumped<T>(
-  _ expected: String, _ object: T, ${TRACE}
+  _ expected: String, _ object: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
   var actual = ""
   dump(object, to: &actual)
-  expectEqual(expected, actual, ${trace})
+  expectEqual(expected, actual, message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 
-// ${'Local Variables'}:
+// Local Variables:
 // eval: (read-only-mode 1)
 // End:
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index e1adb72..47724f1 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -137,12 +137,12 @@
 /// tasked with finding the first two days with absences in the session. To
 /// find the indices of the two days in question, follow these steps:
 ///
-/// 1) Call `index(where:)` to find the index of the first element in the
+/// 1) Call `firstIndex(where:)` to find the index of the first element in the
 ///    `absences` array that is greater than zero.
 /// 2) Create a slice of the `absences` array starting after the index found in
 ///    step 1.
-/// 3) Call `index(where:)` again, this time on the slice created in step 2.
-///    Where in some languages you might pass a starting index into an
+/// 3) Call `firstIndex(where:)` again, this time on the slice created in step
+///    2. Where in some languages you might pass a starting index into an
 ///    `indexOf` method to find the second day, in Swift you perform the same
 ///    operation on a slice of the original array.
 /// 4) Print the results using the indices found in steps 1 and 3 on the
@@ -150,9 +150,9 @@
 ///
 /// Here's an implementation of those steps:
 ///
-///     if let i = absences.index(where: { $0 > 0 }) {                      // 1
+///     if let i = absences.firstIndex(where: { $0 > 0 }) {                 // 1
 ///         let absencesAfterFirst = absences[(i + 1)...]                   // 2
-///         if let j = absencesAfterFirst.index(where: { $0 > 0 }) {        // 3
+///         if let j = absencesAfterFirst.firstIndex(where: { $0 > 0 }) {   // 3
 ///             print("The first day with absences had \(absences[i]).")    // 4
 ///             print("The second day with absences had \(absences[j]).")
 ///         }
@@ -293,7 +293,7 @@
 /// You can replace an existing element with a new value by assigning the new
 /// value to the subscript.
 ///
-///     if let i = students.index(of: "Maxime") {
+///     if let i = students.firstIndex(of: "Maxime") {
 ///         students[i] = "Max"
 ///     }
 ///     // ["Ivy", "Jordell", "Liam", "Max", "Shakia"]
@@ -533,7 +533,7 @@
   /// safe to use with `endIndex`. For example:
   ///
   ///     let numbers = [10, 20, 30, 40, 50]
-  ///     if let i = numbers.index(of: 30) {
+  ///     if let i = numbers.firstIndex(of: 30) {
   ///         print(numbers[i ..< numbers.endIndex])
   ///     }
   ///     // Prints "[30, 40, 50]"
@@ -784,7 +784,7 @@
   ///     print(streetsSlice)
   ///     // Prints "["Channing", "Douglas", "Evarts"]"
   ///
-  ///     let i = streetsSlice.index(of: "Evarts")    // 4
+  ///     let i = streetsSlice.firstIndex(of: "Evarts")    // 4
   ///     print(streets[i!])
   ///     // Prints "Evarts"
   ///
@@ -2270,6 +2270,7 @@
 
   @inlinable // FIXME(sil-serialize-all)
   public func _hash(into hasher: inout _Hasher) {
+    hasher.combine(count) // discriminator
     for element in self {
       hasher.combine(element)
     }
diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift
index 77d037c..3665c56 100644
--- a/stdlib/public/core/BidirectionalCollection.swift
+++ b/stdlib/public/core/BidirectionalCollection.swift
@@ -119,7 +119,7 @@
   ///     print(streetsSlice)
   ///     // Prints "["Channing", "Douglas", "Evarts"]"
   ///
-  ///     let index = streetsSlice.index(of: "Evarts")    // 4
+  ///     let index = streetsSlice.firstIndex(of: "Evarts")    // 4
   ///     print(streets[index!])
   ///     // Prints "Evarts"
   ///
diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift
index dcb73ef..6fe098f 100644
--- a/stdlib/public/core/Collection.swift
+++ b/stdlib/public/core/Collection.swift
@@ -161,7 +161,7 @@
 /// that position.
 ///
 ///     let text = "Buffalo buffalo buffalo buffalo."
-///     if let firstSpace = text.index(of: " ") {
+///     if let firstSpace = text.firstIndex(of: " ") {
 ///         print(text[..<firstSpace])
 ///     }
 ///     // Prints "Buffalo"
@@ -226,7 +226,7 @@
 /// You can retrieve the same slice using the string's ranged subscript, which
 /// takes a range expression.
 ///
-///     if let firstSpace = text.index(of: " ") {
+///     if let firstSpace = text.firstIndex(of: " ") {
 ///         print(text[..<firstSpace]
 ///         // Prints "Buffalo"
 ///     }
@@ -373,7 +373,7 @@
   /// safe to use with `endIndex`. For example:
   ///
   ///     let numbers = [10, 20, 30, 40, 50]
-  ///     if let index = numbers.index(of: 30) {
+  ///     if let index = numbers.firstIndex(of: 30) {
   ///         print(numbers[index ..< numbers.endIndex])
   ///     }
   ///     // Prints "[30, 40, 50]"
@@ -439,7 +439,7 @@
   /// original collection. This example searches `streetsSlice` for one of the
   /// strings in the slice, and then uses that index in the original array.
   ///
-  ///     let index = streetsSlice.index(of: "Evarts")!    // 4
+  ///     let index = streetsSlice.firstIndex(of: "Evarts")!    // 4
   ///     print(streets[index])
   ///     // "Evarts"
   ///
@@ -497,7 +497,7 @@
   /// but not including, that index:
   ///
   ///     let numbers = [10, 20, 30, 40, 50, 60]
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers.prefix(upTo: i))
   ///     }
   ///     // Prints "[10, 20, 30]"
@@ -512,7 +512,7 @@
   /// half-open range as the collection's subscript. The subscript notation is
   /// preferred over `prefix(upTo:)`.
   ///
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers[..<i])
   ///     }
   ///     // Prints "[10, 20, 30]"
@@ -532,7 +532,7 @@
   /// that index:
   ///
   ///     let numbers = [10, 20, 30, 40, 50, 60]
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers.suffix(from: i))
   ///     }
   ///     // Prints "[40, 50, 60]"
@@ -547,7 +547,7 @@
   /// from the index as the collection's subscript. The subscript notation is
   /// preferred over `suffix(from:)`.
   ///
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers[i...])
   ///     }
   ///     // Prints "[40, 50, 60]"
@@ -568,7 +568,7 @@
   /// including, that index:
   ///
   ///     let numbers = [10, 20, 30, 40, 50, 60]
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers.prefix(through: i))
   ///     }
   ///     // Prints "[10, 20, 30, 40]"
@@ -577,7 +577,7 @@
   /// closed range as the collection's subscript. The subscript notation is
   /// preferred over `prefix(through:)`.
   ///
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers[...i])
   ///     }
   ///     // Prints "[10, 20, 30, 40]"
@@ -621,8 +621,9 @@
   ///   of the collection.
   var count: Int { get }
   
-  // The following requirement enables dispatching for index(of:) when
+  // The following requirements enable dispatching for firstIndex(of:) when
   // the element type is Equatable.
+
   /// Returns `Optional(Optional(index))` if an element was found
   /// or `Optional(nil)` if an element was determined to be missing;
   /// otherwise, `nil`.
@@ -1067,7 +1068,7 @@
   ///     print(streetsSlice)
   ///     // Prints "["Channing", "Douglas", "Evarts"]"
   ///
-  ///     let index = streetsSlice.index(of: "Evarts")    // 4
+  ///     let index = streetsSlice.firstIndex(of: "Evarts")    // 4
   ///     print(streets[index!])
   ///     // Prints "Evarts"
   ///
@@ -1180,7 +1181,7 @@
   }
 
   // TODO: swift-3-indexing-model - rename the following to _customIndexOfEquatable(element)?
-  /// Customization point for `Collection.index(of:)`.
+  /// Customization point for `Collection.firstIndex(of:)`.
   ///
   /// Define this method if the collection can find an element in less than
   /// O(*n*) by exploiting collection-specific knowledge.
@@ -1189,7 +1190,7 @@
   ///   `Optional(nil)` if the element was not found, or
   ///   `Optional(Optional(index))` if an element was found.
   ///
-  /// - Complexity: O(`count`).
+  /// - Complexity: Hopefully less than O(`count`).
   @inlinable
   public // dispatching
   func _customIndexOfEquatableElement(_: Iterator.Element) -> Index?? {
@@ -1402,7 +1403,7 @@
   /// but not including, that index:
   ///
   ///     let numbers = [10, 20, 30, 40, 50, 60]
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers.prefix(upTo: i))
   ///     }
   ///     // Prints "[10, 20, 30]"
@@ -1417,7 +1418,7 @@
   /// half-open range as the collection's subscript. The subscript notation is
   /// preferred over `prefix(upTo:)`.
   ///
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers[..<i])
   ///     }
   ///     // Prints "[10, 20, 30]"
@@ -1440,7 +1441,7 @@
   /// that index:
   ///
   ///     let numbers = [10, 20, 30, 40, 50, 60]
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers.suffix(from: i))
   ///     }
   ///     // Prints "[40, 50, 60]"
@@ -1455,7 +1456,7 @@
   /// from the index as the collection's subscript. The subscript notation is
   /// preferred over `suffix(from:)`.
   ///
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers[i...])
   ///     }
   ///     // Prints "[40, 50, 60]"
@@ -1479,7 +1480,7 @@
   /// including, that index:
   ///
   ///     let numbers = [10, 20, 30, 40, 50, 60]
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers.prefix(through: i))
   ///     }
   ///     // Prints "[10, 20, 30, 40]"
@@ -1488,7 +1489,7 @@
   /// closed range as the collection's subscript. The subscript notation is
   /// preferred over `prefix(through:)`.
   ///
-  ///     if let i = numbers.index(of: 40) {
+  ///     if let i = numbers.firstIndex(of: 40) {
   ///         print(numbers[...i])
   ///     }
   ///     // Prints "[10, 20, 30, 40]"
diff --git a/stdlib/public/core/CollectionAlgorithms.swift b/stdlib/public/core/CollectionAlgorithms.swift
index b7e7425..484585f 100644
--- a/stdlib/public/core/CollectionAlgorithms.swift
+++ b/stdlib/public/core/CollectionAlgorithms.swift
@@ -31,20 +31,20 @@
 }
 
 //===----------------------------------------------------------------------===//
-// index(of:)/index(where:)
+// firstIndex(of:)/firstIndex(where:)
 //===----------------------------------------------------------------------===//
 
 extension Collection where Element : Equatable {
   /// Returns the first index where the specified value appears in the
   /// collection.
   ///
-  /// After using `index(of:)` to find the position of a particular element in
-  /// a collection, you can use it to access the element by subscripting. This
-  /// example shows how you can modify one of the names in an array of
+  /// After using `firstIndex(of:)` to find the position of a particular element
+  /// in a collection, you can use it to access the element by subscripting.
+  /// This example shows how you can modify one of the names in an array of
   /// students.
   ///
   ///     var students = ["Ben", "Ivy", "Jordell", "Maxime"]
-  ///     if let i = students.index(of: "Maxime") {
+  ///     if let i = students.firstIndex(of: "Maxime") {
   ///         students[i] = "Max"
   ///     }
   ///     print(students)
@@ -54,7 +54,7 @@
   /// - Returns: The first index where `element` is found. If `element` is not
   ///   found in the collection, returns `nil`.
   @inlinable
-  public func index(of element: Element) -> Index? {
+  public func firstIndex(of element: Element) -> Index? {
     if let result = _customIndexOfEquatableElement(element) {
       return result
     }
@@ -68,6 +68,13 @@
     }
     return nil
   }
+  
+  /// Returns the first index where the specified value appears in the
+  /// collection.
+  @inlinable
+  public func index(of _element: Element) -> Index? {
+    return firstIndex(of: _element)
+  }
 }
 
 extension Collection {
@@ -80,7 +87,7 @@
   /// begins with the letter "A":
   ///
   ///     let students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
-  ///     if let i = students.index(where: { $0.hasPrefix("A") }) {
+  ///     if let i = students.firstIndex(where: { $0.hasPrefix("A") }) {
   ///         print("\(students[i]) starts with 'A'!")
   ///     }
   ///     // Prints "Abena starts with 'A'!"
@@ -92,7 +99,7 @@
   ///   `true`. If no elements in the collection satisfy the given predicate,
   ///   returns `nil`.
   @inlinable
-  public func index(
+  public func firstIndex(
     where predicate: (Element) throws -> Bool
   ) rethrows -> Index? {
     var i = self.startIndex
@@ -104,6 +111,15 @@
     }
     return nil
   }
+  
+  /// Returns the first index in which an element of the collection satisfies
+  /// the given predicate.
+  @inlinable
+  public func index(
+    where _predicate: (Element) throws -> Bool
+  ) rethrows -> Index? {
+    return try firstIndex(where: _predicate)
+  }
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/stdlib/public/core/Dictionary.swift b/stdlib/public/core/Dictionary.swift
index ff9e60f..4525f07 100644
--- a/stdlib/public/core/Dictionary.swift
+++ b/stdlib/public/core/Dictionary.swift
@@ -328,11 +328,11 @@
 /// provides, see the `DictionaryLiteral` type for an alternative.
 ///
 /// You can search a dictionary's contents for a particular value using the
-/// `contains(where:)` or `index(where:)` methods supplied by default
+/// `contains(where:)` or `firstIndex(where:)` methods supplied by default
 /// implementation. The following example checks to see if `imagePaths` contains
 /// any paths in the `"/glyphs"` directory:
 ///
-///     let glyphIndex = imagePaths.index { $0.value.hasPrefix("/glyphs") }
+///     let glyphIndex = imagePaths.firstIndex(where: { $0.value.hasPrefix("/glyphs") })
 ///     if let index = glyphIndex {
 ///         print("The '\(imagesPaths[index].key)' image is a glyph.")
 ///     } else {
@@ -668,10 +668,10 @@
   /// this subscript with the resulting value.
   ///
   /// For example, to find the key for a particular value in a dictionary, use
-  /// the `index(where:)` method.
+  /// the `firstIndex(where:)` method.
   ///
   ///     let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
-  ///     if let index = countryCodes.index(where: { $0.value == "Japan" }) {
+  ///     if let index = countryCodes.firstIndex(where: { $0.value == "Japan" }) {
   ///         print(countryCodes[index])
   ///         print("Japan's country code is '\(countryCodes[index].key)'.")
   ///     } else {
diff --git a/stdlib/public/core/ErrorType.swift b/stdlib/public/core/ErrorType.swift
index 8691233..2d9dfd3 100644
--- a/stdlib/public/core/ErrorType.swift
+++ b/stdlib/public/core/ErrorType.swift
@@ -35,7 +35,7 @@
 ///
 ///     enum IntParsingError: Error {
 ///         case overflow
-///         case invalidInput(String)
+///         case invalidInput(Character)
 ///     }
 ///
 /// The `invalidInput` case includes the invalid character as an associated
@@ -48,8 +48,9 @@
 ///     extension Int {
 ///         init(validating input: String) throws {
 ///             // ...
-///             if !_isValid(s) {
-///                 throw IntParsingError.invalidInput(s)
+///             let c = _nextCharacter(from: input)
+///             if !_isValid(c) {
+///                 throw IntParsingError.invalidInput(c)
 ///             }
 ///             // ...
 ///         }
diff --git a/stdlib/public/core/FloatingPoint.swift.gyb b/stdlib/public/core/FloatingPoint.swift.gyb
index 3ccea1d..09e2635 100644
--- a/stdlib/public/core/FloatingPoint.swift.gyb
+++ b/stdlib/public/core/FloatingPoint.swift.gyb
@@ -1225,6 +1225,31 @@
 
   /// The sign for a negative value.
   case minus
+
+  // Explicit declarations of otherwise-synthesized members to make them
+  // @inlinable, promising that we will never change the implementation.
+
+  @inlinable
+  public init?(rawValue: Int) {
+    switch rawValue {
+    case 0: self = .plus
+    case 1: self = .minus
+    default: return nil
+    }
+  }
+
+  @inlinable
+  public var rawValue: Int {
+    switch self {
+    case .plus: return 0
+    case .minus: return 1
+    }
+  }
+
+  @inlinable
+  public static func ==(a: FloatingPointSign, b: FloatingPointSign) -> Bool {
+    return a.rawValue == b.rawValue
+  }
 }
 
 /// The IEEE 754 floating-point classes.
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 8e531d3..5dfa62f 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -625,23 +625,107 @@
   }
 }
 
+// _semantics("optimize.sil.preserve_exclusivity" forces the compiler to
+// generate access markers regardless of the current build settings. This way,
+// user code that accesses keypaths are properly enforced even if the standard
+// library has exclusivity checking internally disabled. The semantic attribute
+// must be consistently applied to both the begin and end unpaired access
+// markers, otherwise the runtime will fail catastrophically and unpredictably.
+// This relies on Swift module serialization occurring before these _semantic
+// function are inlined, since inlining would unpredictably cause the attribute
+// to be dropped.
+//
+// An exclusivity violation will report the caller's stack frame location.
+// Runtime diagnostics will be improved by inlining this function. However, this
+// cannot be marked @transparent because it can't be inlined prior to
+// serialization.
+@inlinable
+@inline(__always)
+@_semantics("optimize.sil.preserve_exclusivity")
+func beginAccessHelper<T>(_ address: Builtin.RawPointer, _ accessRecordPtr: Builtin.RawPointer, _ type: T.Type) {
+  Builtin.beginUnpairedModifyAccess(address, accessRecordPtr, type)
+}
+
+@inlinable
+@inline(__always)
+@_semantics("optimize.sil.preserve_exclusivity")
+func endAccessHelper(_ accessRecordPtr: Builtin.RawPointer) {
+  Builtin.endUnpairedAccess(accessRecordPtr)
+}
+
+@inlinable
+@inline(__always)
+@_semantics("optimize.sil.preserve_exclusivity")
+func instantaneousAccessHelper<T>(_ address: Builtin.RawPointer, _ type: T.Type) {
+  Builtin.performInstantaneousReadAccess(address, T.self)
+}
+
 // A class that maintains ownership of another object while a mutable projection
-// into it is underway.
+// into it is underway. The lifetime of the instance of this class is also used
+// to begin and end exclusive 'modify' access to the projected address.
 @_fixed_layout // FIXME(sil-serialize-all)
 @usableFromInline // FIXME(sil-serialize-all)
-internal final class ClassHolder {
+internal final class ClassHolder<ProjectionType> {
+
+  /// The type of the scratch record passed to the runtime to record
+  /// accesses to guarantee exlcusive access.
+  internal typealias AccessRecord = Builtin.UnsafeValueBuffer
+
   @usableFromInline // FIXME(sil-serialize-all)
-  internal let previous: AnyObject?
+  internal var previous: AnyObject?
   @usableFromInline // FIXME(sil-serialize-all)
-  internal let instance: AnyObject
+  internal var instance: AnyObject
 
   @inlinable // FIXME(sil-serialize-all)
   internal init(previous: AnyObject?, instance: AnyObject) {
     self.previous = previous
     self.instance = instance
   }
+
   @inlinable // FIXME(sil-serialize-all)
-  deinit {}
+  internal final class func _create(
+      previous: AnyObject?,
+      instance: AnyObject,
+      accessingAddress address: UnsafeRawPointer,
+      type: ProjectionType.Type
+  ) -> ClassHolder {
+
+    // Tail allocate the UnsafeValueBuffer used as the AccessRecord.
+    // This avoids a second heap allocation since there is no source-level way to
+    // initialize a Builtin.UnsafeValueBuffer type and thus we cannot have a
+    // stored property of that type.
+    let holder: ClassHolder = Builtin.allocWithTailElems_1(self,
+                                                          1._builtinWordValue,
+                                                          AccessRecord.self)
+
+    // Initialize the ClassHolder's instance variables. This is done via
+    // withUnsafeMutablePointer(to:) because the instance was just allocated with
+    // allocWithTailElems_1 and so we need to make sure to use an initialization
+    // rather than an assignment.
+    withUnsafeMutablePointer(to: &holder.previous) {
+      $0.initialize(to: previous)
+    }
+
+    withUnsafeMutablePointer(to: &holder.instance) {
+      $0.initialize(to: instance)
+    }
+
+    let accessRecordPtr = Builtin.projectTailElems(holder, AccessRecord.self)
+
+    // Begin a 'modify' access to the address. This access is ended in
+    // ClassHolder's deinitializer.
+    beginAccessHelper(address._rawValue, accessRecordPtr, type)
+
+    return holder
+  }
+
+  @inlinable // FIXME(sil-serialize-all)
+  deinit {
+    let accessRecordPtr = Builtin.projectTailElems(self, AccessRecord.self)
+
+    // Ends the access begun in _create().
+    endAccessHelper(accessRecordPtr)
+  }
 }
 
 // A class that triggers writeback to a pointer when destroyed.
@@ -1185,7 +1269,14 @@
       let baseObj = unsafeBitCast(base, to: AnyObject.self)
       let basePtr = UnsafeRawPointer(Builtin.bridgeToRawPointer(baseObj))
       defer { _fixLifetime(baseObj) }
-      return .continue(basePtr.advanced(by: offset)
+
+      let offsetAddress = basePtr.advanced(by: offset)
+
+      // Perform an instaneous record access on the address in order to
+      // ensure that the read will not conflict with an already in-progress
+      // 'modify' access.
+      instantaneousAccessHelper(offsetAddress._rawValue, NewValue.self)
+      return .continue(offsetAddress
         .assumingMemoryBound(to: NewValue.self)
         .pointee)
 
@@ -1244,12 +1335,16 @@
       // AnyObject memory can alias any class reference memory, so we can
       // assume type here
       let object = base.assumingMemoryBound(to: AnyObject.self).pointee
-      // The base ought to be kept alive for the duration of the derived access
-      keepAlive = keepAlive == nil
-        ? object
-        : ClassHolder(previous: keepAlive, instance: object)
-      return UnsafeRawPointer(Builtin.bridgeToRawPointer(object))
+      let offsetAddress = UnsafeRawPointer(Builtin.bridgeToRawPointer(object))
             .advanced(by: offset)
+
+      // Keep the  base alive for the duration of the derived access and also
+      // enforce exclusive access to the address.
+      keepAlive = ClassHolder._create(previous: keepAlive, instance: object,
+                                      accessingAddress: offsetAddress,
+                                      type: NewValue.self)
+
+      return offsetAddress
     
     case .mutatingGetSet(id: _, get: let rawGet, set: let rawSet,
                          argument: let argument):
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index d43bdc8..0b3ada7 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -422,7 +422,7 @@
   ///         i0 != children.endIndex
   ///     {
   ///         let grandChildren = Mirror(reflecting: children[i0].value).children
-  ///         if let i1 = grandChildren.index(where: { $0.label == "two" }) {
+  ///         if let i1 = grandChildren.firstIndex(where: { $0.label == "two" }) {
   ///             let greatGrandChildren =
   ///                 Mirror(reflecting: grandChildren[i1].value).children
   ///             if let i2 = greatGrandChildren.index(
@@ -459,7 +459,7 @@
       let children = Mirror(reflecting: result).children
       let position: Children.Index
       if case let label as String = e {
-        position = children.index { $0.label == label } ?? children.endIndex
+        position = children.firstIndex { $0.label == label } ?? children.endIndex
       }
       else if let offset = e as? Int {
         position = children.index(children.startIndex,
@@ -665,11 +665,11 @@
 /// Some operations that are efficient on a dictionary are slower when using
 /// `DictionaryLiteral`. In particular, to find the value matching a key, you
 /// must search through every element of the collection. The call to
-/// `index(where:)` in the following example must traverse the whole
+/// `firstIndex(where:)` in the following example must traverse the whole
 /// collection to find the element that matches the predicate:
 ///
 ///     let runner = "Marlies Gohr"
-///     if let index = recordTimes.index(where: { $0.0 == runner }) {
+///     if let index = recordTimes.firstIndex(where: { $0.0 == runner }) {
 ///         let time = recordTimes[index].1
 ///         print("\(runner) set a 100m record of \(time) seconds.")
 ///     } else {
diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift
index b55c1c0..dc1f10b 100644
--- a/stdlib/public/core/MutableCollection.swift
+++ b/stdlib/public/core/MutableCollection.swift
@@ -25,7 +25,7 @@
 /// modify one of the names in an array of students.
 ///
 ///     var students = ["Ben", "Ivy", "Jordell", "Maxime"]
-///     if let i = students.index(of: "Maxime") {
+///     if let i = students.firstIndex(of: "Maxime") {
 ///         students[i] = "Max"
 ///     }
 ///     print(students)
@@ -112,7 +112,7 @@
   ///     print(streetsSlice)
   ///     // Prints "["Channing", "Douglas", "Evarts"]"
   ///
-  ///     let index = streetsSlice.index(of: "Evarts")    // 4
+  ///     let index = streetsSlice.firstIndex(of: "Evarts")    // 4
   ///     streets[index!] = "Eustace"
   ///     print(streets[index!])
   ///     // Prints "Eustace"
@@ -211,7 +211,7 @@
   ///     print(streetsSlice)
   ///     // Prints "["Channing", "Douglas", "Evarts"]"
   ///
-  ///     let index = streetsSlice.index(of: "Evarts")    // 4
+  ///     let index = streetsSlice.firstIndex(of: "Evarts")    // 4
   ///     streets[index!] = "Eustace"
   ///     print(streets[index!])
   ///     // Prints "Eustace"
diff --git a/stdlib/public/core/ObjectIdentifier.swift b/stdlib/public/core/ObjectIdentifier.swift
index 903e49f..60c8211 100644
--- a/stdlib/public/core/ObjectIdentifier.swift
+++ b/stdlib/public/core/ObjectIdentifier.swift
@@ -21,8 +21,8 @@
 
   /// Creates an instance that uniquely identifies the given class instance.
   ///
-  /// The following example creates an example class `A` and compares instances
-  /// of the class using their object identifiers and the identical-to
+  /// The following example creates an example class `IntegerRef` and compares
+  /// instances of the class using their object identifiers and the identical-to
   /// operator (`===`):
   ///
   ///     class IntegerRef {
diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift
index 0130e9a..8e9f34e 100644
--- a/stdlib/public/core/RandomAccessCollection.swift
+++ b/stdlib/public/core/RandomAccessCollection.swift
@@ -87,7 +87,7 @@
   ///     print(streetsSlice)
   ///     // Prints "["Channing", "Douglas", "Evarts"]"
   ///
-  ///     let index = streetsSlice.index(of: "Evarts")    // 4
+  ///     let index = streetsSlice.firstIndex(of: "Evarts")    // 4
   ///     print(streets[index!])
   ///     // Prints "Evarts"
   ///
diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift
index 56c227e..4b10690 100644
--- a/stdlib/public/core/Range.swift
+++ b/stdlib/public/core/Range.swift
@@ -814,7 +814,7 @@
   /// of the strings in the slice, and then uses that index in the original
   /// array.
   ///
-  ///     let index = streetsSlice.index(of: "Evarts")    // 4
+  ///     let index = streetsSlice.firstIndex(of: "Evarts")    // 4
   ///     print(streets[index!])
   ///     // "Evarts"
   ///
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift b/stdlib/public/core/RangeReplaceableCollection.swift
index e9531fe..4ad53bd 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift
+++ b/stdlib/public/core/RangeReplaceableCollection.swift
@@ -1097,7 +1097,7 @@
   public mutating func removeAll(
     where predicate: (Element) throws -> Bool
   ) rethrows {
-    if var i = try index(where: predicate) {
+    if var i = try firstIndex(where: predicate) {
       var j = index(after: i)
       while j != endIndex {
         if try !predicate(self[j]) {
diff --git a/stdlib/public/core/Reverse.swift b/stdlib/public/core/Reverse.swift
index 97aa7bf..cddbe41 100644
--- a/stdlib/public/core/Reverse.swift
+++ b/stdlib/public/core/Reverse.swift
@@ -129,7 +129,7 @@
     ///
     ///     func indexOfLastEven(_ numbers: [Int]) -> Int? {
     ///         let reversedNumbers = numbers.reversed()
-    ///         guard let i = reversedNumbers.index(where: { $0 % 2 == 0 })
+    ///         guard let i = reversedNumbers.firstIndex(where: { $0 % 2 == 0 })
     ///             else { return nil }
     ///
     ///         return numbers.index(before: i.base)
@@ -152,7 +152,7 @@
     /// `"a"` character in a string's character view.
     ///
     ///     let name = "Horatio"
-    ///     let aIndex = name.index(of: "a")!
+    ///     let aIndex = name.firstIndex(of: "a")!
     ///     // name[aIndex] == "a"
     ///
     ///     let reversedName = name.reversed()
diff --git a/stdlib/public/core/Set.swift b/stdlib/public/core/Set.swift
index e37f85c..5c956e3 100644
--- a/stdlib/public/core/Set.swift
+++ b/stdlib/public/core/Set.swift
@@ -349,7 +349,7 @@
   ///
   /// - Complexity: O(1)
   @inlinable // FIXME(sil-serialize-all)
-  public func index(of member: Element) -> Index? {
+  public func firstIndex(of member: Element) -> Index? {
     return _variantBuffer.index(forKey: member)
   }
 
@@ -357,7 +357,7 @@
   public func _customIndexOfEquatableElement(
      _ member: Element
     ) -> Index?? {
-    return Optional(index(of: member))
+    return Optional(firstIndex(of: member))
   }
 
   /// The number of elements in the set.
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index 0572d4b..edead79 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -362,7 +362,7 @@
 /// that point:
 ///
 ///     let name = "Marie Curie"
-///     let firstSpace = name.index(of: " ") ?? name.endIndex
+///     let firstSpace = name.firstIndex(of: " ") ?? name.endIndex
 ///     let firstName = name[..<firstSpace]
 ///     // firstName == "Marie"
 ///
@@ -513,7 +513,7 @@
 /// of the string up to that point.
 ///
 ///     let name = "Marie Curie"
-///     let firstSpace = name.index(of: " ") ?? name.endIndex
+///     let firstSpace = name.firstIndex(of: " ") ?? name.endIndex
 ///     let firstName = name[..<firstSpace]
 ///     print(firstName)
 ///     // Prints "Marie"
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index 263bb63..6c5e87c 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -52,7 +52,7 @@
   /// using the `String` type's `init(_:)` initializer.
   ///
   ///     let name = "Marie Curie"
-  ///     if let firstSpace = name.characters.index(of: " ") {
+  ///     if let firstSpace = name.characters.firstIndex(of: " ") {
   ///         let firstName = String(name.characters[..<firstSpace])
   ///         print(firstName)
   ///     }
@@ -121,7 +121,7 @@
   ///     var str = "All this happened, more or less."
   ///     let afterSpace = str.withMutableCharacters {
   ///         chars -> String.CharacterView in
-  ///         if let i = chars.index(of: " ") {
+  ///         if let i = chars.firstIndex(of: " ") {
   ///             let result = chars[chars.index(after: i)...]
   ///             chars.removeSubrange(i...)
   ///             return result
@@ -274,7 +274,7 @@
   /// letter and then prints the character at the found index:
   ///
   ///     let greeting = "Hello, friend!"
-  ///     if let i = greeting.characters.index(where: { "A"..."Z" ~= $0 }) {
+  ///     if let i = greeting.characters.firstIndex(where: { "A"..."Z" ~= $0 }) {
   ///         print("First capital letter: \(greeting.characters[i])")
   ///     }
   ///     // Prints "First capital letter: H"
@@ -361,7 +361,7 @@
   /// not including, the first comma (`","`) in the string.
   ///
   ///     let str = "All this happened, more or less."
-  ///     let i = str.characters.index(of: ",")!
+  ///     let i = str.characters.firstIndex(of: ",")!
   ///     let substring = str.characters[str.characters.startIndex ..< i]
   ///     print(String(substring))
   ///     // Prints "All this happened"
diff --git a/stdlib/public/core/StringIndexConversions.swift b/stdlib/public/core/StringIndexConversions.swift
index abba2a7..15b5a47 100644
--- a/stdlib/public/core/StringIndexConversions.swift
+++ b/stdlib/public/core/StringIndexConversions.swift
@@ -26,7 +26,7 @@
   ///     print(cafe)
   ///     // Prints "Café"
   ///
-  ///     let scalarsIndex = cafe.unicodeScalars.index(of: "e")!
+  ///     let scalarsIndex = cafe.unicodeScalars.firstIndex(of: "e")!
   ///     let stringIndex = String.Index(scalarsIndex, within: cafe)!
   ///
   ///     print(cafe[...stringIndex])
@@ -67,7 +67,7 @@
   /// uses this method find the same position in the string's `utf8` view.
   ///
   ///     let cafe = "Café"
-  ///     if let i = cafe.index(of: "é") {
+  ///     if let i = cafe.firstIndex(of: "é") {
   ///         let j = i.samePosition(in: cafe.utf8)!
   ///         print(Array(cafe.utf8[j...]))
   ///     }
@@ -96,7 +96,7 @@
   /// uses this method find the same position in the string's `utf16` view.
   ///
   ///     let cafe = "Café"
-  ///     if let i = cafe.index(of: "é") {
+  ///     if let i = cafe.firstIndex(of: "é") {
   ///         let j = i.samePosition(in: cafe.utf16)!
   ///         print(cafe.utf16[j])
   ///     }
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift b/stdlib/public/core/StringRangeReplaceableCollection.swift
index 1d6edc2..80e4780 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift
@@ -258,9 +258,9 @@
   /// For example, this code finds the first letter after the first space:
   ///
   ///     let str = "Greetings, friend! How are you?"
-  ///     let firstSpace = str.index(of: " ") ?? str.endIndex
+  ///     let firstSpace = str.firstIndex(of: " ") ?? str.endIndex
   ///     let substr = str[firstSpace...]
-  ///     if let nextCapital = substr.index(where: { $0 >= "A" && $0 <= "Z" }) {
+  ///     if let nextCapital = substr.firstIndex(where: { $0 >= "A" && $0 <= "Z" }) {
   ///         print("Capital after a space: \(str[nextCapital])")
   ///     }
   ///     // Prints "Capital after a space: H"
@@ -436,7 +436,7 @@
   /// removes the hyphen from the middle of a string.
   ///
   ///     var nonempty = "non-empty"
-  ///     if let i = nonempty.index(of: "-") {
+  ///     if let i = nonempty.firstIndex(of: "-") {
   ///         nonempty.remove(at: i)
   ///     }
   ///     print(nonempty)
diff --git a/stdlib/public/core/StringUTF16.swift b/stdlib/public/core/StringUTF16.swift
index 2713ada..e99d7b7 100644
--- a/stdlib/public/core/StringUTF16.swift
+++ b/stdlib/public/core/StringUTF16.swift
@@ -55,7 +55,7 @@
   /// `String` type's `init(_:)` initializer.
   ///
   ///     let favemoji = "My favorite emoji is 🎉"
-  ///     if let i = favemoji.utf16.index(where: { $0 >= 128 }) {
+  ///     if let i = favemoji.utf16.firstIndex(where: { $0 >= 128 }) {
   ///         let asciiPrefix = String(favemoji.utf16[..<i])
   ///         print(asciiPrefix)
   ///     }
@@ -303,7 +303,7 @@
   /// another string's `utf16` view.
   ///
   ///     let picnicGuest = "Deserving porcupine"
-  ///     if let i = picnicGuest.utf16.index(of: 32) {
+  ///     if let i = picnicGuest.utf16.firstIndex(of: 32) {
   ///         let adjective = String(picnicGuest.utf16[..<i])
   ///         print(adjective)
   ///     }
@@ -379,7 +379,7 @@
   ///
   ///     let cafe = "Café 🍵"
   ///
-  ///     let stringIndex = cafe.index(of: "é")!
+  ///     let stringIndex = cafe.firstIndex(of: "é")!
   ///     let utf16Index = String.Index(stringIndex, within: cafe.utf16)!
   ///
   ///     print(cafe.utf16[...utf16Index])
@@ -407,7 +407,7 @@
   /// position in the string's `unicodeScalars` view.
   ///
   ///     let cafe = "Café 🍵"
-  ///     let i = cafe.utf16.index(of: 32)!
+  ///     let i = cafe.utf16.firstIndex(of: 32)!
   ///     let j = i.samePosition(in: cafe.unicodeScalars)!
   ///     print(cafe.unicodeScalars[..<j])
   ///     // Prints "Café"
diff --git a/stdlib/public/core/StringUTF8.swift b/stdlib/public/core/StringUTF8.swift
index b523234..b7db7e3 100644
--- a/stdlib/public/core/StringUTF8.swift
+++ b/stdlib/public/core/StringUTF8.swift
@@ -390,7 +390,7 @@
   /// another string's `utf8` view.
   ///
   ///     let picnicGuest = "Deserving porcupine"
-  ///     if let i = picnicGuest.utf8.index(of: 32) {
+  ///     if let i = picnicGuest.utf8.firstIndex(of: 32) {
   ///         let adjective = String(picnicGuest.utf8[..<i])
   ///         print(adjective)
   ///     }
@@ -583,7 +583,7 @@
   ///
   ///     let cafe = "Café 🍵"
   ///
-  ///     let utf16Index = cafe.utf16.index(of: 32)!
+  ///     let utf16Index = cafe.utf16.firstIndex(of: 32)!
   ///     let utf8Index = String.UTF8View.Index(utf16Index, within: cafe.utf8)!
   ///
   ///     print(Array(cafe.utf8[..<utf8Index]))
diff --git a/stdlib/public/core/StringUnicodeScalarView.swift b/stdlib/public/core/StringUnicodeScalarView.swift
index 10e6d37..18c7e52 100644
--- a/stdlib/public/core/StringUnicodeScalarView.swift
+++ b/stdlib/public/core/StringUnicodeScalarView.swift
@@ -52,7 +52,7 @@
   /// using the `String` type's `init(_:)` initializer.
   ///
   ///     let favemoji = "My favorite emoji is 🎉"
-  ///     if let i = favemoji.unicodeScalars.index(where: { $0.value >= 128 }) {
+  ///     if let i = favemoji.unicodeScalars.firstIndex(where: { $0.value >= 128 }) {
   ///         let asciiPrefix = String(favemoji.unicodeScalars[..<i])
   ///         print(asciiPrefix)
   ///     }
@@ -156,7 +156,7 @@
     /// at the found index:
     ///
     ///     let greeting = "Hello, friend!"
-    ///     if let i = greeting.unicodeScalars.index(where: { "A"..."Z" ~= $0 }) {
+    ///     if let i = greeting.unicodeScalars.firstIndex(where: { "A"..."Z" ~= $0 }) {
     ///         print("First capital letter: \(greeting.unicodeScalars[i])")
     ///         print("Unicode scalar value: \(greeting.unicodeScalars[i].value)")
     ///     }
@@ -277,7 +277,7 @@
   /// another string's `unicodeScalars` view.
   ///
   ///     let picnicGuest = "Deserving porcupine"
-  ///     if let i = picnicGuest.unicodeScalars.index(of: " ") {
+  ///     if let i = picnicGuest.unicodeScalars.firstIndex(of: " ") {
   ///         let adjective = String(picnicGuest.unicodeScalars[..<i])
   ///         print(adjective)
   ///     }
@@ -474,7 +474,7 @@
   ///
   ///     let cafe = "Café 🍵"
   ///
-  ///     let utf16Index = cafe.utf16.index(of: 32)!
+  ///     let utf16Index = cafe.utf16.firstIndex(of: 32)!
   ///     let scalarIndex = String.Index(utf16Index, within: cafe.unicodeScalars)!
   ///
   ///     print(String(cafe.unicodeScalars[..<scalarIndex]))
@@ -507,7 +507,7 @@
   /// in the string.
   ///
   ///     let cafe = "Café 🍵"
-  ///     let i = cafe.unicodeScalars.index(of: "🍵")
+  ///     let i = cafe.unicodeScalars.firstIndex(of: "🍵")
   ///     let j = i.samePosition(in: cafe)!
   ///     print(cafe[j...])
   ///     // Prints "🍵"
@@ -625,7 +625,7 @@
   /// to, but not including, the first comma (`","`) in the string.
   ///
   ///     let str = "All this happened, more or less."
-  ///     let i = str.unicodeScalars.index(of: ",")!
+  ///     let i = str.unicodeScalars.firstIndex(of: ",")!
   ///     let substring = str.unicodeScalars[str.unicodeScalars.startIndex ..< i]
   ///     print(String(substring))
   ///     // Prints "All this happened"
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 2bb2f06..b619c94 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -37,7 +37,7 @@
 /// substring of the first sentence:
 ///
 ///     let greeting = "Hi there! It's nice to meet you! 👋"
-///     let endOfSentence = greeting.index(of: "!")!
+///     let endOfSentence = greeting.firstIndex(of: "!")!
 ///     let firstSentence = greeting[...endOfSentence]
 ///     // firstSentence == "Hi there!"
 ///
diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
index bc4fe72..d5fa9a6 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -295,7 +295,7 @@
   ///         let streetSlice = buffer[2..<buffer.endIndex]
   ///         print(Array(streetSlice))
   ///         // Prints "["Channing", "Douglas", "Evarts"]"
-  ///         let index = streetSlice.index(of: "Evarts")    // 4
+  ///         let index = streetSlice.firstIndex(of: "Evarts")    // 4
   ///         buffer[index!] = "Eustace"
   ///     }
   ///     print(streets.last!)
@@ -306,7 +306,7 @@
   ///         let streetSlice = buffer[2..<buffer.endIndex]
   ///         print(Array(streetSlice))
   ///         // Prints "["Channing", "Douglas", "Evarts"]"
-  ///         let index = streetSlice.index(of: "Evarts")    // 4
+  ///         let index = streetSlice.firstIndex(of: "Evarts")    // 4
   ///         print(buffer[index!])
   ///         // Prints "Evarts"
   ///     }
diff --git a/stdlib/public/runtime/Exclusivity.cpp b/stdlib/public/runtime/Exclusivity.cpp
index 0c7dc3e..c578e82 100644
--- a/stdlib/public/runtime/Exclusivity.cpp
+++ b/stdlib/public/runtime/Exclusivity.cpp
@@ -260,6 +260,16 @@
 
     swift_runtime_unreachable("access not found in set");
   }
+
+#ifndef NDEBUG
+  /// Only available with asserts. Intended to be used with
+  /// swift_dumpTrackedAccess().
+  void forEach(std::function<void (Access *)> action) {
+    for (auto *iter = Head; iter != nullptr; iter = iter->getNext()) {
+      action(iter);
+    }
+  }
+#endif
 };
 
 } // end anonymous namespace
@@ -348,3 +358,17 @@
 
   getAccessSet().remove(access);
 }
+
+#ifndef NDEBUG
+
+// Dump the accesses that are currently being tracked by the runtime.
+//
+// This is only intended to be used in the debugger.
+void swift::swift_dumpTrackedAccesses() {
+  getAccessSet().forEach([](Access *a) {
+      fprintf(stderr, "Access. Pointer: %p. PC: %p. AccessAction: %s",
+              a->Pointer, a->PC, getAccessName(a->getAccessAction()));
+  });
+}
+
+#endif
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index 4bedefe..227399e 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -263,7 +263,8 @@
 }
 
 static const TypeContextDescriptor *
-_findNominalTypeDescriptor(Demangle::NodePointer node) {
+_findNominalTypeDescriptor(Demangle::NodePointer node,
+                           Demangle::Demangler &Dem) {
   const TypeContextDescriptor *foundNominal = nullptr;
   auto &T = TypeMetadataRecords.get();
 
@@ -275,7 +276,13 @@
     return cast<TypeContextDescriptor>(
       (const ContextDescriptor *)symbolicNode->getIndex());
 
-  auto mangledName = Demangle::mangleNode(node);
+  auto mangledName =
+    Demangle::mangleNode(node,
+                         [&](const void *context) -> NodePointer {
+                           return _buildDemanglingForContext(
+                               (const ContextDescriptor *) context,
+                               {}, false, Dem);
+                         });
 
   // Look for an existing entry.
   // Find the bucket for the metadata entry.
@@ -696,7 +703,7 @@
 #endif
 
     // Look for a nominal type descriptor based on its mangled name.
-    return _findNominalTypeDescriptor(node);
+    return _findNominalTypeDescriptor(node, demangler);
   }
 
   BuiltProtocolDecl createProtocolDecl(
diff --git a/test/ClangImporter/objc_parse.swift b/test/ClangImporter/objc_parse.swift
index 16f2d2d..cd1a7cb 100644
--- a/test/ClangImporter/objc_parse.swift
+++ b/test/ClangImporter/objc_parse.swift
@@ -509,8 +509,7 @@
 }
 
 class IncompleteProtocolAdopter : Incomplete, IncompleteOptional { // expected-error {{type 'IncompleteProtocolAdopter' cannot conform to protocol 'Incomplete' because it has requirements that cannot be satisfied}}
-      // expected-error@-1{{type 'IncompleteProtocolAdopter' does not conform to protocol 'Incomplete'}}
-  @objc func getObject() -> AnyObject { return self } // expected-note{{candidate has non-matching type '() -> AnyObject'}}
+  @objc func getObject() -> AnyObject { return self }
 }
 
 func testNullarySelectorPieces(_ obj: AnyObject) {
diff --git a/test/Compatibility/exhaustive_switch.swift b/test/Compatibility/exhaustive_switch.swift
index a3d3e57..8accf91 100644
--- a/test/Compatibility/exhaustive_switch.swift
+++ b/test/Compatibility/exhaustive_switch.swift
@@ -1,5 +1,5 @@
-// RUN: %target-typecheck-verify-swift -swift-version 3 -enable-resilience -enable-nonfrozen-enum-exhaustivity-diagnostics
-// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-resilience -enable-nonfrozen-enum-exhaustivity-diagnostics
+// RUN: %target-typecheck-verify-swift -swift-version 3 -enable-resilience
+// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-resilience
 
 func foo(a: Int?, b: Int?) -> Int {
   switch (a, b) {
@@ -543,7 +543,7 @@
   }
 
   // Make sure we haven't just stopped emitting diagnostics.
-  switch OverlyLargeSpaceEnum.case1 { // expected-error {{switch must be exhaustive}} expected-note 12 {{add missing case}} expected-note {{handle unknown values}}
+  switch OverlyLargeSpaceEnum.case1 { // expected-error {{switch must be exhaustive}} expected-note 12 {{add missing case}}
   }
 }
 
@@ -840,11 +840,11 @@
 // case.
 @inlinable
 public func testNonExhaustive(_ value: NonExhaustive, _ payload: NonExhaustivePayload, for interval: TemporalProxy, flag: Bool) {
-  switch value { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b'}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{none}}
+  switch value { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b'}} {{none}}
   case .a: break
   }
 
-  switch value { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
+  switch value { // no-warning
   case .a: break
   case .b: break
   }
@@ -876,7 +876,7 @@
   }
 
   // Test being part of other spaces.
-  switch value as Optional { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.some(_)'}}
+  switch value as Optional { // no-warning
   case .a?: break
   case .b?: break
   case nil: break
@@ -894,7 +894,7 @@
   @unknown case _: break
   } // no-warning
 
-  switch (value, flag) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, false)'}}
+  switch (value, flag) { // no-warning
   case (.a, _): break
   case (.b, false): break
   case (_, true): break
@@ -907,7 +907,7 @@
   @unknown case _: break
   } // no-warning
 
-  switch (flag, value) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(false, _)'}}
+  switch (flag, value) { // no-warning
   case (_, .a): break
   case (false, .b): break
   case (true, _): break
@@ -920,7 +920,7 @@
   @unknown case _: break
   } // no-warning
 
-  switch (value, value) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, _)'}}
+  switch (value, value) { // no-warning
   case (.a, _), (_, .a): break
   case (.b, _), (_, .b): break
   }
@@ -932,21 +932,13 @@
   } // no-warning
 
   // Test interaction with @_downgrade_exhaustivity_check.
-  switch (value, interval) { // expected-warning {{switch must be exhaustive}} {{none}}
-  // expected-note@-1 {{add missing case: '(_, .milliseconds(_))'}}
-  // expected-note@-2 {{add missing case: '(_, .microseconds(_))'}}
-  // expected-note@-3 {{add missing case: '(_, .nanoseconds(_))'}}
-  // expected-note@-4 {{add missing case: '(_, .never)'}}
+  switch (value, interval) { // no-warning
   case (_, .seconds): break
   case (.a, _): break
   case (.b, _): break
   }
 
-  switch (value, interval) { // expected-warning {{switch must be exhaustive}} {{none}}
-  // expected-note@-1 {{add missing case: '(_, .seconds(_))'}}
-  // expected-note@-2 {{add missing case: '(_, .milliseconds(_))'}}
-  // expected-note@-3 {{add missing case: '(_, .microseconds(_))'}}
-  // expected-note@-4 {{add missing case: '(_, .nanoseconds(_))'}}
+  switch (value, interval) { // no-warning
   case (_, .never): break
   case (.a, _): break
   case (.b, _): break
@@ -954,11 +946,11 @@
 
 
   // Test payloaded enums.
-  switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b(_)'}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{none}}
+  switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b(_)'}} {{none}}
   case .a: break
   }
 
-  switch payload { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
+  switch payload { // no-warning
   case .a: break
   case .b: break
   }
@@ -980,7 +972,7 @@
   @unknown case _: break
   }
 
-  switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b(true)'}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{none}}
+  switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.b(true)'}} {{none}}
   case .a: break
   case .b(false): break
   }
diff --git a/test/Compatibility/ownership_protocol.swift b/test/Compatibility/ownership_protocol.swift
index 4fbfa6c..c8f62b7 100644
--- a/test/Compatibility/ownership_protocol.swift
+++ b/test/Compatibility/ownership_protocol.swift
@@ -4,9 +4,15 @@
 class SomeClass {}
 
 protocol P {
-  weak var foo: SomeClass? { get set } // expected-warning {{'weak' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
-  unowned var foo2: SomeClass { get set } // expected-warning {{'unowned' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
-  weak var foo3: Int? { get set } // expected-error {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}}
-  unowned var foo4: Int { get set } // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
+  // expected-warning@+1 {{'weak' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
+  weak var foo: SomeClass? { get set }
+  // expected-warning@+1 {{'unowned' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
+  unowned var foo2: SomeClass { get set }
+  // expected-warning@+2 {{'weak' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
+  // expected-error@+1 {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}}
+  weak var foo3: Int? { get set }
+  // expected-warning@+2 {{'unowned' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
+  // expected-error@+1 {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
+  unowned var foo4: Int { get set }
 }
 
diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift
index b6af7f8..752e33a 100644
--- a/test/Constraints/members.swift
+++ b/test/Constraints/members.swift
@@ -463,3 +463,6 @@
     }
   }
 }
+
+// rdar://problem/39514009 - don't crash when trying to diagnose members with special names
+print("hello")[0] // expected-error {{value of tuple type '()' has no member 'subscript'}}
diff --git a/test/Driver/batch_mode_with_WMO_or_index.swift b/test/Driver/batch_mode_with_WMO_or_index.swift
index 2c2462a..92ec9e9 100644
--- a/test/Driver/batch_mode_with_WMO_or_index.swift
+++ b/test/Driver/batch_mode_with_WMO_or_index.swift
@@ -13,6 +13,18 @@
 // RUN: %FileCheck -check-prefix CHECK-INDEX %s <%t/stderr_batch_index
 // CHECK-INDEX: warning: ignoring '-enable-batch-mode' because '-index-file' was also specified
 //
+// The following test is verifying that -disable-batch-mode overrides an earlier
+// -enable-batch-mode and silences the warning about mixing batch mode with
+// -index-file. Tools that take an existing command line and add -index-file can
+// thus add -disable-batch-mode without having to otherwise interpret the
+// arguments.
+//
+// RUN: %swiftc_driver -disable-batch-mode -index-file  %S/../Inputs/empty.swift -### 2>%t/stderr_nobatch_index | %FileCheck %s
+// RUN: %swiftc_driver -enable-batch-mode -index-file  %S/../Inputs/empty.swift -disable-batch-mode -### 2>%t/stderr_batch_nobatch_index | %FileCheck %s
+// RUN: %FileCheck -allow-empty -check-prefix CHECK-INDEX-DISABLED %s <%t/stderr_nobatch_index
+// RUN: %FileCheck -allow-empty -check-prefix CHECK-INDEX-DISABLED %s <%t/stderr_batch_nobatch_index
+// CHECK-INDEX-DISABLED-NOT: warning
+//
 // This next one is a regression test for a specific failure in the past: wmo +
 // batch mode should not just result in wmo, but also preserve the num-threads
 // argument and (crucially) the resulting fact that the single wmo subprocess
diff --git a/test/Driver/createCompilerInvocation.swift b/test/Driver/createCompilerInvocation.swift
index 5dc6fcb..0151cd7 100644
--- a/test/Driver/createCompilerInvocation.swift
+++ b/test/Driver/createCompilerInvocation.swift
@@ -3,5 +3,7 @@
 // RUN: %swift-ide-test_plain -test-createCompilerInvocation -c %s %S/Input/main.swift %S/Input/lib.swift -module-name createCompilerInvocation -emit-module -emit-objc-header 2>&1
 // RUN: not %swift-ide-test_plain -test-createCompilerInvocation -typecheck %s -emit-module-path %t.swiftmodule 2>&1 | %FileCheck --check-prefix=CHECK-FAIL %s
 // RUN: not %swift-ide-test_plain -test-createCompilerInvocation -v 2>&1 | %FileCheck --check-prefix=CHECK-FAIL %s
+// RUN: %swift-ide-test_plain -test-createCompilerInvocation %s -enable-batch-mode 2>&1 | %FileCheck -allow-empty -check-prefix=CHECK-NOWARN %s
 
 // CHECK-FAIL: error: unable to create a CompilerInvocation
+// CHECK-NOWARN-NOT: warning
diff --git a/test/Driver/options.swift b/test/Driver/options.swift
index e9807c4..91d5d4c 100644
--- a/test/Driver/options.swift
+++ b/test/Driver/options.swift
@@ -129,3 +129,7 @@
 // RUN: %swiftc_driver -driver-print-jobs -assume-single-threaded %s | %FileCheck -check-prefix=ASSUME_SINGLE_THREADED %s
 // ASSUME_SINGLE_THREADED: swift
 // ASSUME_SINGLE_THREADED: -frontend {{.*}} -assume-single-threaded
+
+// RUN: not %swiftc_driver -incremental -autolink-force-load %s 2>&1 | %FileCheck -check-prefix=AUTOLINK_FORCE_LOAD %s
+// RUN: not %swiftc_driver -autolink-force-load -incremental %s 2>&1 | %FileCheck -check-prefix=AUTOLINK_FORCE_LOAD %s
+// AUTOLINK_FORCE_LOAD: error: '-autolink-force-load' is not supported with '-incremental'
diff --git a/test/IDE/complete_from_stdlib.swift b/test/IDE/complete_from_stdlib.swift
index 561fbde..ecaea90 100644
--- a/test/IDE/complete_from_stdlib.swift
+++ b/test/IDE/complete_from_stdlib.swift
@@ -93,7 +93,7 @@
 // PRIVATE_NOMINAL_MEMBERS_2A: Begin completions
 // PRIVATE_NOMINAL_MEMBERS_2A-DAG: map({#(transform): (C.Element) throws -> T##(C.Element) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
 // PRIVATE_NOMINAL_MEMBERS_2A: End completions
-// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2A-NOT: Decl{{.*}}: last
+// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2A-NOT: Decl{{.*}}: index({#before: Comparable#})
 
 func protocolExtCollection1b(_ a: Collection) {
   a.#^PRIVATE_NOMINAL_MEMBERS_2B^#
@@ -102,7 +102,7 @@
 // PRIVATE_NOMINAL_MEMBERS_2B: Begin completions
 // PRIVATE_NOMINAL_MEMBERS_2B-DAG: map({#(transform): (Collection.Element) throws -> T##(Collection.Element) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
 // PRIVATE_NOMINAL_MEMBERS_2B: End completions
-// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2B-NOT: Decl{{.*}}: last
+// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2B-NOT: Decl{{.*}}: index({#before: Comparable#})
 
 func protocolExtCollection2<C : Collection where C.Index : BidirectionalIndex>(_ a: C) {
   a.#^PRIVATE_NOMINAL_MEMBERS_3^#
@@ -111,9 +111,9 @@
 // PRIVATE_NOMINAL_MEMBERS_3: Begin completions
 // PRIVATE_NOMINAL_MEMBERS_3-DAG: Decl[InstanceMethod]/Super:         map({#(transform): (C.Element) throws -> T##(C.Element) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
 // PRIVATE_NOMINAL_MEMBERS_3-DAG: Decl[InstanceVar]/Super:            lazy[#LazySequence<Collection>#]{{; name=.+}}
-// PRIVATE_NOMINAL_MEMBERS_3-DAG: index({#where: (C.Element) throws -> Bool##(C.Element) throws -> Bool#})[' rethrows'][#Comparable?#]{{; name=.+}}
+// PRIVATE_NOMINAL_MEMBERS_3-DAG: firstIndex({#where: (C.Element) throws -> Bool##(C.Element) throws -> Bool#})[' rethrows'][#Comparable?#]{{; name=.+}}
 // PRIVATE_NOMINAL_MEMBERS_3: End completions
-// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_3-NOT: Decl{{.*}}:         index({#({{.*}}): Self.Iterator.Element
+// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_3-NOT: Decl{{.*}}:         firstIndex({#({{.*}}): Self.Iterator.Element
 
 func protocolExtArray<T : Equatable>(_ a: [T]) {
   a.#^PRIVATE_NOMINAL_MEMBERS_4^#
@@ -121,8 +121,8 @@
 // PRIVATE_NOMINAL_MEMBERS_4: Begin completions
 // PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super:         map({#(transform): (Equatable) throws -> T##(Equatable) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
 // PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceVar]/Super:            last[#Equatable?#]{{; name=.+}}
-// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super:         index({#of: Equatable#})[#Int?#]{{; name=.+}}
-// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super:         index({#where: (Equatable) throws -> Bool##(Equatable) throws -> Bool#})[' rethrows'][#Int?#]{{; name=.+}}
+// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super:         firstIndex({#of: Equatable#})[#Int?#]{{; name=.+}}
+// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super:         firstIndex({#where: (Equatable) throws -> Bool##(Equatable) throws -> Bool#})[' rethrows'][#Int?#]{{; name=.+}}
 // PRIVATE_NOMINAL_MEMBERS_4: End completions
 
 func testArchetypeReplacement1<FOO : Equatable>(_ a: [FOO]) {
diff --git a/test/IRGen/big_types_corner_cases.swift b/test/IRGen/big_types_corner_cases.swift
index 2cce0b7..d716d41 100644
--- a/test/IRGen/big_types_corner_cases.swift
+++ b/test/IRGen/big_types_corner_cases.swift
@@ -208,7 +208,7 @@
 // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$SSayy22big_types_corner_cases9BigStructVcSgGMa"
 // CHECK: [[CALL1:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
 // CHECK: [[CALL2:%.*]] = call i8** @"$SSayy22big_types_corner_cases9BigStructVcSgGSayxGs10CollectionsWl
-// CHECK: call swiftcc void @"$Ss10CollectionPsE5index5where5IndexQzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret {{.*}}, i8* bitcast (i1 (%T22big_types_corner_cases9BigStructVytIegnr_Sg*, %swift.refcounted*, %swift.error**)* @"$S22big_types_corner_cases9BigStructVIegy_SgSbs5Error_pIggdzo_ACytIegnr_SgSbsAE_pIegndzo_TRTA" to i8*), %swift.opaque* {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself
+// CHECK: call swiftcc void @"$Ss10CollectionPsE10firstIndex5where0C0QzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret {{.*}}, i8* bitcast (i1 (%T22big_types_corner_cases9BigStructVytIegnr_Sg*, %swift.refcounted*, %swift.error**)* @"$S22big_types_corner_cases9BigStructVIegy_SgSbs5Error_pIggdzo_ACytIegnr_SgSbsAE_pIegndzo_TRTA" to i8*), %swift.opaque* {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself
 // CHECK: ret void
 
 // CHECK-LABEL: define{{( protected)?}} hidden swiftcc void @"$S22big_types_corner_cases7TestBigC5test2yyF"(%T22big_types_corner_cases7TestBigC* swiftself)
@@ -222,7 +222,7 @@
 
     func test() {
         let arr = [Handler?]()
-        let d = arr.index(where: { _ in true })
+        let d = arr.firstIndex(where: { _ in true })
     }
     
     func test2() {
diff --git a/test/IRGen/coverage.swift b/test/IRGen/coverage.swift
deleted file mode 100644
index aaac44a..0000000
--- a/test/IRGen/coverage.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -profile-generate -profile-coverage-mapping -emit-sil -o - | %FileCheck %s --check-prefix=SIL
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -profile-generate -profile-coverage-mapping -emit-ir -o - | %FileCheck %s --check-prefix=IR
-
-// IR-NOT: __llvm_coverage_names
-// IR-NOT: __profn
-
-// SIL-DAG: sil hidden @$S8coverage2f1yyF
-// SIL-DAG: string_literal utf8 "{{.*}}coverage.swift:{{.*}}$S8coverage2f1yyF"
-internal func f1() {}
-
-// SIL-DAG: sil private @$S8coverage2f233_[[F2HASH:[_a-zA-Z0-9]+]]
-// SIL-DAG: string_literal utf8 "{{.*}}coverage.swift:$S8coverage2f233_[[F2HASH]]"
-private func f2() {}
-
-// SIL-DAG: sil @$S8coverage2f3yyF
-// SIL-DAG: string_literal utf8 "$S8coverage2f3yyF"
-public func f3() {
-  f1();
-  f2();
-}
diff --git a/test/IRGen/outlined_copy_addr.swift b/test/IRGen/outlined_copy_addr.swift
index b68a57b..63f2356 100644
--- a/test/IRGen/outlined_copy_addr.swift
+++ b/test/IRGen/outlined_copy_addr.swift
@@ -37,7 +37,7 @@
   var otherHelper: OtherInternal<T>? = nil
 
   // CHECK-LABEL: define hidden swiftcc {{i32|i64}} @"$S11outcopyaddr9MyPrivateVyACyxGxcfC"(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.P) {{.*}} {
-  // CHECK: call %T11outcopyaddr9MyPrivateV* @"$S11outcopyaddr9MyPrivateVyxGAA1PRzlWOh"(%T11outcopyaddr9MyPrivateV* %self)
+  // CHECK: call %T11outcopyaddr9MyPrivateV* @"$S11outcopyaddr9MyPrivateVyxGAA1PRzlWOh"(%T11outcopyaddr9MyPrivateV* {{%.*}})
   // CHECK: ret
   init(_: T) { }
 }
diff --git a/test/IRGen/preserve_exclusivity.swift b/test/IRGen/preserve_exclusivity.swift
new file mode 100644
index 0000000..119eea3
--- /dev/null
+++ b/test/IRGen/preserve_exclusivity.swift
@@ -0,0 +1,136 @@
+// RUN: %target-swift-frontend -parse-stdlib -emit-ir -Onone %s | %FileCheck --check-prefix=IR-Onone %s
+//
+// Check that access markers in @_semantics("optimize.sil.preserve_exclusivity") functions generate runtime calls.
+
+// RUN: %target-swift-frontend -parse-stdlib -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=GenericSpecializer -emit-ir -O %s | %FileCheck --check-prefix=IR-O %s
+//
+// Check that the -O pipeline preserves the runtime calls for @_semantics("optimize.sil.preserve_exclusivity") functions.
+
+@_silgen_name("marker1")
+func marker1() -> ()
+
+@_silgen_name("marker2")
+func marker2() -> ()
+
+@_silgen_name("marker3")
+func marker3() -> ()
+
+@_silgen_name("marker4")
+func marker4() -> ()
+
+@_silgen_name("marker5")
+func marker5() -> ()
+
+@_silgen_name("marker6")
+func marker6() -> ()
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*, %swift.type* %T1)
+// IR-Onone: call void @swift_beginAccess
+// IR-Onone-NEXT: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR-O:   call void @swift_beginAccess
+// IR-O-NEXT: ret void
+
+@_semantics("optimize.sil.preserve_exclusivity")
+public func beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+  marker1()
+  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8endNoOptyyBpF"(i8*)
+// IR-Onone: call void @swift_endAccess
+// IR-Onone-NEXT: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8endNoOptyyBpF"(i8*)
+// IR-O:   call void @swift_endAccess
+// IR-O-NEXT: ret void
+@_semantics("optimize.sil.preserve_exclusivity")
+public func endNoOpt(_ address: Builtin.RawPointer) {
+  marker2()
+  Builtin.endUnpairedAccess(address)
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9readNoOptyyBp_xmtlF"(i8*, %swift.type*, %swift.type* %T1)
+// IR-Onone: call void @swift_beginAccess
+// IR-Onone: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9readNoOptyyBp_xmtlF"(i8*, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR-O:   call void @swift_beginAccess
+// IR-O: ret void
+@_semantics("optimize.sil.preserve_exclusivity")
+public func readNoOpt<T1>(_ address: Builtin.RawPointer, _ ty1: T1.Type) {
+  marker3()
+  Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+// Make sure testNoOpt properly inlines in our functions.
+//
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9testNoOptyyBpF"(i8*)
+// IR-O: call swiftcc void @marker1
+// IR-O: call void @swift_beginAccess
+// IR-O: call swiftcc void @marker2
+// IR-O: call void @swift_endAccess
+// IR-O: call swiftcc void @marker3
+// IR-O: call void @swift_beginAccess
+// IR-O: ret void
+public func testNoOpt(_ k1: Builtin.RawPointer) {
+  beginNoOpt(k1, k1, Builtin.RawPointer.self)
+  endNoOpt(k1)
+  readNoOpt(k1, Builtin.RawPointer.self)
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8beginOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*, %swift.type* %T1)
+// IR-Onone: call void @swift_beginAccess
+// IR-Onone-NEXT: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8beginOptyyBp_BpxmtlF"(i8*{{.*}}, i8*{{.*}}, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR-O-NEXT: entry
+// IR-O-NEXT: call swiftcc void @marker4
+// IR-O-NEXT: ret void
+
+public func beginOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+  marker4()
+  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity6endOptyyBpF"(i8*)
+// IR-Onone: call void @swift_endAccess
+// IR-Onone-NEXT: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity6endOptyyBpF"(i8*{{.*}})
+// IR-O-NEXT: entry
+// IR-O-NEXT: call swiftcc void @marker5
+// IR-O-NEXT: ret void
+
+public func endOpt(_ address: Builtin.RawPointer) {
+  marker5()
+  Builtin.endUnpairedAccess(address)
+}
+
+// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7readOptyyBp_xmtlF"(i8*, %swift.type*, %swift.type* %T1)
+// IR-Onone: call void @swift_beginAccess
+// IR-Onone: ret void
+
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7readOptyyBp_xmtlF"(i8*{{.*}}, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR-O-NEXT: entry
+// IR-O-NEXT: call swiftcc void @marker6
+// IR-O-NEXT: ret void
+
+public func readOpt<T1>(_ address: Builtin.RawPointer, _ ty1: T1.Type) {
+  marker6()
+  Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+// Make sure testOpt properly inlines in our functions.
+//
+// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7testOptyyBpF"(i8*{{.*}})
+// IR-O: call swiftcc void @marker4
+// IR-O: call swiftcc void @marker5
+// IR-O: call swiftcc void @marker6
+// IR-O: ret void
+public func testOpt(_ k1: Builtin.RawPointer) {
+  beginOpt(k1, k1, Builtin.RawPointer.self)
+  endOpt(k1)
+  readOpt(k1, Builtin.RawPointer.self)
+}
diff --git a/test/Interpreter/SDK/Foundation_test.swift b/test/Interpreter/SDK/Foundation_test.swift
index f41b2a3..e43b844 100644
--- a/test/Interpreter/SDK/Foundation_test.swift
+++ b/test/Interpreter/SDK/Foundation_test.swift
@@ -163,8 +163,8 @@
   expectEqual("{0, 5}", NSStringFromRange(nsrFromPartial))
 
   let s = "Hello, 🌎!"
-  let b = s.index(of: ",")!
-  let e = s.index(of: "!")!
+  let b = s.firstIndex(of: ",")!
+  let e = s.firstIndex(of: "!")!
   let nsr = NSRange(b..<e, in: s)
   expectEqual(nsr.location, 5)
   expectEqual(nsr.length, 4)
diff --git a/test/Interpreter/SDK/equatable_hashable.swift b/test/Interpreter/SDK/equatable_hashable.swift
index 1a4d700..c99f7ce 100644
--- a/test/Interpreter/SDK/equatable_hashable.swift
+++ b/test/Interpreter/SDK/equatable_hashable.swift
@@ -32,7 +32,7 @@
 func test_Equatable() {
   // CHECK-NEXT: Found 2.5 at index 1
   let array: [NSNumber] = [1, 2.5, 3.14159]
-  if let index = array.index(of: 2.5) {
+  if let index = array.firstIndex(of: 2.5) {
     print("Found \(array[index]) at index \(index)")
   } else {
     print("Did not find 2.5?")
diff --git a/test/Interpreter/enforce_exclusive_access.swift b/test/Interpreter/enforce_exclusive_access.swift
index fe4e811..4b34899 100644
--- a/test/Interpreter/enforce_exclusive_access.swift
+++ b/test/Interpreter/enforce_exclusive_access.swift
@@ -241,26 +241,95 @@
 }
 
 class ClassWithStoredProperty {
-  var f = 7
+  final var f = 7
 }
 
-// FIXME: This should trap with a modify/modify violation at run time.
-ExclusiveAccessTestSuite.test("KeyPathClassStoredProp")
+ExclusiveAccessTestSuite.test("KeyPathInoutDirectWriteClassStoredProp")
   .skip(.custom(
     { _isFastAssertConfiguration() },
     reason: "this trap is not guaranteed to happen in -Ounchecked"))
-//  .crashOutputMatches("Previous access (a modification) started at")
-//  .crashOutputMatches("Current access (a modification) started at")
+  .crashOutputMatches("Previous access (a modification) started at")
+  .crashOutputMatches("Current access (a modification) started at")
   .code
 {
   let getF = \ClassWithStoredProperty.f
   let c = ClassWithStoredProperty()
 
-//  expectCrashLater()
+  expectCrashLater()
+  modifyAndPerform(&c[keyPath: getF]) {
+    c.f = 12
+  }
+}
+
+ExclusiveAccessTestSuite.test("KeyPathInoutDirectReadClassStoredProp")
+  .skip(.custom(
+    { _isFastAssertConfiguration() },
+    reason: "this trap is not guaranteed to happen in -Ounchecked"))
+  .crashOutputMatches("Previous access (a modification) started at")
+  .crashOutputMatches("Current access (a read) started at")
+  .code
+{
+  let getF = \ClassWithStoredProperty.f
+  let c = ClassWithStoredProperty()
+
+  expectCrashLater()
+  modifyAndPerform(&c[keyPath: getF]) {
+    let x = c.f
+    _blackHole(x)
+  }
+}
+
+// Unlike inout accesses, read-only inout-to-pointer conversions on key paths for
+// final stored-properties do not perform a long-term read access. Instead, they
+// materialize a location on the stack, perform an instantaneous read
+// from the storage indicated by the key path and write the read value to the
+// stack location. The stack location is then passed as the pointer for the
+// inout-to-pointer conversion.
+//
+// This means that there is no conflict between a read-only inout-to-pointer
+// conversion of the key path location for a call and an access to the
+// the same location within the call.
+ExclusiveAccessTestSuite.test("KeyPathReadOnlyInoutToPtrDirectWriteClassStoredProp") {
+  let getF = \ClassWithStoredProperty.f
+  let c = ClassWithStoredProperty()
+
+  // This performs an instantaneous read
+  readAndPerform(&c[keyPath: getF]) {
+    c.f = 12 // no-trap
+  }
+}
+
+ExclusiveAccessTestSuite.test("SequentialKeyPathWritesDontOverlap") {
+  let getF = \ClassWithStoredProperty.f
+  let c = ClassWithStoredProperty()
+
+  c[keyPath: getF] = 7
+  c[keyPath: getF] = 8 // no-trap
+  c[keyPath: getF] += c[keyPath: getF] + 1 // no-trap
+}
+
+// This does not trap, for now, because the standard library (and thus KeyPath) is
+// compiled in Swift 3 mode and we currently log rather than trap in Swift mode.
+ExclusiveAccessTestSuite.test("KeyPathInoutKeyPathWriteClassStoredProp")
+{
+  let getF = \ClassWithStoredProperty.f
+  let c = ClassWithStoredProperty()
+
   modifyAndPerform(&c[keyPath: getF]) {
     c[keyPath: getF] = 12
   }
 }
 
+// This does not currently trap because the standard library is compiled in Swift 3 mode,
+// which logs.
+ExclusiveAccessTestSuite.test("KeyPathInoutKeyPathReadClassStoredProp") {
+  let getF = \ClassWithStoredProperty.f
+  let c = ClassWithStoredProperty()
+
+  modifyAndPerform(&c[keyPath: getF]) {
+    let y = c[keyPath: getF]
+    _blackHole(y)
+  }
+}
 
 runAllTests()
diff --git a/test/Interpreter/enforce_exclusive_access_backtrace.swift b/test/Interpreter/enforce_exclusive_access_backtrace.swift
index 3c9485f..b50b114 100644
--- a/test/Interpreter/enforce_exclusive_access_backtrace.swift
+++ b/test/Interpreter/enforce_exclusive_access_backtrace.swift
@@ -17,12 +17,18 @@
   closure()
 }
 
+func writeAndPerform<T>(_ _: UnsafeMutablePointer<T>, closure: () ->()) {
+  closure()
+}
+
 var globalX = X()
 withUnsafePointer(to: &globalX) { _ = fputs(String(format: "globalX: 0x%lx\n", Int(bitPattern: $0)), stderr) }
 // CHECK: globalX: [[ADDR:0x.*]]
 
+fputs("Global Access\n", stderr);
 readAndPerform(&globalX) {
   globalX = X()
+  // CHECK-LABEL: Global Access
   // CHECK: Simultaneous accesses to [[ADDR]], but modification requires exclusive access.
   // CHECK: Previous access (a read) started at a.out`main + {{.*}} (0x{{.*}}).
   // CHECK: Current access (a modification) started at:
@@ -30,3 +36,42 @@
   // CHECK: a.out {{.*}} readAndPerform
   // CHECK: a.out {{.*}} main
 }
+
+class C {
+  final var f = 7
+}
+
+var c = C()
+withUnsafePointer(to: &c.f) { _ = fputs(String(format: "c.f: 0x%lx\n", Int(bitPattern: $0)), stderr) }
+// CHECK: c.f: [[C_F_ADDR:0x.*]]
+
+// Key path accesses are performed in the Standard Library. The Standard Library
+// is currently compiled in Swift 3 mode and the compiler currently logs conflicts
+// (rather than trapping on them) code compiled in Swift 3 mode. For this reason
+// conflicts where the second conflicting access is via a key path will log rather than
+// trap.
+
+fputs("Overlapping Key Path Write Accesses\n", stderr);
+writeAndPerform(&c[keyPath: \C.f]) {
+  c[keyPath: \C.f] = 8
+  // CHECK-LABEL: Overlapping Key Path Write Accesses
+  // CHECK: Simultaneous accesses to [[C_F_ADDR]], but modification requires exclusive access.
+  // CHECK: Previous access (a modification)
+  // CHECK: Current access (a modification)
+  // CHECK: a.out {{.*}} closure
+  // CHECK: a.out {{.*}} writeAndPerform
+  // CHECK: a.out {{.*}} main
+}
+
+fputs("Overlapping Key Path Write Access and Key Path Read Access\n", stderr);
+writeAndPerform(&c[keyPath: \C.f]) {
+  let x = c[keyPath: \C.f]
+  _blackHole(x)
+  // CHECK-LABEL: Overlapping Key Path Write Access and Key Path Read Access
+  // CHECK: Simultaneous accesses to [[C_F_ADDR]], but modification requires exclusive access.
+  // CHECK: Previous access (a modification)
+  // CHECK: Current access (a read)
+  // CHECK: a.out {{.*}} closure
+  // CHECK: a.out {{.*}} writeAndPerform
+  // CHECK: a.out {{.*}} main
+}
diff --git a/test/NameBinding/name_lookup_min_max_conditional_conformance.swift b/test/NameBinding/name_lookup_min_max_conditional_conformance.swift
new file mode 100644
index 0000000..c9847c5
--- /dev/null
+++ b/test/NameBinding/name_lookup_min_max_conditional_conformance.swift
@@ -0,0 +1,58 @@
+// RUN: %target-typecheck-verify-swift
+
+extension Range {
+    func f(_ value: Bound) -> Bound {
+        return max(lowerBound, min(value, upperBound))
+        // expected-warning@-1{{use of 'max' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Range' which comes via a conditional conformance}}
+        // expected-note@-2{{use 'Swift.' to continue to reference the global function}}
+        // expected-warning@-3{{use of 'min' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Range' which comes via a conditional conformance}}
+        // expected-note@-4{{use 'Swift.' to continue to reference the global function}}
+    }
+}
+
+protocol ContainsMinMax {}
+extension ContainsMinMax {
+    func max() {}
+    func min() {}
+}
+
+func foo(_: Int, _: Int) {}
+// expected-note@-1 {{'foo' declared here}}
+
+protocol ContainsFoo {}
+extension ContainsFoo {
+    func foo() {}
+}
+
+struct NonConditional: ContainsMinMax, ContainsFoo {}
+
+extension NonConditional {
+    func f() {
+        _ = max(1, 2)
+        // expected-error@-1{{use of 'max' refers to instance method}}
+        // expected-note@-2{{use 'Swift.' to reference the global function}}
+        _ = min(3, 4)
+        // expected-error@-1{{use of 'min' refers to instance method}}
+        // expected-note@-2{{use 'Swift.' to reference the global function}}
+        _ = foo(5, 6)
+        // expected-error@-1{{use of 'foo' refers to instance method}}
+        // expected-note@-2{{use 'name_lookup_min_max_conditional_conformance.' to reference the global function}}
+    }
+}
+
+struct Conditional<T> {}
+extension Conditional: ContainsMinMax where T: ContainsMinMax {}
+extension Conditional: ContainsFoo where T: ContainsFoo {}
+
+extension Conditional {
+    func f() {
+        _ = max(1, 2)
+        // expected-warning@-1{{use of 'max' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Conditional' which comes via a conditional conformance}}
+        // expected-note@-2{{use 'Swift.' to continue to reference the global function}}
+        _ = min(3, 4)
+        // expected-warning@-1{{use of 'min' as reference to global function in module 'Swift' will change in future versions of Swift to reference instance method in generic struct 'Conditional' which comes via a conditional conformance}}
+        // expected-note@-2{{use 'Swift.' to continue to reference the global function}}
+        _ = foo(5, 6)
+        // expected-error@-1{{type 'T' does not conform to protocol 'ContainsFoo'}}
+    }
+}
diff --git a/test/SILGen/Inputs/coverage_imports.swift b/test/Profiler/Inputs/coverage_imports.swift
similarity index 100%
rename from test/SILGen/Inputs/coverage_imports.swift
rename to test/Profiler/Inputs/coverage_imports.swift
diff --git a/test/SILGen/coverage_class.swift b/test/Profiler/coverage_class.swift
similarity index 100%
rename from test/SILGen/coverage_class.swift
rename to test/Profiler/coverage_class.swift
diff --git a/test/SILGen/coverage_closures.swift b/test/Profiler/coverage_closures.swift
similarity index 70%
rename from test/SILGen/coverage_closures.swift
rename to test/Profiler/coverage_closures.swift
index 6fdf8d9..255767d 100644
--- a/test/SILGen/coverage_closures.swift
+++ b/test/Profiler/coverage_closures.swift
@@ -1,4 +1,44 @@
-// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_closures %s | %FileCheck %s
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sil -module-name coverage_closures %s | %FileCheck %s
+
+func bar(arr: [(Int32) -> Int32]) {
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #2 (Swift.Int32) -> Swift.Int32 in coverage_closures.bar
+// CHECK-NEXT:  [[@LINE+1]]:13 -> [[@LINE+1]]:42 : 0
+  for a in [{ (b : Int32) -> Int32 in b }] {
+    a(0)
+  }
+}
+
+func foo() {
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #1 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
+// CHECK-NEXT: [[@LINE+1]]:12 -> [[@LINE+1]]:59 : 0
+  let c1 = { (i1 : Int32, i2 : Int32) -> Bool in i1 < i2 }
+
+// CHECK-LABEL: sil_coverage_map {{.*}}// f1 #1 ((Swift.Int32, Swift.Int32) -> Swift.Bool) -> Swift.Bool in coverage_closures.foo()
+// CHECK-NEXT: [[@LINE+1]]:55 -> {{.*}}:4 : 0
+  func f1(_ closure : (Int32, Int32) -> Bool) -> Bool {
+// CHECK-LABEL: sil_coverage_map {{.*}}// implicit closure #1 : @autoclosure () throws -> Swift.Bool in f1
+// CHECK-NEXT: [[@LINE+1]]:29 -> [[@LINE+1]]:42 : 0
+    return closure(0, 1) && closure(1, 0)
+  }
+
+  f1(c1)
+
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #2 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
+// CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:27 : 0
+  f1 { i1, i2 in i1 > i2 }
+
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #3 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
+// CHECK-NEXT: [[@LINE+3]]:6 -> [[@LINE+3]]:48 : 0
+// CHECK-LABEL: sil_coverage_map {{.*}}// implicit closure #1 : @autoclosure () throws -> {{.*}} in coverage_closures.foo
+// CHECK-NEXT: [[@LINE+1]]:36 -> [[@LINE+1]]:46 : 0
+  f1 { left, right in left == 0 || right == 1 }
+}
+
+// SR-2615: Implicit constructor decl has no body, and shouldn't be mapped
+struct C1 {
+// CHECK-NOT: sil_coverage_map{{.*}}errors
+  private var errors = [String]()
+}
 
 // rdar://39200851: Closure in init method covered twice
 
@@ -12,60 +52,3 @@
     }
   }
 }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_closures.bar
-// CHECK-NEXT:  [[@LINE+9]]:35 -> [[@LINE+13]]:2 : 0
-// CHECK-NEXT:  [[@LINE+9]]:44 -> [[@LINE+11]]:4 : 1
-// CHECK-NEXT:  [[@LINE+10]]:4 -> [[@LINE+11]]:2 : 0
-// CHECK-NEXT: }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #2 (Swift.Int32) -> Swift.Int32 in coverage_closures.bar
-// CHECK-NEXT:  [[@LINE+4]]:13 -> [[@LINE+4]]:42 : 0
-// CHECK-NEXT: }
-
-func bar(arr: [(Int32) -> Int32]) {
-  for a in [{ (b : Int32) -> Int32 in b }] {
-    a(0)
-  }
-}
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_closures.foo
-func foo() {
-  let c1 = { (i1 : Int32, i2 : Int32) -> Bool in i1 < i2 }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// f1 #1 ((Swift.Int32, Swift.Int32) -> Swift.Bool) -> Swift.Bool in coverage_closures.foo()
-// CHECK-NEXT: [[@LINE+5]]:55 -> [[@LINE+7]]:4 : 0
-// CHECK-NEXT: }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// implicit closure #1 : @autoclosure () throws -> Swift.Bool in f1
-// CHECK-NEXT: [[@LINE+2]]:29 -> [[@LINE+2]]:42 : 0
-  func f1(_ closure : (Int32, Int32) -> Bool) -> Bool {
-    return closure(0, 1) && closure(1, 0)
-  }
-
-  f1(c1)
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #2 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
-// CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:27 : 0
-  f1 { i1, i2 in i1 > i2 }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #3 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
-// CHECK-NEXT: [[@LINE+5]]:6 -> [[@LINE+5]]:48 : 0
-// CHECK-NEXT: }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// implicit closure #1 : @autoclosure () throws -> {{.*}} in coverage_closures.foo
-// CHECK-NEXT: [[@LINE+1]]:36 -> [[@LINE+1]]:46 : 0
-  f1 { left, right in left == 0 || right == 1 }
-}
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #1 (Swift.Int32, Swift.Int32) -> Swift.Bool in coverage_closures.foo()
-// CHECK-NEXT: [[@LINE-27]]:12 -> [[@LINE-27]]:59 : 0
-
-// SR-2615: Implicit constructor decl has no body, and shouldn't be mapped
-struct C1 {
-// CHECK-NOT: sil_coverage_map{{.*}}errors
-  private var errors = [String]()
-}
-
-bar(arr: [{ x in x }])
-foo()
-let _ = C2()
diff --git a/test/SILGen/coverage_curry.swift b/test/Profiler/coverage_curry.swift
similarity index 100%
rename from test/SILGen/coverage_curry.swift
rename to test/Profiler/coverage_curry.swift
diff --git a/test/SILGen/coverage_default_args.swift b/test/Profiler/coverage_default_args.swift
similarity index 100%
rename from test/SILGen/coverage_default_args.swift
rename to test/Profiler/coverage_default_args.swift
diff --git a/test/SILGen/coverage_deinit.swift b/test/Profiler/coverage_deinit.swift
similarity index 100%
rename from test/SILGen/coverage_deinit.swift
rename to test/Profiler/coverage_deinit.swift
diff --git a/test/SILGen/coverage_exceptions.swift b/test/Profiler/coverage_exceptions.swift
similarity index 100%
rename from test/SILGen/coverage_exceptions.swift
rename to test/Profiler/coverage_exceptions.swift
diff --git a/test/SILGen/coverage_force_emission.swift b/test/Profiler/coverage_force_emission.swift
similarity index 100%
rename from test/SILGen/coverage_force_emission.swift
rename to test/Profiler/coverage_force_emission.swift
diff --git a/test/SILGen/coverage_guard.swift b/test/Profiler/coverage_guard.swift
similarity index 100%
rename from test/SILGen/coverage_guard.swift
rename to test/Profiler/coverage_guard.swift
diff --git a/test/SILGen/coverage_if.swift b/test/Profiler/coverage_if.swift
similarity index 100%
rename from test/SILGen/coverage_if.swift
rename to test/Profiler/coverage_if.swift
diff --git a/test/Profiler/coverage_irgen.swift b/test/Profiler/coverage_irgen.swift
new file mode 100644
index 0000000..9360522
--- /dev/null
+++ b/test/Profiler/coverage_irgen.swift
@@ -0,0 +1,20 @@
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -profile-generate -profile-coverage-mapping -emit-sil -o - -module-name=irgen | %FileCheck %s --check-prefix=SIL
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -profile-generate -profile-coverage-mapping -emit-ir -o - -module-name=irgen | %FileCheck %s --check-prefix=IR
+
+// IR-NOT: __llvm_coverage_names
+// IR-NOT: __profn
+
+// SIL: sil hidden @$S5irgen2f1yyF
+// SIL: string_literal utf8 "{{.*}}coverage_irgen.swift:{{.*}}$S5irgen2f1yyF"
+internal func f1() {}
+
+// SIL: sil private @$S5irgen2f2[[F2HASH:[_a-zA-Z0-9]+]]
+// SIL: string_literal utf8 "{{.*}}coverage_irgen.swift:$S5irgen2f2[[F2HASH]]"
+private func f2() {}
+
+// SIL: sil @$S5irgen2f3yyF
+// SIL: string_literal utf8 "$S5irgen2f3yyF"
+public func f3() {
+  f1()
+  f2()
+}
diff --git a/test/IRGen/coverage_ignored.swift b/test/Profiler/coverage_irgen_ignored.swift
similarity index 100%
rename from test/IRGen/coverage_ignored.swift
rename to test/Profiler/coverage_irgen_ignored.swift
diff --git a/test/SILGen/coverage_label.swift b/test/Profiler/coverage_label.swift
similarity index 100%
rename from test/SILGen/coverage_label.swift
rename to test/Profiler/coverage_label.swift
diff --git a/test/SILGen/coverage_member_closure.swift b/test/Profiler/coverage_member_closure.swift
similarity index 100%
rename from test/SILGen/coverage_member_closure.swift
rename to test/Profiler/coverage_member_closure.swift
diff --git a/test/SILGen/coverage_nested_func.swift b/test/Profiler/coverage_nested_func.swift
similarity index 100%
rename from test/SILGen/coverage_nested_func.swift
rename to test/Profiler/coverage_nested_func.swift
diff --git a/test/Profiler/coverage_primary_file.swift b/test/Profiler/coverage_primary_file.swift
new file mode 100644
index 0000000..03b3faf
--- /dev/null
+++ b/test/Profiler/coverage_primary_file.swift
@@ -0,0 +1,27 @@
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_primary_file %s %S/Inputs/coverage_imports.swift | %FileCheck %s -check-prefix=ALL
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_primary_file -primary-file %s %S/Inputs/coverage_imports.swift | %FileCheck %s -check-prefix=PRIMARY
+
+// ALL: sil_coverage_map {{.*}} // closure #1 () -> Swift.Int in coverage_primary_file.Box.x.getter : Swift.Int
+// ALL: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(y: Swift.Int) -> coverage_primary_file.Box
+// ALL: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(z: Swift.String) -> coverage_primary_file.Box
+// ALL: sil_coverage_map {{.*}} // coverage_primary_file.main() -> ()
+// ALL: sil_coverage_map {{.*}} // __ntd_Box
+
+// PRIMARY-NOT: sil_coverage_map
+// PRIMARY: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(y: Swift.Int) -> coverage_primary_file.Box
+// PRIMARY: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(z: Swift.String) -> coverage_primary_file.Box
+// PRIMARY: sil_coverage_map {{.*}} // coverage_primary_file.main() -> ()
+// PRIMARY-NOT: sil_coverage_map
+
+extension Box {
+  init(y: Int) { self.init() }
+}
+
+extension Box {
+  init(z: String) { self.init() }
+}
+
+func main() {
+  var b = Box()
+  let _ = b.x
+}
diff --git a/test/SILGen/coverage_smoke.swift b/test/Profiler/coverage_smoke.swift
similarity index 100%
rename from test/SILGen/coverage_smoke.swift
rename to test/Profiler/coverage_smoke.swift
diff --git a/test/SILGen/coverage_switch.swift b/test/Profiler/coverage_switch.swift
similarity index 100%
rename from test/SILGen/coverage_switch.swift
rename to test/Profiler/coverage_switch.swift
diff --git a/test/SILGen/coverage_ternary.swift b/test/Profiler/coverage_ternary.swift
similarity index 100%
rename from test/SILGen/coverage_ternary.swift
rename to test/Profiler/coverage_ternary.swift
diff --git a/test/SILGen/coverage_toplevel.swift b/test/Profiler/coverage_toplevel.swift
similarity index 100%
rename from test/SILGen/coverage_toplevel.swift
rename to test/Profiler/coverage_toplevel.swift
diff --git a/test/SILGen/coverage_uikit.swift b/test/Profiler/coverage_uikit.swift
similarity index 100%
rename from test/SILGen/coverage_uikit.swift
rename to test/Profiler/coverage_uikit.swift
diff --git a/test/SILGen/coverage_var_init.swift b/test/Profiler/coverage_var_init.swift
similarity index 100%
rename from test/SILGen/coverage_var_init.swift
rename to test/Profiler/coverage_var_init.swift
diff --git a/test/SILGen/coverage_while.swift b/test/Profiler/coverage_while.swift
similarity index 100%
rename from test/SILGen/coverage_while.swift
rename to test/Profiler/coverage_while.swift
diff --git a/test/IRGen/coverage_with_asan.swift b/test/Profiler/coverage_with_asan.swift
similarity index 100%
rename from test/IRGen/coverage_with_asan.swift
rename to test/Profiler/coverage_with_asan.swift
diff --git a/test/SILGen/instrprof_basic.swift b/test/Profiler/instrprof_basic.swift
similarity index 100%
rename from test/SILGen/instrprof_basic.swift
rename to test/Profiler/instrprof_basic.swift
diff --git a/test/SILGen/instrprof_operators.swift b/test/Profiler/instrprof_operators.swift
similarity index 100%
rename from test/SILGen/instrprof_operators.swift
rename to test/Profiler/instrprof_operators.swift
diff --git a/test/SILGen/pgo_checked_cast.swift b/test/Profiler/pgo_checked_cast.swift
similarity index 100%
rename from test/SILGen/pgo_checked_cast.swift
rename to test/Profiler/pgo_checked_cast.swift
diff --git a/test/SILGen/pgo_foreach.swift b/test/Profiler/pgo_foreach.swift
similarity index 100%
rename from test/SILGen/pgo_foreach.swift
rename to test/Profiler/pgo_foreach.swift
diff --git a/test/SILGen/pgo_guard.swift b/test/Profiler/pgo_guard.swift
similarity index 100%
rename from test/SILGen/pgo_guard.swift
rename to test/Profiler/pgo_guard.swift
diff --git a/test/SILGen/pgo_if.swift b/test/Profiler/pgo_if.swift
similarity index 100%
rename from test/SILGen/pgo_if.swift
rename to test/Profiler/pgo_if.swift
diff --git a/test/SILGen/pgo_repeatwhile.swift b/test/Profiler/pgo_repeatwhile.swift
similarity index 100%
rename from test/SILGen/pgo_repeatwhile.swift
rename to test/Profiler/pgo_repeatwhile.swift
diff --git a/test/SILGen/pgo_switchenum.swift b/test/Profiler/pgo_switchenum.swift
similarity index 100%
rename from test/SILGen/pgo_switchenum.swift
rename to test/Profiler/pgo_switchenum.swift
diff --git a/test/SILGen/pgo_while.swift b/test/Profiler/pgo_while.swift
similarity index 100%
rename from test/SILGen/pgo_while.swift
rename to test/Profiler/pgo_while.swift
diff --git a/test/Prototypes/BigInt.swift b/test/Prototypes/BigInt.swift
index f042f99..ada80ab 100644
--- a/test/Prototypes/BigInt.swift
+++ b/test/Prototypes/BigInt.swift
@@ -712,7 +712,7 @@
       return 0
     }
 
-    let i = _data.index(where: { $0 != 0 })!
+    let i = _data.firstIndex(where: { $0 != 0 })!
     _sanityCheck(_data[i] != 0)
     return i * Word.bitWidth + _data[i].trailingZeroBitCount
   }
diff --git a/test/Prototypes/CollectionTransformers.swift b/test/Prototypes/CollectionTransformers.swift
index 55f5b5c..8027b26 100644
--- a/test/Prototypes/CollectionTransformers.swift
+++ b/test/Prototypes/CollectionTransformers.swift
@@ -680,7 +680,7 @@
       _runningThreadsMutex.withLock {
         _submissionQueuesMutex.withLock {
           _workDequesMutex.withLock {
-            let i = _runningThreads.index { $0 === thread }!
+            let i = _runningThreads.firstIndex { $0 === thread }!
             ForkJoinPool._threadRegistry[thread._tid!] = nil
             _runningThreads.remove(at: i)
             _submissionQueues.remove(at: i)
diff --git a/test/Reflection/capture_descriptors.sil b/test/Reflection/capture_descriptors.sil
index 8e63021..4bb334c 100644
--- a/test/Reflection/capture_descriptors.sil
+++ b/test/Reflection/capture_descriptors.sil
@@ -41,8 +41,7 @@
 
 // CHECK:      - Capture types:
 // CHECK-NEXT: (struct Swift.Int)
-// CHECK-NEXT: (sil_box
-// CHECK-NEXT:   (struct Swift.Int))
+// CHECK-NEXT: (builtin Builtin.NativeObject)
 // CHECK-NEXT: (existential_metatype
 // CHECK-NEXT:   (protocol_composition
 // CHECK-NEXT:     (protocol capture_descriptors.P)))
@@ -76,8 +75,7 @@
 
 // CHECK:      - Capture types:
 // CHECK-NEXT: (struct Swift.Int)
-// CHECK-NEXT: (sil_box
-// CHECK-NEXT:   (struct Swift.String))
+// CHECK-NEXT: (builtin Builtin.NativeObject)
 // CHECK-NEXT:   - Metadata sources:
 
 
diff --git a/test/Reflection/typeref_decoding.swift b/test/Reflection/typeref_decoding.swift
index 9ffcc80..6e8c0b8 100644
--- a/test/Reflection/typeref_decoding.swift
+++ b/test/Reflection/typeref_decoding.swift
@@ -708,8 +708,7 @@
 // CHECK: CAPTURE DESCRIPTORS:
 // CHECK: ====================
 // CHECK: - Capture types:
-// CHECK: (sil_box
-// CHECK:   (generic_type_parameter depth=0 index=0))
+// CHECK: (builtin Builtin.NativeObject)
 // CHECK: - Metadata sources:
 // CHECK: (generic_type_parameter depth=0 index=0)
 // CHECK: (closure_binding index=0)
diff --git a/test/Reflection/typeref_decoding_asan.swift b/test/Reflection/typeref_decoding_asan.swift
index 3532397..9a40e21 100644
--- a/test/Reflection/typeref_decoding_asan.swift
+++ b/test/Reflection/typeref_decoding_asan.swift
@@ -708,8 +708,7 @@
 // CHECK: CAPTURE DESCRIPTORS:
 // CHECK: ====================
 // CHECK: - Capture types:
-// CHECK: (sil_box
-// CHECK:   (generic_type_parameter depth=0 index=0))
+// CHECK: (builtin Builtin.NativeObject)
 // CHECK: - Metadata sources:
 // CHECK: (generic_type_parameter depth=0 index=0)
 // CHECK: (closure_binding index=0)
diff --git a/test/SILGen/builtins.swift b/test/SILGen/builtins.swift
index 588c682..d8ef79f 100644
--- a/test/SILGen/builtins.swift
+++ b/test/SILGen/builtins.swift
@@ -370,31 +370,27 @@
 }
 
 // CHECK-LABEL: sil hidden @$S8builtins25beginUnpairedModifyAccess{{[_0-9a-zA-Z]*}}F
-// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
-// CHECK: [[P2A_SCRATCH:%.*]] = pointer_to_address %1
-// CHECK: begin_unpaired_access [modify] [dynamic] [[P2A_ADDR]] : $*T1, [[P2A_SCRATCH]] : $*Builtin.UnsafeValueBuffer
-// CHECK: [[RESULT:%.*]] = tuple ()
-// CHECK: [[RETURN:%.*]] = tuple ()
-// CHECK: return [[RETURN]] : $()
-// CHECK: } // end sil function '$S8builtins25beginUnpairedModifyAccess{{[_0-9a-zA-Z]*}}F'
 func beginUnpairedModifyAccess<T1>(address: Builtin.RawPointer, scratch: Builtin.RawPointer, ty1: T1.Type) {
+  // CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
+  // CHECK: [[P2A_SCRATCH:%.*]] = pointer_to_address %1
+  // CHECK: begin_unpaired_access [modify] [dynamic] [[P2A_ADDR]] : $*T1, [[P2A_SCRATCH]] : $*Builtin.UnsafeValueBuffer
+  // CHECK: [[RESULT:%.*]] = tuple ()
+  // CHECK: [[RETURN:%.*]] = tuple ()
+  // CHECK: return [[RETURN]] : $()
+
   Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
 }
 
-// CHECK-LABEL: sil hidden @$S8builtins17endUnpairedAccess{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.RawPointer) -> () {
-// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
-// CHECK: end_unpaired_access [dynamic] [[P2A_ADDR]]
-// CHECK: } // end sil function '$S8builtins17endUnpairedAccess{{[_0-9a-zA-Z]*}}F'
-func endUnpairedAccess(address: Builtin.RawPointer) {
-  Builtin.endUnpairedAccess(address)
-}
-
 // CHECK-LABEL: sil hidden @$S8builtins30performInstantaneousReadAccess{{[_0-9a-zA-Z]*}}F
-// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
-// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[P2A_ADDR]] : $*T1
-// CHECK-NEXT: end_access [[ACCESS]] : $*T1
-// CHECK: } // end sil function '$S8builtins30performInstantaneousReadAccess{{[_0-9a-zA-Z]*}}F'
 func performInstantaneousReadAccess<T1>(address: Builtin.RawPointer, scratch: Builtin.RawPointer, ty1: T1.Type) {
+  // CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
+  // CHECK: [[SCRATCH:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
+  // CHECK: begin_unpaired_access [read] [dynamic] [no_nested_conflict] [[P2A_ADDR]] : $*T1, [[SCRATCH]] : $*Builtin.UnsafeValueBuffer
+  // CHECK-NOT: end_{{.*}}access
+  // CHECK: [[RESULT:%.*]] = tuple ()
+  // CHECK: [[RETURN:%.*]] = tuple ()
+  // CHECK: return [[RETURN]] : $()
+
   Builtin.performInstantaneousReadAccess(address, ty1);
 }
 
diff --git a/test/SILGen/coverage_decls.swift b/test/SILGen/coverage_decls.swift
deleted file mode 100644
index 5843cb8..0000000
--- a/test/SILGen/coverage_decls.swift
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_decls -primary-file %s %S/Inputs/coverage_imports.swift | %FileCheck %s
-
-// CHECK: sil_coverage_map {{.*}} $S14coverage_decls4mainyyF
-// CHECK-NOT: sil_coverage_map
-
-func main() {
-  var b = Box()
-  let _ = b.x
-}
diff --git a/test/SILGen/enum_raw_representable.swift b/test/SILGen/enum_raw_representable.swift
new file mode 100644
index 0000000..60bea14
--- /dev/null
+++ b/test/SILGen/enum_raw_representable.swift
@@ -0,0 +1,12 @@
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -enable-resilience %s | %FileCheck -check-prefix=CHECK-RESILIENT %s
+
+public enum E: Int {
+  case a, b, c
+}
+
+// CHECK-DAG: sil [serialized] @$S22enum_raw_representable1EO0B5ValueACSgSi_tcfC
+// CHECK-DAG: sil [serialized] @$S22enum_raw_representable1EO0B5ValueSivg
+
+// CHECK-RESILIENT-DAG: sil @$S22enum_raw_representable1EO0B5ValueACSgSi_tcfC
+// CHECK-RESILIENT-DAG: sil @$S22enum_raw_representable1EO0B5ValueSivg
diff --git a/test/SILGen/preserve_exclusivity.swift b/test/SILGen/preserve_exclusivity.swift
new file mode 100644
index 0000000..7902e3d
--- /dev/null
+++ b/test/SILGen/preserve_exclusivity.swift
@@ -0,0 +1,118 @@
+// RUN: %target-swift-frontend -parse-stdlib -emit-silgen %s | %FileCheck --check-prefix=SILGEN %s
+//
+// Check that SILGen emits the correct SIL attributes for @_semantics("optimize.sil.preserve_exclusivity")/
+
+// RUN: %target-swift-frontend -parse-stdlib -parse-stdlib -emit-sil -Onone %s | %FileCheck --check-prefix=CANONICAL %s
+//
+// Check that -Onone pipeline does not eliminate the attribute or access markers.
+
+@_silgen_name("marker1")
+func marker1() -> ()
+
+@_silgen_name("marker2")
+func marker2() -> ()
+
+@_silgen_name("marker3")
+func marker3() -> ()
+
+@_silgen_name("marker4")
+func marker4() -> ()
+
+@_silgen_name("marker5")
+func marker5() -> ()
+
+@_silgen_name("marker6")
+func marker6() -> ()
+
+// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// SILGEN:   begin_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF
+
+// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// CANONICAL:   begin_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF
+
+@_semantics("optimize.sil.preserve_exclusivity")
+public func beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+  marker1()
+  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity8endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// SILGEN:   end_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity8endNoOptyyBpF'
+
+// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity8endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// CANONICAL:   end_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity8endNoOptyyBpF'
+
+@_semantics("optimize.sil.preserve_exclusivity")
+public func endNoOpt(_ address: Builtin.RawPointer) {
+  marker2()
+  Builtin.endUnpairedAccess(address)
+}
+
+// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity9readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// SILGEN:   begin_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity9readNoOptyyBp_BpmtF'
+
+// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity9readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// CANONICAL:   begin_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity9readNoOptyyBp_BpmtF'
+
+@_semantics("optimize.sil.preserve_exclusivity")
+public func readNoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
+  marker3()
+  Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+public func testNoOpt(_ k1: Builtin.RawPointer) {
+  beginNoOpt(k1, k1, Builtin.RawPointer.self)
+  endNoOpt(k1)
+  readNoOpt(k1, Builtin.RawPointer.self)
+}
+
+// SILGEN-LABEL: sil @$S20preserve_exclusivity8beginOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// SILGEN: begin_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity8beginOptyyBp_BpxmtlF'
+
+// CANONICAL-LABEL: sil @$S20preserve_exclusivity8beginOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// CANONICAL: begin_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity8beginOptyyBp_BpxmtlF'
+
+public func beginOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+  marker4()
+  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// SILGEN-LABEL: sil @$S20preserve_exclusivity6endOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// SILGEN: end_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity6endOptyyBpF'
+
+// CANONICAL-LABEL: sil @$S20preserve_exclusivity6endOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// CANONICAL: end_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity6endOptyyBpF'
+
+public func endOpt(_ address: Builtin.RawPointer) {
+  marker5()
+  Builtin.endUnpairedAccess(address)
+}
+
+// SILGEN-LABEL: sil @$S20preserve_exclusivity7readOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// SILGEN: begin_unpaired_access
+// SILGEN: } // end sil function '$S20preserve_exclusivity7readOptyyBp_BpmtF'
+
+// CANONICAL-LABEL: sil @$S20preserve_exclusivity7readOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// CANONICAL: begin_unpaired_access
+// CANONICAL: } // end sil function '$S20preserve_exclusivity7readOptyyBp_BpmtF'
+
+public func readOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
+  marker6()
+  Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+public func testOpt(_ k1: Builtin.RawPointer) {
+  beginOpt(k1, k1, Builtin.RawPointer.self)
+  endOpt(k1)
+  readOpt(k1, Builtin.RawPointer.self)
+}
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index 969e2f0..bb8389a 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -513,7 +513,7 @@
   }
 
   var a: Int {
-    // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
+    // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
     willSet(newA) {
       // CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
       // CHECK-NEXT: debug_value %0
@@ -548,7 +548,7 @@
       // CHECK-NEXT: assign [[ZERO]] to [[AADDR]]
     }
 
-    // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
+    // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
     didSet {
       // CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
       // CHECK-NEXT: debug
@@ -626,7 +626,7 @@
   // CHECK: properties.zero.unsafeMutableAddressor
   // CHECK: return
 
-  // CHECK-LABEL: sil hidden @$S10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
+  // CHECK-LABEL: sil private @$S10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
   didSet {
     // The didSet implementation needs to call takeInt.
     takeInt(global_observing_property)
diff --git a/test/SILGen/properties_swift4.swift b/test/SILGen/properties_swift4.swift
index 9cfc5b4..a51a951 100644
--- a/test/SILGen/properties_swift4.swift
+++ b/test/SILGen/properties_swift4.swift
@@ -13,7 +13,7 @@
   }
 
   var a: Int {
-    // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
+    // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
     willSet(newA) {
       // CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
 
@@ -57,7 +57,7 @@
       // CHECK-NEXT: end_access [[WRITE]] : $*DidSetWillSetTests
     }
 
-    // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
+    // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
     didSet {
       (self).a = zero  // reassign, but don't infinite loop.
 
diff --git a/test/SILGen/properties_swift5.swift b/test/SILGen/properties_swift5.swift
index 0e86b85..c847011 100644
--- a/test/SILGen/properties_swift5.swift
+++ b/test/SILGen/properties_swift5.swift
@@ -13,7 +13,7 @@
   }
 
   var a: Int {
-    // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
+    // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
     willSet(newA) {
       // CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
 
@@ -59,7 +59,7 @@
       // CHECK-NEXT: end_access [[WRITE]] : $*DidSetWillSetTests
     }
 
-    // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
+    // CHECK-LABEL: sil private @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
     didSet {
       (self).a = zero  // reassign, but don't infinite loop, as accessing on 'self'.
 
diff --git a/test/SILOptimizer/definite_init_diagnostics.swift b/test/SILOptimizer/definite_init_diagnostics.swift
index 9b54328..f49732d 100644
--- a/test/SILOptimizer/definite_init_diagnostics.swift
+++ b/test/SILOptimizer/definite_init_diagnostics.swift
@@ -111,7 +111,7 @@
   weak var w1 : SomeClass?
   _ = w1                // ok: default-initialized
 
-  // expected-warning@+3 {{instance will be immediately deallocated as 'w2' is a 'weak' variable}}
+  // expected-warning@+3 {{instance will be immediately deallocated because variable 'w2' is 'weak'}}
   // expected-note@+2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@+1 {{'w2' declared here}}
   weak var w2 = SomeClass()
@@ -124,7 +124,7 @@
   unowned var u1 : SomeClass // expected-note {{variable defined here}}
   _ = u1                // expected-error {{variable 'u1' used before being initialized}}
 
-  // expected-warning@+3 {{instance will be immediately deallocated as 'u2' is an 'unowned' variable}}
+  // expected-warning@+3 {{instance will be immediately deallocated because variable 'u2' is 'unowned'}}
   // expected-note@+2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@+1 {{'u2' declared here}}
   unowned let u2 = SomeClass()
diff --git a/test/SILOptimizer/preserve_exclusivity.swift b/test/SILOptimizer/preserve_exclusivity.swift
new file mode 100644
index 0000000..9ba7e28
--- /dev/null
+++ b/test/SILOptimizer/preserve_exclusivity.swift
@@ -0,0 +1,150 @@
+// RUN: %target-swift-frontend -parse-stdlib -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=GenericSpecializer -emit-sil -O %s | %FileCheck %s
+//
+// The -O pipeline should respect
+// @_semantics("optimize.sil.preserve_exclusivity") and avoid eliminating access
+// markers as long as the semantics call is not inlined.
+
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -parse-stdlib -emit-module -O -primary-file %s -emit-module-path %t/preserve_exclusivity.swiftmodule
+// RUN: %target-sil-opt %t/preserve_exclusivity.swiftmodule -emit-sorted-sil -verify -o - | %FileCheck --check-prefix=DESERIALIZED %s
+//
+// Access markers cannot be stripped prior to module serialization, even when their functions are inlined.
+
+@usableFromInline
+@_silgen_name("marker1")
+func marker1() -> ()
+
+@usableFromInline
+@_silgen_name("marker2")
+func marker2() -> ()
+
+@usableFromInline
+@_silgen_name("marker3")
+func marker3() -> ()
+
+@usableFromInline
+@_silgen_name("marker4")
+func marker4() -> ()
+
+@usableFromInline
+@_silgen_name("marker5")
+func marker5() -> ()
+
+@usableFromInline
+@_silgen_name("marker6")
+func marker6() -> ()
+
+// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// CHECK:   begin_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF'
+
+// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// DESERIALIZED:   begin_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF'
+
+@inlinable
+@_semantics("optimize.sil.preserve_exclusivity")
+public func f1_beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+  marker1()
+  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f2___endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// CHECK:   end_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f2___endNoOptyyBpF'
+
+// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f2___endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// DESERIALIZED:   end_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f2___endNoOptyyBpF'
+
+@inlinable
+@_semantics("optimize.sil.preserve_exclusivity")
+public func f2___endNoOpt(_ address: Builtin.RawPointer) {
+  marker2()
+  Builtin.endUnpairedAccess(address)
+}
+
+// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// CHECK:   begin_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF
+
+// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// DESERIALIZED:   begin_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF
+
+@inlinable
+@_semantics("optimize.sil.preserve_exclusivity")
+public func f3__readNoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
+  marker3()
+  Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f4__testNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// DESERIALIZED: marker1
+// DESERIALIZED: begin_unpaired_access
+// DESERIALIZED: marker2
+// DESERIALIZED: end_unpaired_access
+// DESERIALIZED: marker3
+// DESERIALIZED: begin_unpaired_access
+// DESERIALIZED: return
+
+@inlinable
+public func f4__testNoOpt(_ k1: Builtin.RawPointer) {
+  f1_beginNoOpt(k1, k1, Builtin.RawPointer.self)
+  f2___endNoOpt(k1)
+  f3__readNoOpt(k1, Builtin.RawPointer.self)
+}
+
+// CHECK-LABEL: sil @$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// CHECK-NOT: begin_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF'
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
+// DESERIALIZED-NOT: begin_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF'
+
+@inlinable
+public func f5_beginDoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+  marker4()
+  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// CHECK-LABEL: sil @$S20preserve_exclusivity13f6___endDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// CHECK-NOT: end_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f6___endDoOptyyBpF'
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f6___endDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// DESERIALIZED-NOT: end_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f6___endDoOptyyBpF'
+
+@inlinable
+public func f6___endDoOpt(_ address: Builtin.RawPointer) {
+  marker5()
+  Builtin.endUnpairedAccess(address)
+}
+
+// CHECK-LABEL: sil @$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// CHECK-NOT: begin_unpaired_access
+// CHECK: } // end sil function '$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF'
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
+// DESERIALIZED-NOT: begin_unpaired_access
+// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF'
+
+@inlinable
+public func f7__readDoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
+  marker6()
+  Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
+// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f8__testDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
+// DESERIALIZED: marker4
+// DESERIALIZED: marker5
+// DESERIALIZED: marker6
+// DESERIALIZED: return
+@inlinable
+public func f8__testDoOpt(_ k1: Builtin.RawPointer) {
+  f5_beginDoOpt(k1, k1, Builtin.RawPointer.self)
+  f6___endDoOpt(k1)
+  f7__readDoOpt(k1, Builtin.RawPointer.self)
+}
diff --git a/test/Sema/diag_unowned_immediate_deallocation.swift b/test/Sema/diag_unowned_immediate_deallocation.swift
index 17fee42..56a79ea 100644
--- a/test/Sema/diag_unowned_immediate_deallocation.swift
+++ b/test/Sema/diag_unowned_immediate_deallocation.swift
@@ -15,256 +15,256 @@
 class D : C {}
 
 func testWeakVariableBindingDiag() throws {
-  weak var c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+  weak var c1 = C() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c1' declared here}}
   // expected-note@-3 {{'c1' declared here}}
 
-  c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+  c1 = C() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c2: C? = ModuleName.C() // expected-warning {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+  weak var c2: C? = ModuleName.C() // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c2' declared here}}
   // expected-note@-3 {{'c2' declared here}}
 
-  c2 = C() // expected-warning {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+  c2 = C() // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c3: C? = D() // expected-warning {{instance will be immediately deallocated as 'c3' is a 'weak' variable}}
+  weak var c3: C? = D() // expected-warning {{instance will be immediately deallocated because variable 'c3' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c3' declared here}}
   // expected-note@-3 {{'c3' declared here}}
 
-  c3 = D() // expected-warning {{instance will be immediately deallocated as 'c3' is a 'weak' variable}}
+  c3 = D() // expected-warning {{instance will be immediately deallocated because variable 'c3' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c4 = C(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c4' is a 'weak' variable}}
+  weak var c4 = C(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c4' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c4' declared here}}
   // expected-note@-3 {{'c4' declared here}}
 
-  c4 = C(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c4' is a 'weak' variable}}
+  c4 = C(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c4' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c5: C? = C(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c5' is a 'weak' variable}}
+  weak var c5: C? = C(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c5' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c5' declared here}}
   // expected-note@-3 {{'c5' declared here}}
 
-  c5 = C(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c5' is a 'weak' variable}}
+  c5 = C(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c5' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c6: C? = D(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c6' is a 'weak' variable}}
+  weak var c6: C? = D(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c6' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c6' declared here}}
   // expected-note@-3 {{'c6' declared here}}
 
-  c6 = D(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c6' is a 'weak' variable}}
+  c6 = D(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c6' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c7' is a 'weak' variable}}
+  weak var c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c7' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c7' declared here}}
   // expected-note@-3 {{'c7' declared here}}
 
-  c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c7' is a 'weak' variable}}
+  c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c7' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c8: C? = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c8' is a 'weak' variable}}
+  weak var c8: C? = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c8' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c8' declared here}}
   // expected-note@-3 {{'c8' declared here}}
 
-  c8 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c8' is a 'weak' variable}}
+  c8 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c8' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c9: C? = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c9' is a 'weak' variable}}
+  weak var c9: C? = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c9' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c9' declared here}}
   // expected-note@-3 {{'c9' declared here}}
 
-  c9 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c9' is a 'weak' variable}}
+  c9 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c9' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c10' is a 'weak' variable}}
+  weak var c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c10' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c10' declared here}}
   // expected-note@-3 {{'c10' declared here}}
 
-  c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c10' is a 'weak' variable}}
+  c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c10' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c11: C? = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c11' is a 'weak' variable}}
+  weak var c11: C? = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c11' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c11' declared here}}
   // expected-note@-3 {{'c11' declared here}}
 
-  c11 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c11' is a 'weak' variable}}
+  c11 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c11' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c12: C? = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c12' is a 'weak' variable}}
+  weak var c12: C? = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c12' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c12' declared here}}
   // expected-note@-3 {{'c12' declared here}}
 
-  c12 = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c12' is a 'weak' variable}}
+  c12 = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c12' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c13 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c13' is a 'weak' variable}}
+  weak var c13 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c13' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c13' declared here}}
   // expected-note@-3 {{'c13' declared here}}
 
-  c13 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c13' is a 'weak' variable}}
+  c13 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c13' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c14: C? = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c14' is a 'weak' variable}}
+  weak var c14: C? = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c14' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c14' declared here}}
   // expected-note@-3 {{'c14' declared here}}
 
-  c14 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c14' is a 'weak' variable}}
+  c14 = try? C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c14' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  weak var c15: C? = try? D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c15' is a 'weak' variable}}
+  weak var c15: C? = try? D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c15' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c15' declared here}}
   // expected-note@-3 {{'c15' declared here}}
 
-  c15 = try? D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c15' is a 'weak' variable}}
+  c15 = try? D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c15' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
   _ = c1; _ = c2; _ = c3; _ = c4; _ = c5; _ = c6; _ = c7; _ = c8; _ = c9; _ = c10; _ = c11; _ = c12; _ = c13; _ = c14; _ = c15
 }
 
 func testUnownedVariableBindingDiag() throws {
-  unowned(unsafe) var c = C() // expected-warning {{instance will be immediately deallocated as 'c' is an 'unowned' variable}}
+  unowned(unsafe) var c = C() // expected-warning {{instance will be immediately deallocated because variable 'c' is 'unowned(unsafe)'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c' declared here}}
   // expected-note@-3 {{'c' declared here}}
 
-  c = C() // expected-warning {{instance will be immediately deallocated as 'c' is an 'unowned' variable}}
+  c = C() // expected-warning {{instance will be immediately deallocated because variable 'c' is 'unowned(unsafe)'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' variable}}
+  unowned var c1 = C() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c1' declared here}}
   // expected-note@-3 {{'c1' declared here}}
 
-  c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' variable}}
+  c1 = C() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c2: C = ModuleName.C() // expected-warning {{instance will be immediately deallocated as 'c2' is an 'unowned' variable}}
+  unowned var c2: C = ModuleName.C() // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c2' declared here}}
   // expected-note@-3 {{'c2' declared here}}
 
-  c2 = C() // expected-warning {{instance will be immediately deallocated as 'c2' is an 'unowned' variable}}
+  c2 = C() // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c3: C = D() // expected-warning {{instance will be immediately deallocated as 'c3' is an 'unowned' variable}}
+  unowned var c3: C = D() // expected-warning {{instance will be immediately deallocated because variable 'c3' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c3' declared here}}
   // expected-note@-3 {{'c3' declared here}}
 
-  c3 = D() // expected-warning {{instance will be immediately deallocated as 'c3' is an 'unowned' variable}}
+  c3 = D() // expected-warning {{instance will be immediately deallocated because variable 'c3' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c4 = C(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c4' is an 'unowned' variable}}
+  unowned var c4 = C(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c4' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c4' declared here}}
   // expected-note@-3 {{'c4' declared here}}
 
-  c4 = C(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c4' is an 'unowned' variable}}
+  c4 = C(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c4' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c5: C = C(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c5' is an 'unowned' variable}}
+  unowned var c5: C = C(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c5' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c5' declared here}}
   // expected-note@-3 {{'c5' declared here}}
 
-  c5 = C(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c5' is an 'unowned' variable}}
+  c5 = C(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c5' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c6: C = D(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c6' is an 'unowned' variable}}
+  unowned var c6: C = D(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c6' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c6' declared here}}
   // expected-note@-3 {{'c6' declared here}}
 
-  c6 = D(failable: ())! // expected-warning {{instance will be immediately deallocated as 'c6' is an 'unowned' variable}}
+  c6 = D(failable: ())! // expected-warning {{instance will be immediately deallocated because variable 'c6' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c7' is an 'unowned' variable}}
+  unowned var c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c7' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c7' declared here}}
   // expected-note@-3 {{'c7' declared here}}
 
-  c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c7' is an 'unowned' variable}}
+  c7 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c7' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c8: C = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c8' is an 'unowned' variable}}
+  unowned var c8: C = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c8' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c8' declared here}}
   // expected-note@-3 {{'c8' declared here}}
 
-  c8 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c8' is an 'unowned' variable}}
+  c8 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c8' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c9: C = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c9' is an 'unowned' variable}}
+  unowned var c9: C = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c9' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c9' declared here}}
   // expected-note@-3 {{'c9' declared here}}
 
-  c9 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c9' is an 'unowned' variable}}
+  c9 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c9' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c10' is an 'unowned' variable}}
+  unowned var c10 = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c10' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c10' declared here}}
   // expected-note@-3 {{'c10' declared here}}
 
-  c10 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c10' is an 'unowned' variable}}
+  c10 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c10' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c11: C = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c11' is an 'unowned' variable}}
+  unowned var c11: C = try! C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c11' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c11' declared here}}
   // expected-note@-3 {{'c11' declared here}}
 
-  c11 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c11' is an 'unowned' variable}}
+  c11 = try C(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c11' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c12: C = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c12' is an 'unowned' variable}}
+  unowned var c12: C = try! D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c12' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c12' declared here}}
   // expected-note@-3 {{'c12' declared here}}
 
-  c12 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated as 'c12' is an 'unowned' variable}}
+  c12 = try D(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 'c12' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c13 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c13' is an 'unowned' variable}}
+  unowned var c13 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c13' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c13' declared here}}
   // expected-note@-3 {{'c13' declared here}}
 
-  c13 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c13' is an 'unowned' variable}}
+  c13 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c13' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c14: C = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c14' is an 'unowned' variable}}
+  unowned var c14: C = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c14' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c14' declared here}}
   // expected-note@-3 {{'c14' declared here}}
 
-  c14 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c14' is an 'unowned' variable}}
+  c14 = (try? C(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c14' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-  unowned var c15: C = (try? D(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c15' is an 'unowned' variable}}
+  unowned var c15: C = (try? D(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c15' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c15' declared here}}
   // expected-note@-3 {{'c15' declared here}}
 
-  c15 = (try? D(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 'c15' is an 'unowned' variable}}
+  c15 = (try? D(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 'c15' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
   _ = c; _ = c1; _ = c2; _ = c3; _ = c4; _ = c5; _ = c6; _ = c7; _ = c8; _ = c9; _ = c10; _ = c11; _ = c12; _ = c13; _ = c14; _ = c15
@@ -272,24 +272,24 @@
 
 func testMultipleBindingDiag() {
   weak var c1 = C(), c2: C? = C(), c3: C? = D()
-  // expected-warning@-1 {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+  // expected-warning@-1 {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'c1' declared here}}
-  // expected-warning@-4 {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+  // expected-warning@-4 {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
   // expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-6 {{'c2' declared here}}
-  // expected-warning@-7 {{instance will be immediately deallocated as 'c3' is a 'weak' variable}}
+  // expected-warning@-7 {{instance will be immediately deallocated because variable 'c3' is 'weak'}}
   // expected-note@-8 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-9 {{'c3' declared here}}
 
   unowned let c4 = C(), c5: C = C(), c6: C = D()
-  // expected-warning@-1 {{instance will be immediately deallocated as 'c4' is an 'unowned' variable}}
+  // expected-warning@-1 {{instance will be immediately deallocated because variable 'c4' is 'unowned'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'c4' declared here}}
-  // expected-warning@-4 {{instance will be immediately deallocated as 'c5' is an 'unowned' variable}}
+  // expected-warning@-4 {{instance will be immediately deallocated because variable 'c5' is 'unowned'}}
   // expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-6 {{'c5' declared here}}
-  // expected-warning@-7 {{instance will be immediately deallocated as 'c6' is an 'unowned' variable}}
+  // expected-warning@-7 {{instance will be immediately deallocated because variable 'c6' is 'unowned'}}
   // expected-note@-8 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-9 {{'c6' declared here}}
 
@@ -298,24 +298,24 @@
 
 func testTupleAndParenBinding() throws {
   weak var ((c1), c2, c3): (C?, C?, C?) = (C() as C, (D()), try D(throwing: ()))
-  // expected-warning@-1 {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+  // expected-warning@-1 {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'c1' declared here}}
-  // expected-warning@-4 {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+  // expected-warning@-4 {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
   // expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-6 {{'c2' declared here}}
-  // expected-warning@-7 {{instance will be immediately deallocated as 'c3' is a 'weak' variable}}
+  // expected-warning@-7 {{instance will be immediately deallocated because variable 'c3' is 'weak'}}
   // expected-note@-8 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-9 {{'c3' declared here}}
 
   unowned let ((c4), c5, c6): (C, C, C) = (C() as C, (D()), try D(throwing: ()))
-  // expected-warning@-1 {{instance will be immediately deallocated as 'c4' is an 'unowned' variable}}
+  // expected-warning@-1 {{instance will be immediately deallocated because variable 'c4' is 'unowned'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'c4' declared here}}
-  // expected-warning@-4 {{instance will be immediately deallocated as 'c5' is an 'unowned' variable}}
+  // expected-warning@-4 {{instance will be immediately deallocated because variable 'c5' is 'unowned'}}
   // expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-6 {{'c5' declared here}}
-  // expected-warning@-7 {{instance will be immediately deallocated as 'c6' is an 'unowned' variable}}
+  // expected-warning@-7 {{instance will be immediately deallocated because variable 'c6' is 'unowned'}}
   // expected-note@-8 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-9 {{'c6' declared here}}
 
@@ -323,65 +323,65 @@
 }
 
 func testInitializationThroughClassArchetypeDiag<T : ClassProtocol>(_ t: T, _ p: ClassProtocol) throws {
-  weak var t1: T? = T() // expected-warning {{instance will be immediately deallocated as 't1' is a 'weak' variable}}
+  weak var t1: T? = T() // expected-warning {{instance will be immediately deallocated because variable 't1' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'t1' declared here}}
 
-  weak var t2: ClassProtocol? = T(failable: ()) // expected-warning {{instance will be immediately deallocated as 't2' is a 'weak' variable}}
+  weak var t2: ClassProtocol? = T(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 't2' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'t2' declared here}}
 
-  unowned let t3 = try type(of: t).init(throwing: ()) // expected-warning {{instance will be immediately deallocated as 't3' is an 'unowned' variable}}
+  unowned let t3 = try type(of: t).init(throwing: ()) // expected-warning {{instance will be immediately deallocated because variable 't3' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'t3' declared here}}
 
-  unowned(unsafe) let t4 = type(of: p).init() // expected-warning {{instance will be immediately deallocated as 't4' is an 'unowned' variable}}
+  unowned(unsafe) let t4 = type(of: p).init() // expected-warning {{instance will be immediately deallocated because variable 't4' is 'unowned(unsafe)'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'t4' declared here}}
 
   let optionalTType: T.Type? = T.self
   let optionalPType: ClassProtocol.Type? = type(of: p)
 
-  weak var t5 = optionalTType?.init(failable: ()) // expected-warning {{instance will be immediately deallocated as 't5' is a 'weak' variable}}
+  weak var t5 = optionalTType?.init(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 't5' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'t5' declared here}}
 
-  unowned(unsafe) let t6 = try (optionalPType?.init(throwing: ()))! // expected-warning {{instance will be immediately deallocated as 't6' is an 'unowned' variable}}
+  unowned(unsafe) let t6 = try (optionalPType?.init(throwing: ()))! // expected-warning {{instance will be immediately deallocated because variable 't6' is 'unowned(unsafe)'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'t6' declared here}}
 
   _ = t1; _ = t2; _ = t3; _ = t4; _ = t5; _ = t6
 }
 
-weak var topLevelC = C() // expected-warning {{instance will be immediately deallocated as 'topLevelC' is a 'weak' variable}}
+weak var topLevelC = C() // expected-warning {{instance will be immediately deallocated because variable 'topLevelC' is 'weak'}}
 // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 // expected-note@-2 {{'topLevelC' declared here}}
 // expected-note@-3 {{'topLevelC' declared here}}
 
-topLevelC = C() // expected-warning {{instance will be immediately deallocated as 'topLevelC' is a 'weak' variable}}
+topLevelC = C() // expected-warning {{instance will be immediately deallocated because variable 'topLevelC' is 'weak'}}
 // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-unowned var topLevelC1 = C() // expected-warning {{instance will be immediately deallocated as 'topLevelC1' is an 'unowned' variable}}
+unowned var topLevelC1 = C() // expected-warning {{instance will be immediately deallocated because variable 'topLevelC1' is 'unowned'}}
 // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 // expected-note@-2 {{'topLevelC1' declared here}}
 // expected-note@-3 {{'topLevelC1' declared here}}
 
-topLevelC1 = C() // expected-warning {{instance will be immediately deallocated as 'topLevelC1' is an 'unowned' variable}}
+topLevelC1 = C() // expected-warning {{instance will be immediately deallocated because variable 'topLevelC1' is 'unowned'}}
 // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
 struct S {
   weak var c: C? // expected-note {{'c' declared here}}
 
-  unowned var c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' property}}
+  unowned var c1 = C() // expected-warning {{instance will be immediately deallocated because property 'c1' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c1' declared here}}
   // expected-note@-3 {{'c1' declared here}}
 
   mutating func foo() {
-    c = D() // expected-warning {{instance will be immediately deallocated as 'c' is a 'weak' property}}
+    c = D() // expected-warning {{instance will be immediately deallocated because property 'c' is 'weak'}}
     // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-    c1 = D() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' property}}
+    c1 = D() // expected-warning {{instance will be immediately deallocated because property 'c1' is 'unowned'}}
     // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   }
 }
@@ -389,27 +389,27 @@
 class C1 {
   weak var c: C? // expected-note {{'c' declared here}}
 
-  unowned var c1 = C() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' property}}
+  unowned var c1 = C() // expected-warning {{instance will be immediately deallocated because property 'c1' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c1' declared here}}
   // expected-note@-3 {{'c1' declared here}}
 
   func foo() {
-    c = D() // expected-warning {{instance will be immediately deallocated as 'c' is a 'weak' property}}
+    c = D() // expected-warning {{instance will be immediately deallocated because property 'c' is 'weak'}}
     // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
-    c1 = D() // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' property}}
+    c1 = D() // expected-warning {{instance will be immediately deallocated because property 'c1' is 'unowned'}}
     // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   }
 }
 
 func testInitializationThroughMetaclassDiag(_ t: C.Type) {
-  weak var c1: C? = t.init() // expected-warning {{instance will be immediately deallocated as 'c1' is a 'weak' variable}}
+  weak var c1: C? = t.init() // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c1' declared here}}
 
   let optionaCType: C.Type? = t
-  weak var c2 = optionaCType?.init(failable: ()) // expected-warning {{instance will be immediately deallocated as 'c2' is a 'weak' variable}}
+  weak var c2 = optionaCType?.init(failable: ()) // expected-warning {{instance will be immediately deallocated because variable 'c2' is 'weak'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c2' declared here}}
 
@@ -417,19 +417,19 @@
 }
 
 func testInitializationThroughTupleElementDiag() {
-  unowned var c1 = ((C() as C, C() as C) as (C, C)).0 // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' variable}}
+  unowned var c1 = ((C() as C, C() as C) as (C, C)).0 // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-2 {{'c1' declared here}}
   // expected-note@-3 {{'c1' declared here}}
 
-  c1 = ((C() as C, C() as C) as (C, C)).0 // expected-warning {{instance will be immediately deallocated as 'c1' is an 'unowned' variable}}
+  c1 = ((C() as C, C() as C) as (C, C)).0 // expected-warning {{instance will be immediately deallocated because variable 'c1' is 'unowned'}}
   // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 
   unowned let (c2, c3) = ((C() as C, C()) as (C, C), 5).0
-  // expected-warning@-1 {{instance will be immediately deallocated as 'c2' is an 'unowned' variable}}
+  // expected-warning@-1 {{instance will be immediately deallocated because variable 'c2' is 'unowned'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'c2' declared here}}
-  // expected-warning@-4 {{instance will be immediately deallocated as 'c3' is an 'unowned' variable}}
+  // expected-warning@-4 {{instance will be immediately deallocated because variable 'c3' is 'unowned'}}
   // expected-note@-5 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-6 {{'c3' declared here}}
 
@@ -440,7 +440,7 @@
 
 func testGenericWeakClassDiag() {
   weak var e = E<String>()
-  // expected-warning@-1 {{instance will be immediately deallocated as 'e' is a 'weak' variable}}
+  // expected-warning@-1 {{instance will be immediately deallocated because variable 'e' is 'weak'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'e' declared here}}
 
diff --git a/test/Sema/diag_unowned_immediate_deallocation_global.swift b/test/Sema/diag_unowned_immediate_deallocation_global.swift
index 5867f3b..3212aaa 100644
--- a/test/Sema/diag_unowned_immediate_deallocation_global.swift
+++ b/test/Sema/diag_unowned_immediate_deallocation_global.swift
@@ -4,11 +4,11 @@
   init() {}
 }
 
-weak var globalC = C() // expected-warning {{instance will be immediately deallocated as 'globalC' is a 'weak' variable}}
+weak var globalC = C() // expected-warning {{instance will be immediately deallocated because variable 'globalC' is 'weak'}}
 // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 // expected-note@-2 {{'globalC' declared here}}
 
-unowned var globalC1 = C() // expected-warning {{instance will be immediately deallocated as 'globalC1' is an 'unowned' variable}}
+unowned var globalC1 = C() // expected-warning {{instance will be immediately deallocated because variable 'globalC1' is 'unowned'}}
 // expected-note@-1 {{a strong reference is required to prevent the instance from being deallocated}}
 // expected-note@-2 {{'globalC1' declared here}}
 
diff --git a/test/Sema/exhaustive_switch.swift b/test/Sema/exhaustive_switch.swift
index 8ebbd02..69f243e 100644
--- a/test/Sema/exhaustive_switch.swift
+++ b/test/Sema/exhaustive_switch.swift
@@ -1,4 +1,5 @@
-// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-resilience -enable-nonfrozen-enum-exhaustivity-diagnostics
+// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-resilience
+// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-resilience -enable-nonfrozen-enum-exhaustivity-diagnostics
 
 func foo(a: Int?, b: Int?) -> Int {
   switch (a, b) {
@@ -852,7 +853,7 @@
   case .a: break
   }
 
-  switch value { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
+  switch value { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
   case .a: break
   case .b: break
   }
@@ -884,7 +885,7 @@
   }
 
   // Test being part of other spaces.
-  switch value as Optional { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.some(_)'}}
+  switch value as Optional { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '.some(_)'}}
   case .a?: break
   case .b?: break
   case nil: break
@@ -902,7 +903,7 @@
   case nil: break
   } // no-warning
 
-  switch (value, flag) { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, false)'}}
+  switch (value, flag) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, false)'}}
   case (.a, _): break
   case (.b, false): break
   case (_, true): break
@@ -915,7 +916,7 @@
   @unknown case _: break
   } // no-warning
 
-  switch (flag, value) { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(false, _)'}}
+  switch (flag, value) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(false, _)'}}
   case (_, .a): break
   case (false, .b): break
   case (true, _): break
@@ -928,7 +929,7 @@
   @unknown case _: break
   } // no-warning
 
-  switch (value, value) { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, _)'}}
+  switch (value, value) { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{add missing case: '(_, _)'}}
   case (.a, _), (_, .a): break
   case (.b, _), (_, .b): break
   }
@@ -940,7 +941,7 @@
   } // no-warning
 
   // Test interaction with @_downgrade_exhaustivity_check.
-  switch (value, interval) { // expected-error {{switch must be exhaustive}} {{none}}
+  switch (value, interval) { // expected-warning {{switch must be exhaustive}} {{none}}
   // expected-note@-1 {{add missing case: '(_, .milliseconds(_))'}}
   // expected-note@-2 {{add missing case: '(_, .microseconds(_))'}}
   // expected-note@-3 {{add missing case: '(_, .nanoseconds(_))'}}
@@ -950,7 +951,7 @@
   case (.b, _): break
   }
 
-  switch (value, interval) { // expected-error {{switch must be exhaustive}} {{none}}
+  switch (value, interval) { // expected-warning {{switch must be exhaustive}} {{none}}
   // expected-note@-1 {{add missing case: '(_, .seconds(_))'}}
   // expected-note@-2 {{add missing case: '(_, .milliseconds(_))'}}
   // expected-note@-3 {{add missing case: '(_, .microseconds(_))'}}
@@ -965,7 +966,7 @@
   case .a: break
   }
 
-  switch payload { // expected-error {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
+  switch payload { // expected-warning {{switch must be exhaustive}} {{none}} expected-note {{handle unknown values using "@unknown default"}} {{3-3=@unknown default:\n<#fatalError#>()\n}}
   case .a: break
   case .b: break
   }
diff --git a/test/Sema/exhaustive_switch_testable.swift b/test/Sema/exhaustive_switch_testable.swift
index c261434..a6db6da 100644
--- a/test/Sema/exhaustive_switch_testable.swift
+++ b/test/Sema/exhaustive_switch_testable.swift
@@ -1,7 +1,7 @@
 // RUN: %empty-directory(%t)
 // RUN: %target-swift-frontend -swift-version 5 -enable-resilience -enable-testing %S/Inputs/exhaustive_switch_testable_helper.swift -emit-module -o %t
-// RUN: %target-swift-frontend -typecheck %s -swift-version 5 -enable-nonfrozen-enum-exhaustivity-diagnostics -I %t -DTESTABLE -verify
-// RUN: not %target-swift-frontend -typecheck %s -swift-version 5 -enable-nonfrozen-enum-exhaustivity-diagnostics -I %t 2>&1 | %FileCheck -check-prefix=VERIFY-NON-FROZEN %s
+// RUN: %target-swift-frontend -typecheck %s -swift-version 5 -I %t -DTESTABLE -verify
+// RUN: %target-swift-frontend -typecheck %s -swift-version 5 -I %t 2>&1 | %FileCheck -check-prefix=VERIFY-NON-FROZEN %s
 
 #if TESTABLE
 @testable import exhaustive_switch_testable_helper
@@ -17,7 +17,7 @@
 }
 
 func testNonFrozen(_ e: NonFrozenEnum) -> Int {
-  // VERIFY-NON-FROZEN: exhaustive_switch_testable.swift:[[@LINE+1]]:{{[0-9]+}}: error: switch must be exhaustive
+  // VERIFY-NON-FROZEN: exhaustive_switch_testable.swift:[[@LINE+1]]:{{[0-9]+}}: warning: switch must be exhaustive
   switch e {
   case .a: return 1
   case .b, .c: return 2
diff --git a/test/SourceKit/CompileNotifications/args.swift b/test/SourceKit/CompileNotifications/args.swift
index 8e89a8e..fd01bf2 100644
--- a/test/SourceKit/CompileNotifications/args.swift
+++ b/test/SourceKit/CompileNotifications/args.swift
@@ -2,16 +2,14 @@
 // ARGS1: {
 // ARGS1:  key.notification: source.notification.compile-will-start
 // ARGS1:  key.filepath: "[[PATH:.*]]"
-// ARGS1:  key.compilerargs: [
-// ARGS1-NEXT:    [[PATH]]
-// ARGS1-NEXT:  ]
+// ARGS1:  key.compilerargs-string: "
+// ARGS1-LINE:    [[PATH]]
 
 // RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s -j 1000 | %FileCheck %s -check-prefix=ARGS2
 // ARGS2: {
 // ARGS2:  key.notification: source.notification.compile-will-start
 // ARGS2:  key.filepath: "[[PATH:.*]]"
-// ARGS2:  key.compilerargs: [
-// ARGS2-NEXT:    [[PATH]]
-// ARGS2-NEXT:    "-j"
-// ARGS2-NEXT:    "1000"
-// ARGS2-NEXT:  ]
+// ARGS2:  key.compilerargs-string: "
+// ARGS2-LINE:    [[PATH]]
+// ARGS2-LINE:    -j
+// ARGS2-LINE:    1000
diff --git a/test/SourceKit/CompileNotifications/diagnostics.swift b/test/SourceKit/CompileNotifications/diagnostics.swift
index 9d5eba8..83ea2ae 100644
--- a/test/SourceKit/CompileNotifications/diagnostics.swift
+++ b/test/SourceKit/CompileNotifications/diagnostics.swift
@@ -64,3 +64,7 @@
 // INVALID_ARG_CLANG-NEXT:     key.severity: source.diagnostic.severity.warning,
 // INVALID_ARG_CLANG-NEXT:     key.offset: 0
 // INVALID_ARG_CLANG-NEXT:     key.description: "argument unused
+
+// Ignore the spurious -wmo + -enable-batch-mode warning.
+// RUN: %sourcekitd-test -req=track-compiles == -req=sema %s -- %s -enable-batch-mode | %FileCheck %s -check-prefix=NODIAGS
+// RUN: %sourcekitd-test -req=track-compiles == -req=complete -offset=0 %s -- %s -enable-batch-mode | %FileCheck %s -check-prefix=NODIAGS
diff --git a/test/api-digester/Outputs/apinotes-migrator-gen-revert.json b/test/api-digester/Outputs/apinotes-migrator-gen-revert.json
new file mode 100644
index 0000000..2ddd405
--- /dev/null
+++ b/test/api-digester/Outputs/apinotes-migrator-gen-revert.json
@@ -0,0 +1,238 @@
+[
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertDictionaryKeyUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertDictionaryKeyUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertOptionalDictionaryKeyUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertOptionalDictionaryKeyUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributes:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributesArray:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertArrayMemberUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributesArray:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributesArray:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertArrayMemberUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributesArray:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributesArray:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertOptionalArrayMemberUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributesArray:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributesArray:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertOptionalArrayMemberUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingOptionalAttributesArray:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(cm)animalStatusSingleOptionalAttribute:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "RevertSimpleOptionalStringRepresentableUpdate",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(cm)animalStatusSingleOptionalAttribute:",
+    "LeftComment": "",
+    "RightUsr": "",
+    "RightComment": "",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(cm)animalStatusSingleAttribute:",
+    "LeftComment": "AnimalAttributeName",
+    "RightUsr": "",
+    "RightComment": "String",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "TypeDecl",
+    "NodeAnnotation": "Rename",
+    "ChildIndex": "0",
+    "LeftUsr": "c:objc(pl)TypeWithMethod",
+    "LeftComment": "SwiftTypeWithMethodRight",
+    "RightUsr": "",
+    "RightComment": "SwiftTypeWithMethodLeft",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "TypeMemberDiffItem",
+    "Usr": "c:@ANTGlobalValue",
+    "OldPrintedName": "newMember",
+    "OldTypeName": "NewType",
+    "NewPrintedName": "oldMember",
+    "NewTypeName": "OldType"
+  },
+  {
+    "DiffItemKind": "TypeMemberDiffItem",
+    "Usr": "c:objc(pl)TypeWithMethod(cm)plusPrint",
+    "OldPrintedName": "plusPrint()",
+    "OldTypeName": "SwiftTypeWithMethodRight",
+    "NewPrintedName": "plusPrint()",
+    "NewTypeName": "SwiftTypeWithMethodLeft"
+  }
+]
\ No newline at end of file
diff --git a/test/api-digester/apinotes-migrator-gen.swift b/test/api-digester/apinotes-migrator-gen.swift
index 6967dd3..6966ac9 100644
--- a/test/api-digester/apinotes-migrator-gen.swift
+++ b/test/api-digester/apinotes-migrator-gen.swift
@@ -6,3 +6,5 @@
 // RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump2.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -swift-version 4 -I %S/Inputs/APINotesRight
 // RUN: %api-digester -compare-sdk --input-paths %t.dump1.json -input-paths %t.dump2.json -o %t.result -json
 // RUN: diff -u %S/Outputs/apinotes-migrator-gen.json %t.result
+// RUN: %api-digester -compare-sdk --input-paths %t.dump2.json -input-paths %t.dump1.json -o %t.result -json
+// RUN: diff -u %S/Outputs/apinotes-migrator-gen-revert.json %t.result
diff --git a/test/api-digester/stdlib-stable.json b/test/api-digester/stdlib-stable.json
index f2f0e16..6f63b55 100644
--- a/test/api-digester/stdlib-stable.json
+++ b/test/api-digester/stdlib-stable.json
@@ -74020,7 +74020,7 @@
         {
           "kind": "Function",
           "name": "index",
-          "printedName": "index(of:)",
+          "printedName": "firstIndex(of:)",
           "declKind": "Func",
           "usr": "s:FesRxs10CollectionWx8Iterator7Element_s9EquatablerS_5indexFT2ofWxS0_S1___GSqwx5Index_",
           "location": "",
@@ -78173,7 +78173,7 @@
         {
           "kind": "Function",
           "name": "index",
-          "printedName": "index(of:)",
+          "printedName": "firstIndex(of:)",
           "declKind": "Func",
           "usr": "s:FVs3Set5indexFT2ofx_GSqGVs8SetIndexx__",
           "location": "",
diff --git a/test/attr/attributes.swift b/test/attr/attributes.swift
index b5c8a5a..18f87e0 100644
--- a/test/attr/attributes.swift
+++ b/test/attr/attributes.swift
@@ -159,12 +159,12 @@
 var weak7 : Int // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
 weak
 var weak8 : Class? = Ty0()
-// expected-warning@-1 {{instance will be immediately deallocated as 'weak8' is a 'weak' variable}}
+// expected-warning@-1 {{instance will be immediately deallocated because variable 'weak8' is 'weak'}}
 // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
 // expected-note@-3 {{'weak8' declared here}}
 
 unowned var weak9 : Class = Ty0()
-// expected-warning@-1 {{instance will be immediately deallocated as 'weak9' is an 'unowned' variable}}
+// expected-warning@-1 {{instance will be immediately deallocated because variable 'weak9' is 'unowned'}}
 // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
 // expected-note@-3 {{'weak9' declared here}}
 
diff --git a/test/attr/open.swift b/test/attr/open.swift
index 8da60b8..521d9ae 100644
--- a/test/attr/open.swift
+++ b/test/attr/open.swift
@@ -49,7 +49,6 @@
 open class AnOpenClass {
   open func openMethod() {}
   open var openVar: Int = 0
-  open let openLet: Int = 1 // Should this be allowed?
   open typealias MyInt = Int // expected-error {{only classes and overridable class members can be declared 'open'; use 'public'}}
   open subscript(_: MarkerForOpenSubscripts) -> Int {
     return 0
diff --git a/test/attr/open_swift4.swift b/test/attr/open_swift4.swift
new file mode 100644
index 0000000..0fc71ed
--- /dev/null
+++ b/test/attr/open_swift4.swift
@@ -0,0 +1,12 @@
+// RUN: %target-typecheck-verify-swift -swift-version 3
+// RUN: %target-typecheck-verify-swift -swift-version 4
+
+open class AnOpenClass {
+  open let openLet: Int = 1 // expected-warning {{'let' properties are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+  open static func test() {} // expected-warning {{static declarations are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+}
+
+final public class NonOpenClass {
+  open func test() {} // expected-warning {{members of 'final' classes are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+  open static func test() {} // expected-warning {{static declarations are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+}
diff --git a/test/attr/open_swift5.swift b/test/attr/open_swift5.swift
new file mode 100644
index 0000000..0423008
--- /dev/null
+++ b/test/attr/open_swift5.swift
@@ -0,0 +1,11 @@
+// RUN: %target-typecheck-verify-swift -swift-version 5
+
+open class AnOpenClass {
+  open let openLet: Int = 1 // expected-error {{'let' properties are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+  open static func test() {} // expected-error {{static declarations are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+}
+
+final public class NonOpenClass {
+  open func test() {} // expected-error {{members of 'final' classes are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+  open static func test() {} // expected-error {{static declarations are implicitly 'final'; use 'public' instead of 'open'}} {{3-7=public}}
+}
diff --git a/test/decl/ext/Inputs/extension-generic-objc-protocol.h b/test/decl/ext/Inputs/extension-generic-objc-protocol.h
new file mode 100644
index 0000000..4e8d268
--- /dev/null
+++ b/test/decl/ext/Inputs/extension-generic-objc-protocol.h
@@ -0,0 +1,19 @@
+@import Foundation;
+
+@interface OBJCGeneric<T> : NSObject
+@end
+
+@interface OBJCGenericSubclass<T, U>: OBJCGeneric<T>
+@end
+
+@interface OBJCNongenericSubclass: OBJCGenericSubclass<id, id>
+@end
+
+@protocol OBJCProtocol1
+@end
+
+@protocol OBJCProtocol2
+@end
+
+@protocol OBJCProtocol3
+@end
diff --git a/test/decl/ext/extension-generic-objc-protocol.swift b/test/decl/ext/extension-generic-objc-protocol.swift
index 0a58265..ddfc085 100644
--- a/test/decl/ext/extension-generic-objc-protocol.swift
+++ b/test/decl/ext/extension-generic-objc-protocol.swift
@@ -1,10 +1,12 @@
-// RUN: %target-swift-frontend -typecheck -verify %s
+// RUN: %target-swift-frontend -import-objc-header %S/Inputs/extension-generic-objc-protocol.h -typecheck -verify %s
 
 // REQUIRES: objc_interop
 
 import Foundation
 
 @objc protocol P {}
+@objc protocol Q {}
+@objc protocol R {}
 
 public class C1<T> {}
 extension C1: P {}
@@ -27,3 +29,32 @@
 
 extension SubInner: P {}
 // expected-error@-1 {{conformance of subclass of a class from generic context 'SubInner' to @objc protocol 'P' cannot be in an extension}}
+
+// Lightweight generic ObjC classes can still be extended to conform.
+
+extension OBJCGeneric: OBJCProtocol1 {}
+extension OBJCGeneric: P {}
+extension OBJCGenericSubclass: OBJCProtocol2 {}
+extension OBJCGenericSubclass: Q {}
+extension OBJCNongenericSubclass: OBJCProtocol3 {}
+extension OBJCNongenericSubclass: R {}
+
+public class SwiftSubclassOfObjCGeneric: OBJCGeneric<AnyObject> {}
+
+extension SwiftSubclassOfObjCGeneric: OBJCProtocol2 {}
+extension SwiftSubclassOfObjCGeneric: Q {}
+
+public class SwiftGenericSubclassOfObjCGeneric<T: AnyObject>
+  : OBJCGeneric<AnyObject>
+{}
+
+extension SwiftGenericSubclassOfObjCGeneric: OBJCProtocol2 {} // expected-error {{cannot be in an extension}}
+extension SwiftGenericSubclassOfObjCGeneric: Q {} // expected-error {{cannot be in an extension}}
+
+public class SwiftNongenericSubclassOfGenericSubclassOfObjCGeneric
+  : SwiftGenericSubclassOfObjCGeneric<AnyObject>
+{}
+
+extension SwiftNongenericSubclassOfGenericSubclassOfObjCGeneric: OBJCProtocol3 {} // expected-error {{cannot be in an extension}}
+extension SwiftNongenericSubclassOfGenericSubclassOfObjCGeneric: R {} // expected-error {{cannot be in an extension}}
+
diff --git a/test/decl/protocol/ownership_protocol.swift b/test/decl/protocol/ownership_protocol.swift
index b998a81..2fa4dac 100644
--- a/test/decl/protocol/ownership_protocol.swift
+++ b/test/decl/protocol/ownership_protocol.swift
@@ -3,10 +3,16 @@
 class SomeClass {}
 
 protocol P {
-  weak var foo: SomeClass? { get set } // expected-error {{'weak' cannot be applied to a property declaration in a protocol}}
-  unowned var foo2: SomeClass { get set } // expected-error {{'unowned' cannot be applied to a property declaration in a protocol}}
-  weak var foo3: Int? { get set } // expected-error {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}}
-  unowned var foo4: Int { get set } // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
+  // expected-error@+1 {{'weak' cannot be applied to a property declaration in a protocol}}
+  weak var foo: SomeClass? { get set }
+  // expected-error@+1 {{'unowned' cannot be applied to a property declaration in a protocol}}
+  unowned var foo2: SomeClass { get set }
+  // expected-error@+2 {{'weak' cannot be applied to a property declaration in a protocol}}
+  // expected-error@+1 {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}}
+  weak var foo3: Int? { get set }
+  // expected-error@+2 {{'unowned' cannot be applied to a property declaration in a protocol}}
+  // expected-error@+1 {{'unowned' may only be applied to class and class-bound protocol types, not 'Int'}}
+  unowned var foo4: Int { get set }
   var foo9: SomeClass? { get }
 }
 
diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift
index e0558fa..4c7ab82 100644
--- a/test/decl/protocol/protocols.swift
+++ b/test/decl/protocol/protocols.swift
@@ -465,6 +465,7 @@
 
 // rdar://problem/18168866
 protocol FirstProtocol {
+    // expected-warning@+1 {{'weak' should not be applied to a property declaration in a protocol and will be disallowed in future versions}}
     weak var delegate : SecondProtocol? { get } // expected-error{{'weak' must not be applied to non-class-bound 'SecondProtocol'; consider adding a protocol conformance that has a class bound}}
 }
 
diff --git a/test/decl/protocol/special/coding/Inputs/class_missing_init_multi1.swift b/test/decl/protocol/special/coding/Inputs/class_missing_init_multi1.swift
new file mode 100644
index 0000000..4e720b7
--- /dev/null
+++ b/test/decl/protocol/special/coding/Inputs/class_missing_init_multi1.swift
@@ -0,0 +1,3 @@
+class C1 : Decodable {
+  let str: String
+}
diff --git a/test/decl/protocol/special/coding/Inputs/class_missing_init_multi2.swift b/test/decl/protocol/special/coding/Inputs/class_missing_init_multi2.swift
new file mode 100644
index 0000000..82c142e
--- /dev/null
+++ b/test/decl/protocol/special/coding/Inputs/class_missing_init_multi2.swift
@@ -0,0 +1,3 @@
+class C2 : Decodable {
+  let c: C1
+}
diff --git a/test/decl/protocol/special/coding/class_codable_non_strong_vars.swift b/test/decl/protocol/special/coding/class_codable_non_strong_vars.swift
index 7071933..cfe2497 100644
--- a/test/decl/protocol/special/coding/class_codable_non_strong_vars.swift
+++ b/test/decl/protocol/special/coding/class_codable_non_strong_vars.swift
@@ -8,12 +8,12 @@
   }
 
   weak var x: NestedClass? = NestedClass()
-  // expected-warning@-1 {{instance will be immediately deallocated as 'x' is a 'weak' property}}
+  // expected-warning@-1 {{instance will be immediately deallocated because property 'x' is 'weak'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'x' declared here}}
 
   unowned var y: NestedClass = NestedClass()
-  // expected-warning@-1 {{instance will be immediately deallocated as 'y' is an 'unowned' property}}
+  // expected-warning@-1 {{instance will be immediately deallocated because property 'y' is 'unowned'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'y' declared here}}
 
diff --git a/test/decl/protocol/special/coding/class_missing_init_multi.swift b/test/decl/protocol/special/coding/class_missing_init_multi.swift
new file mode 100644
index 0000000..b6b394c
--- /dev/null
+++ b/test/decl/protocol/special/coding/class_missing_init_multi.swift
@@ -0,0 +1,8 @@
+// RUN: %target-typecheck-verify-swift -verify %S/Inputs/class_missing_init_multi1.swift %S/Inputs/class_missing_init_multi2.swift
+// RUN: %target-typecheck-verify-swift -verify %S/Inputs/class_missing_init_multi2.swift %S/Inputs/class_missing_init_multi1.swift
+
+// RUN: %target-typecheck-verify-swift -verify -primary-file %S/Inputs/class_missing_init_multi1.swift %S/Inputs/class_missing_init_multi2.swift
+// RUN: %target-typecheck-verify-swift -verify %S/Inputs/class_missing_init_multi1.swift -primary-file %S/Inputs/class_missing_init_multi2.swift
+
+// RUN: %target-typecheck-verify-swift -verify -primary-file %S/Inputs/class_missing_init_multi2.swift %S/Inputs/class_missing_init_multi1.swift
+// RUN: %target-typecheck-verify-swift -verify %S/Inputs/class_missing_init_multi2.swift -primary-file %S/Inputs/class_missing_init_multi1.swift
diff --git a/test/decl/protocol/special/coding/struct_codable_non_strong_vars.swift b/test/decl/protocol/special/coding/struct_codable_non_strong_vars.swift
index 7f98b2a..2d02f4a 100644
--- a/test/decl/protocol/special/coding/struct_codable_non_strong_vars.swift
+++ b/test/decl/protocol/special/coding/struct_codable_non_strong_vars.swift
@@ -8,12 +8,12 @@
   }
 
   weak var x: NestedClass? = NestedClass()
-  // expected-warning@-1 {{instance will be immediately deallocated as 'x' is a 'weak' property}}
+  // expected-warning@-1 {{instance will be immediately deallocated because property 'x' is 'weak'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'x' declared here}}
 
   unowned var y: NestedClass = NestedClass()
-  // expected-warning@-1 {{instance will be immediately deallocated as 'y' is an 'unowned' property}}
+  // expected-warning@-1 {{instance will be immediately deallocated because property 'y' is 'unowned'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'y' declared here}}
 
diff --git a/test/decl/var/properties.swift b/test/decl/var/properties.swift
index dac9213..c74e41d 100644
--- a/test/decl/var/properties.swift
+++ b/test/decl/var/properties.swift
@@ -114,7 +114,7 @@
   // applied to the getter.
   weak
   var foo: SomeClass? = SomeClass()  // expected-warning {{variable 'foo' was written to, but never read}}
-  // expected-warning@-1 {{instance will be immediately deallocated as 'foo' is a 'weak' variable}}
+  // expected-warning@-1 {{instance will be immediately deallocated because variable 'foo' is 'weak'}}
   // expected-note@-2 {{a strong reference is required to prevent the instance from being deallocated}}
   // expected-note@-3 {{'foo' declared here}}
   return 0
@@ -1106,16 +1106,16 @@
 }
 
 class OwnershipBadSub : OwnershipBase {
-  override weak var strongVar: AnyObject? { // expected-error {{cannot override strong property with weak property}}
+  override weak var strongVar: AnyObject? { // expected-error {{cannot override 'strong' property with 'weak' property}}
     didSet {}
   }
-  override unowned var weakVar: AnyObject? { // expected-error {{'unowned' may only be applied to class and class-bound protocol types, not 'AnyObject?'}}
+  override unowned var weakVar: AnyObject? { // expected-error {{'unowned' variable cannot have optional type}}
     didSet {}
   }
   override weak var unownedVar: AnyObject { // expected-error {{'weak' variable should have optional type 'AnyObject?'}}
     didSet {}
   }
-  override unowned var unownedUnsafeVar: AnyObject { // expected-error {{cannot override unowned(unsafe) property with unowned property}}
+  override unowned var unownedUnsafeVar: AnyObject { // expected-error {{cannot override 'unowned(unsafe)' property with 'unowned' property}}
     didSet {}
   }
 }
diff --git a/test/refactoring/RefactoringKind/crashers.swift b/test/refactoring/RefactoringKind/crashers.swift
index fd0faa0..1bb893b 100644
--- a/test/refactoring/RefactoringKind/crashers.swift
+++ b/test/refactoring/RefactoringKind/crashers.swift
@@ -11,3 +11,12 @@
 // RUN: %refactor -source-filename %s -pos=6:5 -end-pos=6:13 | %FileCheck %s -check-prefix=CHECK1
 // RUN: %refactor -source-filename %s -pos=8:1 -end-pos=8:13 | %FileCheck %s -check-prefix=CHECK1
 // CHECK1: Action begins
+
+// rdar://33972653
+func test() {
+  break FOO
+  continue FOO
+}
+
+// RUN: %refactor -source-filename %s -pos=17:3 -end-pos=18:15 | %FileCheck %s -check-prefix=CHECK2
+// CHECK2: Action begins
diff --git a/test/stdlib/CodableMultifile.swift b/test/stdlib/CodableMultifile.swift
new file mode 100644
index 0000000..cdfc541
--- /dev/null
+++ b/test/stdlib/CodableMultifile.swift
@@ -0,0 +1,79 @@
+// RUN: %empty-directory(%t)
+// RUN: cp %s %t/main.swift
+// RUN: %target-build-swift %t/main.swift %S/Inputs/CodableMultifileOther.swift -module-name main -o %t/main
+// RUN: %target-run %t/main
+// REQUIRES: executable_test
+
+// FIXME: This test could run on Linux too, if we could either use
+// corelibs-foundation, or implement a mock Encoder for testing.
+
+// REQUIRES: objc_interop
+
+import StdlibUnittest
+import Foundation
+
+var CodableMultifileTestSuite = TestSuite("CodableMultifile")
+
+// The first test doesn't synthesize encode(to:) at all.
+CodableMultifileTestSuite.test("1") {
+  let derived = DerivedFirst()
+
+  // Make sure the vtable offset matches between this translation unit and
+  // the other file, which requires us to force the encode(to:) member when
+  // type checking this translation unit.
+  expectEqual(false, derived.derivedMember)
+}
+
+// The second test synthesizes init(from:) before encode(to:).
+
+// We define a wrapper so that the virtual method BaseSecond.encode(to:) method
+// is called from outside its module. If we use the conformance of BaseSecond
+// to Codable, we don't expose the bug because the virtual method call is
+// encapsulated in the conformance, which is emitted in the same translation unit
+// as BaseSecond.
+struct WrapperSecond : Encodable {
+  let base: BaseSecond
+
+  func encode(to encoder: Encoder) throws {
+    try base.encode(to: encoder)
+  }
+}
+
+CodableMultifileTestSuite.test("2") {
+  // Make sure we synthesize the init(from:) member before encode(to:) in
+  // this translation unit.
+  _ = BaseSecond.init(from:)
+
+  let base = WrapperSecond(base: BaseSecond())
+  let encoder = JSONEncoder()
+
+  expectEqual(
+    "{\"baseMember\":2}",
+    String(data: try! encoder.encode(base), encoding: .utf8)!)
+}
+
+// The third test synthesizes encode(to:) before init(from:).
+
+// See above.
+struct WrapperThird : Encodable {
+  let base: BaseThird
+
+  func encode(to encoder: Encoder) throws {
+    try base.encode(to: encoder)
+  }
+}
+
+CodableMultifileTestSuite.test("3") {
+  // Make sure we synthesize the encode(to:) member before init(from:) in
+  // this translation unit.
+  _ = BaseThird.encode(to:)
+
+  let base = WrapperThird(base: BaseThird())
+  let encoder = JSONEncoder()
+
+  expectEqual(
+    "{\"baseMember\":3}",
+    String(data: try! encoder.encode(base), encoding: .utf8)!)
+}
+
+runAllTests()
diff --git a/test/stdlib/ErrorBridgedStatic.swift b/test/stdlib/ErrorBridgedStatic.swift
index 7638c15..8ac9677 100644
--- a/test/stdlib/ErrorBridgedStatic.swift
+++ b/test/stdlib/ErrorBridgedStatic.swift
@@ -8,6 +8,9 @@
 // REQUIRES: objc_interop
 // REQUIRES: static_stdlib
 
+// rdar://39473208
+// REQUIRES: asserts
+
 import StdlibUnittest
 
 class Bar: Foo {
diff --git a/test/stdlib/ErrorHandling.swift b/test/stdlib/ErrorHandling.swift
index ea5d427..945b0dc 100644
--- a/test/stdlib/ErrorHandling.swift
+++ b/test/stdlib/ErrorHandling.swift
@@ -95,9 +95,9 @@
   // TODO: Some way to check string was deallocated?
 }
 
-ErrorHandlingTests.test("ErrorHandling/index(where:)") {
+ErrorHandlingTests.test("ErrorHandling/firstIndex(where:)") {
   do {
-    let _: Int? = try [1, 2, 3].index {
+    let _: Int? = try [1, 2, 3].firstIndex {
       throw SillyError.JazzHands
       return $0 == $0
     }
diff --git a/test/stdlib/FloatingPoint.swift.gyb b/test/stdlib/FloatingPoint.swift.gyb
index fa98f1b..ab8658e 100644
--- a/test/stdlib/FloatingPoint.swift.gyb
+++ b/test/stdlib/FloatingPoint.swift.gyb
@@ -4,10 +4,6 @@
 // RUN: %line-directive %t/FloatingPoint.swift -- %target-run %t/a.out
 // REQUIRES: executable_test
 
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
 import Swift
 import StdlibUnittest
 
@@ -64,14 +60,24 @@
 #if arch(i386) || arch(x86_64)
 %   end
 func expectBitwiseEqual(
-  _ expected: ${FloatTy}, _ actual: ${FloatTy}, ${TRACE}
+  _ expected: ${FloatTy}, _ actual: ${FloatTy},
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
-  expectEqual(expected.bitPattern, actual.bitPattern, ${trace})
+  expectEqual(expected.bitPattern, actual.bitPattern, message(),
+  stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 func expectBitwiseEqual(
-  bitPattern expected: ${BitPatternTy}, _ actual: ${FloatTy}, ${TRACE}
+  bitPattern expected: ${BitPatternTy}, _ actual: ${FloatTy},
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
 ) {
-  expectBitwiseEqual(${FloatTy}(bitPattern: expected), actual, ${trace})
+  expectBitwiseEqual(${FloatTy}(bitPattern: expected), actual, message(),
+  stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 }
 %   if FloatTy == 'Float80':
 #endif
diff --git a/test/stdlib/IndexOfRenaming.swift b/test/stdlib/IndexOfRenaming.swift
new file mode 100644
index 0000000..7b332d6
--- /dev/null
+++ b/test/stdlib/IndexOfRenaming.swift
@@ -0,0 +1,8 @@
+// RUN: %target-typecheck-verify-swift
+
+let a = [10, 20, 30, 40, 50, 60]
+
+_ = a.index(of: 30)
+_ = a.firstIndex(of: 30)
+_ = a.index(where: { $0 > 30 })
+_ = a.firstIndex(where: { $0 > 30 })
diff --git a/test/stdlib/Inputs/CodableMultifileOther.swift b/test/stdlib/Inputs/CodableMultifileOther.swift
new file mode 100644
index 0000000..e527353
--- /dev/null
+++ b/test/stdlib/Inputs/CodableMultifileOther.swift
@@ -0,0 +1,21 @@
+class BaseFirst: Codable {
+  var baseMember = 1
+
+  init() {}
+}
+
+class DerivedFirst: BaseFirst {
+  var derivedMember = false
+}
+
+class BaseSecond: Codable {
+  var baseMember = 2
+
+  init() {}
+}
+
+class BaseThird: Codable {
+  var baseMember = 3
+
+  init() {}
+}
diff --git a/test/stdlib/Inputs/Mirror/MirrorOther.swift b/test/stdlib/Inputs/Mirror/MirrorOther.swift
new file mode 100644
index 0000000..ee9c176
--- /dev/null
+++ b/test/stdlib/Inputs/Mirror/MirrorOther.swift
@@ -0,0 +1,7 @@
+struct OtherStruct {
+  let a: OtherOuter.Inner
+  let b: OtherOuterGeneric<Int>.Inner<String>
+}
+
+struct OtherOuter {}
+struct OtherOuterGeneric<T> {}
diff --git a/test/stdlib/Mirror.swift b/test/stdlib/Mirror.swift
index 1f23fb3..14ab6b3 100644
--- a/test/stdlib/Mirror.swift
+++ b/test/stdlib/Mirror.swift
@@ -10,13 +10,14 @@
 //
 //===----------------------------------------------------------------------===//
 // RUN: %empty-directory(%t)
+// RUN: cp %s %t/main.swift
 //
 // RUN: if [ %target-runtime == "objc" ]; \
 // RUN: then \
 // RUN:   %target-clang %S/Inputs/Mirror/Mirror.mm -c -o %t/Mirror.mm.o -g && \
-// RUN:   %target-build-swift %s -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o -o %t/Mirror; \
+// RUN:   %target-build-swift %t/main.swift %S/Inputs/Mirror/MirrorOther.swift -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o -o %t/Mirror; \
 // RUN: else \
-// RUN:   %target-build-swift %s -o %t/Mirror; \
+// RUN:   %target-build-swift %t/main.swift %S/Inputs/Mirror/MirrorOther.swift -o %t/Mirror; \
 // RUN: fi
 // RUN: %target-run %t/Mirror
 // REQUIRES: executable_test
@@ -111,7 +112,7 @@
   let description = y.testDescription
   expectEqual(
     "[nil: \"a\", nil: \"b\", nil: \"c\", nil: \"",
-    description[description.startIndex..<description.index(of: "d")!])
+    description[description.startIndex..<description.firstIndex(of: "d")!])
 }
 
 mirrors.test("LabeledStructure") {
@@ -222,6 +223,12 @@
 //===----------------------------------------------------------------------===//
 //===--- Class Support ----------------------------------------------------===//
 
+class DullClass {}
+
+mirrors.test("ClassReflection") {
+  expectEqual(.`class`, Mirror(reflecting: DullClass()).displayStyle)
+}
+
 mirrors.test("Class/Root/Uncustomized") {
   class A { var a: Int = 1 }
 
@@ -358,6 +365,7 @@
 
 #if _runtime(_ObjC)
 import Foundation
+import MirrorObjC
 
 //===--- ObjC Base Classes ------------------------------------------------===//
 
@@ -464,6 +472,14 @@
     }
   }
 }
+
+mirrors.test("ObjC") {
+  // Some Foundation classes lie about their ivars, which would crash
+  // a mirror; make sure we are not automatically exposing ivars of
+  // Objective-C classes from the default mirror implementation.
+  expectEqual(0, Mirror(reflecting: HasIVars()).children.count)
+}
+
 #endif // _runtime(_ObjC)
 
 //===--- Suppressed Superclass Mirrors ------------------------------------===//
@@ -643,7 +659,7 @@
   }
 }
 
-//===--- End Class Support ------------------------------------------------===//
+//===--- Miscellaneous ----------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 
 mirrors.test("Addressing") {
@@ -766,16 +782,6 @@
   }
 }
 
-#if _runtime(_ObjC)
-import MirrorObjC
-mirrors.test("ObjC") {
-  // Some Foundation classes lie about their ivars, which would crash
-  // a mirror; make sure we are not automatically exposing ivars of
-  // Objective-C classes from the default mirror implementation.
-  expectEqual(0, Mirror(reflecting: HasIVars()).children.count)
-}
-#endif
-
 mirrors.test("String.init") {
   expectEqual("42", String(42))
   expectEqual("42", String("42"))
@@ -783,6 +789,949 @@
   expectEqual("\"42\"", String(reflecting: "42"))
 }
 
+//===--- Structs ----------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+struct StructWithDefaultMirror {
+  let s: String
+
+  init (_ s: String) {
+    self.s = s
+  }
+}
+
+mirrors.test("Struct/NonGeneric/DefaultMirror") {
+  do {
+    var output = ""
+    dump(StructWithDefaultMirror("123"), to: &output)
+    expectEqual("▿ Mirror.StructWithDefaultMirror\n  - s: \"123\"\n", output)
+  }
+
+  do {
+    // Build a String around an interpolation as a way of smoke-testing that
+    // the internal _Mirror implementation gets memory management right.
+    var output = ""
+    dump(StructWithDefaultMirror("\(456)"), to: &output)
+    expectEqual("▿ Mirror.StructWithDefaultMirror\n  - s: \"456\"\n", output)
+  }
+
+  expectEqual(
+    .`struct`,
+    Mirror(reflecting: StructWithDefaultMirror("")).displayStyle)
+}
+
+struct GenericStructWithDefaultMirror<T, U> {
+  let first: T
+  let second: U
+}
+
+mirrors.test("Struct/Generic/DefaultMirror") {
+  do {
+    var value = GenericStructWithDefaultMirror<Int, [Any?]>(
+      first: 123,
+      second: ["abc", 456, 789.25])
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ Mirror.GenericStructWithDefaultMirror<Swift.Int, Swift.Array<Swift.Optional<Any>>>\n" +
+      "  - first: 123\n" +
+      "  ▿ second: 3 elements\n" +
+      "    ▿ Optional(\"abc\")\n" +
+      "      - some: \"abc\"\n" +
+      "    ▿ Optional(456)\n" +
+      "      - some: 456\n" +
+      "    ▿ Optional(789.25)\n" +
+      "      - some: 789.25\n"
+
+    expectEqual(expected, output)
+
+  }
+}
+
+//===--- Enums ------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+enum NoPayloadEnumWithDefaultMirror {
+  case A, ß
+}
+
+mirrors.test("Enum/NoPayload/DefaultMirror") {
+  do {
+    let value: [NoPayloadEnumWithDefaultMirror] =
+        [.A, .ß]
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ 2 elements\n" +
+      "  - Mirror.NoPayloadEnumWithDefaultMirror.A\n" +
+      "  - Mirror.NoPayloadEnumWithDefaultMirror.ß\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+enum SingletonNonGenericEnumWithDefaultMirror {
+  case OnlyOne(Int)
+}
+
+mirrors.test("Enum/SingletonNonGeneric/DefaultMirror") {
+  do {
+    let value = SingletonNonGenericEnumWithDefaultMirror.OnlyOne(5)
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ Mirror.SingletonNonGenericEnumWithDefaultMirror.OnlyOne\n" +
+      "  - OnlyOne: 5\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+enum SingletonGenericEnumWithDefaultMirror<T> {
+  case OnlyOne(T)
+}
+
+mirrors.test("Enum/SingletonGeneric/DefaultMirror") {
+  do {
+    let value = SingletonGenericEnumWithDefaultMirror.OnlyOne("IIfx")
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ Mirror.SingletonGenericEnumWithDefaultMirror<Swift.String>.OnlyOne\n" +
+      "  - OnlyOne: \"IIfx\"\n"
+
+    expectEqual(expected, output)
+  }
+  expectEqual(0, LifetimeTracked.instances)
+  do {
+    let value = SingletonGenericEnumWithDefaultMirror.OnlyOne(
+        LifetimeTracked(0))
+    expectEqual(1, LifetimeTracked.instances)
+    var output = ""
+    dump(value, to: &output)
+  }
+  expectEqual(0, LifetimeTracked.instances)
+}
+
+enum SinglePayloadNonGenericEnumWithDefaultMirror {
+  case Cat
+  case Dog
+  case Volleyball(String, Int)
+}
+
+mirrors.test("Enum/SinglePayloadNonGeneric/DefaultMirror") {
+  do {
+    let value: [SinglePayloadNonGenericEnumWithDefaultMirror] =
+        [.Cat,
+         .Dog,
+         .Volleyball("Wilson", 2000)]
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ 3 elements\n" +
+      "  - Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Cat\n" +
+      "  - Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Dog\n" +
+      "  ▿ Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Volleyball\n" +
+      "    ▿ Volleyball: (2 elements)\n" +
+      "      - .0: \"Wilson\"\n" +
+      "      - .1: 2000\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+enum SinglePayloadGenericEnumWithDefaultMirror<T, U> {
+  case Well
+  case Faucet
+  case Pipe(T, U)
+}
+
+mirrors.test("Enum/SinglePayloadGeneric/DefaultMirror") {
+  do {
+    let value: [SinglePayloadGenericEnumWithDefaultMirror<Int, [Int]>] =
+        [.Well,
+         .Faucet,
+         .Pipe(408, [415])]
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ 3 elements\n" +
+      "  - Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Well\n" +
+      "  - Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Faucet\n" +
+      "  ▿ Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Pipe\n" +
+      "    ▿ Pipe: (2 elements)\n" +
+      "      - .0: 408\n" +
+      "      ▿ .1: 1 element\n" +
+      "        - 415\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+enum MultiPayloadTagBitsNonGenericEnumWithDefaultMirror {
+  case Plus
+  case SE30
+  case Classic(mhz: Int)
+  case Performa(model: Int)
+}
+
+mirrors.test("Enum/MultiPayloadTagBitsNonGeneric/DefaultMirror") {
+  do {
+    let value: [MultiPayloadTagBitsNonGenericEnumWithDefaultMirror] =
+        [.Plus,
+         .SE30,
+         .Classic(mhz: 16),
+         .Performa(model: 220)]
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ 4 elements\n" +
+      "  - Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Plus\n" +
+      "  - Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.SE30\n" +
+      "  ▿ Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Classic\n" +
+      "    ▿ Classic: (1 element)\n" +
+      "      - mhz: 16\n" +
+      "  ▿ Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Performa\n" +
+      "    ▿ Performa: (1 element)\n" +
+      "      - model: 220\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+class Floppy {
+  let capacity: Int
+
+  init(capacity: Int) { self.capacity = capacity }
+}
+
+class CDROM {
+  let capacity: Int
+
+  init(capacity: Int) { self.capacity = capacity }
+}
+
+enum MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror {
+  case MacWrite
+  case MacPaint
+  case FileMaker
+  case ClarisWorks(floppy: Floppy)
+  case HyperCard(cdrom: CDROM)
+}
+
+mirrors.test("Enum/MultiPayloadSpareBitsNonGeneric/DefaultMirror") {
+  do {
+    let value: [MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror] =
+        [.MacWrite,
+         .MacPaint,
+         .FileMaker,
+         .ClarisWorks(floppy: Floppy(capacity: 800)),
+         .HyperCard(cdrom: CDROM(capacity: 600))]
+
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ 5 elements\n" +
+      "  - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacWrite\n" +
+      "  - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacPaint\n" +
+      "  - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.FileMaker\n" +
+      "  ▿ Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
+      "    ▿ ClarisWorks: (1 element)\n" +
+      "      ▿ floppy: Mirror.Floppy #0\n" +
+      "        - capacity: 800\n" +
+      "  ▿ Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.HyperCard\n" +
+      "    ▿ HyperCard: (1 element)\n" +
+      "      ▿ cdrom: Mirror.CDROM #1\n" +
+      "        - capacity: 600\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+enum MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror {
+  case MacWrite
+  case MacPaint
+  case FileMaker
+  case ClarisWorks(floppy: Bool)
+  case HyperCard(cdrom: Bool)
+}
+
+mirrors.test("Enum/MultiPayloadTagBitsSmallNonGeneric/DefaultMirror") {
+  do {
+    let value: [MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror] =
+        [.MacWrite,
+         .MacPaint,
+         .FileMaker,
+         .ClarisWorks(floppy: true),
+         .HyperCard(cdrom: false)]
+
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ 5 elements\n" +
+      "  - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacWrite\n" +
+      "  - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacPaint\n" +
+      "  - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.FileMaker\n" +
+      "  ▿ Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
+      "    ▿ ClarisWorks: (1 element)\n" +
+      "      - floppy: true\n" +
+      "  ▿ Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.HyperCard\n" +
+      "    ▿ HyperCard: (1 element)\n" +
+      "      - cdrom: false\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+enum MultiPayloadGenericEnumWithDefaultMirror<T, U> {
+  case IIe
+  case IIgs
+  case Centris(ram: T)
+  case Quadra(hdd: U)
+  case PowerBook170
+  case PowerBookDuo220
+}
+
+mirrors.test("Enum/MultiPayloadGeneric/DefaultMirror") {
+  do {
+    let value: [MultiPayloadGenericEnumWithDefaultMirror<Int, String>] =
+        [.IIe,
+         .IIgs,
+         .Centris(ram: 4096),
+         .Quadra(hdd: "160MB"),
+         .PowerBook170,
+         .PowerBookDuo220]
+
+    var output = ""
+    dump(value, to: &output)
+
+    let expected =
+      "▿ 6 elements\n" +
+      "  - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIe\n" +
+      "  - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIgs\n" +
+      "  ▿ Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Centris\n" +
+      "    ▿ Centris: (1 element)\n" +
+      "      - ram: 4096\n" +
+      "  ▿ Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Quadra\n" +
+      "    ▿ Quadra: (1 element)\n" +
+      "      - hdd: \"160MB\"\n" +
+      "  - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBook170\n" +
+      "  - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBookDuo220\n"
+
+    expectEqual(expected, output)
+  }
+  expectEqual(0, LifetimeTracked.instances)
+  do {
+    let value = MultiPayloadGenericEnumWithDefaultMirror<LifetimeTracked,
+                                                         LifetimeTracked>
+        .Quadra(hdd: LifetimeTracked(0))
+    expectEqual(1, LifetimeTracked.instances)
+    var output = ""
+    dump(value, to: &output)
+  }
+  expectEqual(0, LifetimeTracked.instances)
+}
+
+enum Foo<T> {
+  indirect case Foo(Int)
+  case Bar(T)
+}
+
+enum List<T> {
+  case Nil
+  indirect case Cons(first: T, rest: List<T>)
+}
+
+mirrors.test("Enum/IndirectGeneric/DefaultMirror") {
+  let x = Foo<String>.Foo(22)
+  let y = Foo<String>.Bar("twenty-two")
+
+  expectEqual("\(x)", "Foo(22)")
+  expectEqual("\(y)", "Bar(\"twenty-two\")")
+
+  let list = List.Cons(first: 0, rest: .Cons(first: 1, rest: .Nil))
+  expectEqual("Cons(first: 0, rest: Mirror.List<Swift.Int>.Cons(first: 1, rest: Mirror.List<Swift.Int>.Nil))",
+    "\(list)")
+}
+
+enum MyError: Error {
+  case myFirstError(LifetimeTracked)
+}
+
+mirrors.test("Enum/CaseName/Error") {
+  // Just make sure this doesn't leak.
+  let e: Error = MyError.myFirstError(LifetimeTracked(0))
+  _ = String(describing: e)
+}
+
+class Brilliant : CustomReflectable {
+  let first: Int
+  let second: String
+
+  init(_ fst: Int, _ snd: String) {
+    self.first = fst
+    self.second = snd
+  }
+
+  var customMirror: Mirror {
+    return Mirror(self, children: ["first": first, "second": second, "self": self])
+  }
+}
+
+//===--- Custom mirrors ---------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+/// Subclasses inherit their parents' custom mirrors.
+class Irradiant : Brilliant {
+  init() {
+    super.init(400, "")
+  }
+}
+
+mirrors.test("CustomMirror") {
+  do {
+    var output = ""
+    dump(Brilliant(123, "four five six"), to: &output)
+
+    let expected =
+      "▿ Mirror.Brilliant #0\n" +
+      "  - first: 123\n" +
+      "  - second: \"four five six\"\n" +
+      "  ▿ self: Mirror.Brilliant #0\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    var output = ""
+    dump(Brilliant(123, "four five six"), to: &output, maxDepth: 0)
+    expectEqual("▹ Mirror.Brilliant #0\n", output)
+  }
+
+  do {
+    var output = ""
+    dump(Brilliant(123, "four five six"), to: &output, maxItems: 3)
+
+    let expected =
+      "▿ Mirror.Brilliant #0\n" +
+      "  - first: 123\n" +
+      "  - second: \"four five six\"\n" +
+      "    (1 more child)\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    var output = ""
+    dump(Brilliant(123, "four five six"), to: &output, maxItems: 2)
+
+    let expected =
+      "▿ Mirror.Brilliant #0\n" +
+      "  - first: 123\n" +
+      "    (2 more children)\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    var output = ""
+    dump(Brilliant(123, "four five six"), to: &output, maxItems: 1)
+
+    let expected =
+      "▿ Mirror.Brilliant #0\n" +
+      "    (3 children)\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+mirrors.test("CustomMirrorIsInherited") {
+  do {
+    var output = ""
+    dump(Irradiant(), to: &output)
+
+    let expected =
+      "▿ Mirror.Brilliant #0\n" +
+      "  - first: 400\n" +
+      "  - second: \"\"\n" +
+      "  ▿ self: Mirror.Brilliant #0\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+//===--- Metatypes --------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+protocol SomeNativeProto {}
+extension Int: SomeNativeProto {}
+
+class SomeClass {}
+
+mirrors.test("MetatypeMirror") {
+  do {
+    var output = ""
+    let concreteMetatype = Int.self
+    dump(concreteMetatype, to: &output)
+
+    let expectedInt = "- Swift.Int #0\n"
+    expectEqual(expectedInt, output)
+
+    let anyMetatype: Any.Type = Int.self
+    output = ""
+    dump(anyMetatype, to: &output)
+    expectEqual(expectedInt, output)
+
+    let nativeProtocolMetatype: SomeNativeProto.Type = Int.self
+    output = ""
+    dump(nativeProtocolMetatype, to: &output)
+    expectEqual(expectedInt, output)
+
+    let concreteClassMetatype = SomeClass.self
+    let expectedSomeClass = "- Mirror.SomeClass #0\n"
+    output = ""
+    dump(concreteClassMetatype, to: &output)
+    expectEqual(expectedSomeClass, output)
+
+    let nativeProtocolConcreteMetatype = SomeNativeProto.self
+    let expectedNativeProtocolConcrete = "- Mirror.SomeNativeProto #0\n"
+    output = ""
+    dump(nativeProtocolConcreteMetatype, to: &output)
+    expectEqual(expectedNativeProtocolConcrete, output)
+  }
+}
+
+//===--- Tuples -----------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+mirrors.test("TupleMirror") {
+  do {
+    var output = ""
+    let tuple =
+      (Brilliant(384, "seven six eight"), StructWithDefaultMirror("nine"))
+    dump(tuple, to: &output)
+
+    let expected =
+      "▿ (2 elements)\n" +
+      "  ▿ .0: Mirror.Brilliant #0\n" +
+      "    - first: 384\n" +
+      "    - second: \"seven six eight\"\n" +
+      "    ▿ self: Mirror.Brilliant #0\n" +
+      "  ▿ .1: Mirror.StructWithDefaultMirror\n" +
+      "    - s: \"nine\"\n"
+
+    expectEqual(expected, output)
+
+    expectEqual(.tuple, Mirror(reflecting: tuple).displayStyle)
+  }
+
+  do {
+    // A tuple of stdlib types with mirrors.
+    var output = ""
+    let tuple = (1, 2.5, false, "three")
+    dump(tuple, to: &output)
+
+    let expected =
+      "▿ (4 elements)\n" +
+      "  - .0: 1\n" +
+      "  - .1: 2.5\n" +
+      "  - .2: false\n" +
+      "  - .3: \"three\"\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    // A nested tuple.
+    var output = ""
+    let tuple = (1, ("Hello", "World"))
+    dump(tuple, to: &output)
+
+    let expected =
+      "▿ (2 elements)\n" +
+      "  - .0: 1\n" +
+      "  ▿ .1: (2 elements)\n" +
+      "    - .0: \"Hello\"\n" +
+      "    - .1: \"World\"\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+//===--- Standard library types -------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+mirrors.test("String/Mirror") {
+  do {
+    var output = ""
+    dump("", to: &output)
+
+    let expected =
+      "- \"\"\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    // U+0061 LATIN SMALL LETTER A
+    // U+304B HIRAGANA LETTER KA
+    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+    // U+1F425 FRONT-FACING BABY CHICK
+    var output = ""
+    dump("\u{61}\u{304b}\u{3099}\u{1f425}", to: &output)
+
+    let expected =
+      "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+mirrors.test("String.UTF8View/Mirror") {
+  // U+0061 LATIN SMALL LETTER A
+  // U+304B HIRAGANA LETTER KA
+  // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+  var output = ""
+  dump("\u{61}\u{304b}\u{3099}".utf8, to: &output)
+
+  let expected =
+    "▿ UTF8View(\"\u{61}\u{304b}\u{3099}\")\n" +
+    "  - 97\n" +
+    "  - 227\n" +
+    "  - 129\n" +
+    "  - 139\n" +
+    "  - 227\n" +
+    "  - 130\n" +
+    "  - 153\n"
+
+  expectEqual(expected, output)
+}
+
+mirrors.test("String.UTF16View/Mirror") {
+  // U+0061 LATIN SMALL LETTER A
+  // U+304B HIRAGANA LETTER KA
+  // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+  // U+1F425 FRONT-FACING BABY CHICK
+  var output = ""
+  dump("\u{61}\u{304b}\u{3099}\u{1f425}".utf16, to: &output)
+
+  let expected =
+    "▿ StringUTF16(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
+    "  - 97\n" +
+    "  - 12363\n" +
+    "  - 12441\n" +
+    "  - 55357\n" +
+    "  - 56357\n"
+
+  expectEqual(expected, output)
+}
+
+mirrors.test("String.UnicodeScalarView/Mirror") {
+  // U+0061 LATIN SMALL LETTER A
+  // U+304B HIRAGANA LETTER KA
+  // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+  // U+1F425 FRONT-FACING BABY CHICK
+  var output = ""
+  dump("\u{61}\u{304b}\u{3099}\u{1f425}".unicodeScalars, to: &output)
+
+  let expected =
+    "▿ StringUnicodeScalarView(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
+    "  - \"\u{61}\"\n" +
+    "  - \"\\u{304B}\"\n" +
+    "  - \"\\u{3099}\"\n" +
+    "  - \"\\u{0001F425}\"\n"
+
+  expectEqual(expected, output)
+}
+
+mirrors.test("Character/Mirror") {
+  do {
+    // U+0061 LATIN SMALL LETTER A
+    let input: Character = "\u{61}"
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- \"\u{61}\"\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    // U+304B HIRAGANA LETTER KA
+    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+    let input: Character = "\u{304b}\u{3099}"
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- \"\u{304b}\u{3099}\"\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    // U+1F425 FRONT-FACING BABY CHICK
+    let input: Character = "\u{1f425}"
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- \"\u{1f425}\"\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+mirrors.test("UnicodeScalar") {
+  do {
+    // U+0061 LATIN SMALL LETTER A
+    let input: UnicodeScalar = "\u{61}"
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- \"\u{61}\"\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    // U+304B HIRAGANA LETTER KA
+    let input: UnicodeScalar = "\u{304b}"
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- \"\\u{304B}\"\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+    let input: UnicodeScalar = "\u{3099}"
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- \"\\u{3099}\"\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    // U+1F425 FRONT-FACING BABY CHICK
+    let input: UnicodeScalar = "\u{1f425}"
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- \"\\u{0001F425}\"\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+mirrors.test("Bool") {
+  do {
+    var output = ""
+    dump(false, to: &output)
+
+    let expected =
+      "- false\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    var output = ""
+    dump(true, to: &output)
+
+    let expected =
+      "- true\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+// FIXME: these tests should cover Float80.
+// FIXME: these tests should be automatically generated from the list of
+// available floating point types.
+mirrors.test("Float") {
+  do {
+    var output = ""
+    dump(Float.nan, to: &output)
+
+    let expected =
+      "- nan\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    var output = ""
+    dump(Float.infinity, to: &output)
+
+    let expected =
+      "- inf\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    var input: Float = 42.125
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- 42.125\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+mirrors.test("Double") {
+  do {
+    var output = ""
+    dump(Double.nan, to: &output)
+
+    let expected =
+      "- nan\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    var output = ""
+    dump(Double.infinity, to: &output)
+
+    let expected =
+      "- inf\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    var input: Double = 42.125
+    var output = ""
+    dump(input, to: &output)
+
+    let expected =
+      "- 42.125\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+mirrors.test("StaticString/Mirror") {
+  do {
+    var output = ""
+    dump("" as StaticString, to: &output)
+
+    let expected =
+      "- \"\"\n"
+
+    expectEqual(expected, output)
+  }
+
+  do {
+    // U+0061 LATIN SMALL LETTER A
+    // U+304B HIRAGANA LETTER KA
+    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+    // U+1F425 FRONT-FACING BABY CHICK
+    var output = ""
+    dump("\u{61}\u{304b}\u{3099}\u{1f425}" as StaticString, to: &output)
+
+    let expected =
+      "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
+
+    expectEqual(expected, output)
+  }
+}
+
+mirrors.test("DictionaryIterator/Mirror") {
+  let d: [MinimalHashableValue : OpaqueValue<Int>] =
+    [ MinimalHashableValue(0) : OpaqueValue(0) ]
+
+  var output = ""
+  dump(d.makeIterator(), to: &output)
+
+  let expected =
+    "- Swift.DictionaryIterator<StdlibUnittest.MinimalHashableValue, StdlibUnittest.OpaqueValue<Swift.Int>>\n"
+
+  expectEqual(expected, output)
+}
+
+mirrors.test("SetIterator/Mirror") {
+  let s: Set<MinimalHashableValue> = [ MinimalHashableValue(0)]
+
+  var output = ""
+  dump(s.makeIterator(), to: &output)
+
+  let expected =
+    "- Swift.SetIterator<StdlibUnittest.MinimalHashableValue>\n"
+
+  expectEqual(expected, output)
+}
+
+//===--- Regressions ------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+// A struct type and class type whose NominalTypeDescriptor.FieldNames
+// data is exactly eight bytes long. FieldNames data of exactly
+// 4 or 8 or 16 bytes was once miscompiled on arm64.
+struct EightByteFieldNamesStruct {
+  let abcdef = 42
+}
+class EightByteFieldNamesClass {
+  let abcdef = 42
+}
+
+mirrors.test("FieldNamesBug") {
+  do {
+    let expected =
+      "▿ Mirror.EightByteFieldNamesStruct\n" +
+      "  - abcdef: 42\n"
+    var output = ""
+    dump(EightByteFieldNamesStruct(), to: &output)
+    expectEqual(expected, output)
+  }
+
+  do {
+    let expected =
+      "▿ Mirror.EightByteFieldNamesClass #0\n" +
+      "  - abcdef: 42\n"
+    var output = ""
+    dump(EightByteFieldNamesClass(), to: &output)
+    expectEqual(expected, output)
+  }
+}
+
+mirrors.test("MirrorMirror") {
+  var object = 1
+  var mirror = Mirror(reflecting: object)
+  var mirrorMirror = Mirror(reflecting: mirror)
+
+  expectEqual(0, mirrorMirror.children.count)
+}
+
+mirrors.test("OpaquePointer/null") {
+  // Don't crash on null pointers. rdar://problem/19708338
+  let pointer: OpaquePointer? = nil
+  let mirror = Mirror(reflecting: pointer)
+  expectEqual(0, mirror.children.count)
+}
+
 struct a<b>  {
     enum c{}
 }
@@ -791,11 +1740,34 @@
     var constraints: [Int: a<f>.c] = [:]
 }
 
-mirrors.test("field with generic nested type") {
+mirrors.test("GenericNestedTypeField") {
   let x = e<d>()
   
   expectTrue(type(of: Mirror(reflecting: x).children.first!.value)
               == [Int: a<d>.c].self)
 }
 
+extension OtherOuter {
+  struct Inner {}
+}
+
+extension OtherOuterGeneric {
+  struct Inner<U> {}
+}
+
+mirrors.test("SymbolicReferenceInsideType") {
+  let s = OtherStruct(a: OtherOuter.Inner(),
+                      b: OtherOuterGeneric<Int>.Inner<String>())
+
+  var output = ""
+  dump(s, to: &output)
+
+  let expected =
+    "▿ Mirror.OtherStruct\n" +
+    "  - a: Mirror.OtherOuter.Inner\n" +
+    "  - b: Mirror.OtherOuterGeneric<Swift.Int>.Inner<Swift.String>\n"
+
+  expectEqual(expected, output)
+}
+
 runAllTests()
diff --git a/test/stdlib/PrintFloat.swift.gyb b/test/stdlib/PrintFloat.swift.gyb
index 90b4314..e689206 100644
--- a/test/stdlib/PrintFloat.swift.gyb
+++ b/test/stdlib/PrintFloat.swift.gyb
@@ -5,10 +5,6 @@
 // RUN: %line-directive %t/FloatingPointPrinting.swift -- %target-run %t/main.out --locale ru_RU.UTF-8
 // REQUIRES: executable_test
 
-%{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
-}%
-
 import StdlibUnittest
 #if os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
   import Glibc
@@ -347,11 +343,22 @@
 // Verify that a particular value provides a specific description string.
 // Also check that the generated strings actually satisfy our
 // accuracy requirements.
-fileprivate func expectDescription(_ expected: String, _ object: ${FloatType}, ${TRACE}) {
-  expectEqual(expected, object.description, ${trace})
-  expectEqual(expected, object.debugDescription, ${trace})
-  expectAccurateDescription(object, ${trace})
- }
+fileprivate func expectDescription(_ expected: String, _ object: ${FloatType},
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
+  expectEqual(expected, object.description,
+    message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  expectEqual(expected, object.debugDescription,
+    message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+  expectAccurateDescription(object,
+    message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
+}
 
 // Verify our key requirements:
 //
@@ -364,7 +371,12 @@
 // * Close. If there is more than one accurate and short value, we want the one
 //   that is closest (as an infinitely-precise real number) to the original
 //   binary float (interpreted as an infinitely-precise real number).
-fileprivate func expectAccurateDescription(_ object: ${FloatType}, ${TRACE}) {
+fileprivate func expectAccurateDescription(_ object: ${FloatType},
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) {
   if !object.isFinite {
     return
   }
@@ -376,11 +388,15 @@
   let text = object.debugDescription
   if let roundTrip = ${FloatType}(text) {
     if object != roundTrip {
-      expectationFailure("Round-trip inaccuracy: \(object) != \(roundTrip)", trace: ${trace})
+      expectationFailure("Round-trip inaccuracy: \(object) != \(roundTrip)",
+        trace: message(),
+        stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
       return
     }
   } else {
-    expectationFailure("Failed to parse \(text)", trace: ${trace})
+    expectationFailure("Failed to parse \(text)",
+      trace: message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
     return
   }
 
@@ -397,9 +413,16 @@
 % end
 
 // Special helper for NaN values
-fileprivate func expectNaN<T>(_ expected: String, _ object: T, ${TRACE}) where T: FloatingPoint & CustomDebugStringConvertible & CustomStringConvertible {
+fileprivate func expectNaN<T>(_ expected: String, _ object: T,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where T: FloatingPoint & CustomDebugStringConvertible & CustomStringConvertible {
   // Regular description always returns "nan"
-  expectEqual("nan", object.description, ${trace})
+  expectEqual("nan", object.description,
+    message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 
   // debugDescription prints full details about NaNs, which is tricky to test
   // because NaNs often get truncated: various implementations force all NaNs
@@ -409,7 +432,9 @@
 #if arch(x86_64)
   // Verify the exact debugDescription value only on x86_64, where we
   // know the exact expected String:
-  expectEqual(expected, object.debugDescription, ${trace})
+  expectEqual(expected, object.debugDescription,
+    message(),
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
 #endif
 
   // On all platforms, we verify that the generated debugDescription text
@@ -428,7 +453,9 @@
 
   // Fixed text "nan"
   if actual.prefix(3) != "nan" {
-    expectationFailure("Badly formatted NaN debug description (expected 'nan'): \(object.debugDescription)", trace: ${trace})
+    expectationFailure("Badly formatted NaN debug description (expected 'nan'): \(object.debugDescription)", trace:
+      message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
     return
   }
   actual = String(actual.dropFirst(3))
@@ -439,7 +466,9 @@
     while !actual.isEmpty {
       if actual.hasPrefix(")") {
         if actual != ")" {
-          expectationFailure("Malformed NaN: extra text after payload: \(object.debugDescription)", trace: ${trace})
+          expectationFailure("Malformed NaN: extra text after payload: \(object.debugDescription)", trace:
+            message(),
+            stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
         }
         return
       } else {
@@ -447,9 +476,13 @@
       }
       actual = String(actual.dropFirst())
     }
-    expectationFailure("Malformed NaN: no closing parenthesis after payload: \(object.debugDescription)", trace: ${trace})
+    expectationFailure("Malformed NaN: no closing parenthesis after payload: \(object.debugDescription)", trace:
+      message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   } else if !actual.isEmpty {
-    expectationFailure("Badly formatted NaN debug description has invalid text after 'nan'.  Expected '(0x': \(object.debugDescription)", trace: ${trace})
+    expectationFailure("Badly formatted NaN debug description has invalid text after 'nan'.  Expected '(0x': \(object.debugDescription)", trace:
+      message(),
+      stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
   }
 }
 
@@ -481,7 +514,7 @@
 // this logic to help verify that the output does not depend on
 // the C locale.
 PrintTests.setUp {
-  if let localeArgIndex = CommandLine.arguments.index(of: "--locale") {
+  if let localeArgIndex = CommandLine.arguments.firstIndex(of: "--locale") {
     let locale = CommandLine.arguments[localeArgIndex + 1]
     expectEqual("ru_RU.UTF-8", locale)
     setlocale(LC_ALL, locale)
diff --git a/test/stdlib/Runtime.swift.gyb b/test/stdlib/Runtime.swift.gyb
index 67ee2bf..e181db7 100644
--- a/test/stdlib/Runtime.swift.gyb
+++ b/test/stdlib/Runtime.swift.gyb
@@ -602,385 +602,8 @@
   expectEqual("▿ 2 elements\n  - 42\n  - 4242\n", output)
 }
 
-struct StructWithDefaultMirror {
-  let s: String
 
-  init (_ s: String) {
-    self.s = s
-  }
-}
-
-Reflection.test("Struct/NonGeneric/DefaultMirror") {
-  do {
-    var output = ""
-    dump(StructWithDefaultMirror("123"), to: &output)
-    expectEqual("▿ a.StructWithDefaultMirror\n  - s: \"123\"\n", output)
-  }
-
-  do {
-    // Build a String around an interpolation as a way of smoke-testing that
-    // the internal _Mirror implementation gets memory management right.
-    var output = ""
-    dump(StructWithDefaultMirror("\(456)"), to: &output)
-    expectEqual("▿ a.StructWithDefaultMirror\n  - s: \"456\"\n", output)
-  }
-
-  expectEqual(
-    .`struct`,
-    Mirror(reflecting: StructWithDefaultMirror("")).displayStyle)
-}
-
-struct GenericStructWithDefaultMirror<T, U> {
-  let first: T
-  let second: U
-}
-
-Reflection.test("Struct/Generic/DefaultMirror") {
-  do {
-    var value = GenericStructWithDefaultMirror<Int, [Any?]>(
-      first: 123,
-      second: ["abc", 456, 789.25])
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ a.GenericStructWithDefaultMirror<Swift.Int, Swift.Array<Swift.Optional<Any>>>\n" +
-      "  - first: 123\n" +
-      "  ▿ second: 3 elements\n" +
-      "    ▿ Optional(\"abc\")\n" +
-      "      - some: \"abc\"\n" +
-      "    ▿ Optional(456)\n" +
-      "      - some: 456\n" +
-      "    ▿ Optional(789.25)\n" +
-      "      - some: 789.25\n"
-
-    expectEqual(expected, output)
-
-  }
-}
-
-enum NoPayloadEnumWithDefaultMirror {
-  case A, ß
-}
-
-Reflection.test("Enum/NoPayload/DefaultMirror") {
-  do {
-    let value: [NoPayloadEnumWithDefaultMirror] =
-        [.A, .ß]
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ 2 elements\n" +
-      "  - a.NoPayloadEnumWithDefaultMirror.A\n" +
-      "  - a.NoPayloadEnumWithDefaultMirror.ß\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-enum SingletonNonGenericEnumWithDefaultMirror {
-  case OnlyOne(Int)
-}
-
-Reflection.test("Enum/SingletonNonGeneric/DefaultMirror") {
-  do {
-    let value = SingletonNonGenericEnumWithDefaultMirror.OnlyOne(5)
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ a.SingletonNonGenericEnumWithDefaultMirror.OnlyOne\n" +
-      "  - OnlyOne: 5\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-enum SingletonGenericEnumWithDefaultMirror<T> {
-  case OnlyOne(T)
-}
-
-Reflection.test("Enum/SingletonGeneric/DefaultMirror") {
-  do {
-    let value = SingletonGenericEnumWithDefaultMirror.OnlyOne("IIfx")
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ a.SingletonGenericEnumWithDefaultMirror<Swift.String>.OnlyOne\n" +
-      "  - OnlyOne: \"IIfx\"\n"
-
-    expectEqual(expected, output)
-  }
-  expectEqual(0, LifetimeTracked.instances)
-  do {
-    let value = SingletonGenericEnumWithDefaultMirror.OnlyOne(
-        LifetimeTracked(0))
-    expectEqual(1, LifetimeTracked.instances)
-    var output = ""
-    dump(value, to: &output)
-  }
-  expectEqual(0, LifetimeTracked.instances)
-}
-
-enum SinglePayloadNonGenericEnumWithDefaultMirror {
-  case Cat
-  case Dog
-  case Volleyball(String, Int)
-}
-
-Reflection.test("Enum/SinglePayloadNonGeneric/DefaultMirror") {
-  do {
-    let value: [SinglePayloadNonGenericEnumWithDefaultMirror] =
-        [.Cat,
-         .Dog,
-         .Volleyball("Wilson", 2000)]
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ 3 elements\n" +
-      "  - a.SinglePayloadNonGenericEnumWithDefaultMirror.Cat\n" +
-      "  - a.SinglePayloadNonGenericEnumWithDefaultMirror.Dog\n" +
-      "  ▿ a.SinglePayloadNonGenericEnumWithDefaultMirror.Volleyball\n" +
-      "    ▿ Volleyball: (2 elements)\n" +
-      "      - .0: \"Wilson\"\n" +
-      "      - .1: 2000\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-enum SinglePayloadGenericEnumWithDefaultMirror<T, U> {
-  case Well
-  case Faucet
-  case Pipe(T, U)
-}
-
-Reflection.test("Enum/SinglePayloadGeneric/DefaultMirror") {
-  do {
-    let value: [SinglePayloadGenericEnumWithDefaultMirror<Int, [Int]>] =
-        [.Well,
-         .Faucet,
-         .Pipe(408, [415])]
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ 3 elements\n" +
-      "  - a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Well\n" +
-      "  - a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Faucet\n" +
-      "  ▿ a.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Pipe\n" +
-      "    ▿ Pipe: (2 elements)\n" +
-      "      - .0: 408\n" +
-      "      ▿ .1: 1 element\n" +
-      "        - 415\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-enum MultiPayloadTagBitsNonGenericEnumWithDefaultMirror {
-  case Plus
-  case SE30
-  case Classic(mhz: Int)
-  case Performa(model: Int)
-}
-
-Reflection.test("Enum/MultiPayloadTagBitsNonGeneric/DefaultMirror") {
-  do {
-    let value: [MultiPayloadTagBitsNonGenericEnumWithDefaultMirror] =
-        [.Plus,
-         .SE30,
-         .Classic(mhz: 16),
-         .Performa(model: 220)]
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ 4 elements\n" +
-      "  - a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Plus\n" +
-      "  - a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.SE30\n" +
-      "  ▿ a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Classic\n" +
-      "    ▿ Classic: (1 element)\n" +
-      "      - mhz: 16\n" +
-      "  ▿ a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Performa\n" +
-      "    ▿ Performa: (1 element)\n" +
-      "      - model: 220\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-class Floppy {
-  let capacity: Int
-
-  init(capacity: Int) { self.capacity = capacity }
-}
-
-class CDROM {
-  let capacity: Int
-
-  init(capacity: Int) { self.capacity = capacity }
-}
-
-enum MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror {
-  case MacWrite
-  case MacPaint
-  case FileMaker
-  case ClarisWorks(floppy: Floppy)
-  case HyperCard(cdrom: CDROM)
-}
-
-Reflection.test("Enum/MultiPayloadSpareBitsNonGeneric/DefaultMirror") {
-  do {
-    let value: [MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror] =
-        [.MacWrite,
-         .MacPaint,
-         .FileMaker,
-         .ClarisWorks(floppy: Floppy(capacity: 800)),
-         .HyperCard(cdrom: CDROM(capacity: 600))]
-
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ 5 elements\n" +
-      "  - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacWrite\n" +
-      "  - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacPaint\n" +
-      "  - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.FileMaker\n" +
-      "  ▿ a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
-      "    ▿ ClarisWorks: (1 element)\n" +
-      "      ▿ floppy: a.Floppy #0\n" +
-      "        - capacity: 800\n" +
-      "  ▿ a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.HyperCard\n" +
-      "    ▿ HyperCard: (1 element)\n" +
-      "      ▿ cdrom: a.CDROM #1\n" +
-      "        - capacity: 600\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-enum MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror {
-  case MacWrite
-  case MacPaint
-  case FileMaker
-  case ClarisWorks(floppy: Bool)
-  case HyperCard(cdrom: Bool)
-}
-
-Reflection.test("Enum/MultiPayloadTagBitsSmallNonGeneric/DefaultMirror") {
-  do {
-    let value: [MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror] =
-        [.MacWrite,
-         .MacPaint,
-         .FileMaker,
-         .ClarisWorks(floppy: true),
-         .HyperCard(cdrom: false)]
-
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ 5 elements\n" +
-      "  - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacWrite\n" +
-      "  - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacPaint\n" +
-      "  - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.FileMaker\n" +
-      "  ▿ a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
-      "    ▿ ClarisWorks: (1 element)\n" +
-      "      - floppy: true\n" +
-      "  ▿ a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.HyperCard\n" +
-      "    ▿ HyperCard: (1 element)\n" +
-      "      - cdrom: false\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-enum MultiPayloadGenericEnumWithDefaultMirror<T, U> {
-  case IIe
-  case IIgs
-  case Centris(ram: T)
-  case Quadra(hdd: U)
-  case PowerBook170
-  case PowerBookDuo220
-}
-
-Reflection.test("Enum/MultiPayloadGeneric/DefaultMirror") {
-  do {
-    let value: [MultiPayloadGenericEnumWithDefaultMirror<Int, String>] =
-        [.IIe,
-         .IIgs,
-         .Centris(ram: 4096),
-         .Quadra(hdd: "160MB"),
-         .PowerBook170,
-         .PowerBookDuo220]
-
-    var output = ""
-    dump(value, to: &output)
-
-    let expected =
-      "▿ 6 elements\n" +
-      "  - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIe\n" +
-      "  - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIgs\n" +
-      "  ▿ a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Centris\n" +
-      "    ▿ Centris: (1 element)\n" +
-      "      - ram: 4096\n" +
-      "  ▿ a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Quadra\n" +
-      "    ▿ Quadra: (1 element)\n" +
-      "      - hdd: \"160MB\"\n" +
-      "  - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBook170\n" +
-      "  - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBookDuo220\n"
-
-    expectEqual(expected, output)
-  }
-  expectEqual(0, LifetimeTracked.instances)
-  do {
-    let value = MultiPayloadGenericEnumWithDefaultMirror<LifetimeTracked,
-                                                         LifetimeTracked>
-        .Quadra(hdd: LifetimeTracked(0))
-    expectEqual(1, LifetimeTracked.instances)
-    var output = ""
-    dump(value, to: &output)
-  }
-  expectEqual(0, LifetimeTracked.instances)
-}
-
-enum Foo<T> {
-  indirect case Foo(Int)
-  case Bar(T)
-}
-
-enum List<T> {
-  case Nil
-  indirect case Cons(first: T, rest: List<T>)
-}
-
-Reflection.test("Enum/IndirectGeneric/DefaultMirror") {
-  let x = Foo<String>.Foo(22)
-  let y = Foo<String>.Bar("twenty-two")
-
-  expectEqual("\(x)", "Foo(22)")
-  expectEqual("\(y)", "Bar(\"twenty-two\")")
-
-  let list = List.Cons(first: 0, rest: .Cons(first: 1, rest: .Nil))
-  expectEqual("Cons(first: 0, rest: a.List<Swift.Int>.Cons(first: 1, rest: a.List<Swift.Int>.Nil))",
-    "\(list)")
-}
-
-enum MyError: Error {
-  case myFirstError(LifetimeTracked)
-}
-
-Reflection.test("Enum/CaseName/Error") {
-  // Just make sure this doesn't leak.
-  let e: Error = MyError.myFirstError(LifetimeTracked(0))
-  _ = String(describing: e)
-}
-
-class Brilliant : CustomReflectable {
+class Brilliant {
   let first: Int
   let second: String
 
@@ -988,74 +611,6 @@
     self.first = fst
     self.second = snd
   }
-
-  var customMirror: Mirror {
-    return Mirror(self, children: ["first": first, "second": second, "self": self])
-  }
-}
-
-/// Subclasses inherit their parents' custom mirrors.
-class Irradiant : Brilliant {
-  init() {
-    super.init(400, "")
-  }
-}
-
-Reflection.test("CustomMirror") {
-  do {
-    var output = ""
-    dump(Brilliant(123, "four five six"), to: &output)
-
-    let expected =
-      "▿ a.Brilliant #0\n" +
-      "  - first: 123\n" +
-      "  - second: \"four five six\"\n" +
-      "  ▿ self: a.Brilliant #0\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    var output = ""
-    dump(Brilliant(123, "four five six"), to: &output, maxDepth: 0)
-    expectEqual("▹ a.Brilliant #0\n", output)
-  }
-
-  do {
-    var output = ""
-    dump(Brilliant(123, "four five six"), to: &output, maxItems: 3)
-
-    let expected =
-      "▿ a.Brilliant #0\n" +
-      "  - first: 123\n" +
-      "  - second: \"four five six\"\n" +
-      "    (1 more child)\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    var output = ""
-    dump(Brilliant(123, "four five six"), to: &output, maxItems: 2)
-
-    let expected =
-      "▿ a.Brilliant #0\n" +
-      "  - first: 123\n" +
-      "    (2 more children)\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    var output = ""
-    dump(Brilliant(123, "four five six"), to: &output, maxItems: 1)
-
-    let expected =
-      "▿ a.Brilliant #0\n" +
-      "    (3 children)\n"
-
-    expectEqual(expected, output)
-  }
 }
 
 Reflection.test("ObjectIdentifier/Hashable,Comparable") {
@@ -1102,475 +657,6 @@
 
 }
 
-Reflection.test("CustomMirrorIsInherited") {
-  do {
-    var output = ""
-    dump(Irradiant(), to: &output)
-
-    let expected =
-      "▿ a.Brilliant #0\n" +
-      "  - first: 400\n" +
-      "  - second: \"\"\n" +
-      "  ▿ self: a.Brilliant #0\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-protocol SomeNativeProto {}
-extension Int: SomeNativeProto {}
-
-Reflection.test("MetatypeMirror") {
-  do {
-    var output = ""
-    let concreteMetatype = Int.self
-    dump(concreteMetatype, to: &output)
-
-    let expectedInt = "- Swift.Int #0\n"
-    expectEqual(expectedInt, output)
-
-    let anyMetatype: Any.Type = Int.self
-    output = ""
-    dump(anyMetatype, to: &output)
-    expectEqual(expectedInt, output)
-
-    let nativeProtocolMetatype: SomeNativeProto.Type = Int.self
-    output = ""
-    dump(nativeProtocolMetatype, to: &output)
-    expectEqual(expectedInt, output)
-
-    let concreteClassMetatype = SomeClass.self
-    let expectedSomeClass = "- a.SomeClass #0\n"
-    output = ""
-    dump(concreteClassMetatype, to: &output)
-    expectEqual(expectedSomeClass, output)
-
-    let nativeProtocolConcreteMetatype = SomeNativeProto.self
-    let expectedNativeProtocolConcrete = "- a.SomeNativeProto #0\n"
-    output = ""
-    dump(nativeProtocolConcreteMetatype, to: &output)
-    expectEqual(expectedNativeProtocolConcrete, output)
-  }
-}
-
-Reflection.test("TupleMirror") {
-  do {
-    var output = ""
-    let tuple =
-      (Brilliant(384, "seven six eight"), StructWithDefaultMirror("nine"))
-    dump(tuple, to: &output)
-
-    let expected =
-      "▿ (2 elements)\n" +
-      "  ▿ .0: a.Brilliant #0\n" +
-      "    - first: 384\n" +
-      "    - second: \"seven six eight\"\n" +
-      "    ▿ self: a.Brilliant #0\n" +
-      "  ▿ .1: a.StructWithDefaultMirror\n" +
-      "    - s: \"nine\"\n"
-
-    expectEqual(expected, output)
-
-    expectEqual(.tuple, Mirror(reflecting: tuple).displayStyle)
-  }
-
-  do {
-    // A tuple of stdlib types with mirrors.
-    var output = ""
-    let tuple = (1, 2.5, false, "three")
-    dump(tuple, to: &output)
-
-    let expected =
-      "▿ (4 elements)\n" +
-      "  - .0: 1\n" +
-      "  - .1: 2.5\n" +
-      "  - .2: false\n" +
-      "  - .3: \"three\"\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    // A nested tuple.
-    var output = ""
-    let tuple = (1, ("Hello", "World"))
-    dump(tuple, to: &output)
-
-    let expected =
-      "▿ (2 elements)\n" +
-      "  - .0: 1\n" +
-      "  ▿ .1: (2 elements)\n" +
-      "    - .0: \"Hello\"\n" +
-      "    - .1: \"World\"\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-class DullClass {}
-
-Reflection.test("ClassReflection") {
-  expectEqual(.`class`, Mirror(reflecting: DullClass()).displayStyle)
-}
-
-Reflection.test("String/Mirror") {
-  do {
-    var output = ""
-    dump("", to: &output)
-
-    let expected =
-      "- \"\"\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    // U+0061 LATIN SMALL LETTER A
-    // U+304B HIRAGANA LETTER KA
-    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
-    // U+1F425 FRONT-FACING BABY CHICK
-    var output = ""
-    dump("\u{61}\u{304b}\u{3099}\u{1f425}", to: &output)
-
-    let expected =
-      "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-Reflection.test("String.UTF8View/Mirror") {
-  // U+0061 LATIN SMALL LETTER A
-  // U+304B HIRAGANA LETTER KA
-  // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
-  var output = ""
-  dump("\u{61}\u{304b}\u{3099}".utf8, to: &output)
-
-  let expected =
-    "▿ UTF8View(\"\u{61}\u{304b}\u{3099}\")\n" +
-    "  - 97\n" +
-    "  - 227\n" +
-    "  - 129\n" +
-    "  - 139\n" +
-    "  - 227\n" +
-    "  - 130\n" +
-    "  - 153\n"
-
-  expectEqual(expected, output)
-}
-
-Reflection.test("String.UTF16View/Mirror") {
-  // U+0061 LATIN SMALL LETTER A
-  // U+304B HIRAGANA LETTER KA
-  // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
-  // U+1F425 FRONT-FACING BABY CHICK
-  var output = ""
-  dump("\u{61}\u{304b}\u{3099}\u{1f425}".utf16, to: &output)
-
-  let expected =
-    "▿ StringUTF16(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
-    "  - 97\n" +
-    "  - 12363\n" +
-    "  - 12441\n" +
-    "  - 55357\n" +
-    "  - 56357\n"
-
-  expectEqual(expected, output)
-}
-
-Reflection.test("String.UnicodeScalarView/Mirror") {
-  // U+0061 LATIN SMALL LETTER A
-  // U+304B HIRAGANA LETTER KA
-  // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
-  // U+1F425 FRONT-FACING BABY CHICK
-  var output = ""
-  dump("\u{61}\u{304b}\u{3099}\u{1f425}".unicodeScalars, to: &output)
-
-  let expected =
-    "▿ StringUnicodeScalarView(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
-    "  - \"\u{61}\"\n" +
-    "  - \"\\u{304B}\"\n" +
-    "  - \"\\u{3099}\"\n" +
-    "  - \"\\u{0001F425}\"\n"
-
-  expectEqual(expected, output)
-}
-
-Reflection.test("Character/Mirror") {
-  do {
-    // U+0061 LATIN SMALL LETTER A
-    let input: Character = "\u{61}"
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- \"\u{61}\"\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    // U+304B HIRAGANA LETTER KA
-    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
-    let input: Character = "\u{304b}\u{3099}"
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- \"\u{304b}\u{3099}\"\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    // U+1F425 FRONT-FACING BABY CHICK
-    let input: Character = "\u{1f425}"
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- \"\u{1f425}\"\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-Reflection.test("UnicodeScalar") {
-  do {
-    // U+0061 LATIN SMALL LETTER A
-    let input: UnicodeScalar = "\u{61}"
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- \"\u{61}\"\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    // U+304B HIRAGANA LETTER KA
-    let input: UnicodeScalar = "\u{304b}"
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- \"\\u{304B}\"\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
-    let input: UnicodeScalar = "\u{3099}"
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- \"\\u{3099}\"\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    // U+1F425 FRONT-FACING BABY CHICK
-    let input: UnicodeScalar = "\u{1f425}"
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- \"\\u{0001F425}\"\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-Reflection.test("Bool") {
-  do {
-    var output = ""
-    dump(false, to: &output)
-
-    let expected =
-      "- false\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    var output = ""
-    dump(true, to: &output)
-
-    let expected =
-      "- true\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-// FIXME: these tests should cover Float80.
-// FIXME: these tests should be automatically generated from the list of
-// available floating point types.
-Reflection.test("Float") {
-  do {
-    var output = ""
-    dump(Float.nan, to: &output)
-
-    let expected =
-      "- nan\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    var output = ""
-    dump(Float.infinity, to: &output)
-
-    let expected =
-      "- inf\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    var input: Float = 42.125
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- 42.125\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-Reflection.test("Double") {
-  do {
-    var output = ""
-    dump(Double.nan, to: &output)
-
-    let expected =
-      "- nan\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    var output = ""
-    dump(Double.infinity, to: &output)
-
-    let expected =
-      "- inf\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    var input: Double = 42.125
-    var output = ""
-    dump(input, to: &output)
-
-    let expected =
-      "- 42.125\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-// A struct type and class type whose NominalTypeDescriptor.FieldNames
-// data is exactly eight bytes long. FieldNames data of exactly
-// 4 or 8 or 16 bytes was once miscompiled on arm64.
-struct EightByteFieldNamesStruct {
-  let abcdef = 42
-}
-class EightByteFieldNamesClass {
-  let abcdef = 42
-}
-
-Reflection.test("FieldNamesBug") {
-  do {
-    let expected =
-      "▿ a.EightByteFieldNamesStruct\n" +
-      "  - abcdef: 42\n"
-    var output = ""
-    dump(EightByteFieldNamesStruct(), to: &output)
-    expectEqual(expected, output)
-  }
-
-  do {
-    let expected =
-      "▿ a.EightByteFieldNamesClass #0\n" +
-      "  - abcdef: 42\n"
-    var output = ""
-    dump(EightByteFieldNamesClass(), to: &output)
-    expectEqual(expected, output)
-  }
-}
-
-Reflection.test("MirrorMirror") {
-  var object = 1
-  var mirror = Mirror(reflecting: object)
-  var mirrorMirror = Mirror(reflecting: mirror)
-
-  expectEqual(0, mirrorMirror.children.count)
-}
-
-Reflection.test("OpaquePointer/null") {
-  // Don't crash on null pointers. rdar://problem/19708338
-  let pointer: OpaquePointer? = nil
-  let mirror = Mirror(reflecting: pointer)
-  expectEqual(0, mirror.children.count)
-}
-
-Reflection.test("StaticString/Mirror") {
-  do {
-    var output = ""
-    dump("" as StaticString, to: &output)
-
-    let expected =
-      "- \"\"\n"
-
-    expectEqual(expected, output)
-  }
-
-  do {
-    // U+0061 LATIN SMALL LETTER A
-    // U+304B HIRAGANA LETTER KA
-    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
-    // U+1F425 FRONT-FACING BABY CHICK
-    var output = ""
-    dump("\u{61}\u{304b}\u{3099}\u{1f425}" as StaticString, to: &output)
-
-    let expected =
-      "- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
-
-    expectEqual(expected, output)
-  }
-}
-
-Reflection.test("DictionaryIterator/Mirror") {
-  let d: [MinimalHashableValue : OpaqueValue<Int>] =
-    [ MinimalHashableValue(0) : OpaqueValue(0) ]
-
-  var output = ""
-  dump(d.makeIterator(), to: &output)
-
-  let expected =
-    "- Swift.DictionaryIterator<StdlibUnittest.MinimalHashableValue, StdlibUnittest.OpaqueValue<Swift.Int>>\n"
-
-  expectEqual(expected, output)
-}
-
-Reflection.test("SetIterator/Mirror") {
-  let s: Set<MinimalHashableValue> = [ MinimalHashableValue(0)]
-
-  var output = ""
-  dump(s.makeIterator(), to: &output)
-
-  let expected =
-    "- Swift.SetIterator<StdlibUnittest.MinimalHashableValue>\n"
-
-  expectEqual(expected, output)
-}
 
 var BitTwiddlingTestSuite = TestSuite("BitTwiddling")
 
diff --git a/test/stdlib/SetTraps.swift b/test/stdlib/SetTraps.swift
index a1c3a77..668ca8f 100644
--- a/test/stdlib/SetTraps.swift
+++ b/test/stdlib/SetTraps.swift
@@ -51,7 +51,7 @@
     reason: "this trap is not guaranteed to happen in -Ounchecked"))
   .code {
   var s: Set<Int> = [ 10 ]
-  let index = s.index(of: 10)!
+  let index = s.firstIndex(of: 10)!
   s.remove(at: index)
   expectFalse(s.contains(10))
   expectCrashLater()
diff --git a/test/stdlib/subString.swift b/test/stdlib/subString.swift
index 8fa3258..7fd6b15 100644
--- a/test/stdlib/subString.swift
+++ b/test/stdlib/subString.swift
@@ -43,7 +43,7 @@
   expectNotEqual(s.dropLast(2), s.dropLast(1))
   expectEqual(s.dropFirst(1), s.dropFirst(1))
   expectTrue(s != s[...].dropFirst(1))
-  let i = emoji.index(of: "😄")!
+  let i = emoji.firstIndex(of: "😄")!
   expectEqual("😄👍🏽" as String, emoji[i...].prefix(2))
   expectTrue("😄👍🏽🇫🇷👩‍👩‍👧‍👦🙈😡🇧🇪" as String == emoji[i...].dropLast(2))
   expectTrue("🇫🇷👩‍👩‍👧‍👦🙈😡🇧🇪" as String == emoji[i...].dropLast(2).dropFirst(2))
diff --git a/tools/SourceKit/include/SourceKit/Support/Tracing.h b/tools/SourceKit/include/SourceKit/Support/Tracing.h
index 8fc2ad9..87cc03c 100644
--- a/tools/SourceKit/include/SourceKit/Support/Tracing.h
+++ b/tools/SourceKit/include/SourceKit/Support/Tracing.h
@@ -28,7 +28,7 @@
 
 struct SwiftArguments {
   std::string PrimaryFile;
-  std::vector<std::string> Args;
+  std::string Arguments;
 };
 
 enum class OperationKind : uint64_t {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
index 0313270..56a42a4 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
@@ -795,8 +795,8 @@
   trace::TracedOperation TracedOp(trace::OperationKind::PerformSema);
   trace::SwiftInvocation TraceInfo;
   if (TracedOp.enabled()) {
-    TraceInfo.Args.PrimaryFile = InvokRef->Impl.Opts.PrimaryFile;
-    TraceInfo.Args.Args = InvokRef->Impl.Opts.Args;
+    trace::initTraceInfo(TraceInfo, InvokRef->Impl.Opts.PrimaryFile,
+                         InvokRef->Impl.Opts.Args);
   }
 
   ASTUnitRef ASTRef = new ASTUnit(++ASTUnitGeneration, MgrImpl.Stats);
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
index d3398de..59b1b92 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
@@ -865,7 +865,6 @@
       continue;
     }
   }
-  llvm_unreachable("exit is on null byte");
 }
 
 static void translateFilterRules(ArrayRef<FilterRule> rawFilterRules,
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
index f07a3fd..0240b10 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
@@ -198,11 +198,25 @@
 // IndexSource
 //===----------------------------------------------------------------------===//
 
+template <typename Str>
+static void initTraceInfoImpl(trace::SwiftInvocation &SwiftArgs,
+                              StringRef InputFile,
+                              ArrayRef<Str> Args) {
+  llvm::raw_string_ostream OS(SwiftArgs.Args.Arguments);
+  interleave(Args, [&OS](StringRef arg) { OS << arg; }, [&OS] { OS << ' '; });
+  SwiftArgs.Args.PrimaryFile = InputFile;
+}
+
 void trace::initTraceInfo(trace::SwiftInvocation &SwiftArgs,
                           StringRef InputFile,
                           ArrayRef<const char *> Args) {
-  SwiftArgs.Args.Args.assign(Args.begin(), Args.end());
-  SwiftArgs.Args.PrimaryFile = InputFile;
+  initTraceInfoImpl(SwiftArgs, InputFile, Args);
+}
+
+void trace::initTraceInfo(trace::SwiftInvocation &SwiftArgs,
+                          StringRef InputFile,
+                          ArrayRef<std::string> Args) {
+  initTraceInfoImpl(SwiftArgs, InputFile, Args);
 }
 
 void SwiftLangSupport::indexSource(StringRef InputFile,
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
index 715eee6..d50a62c 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
@@ -516,6 +516,9 @@
   void initTraceInfo(trace::SwiftInvocation &SwiftArgs,
                      StringRef InputFile,
                      ArrayRef<const char *> Args);
+  void initTraceInfo(trace::SwiftInvocation &SwiftArgs,
+                     StringRef InputFile,
+                     ArrayRef<std::string> Args);
 }
 
 /// When we cannot build any more clang modules, close the .pcm / files to
diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h
index 29f7da7..18e6e62 100644
--- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h
+++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/sourcekitd.h
@@ -351,7 +351,7 @@
 sourcekitd_variant_t
 sourcekitd_response_get_value(sourcekitd_response_t resp);
 
-SOURCEKITD_PUBLIC SOURCEKITD_NONNULL_ALL SOURCEKITD_WARN_RESULT
+SOURCEKITD_PUBLIC SOURCEKITD_WARN_RESULT
 sourcekitd_variant_type_t
 sourcekitd_variant_get_type(sourcekitd_variant_t obj);
 
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 9df7cba..dbfb4af 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -2711,7 +2711,7 @@
   Dict.set(KeyCompileID, std::to_string(OpId));
   Dict.set(KeyFilePath, Inv.Args.PrimaryFile);
   // FIXME: OperationKind
-  Dict.set(KeyCompilerArgs, Inv.Args.Args);
+  Dict.set(KeyCompilerArgsString, Inv.Args.Arguments);
   sourcekitd::postNotification(RespBuilder.createResponse());
 }
 
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
index f30f00f..37d6e90 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
@@ -583,9 +583,9 @@
 #define XPC_OBJ(var) ((xpc_object_t)(var).data[1])
 
 #define CUSTOM_BUF_KIND(xobj) \
-  ((CustomBufferKind)*(uint64_t*)xpc_data_get_bytes_ptr(xobj))
+  ((CustomBufferKind)*(const uint64_t*)xpc_data_get_bytes_ptr(xobj))
 #define CUSTOM_BUF_START(xobj) \
-  ((void*)(((uint64_t*)xpc_data_get_bytes_ptr(xobj))+1))
+  ((const void*)(((const uint64_t*)xpc_data_get_bytes_ptr(xobj))+1))
 
 static sourcekitd_variant_type_t XPCVar_get_type(sourcekitd_variant_t var) {
   xpc_object_t obj = XPC_OBJ(var);
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 4798c77..03fcf9e 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -70,6 +70,7 @@
     // The following two are for testing purposes
     DeserializeDiffItems,
     DeserializeSDK,
+    GenerateNameCorrectionTemplate,
   };
 } // end anonymous namespace
 
@@ -141,7 +142,10 @@
                      "Deserialize diff items in a JSON file"),
           clEnumValN(ActionType::DeserializeSDK,
                      "deserialize-sdk",
-                     "Deserialize sdk digester in a JSON file")));
+                     "Deserialize sdk digester in a JSON file"),
+          clEnumValN(ActionType::GenerateNameCorrectionTemplate,
+                     "generate-name-correction",
+                     "Generate name correction template")));
 
 static llvm::cl::list<std::string>
 SDKJsonPaths("input-paths",
@@ -2727,15 +2731,13 @@
   }
 
   bool detectDictionaryKeyChange(SDKNodeType *L, SDKNodeType *R) {
-    if (!IsVisitingLeft)
-      return false;
-
     // We only care if this the top-level type node.
     if (!L->isTopLevelType() || !R->isTopLevelType())
       return false;
     StringRef KeyChangedTo;
-    if (L->getTypeKind() == KnownTypeKind::Optional &&
-        R->getTypeKind() == KnownTypeKind::Optional) {
+    bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
+      R->getTypeKind() == KnownTypeKind::Optional;
+    if (HasOptional) {
       // Detect [String: Any]? to [StringRepresentableStruct: Any]? Chnage
       KeyChangedTo =
         detectDictionaryKeyChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
@@ -2745,10 +2747,16 @@
       KeyChangedTo = detectDictionaryKeyChangeInternal(L, R);
     }
     if (!KeyChangedTo.empty()) {
-      L->annotate(L->getTypeKind() == KnownTypeKind::Optional ?
+      if (IsVisitingLeft) {
+        L->annotate(HasOptional ?
                     NodeAnnotation::OptionalDictionaryKeyUpdate :
                     NodeAnnotation::DictionaryKeyUpdate);
-      L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+        L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+      } else {
+        R->annotate(HasOptional ?
+                    NodeAnnotation::RevertOptionalDictionaryKeyUpdate :
+                    NodeAnnotation::RevertDictionaryKeyUpdate);
+      }
       return true;
     }
     return false;
@@ -2769,14 +2777,13 @@
   }
 
   bool detectArrayMemberChange(SDKNodeType* L, SDKNodeType *R) {
-    if (!IsVisitingLeft)
-      return false;
     // We only care if this the top-level type node.
     if (!L->isTopLevelType() || !R->isTopLevelType())
       return false;
     StringRef KeyChangedTo;
-    if (L->getTypeKind() == KnownTypeKind::Optional &&
-        R->getTypeKind() == KnownTypeKind::Optional) {
+    bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
+      R->getTypeKind() == KnownTypeKind::Optional;
+    if (HasOptional) {
       // Detect [String]? to [StringRepresentableStruct]? Chnage
       KeyChangedTo =
         detectArrayMemberChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
@@ -2786,18 +2793,22 @@
       KeyChangedTo = detectArrayMemberChangeInternal(L, R);
     }
     if (!KeyChangedTo.empty()) {
-      L->annotate(L->getTypeKind() == KnownTypeKind::Optional ?
+      if (IsVisitingLeft) {
+        L->annotate(HasOptional ?
                     NodeAnnotation::OptionalArrayMemberUpdate :
                     NodeAnnotation::ArrayMemberUpdate);
-      L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+        L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+      } else {
+        R->annotate(HasOptional ?
+                    NodeAnnotation::RevertOptionalArrayMemberUpdate :
+                    NodeAnnotation::RevertArrayMemberUpdate);
+      }
       return true;
     }
     return false;
   }
 
   bool detectSimpleStringRepresentableUpdate(SDKNodeType *L, SDKNodeType *R) {
-    if (!IsVisitingLeft)
-      return false;
     if (!L->isTopLevelType() || !R->isTopLevelType())
       return false;
     StringRef KeyChangedTo;
@@ -2813,11 +2824,15 @@
       KeyChangedTo = getStringRepresentableChange(L, R);
     }
     if (!KeyChangedTo.empty()) {
-      L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
-      if (HasOptional) {
-        L->annotate(NodeAnnotation::SimpleOptionalStringRepresentableUpdate);
+      if (IsVisitingLeft) {
+        L->annotate(NodeAnnotation::TypeRewrittenRight, KeyChangedTo);
+        L->annotate(HasOptional ?
+                    NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
+                    NodeAnnotation::SimpleStringRepresentableUpdate);
       } else {
-        L->annotate(NodeAnnotation::SimpleStringRepresentableUpdate);
+        R->annotate(HasOptional ?
+                    NodeAnnotation::RevertSimpleOptionalStringRepresentableUpdate:
+                    NodeAnnotation::RevertSimpleStringRepresentableUpdate);
       }
       return true;
     }
@@ -3965,6 +3980,33 @@
   return 0;
 }
 
+static int deserializeNameCorrection(APIDiffItemStore &Store,
+                                     StringRef OutputPath) {
+  std::error_code EC;
+  llvm::raw_fd_ostream FS(OutputPath, EC, llvm::sys::fs::F_None);
+  std::set<NameCorrectionInfo> Result;
+  for (auto *Item: Store.getAllDiffItems()) {
+    if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
+      if (CI->DiffKind == NodeAnnotation::Rename) {
+        auto NewName = CI->getNewName();
+        auto Module = CI->ModuleName;
+        DeclNameViewer Viewer(NewName);
+        auto HasUnderScore =
+          [](StringRef S) { return S.find('_') != StringRef::npos; };
+        auto Args = Viewer.args();
+        if (HasUnderScore(Viewer.base()) ||
+            std::any_of(Args.begin(), Args.end(), HasUnderScore)) {
+          Result.insert(NameCorrectionInfo(NewName, NewName, Module));
+        }
+      }
+    }
+  }
+  std::vector<NameCorrectionInfo> Vec;
+  Vec.insert(Vec.end(), Result.begin(), Result.end());
+  APIDiffItemStore::serialize(FS, Vec);
+  return EC.value();
+}
+
 /// Mostly for testing purposes, this function de-serializes the SDK dump in
 /// dumpPath and re-serialize them to OutputPath. If the tool performs correctly,
 /// the contents in dumpPath and OutputPath should be identical.
@@ -4029,6 +4071,13 @@
     else
       return deserializeSDKDump(options::SDKJsonPaths[0], options::OutputFile);
   }
+  case ActionType::GenerateNameCorrectionTemplate: {
+    APIDiffItemStore Store;
+    auto &Paths = options::SDKJsonPaths;
+    for (unsigned I = 0; I < Paths.size(); I ++)
+      Store.addStorePath(Paths[I]);
+    return deserializeNameCorrection(Store, options::OutputFile);
+  }
   case ActionType::None:
     llvm::errs() << "Action required\n";
     llvm::cl::PrintHelpMessage();
diff --git a/utils/build-script-impl b/utils/build-script-impl
index a580e6c..b46a7cb 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -3483,7 +3483,7 @@
             fi
 
             LIT_EXECUTABLE_PATH="${LLVM_SOURCE_DIR}/utils/lit/lit.py"
-            FILECHECK_EXECUTABLE_PATH="$(build_directory_bin ${LOCAL_HOST} llvm)/FileCheck"
+            LLVM_BIN_DIR="$(build_directory_bin ${LOCAL_HOST} llvm)"
             echo "-- Test Installable Package --"
             call rm -rf "${PKG_TESTS_SANDBOX_PARENT}"
             call mkdir -p "${PKG_TESTS_SANDBOX}"
@@ -3491,7 +3491,7 @@
                 call tar xzf "${package_for_host}"
 
             with_pushd "${PKG_TESTS_SOURCE_DIR}" \
-                call python "${LIT_EXECUTABLE_PATH}" . -sv --param package-path="${PKG_TESTS_SANDBOX}" --param filecheck="${FILECHECK_EXECUTABLE_PATH}" --param test-exec-root="${PKG_TESTS_TEMPS}"
+                call python "${LIT_EXECUTABLE_PATH}" . -sv --param package-path="${PKG_TESTS_SANDBOX}" --param test-exec-root="${PKG_TESTS_TEMPS}" --param llvm-bin-dir="${LLVM_BIN_DIR}"
         fi
     fi
 }
diff --git a/utils/gyb_sourcekit_support/UIDs.py b/utils/gyb_sourcekit_support/UIDs.py
index df4443b..52e7990 100644
--- a/utils/gyb_sourcekit_support/UIDs.py
+++ b/utils/gyb_sourcekit_support/UIDs.py
@@ -154,6 +154,7 @@
     KEY('ActionUID', 'key.actionuid'),
     KEY('ActionUnavailableReason', 'key.actionunavailablereason'),
     KEY('CompileID', 'key.compileid'),
+    KEY('CompilerArgsString', 'key.compilerargs-string'),
 ]
 
 
diff --git a/utils/gyb_stdlib_unittest_support.py b/utils/gyb_stdlib_unittest_support.py
deleted file mode 100644
index f3a7940..0000000
--- a/utils/gyb_stdlib_unittest_support.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# ===--- gyb_stdlib_unittest_support.py --------------*- coding: utf-8 -*-===//
-#
-# This source file is part of the Swift.org open source project
-#
-# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-# Licensed under Apache License v2.0 with Runtime Library Exception
-#
-# See https://swift.org/LICENSE.txt for license information
-# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-
-TRACE = '''
-  _ message: @autoclosure () -> String = "",
-  stackTrace: SourceLocStack = SourceLocStack(),
-  showFrame: Bool = true,
-  file: String = #file, line: UInt = #line'''
-
-stackTrace = 'stackTrace.pushIf(showFrame, file: file, line: line)'
-
-trace = 'message(),\n  stackTrace: ' + stackTrace
diff --git a/utils/update-checkout-config.json b/utils/update-checkout-config.json
index 039c2df..d4588f1 100644
--- a/utils/update-checkout-config.json
+++ b/utils/update-checkout-config.json
@@ -202,8 +202,8 @@
                 "swift-corelibs-xctest": "swift-4.2-branch",
                 "swift-corelibs-foundation": "swift-4.2-branch",
                 "swift-corelibs-libdispatch": "swift-4.2-branch",
-                "swift-integration-tests": "master",
-                "swift-xcode-playground-support": "master",
+                "swift-integration-tests": "swift-4.2-branch",
+                "swift-xcode-playground-support": "swift-4.2-branch",
                 "ninja": "release"
             }
         },
diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar28145033.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar28145033.swift
index 826f224..bcb2c653 100644
--- a/validation-test/Sema/type_checker_crashers_fixed/rdar28145033.swift
+++ b/validation-test/Sema/type_checker_crashers_fixed/rdar28145033.swift
@@ -1,4 +1,4 @@
 // RUN: not %target-swift-frontend %s -typecheck
 
 let a = [1]
-_ = a.index(of: a.min()) // a.min() returns an optional
+_ = a.firstIndex(of: a.min()) // a.min() returns an optional
diff --git a/validation-test/compiler_crashers_2/0153-rdar39130543.swift b/validation-test/compiler_crashers_2/0153-rdar39130543.swift
index 40d25aa..3a9f7fd 100644
--- a/validation-test/compiler_crashers_2/0153-rdar39130543.swift
+++ b/validation-test/compiler_crashers_2/0153-rdar39130543.swift
@@ -1,4 +1,5 @@
 // RUN: not --crash %target-swift-frontend %s -emit-ir
+// REQUIRES: asserts
 
 protocol P20 { }
 
diff --git a/validation-test/compiler_crashers_2/0123-rdar31164540.swift b/validation-test/compiler_crashers_2_fixed/0123-rdar31164540.swift
similarity index 99%
rename from validation-test/compiler_crashers_2/0123-rdar31164540.swift
rename to validation-test/compiler_crashers_2_fixed/0123-rdar31164540.swift
index 0f3f306..a908f98 100644
--- a/validation-test/compiler_crashers_2/0123-rdar31164540.swift
+++ b/validation-test/compiler_crashers_2_fixed/0123-rdar31164540.swift
@@ -1,4 +1,4 @@
-// RUN: not --crash %target-swift-frontend -parse-stdlib -DBUILDING_OUTSIDE_STDLIB %s -emit-ir
+// RUN: not %target-swift-frontend -parse-stdlib -DBUILDING_OUTSIDE_STDLIB %s -emit-ir
 // REQUIRES: objc_interop
 
 //===----------------------------------------------------------------------===//
diff --git a/validation-test/compiler_crashers_2_fixed/0139-rdar36278079.swift b/validation-test/compiler_crashers_2_fixed/0139-rdar36278079.swift
new file mode 100644
index 0000000..e89e20f
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0139-rdar36278079.swift
@@ -0,0 +1,19 @@
+// RUN: not %target-swift-frontend -typecheck %s
+
+struct S {
+  // presence of a static instance seems to be
+  // necessary to cause this problem
+  static let s = S()
+}
+
+protocol P {
+  associatedtype T
+  init(t: T)
+}
+
+extension S: P {
+// Uncomment to stop assertion:
+//  init(t: Int) {
+//    self = S()
+//  }
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0153-rdar36497404.swift b/validation-test/compiler_crashers_2_fixed/0153-rdar36497404.swift
new file mode 100644
index 0000000..ff06aac
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0153-rdar36497404.swift
@@ -0,0 +1,44 @@
+// RUN: %target-build-swift -emit-module -o %t %s
+
+public protocol P1 {}
+public protocol P2 {}
+
+public protocol P3 {
+  static func a()
+
+  func b()
+  func b<I: P1>(_: (I) -> Void)
+
+  static func c<I: P1>(_: I)
+  static func d()
+  static func d<I: P1>(_: ([(I, I)]) -> Void)
+  static func d<I: P1>(_: ([I: I]) -> Void)
+  static func d<Q: P1>(_: Q)
+
+  static func e<Q: P1, I: P2>(_: Q, _: (I) -> Void)
+  static func f<Q: P1, I: P2>(_: Q, _: (I) -> Void)
+
+  func g<I: P1>(_: I)
+}
+
+public extension P3 {
+  static func a() {}
+
+  func b() {}
+  func b<I: P1>(_: (I) -> Void) {}
+
+  static func c<I: P1>(_: I) {}
+
+  static func d() {}
+  static func d<I: P1>(_: ([(I, I)]) -> Void) {}
+  static func d<I: P1>(_: ([I: I]) -> Void) {}
+  static func d<Q: P1>(_: Q) {}
+
+  static func e<Q: P1, I: P2>(_: Q, _: (I) -> Void) {}
+  static func f<Q: P1, I: P2>(_: Q, _: (I) -> Void) {}
+
+  func g<I: P1>(_: I) {}
+}
+
+struct S: P3 {
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0154-sr7457.swift b/validation-test/compiler_crashers_2_fixed/0154-sr7457.swift
new file mode 100644
index 0000000..808206d
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0154-sr7457.swift
@@ -0,0 +1,16 @@
+// RUN: %target-swift-frontend %s -emit-ir
+protocol Proto { }
+
+class Class {
+    func foo<A>(callback: (A) -> Void) where A: Proto {
+    }
+
+    func foo<A, B>(callback: (A, B) -> Void) where A: Proto, B: Proto {
+    }
+}
+
+class Child: Class {
+    override func foo<A>(callback: (A) -> Void) where A : Proto {
+    }
+}
+
diff --git a/validation-test/compiler_crashers_2_fixed/0155-sr7364.swift b/validation-test/compiler_crashers_2_fixed/0155-sr7364.swift
new file mode 100644
index 0000000..e065a1a
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0155-sr7364.swift
@@ -0,0 +1,22 @@
+// RUN: not %target-swift-frontend %s -emit-ir
+
+
+public protocol E {
+	associatedtype F
+	
+	static func g(_: F) -> Self
+}
+
+internal enum CF {
+	case f
+}
+
+internal enum CE: E {
+	case f(CF)
+	
+	static func g(_ f: CF) -> CE {
+		return CE.f(f)
+	}
+	
+	static let cf = CE.g(.f)
+}
diff --git a/validation-test/stdlib/AnyHashable.swift.gyb b/validation-test/stdlib/AnyHashable.swift.gyb
index fcdefb0..05084ad 100644
--- a/validation-test/stdlib/AnyHashable.swift.gyb
+++ b/validation-test/stdlib/AnyHashable.swift.gyb
@@ -58,7 +58,7 @@
 let AnyHashableTests = TestSuite("AnyHashableTests")
 
 AnyHashableTests.test("CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable") {
-  var v = AnyHashable(CustomPrintableValue(1))
+  let v = AnyHashable(CustomPrintableValue(1))
   expectPrinted("(value: 1).description", v)
   expectDebugPrinted("AnyHashable((value: 1).debugDescription)", v)
   expectDumped(
@@ -117,8 +117,8 @@
   ${wrapped}_equalImpl.value = {
     ($0 as! ${payload}).value == ($1 as! ${payload}).value
   }
-  ${wrapped}_hashValueImpl.value = {
-    ($0 as! ${payload}).value
+  ${wrapped}_hashIntoImpl.value = {
+    $1.combine(($0 as! ${payload}).value)
   }
   let xs = (0...5).flatMap {
     [ ${wrapped}(${payload}($0), identity: 0),
@@ -142,7 +142,7 @@
   var xs: [AnyHashable] = []
 
 % for wrapped in ['MinimalHashableValue', 'MinimalHashableClass']:
-  xs += (0...5).flatMap {
+  xs += (0..<6).flatMap {
     [ ${wrapped}($0, identity: 0),
       ${wrapped}($0, identity: 1) ].map(AnyHashable.init)
   }
@@ -157,25 +157,31 @@
     }
     return (lhs as! LifetimeTracked) == (rhs as! LifetimeTracked)
   }
-  ${wrapped}_hashValueImpl.value = {
-    payload in
+  ${wrapped}_hashIntoImpl.value = { payload, hasher in
     if let x = payload as? OpaqueValue<Int> {
-      return x.value
+      hasher.combine(x.value)
+      return
     }
-    return (payload as! LifetimeTracked).value
+    hasher.combine((payload as! LifetimeTracked).value)
   }
 % end
 
 % for wrapped in ['GenericMinimalHashableValue', 'GenericMinimalHashableClass']:
 %   for payload in [ 'OpaqueValue<Int>', 'LifetimeTracked' ]:
-  xs += (0...5).flatMap {
+  xs += (0..<6).flatMap {
     [ ${wrapped}(${payload}($0), identity: 0),
       ${wrapped}(${payload}($0), identity: 1) ].map(AnyHashable.init)
   }
 %   end
 % end
 
-  checkHashable(xs, equalityOracle: { $0 / 2 == $1 / 2 })
+  checkHashable(
+    xs,
+    equalityOracle: { $0 / 2 == $1 / 2 },
+    // FIXME: Types that hash the same way will produce hash collisions when
+    // converted to AnyHashable. Arguably, the type id should be used as a hash
+    // discriminator.
+    hashEqualityOracle: { $0 / 2 % 6 == $1 / 2 % 6 })
 }
 
 % for (kw, name) in [
@@ -305,8 +311,8 @@
   GenericMinimalHashableValue_equalImpl.value = {
     ($0 as! ${payload}).value == ($1 as! ${payload}).value
   }
-  GenericMinimalHashableValue_hashValueImpl.value = {
-    ($0 as! ${payload}).value
+  GenericMinimalHashableValue_hashIntoImpl.value = { v, hasher in
+    hasher.combine((v as! ${payload}).value)
   }
   let xs = (-2...2).flatMap {
     [ ${genericWrapped}(
@@ -373,8 +379,8 @@
   GenericMinimalHashableValue_equalImpl.value = {
     ($0 as! ${payload}).value == ($1 as! ${payload}).value
   }
-  GenericMinimalHashableValue_hashValueImpl.value = {
-    ($0 as! ${payload}).value
+  GenericMinimalHashableValue_hashIntoImpl.value = { v, hasher in
+    hasher.combine((v as! ${payload}).value)
   }
   // If the custom representation has its own custom representation,
   // we ignore it.
@@ -437,18 +443,20 @@
   init(_ value: Int) {
     self.value = value
   }
-  ${'override' if 'ObjC' in prefix else ''} var hashValue: Int {
+%   if 'ObjC' in prefix:
+  override var hash: Int {
     return value
   }
-%   if 'ObjC' in prefix:
   override func isEqual(_ object: Any?) -> Bool {
     guard let rhs = object as? ${hashable_base.full_name} else {
       return false
     }
     return self.value == rhs.value
   }
-%   end
-%   if not 'ObjC' in prefix:
+%   else:
+  var hashValue: Int {
+    return value
+  }
   static func == ${hashable_base.generic_parameters_decl} (
     lhs: ${hashable_base.full_name},
     rhs: ${hashable_base.full_name}
@@ -575,18 +583,27 @@
 AnyHashableTests.test("AnyHashable(CFBitVector)/Hashable, .base") {
   let bitVectors: [CFBitVector] =
     interestingBitVectorArrays.map(CFBitVector.makeImmutable)
+  let hashEqualityOracle: (Int, Int) -> Bool = {
+    // CFBitVector returns its count as the hash.
+    interestingBitVectorArrays[$0].count == interestingBitVectorArrays[$1].count
+  }
   let arrays = bitVectors.map { $0.asArray }
   func isEq(_ lhs: [[UInt8]], _ rhs: [[UInt8]]) -> Bool {
     return zip(lhs, rhs).map { $0 == $1 }.reduce(true, { $0 && $1 })
   }
   expectEqualTest(interestingBitVectorArrays, arrays, sameValue: isEq)
-  checkHashable(bitVectors, equalityOracle: { $0 == $1 })
+  checkHashable(
+    bitVectors,
+    equalityOracle: { $0 == $1 },
+    hashEqualityOracle: hashEqualityOracle)
 
   do {
     expectEqual(.foreignClass, SwiftRuntime.metadataKind(of: bitVectors.first!))
 
     let anyHashables = bitVectors.map(AnyHashable.init)
-    checkHashable(anyHashables, equalityOracle: { $0 == $1 })
+    checkHashable(anyHashables,
+      equalityOracle: { $0 == $1 },
+      hashEqualityOracle: hashEqualityOracle)
 
     let v = anyHashables.first!.base
     expectTrue(type(of: v) is CFBitVector.Type)
@@ -600,7 +617,9 @@
       SwiftRuntime.metadataKind(of: bitVectorsAsAnyObjects.first!))
 
     let anyHashables = bitVectorsAsAnyObjects.map(AnyHashable.init)
-    checkHashable(anyHashables, equalityOracle: { $0 == $1 })
+    checkHashable(anyHashables,
+      equalityOracle: { $0 == $1 },
+      hashEqualityOracle: hashEqualityOracle)
 
     let v = anyHashables.first!.base
     expectTrue(type(of: v) is CFBitVector.Type)
@@ -612,12 +631,19 @@
   // CFBitVector.
   let bitVectors: [CFMutableBitVector] =
     interestingBitVectorArrays.map(CFMutableBitVector.makeMutable)
+  let hashEqualityOracle: (Int, Int) -> Bool = {
+    // CFBitVector returns its count as the hash.
+    interestingBitVectorArrays[$0].count == interestingBitVectorArrays[$1].count
+  }
   let arrays = bitVectors.map { $0.asArray }
   func isEq(_ lhs: [[UInt8]], _ rhs: [[UInt8]]) -> Bool {
     return zip(lhs, rhs).map { $0 == $1 }.reduce(true, { $0 && $1 })
   }
   expectEqualTest(interestingBitVectorArrays, arrays, sameValue: isEq)
-  checkHashable(bitVectors, equalityOracle: { $0 == $1 })
+  checkHashable(
+    bitVectors,
+    equalityOracle: { $0 == $1 },
+    hashEqualityOracle: hashEqualityOracle)
 
   do {
     expectEqual(
@@ -625,7 +651,10 @@
       SwiftRuntime.metadataKind(of: bitVectors.first!))
 
     let anyHashables = bitVectors.map(AnyHashable.init)
-    checkHashable(anyHashables, equalityOracle: { $0 == $1 })
+    checkHashable(
+      anyHashables,
+      equalityOracle: { $0 == $1 },
+      hashEqualityOracle: hashEqualityOracle)
 
     let v = anyHashables.first!.base
     expectTrue(type(of: v) is CFMutableBitVector.Type)
@@ -634,14 +663,20 @@
     let bitVectorsAsAnyObjects: [NSObject] = bitVectors.map {
       ($0 as AnyObject) as! NSObject
     }
-    checkHashable(bitVectorsAsAnyObjects, equalityOracle: { $0 == $1 })
+    checkHashable(
+      bitVectorsAsAnyObjects,
+      equalityOracle: { $0 == $1 },
+      hashEqualityOracle: hashEqualityOracle)
 
     expectEqual(
       .objCClassWrapper,
       SwiftRuntime.metadataKind(of: bitVectorsAsAnyObjects.first!))
 
     let anyHashables = bitVectorsAsAnyObjects.map(AnyHashable.init)
-    checkHashable(anyHashables, equalityOracle: { $0 == $1 })
+    checkHashable(
+      anyHashables,
+      equalityOracle: { $0 == $1 },
+      hashEqualityOracle: hashEqualityOracle)
 
     let v = anyHashables.first!.base
     expectTrue(type(of: v) is CFMutableBitVector.Type)
@@ -717,10 +752,14 @@
     .caseC(LifetimeTracked(2)), .caseC(LifetimeTracked(2)),
   ]
   expectEqual(.enum, SwiftRuntime.metadataKind(of: xs.first!))
-  checkHashable(xs, equalityOracle: { $0 / 2 == $1 / 2 })
+  checkHashable(
+    xs,
+    equalityOracle: { $0 / 2 == $1 / 2 },
+    hashEqualityOracle: { $0 / 4 == $1 / 4 })
   checkHashable(
     xs.map(AnyHashable.init),
-    equalityOracle: { $0 / 2 == $1 / 2 })
+    equalityOracle: { $0 / 2 == $1 / 2 },
+    hashEqualityOracle: { $0 / 4 == $1 / 4 })
 }
 
 AnyHashableTests.test("AnyHashable(MinimalHashableRCSwiftError).base") {
@@ -763,8 +802,16 @@
     return lhs == rhs
   }
 
-  checkHashable(values, equalityOracle: equalityOracle,
-                allowBrokenTransitivity: true)
+  func hashEqualityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
+    // Elements in [0, 3] hash the same, as do elements in [4, 7].
+    return lhs / 4 == rhs / 4
+  }
+
+  checkHashable(
+    values,
+    equalityOracle: equalityOracle,
+    hashEqualityOracle: hashEqualityOracle,
+    allowBrokenTransitivity: true)
 }
 
 AnyHashableTests.test("AnyHashable(Set)/Hashable") {
@@ -789,8 +836,10 @@
     }
   }
 
-  checkHashable(values, equalityOracle: equalityOracle,
-                allowBrokenTransitivity: true)
+  checkHashable(
+    values,
+    equalityOracle: equalityOracle,
+    allowBrokenTransitivity: true)
 }
 
 AnyHashableTests.test("AnyHashable(Array)/Hashable") {
@@ -902,6 +951,12 @@
     .caseC(LifetimeTracked(1)), .caseC(LifetimeTracked(1)),
     .caseC(LifetimeTracked(2)), .caseC(LifetimeTracked(2)),
   ]
+  checkHashable(
+    swiftErrors,
+    equalityOracle: { $0 / 2 == $1 / 2 },
+    hashEqualityOracle: { $0 / 4 == $1 / 4 },
+    allowBrokenTransitivity: false)
+
   let nsErrors: [NSError] = swiftErrors.flatMap {
     swiftError -> [NSError] in
     let bridgedNSError = swiftError as NSError
@@ -938,16 +993,23 @@
     return false
   }
 
+  func hashEqualityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
+    // Every NSError that has the same domain and code hash the same way.
+    return lhs / 8 == rhs / 8
+  }
+
   // FIXME: transitivity is broken because pure `NSError`s can compare equal to
   // Swift errors with payloads just based on the domain and code, and Swift
   // errors with payloads don't compare equal when payloads differ.
   checkHashable(
     nsErrors,
     equalityOracle: equalityOracle,
+    hashEqualityOracle: hashEqualityOracle,
     allowBrokenTransitivity: true)
   checkHashable(
     nsErrors.map(AnyHashable.init),
     equalityOracle: equalityOracle,
+    hashEqualityOracle: hashEqualityOracle,
     allowBrokenTransitivity: true)
 
   // FIXME(id-as-any): run `checkHashable` on an array of mixed
diff --git a/validation-test/stdlib/Arrays.swift.gyb b/validation-test/stdlib/Arrays.swift.gyb
index 8f81059..2bd0b6b 100644
--- a/validation-test/stdlib/Arrays.swift.gyb
+++ b/validation-test/stdlib/Arrays.swift.gyb
@@ -190,21 +190,55 @@
 }
 
 ArrayTestSuite.test("Hashable") {
-  let a1: Array<Int> = [1, 2, 3]
-  let a2: Array<Int> = [1, 3, 2]
-  let a3: Array<Int> = [3, 1, 2]
-  let a4: Array<Int> = [1, 2]
-  let a5: Array<Int> = [1]
-  let a6: Array<Int> = []
-  let a7: Array<Int> = [1, 1, 1]
-  checkHashable([a1, a2, a3, a4, a5, a6, a7], equalityOracle: { $0 == $1 })
+  let a1: [Array<Int>] = [
+    [1, 2, 3],
+    [1, 3, 2],
+    [3, 1, 2],
+    [1, 2],
+    [1],
+    [],
+    [1, 1, 1]
+  ]
+  checkHashable(a1, equalityOracle: { $0 == $1 })
 
-  let aa1: Array<Array<Int>> = [[], [1], [1, 2], [2, 1]]
-  let aa2: Array<Array<Int>> = [[], [1], [2, 1], [2, 1]]
-  let aa3: Array<Array<Int>> = [[1], [], [2, 1], [2, 1]]
-  let aa4: Array<Array<Int>> = [[1], [], [2, 1], [2]]
-  let aa5: Array<Array<Int>> = [[1], [], [2, 1]]
-  checkHashable([aa1, aa2, aa3, aa4, aa5], equalityOracle: { $0 == $1 })
+  let a2: [Array<Array<Int>>] = [
+    [[], [1], [1, 2], [2, 1]],
+    [[], [1], [2, 1], [2, 1]],
+    [[1], [], [2, 1], [2, 1]],
+    [[1], [], [2, 1], [2]],
+    [[1], [], [2, 1]]
+  ]
+  checkHashable(a2, equalityOracle: { $0 == $1 })
+
+  // These arrays share the same sequence of leaf integers, but they must
+  // still all hash differently.
+  let a3: [Array<Array<Int>>] = [
+    // Grouping changes must perturb the hash.
+    [[1], [2], [3], [4], [5]],
+    [[1, 2], [3], [4], [5]],
+
+    [[1], [2, 3], [4], [5]],
+    [[1], [2], [3, 4], [5]],
+    [[1], [2], [3], [4, 5]],
+
+    [[1, 2, 3], [4], [5]],
+    [[1], [2, 3, 4], [5]],
+    [[1], [2], [3, 4, 5]],
+
+    [[1, 2, 3, 4], [5]],
+    [[1], [2, 3, 4, 5]],
+
+    [[1, 2], [3, 4], [5]],
+    [[1], [2, 3], [4, 5]],
+    [[1, 2, 3, 4, 5]],
+
+    // Empty arrays must perturb the hash.
+    [[], [1], [2], [3], [4], [5]],
+    [[1], [], [2], [3], [4], [5]],
+    [[1], [2], [3], [4], [5], []],
+    [[1], [], [], [2], [3], [], [4], [], [5]],
+  ]
+  checkHashable(a3, equalityOracle: { $0 == $1 })
 }
 
 
diff --git a/validation-test/stdlib/CollectionCasts.swift.gyb b/validation-test/stdlib/CollectionCasts.swift.gyb
index 3c39a10..5748fcc 100644
--- a/validation-test/stdlib/CollectionCasts.swift.gyb
+++ b/validation-test/stdlib/CollectionCasts.swift.gyb
@@ -47,7 +47,6 @@
 }
 
 %{
-from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
 classKeys = ('Derived', 'Base')
 classValues = classKeys + ('AnyObject', 'Any')
 nonClassKeys = ('Int',)
diff --git a/validation-test/stdlib/CollectionType.swift.gyb b/validation-test/stdlib/CollectionType.swift.gyb
index 7ecf241..130e366 100644
--- a/validation-test/stdlib/CollectionType.swift.gyb
+++ b/validation-test/stdlib/CollectionType.swift.gyb
@@ -624,12 +624,12 @@
 }
 
 //===----------------------------------------------------------------------===//
-// index(of:)
+// firstIndex(of:)
 //===----------------------------------------------------------------------===//
 
-CollectionTypeTests.test("index(of:)/WhereElementIsEquatable/dispatch") {
+CollectionTypeTests.test("firstIndex(of:)/WhereElementIsEquatable/dispatch") {
   let tester = CollectionLog.dispatchTester([MinimalEquatableValue(1)])
-  _ = tester.index(of: MinimalEquatableValue(1))
+  _ = tester.firstIndex(of: MinimalEquatableValue(1))
   expectCustomizable(tester, tester.log._customIndexOfEquatableElement)
 }
 
@@ -640,14 +640,14 @@
   C : Collection
 >(_ collection: C, _ element: C.Iterator.Element) -> C.Index? 
 where C.Iterator.Element : Equatable {
-  return collection.index(of: element)
+  return collection.firstIndex(of: element)
 }
 
 func callStaticFind_(
   _ set: Set<MinimalHashableValue>,
   _ element: MinimalHashableValue
 ) -> Set<MinimalHashableValue>.Index? {
-  return set.index(of: element)
+  return set.firstIndex(of: element)
 }
 
 % for dispatch in [ 'Static', 'Generic' ]:
@@ -659,7 +659,7 @@
     let s = Set<MinimalHashableValue>(
       test.sequence.map { MinimalHashableValue($0.value) })
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    MinimalHashableValue.timesHashValueWasCalled = 0
+    MinimalHashableValue.timesHashIntoWasCalled = 0
     expectEqual(
       test.expected
         .map { _ in MinimalHashableValue(test.element.value) },
@@ -671,11 +671,11 @@
         0, MinimalHashableValue.timesEqualEqualWasCalled,
         stackTrace: SourceLocStack().with(test.loc))
       expectEqual(
-        0, MinimalHashableValue.timesHashValueWasCalled,
+        0, MinimalHashableValue.timesHashIntoWasCalled,
         stackTrace: SourceLocStack().with(test.loc))
     } else {
       expectNotEqual(
-        0, MinimalHashableValue.timesHashValueWasCalled,
+        0, MinimalHashableValue.timesHashIntoWasCalled,
         stackTrace: SourceLocStack().with(test.loc))
     }
     if test.expected != nil {
@@ -702,7 +702,7 @@
   func _test_indicesOf(_ element: Iterator.Element) -> [Index] {
     var result: [Index] = []
     var tail = self[startIndex..<endIndex]
-    while let foundIndex = tail.index(of: element) {
+    while let foundIndex = tail.firstIndex(of: element) {
       result.append(foundIndex)
       tail = tail[index(after: foundIndex)..<endIndex]
     }
@@ -710,7 +710,7 @@
   }
 }
 
-CollectionTypeTests.test("index(of:)/ContinueSearch") {
+CollectionTypeTests.test("firstIndex(of:)/ContinueSearch") {
   do {
     let c = MinimalCollection(elements: [] as [MinimalEquatableValue])
     expectEqualSequence(
diff --git a/validation-test/stdlib/Dictionary.swift b/validation-test/stdlib/Dictionary.swift
index 4061f91..4c28044 100644
--- a/validation-test/stdlib/Dictionary.swift
+++ b/validation-test/stdlib/Dictionary.swift
@@ -274,13 +274,13 @@
   do {
     var d2: [MinimalHashableValue : OpaqueValue<Int>] = [:]
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    MinimalHashableValue.timesHashValueWasCalled = 0
+    MinimalHashableValue.timesHashIntoWasCalled = 0
     expectNil(d2[MinimalHashableValue(42)])
 
     // If the dictionary is empty, we shouldn't be computing the hash value of
     // the provided key.
     expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
   }
 }
 
@@ -330,14 +330,14 @@
   do {
     var d2: [MinimalHashableClass : OpaqueValue<Int>] = [:]
     MinimalHashableClass.timesEqualEqualWasCalled = 0
-    MinimalHashableClass.timesHashValueWasCalled = 0
+    MinimalHashableClass.timesHashIntoWasCalled = 0
 
     expectNil(d2[MinimalHashableClass(42)])
 
     // If the dictionary is empty, we shouldn't be computing the hash value of
     // the provided key.
     expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
   }
 }
 
@@ -864,13 +864,13 @@
   do {
     var d2: [MinimalHashableValue : OpaqueValue<Int>] = [:]
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    MinimalHashableValue.timesHashValueWasCalled = 0
+    MinimalHashableValue.timesHashIntoWasCalled = 0
     expectNil(d2.index(forKey: MinimalHashableValue(42)))
 
     // If the dictionary is empty, we shouldn't be computing the hash value of
     // the provided key.
     expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
   }
 }
 
@@ -901,13 +901,13 @@
   do {
     var d2: [MinimalHashableClass : OpaqueValue<Int>] = [:]
     MinimalHashableClass.timesEqualEqualWasCalled = 0
-    MinimalHashableClass.timesHashValueWasCalled = 0
+    MinimalHashableClass.timesHashIntoWasCalled = 0
     expectNil(d2.index(forKey: MinimalHashableClass(42)))
 
     // If the dictionary is empty, we shouldn't be computing the hash value of
     // the provided key.
     expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
   }
 }
 
@@ -1398,9 +1398,9 @@
     var lastKey: MinimalHashableValue = d2.first!.key
     for i in d2.indices { lastKey = d2[i].key }
 
-    // index(where:) - linear search
+    // firstIndex(where:) - linear search
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    let j = d2.index(where: { (k, _) in k == lastKey })!
+    let j = d2.firstIndex(where: { (k, _) in k == lastKey })!
     expectGE(MinimalHashableValue.timesEqualEqualWasCalled, 8)
 
     // index(forKey:) - O(1) bucket + linear search
@@ -1408,9 +1408,9 @@
     let k = d2.index(forKey: lastKey)!
     expectLE(MinimalHashableValue.timesEqualEqualWasCalled, 4)
     
-    // keys.index(of:) - O(1) bucket + linear search
+    // keys.firstIndex(of:) - O(1) bucket + linear search
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    let l = d2.keys.index(of: lastKey)!
+    let l = d2.keys.firstIndex(of: lastKey)!
 #if swift(>=4.0)
     expectLE(MinimalHashableValue.timesEqualEqualWasCalled, 4)
 #endif
@@ -1713,13 +1713,13 @@
       uniqueKeysWithValues: d1.lazy.map { (MinimalHashableValue($0), $1) })
     expectEqual(d3.count, 3)
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    MinimalHashableValue.timesHashValueWasCalled = 0
+    MinimalHashableValue.timesHashIntoWasCalled = 0
 
     // Calling mapValues shouldn't ever recalculate any hashes.
     let d4 = d3.mapValues(String.init)
     expectEqual(d4.count, d3.count)
     expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
   }
 }
 
@@ -4464,11 +4464,11 @@
     expectOptionalEqual(4, d3["four"])
     expectOptionalEqual(5, d3["five"])
 
-    expectEqual(3, d.values[d.keys.index(of: "three")!])
-    expectEqual(4, d.values[d.keys.index(of: "four")!])
+    expectEqual(3, d.values[d.keys.firstIndex(of: "three")!])
+    expectEqual(4, d.values[d.keys.firstIndex(of: "four")!])
 
-    expectEqual(3, d3.values[d3.keys.index(of: "three")!])
-    expectEqual(4, d3.values[d3.keys.index(of: "four")!])
+    expectEqual(3, d3.values[d3.keys.firstIndex(of: "three")!])
+    expectEqual(4, d3.values[d3.keys.firstIndex(of: "four")!])
   }
 }
 
diff --git a/validation-test/stdlib/ExistentialCollection.swift.gyb b/validation-test/stdlib/ExistentialCollection.swift.gyb
index 4e98beb..9bee9b1 100644
--- a/validation-test/stdlib/ExistentialCollection.swift.gyb
+++ b/validation-test/stdlib/ExistentialCollection.swift.gyb
@@ -358,7 +358,7 @@
   let a1 = ContiguousArray(fc0)
   expectEqual(a0, a1)
   for e in a0 {
-    let i = fc0.index(of: e)
+    let i = fc0.firstIndex(of: e)
     expectNotNil(i)
     expectEqual(e, fc0[i!])
   }
@@ -386,7 +386,7 @@
   let a1 = ContiguousArray(bc0.lazy.reversed())
   expectEqual(a0, a1)
   for e in a0 {
-    let i = bc0.index(of: e)
+    let i = bc0.firstIndex(of: e)
     expectNotNil(i)
     expectEqual(e, bc0[i!])
   }
@@ -421,7 +421,7 @@
   let a1 = ContiguousArray(rc0.lazy.reversed())
   expectEqual(a0, a1)
   for e in a0 {
-    let i = rc0.index(of: e)
+    let i = rc0.firstIndex(of: e)
     expectNotNil(i)
     expectEqual(e, rc0[i!])
   }
diff --git a/validation-test/stdlib/ObjectiveC.swift b/validation-test/stdlib/ObjectiveC.swift
index 3e9a038..7dd5b98 100644
--- a/validation-test/stdlib/ObjectiveC.swift
+++ b/validation-test/stdlib/ObjectiveC.swift
@@ -10,6 +10,9 @@
 var ObjectiveCTests = TestSuite("ObjectiveC")
 
 class NSObjectWithCustomHashable : NSObject {
+  var _value: Int
+  var _hashValue: Int
+
   init(value: Int, hashValue: Int) {
     self._value = value
     self._hashValue = hashValue
@@ -20,24 +23,22 @@
     return self._value == other_._value
   }
 
-  override var hashValue: Int {
+  override var hash: Int {
     return _hashValue
   }
-
-  var _value: Int
-  var _hashValue: Int
 }
 
 ObjectiveCTests.test("NSObject/Hashable") {
-  let instances: [(order: Int, object: NSObject)] = [
-    (10, NSObjectWithCustomHashable(value: 10, hashValue: 100)),
-    (10, NSObjectWithCustomHashable(value: 10, hashValue: 100)),
-    (20, NSObjectWithCustomHashable(value: 20, hashValue: 100)),
-    (30, NSObjectWithCustomHashable(value: 30, hashValue: 300)),
+  let instances: [(order: Int, hashOrder: Int, object: NSObject)] = [
+    (10, 1, NSObjectWithCustomHashable(value: 10, hashValue: 100)),
+    (10, 1, NSObjectWithCustomHashable(value: 10, hashValue: 100)),
+    (20, 1, NSObjectWithCustomHashable(value: 20, hashValue: 100)),
+    (30, 2, NSObjectWithCustomHashable(value: 30, hashValue: 300)),
   ]
   checkHashable(
     instances.map { $0.object },
-    equalityOracle: { instances[$0].order == instances[$1].order })
+    equalityOracle: { instances[$0].order == instances[$1].order },
+    hashEqualityOracle: { instances[$0].hashOrder == instances[$1].hashOrder })
 }
 
 runAllTests()
diff --git a/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb b/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
index 89bb34c..9f9421a 100644
--- a/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
+++ b/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
@@ -100,6 +100,13 @@
 import Swift
 import SwiftShims
 
+// This prototype is only partially implemented, and it relies on specific hash
+// values. To keep it working, define an alternative hashing interface emulating
+// pre-SE-0206 Hashable.
+protocol LegacyHashable: Equatable {
+  var legacyHashValue: Int { get }
+}
+
 //
 // Standard library extras
 //
@@ -252,7 +259,7 @@
   var keyCount: Int
 }
 
-struct _PVSparseVectorNodePointer<Key : Hashable, Value>
+struct _PVSparseVectorNodePointer<Key : LegacyHashable, Value>
   : CustomReflectable {
   typealias _Self = _PVSparseVectorNodePointer
 
@@ -917,7 +924,7 @@
   }
 }
 
-struct _PVArrayNodePointer<Key : Hashable, Value>
+struct _PVArrayNodePointer<Key : LegacyHashable, Value>
   : CustomReflectable {
 
   typealias _Self = _PVArrayNodePointer
@@ -1158,7 +1165,7 @@
   var keyCount: Int
 }
 
-struct _PVCollisionNodePointer<Key : Hashable, Value>
+struct _PVCollisionNodePointer<Key : LegacyHashable, Value>
   : CustomReflectable {
 
   typealias _Self = _PVCollisionNodePointer
@@ -1461,7 +1468,7 @@
   }
 }
 
-struct _PVAnyNodePointer<Key : Hashable, Value>
+struct _PVAnyNodePointer<Key : LegacyHashable, Value>
   : CustomReflectable, Equatable {
 
   let taggedPointer: UnsafeMutableRawPointer
@@ -1654,7 +1661,8 @@
   return lhs.taggedPointer == rhs.taggedPointer
 }
 
-final internal class _NativePVDictionaryStorageRef<Key : Hashable, Value> {
+final internal
+class _NativePVDictionaryStorageRef<Key : LegacyHashable, Value> {
 
   var _rootNode: _PVAnyNodePointer<Key, Value>?
   var _count: Int
@@ -1675,7 +1683,7 @@
   }
 }
 
-struct _NativePVDictionaryStorage<Key : Hashable, Value> {
+struct _NativePVDictionaryStorage<Key : LegacyHashable, Value> {
   var _storageRef: _NativePVDictionaryStorageRef<Key, Value>
 
   var _rootNode: _PVAnyNodePointer<Key, Value>? {
@@ -1715,13 +1723,13 @@
 
   func assertingGet(key: Key) -> Value {
     let valuePointer = _rootNode!.unsafeMaybeGet(
-      key: key, hashValue: key.hashValue, depth: 0)
+      key: key, hashValue: key.legacyHashValue, depth: 0)
     return valuePointer!.pointee
   }
 
   func maybeGet(key: Key) -> Value? {
     let valuePointer = _rootNode?.unsafeMaybeGet(
-      key: key, hashValue: key.hashValue, depth: 0)
+      key: key, hashValue: key.legacyHashValue, depth: 0)
     return valuePointer.map { $0.pointee }
   }
 
@@ -1748,7 +1756,7 @@
   }
 
   mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
-    let hashValue = key.hashValue
+    let hashValue = key.legacyHashValue
     guard let oldRootNode = _rootNode else {
       let layout = _PVSparseVectorNodeLayoutParameters(
         childNodeCount: 0,
@@ -1787,7 +1795,7 @@
     guard let oldRootNode = _rootNode else {
       return nil
     }
-    let hashValue = key.hashValue
+    let hashValue = key.legacyHashValue
     let isUnique = isKnownUniquelyReferenced(&_storageRef)
     let (oldValue, newRootNode) = oldRootNode.removeValue(
       forKey: key,
@@ -1858,6 +1866,12 @@
   expectEqualSequence([ 0, 4, 5, 7, 31 ], Array(bm.setBitIndices))
 }
 
+extension MinimalHashableValue: LegacyHashable {
+  var legacyHashValue: Int {
+    return self.value % 10000
+  }
+}
+
 var PersistentVectorTests = TestSuite("PersistentVector")
 
 PersistentVectorTests.test("sizeof") {
@@ -1993,10 +2007,6 @@
     print("---------------------------------------")
   }
 
-  MinimalHashableValue.hashValueImpl.value = {
-    return $0 % 10000
-  }
-
   typealias MyDictionary = _NativePVDictionaryStorage<
     MinimalHashableValue, OpaqueValue<Int>
   >
diff --git a/validation-test/stdlib/SequenceType.swift.gyb b/validation-test/stdlib/SequenceType.swift.gyb
index 9f8f19e..5af4e46 100644
--- a/validation-test/stdlib/SequenceType.swift.gyb
+++ b/validation-test/stdlib/SequenceType.swift.gyb
@@ -573,7 +573,7 @@
     let s = Set<MinimalHashableValue>(
       test.sequence.map { MinimalHashableValue($0.value) })
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    MinimalHashableValue.timesHashValueWasCalled = 0
+    MinimalHashableValue.timesHashIntoWasCalled = 0
     expectEqual(
       test.expected != nil,
       call${dispatch}Contains(s, MinimalHashableValue(test.element.value)),
@@ -583,11 +583,11 @@
         0, MinimalHashableValue.timesEqualEqualWasCalled,
         stackTrace: SourceLocStack().with(test.loc))
       expectEqual(
-        0, MinimalHashableValue.timesHashValueWasCalled,
+        0, MinimalHashableValue.timesHashIntoWasCalled,
         stackTrace: SourceLocStack().with(test.loc))
     } else {
       expectNotEqual(
-        0, MinimalHashableValue.timesHashValueWasCalled,
+        0, MinimalHashableValue.timesHashIntoWasCalled,
         stackTrace: SourceLocStack().with(test.loc))
     }
     if test.expected != nil {
diff --git a/validation-test/stdlib/Set.swift b/validation-test/stdlib/Set.swift
index 93c1a56..1d3fa36 100644
--- a/validation-test/stdlib/Set.swift
+++ b/validation-test/stdlib/Set.swift
@@ -442,13 +442,13 @@
   do {
     var s2: Set<MinimalHashableValue> = []
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    MinimalHashableValue.timesHashValueWasCalled = 0
+    MinimalHashableValue.timesHashIntoWasCalled = 0
     expectFalse(s2.contains(MinimalHashableValue(42)))
 
     // If the set is empty, we shouldn't be computing the hash value of the
     // provided key.
     expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
   }
 }
 
@@ -488,13 +488,13 @@
   do {
     var s2: Set<MinimalHashableClass> = []
     MinimalHashableClass.timesEqualEqualWasCalled = 0
-    MinimalHashableClass.timesHashValueWasCalled = 0
+    MinimalHashableClass.timesHashIntoWasCalled = 0
     expectFalse(s2.contains(MinimalHashableClass(42)))
 
     // If the set is empty, we shouldn't be computing the hash value of the
     // provided key.
     expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
   }
 }
 
@@ -599,10 +599,10 @@
 
   // Find an existing key.
   do {
-    var foundIndex1 = s.index(of: 1010)!
+    var foundIndex1 = s.firstIndex(of: 1010)!
     expectEqual(identity1, s._rawIdentifier())
 
-    var foundIndex2 = s.index(of: 1010)!
+    var foundIndex2 = s.firstIndex(of: 1010)!
     expectEqual(foundIndex1, foundIndex2)
 
     expectEqual(1010, s[foundIndex1])
@@ -611,7 +611,7 @@
 
   // Try to find a key that is not present.
   do {
-    var foundIndex1 = s.index(of: 1111)
+    var foundIndex1 = s.firstIndex(of: 1111)
     expectNil(foundIndex1)
     expectEqual(identity1, s._rawIdentifier())
   }
@@ -619,13 +619,13 @@
   do {
     var s2: Set<MinimalHashableValue> = []
     MinimalHashableValue.timesEqualEqualWasCalled = 0
-    MinimalHashableValue.timesHashValueWasCalled = 0
-    expectNil(s2.index(of: MinimalHashableValue(42)))
+    MinimalHashableValue.timesHashIntoWasCalled = 0
+    expectNil(s2.firstIndex(of: MinimalHashableValue(42)))
 
     // If the set is empty, we shouldn't be computing the hash value of the
     // provided key.
     expectEqual(0, MinimalHashableValue.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableValue.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableValue.timesHashIntoWasCalled)
   }
 }
 
@@ -635,10 +635,10 @@
 
   // Find an existing key.
   do {
-    var foundIndex1 = s.index(of: TestKeyTy(1010))!
+    var foundIndex1 = s.firstIndex(of: TestKeyTy(1010))!
     expectEqual(identity1, s._rawIdentifier())
 
-    var foundIndex2 = s.index(of: TestKeyTy(1010))!
+    var foundIndex2 = s.firstIndex(of: TestKeyTy(1010))!
     expectEqual(foundIndex1, foundIndex2)
 
     expectEqual(TestKeyTy(1010), s[foundIndex1])
@@ -647,7 +647,7 @@
 
   // Try to find a key that is not present.
   do {
-    var foundIndex1 = s.index(of: TestKeyTy(1111))
+    var foundIndex1 = s.firstIndex(of: TestKeyTy(1111))
     expectNil(foundIndex1)
     expectEqual(identity1, s._rawIdentifier())
   }
@@ -655,13 +655,13 @@
   do {
     var s2: Set<MinimalHashableClass> = []
     MinimalHashableClass.timesEqualEqualWasCalled = 0
-    MinimalHashableClass.timesHashValueWasCalled = 0
-    expectNil(s2.index(of: MinimalHashableClass(42)))
+    MinimalHashableClass.timesHashIntoWasCalled = 0
+    expectNil(s2.firstIndex(of: MinimalHashableClass(42)))
 
     // If the set is empty, we shouldn't be computing the hash value of the
     // provided key.
     expectEqual(0, MinimalHashableClass.timesEqualEqualWasCalled)
-    expectEqual(0, MinimalHashableClass.timesHashValueWasCalled)
+    expectEqual(0, MinimalHashableClass.timesHashIntoWasCalled)
   }
 }
 
@@ -671,7 +671,7 @@
     var s = getCOWFastSet()
     var identity1 = s._rawIdentifier()
 
-    let foundIndex1 = s.index(of: 1010)!
+    let foundIndex1 = s.firstIndex(of: 1010)!
     expectEqual(identity1, s._rawIdentifier())
 
     expectEqual(1010, s[foundIndex1])
@@ -680,7 +680,7 @@
     expectEqual(1010, removed)
 
     expectEqual(identity1, s._rawIdentifier())
-    expectNil(s.index(of: 1010))
+    expectNil(s.firstIndex(of: 1010))
   }
 
   do {
@@ -691,7 +691,7 @@
     expectEqual(identity1, s1._rawIdentifier())
     expectEqual(identity1, s2._rawIdentifier())
 
-    var foundIndex1 = s2.index(of: 1010)!
+    var foundIndex1 = s2.firstIndex(of: 1010)!
     expectEqual(1010, s2[foundIndex1])
     expectEqual(identity1, s1._rawIdentifier())
     expectEqual(identity1, s2._rawIdentifier())
@@ -701,7 +701,7 @@
 
     expectEqual(identity1, s1._rawIdentifier())
     expectNotEqual(identity1, s2._rawIdentifier())
-    expectNil(s2.index(of: 1010))
+    expectNil(s2.firstIndex(of: 1010))
   }
 }
 
@@ -711,7 +711,7 @@
     var s = getCOWSlowSet()
     var identity1 = s._rawIdentifier()
 
-    let foundIndex1 = s.index(of: TestKeyTy(1010))!
+    let foundIndex1 = s.firstIndex(of: TestKeyTy(1010))!
     expectEqual(identity1, s._rawIdentifier())
 
     expectEqual(TestKeyTy(1010), s[foundIndex1])
@@ -720,7 +720,7 @@
     expectEqual(TestKeyTy(1010), removed)
 
     expectEqual(identity1, s._rawIdentifier())
-    expectNil(s.index(of: TestKeyTy(1010)))
+    expectNil(s.firstIndex(of: TestKeyTy(1010)))
   }
 
   do {
@@ -731,7 +731,7 @@
     expectEqual(identity1, s1._rawIdentifier())
     expectEqual(identity1, s2._rawIdentifier())
 
-    var foundIndex1 = s2.index(of: TestKeyTy(1010))!
+    var foundIndex1 = s2.firstIndex(of: TestKeyTy(1010))!
     expectEqual(TestKeyTy(1010), s2[foundIndex1])
     expectEqual(identity1, s1._rawIdentifier())
     expectEqual(identity1, s2._rawIdentifier())
@@ -741,7 +741,7 @@
 
     expectEqual(identity1, s1._rawIdentifier())
     expectNotEqual(identity1, s2._rawIdentifier())
-    expectNil(s2.index(of: TestKeyTy(1010)))
+    expectNil(s2.firstIndex(of: TestKeyTy(1010)))
   }
 }
 
@@ -1354,17 +1354,17 @@
   expectTrue(isCocoaSet(s))
 
   // Find an existing key.
-  var member = s[s.index(of: TestObjCKeyTy(1010))!]
+  var member = s[s.firstIndex(of: TestObjCKeyTy(1010))!]
   expectEqual(TestObjCKeyTy(1010), member)
 
-  member = s[s.index(of: TestObjCKeyTy(2020))!]
+  member = s[s.firstIndex(of: TestObjCKeyTy(2020))!]
   expectEqual(TestObjCKeyTy(2020), member)
 
-  member = s[s.index(of: TestObjCKeyTy(3030))!]
+  member = s[s.firstIndex(of: TestObjCKeyTy(3030))!]
   expectEqual(TestObjCKeyTy(3030), member)
 
   // Try to find a key that does not exist.
-  expectNil(s.index(of: TestObjCKeyTy(4040)))
+  expectNil(s.firstIndex(of: TestObjCKeyTy(4040)))
   expectEqual(identity1, s._rawIdentifier())
 }
 
@@ -1373,17 +1373,17 @@
   var identity1 = s._rawIdentifier()
 
   do {
-    var member = s[s.index(of: TestBridgedKeyTy(1010))!]
+    var member = s[s.firstIndex(of: TestBridgedKeyTy(1010))!]
     expectEqual(TestBridgedKeyTy(1010), member)
 
-    member = s[s.index(of: TestBridgedKeyTy(2020))!]
+    member = s[s.firstIndex(of: TestBridgedKeyTy(2020))!]
     expectEqual(TestBridgedKeyTy(2020), member)
 
-    member = s[s.index(of: TestBridgedKeyTy(3030))!]
+    member = s[s.firstIndex(of: TestBridgedKeyTy(3030))!]
     expectEqual(TestBridgedKeyTy(3030), member)
   }
 
-  expectNil(s.index(of: TestBridgedKeyTy(4040)))
+  expectNil(s.firstIndex(of: TestBridgedKeyTy(4040)))
   expectEqual(identity1, s._rawIdentifier())
 }
 
@@ -1649,7 +1649,7 @@
   let identity1 = s._rawIdentifier()
   expectTrue(isCocoaSet(s))
 
-  let foundIndex1 = s.index(of: TestObjCKeyTy(1010))!
+  let foundIndex1 = s.firstIndex(of: TestObjCKeyTy(1010))!
   expectEqual(TestObjCKeyTy(1010), s[foundIndex1])
   expectEqual(identity1, s._rawIdentifier())
 
@@ -1658,7 +1658,7 @@
   expectTrue(isNativeSet(s))
   expectEqual(2, s.count)
   expectEqual(TestObjCKeyTy(1010), removedElement)
-  expectNil(s.index(of: TestObjCKeyTy(1010)))
+  expectNil(s.firstIndex(of: TestObjCKeyTy(1010)))
 }
 
 SetTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveAt")
@@ -1667,7 +1667,7 @@
   let identity1 = s._rawIdentifier()
   expectTrue(isNativeSet(s))
 
-  let foundIndex1 = s.index(of: TestBridgedKeyTy(1010))!
+  let foundIndex1 = s.firstIndex(of: TestBridgedKeyTy(1010))!
   expectEqual(1010, s[foundIndex1].value)
   expectEqual(identity1, s._rawIdentifier())
 
@@ -1676,7 +1676,7 @@
   expectTrue(isNativeSet(s))
   expectEqual(1010, removedElement.value)
   expectEqual(2, s.count)
-  expectNil(s.index(of: TestBridgedKeyTy(1010)))
+  expectNil(s.firstIndex(of: TestBridgedKeyTy(1010)))
 }
 
 SetTestSuite.test("BridgedFromObjC.Verbatim.Remove") {
@@ -3171,7 +3171,7 @@
 SetTestSuite.test("memberAtIndex") {
   let s1 = Set([1010, 2020, 3030])
 
-  let foundIndex = s1.index(of: 1010)!
+  let foundIndex = s1.firstIndex(of: 1010)!
   expectEqual(1010, s1[foundIndex])
 }
 
@@ -3345,12 +3345,12 @@
   expectFalse(Set<Int>()._customContainsEquatableElement(1010)!)
 }
 
-SetTestSuite.test("index(of:)") {
+SetTestSuite.test("firstIndex(of:)") {
   let s1 = Set([1010, 2020, 3030, 4040, 5050, 6060])
-  let foundIndex1 = s1.index(of: 1010)!
+  let foundIndex1 = s1.firstIndex(of: 1010)!
   expectEqual(1010, s1[foundIndex1])
 
-  expectNil(s1.index(of: 999))
+  expectNil(s1.firstIndex(of: 999))
 }
 
 SetTestSuite.test("popFirst") {
@@ -3381,10 +3381,10 @@
   // Test removing from the startIndex, the middle, and the end of a set.
   for i in 1...3 {
     var s = Set<Int>([1010, 2020, 3030])
-    let removed = s.remove(at: s.index(of: i*1010)!)
+    let removed = s.remove(at: s.firstIndex(of: i*1010)!)
     expectEqual(i*1010, removed)
     expectEqual(2, s.count)
-    expectNil(s.index(of: i*1010))
+    expectNil(s.firstIndex(of: i*1010))
     let origKeys: [Int] = [1010, 2020, 3030]
     expectEqual(origKeys.filter { $0 != (i*1010) }, [Int](s).sorted())
   }
diff --git a/validation-test/stdlib/SetAnyHashableExtensions.swift b/validation-test/stdlib/SetAnyHashableExtensions.swift
index 3b53df3..3ab8cea 100644
--- a/validation-test/stdlib/SetAnyHashableExtensions.swift
+++ b/validation-test/stdlib/SetAnyHashableExtensions.swift
@@ -43,13 +43,13 @@
   let s: Set<AnyHashable> = [
     AnyHashable(1010), AnyHashable(2020), AnyHashable(3030.0)
   ]
-  expectEqual(AnyHashable(1010), s[s.index(of: 1010)!])
-  expectEqual(AnyHashable(2020), s[s.index(of: 2020)!])
-  expectEqual(AnyHashable(3030.0), s[s.index(of: 3030.0)!])
+  expectEqual(AnyHashable(1010), s[s.firstIndex(of: 1010)!])
+  expectEqual(AnyHashable(2020), s[s.firstIndex(of: 2020)!])
+  expectEqual(AnyHashable(3030.0), s[s.firstIndex(of: 3030.0)!])
 
-  expectNil(s.index(of: 1010.0))
-  expectNil(s.index(of: 2020.0))
-  expectNil(s.index(of: 3030))
+  expectNil(s.firstIndex(of: 1010.0))
+  expectNil(s.firstIndex(of: 2020.0))
+  expectNil(s.firstIndex(of: 3030))
 }
 
 SetTests.test("insert<Hashable>(_:)") {