Merge pull request #12036 from CodaFi/rank-existentialist-nonsense

[NFC] Remove Existential Ranking Hack
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ec89e5f..a45727a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,8 @@
 Swift 4.0
 ---------
 
+### 2017-09-19 (Xcode 9.0)
+
 * [SE-0165][] and [SE-0154][]
 
   The standard library's `Dictionary` and `Set` types have some new features. You can now create a new dictionary from a sequence of keys and values, and merge keys and values into an existing dictionary.
@@ -6710,3 +6712,9 @@
 [SE-0177]: <https://github.com/apple/swift-evolution/blob/master/proposals/0177-add-clamped-to-method.md>
 [SE-0178]: <https://github.com/apple/swift-evolution/blob/master/proposals/0178-character-unicode-view.md>
 [SE-0179]: <https://github.com/apple/swift-evolution/blob/master/proposals/0179-swift-run-command.md>
+[SE-0180]: <https://github.com/apple/swift-evolution/blob/master/proposals/0180-string-index-overhaul.md>
+[SE-0181]: <https://github.com/apple/swift-evolution/blob/master/proposals/0181-package-manager-cpp-language-version.md>
+[SE-0182]: <https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md>
+[SE-0183]: <https://github.com/apple/swift-evolution/blob/master/proposals/0183-substring-affordances.md>
+[SE-0184]: <https://github.com/apple/swift-evolution/blob/master/proposals/0184-unsafe-pointers-add-missing.md>
+[SE-0185]: <https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md>
diff --git a/README.md b/README.md
index f773f21..dbbfe3b 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@
 
 #### macOS
 
-To build for macOS, you need [Xcode 9.0 beta 6](https://developer.apple.com/xcode/downloads/).
+To build for macOS, you need [Xcode 9.0](https://developer.apple.com/xcode/downloads/).
 The required version of Xcode changes frequently, and is often a beta release.
 Check this document or the host information on <https://ci.swift.org> for the
 current required version.
diff --git a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
index 969994d..bf7f6bc 100644
--- a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
+++ b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
@@ -1,7 +1,6 @@
 
 include(CMakeParseArguments)
 
-
 # Run a shell command and assign output to a variable or fail with an error.
 # Example usage:
 #   runcmd(COMMAND "xcode-select" "-p"
@@ -20,6 +19,57 @@
   set(${RUNCMD_VARIABLE} ${${RUNCMD_VARIABLE}} PARENT_SCOPE)
 endfunction(runcmd)
 
+function (add_swift_benchmark_library objfile_out sibfile_out)
+  cmake_parse_arguments(BENCHLIB "" "MODULE_PATH;SOURCE_DIR;OBJECT_DIR" "SOURCES;LIBRARY_FLAGS" ${ARGN})
+
+  precondition(BENCHLIB_MODULE_PATH)
+  precondition(BENCHLIB_SOURCE_DIR)
+  precondition(BENCHLIB_OBJECT_DIR)
+  precondition(BENCHLIB_SOURCES)
+
+  set(module_name_path "${BENCHLIB_MODULE_PATH}")
+  get_filename_component(module_name "${module_name_path}" NAME)
+  set(srcdir "${BENCHLIB_SOURCE_DIR}")
+  set(objdir "${BENCHLIB_OBJECT_DIR}")
+  set(sources "${BENCHLIB_SOURCES}")
+
+  set(objfile "${objdir}/${module_name}.o")
+  set(swiftmodule "${objdir}/${module_name}.swiftmodule")
+
+  precondition(objfile_out)
+  add_custom_command(
+    OUTPUT "${objfile}"
+    DEPENDS ${stdlib_dependencies} ${sources}
+    COMMAND "${SWIFT_EXEC}"
+      ${BENCHLIB_LIBRARY_FLAGS}
+      "-force-single-frontend-invocation"
+      "-parse-as-library"
+      "-module-name" "${module_name}"
+      "-emit-module" "-emit-module-path" "${swiftmodule}"
+      "-o" "${objfile}"
+      ${sources})
+  set(${objfile_out} "${objfile}" PARENT_SCOPE)
+
+  if(SWIFT_BENCHMARK_EMIT_SIB)
+    precondition(sibfile_out)
+    set(sibfile "${objdir}/${module_name}.sib")
+
+    add_custom_command(
+      OUTPUT "${sibfile}"
+      DEPENDS
+      ${stdlib_dependencies} ${sources}
+      COMMAND "${SWIFT_EXEC}"
+        ${BENCHLIB_LIBRARY_FLAGS}
+        "-force-single-frontend-invocation"
+        "-parse-as-library"
+        "-module-name" "${module_name}"
+        "-emit-sib"
+        "-o" "${sibfile}"
+        ${sources})
+    set(sibfile_out "${sibfile}" PARENT_SCOPE)
+  endif()
+endfunction()
+
 function (swift_benchmark_compile_archopts)
   cmake_parse_arguments(BENCH_COMPILE_ARCHOPTS "" "PLATFORM;ARCH;OPT" "" ${ARGN})
   set(sdk ${${BENCH_COMPILE_ARCHOPTS_PLATFORM}_sdk})
@@ -67,84 +117,43 @@
   set(bench_library_objects)
   set(bench_library_sibfiles)
   foreach(module_name_path ${BENCH_DRIVER_LIBRARY_MODULES})
-    get_filename_component(module_name "${module_name_path}" NAME)
+    set(sources "${srcdir}/${module_name_path}.swift")
 
+    get_filename_component(module_name "${module_name_path}" NAME)
     if("${module_name}" STREQUAL "DriverUtils")
-      set(extra_sources "${srcdir}/utils/ArgParse.swift")
+      list(APPEND sources "${srcdir}/utils/ArgParse.swift")
     endif()
 
-    set(objfile "${objdir}/${module_name}.o")
-    set(swiftmodule "${objdir}/${module_name}.swiftmodule")
-    list(APPEND bench_library_objects "${objfile}")
-    set(source "${srcdir}/${module_name_path}.swift")
-    add_custom_command(
-        OUTPUT "${objfile}"
-        DEPENDS ${stdlib_dependencies} "${source}" ${extra_sources}
-        COMMAND "${SWIFT_EXEC}"
-        ${common_options_driver}
-        ${BENCH_DRIVER_LIBRARY_FLAGS}
-        "-force-single-frontend-invocation"
-        "-parse-as-library"
-        "-module-name" "${module_name}"
-        "-emit-module" "-emit-module-path" "${swiftmodule}"
-        "-o" "${objfile}"
-        "${source}" ${extra_sources})
-    if(SWIFT_BENCHMARK_EMIT_SIB)
-      set(sibfile "${objdir}/${module_name}.sib")
-      list(APPEND bench_library_sibfiles "${sibfile}")
-      add_custom_command(
-          OUTPUT "${sibfile}"
-          DEPENDS
-            ${stdlib_dependencies} "${srcdir}/${module_name_path}.swift"
-            ${extra_sources}
-          COMMAND "${SWIFT_EXEC}"
-          ${common_options_driver}
-          ${BENCH_DRIVER_LIBRARY_FLAGS}
-          "-force-single-frontend-invocation"
-          "-parse-as-library"
-          "-module-name" "${module_name}"
-          "-emit-sib"
-          "-o" "${sibfile}"
-          "${source}" ${extra_sources})
+    set(objfile_out)
+    set(sibfile_out)
+    add_swift_benchmark_library(objfile_out sibfile_out
+      MODULE_PATH "${module_name_path}"
+      SOURCE_DIR "${srcdir}"
+      OBJECT_DIR "${objdir}"
+      SOURCES ${sources}
+      LIBRARY_FLAGS ${common_options_driver} ${BENCH_DRIVER_LIBRARY_FLAGS})
+    precondition(objfile_out)
+    list(APPEND bench_library_objects "${objfile_out}")
+    if (SWIFT_BENCHMARK_EMIT_SIB)
+      precondition(sibfile_out)
+      list(APPEND bench_library_sibfiles "${sibfile_out}")
     endif()
   endforeach()
 
   foreach(module_name_path ${BENCH_LIBRARY_MODULES})
-    get_filename_component(module_name "${module_name_path}" NAME)
+    set(sources "${srcdir}/${module_name_path}.swift")
 
-    set(objfile "${objdir}/${module_name}.o")
-    set(swiftmodule "${objdir}/${module_name}.swiftmodule")
-    set(source "${srcdir}/${module_name_path}.swift")
-    list(APPEND bench_library_objects "${objfile}")
-    add_custom_command(
-        OUTPUT "${objfile}"
-        DEPENDS
-          ${stdlib_dependencies} "${srcdir}/${module_name_path}.swift"
-          ${extra_sources}
-        COMMAND "${SWIFT_EXEC}"
-        ${common_options}
-        "-force-single-frontend-invocation"
-        "-parse-as-library"
-        "-module-name" "${module_name}"
-        "-emit-module" "-emit-module-path" "${swiftmodule}"
-        "-o" "${objfile}"
-        "${source}" ${extra_sources})
+    add_swift_benchmark_library(objfile_out sibfile_out
+      MODULE_PATH "${module_name_path}"
+      SOURCE_DIR "${srcdir}"
+      OBJECT_DIR "${objdir}"
+      SOURCES ${sources}
+      LIBRARY_FLAGS ${common_options})
+    precondition(objfile_out)
+    list(APPEND bench_library_objects "${objfile_out}")
     if (SWIFT_BENCHMARK_EMIT_SIB)
-      set(sibfile "${objdir}/${module_name}.sib")
-      list(APPEND bench_library_sibfiles "${sibfile}")
-      add_custom_command(
-          OUTPUT "${sibfile}"
-          DEPENDS
-            ${stdlib_dependencies} "${srcdir}/${module_name_path}.swift"
-            ${extra_sources}
-          COMMAND "${SWIFT_EXEC}"
-          ${common_options}
-          "-force-single-frontend-invocation"
-          "-parse-as-library"
-          "-module-name" "${module_name}"
-          "-emit-sib"
-          "-o" "${sibfile}"
-          "${source}" ${extra_sources})
+      precondition(sibfile_out)
+      list(APPEND bench_library_sibfiles "${sibfile_out}")
     endif()
   endforeach()
 
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 2857478..1727e84 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -1960,6 +1960,23 @@
   
   /// Does this binding declare something that requires storage?
   bool hasStorage() const;
+
+  /// Determines whether this binding either has an initializer expression, or is
+  /// default initialized, without performing any type checking on it.
+  ///
+  /// This is only valid to check for bindings which have storage.
+  bool isDefaultInitializable() const {
+    assert(hasStorage());
+
+    for (unsigned i = 0, e = getNumPatternEntries(); i < e; ++i)
+      if (!isDefaultInitializable(i))
+        return false;
+
+    return true;
+  }
+
+  /// Can the pattern at index i be default initialized?
+  bool isDefaultInitializable(unsigned i) const;
   
   /// When the pattern binding contains only a single variable with no
   /// destructuring, retrieve that variable.
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index b3ba662..94aba8c 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -270,12 +270,6 @@
 
   /// Gets the type being declared by this context.
   ///
-  /// - Generic types returns an unbound generic type.
-  /// - Non-type contexts returns a null type.
-  Type getDeclaredTypeOfContext() const;
-
-  /// Gets the type being declared by this context.
-  ///
   /// - Generic types return a bound generic type using archetypes.
   /// - Non-type contexts return a null type.
   Type getDeclaredTypeInContext() const;
diff --git a/include/swift/AST/LayoutConstraint.h b/include/swift/AST/LayoutConstraint.h
index b403cdd..ef0561c 100644
--- a/include/swift/AST/LayoutConstraint.h
+++ b/include/swift/AST/LayoutConstraint.h
@@ -150,11 +150,27 @@
     return SizeInBits;
   }
 
-  unsigned getAlignment() const {
-    assert(isKnownSizeTrivial());
+  unsigned getAlignmentInBits() const {
     return Alignment;
   }
 
+  unsigned getAlignmentInBytes() const {
+    assert(isKnownSizeTrivial());
+    if (Alignment)
+      return Alignment;
+
+    // There is no explicitly defined alignment. Try to come up with a
+    // reasonable one.
+
+    // If the size is a power of 2, use it also for the default alignment.
+    auto SizeInBytes = getTrivialSizeInBytes();
+    if (llvm::isPowerOf2_32(SizeInBytes))
+      return SizeInBytes * 8;
+
+    // Otherwise assume the alignment of 8 bytes.
+    return 8*8;
+  }
+
   operator bool() const {
     return isKnownLayout();
   }
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index 0191a17..69341f0 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -543,11 +543,10 @@
     return DC->isLocalContext();
   }
 
-  auto declaredType = DC->getDeclaredTypeOfContext();
-  if (!declaredType || declaredType->hasError())
+  auto *nominal = DC->getAsNominalTypeOrNominalTypeExtensionContext();
+  if (nominal == nullptr)
     return false;
 
-  auto *nominal = declaredType->getAnyNominal();
   if (nominal->getFormalAccess() <= AccessLevel::FilePrivate)
     return true;
   return isInPrivateOrLocalContext(nominal);
@@ -2043,18 +2042,18 @@
     appendOperatorParam("T");
     break;
   case LayoutConstraintKind::TrivialOfExactSize:
-    if (!layout->getAlignment())
+    if (!layout->getAlignmentInBits())
       appendOperatorParam("e", Index(layout->getTrivialSizeInBits()));
     else
       appendOperatorParam("E", Index(layout->getTrivialSizeInBits()),
-                     Index(layout->getAlignment()));
+                          Index(layout->getAlignmentInBits()));
     break;
   case LayoutConstraintKind::TrivialOfAtMostSize:
-    if (!layout->getAlignment())
+    if (!layout->getAlignmentInBits())
       appendOperatorParam("m", Index(layout->getTrivialSizeInBits()));
     else
       appendOperatorParam("M", Index(layout->getTrivialSizeInBits()),
-                     Index(layout->getAlignment()));
+                          Index(layout->getAlignmentInBits()));
     break;
   }
 }
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 2f8f808..fb6ca10 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -1449,7 +1449,7 @@
     bool settable = ASD->isSettable(nullptr);
     bool nonmutatingSetter = false;
     if (settable && !ASD->isSetterMutating() && ASD->isInstanceMember() &&
-        !ASD->getDeclContext()->getDeclaredTypeInContext()
+        !ASD->getDeclContext()->getDeclaredInterfaceType()
             ->hasReferenceSemantics())
       nonmutatingSetter = true;
 
@@ -2146,10 +2146,10 @@
 }
 
 static bool isStructOrClassContext(DeclContext *dc) {
-  if (auto ctx = dc->getDeclaredTypeInContext())
-    return ctx->getClassOrBoundGenericClass() ||
-           ctx->getStructOrBoundGenericStruct();
-  return false;
+  auto *nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
+  if (nominal == nullptr)
+    return false;
+  return isa<ClassDecl>(nominal) || isa<StructDecl>(nominal);
 }
 
 static void printParameterFlags(ASTPrinter &printer, PrintOptions options,
@@ -3921,7 +3921,7 @@
     Printer << "(";
     Printer << SizeInBits;
     if (Alignment)
-      Printer << ", " << Alignment <<")";
+      Printer << ", " << Alignment;
     Printer << ")";
     break;
   }
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index 384248e..e29a206 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -671,7 +671,7 @@
                                   SourceLoc NameLoc, Identifier Name,
                                   SourceLoc RParenLoc) {
   void *mem = Ctx.Allocate(totalSizeToAlloc<SourceLoc>(3), alignof(ObjCAttr));
-  return new (mem) ObjCAttr(AtLoc, SourceRange(ObjCLoc),
+  return new (mem) ObjCAttr(AtLoc, SourceRange(ObjCLoc, RParenLoc),
                             ObjCSelector(Ctx, 0, Name),
                             SourceRange(LParenLoc, RParenLoc),
                             NameLoc);
@@ -690,7 +690,7 @@
   assert(NameLocs.size() == Names.size());
   void *mem = Ctx.Allocate(totalSizeToAlloc<SourceLoc>(NameLocs.size() + 2),
                            alignof(ObjCAttr));
-  return new (mem) ObjCAttr(AtLoc, SourceRange(ObjCLoc),
+  return new (mem) ObjCAttr(AtLoc, SourceRange(ObjCLoc, RParenLoc),
                             ObjCSelector(Ctx, Names.size(), Names),
                             SourceRange(LParenLoc, RParenLoc),
                             NameLocs);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 36d68e9..7bd97a1 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -993,7 +993,7 @@
     auto *DC = singleVar->getDeclContext();
     if (singleVar->getAttrs().hasAttribute<LazyAttr>() &&
         DC->isTypeContext()) {
-      bool isInOut = !DC->getDeclaredTypeOfContext()->hasReferenceSemantics();
+      bool isInOut = !DC->getDeclaredInterfaceType()->hasReferenceSemantics();
       SelfParam = ParamDecl::createSelf(SourceLoc(), DC,
                                         singleVar->isStatic(),
                                         isInOut);
@@ -1132,6 +1132,94 @@
   return nullptr;
 }
 
+/// Check whether the given type representation will be
+/// default-initializable.
+static bool isDefaultInitializable(const TypeRepr *typeRepr) {
+  // Look through most attributes.
+  if (const auto attributed = dyn_cast<AttributedTypeRepr>(typeRepr)) {
+    // Weak ownership implies optionality.
+    if (attributed->getAttrs().getOwnership() == Ownership::Weak)
+      return true;
+
+    return isDefaultInitializable(attributed->getTypeRepr());
+  }
+
+  // Optional types are default-initializable.
+  if (isa<OptionalTypeRepr>(typeRepr) ||
+      isa<ImplicitlyUnwrappedOptionalTypeRepr>(typeRepr))
+    return true;
+
+  // Tuple types are default-initializable if all of their element
+  // types are.
+  if (const auto tuple = dyn_cast<TupleTypeRepr>(typeRepr)) {
+    // ... but not variadic ones.
+    if (tuple->hasEllipsis())
+      return false;
+
+    for (const auto elt : tuple->getElements()) {
+      if (!isDefaultInitializable(elt.Type))
+        return false;
+    }
+
+    return true;
+  }
+
+  // Not default initializable.
+  return false;
+}
+
+// @NSManaged properties never get default initialized, nor do debugger
+// variables and immutable properties.
+bool isNeverDefaultInitializable(const Pattern *p) {
+  bool result = false;
+
+  p->forEachVariable([&](const VarDecl *var) {
+    if (var->getAttrs().hasAttribute<NSManagedAttr>())
+      return;
+
+    if (var->isDebuggerVar() ||
+        var->isLet())
+      result = true;
+  });
+
+  return result;
+}
+
+bool PatternBindingDecl::isDefaultInitializable(unsigned i) const {
+  const auto entry = getPatternList()[i];
+
+  // If it has an initializer expression, this is trivially true.
+  if (entry.getInit())
+    return true;
+
+  if (isNeverDefaultInitializable(entry.getPattern()))
+    return false;
+
+  // If the pattern is typed as optional (or tuples thereof), it is
+  // default initializable.
+  if (const auto typedPattern = dyn_cast<TypedPattern>(entry.getPattern())) {
+    if (const auto typeRepr = typedPattern->getTypeLoc().getTypeRepr()) {
+      if (::isDefaultInitializable(typeRepr))
+        return true;
+    } else if (typedPattern->isImplicit()) {
+      // Lazy vars have implicit storage assigned to back them. Because the
+      // storage is implicit, the pattern is typed and has a TypeLoc, but not a
+      // TypeRepr.
+      //
+      // All lazy storage is implicitly default initializable, though, because
+      // lazy backing storage is optional.
+      if (const auto *varDecl = typedPattern->getSingleVar())
+        // Lazy storage is never user accessible.
+        if (!varDecl->isUserAccessible())
+          if (typedPattern->getTypeLoc().getType()->getAnyOptionalObjectType())
+            return true;
+    }
+  }
+
+  // Otherwise, we can't default initialize this binding.
+  return false;
+}
+
 SourceLoc TopLevelCodeDecl::getStartLoc() const {
   return Body->getStartLoc();
 }
@@ -1350,10 +1438,10 @@
   auto *dc = getDeclContext();
 
   if (dc->isTypeContext()) {
-    auto declaredType = dc->getDeclaredTypeOfContext();
-    if (declaredType->hasError())
+    auto *nominalDecl = dc->getAsNominalTypeOrNominalTypeExtensionContext();
+    if (nominalDecl == nullptr)
       return true;
-    return declaredType->getAnyNominal()->hasFixedLayout();
+    return nominalDecl->hasFixedLayout();
   }
 
   // Private and (unversioned) internal variables always have a
@@ -1731,12 +1819,8 @@
 
   // Dynamic lookup can only find class and protocol members, or extensions of
   // classes.
-  auto declaredType = getDeclContext()->getDeclaredTypeOfContext();
-  
-  if (!declaredType)
-    return false;
-  
-  auto nominalDC = declaredType->getAnyNominal();
+  auto nominalDC =
+    getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
   if (!nominalDC ||
       (!isa<ClassDecl>(nominalDC) && !isa<ProtocolDecl>(nominalDC)))
     return false;
@@ -2264,9 +2348,14 @@
   DeclContext *dc = decl->getDeclContext();
   if (dc->isTypeContext()) {
     switch (kind) {
-    case DeclTypeKind::DeclaredType:
-      Ty = dc->getDeclaredTypeOfContext();
+    case DeclTypeKind::DeclaredType: {
+      auto *nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
+      if (nominal)
+        Ty = nominal->getDeclaredType();
+      else
+        Ty = ErrorType::get(ctx);
       break;
+    }
     case DeclTypeKind::DeclaredTypeInContext:
       llvm_unreachable("Handled above");
     case DeclTypeKind::DeclaredInterfaceType:
@@ -2431,10 +2520,15 @@
 
 UnboundGenericType *TypeAliasDecl::getUnboundGenericType() const {
   assert(getGenericParams());
+
+  Type parentTy;
+  auto parentDC = getDeclContext();
+  if (auto nominal = parentDC->getAsNominalTypeOrNominalTypeExtensionContext())
+    parentTy = nominal->getDeclaredType();
+
   return UnboundGenericType::get(
       const_cast<TypeAliasDecl *>(this),
-      getDeclContext()->getDeclaredTypeOfContext(),
-      getASTContext());
+      parentTy, getASTContext());
 }
 
 Type AbstractTypeParamDecl::getSuperclass() const {
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index 45690b5..27f3d50 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -147,14 +147,6 @@
   llvm_unreachable("Unhandled DeclTypeKind in switch.");
 }
 
-Type DeclContext::getDeclaredTypeOfContext() const {
-  if (auto *ED = dyn_cast<ExtensionDecl>(this))
-    return computeExtensionType(ED, DeclTypeKind::DeclaredType);
-  if (auto *NTD = dyn_cast<NominalTypeDecl>(this))
-    return NTD->getDeclaredType();
-  return Type();
-}
-
 Type DeclContext::getDeclaredTypeInContext() const {
   if (auto *ED = dyn_cast<ExtensionDecl>(this))
     return computeExtensionType(ED, DeclTypeKind::DeclaredTypeInContext);
@@ -519,7 +511,7 @@
   for (const auto *dc = this; dc->isLocalContext(); dc = dc->getParent()) {
     // Default argument initializer contexts have their resilience expansion
     // set when they're type checked.
-    if (auto *DAI = dyn_cast<DefaultArgumentInitializer>(dc)) {
+    if (isa<DefaultArgumentInitializer>(dc)) {
       return cast<AbstractFunctionDecl>(dc->getParent())
           ->getDefaultArgumentResilienceExpansion();
     }
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index ed9d420..f0b85ea 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -4568,7 +4568,7 @@
   visitPotentialArchetypes([&](PotentialArchetype *archetype) {
     if (archetype != archetype->getRepresentative()) return;
 
-    if (auto equivClass = archetype->getEquivalenceClassIfPresent())
+    if (archetype->getEquivalenceClassIfPresent())
       checkSameTypeConstraints(genericParams, archetype);
   });
 
diff --git a/lib/AST/LayoutConstraint.cpp b/lib/AST/LayoutConstraint.cpp
index b18b2a0..7062e53 100644
--- a/lib/AST/LayoutConstraint.cpp
+++ b/lib/AST/LayoutConstraint.cpp
@@ -250,12 +250,13 @@
   // Check alignments
 
   // Quick exit if at_most_size_layout does not care about the alignment.
-  if (!RHS->getAlignment())
+  if (!RHS->getAlignmentInBits())
     return LHS;
 
   // Check if fixed_size_layout.alignment is a multiple of
   // at_most_size_layout.alignment.
-  if (LHS->getAlignment() && LHS->getAlignment() % RHS->getAlignment() == 0)
+  if (LHS->getAlignmentInBits() &&
+      LHS->getAlignmentInBits() % RHS->getAlignmentInBits() == 0)
     return LHS;
 
   return LayoutConstraint::getUnknownLayout();
diff --git a/lib/AST/LookupVisibleDecls.cpp b/lib/AST/LookupVisibleDecls.cpp
index 54ad443..cf9e7c3 100644
--- a/lib/AST/LookupVisibleDecls.cpp
+++ b/lib/AST/LookupVisibleDecls.cpp
@@ -722,13 +722,16 @@
   Type BaseTy;
   const DeclContext *DC;
   LazyResolver *TypeResolver;
+  bool IsTypeLookup = false;
 
   OverrideFilteringConsumer(Type BaseTy, const DeclContext *DC,
                             LazyResolver *resolver)
       : BaseTy(BaseTy), DC(DC), TypeResolver(resolver) {
     assert(!BaseTy->hasLValueType());
-    if (auto *MetaTy = BaseTy->getAs<AnyMetatypeType>())
+    if (auto *MetaTy = BaseTy->getAs<AnyMetatypeType>()) {
       BaseTy = MetaTy->getInstanceType();
+      IsTypeLookup = true;
+    }
     assert(DC && BaseTy);
   }
 
@@ -781,7 +784,7 @@
 
     // Don't pass UnboundGenericType here. If you see this assertion
     // being hit, fix the caller, don't remove it.
-    assert(!BaseTy->hasUnboundGenericType());
+    assert(IsTypeLookup || !BaseTy->hasUnboundGenericType());
 
     // If the base type is AnyObject, we might be doing a dynamic
     // lookup, so the base type won't match the type of the member's
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index 1979883..718e573 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -283,10 +283,10 @@
         continue;
 
       for (ValueDecl *vd : member.second) {
-        Type ty = vd->getDeclContext()->getDeclaredTypeOfContext();
-        if (auto nominal = ty->getAnyNominal())
-          if (nominal->getName() == accessPath.front().first)
-            consumer.foundDecl(vd, DeclVisibilityKind::DynamicLookup);
+        auto *nominal = vd->getDeclContext()
+           ->getAsNominalTypeOrNominalTypeExtensionContext();
+        if (nominal && nominal->getName() == accessPath.front().first)
+          consumer.foundDecl(vd, DeclVisibilityKind::DynamicLookup);
       }
     }
     return;
@@ -318,10 +318,10 @@
   
   if (!accessPath.empty()) {
     for (ValueDecl *vd : iter->second) {
-      Type ty = vd->getDeclContext()->getDeclaredTypeOfContext();
-      if (auto nominal = ty->getAnyNominal())
-        if (nominal->getName() == accessPath.front().first)
-          results.push_back(vd);
+      auto *nominal = vd->getDeclContext()
+         ->getAsNominalTypeOrNominalTypeExtensionContext();
+      if (nominal && nominal->getName() == accessPath.front().first)
+        results.push_back(vd);
     }
     return;
   }
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 6cb983d..903d770 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -4033,6 +4033,17 @@
 
   CanType self = getCanonicalType();
 
+  // Archetypes with a trivial layout constraint can never
+  // represent a class.
+  if (auto Archetype = dyn_cast<ArchetypeType>(self)) {
+    if (auto Layout = Archetype->getLayoutConstraint()) {
+      if (Layout->isTrivial())
+        return TypeTraitResult::IsNot;
+      if (Layout->isClass())
+        return TypeTraitResult::Is;
+    }
+  }
+
   // Dependent types might be bound to classes.
   if (isa<SubstitutableType>(self))
     return TypeTraitResult::CanBe;
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index e539e2b..b4dd301 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -3678,7 +3678,7 @@
                                       ImportedName importedName,
                                       ObjCSelector selector,
                                       bool forceClassMethod) {
-      assert(dc->getDeclaredTypeOfContext() && "Method in non-type context?");
+      assert(dc->isTypeContext() && "Method in non-type context?");
       assert(isa<ClangModuleUnit>(dc->getModuleScopeContext()) &&
              "Clang method in Swift context?");
 
@@ -5324,7 +5324,7 @@
   // instance of the type we're importing onto. Importing this as a method means
   // that the method should be treated as mutating in this situation.
   bool selfIsInOut = false;
-  if (selfIdx && !dc->getDeclaredTypeOfContext()->hasReferenceSemantics()) {
+  if (selfIdx && !dc->getDeclaredInterfaceType()->hasReferenceSemantics()) {
     auto selfParam = decl->getParamDecl(*selfIdx);
     auto selfParamTy = selfParam->getType();
     if ((selfParamTy->isPointerType() || selfParamTy->isReferenceType()) &&
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 974d49e..ee12bc8 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -1307,36 +1307,33 @@
     auto *DC = CurDeclContext->getInnermostTypeContext();
     if (!DC)
       return;
-    Type DT = DC->getDeclaredTypeOfContext();
-    if (DT.isNull() || DT->is<ErrorType>())
+    auto *CD = DC->getAsClassOrClassExtensionContext();
+    if (CD == nullptr)
       return;
-    Type ST = DT->getSuperclass();
+    Type ST = CD->getSuperclass();
     if (ST.isNull() || ST->is<ErrorType>())
       return;
-    if (ST->getNominalOrBoundGenericNominal()) {
-      CodeCompletionResultBuilder Builder(Sink,
-                                          CodeCompletionResult::ResultKind::Keyword,
-                                          SemanticContextKind::CurrentNominal,
-                                          {});
-      Builder.setKeywordKind(CodeCompletionKeywordKind::kw_super);
-      Builder.addTextChunk("super");
-      ST = ST->getReferenceStorageReferent();
-      assert(!ST->isVoid() && "Cannot get type name.");
-      Builder.addTypeAnnotation(ST.getString());
-    }
+
+    CodeCompletionResultBuilder Builder(Sink,
+                                        CodeCompletionResult::ResultKind::Keyword,
+                                        SemanticContextKind::CurrentNominal,
+                                        {});
+    Builder.setKeywordKind(CodeCompletionKeywordKind::kw_super);
+    Builder.addTextChunk("super");
+    Builder.addTypeAnnotation(ST.getString());
   }
 
   /// \brief Set to true when we have delivered code completion results
   /// to the \c Consumer.
   bool DeliveredResults = false;
 
-  bool typecheckContextImpl(DeclContext *DC) {
+  bool typecheckContext(DeclContext *DC) {
     // Nothing to type check in module context.
     if (DC->isModuleScopeContext())
       return true;
 
     // Type check the parent context.
-    if (!typecheckContextImpl(DC->getParent()))
+    if (!typecheckContext(DC->getParent()))
       return false;
 
     // Type-check this context.
@@ -1373,17 +1370,6 @@
     llvm_unreachable("Unhandled DeclContextKind in switch.");
   }
 
-  /// \returns true on success, false on failure.
-  bool typecheckContext() {
-    return typecheckContextImpl(CurDeclContext);
-  }
-
-  /// \returns true on success, false on failure.
-  bool typecheckParsedDecl() {
-    assert(ParsedDecl && "should have a parsed decl");
-    return typeCheckCompletionDecl(ParsedDecl);
-  }
-
   Optional<std::pair<Type, ConcreteDeclRef>> typeCheckParsedExpr() {
     assert(ParsedExpr && "should have an expression");
 
@@ -2540,7 +2526,7 @@
     }
 
     // If we won't be able to provide a result, bail out.
-    if (MemberType->is<ErrorType>() && addName.empty() && !needInit)
+    if (MemberType->hasError() && addName.empty() && !needInit)
       return;
 
     // Add the constructor, possibly including any default arguments.
@@ -5118,15 +5104,14 @@
   // Add keywords even if type checking fails completely.
   addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
 
-  if (!typecheckContext())
-    return;
+  if (auto *DC = dyn_cast_or_null<DeclContext>(ParsedDecl)) {
+    if (DC->isChildContextOf(CurDeclContext))
+      CurDeclContext = DC;
+  }
 
-  if (ParsedDecl && !typecheckParsedDecl())
+  if (!typecheckContext(CurDeclContext))
     return;
 
-  if (auto *DC = dyn_cast_or_null<DeclContext>(ParsedDecl))
-    CurDeclContext = DC;
-
   Optional<Type> ExprType;
   ConcreteDeclRef ReferencedDecl = nullptr;
   if (ParsedExpr) {
diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp
index 4804122..a257fbb 100644
--- a/lib/IRGen/GenArchetype.cpp
+++ b/lib/IRGen/GenArchetype.cpp
@@ -318,7 +318,9 @@
   // representation.
   if (layout && layout->isFixedSizeTrivial()) {
     Size size(layout->getTrivialSizeInBytes());
-    Alignment align(layout->getTrivialSizeInBytes());
+    auto layoutAlignment = layout->getAlignmentInBytes();
+    assert(layoutAlignment && "layout constraint alignment should not be 0");
+    Alignment align(layoutAlignment);
     auto spareBits =
       SpareBitVector::getConstant(size.getValueInBits(), false);
     // Get an integer type of the required size.
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 7b6da1c..c63fb59 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -130,7 +130,8 @@
     class_replaceMethod = IGM.getClassReplaceMethodFn();
     class_addProtocol = IGM.getClassAddProtocolFn();
 
-    CanType origTy = ext->getDeclaredTypeOfContext()->getCanonicalType();
+    CanType origTy = ext->getAsNominalTypeOrNominalTypeExtensionContext()
+        ->getDeclaredType()->getCanonicalType();
     classMetadata =
       tryEmitConstantHeapMetadataRef(IGM, origTy, /*allowUninit*/ true);
     assert(classMetadata &&
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 5fab631..174a627 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -4563,7 +4563,7 @@
                                           NominalTypeDecl *decl,
                                           bool &dependent) {
     CanType unboundType
-      = decl->getDeclaredTypeOfContext()->getCanonicalType();
+      = decl->getDeclaredType()->getCanonicalType();
     
     dependent = hasDependentValueWitnessTable(IGM, unboundType);    
     if (dependent)
@@ -4611,7 +4611,7 @@
                         
     void addDependentValueWitnessTablePattern() {
       emitDependentValueWitnessTablePattern(IGM, B,
-                        Target->getDeclaredTypeOfContext()->getCanonicalType());
+                        Target->getDeclaredType()->getCanonicalType());
     }
                         
     void emitInitializeMetadata(IRGenFunction &IGF,
@@ -4779,7 +4779,7 @@
   
   void addDependentValueWitnessTablePattern() {
     emitDependentValueWitnessTablePattern(IGM, B,
-                        Target->getDeclaredTypeOfContext()->getCanonicalType());
+                        Target->getDeclaredType()->getCanonicalType());
   }
   
   void addPayloadSize() {
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 2081613..53c5571 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -1025,10 +1025,7 @@
 }
 
 static NominalTypeDecl *getNominalParent(ValueDecl *D) {
-  Type Ty = D->getDeclContext()->getDeclaredTypeOfContext();
-  if (!Ty)
-    return nullptr;
-  return Ty->getAnyNominal();
+  return D->getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
 }
 
 bool IndexSwiftASTWalker::initFuncDeclIndexSymbol(FuncDecl *D,
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index 3be2ff5..f9774da 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -20,10 +20,7 @@
 using namespace swift::index;
 
 static NominalTypeDecl *getNominalParent(const ValueDecl *D) {
-  Type Ty = D->getDeclContext()->getDeclaredTypeOfContext();
-  if (!Ty)
-    return nullptr;
-  return Ty->getAnyNominal();
+  return D->getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
 }
 
 /// \returns true if \c D is a subclass of 'XCTestCase'.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e4f5385..42880bf 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -4846,8 +4846,18 @@
 
   diagnoseWhereClauseInGenericParamList(GenericParams);
 
+  // Create the decl for the func and add it to the parent scope.
+  auto *FD = FuncDecl::create(Context, StaticLoc, StaticSpelling,
+                              FuncLoc, FullName, NameLoc,
+                              /*Throws=*/throwsLoc.isValid(), throwsLoc,
+                              /*AccessorKeywordLoc=*/SourceLoc(),
+                              nullptr, BodyParams, FuncRetTy,
+                              CurDeclContext);
+
   // Parse a 'where' clause if present, adding it to our GenericParamList.
   if (Tok.is(tok::kw_where)) {
+    ContextChange CC(*this, FD);
+
     auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
     SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
     if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
@@ -4855,6 +4865,8 @@
       return whereStatus;
     }
   }
+
+  FD->setGenericParams(GenericParams);
   
   // Protocol method arguments may not have default values.
   if (Flags.contains(PD_InProtocol) && DefaultArgs.HasDefaultArgument) {
@@ -4870,18 +4882,9 @@
   // Enter the arguments for the function into a new function-body scope.  We
   // need this even if there is no function body to detect argument name
   // duplication.
-  FuncDecl *FD;
   {
     Scope S(this, ScopeKind::FunctionBody);
 
-    // Create the decl for the func and add it to the parent scope.
-    FD = FuncDecl::create(Context, StaticLoc, StaticSpelling,
-                          FuncLoc, FullName, NameLoc,
-                          /*Throws=*/throwsLoc.isValid(), throwsLoc,
-                          /*AccessorKeywordLoc=*/SourceLoc(),
-                          GenericParams, BodyParams, FuncRetTy,
-                          CurDeclContext);
-    
     diagnoseOperatorFixityAttributes(*this, Attributes, FD);
     
     // Add the attributes here so if we need them while parsing the body
@@ -5016,7 +5019,7 @@
   }
 
   EnumDecl *ED = new (Context) EnumDecl(EnumLoc, EnumName, EnumNameLoc,
-                                        { }, GenericParams, CurDeclContext);
+                                        { }, nullptr, CurDeclContext);
   setLocalDiscriminator(ED);
   ED->getAttrs() = Attributes;
 
@@ -5041,9 +5044,10 @@
       // Trigger delayed parsing, no need to continue.
       return whereStatus;
     }
-    ED->setGenericParams(GenericParams);
   }
 
+  ED->setGenericParams(GenericParams);
+
   SourceLoc LBLoc, RBLoc;
   if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_enum)) {
     LBLoc = PreviousLoc;
@@ -5277,7 +5281,7 @@
   StructDecl *SD = new (Context) StructDecl(StructLoc, StructName,
                                             StructNameLoc,
                                             { },
-                                            GenericParams,
+                                            nullptr,
                                             CurDeclContext);
   setLocalDiscriminator(SD);
   SD->getAttrs() = Attributes;
@@ -5303,9 +5307,10 @@
       // Trigger delayed parsing, no need to continue.
       return whereStatus;
     }
-    SD->setGenericParams(GenericParams);
   }
-  
+
+  SD->setGenericParams(GenericParams);
+
   SourceLoc LBLoc, RBLoc;
   if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_struct)) {
     LBLoc = PreviousLoc;
@@ -5363,7 +5368,7 @@
 
   // Create the class.
   ClassDecl *CD = new (Context) ClassDecl(ClassLoc, ClassName, ClassNameLoc,
-                                          { }, GenericParams, CurDeclContext);
+                                          { }, nullptr, CurDeclContext);
   setLocalDiscriminator(CD);
 
   // Attach attributes.
@@ -5390,9 +5395,10 @@
       // Trigger delayed parsing, no need to continue.
       return whereStatus;
     }
-    CD->setGenericParams(GenericParams);
   }
 
+  CD->setGenericParams(GenericParams);
+
   SourceLoc LBLoc, RBLoc;
   if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_class)) {
     LBLoc = PreviousLoc;
@@ -5563,8 +5569,20 @@
 
   diagnoseWhereClauseInGenericParamList(GenericParams);
 
+  // Build an AST for the subscript declaration.
+  DeclName name = DeclName(Context, DeclBaseName::createSubscript(),
+                           argumentNames);
+  auto *Subscript = new (Context) SubscriptDecl(name,
+                                                SubscriptLoc, Indices.get(),
+                                                ArrowLoc, ElementTy.get(),
+                                                CurDeclContext,
+                                                nullptr);
+  Subscript->getAttrs() = Attributes;
+
   // Parse a 'where' clause if present, adding it to our GenericParamList.
   if (Tok.is(tok::kw_where)) {
+    ContextChange CC(*this, Subscript);
+
     auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
     SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
     if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
@@ -5573,15 +5591,7 @@
     }
   }
 
-  // Build an AST for the subscript declaration.
-  DeclName name = DeclName(Context, DeclBaseName::createSubscript(),
-                           argumentNames);
-  auto *Subscript = new (Context) SubscriptDecl(name,
-                                                SubscriptLoc, Indices.get(),
-                                                ArrowLoc, ElementTy.get(),
-                                                CurDeclContext,
-                                                GenericParams);
-  Subscript->getAttrs() = Attributes;
+  Subscript->setGenericParams(GenericParams);
 
   // Pass the function signature to code completion.
   if (SignatureHasCodeCompletion)
@@ -5690,8 +5700,19 @@
 
   diagnoseWhereClauseInGenericParamList(GenericParams);
 
+  auto *SelfDecl = ParamDecl::createUnboundSelf(ConstructorLoc, CurDeclContext);
+  DeclName FullName(Context, Context.Id_init, namePieces);
+
+  auto *CD = new (Context) ConstructorDecl(FullName, ConstructorLoc,
+                                           Failability, FailabilityLoc,
+                                           throwsLoc.isValid(), throwsLoc,
+                                           SelfDecl, Params.get(), nullptr,
+                                           CurDeclContext);
+
   // Parse a 'where' clause if present, adding it to our GenericParamList.
   if (Tok.is(tok::kw_where)) {
+    ContextChange(*this, CD);
+
     auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
     SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
     if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
@@ -5699,18 +5720,10 @@
       return whereStatus;
     }
   }
-  
-  auto *SelfDecl = ParamDecl::createUnboundSelf(ConstructorLoc, CurDeclContext);
-  DeclName FullName(Context, Context.Id_init, namePieces);
+
+  CD->setGenericParams(GenericParams);
 
   Scope S2(this, ScopeKind::ConstructorBody);
-  auto *CD = new (Context) ConstructorDecl(FullName, ConstructorLoc,
-                                           Failability, FailabilityLoc,
-                                           throwsLoc.isValid(), throwsLoc,
-                                           SelfDecl, Params.get(),
-                                           GenericParams,
-                                           CurDeclContext);
-  
   CtorInitializerKind initKind = CtorInitializerKind::Designated;
   if (Attributes.hasAttribute<ConvenienceAttr>())
     initKind = CtorInitializerKind::Convenience;
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 7733a2c..f782af6 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -354,12 +354,11 @@
 }
 
 void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) {
-  CanType enumTy = element->getParentEnum()
-                      ->getDeclaredTypeInContext()
-                      ->getCanonicalType();
   CanType enumIfaceTy = element->getParentEnum()
                       ->getDeclaredInterfaceType()
                       ->getCanonicalType();
+  CanType enumTy = F.mapTypeIntoContext(enumIfaceTy)
+                      ->getCanonicalType();
   auto &enumTI = getTypeLowering(enumTy);
 
   RegularLocation Loc(element);
diff --git a/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp b/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
index 6030a07..bce9658 100644
--- a/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
+++ b/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
@@ -716,7 +716,7 @@
   // TODO: handle cases where a function got smaller.
   if ((SILStatsDumpAll &&
        (DeltaBlockCount != 0.0 || OldStat.BlockCount == 0)) ||
-      (abs(DeltaBlockCount) > FuncBlockCountDeltaThreshold &&
+      (std::abs(DeltaBlockCount) > FuncBlockCountDeltaThreshold &&
        OldStat.BlockCount > FuncBlockCountMinThreshold)) {
     stats_os() << nl.get();
     printCounterChange("function", "block", DeltaBlockCount, OldStat.BlockCount,
@@ -724,7 +724,7 @@
   }
 
   if ((SILStatsDumpAll && (DeltaInstCount != 0.0 || OldStat.InstCount == 0)) ||
-      (abs(DeltaInstCount) > FuncInstCountDeltaThreshold &&
+      (std::abs(DeltaInstCount) > FuncInstCountDeltaThreshold &&
        OldStat.InstCount > FuncInstCountMinThreshold)) {
     stats_os() << nl.get();
     printCounterChange("function", "inst", DeltaInstCount, OldStat.InstCount,
@@ -760,7 +760,7 @@
   if ((SILStatsDumpAll &&
        (DeltaBlockCount != 0.0 ||
         isFirstTimeData(OldStat.BlockCount, NewStat.BlockCount))) ||
-      (abs(DeltaBlockCount) > BlockCountDeltaThreshold)) {
+      (std::abs(DeltaBlockCount) > BlockCountDeltaThreshold)) {
     stats_os() << nl.get();
     printCounterChange("module", "block", DeltaBlockCount, OldStat.BlockCount,
                        NewStat.BlockCount, Ctx);
@@ -771,7 +771,7 @@
   if ((SILStatsDumpAll &&
        (DeltaInstCount != 0.0 ||
         isFirstTimeData(OldStat.InstCount, NewStat.InstCount))) ||
-      (abs(DeltaInstCount) > InstCountDeltaThreshold)) {
+      (std::abs(DeltaInstCount) > InstCountDeltaThreshold)) {
     stats_os() << nl.get();
     printCounterChange("module", "inst", DeltaInstCount, OldStat.InstCount,
                        NewStat.InstCount, Ctx);
@@ -782,7 +782,7 @@
   if ((SILStatsDumpAll &&
        (DeltaFunctionCount != 0.0 ||
         isFirstTimeData(OldStat.FunctionCount, NewStat.FunctionCount))) ||
-      (abs(DeltaFunctionCount) > FunctionCountDeltaThreshold)) {
+      (std::abs(DeltaFunctionCount) > FunctionCountDeltaThreshold)) {
     stats_os() << nl.get();
     printCounterChange("module", "functions", DeltaFunctionCount,
                        OldStat.FunctionCount, NewStat.FunctionCount, Ctx);
@@ -791,9 +791,9 @@
   // Print delta for the used memory only if it is above a threshold or we are
   // asked to dump all changes.
   if ((SILStatsDumpAll &&
-       (abs(DeltaUsedMemory) > UsedMemoryMinDeltaThreshold ||
+       (std::abs(DeltaUsedMemory) > UsedMemoryMinDeltaThreshold ||
         isFirstTimeData(OldStat.UsedMemory, NewStat.UsedMemory))) ||
-      (abs(DeltaUsedMemory) > UsedMemoryDeltaThreshold)) {
+      (std::abs(DeltaUsedMemory) > UsedMemoryDeltaThreshold)) {
     stats_os() << nl.get();
     printCounterChange("module", "memory", DeltaUsedMemory, OldStat.UsedMemory,
                        NewStat.UsedMemory, Ctx);
diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
index 595de0c..bb78605 100644
--- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
+++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
@@ -621,6 +621,37 @@
   return false;
 }
 
+/// Checks if a generic callee and caller have compatible layout constraints.
+static bool isCallerAndCalleeLayoutConstraintsCompatible(FullApplySite AI) {
+  SILFunction *Callee = AI.getReferencedFunction();
+  auto CalleeSig = Callee->getLoweredFunctionType()->getGenericSignature();
+  auto SubstParams = CalleeSig->getSubstitutableParams();
+  auto AISubs = AI.getSubstitutions();
+  for (auto idx : indices(SubstParams)) {
+    auto Param = SubstParams[idx];
+    // Map the parameter into context
+    auto ContextTy = Callee->mapTypeIntoContext(Param->getCanonicalType());
+    auto Archetype = ContextTy->getAs<ArchetypeType>();
+    if (!Archetype)
+      continue;
+    auto Layout = Archetype->getLayoutConstraint();
+    if (!Layout)
+      continue;
+    // The generic parameter has a layout constraint.
+    // Check that the substitution has the same constraint.
+    auto AIReplacement = AISubs[idx].getReplacement();
+    auto AIArchetype = AIReplacement->getAs<ArchetypeType>();
+    if (!AIArchetype)
+      return false;
+    auto AILayout = AIArchetype->getLayoutConstraint();
+    if (!AILayout)
+      return false;
+    if (AILayout != Layout)
+      return false;
+  }
+  return true;
+}
+
 // Returns the callee of an apply_inst if it is basically inlineable.
 SILFunction *swift::getEligibleFunction(FullApplySite AI,
                                         InlineSelection WhatToInline) {
@@ -725,6 +756,16 @@
       return nullptr;
   }
 
+  // We cannot inline function with layout constraints on its generic types
+  // if the corresponding substitution type does not have the same constraints.
+  // The reason for this restriction is that we'd need to be able to express
+  // in SIL something like casting a value of generic type T into a value of
+  // generic type T: _LayoutConstraint, which is impossible currently.
+  if (EnableSILInliningOfGenerics && AI.hasSubstitutions()) {
+    if (!isCallerAndCalleeLayoutConstraintsCompatible(AI))
+      return nullptr;
+  }
+
   // IRGen cannot handle partial_applies containing opened_existentials
   // in its substitutions list.
   if (calleeHasPartialApplyWithOpenedExistentials(AI)) {
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index fc9e7f0..c06fa51 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -710,7 +710,7 @@
       // better SILGen.
       if (isLValue &&
           (isNonMutatingMember(member) ||
-           member->getDeclContext()->getDeclaredTypeOfContext()
+           member->getDeclContext()->getDeclaredInterfaceType()
              ->hasReferenceSemantics())) {
         base = cs.coerceToRValue(base);
         isLValue = false;
@@ -2480,11 +2480,9 @@
           // Determine whether 'super' would have made sense as a base.
           bool hasSuper = false;
           if (auto func = cs.DC->getInnermostMethodContext()) {
-            if (auto nominalType
-                       = func->getDeclContext()->getDeclaredTypeOfContext()) {
-              if (auto classDecl = nominalType->getClassOrBoundGenericClass()) {
-                hasSuper = classDecl->hasSuperclass();
-              }
+            if (auto classDecl = func->getDeclContext()
+                    ->getAsClassOrClassExtensionContext()) {
+              hasSuper = classDecl->hasSuperclass();
             }
           }
 
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index eadc66f..bea32ae 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -2754,7 +2754,7 @@
           currentTypeContext->getSemanticDepth()) {
         diagnose(loc, diag::could_not_use_instance_member_on_type,
                  currentTypeContext->getDeclaredInterfaceType(), memberName,
-                 memberTypeContext->getDeclaredTypeOfContext(),
+                 memberTypeContext->getDeclaredInterfaceType(),
                  true)
           .highlight(baseRange).highlight(nameLoc.getSourceRange());
       } else {
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index a23020c..692dfde 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2040,11 +2040,13 @@
   //
   // FIXME: Remove this when lookup of initializers becomes restricted to our
   // immediate superclass.
-  Type superclassTyInCtor = superclassCtor->getDeclContext()->getDeclaredTypeOfContext();
+  auto *superclassCtorDecl =
+      superclassCtor->getDeclContext()
+          ->getAsNominalTypeOrNominalTypeExtensionContext();
   Type superclassTy = classDecl->getSuperclass();
   Type superclassTyInContext = classDecl->mapTypeIntoContext(superclassTy);
   NominalTypeDecl *superclassDecl = superclassTy->getAnyNominal();
-  if (superclassTyInCtor->getAnyNominal() != superclassDecl) {
+  if (superclassCtorDecl != superclassDecl) {
     return nullptr;
   }
 
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 0968467..478a588 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1225,7 +1225,7 @@
     // If self is a value type and the base type is an lvalue, wrap it in an
     // inout type.
     auto selfFlags = ParameterTypeFlags();
-    if (!outerDC->getDeclaredTypeOfContext()->hasReferenceSemantics() &&
+    if (!outerDC->getDeclaredInterfaceType()->hasReferenceSemantics() &&
         baseTy->is<LValueType>() &&
         !selfTy->hasError())
       selfFlags = selfFlags.withInOut(true);
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index a0b6b10..8b3d787 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -244,26 +244,19 @@
   if (!properties.empty() &&
       proto->isSpecificProtocol(KnownProtocolKind::Decodable)) {
     for (auto it = properties.begin(); it != properties.end(); ++it) {
+      // If the var is default initializable, then it need not have an explicit
+      // initial value.
       auto *varDecl = it->second;
-
-      // Optional vars (not lets!) have an implicit default value of nil.
-      if (!varDecl->isLet()) {
-        if (!varDecl->hasType())
-          tc.validateDecl(varDecl);
-
-        if (varDecl->hasType()) {
-          auto varTypeDecl = varDecl->getType()->getAnyNominal();
-          if (varTypeDecl == tc.Context.getOptionalDecl() ||
-              varTypeDecl == tc.Context.getImplicitlyUnwrappedOptionalDecl())
-            continue;
-        }
+      if (auto pbd = varDecl->getParentPatternBinding()) {
+        if (pbd->isDefaultInitializable())
+          continue;
       }
 
-      if (varDecl->getParentInitializer() != nullptr) {
-        // Var has a default value.
+      if (varDecl->getParentInitializer())
         continue;
-      }
 
+      // The var was not default initializable, and did not have an explicit
+      // initial value.
       propertiesAreValid = false;
       tc.diagnose(it->second->getLoc(), diag::codable_non_decoded_property_here,
                   proto->getDeclaredType(), it->first);
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 07ce81e..54fd144 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -2998,7 +2998,9 @@
       if (!ctor) return { true, expr };
 
       // Make sure the constructor is within Selector.
-      auto ctorContextType = ctor->getDeclContext()->getDeclaredTypeOfContext();
+      auto ctorContextType = ctor->getDeclContext()
+          ->getAsNominalTypeOrNominalTypeExtensionContext()
+          ->getDeclaredType();
       if (!ctorContextType || !ctorContextType->isEqual(SelectorTy))
         return { true, expr };
 
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 6b59ab4..9f46093 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -840,88 +840,6 @@
   return parentEnv;
 }
 
-/// Check whether the given type representation will be
-/// default-initializable.
-static bool isDefaultInitializable(TypeRepr *typeRepr) {
-  // Look through most attributes.
-  if (auto attributed = dyn_cast<AttributedTypeRepr>(typeRepr)) {
-    // Weak ownership implies optionality.
-    if (attributed->getAttrs().getOwnership() == Ownership::Weak)
-      return true;
-    
-    return isDefaultInitializable(attributed->getTypeRepr());
-  }
-
-  // Optional types are default-initializable.
-  if (isa<OptionalTypeRepr>(typeRepr) ||
-      isa<ImplicitlyUnwrappedOptionalTypeRepr>(typeRepr))
-    return true;
-
-  // Tuple types are default-initializable if all of their element
-  // types are.
-  if (auto tuple = dyn_cast<TupleTypeRepr>(typeRepr)) {
-    // ... but not variadic ones.
-    if (tuple->hasEllipsis())
-      return false;
-
-    for (auto elt : tuple->getElements()) {
-      if (!isDefaultInitializable(elt.Type))
-        return false;
-    }
-
-    return true;
-  }
-
-  // Not default initializable.
-  return false;
-}
-
-// @NSManaged properties never get default initialized, nor do debugger
-// variables and immutable properties.
-static bool isNeverDefaultInitializable(Pattern *p) {
-  bool result = false;
-
-  p->forEachVariable([&](VarDecl *var) {
-    if (var->getAttrs().hasAttribute<NSManagedAttr>())
-      return;
-
-    if (var->isDebuggerVar() ||
-        var->isLet())
-      result = true;
-  });
-
-  return result;
-}
-
-/// Determine whether the given pattern binding declaration either has
-/// an initializer expression, or is default initialized, without performing
-/// any type checking on it.
-static bool isDefaultInitializable(PatternBindingDecl *pbd) {
-  assert(pbd->hasStorage());
-
-  for (auto entry : pbd->getPatternList()) {
-    // If it has an initializer expression, this is trivially true.
-    if (entry.getInit())
-      continue;
-
-    if (isNeverDefaultInitializable(entry.getPattern()))
-      return false;
-
-    // If the pattern is typed as optional (or tuples thereof), it is
-    // default initializable.
-    if (auto typedPattern = dyn_cast<TypedPattern>(entry.getPattern())) {
-      if (auto typeRepr = typedPattern->getTypeLoc().getTypeRepr())
-        if (isDefaultInitializable(typeRepr))
-          continue;
-    }
-
-    // Otherwise, we can't default initialize this binding.
-    return false;
-  }
-  
-  return true;
-}
-
 /// Build a default initializer for the given type.
 static Expr *buildDefaultInitializer(TypeChecker &tc, Type type) {
   // Default-initialize optional types and weak values to 'nil'.
@@ -4225,7 +4143,7 @@
             TC.checkTypeModifyingDeclAttributes(var);
 
           // Decide whether we should suppress default initialization.
-          if (isNeverDefaultInitializable(PBD->getPattern(i)))
+          if (!PBD->isDefaultInitializable(i))
             continue;
 
           auto type = PBD->getPattern(i)->getType();
@@ -4602,7 +4520,7 @@
         continue;
 
       if (pbd->isStatic() || !pbd->hasStorage() || 
-          isDefaultInitializable(pbd) || pbd->isInvalid())
+          pbd->isDefaultInitializable() || pbd->isInvalid())
         continue;
 
       // The variables in this pattern have not been
@@ -8375,8 +8293,8 @@
     if (!pbd)
       continue;
 
-    if (pbd->isStatic() || !pbd->hasStorage() || isDefaultInitializable(pbd) ||
-        pbd->isInvalid())
+    if (pbd->isStatic() || !pbd->hasStorage() ||
+        pbd->isDefaultInitializable() || pbd->isInvalid())
       continue;
    
     for (auto entry : pbd->getPatternList()) {
@@ -8504,7 +8422,7 @@
   // Complain.
   TC.diagnose(insertionLoc, diag::required_initializer_missing,
               superInitializer->getFullName(),
-              superInitializer->getDeclContext()->getDeclaredTypeOfContext())
+              superInitializer->getDeclContext()->getDeclaredInterfaceType())
     .fixItInsert(insertionLoc, initializerText);
 
   TC.diagnose(findNonImplicitRequiredInit(superInitializer),
@@ -8659,7 +8577,7 @@
           
           // If we cannot default initialize the property, we cannot
           // synthesize a default initializer for the class.
-          if (CheckDefaultInitializer && !isDefaultInitializable(pbd))
+          if (CheckDefaultInitializer && !pbd->isDefaultInitializable())
             SuppressDefaultInitializer = true;
         }
       continue;
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 4d85138..79badd0 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -1181,7 +1181,7 @@
     // Other unused constructor calls.
     if (callee && isa<ConstructorDecl>(callee) && !call->isImplicit()) {
       diagnose(fn->getLoc(), diag::expression_unused_init_result,
-               callee->getDeclContext()->getDeclaredTypeOfContext())
+               callee->getDeclContext()->getDeclaredInterfaceType())
         .highlight(call->getArg()->getSourceRange());
       return;
     }
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 82c443d..44c9f79 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1174,7 +1174,7 @@
       unsigned alignment = 0;
       if (layout->isKnownSizeTrivial()) {
         size = layout->getTrivialSizeInBits();
-        alignment = layout->getAlignment();
+        alignment = layout->getAlignmentInBits();
       }
       LayoutRequirementKind rawKind = LayoutRequirementKind::UnknownLayout;
       switch (layout->getKind()) {
diff --git a/stdlib/public/SDK/Dispatch/Private.swift b/stdlib/public/SDK/Dispatch/Private.swift
index fe0a928..9716834 100644
--- a/stdlib/public/SDK/Dispatch/Private.swift
+++ b/stdlib/public/SDK/Dispatch/Private.swift
@@ -138,7 +138,7 @@
 	fatalError()
 }
 
-@available(*, unavailable, renamed:"DispatchQueue.apply(attributes:iterations:execute:)")
+@available(*, unavailable, message:"Use DispatchQueue.concurrentPerform(iterations:execute:). The 'queue' argument is not required because the system chooses the appropriate execution context for the block")
 public func dispatch_apply(_ iterations: Int, _ queue: DispatchQueue, _ block: (Int) -> Void) 
 {
 	fatalError()
diff --git a/stdlib/public/SDK/Dispatch/Time.swift b/stdlib/public/SDK/Dispatch/Time.swift
index 3459d55..721635f 100644
--- a/stdlib/public/SDK/Dispatch/Time.swift
+++ b/stdlib/public/SDK/Dispatch/Time.swift
@@ -114,6 +114,41 @@
   }
 }
 
+
+// Returns m1 * m2, clamped to the range [Int64.min, Int64.max].
+// Because of the way this function is used, we can always assume
+// that m2 > 0.
+private func clampedInt64Product(_ m1: Int64, _ m2: Int64) -> Int64 {
+	assert(m2 > 0, "multiplier must be positive")
+	let (result, overflow) = m1.multipliedReportingOverflow(by: m2)
+	if overflow {
+		return m1 > 0 ? Int64.max : Int64.min
+	}
+	return result
+}
+
+// Returns its argument clamped to the range [Int64.min, Int64.max].
+private func toInt64Clamped(_ value: Double) -> Int64 {
+	if value.isNaN { return Int64.max }
+	if value >= Double(Int64.max) { return Int64.max }
+	if value <= Double(Int64.min) { return Int64.min }
+	return Int64(value)
+}
+
+/// Represents a time interval that can be used as an offset from a `DispatchTime`
+/// or `DispatchWallTime`.
+///
+/// For example:
+///		let inOneSecond = DispatchTime.now() + DispatchTimeInterval.seconds(1)
+///
+///	If the requested time interval is larger then the internal representation
+/// permits, the result of adding it to a `DispatchTime` or `DispatchWallTime`
+/// is `DispatchTime.distantFuture` and `DispatchWallTime.distantFuture`
+/// respectively. Such time intervals compare as equal:
+///
+///		let t1 = DispatchTimeInterval.seconds(Int.max)
+///		let t2 = DispatchTimeInterval.milliseconds(Int.max)
+///		let result = t1 == t2   // true
 public enum DispatchTimeInterval : Equatable {
 	case seconds(Int)
 	case milliseconds(Int)
@@ -124,9 +159,9 @@
 
 	internal var rawValue: Int64 {
 		switch self {
-		case .seconds(let s): return Int64(s) * Int64(NSEC_PER_SEC)
-		case .milliseconds(let ms): return Int64(ms) * Int64(NSEC_PER_MSEC)
-		case .microseconds(let us): return Int64(us) * Int64(NSEC_PER_USEC)
+		case .seconds(let s): return clampedInt64Product(Int64(s), Int64(NSEC_PER_SEC))
+		case .milliseconds(let ms): return clampedInt64Product(Int64(ms), Int64(NSEC_PER_MSEC))
+		case .microseconds(let us): return clampedInt64Product(Int64(us), Int64(NSEC_PER_USEC))
 		case .nanoseconds(let ns): return Int64(ns)
 		case .never: return Int64.max
 		}
@@ -153,16 +188,12 @@
 }
 
 public func +(time: DispatchTime, seconds: Double) -> DispatchTime {
-	let interval = seconds * Double(NSEC_PER_SEC)
-	let t = __dispatch_time(time.rawValue,
-		interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
+	let t = __dispatch_time(time.rawValue, toInt64Clamped(seconds * Double(NSEC_PER_SEC)));
 	return DispatchTime(rawValue: t)
 }
 
 public func -(time: DispatchTime, seconds: Double) -> DispatchTime {
-	let interval = -seconds * Double(NSEC_PER_SEC)
-	let t = __dispatch_time(time.rawValue,
-		interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
+	let t = __dispatch_time(time.rawValue, toInt64Clamped(-seconds * Double(NSEC_PER_SEC)));
 	return DispatchTime(rawValue: t)
 }
 
@@ -177,15 +208,11 @@
 }
 
 public func +(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
-	let interval = seconds * Double(NSEC_PER_SEC)
-	let t = __dispatch_time(time.rawValue,
-		interval.isInfinite || interval.isNaN ? Int64.max : Int64(interval))
+	let t = __dispatch_time(time.rawValue, toInt64Clamped(seconds * Double(NSEC_PER_SEC)));
 	return DispatchWallTime(rawValue: t)
 }
 
 public func -(time: DispatchWallTime, seconds: Double) -> DispatchWallTime {
-	let interval = -seconds * Double(NSEC_PER_SEC)
-	let t = __dispatch_time(time.rawValue,
-		interval.isInfinite || interval.isNaN ? Int64.min : Int64(interval))
+	let t = __dispatch_time(time.rawValue, toInt64Clamped(-seconds * Double(NSEC_PER_SEC)));
 	return DispatchWallTime(rawValue: t)
 }
diff --git a/test/SILOptimizer/eager_specialize.sil b/test/SILOptimizer/eager_specialize.sil
index d9d66a4..674e125 100644
--- a/test/SILOptimizer/eager_specialize.sil
+++ b/test/SILOptimizer/eager_specialize.sil
@@ -1,6 +1,7 @@
 // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -eager-specializer  %s | %FileCheck %s
 // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -eager-specializer -sil-deadfuncelim  %s | %FileCheck --check-prefix=CHECK-DEADFUNCELIM %s
 // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -eager-specializer  %s -o %t.sil && %target-swift-frontend -assume-parsing-unqualified-ownership-sil -module-name=eager_specialize -emit-ir %t.sil | %FileCheck --check-prefix=CHECK-IRGEN %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -eager-specializer -sil-inline-generics=true -inline %s | %FileCheck --check-prefix=CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE %s
 
 sil_stage canonical
 
@@ -828,6 +829,27 @@
   throw %10 : $Error
 } // end sil function '_T034eager_specialize_throwing_function19ClassUsingThrowingPC1gs5Int64VxKAA0G1PRzlFZ'
 
+// Check that a specialization was produced and it is not inlined.
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE-LABEL: sil{{.*}}@{{.*}}testSimpleGeneric{{.*}}where τ_0_0 : _Trivial(64, 64)
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE-LABEL: sil{{.*}}@testSimpleGeneric :
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: [[METATYPE:%.*]] = metatype $@thick T.Type
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: [[SIZEOF:%.*]] = builtin "sizeof"<T>([[METATYPE]] : $@thick T.Type)
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: [[SIZE:%.*]] = integer_literal $Builtin.Word, 8
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: builtin "cmp_eq_Word"([[SIZEOF]] : $Builtin.Word, [[SIZE]] : $Builtin.Word)
+// Invoke the specialization, but do not inline it!
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: function_ref @{{.*}}testSimpleGeneric{{.*}}
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: apply
+// CHECK-EAGER-SPECIALIZE-AND-GENERICS-INLINE: // end sil function 'testSimpleGeneric'
+
+sil [_specialize exported: false, kind: full, where T: _Trivial(64, 64)] @testSimpleGeneric : $@convention(thin) <T>(@in T) -> Builtin.Int64 {
+bb0(%0 : $*T):
+  %1 = metatype $@thick T.Type
+  %2 = builtin "sizeof"<T>(%1 : $@thick T.Type) : $Builtin.Word 
+  %8 = builtin "zextOrBitCast_Word_Int64"(%2 : $Builtin.Word) : $Builtin.Int64
+  destroy_addr %0 : $*T
+  return %8 : $Builtin.Int64
+}
+
 sil_vtable ClassUsingThrowingP {
   #ClassUsingThrowingP.init!allocator.1: (ClassUsingThrowingP.Type) -> () -> ClassUsingThrowingP : _T034eager_specialize_throwing_function19ClassUsingThrowingPCACycfC	// ClassUsingThrowingP.__allocating_init()
   #ClassUsingThrowingP.init!initializer.1: (ClassUsingThrowingP.Type) -> () -> ClassUsingThrowingP : _T034eager_specialize_throwing_function19ClassUsingThrowingPCACycfc	// ClassUsingThrowingP.init()
diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil
index 6a82113..c97f8b2 100644
--- a/test/SILOptimizer/sil_combine.sil
+++ b/test/SILOptimizer/sil_combine.sil
@@ -859,6 +859,51 @@
   return %4 : $Int8                               // id: %5
 }
 
+// An archetype with a trivial layout constraint can never be a class.
+// CHECK-LABEL: sil @is_trivial_layout_constraint_class
+sil @is_trivial_layout_constraint_class : $@convention(thin) <T where T: _Trivial> (@in T) -> Int8 {
+bb0(%0 : $*T):
+  %1 = metatype $@thick T.Type
+// CHECK-NOT: builtin "canBeClass"
+// CHECK-NOT: apply
+  %3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
+// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 0
+// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
+  %4 = struct $Int8 (%3 : $Builtin.Int8)
+// CHECK: return [[RESULT]] : $Int8
+  return %4 : $Int8
+}
+
+// An archetype with a _Class layout constraint is always a class.
+// CHECK-LABEL: sil @is_class_layout_constraint_class
+sil @is_class_layout_constraint_class : $@convention(thin) <T where T: _Class> (@in T) -> Int8 {
+bb0(%0 : $*T):
+  %1 = metatype $@thick T.Type
+// CHECK-NOT: builtin "canBeClass"
+// CHECK-NOT: apply
+  %3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
+// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 1
+// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
+  %4 = struct $Int8 (%3 : $Builtin.Int8)
+// CHECK: return [[RESULT]] : $Int8
+  return %4 : $Int8
+}
+
+// An archetype with a _NativeClass layout constraint is always a class.
+// CHECK-LABEL: sil @is_native_class_layout_constraint_class
+sil @is_native_class_layout_constraint_class : $@convention(thin) <T where T: _NativeClass> (@in T) -> Int8 {
+bb0(%0 : $*T):
+  %1 = metatype $@thick T.Type
+// CHECK-NOT: builtin "canBeClass"
+// CHECK-NOT: apply
+  %3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
+// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 1
+// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
+  %4 = struct $Int8 (%3 : $Builtin.Int8)
+// CHECK: return [[RESULT]] : $Int8
+  return %4 : $Int8
+}
+
 @objc class MyClass {
 }
 
diff --git a/test/SILOptimizer/string_switch.swift b/test/SILOptimizer/string_switch.swift
index 933c78d..d563a58 100644
--- a/test/SILOptimizer/string_switch.swift
+++ b/test/SILOptimizer/string_switch.swift
@@ -2,6 +2,7 @@
 // RUN: %target-build-swift -O %s -module-name=test -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil | %FileCheck %s
 // RUN: %target-run %t.out
 // UNSUPPORTED: nonatomic_rc
+// UNSUPPORTED: resilient_stdlib
 
 import StdlibUnittest
 
diff --git a/test/SourceKit/DocumentStructure/structure.swift.response b/test/SourceKit/DocumentStructure/structure.swift.response
index cf78d08..b853950 100644
--- a/test/SourceKit/DocumentStructure/structure.swift.response
+++ b/test/SourceKit/DocumentStructure/structure.swift.response
@@ -50,6 +50,8 @@
           key.namelength: 10,
           key.attributes: [
             {
+              key.offset: 41,
+              key.length: 9,
               key.attribute: source.decl.attribute.iboutlet
             }
           ]
@@ -105,6 +107,8 @@
           key.bodylength: 5,
           key.attributes: [
             {
+              key.offset: 136,
+              key.length: 9,
               key.attribute: source.decl.attribute.ibaction
             }
           ]
@@ -124,6 +128,8 @@
       key.bodylength: 0,
       key.attributes: [
         {
+          key.offset: 175,
+          key.length: 13,
           key.attribute: source.decl.attribute.ibdesignable
         }
       ]
@@ -152,6 +158,8 @@
           key.namelength: 17,
           key.attributes: [
             {
+              key.offset: 221,
+              key.length: 14,
               key.attribute: source.decl.attribute.ibinspectable
             }
           ]
@@ -168,6 +176,8 @@
           key.namelength: 17,
           key.attributes: [
             {
+              key.offset: 268,
+              key.length: 14,
               key.attribute: source.decl.attribute.gkinspectable
             }
           ]
@@ -938,6 +948,8 @@
       ],
       key.attributes: [
         {
+          key.offset: 1406,
+          key.length: 5,
           key.attribute: source.decl.attribute.objc
         }
       ],
@@ -961,6 +973,8 @@
           key.bodylength: 0,
           key.attributes: [
             {
+              key.offset: 1449,
+              key.length: 5,
               key.attribute: source.decl.attribute.objc
             }
           ]
@@ -985,6 +999,8 @@
       ],
       key.attributes: [
         {
+          key.offset: 1474,
+          key.length: 11,
           key.attribute: source.decl.attribute.objc.name
         }
       ],
@@ -1008,6 +1024,8 @@
           key.bodylength: 0,
           key.attributes: [
             {
+              key.offset: 1524,
+              key.length: 10,
               key.attribute: source.decl.attribute.objc.name
             }
           ]
diff --git a/test/SourceKit/InterfaceGen/gen_clang_module.swift.response b/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
index 800b13c..fec916e 100644
--- a/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
+++ b/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
@@ -5380,6 +5380,8 @@
         key.namelength: 21,
         key.attributes: [
           {
+            key.offset: 3991,
+            key.length: 11,
             key.attribute: source.decl.attribute.convenience
           }
         ],
@@ -5975,6 +5977,8 @@
         key.namelength: 10,
         key.attributes: [
           {
+            key.offset: 6061,
+            key.length: 15,
             key.attribute: source.decl.attribute.weak
           }
         ]
@@ -5991,6 +5995,8 @@
         key.namelength: 16,
         key.attributes: [
           {
+            key.offset: 6114,
+            key.length: 15,
             key.attribute: source.decl.attribute.weak
           }
         ]
@@ -6040,6 +6046,8 @@
         key.namelength: 7,
         key.attributes: [
           {
+            key.offset: 6263,
+            key.length: 4,
             key.attribute: source.decl.attribute.weak
           }
         ]
@@ -6091,6 +6099,8 @@
         key.namelength: 19,
         key.attributes: [
           {
+            key.offset: 6390,
+            key.length: 11,
             key.attribute: source.decl.attribute.convenience
           }
         ],
@@ -6116,6 +6126,8 @@
         key.namelength: 12,
         key.attributes: [
           {
+            key.offset: 6432,
+            key.length: 39,
             key.attribute: source.decl.attribute.available
           }
         ]
@@ -6130,6 +6142,8 @@
         key.namelength: 24,
         key.attributes: [
           {
+            key.offset: 6509,
+            key.length: 23,
             key.attribute: source.decl.attribute.available
           }
         ]
@@ -6144,6 +6158,8 @@
         key.namelength: 27,
         key.attributes: [
           {
+            key.offset: 6582,
+            key.length: 47,
             key.attribute: source.decl.attribute.available
           }
         ]
@@ -6179,6 +6195,8 @@
     ],
     key.attributes: [
       {
+        key.offset: 6703,
+        key.length: 63,
         key.attribute: source.decl.attribute.available
       }
     ],
@@ -6285,6 +6303,8 @@
         key.namelength: 3,
         key.attributes: [
           {
+            key.offset: 7094,
+            key.length: 8,
             key.attribute: source.decl.attribute.override
           }
         ]
diff --git a/test/SourceKit/InterfaceGen/gen_swift_source.swift.response b/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
index 7834451..537fc33 100644
--- a/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
+++ b/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
@@ -449,6 +449,8 @@
         key.namelength: 3,
         key.attributes: [
           {
+            key.offset: 319,
+            key.length: 8,
             key.attribute: source.decl.attribute.override
           }
         ]
diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift
index 7fe75bd..589dba4 100644
--- a/test/attr/attr_objc.swift
+++ b/test/attr/attr_objc.swift
@@ -204,7 +204,7 @@
   case subject_enumElement2
 
   @objc(subject_enumElement3)
-  case subject_enumElement3, subject_enumElement4 // expected-error {{'@objc' enum case declaration defines multiple enum cases with the same Objective-C name}}{{3-8=}}
+  case subject_enumElement3, subject_enumElement4 // expected-error {{'@objc' enum case declaration defines multiple enum cases with the same Objective-C name}}{{3-30=}}
 
   @objc   // expected-error {{attribute has no effect; cases within an '@objc' enum are already exposed to Objective-C}} {{3-9=}}
   case subject_enumElement5, subject_enumElement6
@@ -221,7 +221,7 @@
 
 enum subject_enum2 {
   @objc(subject_enum2Element1)
-  case subject_enumElement1 // expected-error{{'@objc' enum case is not allowed outside of an '@objc' enum}}{{3-8=}}
+  case subject_enumElement1 // expected-error{{'@objc' enum case is not allowed outside of an '@objc' enum}}{{3-31=}}
 }
 
 @objc
@@ -1839,7 +1839,7 @@
   }
 
   var prop3: Int {
-    @objc(setProperty:) didSet { } // expected-error{{observing accessors are not allowed to be marked @objc}} {{5-10=}}
+    @objc(setProperty:) didSet { } // expected-error{{observing accessors are not allowed to be marked @objc}} {{5-25=}}
   }
 
   @objc
diff --git a/test/stdlib/Dispatch.swift b/test/stdlib/Dispatch.swift
index a9a5d81..dbf542f 100644
--- a/test/stdlib/Dispatch.swift
+++ b/test/stdlib/Dispatch.swift
@@ -126,10 +126,24 @@
 	expectEqual(DispatchTime(uptimeNanoseconds: 1), then)
 
 	then = DispatchTime.now() - Double.nan
+	expectEqual(DispatchTime.distantFuture, then)
+
+	then = DispatchTime.now() + Date.distantFuture.timeIntervalSinceNow
+	expectEqual(DispatchTime(uptimeNanoseconds: UInt64.max), then)
+
+	then = DispatchTime.now() + Date.distantPast.timeIntervalSinceNow
 	expectEqual(DispatchTime(uptimeNanoseconds: 1), then)
+
+	then = DispatchTime.now() - Date.distantFuture.timeIntervalSinceNow
+	expectEqual(DispatchTime(uptimeNanoseconds: 1), then)
+
+	then = DispatchTime.now() - Date.distantPast.timeIntervalSinceNow
+	expectEqual(DispatchTime(uptimeNanoseconds: UInt64.max), then)
 }
 
 DispatchAPI.test("DispatchWallTime.addSubtract") {
+	let distantPastRawValue = DispatchWallTime.distantFuture.rawValue - UInt64(1)
+
 	var then = DispatchWallTime.now() + Double.infinity
 	expectEqual(DispatchWallTime.distantFuture, then)
 
@@ -137,10 +151,22 @@
 	expectEqual(DispatchWallTime.distantFuture, then)
 
 	then = DispatchWallTime.now() - Double.infinity
-	expectEqual(DispatchWallTime.distantFuture.rawValue - UInt64(1), then.rawValue)
+	expectEqual(distantPastRawValue, then.rawValue)
 
 	then = DispatchWallTime.now() - Double.nan
-	expectEqual(DispatchWallTime.distantFuture.rawValue - UInt64(1), then.rawValue)
+	expectEqual(DispatchWallTime.distantFuture, then)
+
+	then = DispatchWallTime.now() + Date.distantFuture.timeIntervalSinceNow
+	expectEqual(DispatchWallTime.distantFuture, then)
+
+	then = DispatchWallTime.now() + Date.distantPast.timeIntervalSinceNow
+	expectEqual(distantPastRawValue, then.rawValue)
+
+	then = DispatchWallTime.now() - Date.distantFuture.timeIntervalSinceNow
+	expectEqual(distantPastRawValue, then.rawValue)
+
+	then = DispatchWallTime.now() - Date.distantPast.timeIntervalSinceNow
+	expectEqual(DispatchWallTime.distantFuture, then)
 }
 
 DispatchAPI.test("DispatchTime.uptimeNanos") {
@@ -516,6 +542,35 @@
 	}
 }
 
+DispatchAPI.test("DispatchTimeInterval") {
+	// Basic tests that the correct value is stored and the == method works
+	for i in stride(from:1, through: 100, by: 5) {
+		expectEqual(DispatchTimeInterval.seconds(i), DispatchTimeInterval.milliseconds(i * 1000))
+		expectEqual(DispatchTimeInterval.milliseconds(i), DispatchTimeInterval.microseconds(i * 1000))
+		expectEqual(DispatchTimeInterval.microseconds(i), DispatchTimeInterval.nanoseconds(i * 1000))
+	}
+
+
+	// Check some cases that used to cause arithmetic overflow when evaluating the rawValue for ==
+	var t = DispatchTimeInterval.seconds(Int.max)
+	expectTrue(t == t) // This would crash.
+
+	t = DispatchTimeInterval.seconds(-Int.max)
+	expectTrue(t == t) // This would crash.
+
+	t = DispatchTimeInterval.milliseconds(Int.max)
+	expectTrue(t == t) // This would crash.
+
+	t = DispatchTimeInterval.milliseconds(-Int.max)
+	expectTrue(t == t) // This would crash.
+
+	t = DispatchTimeInterval.microseconds(Int.max)
+	expectTrue(t == t) // This would crash.
+
+	t = DispatchTimeInterval.microseconds(-Int.max)
+	expectTrue(t == t) // This would crash.
+}
+
 #if swift(>=4.0)
 DispatchAPI.test("DispatchTimeInterval.never.equals") {
 	expectTrue(DispatchTimeInterval.never == DispatchTimeInterval.never)
diff --git a/test/stdlib/Inputs/ArrayTypesAndHelpers.swift b/test/stdlib/Inputs/ArrayTypesAndHelpers.swift
new file mode 100644
index 0000000..400e730
--- /dev/null
+++ b/test/stdlib/Inputs/ArrayTypesAndHelpers.swift
@@ -0,0 +1,714 @@
+import Swift
+import StdlibUnittest
+#if _runtime(_ObjC)
+import Darwin
+import Foundation
+#endif
+
+
+#if _runtime(_ObjC)
+
+/// Expect some number of autoreleased value objects.
+///
+/// - parameter opt: applies to platforms that have the return-autoreleased
+///   optimization.
+///
+/// - parameter unopt: applies to platforms that don't.
+///
+/// FIXME: Some non-zero `opt` might be cases of missed return-autorelease.
+func expectAutoreleasedValues(
+  opt: Int = 0, unopt: Int = 0) {
+  _expectAutoreleasedKeysAndValues(opt: (0, opt), unopt: (0, unopt))
+}
+
+func isNativeNSArray(_ d: NSArray) -> Bool {
+  let className: NSString = NSStringFromClass(type(of: d)) as NSString
+  return ["_SwiftDeferredNSArray", "_ContiguousArray", "_EmptyArray"].contains {
+    className.range(of: $0).length > 0
+  }
+}
+
+func isCocoaNSArray(_ a: NSArray) -> Bool {
+  let className: NSString = NSStringFromClass(type(of: a)) as NSString
+  return className.range(of: "NSArray").length > 0 ||
+    className.range(of: "NSCFArray").length > 0
+}
+
+func getBridgedNSArrayOfRefTypesBridgedVerbatim() -> NSArray {
+  expectTrue(_isBridgedVerbatimToObjectiveC(TestObjCValueTy.self))
+
+  var a = Array<TestObjCValueTy>()
+  a.reserveCapacity(32)
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  let bridged = convertArrayToNSArray(a)
+
+  assert(isNativeNSArray(bridged))
+
+  return bridged
+}
+
+func getBridgedEmptyNSArray() -> NSArray {
+  let a = Array<TestObjCValueTy>()
+
+  let bridged = convertArrayToNSArray(a)
+  assert(isNativeNSArray(bridged))
+
+  return bridged
+}
+
+#endif
+
+func getDerivedAPIsArray() -> Array<Int> {
+  var a = Array<Int>()
+  a.append(1010)
+  a.append(1020)
+  a.append(1030)
+  return a
+}
+
+func _makeExpectedArrayContents(
+  _ expected: [Int]
+) -> [ExpectedArrayElement] {
+  var result = [ExpectedArrayElement]()
+  for value in expected {
+    result.append(ExpectedArrayElement(value: value))
+  }
+  return result
+}
+
+func _equalsWithoutElementIdentity(
+  _ lhs: [ExpectedArrayElement], _ rhs: [ExpectedArrayElement]
+) -> Bool {
+  func stripIdentity(
+    _ list: [ExpectedArrayElement]
+  ) -> [ExpectedArrayElement] {
+    return list.map { ExpectedArrayElement(value: $0.value) }
+  }
+
+  return stripIdentity(lhs).elementsEqual(stripIdentity(rhs))
+}
+
+struct ExpectedArrayElement : Comparable, CustomStringConvertible {
+  var value: Int
+  var valueIdentity: UInt
+
+  init(value: Int, valueIdentity: UInt = 0) {
+    self.value = value
+    self.valueIdentity = valueIdentity
+  }
+
+  var description: String {
+    return "(\(value), \(valueIdentity))"
+  }
+}
+
+func == (
+  lhs: ExpectedArrayElement,
+  rhs: ExpectedArrayElement
+) -> Bool {
+  return
+    lhs.value == rhs.value &&
+    lhs.valueIdentity == rhs.valueIdentity
+}
+
+func < (
+  lhs: ExpectedArrayElement,
+  rhs: ExpectedArrayElement
+) -> Bool {
+  let lhsElements = [ lhs.value, Int(bitPattern: lhs.valueIdentity) ]
+  let rhsElements = [ rhs.value, Int(bitPattern: rhs.valueIdentity) ]
+  return lhsElements.lexicographicallyPrecedes(rhsElements)
+}
+
+#if _runtime(_ObjC)
+ func _checkArrayFastEnumerationImpl(
+  _ expected: [Int],
+  _ a: NSArray,
+  _ makeEnumerator: () -> NSFastEnumeration,
+  _ useEnumerator: (NSArray, NSFastEnumeration, (AnyObject) -> ()) -> Void,
+  _ convertValue: @escaping (AnyObject) -> Int
+) {
+  let expectedContentsWithoutIdentity =
+  _makeExpectedArrayContents(expected)
+  
+  var expectedContents = [ExpectedArrayElement]()
+  
+  for i in 0..<3 {
+    var actualContents = [ExpectedArrayElement]()
+    let sink = {
+      (value: AnyObject) in
+      actualContents.append(ExpectedArrayElement(
+        value: convertValue(value),
+        valueIdentity: unsafeBitCast(value, to: UInt.self)))
+    }
+
+    useEnumerator(a, makeEnumerator(), sink)
+
+    expectTrue(
+      _equalsWithoutElementIdentity(
+        expectedContentsWithoutIdentity, actualContents),
+      "expected: \(expectedContentsWithoutIdentity)\n" +
+      "actual: \(actualContents)\n")
+
+    if i == 0 {
+      expectedContents = actualContents
+    }
+    
+    expectEqualSequence(expectedContents, actualContents)
+  }
+}
+#endif
+
+func getCOWFastArray() -> Array<Int> {
+  var a = Array<Int>()
+  a.reserveCapacity(10)
+  a.append(1)
+  a.append(2)
+  a.append(3)
+  return a
+}
+
+func getCOWSlowArray() -> Array<COWBox<Int>> {
+  var a = Array<COWBox<Int>>()
+  a.reserveCapacity(10)
+  a.append(COWBox(1))
+  a.append(COWBox(2))
+  a.append(COWBox(3))
+  return a
+}
+
+#if _runtime(_ObjC)
+ func slurpFastEnumerationFromObjC(
+  _ a: NSArray, _ fe: NSFastEnumeration, _ sink: (AnyObject) -> Void
+) {
+  let objcValues = NSMutableArray()
+  slurpFastEnumerationOfArrayFromObjCImpl(a, fe, objcValues)
+  for value in objcValues {
+    sink(value as AnyObject)
+  }
+}
+
+import SlurpFastEnumeration
+
+ func slurpFastEnumerationFromSwift(
+  _ a: NSArray, _ fe: NSFastEnumeration, _ sink: (AnyObject) -> Void,
+  maxItems: Int? = nil
+) {
+  var state = NSFastEnumerationState()
+
+  let stackBufLength = 3
+  let stackBuf = _HeapBuffer<(), AnyObject?>(
+    _HeapBufferStorage<(), AnyObject?>.self, (), stackBufLength)
+
+  var itemsReturned = 0
+  while true {
+    let returnedCount = fe.countByEnumerating(
+      with: &state, objects: AutoreleasingUnsafeMutablePointer(stackBuf.baseAddress),
+      count: stackBufLength)
+    expectNotEqual(0, state.state)
+    expectNotNil(state.mutationsPtr)
+    if returnedCount == 0 {
+      break
+    }
+    for i in 0..<returnedCount {
+      let value: AnyObject = state.itemsPtr![i]!
+      sink(value)
+      itemsReturned += 1
+    }
+    if maxItems != nil && itemsReturned >= maxItems! {
+      return
+    }
+  }
+
+  for _ in 0..<3 {
+    let returnedCount = fe.countByEnumerating(
+      with: &state, objects: AutoreleasingUnsafeMutablePointer(stackBuf.baseAddress),
+      count: stackBufLength)
+    expectNotEqual(0, state.state)
+    expectNotNil(state.mutationsPtr)
+    expectEqual(0, returnedCount)
+  }
+}
+
+ func checkArrayFastEnumerationFromSwift(
+  _ expected: [Int],
+  _ a: NSArray, _ makeEnumerator: () -> NSFastEnumeration,
+  _ convertValue: @escaping (AnyObject) -> Int
+) {
+  _checkArrayFastEnumerationImpl(
+    expected, a, makeEnumerator,
+    { (a, fe, sink) in
+      slurpFastEnumerationFromSwift(a, fe, sink)
+    },
+    convertValue)
+}
+
+ func checkArrayFastEnumerationFromObjC(
+  _ expected: [Int],
+  _ a: NSArray, _ makeEnumerator: () -> NSFastEnumeration,
+  _ convertValue: @escaping (AnyObject) -> Int
+) {
+  _checkArrayFastEnumerationImpl(
+    expected, a, makeEnumerator,
+    { (a, fe, sink) in
+      slurpFastEnumerationFromObjC(a, fe, sink)
+    },
+    convertValue)
+}
+
+func getBridgedNSArrayOfObjValue_ValueTypesCustomBridged(
+  numElements: Int = 3
+) -> NSArray {
+  expectFalse(_isBridgedVerbatimToObjectiveC(TestBridgedValueTy.self))
+
+  var a = Array<TestBridgedValueTy>()
+  for i in 1..<(numElements + 1) {
+    a.append(TestBridgedValueTy(i * 10 + 1000))
+  }
+
+  let bridged = convertArrayToNSArray(a)
+  expectTrue(isNativeNSArray(bridged))
+
+  return bridged
+}
+
+ func checkArrayEnumeratorPartialFastEnumerationFromSwift(
+  _ expected: [Int],
+  _ a: NSArray,
+  maxFastEnumerationItems: Int,
+  _ convertValue: @escaping (AnyObject) -> Int
+) {
+  _checkArrayFastEnumerationImpl(
+    expected, a, { a.objectEnumerator() },
+    { (a, fe, sink) in
+      slurpFastEnumerationOfNSEnumeratorFromSwift(
+        a, fe as! NSEnumerator, sink,
+        maxFastEnumerationItems: maxFastEnumerationItems)
+    },
+    convertValue)
+}
+
+ func slurpFastEnumerationOfNSEnumeratorFromSwift(
+  _ a: NSArray, _ enumerator: NSEnumerator, _ sink: (AnyObject) -> Void,
+  maxFastEnumerationItems: Int
+) {
+  slurpFastEnumerationFromSwift(
+    a, enumerator, sink, maxItems: maxFastEnumerationItems)
+  while let value = enumerator.nextObject() {
+    sink(value as AnyObject)
+  }
+}
+
+func _expectAutoreleasedKeysAndValues(
+  opt: (Int, Int) = (0, 0), unopt: (Int, Int) = (0, 0)) {
+  var expectedKeys = 0
+  var expectedValues = 0
+#if arch(i386)
+  (expectedKeys, expectedValues) = unopt
+#else
+  (expectedKeys, expectedValues) = opt
+#endif
+
+  TestObjCValueTy.objectCount -= expectedValues
+}
+
+func isCocoaArray<T>(_ a: Array<T>) -> Bool {
+  return !isNativeArray(a)
+}
+
+func isNativeArray<T>(_ a: Array<T>) -> Bool {
+  return a._buffer._storage.isNative
+}
+
+func convertArrayToNSArray<T>(_ a: [T]) -> NSArray {
+  return a._bridgeToObjectiveC()
+}
+
+func convertNSArrayToArray<T>(_ a: NSArray?) -> [T] {
+  if _slowPath(a == nil) { return [] }
+  var result: [T]?
+  Array._forceBridgeFromObjectiveC(a!, result: &result)
+  return result!
+}
+
+func getAsNSArray(_ a: Array<Int>) -> NSArray {
+  let values = Array(a.map { TestObjCValueTy($0) })
+  
+  // Return an `NSMutableArray` to make sure that it has a unique
+  // pointer identity.
+  let nsarray = NSMutableArray()
+  nsarray.addObjects(from: values)
+  return nsarray
+}
+
+func getAsEquatableNSArray(_ a: Array<Int>) -> NSArray {
+  let values = Array(a.map { TestObjCEquatableValueTy($0) })
+
+  // Return an `NSMutableArray` to make sure that it has a unique
+  // pointer identity.
+  let nsarray = NSMutableArray()
+  nsarray.addObjects(from: values)
+  return nsarray
+}
+
+func getAsNSMutableArray(_ a: Array<Int>) -> NSMutableArray {
+  let values = Array(a.map { TestObjCValueTy($0) })
+  let nsarray = NSMutableArray()
+  nsarray.addObjects(from: values)
+  return nsarray
+}
+
+func getBridgedVerbatimArrayAndNSMutableArray()
+    -> (Array<AnyObject>, NSMutableArray) {
+  let nsa = getAsNSMutableArray([1010, 1020, 1030])
+  return (convertNSArrayToArray(nsa), nsa)
+}
+
+func getBridgedVerbatimArray() -> Array<AnyObject> {
+  let nsa = getAsNSArray([1010, 1020, 1030])
+  return convertNSArrayToArray(nsa)
+}
+
+func getBridgedVerbatimArray(_ a: Array<Int>) -> Array<AnyObject> {
+  let nsa = getAsNSArray(a)
+  return convertNSArrayToArray(nsa)
+}
+
+func getBridgedNonverbatimArray() -> Array<TestBridgedValueTy> {
+  let nsa = getAsNSArray([1010, 1020, 1030 ])
+  return Swift._forceBridgeFromObjectiveC(nsa, Array.self)
+}
+
+func getBridgedNonverbatimArray(_ a: Array<Int>) -> Array<TestBridgedValueTy> {
+  let nsa = getAsNSArray(a)
+  return Swift._forceBridgeFromObjectiveC(nsa, Array.self)
+}
+
+func getBridgedNonverbatimArrayAndNSMutableArray()
+    -> (Array<TestBridgedValueTy>, NSMutableArray) {
+  let nsa = getAsNSMutableArray([1010, 1020, 1030])
+  return (Swift._forceBridgeFromObjectiveC(nsa, Array.self), nsa)
+}
+
+func getBridgedVerbatimEquatableArray(_ a: Array<Int>) 
+    -> Array<TestObjCEquatableValueTy> {
+  let nsa = getAsEquatableNSArray(a)
+  return convertNSArrayToArray(nsa)
+}
+
+func getBridgedNonverbatimEquatableArray(_ a: Array<Int>) 
+    -> Array<TestBridgedEquatableValueTy> {
+  let nsa = getAsEquatableNSArray(a)
+  return Swift._forceBridgeFromObjectiveC(nsa, Array.self)
+}
+
+func getHugeBridgedVerbatimArrayHelper() -> NSArray {
+  let values = (1...32).map { TestObjCValueTy(1000 + $0) }
+
+  let nsa = NSMutableArray()
+  nsa.addObjects(from: values)
+  return nsa
+}
+
+func getHugeBridgedVerbatimArray() -> Array<AnyObject> {
+  let nsa = getHugeBridgedVerbatimArrayHelper()
+  return convertNSArrayToArray(nsa)
+}
+
+func getHugeBridgedNonverbatimArray() 
+    -> Array<TestBridgedValueTy> {
+  let nsa = getHugeBridgedVerbatimArrayHelper()
+  return Swift._forceBridgeFromObjectiveC(nsa, Array.self)
+}
+
+func getBridgedNSArrayOfObj_ValueTypeCustomBridged() -> NSArray {
+  expectTrue(_isBridgedVerbatimToObjectiveC(TestObjCValueTy.self))
+
+  var a = Array<TestObjCValueTy>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  let bridged = convertArrayToNSArray(a)
+  expectTrue(isNativeNSArray(bridged))
+
+  return bridged
+}
+
+func getBridgedNSArrayOfValue_ValueTypeCustomBridged() -> NSArray {
+  expectFalse(_isBridgedVerbatimToObjectiveC(TestBridgedValueTy.self))
+
+  var a = Array<TestBridgedValueTy>()
+  a.append(TestBridgedValueTy(1010))
+  a.append(TestBridgedValueTy(1020))
+  a.append(TestBridgedValueTy(1030))
+
+  let bridged = convertArrayToNSArray(a)
+  expectTrue(isNativeNSArray(bridged))
+
+  return bridged
+}
+
+func getRoundtripBridgedNSArray() -> NSArray {
+  let values = [ 1010, 1020, 1030 ].map { TestObjCValueTy($0) }
+
+  let nsa = NSArray(array: values)
+
+  let a: Array<AnyObject> = convertNSArrayToArray(nsa)
+
+  let bridgedBack = convertArrayToNSArray(a)
+  expectTrue(isCocoaNSArray(bridgedBack))
+  expectEqual(unsafeBitCast(nsa, to: Int.self), unsafeBitCast(bridgedBack, to: Int.self))
+
+  return bridgedBack
+}
+
+var _objcValueCount = _stdlib_AtomicInt(0)
+var _objcValueSerial = _stdlib_AtomicInt(0)
+
+class TestObjCValueTy : NSObject {
+  class var objectCount: Int {
+    get {
+      return _objcValueCount.load()
+    }
+    set {
+      _objcValueCount.store(newValue)
+    }
+  }
+
+  init(_ value: Int) {
+    _objcValueCount.fetchAndAdd(1)
+    serial = _objcValueSerial.addAndFetch(1)
+    self.value = value
+  }
+
+  deinit {
+    assert(serial > 0, "double destruction")
+    _objcValueCount.fetchAndAdd(-1)
+    serial = -serial
+  }
+
+  override var description: String {
+    assert(serial > 0, "dead TestObjCValueTy")
+    return value.description
+  }
+
+  var value: Int
+  var serial: Int
+}
+
+var _objcEquatableValueCount = _stdlib_AtomicInt(0)
+var _objcEquatableValueSerial = _stdlib_AtomicInt(0)
+
+class TestObjCEquatableValueTy : NSObject {
+  class var objectCount: Int {
+    get {
+      return _objcEquatableValueCount.load()
+    }
+    set {
+      _objcEquatableValueCount.store(newValue)
+    }
+  }
+
+  init(_ value: Int) {
+    _objcEquatableValueCount.fetchAndAdd(1)
+    serial = _objcEquatableValueSerial.addAndFetch(1)
+    self.value = value
+  }
+
+  deinit {
+    assert(serial > 0, "double destruction")
+    _objcEquatableValueCount.fetchAndAdd(-1)
+    serial = -serial
+  }
+
+  override func isEqual(_ object: Any!) -> Bool {
+    if let other = object {
+      if let otherObjcKey = other as? TestObjCEquatableValueTy {
+        return self.value == otherObjcKey.value
+      }
+    }
+    return false
+  }
+
+  override var description: String {
+    assert(serial > 0, "dead TestObjCValueTy")
+    return value.description
+  }
+
+  var value: Int
+  var serial: Int
+}
+
+func == (lhs: TestObjCEquatableValueTy, rhs: TestObjCEquatableValueTy) -> Bool {
+  return lhs.value == rhs.value
+}
+
+var _bridgedValueSerial = _stdlib_AtomicInt(0)
+var _bridgedValueBridgeOperations = _stdlib_AtomicInt(0)
+
+struct TestBridgedValueTy : CustomStringConvertible, _ObjectiveCBridgeable {
+  static var bridgeOperations: Int {
+    get {
+      return _bridgedValueBridgeOperations.load()
+    }
+    set {
+      _bridgedValueBridgeOperations.store(newValue)
+    }
+  }
+
+  init(_ value: Int) {
+    serial = _bridgedValueSerial.fetchAndAdd(1)
+    self.value = value
+  }
+
+  var description: String {
+    assert(serial > 0, "dead TestBridgedValueTy")
+    return value.description
+  }
+
+  func _bridgeToObjectiveC() -> TestObjCValueTy {
+    TestBridgedValueTy.bridgeOperations += 1
+    return TestObjCValueTy(value)
+  }
+
+  static func _forceBridgeFromObjectiveC(
+    _ x: TestObjCValueTy,
+    result: inout TestBridgedValueTy?
+  ) {
+    TestBridgedValueTy.bridgeOperations += 1
+    result = TestBridgedValueTy(x.value)
+  }
+
+  static func _conditionallyBridgeFromObjectiveC(
+    _ x: TestObjCValueTy,
+    result: inout TestBridgedValueTy?
+  ) -> Bool {
+    self._forceBridgeFromObjectiveC(x, result: &result)
+    return true
+  }
+
+  static func _unconditionallyBridgeFromObjectiveC(_ source: TestObjCValueTy?)
+      -> TestBridgedValueTy {
+    var result: TestBridgedValueTy? = nil
+    _forceBridgeFromObjectiveC(source!, result: &result)
+    return result!
+  }
+
+  var value: Int
+  var serial: Int
+}
+
+var _bridgedEquatableValueSerial = _stdlib_AtomicInt(0)
+var _bridgedEquatableValueBridgeOperations = _stdlib_AtomicInt(0)
+
+struct TestBridgedEquatableValueTy
+  : Equatable, CustomStringConvertible, _ObjectiveCBridgeable {
+
+  static var bridgeOperations: Int {
+    get {
+      return _bridgedEquatableValueBridgeOperations.load()
+    }
+    set {
+      _bridgedEquatableValueBridgeOperations.store(newValue)
+    }
+  }
+
+  init(_ value: Int) {
+    serial = _bridgedEquatableValueSerial.addAndFetch(1)
+    self.value = value
+  }
+
+  var description: String {
+    assert(serial > 0, "dead TestBridgedValueTy")
+    return value.description
+  }
+
+  func _bridgeToObjectiveC() -> TestObjCEquatableValueTy {
+    _bridgedEquatableValueBridgeOperations.fetchAndAdd(1)
+    return TestObjCEquatableValueTy(value)
+  }
+
+  static func _forceBridgeFromObjectiveC(
+    _ x: TestObjCEquatableValueTy,
+    result: inout TestBridgedEquatableValueTy?
+  ) {
+    _bridgedEquatableValueBridgeOperations.fetchAndAdd(1)
+    result = TestBridgedEquatableValueTy(x.value)
+  }
+
+  static func _conditionallyBridgeFromObjectiveC(
+    _ x: TestObjCEquatableValueTy,
+    result: inout TestBridgedEquatableValueTy?
+  ) -> Bool {
+    self._forceBridgeFromObjectiveC(x, result: &result)
+    return true
+  }
+
+  static func _unconditionallyBridgeFromObjectiveC(
+    _ source: TestObjCEquatableValueTy?
+  ) -> TestBridgedEquatableValueTy {
+    var result: TestBridgedEquatableValueTy? = nil
+    _forceBridgeFromObjectiveC(source!, result: &result)
+    return result!
+  }
+
+  var value: Int
+  var serial: Int
+}
+
+func == (lhs: TestBridgedEquatableValueTy, rhs: TestBridgedEquatableValueTy) -> Bool {
+  return lhs.value == rhs.value
+}
+
+@objc
+class CustomImmutableNSArray : NSArray {
+  init(_privateInit: ()) {
+    super.init()
+  }
+    
+  override init() {
+    expectUnreachable()
+    super.init()
+  }
+  
+  override init(objects: UnsafePointer<AnyObject>!, count cnt: Int) {
+    expectUnreachable()
+    super.init(objects: objects, count: cnt)
+  }
+
+  required init?(coder aDecoder: NSCoder) {
+    fatalError("init(coder:) not implemented by CustomImmutableNSArray")
+  }
+
+  @objc(copyWithZone:)
+  override func copy(with zone: NSZone?) -> Any {
+    CustomImmutableNSArray.timesCopyWithZoneWasCalled += 1
+    return self
+  }
+
+  override func object(at index: Int) -> Any {
+    CustomImmutableNSArray.timesObjectAtIndexWasCalled += 1
+    return getAsNSArray([1010, 1020, 1030]).object(at: index)
+  }
+  
+  override func objectEnumerator() -> NSEnumerator {
+    CustomImmutableNSArray.timesObjectEnumeratorWasCalled += 1
+    return getAsNSArray([1010, 1020, 1030]).objectEnumerator()
+  }
+
+  override var count: Int {
+    CustomImmutableNSArray.timesCountWasCalled += 1
+    return 3
+  }
+
+  static var timesCopyWithZoneWasCalled = 0
+  static var timesObjectAtIndexWasCalled = 0
+  static var timesObjectEnumeratorWasCalled = 0
+  static var timesCountWasCalled = 0
+}
+
+#endif
diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
index c7992e0..7cb7f86 100644
--- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h
+++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
@@ -218,7 +218,7 @@
                                          StringRef RuntimeName,
                                          StringRef SelectorName,
                                          ArrayRef<StringRef> InheritedTypes,
-                                         ArrayRef<UIdent> Attrs) = 0;
+                                         ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) = 0;
 
   virtual bool endDocumentSubStructure() = 0;
 
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 67abda9..94d30e9 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -1237,7 +1237,27 @@
     SmallString<64> SelectorNameBuf;
     StringRef SelectorName = getObjCSelectorName(Node.Dcl, SelectorNameBuf);
 
-    std::vector<UIdent> Attrs = SwiftLangSupport::UIDsFromDeclAttributes(Node.Attrs);
+    std::vector<std::tuple<UIdent, unsigned, unsigned>> Attrs;
+
+    for (auto Attr : Node.Attrs) {
+      if (auto AttrUID = SwiftLangSupport::getUIDForDeclAttribute(Attr)) {
+        unsigned AttrOffset = 0;
+        unsigned AttrEnd = 0;
+        auto AttrRange = Attr->getRangeWithAt();
+        if (AttrRange.isValid()) {
+          auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SrcManager,
+                                                                    AttrRange);
+          AttrOffset = SrcManager.getLocOffsetInBuffer(CharRange.getStart(),
+                                                       BufferID);
+          AttrEnd = SrcManager.getLocOffsetInBuffer(CharRange.getEnd(),
+                                                    BufferID);
+        }
+
+        auto AttrTuple = std::make_tuple(AttrUID.getValue(), AttrOffset,
+                                         AttrEnd - AttrOffset);
+        Attrs.push_back(AttrTuple);
+      }
+    }
 
     Consumer.beginDocumentSubStructure(StartOffset, EndOffset - StartOffset,
                                        Kind, AccessLevel, SetterAccessLevel,
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
index 7c719b3..3e7ad81 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
@@ -591,53 +591,37 @@
   return swift::ide::NameKind::Swift;
 }
 
-std::vector<UIdent> SwiftLangSupport::UIDsFromDeclAttributes(const DeclAttributes &Attrs) {
-  std::vector<UIdent> AttrUIDs;
-
-#define ATTR(X) \
-  if (Attrs.has(AK_##X)) { \
-    static UIdent Attr_##X("source.decl.attribute."#X); \
-    AttrUIDs.push_back(Attr_##X); \
-  }
-#include "swift/AST/Attr.def"
-
-  for (auto Attr : Attrs) {
-    // Check special-case names first.
-    switch (Attr->getKind()) {
+Optional<UIdent> SwiftLangSupport::getUIDForDeclAttribute(const swift::DeclAttribute *Attr) {
+  // Check special-case names first.
+  switch (Attr->getKind()) {
     case DAK_IBAction: {
       static UIdent Attr_IBAction("source.decl.attribute.ibaction");
-      AttrUIDs.push_back(Attr_IBAction);
-      continue;
+      return Attr_IBAction;
     }
     case DAK_IBOutlet: {
       static UIdent Attr_IBOutlet("source.decl.attribute.iboutlet");
-      AttrUIDs.push_back(Attr_IBOutlet);
-      continue;
+      return Attr_IBOutlet;
     }
     case DAK_IBDesignable: {
       static UIdent Attr_IBDesignable("source.decl.attribute.ibdesignable");
-      AttrUIDs.push_back(Attr_IBDesignable);
-      continue;
+      return Attr_IBDesignable;
     }
     case DAK_IBInspectable: {
       static UIdent Attr_IBInspectable("source.decl.attribute.ibinspectable");
-      AttrUIDs.push_back(Attr_IBInspectable);
-      continue;
+      return Attr_IBInspectable;
     }
     case DAK_GKInspectable: {
       static UIdent Attr_GKInspectable("source.decl.attribute.gkinspectable");
-      AttrUIDs.push_back(Attr_GKInspectable);
-      continue;
+      return Attr_GKInspectable;
     }
     case DAK_ObjC: {
       static UIdent Attr_Objc("source.decl.attribute.objc");
       static UIdent Attr_ObjcNamed("source.decl.attribute.objc.name");
       if (cast<ObjCAttr>(Attr)->hasName()) {
-        AttrUIDs.push_back(Attr_ObjcNamed);
+        return Attr_ObjcNamed;
       } else {
-        AttrUIDs.push_back(Attr_Objc);
+        return Attr_Objc;
       }
-      continue;
     }
 
     // We handle access control explicitly.
@@ -647,21 +631,31 @@
     case DAK_ShowInInterface:
     case DAK_RawDocComment:
     case DAK_DowngradeExhaustivityCheck:
-      continue;
+      return None;
     default:
       break;
-    }
+  }
 
-    switch (Attr->getKind()) {
+  switch (Attr->getKind()) {
     case DAK_Count:
       break;
 #define DECL_ATTR(X, CLASS, ...)\
     case DAK_##CLASS: {\
       static UIdent Attr_##X("source.decl.attribute."#X); \
-      AttrUIDs.push_back(Attr_##X); \
-      break;\
+      return Attr_##X; \
     }
 #include "swift/AST/Attr.def"
+  }
+
+  return None;
+}
+
+std::vector<UIdent> SwiftLangSupport::UIDsFromDeclAttributes(const DeclAttributes &Attrs) {
+  std::vector<UIdent> AttrUIDs;
+
+  for (auto Attr : Attrs) {
+    if (auto AttrUID = getUIDForDeclAttribute(Attr)) {
+      AttrUIDs.push_back(AttrUID.getValue());
     }
   }
 
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
index 656af5d..4e837c1 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
@@ -305,6 +305,8 @@
 
   static SourceKit::UIdent getUIDForRefactoringRangeKind(swift::ide::RefactoringRangeKind Kind);
 
+  static Optional<UIdent> getUIDForDeclAttribute(const swift::DeclAttribute *Attr);
+
   static std::vector<UIdent> UIDsFromDeclAttributes(const swift::DeclAttributes &Attrs);
 
   static SourceKit::UIdent getUIDForNameKind(swift::ide::NameKind Kind);
diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
index 6c931c6..a4023ce 100644
--- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
+++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
@@ -38,7 +38,7 @@
                          llvm::StringRef RuntimeName,
                          llvm::StringRef SelectorName,
                          llvm::ArrayRef<llvm::StringRef> InheritedTypes,
-                         llvm::ArrayRef<SourceKit::UIdent> Attrs);
+                         llvm::ArrayRef<std::tuple<SourceKit::UIdent, unsigned, unsigned>> Attrs);
 
   void addElement(SourceKit::UIdent Kind, unsigned Offset, unsigned Length);
 
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
index 33d2deb..c03f0d8 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
@@ -58,7 +58,7 @@
 struct DocStructureArrayBuilder::Implementation {
   typedef CompactArrayBuilder<StringRef> InheritedTypesBuilder;
   SmallVector<char, 256> inheritedTypesBuffer;
-  typedef CompactArrayBuilder<UIdent> AttrsBuilder;
+  typedef CompactArrayBuilder<UIdent, unsigned, unsigned> AttrsBuilder;
   SmallVector<char, 256> attrsBuffer;
   typedef CompactArrayBuilder<UIdent, unsigned, unsigned> ElementsBuilder;
   SmallVector<char, 256> elementsBuffer;
@@ -91,7 +91,7 @@
   SmallVector<unsigned, 16> topIndices;
 
   unsigned addInheritedTypes(ArrayRef<StringRef> inheritedTypes);
-  unsigned addAttrs(ArrayRef<UIdent> attrs);
+  unsigned addAttrs(ArrayRef<std::tuple<UIdent, unsigned, unsigned>> attrs);
   unsigned addElements(ArrayRef<Node::Element> elements);
   unsigned addChildren(ArrayRef<unsigned> offsets);
 
@@ -122,13 +122,17 @@
 }
 
 unsigned
-DocStructureArrayBuilder::Implementation::addAttrs(ArrayRef<UIdent> attrs) {
+DocStructureArrayBuilder::Implementation::addAttrs(ArrayRef<std::tuple<UIdent, unsigned, unsigned>> attrs) {
   if (attrs.empty())
     return 0;
 
   AttrsBuilder builder;
-  for (UIdent uid : attrs)
-    builder.addEntry(uid);
+  for (auto attr : attrs) {
+    UIdent uid;
+    unsigned offset, length;
+    std::tie(uid, offset, length) = attr;
+    builder.addEntry(uid, offset, length);
+  }
 
   unsigned offset = attrsBuffer.size();
   builder.appendTo(attrsBuffer);
@@ -174,7 +178,8 @@
     unsigned BodyLength, unsigned DocOffset, unsigned DocLength,
     StringRef DisplayName, StringRef TypeName,
     StringRef RuntimeName, StringRef SelectorName,
-    ArrayRef<StringRef> InheritedTypes, ArrayRef<UIdent> Attrs) {
+    ArrayRef<StringRef> InheritedTypes,
+    ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) {
 
   Node node = {
       Offset,
@@ -437,7 +442,7 @@
 };
 
 struct AttributesReader {
-  typedef CompactArrayReader<sourcekitd_uid_t> CompactArrayReaderTy;
+  typedef CompactArrayReader<sourcekitd_uid_t, unsigned, unsigned> CompactArrayReaderTy;
 
   static bool
   dictionary_apply(void *buffer, size_t index,
@@ -446,8 +451,13 @@
 
     CompactArrayReaderTy reader(buffer);
     sourcekitd_uid_t value;
-    reader.readEntries(index, value);
+    unsigned offset;
+    unsigned length;
+    reader.readEntries(index, value, offset, length);
+
     APPLY(KeyAttribute, UID, value);
+    APPLY(KeyOffset, Int, offset);
+    APPLY(KeyLength, Int, length);
     return true;
   }
 };
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 875b962..f20d429 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -2000,7 +2000,7 @@
                                  StringRef RuntimeName,
                                  StringRef SelectorName,
                                  ArrayRef<StringRef> InheritedTypes,
-                                 ArrayRef<UIdent> Attrs) override;
+                                 ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) override;
 
   bool endDocumentSubStructure() override;
 
@@ -2227,7 +2227,7 @@
                                             StringRef RuntimeName,
                                             StringRef SelectorName,
                                             ArrayRef<StringRef> InheritedTypes,
-                                            ArrayRef<UIdent> Attrs) {
+                                            ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) {
   if (EnableStructure) {
     DocStructure.beginSubStructure(
         Offset, Length, Kind, AccessLevel, SetterAccessLevel, NameOffset,
diff --git a/tools/SourceKit/utils/buildbot-package-sourcekit.sh b/tools/SourceKit/utils/buildbot-package-sourcekit.sh
deleted file mode 100644
index 282ad6f..0000000
--- a/tools/SourceKit/utils/buildbot-package-sourcekit.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-
-# Make sure the variables and directories we expect to exist actually do.
-test "$WORKSPACE"
-test -d "$WORKSPACE/swift/build"
-test -d "$WORKSPACE/SourceKit/build"
-
-DATE_TAG=`date +%y%m%d%H%M`
-
-mkdir -p SourceKit && cd SourceKit
-mkdir -p bin && mkdir -p lib
-cp "$WORKSPACE/SourceKit/build/bin/sourcekitd-test" bin
-cp "$WORKSPACE/SourceKit/build/bin/sourcekitd-repl" bin
-cp "$WORKSPACE/SourceKit/build/lib/libsourcekitdInProc.dylib" lib
-ditto "$WORKSPACE/SourceKit/build/lib/sourcekitd.framework" lib/sourcekitd.framework
-cp -r "$WORKSPACE/swift/build/lib/swift" lib
-ditto "$WORKSPACE/llvm/build/lib/clang" lib/clang
-cp "$WORKSPACE/llvm/build/lib/libclang.dylib" lib
-install_name_tool -id @rpath/libclang.dylib lib/libclang.dylib
-cd ..
-tar -cvzf SourceKit-$DATE_TAG.tar.gz SourceKit
diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
index c947446..fac8a8d 100644
--- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
+++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
@@ -59,7 +59,7 @@
                                  StringRef RuntimeName,
                                  StringRef SelectorName,
                                  ArrayRef<StringRef> InheritedTypes,
-                                 ArrayRef<UIdent> Attrs) override {
+                                 ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) override {
     return false;
   }
 
diff --git a/unittests/SourceKit/SwiftLang/EditingTest.cpp b/unittests/SourceKit/SwiftLang/EditingTest.cpp
index 0ba2cb8..7eace92 100644
--- a/unittests/SourceKit/SwiftLang/EditingTest.cpp
+++ b/unittests/SourceKit/SwiftLang/EditingTest.cpp
@@ -64,7 +64,7 @@
                                  StringRef RuntimeName,
                                  StringRef SelectorName,
                                  ArrayRef<StringRef> InheritedTypes,
-                                 ArrayRef<UIdent> Attrs) override {
+                                 ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) override {
     return false;
   }
 
diff --git a/utils/process-stats-dir.py b/utils/process-stats-dir.py
index c9a3425..ac24e0e 100755
--- a/utils/process-stats-dir.py
+++ b/utils/process-stats-dir.py
@@ -20,6 +20,7 @@
 import json
 import os
 import platform
+import re
 import sys
 import time
 import urllib
@@ -154,15 +155,19 @@
     return (epoch, value, changed)
 
 
-def read_stats_dict_from_csv(f):
+def read_stats_dict_from_csv(f, select_stat=''):
     infieldnames = ["epoch", "name", "value"]
     c = csv.DictReader(f, infieldnames,
                        dialect='excel-tab',
                        quoting=csv.QUOTE_NONNUMERIC)
     d = {}
+    sre = re.compile('.*' if len(select_stat) == 0 else
+                     '|'.join(select_stat))
     for row in c:
         epoch = int(row["epoch"])
         name = row["name"]
+        if sre.search(name) is None:
+            continue
         value = int(row["value"])
         update_epoch_value(d, name, epoch, value)
     return d
@@ -189,7 +194,8 @@
     existing = None
     if os.path.exists(args.set_csv_baseline):
         with open(args.set_csv_baseline, "r") as f:
-            existing = read_stats_dict_from_csv(f)
+            existing = read_stats_dict_from_csv(f,
+                                                select_stat=args.select_stat)
             print ("updating %d baseline entries in %s" %
                    (len(existing), args.set_csv_baseline))
     else:
@@ -273,7 +279,8 @@
 
 
 def compare_to_csv_baseline(args):
-    old_stats = read_stats_dict_from_csv(args.compare_to_csv_baseline)
+    old_stats = read_stats_dict_from_csv(args.compare_to_csv_baseline,
+                                         select_stat=args.select_stat)
     m = merge_all_jobstats((s for d in args.remainder
                             for s in load_stats_dir(d, **vars(args))),
                            **vars(args))
@@ -344,7 +351,7 @@
     parser.add_argument("--sort-by-delta-pct",
                         default=False,
                         action="store_true",
-                        help="Sort comparison results by delta-%, not stat")
+                        help="Sort comparison results by delta-%%, not stat")
     parser.add_argument("--sort-descending",
                         default=False,
                         action="store_true",
diff --git a/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift b/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift
new file mode 100644
index 0000000..3447451
--- /dev/null
+++ b/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift
@@ -0,0 +1,195 @@
+// --- sourcekit_fuzzer.swift - a simple code completion fuzzer ---------------
+//
+// 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
+//
+// ----------------------------------------------------------------------------
+//
+// The idea here is we start with a source file and proceed to place the cursor
+// at random locations in the file, eventually visiting all locations exactly
+// once in a shuffled random order.
+//
+// If completion at a location crashes, we run the test case through 'creduce'
+// to find a minimal reproducer that also crashes (possibly with a different
+// crash, but in practice all the examples I've seen continue to crash in the
+// same way as creduce performs its reduction).
+//
+// Once creduce fully reduces a test case, we save it to a file named
+// 'crash-NNN.swift', with a RUN: line suitable for placing the test case in
+// 'validation-tests/IDE/crashers_2'.
+//
+// The overall script execution stops once all source locations in the file
+// have been tested.
+//
+// You must first install creduce <https://embed.cs.utah.edu/creduce/>
+// somewhere in your $PATH. Then, run this script as follows:
+//
+// swift utils/sourcekit_fuzzer/sourcekit_fuzzer.swift <build dir> <source file>
+//
+// - <build dir> is your Swift build directory (the one with subdirectories
+//   named swift-macosx-x86_64 and llvm-macosx-x86_64).
+//
+// - <source file> is the source file to fuzz. Try any complex but
+//   self-contained Swift file that exercises a variety of language features;
+//   for example, I've had good results with the files in test/Prototypes/.
+//
+// TODO:
+// - Add fuzzing for CursorInfo and RangeInfo
+// - Get it running on Linux
+// - Better error handling
+// - More user-friendly output
+
+import Darwin
+import Foundation
+
+// https://stackoverflow.com/questions/24026510/how-do-i-shuffle-an-array-in-swift/24029847
+extension MutableCollection {
+  /// Shuffles the contents of this collection.
+  mutating func shuffle() {
+    let c = count
+    guard c > 1 else { return }
+
+    for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
+      let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
+      guard d != 0 else { continue }
+      let i = index(firstUnshuffled, offsetBy: d)
+      swapAt(firstUnshuffled, i)
+    }
+  }
+}
+
+extension String {
+  func write(to path: String) throws {
+    try write(to: URL(fileURLWithPath: path), atomically: true, encoding: String.Encoding.utf8)
+  }
+}
+
+// Gross
+enum ProcessError : Error {
+  case failed
+}
+
+func run(_ args: [String]) throws -> Int32 {
+  var pid: pid_t = 0
+
+  let argv = args.map {
+    $0.withCString(strdup)
+  }
+  defer { argv.forEach { free($0) } }
+
+  let envp = ProcessInfo.processInfo.environment.map {
+    "\($0.0)=\($0.1)".withCString(strdup)
+  }
+  defer { envp.forEach { free($0) } }
+
+  let result = posix_spawn(&pid, argv[0], nil, nil, argv + [nil], envp + [nil])
+  if result != 0 { throw ProcessError.failed }
+
+  var stat: Int32 = 0
+  waitpid(pid, &stat, 0)
+
+  return stat
+}
+
+var arguments = CommandLine.arguments
+
+// Workaround for behavior of CommandLine in script mode, where we don't drop
+// the filename argument from the list.
+if arguments.first == "sourcekit_fuzzer.swift" {
+  arguments = Array(arguments[1...])
+}
+
+if arguments.count != 2 {
+  print("Usage: sourcekit_fuzzer <build directory> <file>")
+  exit(1)
+}
+
+let buildDir = arguments[0]
+
+let notPath = "\(buildDir)/llvm-macosx-x86_64/bin/not"
+let swiftIdeTestPath = "\(buildDir)/swift-macosx-x86_64/bin/swift-ide-test"
+let creducePath = "/usr/local/bin/creduce"
+
+let file = arguments[1]
+
+let contents = try! String(contentsOfFile: file)
+
+var offsets = Array(0...contents.count)
+offsets.shuffle()
+
+var good = 0
+var bad = 0
+
+for offset in offsets {
+  print("TOTAL FAILURES: \(bad) out of \(bad + good)")
+
+  let index = contents.index(contents.startIndex, offsetBy: offset)
+  let prefix = contents[..<index]
+  let suffix = contents[index...]
+  let newContents = String(prefix + "#^A^#" + suffix)
+
+  let sourcePath = "out\(offset).swift"
+  try! newContents.write(to: sourcePath)
+
+  let shellScriptPath = "out\(offset).sh"
+  let shellScript = """
+  #!/bin/sh
+  \(notPath) --crash \(swiftIdeTestPath) -code-completion -code-completion-token=A -source-filename=\(sourcePath)
+  """
+  try! shellScript.write(to: shellScriptPath)
+
+  defer {
+    unlink(shellScriptPath)
+    unlink(sourcePath)
+  }
+
+  do {
+    let result = chmod(shellScriptPath, 0o700)
+    if result != 0 {
+      print("chmod failed")
+      exit(1)
+    }
+  }
+
+  do {
+    let result = try! run(["./\(shellScriptPath)"])
+    if result != 0 {
+      good += 1
+      continue
+    }
+  }
+
+  do {
+    // Because we invert the exit code with 'not', an exit code for 0 actually
+    // indicates failure
+    print("Failed at offset \(offset)")
+    print("Reducing...")
+
+    let result = try! run([creducePath, shellScriptPath, sourcePath])
+    if result != 0 {
+      print("creduce failed")
+      exit(1)
+    }
+
+    bad += 1
+  }
+
+  do {
+    let reduction = try! String(contentsOfFile: sourcePath)
+
+    let testcasePath = "crash-\(bad).swift"
+    let testcase = """
+    // RUN: \(notPath) --crash \(swiftIdeTestPath) -code-completion -code-completion-token=A -source-filename=%s
+    // REQUIRES: asserts
+
+    \(reduction)
+    """
+
+    try! testcase.write(to: testcasePath)
+  }
+}
diff --git a/utils/type-layout-fuzzer.py b/utils/type-layout-fuzzer.py
new file mode 100644
index 0000000..bb3d8c3
--- /dev/null
+++ b/utils/type-layout-fuzzer.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+
+# This script outputs a Swift source with randomly-generated type definitions,
+# which can be used for ABI or layout algorithm fuzzing.
+
+# TODO: generate types with generics, existentials, compositions
+
+from __future__ import print_function
+
+import random
+import sys
+
+maxDepth = 5
+maxMembers = 5
+typesDefined = []
+classesDefined = []
+nextToDefine = 0
+objcInterop = False
+
+if len(sys.argv) >= 2:
+    if sys.argv[1] == "--objc":
+        objcInterop = True
+    if sys.argv[1] == "--help":
+        print("Usage: " + sys.argv[0] + " [--objc]", file=sys.stderr)
+        print("", file=sys.stderr)
+        print("  --objc          Include ObjC-interop types", file=sys.stderr)
+        sys.exit(2)
+
+random.seed()
+if objcInterop:
+    print("import Foundation")
+    print()
+
+
+def randomTypeList(depth):
+    count = random.randint(0, maxMembers)
+    result = "("
+    for i in xrange(count):
+        if i > 0:
+            result += ", "
+        result += randomTypeReference(depth + 1)
+    result += ")"
+    return result
+
+
+def randomTypeReference(depth):
+    def nominal():
+        global typesDefined
+        allowNew = depth < maxDepth
+        bound = len(classesDefined) if allowNew else len(classesDefined) - 1
+        which = random.randint(0, bound)
+        if which < len(classesDefined):
+            return classesDefined[which]
+        newName = "T" + str(len(typesDefined))
+
+        def defineRandomRelatedType(name):
+            defineRandomNominalType(name, depth)
+
+        typesDefined.append((newName, defineRandomRelatedType))
+        return newName
+
+    def tuple():
+        return randomTypeList(depth + 1)
+
+    def metatype():
+        return "(" + randomTypeReference(depth + 1) + ").Type"
+
+    def leaf():
+        leaves = ["Int", "String", "Int8", "Int16", "Int32", "Int64",
+                  "(() -> ())", "(@convention(c) () -> ())", "AnyObject"]
+        if objcInterop:
+            leaves += ["NSObject", "(@convention(block) () -> ())"]
+        return random.choice(leaves)
+
+    if depth < maxDepth:
+        kinds = [nominal, tuple, metatype, leaf, leaf, leaf, leaf, leaf]
+    else:
+        kinds = [leaf]
+    return random.choice(kinds)()
+
+
+def defineRandomFields(depth, basename):
+    numMembers = random.randint(0, maxMembers)
+    for i in xrange(numMembers):
+        print("  var " + basename + str(i) + ": " +
+              randomTypeReference(depth + 1))
+
+
+def defineRandomClass(name, depth):
+    global classesDefined
+    classesDefined.append(name)
+    print("class " + name, end="")
+
+    def inheritNSObject():
+        print(": NSObject", end="")
+
+    def inheritsOtherClass():
+        print(": ", end="")
+        name = "T" + str(len(typesDefined))
+
+        def defineRandomBaseClass(name):
+            defineRandomClass(name, depth)
+
+        typesDefined.append((name, defineRandomBaseClass))
+        print(name, end="")
+
+    def inheritsNothing():
+        pass
+
+    inheritances = [inheritsNothing]
+    if depth == 0:
+        # The contents of classes are interesting only for top-level type
+        inheritances += [inheritsOtherClass]
+
+    if objcInterop:
+        inheritances += [inheritNSObject]
+    random.choice(inheritances)()
+
+    print(" {")
+    # Prevent errors about lack of initializers
+    print("  init(" + name + ": ()) { fatalError() }")
+    # The contents of classes are interesting only for top-level type
+    if depth == 0:
+        defineRandomFields(depth, "x" + name)
+    print("}")
+    print()
+
+
+def defineRandomNominalType(name, depth=0):
+    def struct():
+        print("struct " + name + " {")
+        defineRandomFields(depth, "x")
+        print("}")
+        print()
+
+    def clas():
+        defineRandomClass(name, depth)
+
+    def enum():
+        # TODO: indirect cases
+        print("enum " + name + " {")
+
+        numCases = random.randint(0, maxMembers)
+        for i in xrange(numCases):
+            print("  case x" + str(i) + randomTypeList(depth + 1))
+
+        print("}")
+        print()
+
+    kinds = [struct, clas, enum]
+    return random.choice(kinds)()
+
+
+typesDefined.append(("Generated", defineRandomNominalType))
+
+while nextToDefine < len(typesDefined):
+    name, definer = typesDefined[nextToDefine]
+    definer(name)
+    nextToDefine += 1
diff --git a/validation-test/IDE/crashers_2/0002-complete-unbound-generic-type.swift b/validation-test/IDE/crashers_2/0002-complete-unbound-generic-type.swift
deleted file mode 100644
index 392dc02..0000000
--- a/validation-test/IDE/crashers_2/0002-complete-unbound-generic-type.swift
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
-// REQUIRES: asserts
-
-let bounds: Range#^A^#
diff --git a/validation-test/IDE/crashers_2/0003-complete-default-argument-closure.swift b/validation-test/IDE/crashers_2/0003-complete-default-argument-closure.swift
deleted file mode 100644
index 0492b75..0000000
--- a/validation-test/IDE/crashers_2/0003-complete-default-argument-closure.swift
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
-// REQUIRES: asserts
-
-func searchTest(format: ()->String = { "" }#^A^#) {}
diff --git a/validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift b/validation-test/IDE/crashers_2/0015-pound-if-without-endif.swift
similarity index 90%
rename from validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift
rename to validation-test/IDE/crashers_2/0015-pound-if-without-endif.swift
index 15d2940..941f317 100644
--- a/validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift
+++ b/validation-test/IDE/crashers_2/0015-pound-if-without-endif.swift
@@ -1,4 +1,5 @@
 // RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
 // REQUIRES: asserts
 
-Integer#^A^#
+#if a
+#^A^#
diff --git a/validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift b/validation-test/IDE/crashers_2/0016-operator-unresolved-dot.swift
similarity index 73%
copy from validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift
copy to validation-test/IDE/crashers_2/0016-operator-unresolved-dot.swift
index 15d2940..aaadffe 100644
--- a/validation-test/IDE/crashers_2/0011-complete-protocol-with-initializer.swift
+++ b/validation-test/IDE/crashers_2/0016-operator-unresolved-dot.swift
@@ -1,4 +1,4 @@
 // RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
 // REQUIRES: asserts
 
-Integer#^A^#
+struct a { func b(c d: a) { b(c: d) == .#^A^#
diff --git a/validation-test/IDE/crashers_2_fixed/0002-complete-unbound-generic-type.swift b/validation-test/IDE/crashers_2_fixed/0002-complete-unbound-generic-type.swift
new file mode 100644
index 0000000..48bdf3a
--- /dev/null
+++ b/validation-test/IDE/crashers_2_fixed/0002-complete-unbound-generic-type.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+
+let bounds: Range#^A^#
diff --git a/validation-test/IDE/crashers_2_fixed/0003-complete-default-argument-closure.swift b/validation-test/IDE/crashers_2_fixed/0003-complete-default-argument-closure.swift
new file mode 100644
index 0000000..7438f2c
--- /dev/null
+++ b/validation-test/IDE/crashers_2_fixed/0003-complete-default-argument-closure.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+
+func searchTest(format: ()->String = { "" }#^A^#) {}
diff --git a/validation-test/IDE/crashers_2_fixed/0011-complete-protocol-with-initializer.swift b/validation-test/IDE/crashers_2_fixed/0011-complete-protocol-with-initializer.swift
new file mode 100644
index 0000000..02f1aeb
--- /dev/null
+++ b/validation-test/IDE/crashers_2_fixed/0011-complete-protocol-with-initializer.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+
+Integer#^A^#
diff --git a/validation-test/compiler_crashers/28837-swift-protocolcompositiontype-get-swift-astcontext-const-llvm-arrayref-swift-typ.swift b/validation-test/compiler_crashers/28837-swift-protocolcompositiontype-get-swift-astcontext-const-llvm-arrayref-swift-typ.swift
new file mode 100644
index 0000000..bc45c00
--- /dev/null
+++ b/validation-test/compiler_crashers/28837-swift-protocolcompositiontype-get-swift-astcontext-const-llvm-arrayref-swift-typ.swift
@@ -0,0 +1,10 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol b:Self.a&(Int
+protocol b{}
diff --git a/validation-test/compiler_crashers/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
new file mode 100644
index 0000000..93668fb
--- /dev/null
+++ b/validation-test/compiler_crashers/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -0,0 +1,12 @@
+// 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
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol P{typealias e:A
+protocol A:P{}typealias a
+class a<a
diff --git a/validation-test/compiler_crashers/28839-genericsig.swift b/validation-test/compiler_crashers/28839-genericsig.swift
new file mode 100644
index 0000000..0e6d692
--- /dev/null
+++ b/validation-test/compiler_crashers/28839-genericsig.swift
@@ -0,0 +1,12 @@
+// 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
+
+// REQUIRES: asserts
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+class a{
+class a<a:A
+protocol A:a{typealias wh:Self.a
diff --git a/validation-test/compiler_crashers/28840-swift-typebase-getcanonicaltype.swift b/validation-test/compiler_crashers/28840-swift-typebase-getcanonicaltype.swift
new file mode 100644
index 0000000..0222a22
--- /dev/null
+++ b/validation-test/compiler_crashers/28840-swift-typebase-getcanonicaltype.swift
@@ -0,0 +1,9 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol P{{}typealias a=(t:Self.a{}typealias a:a
diff --git a/validation-test/stdlib/Arrays.swift.gyb b/validation-test/stdlib/Arrays.swift.gyb
index fd7c6ad..38c3e5a 100644
--- a/validation-test/stdlib/Arrays.swift.gyb
+++ b/validation-test/stdlib/Arrays.swift.gyb
@@ -1,9 +1,25 @@
-// RUN: %target-run-simple-swiftgyb
+// RUN: %empty-directory(%t)
+//
+// RUN: %gyb %s -o %t/main.swift
+// RUN: if [ %target-runtime == "objc" ]; then \
+// RUN:   %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o; \
+// RUN:   %line-directive %t/main.swift -- %target-build-swift %t/main.swift %S/Inputs/ArrayTypesAndHelpers.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Arrays -Xfrontend -disable-access-control; \
+// RUN: else \
+// RUN:   %line-directive %t/main.swift -- %target-build-swift %S/Inputs/ArrayTypesAndHelpers.swift %t/main.swift -o %t/Arrays -Xfrontend -disable-access-control; \
+// RUN: fi
+//
+// RUN: %line-directive %t/main.swift -- %target-run %t/Arrays
 // REQUIRES: executable_test
 
+import Swift
 import StdlibUnittest
 import StdlibCollectionUnittest
 
+#if _runtime(_ObjC)
+import Foundation
+import StdlibUnittestFoundationExtras
+#endif
+
 let CopyToNativeArrayBufferTests = TestSuite("CopyToNativeArrayBufferTests")
 
 extension Array {
@@ -97,6 +113,1381 @@
   }
 }
 
+ArrayTestSuite.test("capacity/reserveCapacity(_:)") {
+  var a1 = [1010, 1020, 1030]
+  expectGE(a1.capacity, 3)
+  a1.append(1040)
+  expectGT(a1.capacity, 3)
+
+  // Reserving new capacity jumps up to next limit.
+  a1.reserveCapacity(7)
+  expectGE(a1.capacity, 7)
+
+  // Can reserve right up to a limit.
+  a1.reserveCapacity(24)
+  expectGE(a1.capacity, 24)
+
+  // Fill up to the limit, no reallocation.
+  for v in stride(from: 50, through: 240, by: 10).lazy.map({ 1000 + $0 }) {
+    a1.append(v)
+  }
+  expectEqual(24, a1.count)
+  expectGE(a1.capacity, 24)
+  a1.append(1250)
+  expectGT(a1.capacity, 24)
+}
+
+ArrayTestSuite.test("init(arrayLiteral:)") {
+  do {
+    let empty = Array<Int>()
+    expectEqual(0, empty.count)
+  }
+  do {
+    let a = Array(arrayLiteral: 1010)
+    expectEqual(1, a.count)
+    expectEqual(1010, a[0])
+  }
+  do {
+    let a = Array(arrayLiteral: 1010, 1020)
+    expectEqual(2, a.count)
+    expectEqual(1010, a[0])
+    expectEqual(1020, a[1])
+  }
+  do {
+    let a = Array(arrayLiteral: 1010, 1020, 1030)
+    expectEqual(3, a.count)
+    expectEqual(1010, a[0])
+    expectEqual(1020, a[1])
+    expectEqual(1030, a[2])
+  }
+  do {
+    let a = Array(arrayLiteral: 1010, 1020, 1030, 1040)
+    expectEqual(4, a.count)
+    expectEqual(1010, a[0])
+    expectEqual(1020, a[1])
+    expectEqual(1030, a[2])
+    expectEqual(1040, a[3])
+  }
+  do {
+    let a: Array<Int> = [ 1010, 1020, 1030 ]
+    expectEqual(3, a.count)
+    expectEqual(1010, a[0])
+    expectEqual(1020, a[1])
+    expectEqual(1030, a[2])
+  }
+}
+
+ArrayTestSuite.test("init(repeating:count:)") {
+  do {
+    let a = Array(repeating: 1010, count: 5)
+    expectEqual(a.count, 5)
+    expectEqual(1010, a[0])
+    expectEqual(1010, a[1])
+    expectEqual(1010, a[2])
+    expectEqual(1010, a[3])
+    expectEqual(1010, a[4])
+  }
+}
+
+#if _runtime(_ObjC)
+//===----------------------------------------------------------------------===//
+// NSArray -> Array bridging tests.
+//===----------------------------------------------------------------------===//
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.ArrayIsCopied") {
+  var (a, nsa) = getBridgedVerbatimArrayAndNSMutableArray()
+  expectTrue(isCocoaArray(a))
+
+  // Find an existing value.
+  do {
+    let v = a[0] as! TestObjCValueTy
+    expectEqual(1010, v.value)
+  }
+
+  // Remove the value from the NSMutableArray.
+  nsa.removeObject(at: 0)
+
+  // Find an existing value, again.
+  do {
+    let v = a[0] as! TestObjCValueTy
+    expectEqual(1010, v.value)
+  }
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.ArrayIsCopied") {
+  var (a, nsa) = getBridgedNonverbatimArrayAndNSMutableArray()
+  expectTrue(isNativeArray(a))
+
+  // Find an existing value.
+  do {
+    let v = a[0]
+    expectEqual(1010, v.value)
+  }
+
+  // Remove the value from the NSMutableArray.
+  nsa.removeObject(at: 0)
+
+  // Find an existing value, again.
+  do {
+    let v = a[0]
+    expectEqual(1010, v.value)
+  }
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.NSArrayIsRetained") {
+  let nsa: NSArray = autoreleasepool {
+    NSArray(array: getAsNSArray([1010, 1020, 1030]))
+  }
+  
+  let a: [AnyObject] = convertNSArrayToArray(nsa)
+  
+  let bridgedBack: NSArray = convertArrayToNSArray(a)
+  
+  expectEqual(
+    unsafeBitCast(nsa, to: Int.self),
+    unsafeBitCast(bridgedBack, to: Int.self))
+  
+  _blackHole(nsa)
+  _blackHole(a)
+  _blackHole(bridgedBack)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.NSArrayIsCopied") {
+  let nsa: NSArray = autoreleasepool {
+    NSArray(array: getAsNSArray([1010, 1020, 1030]))
+  }
+  
+  let a: [TestBridgedValueTy] = convertNSArrayToArray(nsa)
+  
+  let bridgedBack: NSArray = convertArrayToNSArray(a)
+  
+  expectNotEqual(
+    unsafeBitCast(nsa, to: Int.self),
+    unsafeBitCast(bridgedBack, to: Int.self))
+  
+  _blackHole(nsa)
+  _blackHole(a)
+  _blackHole(bridgedBack)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.ImmutableArrayIsRetained") {
+  let nsa: NSArray = CustomImmutableNSArray(_privateInit: ())
+  
+  CustomImmutableNSArray.timesCopyWithZoneWasCalled = 0
+  CustomImmutableNSArray.timesObjectAtIndexWasCalled = 0
+  CustomImmutableNSArray.timesObjectEnumeratorWasCalled = 0
+  CustomImmutableNSArray.timesCountWasCalled = 0
+  let a: [AnyObject] = convertNSArrayToArray(nsa)
+  expectEqual(1, CustomImmutableNSArray.timesCopyWithZoneWasCalled)
+  expectEqual(0, CustomImmutableNSArray.timesObjectAtIndexWasCalled)
+  expectEqual(0, CustomImmutableNSArray.timesObjectEnumeratorWasCalled)
+  expectEqual(0, CustomImmutableNSArray.timesCountWasCalled)
+  
+  let bridgedBack: NSArray = convertArrayToNSArray(a)
+  expectEqual(
+    unsafeBitCast(nsa, to: Int.self),
+    unsafeBitCast(bridgedBack, to: Int.self))
+  
+  _blackHole(nsa)
+  _blackHole(a)
+  _blackHole(bridgedBack)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.ImmutableArrayIsCopied") {
+  let nsa: NSArray = CustomImmutableNSArray(_privateInit: ())
+
+  CustomImmutableNSArray.timesCopyWithZoneWasCalled = 0
+  CustomImmutableNSArray.timesObjectAtIndexWasCalled = 0
+  CustomImmutableNSArray.timesObjectEnumeratorWasCalled = 0
+  CustomImmutableNSArray.timesCountWasCalled = 0
+  TestBridgedValueTy.bridgeOperations = 0
+  let a: [TestBridgedValueTy] = convertNSArrayToArray(nsa)
+  //FIXME: Why is this copied?
+  expectEqual(1, CustomImmutableNSArray.timesCopyWithZoneWasCalled)
+  expectEqual(3, CustomImmutableNSArray.timesObjectAtIndexWasCalled)
+  expectNotEqual(0, CustomImmutableNSArray.timesCountWasCalled)
+  expectEqual(3, TestBridgedValueTy.bridgeOperations)
+
+  let bridgedBack: NSArray = convertArrayToNSArray(a)
+  expectNotEqual(
+    unsafeBitCast(nsa, to: Int.self),
+    unsafeBitCast(bridgedBack, to: Int.self))
+
+  _blackHole(nsa)
+  _blackHole(a)
+  _blackHole(bridgedBack)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Subscript") {
+  let a = getBridgedVerbatimArray()
+  let identity1 = a._rawIdentifier()
+  expectTrue(isCocoaArray(a))
+
+  // Find an existing value.
+  do {
+    var v = a[0]
+    expectEqual(1010, (v as! TestObjCValueTy).value)
+
+    v = a[1]
+    expectEqual(1020, (v as! TestObjCValueTy).value)
+
+    v = a[2]
+    expectEqual(1030, (v as! TestObjCValueTy).value)
+  }
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Subscript") {
+  var a = getBridgedNonverbatimArray()
+  let identity1 = a._rawIdentifier()
+  expectTrue(isNativeArray(a))
+
+  // Find an existing value.
+  do {
+    var v = a[0]
+    expectEqual(1010, v.value)
+
+    v = a[1]
+    expectEqual(1020, v.value)
+
+    v = a[2]
+    expectEqual(1030, v.value)
+  }
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.RemoveAt") {
+  var a = getBridgedVerbatimArray()
+  let identity = a._rawIdentifier()
+  expectTrue(isCocoaArray(a))
+
+  let index = 0
+  expectEqual(1010, (a[index] as! TestObjCValueTy).value)
+  expectEqual(identity, a._rawIdentifier())
+
+  let removedElement = a.remove(at: index)
+  expectNotEqual(identity, a._rawIdentifier())
+  expectTrue(isNativeArray(a))
+  expectEqual(1010, (removedElement as! TestObjCValueTy).value)
+  expectEqual(2, a.count)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveAt") {
+  var a = getBridgedNonverbatimArray()
+  let identity = a._rawIdentifier()
+  expectTrue(isNativeArray(a))
+
+  let index = 0
+  expectEqual(1010, a[index].value)
+  expectEqual(identity, a._rawIdentifier())
+
+  let removedElement = a.remove(at: index)
+  expectEqual(identity, a._rawIdentifier())
+  expectTrue(isNativeArray(a))
+  expectEqual(1010, removedElement.value)
+  expectEqual(2, a.count)
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.RemoveAll") {
+  do {
+    var a = getBridgedVerbatimArray()
+    let identity1 = a._rawIdentifier()
+    expectTrue(isCocoaArray(a))
+    let originalCapacity = a.count
+    expectEqual(3, a.count)
+    expectEqual(1010, (a[0] as! TestObjCValueTy).value)
+
+    a.removeAll()
+    expectNotEqual(identity1, a._rawIdentifier())
+    expectLT(a._buffer.capacity, originalCapacity)
+    expectEqual(0, a.count)
+  }
+
+  do {
+    var a = getBridgedVerbatimArray()
+    let identity1 = a._rawIdentifier()
+    expectTrue(isCocoaArray(a))
+    let originalCapacity = a.count
+    expectEqual(3, a.count)
+    expectEqual(1010, (a[0] as! TestObjCValueTy).value)
+
+    a.removeAll(keepingCapacity: true)
+    expectNotEqual(identity1, a._rawIdentifier())
+    expectGE(a._buffer.capacity, originalCapacity)
+    expectEqual(0, a.count)
+  }
+
+  do {
+    var a1 = getBridgedVerbatimArray()
+    let identity1 = a1._rawIdentifier()
+    expectTrue(isCocoaArray(a1))
+    let originalCapacity = a1.count
+    expectEqual(3, a1.count)
+    expectEqual(1010, (a1[0] as! TestObjCValueTy).value)
+
+    var a2 = a1
+    a2.removeAll()
+    let identity2 = a2._rawIdentifier()
+    expectEqual(identity1, a1._rawIdentifier())
+    expectNotEqual(identity2, identity1)
+    expectEqual(3, a1.count)
+    expectEqual(1010, (a1[0] as! TestObjCValueTy).value)
+    expectLT(a2._buffer.capacity, originalCapacity)
+    expectEqual(0, a2.count)
+  }
+
+  do {
+    var a1 = getBridgedVerbatimArray()
+    let identity1 = a1._rawIdentifier()
+    expectTrue(isCocoaArray(a1))
+    let originalCapacity = a1.count
+    expectEqual(3, a1.count)
+    expectEqual(1010, (a1[0] as! TestObjCValueTy).value)
+
+    var a2 = a1
+    a2.removeAll(keepingCapacity: true)
+    let identity2 = a2._rawIdentifier()
+    expectEqual(identity1, a1._rawIdentifier())
+    expectNotEqual(identity2, identity1)
+    expectEqual(3, a1.count)
+    expectEqual(1010, (a1[0] as! TestObjCValueTy).value)
+    expectGE(a2._buffer.capacity, originalCapacity)
+    expectEqual(0, a2.count)
+  }
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.RemoveAll") {
+  do {
+    var a = getBridgedNonverbatimArray()
+    let identity1 = a._rawIdentifier()
+    expectTrue(isNativeArray(a))
+    let originalCapacity = a.count
+    expectEqual(3, a.count)
+    expectEqual(1010, a[0].value)
+
+    a.removeAll()
+    expectNotEqual(identity1, a._rawIdentifier())
+    expectLT(a._buffer.capacity, originalCapacity)
+    expectEqual(0, a.count)
+  }
+
+  do {
+    var a = getBridgedNonverbatimArray()
+    let identity1 = a._rawIdentifier()
+    expectTrue(isNativeArray(a))
+    let originalCapacity = a.count
+    expectEqual(3, a.count)
+    expectEqual(1010, a[0].value)
+
+    a.removeAll(keepingCapacity: true)
+    expectEqual(identity1, a._rawIdentifier())
+    expectGE(a._buffer.capacity, originalCapacity)
+    expectEqual(0, a.count)
+  }
+
+  do {
+    var a1 = getBridgedNonverbatimArray()
+    let identity1 = a1._rawIdentifier()
+    expectTrue(isNativeArray(a1))
+    let originalCapacity = a1.count
+    expectEqual(3, a1.count)
+    expectEqual(1010, a1[0].value)
+
+    var a2 = a1
+    a2.removeAll()
+    let identity2 = a2._rawIdentifier()
+    expectEqual(identity1, a1._rawIdentifier())
+    expectNotEqual(identity2, identity1)
+    expectEqual(3, a1.count)
+    expectEqual(1010, a1[0].value)
+    expectLT(a2._buffer.capacity, originalCapacity)
+    expectEqual(0, a2.count)
+  }
+
+  do {
+    var a1 = getBridgedNonverbatimArray()
+    let identity1 = a1._rawIdentifier()
+    expectTrue(isNativeArray(a1))
+    let originalCapacity = a1.count
+    expectEqual(3, a1.count)
+    expectEqual(1010, a1[0].value)
+
+    var a2 = a1
+    a2.removeAll(keepingCapacity: true)
+    let identity2 = a2._rawIdentifier()
+    expectEqual(identity1, a1._rawIdentifier())
+    expectNotEqual(identity2, identity1)
+    expectEqual(3, a1.count)
+    expectEqual(1010, a1[0].value)
+    expectGE(a2._buffer.capacity, originalCapacity)
+    expectEqual(0, a2.count)
+  }
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Count") {
+  let a = getBridgedVerbatimArray()
+  let identity1 = a._rawIdentifier()
+  expectTrue(isCocoaArray(a))
+
+  expectEqual(3, a.count)
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Count") {
+  let a = getBridgedNonverbatimArray()
+  let identity1 = a._rawIdentifier()
+  expectTrue(isNativeArray(a))
+
+  expectEqual(3, a.count)
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Generate") {
+  let a = getBridgedVerbatimArray()
+  let identity1 = a._rawIdentifier()
+  expectTrue(isCocoaArray(a))
+
+  var iter = a.makeIterator()
+  var values = Array<Int>()
+  while let value = iter.next() {
+    values.append((value as! TestObjCValueTy).value)
+  }
+  expectEqual(values, [1010, 1020, 1030])
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Generate") {
+  let a = getBridgedNonverbatimArray()
+  let identity1 = a._rawIdentifier()
+  expectTrue(isNativeArray(a))
+
+  var iter = a.makeIterator()
+  var values = Array<Int>()
+  while let value = iter.next() {
+    values.append(value.value)
+  }
+  expectEqual(values, [1010, 1020, 1030])
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Generate_Empty") {
+  let a = getBridgedVerbatimArray([])
+  let identity1 = a._rawIdentifier()
+  expectTrue(isCocoaArray(a))
+
+  var iter = a.makeIterator()
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Generate_Empty") {
+  let a = getBridgedNonverbatimArray([])
+  let identity1 = a._rawIdentifier()
+  expectTrue(isNativeArray(a))
+
+  var iter = a.makeIterator()
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.Generate_Huge") {
+  let a = getHugeBridgedVerbatimArray()
+  let identity1 = a._rawIdentifier()
+  expectTrue(isCocoaArray(a))
+
+  var iter = a.makeIterator()
+  var values = Array<Int>()
+  while let value = iter.next() {
+    values.append((value as! TestObjCValueTy).value)
+  }
+  var expectedValues = Array<Int>()
+  for i in 1...32 {
+    expectedValues += [1000 + i]
+  }
+  expectEqual(values, expectedValues)
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.Generate_Huge") {
+  let a = getHugeBridgedNonverbatimArray()
+  let identity1 = a._rawIdentifier()
+  expectTrue(isNativeArray(a))
+
+  var iter = a.makeIterator()
+  var values = Array<Int>()
+  while let value = iter.next() {
+    values.append(value.value)
+  }
+  var expectedValues = Array<Int>()
+  for i in 1...32 {
+    expectedValues += [1000 + i]
+  }
+  expectEqual(values, expectedValues)
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectNil(iter.next())
+  expectEqual(identity1, a._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.EqualityTest_Empty") {
+  let a1 = getBridgedVerbatimEquatableArray([])
+  let identity1 = a1._rawIdentifier()
+  expectTrue(isCocoaArray(a1))
+
+  let a2 = getBridgedVerbatimEquatableArray([])
+  let identity2 = a2._rawIdentifier()
+  expectTrue(isCocoaArray(a2))
+
+  // We can't check that `identity1 != identity2` because Foundation might be
+  // returning the same singleton NSArray for empty arrays.
+
+  expectEqual(a1, a2)
+  expectEqual(identity1, a1._rawIdentifier())
+  expectEqual(identity2, a2._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Nonverbatim.EqualityTest_Empty") {
+  var a1 = getBridgedNonverbatimEquatableArray([])
+  a1.append(TestBridgedEquatableValueTy(1))
+  a1.removeLast()
+  let identity1 = a1._rawIdentifier()
+  expectTrue(isNativeArray(a1))
+
+  let a2 = getBridgedNonverbatimEquatableArray([])
+  let identity2 = a2._rawIdentifier()
+  expectTrue(isNativeArray(a2))
+  expectNotEqual(identity1, identity2)
+
+  expectEqual(a1, a2)
+  expectEqual(identity1, a1._rawIdentifier())
+  expectEqual(identity2, a2._rawIdentifier())
+}
+
+ArrayTestSuite.test("BridgedFromObjC.Verbatim.EqualityTest_Small") {
+  func helper(_ na1: Array<Int>, _ na2: Array<Int>, _ expectedEq: Bool) {
+    let a1 = getBridgedVerbatimEquatableArray(na1)
+    let identity1 = a1._rawIdentifier()
+    expectTrue(isCocoaArray(a1))
+
+    var a2 = getBridgedVerbatimEquatableArray(na2)
+    var identity2 = a2._rawIdentifier()
+    expectTrue(isCocoaArray(a2))
+
+    do {
+      let eq1 = (a1 == a2)
+      expectEqual(eq1, expectedEq)
+
+      let eq2 = (a2 == a1)
+      expectEqual(eq2, expectedEq)
+
+      let neq1 = (a1 != a2)
+      expectNotEqual(neq1, expectedEq)
+
+      let neq2 = (a2 != a1)
+      expectNotEqual(neq2, expectedEq)
+    }
+    expectEqual(identity1, a1._rawIdentifier())
+    expectEqual(identity2, a2._rawIdentifier())
+
+    a2.append(TestObjCEquatableValueTy(1111))
+    a2.removeLast()
+    expectTrue(isNativeArray(a2))
+    expectNotEqual(identity2, a2._rawIdentifier())
+    identity2 = a2._rawIdentifier()
+
+    do {
+      let eq1 = (a1 == a2)
+      expectEqual(eq1, expectedEq)
+
+      let eq2 = (a2 == a1)
+      expectEqual(eq2, expectedEq)
+
+      let neq1 = (a1 != a2)
+      expectNotEqual(neq1, expectedEq)
+
+      let neq2 = (a2 != a1)
+      expectNotEqual(neq2, expectedEq)
+    }
+    expectEqual(identity1, a1._rawIdentifier())
+    expectEqual(identity2, a2._rawIdentifier())
+  }
+
+  helper([], [], true)
+
+  helper([1010],
+         [1010],
+         true)
+
+  helper([1010, 1020],
+         [1010, 1020],
+         true)
+
+  helper([1010, 1020, 1030],
+         [1010, 1020, 1030],
+         true)
+
+  helper([1010, 1020, 1030],
+         [1010, 1020, 1111],
+         false)
+
+  helper([1010, 1020, 1030],
+         [1010, 1020],
+         false)
+
+  helper([1010, 1020, 1030],
+         [1010],
+         false)
+
+  helper([1010, 1020, 1030],
+         [],
+         false)
+
+  helper([1010, 1020, 1030],
+         [1010, 1020, 1030, 1040],
+         false)
+}
+
+//===---
+// Array -> NSArray bridging tests.
+//
+// Values are bridged verbatim.
+//===---
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.Count") {
+  let d = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+  expectEqual(3, d.count)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectForKey") {
+  let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+  var v: AnyObject? = a.object(at: 0) as AnyObject
+  expectEqual(1010, (v as! TestObjCValueTy).value)
+  let idValue10 = unsafeBitCast(v, to: UInt.self)
+
+  v = a.object(at: 1) as AnyObject
+  expectEqual(1020, (v as! TestObjCValueTy).value)
+  let idValue20 = unsafeBitCast(v, to: UInt.self)
+
+  v = a.object(at: 2) as AnyObject
+  expectEqual(1030, (v as! TestObjCValueTy).value)
+  let idValue30 = unsafeBitCast(v, to: UInt.self)
+
+  for _ in 0..<3 {
+    expectEqual(idValue10, unsafeBitCast(
+      a.object(at: 0) as AnyObject, to: UInt.self))
+
+    expectEqual(idValue20, unsafeBitCast(
+      a.object(at: 1) as AnyObject, to: UInt.self))
+
+    expectEqual(idValue30, unsafeBitCast(
+      a.object(at: 2) as AnyObject, to: UInt.self))
+  }
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.NextObject") {
+  let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+  var capturedIdentities = Array<UInt>()
+
+  for _ in 0..<3 {
+    let enumerator = a.objectEnumerator()
+
+    var values = Array<Int>()
+    var identities = Array<UInt>()
+    while let value = enumerator.nextObject() {
+      let valueObj = (value as! TestObjCValueTy)
+      values.append(valueObj.value)
+
+      let identity = unsafeBitCast(valueObj, to: UInt.self)
+      identities.append(identity)
+    }
+    expectEqual([ 1010, 1020, 1030 ], values)
+
+    if capturedIdentities.isEmpty {
+      capturedIdentities = identities
+    } else {
+      expectEqual(capturedIdentities, identities)
+    }
+
+    expectNil(enumerator.nextObject())
+    expectNil(enumerator.nextObject())
+    expectNil(enumerator.nextObject())
+  }
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.NextObject_Empty") {
+  let a = getBridgedEmptyNSArray()
+  let enumerator = a.objectEnumerator()
+
+  expectNil(enumerator.nextObject())
+  expectNil(enumerator.nextObject())
+  expectNil(enumerator.nextObject())
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.FastEnumeration.UseFromSwift") {
+  let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+  checkArrayFastEnumerationFromSwift(
+    [ 1010, 1020, 1030 ],
+    a, { a.objectEnumerator() },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.FastEnumeration.UseFromObjC") {
+  let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+  checkArrayFastEnumerationFromObjC(
+    [ 1010, 1020, 1030 ],
+    a, { a.objectEnumerator() },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.FastEnumeration_Empty") {
+  let a = getBridgedEmptyNSArray()
+
+  checkArrayFastEnumerationFromSwift(
+    [], a, { a.objectEnumerator() },
+    { ($0 as! TestObjCValueTy).value })
+
+  checkArrayFastEnumerationFromObjC(
+    [], a, { a.objectEnumerator() },
+    { ($0 as! TestObjCValueTy).value })
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration.UseFromSwift") {
+  let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+  checkArrayFastEnumerationFromSwift(
+    [ 1010, 1020, 1030 ],
+    a, { a },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration.UseFromObjC") {
+  let a = getBridgedNSArrayOfRefTypesBridgedVerbatim()
+
+  checkArrayFastEnumerationFromObjC(
+    [ 1010, 1020, 1030 ],
+    a, { a },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration_Empty") {
+  let a = getBridgedEmptyNSArray()
+
+  checkArrayFastEnumerationFromSwift(
+    [], a, { a },
+    { ($0 as! TestObjCValueTy).value })
+
+  checkArrayFastEnumerationFromObjC(
+    [], a, { a },
+    { ($0 as! TestObjCValueTy).value })
+}
+
+//===---
+// Array -> NSArray bridging tests.
+//
+// Values are bridged non-verbatim.
+//===---
+
+ArrayTestSuite.test("BridgedToObjC.KeyValue_ValueTypesCustomBridged") {
+  let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+  let enumerator = a.objectEnumerator()
+
+  var values = Array<Int>()
+  while let valueObj = enumerator.nextObject() {
+    let value: AnyObject = valueObj as AnyObject
+    let v = (value as! TestObjCValueTy).value
+    values.append(v)
+  }
+  expectEqual([ 1010, 1020, 1030 ], values)
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.ObjectEnumerator.FastEnumeration.UseFromSwift") {
+  let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+
+  checkArrayFastEnumerationFromSwift(
+    [ 1010, 1020, 1030 ],
+    a, { a.objectEnumerator() },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.ObjectEnumerator.FastEnumeration.UseFromSwift.Partial") {
+  let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged(
+    numElements: 9)
+
+  checkArrayEnumeratorPartialFastEnumerationFromSwift(
+    [ 1010, 1020, 1030, 1040, 1050,
+      1060, 1070, 1080, 1090 ],
+    a, maxFastEnumerationItems: 5,
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 9)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.ObjectEnumerator.FastEnumeration.UseFromObjC") {
+  let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+
+  checkArrayFastEnumerationFromObjC(
+    [ 1010, 1020, 1030 ],
+    a, { a.objectEnumerator() },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.FastEnumeration.UseFromSwift") {
+  let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+
+  checkArrayFastEnumerationFromSwift(
+    [ 1010, 1020, 1030 ],
+    a, { a },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.FastEnumeration.UseFromObjC") {
+  let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged()
+
+  checkArrayFastEnumerationFromObjC(
+    [ 1010, 1020, 1030 ],
+    a, { a },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Custom.FastEnumeration_Empty") {
+  let a = getBridgedNSArrayOfObjValue_ValueTypesCustomBridged(
+    numElements: 0)
+
+  checkArrayFastEnumerationFromSwift(
+    [], a, { a },
+    { ($0 as! TestObjCValueTy).value })
+
+  checkArrayFastEnumerationFromObjC(
+    [], a, { a },
+    { ($0 as! TestObjCValueTy).value })
+}
+
+ArrayTestSuite.test("BridgedToObjC.Key_ValueTypeCustomBridged") {
+  let a = getBridgedNSArrayOfObj_ValueTypeCustomBridged()
+  let enumerator = a.objectEnumerator()
+
+  var values = Array<Int>()
+  while let valueObj = enumerator.nextObject() {
+    let value: AnyObject = valueObj as AnyObject
+    let v = (value as! TestObjCValueTy).value
+    values.append(v)
+  }
+  expectEqual([ 1010, 1020, 1030 ], values)
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("BridgedToObjC.Value_ValueTypeCustomBridged") {
+  let a = getBridgedNSArrayOfValue_ValueTypeCustomBridged()
+  let enumerator = a.objectEnumerator()
+
+  var values = Array<Int>()
+  while let valueObj = enumerator.nextObject() {
+    let value: AnyObject = valueObj as AnyObject
+    let v = (value as! TestObjCValueTy).value
+    values.append(v)
+  }
+  expectEqual([ 1010, 1020, 1030 ], values)
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+//===---
+// NSArray -> Array -> NSArray bridging tests.
+//===---
+
+ArrayTestSuite.test("BridgingRoundtrip") {
+  let a = getRoundtripBridgedNSArray()
+  let enumerator = a.objectEnumerator()
+
+  var values = Array<Int>()
+  while let valueObj = enumerator.nextObject() {
+    let value: AnyObject = valueObj as AnyObject
+    let v = (value as! TestObjCValueTy).value
+    values.append(v)
+  }
+  expectEqual([ 1010, 1020, 1030 ], values)
+}
+
+//===---
+// NSArray -> Array implicit conversion.
+//===---
+
+ArrayTestSuite.test("NSArrayToArrayConversion") {
+  let values = [ 1010, 1020, 1030 ].map { TestObjCValueTy($0) }
+
+  let nsa = NSArray(array: values)
+
+  let a: Array = nsa as Array
+
+  var bridgedValues = Array<Int>()
+  for value in a {
+    let v = (value as! TestObjCValueTy).value
+    bridgedValues.append(v)
+  }
+  expectEqual([ 1010, 1020, 1030 ], bridgedValues)
+}
+
+ArrayTestSuite.test("ArrayToNSArrayConversion") {
+  var a = Array<TestObjCValueTy>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+  let nsa: NSArray = a as NSArray
+
+  checkArrayFastEnumerationFromSwift(
+    [ 1010, 1020, 1030 ],
+    nsa, { a as NSArray },
+    { ($0 as! TestObjCValueTy).value })
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+//===---
+// Array upcasts
+//===---
+
+ArrayTestSuite.test("ArrayUpcastEntryPoint") {
+  var a = Array<TestObjCValueTy>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  var aAsAnyObject: Array<AnyObject> = _arrayForceCast(a)
+
+  expectEqual(3, aAsAnyObject.count)
+  var v: AnyObject = aAsAnyObject[0]
+  expectEqual(1010, (v as! TestObjCValueTy).value)
+
+  v = aAsAnyObject[1]
+  expectEqual(1020, (v as! TestObjCValueTy).value)
+
+  v = aAsAnyObject[2]
+  expectEqual(1030, (v as! TestObjCValueTy).value)
+}
+
+ArrayTestSuite.test("ArrayUpcast") {
+  var a = Array<TestObjCValueTy>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  var dAsAnyObject: Array<AnyObject> = a
+
+  expectEqual(3, dAsAnyObject.count)
+  var v: AnyObject = dAsAnyObject[0]
+  expectEqual(1010, (v as! TestObjCValueTy).value)
+
+  v = dAsAnyObject[1]
+  expectEqual(1020, (v as! TestObjCValueTy).value)
+
+  v = dAsAnyObject[2]
+  expectEqual(1030, (v as! TestObjCValueTy).value)
+}
+
+ArrayTestSuite.test("ArrayUpcastBridgedEntryPoint") {
+  var a = Array<TestBridgedValueTy>()
+  a.append(TestBridgedValueTy(1010))
+  a.append(TestBridgedValueTy(1020))
+  a.append(TestBridgedValueTy(1030))
+
+  do {
+    var aOO: Array<AnyObject> = _arrayConditionalCast(a)!
+
+    expectEqual(3, aOO.count)
+    var v: AnyObject = aOO[0]
+    expectEqual(1010, (v as! TestBridgedValueTy).value)
+
+    v = aOO[1]
+    expectEqual(1020, (v as! TestBridgedValueTy).value)
+
+    v = aOO[2]
+    expectEqual(1030, (v as! TestBridgedValueTy).value)
+  }
+}
+
+ArrayTestSuite.test("ArrayUpcastBridged") {
+  var a = Array<TestBridgedValueTy>()
+  a.append(TestBridgedValueTy(1010))
+  a.append(TestBridgedValueTy(1020))
+  a.append(TestBridgedValueTy(1030))
+
+  do {
+    var aOO = a as Array<AnyObject>
+
+    expectEqual(3, aOO.count)
+    var v: AnyObject = aOO[0]
+    expectEqual(1010, (v as! TestBridgedValueTy).value)
+
+    v = aOO[1]
+    expectEqual(1020, (v as! TestBridgedValueTy).value)
+
+    v = aOO[2]
+    expectEqual(1030, (v as! TestBridgedValueTy).value)
+  }
+}
+
+//===---
+// Array downcasts
+//===---
+
+ArrayTestSuite.test("ArrayDowncastEntryPoint") {
+  var a = Array<AnyObject>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  // Successful downcast.
+  let aCC: Array<TestObjCValueTy> = _arrayForceCast(a)
+  expectEqual(3, aCC.count)
+  var v = aCC[0]
+  expectEqual(1010, v.value)
+
+  v = aCC[1]
+  expectEqual(1020, v.value)
+
+  v = aCC[2]
+  expectEqual(1030, v.value)
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("ArrayDowncast") {
+  var a = Array<AnyObject>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  // Successful downcast.
+  let aCC = a as! Array<TestObjCValueTy>
+  expectEqual(3, aCC.count)
+  var v = aCC[0]
+  expectEqual(1010, v.value)
+
+  v = aCC[1]
+  expectEqual(1020, v.value)
+
+  v = aCC[2]
+  expectEqual(1030, v.value)
+
+  expectAutoreleasedValues(unopt: 3)
+}
+
+ArrayTestSuite.test("ArrayDowncastConditionalEntryPoint") {
+  var a = Array<AnyObject>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  // Successful downcast.
+  if let aCC
+       = _arrayConditionalCast(a) as Array<TestObjCValueTy>? {
+    expectEqual(3, aCC.count)
+    var v = aCC[0]
+    expectEqual(1010, v.value)
+
+    v = aCC[1]
+    expectEqual(1020, v.value)
+
+    v = aCC[2]
+    expectEqual(1030, v.value)
+  } else {
+    expectTrue(false)
+  }
+
+  // Unsuccessful downcast
+  a[0] = 17 as NSNumber
+  a[1] = "hello" as NSString
+  if let _ = _arrayConditionalCast(a) as Array<TestObjCValueTy>? {
+    expectTrue(false)
+  }
+}
+
+ArrayTestSuite.test("ArrayDowncastConditional") {
+  var a = Array<AnyObject>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  // Successful downcast.
+  if let aCC = a as? Array<TestObjCValueTy> {
+    expectEqual(3, aCC.count)
+    var v = aCC[0]
+    expectEqual(1010, v.value)
+
+    v = aCC[1]
+    expectEqual(1020, v.value)
+
+    v = aCC[2]
+    expectEqual(1030, v.value)
+  } else {
+    expectTrue(false)
+  }
+
+  // Unsuccessful downcast
+  a[0] = 17 as NSNumber
+  a[1] = "hello" as NSString
+  if let _ = a as? Array<TestObjCValueTy> {
+    expectTrue(false)
+  }
+}
+
+ArrayTestSuite.test("ArrayBridgeFromObjectiveCEntryPoint") {
+  var a = Array<AnyObject>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  // Successful downcast.
+  let aCV: Array<TestBridgedValueTy> = _arrayConditionalCast(a)!
+  do {
+    expectEqual(3, aCV.count)
+    var v = aCV[0]
+    expectEqual(1010, v.value)
+
+    v = aCV[1]
+    expectEqual(1020, v.value)
+
+    v = aCV[2]
+    expectEqual(1030, v.value)
+  }
+
+  // // Successful downcast.
+  let aVC: Array<TestObjCValueTy> = _arrayConditionalCast(a)!
+  do {
+    expectEqual(3, aVC.count)
+    var v = aVC[0]
+    expectEqual(1010, v.value)
+
+    v = aVC[1]
+    expectEqual(1020, v.value)
+
+    v = aVC[2]
+    expectEqual(1030, v.value)
+  }
+}
+
+ArrayTestSuite.test("ArrayBridgeFromObjectiveC") {
+  var a = Array<AnyObject>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  // Successful downcast.
+  let aCV = a as! Array<TestBridgedValueTy>
+  do {
+    expectEqual(3, aCV.count)
+    var v = aCV[0]
+    expectEqual(1010, v.value)
+
+    v = aCV[1]
+    expectEqual(1020, v.value)
+
+    v = aCV[2]
+    expectEqual(1030, v.value)
+  }
+
+  // Successful downcast.
+  let aVC = a as! Array<TestObjCValueTy>
+  do {
+    expectEqual(3, aVC.count)
+    var v = aVC[0]
+    expectEqual(1010, v.value)
+
+    v = aVC[1]
+    expectEqual(1020, v.value)
+
+    v = aVC[2]
+    expectEqual(1030, v.value)
+  }
+}
+
+ArrayTestSuite.test("ArrayBridgeFromObjectiveCConditionalEntryPoint") {
+  var a = Array<AnyObject>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  // Successful downcast.
+  if let aCV = _arrayConditionalCast(a) as Array<TestBridgedValueTy>? {
+    expectEqual(3, aCV.count)
+    var v = aCV[0]
+    expectEqual(1010, v.value)
+
+    v = aCV[1]
+    expectEqual(1020, v.value)
+
+    v = aCV[2]
+    expectEqual(1030, v.value)
+  } else {
+    expectTrue(false)
+  }
+
+  // Successful downcast.
+  if let aVC = _arrayConditionalCast(a) as Array<TestObjCValueTy>? {
+    expectEqual(3, aVC.count)
+    var v = aVC[0]
+    expectEqual(1010, v.value)
+
+    v = aVC[1]
+    expectEqual(1020, v.value)
+
+    v = aVC[2]
+    expectEqual(1030, v.value)
+  } else {
+    expectTrue(false)
+  }
+
+  // Unsuccessful downcasts
+  a[0] = 17 as NSNumber
+  a[1] = "hello" as NSString
+  if let _ = _arrayConditionalCast(a) as Array<TestBridgedValueTy>? {
+    expectTrue(false)
+  }
+  if let _ = _arrayConditionalCast(a) as Array<TestObjCValueTy>? {
+    expectTrue(false)
+  }
+}
+
+ArrayTestSuite.test("ArrayBridgeFromObjectiveCConditional") {
+  var a = Array<AnyObject>()
+  a.append(TestObjCValueTy(1010))
+  a.append(TestObjCValueTy(1020))
+  a.append(TestObjCValueTy(1030))
+
+  // Successful downcast.
+  if let aCV = a as? Array<TestBridgedValueTy> {
+    expectEqual(3, aCV.count)
+    var v = aCV[0]
+    expectEqual(1010, v.value)
+
+    v = aCV[1]
+    expectEqual(1020, v.value)
+
+    v = aCV[2]
+    expectEqual(1030, v.value)
+  } else {
+    expectTrue(false)
+  }
+
+  // Successful downcast.
+  if let aVC = a as? Array<TestObjCValueTy> {
+    expectEqual(3, aVC.count)
+    var v = aVC[0]
+    expectEqual(1010, v.value)
+
+    v = aVC[1]
+    expectEqual(1020, v.value)
+
+    v = aVC[2]
+    expectEqual(1030, v.value)
+  } else {
+    expectTrue(false)
+  }
+
+  // Unsuccessful downcasts
+  a[0] = 17 as NSNumber
+  a[1] = "hello" as NSString
+  if let _ = a as? Array<TestBridgedValueTy> {
+    expectTrue(false)
+  }
+  if let _ = a as? Array<TestObjCValueTy> {
+    expectTrue(false)
+  }
+}
+
+#endif
+
+//===---
+// Check that iterators traverse a snapshot of the collection.
+//===---
+
+ArrayTestSuite.test("mutationDoesNotAffectIterator/subscript/store") {
+  var array = getDerivedAPIsArray()
+  let iter = array.makeIterator()
+  array[0] = 1011
+
+  expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
+ArrayTestSuite.test("mutationDoesNotAffectIterator/removeAt,1") {
+  var array = getDerivedAPIsArray()
+  let iter = array.makeIterator()
+  expectEqual(1010, array.remove(at: 0))
+
+  expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
+ArrayTestSuite.test("mutationDoesNotAffectIterator/removeAt,all") {
+  var array = getDerivedAPIsArray()
+  let iter = array.makeIterator()
+  expectEqual(1010, array.remove(at: 0))
+  expectEqual(1020, array.remove(at: 0))
+  expectEqual(1030, array.remove(at: 0))
+
+  expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
+ArrayTestSuite.test(
+  "mutationDoesNotAffectIterator/removeAll,keepingCapacity=false") {
+  var array = getDerivedAPIsArray()
+  let iter = array.makeIterator()
+  array.removeAll(keepingCapacity: false)
+
+  expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
+ArrayTestSuite.test(
+  "mutationDoesNotAffectIterator/removeAll,keepingCapacity=true") {
+  var array = getDerivedAPIsArray()
+  let iter = array.makeIterator()
+  array.removeAll(keepingCapacity: true)
+
+  expectEqual([1010 ,1020, 1030], Array(IteratorSequence(iter)))
+}
+
 //===----------------------------------------------------------------------===//
 // Native array tests
 // FIXME: incomplete.
@@ -168,7 +1559,7 @@
 
 ArrayTestSuite.test("COW.Smoke") {
   var a1 = Array<COWBox<Int>>(repeating: COWBox(0), count: 10)
-  var identity1 = a1._rawIdentifier()
+  let identity1 = a1._rawIdentifier()
   
   a1[0] = COWBox(1)
   a1[1] = COWBox(2)
@@ -187,28 +1578,10 @@
   _blackHole(a2)  
 }
 
-func getCOWFastArray() -> Array<Int> {
-  var a = Array<Int>()
-  a.reserveCapacity(10)
-  a.append(1)
-  a.append(2)
-  a.append(3)
-  return a
-}
-
-func getCOWSlowArray() -> Array<COWBox<Int>> {
-  var a = Array<COWBox<Int>>()
-  a.reserveCapacity(10)
-  a.append(COWBox(1))
-  a.append(COWBox(2))
-  a.append(COWBox(3))
-  return a
-}
-
 ArrayTestSuite.test("COW.Fast.SubscriptWithIndexDoesNotReallocate") {
   var a = getCOWFastArray()
-  var identity1 = a._rawIdentifier()
-  var startIndex = a.startIndex
+  let identity1 = a._rawIdentifier()
+  let startIndex = a.startIndex
 
   expectNotEqual(0, a[startIndex])
   expectEqual(identity1, a._rawIdentifier())
@@ -216,8 +1589,8 @@
 
 ArrayTestSuite.test("COW.Slow.SubscriptWithIndexDoesNotReallocate") {
   var a = getCOWSlowArray()
-  var identity1 = a._rawIdentifier()
-  var startIndex = a.startIndex
+  let identity1 = a._rawIdentifier()
+  let startIndex = a.startIndex
 
   expectNotEqual(0, a[startIndex].value)
   expectEqual(identity1, a._rawIdentifier())
@@ -226,7 +1599,7 @@
 ArrayTestSuite.test("COW.Fast.RemoveAtDoesNotReallocate") {
   do {
     var a = getCOWFastArray()
-    var identity1 = a._rawIdentifier()
+    let identity1 = a._rawIdentifier()
 
     let index1 = 1
     expectEqual(identity1, a._rawIdentifier())
@@ -240,14 +1613,14 @@
   }
 
   do {
-    var a1 = getCOWFastArray()
-    var identity1 = a1._rawIdentifier()
+    let a1 = getCOWFastArray()
+    let identity1 = a1._rawIdentifier()
 
     var a2 = a1
     expectEqual(identity1, a1._rawIdentifier())
     expectEqual(identity1, a2._rawIdentifier())
 
-    var index1 = 1
+    let index1 = 1
     expectEqual(2, a2[index1])
     expectEqual(identity1, a1._rawIdentifier())
     expectEqual(identity1, a2._rawIdentifier())
@@ -263,7 +1636,7 @@
 ArrayTestSuite.test("COW.Slow.RemoveAtDoesNotReallocate") {
   do {
     var a = getCOWSlowArray()
-    var identity1 = a._rawIdentifier()
+    let identity1 = a._rawIdentifier()
 
     let index1 = 1
     expectEqual(identity1, a._rawIdentifier())
@@ -277,14 +1650,14 @@
   }
 
   do {
-    var a1 = getCOWSlowArray()
-    var identity1 = a1._rawIdentifier()
+    let a1 = getCOWSlowArray()
+    let identity1 = a1._rawIdentifier()
 
     var a2 = a1
     expectEqual(identity1, a1._rawIdentifier())
     expectEqual(identity1, a2._rawIdentifier())
 
-    var index1 = 1
+    let index1 = 1
     expectEqual(2, a2[index1].value)
     expectEqual(identity1, a1._rawIdentifier())
     expectEqual(identity1, a2._rawIdentifier())
@@ -306,7 +1679,7 @@
     expectEqual(2, a[1])
 
     a.removeAll()
-    var identity1 = a._rawIdentifier()
+    let identity1 = a._rawIdentifier()
     expectLT(a.capacity, originalCapacity)
     expectEqual(0, a.count)
     expectEqual(identity1, a._rawIdentifier())
@@ -314,7 +1687,7 @@
 
   do {
     var a = getCOWFastArray()
-    var identity1 = a._rawIdentifier()
+    let identity1 = a._rawIdentifier()
     let originalCapacity = a.capacity
     expectEqual(3, a.count)
     expectEqual(2, a[1])
@@ -327,13 +1700,13 @@
 
   do {
     var a1 = getCOWFastArray()
-    var identity1 = a1._rawIdentifier()
+    let identity1 = a1._rawIdentifier()
     expectEqual(3, a1.count)
     expectEqual(2, a1[1])
 
     var a2 = a1
     a2.removeAll()
-    var identity2 = a2._rawIdentifier()
+    let identity2 = a2._rawIdentifier()
     expectEqual(identity1, a1._rawIdentifier())
     expectNotEqual(identity2, identity1)
     expectEqual(3, a1.count)
@@ -347,14 +1720,14 @@
 
   do {
     var a1 = getCOWFastArray()
-    var identity1 = a1._rawIdentifier()
+    let identity1 = a1._rawIdentifier()
     let originalCapacity = a1.capacity
     expectEqual(3, a1.count)
     expectEqual(2, a1[1])
 
     var a2 = a1
     a2.removeAll(keepingCapacity: true)
-    var identity2 = a2._rawIdentifier()
+    let identity2 = a2._rawIdentifier()
     expectEqual(identity1, a1._rawIdentifier())
     expectNotEqual(identity2, identity1)
     expectEqual(3, a1.count)
@@ -377,7 +1750,7 @@
     expectEqual(2, a[1].value)
 
     a.removeAll()
-    var identity1 = a._rawIdentifier()
+    let identity1 = a._rawIdentifier()
     expectLT(a.capacity, originalCapacity)
     expectEqual(0, a.count)
     expectEqual(identity1, a._rawIdentifier())
@@ -385,7 +1758,7 @@
 
   do {
     var a = getCOWSlowArray()
-    var identity1 = a._rawIdentifier()
+    let identity1 = a._rawIdentifier()
     let originalCapacity = a.capacity
     expectEqual(3, a.count)
     expectEqual(2, a[1].value)
@@ -398,13 +1771,13 @@
 
   do {
     var a1 = getCOWSlowArray()
-    var identity1 = a1._rawIdentifier()
+    let identity1 = a1._rawIdentifier()
     expectEqual(3, a1.count)
     expectEqual(2, a1[1].value)
 
     var a2 = a1
     a2.removeAll()
-    var identity2 = a2._rawIdentifier()
+    let identity2 = a2._rawIdentifier()
     expectEqual(identity1, a1._rawIdentifier())
     expectNotEqual(identity2, identity1)
     expectEqual(3, a1.count)
@@ -418,14 +1791,14 @@
 
   do {
     var a1 = getCOWSlowArray()
-    var identity1 = a1._rawIdentifier()
+    let identity1 = a1._rawIdentifier()
     let originalCapacity = a1.capacity
     expectEqual(3, a1.count)
     expectEqual(2, a1[1].value)
 
     var a2 = a1
     a2.removeAll(keepingCapacity: true)
-    var identity2 = a2._rawIdentifier()
+    let identity2 = a2._rawIdentifier()
     expectEqual(identity1, a1._rawIdentifier())
     expectNotEqual(identity2, identity1)
     expectEqual(3, a1.count)
@@ -440,24 +1813,24 @@
 }
 
 ArrayTestSuite.test("COW.Fast.CountDoesNotReallocate") {
-  var a = getCOWFastArray()
-  var identity1 = a._rawIdentifier()
+  let a = getCOWFastArray()
+  let identity1 = a._rawIdentifier()
 
   expectEqual(3, a.count)
   expectEqual(identity1, a._rawIdentifier())
 }
 
 ArrayTestSuite.test("COW.Slow.CountDoesNotReallocate") {
-  var a = getCOWSlowArray()
-  var identity1 = a._rawIdentifier()
+  let a = getCOWSlowArray()
+  let identity1 = a._rawIdentifier()
 
   expectEqual(3, a.count)
   expectEqual(identity1, a._rawIdentifier())
 }
 
 ArrayTestSuite.test("COW.Fast.GenerateDoesNotReallocate") {
-  var a = getCOWFastArray()
-  var identity1 = a._rawIdentifier()
+  let a = getCOWFastArray()
+  let identity1 = a._rawIdentifier()
 
   var iter = a.makeIterator()
   var copy = Array<Int>()
@@ -469,8 +1842,8 @@
 }
 
 ArrayTestSuite.test("COW.Slow.GenerateDoesNotReallocate") {
-  var a = getCOWSlowArray()
-  var identity1 = a._rawIdentifier()
+  let a = getCOWSlowArray()
+  let identity1 = a._rawIdentifier()
 
   var iter = a.makeIterator()
   var copy = Array<Int>()
@@ -482,11 +1855,11 @@
 }
 
 ArrayTestSuite.test("COW.Fast.EqualityTestDoesNotReallocate") {
-  var a1 = getCOWFastArray()
-  var identity1 = a1._rawIdentifier()
+  let a1 = getCOWFastArray()
+  let identity1 = a1._rawIdentifier()
 
   var a2 = getCOWFastArray()
-  var identity2 = a2._rawIdentifier()
+  let identity2 = a2._rawIdentifier()
 
   expectEqual(a1, a2)
   expectEqual(identity1, a1._rawIdentifier())
@@ -499,11 +1872,11 @@
 }
 
 ArrayTestSuite.test("COW.Slow.EqualityTestDoesNotReallocate") {
-  var a1 = getCOWSlowArray()
-  var identity1 = a1._rawIdentifier()
+  let a1 = getCOWSlowArray()
+  let identity1 = a1._rawIdentifier()
 
   var a2 = getCOWSlowArray()
-  var identity2 = a2._rawIdentifier()
+  let identity2 = a2._rawIdentifier()
 
   expectEqual(a1, a2)
   expectEqual(identity1, a1._rawIdentifier())
@@ -1071,7 +2444,7 @@
     .code {
       let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
       var a = Array((0..<200).lazy.map { LifetimeTracked($0) })
-      var b = a
+      let b = a
       if expectedToFail {
         expectCrashLater()
       }
diff --git a/validation-test/stdlib/Dictionary.swift b/validation-test/stdlib/Dictionary.swift
index d525909..b9262dd 100644
--- a/validation-test/stdlib/Dictionary.swift
+++ b/validation-test/stdlib/Dictionary.swift
@@ -2773,8 +2773,6 @@
     pairs.append(kv)
   }
   assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   assert(iter.next() == nil)
   assert(iter.next() == nil)
   assert(iter.next() == nil)
@@ -2793,8 +2791,6 @@
     pairs.append(kv)
   }
   assert(equalsUnordered(pairs, [ (10, 1010), (20, 1020), (30, 1030) ]))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   assert(iter.next() == nil)
   assert(iter.next() == nil)
   assert(iter.next() == nil)
@@ -2811,8 +2807,6 @@
   // <rdar://problem/16811736> Optional tuples are broken as optionals regarding == comparison
   // assert(iter.next() == .none)
   assert(iter.next() == nil)
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   assert(iter.next() == nil)
   assert(iter.next() == nil)
   assert(iter.next() == nil)
@@ -2829,8 +2823,6 @@
   // <rdar://problem/16811736> Optional tuples are broken as optionals regarding == comparison
   // assert(iter.next() == .none)
   assert(iter.next() == nil)
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   assert(iter.next() == nil)
   assert(iter.next() == nil)
   assert(iter.next() == nil)
@@ -2854,8 +2846,6 @@
     expectedPairs += [(i, 1000 + i)]
   }
   assert(equalsUnordered(pairs, expectedPairs))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   assert(iter.next() == nil)
   assert(iter.next() == nil)
   assert(iter.next() == nil)
@@ -2878,8 +2868,6 @@
     expectedPairs += [(i, 1000 + i)]
   }
   assert(equalsUnordered(pairs, expectedPairs))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   assert(iter.next() == nil)
   assert(iter.next() == nil)
   assert(iter.next() == nil)
@@ -2904,8 +2892,6 @@
   }
   var expectedPairs = [ (10, 1111), (20, 1111), (30, 1111), (40, 1111) ]
   assert(equalsUnordered(pairs, expectedPairs))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   assert(iter.next() == nil)
   assert(iter.next() == nil)
   assert(iter.next() == nil)
@@ -2930,8 +2916,6 @@
   }
   var expectedPairs = [ (10, 1111), (20, 1111), (30, 1111), (40, 1111) ]
   assert(equalsUnordered(pairs, expectedPairs))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   assert(iter.next() == nil)
   assert(iter.next() == nil)
   assert(iter.next() == nil)
diff --git a/validation-test/stdlib/Set.swift b/validation-test/stdlib/Set.swift
index ed9fe61..b409796 100644
--- a/validation-test/stdlib/Set.swift
+++ b/validation-test/stdlib/Set.swift
@@ -1965,8 +1965,6 @@
     members.append((member as! TestObjCKeyTy).value)
   }
   expectTrue(equalsUnordered(members, [1010, 2020, 3030]))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   expectNil(iter.next())
   expectNil(iter.next())
   expectNil(iter.next())
@@ -1984,8 +1982,6 @@
     members.append(member.value)
   }
   expectTrue(equalsUnordered(members, [1010, 2020, 3030]))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   expectNil(iter.next())
   expectNil(iter.next())
   expectNil(iter.next())
@@ -1999,8 +1995,6 @@
 
   var iter = s.makeIterator()
   expectNil(iter.next())
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   expectNil(iter.next())
   expectNil(iter.next())
   expectNil(iter.next())
@@ -2014,8 +2008,6 @@
 
   var iter = s.makeIterator()
   expectNil(iter.next())
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   expectNil(iter.next())
   expectNil(iter.next())
   expectNil(iter.next())
@@ -2033,8 +2025,6 @@
     members.append((member as! TestObjCKeyTy).value)
   }
   expectTrue(equalsUnordered(members, hugeNumberArray))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   expectNil(iter.next())
   expectNil(iter.next())
   expectNil(iter.next())
@@ -2052,8 +2042,6 @@
     members.append((member as! TestBridgedKeyTy).value)
   }
   expectTrue(equalsUnordered(members, hugeNumberArray))
-  // The following is not required by the IteratorProtocol protocol, but
-  // it is a nice QoI.
   expectNil(iter.next())
   expectNil(iter.next())
   expectNil(iter.next())