Merge pull request #15450 from DougGregor/infer-ext-generic-typealias

Retain type sugar for extension declarations that name generic typealiases
diff --git a/docs/RefcountingStates.graffle b/docs/RefcountingStates.graffle
new file mode 100644
index 0000000..ebda0fc
--- /dev/null
+++ b/docs/RefcountingStates.graffle
Binary files differ
diff --git a/docs/StandardLibraryProgrammersManual.md b/docs/StandardLibraryProgrammersManual.md
index 3318415..558e973 100644
--- a/docs/StandardLibraryProgrammersManual.md
+++ b/docs/StandardLibraryProgrammersManual.md
@@ -170,3 +170,23 @@
 3. If the field is not trivially destructable, update `_destroyTLS` to properly destroy the value.
 
 See [ThreadLocalStorage.swift](https://github.com/apple/swift/blob/master/stdlib/public/core/ThreadLocalStorage.swift) for more details.
+
+## Productivity Hacks
+
+### Be a Ninja
+
+To *be* a productivity ninja, one must *use* `ninja`. `ninja` can be invoked inside the swift build directory, e.g. `<path>/build/Ninja-ReleaseAssert/swift-macosx-x86_64/`. Running `ninja` (which is equivalent to `ninja all`) will build the local swift, stdlib and overlays. It doesn’t necessarily build all the testing infrastructure, benchmarks, etc.
+
+`ninja -t targets` gives a list of all possible targets to pass to ninja. This is useful for grepping.
+
+For this example, we will figure out how to quickly iterate on a change to the standard library to fix 32-bit build errors while building on a 64-bit host, suppressing warnings along the way.
+
+`ninja -t targets | grep stdlib | grep i386` will output many targets, but at the bottom we see `swift-stdlib-iphonesimulator-i386`, which looks like a good first step. This target will just build i386 parts and not waste our time also building the 64-bit stdlib, overlays, etc.
+
+Going further, ninja can spawn a web browser for you to navigate dependencies and rules. `ninja -t browse swift-stdlib-iphonesimulator-i386`  will open a webpage with hyperlinks for all related targets. “target is built using” lists all this target’s dependencies, while “dependent edges build” list all the targets that depend directly on this.
+
+Clicking around a little bit, we can find `lib/swift/iphonesimulator/i386/libswiftCore.dylib` as a commonly-depended-upon target. This will perform just what is needed to compile the standard library for i386 and nothing else.
+
+Going further, for various reasons the standard library has lots of warnings. This is actively being addressed, but fixing all of them may require language features, etc. In the mean time, let’s suppress warnings in our build so that we just see the errors. `ninja -nv lib/swift/iphonesimulator/i386/libswiftCore.dylib` will show us the actual commands ninja will issue to build the i386 stdlib. (You’ll notice that an incremental build here is merely 3 commands as opposed to ~150 for `swift-stdlib-iphonesimulator-i386`).
+
+Copy the invocation that has  ` -o <build-path>/swift-macosx-x86_64/stdlib/public/core/iphonesimulator/i386/Swift.o`, so that we can perform the actual call to swiftc ourselves. Tack on `-suppress-warnings` at the end, and now we have the command to just build `Swift.o` for i386 while only displaying the actual errors.
diff --git a/docs/WindowsBuild.md b/docs/WindowsBuild.md
index 7bf7324..cfa2357 100644
--- a/docs/WindowsBuild.md
+++ b/docs/WindowsBuild.md
@@ -74,7 +74,9 @@
 VsDevCmd -arch=x86
 ```
 
-- Then adapt the following command and run it.
+- Then adapt the following command and run it. Make sure to use forward slashes 
+  (`/`) instead of backslashes (`\`) as the path separators. `clang` breaks 
+  with backslashed paths.
 ```cmd
 set swift_source_dir=path-to-directory-containing-all-cloned-repositories
 ```
@@ -113,7 +115,14 @@
  -DLLVM_TARGETS_TO_BUILD=X86^
  "%swift_source_dir%/llvm"
 popd
-cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/llvm-windows-amd64"
+cmake --build "%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"
+```
+- Store the LLVM `bin` directory in an environment variable so it can be used
+  to build Swift. Assuming you followed the instructions exactly, the path
+  below is correct, but it may be different based on your build variant and
+  platform, so double check.
+```cmd
+set llvm_bin_dir="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64/bin"
 ```
 
 ### 7. Build Swift
@@ -122,8 +131,8 @@
 - You may need to adjust the `SWIFT_WINDOWS_LIB_DIRECTORY` parameter depending on
   your target platform or Windows SDK version.
 ```cmd
-mkdir "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
-pushd "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+mkdir "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64"
+pushd "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64"
 cmake -G "Ninja" "%swift_source_dir%/swift"^
  -DCMAKE_BUILD_TYPE=Debug^
  -DSWIFT_PATH_TO_CMARK_SOURCE="%swift_source_dir%/cmark"^
@@ -141,13 +150,13 @@
  -DICU_I18N_LIB_NAME="icuin"^
  -DSWIFT_INCLUDE_DOCS=FALSE^
  -DSWIFT_INCLUDE_TESTS=FALSE^
- -DCMAKE_C_COMPILER="<path-to-llvm-bin>/clang-cl.exe"^
- -DCMAKE_CXX_COMPILER="<path-to-llvm-bin>/bin/clang-cl.exe"^
+ -DCMAKE_C_COMPILER="%llvm_bin_dir%/clang-cl.exe"^
+ -DCMAKE_CXX_COMPILER="%llvm_bin_dir%/clang-cl.exe"^
  -DCMAKE_C_FLAGS="-fms-compatibility-version=19.00 /Z7"^
  -DCMAKE_CXX_FLAGS="-fms-compatibility-version=19.00 -Z7" ^
  -DSWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER=FALSE
 popd
-cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64"
 ```
 
 - To create a Visual Studio project, you'll need to change the generator and,
@@ -168,13 +177,13 @@
 Follow instructions 1-6 for `clang-cl`, but run the following instead to build Swift
 
 ```cmd
-mkdir "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
-pushd "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+mkdir "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64"
+pushd "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64"
 cmake -G "Ninja" "%swift_source_dir%/swift"^
  -DCMAKE_BUILD_TYPE=Debug^
  -DSWIFT_PATH_TO_CMARK_SOURCE="%swift_source_dir%/cmark"^
- -DSWIFT_PATH_TO_CMARK_BUILD="%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64"^
- -DSWIFT_CMARK_LIBRARY_DIR="%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64/src"^
+ -DSWIFT_PATH_TO_CMARK_BUILD="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/cmark-windows-amd64"^
+ -DSWIFT_CMARK_LIBRARY_DIR="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/cmark-windows-amd64/src"^
  -DSWIFT_PATH_TO_LLVM_SOURCE="%swift_source_dir%/llvm"^
  -DSWIFT_PATH_TO_LLVM_BUILD="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"^
  -DSWIFT_PATH_TO_CLANG_SOURCE="%swift_source_dir%/llvm/tools/clang"^
@@ -190,5 +199,5 @@
  -DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY=FALSE^
  -DSWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER=FALSE
 popd
-cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64"
 ```
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index cc0922b..9bc0cd8 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -980,6 +980,27 @@
   return uintptr_t(flags) & uintptr_t(StructLayoutFlags::IsVWTMutable);
 }
 
+/// Flags for class layout.
+enum class ClassLayoutFlags : uintptr_t {
+  /// Reserve space for 256 layout algorithms.
+  AlgorithmMask     = 0xff,
+
+  /// The ABI baseline algorithm, i.e. the algorithm implemented in Swift 5.
+  Swift5Algorithm   = 0x00,
+};
+static inline ClassLayoutFlags operator|(ClassLayoutFlags lhs,
+                                         ClassLayoutFlags rhs) {
+  return ClassLayoutFlags(uintptr_t(lhs) | uintptr_t(rhs));
+}
+static inline ClassLayoutFlags &operator|=(ClassLayoutFlags &lhs,
+                                           ClassLayoutFlags rhs) {
+  return (lhs = (lhs | rhs));
+}
+static inline ClassLayoutFlags getLayoutAlgorithm(ClassLayoutFlags flags) {
+  return ClassLayoutFlags(uintptr_t(flags)
+                             & uintptr_t(ClassLayoutFlags::AlgorithmMask));
+}
+
 /// Flags for enum layout.
 enum class EnumLayoutFlags : uintptr_t {
   /// Reserve space for 256 layout algorithms.
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 8b8699c..d0c13bd 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -180,18 +180,6 @@
   HasAssociatedValues,
 };
 
-/// Describes if an enum element constructor directly or indirectly references
-/// its enclosing type.
-enum class ElementRecursiveness {
-  /// The element does not reference its enclosing type.
-  NotRecursive,
-  /// The element is currently being validated, and may references its enclosing
-  /// type.
-  PotentiallyRecursive,
-  /// The element does not reference its enclosing type.
-  Recursive
-};
-
 /// Diagnostic printing of \c StaticSpellingKind.
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK);
 
@@ -225,6 +213,12 @@
 
 /// Decl - Base class for all declarations in Swift.
 class alignas(1 << DeclAlignInBits) Decl {
+  enum class ValidationState {
+    Unchecked,
+    Checking,
+    Checked,
+  };
+
 protected:
   union { uint64_t OpaqueBits;
 
@@ -247,12 +241,8 @@
     /// FIXME: This is ugly.
     EarlyAttrValidation : 1,
 
-    /// \brief Whether this declaration is currently being validated.
-    BeingValidated : 1,
-
-    /// \brief Whether we have started validating the declaration; this *isn't*
-    /// reset after finishing it.
-    ValidationStarted : 1,
+    /// \brief The validation state of this declaration.
+    ValidationState : 2,
 
     /// \brief Whether this declaration was added to the surrounding
     /// DeclContext of an active #if config clause.
@@ -339,13 +329,9 @@
     defaultArgumentKind : NumDefaultArgumentKindBits
   );
 
-  SWIFT_INLINE_BITFIELD(EnumElementDecl, ValueDecl, 3,
+  SWIFT_INLINE_BITFIELD(EnumElementDecl, ValueDecl, 1,
     /// \brief Whether or not this element has an associated value.
-    HasArgumentType : 1,
-
-    /// \brief Whether or not this element directly or indirectly references
-    /// the enum type.
-    Recursiveness : 2
+    HasArgumentType : 1
   );
   
   SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+5+1+1+1+1+1,
@@ -625,8 +611,7 @@
     Bits.Decl.Implicit = false;
     Bits.Decl.FromClang = false;
     Bits.Decl.EarlyAttrValidation = false;
-    Bits.Decl.BeingValidated = false;
-    Bits.Decl.ValidationStarted = false;
+    Bits.Decl.ValidationState = unsigned(ValidationState::Unchecked);
     Bits.Decl.EscapedFromIfConfig = false;
   }
 
@@ -775,25 +760,32 @@
   /// Whether the declaration has a valid interface type and
   /// generic signature.
   bool isBeingValidated() const {
-    return Bits.Decl.BeingValidated;
+    return Bits.Decl.ValidationState == unsigned(ValidationState::Checking);
   }
 
   /// Toggle whether or not the declaration is being validated.
   void setIsBeingValidated(bool ibv = true) {
-    assert(Bits.Decl.BeingValidated != ibv);
-    Bits.Decl.BeingValidated = ibv;
     if (ibv) {
-      Bits.Decl.ValidationStarted = true;
+      assert(Bits.Decl.ValidationState == unsigned(ValidationState::Unchecked));
+      Bits.Decl.ValidationState = unsigned(ValidationState::Checking);
+    } else {
+      assert(Bits.Decl.ValidationState == unsigned(ValidationState::Checking));
+      Bits.Decl.ValidationState = unsigned(ValidationState::Checked);
     }
   }
 
-  bool hasValidationStarted() const { return Bits.Decl.ValidationStarted; }
+  bool hasValidationStarted() const {
+    return Bits.Decl.ValidationState >= unsigned(ValidationState::Checking);
+  }
 
   /// Manually indicate that validation has started for the declaration.
   ///
   /// This is implied by setIsBeingValidated(true) (i.e. starting validation)
   /// and so rarely needs to be called directly.
-  void setValidationStarted() { Bits.Decl.ValidationStarted = true; }
+  void setValidationStarted() {
+    if (Bits.Decl.ValidationState != unsigned(ValidationState::Checking))
+      Bits.Decl.ValidationState = unsigned(ValidationState::Checked);
+  }
 
   bool escapedFromIfConfig() const {
     return Bits.Decl.EscapedFromIfConfig;
@@ -5769,8 +5761,6 @@
     EqualsLoc(EqualsLoc),
     RawValueExpr(RawValueExpr)
   {
-    Bits.EnumElementDecl.Recursiveness =
-        static_cast<unsigned>(ElementRecursiveness::NotRecursive);
     Bits.EnumElementDecl.HasArgumentType = HasArgumentType;
   }
 
@@ -5815,15 +5805,6 @@
   }
   SourceRange getSourceRange() const;
   
-  ElementRecursiveness getRecursiveness() const {
-    return
-      static_cast<ElementRecursiveness>(Bits.EnumElementDecl.Recursiveness);
-  }
-  
-  void setRecursiveness(ElementRecursiveness recursiveness) {
-    Bits.EnumElementDecl.Recursiveness = static_cast<unsigned>(recursiveness);
-  }
-
   bool hasAssociatedValues() const {
     return Bits.EnumElementDecl.HasArgumentType;
   }
diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def
index 34f3eb2..22346ae 100644
--- a/include/swift/AST/DiagnosticsFrontend.def
+++ b/include/swift/AST/DiagnosticsFrontend.def
@@ -136,6 +136,9 @@
 ERROR(error_unable_to_load_supplementary_output_file_map, none,
       "unable to load supplementary output file map '%0': %1", (StringRef, StringRef))
 
+ERROR(error_missing_entry_in_supplementary_output_file_map, none,
+      "supplementary output file map '%0' is missing an entry for '%1' (this likely indicates a compiler issue; please file a bug report)", (StringRef, StringRef))
+
 ERROR(error_repl_requires_no_input_files,none,
   "REPL mode requires no input files", ())
 ERROR(error_mode_requires_one_input_file,none,
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 35f3964..47762d7 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -2163,10 +2163,6 @@
       "'Self' is only available in a protocol or as the result of a "
       "method in a class; did you mean '%0'?", (StringRef))
 
-// Duplicate declarations
-ERROR(duplicate_enum_element,none,
-      "duplicate definition of enum element",())
-
 // Property behaviors
 ERROR(property_behavior_not_protocol,none,
       "property behavior name must refer to a protocol", ())
diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h
index 85c2892..6d9997a 100644
--- a/include/swift/AST/GenericEnvironment.h
+++ b/include/swift/AST/GenericEnvironment.h
@@ -150,6 +150,19 @@
   /// abstraction level of their associated type requirements.
   SILType mapTypeIntoContext(SILModule &M, SILType type) const;
 
+  /// Map an interface type's protocol conformance into the corresponding
+  /// conformance for the contextual type.
+  static std::pair<Type, ProtocolConformanceRef>
+  mapConformanceRefIntoContext(GenericEnvironment *genericEnv,
+                               Type conformingType,
+                               ProtocolConformanceRef conformance);
+
+  /// Map an interface type's protocol conformance into the corresponding
+  /// conformance for the contextual type.
+  std::pair<Type, ProtocolConformanceRef>
+  mapConformanceRefIntoContext(Type conformingType,
+                               ProtocolConformanceRef conformance) const;
+          
   /// Get the sugared form of a generic parameter type.
   GenericTypeParamType *getSugaredType(GenericTypeParamType *type) const;
 
diff --git a/include/swift/AST/ProtocolConformanceRef.h b/include/swift/AST/ProtocolConformanceRef.h
index b373a15..327a916 100644
--- a/include/swift/AST/ProtocolConformanceRef.h
+++ b/include/swift/AST/ProtocolConformanceRef.h
@@ -133,6 +133,11 @@
   /// Get any additional requirements that are required for this conformance to
   /// be satisfied.
   ArrayRef<Requirement> getConditionalRequirements() const;
+  
+  /// If this is a conformance reference for a protocol that inherits other
+  /// protocols, get a reference to the related conformance for the inherited
+  /// protocol.
+  ProtocolConformanceRef getInheritedConformanceRef(ProtocolDecl *base) const;
 };
 
 } // end namespace swift
diff --git a/include/swift/Basic/Version.h b/include/swift/Basic/Version.h
index 25fff6f..6c46eb2 100644
--- a/include/swift/Basic/Version.h
+++ b/include/swift/Basic/Version.h
@@ -119,6 +119,9 @@
   /// Return this Version struct with minor and sub-minor components stripped
   Version asMajorVersion() const;
 
+  /// Return this Version struct as the appropriate version string for APINotes.
+  std::string asAPINotesVersionString() const;
+
   /// Parse a version in the form used by the _compiler_version \#if condition.
   static Optional<Version> parseCompilerVersionString(StringRef VersionString,
                                                       SourceLoc Loc,
@@ -143,8 +146,8 @@
 
   // List of backward-compatibility versions that we permit passing as
   // -swift-version <vers>
-  static std::array<StringRef, 3> getValidEffectiveVersions() {
-    return {{"3", "4", "5"}};
+  static std::array<StringRef, 4> getValidEffectiveVersions() {
+    return {{"3", "4", "4.2", "5"}};
   };
 };
 
diff --git a/include/swift/Driver/Action.h b/include/swift/Driver/Action.h
index 831bed5..28dee31 100644
--- a/include/swift/Driver/Action.h
+++ b/include/swift/Driver/Action.h
@@ -15,7 +15,7 @@
 
 #include "swift/Basic/LLVM.h"
 #include "swift/Driver/Util.h"
-#include "swift/Frontend/Types.h"
+#include "swift/Frontend/FileTypes.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -34,11 +34,11 @@
 
 class Action {
 public:
-  typedef ArrayRef<const Action *>::size_type size_type;
-  typedef ArrayRef<const Action *>::iterator iterator;
-  typedef ArrayRef<const Action *>::const_iterator const_iterator;
+  using size_type = ArrayRef<const Action *>::size_type;
+  using iterator = ArrayRef<const Action *>::iterator;
+  using const_iterator = ArrayRef<const Action *>::const_iterator;
 
-  enum ActionClass {
+  enum class Kind : unsigned {
     Input = 0,
     CompileJob,
     InterpretJob,
@@ -52,14 +52,14 @@
     VerifyDebugInfoJob,
     GeneratePCHJob,
 
-    JobFirst=CompileJob,
-    JobLast=GeneratePCHJob
+    JobFirst = CompileJob,
+    JobLast = GeneratePCHJob
   };
 
-  static const char *getClassName(ActionClass AC);
+  static const char *getClassName(Kind AC);
 
 private:
-  unsigned Kind : 4;
+  unsigned RawKind : 4;
   unsigned Type : 28;
 
   friend class Compilation;
@@ -67,9 +67,9 @@
   void *operator new(size_t size) { return ::operator new(size); };
 
 protected:
-  Action(ActionClass Kind, types::ID Type)
-    : Kind(Kind), Type(Type) {
-    assert(Kind == getKind() && "not enough bits");
+  Action(Kind K, file_types::ID Type)
+      : RawKind(unsigned(K)), Type(Type) {
+    assert(K == getKind() && "not enough bits");
     assert(Type == getType() && "not enough bits");
   }
 
@@ -78,8 +78,8 @@
 
   const char *getClassName() const { return Action::getClassName(getKind()); }
 
-  ActionClass getKind() const { return static_cast<ActionClass>(Kind); }
-  types::ID getType() const { return static_cast<types::ID>(Type); }
+  Kind getKind() const { return static_cast<Kind>(RawKind); }
+  file_types::ID getType() const { return static_cast<file_types::ID>(Type); }
 };
 
 class InputAction : public Action {
@@ -87,12 +87,12 @@
   const llvm::opt::Arg &Input;
 
 public:
-  InputAction(const llvm::opt::Arg &Input, types::ID Type)
-      : Action(Action::Input, Type), Input(Input) {}
+  InputAction(const llvm::opt::Arg &Input, file_types::ID Type)
+      : Action(Action::Kind::Input, Type), Input(Input) {}
   const llvm::opt::Arg &getInputArg() const { return Input; }
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::Input;
+    return A->getKind() == Action::Kind::Input;
   }
 };
 
@@ -100,7 +100,8 @@
   TinyPtrVector<const Action *> Inputs;
   virtual void anchor();
 protected:
-  JobAction(ActionClass Kind, ArrayRef<const Action *> Inputs, types::ID Type)
+  JobAction(Kind Kind, ArrayRef<const Action *> Inputs,
+            file_types::ID Type)
       : Action(Kind, Type), Inputs(Inputs) {}
 
 public:
@@ -120,8 +121,8 @@
   virtual size_t getInputIndex() const { return 0; }
 
   static bool classof(const Action *A) {
-    return (A->getKind() >= ActionClass::JobFirst &&
-            A->getKind() <= ActionClass::JobLast);
+    return (A->getKind() >= Kind::JobFirst &&
+            A->getKind() <= Kind::JobLast);
   }
 };
 
@@ -151,12 +152,12 @@
   InputInfo inputInfo;
 
 public:
-  CompileJobAction(types::ID OutputType)
-      : JobAction(Action::CompileJob, None, OutputType), inputInfo() {}
+  CompileJobAction(file_types::ID OutputType)
+      : JobAction(Action::Kind::CompileJob, None, OutputType),
+        inputInfo() {}
 
-  CompileJobAction(Action *Input, types::ID OutputType,
-                   InputInfo info)
-      : JobAction(Action::CompileJob, Input, OutputType),
+  CompileJobAction(Action *Input, file_types::ID OutputType, InputInfo info)
+      : JobAction(Action::Kind::CompileJob, Input, OutputType),
         inputInfo(info) {}
 
   InputInfo getInputInfo() const {
@@ -164,7 +165,7 @@
   }
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::CompileJob;
+    return A->getKind() == Action::Kind::CompileJob;
   }
 };
 
@@ -174,10 +175,11 @@
 
 public:
   explicit InterpretJobAction()
-      : JobAction(Action::InterpretJob, llvm::None, types::TY_Nothing) {}
+      : JobAction(Action::Kind::InterpretJob, llvm::None,
+                  file_types::TY_Nothing) {}
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::InterpretJob;
+    return A->getKind() == Action::Kind::InterpretJob;
   }
 };
 
@@ -190,11 +192,12 @@
   // This index specifies which of the files to select for the input.
   size_t InputIndex;
 public:
-  BackendJobAction(const Action *Input, types::ID OutputType, size_t InputIndex)
-      : JobAction(Action::BackendJob, Input, OutputType),
+  BackendJobAction(const Action *Input, file_types::ID OutputType,
+                   size_t InputIndex)
+      : JobAction(Action::Kind::BackendJob, Input, OutputType),
         InputIndex(InputIndex) {}
   static bool classof(const Action *A) {
-    return A->getKind() == Action::BackendJob;
+    return A->getKind() == Action::Kind::BackendJob;
   }
   
   virtual size_t getInputIndex() const { return InputIndex; }
@@ -212,13 +215,14 @@
   Mode RequestedMode;
 public:
   REPLJobAction(Mode mode)
-    : JobAction(Action::REPLJob, llvm::None, types::TY_Nothing),
-      RequestedMode(mode) {}
+      : JobAction(Action::Kind::REPLJob, llvm::None,
+                  file_types::TY_Nothing),
+        RequestedMode(mode) {}
 
   Mode getRequestedMode() const { return RequestedMode; }
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::REPLJob;
+    return A->getKind() == Action::Kind::REPLJob;
   }
 };
 
@@ -226,10 +230,11 @@
   virtual void anchor();
 public:
   MergeModuleJobAction(ArrayRef<const Action *> Inputs)
-      : JobAction(Action::MergeModuleJob, Inputs, types::TY_SwiftModuleFile) {}
+      : JobAction(Action::Kind::MergeModuleJob, Inputs,
+                  file_types::TY_SwiftModuleFile) {}
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::MergeModuleJob;
+    return A->getKind() == Action::Kind::MergeModuleJob;
   }
 };
 
@@ -237,10 +242,11 @@
   virtual void anchor();
 public:
   ModuleWrapJobAction(ArrayRef<const Action *> Inputs)
-      : JobAction(Action::ModuleWrapJob, Inputs, types::TY_Object) {}
+      : JobAction(Action::Kind::ModuleWrapJob, Inputs,
+                  file_types::TY_Object) {}
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::ModuleWrapJob;
+    return A->getKind() == Action::Kind::ModuleWrapJob;
   }
 };
 
@@ -248,10 +254,11 @@
   virtual void anchor();
 public:
   AutolinkExtractJobAction(ArrayRef<const Action *> Inputs)
-      : JobAction(Action::AutolinkExtractJob, Inputs, types::TY_AutolinkFile) {}
+      : JobAction(Action::Kind::AutolinkExtractJob, Inputs,
+                  file_types::TY_AutolinkFile) {}
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::AutolinkExtractJob;
+    return A->getKind() == Action::Kind::AutolinkExtractJob;
   }
 };
 
@@ -259,10 +266,11 @@
   virtual void anchor();
 public:
   explicit GenerateDSYMJobAction(const Action *Input)
-    : JobAction(Action::GenerateDSYMJob, Input, types::TY_dSYM) {}
+      : JobAction(Action::Kind::GenerateDSYMJob, Input,
+                  file_types::TY_dSYM) {}
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::GenerateDSYMJob;
+    return A->getKind() == Action::Kind::GenerateDSYMJob;
   }
 };
 
@@ -270,10 +278,11 @@
   virtual void anchor();
 public:
   explicit VerifyDebugInfoJobAction(const Action *Input)
-    : JobAction(Action::VerifyDebugInfoJob, Input, types::TY_Nothing) {}
+      : JobAction(Action::Kind::VerifyDebugInfoJob, Input,
+                  file_types::TY_Nothing) {}
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::VerifyDebugInfoJob;
+    return A->getKind() == Action::Kind::VerifyDebugInfoJob;
   }
 };
   
@@ -283,15 +292,16 @@
   virtual void anchor();
 public:
   GeneratePCHJobAction(const Action *Input, StringRef persistentPCHDir)
-    : JobAction(Action::GeneratePCHJob, Input,
-                persistentPCHDir.empty() ? types::TY_PCH : types::TY_Nothing),
-      PersistentPCHDir(persistentPCHDir) {}
+      : JobAction(Action::Kind::GeneratePCHJob, Input,
+                  persistentPCHDir.empty() ? file_types::TY_PCH
+                                           : file_types::TY_Nothing),
+        PersistentPCHDir(persistentPCHDir) {}
 
   bool isPersistentPCH() const { return !PersistentPCHDir.empty(); }
   StringRef getPersistentPCHDir() const { return PersistentPCHDir; }
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::GeneratePCHJob;
+    return A->getKind() == Action::Kind::GeneratePCHJob;
   }
 };
 
@@ -301,14 +311,15 @@
 
 public:
   LinkJobAction(ArrayRef<const Action *> Inputs, LinkKind K)
-      : JobAction(Action::LinkJob, Inputs, types::TY_Image), Kind(K) {
+      : JobAction(Action::Kind::LinkJob, Inputs, file_types::TY_Image),
+        Kind(K) {
     assert(Kind != LinkKind::None);
   }
 
   LinkKind getKind() const { return Kind; }
 
   static bool classof(const Action *A) {
-    return A->getKind() == Action::LinkJob;
+    return A->getKind() == Action::Kind::LinkJob;
   }
 };
 
diff --git a/include/swift/Driver/DependencyGraph.h b/include/swift/Driver/DependencyGraph.h
index 2148cf2..106f00c 100644
--- a/include/swift/Driver/DependencyGraph.h
+++ b/include/swift/Driver/DependencyGraph.h
@@ -140,11 +140,11 @@
   class StringSetIterator {
     llvm::StringSet<>::const_iterator I;
   public:
-    typedef llvm::StringSet<>::const_iterator::value_type value_type;
-    typedef std::input_iterator_tag iterator_category;
-    typedef ptrdiff_t difference_type;
-    typedef value_type &reference;
-    typedef value_type *pointer;
+    using value_type = llvm::StringSet<>::const_iterator::value_type;
+    using iterator_category = std::input_iterator_tag;
+    using difference_type = ptrdiff_t;
+    using reference = value_type &;
+    using pointer = value_type *;
 
     /*implicit*/ StringSetIterator(llvm::StringSet<>::const_iterator base)
        : I(base) {}
diff --git a/include/swift/Driver/Driver.h b/include/swift/Driver/Driver.h
index 2325851..bb41075 100644
--- a/include/swift/Driver/Driver.h
+++ b/include/swift/Driver/Driver.h
@@ -22,8 +22,8 @@
 #include "swift/Basic/OptionSet.h"
 #include "swift/Basic/Sanitizers.h"
 #include "swift/Driver/Util.h"
+#include "swift/Frontend/FileTypes.h"
 #include "swift/Frontend/OutputFileMap.h"
-#include "swift/Frontend/Types.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -78,7 +78,7 @@
   Mode CompilerMode = Mode::StandardCompile;
 
   /// The output type which should be used for compile actions.
-  types::ID CompilerOutputType = types::ID::TY_INVALID;
+  file_types::ID CompilerOutputType = file_types::ID::TY_INVALID;
 
   /// Describes if and how the output of compile actions should be
   /// linked together.
diff --git a/include/swift/Driver/Job.h b/include/swift/Driver/Job.h
index c993a52..cfdbe34 100644
--- a/include/swift/Driver/Job.h
+++ b/include/swift/Driver/Job.h
@@ -16,8 +16,8 @@
 #include "swift/Basic/LLVM.h"
 #include "swift/Driver/Action.h"
 #include "swift/Driver/Util.h"
+#include "swift/Frontend/FileTypes.h"
 #include "swift/Frontend/OutputFileMap.h"
-#include "swift/Frontend/Types.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerIntPair.h"
@@ -109,7 +109,7 @@
 
   /// A CommandOutput designates one type of output as primary, though there
   /// may be multiple outputs of that type.
-  types::ID PrimaryOutputType;
+  file_types::ID PrimaryOutputType;
 
   /// A CommandOutput also restricts its attention regarding additional-outputs
   /// to a subset of the PrimaryOutputs associated with its PrimaryInputs;
@@ -117,7 +117,7 @@
   /// phases (eg. autolink-extract and link both operate on the same .o file),
   /// so Jobs cannot _just_ rely on the presence of a primary output in the
   /// DerivedOutputFileMap.
-  llvm::SmallSet<types::ID, 4> AdditionalOutputTypes;
+  llvm::SmallSet<file_types::ID, 4> AdditionalOutputTypes;
 
   /// The list of inputs for this \c CommandOutput. Each input in the list has
   /// two names (often but not always the same), of which the second (\c
@@ -135,23 +135,21 @@
   // If there is an entry in the DerivedOutputMap for a given (\p
   // PrimaryInputFile, \p Type) pair, return a nonempty StringRef, otherwise
   // return an empty StringRef.
-  StringRef
-  getOutputForInputAndType(StringRef PrimaryInputFile, types::ID Type) const;
+  StringRef getOutputForInputAndType(StringRef PrimaryInputFile,
+                                     file_types::ID Type) const;
 
   /// Add an entry to the \c DerivedOutputMap if it doesn't exist. If an entry
   /// already exists for \p PrimaryInputFile of type \p type, then either
   /// overwrite the entry (if \p overwrite is \c true) or assert that it has
   /// the same value as \p OutputFile.
-  void ensureEntry(StringRef PrimaryInputFile,
-                   types::ID Type,
-                   StringRef OutputFile,
-                   bool Overwrite);
+  void ensureEntry(StringRef PrimaryInputFile, file_types::ID Type,
+                   StringRef OutputFile, bool Overwrite);
 
 public:
-  CommandOutput(types::ID PrimaryOutputType, OutputFileMap &Derived);
+  CommandOutput(file_types::ID PrimaryOutputType, OutputFileMap &Derived);
 
   /// Return the primary output type for this CommandOutput.
-  types::ID getPrimaryOutputType() const;
+  file_types::ID getPrimaryOutputType() const;
 
   /// Associate a new \p PrimaryOutputFile (of type \c getPrimaryOutputType())
   /// with the provided \p Input pair of Base and Primary inputs.
@@ -186,12 +184,13 @@
   /// an additional output named \p OutputFilename of type \p type with the
   /// first primary input. If the provided \p type is the primary output type,
   /// overwrite the existing entry assocaited with the first primary input.
-  void setAdditionalOutputForType(types::ID type, StringRef OutputFilename);
+  void setAdditionalOutputForType(file_types::ID type,
+                                  StringRef OutputFilename);
 
   /// Assuming (and asserting) that there are one or more input pairs, return
   /// the _additional_ (not primary) output of type \p type associated with the
   /// first primary input.
-  StringRef getAdditionalOutputForType(types::ID type) const;
+  StringRef getAdditionalOutputForType(file_types::ID type) const;
 
   /// Return a vector of additional (not primary) outputs of type \p type
   /// associated with the primary inputs.
@@ -202,12 +201,13 @@
   /// length is _either_ zero, one, or equal to the size of the set of inputs,
   /// as these are the only valid arity relationships between primary and
   /// additional outputs.
-  SmallVector<StringRef, 16> getAdditionalOutputsForType(types::ID type) const;
+  SmallVector<StringRef, 16>
+  getAdditionalOutputsForType(file_types::ID type) const;
 
   /// Assuming (and asserting) that there is only one input pair, return any
   /// output -- primary or additional -- of type \p type associated with that
   /// the sole primary input.
-  StringRef getAnyOutputForType(types::ID type) const;
+  StringRef getAnyOutputForType(file_types::ID type) const;
 
   /// Return the whole derived output map.
   const OutputFileMap &getDerivedOutputMap() const;
diff --git a/include/swift/Driver/PrettyStackTrace.h b/include/swift/Driver/PrettyStackTrace.h
index c2ddaaf..f30030b 100644
--- a/include/swift/Driver/PrettyStackTrace.h
+++ b/include/swift/Driver/PrettyStackTrace.h
@@ -13,7 +13,7 @@
 #ifndef SWIFT_DRIVER_PRETTYSTACKTRACE_H
 #define SWIFT_DRIVER_PRETTYSTACKTRACE_H
 
-#include "swift/Frontend/Types.h"
+#include "swift/Frontend/FileTypes.h"
 #include "llvm/Support/PrettyStackTrace.h"
 
 namespace swift {
@@ -57,14 +57,15 @@
     : public llvm::PrettyStackTraceEntry {
   const CommandOutput *TheCommandOutput;
   StringRef PrimaryInput;
-  types::ID NewOutputType;
+  file_types::ID NewOutputType;
   StringRef NewOutputName;
   const char *Description;
 
 public:
   PrettyStackTraceDriverCommandOutputAddition(const char *desc,
                                               const CommandOutput *A,
-                                              StringRef Primary, types::ID type,
+                                              StringRef Primary,
+                                              file_types::ID type,
                                               StringRef New)
       : TheCommandOutput(A), PrimaryInput(Primary), NewOutputType(type),
         NewOutputName(New), Description(desc) {}
diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h
index 26e5987..c86cdba 100644
--- a/include/swift/Driver/ToolChain.h
+++ b/include/swift/Driver/ToolChain.h
@@ -15,7 +15,7 @@
 
 #include "swift/Basic/LLVM.h"
 #include "swift/Driver/Action.h"
-#include "swift/Frontend/Types.h"
+#include "swift/Frontend/FileTypes.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Option/Option.h"
 
@@ -224,7 +224,7 @@
   /// Return the default language type to use for the given extension.
   /// If the extension is empty or is otherwise not recognized, return
   /// the invalid type \c TY_INVALID.
-  virtual types::ID lookupTypeForExtension(StringRef Ext) const;
+  virtual file_types::ID lookupTypeForExtension(StringRef Ext) const;
 
   /// Check whether a clang library with a given name exists.
   ///
diff --git a/include/swift/Driver/Util.h b/include/swift/Driver/Util.h
index 6ebdf64..1752e38 100644
--- a/include/swift/Driver/Util.h
+++ b/include/swift/Driver/Util.h
@@ -14,7 +14,7 @@
 #define SWIFT_DRIVER_UTIL_H
 
 #include "swift/Basic/LLVM.h"
-#include "swift/Frontend/Types.h"
+#include "swift/Frontend/FileTypes.h"
 #include "llvm/ADT/SmallVector.h"
 
 namespace llvm {
@@ -27,9 +27,9 @@
 
 namespace driver {
   /// An input argument from the command line and its inferred type.
-  typedef std::pair<types::ID, const llvm::opt::Arg *> InputPair;
+  using InputPair = std::pair<file_types::ID, const llvm::opt::Arg *>;
   /// Type used for a list of input arguments.
-  typedef SmallVector<InputPair, 16> InputFileList;
+  using InputFileList = SmallVector<InputPair, 16>;
 
   enum class LinkKind {
     None,
@@ -55,7 +55,7 @@
     };
 
     StringRef path;
-    types::ID type;
+    file_types::ID type;
     WhichFiles whichFiles;
   };
 
diff --git a/include/swift/Frontend/ArgsToFrontendOutputsConverter.h b/include/swift/Frontend/ArgsToFrontendOutputsConverter.h
index aad33ba..6273d41 100644
--- a/include/swift/Frontend/ArgsToFrontendOutputsConverter.h
+++ b/include/swift/Frontend/ArgsToFrontendOutputsConverter.h
@@ -24,6 +24,7 @@
 #include <vector>
 
 namespace swift {
+class OutputFileMap;
 
 /// Given the command line arguments and information about the inputs,
 /// Fill in all the information in FrontendInputsAndOutputs.
diff --git a/include/swift/Frontend/FileTypes.h b/include/swift/Frontend/FileTypes.h
new file mode 100644
index 0000000..fb8cf55
--- /dev/null
+++ b/include/swift/Frontend/FileTypes.h
@@ -0,0 +1,85 @@
+//===--- FileTypes.h - Input & Temporary Driver Types -----------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_FRONTEND_FILETYPES_H
+#define SWIFT_FRONTEND_FILETYPES_H
+
+#include "swift/Basic/LLVM.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/StringRef.h"
+#include <functional>
+
+namespace swift {
+namespace file_types {
+enum ID : uint8_t {
+#define TYPE(NAME, ID, TEMP_SUFFIX, FLAGS) TY_##ID,
+#include "swift/Frontend/Types.def"
+#undef TYPE
+  TY_INVALID
+};
+
+/// Return the name of the type for \p Id.
+StringRef getTypeName(ID Id);
+
+/// Return the suffix to use when creating a temp file of this type,
+/// or null if unspecified.
+StringRef getTypeTempSuffix(ID Id);
+
+/// Lookup the type to use for the file extension \p Ext.
+/// If the extension is empty or is otherwise not recognized, return
+/// the invalid type \c TY_INVALID.
+ID lookupTypeForExtension(StringRef Ext);
+
+/// Lookup the type to use for the name \p Name.
+ID lookupTypeForName(StringRef Name);
+
+/// Returns true if the type represents textual data.
+bool isTextual(ID Id);
+
+/// Returns true if the type is produced in the compiler after the LLVM
+/// passes.
+///
+/// For those types the compiler produces multiple output files in multi-
+/// threaded compilation.
+bool isAfterLLVM(ID Id);
+
+/// Returns true if the type is a file that contributes to the Swift module
+/// being compiled.
+///
+/// These need to be passed to the Swift frontend
+bool isPartOfSwiftCompilation(ID Id);
+
+template <typename Fn> void forAllTypes(const Fn &fn);
+} // namespace file_types
+} // end namespace swift
+
+namespace llvm {
+template <> struct DenseMapInfo<swift::file_types::ID> {
+  using ID = swift::file_types::ID;
+  static inline ID getEmptyKey() { return ID::TY_INVALID; }
+  static inline ID getTombstoneKey() {
+    return static_cast<ID>(ID::TY_INVALID + 1);
+  }
+  static unsigned getHashValue(ID Val) { return (unsigned)Val * 37U; }
+  static bool isEqual(ID LHS, ID RHS) { return LHS == RHS; }
+};
+} // namespace llvm
+
+template <typename Fn> void swift::file_types::forAllTypes(const Fn &fn) {
+  static_assert(
+      std::is_constructible<std::function<void(file_types::ID)>, Fn>::value,
+      "must have the signature 'void(file_types::ID)'");
+  for (uint8_t i = 0; i < static_cast<uint8_t>(TY_INVALID); ++i)
+    fn(static_cast<ID>(i));
+}
+
+#endif
diff --git a/include/swift/Frontend/OutputFileMap.h b/include/swift/Frontend/OutputFileMap.h
index a6fa2f9..96fe785 100644
--- a/include/swift/Frontend/OutputFileMap.h
+++ b/include/swift/Frontend/OutputFileMap.h
@@ -14,7 +14,7 @@
 #define SWIFT_DRIVER_OUTPUTFILEMAP_H
 
 #include "swift/Basic/LLVM.h"
-#include "swift/Frontend/Types.h"
+#include "swift/Frontend/FileTypes.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSet.h"
@@ -28,7 +28,7 @@
 
 namespace swift {
 
-typedef llvm::DenseMap<types::ID, std::string> TypeToPathMap;
+typedef llvm::DenseMap<file_types::ID, std::string> TypeToPathMap;
 
 class OutputFileMap {
 private:
diff --git a/include/swift/Frontend/Types.def b/include/swift/Frontend/Types.def
index 3d29dcc..1a559f3 100644
--- a/include/swift/Frontend/Types.def
+++ b/include/swift/Frontend/Types.def
@@ -25,7 +25,7 @@
 // could be displayed to the user, or something which the user could provide.
 
 // The second value is the type id, which will result in a
-// swift::driver::types::TY_XX enum constant.
+// swift::driver::file_types::TY_XX enum constant.
 
 // The third value is the suffix to use when creating temporary files
 // of this type. It is also used when inferring a type from an extension.
diff --git a/include/swift/Frontend/Types.h b/include/swift/Frontend/Types.h
deleted file mode 100644
index ebbc770..0000000
--- a/include/swift/Frontend/Types.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//===--- Types.h - Input & Temporary Driver Types ---------------*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SWIFT_DRIVER_TYPES_H
-#define SWIFT_DRIVER_TYPES_H
-
-#include "swift/Basic/LLVM.h"
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/StringRef.h"
-#include <functional>
-
-namespace swift {
-namespace types {
-  enum ID : uint8_t {
-#define TYPE(NAME, ID, TEMP_SUFFIX, FLAGS) TY_##ID,
-#include "swift/Frontend/Types.def"
-#undef TYPE
-    TY_INVALID
-  };
-
-  /// Return the name of the type for \p Id.
-  StringRef getTypeName(ID Id);
-
-  /// Return the suffix to use when creating a temp file of this type,
-  /// or null if unspecified.
-  StringRef getTypeTempSuffix(ID Id);
-
-  /// Lookup the type to use for the file extension \p Ext.
-  /// If the extension is empty or is otherwise not recognized, return
-  /// the invalid type \c TY_INVALID.
-  ID lookupTypeForExtension(StringRef Ext);
-
-  /// Lookup the type to use for the name \p Name.
-  ID lookupTypeForName(StringRef Name);
-
-  /// Returns true if the type represents textual data.
-  bool isTextual(ID Id);
-
-  /// Returns true if the type is produced in the compiler after the LLVM 
-  /// passes.
-  ///
-  /// For those types the compiler produces multiple output files in multi-
-  /// threaded compilation.
-  bool isAfterLLVM(ID Id);
-
-  /// Returns true if the type is a file that contributes to the Swift module
-  /// being compiled.
-  ///
-  /// These need to be passed to the Swift frontend 
-  bool isPartOfSwiftCompilation(ID Id);
-
-  template <typename Fn>
-  void forAllTypes(const Fn &fn);
-} // end namespace types
-} // end namespace swift
-
-namespace llvm {
-  template<>
-  struct DenseMapInfo<swift::types::ID> {
-    using ID = swift::types::ID;
-    static inline ID getEmptyKey() {
-      return ID::TY_INVALID;
-    }
-    static inline ID getTombstoneKey() {
-      return static_cast<ID>(ID::TY_INVALID + 1);
-    }
-    static unsigned getHashValue(ID Val) {
-      return (unsigned)Val * 37U;
-    }
-    static bool isEqual(ID LHS, ID RHS) {
-      return LHS == RHS;
-    }
-  };
-}
-
-template <typename Fn>
-void swift::types::forAllTypes(const Fn &fn) {
-  static_assert(std::is_constructible<std::function<void(types::ID)>,Fn>::value,
-                "must have the signature 'void(types::ID)'");
-  for (uint8_t i = 0; i < static_cast<uint8_t>(TY_INVALID); ++i)
-    fn(static_cast<ID>(i));
-}
-
-#endif
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index a3bdad4..00633a1 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -1896,11 +1896,27 @@
 };
 using LiteralProtocolDescriptorList = TargetProtocolDescriptorList<InProcess>;
 
+/// A protocol requirement descriptor. This describes a single protocol
+/// requirement in a protocol descriptor. The index of the requirement in
+/// the descriptor determines the offset of the witness in a witness table
+/// for this protocol.
 template <typename Runtime>
 struct TargetProtocolRequirement {
   ProtocolRequirementFlags Flags;
   // TODO: name, type
 
+  /// A function pointer to a global symbol which is used by client code
+  /// to invoke the protocol requirement from a witness table. This pointer
+  /// is also to uniquely identify the requirement in resilient witness
+  /// tables, which is why it appears here.
+  ///
+  /// This forms the basis of our mechanism to hide witness table offsets
+  /// from clients, both when calling protocol requirements and when
+  /// defining witness tables.
+  ///
+  /// Will be null if the protocol is not resilient.
+  RelativeDirectPointer<void, /*nullable*/ true> Function;
+
   /// The optional default implementation of the protocol.
   RelativeDirectPointer<void, /*nullable*/ true> DefaultImplementation;
 };
@@ -4075,10 +4091,11 @@
 /// Initialize the field offset vector for a dependent-layout class, using the
 /// "Universal" layout strategy.
 SWIFT_RUNTIME_EXPORT
-void swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
-                                               size_t numFields,
-                                               const TypeLayout * const *fieldTypes,
-                                               size_t *fieldOffsets);
+void swift_initClassMetadata(ClassMetadata *self,
+                             ClassLayoutFlags flags,
+                             size_t numFields,
+                             const TypeLayout * const *fieldTypes,
+                             size_t *fieldOffsets);
 
 /// \brief Fetch a uniqued metadata for a metatype type.
 SWIFT_RUNTIME_EXPORT
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index cbabad5..6643511 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -914,14 +914,15 @@
          ATTRS(NoUnwind))
 
 // struct FieldInfo { size_t Size; size_t AlignMask; };
-// void swift_initClassMetadata_UniversalStrategy(Metadata *self,
-//                                                size_t numFields,
-//                                                TypeLayout * const *fieldTypes,
-//                                                size_t *fieldOffsets);
-FUNCTION(InitClassMetadataUniversal,
-         swift_initClassMetadata_UniversalStrategy, C_CC,
+// void swift_initClassMetadata(Metadata *self,
+//                              ClassLayoutFlags flags,
+//                              size_t numFields,
+//                              TypeLayout * const *fieldTypes,
+//                              size_t *fieldOffsets);
+FUNCTION(InitClassMetadata,
+         swift_initClassMetadata, C_CC,
          RETURNS(VoidTy),
-         ARGS(TypeMetadataPtrTy, SizeTy,
+         ARGS(TypeMetadataPtrTy, SizeTy, SizeTy,
               Int8PtrPtrTy->getPointerTo(),
               SizeTy->getPointerTo()),
          ATTRS(NoUnwind))
@@ -934,7 +935,8 @@
 FUNCTION(InitStructMetadata,
          swift_initStructMetadata, C_CC,
          RETURNS(VoidTy),
-         ARGS(TypeMetadataPtrTy, SizeTy, SizeTy, Int8PtrPtrTy->getPointerTo(0),
+         ARGS(TypeMetadataPtrTy, SizeTy, SizeTy,
+              Int8PtrPtrTy->getPointerTo(0),
               SizeTy->getPointerTo()),
          ATTRS(NoUnwind))
 
diff --git a/include/swift/SIL/SILGlobalVariable.h b/include/swift/SIL/SILGlobalVariable.h
index 7fe6ba5..de41c52 100644
--- a/include/swift/SIL/SILGlobalVariable.h
+++ b/include/swift/SIL/SILGlobalVariable.h
@@ -206,7 +206,7 @@
 } // end swift namespace
 
 //===----------------------------------------------------------------------===//
-// ilist_traits for SILGLobalVariable
+// ilist_traits for SILGlobalVariable
 //===----------------------------------------------------------------------===//
 
 namespace llvm {
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 5450faf..fffdcb9 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -2478,7 +2478,7 @@
     case Kind::OptionalChain:
     case Kind::OptionalForce:
     case Kind::OptionalWrap:
-      llvm_unreachable("not a computed property");
+      return {};
     case Kind::GettableProperty:
     case Kind::SettableProperty:
     case Kind::External:
diff --git a/include/swift/SIL/SILWitnessTable.h b/include/swift/SIL/SILWitnessTable.h
index 2144263..48f32bd 100644
--- a/include/swift/SIL/SILWitnessTable.h
+++ b/include/swift/SIL/SILWitnessTable.h
@@ -84,20 +84,13 @@
     ProtocolConformance *Witness;
   };
                           
-  /// A witness table entry for an optional requirement that is not present.
-  struct MissingOptionalWitness {
-    /// The witness for the optional requirement that wasn't present.
-    ValueDecl *Witness;
-  };
-  
   /// A witness table entry kind.
   enum WitnessKind {
     Invalid,
     Method,
     AssociatedType,
     AssociatedTypeProtocol,
-    BaseProtocol,
-    MissingOptional
+    BaseProtocol
   };
   
   /// A witness table entry.
@@ -108,7 +101,6 @@
       AssociatedTypeWitness AssociatedType;
       AssociatedTypeProtocolWitness AssociatedTypeProtocol;
       BaseProtocolWitness BaseProtocol;
-      MissingOptionalWitness MissingOptional;
     };
     
   public:
@@ -132,10 +124,6 @@
         BaseProtocol(BaseProtocol)
     {}
     
-    Entry(const MissingOptionalWitness &MissingOptional)
-      : Kind(WitnessKind::MissingOptional), MissingOptional(MissingOptional) {
-    }
-    
     WitnessKind getKind() const { return Kind; }
     
     const MethodWitness &getMethodWitness() const {
@@ -156,11 +144,6 @@
       return BaseProtocol;
     }
     
-    const MissingOptionalWitness &getMissingOptionalWitness() const {
-      assert(Kind == WitnessKind::MissingOptional);
-      return MissingOptional;
-    }
-
     void removeWitnessMethod() {
       assert(Kind == WitnessKind::Method);
       if (Method.Witness) {
diff --git a/include/swift/Strings.h b/include/swift/Strings.h
index 7a501d5..f471278 100644
--- a/include/swift/Strings.h
+++ b/include/swift/Strings.h
@@ -35,6 +35,8 @@
   static const char SWIFT_ONONE_SUPPORT[] = "SwiftOnoneSupport";
   /// The name of the SwiftShims module, which contains private stdlib decls.
   static const char SWIFT_SHIMS_NAME[] = "SwiftShims";
+  /// The name of the Builtin module, which contains Builtin functions.
+  static const char BUILTIN_NAME[] = "Builtin";
   /// The prefix of module names used by LLDB to capture Swift expressions
   static const char LLDB_EXPRESSIONS_MODULE_NAME_PREFIX[] = "__lldb_expr_";
 
@@ -42,6 +44,43 @@
   static const char MANGLING_MODULE_OBJC[] = "__C";
   /// The name of the fake module used to hold synthesized ClangImporter things.
   static const char MANGLING_MODULE_CLANG_IMPORTER[] = "__C_Synthesized";
+
+  /// The name of the Builtin type prefix
+  static const char BUILTIN_TYPE_NAME_PREFIX[] = "Builtin.";
+  /// The name of the Builtin type for Int
+  static const char BUILTIN_TYPE_NAME_INT[] = "Builtin.Int";
+  /// The name of the Builtin type for Int8
+  static const char BUILTIN_TYPE_NAME_INT8[] = "Builtin.Int8";
+  /// The name of the Builtin type for Int16
+  static const char BUILTIN_TYPE_NAME_INT16[] = "Builtin.Int16";
+  /// The name of the Builtin type for Int32
+  static const char BUILTIN_TYPE_NAME_INT32[] = "Builtin.Int32";
+  /// The name of the Builtin type for Int64
+  static const char BUILTIN_TYPE_NAME_INT64[] = "Builtin.Int64";
+  /// The name of the Builtin type for Int128
+  static const char BUILTIN_TYPE_NAME_INT128[] = "Builtin.Int128";
+  /// The name of the Builtin type for Int256
+  static const char BUILTIN_TYPE_NAME_INT256[] = "Builtin.Int256";
+  /// The name of the Builtin type for Int512
+  static const char BUILTIN_TYPE_NAME_INT512[] = "Builtin.Int512";
+  /// The name of the Builtin type for Float
+  static const char BUILTIN_TYPE_NAME_FLOAT[] = "Builtin.Float";
+  /// The name of the Builtin type for NativeObject
+  static const char BUILTIN_TYPE_NAME_NATIVEOBJECT[] = "Builtin.NativeObject";
+  /// The name of the Builtin type for BridgeObject
+  static const char BUILTIN_TYPE_NAME_BRIDGEOBJECT[] = "Builtin.BridgeObject";
+  /// The name of the Builtin type for RawPointer
+  static const char BUILTIN_TYPE_NAME_RAWPOINTER[] = "Builtin.RawPointer";
+  /// The name of the Builtin type for UnsafeValueBuffer
+  static const char BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER[] = "Builtin.UnsafeValueBuffer";
+  /// The name of the Builtin type for UnknownObject
+  static const char BUILTIN_TYPE_NAME_UNKNOWNOBJECT[] = "Builtin.UnknownObject";
+  /// The name of the Builtin type for Vector
+  static const char BUILTIN_TYPE_NAME_VEC[] = "Builtin.Vec";
+  /// The name of the Builtin type for SILToken
+  static const char BUILTIN_TYPE_NAME_SILTOKEN[] = "Builtin.SILToken";
+  /// The name of the Builtin type for Word
+  static const char BUILTIN_TYPE_NAME_WORD[] = "Builtin.Word";
 } // end namespace swift
 
 #endif // SWIFT_STRINGS_H
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 14f5bd1..c29135e 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -426,7 +426,7 @@
 }
 
 static ModuleDecl *createBuiltinModule(ASTContext &ctx) {
-  auto M = ModuleDecl::create(ctx.getIdentifier("Builtin"), ctx);
+  auto M = ModuleDecl::create(ctx.getIdentifier(BUILTIN_NAME), ctx);
   M->addFile(*new (ctx) BuiltinUnit(*M));
   return M;
 }
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 2768f45..5b3fcf0 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -3200,23 +3200,23 @@
   }
 
   void visitBuiltinRawPointerType(BuiltinRawPointerType *T) {
-    Printer << "Builtin.RawPointer";
+    Printer << BUILTIN_TYPE_NAME_RAWPOINTER;
   }
 
   void visitBuiltinNativeObjectType(BuiltinNativeObjectType *T) {
-    Printer << "Builtin.NativeObject";
+    Printer << BUILTIN_TYPE_NAME_NATIVEOBJECT;
   }
 
   void visitBuiltinUnknownObjectType(BuiltinUnknownObjectType *T) {
-    Printer << "Builtin.UnknownObject";
+    Printer << BUILTIN_TYPE_NAME_UNKNOWNOBJECT;
   }
 
   void visitBuiltinBridgeObjectType(BuiltinBridgeObjectType *T) {
-    Printer << "Builtin.BridgeObject";
+    Printer << BUILTIN_TYPE_NAME_BRIDGEOBJECT;
   }
 
   void visitBuiltinUnsafeValueBufferType(BuiltinUnsafeValueBufferType *T) {
-    Printer << "Builtin.UnsafeValueBuffer";
+    Printer << BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER;
   }
 
   void visitBuiltinVectorType(BuiltinVectorType *T) {
@@ -3228,21 +3228,21 @@
         llvm::raw_svector_ostream UnderlyingOS(UnderlyingStrVec);
         T->getElementType().print(UnderlyingOS);
       }
-      if (UnderlyingStrVec.startswith("Builtin."))
+      if (UnderlyingStrVec.startswith(BUILTIN_TYPE_NAME_PREFIX))
         UnderlyingStr = UnderlyingStrVec.substr(8);
       else
         UnderlyingStr = UnderlyingStrVec;
     }
 
-    Printer << "Builtin.Vec" << T->getNumElements() << "x" << UnderlyingStr;
+    Printer << BUILTIN_TYPE_NAME_VEC << T->getNumElements() << "x" << UnderlyingStr;
   }
 
   void visitBuiltinIntegerType(BuiltinIntegerType *T) {
     auto width = T->getWidth();
     if (width.isFixedWidth()) {
-      Printer << "Builtin.Int" << width.getFixedWidth();
+      Printer << BUILTIN_TYPE_NAME_INT << width.getFixedWidth();
     } else if (width.isPointerWidth()) {
-      Printer << "Builtin.Word";
+      Printer << BUILTIN_TYPE_NAME_WORD;
     } else {
       llvm_unreachable("impossible bit width");
     }
@@ -3260,7 +3260,7 @@
   }
 
   void visitSILTokenType(SILTokenType *T) {
-    Printer << "Builtin.SILToken";
+    Printer << BUILTIN_TYPE_NAME_SILTOKEN;
   }
 
   void visitNameAliasType(NameAliasType *T) {
diff --git a/lib/AST/DiagnosticConsumer.cpp b/lib/AST/DiagnosticConsumer.cpp
index 230dc55..3678e1a 100644
--- a/lib/AST/DiagnosticConsumer.cpp
+++ b/lib/AST/DiagnosticConsumer.cpp
@@ -19,6 +19,7 @@
 #include "swift/AST/DiagnosticEngine.h"
 #include "swift/Basic/Defer.h"
 #include "swift/Basic/SourceManager.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Debug.h"
@@ -116,6 +117,20 @@
   // FileSpecificDiagnosticConsumer to be set up before the source files are
   // actually loaded.
   if (ConsumersOrderedByRange.empty()) {
+
+    // It's possible to get here while a bridging header PCH is being
+    // attached-to, if there's some sort of AST-reader warning or error, which
+    // happens before CompilerInstance::setUpInputs(), at which point _no_
+    // source buffers are loaded in yet. In that case we return nullptr, rather
+    // than trying to build a nonsensical map (and actually crashing since we
+    // can't find buffers for the inputs).
+    assert(!SubConsumers.empty());
+    if (!SM.getIDForBufferIdentifier(SubConsumers.begin()->first).hasValue()) {
+      assert(llvm::none_of(SubConsumers, [&](const ConsumerPair &pair) {
+            return SM.getIDForBufferIdentifier(pair.first).hasValue();
+          }));
+      return nullptr;
+    }
     auto *mutableThis = const_cast<FileSpecificDiagnosticConsumer*>(this);
     mutableThis->computeConsumersOrderedByRange(SM);
   }
diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp
index 3629b03..a40db12 100644
--- a/lib/AST/GenericEnvironment.cpp
+++ b/lib/AST/GenericEnvironment.cpp
@@ -230,3 +230,25 @@
   genericSig->getSubstitutions(subMap, result);
   return genericSig->getASTContext().AllocateCopy(result);
 }
+
+std::pair<Type, ProtocolConformanceRef>
+GenericEnvironment::mapConformanceRefIntoContext(GenericEnvironment *genericEnv,
+                                           Type conformingType,
+                                           ProtocolConformanceRef conformance) {
+  if (!genericEnv)
+    return {conformingType, conformance};
+  
+  return genericEnv->mapConformanceRefIntoContext(conformingType, conformance);
+}
+
+std::pair<Type, ProtocolConformanceRef>
+GenericEnvironment::mapConformanceRefIntoContext(
+                                     Type conformingInterfaceType,
+                                     ProtocolConformanceRef conformance) const {
+  auto contextConformance = conformance.subst(conformingInterfaceType,
+    QueryInterfaceTypeSubstitutions(this),
+    LookUpConformanceInSignature(*getGenericSignature()));
+  
+  auto contextType = mapTypeIntoContext(conformingInterfaceType);
+  return {contextType, contextConformance};
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 9b59b87..0ca395b 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1466,26 +1466,14 @@
       if (bound != Bindings.end()) {
         return bound->second->isEqual(subst);
       }
-      
-      auto canBindClassConstrainedArchetype = [](CanType t) -> bool {
-        // Classes and class-constrained archetypes.
-        if (t->mayHaveSuperclass())
-          return true;
-        
-        // Pure @objc existentials.
-        if (t->isObjCExistentialType())
-          return true;
-        
-        return false;
-      };
-      
+
       // Check that the archetype isn't constrained in a way that makes the
       // binding impossible.
       // For instance, if the archetype is class-constrained, and the binding
       // is not a class, it can never be bound.
-      if (orig->requiresClass() && !canBindClassConstrainedArchetype(subst))
+      if (orig->requiresClass() && !subst->satisfiesClassConstraint())
         return false;
-      
+
       // TODO: If the archetype has a superclass constraint, check that the
       // substitution is a subclass.
       
diff --git a/lib/AST/TypeJoinMeet.cpp b/lib/AST/TypeJoinMeet.cpp
index cffb11f..d32e4f4 100644
--- a/lib/AST/TypeJoinMeet.cpp
+++ b/lib/AST/TypeJoinMeet.cpp
@@ -73,9 +73,10 @@
   CanType visitProtocolCompositionType(CanType second);
   CanType visitLValueType(CanType second);
   CanType visitInOutType(CanType second);
+  CanType visitBuiltinType(CanType second);
 
   CanType visitType(CanType second) {
-    llvm_unreachable("Unimplemented type visitor!");
+    return Unimplemented;
   }
 
 public:
@@ -368,6 +369,13 @@
 
 CanType TypeJoin::visitInOutType(CanType second) { return Unimplemented; }
 
+CanType TypeJoin::visitBuiltinType(CanType second) {
+  assert(First != second);
+
+  // BuiltinType with any non-equal type results in Any.
+  return TheAnyType;
+}
+
 } // namespace
 
 Optional<Type> Type::join(Type first, Type second) {
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index 3d9e6c4..f20b5ce 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -17,6 +17,7 @@
 #include "clang/Basic/CharInfo.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
 #include "swift/AST/DiagnosticsParse.h"
 #include "swift/Basic/LLVM.h"
 #include "swift/Basic/Version.h"
@@ -303,6 +304,12 @@
     return None;
   case 1:
     break;
+  case 2:
+    // The only valid explicit language version with a minor
+    // component is 4.2.
+    if (Components[0] == 4 && Components[1] == 2)
+      break;
+    return None;
   default:
     // We do not want to permit users requesting more precise effective language
     // versions since accepting such an argument promises more than we're able
@@ -326,6 +333,9 @@
   case 4:
     static_assert(SWIFT_VERSION_MAJOR == 4,
                   "getCurrentLanguageVersion is no longer correct here");
+    // Version '4' on its own implies '4.1.50'.
+    if (size() == 1)
+      return Version{4, 1, 50};
     return Version::getCurrentLanguageVersion();
   case 5:
     return Version{5, 0};
@@ -342,6 +352,16 @@
   return res;
 }
 
+std::string Version::asAPINotesVersionString() const {
+  // Other than for "4.2.x", map the Swift major version into
+  // the API notes version for Swift. This has the effect of allowing
+  // API notes to effect changes only on Swift major versions,
+  // not minor versions.
+  if (size() >= 2 && Components[0] == 4 && Components[1] == 2)
+    return "4.2";
+  return llvm::itostr(Components[0]);
+}
+
 bool operator>=(const class Version &lhs,
                 const class Version &rhs) {
 
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index ae49fb1..217d6f6 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -611,12 +611,8 @@
   }
   invocationArgStrs.push_back("-iapinotes-modules");
   invocationArgStrs.push_back(searchPathOpts.RuntimeLibraryImportPath);
-
-  // Map the Swift major version into the API notes version for Swift. This
-  // has the effect of allowing API notes to effect changes only on Swift
-  // major versions, not minor versions.
   invocationArgStrs.push_back("-fapinotes-swift-version=" +
-                              llvm::itostr(languageVersion[0]));
+      languageVersion.asAPINotesVersionString());
 }
 
 static void
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 5c435a3..58c83c0 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -3250,23 +3250,24 @@
       if (hasZeroInitializableStorage) {
         // Add constructors for the struct.
         ctors.push_back(createDefaultConstructor(Impl, result));
-        if (hasReferenceableFields && hasMemberwiseInitializer) {
-          // The default zero initializer suppresses the implicit value
-          // constructor that would normally be formed, so we have to add that
-          // explicitly as well.
-          //
-          // If we can completely represent the struct in SIL, leave the body
-          // implicit, otherwise synthesize one to call property setters.
-          bool wantBody = (hasUnreferenceableStorage &&
-                           !Impl.hasFinishedTypeChecking());
-          auto valueCtor = createValueConstructor(Impl, result, members,
-                                                  /*want param names*/true,
-                                                  /*want body*/wantBody);
-          if (!hasUnreferenceableStorage)
-            valueCtor->setIsMemberwiseInitializer();
+      }
 
-          ctors.push_back(valueCtor);
-        }
+      if (hasReferenceableFields && hasMemberwiseInitializer) {
+        // The default zero initializer suppresses the implicit value
+        // constructor that would normally be formed, so we have to add that
+        // explicitly as well.
+        //
+        // If we can completely represent the struct in SIL, leave the body
+        // implicit, otherwise synthesize one to call property setters.
+        bool wantBody = (hasUnreferenceableStorage &&
+                         !Impl.hasFinishedTypeChecking());
+        auto valueCtor = createValueConstructor(Impl, result, members,
+                                                /*want param names*/true,
+                                                /*want body*/wantBody);
+        if (!hasUnreferenceableStorage)
+          valueCtor->setIsMemberwiseInitializer();
+
+        ctors.push_back(valueCtor);
       }
 
       for (auto member : members) {
diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp
index 211ca0d..8fcb6eb 100644
--- a/lib/ClangImporter/ImportName.cpp
+++ b/lib/ClangImporter/ImportName.cpp
@@ -578,6 +578,8 @@
   if (!bestSoFar.empty() && bestSoFar <= info.Version)
     return VersionedSwiftNameAction::Ignore;
 
+  auto requestedClangVersion = requestedVersion.asClangVersionTuple();
+
   if (info.IsReplacedByActive) {
     // We know that there are no versioned names between the active version and
     // a replacement version, because otherwise /that/ name would be active.
@@ -586,7 +588,7 @@
     // new value that is now active. (Special case: replacement = 0 means that
     // a header annotation was replaced by an unversioned API notes annotation.)
     if (info.Version.empty() ||
-        info.Version.getMajor() >= requestedVersion.majorVersionNumber()) {
+        info.Version >= requestedClangVersion) {
       return VersionedSwiftNameAction::ResetToActive;
     }
     if (bestSoFar.empty())
@@ -594,7 +596,7 @@
     return VersionedSwiftNameAction::Ignore;
   }
 
-  if (info.Version.getMajor() < requestedVersion.majorVersionNumber())
+  if (info.Version < requestedClangVersion)
     return VersionedSwiftNameAction::Ignore;
   return VersionedSwiftNameAction::Use;
 }
diff --git a/lib/ClangImporter/ImportName.h b/lib/ClangImporter/ImportName.h
index 83e302a..dc67c5c 100644
--- a/lib/ClangImporter/ImportName.h
+++ b/lib/ClangImporter/ImportName.h
@@ -56,12 +56,35 @@
 public:
   /// Map a language version into an import name version.
   static ImportNameVersion fromOptions(const LangOptions &langOpts) {
-    return ImportNameVersion(langOpts.EffectiveLanguageVersion[0]);
+    // We encode the 'rawValue' as just major version numbers with the
+    // exception of '4.2', which is a special minor version that can impact
+    // importing of names.  We treat that with a rawValue of 5, and treat
+    // all major values of 5 or higher as being rawValue = majorversion + 1.
+    const auto &version = langOpts.EffectiveLanguageVersion;
+    if (version.size() > 1 && version[0] == 4 && version[1] == 2) {
+      return ImportNameVersion::swift4_2();
+    }
+    unsigned major = version[0];
+    return ImportNameVersion(major >= 5 ? major + 1 : major);
   }
 
   unsigned majorVersionNumber() const {
     assert(*this != ImportNameVersion::raw());
-    return rawValue;
+    if (*this == ImportNameVersion::swift4_2())
+      return 4;
+    return rawValue < 5 ? rawValue : rawValue - 1;
+  }
+
+  unsigned minorVersionNumber() const {
+    assert(*this != ImportNameVersion::raw());
+    if (*this == ImportNameVersion::swift4_2())
+      return 2;
+    return 0;
+  }
+
+  clang::VersionTuple asClangVersionTuple() const {
+    assert(*this != ImportNameVersion::raw());
+    return clang::VersionTuple(majorVersionNumber(), minorVersionNumber());    
   }
 
   bool operator==(ImportNameVersion other) const {
@@ -105,12 +128,17 @@
     return ImportNameVersion{2, AsConstExpr};
   }
 
+  /// Names as they appeared in Swift 4.2 family.
+  static constexpr inline ImportNameVersion swift4_2() {
+    return ImportNameVersion{5, AsConstExpr};
+  }
+
   /// The latest supported version.
   ///
   /// FIXME: All other version information is in Version.h. Can this go there
   /// instead?
   static constexpr inline ImportNameVersion maxVersion() {
-    return ImportNameVersion{5, AsConstExpr};
+    return ImportNameVersion{6, AsConstExpr};
   }
 
   /// The version which should be used for importing types, which need to have
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index f5fff72..7a3a3db 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -140,7 +140,10 @@
 int swift::Demangle::getManglingPrefixLength(llvm::StringRef mangledName) {
   if (mangledName.empty()) return 0;
 
-  llvm::StringRef prefixes[] = {/*Swift 4*/ "_T0", /*Swift > 4*/ "$S", "_$S"};
+  llvm::StringRef prefixes[] = {
+    /*Swift 4*/   "_T0",
+    /*Swift 4.x*/ "$S", "_$S",
+    /*Swift 5+*/  "$s", "_$s"};
 
   // Look for any of the known prefixes
   for (auto prefix : prefixes) {
@@ -923,18 +926,18 @@
   switch (nextChar()) {
     case 'b':
       Ty = createNode(Node::Kind::BuiltinTypeName,
-                               "Builtin.BridgeObject");
+                               BUILTIN_TYPE_NAME_BRIDGEOBJECT);
       break;
     case 'B':
       Ty = createNode(Node::Kind::BuiltinTypeName,
-                              "Builtin.UnsafeValueBuffer");
+                              BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER);
       break;
     case 'f': {
       int size = demangleIndex() - 1;
       if (size <= 0)
         return nullptr;
       CharVector name;
-      name.append("Builtin.Float", *this);
+      name.append(BUILTIN_TYPE_NAME_FLOAT, *this);
       name.append(size, *this);
       Ty = createNode(Node::Kind::BuiltinTypeName, name);
       break;
@@ -944,7 +947,7 @@
       if (size <= 0)
         return nullptr;
       CharVector name;
-      name.append("Builtin.Int", *this);
+      name.append(BUILTIN_TYPE_NAME_INT, *this);
       name.append(size, *this);
       Ty = createNode(Node::Kind::BuiltinTypeName, name);
       break;
@@ -955,34 +958,34 @@
         return nullptr;
       NodePointer EltType = popTypeAndGetChild();
       if (!EltType || EltType->getKind() != Node::Kind::BuiltinTypeName ||
-          !EltType->getText().startswith("Builtin."))
+          !EltType->getText().startswith(BUILTIN_TYPE_NAME_PREFIX))
         return nullptr;
       CharVector name;
-      name.append("Builtin.Vec", *this);
+      name.append(BUILTIN_TYPE_NAME_VEC, *this);
       name.append(elts, *this);
       name.push_back('x', *this);
-      name.append(EltType->getText().substr(sizeof("Builtin.") - 1), *this);
+      name.append(EltType->getText().substr(strlen(BUILTIN_TYPE_NAME_PREFIX)), *this);
       Ty = createNode(Node::Kind::BuiltinTypeName, name);
       break;
     }
     case 'O':
       Ty = createNode(Node::Kind::BuiltinTypeName,
-                               "Builtin.UnknownObject");
+                               BUILTIN_TYPE_NAME_UNKNOWNOBJECT);
       break;
     case 'o':
       Ty = createNode(Node::Kind::BuiltinTypeName,
-                               "Builtin.NativeObject");
+                               BUILTIN_TYPE_NAME_NATIVEOBJECT);
       break;
     case 'p':
       Ty = createNode(Node::Kind::BuiltinTypeName,
-                               "Builtin.RawPointer");
+                               BUILTIN_TYPE_NAME_RAWPOINTER);
       break;
     case 't':
-      Ty = createNode(Node::Kind::BuiltinTypeName, "Builtin.SILToken");
+      Ty = createNode(Node::Kind::BuiltinTypeName, BUILTIN_TYPE_NAME_SILTOKEN);
       break;
     case 'w':
       Ty = createNode(Node::Kind::BuiltinTypeName,
-                               "Builtin.Word");
+                               BUILTIN_TYPE_NAME_WORD);
       break;
     default:
       return nullptr;
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 5a50dfa..04adffe 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -598,25 +598,25 @@
   Buffer << 'B';
   StringRef text = node->getText();
 
-  if (text == "Builtin.BridgeObject") {
+  if (text == BUILTIN_TYPE_NAME_BRIDGEOBJECT) {
     Buffer << 'b';
-  } else if (text == "Builtin.UnsafeValueBuffer") {
+  } else if (text == BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER) {
     Buffer << 'B';
-  } else if (text == "Builtin.UnknownObject") {
+  } else if (text == BUILTIN_TYPE_NAME_UNKNOWNOBJECT) {
     Buffer << 'O';
-  } else if (text == "Builtin.NativeObject") {
+  } else if (text == BUILTIN_TYPE_NAME_NATIVEOBJECT) {
     Buffer << 'o';
-  } else if (text == "Builtin.RawPointer") {
+  } else if (text == BUILTIN_TYPE_NAME_RAWPOINTER) {
     Buffer << 'p';
-  } else if (text == "Builtin.SILToken") {
+  } else if (text == BUILTIN_TYPE_NAME_SILTOKEN) {
     Buffer << 't';
-  } else if (text == "Builtin.Word") {
+  } else if (text == BUILTIN_TYPE_NAME_WORD) {
     Buffer << 'w';
-  } else if (stripPrefix(text, "Builtin.Int")) {
+  } else if (stripPrefix(text, BUILTIN_TYPE_NAME_INT)) {
     Buffer << 'i' << text << '_';
-  } else if (stripPrefix(text, "Builtin.Float")) {
+  } else if (stripPrefix(text, BUILTIN_TYPE_NAME_FLOAT)) {
     Buffer << 'f' << text << '_';
-  } else if (stripPrefix(text, "Builtin.Vec")) {
+  } else if (stripPrefix(text, BUILTIN_TYPE_NAME_VEC)) {
     auto split = text.split('x');
     if (split.second == "RawPointer") {
       Buffer << 'p';
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index 104b27b..95df884 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -18,20 +18,20 @@
 using namespace swift::driver;
 using namespace llvm::opt;
 
-const char *Action::getClassName(ActionClass AC) {
+const char *Action::getClassName(Kind AC) {
   switch (AC) {
-    case Input: return "input";
-    case CompileJob: return "compile";
-    case InterpretJob: return "interpret";
-    case BackendJob: return "backend";
-    case MergeModuleJob: return "merge-module";
-    case ModuleWrapJob: return "modulewrap";
-    case AutolinkExtractJob: return "swift-autolink-extract";
-    case REPLJob: return "repl";
-    case LinkJob: return "link";
-    case GenerateDSYMJob: return "generate-dSYM";
-    case VerifyDebugInfoJob: return "verify-debug-info";
-    case GeneratePCHJob: return "generate-pch";
+  case Kind::Input:  return "input";
+  case Kind::CompileJob:  return "compile";
+  case Kind::InterpretJob:  return "interpret";
+  case Kind::BackendJob:  return "backend";
+  case Kind::MergeModuleJob:  return "merge-module";
+  case Kind::ModuleWrapJob:  return "modulewrap";
+  case Kind::AutolinkExtractJob:  return "swift-autolink-extract";
+  case Kind::REPLJob:  return "repl";
+  case Kind::LinkJob:  return "link";
+  case Kind::GenerateDSYMJob:  return "generate-dSYM";
+  case Kind::VerifyDebugInfoJob:  return "verify-debug-info";
+  case Kind::GeneratePCHJob:  return "generate-pch";
   }
 
   llvm_unreachable("invalid class");
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 6ce16d7..3244b5e 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -361,7 +361,7 @@
                              SmallVector<const Job *, N> &Dependents) {
       const CommandOutput &Output = FinishedCmd->getOutput();
       StringRef DependenciesFile =
-        Output.getAdditionalOutputForType(types::TY_SwiftDeps);
+          Output.getAdditionalOutputForType(file_types::TY_SwiftDeps);
 
       if (DependenciesFile.empty()) {
         // If this job doesn't track dependencies, it must always be run.
@@ -602,7 +602,8 @@
         // FIXME: We can probably do better here!
         Job::Condition Condition = Job::Condition::Always;
         StringRef DependenciesFile =
-          Cmd->getOutput().getAdditionalOutputForType(types::TY_SwiftDeps);
+            Cmd->getOutput().getAdditionalOutputForType(
+                file_types::TY_SwiftDeps);
         if (!DependenciesFile.empty()) {
           if (Cmd->getCondition() == Job::Condition::NewlyAdded) {
             DepGraph.addIndependentNode(Cmd);
@@ -950,7 +951,8 @@
         for (const Job *Cmd : Comp.getJobs()) {
           // Skip files that don't use dependency analysis.
           StringRef DependenciesFile =
-            Cmd->getOutput().getAdditionalOutputForType(types::TY_SwiftDeps);
+              Cmd->getOutput().getAdditionalOutputForType(
+                  file_types::TY_SwiftDeps);
           if (DependenciesFile.empty())
             continue;
 
@@ -1258,7 +1260,7 @@
   }
 
   for (auto inputPair : inputFiles) {
-    if (!types::isPartOfSwiftCompilation(inputPair.first))
+    if (!file_types::isPartOfSwiftCompilation(inputPair.first))
       continue;
     out << inputPair.second->getValue() << "\n";
   }
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 275df8d..704c14c 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -496,7 +496,7 @@
 static void validateEmbedBitcode(DerivedArgList &Args, OutputInfo &OI,
                                  DiagnosticEngine &Diags) {
   if (Args.hasArg(options::OPT_embed_bitcode) &&
-      OI.CompilerOutputType != types::TY_Object) {
+      OI.CompilerOutputType != file_types::TY_Object) {
     Diags.diagnose(SourceLoc(), diag::warn_ignore_embed_bitcode);
     Args.eraseArg(options::OPT_embed_bitcode);
   }
@@ -604,7 +604,7 @@
     if (Inputs.size() == 1) {
       InputName = Inputs[0].second->getSpelling();
     }
-    StringRef OutputType = types::getTypeTempSuffix(OI.CompilerOutputType);
+    StringRef OutputType = file_types::getTypeTempSuffix(OI.CompilerOutputType);
     StatsReporter = llvm::make_unique<UnifiedStatsReporter>("swift-driver",
                                                             OI.ModuleName,
                                                             InputName,
@@ -614,9 +614,9 @@
                                                             A->getValue());
   }
 
-  assert(OI.CompilerOutputType != types::ID::TY_INVALID &&
+  assert(OI.CompilerOutputType != file_types::ID::TY_INVALID &&
          "buildOutputInfo() must set a valid output type!");
-  
+
   validateEmbedBitcode(*TranslatedArgList, OI, Diags);
 
   if (OI.CompilerMode == OutputInfo::Mode::REPL)
@@ -651,7 +651,7 @@
     } else {
       StringRef buildRecordPath;
       if (auto *masterOutputMap = OFM->getOutputMapForSingleOutput()) {
-        auto iter = masterOutputMap->find(types::TY_SwiftDeps);
+        auto iter = masterOutputMap->find(file_types::TY_SwiftDeps);
         if (iter != masterOutputMap->end())
           buildRecordPath = iter->second;
       }
@@ -659,7 +659,7 @@
       if (buildRecordPath.empty()) {
         Diags.diagnose(SourceLoc(),
                        diag::incremental_requires_build_record_entry,
-                       types::getTypeName(types::TY_SwiftDeps));
+                       file_types::getTypeName(file_types::TY_SwiftDeps));
         rebuildEverything = true;
 
       } else {
@@ -750,7 +750,8 @@
 
   if (OFM) {
     if (auto *masterOutputMap = OFM->getOutputMapForSingleOutput()) {
-      C->setCompilationRecordPath(masterOutputMap->lookup(types::TY_SwiftDeps));
+      C->setCompilationRecordPath(
+          masterOutputMap->lookup(file_types::TY_SwiftDeps));
 
       auto buildEntry = outOfDateMap.find(nullptr);
       if (buildEntry != outOfDateMap.end())
@@ -775,8 +776,7 @@
   return A;
 }
 
-
-typedef std::function<void(InputArgList &, unsigned)> RemainingArgsHandler;
+using RemainingArgsHandler = std::function<void(InputArgList &, unsigned)>;
 
 std::unique_ptr<InputArgList>
 parseArgsUntil(const llvm::opt::OptTable& Opts,
@@ -974,27 +974,27 @@
   for (Arg *A : Args) {
     if (A->getOption().getKind() == Option::InputClass) {
       StringRef Value = A->getValue();
-      types::ID Ty = types::TY_INVALID;
+      file_types::ID Ty = file_types::TY_INVALID;
 
       // stdin must be handled specially.
       if (Value.equals("-")) {
         // By default, treat stdin as Swift input.
-        Ty = types::TY_Swift;
+        Ty = file_types::TY_Swift;
       } else {
         // Otherwise lookup by extension.
         Ty = TC.lookupTypeForExtension(llvm::sys::path::extension(Value));
 
-        if (Ty == types::TY_INVALID) {
+        if (Ty == file_types::TY_INVALID) {
           // By default, treat inputs with no extension, or with an
           // extension that isn't recognized, as object files.
-          Ty = types::TY_Object;
+          Ty = file_types::TY_Object;
         }
       }
 
       if (checkInputExistence(*this, Args, Diags, Value))
         Inputs.push_back(std::make_pair(Ty, A));
 
-      if (Ty == types::TY_Swift) {
+      if (Ty == file_types::TY_Swift) {
         StringRef Basename = llvm::sys::path::filename(Value);
         if (!SourceFileNames.insert({Basename, Value}).second) {
           Diags.diagnose(SourceLoc(), diag::error_two_files_same_name,
@@ -1102,14 +1102,14 @@
     OI.CompilerMode = OutputInfo::Mode::Immediate;
     if (Inputs.empty())
       OI.CompilerMode = OutputInfo::Mode::REPL;
-    OI.CompilerOutputType = types::TY_Nothing;
+    OI.CompilerOutputType = file_types::TY_Nothing;
 
   } else { // DriverKind::Batch
     OI.CompilerMode = OutputInfo::Mode::StandardCompile;
     if (Args.hasArg(options::OPT_whole_module_optimization,
                     options::OPT_index_file))
       OI.CompilerMode = OutputInfo::Mode::SingleCompile;
-    OI.CompilerOutputType = types::TY_Object;
+    OI.CompilerOutputType = file_types::TY_Object;
   }
 
   if (const Arg *A = Args.getLastArg(options::OPT_num_threads)) {
@@ -1123,7 +1123,7 @@
 
   if (!OutputModeArg) {
     if (Args.hasArg(options::OPT_emit_module, options::OPT_emit_module_path)) {
-      OI.CompilerOutputType = types::TY_SwiftModuleFile;
+      OI.CompilerOutputType = file_types::TY_SwiftModuleFile;
     } else if (driverKind != DriverKind::Interactive) {
       OI.LinkAction = LinkKind::Executable;
     }
@@ -1134,53 +1134,53 @@
     switch (OutputModeArg->getOption().getID()) {
     case options::OPT_emit_executable:
       OI.LinkAction = LinkKind::Executable;
-      OI.CompilerOutputType = types::TY_Object;
+      OI.CompilerOutputType = file_types::TY_Object;
       break;
 
     case options::OPT_emit_library:
       OI.LinkAction = LinkKind::DynamicLibrary;
-      OI.CompilerOutputType = types::TY_Object;
+      OI.CompilerOutputType = file_types::TY_Object;
       break;
 
     case options::OPT_emit_object:
-      OI.CompilerOutputType = types::TY_Object;
+      OI.CompilerOutputType = file_types::TY_Object;
       break;
 
     case options::OPT_emit_assembly:
-      OI.CompilerOutputType = types::TY_Assembly;
+      OI.CompilerOutputType = file_types::TY_Assembly;
       break;
 
     case options::OPT_emit_sil:
-      OI.CompilerOutputType = types::TY_SIL;
+      OI.CompilerOutputType = file_types::TY_SIL;
       break;
 
     case options::OPT_emit_silgen:
-      OI.CompilerOutputType = types::TY_RawSIL;
+      OI.CompilerOutputType = file_types::TY_RawSIL;
       break;
 
     case options::OPT_emit_sib:
-      OI.CompilerOutputType = types::TY_SIB;
+      OI.CompilerOutputType = file_types::TY_SIB;
       break;
 
     case options::OPT_emit_sibgen:
-      OI.CompilerOutputType = types::TY_RawSIB;
+      OI.CompilerOutputType = file_types::TY_RawSIB;
       break;
 
     case options::OPT_emit_ir:
-      OI.CompilerOutputType = types::TY_LLVM_IR;
+      OI.CompilerOutputType = file_types::TY_LLVM_IR;
       break;
 
     case options::OPT_emit_bc:
-      OI.CompilerOutputType = types::TY_LLVM_BC;
+      OI.CompilerOutputType = file_types::TY_LLVM_BC;
       break;
 
     case options::OPT_emit_pch:
       OI.CompilerMode = OutputInfo::Mode::SingleCompile;
-      OI.CompilerOutputType = types::TY_PCH;
+      OI.CompilerOutputType = file_types::TY_PCH;
       break;
 
     case options::OPT_emit_imported_modules:
-      OI.CompilerOutputType = types::TY_ImportedModules;
+      OI.CompilerOutputType = file_types::TY_ImportedModules;
       // We want the imported modules from the module as a whole, not individual
       // files, so let's do it in one invocation rather than having to collate
       // later.
@@ -1189,11 +1189,11 @@
 
     case options::OPT_index_file:
       OI.CompilerMode = OutputInfo::Mode::SingleCompile;
-      OI.CompilerOutputType = types::TY_IndexData;
+      OI.CompilerOutputType = file_types::TY_IndexData;
       break;
 
     case options::OPT_update_code:
-      OI.CompilerOutputType = types::TY_Remapping;
+      OI.CompilerOutputType = file_types::TY_Remapping;
       OI.LinkAction = LinkKind::None;
       break;
     case options::OPT_parse:
@@ -1206,7 +1206,7 @@
     case options::OPT_dump_scope_maps:
     case options::OPT_dump_interface_hash:
     case options::OPT_verify_debug_info:
-      OI.CompilerOutputType = types::TY_Nothing;
+      OI.CompilerOutputType = file_types::TY_Nothing;
       break;
 
     case options::OPT_i:
@@ -1218,7 +1218,7 @@
     case options::OPT_repl:
     case options::OPT_deprecated_integrated_repl:
     case options::OPT_lldb_repl:
-      OI.CompilerOutputType = types::TY_Nothing;
+      OI.CompilerOutputType = file_types::TY_Nothing;
       OI.CompilerMode = OutputInfo::Mode::REPL;
       break;
 
@@ -1227,7 +1227,7 @@
     }
   }
 
-  assert(OI.CompilerOutputType != types::ID::TY_INVALID);
+  assert(OI.CompilerOutputType != file_types::ID::TY_INVALID);
 
   if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
     if (A->getOption().matches(options::OPT_g))
@@ -1288,7 +1288,7 @@
       (OI.ModuleName == STDLIB_NAME &&
        !Args.hasArg(options::OPT_parse_stdlib))) {
     OI.ModuleNameIsFallback = true;
-    if (OI.CompilerOutputType == types::TY_Nothing ||
+    if (OI.CompilerOutputType == file_types::TY_Nothing ||
         maybeBuildingExecutable(OI, Args, Inputs))
       OI.ModuleName = "main";
     else if (!Inputs.empty() || OI.CompilerMode == OutputInfo::Mode::REPL) {
@@ -1407,7 +1407,7 @@
       if (Arg *A = Args.getLastArg(options::OPT_import_objc_header)) {
         StringRef Value = A->getValue();
         auto Ty = TC.lookupTypeForExtension(llvm::sys::path::extension(Value));
-        if (Ty == types::TY_ObjCHeader) {
+        if (Ty == file_types::TY_ObjCHeader) {
           auto *HeaderInput = C.createAction<InputAction>(*A, Ty);
           StringRef PersistentPCHDir;
           if (const Arg *A = Args.getLastArg(options::OPT_pch_output_dir)) {
@@ -1420,16 +1420,16 @@
     }
 
     for (const InputPair &Input : Inputs) {
-      types::ID InputType = Input.first;
+      file_types::ID InputType = Input.first;
       const Arg *InputArg = Input.second;
 
       Action *Current = C.createAction<InputAction>(*InputArg, InputType);
       switch (InputType) {
-      case types::TY_Swift:
-      case types::TY_SIL:
-      case types::TY_SIB: {
+      case file_types::TY_Swift:
+      case file_types::TY_SIL:
+      case file_types::TY_SIB: {
         // Source inputs always need to be compiled.
-        assert(types::isPartOfSwiftCompilation(InputType));
+        assert(file_types::isPartOfSwiftCompilation(InputType));
 
         CompileJobAction::InputInfo previousBuildState = {
           CompileJobAction::InputInfo::NeedsCascadingBuild,
@@ -1438,8 +1438,8 @@
         if (OutOfDateMap)
           previousBuildState = OutOfDateMap->lookup(InputArg);
         if (Args.hasArg(options::OPT_embed_bitcode)) {
-          Current = C.createAction<CompileJobAction>(Current, types::TY_LLVM_BC,
-                                                     previousBuildState);
+          Current = C.createAction<CompileJobAction>(
+              Current, file_types::TY_LLVM_BC, previousBuildState);
           if (PCH)
             cast<JobAction>(Current)->addInput(PCH);
           AllModuleInputs.push_back(Current);
@@ -1456,8 +1456,8 @@
         AllLinkerInputs.push_back(Current);
         break;
       }
-      case types::TY_SwiftModuleFile:
-      case types::TY_SwiftModuleDocFile:
+      case file_types::TY_SwiftModuleFile:
+      case file_types::TY_SwiftModuleDocFile:
         if (OI.ShouldGenerateModule && !OI.shouldLink()) {
           // When generating a .swiftmodule as a top-level output (as opposed
           // to, for example, linking an image), treat .swiftmodule files as
@@ -1474,40 +1474,40 @@
                          InputArg->getValue());
           continue;
         }
-      case types::TY_AutolinkFile:
-      case types::TY_Object:
+      case file_types::TY_AutolinkFile:
+      case file_types::TY_Object:
         // Object inputs are only okay if linking.
         if (OI.shouldLink()) {
           AllLinkerInputs.push_back(Current);
           break;
         }
         LLVM_FALLTHROUGH;
-      case types::TY_Image:
-      case types::TY_dSYM:
-      case types::TY_Dependencies:
-      case types::TY_Assembly:
-      case types::TY_LLVM_IR:
-      case types::TY_LLVM_BC:
-      case types::TY_SerializedDiagnostics:
-      case types::TY_ObjCHeader:
-      case types::TY_ClangModuleFile:
-      case types::TY_SwiftDeps:
-      case types::TY_Remapping:
-      case types::TY_IndexData:
-      case types::TY_PCH:
-      case types::TY_ImportedModules:
-      case types::TY_TBD:
-      case types::TY_ModuleTrace:
-      case types::TY_OptRecord:
+      case file_types::TY_Image:
+      case file_types::TY_dSYM:
+      case file_types::TY_Dependencies:
+      case file_types::TY_Assembly:
+      case file_types::TY_LLVM_IR:
+      case file_types::TY_LLVM_BC:
+      case file_types::TY_SerializedDiagnostics:
+      case file_types::TY_ObjCHeader:
+      case file_types::TY_ClangModuleFile:
+      case file_types::TY_SwiftDeps:
+      case file_types::TY_Remapping:
+      case file_types::TY_IndexData:
+      case file_types::TY_PCH:
+      case file_types::TY_ImportedModules:
+      case file_types::TY_TBD:
+      case file_types::TY_ModuleTrace:
+      case file_types::TY_OptRecord:
         // We could in theory handle assembly or LLVM input, but let's not.
         // FIXME: What about LTO?
         Diags.diagnose(SourceLoc(), diag::error_unexpected_input_file,
                        InputArg->getValue());
         continue;
-      case types::TY_RawSIB:
-      case types::TY_RawSIL:
-      case types::TY_Nothing:
-      case types::TY_INVALID:
+      case file_types::TY_RawSIB:
+      case file_types::TY_RawSIL:
+      case file_types::TY_Nothing:
+      case file_types::TY_INVALID:
         llvm_unreachable("these types should never be inferred");
       }
     }
@@ -1519,20 +1519,21 @@
       // Make sure we can handle the inputs.
       bool HandledHere = true;
       for (const InputPair &Input : Inputs) {
-        types::ID InputType = Input.first;
-        if (!types::isPartOfSwiftCompilation(InputType)) {
+        file_types::ID InputType = Input.first;
+        if (!file_types::isPartOfSwiftCompilation(InputType)) {
           HandledHere = false;
           break;
         }
       }
       if (HandledHere) {
         // Create a single CompileJobAction and a single BackendJobAction.
-        JobAction *CA = C.createAction<CompileJobAction>(types::TY_LLVM_BC);
+        JobAction *CA =
+            C.createAction<CompileJobAction>(file_types::TY_LLVM_BC);
         AllModuleInputs.push_back(CA);
 
         int InputIndex = 0;
         for (const InputPair &Input : Inputs) {
-          types::ID InputType = Input.first;
+          file_types::ID InputType = Input.first;
           const Arg *InputArg = Input.second;
 
           CA->addInput(C.createAction<InputAction>(*InputArg, InputType));
@@ -1559,7 +1560,7 @@
     // Create a single CompileJobAction for all of the driver's inputs.
     auto *CA = C.createAction<CompileJobAction>(OI.CompilerOutputType);
     for (const InputPair &Input : Inputs) {
-      types::ID InputType = Input.first;
+      file_types::ID InputType = Input.first;
       const Arg *InputArg = Input.second;
 
       CA->addInput(C.createAction<InputAction>(*InputArg, InputType));
@@ -1575,10 +1576,10 @@
     if (Inputs.empty())
       return;
 
-    assert(OI.CompilerOutputType == types::TY_Nothing);
+    assert(OI.CompilerOutputType == file_types::TY_Nothing);
     auto *CA = C.createAction<InterpretJobAction>();
     for (const InputPair &Input : Inputs) {
-      types::ID InputType = Input.first;
+      file_types::ID InputType = Input.first;
       const Arg *InputArg = Input.second;
 
       CA->addInput(C.createAction<InputAction>(*InputArg, InputType));
@@ -1625,7 +1626,7 @@
     // argument input file to the linker.
     SmallVector<const Action *, 2> AutolinkExtractInputs;
     for (const Action *A : AllLinkerInputs)
-      if (A->getType() == types::TY_Object)
+      if (A->getType() == file_types::TY_Object)
         AutolinkExtractInputs.push_back(A);
     if (!AutolinkExtractInputs.empty() &&
         (TC.getTriple().getObjectFormat() == llvm::Triple::ELF ||
@@ -1777,7 +1778,7 @@
 
 static Optional<StringRef> getOutputFilenameFromPathArgOrAsTopLevel(
     const OutputInfo &OI, const llvm::opt::DerivedArgList &Args,
-    llvm::opt::OptSpecifier PathArg, types::ID ExpectedOutputType,
+    llvm::opt::OptSpecifier PathArg, file_types::ID ExpectedOutputType,
     bool TreatAsTopLevelOutput, StringRef workingDirectory, StringRef ext,
     llvm::SmallString<128> &Buffer) {
   if (const Arg *A = Args.getLastArg(PathArg))
@@ -1813,7 +1814,7 @@
   // We should output to a temporary file, since we're not at the top level
   // (or are generating a bridging PCH, which is currently always a temp).
   StringRef Stem = llvm::sys::path::stem(BaseName);
-  StringRef Suffix = types::getTypeTempSuffix(JA->getType());
+  StringRef Suffix = file_types::getTypeTempSuffix(JA->getType());
   std::error_code EC = llvm::sys::fs::createTemporaryFile(Stem, Suffix, Buffer);
   if (EC) {
     Diags.diagnose(SourceLoc(), diag::error_unable_to_make_temporary_file,
@@ -1861,7 +1862,7 @@
                                    StringRef PrimaryInput,
                                    DiagnosticEngine &Diags,
                                    llvm::SmallString<128> &Buffer) {
-  if (JA->getType() == types::TY_Nothing)
+  if (JA->getType() == file_types::TY_Nothing)
     return {};
 
   // If available, check the OutputMap first.
@@ -1876,7 +1877,7 @@
 
   if (isa<MergeModuleJobAction>(JA)) {
     auto optFilename = getOutputFilenameFromPathArgOrAsTopLevel(
-        OI, Args, options::OPT_emit_module_path, types::TY_SwiftModuleFile,
+        OI, Args, options::OPT_emit_module_path, file_types::TY_SwiftModuleFile,
         OI.ShouldTreatModuleAsTopLevelOutput, workingDirectory,
         SERIALIZED_MODULE_EXTENSION, Buffer);
     if (optFilename)
@@ -1887,7 +1888,7 @@
   if (isa<GenerateDSYMJobAction>(JA)) {
     Buffer = PrimaryInput;
     Buffer.push_back('.');
-    Buffer.append(types::getTypeTempSuffix(JA->getType()));
+    Buffer.append(file_types::getTypeTempSuffix(JA->getType()));
     return Buffer.str();
   }
 
@@ -1905,7 +1906,7 @@
   if (AtTopLevel) {
     if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))
       return FinalOutput->getValue();
-    if (types::isTextual(JA->getType()))
+    if (file_types::isTextual(JA->getType()))
       return "-";
   }
 
@@ -1915,7 +1916,7 @@
   if (isa<MergeModuleJobAction>(JA) ||
       (OI.CompilerMode == OutputInfo::Mode::SingleCompile &&
        !OI.isMultiThreading()) ||
-      JA->getType() == types::TY_Image)
+      JA->getType() == file_types::TY_Image)
     BaseName = OI.ModuleName;
 
   // We don't yet have a name, assign one.
@@ -1923,14 +1924,14 @@
     return assignOutputName(C, JA, Diags, Buffer, BaseName,
                             ShouldPreserveOnSignal);
 
-  if (JA->getType() == types::TY_Image) {
+  if (JA->getType() == file_types::TY_Image) {
     SmallString<16> Base =
         baseNameForImage(JA, OI, Triple, Buffer, BaseInput, BaseName);
     formFilenameFromBaseAndExt(Base, /*newExt=*/"", workingDirectory, Buffer);
     return Buffer.str();
   }
 
-  StringRef Suffix = types::getTypeTempSuffix(JA->getType());
+  StringRef Suffix = file_types::getTypeTempSuffix(JA->getType());
   assert(Suffix.data() &&
          "All types used for output should have a suffix.");
 
@@ -1940,7 +1941,7 @@
 }
 
 static bool hasExistingAdditionalOutput(CommandOutput &output,
-                                        types::ID outputType,
+                                        file_types::ID outputType,
                                         StringRef outputPath = StringRef()) {
 
   auto existing = output.getAdditionalOutputForType(outputType);
@@ -1952,7 +1953,7 @@
 }
 
 static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
-                               types::ID outputType, const OutputInfo &OI,
+                               file_types::ID outputType, const OutputInfo &OI,
                                const TypeToPathMap *outputMap,
                                StringRef workingDirectory,
                                StringRef outputPath = StringRef()) {
@@ -1984,7 +1985,7 @@
     // a whole -- derived OFM input "" -- but that's a more general thing to
     // fix.
     llvm::SmallString<128> path;
-    if (output.getPrimaryOutputType() != types::TY_Nothing)
+    if (output.getPrimaryOutputType() != file_types::TY_Nothing)
       path = output.getPrimaryOutputFilenames()[0];
     else if (!output.getBaseInput(0).empty())
       path = llvm::sys::path::stem(output.getBaseInput(0));
@@ -1995,8 +1996,8 @@
     assert(!path.empty());
 
     bool isTempFile = C.isTemporaryFile(path);
-    llvm::sys::path::replace_extension(path,
-                                       types::getTypeTempSuffix(outputType));
+    llvm::sys::path::replace_extension(
+        path, file_types::getTypeTempSuffix(outputType));
     output.setAdditionalOutputForType(outputType, path);
     if (isTempFile)
       C.addTemporaryFile(path);
@@ -2018,7 +2019,8 @@
   StringRef pchOutDir = JA->getPersistentPCHDir();
   StringRef headerPath = output.getBaseInput(JA->getInputIndex());
   StringRef stem = llvm::sys::path::stem(headerPath);
-  StringRef suffix = types::getTypeTempSuffix(types::TY_SerializedDiagnostics);
+  StringRef suffix =
+      file_types::getTypeTempSuffix(file_types::TY_SerializedDiagnostics);
   SmallString<256> outPathBuf;
 
   if (const Arg *A = C.getArgs().getLastArg(options::OPT_emit_module_path)) {
@@ -2048,7 +2050,7 @@
   }
 
   if (!outPathBuf.empty()) {
-    addAuxiliaryOutput(C, output, types::TY_SerializedDiagnostics, OI,
+    addAuxiliaryOutput(C, output, file_types::TY_SerializedDiagnostics, OI,
                        outputMap, workingDirectory, outPathBuf.str());
   }
 }
@@ -2210,7 +2212,9 @@
   Job *J = C.addJob(std::move(ownedJob));
 
   // If we track dependencies for this job, we may be able to avoid running it.
-  if (!J->getOutput().getAdditionalOutputForType(types::TY_SwiftDeps).empty()) {
+  if (!J->getOutput()
+           .getAdditionalOutputForType(file_types::TY_SwiftDeps)
+           .empty()) {
     if (InputActions.size() == 1) {
       auto compileJob = cast<CompileJobAction>(JA);
       bool alwaysRebuildDependents =
@@ -2250,19 +2254,20 @@
 
     llvm::outs() << "], output: {";
     auto OutputFileNames = J->getOutput().getPrimaryOutputFilenames();
-    StringRef TypeName = types::getTypeName(J->getOutput().getPrimaryOutputType());
+    StringRef TypeName =
+        file_types::getTypeName(J->getOutput().getPrimaryOutputType());
     interleave(OutputFileNames.begin(), OutputFileNames.end(),
                [TypeName](const std::string &FileName) {
                  llvm::outs() << TypeName << ": \"" << FileName << '"';
                },
                [] { llvm::outs() << ", "; });
 
-    types::forAllTypes([&J](types::ID Ty) {
+    file_types::forAllTypes([&J](file_types::ID Ty) {
       StringRef AdditionalOutput =
         J->getOutput().getAdditionalOutputForType(Ty);
       if (!AdditionalOutput.empty()) {
-        llvm::outs() << ", " << types::getTypeName(Ty) << ": \""
-          << AdditionalOutput << '"';
+        llvm::outs() << ", " << file_types::getTypeName(Ty) << ": \""
+                     << AdditionalOutput << '"';
       }
     });
     llvm::outs() << '}';
@@ -2296,7 +2301,7 @@
     llvm::SmallString<128> &Buf, CommandOutput *Output) const {
   StringRef OutputFile;
   if (OI.isMultiThreading() && isa<CompileJobAction>(JA) &&
-      types::isAfterLLVM(JA->getType())) {
+      file_types::isAfterLLVM(JA->getType())) {
     // Multi-threaded compilation: A single frontend command produces multiple
     // output file: one for each input files.
     auto OutputFunc = [&](StringRef Base, StringRef Primary) {
@@ -2340,12 +2345,12 @@
                                          StringRef workingDirectory,
                                          CommandOutput *Output) const {
 
-  if (hasExistingAdditionalOutput(*Output, types::TY_SwiftModuleFile))
+  if (hasExistingAdditionalOutput(*Output, file_types::TY_SwiftModuleFile))
     return;
 
   StringRef OFMModuleOutputPath;
   if (OutputMap) {
-    auto iter = OutputMap->find(types::TY_SwiftModuleFile);
+    auto iter = OutputMap->find(file_types::TY_SwiftModuleFile);
     if (iter != OutputMap->end())
       OFMModuleOutputPath = iter->second;
   }
@@ -2354,14 +2359,14 @@
 
   if (!OFMModuleOutputPath.empty()) {
     // Prefer a path from the OutputMap.
-    Output->setAdditionalOutputForType(types::TY_SwiftModuleFile,
+    Output->setAdditionalOutputForType(file_types::TY_SwiftModuleFile,
                                        OFMModuleOutputPath);
   } else if (A && OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
     // We're performing a single compilation (and thus no merge module step),
     // so prefer to use -emit-module-path, if present.
-    Output->setAdditionalOutputForType(types::TY_SwiftModuleFile,
+    Output->setAdditionalOutputForType(file_types::TY_SwiftModuleFile,
                                        A->getValue());
-  } else if (Output->getPrimaryOutputType() == types::TY_SwiftModuleFile) {
+  } else if (Output->getPrimaryOutputType() == file_types::TY_SwiftModuleFile) {
     // If the primary type is already a module type, we're out of
     // options for overriding the primary name choice: stop now.
     assert(!Output->getPrimaryOutputFilename().empty());
@@ -2377,22 +2382,23 @@
       llvm::sys::path::remove_filename(Path);
       llvm::sys::path::append(Path, OI.ModuleName);
       llvm::sys::path::replace_extension(Path, SERIALIZED_MODULE_EXTENSION);
-      Output->setAdditionalOutputForType(types::TY_SwiftModuleFile, Path);
+      Output->setAdditionalOutputForType(file_types::TY_SwiftModuleFile, Path);
     } else {
       // A top-level output wasn't specified, so just output to
       // <ModuleName>.swiftmodule.
       llvm::SmallString<128> Path(OI.ModuleName);
       llvm::sys::path::replace_extension(Path, SERIALIZED_MODULE_EXTENSION);
-      Output->setAdditionalOutputForType(types::TY_SwiftModuleFile, Path);
+      Output->setAdditionalOutputForType(file_types::TY_SwiftModuleFile, Path);
     }
-  } else if (Output->getPrimaryOutputType() != types::TY_Nothing) {
+  } else if (Output->getPrimaryOutputType() != file_types::TY_Nothing) {
     // We're only generating the module as an intermediate, so put it next
     // to the primary output of the compile command.
     llvm::SmallString<128> Path(Output->getPrimaryOutputFilenames()[0]);
     assert(!Path.empty());
     bool isTempFile = C.isTemporaryFile(Path);
     llvm::sys::path::replace_extension(Path, SERIALIZED_MODULE_EXTENSION);
-    Output->setAdditionalOutputForType(types::ID::TY_SwiftModuleFile, Path);
+    Output->setAdditionalOutputForType(file_types::ID::TY_SwiftModuleFile,
+                                       Path);
     if (isTempFile)
       C.addTemporaryFile(Path);
   }
@@ -2403,26 +2409,26 @@
                                             StringRef workingDirectory,
                                             CommandOutput *Output) const {
 
-  if (hasExistingAdditionalOutput(*Output, types::TY_SwiftModuleDocFile))
+  if (hasExistingAdditionalOutput(*Output, file_types::TY_SwiftModuleDocFile))
     return;
 
   StringRef OFMModuleDocOutputPath;
   if (OutputMap) {
-    auto iter = OutputMap->find(types::TY_SwiftModuleDocFile);
+    auto iter = OutputMap->find(file_types::TY_SwiftModuleDocFile);
     if (iter != OutputMap->end())
       OFMModuleDocOutputPath = iter->second;
   }
   if (!OFMModuleDocOutputPath.empty()) {
     // Prefer a path from the OutputMap.
-    Output->setAdditionalOutputForType(types::TY_SwiftModuleDocFile,
+    Output->setAdditionalOutputForType(file_types::TY_SwiftModuleDocFile,
                                        OFMModuleDocOutputPath);
-  } else if (Output->getPrimaryOutputType() != types::TY_Nothing) {
+  } else if (Output->getPrimaryOutputType() != file_types::TY_Nothing) {
     // Otherwise, put it next to the swiftmodule file.
     llvm::SmallString<128> Path(
-        Output->getAnyOutputForType(types::TY_SwiftModuleFile));
+        Output->getAnyOutputForType(file_types::TY_SwiftModuleFile));
     bool isTempFile = C.isTemporaryFile(Path);
     llvm::sys::path::replace_extension(Path, SERIALIZED_MODULE_DOC_EXTENSION);
-    Output->setAdditionalOutputForType(types::TY_SwiftModuleDocFile, Path);
+    Output->setAdditionalOutputForType(file_types::TY_SwiftModuleDocFile, Path);
     if (isTempFile)
       C.addTemporaryFile(Path);
   }
@@ -2432,23 +2438,23 @@
                                        const TypeToPathMap *OutputMap,
                                        CommandOutput *Output) const {
 
-  if (hasExistingAdditionalOutput(*Output, types::TY_Remapping))
+  if (hasExistingAdditionalOutput(*Output, file_types::TY_Remapping))
     return;
 
   StringRef OFMFixitsOutputPath;
   if (OutputMap) {
-    auto iter = OutputMap->find(types::TY_Remapping);
+    auto iter = OutputMap->find(file_types::TY_Remapping);
     if (iter != OutputMap->end())
       OFMFixitsOutputPath = iter->second;
   }
   if (!OFMFixitsOutputPath.empty()) {
-    Output->setAdditionalOutputForType(types::ID::TY_Remapping,
+    Output->setAdditionalOutputForType(file_types::ID::TY_Remapping,
                                        OFMFixitsOutputPath);
   } else {
     llvm::SmallString<128> Path(Output->getPrimaryOutputFilenames()[0]);
     bool isTempFile = C.isTemporaryFile(Path);
     llvm::sys::path::replace_extension(Path, "remap");
-    Output->setAdditionalOutputForType(types::ID::TY_Remapping, Path);
+    Output->setAdditionalOutputForType(file_types::ID::TY_Remapping, Path);
     if (isTempFile)
       C.addTemporaryFile(Path);
   }
@@ -2466,14 +2472,14 @@
       addDiagFileOutputForPersistentPCHAction(C, pchJA, *Output, OI, OutputMap,
                                               workingDirectory, Diags);
     } else {
-      addAuxiliaryOutput(C, *Output, types::TY_SerializedDiagnostics, OI,
+      addAuxiliaryOutput(C, *Output, file_types::TY_SerializedDiagnostics, OI,
                          OutputMap, workingDirectory);
     }
 
     // Remove any existing diagnostics files so that clients can detect their
     // presence to determine if a command was run.
     StringRef OutputPath =
-        Output->getAnyOutputForType(types::TY_SerializedDiagnostics);
+        Output->getAnyOutputForType(file_types::TY_SerializedDiagnostics);
     if (llvm::sys::fs::is_regular_file(OutputPath))
       llvm::sys::fs::remove(OutputPath);
   }
@@ -2485,11 +2491,11 @@
                                            llvm::SmallString<128> &Buf,
                                            CommandOutput *Output) const {
   if (C.getArgs().hasArg(options::OPT_emit_dependencies)) {
-    addAuxiliaryOutput(C, *Output, types::TY_Dependencies, OI, OutputMap,
+    addAuxiliaryOutput(C, *Output, file_types::TY_Dependencies, OI, OutputMap,
                        workingDirectory);
   }
   if (C.getIncrementalBuildEnabled()) {
-    addAuxiliaryOutput(C, *Output, types::TY_SwiftDeps, OI, OutputMap,
+    addAuxiliaryOutput(C, *Output, file_types::TY_SwiftDeps, OI, OutputMap,
                        workingDirectory);
   }
   chooseLoadedModuleTracePath(C, OI, workingDirectory, Buf, Output);
@@ -2521,11 +2527,11 @@
       // exists.
       filename = *getOutputFilenameFromPathArgOrAsTopLevel(
           OI, C.getArgs(), options::OPT_emit_loaded_module_trace_path,
-          types::TY_ModuleTrace,
+          file_types::TY_ModuleTrace,
           /*TreatAsTopLevelOutput=*/true, workingDirectory, "trace.json", Buf);
     }
 
-    Output->setAdditionalOutputForType(types::TY_ModuleTrace, filename);
+    Output->setAdditionalOutputForType(file_types::TY_ModuleTrace, filename);
   }
 }
 
@@ -2540,10 +2546,10 @@
                    << "-whole-module-optimization flag.\n";
     } else {
       auto filename = *getOutputFilenameFromPathArgOrAsTopLevel(
-          OI, C.getArgs(), options::OPT_emit_tbd_path, types::TY_TBD,
+          OI, C.getArgs(), options::OPT_emit_tbd_path, file_types::TY_TBD,
           /*TreatAsTopLevelOutput=*/true, workingDirectory, "tbd", Buf);
 
-      Output->setAdditionalOutputForType(types::TY_TBD, filename);
+      Output->setAdditionalOutputForType(file_types::TY_TBD, filename);
     }
   }
 }
@@ -2555,10 +2561,10 @@
   if (OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
     auto filename = *getOutputFilenameFromPathArgOrAsTopLevel(
         OI, C.getArgs(), options::OPT_save_optimization_record_path,
-        types::TY_OptRecord, /*TreatAsTopLevelOutput=*/true, workingDirectory,
-        "opt.yaml", Buf);
+        file_types::TY_OptRecord, /*TreatAsTopLevelOutput=*/true,
+        workingDirectory, "opt.yaml", Buf);
 
-    Output->setAdditionalOutputForType(types::TY_OptRecord, filename);
+    Output->setAdditionalOutputForType(file_types::TY_OptRecord, filename);
   } else
     // FIXME: We should use the OutputMap in this case.
     Diags.diagnose({}, diag::warn_opt_remark_disabled);
@@ -2570,12 +2576,12 @@
                                               StringRef workingDirectory,
                                               CommandOutput *Output) const {
 
-  if (hasExistingAdditionalOutput(*Output, types::TY_ObjCHeader))
+  if (hasExistingAdditionalOutput(*Output, file_types::TY_ObjCHeader))
     return;
 
   StringRef ObjCHeaderPath;
   if (OutputMap) {
-    auto iter = OutputMap->find(types::TY_ObjCHeader);
+    auto iter = OutputMap->find(file_types::TY_ObjCHeader);
     if (iter != OutputMap->end())
       ObjCHeaderPath = iter->second;
   }
@@ -2585,12 +2591,13 @@
       ObjCHeaderPath = A->getValue();
 
   if (!ObjCHeaderPath.empty()) {
-    Output->setAdditionalOutputForType(types::TY_ObjCHeader, ObjCHeaderPath);
+    Output->setAdditionalOutputForType(file_types::TY_ObjCHeader,
+                                       ObjCHeaderPath);
   } else {
     // Put the header next to the primary output file.
     // FIXME: That's not correct if the user /just/ passed -emit-header
     // and not -emit-module.
-    addAuxiliaryOutput(C, *Output, types::TY_ObjCHeader, OI,
+    addAuxiliaryOutput(C, *Output, file_types::TY_ObjCHeader, OI,
                        /*output file map*/ nullptr, workingDirectory);
   }
 }
@@ -2617,7 +2624,7 @@
   unsigned Id = Ids.size();
   Ids[A] = Id;
   llvm::errs() << Id << ": " << os.str() << ", "
-               << types::getTypeName(A->getType()) << "\n";
+               << file_types::getTypeName(A->getType()) << "\n";
 
   return Id;
 }
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index e6173fc..48c93f7 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -24,8 +24,8 @@
 using namespace swift::driver;
 
 StringRef CommandOutput::getOutputForInputAndType(StringRef PrimaryInputFile,
-                                                  types::ID Type) const {
-  if (Type == types::TY_Nothing)
+                                                  file_types::ID Type) const {
+  if (Type == file_types::TY_Nothing)
     return StringRef();
   auto const *M = DerivedOutputMap.getOutputMapForInput(PrimaryInputFile);
   if (!M)
@@ -52,12 +52,12 @@
 };
 
 void CommandOutput::ensureEntry(StringRef PrimaryInputFile,
-                                types::ID Type,
+                                file_types::ID Type,
                                 StringRef OutputFile,
                                 bool Overwrite) {
   assert(!PrimaryInputFile.empty());
   assert(!OutputFile.empty());
-  assert(Type != types::TY_Nothing);
+  assert(Type != file_types::TY_Nothing);
   auto &M = DerivedOutputMap.getOrCreateOutputMapForInput(PrimaryInputFile);
   if (Overwrite) {
     M[Type] = OutputFile;
@@ -73,7 +73,7 @@
 }
 
 void CommandOutput::checkInvariants() const {
-  types::forAllTypes([&](types::ID Type) {
+  file_types::forAllTypes([&](file_types::ID Type) {
       size_t numOutputsOfType = 0;
       for (auto const &I : Inputs) {
         // FIXME: At the moment, empty primary input names correspond to
@@ -84,7 +84,7 @@
         // are presently (arbitrarily and wrongly) stored in entries
         // associated with the first primary input of the CommandOutput
         // that they were derived from.
-        assert(PrimaryOutputType == types::TY_Nothing || !I.Primary.empty());
+        assert(PrimaryOutputType == file_types::TY_Nothing || !I.Primary.empty());
         auto const *M = DerivedOutputMap.getOutputMapForInput(I.Primary);
         if (!M)
           continue;
@@ -104,7 +104,7 @@
 bool CommandOutput::hasSameAdditionalOutputTypes(
     CommandOutput const &other) const {
   bool sameAdditionalOutputTypes = true;
-  types::forAllTypes([&](types::ID Type) {
+  file_types::forAllTypes([&](file_types::ID Type) {
       bool a = AdditionalOutputTypes.count(Type) == 0;
       bool b = other.AdditionalOutputTypes.count(Type) == 0;
       if (a != b)
@@ -128,13 +128,13 @@
   }
 }
 
-CommandOutput::CommandOutput(types::ID PrimaryOutputType,
+CommandOutput::CommandOutput(file_types::ID PrimaryOutputType,
                              OutputFileMap &Derived)
     : PrimaryOutputType(PrimaryOutputType), DerivedOutputMap(Derived) {
   CommandOutputInvariantChecker Check(*this);
 }
 
-types::ID CommandOutput::getPrimaryOutputType() const {
+file_types::ID CommandOutput::getPrimaryOutputType() const {
   return PrimaryOutputType;
 }
 
@@ -142,7 +142,7 @@
                                      StringRef PrimaryOutputFile) {
   PrettyStackTraceDriverCommandOutputAddition CrashInfo(
     "primary", this, Input.Primary, PrimaryOutputType, PrimaryOutputFile);
-  if (PrimaryOutputType == types::TY_Nothing) {
+  if (PrimaryOutputType == file_types::TY_Nothing) {
     // For TY_Nothing, we accumulate the inputs but do not add any outputs.
     // The invariant holds on either side of this action because all primary
     // outputs for this command will be absent (so the length == 0 case in the
@@ -176,20 +176,20 @@
     V.push_back(Out);
     if (!Out.empty())
       ++NonEmpty;
-    assert(!Out.empty() || PrimaryOutputType == types::TY_Nothing);
+    assert(!Out.empty() || PrimaryOutputType == file_types::TY_Nothing);
   }
   assert(NonEmpty == 0 || NonEmpty == Inputs.size());
   return V;
 }
 
-void CommandOutput::setAdditionalOutputForType(types::ID Type,
+void CommandOutput::setAdditionalOutputForType(file_types::ID Type,
                                                StringRef OutputFilename) {
   PrettyStackTraceDriverCommandOutputAddition CrashInfo(
       "additional", this, Inputs[0].Primary, Type, OutputFilename);
   CommandOutputInvariantChecker Check(*this);
   assert(Inputs.size() >= 1);
   assert(!OutputFilename.empty());
-  assert(Type != types::TY_Nothing);
+  assert(Type != file_types::TY_Nothing);
 
   // If we're given an "additional" output with the same type as the primary,
   // and we've not yet had such an additional type added, we treat it as a
@@ -204,7 +204,7 @@
   ensureEntry(Inputs[0].Primary, Type, OutputFilename, Overwrite);
 }
 
-StringRef CommandOutput::getAdditionalOutputForType(types::ID Type) const {
+StringRef CommandOutput::getAdditionalOutputForType(file_types::ID Type) const {
   if (AdditionalOutputTypes.count(Type) == 0)
     return StringRef();
   assert(Inputs.size() >= 1);
@@ -216,7 +216,7 @@
 }
 
 SmallVector<StringRef, 16>
-CommandOutput::getAdditionalOutputsForType(types::ID Type) const {
+CommandOutput::getAdditionalOutputsForType(file_types::ID Type) const {
   SmallVector<StringRef, 16> V;
   if (AdditionalOutputTypes.count(Type) != 0) {
     for (auto const &I : Inputs) {
@@ -234,7 +234,7 @@
   return V;
 }
 
-StringRef CommandOutput::getAnyOutputForType(types::ID Type) const {
+StringRef CommandOutput::getAnyOutputForType(file_types::ID Type) const {
   if (PrimaryOutputType == Type)
     return getPrimaryOutputFilename();
   return getAdditionalOutputForType(Type);
@@ -288,7 +288,7 @@
 CommandOutput::print(raw_ostream &out) const {
   out
     << "{\n"
-    << "    PrimaryOutputType = " << types::getTypeName(PrimaryOutputType)
+    << "    PrimaryOutputType = " << file_types::getTypeName(PrimaryOutputType)
     << ";\n"
     << "    Inputs = [\n";
   interleave(Inputs,
diff --git a/lib/Driver/ParseableOutput.cpp b/lib/Driver/ParseableOutput.cpp
index 27fc505..9fb441d 100644
--- a/lib/Driver/ParseableOutput.cpp
+++ b/lib/Driver/ParseableOutput.cpp
@@ -15,7 +15,7 @@
 #include "swift/Basic/JSONSerialization.h"
 #include "swift/Driver/Action.h"
 #include "swift/Driver/Job.h"
-#include "swift/Frontend/Types.h"
+#include "swift/Frontend/FileTypes.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -30,7 +30,7 @@
     CommandInput(StringRef Path) : Path(Path) {}
   };
 
-  typedef std::pair<types::ID, std::string> OutputPair;
+  using OutputPair = std::pair<file_types::ID, std::string>;
 } // end anonymous namespace
 
 namespace swift {
@@ -43,19 +43,18 @@
     static bool mustQuote(StringRef) { return true; }
   };
 
-  template<>
-  struct ScalarEnumerationTraits<types::ID> {
-    static void enumeration(Output &out, types::ID &value) {
-      types::forAllTypes([&](types::ID ty) {
-        std::string typeName = types::getTypeName(ty);
+  template <> struct ScalarEnumerationTraits<file_types::ID> {
+    static void enumeration(Output &out, file_types::ID &value) {
+      file_types::forAllTypes([&](file_types::ID ty) {
+        std::string typeName = file_types::getTypeName(ty);
         out.enumCase(value, typeName.c_str(), ty);
       });
     }
   };
 
-  template<>
-  struct ObjectTraits<std::pair<types::ID, std::string>> {
-    static void mapping(Output &out, std::pair<types::ID, std::string> &value) {
+  template <> struct ObjectTraits<std::pair<file_types::ID, std::string>> {
+    static void mapping(Output &out,
+                        std::pair<file_types::ID, std::string> &value) {
       out.mapRequired("type", value.first);
       out.mapRequired("path", value.second);
     }
@@ -131,17 +130,17 @@
     }
 
     // TODO: set up Outputs appropriately.
-    types::ID PrimaryOutputType = Cmd.getOutput().getPrimaryOutputType();
-    if (PrimaryOutputType != types::TY_Nothing) {
+    file_types::ID PrimaryOutputType = Cmd.getOutput().getPrimaryOutputType();
+    if (PrimaryOutputType != file_types::TY_Nothing) {
       for (const std::string &OutputFileName : Cmd.getOutput().
                                                  getPrimaryOutputFilenames()) {
         Outputs.push_back(OutputPair(PrimaryOutputType, OutputFileName));
       }
     }
-    types::forAllTypes([&](types::ID Ty) {
-        for (auto Output : Cmd.getOutput().getAdditionalOutputsForType(Ty)) {
-          Outputs.push_back(OutputPair(Ty, Output));
-        }
+    file_types::forAllTypes([&](file_types::ID Ty) {
+      for (auto Output : Cmd.getOutput().getAdditionalOutputsForType(Ty)) {
+        Outputs.push_back(OutputPair(Ty, Output));
+      }
     });
   }
 
diff --git a/lib/Driver/PrettyStackTrace.cpp b/lib/Driver/PrettyStackTrace.cpp
index 6f403ec..1bfd8ad 100644
--- a/lib/Driver/PrettyStackTrace.cpp
+++ b/lib/Driver/PrettyStackTrace.cpp
@@ -13,7 +13,7 @@
 #include "swift/Driver/PrettyStackTrace.h"
 #include "swift/Driver/Action.h"
 #include "swift/Driver/Job.h"
-#include "swift/Frontend/Types.h"
+#include "swift/Frontend/FileTypes.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -21,9 +21,8 @@
 
 void PrettyStackTraceDriverAction::print(llvm::raw_ostream &out) const {
   out << "While " << Description << " for driver Action "
-      << TheAction->getClassName()
-      << " of type "
-      << types::getTypeName(TheAction->getType());
+      << TheAction->getClassName() << " of type "
+      << file_types::getTypeName(TheAction->getType());
   if (auto *IA = dyn_cast<InputAction>(TheAction)) {
     out << " = ";
     IA->getInputArg().print(out);
@@ -45,11 +44,9 @@
 
 void PrettyStackTraceDriverCommandOutputAddition::print(
     llvm::raw_ostream &out) const {
-  out << "While adding " << Description
-      << " output named " << NewOutputName
-      << " of type " << types::getTypeName(NewOutputType)
-      << " for input " << PrimaryInput
-      << " to driver CommandOutput\n";
+  out << "While adding " << Description << " output named " << NewOutputName
+      << " of type " << file_types::getTypeName(NewOutputType) << " for input "
+      << PrimaryInput << " to driver CommandOutput\n";
   TheCommandOutput->print(out);
   out << '\n';
 }
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 2085319..7cbace5 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -74,8 +74,9 @@
 
   auto invocationInfo = [&]() -> InvocationInfo {
     switch (JA.getKind()) {
-  #define CASE(K) case Action::K: \
-      return constructInvocation(cast<K##Action>(JA), context);
+#define CASE(K)                                                                \
+  case Action::Kind::K:                                                        \
+    return constructInvocation(cast<K##Action>(JA), context);
     CASE(CompileJob)
     CASE(InterpretJob)
     CASE(BackendJob)
@@ -88,7 +89,7 @@
     CASE(AutolinkExtractJob)
     CASE(REPLJob)
 #undef CASE
-    case Action::Input:
+    case Action::Kind::Input:
       llvm_unreachable("not a JobAction");
     }
 
@@ -146,8 +147,8 @@
   return {};
 }
 
-types::ID ToolChain::lookupTypeForExtension(StringRef Ext) const {
-  return types::lookupTypeForExtension(Ext);
+file_types::ID ToolChain::lookupTypeForExtension(StringRef Ext) const {
+  return file_types::lookupTypeForExtension(Ext);
 }
 
 /// Return a _single_ TY_Swift InputAction, if one exists;
@@ -158,7 +159,7 @@
   const InputAction *IA = nullptr;
   for (auto const *I : Inputs) {
     if (auto const *S = dyn_cast<InputAction>(I)) {
-      if (S->getType() == types::TY_Swift) {
+      if (S->getType() == file_types::TY_Swift) {
         if (IA == nullptr) {
           IA = S;
         } else {
@@ -232,7 +233,7 @@
 /// \c CommandOutputs of all the jobs passed.
 static std::unique_ptr<CommandOutput>
 makeBatchCommandOutput(ArrayRef<const Job *> jobs, Compilation &C,
-                       types::ID outputType) {
+                       file_types::ID outputType) {
   auto output =
       llvm::make_unique<CommandOutput>(outputType, C.getDerivedOutputFileMap());
   for (auto const *J : jobs) {
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 3219b3a..f3a6ae3 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -63,7 +63,7 @@
   if (Args.hasArg(options::OPT_driver_use_filelists))
     return true;
   static const unsigned UpperBoundOnSupplementaryOutputFileTypes =
-      types::TY_INVALID;
+      file_types::TY_INVALID;
   return InputActions.size() * UpperBoundOnSupplementaryOutputFileTypes >
          TOO_MANY_FILES;
 }
@@ -76,7 +76,7 @@
 
 static void addInputsOfType(ArgStringList &Arguments,
                             ArrayRef<const Action *> Inputs,
-                            types::ID InputType,
+                            file_types::ID InputType,
                             const char *PrefixArgument = nullptr) {
   for (auto &Input : Inputs) {
     if (Input->getType() != InputType)
@@ -90,7 +90,7 @@
 static void addInputsOfType(ArgStringList &Arguments,
                             ArrayRef<const Job *> Jobs,
                             const llvm::opt::ArgList &Args,
-                            types::ID InputType,
+                            file_types::ID InputType,
                             const char *PrefixArgument = nullptr) {
   for (const Job *Cmd : Jobs) {
     auto output = Cmd->getOutput().getAnyOutputForType(InputType);
@@ -105,7 +105,7 @@
 static void addPrimaryInputsOfType(ArgStringList &Arguments,
                                    ArrayRef<const Job *> Jobs,
                                    const llvm::opt::ArgList &Args,
-                                   types::ID InputType,
+                                   file_types::ID InputType,
                                    const char *PrefixArgument = nullptr) {
   for (const Job *Cmd : Jobs) {
     auto &outputInfo = Cmd->getOutput();
@@ -119,12 +119,11 @@
   }
 }
 
-static bool
-addOutputsOfType(ArgStringList &Arguments,
-                 CommandOutput const &Output,
-                 const llvm::opt::ArgList &Args,
-                 types::ID OutputType,
-                 const char *PrefixArgument = nullptr) {
+static bool addOutputsOfType(ArgStringList &Arguments,
+                             CommandOutput const &Output,
+                             const llvm::opt::ArgList &Args,
+                             file_types::ID OutputType,
+                             const char *PrefixArgument = nullptr) {
   bool Added = false;
   for (auto Output : Output.getAdditionalOutputsForType(OutputType)) {
     assert(!Output.empty());
@@ -298,9 +297,10 @@
         context.Args.hasArg(options::OPT_pch_output_dir);
     if (!usePersistentPCH) {
       for (auto *IJ : context.Inputs) {
-        if (!IJ->getOutput().getAnyOutputForType(types::TY_PCH).empty()) {
+        if (!IJ->getOutput().getAnyOutputForType(file_types::TY_PCH).empty()) {
           Arguments.push_back("-import-objc-header");
-          addInputsOfType(Arguments, context.Inputs, context.Args, types::TY_PCH);
+          addInputsOfType(Arguments, context.Inputs, context.Args,
+                          file_types::TY_PCH);
           ForwardAsIs = false;
           break;
         }
@@ -330,16 +330,14 @@
   Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName));
 
   addOutputsOfType(Arguments, context.Output, context.Args,
-                   types::TY_OptRecord,
-                   "-save-optimization-record-path");
+                   file_types::TY_OptRecord, "-save-optimization-record-path");
 
   if (context.Args.hasArg(options::OPT_migrate_keep_objc_visibility)) {
     Arguments.push_back("-migrate-keep-objc-visibility");
   }
 
   addOutputsOfType(Arguments, context.Output, context.Args,
-                   types::TY_Remapping,
-                   "-emit-remap-file-path");
+                   file_types::TY_Remapping, "-emit-remap-file-path");
 
   if (context.OI.numThreads > 0) {
     Arguments.push_back("-num-threads");
@@ -348,7 +346,7 @@
   }
 
   // Add the output file argument if necessary.
-  if (context.Output.getPrimaryOutputType() != types::TY_Nothing) {
+  if (context.Output.getPrimaryOutputType() != file_types::TY_Nothing) {
     if (context.shouldUseMainOutputFileListInFrontendInvocation()) {
       Arguments.push_back("-output-filelist");
       Arguments.push_back(context.getTemporaryFilePath("outputs", ""));
@@ -385,55 +383,55 @@
     llvm_unreachable("REPL and immediate modes handled elsewhere");
   }
   switch (Output.getPrimaryOutputType()) {
-  case types::TY_Object:
+  case file_types::TY_Object:
     return "-c";
-  case types::TY_PCH:
+  case file_types::TY_PCH:
     return "-emit-pch";
-  case types::TY_RawSIL:
+  case file_types::TY_RawSIL:
     return "-emit-silgen";
-  case types::TY_SIL:
+  case file_types::TY_SIL:
     return "-emit-sil";
-  case types::TY_RawSIB:
+  case file_types::TY_RawSIB:
     return "-emit-sibgen";
-  case types::TY_SIB:
+  case file_types::TY_SIB:
     return "-emit-sib";
-  case types::TY_LLVM_IR:
+  case file_types::TY_LLVM_IR:
     return "-emit-ir";
-  case types::TY_LLVM_BC:
+  case file_types::TY_LLVM_BC:
     return "-emit-bc";
-  case types::TY_Assembly:
+  case file_types::TY_Assembly:
     return "-S";
-  case types::TY_SwiftModuleFile:
+  case file_types::TY_SwiftModuleFile:
     // Since this is our primary output, we need to specify the option here.
     return "-emit-module";
-  case types::TY_ImportedModules:
+  case file_types::TY_ImportedModules:
     return "-emit-imported-modules";
-  case types::TY_IndexData:
+  case file_types::TY_IndexData:
     return "-typecheck";
-  case types::TY_Remapping:
+  case file_types::TY_Remapping:
     return "-update-code";
-  case types::TY_Nothing:
+  case file_types::TY_Nothing:
     // We were told to output nothing, so get the last mode option and use that.
     if (const Arg *A = Args.getLastArg(options::OPT_modes_Group))
       return A->getSpelling().data();
     else
       llvm_unreachable("We were told to perform a standard compile, "
                        "but no mode option was passed to the driver.");
-  case types::TY_Swift:
-  case types::TY_dSYM:
-  case types::TY_AutolinkFile:
-  case types::TY_Dependencies:
-  case types::TY_SwiftModuleDocFile:
-  case types::TY_ClangModuleFile:
-  case types::TY_SerializedDiagnostics:
-  case types::TY_ObjCHeader:
-  case types::TY_Image:
-  case types::TY_SwiftDeps:
-  case types::TY_ModuleTrace:
-  case types::TY_TBD:
-  case types::TY_OptRecord:
+  case file_types::TY_Swift:
+  case file_types::TY_dSYM:
+  case file_types::TY_AutolinkFile:
+  case file_types::TY_Dependencies:
+  case file_types::TY_SwiftModuleDocFile:
+  case file_types::TY_ClangModuleFile:
+  case file_types::TY_SerializedDiagnostics:
+  case file_types::TY_ObjCHeader:
+  case file_types::TY_Image:
+  case file_types::TY_SwiftDeps:
+  case file_types::TY_ModuleTrace:
+  case file_types::TY_TBD:
+  case file_types::TY_OptRecord:
     llvm_unreachable("Output type can never be primary output.");
-  case types::TY_INVALID:
+  case file_types::TY_INVALID:
     llvm_unreachable("Invalid type ID");
   }
 }
@@ -470,7 +468,7 @@
   if (UsePrimaryFileList) {
     Arguments.push_back("-primary-filelist");
     Arguments.push_back(getTemporaryFilePath("primaryInputs", ""));
-    FilelistInfos.push_back({Arguments.back(), types::TY_Swift,
+    FilelistInfos.push_back({Arguments.back(), file_types::TY_Swift,
                              FilelistInfo::WhichFiles::PrimaryInputs});
   }
   if (!UseFileList || !UsePrimaryFileList) {
@@ -482,7 +480,7 @@
   if (UseSupplementaryOutputFileList) {
     Arguments.push_back("-supplementary-output-file-map");
     Arguments.push_back(getTemporaryFilePath("supplementaryOutputs", ""));
-    FilelistInfos.push_back({Arguments.back(), types::TY_INVALID,
+    FilelistInfos.push_back({Arguments.back(), file_types::TY_INVALID,
                              FilelistInfo::WhichFiles::SupplementaryOutput});
   } else {
     addFrontendSupplementaryOutputArguments(Arguments);
@@ -511,7 +509,7 @@
     primaries.insert(A->getValue());
   }
   for (auto inputPair : getTopLevelInputFiles()) {
-    if (filterByType && !types::isPartOfSwiftCompilation(inputPair.first))
+    if (filterByType && !file_types::isPartOfSwiftCompilation(inputPair.first))
       continue;
     const char *inputName = inputPair.second->getValue();
     const bool isPrimary = primaries.count(inputName);
@@ -528,29 +526,31 @@
     ArgStringList &arguments) const {
   // FIXME: Get these and other argument strings from the same place for both
   // driver and frontend.
-  addOutputsOfType(arguments, Output, Args, types::ID::TY_SwiftModuleFile,
+  addOutputsOfType(arguments, Output, Args, file_types::ID::TY_SwiftModuleFile,
                    "-emit-module-path");
 
-  addOutputsOfType(arguments, Output, Args, types::TY_SwiftModuleDocFile,
+  addOutputsOfType(arguments, Output, Args, file_types::TY_SwiftModuleDocFile,
                    "-emit-module-doc-path");
 
-  addOutputsOfType(arguments, Output, Args, types::TY_SerializedDiagnostics,
+  addOutputsOfType(arguments, Output, Args,
+                   file_types::TY_SerializedDiagnostics,
                    "-serialize-diagnostics-path");
 
-  if (addOutputsOfType(arguments, Output, Args, types::ID::TY_ObjCHeader,
+  if (addOutputsOfType(arguments, Output, Args, file_types::ID::TY_ObjCHeader,
                        "-emit-objc-header-path")) {
     assert(OI.CompilerMode == OutputInfo::Mode::SingleCompile &&
            "The Swift tool should only emit an Obj-C header in single compile"
            "mode!");
   }
 
-  addOutputsOfType(arguments, Output, Args, types::TY_Dependencies,
+  addOutputsOfType(arguments, Output, Args, file_types::TY_Dependencies,
                    "-emit-dependencies-path");
-  addOutputsOfType(arguments, Output, Args, types::TY_SwiftDeps,
+  addOutputsOfType(arguments, Output, Args, file_types::TY_SwiftDeps,
                    "-emit-reference-dependencies-path");
-  addOutputsOfType(arguments, Output, Args, types::TY_ModuleTrace,
+  addOutputsOfType(arguments, Output, Args, file_types::TY_ModuleTrace,
                    "-emit-loaded-module-trace-path");
-  addOutputsOfType(arguments, Output, Args, types::TY_TBD, "-emit-tbd-path");
+  addOutputsOfType(arguments, Output, Args, file_types::TY_TBD,
+                   "-emit-tbd-path");
 }
 
 ToolChain::InvocationInfo
@@ -603,19 +603,19 @@
   case OutputInfo::Mode::StandardCompile:
   case OutputInfo::Mode::SingleCompile: {
     switch (context.Output.getPrimaryOutputType()) {
-    case types::TY_Object:
+    case file_types::TY_Object:
       FrontendModeOption = "-c";
       break;
-    case types::TY_LLVM_IR:
+    case file_types::TY_LLVM_IR:
       FrontendModeOption = "-emit-ir";
       break;
-    case types::TY_LLVM_BC:
+    case file_types::TY_LLVM_BC:
       FrontendModeOption = "-emit-bc";
       break;
-    case types::TY_Assembly:
+    case file_types::TY_Assembly:
       FrontendModeOption = "-S";
       break;
-    case types::TY_Nothing:
+    case file_types::TY_Nothing:
       // We were told to output nothing, so get the last mode option and use that.
       if (const Arg *A = context.Args.getLastArg(options::OPT_modes_Group))
         FrontendModeOption = A->getSpelling().data();
@@ -624,31 +624,31 @@
                          "but no mode option was passed to the driver.");
       break;
 
-    case types::TY_ImportedModules:
-    case types::TY_TBD:
-    case types::TY_SwiftModuleFile:
-    case types::TY_RawSIL:
-    case types::TY_RawSIB:
-    case types::TY_SIL:
-    case types::TY_SIB:
-    case types::TY_PCH:
-    case types::TY_IndexData:
+    case file_types::TY_ImportedModules:
+    case file_types::TY_TBD:
+    case file_types::TY_SwiftModuleFile:
+    case file_types::TY_RawSIL:
+    case file_types::TY_RawSIB:
+    case file_types::TY_SIL:
+    case file_types::TY_SIB:
+    case file_types::TY_PCH:
+    case file_types::TY_IndexData:
       llvm_unreachable("Cannot be output from backend job");
-    case types::TY_Swift:
-    case types::TY_dSYM:
-    case types::TY_AutolinkFile:
-    case types::TY_Dependencies:
-    case types::TY_SwiftModuleDocFile:
-    case types::TY_ClangModuleFile:
-    case types::TY_SerializedDiagnostics:
-    case types::TY_ObjCHeader:
-    case types::TY_Image:
-    case types::TY_SwiftDeps:
-    case types::TY_Remapping:
-    case types::TY_ModuleTrace:
-    case types::TY_OptRecord:
+    case file_types::TY_Swift:
+    case file_types::TY_dSYM:
+    case file_types::TY_AutolinkFile:
+    case file_types::TY_Dependencies:
+    case file_types::TY_SwiftModuleDocFile:
+    case file_types::TY_ClangModuleFile:
+    case file_types::TY_SerializedDiagnostics:
+    case file_types::TY_ObjCHeader:
+    case file_types::TY_Image:
+    case file_types::TY_SwiftDeps:
+    case file_types::TY_Remapping:
+    case file_types::TY_ModuleTrace:
+    case file_types::TY_OptRecord:
       llvm_unreachable("Output type can never be primary output.");
-    case types::TY_INVALID:
+    case file_types::TY_INVALID:
       llvm_unreachable("Invalid type ID");
     }
     break;
@@ -717,7 +717,7 @@
   Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName));
 
   // Add the output file argument if necessary.
-  if (context.Output.getPrimaryOutputType() != types::TY_Nothing) {
+  if (context.Output.getPrimaryOutputType() != file_types::TY_Nothing) {
     for (auto FileName : context.Output.getPrimaryOutputFilenames()) {
       Arguments.push_back("-o");
       Arguments.push_back(context.Args.MakeArgString(FileName));
@@ -741,20 +741,24 @@
   if (context.shouldUseInputFileList()) {
     Arguments.push_back("-filelist");
     Arguments.push_back(context.getTemporaryFilePath("inputs", ""));
-    II.FilelistInfos.push_back({Arguments.back(), types::TY_SwiftModuleFile,
+    II.FilelistInfos.push_back({Arguments.back(),
+                                file_types::TY_SwiftModuleFile,
                                 FilelistInfo::WhichFiles::Input});
 
-    addInputsOfType(Arguments, context.InputActions, types::TY_SwiftModuleFile);
+    addInputsOfType(Arguments, context.InputActions,
+                    file_types::TY_SwiftModuleFile);
   } else {
     size_t origLen = Arguments.size();
     (void)origLen;
-    addInputsOfType(Arguments, context.Inputs, context.Args, types::TY_SwiftModuleFile);
-    addInputsOfType(Arguments, context.InputActions, types::TY_SwiftModuleFile);
+    addInputsOfType(Arguments, context.Inputs, context.Args,
+                    file_types::TY_SwiftModuleFile);
+    addInputsOfType(Arguments, context.InputActions,
+                    file_types::TY_SwiftModuleFile);
     assert(Arguments.size() - origLen >=
-           context.Inputs.size() + context.InputActions.size() ||
-           context.OI.CompilerOutputType == types::TY_Nothing);
+               context.Inputs.size() + context.InputActions.size() ||
+           context.OI.CompilerOutputType == file_types::TY_Nothing);
     assert((Arguments.size() - origLen == context.Inputs.size() ||
-            context.OI.CompilerOutputType == types::TY_Nothing ||
+            context.OI.CompilerOutputType == file_types::TY_Nothing ||
             !context.InputActions.empty()) &&
            "every input to MergeModule must generate a swiftmodule");
   }
@@ -774,22 +778,22 @@
   addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
                         Arguments);
   addOutputsOfType(Arguments, context.Output, context.Args,
-                   types::TY_SwiftModuleDocFile, "-emit-module-doc-path");
+                   file_types::TY_SwiftModuleDocFile, "-emit-module-doc-path");
   addOutputsOfType(Arguments, context.Output, context.Args,
-                   types::TY_SerializedDiagnostics,
+                   file_types::TY_SerializedDiagnostics,
                    "-serialize-diagnostics-path");
   addOutputsOfType(Arguments, context.Output, context.Args,
-                   types::TY_ObjCHeader, "-emit-objc-header-path");
+                   file_types::TY_ObjCHeader, "-emit-objc-header-path");
 
   context.Args.AddLastArg(Arguments, options::OPT_import_objc_header);
 
   Arguments.push_back("-module-name");
   Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName));
 
-  assert(context.Output.getPrimaryOutputType() == types::TY_SwiftModuleFile &&
+  assert(context.Output.getPrimaryOutputType() ==
+             file_types::TY_SwiftModuleFile &&
          "The MergeModule tool only produces swiftmodule files!");
 
-
   Arguments.push_back("-o");
   Arguments.push_back(context.Args.MakeArgString(
       context.Output.getPrimaryOutputFilename()));
@@ -804,12 +808,14 @@
 
   Arguments.push_back("-modulewrap");
 
-  addInputsOfType(Arguments, context.Inputs, context.Args, types::TY_SwiftModuleFile);
-  addInputsOfType(Arguments, context.InputActions, types::TY_SwiftModuleFile);
+  addInputsOfType(Arguments, context.Inputs, context.Args,
+                  file_types::TY_SwiftModuleFile);
+  addInputsOfType(Arguments, context.InputActions,
+                  file_types::TY_SwiftModuleFile);
   assert(Arguments.size() == 2 &&
          "ModuleWrap expects exactly one merged swiftmodule as input");
 
-  assert(context.Output.getPrimaryOutputType() == types::TY_Object &&
+  assert(context.Output.getPrimaryOutputType() == file_types::TY_Object &&
          "The -modulewrap mode only produces object files");
 
   Arguments.push_back("-target");
@@ -875,7 +881,7 @@
                                const JobContext &context) const {
   assert(context.Inputs.size() == 1);
   assert(context.InputActions.empty());
-  assert(context.Output.getPrimaryOutputType() == types::TY_dSYM);
+  assert(context.Output.getPrimaryOutputType() == file_types::TY_dSYM);
 
   ArgStringList Arguments;
 
@@ -916,9 +922,9 @@
   assert(context.Inputs.empty());
   assert(context.InputActions.size() == 1);
   assert((!job.isPersistentPCH() &&
-            context.Output.getPrimaryOutputType() == types::TY_PCH) ||
+          context.Output.getPrimaryOutputType() == file_types::TY_PCH) ||
          (job.isPersistentPCH() &&
-            context.Output.getPrimaryOutputType() == types::TY_Nothing));
+          context.Output.getPrimaryOutputType() == file_types::TY_Nothing));
 
   ArgStringList Arguments;
 
@@ -927,10 +933,10 @@
   addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
                         Arguments);
   addOutputsOfType(Arguments, context.Output, context.Args,
-                   types::TY_SerializedDiagnostics,
+                   file_types::TY_SerializedDiagnostics,
                    "-serialize-diagnostics-path");
 
-  addInputsOfType(Arguments, context.InputActions, types::TY_ObjCHeader);
+  addInputsOfType(Arguments, context.InputActions, file_types::TY_ObjCHeader);
   context.Args.AddLastArg(Arguments, options::OPT_index_store_path);
 
   if (job.isPersistentPCH()) {
@@ -1055,7 +1061,8 @@
 /// relative to the compiler.
 static void getRuntimeLibraryPath(SmallVectorImpl<char> &runtimeLibPath,
                                   const llvm::opt::ArgList &args,
-                                  const ToolChain &TC) {
+                                  const ToolChain &TC,
+                                  bool shared) {
   // FIXME: Duplicated from CompilerInvocation, but in theory the runtime
   // library link path and the standard library module import path don't
   // need to be the same.
@@ -1067,7 +1074,7 @@
     runtimeLibPath.append(programPath.begin(), programPath.end());
     llvm::sys::path::remove_filename(runtimeLibPath); // remove /swift
     llvm::sys::path::remove_filename(runtimeLibPath); // remove /bin
-    llvm::sys::path::append(runtimeLibPath, "lib", "swift");
+    llvm::sys::path::append(runtimeLibPath, "lib", shared ? "swift" : "swift_static");
   }
   llvm::sys::path::append(runtimeLibPath,
                           getPlatformNameForTriple(TC.getTriple()));
@@ -1077,7 +1084,7 @@
                                 SmallString<128> &LibPath) {
   const llvm::Triple &T = TC.getTriple();
 
-  getRuntimeLibraryPath(LibPath, Args, TC);
+  getRuntimeLibraryPath(LibPath, Args, TC, /*Shared=*/ true);
   // Remove platform name.
   llvm::sys::path::remove_filename(LibPath);
   llvm::sys::path::append(LibPath, "clang", "lib",
@@ -1085,35 +1092,13 @@
                                          : getPlatformNameForTriple(T));
 }
 
-/// Get the runtime library link path for static linking,
-/// which is platform-specific and found relative to the compiler.
-static void getRuntimeStaticLibraryPath(SmallVectorImpl<char> &runtimeLibPath,
-                                  const llvm::opt::ArgList &args,
-                                  const ToolChain &TC) {
-  // FIXME: Duplicated from CompilerInvocation, but in theory the runtime
-  // library link path and the standard library module import path don't
-  // need to be the same.
-  if (const Arg *A = args.getLastArg(options::OPT_resource_dir)) {
-    StringRef value = A->getValue();
-    runtimeLibPath.append(value.begin(), value.end());
-  } else {
-    auto programPath = TC.getDriver().getSwiftProgramPath();
-    runtimeLibPath.append(programPath.begin(), programPath.end());
-    llvm::sys::path::remove_filename(runtimeLibPath); // remove /swift
-    llvm::sys::path::remove_filename(runtimeLibPath); // remove /bin
-    llvm::sys::path::append(runtimeLibPath, "lib", "swift_static");
-  }
-  llvm::sys::path::append(runtimeLibPath,
-                          getPlatformNameForTriple(TC.getTriple()));
-}
-
 ToolChain::InvocationInfo
 toolchains::Darwin::constructInvocation(const InterpretJobAction &job,
                                         const JobContext &context) const {
   InvocationInfo II = ToolChain::constructInvocation(job, context);
 
   SmallString<128> runtimeLibraryPath;
-  getRuntimeLibraryPath(runtimeLibraryPath, context.Args, *this);
+  getRuntimeLibraryPath(runtimeLibraryPath, context.Args, *this, /*Shared=*/ true);
 
   addPathEnvironmentVariableIfNeeded(II.ExtraEnvironment, "DYLD_LIBRARY_PATH",
                                      ":", options::OPT_L, context.Args,
@@ -1218,7 +1203,7 @@
                            StringRef LinuxLibName,
                            const ToolChain &TC) {
   SmallString<128> Dir;
-  getRuntimeLibraryPath(Dir, Args, TC);
+  getRuntimeLibraryPath(Dir, Args, TC, /*Shared=*/ true);
   // Remove platform name.
   llvm::sys::path::remove_filename(Dir);
   llvm::sys::path::append(Dir, "clang", "lib", "linux");
@@ -1270,7 +1255,7 @@
 ToolChain::InvocationInfo
 toolchains::Darwin::constructInvocation(const LinkJobAction &job,
                                         const JobContext &context) const {
-  assert(context.Output.getPrimaryOutputType() == types::TY_Image &&
+  assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
          "Invalid linker output type.");
 
   if (context.Args.hasFlag(options::OPT_static_executable,
@@ -1300,26 +1285,26 @@
   if (context.shouldUseInputFileList()) {
     Arguments.push_back("-filelist");
     Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList"));
-    II.FilelistInfos.push_back(
-        {Arguments.back(), types::TY_Object, FilelistInfo::WhichFiles::Input});
+    II.FilelistInfos.push_back({Arguments.back(), file_types::TY_Object,
+                                FilelistInfo::WhichFiles::Input});
   } else {
     addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
-                           types::TY_Object);
+                           file_types::TY_Object);
   }
 
-  addInputsOfType(Arguments, context.InputActions, types::TY_Object);
+  addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
 
   if (context.OI.CompilerMode == OutputInfo::Mode::SingleCompile)
     addInputsOfType(Arguments, context.Inputs, context.Args,
-                    types::TY_SwiftModuleFile, "-add_ast_path");
+                    file_types::TY_SwiftModuleFile, "-add_ast_path");
   else
     addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
-                           types::TY_SwiftModuleFile, "-add_ast_path");
+                           file_types::TY_SwiftModuleFile, "-add_ast_path");
 
   // Add all .swiftmodule file inputs as arguments, preceded by the
   // "-add_ast_path" linker option.
-  addInputsOfType(Arguments, context.InputActions, types::TY_SwiftModuleFile,
-                  "-add_ast_path");
+  addInputsOfType(Arguments, context.InputActions,
+                  file_types::TY_SwiftModuleFile, "-add_ast_path");
 
   switch (job.getKind()) {
   case LinkKind::None:
@@ -1426,7 +1411,7 @@
   // Add the runtime library link path, which is platform-specific and found
   // relative to the compiler.
   SmallString<128> RuntimeLibPath;
-  getRuntimeLibraryPath(RuntimeLibPath, context.Args, *this);
+  getRuntimeLibraryPath(RuntimeLibPath, context.Args, *this, /*Shared=*/ true);
 
   // Link the standard library.
   Arguments.push_back("-L");
@@ -1434,7 +1419,7 @@
                             options::OPT_no_static_stdlib,
                             false)) {
     SmallString<128> StaticRuntimeLibPath;
-    getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this);
+    getRuntimeLibraryPath(StaticRuntimeLibPath, context.Args, *this, /*Shared=*/ false);
     Arguments.push_back(context.Args.MakeArgString(StaticRuntimeLibPath));
     Arguments.push_back("-lc++");
     Arguments.push_back("-framework");
@@ -1533,7 +1518,7 @@
   InvocationInfo II = ToolChain::constructInvocation(job, context);
 
   SmallString<128> runtimeLibraryPath;
-  getRuntimeLibraryPath(runtimeLibraryPath, context.Args, *this);
+  getRuntimeLibraryPath(runtimeLibraryPath, context.Args, *this, /*Shared=*/ true);
 
   addPathEnvironmentVariableIfNeeded(II.ExtraEnvironment, "LD_LIBRARY_PATH",
                                      ":", options::OPT_L, context.Args,
@@ -1545,12 +1530,12 @@
 ToolChain::InvocationInfo
 toolchains::GenericUnix::constructInvocation(const AutolinkExtractJobAction &job,
                                              const JobContext &context) const {
-  assert(context.Output.getPrimaryOutputType() == types::TY_AutolinkFile);
+  assert(context.Output.getPrimaryOutputType() == file_types::TY_AutolinkFile);
 
   ArgStringList Arguments;
   addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
-                         types::TY_Object);
-  addInputsOfType(Arguments, context.InputActions, types::TY_Object);
+                         file_types::TY_Object);
+  addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
 
   Arguments.push_back("-o");
   Arguments.push_back(context.Args.MakeArgString(
@@ -1593,7 +1578,7 @@
 ToolChain::InvocationInfo
 toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
                                              const JobContext &context) const {
-  assert(context.Output.getPrimaryOutputType() == types::TY_Image &&
+  assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
          "Invalid linker output type.");
 
   ArgStringList Arguments;
@@ -1667,10 +1652,10 @@
   }
 
   SmallString<128> SharedRuntimeLibPath;
-  getRuntimeLibraryPath(SharedRuntimeLibPath, context.Args, *this);
+  getRuntimeLibraryPath(SharedRuntimeLibPath, context.Args, *this, /*Shared=*/ true);
 
   SmallString<128> StaticRuntimeLibPath;
-  getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this);
+  getRuntimeLibraryPath(StaticRuntimeLibPath, context.Args, *this, /*Shared=*/ false);
 
   // Add the runtime library link path, which is platform-specific and found
   // relative to the compiler.
@@ -1690,8 +1675,8 @@
   Arguments.push_back(context.Args.MakeArgString(swiftrtPath));
 
   addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
-                         types::TY_Object);
-  addInputsOfType(Arguments, context.InputActions, types::TY_Object);
+                         file_types::TY_Object);
+  addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
 
   for (const Arg *arg : context.Args.filtered(options::OPT_F,
                                               options::OPT_Fsystem)) {
@@ -1710,7 +1695,7 @@
   // Add any autolinking scripts to the arguments
   for (const Job *Cmd : context.Inputs) {
     auto &OutputInfo = Cmd->getOutput();
-    if (OutputInfo.getPrimaryOutputType() == types::TY_AutolinkFile)
+    if (OutputInfo.getPrimaryOutputType() == file_types::TY_AutolinkFile)
       Arguments.push_back(context.Args.MakeArgString(
           Twine("@") + OutputInfo.getPrimaryOutputFilename()));
   }
diff --git a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp
index 1e84a82..58473d2 100644
--- a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp
+++ b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp
@@ -467,16 +467,16 @@
   SupplementaryOutputPaths paths;
   if (!map)
     return paths;
-  const std::pair<types::ID, std::string &> typesAndStrings[] = {
-      {types::TY_ObjCHeader, paths.ObjCHeaderOutputPath},
-      {types::TY_SwiftModuleFile, paths.ModuleOutputPath},
-      {types::TY_SwiftModuleDocFile, paths.ModuleDocOutputPath},
-      {types::TY_Dependencies, paths.DependenciesFilePath},
-      {types::TY_SwiftDeps, paths.ReferenceDependenciesFilePath},
-      {types::TY_SerializedDiagnostics, paths.SerializedDiagnosticsPath},
-      {types::TY_ModuleTrace, paths.LoadedModuleTracePath},
-      {types::TY_TBD, paths.TBDPath}};
-  for (const std::pair<types::ID, std::string &> &typeAndString :
+  const std::pair<file_types::ID, std::string &> typesAndStrings[] = {
+      {file_types::TY_ObjCHeader, paths.ObjCHeaderOutputPath},
+      {file_types::TY_SwiftModuleFile, paths.ModuleOutputPath},
+      {file_types::TY_SwiftModuleDocFile, paths.ModuleDocOutputPath},
+      {file_types::TY_Dependencies, paths.DependenciesFilePath},
+      {file_types::TY_SwiftDeps, paths.ReferenceDependenciesFilePath},
+      {file_types::TY_SerializedDiagnostics, paths.SerializedDiagnosticsPath},
+      {file_types::TY_ModuleTrace, paths.LoadedModuleTracePath},
+      {file_types::TY_TBD, paths.TBDPath}};
+  for (const std::pair<file_types::ID, std::string &> &typeAndString :
        typesAndStrings) {
     auto const out = map->find(typeAndString.first);
     typeAndString.second = out == map->end() ? "" : out->second;
@@ -518,13 +518,23 @@
   }
 
   std::vector<SupplementaryOutputPaths> outputPaths;
+  bool hadError = false;
   InputsAndOutputs.forEachInputProducingSupplementaryOutput(
       [&](const InputFile &input) -> bool {
         const TypeToPathMap *mapForInput =
             OFM->getOutputMapForInput(input.file());
+        if (!mapForInput) {
+          Diags.diagnose(
+              SourceLoc(),
+              diag::error_missing_entry_in_supplementary_output_file_map,
+              supplementaryFileMapPath, input.file());
+          hadError = true;
+        }
         outputPaths.push_back(createFromTypeToPathMap(mapForInput));
         return false;
       });
+  if (hadError)
+    return None;
 
   return outputPaths;
 }
diff --git a/lib/Frontend/OutputFileMap.cpp b/lib/Frontend/OutputFileMap.cpp
index 0ed1356..02805e3 100644
--- a/lib/Frontend/OutputFileMap.cpp
+++ b/lib/Frontend/OutputFileMap.cpp
@@ -65,12 +65,12 @@
 }
 
 void OutputFileMap::dump(llvm::raw_ostream &os, bool Sort) const {
-  typedef std::pair<types::ID, std::string> TypePathPair;
+  typedef std::pair<file_types::ID, std::string> TypePathPair;
 
-  auto printOutputPair = [&os] (StringRef InputPath,
-                                const TypePathPair &OutputPair) -> void {
-    os << InputPath << " -> " << types::getTypeName(OutputPair.first) << ": \""
-       << OutputPair.second << "\"\n";
+  auto printOutputPair = [&os](StringRef InputPath,
+                               const TypePathPair &OutputPair) -> void {
+    os << InputPath << " -> " << file_types::getTypeName(OutputPair.first)
+       << ": \"" << OutputPair.second << "\"\n";
   };
 
   if (Sort) {
@@ -116,9 +116,9 @@
     writeQuotedEscaped(os, input);
     os << ":\n";
     for (auto &typeAndOutputPath : *outputMap) {
-      types::ID type = typeAndOutputPath.getFirst();
+      file_types::ID type = typeAndOutputPath.getFirst();
       StringRef output = typeAndOutputPath.getSecond();
-      os << "  " << types::getTypeName(type) << ": ";
+      os << "  " << file_types::getTypeName(type) << ": ";
       writeQuotedEscaped(os, output);
       os << "\n";
     }
@@ -205,16 +205,16 @@
         return constructError("path not a scalar node");
 
       llvm::SmallString<16> KindStorage;
-      types::ID Kind =
-        types::lookupTypeForName(KindNode->getValue(KindStorage));
+      file_types::ID Kind =
+          file_types::lookupTypeForName(KindNode->getValue(KindStorage));
 
       // Ignore unknown types, so that an older swiftc can be used with a newer
       // build system.
-      if (Kind == types::TY_INVALID)
+      if (Kind == file_types::TY_INVALID)
         continue;
 
       llvm::SmallString<128> PathStorage;
-      OutputMap.insert(std::pair<types::ID, std::string>(
+      OutputMap.insert(std::pair<file_types::ID, std::string>(
           Kind, resolvePath(Path, PathStorage)));
     }
 
diff --git a/lib/Frontend/Types.cpp b/lib/Frontend/Types.cpp
index b0e24b7..f79bed8 100644
--- a/lib/Frontend/Types.cpp
+++ b/lib/Frontend/Types.cpp
@@ -10,14 +10,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "swift/Frontend/Types.h"
+#include "swift/Frontend/FileTypes.h"
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
 
 using namespace swift;
-using namespace swift::types;
+using namespace swift::file_types;
 
 struct TypeInfo {
   const char *Name;
@@ -36,65 +36,63 @@
   return TypeInfos[Id];
 }
 
-StringRef types::getTypeName(ID Id) {
-  return getInfo(Id).Name;
-}
+StringRef file_types::getTypeName(ID Id) { return getInfo(Id).Name; }
 
-StringRef types::getTypeTempSuffix(ID Id) {
+StringRef file_types::getTypeTempSuffix(ID Id) {
   return getInfo(Id).TempSuffix;
 }
 
-ID types::lookupTypeForExtension(StringRef Ext) {
+ID file_types::lookupTypeForExtension(StringRef Ext) {
   if (Ext.empty())
     return TY_INVALID;
   assert(Ext.front() == '.' && "not a file extension");
-  return llvm::StringSwitch<types::ID>(Ext.drop_front())
+  return llvm::StringSwitch<file_types::ID>(Ext.drop_front())
 #define TYPE(NAME, ID, SUFFIX, FLAGS) \
            .Case(SUFFIX, TY_##ID)
 #include "swift/Frontend/Types.def"
-           .Default(TY_INVALID);
+      .Default(TY_INVALID);
 }
 
-ID types::lookupTypeForName(StringRef Name) {
-  return llvm::StringSwitch<types::ID>(Name)
+ID file_types::lookupTypeForName(StringRef Name) {
+  return llvm::StringSwitch<file_types::ID>(Name)
 #define TYPE(NAME, ID, SUFFIX, FLAGS) \
            .Case(NAME, TY_##ID)
 #include "swift/Frontend/Types.def"
-           .Default(TY_INVALID);
+      .Default(TY_INVALID);
 }
 
-bool types::isTextual(ID Id) {
+bool file_types::isTextual(ID Id) {
   switch (Id) {
-  case types::TY_Swift:
-  case types::TY_SIL:
-  case types::TY_Dependencies:
-  case types::TY_Assembly:
-  case types::TY_RawSIL:
-  case types::TY_LLVM_IR:
-  case types::TY_ObjCHeader:
-  case types::TY_AutolinkFile:
-  case types::TY_ImportedModules:
-  case types::TY_TBD:
-  case types::TY_ModuleTrace:
-  case types::TY_OptRecord:
+  case file_types::TY_Swift:
+  case file_types::TY_SIL:
+  case file_types::TY_Dependencies:
+  case file_types::TY_Assembly:
+  case file_types::TY_RawSIL:
+  case file_types::TY_LLVM_IR:
+  case file_types::TY_ObjCHeader:
+  case file_types::TY_AutolinkFile:
+  case file_types::TY_ImportedModules:
+  case file_types::TY_TBD:
+  case file_types::TY_ModuleTrace:
+  case file_types::TY_OptRecord:
     return true;
-  case types::TY_Image:
-  case types::TY_Object:
-  case types::TY_dSYM:
-  case types::TY_PCH:
-  case types::TY_SIB:
-  case types::TY_RawSIB:
-  case types::TY_SwiftModuleFile:
-  case types::TY_SwiftModuleDocFile:
-  case types::TY_LLVM_BC:
-  case types::TY_SerializedDiagnostics:
-  case types::TY_ClangModuleFile:
-  case types::TY_SwiftDeps:
-  case types::TY_Nothing:
-  case types::TY_Remapping:
-  case types::TY_IndexData:
+  case file_types::TY_Image:
+  case file_types::TY_Object:
+  case file_types::TY_dSYM:
+  case file_types::TY_PCH:
+  case file_types::TY_SIB:
+  case file_types::TY_RawSIB:
+  case file_types::TY_SwiftModuleFile:
+  case file_types::TY_SwiftModuleDocFile:
+  case file_types::TY_LLVM_BC:
+  case file_types::TY_SerializedDiagnostics:
+  case file_types::TY_ClangModuleFile:
+  case file_types::TY_SwiftDeps:
+  case file_types::TY_Nothing:
+  case file_types::TY_Remapping:
+  case file_types::TY_IndexData:
     return false;
-  case types::TY_INVALID:
+  case file_types::TY_INVALID:
     llvm_unreachable("Invalid type ID.");
   }
 
@@ -102,38 +100,38 @@
   llvm_unreachable("All switch cases are covered");
 }
 
-bool types::isAfterLLVM(ID Id) {
+bool file_types::isAfterLLVM(ID Id) {
   switch (Id) {
-  case types::TY_Assembly:
-  case types::TY_LLVM_IR:
-  case types::TY_LLVM_BC:
-  case types::TY_Object:
+  case file_types::TY_Assembly:
+  case file_types::TY_LLVM_IR:
+  case file_types::TY_LLVM_BC:
+  case file_types::TY_Object:
     return true;
-  case types::TY_Swift:
-  case types::TY_PCH:
-  case types::TY_ImportedModules:
-  case types::TY_TBD:
-  case types::TY_SIL:
-  case types::TY_Dependencies:
-  case types::TY_RawSIL:
-  case types::TY_ObjCHeader:
-  case types::TY_AutolinkFile:
-  case types::TY_Image:
-  case types::TY_dSYM:
-  case types::TY_SIB:
-  case types::TY_RawSIB:
-  case types::TY_SwiftModuleFile:
-  case types::TY_SwiftModuleDocFile:
-  case types::TY_SerializedDiagnostics:
-  case types::TY_ClangModuleFile:
-  case types::TY_SwiftDeps:
-  case types::TY_Nothing:
-  case types::TY_Remapping:
-  case types::TY_IndexData:
-  case types::TY_ModuleTrace:
-  case types::TY_OptRecord:
+  case file_types::TY_Swift:
+  case file_types::TY_PCH:
+  case file_types::TY_ImportedModules:
+  case file_types::TY_TBD:
+  case file_types::TY_SIL:
+  case file_types::TY_Dependencies:
+  case file_types::TY_RawSIL:
+  case file_types::TY_ObjCHeader:
+  case file_types::TY_AutolinkFile:
+  case file_types::TY_Image:
+  case file_types::TY_dSYM:
+  case file_types::TY_SIB:
+  case file_types::TY_RawSIB:
+  case file_types::TY_SwiftModuleFile:
+  case file_types::TY_SwiftModuleDocFile:
+  case file_types::TY_SerializedDiagnostics:
+  case file_types::TY_ClangModuleFile:
+  case file_types::TY_SwiftDeps:
+  case file_types::TY_Nothing:
+  case file_types::TY_Remapping:
+  case file_types::TY_IndexData:
+  case file_types::TY_ModuleTrace:
+  case file_types::TY_OptRecord:
     return false;
-  case types::TY_INVALID:
+  case file_types::TY_INVALID:
     llvm_unreachable("Invalid type ID.");
   }
 
@@ -141,38 +139,38 @@
   llvm_unreachable("All switch cases are covered");
 }
 
-bool types::isPartOfSwiftCompilation(ID Id) {
+bool file_types::isPartOfSwiftCompilation(ID Id) {
   switch (Id) {
-  case types::TY_Swift:
-  case types::TY_SIL:
-  case types::TY_RawSIL:
-  case types::TY_SIB:
-  case types::TY_RawSIB:
+  case file_types::TY_Swift:
+  case file_types::TY_SIL:
+  case file_types::TY_RawSIL:
+  case file_types::TY_SIB:
+  case file_types::TY_RawSIB:
     return true;
-  case types::TY_Assembly:
-  case types::TY_LLVM_IR:
-  case types::TY_LLVM_BC:
-  case types::TY_Object:
-  case types::TY_Dependencies:
-  case types::TY_ObjCHeader:
-  case types::TY_AutolinkFile:
-  case types::TY_PCH:
-  case types::TY_ImportedModules:
-  case types::TY_TBD:
-  case types::TY_Image:
-  case types::TY_dSYM:
-  case types::TY_SwiftModuleFile:
-  case types::TY_SwiftModuleDocFile:
-  case types::TY_SerializedDiagnostics:
-  case types::TY_ClangModuleFile:
-  case types::TY_SwiftDeps:
-  case types::TY_Nothing:
-  case types::TY_Remapping:
-  case types::TY_IndexData:
-  case types::TY_ModuleTrace:
-  case types::TY_OptRecord:
+  case file_types::TY_Assembly:
+  case file_types::TY_LLVM_IR:
+  case file_types::TY_LLVM_BC:
+  case file_types::TY_Object:
+  case file_types::TY_Dependencies:
+  case file_types::TY_ObjCHeader:
+  case file_types::TY_AutolinkFile:
+  case file_types::TY_PCH:
+  case file_types::TY_ImportedModules:
+  case file_types::TY_TBD:
+  case file_types::TY_Image:
+  case file_types::TY_dSYM:
+  case file_types::TY_SwiftModuleFile:
+  case file_types::TY_SwiftModuleDocFile:
+  case file_types::TY_SerializedDiagnostics:
+  case file_types::TY_ClangModuleFile:
+  case file_types::TY_SwiftDeps:
+  case file_types::TY_Nothing:
+  case file_types::TY_Remapping:
+  case file_types::TY_IndexData:
+  case file_types::TY_ModuleTrace:
+  case file_types::TY_OptRecord:
     return false;
-  case types::TY_INVALID:
+  case file_types::TY_INVALID:
     llvm_unreachable("Invalid type ID.");
   }
 
diff --git a/lib/IDE/TypeReconstruction.cpp b/lib/IDE/TypeReconstruction.cpp
index f522ab6..c3e3b15 100644
--- a/lib/IDE/TypeReconstruction.cpp
+++ b/lib/IDE/TypeReconstruction.cpp
@@ -131,7 +131,7 @@
                        bool allow_clang_importer = true) {
     assert(!module_name.empty());
     static ConstString g_ObjectiveCModule(MANGLING_MODULE_OBJC);
-    static ConstString g_BuiltinModule("Builtin");
+    static ConstString g_BuiltinModule(BUILTIN_NAME);
     static ConstString g_CModule(MANGLING_MODULE_CLANG_IMPORTER);
     if (allow_clang_importer) {
       if (module_name == g_ObjectiveCModule || module_name == g_CModule)
@@ -799,13 +799,13 @@
 
   StringRef builtin_name_ref(builtin_name);
 
-  if (builtin_name_ref.startswith("Builtin.")) {
+  if (builtin_name_ref.startswith(BUILTIN_TYPE_NAME_PREFIX)) {
     StringRef stripped_name_ref =
-        builtin_name_ref.drop_front(strlen("Builtin."));
+        builtin_name_ref.drop_front(strlen(BUILTIN_TYPE_NAME_PREFIX));
     SmallVector<ValueDecl *, 1> builtin_decls;
 
     result._module =
-        DeclsLookupSource::GetDeclsLookupSource(*ast, ConstString("Builtin"));
+        DeclsLookupSource::GetDeclsLookupSource(*ast, ConstString(BUILTIN_NAME));
 
     if (!FindNamedDecls(ast, ast->getIdentifier(stripped_name_ref), result)) {
       result.Clear();
@@ -814,7 +814,7 @@
     }
   } else {
     result._error = stringWithFormat(
-        "BuiltinTypeName %s doesn't start with Builtin.", builtin_name.c_str());
+        "BuiltinTypeName %s doesn't start with %s", builtin_name.c_str(), BUILTIN_TYPE_NAME_PREFIX);
   }
 }
 
@@ -1217,7 +1217,7 @@
       name->getText());
 }
 
-// VisitNodeFunction gets used for Function, Variable and Allocator:
+// VisitNodeFunction gets used for Function and Variable.
 static void VisitNodeFunction(
     ASTContext *ast,
     Demangle::NodePointer cur_node, VisitNodeResult &result) {
@@ -1347,25 +1347,6 @@
     }
   } while (0);
 
-  //                    if (node_kind == Demangle::Node::Kind::Allocator)
-  //                    {
-  //                        // For allocators we don't have an identifier for
-  //                        the name, we will
-  //                        // need to extract it from the class or struct in
-  //                        "identifier_result"
-  //                        //Find
-  //                        if (identifier_result.HasSingleType())
-  //                        {
-  //                            // This contains the class or struct
-  //                            StringRef init_name("init");
-  //
-  //                            if (FindFirstNamedDeclWithKind(ast, init_name,
-  //                            DeclKind::Constructor, identifier_result))
-  //                            {
-  //                            }
-  //                        }
-  //                    }
-
   if (identifier_result._types.size() == 1) {
     result._module = identifier_result._module;
     result._decls.push_back(identifier_result._decls[0]);
@@ -2229,6 +2210,7 @@
     VisitAllChildNodes(ast, node, result);
     break;
 
+  case Demangle::Node::Kind::Allocator:
   case Demangle::Node::Kind::Constructor:
     VisitNodeConstructor(ast, node, result);
     break;
@@ -2254,7 +2236,6 @@
     break;
 
   case Demangle::Node::Kind::Function:
-  case Demangle::Node::Kind::Allocator:
   case Demangle::Node::Kind::Variable:
   case Demangle::Node::Kind::Subscript: // Out of order on purpose
     VisitNodeFunction(ast, node, result);
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index c8c54bb..64cbec31 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -1810,9 +1810,8 @@
         break;
       }
       case FieldAccess::ConstantIndirect:
-        // Otherwise, swift_initClassMetadata_UniversalStrategy() will point
-        // the Objective-C runtime into the field offset vector of the
-        // instantiated metadata.
+        // Otherwise, swift_initClassMetadata() will point the Objective-C
+        // runtime into the field offset vector of the instantiated metadata.
         offsetPtr
           = llvm::ConstantPointerNull::get(IGM.IntPtrTy->getPointerTo());
         break;
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 6064068..9a3cfc2 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -1090,6 +1090,12 @@
     }
   }
   
+  // Emit property descriptors.
+  for (auto &prop : PrimaryIGM->getSILModule().getPropertyList()) {
+    CurrentIGMPtr IGM = getGenModule(prop.getDecl()->getInnermostDeclContext());
+    IGM->emitSILProperty(&prop);
+  }
+  
   for (auto Iter : *this) {
     IRGenModule *IGM = Iter.second;
     IGM->finishEmitAfterTopLevel();
@@ -1627,8 +1633,15 @@
   switch (getKind()) {
   case Kind::DispatchThunk:
   case Kind::DispatchThunkInitializer:
-  case Kind::DispatchThunkAllocator:
+  case Kind::DispatchThunkAllocator: {
+    auto *decl = getDecl();
+
+    // Protocol requirements don't have their own access control
+    if (auto *proto = dyn_cast<ProtocolDecl>(decl->getDeclContext()))
+      decl = proto;
+
     return ::isAvailableExternally(IGM, getDecl());
+  }
 
   case Kind::ValueWitnessTable:
   case Kind::TypeMetadata:
diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp
index 93ef889..ffcb7d0 100644
--- a/lib/IRGen/GenEnum.cpp
+++ b/lib/IRGen/GenEnum.cpp
@@ -6106,7 +6106,7 @@
 
   emitFieldMetadataRecord(theEnum);
 
-  if (isResilient(theEnum, ResilienceExpansion::Maximal))
+  if (!isResilient(theEnum, ResilienceExpansion::Minimal))
     return;
 
   // Emit resilient tag indices.
diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp
index 8314bb2..39f7616 100644
--- a/lib/IRGen/GenKeyPath.cpp
+++ b/lib/IRGen/GenKeyPath.cpp
@@ -23,6 +23,7 @@
 #include "GenMeta.h"
 #include "GenProto.h"
 #include "GenStruct.h"
+#include "GenType.h"
 #include "GenericRequirement.h"
 #include "IRGenDebugInfo.h"
 #include "IRGenFunction.h"
@@ -39,9 +40,11 @@
 #include "swift/ABI/KeyPath.h"
 #include "swift/ABI/HeapObject.h"
 #include "swift/AST/ASTContext.h"
+#include "swift/AST/Decl.h"
 #include "swift/AST/DiagnosticEngine.h"
 #include "swift/AST/DiagnosticsIRGen.h"
 #include "swift/AST/GenericEnvironment.h"
+#include "swift/AST/ParameterList.h"
 #include "swift/AST/Types.h"
 #include "swift/IRGen/Linking.h"
 
@@ -61,14 +64,15 @@
                                      GenericEnvironment *genericEnv,
                                      ArrayRef<GenericRequirement> requirements,
                                      llvm::Value *args,
-                                     llvm::Value *size) {
+                                     llvm::Value *size,
+                                     bool hasSubscriptIndices) {
   if (!genericEnv)
     return;
   
   // The generic environment is marshaled into the end of the component
   // argument area inside the instance. Bind the generic information out of
   // the buffer.
-  if (!component.getSubscriptIndices().empty()) {
+  if (hasSubscriptIndices) {
     auto genericArgsSize = llvm::ConstantInt::get(IGF.IGM.SizeTy,
       requirements.size() * IGF.IGM.getPointerSize().getValue());
 
@@ -87,7 +91,8 @@
                                 const KeyPathPatternComponent &component,
                                 KeyPathAccessor whichAccessor,
                                 GenericEnvironment *genericEnv,
-                                ArrayRef<GenericRequirement> requirements) {
+                                ArrayRef<GenericRequirement> requirements,
+                                bool hasSubscriptIndices) {
   SILFunction *accessor;
   switch (whichAccessor) {
   case Getter:
@@ -202,8 +207,9 @@
     case Setter:
       // The component arguments are passed alongside the base being projected.
       componentArgsBuf = params.claimNext();
-      // Pass the argument pointer down to the underlying function.
-      if (!component.getSubscriptIndices().empty()) {
+      // Pass the argument pointer down to the underlying function, if it
+      // wants it.
+      if (hasSubscriptIndices) {
         forwardedArgs.add(componentArgsBuf);
       }
       break;
@@ -217,7 +223,8 @@
     bindPolymorphicArgumentsFromComponentIndices(IGF, component,
                                                  genericEnv, requirements,
                                                  componentArgsBuf,
-                                                 componentArgsBufSize);
+                                                 componentArgsBufSize,
+                                                 hasSubscriptIndices);
     
     // Use the bound generic metadata to form a call to the original generic
     // accessor.
@@ -374,9 +381,10 @@
       auto componentArgsBuf = params.claimNext();
       auto componentArgsBufSize = params.claimNext();
       bindPolymorphicArgumentsFromComponentIndices(IGF, component,
-                                                   genericEnv, requirements,
-                                                   componentArgsBuf,
-                                                   componentArgsBufSize);
+                                     genericEnv, requirements,
+                                     componentArgsBuf,
+                                     componentArgsBufSize,
+                                     !component.getSubscriptIndices().empty());
       
       llvm::Value *offset = nullptr;
       for (auto &component : component.getSubscriptIndices()) {
@@ -422,9 +430,10 @@
       auto destArgsBuf = params.claimNext();
       auto componentArgsBufSize = params.claimNext();
       bindPolymorphicArgumentsFromComponentIndices(IGF, component,
-                                                   genericEnv, requirements,
-                                                   sourceArgsBuf,
-                                                   componentArgsBufSize);
+                                     genericEnv, requirements,
+                                     sourceArgsBuf,
+                                     componentArgsBufSize,
+                                     !component.getSubscriptIndices().empty());
       
       // Copy over the index values.
       llvm::Value *offset = nullptr;
@@ -477,9 +486,11 @@
   }
   
   auto equals = getAccessorForComputedComponent(IGM, component, Equals,
-                                                genericEnv, requirements);
+                                      genericEnv, requirements,
+                                      !component.getSubscriptIndices().empty());
   auto hash = getAccessorForComputedComponent(IGM, component, Hash,
-                                              genericEnv, requirements);
+                                      genericEnv, requirements,
+                                      !component.getSubscriptIndices().empty());
   
   auto witnesses = llvm::ConstantStruct::getAnon({destroy, copy, equals, hash});
   return new llvm::GlobalVariable(IGM.Module, witnesses->getType(),
@@ -631,6 +642,435 @@
   return initFn;
 }
 
+/// Emit a generator function to produce a reference to a type or
+/// protocol conformance metadata record.
+/// TODO: It would be much better to emit typeref strings and use runtime
+/// demangling here.
+static llvm::Function *
+emitGeneratorForKeyPath(IRGenModule &IGM,
+                        StringRef name, CanType type, llvm::Type *returnType,
+                        GenericEnvironment *genericEnv,
+                        ArrayRef<GenericRequirement> requirements,
+                        llvm::function_ref<void(IRGenFunction&,CanType)> emit) {
+  // TODO: Use the standard metadata accessor when there are no arguments
+  // and the metadata accessor is defined.
+
+  // Build a stub that loads the necessary bindings from the key path's
+  // argument buffer then fetches the metadata.
+  auto fnTy = llvm::FunctionType::get(returnType,
+                                      {IGM.Int8PtrTy}, /*vararg*/ false);
+  auto accessorThunk = llvm::Function::Create(fnTy,
+                                          llvm::GlobalValue::PrivateLinkage,
+                                          name, IGM.getModule());
+  accessorThunk->setAttributes(IGM.constructInitialAttributes());
+  {
+    IRGenFunction IGF(IGM, accessorThunk);
+    if (IGM.DebugInfo)
+      IGM.DebugInfo->emitArtificialFunction(IGF, accessorThunk);
+    
+    if (type->hasTypeParameter()) {
+      auto bindingsBufPtr = IGF.collectParameters().claimNext();
+      
+      bindFromGenericRequirementsBuffer(IGF, requirements,
+            Address(bindingsBufPtr, IGM.getPointerAlignment()),
+            [&](CanType t) {
+              return genericEnv->mapTypeIntoContext(t)->getCanonicalType();
+            });
+      
+      type = genericEnv->mapTypeIntoContext(type)->getCanonicalType();
+    }
+    emit(IGF, type);
+  }
+  return accessorThunk;
+}
+
+static llvm::Function *
+emitMetadataGeneratorForKeyPath(IRGenModule &IGM,
+                                CanType type,
+                                GenericEnvironment *genericEnv,
+                                ArrayRef<GenericRequirement> requirements) {
+  // TODO: Use the standard metadata accessor when there are no arguments
+  // and the metadata accessor is defined.
+  return emitGeneratorForKeyPath(IGM, "keypath_get_type", type,
+    IGM.TypeMetadataPtrTy,
+    genericEnv, requirements,
+    [&](IRGenFunction &IGF, CanType substType) {
+      auto ret = IGF.emitTypeMetadataRef(substType);
+      IGF.Builder.CreateRet(ret);
+    });
+};
+
+static llvm::Function *
+emitWitnessTableGeneratorForKeyPath(IRGenModule &IGM,
+                                    CanType type,
+                                    ProtocolConformanceRef conformance,
+                                    GenericEnvironment *genericEnv,
+                                    ArrayRef<GenericRequirement> requirements) {
+  // TODO: Use the standard conformance accessor when there are no arguments
+  // and the conformance accessor is defined.
+  return emitGeneratorForKeyPath(IGM, "keypath_get_witness_table", type,
+    IGM.WitnessTablePtrTy,
+    genericEnv, requirements,
+    [&](IRGenFunction &IGF, CanType substType) {
+      if (type->hasTypeParameter())
+        conformance = conformance.subst(type,
+          QueryInterfaceTypeSubstitutions(genericEnv),
+          LookUpConformanceInSignature(*genericEnv->getGenericSignature()));
+      auto ret = emitWitnessTableRef(IGF, substType, conformance);
+      IGF.Builder.CreateRet(ret);
+    });
+}
+
+
+static void
+emitKeyPathComponent(IRGenModule &IGM,
+                     ConstantStructBuilder &fields,
+                     const KeyPathPatternComponent &component,
+                     bool isInstantiableInPlace,
+                     GenericEnvironment *genericEnv,
+                     ArrayRef<GenericRequirement> requirements,
+                     CanType baseTy,
+                     ArrayRef<KeyPathIndexOperand> operands,
+                     bool hasSubscriptIndices) {
+  assert(fields.getNextOffsetFromGlobal() % IGM.getPointerAlignment() == Size(0)
+         && "must be pointer-aligned here");
+
+  SILType loweredBaseTy;
+  GenericContextScope scope(IGM,
+         genericEnv ? genericEnv->getGenericSignature()->getCanonicalSignature()
+                    : nullptr);
+  loweredBaseTy = IGM.getLoweredType(AbstractionPattern::getOpaque(),
+                                     baseTy->getWithoutSpecifierType());
+  switch (auto kind = component.getKind()) {
+  case KeyPathPatternComponent::Kind::External: {
+    fields.addInt32(KeyPathComponentHeader::forExternalComponent().getData());
+    // Emit accessors for all of the external declaration's necessary
+    // bindings.
+    SmallVector<llvm::Constant*, 4> descriptorArgs;
+    auto componentSig = component.getExternalDecl()->getInnermostDeclContext()
+      ->getGenericSignatureOfContext();
+    auto subs = componentSig->getSubstitutionMap(
+                                        component.getExternalSubstitutions());
+    enumerateGenericSignatureRequirements(
+      componentSig->getCanonicalSignature(),
+      [&](GenericRequirement reqt) {
+        auto substType = reqt.TypeParameter.subst(subs)
+          ->getCanonicalType();
+        if (!reqt.Protocol) {
+          // Type requirement.
+          descriptorArgs.push_back(
+            emitMetadataGeneratorForKeyPath(IGM, substType,
+                                            genericEnv, requirements));
+        } else {
+          // Protocol requirement.
+          auto conformance = subs.lookupConformance(
+                       reqt.TypeParameter->getCanonicalType(), reqt.Protocol);
+          descriptorArgs.push_back(
+            emitWitnessTableGeneratorForKeyPath(IGM, substType,
+                                                *conformance,
+                                                genericEnv, requirements));
+        }
+      });
+    // If instantiable in-place, pad out the argument count here to ensure
+    // there's room enough to instantiate a settable computed property
+    // with two captured words in-place. The runtime instantiation of the
+    // external component will ignore the padding, and this will make in-place
+    // instantiation more likely to avoid needing an allocation.
+    unsigned argSize = descriptorArgs.size();
+    if (isInstantiableInPlace) {
+      argSize = std::max(argSize, 3u);
+    }
+    
+    fields.addInt32(argSize);
+    fields.add(IGM.getAddrOfPropertyDescriptor(component.getExternalDecl()));
+    
+    // Add an initializer function that copies generic arguments out of the
+    // pattern argument buffer into the instantiated object, along with the
+    // index equality/hash operations we have from our perspective, or null
+    // if there are no arguments.
+    if (component.getSubscriptIndices().empty()) {
+      fields.addInt(IGM.IntPtrTy, 0);
+      fields.addInt(IGM.IntPtrTy, 0);
+      fields.addInt(IGM.IntPtrTy, 0);
+    } else {
+      fields.add(getInitializerForComputedComponent(IGM, component,
+                                                    operands,
+                                                    genericEnv,
+                                                    requirements));
+      fields.add(IGM.getAddrOfSILFunction(component.getSubscriptIndexEquals(),
+                                          NotForDefinition));
+      fields.add(IGM.getAddrOfSILFunction(component.getSubscriptIndexHash(),
+                                          NotForDefinition));
+    }
+    
+    // Add the generic arguments for the external context.
+    for (auto arg : descriptorArgs)
+      fields.add(arg);
+    
+    // Add padding.
+    for (unsigned i = descriptorArgs.size(); i < argSize; ++i)
+      fields.addInt(IGM.IntPtrTy, 0);
+    break;
+  }
+  case KeyPathPatternComponent::Kind::StoredProperty: {
+    auto property = cast<VarDecl>(component.getStoredPropertyDecl());
+    
+    auto addFixedOffset = [&](bool isStruct, llvm::Constant *offset) {
+      if (auto offsetInt = dyn_cast_or_null<llvm::ConstantInt>(offset)) {
+        auto offsetValue = offsetInt->getValue().getZExtValue();
+        if (KeyPathComponentHeader::offsetCanBeInline(offsetValue)) {
+          auto header = isStruct
+            ? KeyPathComponentHeader
+                ::forStructComponentWithInlineOffset(offsetValue)
+            : KeyPathComponentHeader
+                ::forClassComponentWithInlineOffset(offsetValue);
+          fields.addInt32(header.getData());
+          return;
+        }
+      }
+      auto header = isStruct
+        ? KeyPathComponentHeader::forStructComponentWithOutOfLineOffset()
+        : KeyPathComponentHeader::forClassComponentWithOutOfLineOffset();
+      fields.addInt32(header.getData());
+      fields.add(llvm::ConstantExpr::getTruncOrBitCast(offset, IGM.Int32Ty));
+    };
+    
+    // For a struct stored property, we may know the fixed offset of the field,
+    // or we may need to fetch it out of the type's metadata at instantiation
+    // time.
+    if (auto theStruct = loweredBaseTy.getStructOrBoundGenericStruct()) {
+      if (auto offset = emitPhysicalStructMemberFixedOffset(IGM,
+                                                            loweredBaseTy,
+                                                            property)) {
+        // We have a known constant fixed offset.
+        addFixedOffset(/*struct*/ true, offset);
+        break;
+      }
+
+      // If the offset isn't fixed, try instead to get the field offset out
+      // of the type metadata at instantiation time.
+      auto &metadataLayout = IGM.getMetadataLayout(theStruct);
+      auto fieldOffset = metadataLayout.getStaticFieldOffset(property);
+
+      auto header = KeyPathComponentHeader
+        ::forStructComponentWithUnresolvedFieldOffset();
+      fields.addInt32(header.getData());
+      fields.addInt32(fieldOffset.getValue());
+      break;
+    }
+    
+    // For a class, we may know the fixed offset of a field at compile time,
+    // or we may need to fetch it at instantiation time. Depending on the
+    // ObjC-ness and resilience of the class hierarchy, there might be a few
+    // different ways we need to go about this.
+    if (loweredBaseTy.getClassOrBoundGenericClass()) {
+      switch (getClassFieldAccess(IGM, loweredBaseTy, property)) {
+      case FieldAccess::ConstantDirect: {
+        // Known constant fixed offset.
+        auto offset = tryEmitConstantClassFragilePhysicalMemberOffset(IGM,
+                                                                loweredBaseTy,
+                                                                property);
+        assert(offset && "no constant offset for ConstantDirect field?!");
+        addFixedOffset(/*struct*/ false, offset);
+        break;
+      }
+      case FieldAccess::NonConstantDirect: {
+        // A constant offset that's determined at class realization time.
+        // We have to load the offset from a global ivar.
+        auto header = KeyPathComponentHeader
+          ::forClassComponentWithUnresolvedIndirectOffset();
+        fields.addInt32(header.getData());
+        fields.addAlignmentPadding(IGM.getPointerAlignment());
+        auto offsetVar = IGM.getAddrOfFieldOffset(property, NotForDefinition);
+        fields.add(cast<llvm::Constant>(offsetVar.getAddress()));
+        break;
+      }
+      case FieldAccess::ConstantIndirect: {
+        // An offset that depends on the instance's generic parameterization,
+        // but whose field offset is at a known vtable offset.
+        auto header =
+          KeyPathComponentHeader::forClassComponentWithUnresolvedFieldOffset();
+        fields.addInt32(header.getData());
+        auto fieldOffset =
+          getClassFieldOffsetOffset(IGM,
+                                    loweredBaseTy.getClassOrBoundGenericClass(),
+                                    property);
+        fields.addInt32(fieldOffset.getValue());
+        break;
+      }
+      }
+      break;
+    }
+    llvm_unreachable("not struct or class");
+  }
+  case KeyPathPatternComponent::Kind::GettableProperty:
+  case KeyPathPatternComponent::Kind::SettableProperty: {
+    // Encode the settability.
+    bool settable = kind == KeyPathPatternComponent::Kind::SettableProperty;
+    KeyPathComponentHeader::ComputedPropertyKind componentKind;
+    if (settable) {
+      componentKind = component.isComputedSettablePropertyMutating()
+        ? KeyPathComponentHeader::SettableMutating
+        : KeyPathComponentHeader::SettableNonmutating;
+    } else {
+      componentKind = KeyPathComponentHeader::GetOnly;
+    }
+    
+    // Lower the id reference.
+    auto id = component.getComputedPropertyId();
+    KeyPathComponentHeader::ComputedPropertyIDKind idKind;
+    llvm::Constant *idValue;
+    bool idResolved;
+    switch (id.getKind()) {
+    case KeyPathPatternComponent::ComputedPropertyId::Function:
+      idKind = KeyPathComponentHeader::Pointer;
+      idValue = IGM.getAddrOfSILFunction(id.getFunction(), NotForDefinition);
+      idResolved = true;
+      break;
+    case KeyPathPatternComponent::ComputedPropertyId::DeclRef: {
+      auto declRef = id.getDeclRef();
+    
+      // Foreign method refs identify using a selector
+      // reference, which is doubly-indirected and filled in with a unique
+      // pointer by dyld.
+      if (declRef.isForeign) {
+        assert(IGM.ObjCInterop && "foreign keypath component w/o objc interop?!");
+        idKind = KeyPathComponentHeader::Pointer;
+        idValue = IGM.getAddrOfObjCSelectorRef(declRef);
+        idResolved = false;
+      } else {
+        idKind = KeyPathComponentHeader::VTableOffset;
+        auto dc = declRef.getDecl()->getDeclContext();
+        if (isa<ClassDecl>(dc) && !cast<ClassDecl>(dc)->isForeign()) {
+          auto overridden = declRef.getOverriddenVTableEntry();
+          auto declaringClass =
+            cast<ClassDecl>(overridden.getDecl()->getDeclContext());
+          auto &metadataLayout = IGM.getClassMetadataLayout(declaringClass);
+          // FIXME: Resilience. We don't want vtable layout to be ABI, so this
+          // should be encoded as a reference to the method dispatch thunk
+          // instead.
+          auto offset = metadataLayout.getStaticMethodOffset(overridden);
+          idValue = llvm::ConstantInt::get(IGM.SizeTy, offset.getValue());
+          idResolved = true;
+        } else if (auto methodProto = dyn_cast<ProtocolDecl>(dc)) {
+          // FIXME: Resilience. We don't want witness table layout to be ABI,
+          // so this should be encoded as a reference to the method dispatch
+          // thunk instead.
+          auto &protoInfo = IGM.getProtocolInfo(methodProto);
+          auto index = protoInfo.getFunctionIndex(
+                               cast<AbstractFunctionDecl>(declRef.getDecl()));
+          idValue = llvm::ConstantInt::get(IGM.SizeTy, -index.getValue());
+          idResolved = true;
+        } else {
+          llvm_unreachable("neither a class nor protocol dynamic method?");
+        }
+      }
+      break;
+    }
+    case KeyPathPatternComponent::ComputedPropertyId::Property:
+      // Use the index of the stored property within the aggregate to key
+      // the property.
+      auto property = id.getProperty();
+      idKind = KeyPathComponentHeader::StoredPropertyIndex;
+      if (auto struc = baseTy->getStructOrBoundGenericStruct()) {
+        // Scan the stored properties of the struct to find the index. We should
+        // only ever use a struct field as a uniquing key from inside the
+        // struct's own module, so this is OK.
+        idResolved = true;
+        Optional<unsigned> structIdx;
+        unsigned i = 0;
+        for (auto storedProp : struc->getStoredProperties()) {
+          if (storedProp == property) {
+            structIdx = i;
+            break;
+          }
+          ++i;
+        }
+        assert(structIdx && "not a stored property of the struct?!");
+        idValue = llvm::ConstantInt::get(IGM.SizeTy, structIdx.getValue());
+      } else if (baseTy->getClassOrBoundGenericClass()) {
+        // TODO: This field index would require runtime resolution with Swift
+        // native class resilience. We never directly access ObjC-imported
+        // ivars so we can disregard ObjC ivar resilience for this computation
+        // and start counting at the Swift native root.
+        switch (getClassFieldAccess(IGM, loweredBaseTy, property)) {
+        case FieldAccess::ConstantDirect:
+        case FieldAccess::ConstantIndirect:
+        case FieldAccess::NonConstantDirect:
+          idResolved = true;
+          idValue = llvm::ConstantInt::get(IGM.SizeTy,
+            getClassFieldIndex(IGM,
+                         SILType::getPrimitiveAddressType(baseTy), property));
+          break;
+        }
+        
+      } else {
+        llvm_unreachable("neither struct nor class");
+      }
+      break;
+    }
+    
+    auto header = KeyPathComponentHeader::forComputedProperty(componentKind,
+                                  idKind, !isInstantiableInPlace, idResolved);
+    
+    fields.addInt32(header.getData());
+    fields.addAlignmentPadding(IGM.getPointerAlignment());
+    fields.add(idValue);
+    
+    if (isInstantiableInPlace) {
+      // No generic arguments or indexes, so we can invoke the
+      // getter/setter as is.
+      fields.add(IGM.getAddrOfSILFunction(component.getComputedPropertyGetter(),
+                                          NotForDefinition));
+      if (settable)
+        fields.add(IGM.getAddrOfSILFunction(component.getComputedPropertySetter(),
+                                            NotForDefinition));
+    } else {
+      // If there's generic context or subscript indexes, embed as
+      // arguments in the component. Thunk the SIL-level accessors to give the
+      // runtime implementation a polymorphically-callable interface.
+      
+      // Push the accessors, possibly thunked to marshal generic environment.
+      fields.add(getAccessorForComputedComponent(IGM, component, Getter,
+                                                 genericEnv, requirements,
+                                                 hasSubscriptIndices));
+      if (settable)
+        fields.add(getAccessorForComputedComponent(IGM, component, Setter,
+                                                   genericEnv, requirements,
+                                                   hasSubscriptIndices));
+      
+      fields.add(getLayoutFunctionForComputedComponent(IGM, component,
+                                                     genericEnv, requirements));
+      
+      // Set up a "witness table" for the component that handles copying,
+      // destroying, equating, and hashing the captured contents of the
+      // component.
+      // If there are only generic parameters, we can use a prefab witness
+      // table from the runtime.
+      // For subscripts we generate functions that dispatch out to
+      // the copy/destroy/equals/hash functionality of the subscript indexes.
+      fields.add(getWitnessTableForComputedComponent(IGM, component,
+                                                   genericEnv, requirements));
+      
+      // Add an initializer function that copies generic arguments out of the
+      // pattern argument buffer into the instantiated object.
+      fields.add(getInitializerForComputedComponent(IGM, component, operands,
+                                                   genericEnv, requirements));
+    }
+    break;
+  }
+  case KeyPathPatternComponent::Kind::OptionalChain:
+    fields.addInt32(KeyPathComponentHeader::forOptionalChain().getData());
+    break;
+  case KeyPathPatternComponent::Kind::OptionalForce:
+    fields.addInt32(KeyPathComponentHeader::forOptionalForce().getData());
+    break;
+  case KeyPathPatternComponent::Kind::OptionalWrap:
+    fields.addInt32(KeyPathComponentHeader::forOptionalWrap().getData());
+    break;
+  }
+}
+
 llvm::Constant *
 IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
                                      SILLocation diagLoc) {
@@ -658,70 +1098,6 @@
       [&](GenericRequirement reqt) { requirements.push_back(reqt); });
   }
 
-  auto emitGenerator =
-    [&](StringRef name, CanType type, llvm::Type *returnType,
-        llvm::function_ref<void (IRGenFunction&, CanType)> emit)
-    -> llvm::Function * {
-      // TODO: Use the standard metadata accessor when there are no arguments
-      // and the metadata accessor is defined.
-      
-      // Build a stub that loads the necessary bindings from the key path's
-      // argument buffer then fetches the metadata.
-      auto fnTy = llvm::FunctionType::get(returnType,
-                                          {Int8PtrTy}, /*vararg*/ false);
-      auto accessorThunk = llvm::Function::Create(fnTy,
-                                              llvm::GlobalValue::PrivateLinkage,
-                                              name, getModule());
-      accessorThunk->setAttributes(constructInitialAttributes());
-      {
-        IRGenFunction IGF(*this, accessorThunk);
-        if (DebugInfo)
-          DebugInfo->emitArtificialFunction(IGF, accessorThunk);
-        
-        if (type->hasTypeParameter()) {
-          auto bindingsBufPtr = IGF.collectParameters().claimNext();
-          
-          bindFromGenericRequirementsBuffer(IGF, requirements,
-                Address(bindingsBufPtr, getPointerAlignment()),
-                [&](CanType t) {
-                  return genericEnv->mapTypeIntoContext(t)->getCanonicalType();
-                });
-          
-          type = genericEnv->mapTypeIntoContext(type)->getCanonicalType();
-        }
-        emit(IGF, type);
-      }
-      return accessorThunk;
-    };
-
-  /// Generate a metadata accessor that produces metadata for the given type
-  /// using arguments from the generic context of the key path.
-  auto emitMetadataGenerator = [&](CanType type) -> llvm::Function * {
-    // TODO: Use the standard metadata accessor when there are no arguments
-    // and the metadata accessor is defined.
-    return emitGenerator("keypath_get_type", type, TypeMetadataPtrTy,
-      [&](IRGenFunction &IGF, CanType substType) {
-        auto ret = IGF.emitTypeMetadataRef(substType);
-        IGF.Builder.CreateRet(ret);
-      });
-  };
-    
-  auto emitWitnessTableGenerator =
-    [&](CanType type,
-        ProtocolConformanceRef conformance) -> llvm::Function * {
-      // TODO: Use the standard conformance accessor when there are no arguments
-      // and the conformance accessor is defined.
-      return emitGenerator("keypath_get_witness_table", type, WitnessTablePtrTy,
-        [&](IRGenFunction &IGF, CanType substType) {
-          if (type->hasTypeParameter())
-            conformance = conformance.subst(type,
-              QueryInterfaceTypeSubstitutions(genericEnv),
-              LookUpConformanceInSignature(*genericEnv->getGenericSignature()));
-          auto ret = emitWitnessTableRef(IGF, substType, conformance);
-          IGF.Builder.CreateRet(ret);
-        });
-    };
-  
   // Start building the key path pattern.
   ConstantInitBuilder builder(*this);
   ConstantStructBuilder fields = builder.beginStruct();
@@ -736,8 +1112,10 @@
   // Store references to metadata generator functions to generate the metadata
   // for the root and leaf. These sit in the "isa" and object header parts of
   // the final object.
-  fields.add(emitMetadataGenerator(rootTy));
-  fields.add(emitMetadataGenerator(valueTy));
+  fields.add(emitMetadataGeneratorForKeyPath(*this, rootTy,
+                                             genericEnv, requirements));
+  fields.add(emitMetadataGeneratorForKeyPath(*this, valueTy,
+                                             genericEnv, requirements));
   
 #ifndef NDEBUG
   auto endOfObjectHeader = fields.getNextOffsetFromGlobal();
@@ -773,11 +1151,6 @@
   // Build out the components.
   auto baseTy = rootTy;
   
-  auto assertPointerAlignment = [&]{
-    assert(fields.getNextOffsetFromGlobal() % getPointerAlignment() == Size(0)
-           && "must be pointer-aligned here");
-  };
-  
   // Collect the order and types of any captured index operands, which will
   // determine the layout of the buffer that gets passed to the initializer
   // for each component.
@@ -802,329 +1175,19 @@
   }
   
   for (unsigned i : indices(pattern->getComponents())) {
-    assertPointerAlignment();
-    SILType loweredBaseTy;
-    Lowering::GenericContextScope scope(getSILTypes(),
-                                        pattern->getGenericSignature());
-    loweredBaseTy = getLoweredType(AbstractionPattern::getOpaque(),
-                                   baseTy->getWithoutSpecifierType());
     auto &component = pattern->getComponents()[i];
-    switch (auto kind = component.getKind()) {
-    case KeyPathPatternComponent::Kind::External: {
-      fields.addInt32(KeyPathComponentHeader::forExternalComponent().getData());
-      // Emit accessors for all of the external declaration's necessary
-      // bindings.
-      SmallVector<llvm::Constant*, 4> descriptorArgs;
-      auto componentSig = component.getExternalDecl()->getInnermostDeclContext()
-        ->getGenericSignatureOfContext();
-      auto subs = componentSig->getSubstitutionMap(
-                                          component.getExternalSubstitutions());
-      enumerateGenericSignatureRequirements(
-        componentSig->getCanonicalSignature(),
-        [&](GenericRequirement reqt) {
-          auto substType = reqt.TypeParameter.subst(subs)
-            ->getCanonicalType();
-          if (!reqt.Protocol) {
-            // Type requirement.
-            descriptorArgs.push_back(emitMetadataGenerator(substType));
-          } else {
-            // Protocol requirement.
-            auto conformance = subs.lookupConformance(
-                         reqt.TypeParameter->getCanonicalType(), reqt.Protocol);
-            descriptorArgs.push_back(emitWitnessTableGenerator(substType,
-                                                               *conformance));
-          }
-        });
-      // If instantiable in-place, pad out the argument count here to ensure
-      // there's room enough to instantiate a settable computed property
-      // with two captured words in-place. The runtime instantiation of the
-      // external component will ignore the padding, and this will make in-place
-      // instantiation more likely to avoid needing an allocation.
-      unsigned argSize = descriptorArgs.size();
-      if (isInstantiableInPlace) {
-        argSize = std::max(argSize, 3u);
-      }
-      
-      fields.addInt32(argSize);
-      fields.add(getAddrOfPropertyDescriptor(component.getExternalDecl()));
-      
-      // Add an initializer function that copies generic arguments out of the
-      // pattern argument buffer into the instantiated object, along with the
-      // index equality/hash operations we have from our perspective, or null
-      // if there are no arguments.
-      if (component.getSubscriptIndices().empty()) {
-        fields.addInt(IntPtrTy, 0);
-        fields.addInt(IntPtrTy, 0);
-        fields.addInt(IntPtrTy, 0);
-      } else {
-        fields.add(getInitializerForComputedComponent(*this, component,
-                                                      operands,
-                                                      genericEnv,
-                                                      requirements));
-        fields.add(getAddrOfSILFunction(component.getSubscriptIndexEquals(),
-                                        NotForDefinition));
-        fields.add(getAddrOfSILFunction(component.getSubscriptIndexHash(),
-                                        NotForDefinition));
-      }
-      
-      // Add the generic arguments for the external context.
-      for (auto arg : descriptorArgs)
-        fields.add(arg);
-      
-      // Add padding.
-      for (unsigned i = descriptorArgs.size(); i < argSize; ++i)
-        fields.addInt(IntPtrTy, 0);
-      break;
-    }
-    case KeyPathPatternComponent::Kind::StoredProperty: {
-      auto property = cast<VarDecl>(component.getStoredPropertyDecl());
-      
-      auto addFixedOffset = [&](bool isStruct, llvm::Constant *offset) {
-        if (auto offsetInt = dyn_cast_or_null<llvm::ConstantInt>(offset)) {
-          auto offsetValue = offsetInt->getValue().getZExtValue();
-          if (KeyPathComponentHeader::offsetCanBeInline(offsetValue)) {
-            auto header = isStruct
-              ? KeyPathComponentHeader
-                  ::forStructComponentWithInlineOffset(offsetValue)
-              : KeyPathComponentHeader
-                  ::forClassComponentWithInlineOffset(offsetValue);
-            fields.addInt32(header.getData());
-            return;
-          }
-        }
-        auto header = isStruct
-          ? KeyPathComponentHeader::forStructComponentWithOutOfLineOffset()
-          : KeyPathComponentHeader::forClassComponentWithOutOfLineOffset();
-        fields.addInt32(header.getData());
-        fields.add(llvm::ConstantExpr::getTruncOrBitCast(offset, Int32Ty));
-      };
-      
-      // For a struct stored property, we may know the fixed offset of the field,
-      // or we may need to fetch it out of the type's metadata at instantiation
-      // time.
-      if (auto theStruct = loweredBaseTy.getStructOrBoundGenericStruct()) {
-        if (auto offset = emitPhysicalStructMemberFixedOffset(*this,
-                                                              loweredBaseTy,
-                                                              property)) {
-          // We have a known constant fixed offset.
-          addFixedOffset(/*struct*/ true, offset);
-          break;
-        }
-
-        // If the offset isn't fixed, try instead to get the field offset out
-        // of the type metadata at instantiation time.
-        auto &metadataLayout = getMetadataLayout(theStruct);
-        auto fieldOffset = metadataLayout.getStaticFieldOffset(property);
-
-        auto header = KeyPathComponentHeader
-          ::forStructComponentWithUnresolvedFieldOffset();
-        fields.addInt32(header.getData());
-        fields.addInt32(fieldOffset.getValue());
-        break;
-      }
-      
-      // For a class, we may know the fixed offset of a field at compile time,
-      // or we may need to fetch it at instantiation time. Depending on the
-      // ObjC-ness and resilience of the class hierarchy, there might be a few
-      // different ways we need to go about this.
-      if (loweredBaseTy.getClassOrBoundGenericClass()) {
-        switch (getClassFieldAccess(*this, loweredBaseTy, property)) {
-        case FieldAccess::ConstantDirect: {
-          // Known constant fixed offset.
-          auto offset = tryEmitConstantClassFragilePhysicalMemberOffset(*this,
-                                                                  loweredBaseTy,
-                                                                  property);
-          assert(offset && "no constant offset for ConstantDirect field?!");
-          addFixedOffset(/*struct*/ false, offset);
-          break;
-        }
-        case FieldAccess::NonConstantDirect: {
-          // A constant offset that's determined at class realization time.
-          // We have to load the offset from a global ivar.
-          auto header = KeyPathComponentHeader
-            ::forClassComponentWithUnresolvedIndirectOffset();
-          fields.addInt32(header.getData());
-          fields.addAlignmentPadding(getPointerAlignment());
-          auto offsetVar = getAddrOfFieldOffset(property, NotForDefinition);
-          fields.add(cast<llvm::Constant>(offsetVar.getAddress()));
-          break;
-        }
-        case FieldAccess::ConstantIndirect: {
-          // An offset that depends on the instance's generic parameterization,
-          // but whose field offset is at a known vtable offset.
-          auto header =
-            KeyPathComponentHeader::forClassComponentWithUnresolvedFieldOffset();
-          fields.addInt32(header.getData());
-          auto fieldOffset =
-            getClassFieldOffsetOffset(*this, loweredBaseTy.getClassOrBoundGenericClass(),
-                                      property);
-          fields.addInt32(fieldOffset.getValue());
-          break;
-        }
-        }
-        break;
-      }
-      llvm_unreachable("not struct or class");
-    }
-    case KeyPathPatternComponent::Kind::GettableProperty:
-    case KeyPathPatternComponent::Kind::SettableProperty: {
-      // Encode the settability.
-      bool settable = kind == KeyPathPatternComponent::Kind::SettableProperty;
-      KeyPathComponentHeader::ComputedPropertyKind componentKind;
-      if (settable) {
-        componentKind = component.isComputedSettablePropertyMutating()
-          ? KeyPathComponentHeader::SettableMutating
-          : KeyPathComponentHeader::SettableNonmutating;
-      } else {
-        componentKind = KeyPathComponentHeader::GetOnly;
-      }
-      
-      // Lower the id reference.
-      auto id = component.getComputedPropertyId();
-      KeyPathComponentHeader::ComputedPropertyIDKind idKind;
-      llvm::Constant *idValue;
-      bool idResolved;
-      switch (id.getKind()) {
-      case KeyPathPatternComponent::ComputedPropertyId::Function:
-        idKind = KeyPathComponentHeader::Pointer;
-        idValue = getAddrOfSILFunction(id.getFunction(), NotForDefinition);
-        idResolved = true;
-        break;
-      case KeyPathPatternComponent::ComputedPropertyId::DeclRef: {
-        auto declRef = id.getDeclRef();
-      
-        // Foreign method refs identify using a selector
-        // reference, which is doubly-indirected and filled in with a unique
-        // pointer by dyld.
-        if (declRef.isForeign) {
-          assert(ObjCInterop && "foreign keypath component w/o objc interop?!");
-          idKind = KeyPathComponentHeader::Pointer;
-          idValue = getAddrOfObjCSelectorRef(declRef);
-          idResolved = false;
-        } else {
-          idKind = KeyPathComponentHeader::VTableOffset;
-          auto dc = declRef.getDecl()->getDeclContext();
-          if (isa<ClassDecl>(dc) && !cast<ClassDecl>(dc)->isForeign()) {
-            auto overridden = declRef.getOverriddenVTableEntry();
-            auto declaringClass =
-              cast<ClassDecl>(overridden.getDecl()->getDeclContext());
-            auto &metadataLayout = getClassMetadataLayout(declaringClass);
-            // FIXME: Resilience. We don't want vtable layout to be ABI, so this
-            // should be encoded as a reference to the method dispatch thunk
-            // instead.
-            auto offset = metadataLayout.getStaticMethodOffset(overridden);
-            idValue = llvm::ConstantInt::get(SizeTy, offset.getValue());
-            idResolved = true;
-          } else if (auto methodProto = dyn_cast<ProtocolDecl>(dc)) {
-            // FIXME: Resilience. We don't want witness table layout to be ABI,
-            // so this should be encoded as a reference to the method dispatch
-            // thunk instead.
-            auto &protoInfo = getProtocolInfo(methodProto);
-            auto index = protoInfo.getFunctionIndex(
-                                 cast<AbstractFunctionDecl>(declRef.getDecl()));
-            idValue = llvm::ConstantInt::get(SizeTy, -index.getValue());
-            idResolved = true;
-          } else {
-            llvm_unreachable("neither a class nor protocol dynamic method?");
-          }
-        }
-        break;
-      }
-      case KeyPathPatternComponent::ComputedPropertyId::Property:
-        // Use the index of the stored property within the aggregate to key
-        // the property.
-        auto property = id.getProperty();
-        idKind = KeyPathComponentHeader::StoredPropertyIndex;
-        if (baseTy->getStructOrBoundGenericStruct()) {
-          idResolved = true;
-          Optional<unsigned> structIdx =  getPhysicalStructFieldIndex(*this,
-                            SILType::getPrimitiveAddressType(baseTy), property);
-          assert(structIdx.hasValue() && "empty property");
-          idValue = llvm::ConstantInt::get(SizeTy, structIdx.getValue());
-        } else if (baseTy->getClassOrBoundGenericClass()) {
-          // TODO: This field index would require runtime resolution with Swift
-          // native class resilience. We never directly access ObjC-imported
-          // ivars so we can disregard ObjC ivar resilience for this computation
-          // and start counting at the Swift native root.
-          switch (getClassFieldAccess(*this, loweredBaseTy, property)) {
-          case FieldAccess::ConstantDirect:
-          case FieldAccess::ConstantIndirect:
-          case FieldAccess::NonConstantDirect:
-            idResolved = true;
-            idValue = llvm::ConstantInt::get(SizeTy,
-              getClassFieldIndex(*this,
-                           SILType::getPrimitiveAddressType(baseTy), property));
-            break;
-          }
-          
-        } else {
-          llvm_unreachable("neither struct nor class");
-        }
-        break;
-      }
-      
-      auto header = KeyPathComponentHeader::forComputedProperty(componentKind,
-                                    idKind, !isInstantiableInPlace, idResolved);
-      
-      fields.addInt32(header.getData());
-      fields.addAlignmentPadding(getPointerAlignment());
-      fields.add(idValue);
-      
-      if (isInstantiableInPlace) {
-        // No generic arguments or indexes, so we can invoke the
-        // getter/setter as is.
-        fields.add(getAddrOfSILFunction(component.getComputedPropertyGetter(),
-                                        NotForDefinition));
-        if (settable)
-          fields.add(getAddrOfSILFunction(component.getComputedPropertySetter(),
-                                          NotForDefinition));
-      } else {
-        // If there's generic context or subscript indexes, embed as
-        // arguments in the component. Thunk the SIL-level accessors to give the
-        // runtime implementation a polymorphically-callable interface.
-        
-        // Push the accessors, possibly thunked to marshal generic environment.
-        fields.add(getAccessorForComputedComponent(*this, component, Getter,
-                                                     genericEnv, requirements));
-        if (settable)
-          fields.add(getAccessorForComputedComponent(*this, component, Setter,
-                                                     genericEnv, requirements));
-                                                     
-        fields.add(getLayoutFunctionForComputedComponent(*this, component,
-                                                     genericEnv, requirements));
-                                                     
-        // Set up a "witness table" for the component that handles copying,
-        // destroying, equating, and hashing the captured contents of the
-        // component.
-        // If there are only generic parameters, we can use a prefab witness
-        // table from the runtime.
-        // For subscripts we generate functions that dispatch out to
-        // the copy/destroy/equals/hash functionality of the subscript indexes.
-        fields.add(getWitnessTableForComputedComponent(*this, component,
-                                                     genericEnv, requirements));
-        
-        // Add an initializer function that copies generic arguments out of the
-        // pattern argument buffer into the instantiated object.
-        fields.add(getInitializerForComputedComponent(*this, component, operands,
-                                                     genericEnv, requirements));
-      }
-      break;
-    }
-    case KeyPathPatternComponent::Kind::OptionalChain:
-      fields.addInt32(KeyPathComponentHeader::forOptionalChain().getData());
-      break;
-    case KeyPathPatternComponent::Kind::OptionalForce:
-      fields.addInt32(KeyPathComponentHeader::forOptionalForce().getData());
-      break;
-    case KeyPathPatternComponent::Kind::OptionalWrap:
-      fields.addInt32(KeyPathComponentHeader::forOptionalWrap().getData());
-      break;
-    }
+    
+    emitKeyPathComponent(*this, fields, component, isInstantiableInPlace,
+                         genericEnv, requirements,
+                         baseTy, operands,
+                         !component.getSubscriptIndices().empty());
     
     // For all but the last component, we pack in the type of the component.
     if (i + 1 != pattern->getComponents().size()) {
       fields.addAlignmentPadding(getPointerAlignment());
-      fields.add(emitMetadataGenerator(component.getComponentType()));
+      fields.add(
+        emitMetadataGeneratorForKeyPath(*this, component.getComponentType(),
+                                        genericEnv, requirements));
     }
     baseTy = component.getComponentType();
   }
@@ -1151,3 +1214,54 @@
   KeyPathPatterns.insert({pattern, patternVar});
   return patternVar;
 }
+
+void IRGenModule::emitSILProperty(SILProperty *prop) {
+  ConstantInitBuilder builder(*this);
+  ConstantStructBuilder fields = builder.beginStruct();
+  fields.setPacked(true);
+  
+  bool hasSubscriptIndices = false;
+  bool isInstantiableInPlace = true;
+  if (prop->getDecl()->getInnermostDeclContext()->isGenericContext()) {
+    isInstantiableInPlace = false;
+  }
+  
+  if (auto subscript = dyn_cast<SubscriptDecl>(prop->getDecl())) {
+    hasSubscriptIndices = subscript->getIndices()->size() != 0;
+    isInstantiableInPlace &= !hasSubscriptIndices;
+  }
+  
+  auto genericEnv = prop->getDecl()->getInnermostDeclContext()
+                        ->getGenericEnvironmentOfContext();
+  SmallVector<GenericRequirement, 4> requirements;
+  CanGenericSignature genericSig;
+  if (genericEnv) {
+    genericSig = prop->getDecl()->getInnermostDeclContext()
+                                ->getGenericSignatureOfContext()
+                                ->getCanonicalSignature();
+    enumerateGenericSignatureRequirements(genericSig,
+      [&](GenericRequirement reqt) { requirements.push_back(reqt); });
+  }
+  
+  emitKeyPathComponent(*this, fields, prop->getComponent(),
+                       isInstantiableInPlace, genericEnv, requirements,
+                       prop->getDecl()->getInnermostDeclContext()
+                                      ->getInnermostTypeContext()
+                                      ->getSelfInterfaceType()
+                                      ->getCanonicalType(genericSig),
+                       {},
+                       hasSubscriptIndices);
+  
+  auto size = fields.getNextOffsetFromGlobal();
+  
+  auto var = cast<llvm::GlobalVariable>(
+    getAddrOfPropertyDescriptor(prop->getDecl(),
+                                fields.finishAndCreateFuture()));
+  var->setConstant(true);
+  // A simple stored component descriptor can fit in four bytes. Anything else
+  // needs pointer alignment.
+  if (size <= Size(4))
+    var->setAlignment(4);
+  else
+    var->setAlignment(getPointerAlignment().getValue());
+}
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 658a9f4..c07d802 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -1405,9 +1405,11 @@
   auto numFields = IGF.IGM.getSize(Size(storedProperties.size()));
 
   if (isa<ClassDecl>(target)) {
-    IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
-                           {metadata, numFields,
-                            fields.getAddress(), fieldVector});
+    ClassLayoutFlags flags = ClassLayoutFlags::Swift5Algorithm;
+
+    IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataFn(),
+                           {metadata, IGF.IGM.getSize(Size(uintptr_t(flags))),
+                            numFields, fields.getAddress(), fieldVector});
   } else {
     assert(isa<StructDecl>(target));
     StructLayoutFlags flags = StructLayoutFlags::Swift5Algorithm;
@@ -3555,6 +3557,9 @@
         // Flags.
         reqt.addInt32(info.Flags.getIntValue());
 
+        // Dispatch thunk.
+        reqt.addRelativeAddressOrNull(info.Thunk);
+
         // Default implementation.
         reqt.addRelativeAddressOrNull(info.DefaultImpl);
 #ifndef NDEBUG
@@ -3592,6 +3597,7 @@
 
     struct RequirementInfo {
       ProtocolRequirementFlags Flags;
+      llvm::Constant *Thunk;
       llvm::Constant *DefaultImpl;
     };
 
@@ -3601,36 +3607,41 @@
       if (entry.isBase()) {
         assert(entry.isOutOfLineBase());
         auto flags = Flags(Flags::Kind::BaseProtocol);
-        return { flags, nullptr };
+        return { flags, nullptr, nullptr };
       }
 
       if (entry.isAssociatedType()) {
         auto flags = Flags(Flags::Kind::AssociatedTypeAccessFunction);
-        return { flags, nullptr };
+        return { flags, nullptr, nullptr };
       }
 
       if (entry.isAssociatedConformance()) {
         auto flags = Flags(Flags::Kind::AssociatedConformanceAccessFunction);
-        return { flags, nullptr };
+        return { flags, nullptr, nullptr };
       }
 
       assert(entry.isFunction());
-      auto func = entry.getFunction();
+      SILDeclRef func(entry.getFunction());
+
+      // Look up the dispatch thunk if the protocol is resilient.
+      llvm::Constant *thunk = nullptr;
+      if (Protocol->isResilient())
+        thunk = IGM.getAddrOfDispatchThunk(func, NotForDefinition);
 
       // Classify the function.
-      auto flags = getMethodDescriptorFlags<Flags>(func);
+      auto flags = getMethodDescriptorFlags<Flags>(func.getDecl());
 
       // Look for a default witness.
       llvm::Constant *defaultImpl = findDefaultWitness(func);
 
-      return { flags, defaultImpl };
+      return { flags, thunk, defaultImpl };
     }
 
-    llvm::Constant *findDefaultWitness(AbstractFunctionDecl *func) {
+    llvm::Constant *findDefaultWitness(SILDeclRef func) {
       if (!DefaultWitnesses) return nullptr;
 
       for (auto &entry : DefaultWitnesses->getResilientDefaultEntries()) {
-        if (entry.getRequirement().getDecl() != func)
+        if (entry.getRequirement() != func)
           continue;
         return IGM.getAddrOfSILFunction(entry.getWitness(), NotForDefinition);
       }
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index c284eb1..2902b11 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -730,18 +730,6 @@
 }
 
 namespace {
-  /// A concrete witness table, together with its known layout.
-  class WitnessTable {
-    llvm::Value *Table;
-    const ProtocolInfo &Info;
-  public:
-    WitnessTable(llvm::Value *wtable, const ProtocolInfo &info)
-      : Table(wtable), Info(info) {}
-
-    llvm::Value *getTable() const { return Table; }
-    const ProtocolInfo &getInfo() const { return Info; }
-  };
-
   /// A class which lays out a witness table in the abstract.
   class WitnessTableLayout : public SILWitnessVisitor<WitnessTableLayout> {
     SmallVector<WitnessTableEntry, 16> Entries;
@@ -1194,8 +1182,7 @@
         : IGM(IGM), Table(table),
           ConcreteType(SILWT->getConformance()->getDeclContext()
                          ->mapTypeIntoContext(
-                           SILWT->getConformance()->getType()
-                             ->getCanonicalType())
+                           SILWT->getConformance()->getType())
                          ->getCanonicalType()),
           Conformance(*SILWT->getConformance()),
           ConformanceInContext(mapConformanceIntoContext(IGM,
@@ -1271,12 +1258,6 @@
       auto &entry = SILEntries.front();
       SILEntries = SILEntries.slice(1);
 
-      // Handle missing optional requirements.
-      if (entry.getKind() == SILWitnessTable::MissingOptional) {
-        Table.addNullPointer(IGM.Int8PtrTy);
-        return;
-      }
-
 #ifndef NDEBUG
       assert(entry.getKind() == SILWitnessTable::Method
              && "sil witness table does not match protocol");
diff --git a/lib/IRGen/GenThunk.cpp b/lib/IRGen/GenThunk.cpp
index c72ada5..38633c7 100644
--- a/lib/IRGen/GenThunk.cpp
+++ b/lib/IRGen/GenThunk.cpp
@@ -50,7 +50,8 @@
   Signature signature = getSignature(fnType);
   LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
 
-  return createFunction(*this, link, signature);
+  entry = createFunction(*this, link, signature);
+  return entry;
 }
 
 static FunctionPointer lookupMethod(IRGenFunction &IGF,
diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp
index 3268144..e7b7e6b 100644
--- a/lib/IRGen/GenType.cpp
+++ b/lib/IRGen/GenType.cpp
@@ -1077,6 +1077,10 @@
   // Push the generic context down to the SIL TypeConverter, so we can share
   // archetypes with SIL.
   IGM.getSILTypes().pushGenericContext(signature);
+
+  // Clear the dependent type info cache since we have a new active signature
+  // now.
+  Types.DependentCache.clear();
 }
 
 void TypeConverter::popGenericContext(CanGenericSignature signature) {
diff --git a/lib/IRGen/GenType.h b/lib/IRGen/GenType.h
index e733d15..e6cd38a 100644
--- a/lib/IRGen/GenType.h
+++ b/lib/IRGen/GenType.h
@@ -188,6 +188,7 @@
                                                            NominalTypeDecl *D);
     friend void TypeConverter::addForwardDecl(TypeBase*, llvm::Type*);
     friend ArchetypeType *TypeConverter::getExemplarArchetype(ArchetypeType *t);
+    friend void TypeConverter::pushGenericContext(CanGenericSignature signature);
     friend void TypeConverter::popGenericContext(CanGenericSignature signature);
     
 #ifndef NDEBUG
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index ee86454..62ec5c0 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -217,6 +217,7 @@
   ProtocolRequirementStructTy =
       createStructType(*this, "swift.protocol_requirement", {
     Int32Ty,                // flags
+    Int32Ty,                // thunk
     Int32Ty                 // default implementation
   });
   
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index fde73b9..e4c332f 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -92,6 +92,7 @@
   struct SILDeclRef;
   class SILGlobalVariable;
   class SILModule;
+  class SILProperty;
   class SILType;
   class SILWitnessTable;
   class SourceLoc;
@@ -1096,6 +1097,7 @@
   void emitCoverageMapping();
   void emitSILFunction(SILFunction *f);
   void emitSILWitnessTable(SILWitnessTable *wt);
+  void emitSILProperty(SILProperty *prop);
   void emitSILStaticInitializers();
   llvm::Constant *emitFixedTypeLayout(CanType t, const FixedTypeInfo &ti);
   void emitProtocolConformance(const NormalProtocolConformance *conformance);
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index e2e8284..10f82fc 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -28,6 +28,7 @@
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Transforms/Utils/Local.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/Basic/TargetInfo.h"
 #include "swift/Basic/ExternalUnion.h"
@@ -646,6 +647,41 @@
     return Name;
   }
 
+  /// Try to emit an inline assembly gadget which extends the lifetime of
+  /// \p Var. Returns whether or not this was successful.
+  bool emitLifetimeExtendingUse(llvm::Value *Var) {
+    llvm::Type *ArgTys;
+    auto *Ty = Var->getType();
+    // Vectors, Pointers and Floats are expected to fit into a register.
+    if (Ty->isPointerTy() || Ty->isFloatingPointTy() || Ty->isVectorTy())
+      ArgTys = {Ty};
+    else {
+      // If this is not a scalar or vector type, we can't handle it.
+      if (isa<llvm::CompositeType>(Ty))
+        return false;
+      // The storage is guaranteed to be no larger than the register width.
+      // Extend the storage so it would fit into a register.
+      llvm::Type *IntTy;
+      switch (IGM.getClangASTContext().getTargetInfo().getRegisterWidth()) {
+      case 64:
+        IntTy = IGM.Int64Ty;
+        break;
+      case 32:
+        IntTy = IGM.Int32Ty;
+        break;
+      default:
+        llvm_unreachable("unsupported register width");
+      }
+      ArgTys = {IntTy};
+      Var = Builder.CreateZExtOrBitCast(Var, IntTy);
+    }
+    // Emit an empty inline assembler expression depending on the register.
+    auto *AsmFnTy = llvm::FunctionType::get(IGM.VoidTy, ArgTys, false);
+    auto *InlineAsm = llvm::InlineAsm::get(AsmFnTy, "", "r", true);
+    Builder.CreateAsmCall(InlineAsm, Var);
+    return true;
+  }
+
   /// At -Onone, forcibly keep all LLVM values that are tracked by
   /// debug variables alive by inserting an empty inline assembler
   /// expression depending on the value in the blocks dominated by the
@@ -654,53 +690,31 @@
     if (IGM.IRGen.Opts.shouldOptimize())
       return;
     for (auto &Variable : ValueDomPoints) {
-      auto VarDominancePoint = Variable.second;
-      llvm::Value *Storage = Variable.first;
+      llvm::Instruction *Var = Variable.first;
+      DominancePoint VarDominancePoint = Variable.second;
       if (getActiveDominancePoint() == VarDominancePoint ||
           isActiveDominancePointDominatedBy(VarDominancePoint)) {
-        llvm::Type *ArgTys;
-        auto *Ty = Storage->getType();
-        // Vectors, Pointers and Floats are expected to fit into a register.
-        if (Ty->isPointerTy() || Ty->isFloatingPointTy() || Ty->isVectorTy())
-          ArgTys = { Ty };
-        else {
-          // If this is not a scalar or vector type, we can't handle it.
-          if (isa<llvm::CompositeType>(Ty))
-            continue;
-          // The storage is guaranteed to be no larger than the register width.
-          // Extend the storage so it would fit into a register.
-          llvm::Type *IntTy;
-          switch (IGM.getClangASTContext().getTargetInfo().getRegisterWidth()) {
-          case 64: IntTy = IGM.Int64Ty; break;
-          case 32: IntTy = IGM.Int32Ty; break;
-          default: llvm_unreachable("unsupported register width");
-          }
-          ArgTys = { IntTy };
-          Storage = Builder.CreateZExtOrBitCast(Storage, IntTy);
-        }
-        // Emit an empty inline assembler expression depending on the register.
-        auto *AsmFnTy = llvm::FunctionType::get(IGM.VoidTy, ArgTys, false);
-        auto *InlineAsm = llvm::InlineAsm::get(AsmFnTy, "", "r", true);
-        Builder.CreateAsmCall(InlineAsm, Storage);
-        // Propagate the dbg.value intrinsics into the later basic blocks.  Note
+        bool ExtendedLifetime = emitLifetimeExtendingUse(Var);
+        if (!ExtendedLifetime)
+          continue;
+
+        // Propagate dbg.values for Var into the current basic block. Note
         // that this shouldn't be necessary. LiveDebugValues should be doing
         // this but can't in general because it currently only tracks register
         // locations.
-        llvm::Instruction *Value = Variable.first;
-        auto It = llvm::BasicBlock::iterator(Value);
-        auto *BB = Value->getParent();
-        auto *CurBB = Builder.GetInsertBlock();
-        if (BB != CurBB)
-          for (auto I = std::next(It), E = BB->end(); I != E; ++I) {
-            auto *DVI = dyn_cast<llvm::DbgValueInst>(I);
-            if (DVI && DVI->getValue() == Value)
-              IGM.DebugInfo->getBuilder().insertDbgValueIntrinsic(
-                  DVI->getValue(), DVI->getVariable(), DVI->getExpression(),
-                  DVI->getDebugLoc(), &*CurBB->getFirstInsertionPt());
-            else
-              // Found all dbg.value intrinsics describing this location.
-              break;
-        }
+        llvm::BasicBlock *BB = Var->getParent();
+        llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
+        if (BB == CurBB)
+          // The current basic block must be a successor of the dbg.value().
+          continue;
+
+        llvm::SmallVector<llvm::DbgValueInst *, 4> DbgValues;
+        llvm::findDbgValues(DbgValues, Var);
+        for (auto *DVI : DbgValues)
+          if (DVI->getParent() == BB)
+            IGM.DebugInfo->getBuilder().insertDbgValueIntrinsic(
+                DVI->getValue(), DVI->getVariable(), DVI->getExpression(),
+                DVI->getDebugLoc(), &*CurBB->getFirstInsertionPt());
       }
     }
   }
@@ -754,10 +768,18 @@
     if (ArgNo == 0)
       // Otherwise only if debug value range extension is not feasible.
       if (!needsShadowCopy(Storage)) {
-        // Mark for debug value range extension unless this is a constant.
-        if (auto *Value = dyn_cast<llvm::Instruction>(Storage))
-          if (ValueVariables.insert(Value).second)
-            ValueDomPoints.push_back({Value, getActiveDominancePoint()});
+        // Mark for debug value range extension unless this is a constant, or
+        // unless it's not possible to emit lifetime-extending uses for this.
+        if (auto *Value = dyn_cast<llvm::Instruction>(Storage)) {
+          // Emit a use at the start of the storage lifetime to force early
+          // materialization. This makes variables available for inspection as
+          // soon as they are defined.
+          bool ExtendedLifetime = emitLifetimeExtendingUse(Value);
+          if (ExtendedLifetime)
+            if (ValueVariables.insert(Value).second)
+              ValueDomPoints.push_back({Value, getActiveDominancePoint()});
+        }
+
         return Storage;
       }
     return emitShadowCopy(Storage, Scope, Name, ArgNo, Align);
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index c186946..a8bd4ba 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -264,6 +264,7 @@
          Tok.isNot(tok::kw_sil_global) &&
          Tok.isNot(tok::kw_sil_witness_table) &&
          Tok.isNot(tok::kw_sil_default_witness_table) &&
+         Tok.isNot(tok::kw_sil_property) &&
          (isConditionalBlock ||
           !isTerminatorForBraceItemListKind(Kind, Entries))) {
 
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index d525751..5175609 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -5387,11 +5387,18 @@
   generics = P.maybeParseGenericParams().getPtrOrNull();
   patternEnv = handleSILGenericParams(P.Context, generics, &P.SF);
   
-  if (patternEnv->getGenericSignature()->getCanonicalSignature()
-        != VD->getInnermostDeclContext()->getGenericSignatureOfContext()
-      ->getCanonicalSignature()) {
-    P.diagnose(loc, diag::sil_property_generic_signature_mismatch);
-    return true;
+  if (patternEnv) {
+    if (patternEnv->getGenericSignature()->getCanonicalSignature()
+           != VD->getInnermostDeclContext()->getGenericSignatureOfContext()
+                ->getCanonicalSignature()) {
+      P.diagnose(loc, diag::sil_property_generic_signature_mismatch);
+      return true;
+    }
+  } else {
+    if (VD->getInnermostDeclContext()->getGenericSignatureOfContext()) {
+      P.diagnose(loc, diag::sil_property_generic_signature_mismatch);
+      return true;
+    }
   }
 
   Identifier ComponentKind;
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 726611d..c5b54a6 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -2654,7 +2654,8 @@
     break;
   }
   
-  OS << "\n\nimport Builtin\nimport " << STDLIB_NAME
+  OS << "\n\nimport " << BUILTIN_NAME
+     << "\nimport " << STDLIB_NAME
      << "\nimport " << SWIFT_SHIMS_NAME << "\n\n";
 
   // Print the declarations and types from the associated context (origin module or
@@ -2856,13 +2857,6 @@
       baseProtoWitness.Witness->printName(OS, Options);
       break;
     }
-    case MissingOptional: {
-      // optional requirement 'declref': <<not present>>
-      OS << "optional requirement '"
-         << witness.getMissingOptionalWitness().Witness->getBaseName()
-         << "': <<not present>>";
-      break;
-    }
     }
     OS << '\n';
   }
diff --git a/lib/SIL/SILWitnessTable.cpp b/lib/SIL/SILWitnessTable.cpp
index c69dd8d..732c3a7 100644
--- a/lib/SIL/SILWitnessTable.cpp
+++ b/lib/SIL/SILWitnessTable.cpp
@@ -116,7 +116,6 @@
     case AssociatedType:
     case AssociatedTypeProtocol:
     case BaseProtocol:
-    case MissingOptional:
     case Invalid:
       break;
     }
@@ -146,7 +145,6 @@
     case AssociatedType:
     case AssociatedTypeProtocol:
     case BaseProtocol:
-    case MissingOptional:
     case Invalid:
       break;
     }
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index d1dd6eb..e17aca4 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -1205,6 +1205,9 @@
 }
 
 void SILGenModule::tryEmitPropertyDescriptor(AbstractStorageDecl *decl) {
+  if (!M.getASTContext().LangOpts.EnableKeyPathResilience)
+    return;
+  
   // TODO: Key path code emission doesn't handle opaque values properly yet.
   if (!SILModuleConventions(M).useLoweredAddresses())
     return;
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 42c19d3..a6c5d89 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -3433,7 +3433,7 @@
   auto indexLoweredTy = SGM.Types.getLoweredType(indexTupleTy);
   // Get or create the equals witness
   [&unsafeRawPointerTy, &boolTy, &genericSig, &C, &indexTypes, &equals, &loc,
-   &SGM, &genericEnv, &indexLoweredTy, &hashableProto, &indexes]{
+   &SGM, &genericEnv, &indexLoweredTy, &indexes]{
     // (RawPointer, RawPointer) -> Bool
     SmallVector<SILParameterInfo, 2> params;
     params.push_back({unsafeRawPointerTy,
@@ -3448,7 +3448,7 @@
       SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                                /*pseudogeneric*/ false,
                                /*noescape*/ false),
-    SILCoroutineKind::None,
+      SILCoroutineKind::None,
       ParameterConvention::Direct_Unowned,
       params, /*yields*/ {}, results, None, C);
     
@@ -3486,42 +3486,37 @@
     auto equalsRef = SILDeclRef(equalsMethod);
     auto equalsTy = subSGF.SGM.Types.getConstantType(equalsRef);
     
-    auto hashableSig = C.getExistentialSignature(
-      hashableProto->getDeclaredType()->getCanonicalType(),
-      SGM.M.getSwiftModule());
-    
     auto isFalseBB = subSGF.createBasicBlock();
     auto i1Ty = SILType::getBuiltinIntegerType(1, C);
     for (unsigned i : indices(indexes)) {
       auto &index = indexes[i];
       
-      auto formalTy = index.FormalType;
-      auto hashable = index.Hashable;
-      if (genericEnv) {
-        formalTy = genericEnv->mapTypeIntoContext(formalTy)->getCanonicalType();
-        hashable = hashable.subst(index.FormalType,
-          [&](Type t) -> Type { return genericEnv->mapTypeIntoContext(t); },
-          LookUpConformanceInSignature(*genericSig));
-      }
+      Type formalTy = index.FormalType;
+      ProtocolConformanceRef hashable = index.Hashable;
+      std::tie(formalTy, hashable)
+        = GenericEnvironment::mapConformanceRefIntoContext(genericEnv,
+                                                           formalTy,
+                                                           hashable);
+      auto formalCanTy = formalTy->getCanonicalType(genericSig);
       
-      // Get the Equatable conformance from the Hashable conformance
-      auto subMap = hashableSig->getSubstitutionMap(
-        Substitution(formalTy, hashable));
-      auto equatable = *subMap
-        .lookupConformance(CanType(hashableSig->getGenericParams()[0]),
-                           equatableProtocol);
+      // Get the Equatable conformance from the Hashable conformance.
+      auto equatable = hashable.getAssociatedConformance(formalTy,
+        GenericTypeParamType::get(0, 0, C),
+        equatableProtocol);
       
       assert(equatable.isAbstract() == hashable.isAbstract());
       if (equatable.isConcrete())
         assert(equatable.getConcrete()->getType()->isEqual(
                   hashable.getConcrete()->getType()));
-      auto equatableSub = Substitution(formalTy,
-                   C.AllocateCopy(ArrayRef<ProtocolConformanceRef>(equatable)));
     
       auto equalsWitness = subSGF.B.createWitnessMethod(loc,
-        formalTy, equatable,
+        formalCanTy, equatable,
         equalsRef, equalsTy);
       
+      auto equatableSub
+        = SubstitutionMap::getProtocolSubstitutions(equatableProtocol,
+                                                    formalCanTy,
+                                                    equatable);
       auto equalsSubstTy = equalsTy.castTo<SILFunctionType>()
         ->substGenericArgs(SGM.M, equatableSub);
       auto equalsInfo = CalleeTypeInfo(equalsSubstTy,
@@ -3554,7 +3549,7 @@
         rhsArg = subSGF.emitManagedBufferWithCleanup(rhsBuf);
       }
 
-      auto metaty = CanMetatypeType::get(formalTy,
+      auto metaty = CanMetatypeType::get(formalCanTy,
                                          MetatypeRepresentation::Thick);
       auto metatyValue = ManagedValue::forUnmanaged(subSGF.B.createMetatype(loc,
         SILType::getPrimitiveObjectType(metaty)));
@@ -3564,14 +3559,17 @@
           equalsInfo, loc, SGFContext());
         ArgumentScope argScope(subSGF, loc);
         PostponedCleanup postpone(subSGF);
-        isEqual =
-            subSGF
-                .emitApply(std::move(equalsResultPlan), std::move(argScope),
-                           loc, ManagedValue::forUnmanaged(equalsWitness),
-                           equatableSub, {lhsArg, rhsArg, metatyValue},
-                           equalsInfo, ApplyOptions::None, SGFContext(),
-                           postpone)
-                .getUnmanagedSingleValue(subSGF, loc);
+        SmallVector<Substitution, 1> equatableSubListBuf;
+        equatableProtocol->getGenericSignature()
+          ->getSubstitutions(equatableSub, equatableSubListBuf);
+        isEqual = subSGF
+          .emitApply(std::move(equalsResultPlan), std::move(argScope),
+                     loc, ManagedValue::forUnmanaged(equalsWitness),
+                     C.AllocateCopy(equatableSubListBuf),
+                     {lhsArg, rhsArg, metatyValue},
+                     equalsInfo, ApplyOptions::None, SGFContext(),
+                     postpone)
+          .getUnmanagedSingleValue(subSGF, loc);
       }
       
       branchScope.pop();
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index b66aefa..38908c5 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -478,16 +478,6 @@
                                IsFreeFunctionWitness_t isFree,
                                Witness witness) {
     // Emit the witness thunk and add it to the table.
-
-    // If this is a non-present optional requirement, emit a MissingOptional.
-    if (!witnessRef) {
-      auto *fd = requirementRef.getDecl();
-      assert(fd->getAttrs().hasAttribute<OptionalAttr>() &&
-             "Non-optional protocol requirement lacks a witness?");
-      Entries.push_back(SILWitnessTable::MissingOptionalWitness{ fd });
-      return;
-    }
-
     auto witnessLinkage = witnessRef.getLinkage(ForDefinition);
     auto witnessSerialized = Serialized;
     if (witnessSerialized &&
diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
index 3605418..14a87a3 100644
--- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
+++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
@@ -177,7 +177,6 @@
           break;
 
         case SILWitnessTable::Invalid:
-        case SILWitnessTable::MissingOptional:
         case SILWitnessTable::AssociatedType:
           break;
       }
@@ -191,57 +190,56 @@
 
   /// Marks the declarations referenced by a key path pattern as alive if they
   /// aren't yet.
-  void ensureKeyPathComponentsAreAlive(KeyPathPattern *KP) {
-    for (auto &component : KP->getComponents()) {
-      switch (component.getKind()) {
-      case KeyPathPatternComponent::Kind::SettableProperty:
-        ensureAlive(component.getComputedPropertySetter());
-        LLVM_FALLTHROUGH;
-      case KeyPathPatternComponent::Kind::GettableProperty: {
-        ensureAlive(component.getComputedPropertyGetter());
-        auto id = component.getComputedPropertyId();
-        switch (id.getKind()) {
-        case KeyPathPatternComponent::ComputedPropertyId::DeclRef: {
-          auto declRef = id.getDeclRef();
-          if (declRef.isForeign) {
-            // Nothing to do here: foreign functions aren't ours to be deleting.
-            // (And even if they were, they're ObjC-dispatched and thus anchored
-            // already: see isAnchorFunction)
+  void
+  ensureKeyPathComponentIsAlive(const KeyPathPatternComponent &component) {
+    switch (component.getKind()) {
+    case KeyPathPatternComponent::Kind::SettableProperty:
+      ensureAlive(component.getComputedPropertySetter());
+      LLVM_FALLTHROUGH;
+    case KeyPathPatternComponent::Kind::GettableProperty: {
+      ensureAlive(component.getComputedPropertyGetter());
+      auto id = component.getComputedPropertyId();
+      switch (id.getKind()) {
+      case KeyPathPatternComponent::ComputedPropertyId::DeclRef: {
+        auto declRef = id.getDeclRef();
+        if (declRef.isForeign) {
+          // Nothing to do here: foreign functions aren't ours to be deleting.
+          // (And even if they were, they're ObjC-dispatched and thus anchored
+          // already: see isAnchorFunction)
+        } else {
+          auto decl = cast<AbstractFunctionDecl>(declRef.getDecl());
+          if (auto clas = dyn_cast<ClassDecl>(decl->getDeclContext())) {
+            ensureAliveClassMethod(getMethodInfo(decl, /*witness*/ false),
+                                   dyn_cast<FuncDecl>(decl),
+                                   clas);
+          } else if (isa<ProtocolDecl>(decl->getDeclContext())) {
+            ensureAliveProtocolMethod(getMethodInfo(decl, /*witness*/ true));
           } else {
-            auto decl = cast<AbstractFunctionDecl>(declRef.getDecl());
-            if (auto clas = dyn_cast<ClassDecl>(decl->getDeclContext())) {
-              ensureAliveClassMethod(getMethodInfo(decl, /*witness*/ false),
-                                     dyn_cast<FuncDecl>(decl),
-                                     clas);
-            } else if (isa<ProtocolDecl>(decl->getDeclContext())) {
-              ensureAliveProtocolMethod(getMethodInfo(decl, /*witness*/ true));
-            } else {
-              llvm_unreachable("key path keyed by a non-class, non-protocol method");
-            }
+            llvm_unreachable("key path keyed by a non-class, non-protocol method");
           }
-          break;
         }
-        case KeyPathPatternComponent::ComputedPropertyId::Function:
-          ensureAlive(id.getFunction());
-          break;
-        case KeyPathPatternComponent::ComputedPropertyId::Property:
-          break;
-        }
-
-        if (auto equals = component.getSubscriptIndexEquals())
-          ensureAlive(equals);
-        if (auto hash = component.getSubscriptIndexHash())
-          ensureAlive(hash);
-
-        continue;
+        break;
       }
-      case KeyPathPatternComponent::Kind::StoredProperty:
-      case KeyPathPatternComponent::Kind::OptionalChain:
-      case KeyPathPatternComponent::Kind::OptionalForce:
-      case KeyPathPatternComponent::Kind::OptionalWrap:
-      case KeyPathPatternComponent::Kind::External:
-        continue;
+      case KeyPathPatternComponent::ComputedPropertyId::Function:
+        ensureAlive(id.getFunction());
+        break;
+      case KeyPathPatternComponent::ComputedPropertyId::Property:
+        break;
       }
+
+      if (auto equals = component.getSubscriptIndexEquals())
+        ensureAlive(equals);
+      if (auto hash = component.getSubscriptIndexHash())
+        ensureAlive(hash);
+
+      break;
+    }
+    case KeyPathPatternComponent::Kind::StoredProperty:
+    case KeyPathPatternComponent::Kind::OptionalChain:
+    case KeyPathPatternComponent::Kind::OptionalForce:
+    case KeyPathPatternComponent::Kind::OptionalWrap:
+    case KeyPathPatternComponent::Kind::External:
+      break;
     }
   }
 
@@ -367,7 +365,8 @@
         } else if (auto *FRI = dyn_cast<FunctionRefInst>(&I)) {
           ensureAlive(FRI->getReferencedFunction());
         } else if (auto *KPI = dyn_cast<KeyPathInst>(&I)) {
-          ensureKeyPathComponentsAreAlive(KPI->getPattern());
+          for (auto &component : KPI->getPattern()->getComponents())
+            ensureKeyPathComponentIsAlive(component);
         }
       }
     }
@@ -510,8 +509,6 @@
         mi->addWitnessFunction(F, nullptr);
       }
     }
-
-
   }
 
   /// DeadFunctionElimination pass takes functions
@@ -600,6 +597,11 @@
         }
       }
     }
+    // Check property descriptor implementations.
+    for (SILProperty &P : Module->getPropertyList()) {
+      ensureKeyPathComponentIsAlive(P.getComponent());
+    }
+
   }
 
   /// Removes all dead methods from vtables and witness tables.
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 44589fb..6c2c004 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -27,9 +27,11 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "swift/AST/ASTMangler.h"
+
 using namespace swift;
 
 namespace {
+
 /// Optimize the placement of global initializers.
 ///
 /// TODO:
@@ -47,61 +49,99 @@
 ///   constant propagation in case of statically initialized "lets".
 class SILGlobalOpt {
   SILModule *Module;
-  DominanceAnalysis* DA;
+  DominanceAnalysis *DA;
   bool HasChanged = false;
 
-  // Map each global initializer to a list of call sites.
   typedef SmallVector<ApplyInst *, 4> GlobalInitCalls;
   typedef SmallVector<LoadInst *, 4> GlobalLoads;
-  llvm::MapVector<SILFunction*, GlobalInitCalls> GlobalInitCallMap;
+
+  /// A map from each visited global initializer call to a list of call sites.
+  llvm::MapVector<SILFunction *, GlobalInitCalls> GlobalInitCallMap;
 
   // The following mappings are used if this is a compilation
   // in scripting mode and global variables are accessed without
   // addressors.
 
-  // Map each global let variable to a set of loads from it.
-  llvm::MapVector<SILGlobalVariable*, GlobalLoads> GlobalLoadMap;
-  // Map each global let variable to the store instruction which initializes it.
-  llvm::MapVector<SILGlobalVariable*, StoreInst *> GlobalVarStore;
-  // Variables in this set should not be processed by this pass
-  // anymore.
-  llvm::SmallPtrSet<SILGlobalVariable*, 16> GlobalVarSkipProcessing;
+  /// A map from each visited global let variable to its set of loads.
+  llvm::MapVector<SILGlobalVariable *, GlobalLoads> GlobalLoadMap;
 
-  // Mark any block that this pass has determined to be inside a loop.
-  llvm::DenseSet<SILBasicBlock*> LoopBlocks;
-  // Mark any functions for which loops have been analyzed.
-  llvm::DenseSet<SILFunction*> LoopCheckedFunctions;
-  // Keep track of cold blocks.
-  ColdBlockInfo ColdBlocks;
+  /// A map from each visited global let variable to the store instructions
+  /// which initialize it.
+  llvm::MapVector<SILGlobalVariable *, StoreInst *> GlobalVarStore;
 
-  // Whether we see a "once" call to callees that we currently don't handle.
+  /// A set of visited global variables that for some reason we have decided is
+  /// not able to be optimized safely or for which we do not know how to
+  /// optimize safely.
+  ///
+  /// Once a global variable is in this set, we no longer will process it.
+  llvm::SmallPtrSet<SILGlobalVariable *, 16> GlobalVarSkipProcessing;
+
+  /// The set of blocks that this pass has determined to be inside a loop.
+  ///
+  /// This is used to mark any block that this pass has determined to be inside
+  /// a loop.
+  llvm::DenseSet<SILBasicBlock *> LoopBlocks;
+
+  /// The set of functions that have had their loops analyzed.
+  llvm::DenseSet<SILFunction *> LoopCheckedFunctions;
+
+  /// Whether we have seen any "once" calls to callees that we currently don't
+  /// handle.
   bool UnhandledOnceCallee = false;
-  // Record number of times a globalinit_func is called by "once".
-  llvm::DenseMap<SILFunction*, unsigned> InitializerCount;
+
+  /// A map from a globalinit_func to the number of times "once" has called the
+  /// function.
+  llvm::DenseMap<SILFunction *, unsigned> InitializerCount;
 public:
   SILGlobalOpt(SILModule *M, DominanceAnalysis *DA)
-      : Module(M), DA(DA), ColdBlocks(DA) {}
+      : Module(M), DA(DA) {}
 
   bool run();
 
 protected:
+  /// If this is a call to a global initializer, map it.
   void collectGlobalInitCall(ApplyInst *AI);
+
+  /// If this load is a read from a global let variable, add the load to
+  /// GlobalLoadMap[SILG].
   void collectGlobalLoad(LoadInst *SI, SILGlobalVariable *SILG);
+
+  /// If this store is a write to a global let variable, add the store to
+  /// GlobalStoreMap[SILG].
   void collectGlobalStore(StoreInst *SI, SILGlobalVariable *SILG);
+
+  /// This is the main entrypoint for collecting global accesses.
   void collectGlobalAccess(GlobalAddrInst *GAI);
 
   SILGlobalVariable *getVariableOfGlobalInit(SILFunction *AddrF);
-  bool isInLoop(SILBasicBlock *CurBB);
-  void placeInitializers(SILFunction *InitF, ArrayRef<ApplyInst*> Calls);
 
-  // Update UnhandledOnceCallee and InitializerCount by going through all "once"
-  // calls.
+  /// Returns true if we think that \p CurBB is inside a loop.
+  bool isInLoop(SILBasicBlock *CurBB);
+
+  /// Given that we are trying to place initializers in new locations, see if
+  /// we can hoist the passed in apply \p AI out of any loops that it is
+  /// currently within.
+  ApplyInst *getHoistedApplyForInitializer(
+      ApplyInst *AI, DominanceInfo *DT, SILFunction *InitF,
+      SILFunction *ParentF,
+      llvm::DenseMap<SILFunction *, ApplyInst *> &ParentFuncs);
+
+  void placeInitializers(SILFunction *InitF, ArrayRef<ApplyInst *> Calls);
+
+  /// Update UnhandledOnceCallee and InitializerCount by going through all
+  /// "once" calls.
   void collectOnceCall(BuiltinInst *AI);
-  // Set the static initializer and remove "once" from addressor if a global can
-  // be statically initialized.
+
+  /// Set the static initializer and remove "once" from addressor if a global
+  /// can be statically initialized.
   void optimizeInitializer(SILFunction *AddrF, GlobalInitCalls &Calls);
+
+  /// Optimize access to the global variable, which is known to have a constant
+  /// value. Replace all loads from the global address by invocations of a
+  /// getter that returns the value of this variable.
   void optimizeGlobalAccess(SILGlobalVariable *SILG, StoreInst *SI);
-  // Replace loads from a global variable by the known value.
+
+  /// Replace loads from a global variable by the known value.
   void replaceLoadsByKnownValue(BuiltinInst *CallToOnce,
                                 SILFunction *AddrF,
                                 SILFunction *InitF,
@@ -118,11 +158,11 @@
 
   ArrayRef<SILInstruction *> Insns;
 
-  protected:
+protected:
   SILBasicBlock *FromBB, *DestBB;
 
-  public:
-  // A map of old to new available values.
+public:
+  /// A map of old to new available values.
   SmallVector<std::pair<ValueBase *, SILValue>, 16> AvailVals;
 
   InstructionsCloner(SILFunction &F,
@@ -147,7 +187,7 @@
       AvailVals.push_back(std::make_pair(origResults[i], clonedResults[i]));
   }
 
-  // Clone all instructions from Insns into DestBB
+  /// Clone all instructions from Insns into DestBB
   void clone() {
     for (auto I : Insns)
       process(I);
@@ -156,7 +196,7 @@
 
 } // end anonymous namespace
 
-/// If this is a call to a global initializer, map it.
+// If this is a call to a global initializer, map it.
 void SILGlobalOpt::collectGlobalInitCall(ApplyInst *AI) {
   SILFunction *F = AI->getReferencedFunction();
   if (!F || !F->isGlobalInit())
@@ -165,10 +205,10 @@
   GlobalInitCallMap[F].push_back(AI);
 }
 
-/// If this is a read from a global let variable, map it.
+// Map the load if this load is a read from a global variable that is either a
+// let or a global variable that can not be changed externally
 void SILGlobalOpt::collectGlobalLoad(LoadInst *LI, SILGlobalVariable *SILG) {
   assert(SILG);
-  //assert(SILG->isLet());
 
   // This is read from a let variable.
   // Figure out if the value of this variable is statically known.
@@ -237,8 +277,8 @@
       IsBare, IsNotTransparent, Serialized);
 }
 
-/// Generate getter from the initialization code whose
-/// result is stored by a given store instruction.
+/// Generate getter from the initialization code whose result is stored by a
+/// given store instruction.
 static SILFunction *genGetterFromInit(StoreInst *Store,
                                       SILGlobalVariable *SILG) {
   auto *varDecl = SILG->getDecl();
@@ -248,17 +288,14 @@
 
   auto V = Store->getSrc();
 
-  SmallVector<SILInstruction *, 8> ReverseInsns;
-  SmallVector<SILInstruction *, 8> Insns;
-  ReverseInsns.push_back(Store);
-  ReverseInsns.push_back(dyn_cast<SingleValueInstruction>(Store->getDest()));
-  if (!analyzeStaticInitializer(V, ReverseInsns))
+  SmallVector<SILInstruction *, 8> Insts;
+  Insts.push_back(Store);
+  Insts.push_back(cast<SingleValueInstruction>(Store->getDest()));
+  if (!analyzeStaticInitializer(V, Insts))
     return nullptr;
 
   // Produce a correct order of instructions.
-  while (!ReverseInsns.empty()) {
-    Insns.push_back(ReverseInsns.pop_back_val());
-  }
+  std::reverse(Insts.begin(), Insts.end());
 
   auto *GetterF = getGlobalGetterFunction(Store->getModule(),
                                           Store->getLoc(),
@@ -270,7 +307,7 @@
   auto *EntryBB = GetterF->createBasicBlock();
 
   // Copy instructions into GetterF
-  InstructionsCloner Cloner(*GetterF, Insns, EntryBB);
+  InstructionsCloner Cloner(*GetterF, Insts, EntryBB);
   Cloner.clone();
   GetterF->setInlined();
 
@@ -299,7 +336,7 @@
   return GetterF;
 }
 
-/// If this is a read from a global let variable, map it.
+// If this is a write to a global let variable, map it.
 void SILGlobalOpt::collectGlobalStore(StoreInst *SI, SILGlobalVariable *SILG) {
 
   if (GlobalVarStore.count(SILG)) {
@@ -327,8 +364,8 @@
   return nullptr;
 }
 
-/// Update UnhandledOnceCallee and InitializerCount by going through all "once"
-/// calls.
+// Update UnhandledOnceCallee and InitializerCount by going through all "once"
+// calls.
 void SILGlobalOpt::collectOnceCall(BuiltinInst *BI) {
   if (UnhandledOnceCallee)
     return;
@@ -410,6 +447,48 @@
   }
 }
 
+ApplyInst *SILGlobalOpt::getHoistedApplyForInitializer(
+    ApplyInst *AI, DominanceInfo *DT, SILFunction *InitF, SILFunction *ParentF,
+    llvm::DenseMap<SILFunction *, ApplyInst *> &ParentFuncs) {
+  auto PFI = ParentFuncs.find(ParentF);
+  if (PFI == ParentFuncs.end()) {
+    ParentFuncs[ParentF] = AI;
+
+    // It's the first time we found a call to InitF in this function, so we
+    // try to hoist it out of any loop.
+    return AI;
+  }
+
+  // Found a replacement for this init call. Ensure the replacement dominates
+  // the original call site.
+  ApplyInst *CommonAI = PFI->second;
+  assert(
+      cast<FunctionRefInst>(CommonAI->getCallee())->getReferencedFunction() ==
+          InitF &&
+      "ill-formed global init call");
+  SILBasicBlock *DomBB =
+      DT->findNearestCommonDominator(AI->getParent(), CommonAI->getParent());
+
+  // We must not move initializers around availability-checks.
+  if (isAvailabilityCheckOnDomPath(DomBB, CommonAI->getParent(), DT))
+    return nullptr;
+
+  ApplyInst *Result = nullptr;
+  if (DomBB != CommonAI->getParent()) {
+    CommonAI->moveBefore(&*DomBB->begin());
+    placeFuncRef(CommonAI, DT);
+
+    // Try to hoist the existing AI again if we move it to another block,
+    // e.g. from a loop exit into the loop.
+    Result = CommonAI;
+  }
+
+  AI->replaceAllUsesWith(CommonAI);
+  AI->eraseFromParent();
+  HasChanged = true;
+  return Result;
+}
+
 /// Optimize placement of initializer calls given a list of calls to the
 /// same initializer. All original initialization points must be dominated by
 /// the final initialization calls.
@@ -417,82 +496,56 @@
 /// The current heuristic hoists all initialization points within a function to
 /// a single dominating call in the outer loop preheader.
 void SILGlobalOpt::placeInitializers(SILFunction *InitF,
-                                     ArrayRef<ApplyInst*> Calls) {
+                                     ArrayRef<ApplyInst *> Calls) {
   DEBUG(llvm::dbgs() << "GlobalOpt: calls to "
         << Demangle::demangleSymbolAsString(InitF->getName())
         << " : " << Calls.size() << "\n");
   // Map each initializer-containing function to its final initializer call.
-  llvm::DenseMap<SILFunction*, ApplyInst*> ParentFuncs;
+  llvm::DenseMap<SILFunction *, ApplyInst *> ParentFuncs;
   for (auto *AI : Calls) {
     assert(AI->getNumArguments() == 0 && "ill-formed global init call");
     assert(cast<FunctionRefInst>(AI->getCallee())->getReferencedFunction()
            == InitF && "wrong init call");
-
     SILFunction *ParentF = AI->getFunction();
     DominanceInfo *DT = DA->get(ParentF);
-    auto PFI = ParentFuncs.find(ParentF);
-    ApplyInst *HoistAI = nullptr;
-    if (PFI != ParentFuncs.end()) {
-      // Found a replacement for this init call.
-      // Ensure the replacement dominates the original call site.
-      ApplyInst *CommonAI = PFI->second;
-      assert(cast<FunctionRefInst>(CommonAI->getCallee())
-             ->getReferencedFunction() == InitF &&
-             "ill-formed global init call");
-      SILBasicBlock *DomBB =
-        DT->findNearestCommonDominator(AI->getParent(), CommonAI->getParent());
-      
-      // We must not move initializers around availability-checks.
-      if (!isAvailabilityCheckOnDomPath(DomBB, CommonAI->getParent(), DT)) {
-        if (DomBB != CommonAI->getParent()) {
-          CommonAI->moveBefore(&*DomBB->begin());
-          placeFuncRef(CommonAI, DT);
-          
-          // Try to hoist the existing AI again if we move it to another block,
-          // e.g. from a loop exit into the loop.
-          HoistAI = CommonAI;
-        }
-        AI->replaceAllUsesWith(CommonAI);
-        AI->eraseFromParent();
-        HasChanged = true;
-      }
-    } else {
-      ParentFuncs[ParentF] = AI;
-      
-      // It's the first time we found a call to InitF in this function, so we
-      // try to hoist it out of any loop.
-      HoistAI = AI;
+    ApplyInst *HoistAI =
+        getHoistedApplyForInitializer(AI, DT, InitF, ParentF, ParentFuncs);
+
+    // If we were unable to find anything, just go onto the next apply.
+    if (!HoistAI) {
+      continue;
     }
-    if (HoistAI) {
-      // Move this call to the outermost loop preheader.
-      SILBasicBlock *BB = HoistAI->getParent();
-      typedef llvm::DomTreeNodeBase<SILBasicBlock> DomTreeNode;
-      DomTreeNode *Node = DT->getNode(BB);
-      while (Node) {
-        SILBasicBlock *DomParentBB = Node->getBlock();
-        if (isAvailabilityCheck(DomParentBB)) {
-          DEBUG(llvm::dbgs() << "  don't hoist above availability check at bb"
-                             << DomParentBB->getDebugID() << "\n");
-          break;
-        }
-        BB = DomParentBB;
-        if (!isInLoop(BB))
-          break;
-        Node = Node->getIDom();
+
+    // Otherwise, move this call to the outermost loop preheader.
+    SILBasicBlock *BB = HoistAI->getParent();
+    typedef llvm::DomTreeNodeBase<SILBasicBlock> DomTreeNode;
+    DomTreeNode *Node = DT->getNode(BB);
+    while (Node) {
+      SILBasicBlock *DomParentBB = Node->getBlock();
+      if (isAvailabilityCheck(DomParentBB)) {
+        DEBUG(llvm::dbgs() << "  don't hoist above availability check at bb"
+                           << DomParentBB->getDebugID() << "\n");
+        break;
       }
-      if (BB == HoistAI->getParent()) {
-        // BB is either unreachable or not in a loop.
-        DEBUG(llvm::dbgs() << "  skipping (not in a loop): " << *HoistAI
-              << "  in " << HoistAI->getFunction()->getName() << "\n");
-      }
-      else {
-        DEBUG(llvm::dbgs() << "  hoisting: " << *HoistAI
-              << "  in " << HoistAI->getFunction()->getName() << "\n");
-        HoistAI->moveBefore(&*BB->begin());
-        placeFuncRef(HoistAI, DT);
-        HasChanged = true;
-      }
+      BB = DomParentBB;
+      if (!isInLoop(BB))
+        break;
+      Node = Node->getIDom();
     }
+
+    if (BB == HoistAI->getParent()) {
+      // BB is either unreachable or not in a loop.
+      DEBUG(llvm::dbgs() << "  skipping (not in a loop): " << *HoistAI
+                         << "  in " << HoistAI->getFunction()->getName()
+                         << "\n");
+      continue;
+    }
+
+    DEBUG(llvm::dbgs() << "  hoisting: " << *HoistAI << "  in "
+                       << HoistAI->getFunction()->getName() << "\n");
+    HoistAI->moveBefore(&*BB->begin());
+    placeFuncRef(HoistAI, DT);
+    HasChanged = true;
   }
 }
 
@@ -659,10 +712,6 @@
   return GVar;
 }
 
-namespace {
-
-} // end anonymous namespace
-
 /// Replace loads from a global variable by the known value.
 void SILGlobalOpt::
 replaceLoadsByKnownValue(BuiltinInst *CallToOnce, SILFunction *AddrF,
@@ -774,30 +823,29 @@
 }
 
 SILGlobalVariable *SILGlobalOpt::getVariableOfGlobalInit(SILFunction *AddrF) {
-  if (AddrF->isGlobalInit()) {
-    // If the addressor contains a single "once" call, it calls globalinit_func,
-    // and the globalinit_func is called by "once" from a single location,
-    // continue; otherwise bail.
-    BuiltinInst *CallToOnce;
-    auto *InitF = findInitializer(Module, AddrF, CallToOnce);
+  if (!AddrF->isGlobalInit())
+    return nullptr;
 
-    if (!InitF || !InitF->getName().startswith("globalinit_")
-        || InitializerCount[InitF] > 1)
-      return nullptr;
+  // If the addressor contains a single "once" call, it calls globalinit_func,
+  // and the globalinit_func is called by "once" from a single location,
+  // continue; otherwise bail.
+  BuiltinInst *CallToOnce;
+  auto *InitF = findInitializer(Module, AddrF, CallToOnce);
 
-    // If the globalinit_func is trivial, continue; otherwise bail.
-    SingleValueInstruction *dummyInitVal;
-    auto *SILG = getVariableOfStaticInitializer(InitF, dummyInitVal);
-    if (!SILG || !SILG->isDefinition())
-      return nullptr;
+  if (!InitF || !InitF->getName().startswith("globalinit_")
+      || InitializerCount[InitF] > 1)
+    return nullptr;
 
-    return SILG;
-  }
-  return nullptr;
+  // If the globalinit_func is trivial, continue; otherwise bail.
+  SingleValueInstruction *dummyInitVal;
+  auto *SILG = getVariableOfStaticInitializer(InitF, dummyInitVal);
+  if (!SILG || !SILG->isDefinition())
+    return nullptr;
+
+  return SILG;
 }
 
 static bool canBeChangedExternally(SILGlobalVariable *SILG) {
-
   // Don't assume anything about globals which are imported from other modules.
   if (isAvailableExternally(SILG->getLinkage()))
     return true;
@@ -880,16 +928,14 @@
   if (!SILG->getDecl())
     return;
 
-  SILValue V = GAI;
-  for (auto Use : getNonDebugUses(V)) {
-
-    if (auto *SI = dyn_cast<StoreInst>(Use->getUser())) {
+  for (auto *Op : getNonDebugUses(GAI)) {
+    if (auto *SI = dyn_cast<StoreInst>(Op->getUser())) {
       if (SI->getDest() == GAI)
         collectGlobalStore(SI, SILG);
       continue;
     }
 
-    if (auto *Load = getValidLoad(Use->getUser(), GAI)) {
+    if (auto *Load = getValidLoad(Op->getUser(), GAI)) {
       collectGlobalLoad(Load, SILG);
       continue;
     }
@@ -901,10 +947,9 @@
   }
 }
 
-/// Optimize access to the global variable, which is known
-/// to have a constant value. Replace all loads from the
-/// global address by invocations of a getter that returns
-/// the value of this variable.
+// Optimize access to the global variable, which is known to have a constant
+// value. Replace all loads from the global address by invocations of a getter
+// that returns the value of this variable.
 void SILGlobalOpt::optimizeGlobalAccess(SILGlobalVariable *SILG,
                                         StoreInst *SI) {
   DEBUG(llvm::dbgs() << "GlobalOpt: use static initializer for " <<
@@ -931,7 +976,7 @@
   // inside each function that loads from the global. This
   // invocation should happen at the common dominator of all
   // loads inside this function.
-  for (auto *Load: GlobalLoadMap[SILG]) {
+  for (auto *Load : GlobalLoadMap[SILG]) {
     SILBuilderWithScope B(Load);
     auto *GetterRef = B.createFunctionRef(Load->getLoc(), GetterF);
     auto *Value = B.createApply(Load->getLoc(), GetterRef, {}, false);
@@ -953,30 +998,26 @@
     ColdBlockInfo ColdBlocks(DA);
     for (auto &BB : F) {
       bool IsCold = ColdBlocks.isCold(&BB);
-      auto Iter = BB.begin();
-
-      // We can't remove instructions willy-nilly as we iterate because
-      // that might cause a pointer to the next instruction to become
-      // garbage, causing iterator invalidations (and crashes).
-      // Instead, we collect in a list the instructions we want to remove
-      // and erase the BB they belong to at the end of the loop, once we're
-      // sure it's safe to do so.
-      llvm::SmallVector<SILInstruction *, 4> ToRemove;
-
-      while (Iter != BB.end()) {
-        SILInstruction *I = &*Iter;
-        Iter++;
-        if (auto *BI = dyn_cast<BuiltinInst>(I)) {
+      for (auto &I : BB) {
+        if (auto *BI = dyn_cast<BuiltinInst>(&I)) {
           collectOnceCall(BI);
-        } else if (auto *AI = dyn_cast<ApplyInst>(I)) {
-          if (!IsCold)
-            collectGlobalInitCall(AI);
-        } else if (auto *GAI = dyn_cast<GlobalAddrInst>(I)) {
-          collectGlobalAccess(GAI);
+          continue;
         }
+
+        if (auto *AI = dyn_cast<ApplyInst>(&I)) {
+          if (!IsCold) {
+            collectGlobalInitCall(AI);
+          }
+          continue;
+        }
+
+        auto *GAI = dyn_cast<GlobalAddrInst>(&I);
+        if (!GAI) {
+          continue;
+        }
+
+        collectGlobalAccess(GAI);
       }
-      for (auto *I : ToRemove)
-        I->eraseFromParent();
     }
   }
 
@@ -994,17 +1035,21 @@
   return HasChanged;
 }
 
+//===----------------------------------------------------------------------===//
+//                           Top Level Entry Point
+//===----------------------------------------------------------------------===//
+
 namespace {
-class SILGlobalOptPass : public SILModuleTransform
-{
+
+class SILGlobalOptPass : public SILModuleTransform {
   void run() override {
-    DominanceAnalysis *DA = PM->getAnalysis<DominanceAnalysis>();
+    auto *DA = PM->getAnalysis<DominanceAnalysis>();
     if (SILGlobalOpt(getModule(), DA).run()) {
       invalidateAll();
     }
   }
-
 };
+
 } // end anonymous namespace
 
 SILTransform *swift::createGlobalOpt() {
diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
index 0229d8d..846dc04 100644
--- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
+++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
@@ -277,6 +277,8 @@
 /// Promote a DebugValueAddr to a DebugValue of the given value.
 static void
 promoteDebugValueAddr(DebugValueAddrInst *DVAI, SILValue Value, SILBuilder &B) {
+  assert(DVAI->getOperand()->getType().isLoadable(DVAI->getModule()) &&
+         "Unexpected promotion of address-only type!");
   assert(Value && "Expected valid value");
   B.setInsertionPoint(DVAI);
   B.setCurrentDebugScope(DVAI->getDebugScope());
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 55d3ad3..ee55a7d 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -4655,6 +4655,8 @@
       
         auto hashable =
           cs.getASTContext().getProtocol(KnownProtocolKind::Hashable);
+        auto equatable =
+          cs.getASTContext().getProtocol(KnownProtocolKind::Equatable);
         for (auto indexType : indexTypes) {
           auto conformance =
             cs.TC.conformsToProtocol(indexType.getType(), hashable,
@@ -4669,6 +4671,17 @@
             continue;
           }
           hashables.push_back(*conformance);
+          
+          // FIXME: Hashable implies Equatable, but we need to make sure the
+          // Equatable conformance is forced into existence during type checking
+          // so that it's available for SILGen.
+          auto eqConformance =
+            cs.TC.conformsToProtocol(indexType.getType(), equatable,
+                                     cs.DC,
+                                     (ConformanceCheckFlags::Used|
+                                      ConformanceCheckFlags::InExpression));
+          assert(eqConformance.hasValue());
+          (void)eqConformance;
         }
 
         if (allIndexesHashable) {
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 264c08b..4153853 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -2111,13 +2111,17 @@
         // Walk the base expression to ensure we erase any existentials within
         // it.
         base = base->walk(*this);
-        
-        bool inserted = OpenExistentials.insert({archetypeVal, base}).second;
-        assert(inserted && "OpaqueValue appears multiple times?");
-        (void)inserted;
+
+        registerOpaqueValue(archetypeVal, base);
         return { true, OOE->getSubExpr() };
       }
-      
+
+      if (auto *MTEE = dyn_cast<MakeTemporarilyEscapableExpr>(expr)) {
+        registerOpaqueValue(MTEE->getOpaqueValue(),
+                            MTEE->getNonescapingClosureValue());
+        return {true, MTEE->getSubExpr()};
+      }
+
       if (auto OVE = dyn_cast<OpaqueValueExpr>(expr)) {
         auto value = OpenExistentials.find(OVE);
         assert(value != OpenExistentials.end() &&
@@ -2166,6 +2170,12 @@
     std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
       return { false, S };
     }
+
+    void registerOpaqueValue(OpaqueValueExpr *opaque, Expr *base) {
+      bool inserted = OpenExistentials.insert({opaque, base}).second;
+      assert(inserted && "OpaqueValue appears multiple times?");
+      (void)inserted;
+    }
   };
 
   expr = expr->walk(ExistentialEraser(CS));
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index ae91de4..c621a49 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -3476,6 +3476,7 @@
 
   ConstraintSystemOptions Options = ConstraintSystemFlags::AllowFixes;
   auto *TC = static_cast<TypeChecker*>(DC.getASTContext().getLazyResolver());
+  Parent = Parent->walk(SanitizeExpr(*TC));
   ConstraintSystem CS(*TC, &DC, Options);
   CleanupIllFormedExpressionRAII cleanup(TC->Context, Parent);
   InferUnresolvedMemberConstraintGenerator MCG(E, CS);
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index 451f047..c28715a 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -384,6 +384,21 @@
   return param.getType();
 }
 
+// Is a particular parameter of a function or subscript declaration
+// declared to be an IUO?
+static bool paramIsIUO(Decl *decl, int paramNum) {
+  if (auto *fn = dyn_cast<AbstractFunctionDecl>(decl)) {
+    auto *paramList =
+        fn->getParameterList(fn->getDeclContext()->isTypeContext());
+    auto *param = paramList->get(paramNum);
+    return param->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
+  }
+
+  auto *subscript = cast<SubscriptDecl>(decl);
+  auto *index = subscript->getIndices()->get(paramNum);
+  return index->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
+}
+
 /// \brief Determine whether the first declaration is as "specialized" as
 /// the second declaration.
 ///
@@ -676,6 +691,17 @@
             continue;
           }
 
+          // Emulate behavior from when IUO was a type, where IUOs
+          // were considered subtypes of plain optionals, but not
+          // vice-versa.  This wouldn't normally happen, but there are
+          // cases where we can rename imported APIs so that we have a
+          // name collision, and where the parameter type(s) are the
+          // same except for details of the kind of optional declared.
+          auto param1IsIUO = paramIsIUO(decl1, param1);
+          auto param2IsIUO = paramIsIUO(decl2, param2);
+          if (param2IsIUO && !param1IsIUO)
+            return false;
+
           if (!maybeAddSubtypeConstraint(params1[param1], params2[param2]))
             return false;
 
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 188bb4b..d22a2c4 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1776,6 +1776,10 @@
     return true;
   }
 
+  // Skip unavailable overloads unless solver is in the "diagnostic" mode.
+  if (!cs.shouldAttemptFixes() && choice.isUnavailable())
+    return true;
+
   // Don't attempt to solve for generic operators if we already have
   // a non-generic solution.
 
@@ -1784,7 +1788,7 @@
   //        already have a solution involving non-generic operators,
   //        but continue looking for a better non-generic operator
   //        solution.
-  if (bestNonGenericScore && choice.isGenericOperatorOrUnavailable()) {
+  if (bestNonGenericScore && choice.isGenericOperator()) {
     auto &score = bestNonGenericScore->Data;
     // Let's skip generic overload choices only in case if
     // non-generic score indicates that there were no forced
@@ -1943,7 +1947,7 @@
     // We already have a solution; check whether we should
     // short-circuit the disjunction.
     if (lastSolvedChoice) {
-      auto *lastChoice = lastSolvedChoice->first.getConstraint();
+      Constraint *lastChoice = lastSolvedChoice->first;
       auto &score = lastSolvedChoice->second;
       bool hasUnavailableOverloads = score.Data[SK_Unavailable] > 0;
       bool hasFixes = score.Data[SK_Fix] > 0;
@@ -1952,8 +1956,7 @@
       // that there are no unavailable overload choices present in the
       // solution, and the solution does not involve fixes.
       if (!hasUnavailableOverloads && !hasFixes &&
-          shortCircuitDisjunctionAt(&currentChoice, lastChoice,
-                                    getASTContext()))
+          shortCircuitDisjunctionAt(currentChoice, lastChoice, getASTContext()))
         break;
     }
 
@@ -1981,7 +1984,7 @@
     }
 
     if (auto score = currentChoice.solve(solutions, allowFreeTypeVariables)) {
-      if (!currentChoice.isGenericOperatorOrUnavailable() &&
+      if (!currentChoice.isGenericOperator() &&
           currentChoice.isSymmetricOperator()) {
         if (!bestNonGenericScore || score < bestNonGenericScore)
           bestNonGenericScore = score;
@@ -2046,21 +2049,17 @@
   return bestScore;
 }
 
-bool DisjunctionChoice::isGenericOperatorOrUnavailable() const {
-  auto *decl = getOperatorDecl(Choice);
+bool DisjunctionChoice::isGenericOperator() const {
+  auto *decl = getOperatorDecl();
   if (!decl)
     return false;
 
-  auto &ctx = decl->getASTContext();
-  if (decl->getAttrs().isUnavailable(ctx))
-    return true;
-
   auto interfaceType = decl->getInterfaceType();
   return interfaceType->is<GenericFunctionType>();
 }
 
 bool DisjunctionChoice::isSymmetricOperator() const {
-  auto *decl = getOperatorDecl(Choice);
+  auto *decl = getOperatorDecl();
   if (!decl)
     return false;
 
diff --git a/lib/Sema/CalleeCandidateInfo.cpp b/lib/Sema/CalleeCandidateInfo.cpp
index d1a0570..d8ad621 100644
--- a/lib/Sema/CalleeCandidateInfo.cpp
+++ b/lib/Sema/CalleeCandidateInfo.cpp
@@ -25,6 +25,36 @@
 using namespace swift;
 using namespace constraints;
 
+/// \brief Determine whether one type would be a valid substitution for an
+/// archetype.
+///
+/// \param type The potential type.
+///
+/// \param archetype The archetype for which type may (or may not) be
+/// substituted.
+///
+/// \param dc The context of the check.
+///
+/// \returns true if \c t1 is a valid substitution for \c t2.
+static bool isSubstitutableFor(Type type, ArchetypeType *archetype,
+                               DeclContext *dc) {
+  if (archetype->requiresClass() && !type->satisfiesClassConstraint())
+    return false;
+
+  if (auto superclass = archetype->getSuperclass()) {
+    if (!superclass->isExactSuperclassOf(type))
+      return false;
+  }
+
+  for (auto proto : archetype->getConformsTo()) {
+    if (!dc->getParentModule()->lookupConformance(
+          type, proto))
+      return false;
+  }
+
+  return true;
+}
+
 UncurriedCandidate::UncurriedCandidate(ValueDecl *decl, unsigned level)
 : declOrExpr(decl), level(level), substituted(false) {
   
@@ -426,14 +456,14 @@
             if (!archetype->isPrimary())
               return { CC_ArgumentMismatch, {}};
             
-            if (!CS.TC.isSubstitutableFor(substitution, archetype, CS.DC)) {
+            if (!isSubstitutableFor(substitution, archetype, CS.DC)) {
               // If we have multiple non-substitutable types, this is just a mismatched mess.
               if (!nonSubstitutableArchetype.isNull())
                 return { CC_ArgumentMismatch, {}};
               
               if (auto argOptType = argType->getOptionalObjectType())
                 mismatchesAreNearMisses &=
-                CS.TC.isSubstitutableFor(argOptType, archetype, CS.DC);
+                  isSubstitutableFor(argOptType, archetype, CS.DC);
               else
                 mismatchesAreNearMisses = false;
               
@@ -455,7 +485,7 @@
               // type might be the one that we should be substituting for instead.
               // Note that failureInfo is already set correctly for that case.
               if (isNonSubstitutableArchetype && nonSubstitutableArgs == 1 &&
-                  CS.TC.isSubstitutableFor(substitution, archetype, CS.DC)) {
+                  isSubstitutableFor(substitution, archetype, CS.DC)) {
                 mismatchesAreNearMisses = argumentMismatchIsNearMiss(existingSubstitution, substitution);
                 allGenericSubstitutions[archetype] = substitution;
               } else {
@@ -959,7 +989,7 @@
     
     // Check for optional near miss.
     if (auto argOptType = substitution->getOptionalObjectType()) {
-      if (CS.TC.isSubstitutableFor(argOptType, paramArchetype, CS.DC)) {
+      if (isSubstitutableFor(argOptType, paramArchetype, CS.DC)) {
         CS.TC.diagnose(badArgExpr->getLoc(), diag::missing_unwrap_optional,
                        argType);
         foundFailure = true;
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 4a1d3a0..4d62a90 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -1397,6 +1397,7 @@
 
   Parameter->setInterfaceType(SubstInterfaceTy);
   Parameter->setGenericEnvironment(genericEnv);
+  Parameter->setValidationStarted();
 
   // Mark the method to be final, implicit, and private.  In a class, this
   // prevents it from being dynamically dispatched.
@@ -1895,11 +1896,11 @@
 ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc,
                                                   NominalTypeDecl *decl,
                                                   ImplicitConstructorKind ICK) {
+  assert(!decl->hasClangNode());
+
   ASTContext &context = tc.Context;
   SourceLoc Loc = decl->getLoc();
   auto accessLevel = AccessLevel::Internal;
-  if (decl->hasClangNode())
-    accessLevel = std::max(accessLevel, decl->getFormalAccess());
 
   // Determine the parameter type of the implicit constructor.
   SmallVector<ParamDecl*, 8> params;
@@ -1975,13 +1976,7 @@
   }
 
   // Type-check the constructor declaration.
-  tc.typeCheckDecl(ctor, /*isFirstPass=*/true);
-
-  // If the struct in which this constructor is being added was imported,
-  // add it as an external definition.
-  if (decl->hasClangNode()) {
-    tc.Context.addExternalDecl(ctor);
-  }
+  tc.validateDecl(ctor);
 
   return ctor;
 }
@@ -2152,6 +2147,7 @@
   // Wire up the overrides.
   ctor->getAttrs().add(new (tc.Context) OverrideAttr(/*IsImplicit=*/true));
   ctor->setOverriddenDecl(superclassCtor);
+  ctor->setValidationStarted();
 
   if (kind == DesignatedInitKind::Stub) {
     // Make this a stub implementation.
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 155a3a5..f127365 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -3246,30 +3246,42 @@
                     Constraint *choice)
       : CS(cs), Disjunction(disjunction), Choice(choice) {}
 
-  Constraint *operator&() const { return Choice; }
-
-  Constraint *getConstraint() const { return Choice; }
-
   Constraint *operator->() const { return Choice; }
 
   bool isDisabled() const { return Choice->isDisabled(); }
 
+  bool isUnavailable() const {
+    if (auto *decl = getDecl(Choice))
+      return decl->getAttrs().isUnavailable(decl->getASTContext());
+    return false;
+  }
+
   // FIXME: Both of the accessors below are required to support
   //        performance optimization hacks in constraint solver.
 
-  bool isGenericOperatorOrUnavailable() const;
+  bool isGenericOperator() const;
   bool isSymmetricOperator() const;
 
   /// \brief Apply given choice to the system and try to solve it.
   Optional<Score> solve(SmallVectorImpl<Solution> &solutions,
                         FreeTypeVariableBinding allowFreeTypeVariables);
 
+  operator Constraint *() { return Choice; }
+
 private:
   /// \brief If associated disjunction is an explicit conversion,
   /// let's try to propagate its type early to prune search space.
   void propagateConversionInfo() const;
 
-  static ValueDecl *getOperatorDecl(Constraint *constraint) {
+  ValueDecl *getOperatorDecl() const {
+    auto *decl = getDecl(Choice);
+    if (!decl)
+      return nullptr;
+
+    return decl->isOperator() ? decl : nullptr;
+  }
+
+  static ValueDecl *getDecl(Constraint *constraint) {
     if (constraint->getKind() != ConstraintKind::BindOverload)
       return nullptr;
 
@@ -3277,8 +3289,7 @@
     if (choice.getKind() != OverloadChoiceKind::Decl)
       return nullptr;
 
-    auto *decl = choice.getDecl();
-    return decl->isOperator() ? decl : nullptr;
+    return choice.getDecl();
   }
 };
 
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index 66c8a94..03cbff2 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -768,6 +768,7 @@
   }
 
   encodeDecl->setInterfaceType(interfaceType);
+  encodeDecl->setValidationStarted();
   encodeDecl->setAccess(target->getFormalAccess());
 
   // If the type was not imported, the derived conformance is either from the
@@ -1109,6 +1110,7 @@
   }
 
   initDecl->setInterfaceType(interfaceType);
+  initDecl->setValidationStarted();
   initDecl->setInitializerInterfaceType(initializerType);
   initDecl->setAccess(target->getFormalAccess());
 
diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp
index f2e673b..c79da29 100644
--- a/lib/Sema/DerivedConformanceCodingKey.cpp
+++ b/lib/Sema/DerivedConformanceCodingKey.cpp
@@ -181,6 +181,7 @@
   initDecl->setInterfaceType(allocIfaceType);
   initDecl->setInitializerInterfaceType(initIfaceType);
   initDecl->setAccess(enumDecl->getFormalAccess());
+  initDecl->setValidationStarted();
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index abf95b5..ee00f46 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -671,6 +671,7 @@
   }
   eqDecl->setInterfaceType(interfaceTy);
   eqDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
+  eqDecl->setValidationStarted();
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
@@ -1062,6 +1063,7 @@
                                       AnyFunctionType::ExtInfo());
 
   getterDecl->setInterfaceType(interfaceType);
+  getterDecl->setValidationStarted();
   getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   // If the enum was not imported, the derived conformance is either from the
@@ -1073,6 +1075,7 @@
   // Finish creating the property.
   hashValueDecl->setImplicit();
   hashValueDecl->setInterfaceType(intType);
+  hashValueDecl->setValidationStarted();
   hashValueDecl->makeComputed(SourceLoc(), getterDecl,
                               nullptr, nullptr, SourceLoc());
   hashValueDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index d6222f6..a8ca15e 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -344,6 +344,7 @@
   initDecl->setInterfaceType(allocIfaceType);
   initDecl->setInitializerInterfaceType(initIfaceType);
   initDecl->copyFormalAccessAndVersionedAttrFrom(enumDecl);
+  initDecl->setValidationStarted();
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 22d063d..667ef2c 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -281,6 +281,7 @@
                                       FunctionType::ExtInfo());
   getterDecl->setInterfaceType(interfaceType);
   getterDecl->copyFormalAccessAndVersionedAttrFrom(property);
+  getterDecl->setValidationStarted();
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
@@ -308,6 +309,7 @@
   propDecl->setImplicit();
   propDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
   propDecl->setInterfaceType(propertyInterfaceType);
+  propDecl->setValidationStarted();
 
   // If this is supposed to be a final property, mark it as such.
   assert(isFinal || !parentDC->getAsClassOrClassExtensionContext());
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index d6f9f77..ddf04b2 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -3981,23 +3981,24 @@
 
   /// Retrieve a replacement identifier.
   auto getReplacementIdentifier = [&](StringRef name,
-                                      Identifier old) -> Identifier{
+                                      DeclBaseName old) -> DeclBaseName{
     if (name.empty())
       return Identifier();
 
-    if (!old.empty() && name == old.str())
+    if (!old.empty() && name == old.userFacingName())
       return old;
 
     return Context.getIdentifier(name);
   };
 
-  Identifier newBaseName = getReplacementIdentifier(baseNameStr,
-                                                    name.getBaseIdentifier());
+  auto newBaseName = getReplacementIdentifier(
+      baseNameStr, name.getBaseName());
   SmallVector<Identifier, 4> newArgNames;
   auto oldArgNames = name.getArgumentNames();
   for (unsigned i = 0, n = argNameStrs.size(); i != n; ++i) {
-    newArgNames.push_back(getReplacementIdentifier(argNameStrs[i],
-                                                   oldArgNames[i]));
+    auto argBaseName = getReplacementIdentifier(argNameStrs[i],
+                                                oldArgNames[i]);
+    newArgNames.push_back(argBaseName.getIdentifier());
   }
 
   return DeclName(Context, newBaseName, newArgNames);
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index fe32aa5..a654ec6 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -2816,25 +2816,6 @@
   return (kind != CheckedCastKind::Unresolved);
 }
 
-bool TypeChecker::isSubstitutableFor(Type type, ArchetypeType *archetype,
-                                     DeclContext *dc) {
-  if (archetype->requiresClass() && !type->satisfiesClassConstraint())
-    return false;
-
-  if (auto superclass = archetype->getSuperclass()) {
-    if (!superclass->isExactSuperclassOf(type))
-      return false;
-  }
-
-  for (auto proto : archetype->getConformsTo()) {
-    if (!dc->getParentModule()->lookupConformance(
-          type, proto))
-      return false;
-  }
-
-  return true;
-}
-
 Expr *TypeChecker::coerceToRValue(Expr *expr,
                                llvm::function_ref<Type(Expr *)> getType,
                                llvm::function_ref<void(Expr *, Type)> setType) {
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 36eb687..4d451f2 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -921,8 +921,11 @@
     if (!conflicting(currentSig, otherSig))
       continue;
 
-    // Validate the declaration.
-    tc.validateDecl(other);
+    // Validate the declaration but only if it came from a different context.
+    if (other->getDeclContext() != current->getDeclContext())
+      tc.validateDecl(other);
+
+    // Skip invalid or not yet seen declarations.
     if (other->isInvalid() || !other->hasInterfaceType())
       continue;
 
@@ -3954,10 +3957,9 @@
   // second pass over the global scope (or neither, if we're in a context where
   // we only visit each decl once).
   unsigned IsFirstPass : 1;
-  unsigned IsSecondPass : 1;
 
-  DeclChecker(TypeChecker &TC, bool IsFirstPass, bool IsSecondPass)
-      : TC(TC), IsFirstPass(IsFirstPass), IsSecondPass(IsSecondPass) {}
+  DeclChecker(TypeChecker &TC, bool IsFirstPass)
+      : TC(TC), IsFirstPass(IsFirstPass) {}
 
   void visit(Decl *decl) {
     FrontendStatsTracer StatsTracer(TC.Context.Stats, "typecheck-decl", decl);
@@ -4149,7 +4151,7 @@
 
     TC.checkDeclAttributesEarly(PBD);
 
-    if (!IsSecondPass) {
+    if (IsFirstPass) {
       for (unsigned i = 0, e = PBD->getNumPatternEntries(); i != e; ++i) {
         // Type check each VarDecl that this PatternBinding handles.
         visitBoundVars(PBD->getPattern(i));
@@ -4218,7 +4220,7 @@
 
         // Non-member observing properties need an initializer.
         if (var->getStorageKind() == VarDecl::StoredWithObservers &&
-            !isTypeContext) {
+            !isTypeContext && !var->isInvalid() && !PBD->isInvalid()) {
           TC.diagnose(var->getLoc(), diag::observingprop_requires_initializer);
           PBD->setInvalid();
           var->setInvalid();
@@ -4258,150 +4260,51 @@
       });
     }
 
-    if (!IsFirstPass)
-      checkAccessControl(TC, PBD);
-
     TC.checkDeclAttributes(PBD);
+
+    if (IsFirstPass)
+      checkAccessControl(TC, PBD);
   }
 
   void visitSubscriptDecl(SubscriptDecl *SD) {
-    if (IsSecondPass) {
-      checkAccessControl(TC, SD);
+    if (!IsFirstPass) {
       return;
     }
 
-    if (SD->hasInterfaceType() || SD->isBeingValidated())
-      return;
-
-    SD->setIsBeingValidated();
-
-    auto dc = SD->getDeclContext();
-
-    if (auto gp = SD->getGenericParams()) {
-      // Write up generic parameters and check the generic parameter list.
-      gp->setOuterParameters(dc->getGenericParamsOfContext());
-
-      auto *sig = TC.validateGenericSubscriptSignature(SD);
-      auto *env = sig->createGenericEnvironment();
-      SD->setGenericEnvironment(env);
-
-      // Revert the types within the signature so it can be type-checked with
-      // archetypes below.
-      TC.revertGenericSubscriptSignature(SD);
-    } else if (dc->getGenericSignatureOfContext()) {
-      (void)TC.validateGenericSubscriptSignature(SD);
-
-      // Revert all of the types within the signature of the subscript.
-      TC.revertGenericSubscriptSignature(SD);
-
-      SD->setGenericEnvironment(
-          SD->getDeclContext()->getGenericEnvironmentOfContext());
-    }
-
-    // Type check the subscript parameters.
-    GenericTypeToArchetypeResolver resolver(SD);
-
-    bool isInvalid = TC.validateType(SD->getElementTypeLoc(), SD,
-                                     TypeResolutionFlags::AllowIUO,
-                                     &resolver);
-    TypeResolutionOptions options;
-    options |= TypeResolutionFlags::SubscriptParameters;
-
-    isInvalid |= TC.typeCheckParameterList(SD->getIndices(), SD,
-                                           options,
-                                           resolver);
-
-    if (isInvalid || SD->isInvalid()) {
-      SD->setInterfaceType(ErrorType::get(TC.Context));
-      SD->setInvalid();
-    } else {
-      if (!SD->getGenericSignatureOfContext())
-        TC.configureInterfaceType(SD, SD->getGenericSignature());
-    }
-
-    SD->setIsBeingValidated(false);
-
-    TC.checkDeclAttributesEarly(SD);
-    TC.computeAccessLevel(SD);
-
-    validateAttributes(TC, SD);
-
-    auto *TyR = SD->getElementTypeLoc().getTypeRepr();
-    if (TyR && TyR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional) {
-      auto &C = SD->getASTContext();
-      SD->getAttrs().add(
-          new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
-    }
-
-    if (!checkOverrides(TC, SD)) {
-      // If a subscript has an override attribute but does not override
-      // anything, complain.
-      if (auto *OA = SD->getAttrs().getAttribute<OverrideAttr>()) {
-        if (!SD->getOverriddenDecl()) {
-          TC.diagnose(SD, diag::subscript_does_not_override)
-              .highlight(OA->getLocation());
-          OA->setInvalid();
-        }
-      }
-    }
-
-    // Member subscripts need some special validation logic.
-    if (auto nominalDecl = dc->getAsNominalTypeOrNominalTypeExtensionContext()) {
-      // If this is a class member, mark it final if the class is final.
-      if (auto cls = dyn_cast<ClassDecl>(nominalDecl)) {
-        if (cls->isFinal() && !SD->isFinal()) {
-          makeFinal(TC.Context, SD);
-        }
-      }
-
-      // A subscript is ObjC-compatible if it's explicitly @objc, or a
-      // member of an ObjC-compatible class or protocol.
-      Optional<ObjCReason> isObjC = shouldMarkAsObjC(TC, SD);
-
-      if (isObjC && !TC.isRepresentableInObjC(SD, *isObjC))
-        isObjC = None;
-      markAsObjC(TC, SD, isObjC);
-
-      // Infer 'dynamic' before touching accessors.
-      inferDynamic(TC.Context, SD);
-    }
-
-    // Perform accessor-related validation.
-    validateAbstractStorageDecl(TC, SD);
-
-    // If this is a get+mutableAddress property, synthesize the setter body.
-    if (SD->getStorageKind() == SubscriptDecl::ComputedWithMutableAddress &&
-        !SD->getSetter()->getBody()) {
-      synthesizeSetterForMutableAddressedStorage(SD, TC);
-    }
-
+    TC.validateDecl(SD);
     TC.checkDeclAttributes(SD);
+    checkAccessControl(TC, SD);
   }
 
   void visitTypeAliasDecl(TypeAliasDecl *TAD) {
+    if (!IsFirstPass) {
+      return;
+    }
+
     TC.checkDeclAttributesEarly(TAD);
     TC.computeAccessLevel(TAD);
 
-    if (!IsSecondPass)
-      TC.validateDecl(TAD);
-
-    if (IsSecondPass)
-      checkAccessControl(TC, TAD);
-
+    TC.validateDecl(TAD);
     TC.checkDeclAttributes(TAD);
+    checkAccessControl(TC, TAD);
   }
   
-  void visitAssociatedTypeDecl(AssociatedTypeDecl *assocType) {
-    if (!assocType->hasValidationStarted())
-      TC.validateDecl(assocType);
+  void visitAssociatedTypeDecl(AssociatedTypeDecl *AT) {
+    if (!IsFirstPass) {
+      return;
+    }
 
-    auto *proto = assocType->getProtocol();
+    TC.validateDecl(AT);
+
+    auto *proto = AT->getProtocol();
     if (proto->isObjC()) {
-      TC.diagnose(assocType->getLoc(),
+      TC.diagnose(AT->getLoc(),
                   diag::associated_type_objc,
-                  assocType->getName(),
+                  AT->getName(),
                   proto->getName());
     }
+
+    checkAccessControl(TC, AT);
   }
 
   void checkUnsupportedNestedType(NominalTypeDecl *NTD) {
@@ -4453,7 +4356,7 @@
     TC.checkDeclAttributesEarly(ED);
     TC.computeAccessLevel(ED);
 
-    if (!IsSecondPass) {
+    if (IsFirstPass) {
       checkUnsupportedNestedType(ED);
 
       TC.validateDecl(ED);
@@ -4467,28 +4370,6 @@
         checkCircularity(TC, ED, diag::circular_enum_inheritance,
                          diag::enum_here, path);
       }
-      {
-        // Check for duplicate enum members.
-        llvm::DenseMap<Identifier, EnumElementDecl *> Elements;
-        bool hasErrors = false;
-        for (auto *EED : ED->getAllElements()) {
-          auto Res = Elements.insert({ EED->getName(), EED });
-          if (!Res.second) {
-            EED->setInvalid();
-
-            auto PreviousEED = Res.first->second;
-            TC.diagnose(EED->getLoc(), diag::duplicate_enum_element);
-            TC.diagnose(PreviousEED->getLoc(),
-                        diag::previous_decldef, true, EED->getName());
-            hasErrors = true;
-          }
-        }
-
-        // If one of the cases is invalid, let's mark
-        // whole enum as invalid as well.
-        if (hasErrors)
-          ED->setInvalid();
-      }
     }
 
     if (!IsFirstPass) {
@@ -4502,7 +4383,7 @@
 
       TC.checkConformancesInContext(ED, ED);
     }
-    
+
     for (Decl *member : ED->getMembers())
       visit(member);
     
@@ -4511,29 +4392,31 @@
   }
 
   void visitStructDecl(StructDecl *SD) {
+    if (!IsFirstPass) {
+      for (Decl *Member : SD->getMembers())
+        visit(Member);
+
+      return;
+    }
+
     TC.checkDeclAttributesEarly(SD);
     TC.computeAccessLevel(SD);
 
-    if (!IsSecondPass) {
-      checkUnsupportedNestedType(SD);
+    checkUnsupportedNestedType(SD);
 
-      TC.validateDecl(SD);
-      TC.DeclsToFinalize.remove(SD);
-      TC.addImplicitConstructors(SD);
-    }
+    TC.validateDecl(SD);
+    TC.DeclsToFinalize.remove(SD);
 
-    if (!IsFirstPass) {
-      checkAccessControl(TC, SD);
+    TC.addImplicitConstructors(SD);
 
-      if (!SD->isInvalid())
-        TC.checkConformancesInContext(SD, SD);
-    }
-
-    // Visit each of the members.
     for (Decl *Member : SD->getMembers())
       visit(Member);
 
     TC.checkDeclAttributes(SD);
+    checkAccessControl(TC, SD);
+
+    if (!SD->isInvalid())
+      TC.checkConformancesInContext(SD, SD);
   }
 
   /// Check whether the given properties can be @NSManaged in this class.
@@ -4643,7 +4526,7 @@
     TC.checkDeclAttributesEarly(CD);
     TC.computeAccessLevel(CD);
 
-    if (!IsSecondPass) {
+    if (IsFirstPass) {
       checkUnsupportedNestedType(CD);
 
       TC.validateDecl(CD);
@@ -4775,25 +4658,14 @@
   }
 
   void visitProtocolDecl(ProtocolDecl *PD) {
+    if (!IsFirstPass) {
+      return;
+    }
+
     TC.checkDeclAttributesEarly(PD);
     TC.computeAccessLevel(PD);
 
-    if (!IsSecondPass) {
-      checkUnsupportedNestedType(PD);
-    }
-
-    if (IsSecondPass) {
-      checkAccessControl(TC, PD);
-      for (auto member : PD->getMembers()) {
-        TC.checkUnsupportedProtocolType(member);
-        checkAccessControl(TC, member);
-      }
-      TC.checkInheritanceClause(PD);
-
-      GenericTypeToArchetypeResolver resolver(PD);
-      TC.validateWhereClauses(PD, &resolver);
-      return;
-    }
+    checkUnsupportedNestedType(PD);
 
     TC.validateDecl(PD);
     if (!PD->hasValidSignature())
@@ -4830,6 +4702,15 @@
 
     TC.checkDeclAttributes(PD);
 
+    checkAccessControl(TC, PD);
+    for (auto member : PD->getMembers()) {
+      TC.checkUnsupportedProtocolType(member);
+    }
+    TC.checkInheritanceClause(PD);
+
+    GenericTypeToArchetypeResolver resolver(PD);
+    TC.validateWhereClauses(PD, &resolver);
+
     if (TC.Context.LangOpts.DebugGenericSignatures) {
       auto requirementsSig =
         GenericSignature::get({PD->getProtocolSelfType()},
@@ -4859,181 +4740,6 @@
     // PatternBindingDecl.
   }
 
-  bool semaFuncParamPatterns(AbstractFunctionDecl *fd,
-                             GenericTypeResolver &resolver) {
-    bool hadError = false;
-    for (auto paramList : fd->getParameterLists()) {
-      hadError |= TC.typeCheckParameterList(paramList, fd,
-                                            TypeResolutionOptions(), resolver);
-    }
-
-    return hadError;
-  }
-
-  static TypeLoc getTypeLocForFunctionResult(FuncDecl *FD) {
-    auto accessor = dyn_cast<AccessorDecl>(FD);
-    if (!accessor) {
-      return FD->getBodyResultTypeLoc();
-    }
-
-    assert(accessor->isGetter());
-    auto *storage = accessor->getStorage();
-    assert(isa<VarDecl>(storage) || isa<SubscriptDecl>(storage));
-
-    if (auto *subscript = dyn_cast<SubscriptDecl>(storage))
-      return subscript->getElementTypeLoc();
-
-    return cast<VarDecl>(storage)->getTypeLoc();
-  }
-
-  bool semaFuncDecl(FuncDecl *FD, GenericTypeResolver &resolver) {
-    TC.checkForForbiddenPrefix(FD);
-
-    bool badType = false;
-    if (!FD->getBodyResultTypeLoc().isNull()) {
-      TypeResolutionOptions options = TypeResolutionFlags::AllowIUO;
-      if (FD->hasDynamicSelf())
-        options |= TypeResolutionFlags::DynamicSelfResult;
-
-      if (TC.validateType(FD->getBodyResultTypeLoc(), FD, options,
-                          &resolver)) {
-        badType = true;
-      }
-    }
-
-    badType |= semaFuncParamPatterns(FD, resolver);
-
-    if (badType) {
-      FD->setInterfaceType(ErrorType::get(TC.Context));
-      FD->setInvalid();
-      return true;
-    }
-
-    if (!isa<AccessorDecl>(FD) || cast<AccessorDecl>(FD)->isGetter()) {
-      auto *TyR = getTypeLocForFunctionResult(FD).getTypeRepr();
-      if (TyR && TyR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional) {
-        auto &C = FD->getASTContext();
-        FD->getAttrs().add(
-            new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
-      }
-    }
-
-    return false;
-  }
-
-  /// Bind the given function declaration, which declares an operator, to
-  /// the corresponding operator declaration.
-  void bindFuncDeclToOperator(FuncDecl *FD) {
-    OperatorDecl *op = nullptr;
-    auto operatorName = FD->getFullName().getBaseIdentifier();
-
-    // Check for static/final/class when we're in a type.
-    auto dc = FD->getDeclContext();
-    if (dc->isTypeContext()) {
-      if (!FD->isStatic()) {
-        TC.diagnose(FD->getLoc(), diag::nonstatic_operator_in_type,
-                    operatorName,
-                    dc->getDeclaredInterfaceType())
-          .fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
-                       "static ");
-
-        FD->setStatic();
-      } else if (auto classDecl = dc->getAsClassOrClassExtensionContext()) {
-        // For a class, we also need the function or class to be 'final'.
-        if (!classDecl->isFinal() && !FD->isFinal() &&
-            FD->getStaticSpelling() != StaticSpellingKind::KeywordStatic) {
-          TC.diagnose(FD->getLoc(), diag::nonfinal_operator_in_class,
-                      operatorName, dc->getDeclaredInterfaceType())
-            .fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
-                         "final ");
-          FD->getAttrs().add(new (TC.Context) FinalAttr(/*IsImplicit=*/true));
-        }
-      }
-    } else if (!dc->isModuleScopeContext()) {
-      TC.diagnose(FD, diag::operator_in_local_scope);
-    }
-
-    SourceFile &SF = *FD->getDeclContext()->getParentSourceFile();
-    if (FD->isUnaryOperator()) {
-      if (FD->getAttrs().hasAttribute<PrefixAttr>()) {
-        op = SF.lookupPrefixOperator(operatorName,
-                                     FD->isCascadingContextForLookup(false),
-                                     FD->getLoc());
-      } else if (FD->getAttrs().hasAttribute<PostfixAttr>()) {
-        op = SF.lookupPostfixOperator(operatorName,
-                                      FD->isCascadingContextForLookup(false),
-                                      FD->getLoc());
-      } else {
-        auto prefixOp =
-            SF.lookupPrefixOperator(operatorName,
-                                    FD->isCascadingContextForLookup(false),
-                                    FD->getLoc());
-        auto postfixOp =
-            SF.lookupPostfixOperator(operatorName,
-                                     FD->isCascadingContextForLookup(false),
-                                     FD->getLoc());
-
-        // If we found both prefix and postfix, or neither prefix nor postfix,
-        // complain. We can't fix this situation.
-        if (static_cast<bool>(prefixOp) == static_cast<bool>(postfixOp)) {
-          TC.diagnose(FD, diag::declared_unary_op_without_attribute);
-
-          // If we found both, point at them.
-          if (prefixOp) {
-            TC.diagnose(prefixOp, diag::unary_operator_declaration_here, false)
-              .fixItInsert(FD->getLoc(), "prefix ");
-            TC.diagnose(postfixOp, diag::unary_operator_declaration_here, true)
-              .fixItInsert(FD->getLoc(), "postfix ");
-          } else {
-            // FIXME: Introduce a Fix-It that adds the operator declaration?
-          }
-
-          // FIXME: Errors could cascade here, because name lookup for this
-          // operator won't find this declaration.
-          return;
-        }
-
-        // We found only one operator declaration, so we know whether this
-        // should be a prefix or a postfix operator.
-
-        // Fix the AST and determine the insertion text.
-        const char *insertionText;
-        auto &C = FD->getASTContext();
-        if (postfixOp) {
-          insertionText = "postfix ";
-          op = postfixOp;
-          FD->getAttrs().add(new (C) PostfixAttr(/*implicit*/false));
-        } else {
-          insertionText = "prefix ";
-          op = prefixOp;
-          FD->getAttrs().add(new (C) PrefixAttr(/*implicit*/false));
-        }
-
-        // Emit diagnostic with the Fix-It.
-        TC.diagnose(FD->getFuncLoc(), diag::unary_op_missing_prepos_attribute,
-                    static_cast<bool>(postfixOp))
-          .fixItInsert(FD->getFuncLoc(), insertionText);
-        TC.diagnose(op, diag::unary_operator_declaration_here,
-                    static_cast<bool>(postfixOp));
-      }
-    } else if (FD->isBinaryOperator()) {
-      op = SF.lookupInfixOperator(operatorName,
-                                  FD->isCascadingContextForLookup(false),
-                                  FD->getLoc());
-    } else {
-      TC.diagnose(FD, diag::invalid_arg_count_for_operator);
-      return;
-    }
-
-    if (!op) {
-      // FIXME: Add Fix-It introducing an operator declaration?
-      TC.diagnose(FD, diag::declared_operator_without_operator_decl);
-      return;
-    }
-
-    FD->setOperatorDecl(op);
-  }
-
   /// Determine whether the given declaration requires a definition.
   ///
   /// Only valid for declarations that can have definitions, i.e.,
@@ -5062,110 +4768,6 @@
     return true;
   }
 
-  /// Check for methods that return 'DynamicResult'.
-  bool checkDynamicSelfReturn(FuncDecl *func) {
-    // Check whether we have a specified result type.
-    auto typeRepr = func->getBodyResultTypeLoc().getTypeRepr();
-    if (!typeRepr)
-      return false;
-
-    // 'Self' on a free function is not dynamic 'Self'.
-    if (!func->getDeclContext()->getAsClassOrClassExtensionContext() &&
-        !isa<ProtocolDecl>(func->getDeclContext()))
-      return false;
-
-    // 'Self' on a property accessor is not dynamic 'Self'...even on a read-only
-    // property. We could implement it as such in the future.
-    if (isa<AccessorDecl>(func))
-      return false;
-
-    return checkDynamicSelfReturn(func, typeRepr, 0);
-  }
-
-  bool checkDynamicSelfReturn(FuncDecl *func, TypeRepr *typeRepr,
-                              unsigned optionalDepth) {
-    // Look through parentheses.
-    if (auto parenRepr = dyn_cast<TupleTypeRepr>(typeRepr)) {
-      if (!parenRepr->isParenType()) return false;
-      return checkDynamicSelfReturn(func, parenRepr->getElementType(0),
-                                    optionalDepth);
-    }
-
-    // Look through attributes.
-    if (auto attrRepr = dyn_cast<AttributedTypeRepr>(typeRepr)) {
-      TypeAttributes attrs = attrRepr->getAttrs();
-      if (!attrs.empty())
-        return false;
-      return checkDynamicSelfReturn(func, attrRepr->getTypeRepr(),
-                                    optionalDepth);
-    }
-
-    // Look through optional types.
-    TypeRepr *base = nullptr;
-    if (auto *optRepr = dyn_cast<OptionalTypeRepr>(typeRepr))
-      base = optRepr->getBase();
-    else if (auto *optRepr =
-                 dyn_cast<ImplicitlyUnwrappedOptionalTypeRepr>(typeRepr))
-      base = optRepr->getBase();
-
-    if (base) {
-      // But only one level.
-      if (optionalDepth != 0) return false;
-      return checkDynamicSelfReturn(func, base, optionalDepth + 1);
-    }
-
-    // Check whether we have a simple identifier type.
-    auto simpleRepr = dyn_cast<SimpleIdentTypeRepr>(typeRepr);
-    if (!simpleRepr)
-      return false;
-
-    // Check whether it is 'Self'.
-    if (simpleRepr->getIdentifier() != TC.Context.Id_Self)
-      return false;
-
-    // Note that the function has a dynamic Self return type and set
-    // the return type component to the dynamic self type.
-    func->setDynamicSelf(true);
-    return false;
-  }
-
-  void checkMemberOperator(FuncDecl *FD) {
-    // Check that member operators reference the type of 'Self'.
-    if (FD->getNumParameterLists() != 2 || FD->isInvalid()) return;
-
-    auto *DC = FD->getDeclContext();
-    auto selfNominal = DC->getAsNominalTypeOrNominalTypeExtensionContext();
-    if (!selfNominal) return;
-
-    // Check the parameters for a reference to 'Self'.
-    bool isProtocol = isa<ProtocolDecl>(selfNominal);
-    for (auto param : *FD->getParameterList(1)) {
-      auto paramType = param->getInterfaceType();
-      if (!paramType) break;
-
-      // Look through 'inout'.
-      paramType = paramType->getInOutObjectType();
-      // Look through a metatype reference, if there is one.
-      if (auto metatypeType = paramType->getAs<AnyMetatypeType>())
-        paramType = metatypeType->getInstanceType();
-
-      // Is it the same nominal type?
-      if (paramType->getAnyNominal() == selfNominal) return;
-
-      if (isProtocol) {
-        // For a protocol, is it the 'Self' type parameter?
-        if (auto genericParam = paramType->getAs<GenericTypeParamType>())
-          if (genericParam->isEqual(DC->getSelfInterfaceType()))
-            return;
-      }
-    }
-
-    // We did not find 'Self'. Complain.
-    TC.diagnose(FD, diag::operator_in_unrelated_type,
-                FD->getDeclContext()->getDeclaredInterfaceType(),
-                isProtocol, FD->getFullName());
-  }
-
   void visitFuncDecl(FuncDecl *FD) {
     if (!IsFirstPass) {
       if (FD->hasBody()) {
@@ -5175,361 +4777,14 @@
         // Complain if we should have a body.
         TC.diagnose(FD->getLoc(), diag::func_decl_without_brace);
       }
-    }
 
-    if (IsSecondPass) {
-      checkAccessControl(TC, FD);
       return;
     }
 
-    TC.checkDeclAttributesEarly(FD);
-    TC.computeAccessLevel(FD);
-
-    if (FD->hasInterfaceType() || FD->isBeingValidated())
-      return;
-
-    FD->setIsBeingValidated();
-
-    SWIFT_DEFER {
-      assert(FD->hasInterfaceType() && "didn't assign interface type");
-    };
-
-    // Bind operator functions to the corresponding operator declaration.
-    if (FD->isOperator())
-      bindFuncDeclToOperator(FD);
-
-    // Validate 'static'/'class' on functions in extensions.
-    auto StaticSpelling = FD->getStaticSpelling();
-    if (StaticSpelling != StaticSpellingKind::None &&
-        FD->getDeclContext()->isExtensionContext()) {
-      if (auto *NTD = FD->getDeclContext()
-              ->getAsNominalTypeOrNominalTypeExtensionContext()) {
-        if (!isa<ClassDecl>(NTD)) {
-          if (StaticSpelling == StaticSpellingKind::KeywordClass) {
-            TC.diagnose(FD, diag::class_func_not_in_class)
-                .fixItReplace(FD->getStaticLoc(), "static");
-            TC.diagnose(NTD, diag::extended_type_declared_here);
-          }
-        }
-      }
-    }
-
-    validateSelfAccessKind(TC, FD);
-
-    // Check whether the return type is dynamic 'Self'.
-    if (checkDynamicSelfReturn(FD))
-      FD->setInvalid();
-
-    // Accessors should pick up various parts of their type signatures
-    // directly from the storage declaration instead of re-deriving them.
-    // FIXME: should this include the generic signature?
-    if (auto accessor = dyn_cast<AccessorDecl>(FD)) {
-      auto storage = accessor->getStorage();
-      TC.validateDecl(storage);
-
-      // Note that it's important for correctness that we're filling in
-      // empty TypeLocs, because otherwise revertGenericFuncSignature might
-      // erase the types we set, causing them to be re-validated in a later
-      // pass.  That later validation might be incorrect even if the TypeLocs
-      // are a clone of the type locs from which we derived the value type,
-      // because the rules for interpreting types in parameter contexts
-      // are sometimes different from the rules elsewhere; for example,
-      // function types default to non-escaping.
-
-      auto valueParams =
-        accessor->getParameterList(accessor->getParent()->isTypeContext());
-
-      // Determine the value type.
-      Type valueIfaceTy, valueTy;
-      if (auto VD = dyn_cast<VarDecl>(storage)) {
-        valueIfaceTy = VD->getInterfaceType()->getReferenceStorageReferent();
-        valueTy = VD->getType()->getReferenceStorageReferent();
-      } else {
-        auto SD = cast<SubscriptDecl>(storage);
-        valueIfaceTy = SD->getElementInterfaceType();
-        valueTy = SD->mapTypeIntoContext(valueIfaceTy);
-
-        // Copy the index types instead of re-validating them.
-        auto indices = SD->getIndices();
-        for (size_t i = 0, e = indices->size(); i != e; ++i) {
-          auto subscriptParam = indices->get(i);
-          if (!subscriptParam->hasInterfaceType())
-            continue;
-
-          Type paramIfaceTy = subscriptParam->getInterfaceType();
-          Type paramTy = SD->mapTypeIntoContext(paramIfaceTy);
-
-          auto accessorParam = valueParams->get(valueParams->size() - e + i);
-          accessorParam->setType(paramTy);
-          accessorParam->setInterfaceType(paramIfaceTy);
-          accessorParam->getTypeLoc().setType(paramTy);
-        }
-      }
-
-      // Propagate the value type into the correct position.
-      switch (accessor->getAccessorKind()) {
-      // For getters, set the result type to the value type.
-      case AccessorKind::IsGetter:
-        accessor->getBodyResultTypeLoc().setType(valueIfaceTy, true);
-        break;
-
-      // For setters and observers, set the old/new value parameter's type
-      // to the value type.
-      case AccessorKind::IsDidSet:
-      case AccessorKind::IsWillSet:
-      case AccessorKind::IsSetter: {
-        auto newValueParam = valueParams->get(0);
-        newValueParam->setType(valueTy);
-        newValueParam->setInterfaceType(valueIfaceTy);
-        newValueParam->getTypeLoc().setType(valueTy);
-        break;
-      }
-
-      // Addressor result types can get complicated because of the owner.
-      case AccessorKind::IsAddressor:
-      case AccessorKind::IsMutableAddressor:
-        if (Type resultType =
-              buildAddressorResultType(accessor, valueIfaceTy)) {
-          accessor->getBodyResultTypeLoc().setType(resultType, true);
-        }
-        break;
-
-      // These don't mention the value types directly.
-      case AccessorKind::IsMaterializeForSet:
-        break;
-      }
-    }
-
-    // Before anything else, set up the 'self' argument correctly if present.
-    if (FD->getDeclContext()->isTypeContext())
-      configureImplicitSelf(TC, FD);
-
-    // If we have generic parameters, check the generic signature now.
-    if (auto gp = FD->getGenericParams()) {
-      gp->setOuterParameters(FD->getDeclContext()->getGenericParamsOfContext());
-
-      auto *sig = TC.validateGenericFuncSignature(FD);
-
-      GenericEnvironment *env;
-      if (auto AD = dyn_cast<AccessorDecl>(FD)) {
-        env = cast<SubscriptDecl>(AD->getStorage())->getGenericEnvironment();
-        assert(env && "accessor has generics but subscript is not generic");
-      } else {
-        env = sig->createGenericEnvironment();
-      }
-      FD->setGenericEnvironment(env);
-
-      // Revert the types within the signature so it can be type-checked with
-      // archetypes below.
-      TC.revertGenericFuncSignature(FD);
-    } else if (auto genericSig =
-                 FD->getDeclContext()->getGenericSignatureOfContext()) {
-      if (!isa<AccessorDecl>(FD)) {
-        (void)TC.validateGenericFuncSignature(FD);
-
-        // Revert all of the types within the signature of the function.
-        TC.revertGenericFuncSignature(FD);
-      } else {
-        // We've inherited all of the type information already.
-        TC.configureInterfaceType(FD, genericSig);
-      }
-
-      FD->setGenericEnvironment(
-          FD->getDeclContext()->getGenericEnvironmentOfContext());
-    }
-
-    // Set the context type of 'self'.
-    if (FD->getDeclContext()->isTypeContext())
-      recordSelfContextType(FD);
-
-    // Type check the parameters and return type again, now with archetypes.
-    GenericTypeToArchetypeResolver resolver(FD);
-    if (semaFuncDecl(FD, resolver)) {
-      FD->setIsBeingValidated(false);
-      return;
-    }
-
-    if (!FD->getGenericSignatureOfContext())
-      TC.configureInterfaceType(FD, FD->getGenericSignature());
-
-    // We want the function to be available for name lookup as soon
-    // as it has a valid interface type.
-    FD->setIsBeingValidated(false);
-
-    if (FD->isInvalid())
-      return;
-
-    validateAttributes(TC, FD);
-
-    // Member functions need some special validation logic.
-    if (FD->getDeclContext()->isTypeContext()) {
-      if (!checkOverrides(TC, FD)) {
-        // If a method has an 'override' keyword but does not
-        // override anything, complain.
-        if (auto *OA = FD->getAttrs().getAttribute<OverrideAttr>()) {
-          if (!FD->getOverriddenDecl()) {
-            TC.diagnose(FD, diag::method_does_not_override)
-              .highlight(OA->getLocation());
-            OA->setInvalid();
-          }
-        }
-      }
-
-      if (FD->isOperator())
-        checkMemberOperator(FD);
-
-      Optional<ObjCReason> isObjC = shouldMarkAsObjC(TC, FD);
-      auto accessor = dyn_cast<AccessorDecl>(FD);
-
-      auto *protocolContext = dyn_cast<ProtocolDecl>(
-          FD->getDeclContext());
-      if (protocolContext && accessor) {
-        if (isObjC)
-          isObjC = ObjCReason::Accessor;
-      }
-
-      if (accessor && accessor->isGetterOrSetter()) {
-        // If the property decl is an instance property, its accessors will
-        // be instance methods and the above condition will mark them ObjC.
-        // The only additional condition we need to check is if the var decl
-        // had an @objc or @iboutlet property.
-
-        AbstractStorageDecl *storage = accessor->getStorage();
-        // Validate the subscript or property because it might not be type
-        // checked yet.
-        TC.validateDecl(storage);
-
-        if (storage->getAttrs().hasAttribute<NonObjCAttr>())
-          isObjC = None;
-        else if (storage->isObjC()) {
-          if (!isObjC) {
-            // Make this accessor @objc because its property is @objc.
-            isObjC = ObjCReason::Accessor;
-          } else {
-            // If @objc on the storage declaration was inferred using a
-            // deprecated rule, but this accessor is @objc in its own right,
-            // complain.
-            auto storageObjCAttr = storage->getAttrs().getAttribute<ObjCAttr>();
-            if (storageObjCAttr->isSwift3Inferred() &&
-                shouldDiagnoseObjCReason(*isObjC, TC.Context)) {
-              TC.diagnose(storage, diag::accessor_swift3_objc_inference,
-                          storage->getDescriptiveKind(), storage->getFullName(),
-                          isa<SubscriptDecl>(storage), accessor->isSetter())
-                .fixItInsert(storage->getAttributeInsertionLoc(
-                                                      /*forModifier=*/false),
-                             "@objc ");
-            }
-          }
-        }
-
-        // If the storage is dynamic or final, propagate to this accessor.
-        if (isObjC &&
-            storage->isDynamic())
-          makeDynamic(TC.Context, FD);
-
-        if (storage->isFinal())
-          makeFinal(TC.Context, FD);
-      }
-
-      Optional<ForeignErrorConvention> errorConvention;
-      if (isObjC &&
-          (FD->isInvalid() || !TC.isRepresentableInObjC(FD, *isObjC,
-                                                        errorConvention)))
-        isObjC = None;
-      markAsObjC(TC, FD, isObjC, errorConvention);
-    }
-    
-    // If the function is exported to C, it must be representable in (Obj-)C.
-    if (auto CDeclAttr = FD->getAttrs().getAttribute<swift::CDeclAttr>()) {
-      Optional<ForeignErrorConvention> errorConvention;
-      if (TC.isRepresentableInObjC(FD, ObjCReason::ExplicitlyCDecl,
-                                   errorConvention)) {
-        if (FD->hasThrows()) {
-          FD->setForeignErrorConvention(*errorConvention);
-          TC.diagnose(CDeclAttr->getLocation(), diag::cdecl_throws);
-        }
-      }
-    }
-    
-    inferDynamic(TC.Context, FD);
-
-    TC.checkDeclAttributes(FD);
-
-    // If this is a class member, mark it final if the class is final.
-    if (auto cls = FD->getDeclContext()->getAsClassOrClassExtensionContext()) {
-      if (cls->isFinal() && !FD->isFinal()) {
-        makeFinal(TC.Context, FD);
-      }
-      // static func declarations in classes are synonyms
-      // for `class final func` declarations.
-      if (FD->getStaticSpelling() == StaticSpellingKind::KeywordStatic) {
-        auto finalAttr = FD->getAttrs().getAttribute<FinalAttr>();
-        if (finalAttr) {
-          auto finalRange = finalAttr->getRange();
-          if (finalRange.isValid())
-            TC.diagnose(finalRange.Start, diag::decl_already_final)
-            .highlight(finalRange)
-            .fixItRemove(finalRange);
-        }
-        makeFinal(TC.Context, FD);
-      }
-    }
+    TC.validateDecl(FD);
+    checkAccessControl(TC, FD);
   }
 
-  Type buildAddressorResultType(AccessorDecl *addressor, Type valueType) {
-    assert(addressor->getAccessorKind() == AccessorKind::IsAddressor ||
-           addressor->getAccessorKind() == AccessorKind::IsMutableAddressor);
-
-    Type pointerType =
-      (addressor->getAccessorKind() == AccessorKind::IsAddressor)
-        ? TC.getUnsafePointerType(addressor->getLoc(), valueType)
-        : TC.getUnsafeMutablePointerType(addressor->getLoc(), valueType);
-    if (!pointerType) return Type();
-
-    switch (addressor->getAddressorKind()) {
-    case AddressorKind::NotAddressor:
-      llvm_unreachable("addressor without addressor kind");
-
-    // For unsafe addressors, it's just the pointer type.
-    case AddressorKind::Unsafe:
-      return pointerType;
-
-    // For non-native owning addressors, the return type is actually
-    //   (Unsafe{,Mutable}Pointer<T>, AnyObject)
-    case AddressorKind::Owning: {
-      TupleTypeElt elts[] = {
-        pointerType,
-        TC.Context.getAnyObjectType()
-      };
-      return TupleType::get(elts, TC.Context);
-    }
-
-    // For native owning addressors, the return type is actually
-    //   (Unsafe{,Mutable}Pointer<T>, Builtin.NativeObject)
-    case AddressorKind::NativeOwning: {
-      TupleTypeElt elts[] = {
-        pointerType,
-        TC.Context.TheNativeObjectType
-      };
-      return TupleType::get(elts, TC.Context);
-    }
-
-    // For native pinning addressors, the return type is actually
-    //   (Unsafe{,Mutable}Pointer<T>, Builtin.NativeObject?)
-    case AddressorKind::NativePinning: {
-      Type pinTokenType =
-        TC.getOptionalType(addressor->getLoc(), TC.Context.TheNativeObjectType);
-      if (!pinTokenType) return Type();
-
-      TupleTypeElt elts[] = {
-        pointerType,
-        pinTokenType
-      };
-      return TupleType::get(elts, TC.Context);
-    }
-    }
-    llvm_unreachable("bad addressor kind");
-  }
 
   void visitModuleDecl(ModuleDecl *) { }
 
@@ -5580,17 +4835,17 @@
     // Determine the input and result types of this function.
     auto fnType = type->castTo<AnyFunctionType>();
     Type inputType = fnType->getInput();
-    Type resultType = dropResultOptionality(fnType->getResult(), 
+    Type resultType = dropResultOptionality(fnType->getResult(),
                                             uncurryLevel - 1);
-    
+
     // Produce the resulting function type.
     if (auto genericFn = dyn_cast<GenericFunctionType>(fnType)) {
       return GenericFunctionType::get(genericFn->getGenericSignature(),
                                       inputType, resultType,
                                       fnType->getExtInfo());
     }
-    
-    return FunctionType::get(inputType, resultType, fnType->getExtInfo());    
+
+    return FunctionType::get(inputType, resultType, fnType->getExtInfo());
   }
 
   static bool
@@ -6930,153 +6185,93 @@
   }
 
   void visitEnumElementDecl(EnumElementDecl *EED) {
-    if (IsSecondPass) {
-      checkAccessControl(TC, EED);
+    if (!IsFirstPass) {
       return;
     }
-    if (EED->hasInterfaceType() || EED->isBeingValidated())
-      return;
-    
-    TC.checkDeclAttributesEarly(EED);
-    TC.validateAccessControl(EED);
 
-    // Only attempt to validate the argument type or raw value if the element
-    // is not currently being validated.
-    if (EED->getRecursiveness() == ElementRecursiveness::NotRecursive) {
-      EED->setRecursiveness(ElementRecursiveness::PotentiallyRecursive);
-      
-      validateAttributes(TC, EED);
-      
-      if (!EED->getArgumentTypeLoc().isNull()) {
-        if (TC.validateType(EED->getArgumentTypeLoc(), EED->getDeclContext(),
-                            TypeResolutionFlags::EnumCase)) {
-          EED->setInterfaceType(ErrorType::get(TC.Context));
-          EED->setInvalid();
-          return;
-        }
-      }
-
-      // If we have a raw value, make sure there's a raw type as well.
-      if (auto *rawValue = EED->getRawValueExpr()) {
-        EnumDecl *ED = EED->getParentEnum();
-        if (!ED->hasRawType()) {
-          TC.diagnose(rawValue->getLoc(),diag::enum_raw_value_without_raw_type);
-          // Recover by setting the raw type as this element's type.
-          Expr *typeCheckedExpr = rawValue;
-          if (!TC.typeCheckExpression(typeCheckedExpr, ED)) {
-            EED->setTypeCheckedRawValueExpr(typeCheckedExpr);
-            TC.checkEnumElementErrorHandling(EED);
-          }
-        } else {
-          // Wait until the second pass, when all the raw value expressions
-          // can be checked together.
-        }
-      }
-    } else if (EED->getRecursiveness() ==
-                ElementRecursiveness::PotentiallyRecursive) {
-      EED->setRecursiveness(ElementRecursiveness::Recursive);
-    }
-    
-    // If the element was not already marked as recursive by a re-entrant call,
-    // we can be sure it's not recursive.
-    if (EED->getRecursiveness() == ElementRecursiveness::PotentiallyRecursive) {
-      EED->setRecursiveness(ElementRecursiveness::NotRecursive);
-    }
-
-    // Now that we have an argument type we can set the element's declared
-    // type.
-    if (!EED->hasInterfaceType() && !EED->computeType())
-      return;
-
-    // Require the carried type to be materializable.
-    if (auto argTy = EED->getArgumentInterfaceType()) {
-      assert(!argTy->hasLValueType() && "enum element cannot carry @lvalue");
-      
-      if (!argTy->isMaterializable()) {
-        TC.diagnose(EED->getLoc(), diag::enum_element_not_materializable, argTy);
-        EED->setInterfaceType(ErrorType::get(TC.Context));
-        EED->setInvalid();
-      }
-    }
+    TC.validateDecl(EED);
     TC.checkDeclAttributes(EED);
+    checkAccessControl(TC, EED);
   }
 
   void visitExtensionDecl(ExtensionDecl *ED) {
+    if (!IsFirstPass) {
+      for (Decl *Member : ED->getMembers())
+        visit(Member);
+      return;
+    }
+
     TC.validateExtension(ED);
 
     TC.checkDeclAttributesEarly(ED);
 
-    if (!IsSecondPass) {
-      if (auto extendedTy = ED->getExtendedType()) {
-        if (!extendedTy->is<NominalType>() &&
-            !extendedTy->is<BoundGenericType>() &&
-            !extendedTy->hasError()) {
-          // FIXME: Redundant diagnostic test here?
-          TC.diagnose(ED->getStartLoc(), diag::non_nominal_extension,
-                      extendedTy);
-          // FIXME: It would be nice to point out where we found the named type
-          // declaration, if any.
-          ED->setInvalid();
-        }
+    if (auto extendedTy = ED->getExtendedType()) {
+      if (!extendedTy->is<NominalType>() &&
+          !extendedTy->is<BoundGenericType>() &&
+          !extendedTy->hasError()) {
+        // FIXME: Redundant diagnostic test here?
+        TC.diagnose(ED->getStartLoc(), diag::non_nominal_extension,
+                    extendedTy);
+        // FIXME: It would be nice to point out where we found the named type
+        // declaration, if any.
+        ED->setInvalid();
       }
-
-      TC.checkInheritanceClause(ED);
-      if (auto extendedTy = ED->getExtendedType()) {
-        if (auto nominal = extendedTy->getAnyNominal()) {
-          TC.validateDecl(nominal);
-          if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
-            TC.requestNominalLayout(classDecl);
-
-          // Check the raw values of an enum, since we might synthesize
-          // RawRepresentable while checking conformances on this extension.
-          if (auto enumDecl = dyn_cast<EnumDecl>(nominal)) {
-            if (enumDecl->hasRawType())
-              checkEnumRawValues(TC, enumDecl);
-          }
-        }
-      }
-
-      validateAttributes(TC, ED);
     }
 
-    // Check conformances before visiting members, since we might
-    // synthesize bodies for derived conformances
-    if (!IsFirstPass) {
-      TC.computeDefaultAccessLevel(ED);
-      if (auto *AA = ED->getAttrs().getAttribute<AccessControlAttr>()) {
-        const auto access = AA->getAccess();
-        AccessScope desiredAccessScope = AccessScope::getPublic();
-        switch (access) {
-        case AccessLevel::Private:
-          assert((ED->isInvalid() ||
-                  ED->getDeclContext()->isModuleScopeContext()) &&
-                 "non-top-level extensions make 'private' != 'fileprivate'");
-          LLVM_FALLTHROUGH;
-        case AccessLevel::FilePrivate: {
-          const DeclContext *DC = ED->getModuleScopeContext();
-          bool isPrivate = access == AccessLevel::Private;
-          desiredAccessScope = AccessScope(DC, isPrivate);
-          break;
+    TC.checkInheritanceClause(ED);
+    if (auto extendedTy = ED->getExtendedType()) {
+      if (auto nominal = extendedTy->getAnyNominal()) {
+        TC.validateDecl(nominal);
+        if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
+          TC.requestNominalLayout(classDecl);
+
+        // Check the raw values of an enum, since we might synthesize
+        // RawRepresentable while checking conformances on this extension.
+        if (auto enumDecl = dyn_cast<EnumDecl>(nominal)) {
+          if (enumDecl->hasRawType())
+            checkEnumRawValues(TC, enumDecl);
         }
-        case AccessLevel::Internal:
-          desiredAccessScope = AccessScope(ED->getModuleContext());
-          break;
-        case AccessLevel::Public:
-        case AccessLevel::Open:
-          break;
-        }
-        checkGenericParamAccess(TC, ED->getGenericParams(), ED,
-                                desiredAccessScope, access);
       }
-      TC.checkConformancesInContext(ED, ED);
     }
 
+    validateAttributes(TC, ED);
+
+    TC.computeDefaultAccessLevel(ED);
+
     for (Decl *Member : ED->getMembers())
       visit(Member);
 
+    TC.checkConformancesInContext(ED, ED);
+
     if (!ED->isInvalid())
       TC.checkDeclAttributes(ED);
- }
+
+    if (auto *AA = ED->getAttrs().getAttribute<AccessControlAttr>()) {
+      const auto access = AA->getAccess();
+      AccessScope desiredAccessScope = AccessScope::getPublic();
+      switch (access) {
+      case AccessLevel::Private:
+        assert((ED->isInvalid() ||
+                ED->getDeclContext()->isModuleScopeContext()) &&
+               "non-top-level extensions make 'private' != 'fileprivate'");
+        LLVM_FALLTHROUGH;
+      case AccessLevel::FilePrivate: {
+        const DeclContext *DC = ED->getModuleScopeContext();
+        bool isPrivate = access == AccessLevel::Private;
+        desiredAccessScope = AccessScope(DC, isPrivate);
+        break;
+      }
+      case AccessLevel::Internal:
+        desiredAccessScope = AccessScope(ED->getModuleContext());
+        break;
+      case AccessLevel::Public:
+      case AccessLevel::Open:
+        break;
+      }
+      checkGenericParamAccess(TC, ED->getGenericParams(), ED,
+                              desiredAccessScope, access);
+    }
+  }
 
   void visitTopLevelCodeDecl(TopLevelCodeDecl *TLCD) {
     // See swift::performTypeChecking for TopLevelCodeDecl handling.
@@ -7109,178 +6304,11 @@
       }
     }
 
-    if (IsSecondPass) {
-      checkAccessControl(TC, CD);
+    if (!IsFirstPass) {
       return;
     }
-    if (CD->hasInterfaceType() || CD->isBeingValidated())
-      return;
 
-    CD->setIsBeingValidated();
-
-    TC.checkDeclAttributesEarly(CD);
-    TC.computeAccessLevel(CD);
-
-    // convenience initializers are only allowed on classes and in
-    // extensions thereof.
-    if (CD->isConvenienceInit()) {
-      if (auto extType = CD->getDeclContext()->getDeclaredInterfaceType()) {
-        auto extClass = extType->getClassOrBoundGenericClass();
-
-        // Forbid convenience inits on Foreign CF types, as Swift does not yet
-        // support user-defined factory inits.
-        if (extClass &&
-            extClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType) {
-          TC.diagnose(CD->getLoc(), diag::cfclass_convenience_init);
-        }
-
-        if (!extClass && !extType->hasError()) {
-          auto ConvenienceLoc =
-            CD->getAttrs().getAttribute<ConvenienceAttr>()->getLocation();
-
-          // Produce a tailored diagnostic for structs and enums.
-          bool isStruct = extType->getStructOrBoundGenericStruct() != nullptr;
-          if (isStruct || extType->getEnumOrBoundGenericEnum()) {
-            TC.diagnose(CD->getLoc(), diag::enumstruct_convenience_init,
-                        isStruct ? "structs" : "enums")
-              .fixItRemove(ConvenienceLoc);
-          } else {
-            TC.diagnose(CD->getLoc(), diag::nonclass_convenience_init, extType)
-              .fixItRemove(ConvenienceLoc);
-          }
-          CD->setInitKind(CtorInitializerKind::Designated);
-        }
-      }
-    } else if (auto extType = CD->getDeclContext()->getDeclaredInterfaceType()) {
-      // A designated initializer for a class must be written within the class
-      // itself.
-      //
-      // This is because designated initializers of classes get a vtable entry,
-      // and extensions cannot add vtable entries to the extended type.
-      //
-      // If we implement the ability for extensions defined in the same module
-      // (or the same file) to add vtable entries, we can re-evaluate this
-      // restriction.
-      if (extType->getClassOrBoundGenericClass() &&
-          isa<ExtensionDecl>(CD->getDeclContext())) {
-        TC.diagnose(CD->getLoc(), diag::designated_init_in_extension, extType)
-          .fixItInsert(CD->getLoc(), "convenience ");
-        CD->setInitKind(CtorInitializerKind::Convenience);
-      } else if (CD->getDeclContext()->getAsProtocolExtensionContext()) {
-        CD->setInitKind(CtorInitializerKind::Convenience);
-      }
-    }
-
-    if (CD->getDeclContext()->isTypeContext())
-      configureImplicitSelf(TC, CD);
-
-    if (auto gp = CD->getGenericParams()) {
-      // Write up generic parameters and check the generic parameter list.
-      gp->setOuterParameters(CD->getDeclContext()->getGenericParamsOfContext());
-
-      auto *sig = TC.validateGenericFuncSignature(CD);
-      auto *env = sig->createGenericEnvironment();
-      CD->setGenericEnvironment(env);
-
-      // Revert the types within the signature so it can be type-checked with
-      // archetypes below.
-      TC.revertGenericFuncSignature(CD);
-    } else if (CD->getDeclContext()->getGenericSignatureOfContext()) {
-      (void)TC.validateGenericFuncSignature(CD);
-
-      // Revert all of the types within the signature of the constructor.
-      TC.revertGenericFuncSignature(CD);
-
-      CD->setGenericEnvironment(
-          CD->getDeclContext()->getGenericEnvironmentOfContext());
-    }
-
-    // Set the context type of 'self'.
-    if (CD->getDeclContext()->isTypeContext())
-      recordSelfContextType(CD);
-
-    // Type check the constructor parameters.
-    GenericTypeToArchetypeResolver resolver(CD);
-    if (semaFuncParamPatterns(CD, resolver) || CD->isInvalid()) {
-      CD->setInterfaceType(ErrorType::get(TC.Context));
-      CD->setInvalid();
-    } else {
-      if (!CD->getGenericSignatureOfContext())
-        TC.configureInterfaceType(CD, CD->getGenericSignature());
-    }
-
-    // We want the constructor to be available for name lookup as soon
-    // as it has a valid interface type.
-    CD->setIsBeingValidated(false);
-
-    validateAttributes(TC, CD);
-
-    // Check whether this initializer overrides an initializer in its
-    // superclass.
-    if (!checkOverrides(TC, CD)) {
-      // If an initializer has an override attribute but does not override
-      // anything or overrides something that doesn't need an 'override'
-      // keyword (e.g., a convenience initializer), complain.
-      // anything, or overrides something that complain.
-      if (auto *attr = CD->getAttrs().getAttribute<OverrideAttr>()) {
-        if (!CD->getOverriddenDecl()) {
-          TC.diagnose(CD, diag::initializer_does_not_override)
-            .highlight(attr->getLocation());
-          attr->setInvalid();
-        } else if (!overrideRequiresKeyword(CD->getOverriddenDecl())) {
-          // Special case: we are overriding a 'required' initializer, so we
-          // need (only) the 'required' keyword.
-          if (cast<ConstructorDecl>(CD->getOverriddenDecl())->isRequired()) {
-            if (CD->getAttrs().hasAttribute<RequiredAttr>()) {
-              TC.diagnose(CD, diag::required_initializer_override_keyword)
-                .fixItRemove(attr->getLocation());
-            } else {
-              TC.diagnose(CD, diag::required_initializer_override_wrong_keyword)
-                .fixItReplace(attr->getLocation(), "required");
-              CD->getAttrs().add(
-                new (TC.Context) RequiredAttr(/*IsImplicit=*/true));
-            }
-
-            TC.diagnose(findNonImplicitRequiredInit(CD->getOverriddenDecl()),
-                        diag::overridden_required_initializer_here);
-          } else {
-            // We tried to override a convenience initializer.
-            TC.diagnose(CD, diag::initializer_does_not_override)
-              .highlight(attr->getLocation());
-            TC.diagnose(CD->getOverriddenDecl(),
-                        diag::convenience_init_override_here);
-          }
-        }
-      }
-
-      // A failable initializer cannot override a non-failable one.
-      // This would normally be diagnosed by the covariance rules;
-      // however, those are disabled so that we can provide a more
-      // specific diagnostic here.
-      if (CD->getFailability() != OTK_None &&
-          CD->getOverriddenDecl() &&
-          CD->getOverriddenDecl()->getFailability() == OTK_None) {
-        TC.diagnose(CD, diag::failable_initializer_override,
-                    CD->getFullName());
-        TC.diagnose(CD->getOverriddenDecl(), 
-                    diag::nonfailable_initializer_override_here,
-                    CD->getOverriddenDecl()->getFullName());
-      }
-    }
-
-    // An initializer is ObjC-compatible if it's explicitly @objc or a member
-    // of an ObjC-compatible class.
-    if (CD->getDeclContext()->isTypeContext()) {
-      Optional<ObjCReason> isObjC = shouldMarkAsObjC(TC, CD,
-          /*allowImplicit=*/true);
-
-      Optional<ForeignErrorConvention> errorConvention;
-      if (isObjC &&
-          (CD->isInvalid() ||
-           !TC.isRepresentableInObjC(CD, *isObjC, errorConvention)))
-        isObjC = None;
-      markAsObjC(TC, CD, isObjC, errorConvention);
-    }
+    TC.validateDecl(CD);
 
     // If this initializer overrides a 'required' initializer, it must itself
     // be marked 'required'.
@@ -7322,74 +6350,19 @@
       }
     }
 
-    inferDynamic(TC.Context, CD);
-
-    if (CD->getFailability() == OTK_ImplicitlyUnwrappedOptional) {
-      auto &C = CD->getASTContext();
-      CD->getAttrs().add(
-          new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
-    }
-
     TC.checkDeclAttributes(CD);
+    checkAccessControl(TC, CD);
   }
 
   void visitDestructorDecl(DestructorDecl *DD) {
-    auto enclosingClass = dyn_cast<ClassDecl>(DD->getDeclContext());
-    if (DD->isInvalid() ||
-        enclosingClass == nullptr) {
-      DD->setInterfaceType(ErrorType::get(TC.Context));
-      DD->setInvalid();
-      return;
-    }
-
     if (!IsFirstPass) {
       if (DD->getBody())
         TC.definedFunctions.push_back(DD);
-    }
 
-    if (IsSecondPass ||
-        DD->hasInterfaceType() ||
-        DD->isBeingValidated()) {
       return;
     }
 
-    DD->setIsBeingValidated();
-
-    assert(DD->getDeclContext()->isTypeContext()
-           && "Decl parsing must prevent destructors outside of types!");
-
-    TC.checkDeclAttributesEarly(DD);
-    DD->copyFormalAccessAndVersionedAttrFrom(enclosingClass);
-
-    configureImplicitSelf(TC, DD);
-
-    if (DD->getDeclContext()->getGenericSignatureOfContext()) {
-      (void)TC.validateGenericFuncSignature(DD);
-      DD->setGenericEnvironment(
-          DD->getDeclContext()->getGenericEnvironmentOfContext());
-    }
-
-    // Set the context type of 'self'.
-    recordSelfContextType(DD);
-
-    GenericTypeToArchetypeResolver resolver(DD);
-    if (semaFuncParamPatterns(DD, resolver)) {
-      DD->setInterfaceType(ErrorType::get(TC.Context));
-      DD->setInvalid();
-    }
-
-    if (!DD->getGenericSignatureOfContext())
-      TC.configureInterfaceType(DD, DD->getGenericSignature());
-
-    DD->setIsBeingValidated(false);
-
-    // Do this before markAsObjC() to diagnose @nonobjc better
-    validateAttributes(TC, DD);
-
-    // Destructors are always @objc, because their Objective-C entry point is
-    // -dealloc.
-    markAsObjC(TC, DD, ObjCReason::ImplicitlyObjC);
-
+    TC.validateDecl(DD);
     TC.checkDeclAttributes(DD);
   }
 };
@@ -7457,9 +6430,7 @@
 
 void TypeChecker::typeCheckDecl(Decl *D, bool isFirstPass) {
   checkForForbiddenPrefix(D);
-  bool isSecondPass =
-    !isFirstPass && D->getDeclContext()->isModuleScopeContext();
-  DeclChecker(*this, isFirstPass, isSecondPass).visit(D);
+  DeclChecker(*this, isFirstPass).visit(D);
 }
 
 // A class is @objc if it does not have generic ancestry, and it either has
@@ -7522,6 +6493,298 @@
   }
 }
 
+
+/// Bind the given function declaration, which declares an operator, to
+/// the corresponding operator declaration.
+void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) {
+  OperatorDecl *op = nullptr;
+  auto operatorName = FD->getFullName().getBaseIdentifier();
+
+  // Check for static/final/class when we're in a type.
+  auto dc = FD->getDeclContext();
+  if (dc->isTypeContext()) {
+    if (!FD->isStatic()) {
+      TC.diagnose(FD->getLoc(), diag::nonstatic_operator_in_type,
+                  operatorName,
+                  dc->getDeclaredInterfaceType())
+        .fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
+                     "static ");
+
+      FD->setStatic();
+    } else if (auto classDecl = dc->getAsClassOrClassExtensionContext()) {
+      // For a class, we also need the function or class to be 'final'.
+      if (!classDecl->isFinal() && !FD->isFinal() &&
+          FD->getStaticSpelling() != StaticSpellingKind::KeywordStatic) {
+        TC.diagnose(FD->getLoc(), diag::nonfinal_operator_in_class,
+                    operatorName, dc->getDeclaredInterfaceType())
+          .fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
+                       "final ");
+        FD->getAttrs().add(new (TC.Context) FinalAttr(/*IsImplicit=*/true));
+      }
+    }
+  } else if (!dc->isModuleScopeContext()) {
+    TC.diagnose(FD, diag::operator_in_local_scope);
+  }
+
+  SourceFile &SF = *FD->getDeclContext()->getParentSourceFile();
+  if (FD->isUnaryOperator()) {
+    if (FD->getAttrs().hasAttribute<PrefixAttr>()) {
+      op = SF.lookupPrefixOperator(operatorName,
+                                   FD->isCascadingContextForLookup(false),
+                                   FD->getLoc());
+    } else if (FD->getAttrs().hasAttribute<PostfixAttr>()) {
+      op = SF.lookupPostfixOperator(operatorName,
+                                    FD->isCascadingContextForLookup(false),
+                                    FD->getLoc());
+    } else {
+      auto prefixOp =
+          SF.lookupPrefixOperator(operatorName,
+                                  FD->isCascadingContextForLookup(false),
+                                  FD->getLoc());
+      auto postfixOp =
+          SF.lookupPostfixOperator(operatorName,
+                                   FD->isCascadingContextForLookup(false),
+                                   FD->getLoc());
+
+      // If we found both prefix and postfix, or neither prefix nor postfix,
+      // complain. We can't fix this situation.
+      if (static_cast<bool>(prefixOp) == static_cast<bool>(postfixOp)) {
+        TC.diagnose(FD, diag::declared_unary_op_without_attribute);
+
+        // If we found both, point at them.
+        if (prefixOp) {
+          TC.diagnose(prefixOp, diag::unary_operator_declaration_here, false)
+            .fixItInsert(FD->getLoc(), "prefix ");
+          TC.diagnose(postfixOp, diag::unary_operator_declaration_here, true)
+            .fixItInsert(FD->getLoc(), "postfix ");
+        } else {
+          // FIXME: Introduce a Fix-It that adds the operator declaration?
+        }
+
+        // FIXME: Errors could cascade here, because name lookup for this
+        // operator won't find this declaration.
+        return;
+      }
+
+      // We found only one operator declaration, so we know whether this
+      // should be a prefix or a postfix operator.
+
+      // Fix the AST and determine the insertion text.
+      const char *insertionText;
+      auto &C = FD->getASTContext();
+      if (postfixOp) {
+        insertionText = "postfix ";
+        op = postfixOp;
+        FD->getAttrs().add(new (C) PostfixAttr(/*implicit*/false));
+      } else {
+        insertionText = "prefix ";
+        op = prefixOp;
+        FD->getAttrs().add(new (C) PrefixAttr(/*implicit*/false));
+      }
+
+      // Emit diagnostic with the Fix-It.
+      TC.diagnose(FD->getFuncLoc(), diag::unary_op_missing_prepos_attribute,
+                  static_cast<bool>(postfixOp))
+        .fixItInsert(FD->getFuncLoc(), insertionText);
+      TC.diagnose(op, diag::unary_operator_declaration_here,
+                  static_cast<bool>(postfixOp));
+    }
+  } else if (FD->isBinaryOperator()) {
+    op = SF.lookupInfixOperator(operatorName,
+                                FD->isCascadingContextForLookup(false),
+                                FD->getLoc());
+  } else {
+    TC.diagnose(FD, diag::invalid_arg_count_for_operator);
+    return;
+  }
+
+  if (!op) {
+    // FIXME: Add Fix-It introducing an operator declaration?
+    TC.diagnose(FD, diag::declared_operator_without_operator_decl);
+    return;
+  }
+
+  FD->setOperatorDecl(op);
+}
+
+void checkMemberOperator(TypeChecker &TC, FuncDecl *FD) {
+  // Check that member operators reference the type of 'Self'.
+  if (FD->getNumParameterLists() != 2 || FD->isInvalid()) return;
+
+  auto *DC = FD->getDeclContext();
+  auto selfNominal = DC->getAsNominalTypeOrNominalTypeExtensionContext();
+  if (!selfNominal) return;
+
+  // Check the parameters for a reference to 'Self'.
+  bool isProtocol = isa<ProtocolDecl>(selfNominal);
+  for (auto param : *FD->getParameterList(1)) {
+    auto paramType = param->getInterfaceType();
+    if (!paramType) break;
+
+    // Look through 'inout'.
+    paramType = paramType->getInOutObjectType();
+    // Look through a metatype reference, if there is one.
+    if (auto metatypeType = paramType->getAs<AnyMetatypeType>())
+      paramType = metatypeType->getInstanceType();
+
+    // Is it the same nominal type?
+    if (paramType->getAnyNominal() == selfNominal) return;
+
+    if (isProtocol) {
+      // For a protocol, is it the 'Self' type parameter?
+      if (auto genericParam = paramType->getAs<GenericTypeParamType>())
+        if (genericParam->isEqual(DC->getSelfInterfaceType()))
+          return;
+    }
+  }
+
+  // We did not find 'Self'. Complain.
+  TC.diagnose(FD, diag::operator_in_unrelated_type,
+              FD->getDeclContext()->getDeclaredInterfaceType(),
+              isProtocol, FD->getFullName());
+}
+
+bool checkDynamicSelfReturn(TypeChecker &TC, FuncDecl *func,
+                            TypeRepr *typeRepr,
+                            unsigned optionalDepth) {
+  // Look through parentheses.
+  if (auto parenRepr = dyn_cast<TupleTypeRepr>(typeRepr)) {
+    if (!parenRepr->isParenType()) return false;
+    return checkDynamicSelfReturn(TC, func, parenRepr->getElementType(0),
+                                  optionalDepth);
+  }
+
+  // Look through attributes.
+  if (auto attrRepr = dyn_cast<AttributedTypeRepr>(typeRepr)) {
+    TypeAttributes attrs = attrRepr->getAttrs();
+    if (!attrs.empty())
+      return false;
+    return checkDynamicSelfReturn(TC, func, attrRepr->getTypeRepr(),
+                                  optionalDepth);
+  }
+
+  // Look through optional types.
+  TypeRepr *base = nullptr;
+  if (auto *optRepr = dyn_cast<OptionalTypeRepr>(typeRepr))
+    base = optRepr->getBase();
+  else if (auto *optRepr =
+               dyn_cast<ImplicitlyUnwrappedOptionalTypeRepr>(typeRepr))
+    base = optRepr->getBase();
+
+  if (base) {
+    // But only one level.
+    if (optionalDepth != 0) return false;
+    return checkDynamicSelfReturn(TC, func, base, optionalDepth + 1);
+  }
+
+  // Check whether we have a simple identifier type.
+  auto simpleRepr = dyn_cast<SimpleIdentTypeRepr>(typeRepr);
+  if (!simpleRepr)
+    return false;
+
+  // Check whether it is 'Self'.
+  if (simpleRepr->getIdentifier() != TC.Context.Id_Self)
+    return false;
+
+  // Note that the function has a dynamic Self return type and set
+  // the return type component to the dynamic self type.
+  func->setDynamicSelf(true);
+  return false;
+}
+
+/// Check for methods that return 'DynamicResult'.
+bool checkDynamicSelfReturn(TypeChecker &TC, FuncDecl *func) {
+  // Check whether we have a specified result type.
+  auto typeRepr = func->getBodyResultTypeLoc().getTypeRepr();
+  if (!typeRepr)
+    return false;
+
+  // 'Self' on a free function is not dynamic 'Self'.
+  if (!func->getDeclContext()->getAsClassOrClassExtensionContext() &&
+      !isa<ProtocolDecl>(func->getDeclContext()))
+    return false;
+
+  // 'Self' on a property accessor is not dynamic 'Self'...even on a read-only
+  // property. We could implement it as such in the future.
+  if (isa<AccessorDecl>(func))
+    return false;
+
+  return checkDynamicSelfReturn(TC, func, typeRepr, 0);
+}
+
+Type buildAddressorResultType(TypeChecker &TC,
+                              AccessorDecl *addressor,
+                              Type valueType) {
+  assert(addressor->getAccessorKind() == AccessorKind::IsAddressor ||
+         addressor->getAccessorKind() == AccessorKind::IsMutableAddressor);
+
+  Type pointerType =
+    (addressor->getAccessorKind() == AccessorKind::IsAddressor)
+      ? TC.getUnsafePointerType(addressor->getLoc(), valueType)
+      : TC.getUnsafeMutablePointerType(addressor->getLoc(), valueType);
+  if (!pointerType) return Type();
+
+  switch (addressor->getAddressorKind()) {
+  case AddressorKind::NotAddressor:
+    llvm_unreachable("addressor without addressor kind");
+
+  // For unsafe addressors, it's just the pointer type.
+  case AddressorKind::Unsafe:
+    return pointerType;
+
+  // For non-native owning addressors, the return type is actually
+  //   (Unsafe{,Mutable}Pointer<T>, AnyObject)
+  case AddressorKind::Owning: {
+    TupleTypeElt elts[] = {
+      pointerType,
+      TC.Context.getAnyObjectType()
+    };
+    return TupleType::get(elts, TC.Context);
+  }
+
+  // For native owning addressors, the return type is actually
+  //   (Unsafe{,Mutable}Pointer<T>, Builtin.NativeObject)
+  case AddressorKind::NativeOwning: {
+    TupleTypeElt elts[] = {
+      pointerType,
+      TC.Context.TheNativeObjectType
+    };
+    return TupleType::get(elts, TC.Context);
+  }
+
+  // For native pinning addressors, the return type is actually
+  //   (Unsafe{,Mutable}Pointer<T>, Builtin.NativeObject?)
+  case AddressorKind::NativePinning: {
+    Type pinTokenType =
+      TC.getOptionalType(addressor->getLoc(), TC.Context.TheNativeObjectType);
+    if (!pinTokenType) return Type();
+
+    TupleTypeElt elts[] = {
+      pointerType,
+      pinTokenType
+    };
+    return TupleType::get(elts, TC.Context);
+  }
+  }
+  llvm_unreachable("bad addressor kind");
+}
+
+static TypeLoc getTypeLocForFunctionResult(FuncDecl *FD) {
+  auto accessor = dyn_cast<AccessorDecl>(FD);
+  if (!accessor) {
+    return FD->getBodyResultTypeLoc();
+  }
+
+  assert(accessor->isGetter());
+  auto *storage = accessor->getStorage();
+  assert(isa<VarDecl>(storage) || isa<SubscriptDecl>(storage));
+
+  if (auto *subscript = dyn_cast<SubscriptDecl>(storage))
+    return subscript->getElementTypeLoc();
+
+  return cast<VarDecl>(storage)->getTypeLoc();
+}
+
 void TypeChecker::validateDecl(ValueDecl *D) {
   // Generic parameters are validated as part of their context.
   if (isa<GenericTypeParamDecl>(D))
@@ -7720,8 +6983,13 @@
             validateAccessControl(aliasDecl);
 
             // Check generic parameters, if needed.
-            aliasDecl->setIsBeingValidated();
-            SWIFT_DEFER { aliasDecl->setIsBeingValidated(false); };
+            bool validated = aliasDecl->hasValidationStarted();
+            if (!validated)
+              aliasDecl->setIsBeingValidated();
+            SWIFT_DEFER {
+              if (!validated)
+                aliasDecl->setIsBeingValidated(false);
+            };
 
             validateTypealiasType(*this, aliasDecl);
           }
@@ -7900,12 +7168,719 @@
   }
 
   case DeclKind::Func:
-  case DeclKind::Accessor:
-  case DeclKind::Subscript:
-  case DeclKind::Constructor:
-  case DeclKind::Destructor:
+  case DeclKind::Accessor: {
+    auto *FD = cast<FuncDecl>(D);
+    assert(!FD->hasInterfaceType());
+
+    checkDeclAttributesEarly(FD);
+    computeAccessLevel(FD);
+
+    FD->setIsBeingValidated();
+
+    // Bind operator functions to the corresponding operator declaration.
+    if (FD->isOperator())
+      bindFuncDeclToOperator(*this, FD);
+
+    // Validate 'static'/'class' on functions in extensions.
+    auto StaticSpelling = FD->getStaticSpelling();
+    if (StaticSpelling != StaticSpellingKind::None &&
+        FD->getDeclContext()->isExtensionContext()) {
+      if (auto *NTD = FD->getDeclContext()
+              ->getAsNominalTypeOrNominalTypeExtensionContext()) {
+        if (!isa<ClassDecl>(NTD)) {
+          if (StaticSpelling == StaticSpellingKind::KeywordClass) {
+            diagnose(FD, diag::class_func_not_in_class)
+                .fixItReplace(FD->getStaticLoc(), "static");
+            diagnose(NTD, diag::extended_type_declared_here);
+          }
+        }
+      }
+    }
+
+    validateSelfAccessKind(*this, FD);
+
+    // Check whether the return type is dynamic 'Self'.
+    if (checkDynamicSelfReturn(*this, FD))
+      FD->setInvalid();
+
+    // Accessors should pick up various parts of their type signatures
+    // directly from the storage declaration instead of re-deriving them.
+    // FIXME: should this include the generic signature?
+    if (auto accessor = dyn_cast<AccessorDecl>(FD)) {
+      auto storage = accessor->getStorage();
+      validateDecl(storage);
+
+      // Note that it's important for correctness that we're filling in
+      // empty TypeLocs, because otherwise revertGenericFuncSignature might
+      // erase the types we set, causing them to be re-validated in a later
+      // pass.  That later validation might be incorrect even if the TypeLocs
+      // are a clone of the type locs from which we derived the value type,
+      // because the rules for interpreting types in parameter contexts
+      // are sometimes different from the rules elsewhere; for example,
+      // function types default to non-escaping.
+
+      auto valueParams =
+        accessor->getParameterList(accessor->getParent()->isTypeContext());
+
+      // Determine the value type.
+      Type valueIfaceTy, valueTy;
+      if (auto VD = dyn_cast<VarDecl>(storage)) {
+        valueIfaceTy = VD->getInterfaceType()->getReferenceStorageReferent();
+        valueTy = VD->getType()->getReferenceStorageReferent();
+      } else {
+        auto SD = cast<SubscriptDecl>(storage);
+        valueIfaceTy = SD->getElementInterfaceType();
+        valueTy = SD->mapTypeIntoContext(valueIfaceTy);
+
+        // Copy the index types instead of re-validating them.
+        auto indices = SD->getIndices();
+        for (size_t i = 0, e = indices->size(); i != e; ++i) {
+          auto subscriptParam = indices->get(i);
+          if (!subscriptParam->hasInterfaceType())
+            continue;
+
+          Type paramIfaceTy = subscriptParam->getInterfaceType();
+          Type paramTy = SD->mapTypeIntoContext(paramIfaceTy);
+
+          auto accessorParam = valueParams->get(valueParams->size() - e + i);
+          accessorParam->setType(paramTy);
+          accessorParam->setInterfaceType(paramIfaceTy);
+          accessorParam->getTypeLoc().setType(paramTy);
+        }
+      }
+
+      // Propagate the value type into the correct position.
+      switch (accessor->getAccessorKind()) {
+      // For getters, set the result type to the value type.
+      case AccessorKind::IsGetter:
+        accessor->getBodyResultTypeLoc().setType(valueIfaceTy, true);
+        break;
+
+      // For setters and observers, set the old/new value parameter's type
+      // to the value type.
+      case AccessorKind::IsDidSet:
+      case AccessorKind::IsWillSet:
+      case AccessorKind::IsSetter: {
+        auto newValueParam = valueParams->get(0);
+        newValueParam->setType(valueTy);
+        newValueParam->setInterfaceType(valueIfaceTy);
+        newValueParam->getTypeLoc().setType(valueTy);
+        break;
+      }
+
+      // Addressor result types can get complicated because of the owner.
+      case AccessorKind::IsAddressor:
+      case AccessorKind::IsMutableAddressor:
+        if (Type resultType =
+              buildAddressorResultType(*this, accessor, valueIfaceTy)) {
+          accessor->getBodyResultTypeLoc().setType(resultType, true);
+        }
+        break;
+
+      // These don't mention the value types directly.
+      case AccessorKind::IsMaterializeForSet:
+        break;
+      }
+    }
+
+    // Before anything else, set up the 'self' argument correctly if present.
+    if (FD->getDeclContext()->isTypeContext())
+      configureImplicitSelf(*this, FD);
+
+    // If we have generic parameters, check the generic signature now.
+    if (auto gp = FD->getGenericParams()) {
+      gp->setOuterParameters(FD->getDeclContext()->getGenericParamsOfContext());
+
+      auto *sig = validateGenericFuncSignature(FD);
+
+      GenericEnvironment *env;
+      if (auto AD = dyn_cast<AccessorDecl>(FD)) {
+        env = cast<SubscriptDecl>(AD->getStorage())->getGenericEnvironment();
+        assert(env && "accessor has generics but subscript is not generic");
+      } else {
+        env = sig->createGenericEnvironment();
+      }
+      FD->setGenericEnvironment(env);
+
+      // Revert the types within the signature so it can be type-checked with
+      // archetypes below.
+      revertGenericFuncSignature(FD);
+    } else if (auto genericSig =
+                 FD->getDeclContext()->getGenericSignatureOfContext()) {
+      if (!isa<AccessorDecl>(FD)) {
+        (void)validateGenericFuncSignature(FD);
+
+        // Revert all of the types within the signature of the function.
+        revertGenericFuncSignature(FD);
+      } else {
+        // We've inherited all of the type information already.
+        configureInterfaceType(FD, genericSig);
+      }
+
+      FD->setGenericEnvironment(
+          FD->getDeclContext()->getGenericEnvironmentOfContext());
+    }
+
+    // Set the context type of 'self'.
+    if (FD->getDeclContext()->isTypeContext())
+      recordSelfContextType(FD);
+
+    // Type check the parameters and return type again, now with archetypes.
+    GenericTypeToArchetypeResolver resolver(FD);
+
+    bool badType = false;
+    if (!FD->getBodyResultTypeLoc().isNull()) {
+      TypeResolutionOptions options = TypeResolutionFlags::AllowIUO;
+      if (FD->hasDynamicSelf())
+        options |= TypeResolutionFlags::DynamicSelfResult;
+
+      if (validateType(FD->getBodyResultTypeLoc(), FD, options,
+                       &resolver)) {
+        badType = true;
+      }
+    }
+
+    badType |= typeCheckParameterLists(FD, resolver);
+
+    if (badType) {
+      FD->setInterfaceType(ErrorType::get(Context));
+      FD->setInvalid();
+      FD->setIsBeingValidated(false);
+      break;
+    }
+
+    if (!isa<AccessorDecl>(FD) || cast<AccessorDecl>(FD)->isGetter()) {
+      auto *TyR = getTypeLocForFunctionResult(FD).getTypeRepr();
+      if (TyR && TyR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional) {
+        auto &C = FD->getASTContext();
+        FD->getAttrs().add(
+            new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
+      }
+    }
+
+    if (!FD->getGenericSignatureOfContext())
+      configureInterfaceType(FD, FD->getGenericSignature());
+
+    // We want the function to be available for name lookup as soon
+    // as it has a valid interface type.
+    FD->setIsBeingValidated(false);
+
+    if (FD->isInvalid())
+      break;
+
+    validateAttributes(*this, FD);
+
+    // Member functions need some special validation logic.
+    if (FD->getDeclContext()->isTypeContext()) {
+      if (!checkOverrides(*this, FD)) {
+        // If a method has an 'override' keyword but does not
+        // override anything, complain.
+        if (auto *OA = FD->getAttrs().getAttribute<OverrideAttr>()) {
+          if (!FD->getOverriddenDecl()) {
+            diagnose(FD, diag::method_does_not_override)
+              .highlight(OA->getLocation());
+            OA->setInvalid();
+          }
+        }
+      }
+
+      if (FD->isOperator())
+        checkMemberOperator(*this, FD);
+
+      Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, FD);
+      auto accessor = dyn_cast<AccessorDecl>(FD);
+
+      auto *protocolContext = dyn_cast<ProtocolDecl>(
+          FD->getDeclContext());
+      if (protocolContext && accessor) {
+        if (isObjC)
+          isObjC = ObjCReason::Accessor;
+      }
+
+      if (accessor && accessor->isGetterOrSetter()) {
+        // If the property decl is an instance property, its accessors will
+        // be instance methods and the above condition will mark them ObjC.
+        // The only additional condition we need to check is if the var decl
+        // had an @objc or @iboutlet property.
+
+        AbstractStorageDecl *storage = accessor->getStorage();
+        // Validate the subscript or property because it might not be type
+        // checked yet.
+        validateDecl(storage);
+
+        if (storage->getAttrs().hasAttribute<NonObjCAttr>())
+          isObjC = None;
+        else if (storage->isObjC()) {
+          if (!isObjC) {
+            // Make this accessor @objc because its property is @objc.
+            isObjC = ObjCReason::Accessor;
+          } else {
+            // If @objc on the storage declaration was inferred using a
+            // deprecated rule, but this accessor is @objc in its own right,
+            // complain.
+            auto storageObjCAttr = storage->getAttrs().getAttribute<ObjCAttr>();
+            if (storageObjCAttr->isSwift3Inferred() &&
+                shouldDiagnoseObjCReason(*isObjC, Context)) {
+              diagnose(storage, diag::accessor_swift3_objc_inference,
+                       storage->getDescriptiveKind(), storage->getFullName(),
+                       isa<SubscriptDecl>(storage), accessor->isSetter())
+                .fixItInsert(storage->getAttributeInsertionLoc(
+                                                      /*forModifier=*/false),
+                             "@objc ");
+            }
+          }
+        }
+
+        // If the storage is dynamic or final, propagate to this accessor.
+        if (isObjC &&
+            storage->isDynamic())
+          makeDynamic(Context, FD);
+
+        if (storage->isFinal())
+          makeFinal(Context, FD);
+      }
+
+      Optional<ForeignErrorConvention> errorConvention;
+      if (isObjC &&
+          (FD->isInvalid() || !isRepresentableInObjC(FD, *isObjC,
+                                                     errorConvention)))
+        isObjC = None;
+      markAsObjC(*this, FD, isObjC, errorConvention);
+    }
+
+    // If the function is exported to C, it must be representable in (Obj-)C.
+    if (auto CDeclAttr = FD->getAttrs().getAttribute<swift::CDeclAttr>()) {
+      Optional<ForeignErrorConvention> errorConvention;
+      if (isRepresentableInObjC(FD, ObjCReason::ExplicitlyCDecl,
+                                errorConvention)) {
+        if (FD->hasThrows()) {
+          FD->setForeignErrorConvention(*errorConvention);
+          diagnose(CDeclAttr->getLocation(), diag::cdecl_throws);
+        }
+      }
+    }
+
+    inferDynamic(Context, FD);
+
+    // If this is a class member, mark it final if the class is final.
+    if (auto cls = FD->getDeclContext()->getAsClassOrClassExtensionContext()) {
+      if (cls->isFinal() && !FD->isFinal()) {
+        makeFinal(Context, FD);
+      }
+      // static func declarations in classes are synonyms
+      // for `class final func` declarations.
+      if (FD->getStaticSpelling() == StaticSpellingKind::KeywordStatic) {
+        auto finalAttr = FD->getAttrs().getAttribute<FinalAttr>();
+        if (finalAttr) {
+          auto finalRange = finalAttr->getRange();
+          if (finalRange.isValid())
+            diagnose(finalRange.Start, diag::decl_already_final)
+              .highlight(finalRange)
+              .fixItRemove(finalRange);
+        }
+        makeFinal(Context, FD);
+      }
+    }
+
+    checkDeclAttributes(FD);
+
+    break;
+  }
+
+  case DeclKind::Constructor: {
+    auto *CD = cast<ConstructorDecl>(D);
+
+    CD->setIsBeingValidated();
+
+    checkDeclAttributesEarly(CD);
+    computeAccessLevel(CD);
+
+    // convenience initializers are only allowed on classes and in
+    // extensions thereof.
+    if (CD->isConvenienceInit()) {
+      if (auto extType = CD->getDeclContext()->getDeclaredInterfaceType()) {
+        auto extClass = extType->getClassOrBoundGenericClass();
+
+        // Forbid convenience inits on Foreign CF types, as Swift does not yet
+        // support user-defined factory inits.
+        if (extClass &&
+            extClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType) {
+          diagnose(CD->getLoc(), diag::cfclass_convenience_init);
+        }
+
+        if (!extClass && !extType->hasError()) {
+          auto ConvenienceLoc =
+            CD->getAttrs().getAttribute<ConvenienceAttr>()->getLocation();
+
+          // Produce a tailored diagnostic for structs and enums.
+          bool isStruct = extType->getStructOrBoundGenericStruct() != nullptr;
+          if (isStruct || extType->getEnumOrBoundGenericEnum()) {
+            diagnose(CD->getLoc(), diag::enumstruct_convenience_init,
+                     isStruct ? "structs" : "enums")
+              .fixItRemove(ConvenienceLoc);
+          } else {
+            diagnose(CD->getLoc(), diag::nonclass_convenience_init, extType)
+              .fixItRemove(ConvenienceLoc);
+          }
+          CD->setInitKind(CtorInitializerKind::Designated);
+        }
+      }
+    } else if (auto extType = CD->getDeclContext()->getDeclaredInterfaceType()) {
+      // A designated initializer for a class must be written within the class
+      // itself.
+      //
+      // This is because designated initializers of classes get a vtable entry,
+      // and extensions cannot add vtable entries to the extended type.
+      //
+      // If we implement the ability for extensions defined in the same module
+      // (or the same file) to add vtable entries, we can re-evaluate this
+      // restriction.
+      if (extType->getClassOrBoundGenericClass() &&
+          isa<ExtensionDecl>(CD->getDeclContext())) {
+        diagnose(CD->getLoc(), diag::designated_init_in_extension, extType)
+          .fixItInsert(CD->getLoc(), "convenience ");
+        CD->setInitKind(CtorInitializerKind::Convenience);
+      } else if (CD->getDeclContext()->getAsProtocolExtensionContext()) {
+        CD->setInitKind(CtorInitializerKind::Convenience);
+      }
+    }
+
+    if (CD->getDeclContext()->isTypeContext())
+      configureImplicitSelf(*this, CD);
+
+    if (auto gp = CD->getGenericParams()) {
+      // Write up generic parameters and check the generic parameter list.
+      gp->setOuterParameters(CD->getDeclContext()->getGenericParamsOfContext());
+
+      auto *sig = validateGenericFuncSignature(CD);
+      auto *env = sig->createGenericEnvironment();
+      CD->setGenericEnvironment(env);
+
+      // Revert the types within the signature so it can be type-checked with
+      // archetypes below.
+      revertGenericFuncSignature(CD);
+    } else if (CD->getDeclContext()->getGenericSignatureOfContext()) {
+      (void)validateGenericFuncSignature(CD);
+
+      // Revert all of the types within the signature of the constructor.
+      revertGenericFuncSignature(CD);
+
+      CD->setGenericEnvironment(
+          CD->getDeclContext()->getGenericEnvironmentOfContext());
+    }
+
+    // Set the context type of 'self'.
+    if (CD->getDeclContext()->isTypeContext())
+      recordSelfContextType(CD);
+
+    // Type check the constructor parameters.
+    GenericTypeToArchetypeResolver resolver(CD);
+    if (typeCheckParameterLists(CD, resolver) || CD->isInvalid()) {
+      CD->setInterfaceType(ErrorType::get(Context));
+      CD->setInvalid();
+    } else {
+      if (!CD->getGenericSignatureOfContext())
+        configureInterfaceType(CD, CD->getGenericSignature());
+    }
+
+    // We want the constructor to be available for name lookup as soon
+    // as it has a valid interface type.
+    CD->setIsBeingValidated(false);
+
+    validateAttributes(*this, CD);
+
+    // Check whether this initializer overrides an initializer in its
+    // superclass.
+    if (!checkOverrides(*this, CD)) {
+      // If an initializer has an override attribute but does not override
+      // anything or overrides something that doesn't need an 'override'
+      // keyword (e.g., a convenience initializer), complain.
+      // anything, or overrides something that complain.
+      if (auto *attr = CD->getAttrs().getAttribute<OverrideAttr>()) {
+        if (!CD->getOverriddenDecl()) {
+          diagnose(CD, diag::initializer_does_not_override)
+            .highlight(attr->getLocation());
+          attr->setInvalid();
+        } else if (!DeclChecker::overrideRequiresKeyword(CD->getOverriddenDecl())) {
+          // Special case: we are overriding a 'required' initializer, so we
+          // need (only) the 'required' keyword.
+          if (cast<ConstructorDecl>(CD->getOverriddenDecl())->isRequired()) {
+            if (CD->getAttrs().hasAttribute<RequiredAttr>()) {
+              diagnose(CD, diag::required_initializer_override_keyword)
+                .fixItRemove(attr->getLocation());
+            } else {
+              diagnose(CD, diag::required_initializer_override_wrong_keyword)
+                .fixItReplace(attr->getLocation(), "required");
+              CD->getAttrs().add(
+                new (Context) RequiredAttr(/*IsImplicit=*/true));
+            }
+
+            diagnose(findNonImplicitRequiredInit(CD->getOverriddenDecl()),
+                     diag::overridden_required_initializer_here);
+          } else {
+            // We tried to override a convenience initializer.
+            diagnose(CD, diag::initializer_does_not_override)
+              .highlight(attr->getLocation());
+            diagnose(CD->getOverriddenDecl(),
+                     diag::convenience_init_override_here);
+          }
+        }
+      }
+
+      // A failable initializer cannot override a non-failable one.
+      // This would normally be diagnosed by the covariance rules;
+      // however, those are disabled so that we can provide a more
+      // specific diagnostic here.
+      if (CD->getFailability() != OTK_None &&
+          CD->getOverriddenDecl() &&
+          CD->getOverriddenDecl()->getFailability() == OTK_None) {
+        diagnose(CD, diag::failable_initializer_override,
+                 CD->getFullName());
+        diagnose(CD->getOverriddenDecl(),
+                 diag::nonfailable_initializer_override_here,
+                 CD->getOverriddenDecl()->getFullName());
+      }
+    }
+
+    // An initializer is ObjC-compatible if it's explicitly @objc or a member
+    // of an ObjC-compatible class.
+    if (CD->getDeclContext()->isTypeContext()) {
+      Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, CD,
+          /*allowImplicit=*/true);
+
+      Optional<ForeignErrorConvention> errorConvention;
+      if (isObjC &&
+          (CD->isInvalid() ||
+           !isRepresentableInObjC(CD, *isObjC, errorConvention)))
+        isObjC = None;
+      markAsObjC(*this, CD, isObjC, errorConvention);
+    }
+
+    inferDynamic(Context, CD);
+
+    if (CD->getFailability() == OTK_ImplicitlyUnwrappedOptional) {
+      auto &C = CD->getASTContext();
+      CD->getAttrs().add(
+          new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
+    }
+
+    break;
+  }
+
+  case DeclKind::Destructor: {
+    auto *DD = cast<DestructorDecl>(D);
+
+    auto enclosingClass = dyn_cast<ClassDecl>(DD->getDeclContext());
+    if (DD->isInvalid() ||
+        enclosingClass == nullptr) {
+      DD->setInterfaceType(ErrorType::get(Context));
+      DD->setInvalid();
+      return;
+    }
+
+    DD->setIsBeingValidated();
+
+    assert(DD->getDeclContext()->isTypeContext()
+           && "Decl parsing must prevent destructors outside of types!");
+
+    checkDeclAttributesEarly(DD);
+    DD->copyFormalAccessAndVersionedAttrFrom(enclosingClass);
+
+    configureImplicitSelf(*this, DD);
+
+    if (DD->getDeclContext()->getGenericSignatureOfContext()) {
+      (void)validateGenericFuncSignature(DD);
+      DD->setGenericEnvironment(
+          DD->getDeclContext()->getGenericEnvironmentOfContext());
+    }
+
+    // Set the context type of 'self'.
+    recordSelfContextType(DD);
+
+    GenericTypeToArchetypeResolver resolver(DD);
+    if (typeCheckParameterLists(DD, resolver)) {
+      DD->setInterfaceType(ErrorType::get(Context));
+      DD->setInvalid();
+    }
+
+    if (!DD->getGenericSignatureOfContext())
+      configureInterfaceType(DD, DD->getGenericSignature());
+
+    DD->setIsBeingValidated(false);
+
+    // Do this before markAsObjC() to diagnose @nonobjc better
+    validateAttributes(*this, DD);
+
+    // Destructors are always @objc, because their Objective-C entry point is
+    // -dealloc.
+    markAsObjC(*this, DD, ObjCReason::ImplicitlyObjC);
+
+    break;
+  }
+
+  case DeclKind::Subscript: {
+    auto *SD = cast<SubscriptDecl>(D);
+
+    SD->setIsBeingValidated();
+
+    auto dc = SD->getDeclContext();
+
+    if (auto gp = SD->getGenericParams()) {
+      // Write up generic parameters and check the generic parameter list.
+      gp->setOuterParameters(dc->getGenericParamsOfContext());
+
+      auto *sig = validateGenericSubscriptSignature(SD);
+      auto *env = sig->createGenericEnvironment();
+      SD->setGenericEnvironment(env);
+
+      // Revert the types within the signature so it can be type-checked with
+      // archetypes below.
+      revertGenericSubscriptSignature(SD);
+    } else if (dc->getGenericSignatureOfContext()) {
+      (void)validateGenericSubscriptSignature(SD);
+
+      // Revert all of the types within the signature of the subscript.
+      revertGenericSubscriptSignature(SD);
+
+      SD->setGenericEnvironment(
+          SD->getDeclContext()->getGenericEnvironmentOfContext());
+    }
+
+    // Type check the subscript parameters.
+    GenericTypeToArchetypeResolver resolver(SD);
+
+    bool isInvalid = validateType(SD->getElementTypeLoc(), SD,
+                                  TypeResolutionFlags::AllowIUO,
+                                  &resolver);
+    TypeResolutionOptions options;
+    options |= TypeResolutionFlags::SubscriptParameters;
+
+    isInvalid |= typeCheckParameterList(SD->getIndices(), SD,
+                                        options,
+                                        resolver);
+
+    if (isInvalid || SD->isInvalid()) {
+      SD->setInterfaceType(ErrorType::get(Context));
+      SD->setInvalid();
+    } else {
+      if (!SD->getGenericSignatureOfContext())
+        configureInterfaceType(SD, SD->getGenericSignature());
+    }
+
+    SD->setIsBeingValidated(false);
+
+    checkDeclAttributesEarly(SD);
+    computeAccessLevel(SD);
+
+    validateAttributes(*this, SD);
+
+    auto *TyR = SD->getElementTypeLoc().getTypeRepr();
+    if (TyR && TyR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional) {
+      auto &C = SD->getASTContext();
+      SD->getAttrs().add(
+          new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
+    }
+
+    if (!checkOverrides(*this, SD)) {
+      // If a subscript has an override attribute but does not override
+      // anything, complain.
+      if (auto *OA = SD->getAttrs().getAttribute<OverrideAttr>()) {
+        if (!SD->getOverriddenDecl()) {
+          diagnose(SD, diag::subscript_does_not_override)
+              .highlight(OA->getLocation());
+          OA->setInvalid();
+        }
+      }
+    }
+
+    // Member subscripts need some special validation logic.
+    if (auto nominalDecl = dc->getAsNominalTypeOrNominalTypeExtensionContext()) {
+      // If this is a class member, mark it final if the class is final.
+      if (auto cls = dyn_cast<ClassDecl>(nominalDecl)) {
+        if (cls->isFinal() && !SD->isFinal()) {
+          makeFinal(Context, SD);
+        }
+      }
+
+      // A subscript is ObjC-compatible if it's explicitly @objc, or a
+      // member of an ObjC-compatible class or protocol.
+      Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, SD);
+
+      if (isObjC && !isRepresentableInObjC(SD, *isObjC))
+        isObjC = None;
+      markAsObjC(*this, SD, isObjC);
+
+      // Infer 'dynamic' before touching accessors.
+      inferDynamic(Context, SD);
+    }
+
+    // Perform accessor-related validation.
+    validateAbstractStorageDecl(*this, SD);
+
+    // If this is a get+mutableAddress property, synthesize the setter body.
+    if (SD->getStorageKind() == SubscriptDecl::ComputedWithMutableAddress &&
+        !SD->getSetter()->getBody()) {
+      synthesizeSetterForMutableAddressedStorage(SD, *this);
+    }
+
+    break;
+  }
+
   case DeclKind::EnumElement: {
-    typeCheckDecl(D, true);
+    auto *EED = cast<EnumElementDecl>(D);
+
+    checkDeclAttributesEarly(EED);
+    validateAccessControl(EED);
+
+    validateAttributes(*this, EED);
+
+    EED->setIsBeingValidated(true);
+
+    if (!EED->getArgumentTypeLoc().isNull()) {
+      if (validateType(EED->getArgumentTypeLoc(), EED->getDeclContext(),
+                       TypeResolutionFlags::EnumCase)) {
+        EED->setIsBeingValidated(false);
+        EED->setInterfaceType(ErrorType::get(Context));
+        EED->setInvalid();
+        break;
+      }
+    }
+
+    // If we have a raw value, make sure there's a raw type as well.
+    if (auto *rawValue = EED->getRawValueExpr()) {
+      EnumDecl *ED = EED->getParentEnum();
+      if (!ED->hasRawType()) {
+        diagnose(rawValue->getLoc(),diag::enum_raw_value_without_raw_type);
+        // Recover by setting the raw type as this element's type.
+        Expr *typeCheckedExpr = rawValue;
+        if (!typeCheckExpression(typeCheckedExpr, ED)) {
+          EED->setTypeCheckedRawValueExpr(typeCheckedExpr);
+          checkEnumElementErrorHandling(EED);
+        }
+      } else {
+        // Wait until the second pass, when all the raw value expressions
+        // can be checked together.
+      }
+    }
+
+    EED->setIsBeingValidated(false);
+
+    // Now that we have an argument type we can set the element's declared
+    // type.
+    if (!EED->computeType())
+      break;
+
+    // Require the carried type to be materializable.
+    if (auto argTy = EED->getArgumentInterfaceType()) {
+      assert(!argTy->hasLValueType() && "enum element cannot carry @lvalue");
+
+      if (!argTy->isMaterializable()) {
+        diagnose(EED->getLoc(), diag::enum_element_not_materializable, argTy);
+        EED->setInterfaceType(ErrorType::get(Context));
+        EED->setInvalid();
+      }
+    }
+
     break;
   }
   }
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 5e205c5..cdadb3b 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -876,6 +876,17 @@
   return hadError;
 }
 
+bool TypeChecker::typeCheckParameterLists(AbstractFunctionDecl *fd,
+                                          GenericTypeResolver &resolver) {
+  bool hadError = false;
+  for (auto paramList : fd->getParameterLists()) {
+    hadError |= typeCheckParameterList(paramList, fd,
+                                       TypeResolutionOptions(),
+                                       resolver);
+  }
+
+  return hadError;
+}
 
 bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc,
                                    TypeResolutionOptions options) {
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index b0c64a3..ee61b00 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1910,8 +1910,7 @@
 
   assert(!type->hasArchetype() && "Got a contextual type here?");
 
-  if (checkObjCTypeErasedGenerics(assocType, type, typeDecl))
-    type = ErrorType::get(type);
+  checkObjCTypeErasedGenerics(assocType, type, typeDecl);
 
   if (typeDecl) {
     // Check access.
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index ee3c869..fdd6e77 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -480,6 +480,7 @@
   }
     
   Stmt *visitDeferStmt(DeferStmt *DS) {
+    TC.typeCheckDecl(DS->getTempDecl(), /*isFirstPass*/true);
     TC.typeCheckDecl(DS->getTempDecl(), /*isFirstPass*/false);
 
     Expr *theCall = DS->getCallExpr();
@@ -835,6 +836,7 @@
     // the list of raw cases.
     for (auto node : S->getRawCases()) {
       if (!node.is<Decl*>()) continue;
+      TC.typeCheckDecl(node.get<Decl*>(), /*isFirstPass*/true);
       TC.typeCheckDecl(node.get<Decl*>(), /*isFirstPass*/false);
     }
 
@@ -1338,6 +1340,7 @@
         (Loc == EndTypeCheckLoc || SM.isBeforeInBuffer(EndTypeCheckLoc, Loc)))
       break;
 
+    TC.typeCheckDecl(SubDecl, /*isFirstPass*/true);
     TC.typeCheckDecl(SubDecl, /*isFirstPass*/false);
   }
   
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 11d6748..cc64d6d 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -1042,13 +1042,12 @@
     SmallVector<ValueDecl *, 4> decls;
     if (DC->lookupQualified(nominal->getDeclaredInterfaceType(),
                             comp->getIdentifier(),
-                            NL_QualifiedDefault|NL_ProtocolMembers,
+                            NL_OnlyTypes|NL_QualifiedDefault|NL_ProtocolMembers,
                             &TC,
                             decls)) {
       for (const auto decl : decls) {
         // FIXME: Better ambiguity handling.
-        auto typeDecl = dyn_cast<TypeDecl>(decl);
-        if (!typeDecl) continue;
+        auto typeDecl = cast<TypeDecl>(decl);
 
         if (!isa<ProtocolDecl>(typeDecl->getDeclContext())) continue;
 
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 0cfb0d7..0e5d12f 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1277,19 +1277,6 @@
                               DeclContext *dc,
                               bool *unwrappedIUO = nullptr);
 
-  /// \brief Determine whether one type would be a valid substitution for an
-  /// archetype.
-  ///
-  /// \param type The potential type.
-  ///
-  /// \param archetype The archetype for which type may (or may not) be
-  /// substituted.
-  ///
-  /// \param dc The context of the check.
-  ///
-  /// \returns true if \c t1 is a valid substitution for \c t2.
-  bool isSubstitutableFor(Type type, ArchetypeType *archetype, DeclContext *dc);
-
   /// If the inputs to an apply expression use a consistent "sugar" type
   /// (that is, a typealias or shorthand syntax) equivalent to the result type
   /// of the function, set the result type of the expression to that sugar type.
@@ -1824,6 +1811,10 @@
                               TypeResolutionOptions options,
                               GenericTypeResolver &resolver);
 
+  /// Type check all parameter lists of a function.
+  bool typeCheckParameterLists(AbstractFunctionDecl *fd,
+                               GenericTypeResolver &resolver);
+
   /// Coerce a pattern to the given type.
   ///
   /// \param P The pattern, which may be modified by this coercion.
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 269b9a4..ba32d75 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -36,6 +36,7 @@
 #include "swift/ClangImporter/ClangImporter.h"
 #include "swift/ClangImporter/ClangModule.h"
 #include "swift/Serialization/SerializationOptions.h"
+#include "swift/Strings.h"
 
 // FIXME: We're just using CompilerInstance::createOutputFile.
 // This API should be sunk down to LLVM.
@@ -3556,7 +3557,7 @@
   llvm::SmallString<32> FullName;
   llvm::raw_svector_ostream OS(FullName);
   T->print(OS);
-  assert(FullName.startswith("Builtin."));
+  assert(FullName.startswith(BUILTIN_TYPE_NAME_PREFIX));
   StringRef TypeName = FullName.substr(8);
 
   SmallVector<ValueDecl*, 4> CurModuleResults;
diff --git a/stdlib/public/SDK/Accelerate/BNNS.swift.gyb b/stdlib/public/SDK/Accelerate/BNNS.swift.gyb
index 7552db1..c2843df 100644
--- a/stdlib/public/SDK/Accelerate/BNNS.swift.gyb
+++ b/stdlib/public/SDK/Accelerate/BNNS.swift.gyb
@@ -16,11 +16,11 @@
 
 %{
 bnns2016 = [
-  ('OSX','10.12'), ('iOS','10.0'), ('tvOS','10.0'), ('watchOS','3.0')
+  ('macOS','10.12'), ('iOS','10.0'), ('tvOS','10.0'), ('watchOS','3.0')
 ]
 
 bnns2017 = [
-  ('OSX','10.13'), ('iOS','11.0'), ('tvOS','11.0'), ('watchOS','4.0')
+  ('macOS','10.13'), ('iOS','11.0'), ('tvOS','11.0'), ('watchOS','4.0')
 ]
 
 def relString(releases):
diff --git a/stdlib/public/SDK/AppKit/AppKit_FoundationExtensions.swift b/stdlib/public/SDK/AppKit/AppKit_FoundationExtensions.swift
index a5afb5e..22e4149 100644
--- a/stdlib/public/SDK/AppKit/AppKit_FoundationExtensions.swift
+++ b/stdlib/public/SDK/AppKit/AppKit_FoundationExtensions.swift
@@ -53,7 +53,7 @@
 
 public extension URLResourceValues {
     /// Returns all thumbnails as a single NSImage.
-    @available(OSX 10.10, *)
+    @available(macOS 10.10, *)
     public var thumbnail : NSImage? {
         return allValues[URLResourceKey.thumbnailKey] as? NSImage
     }
@@ -74,7 +74,7 @@
     }
     
     /// Returns a dictionary of NSImage objects keyed by size.
-    @available(OSX 10.10, *)
+    @available(macOS 10.10, *)
     public var thumbnailDictionary : [URLThumbnailDictionaryItem : NSImage]? {
         return allValues[URLResourceKey.thumbnailDictionaryKey] as? [URLThumbnailDictionaryItem : NSImage]
     }
diff --git a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
index a4f8308..1ce4f6b 100644
--- a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
+++ b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
@@ -29,7 +29,7 @@
 //===----------------------------------------------------------------------===//
 
 extension CGColor {
-  @available(OSX 10.3, iOS 2.0, *)
+  @available(macOS 10.3, iOS 2.0, *)
   public var components: [CGFloat]? {
     guard let pointer = self.__unsafeComponents else { return nil }
     let buffer = UnsafeBufferPointer(start: pointer, count: self.numberOfComponents)
diff --git a/stdlib/public/SDK/CoreImage/CoreImage.swift b/stdlib/public/SDK/CoreImage/CoreImage.swift
index 794b49d..19102ce 100644
--- a/stdlib/public/SDK/CoreImage/CoreImage.swift
+++ b/stdlib/public/SDK/CoreImage/CoreImage.swift
@@ -30,7 +30,7 @@
 #endif
 
   @available(iOS, introduced: 8.0)
-  @available(OSX, introduced: 10.10)
+  @available(macOS, introduced: 10.10)
   convenience init?(
     name: String, elements: (String, AnyObject)...
   ) {
diff --git a/stdlib/public/SDK/CryptoTokenKit/TKSmartCard.swift b/stdlib/public/SDK/CryptoTokenKit/TKSmartCard.swift
index 752cb51..d6756b8 100644
--- a/stdlib/public/SDK/CryptoTokenKit/TKSmartCard.swift
+++ b/stdlib/public/SDK/CryptoTokenKit/TKSmartCard.swift
@@ -14,7 +14,7 @@
 
 import Foundation
 
-@available(OSX 10.10, *)
+@available(macOS 10.10, *)
 extension TKSmartCard {
   public func send(ins: UInt8, p1: UInt8, p2: UInt8, data: Data? = nil,
     le: Int? = nil, reply: @escaping (Data?, UInt16, Error?) -> Void) {
@@ -23,7 +23,7 @@
       le: le.map { NSNumber(value: $0) }, reply: reply)
   }
 
-  @available(OSX 10.12, *)
+  @available(macOS 10.12, *)
   public func send(ins: UInt8, p1: UInt8, p2: UInt8, data: Data? = nil,
     le: Int? = nil) throws -> (sw: UInt16, response: Data) {
 
@@ -33,7 +33,7 @@
     return (sw: sw, response: response)
   }
 
-  @available(OSX 10.12, *)
+  @available(macOS 10.12, *)
   public func withSession<T>(_ body: @escaping () throws -> T) throws -> T {
     var result: T?
     try self.__inSession(executeBlock: {
diff --git a/stdlib/public/SDK/GameplayKit/GameplayKit.swift b/stdlib/public/SDK/GameplayKit/GameplayKit.swift
index 103c8f5..77e0eef 100644
--- a/stdlib/public/SDK/GameplayKit/GameplayKit.swift
+++ b/stdlib/public/SDK/GameplayKit/GameplayKit.swift
@@ -16,7 +16,7 @@
 
 
 @available(iOS, introduced: 9.0)
-@available(OSX, introduced: 10.11)
+@available(macOS, introduced: 10.11)
 @available(tvOS, introduced: 9.0)
 extension GKPath {
   /// Creates a path from an array of points
@@ -31,7 +31,7 @@
 
 
 @available(iOS, introduced: 10.0)
-@available(OSX, introduced: 10.12)
+@available(macOS, introduced: 10.12)
 @available(tvOS, introduced: 10.0)
 extension GKPath {
   /// Creates a path from an array of points
@@ -45,7 +45,7 @@
 }
 
 @available(iOS, introduced: 9.0)
-@available(OSX, introduced: 10.11)
+@available(macOS, introduced: 10.11)
 @available(tvOS, introduced: 9.0)
 extension GKPolygonObstacle {
   /// Creates a polygon obstacle with an array of points.
@@ -57,7 +57,7 @@
 }
 
 @available(iOS, introduced: 9.0)
-@available(OSX, introduced: 10.11)
+@available(macOS, introduced: 10.11)
 @available(tvOS, introduced: 9.0)
 extension GKEntity {
   /// Gets the component of the indicated class.  Returns nil if entity does not have this component
@@ -79,7 +79,7 @@
 }
 
 @available(iOS, introduced: 9.0)
-@available(OSX, introduced: 10.11)
+@available(macOS, introduced: 10.11)
 @available(tvOS, introduced: 9.0)
 extension GKStateMachine {
   /// Gets the state of the indicated class.  Returns nil if the state machine does not have this state.
diff --git a/stdlib/public/SDK/ModelIO/ModelIO.swift b/stdlib/public/SDK/ModelIO/ModelIO.swift
index 36234b7..71f7b75 100644
--- a/stdlib/public/SDK/ModelIO/ModelIO.swift
+++ b/stdlib/public/SDK/ModelIO/ModelIO.swift
@@ -13,7 +13,7 @@
 @_exported import ModelIO
 import simd
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLMatrix4x4Array {
@@ -44,7 +44,7 @@
 
 
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedValue {
@@ -57,7 +57,7 @@
     }
 }
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedScalarArray {
@@ -108,7 +108,7 @@
     }
 }
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedVector3Array {
@@ -159,7 +159,7 @@
     }
 }
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedQuaternionArray {
@@ -210,7 +210,7 @@
     }
 }
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedScalar {
@@ -239,7 +239,7 @@
     }
 }
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedVector2 {
@@ -268,7 +268,7 @@
     }
 }
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedVector3 {
@@ -297,7 +297,7 @@
     }
 }
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedVector4 {
@@ -326,7 +326,7 @@
     }
 }
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension MDLAnimatedMatrix4x4 {
diff --git a/stdlib/public/SDK/OpenCL/OpenCL.swift b/stdlib/public/SDK/OpenCL/OpenCL.swift
index 44cc953..f8b9edc 100644
--- a/stdlib/public/SDK/OpenCL/OpenCL.swift
+++ b/stdlib/public/SDK/OpenCL/OpenCL.swift
@@ -12,7 +12,7 @@
 
 @_exported import OpenCL // Clang module
 
-@available(OSX, introduced: 10.7)
+@available(macOS, introduced: 10.7)
 public func clSetKernelArgsListAPPLE(
   _ kernel: cl_kernel, _ uint: cl_uint, _ args: CVarArg...
 ) -> cl_int {
diff --git a/stdlib/public/SDK/SafariServices/SafariServices.swift b/stdlib/public/SDK/SafariServices/SafariServices.swift
index 6f04fa3..32147d4 100644
--- a/stdlib/public/SDK/SafariServices/SafariServices.swift
+++ b/stdlib/public/SDK/SafariServices/SafariServices.swift
@@ -15,7 +15,7 @@
 
 #if os(macOS)
 
-@available(OSX, introduced: 10.11)
+@available(macOS, introduced: 10.11)
 public func SFSafariServicesAvailable(_ version: SFSafariServicesVersion = SFSafariServicesVersion.version10_0) -> Bool {
   return _swift_SafariServices_isSafariServicesAvailable(version)
 }
diff --git a/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb b/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
index 1581b39..bc034e4 100644
--- a/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
+++ b/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
@@ -142,7 +142,7 @@
 // MARK: Swift Extensions
 
 @available(iOS, introduced: 8.0)
-@available(OSX, introduced: 10.8)
+@available(macOS, introduced: 10.8)
 extension SCNGeometryElement {
   /// Creates an instance from `indices` for a `primitiveType`
   /// that has a constant number of indices per primitive
@@ -175,7 +175,7 @@
 }
 
 @available(iOS, introduced: 8.0)
-@available(OSX, introduced: 10.8)
+@available(macOS, introduced: 10.8)
 extension SCNGeometrySource {
   @nonobjc
   public convenience init(vertices: [SCNVector3]) {
@@ -192,7 +192,7 @@
 }
 
 @available(iOS, introduced: 8.0)
-@available(OSX, introduced: 10.10)
+@available(macOS, introduced: 10.10)
 extension SCNBoundingVolume {
   public var boundingBox: (min: SCNVector3, max: SCNVector3) {
     get {
@@ -218,7 +218,7 @@
 // MARK: APIs refined for Swift
 
 @available(iOS, introduced: 8.0)
-@available(OSX, introduced: 10.8)
+@available(macOS, introduced: 10.8)
 extension SCNSceneSource {
   public func entryWithIdentifier<T: AnyObject>(_ uid: String, withClass entryClass: T.Type) -> T? {
     return self.__entry(withIdentifier: uid, with: entryClass) as! T?
diff --git a/stdlib/public/SDK/SpriteKit/SpriteKit.swift b/stdlib/public/SDK/SpriteKit/SpriteKit.swift
index 947b33c..fade599 100644
--- a/stdlib/public/SDK/SpriteKit/SpriteKit.swift
+++ b/stdlib/public/SDK/SpriteKit/SpriteKit.swift
@@ -30,7 +30,7 @@
 }
 
 @available(iOS, introduced: 10.0)
-@available(OSX, introduced: 10.12)
+@available(macOS, introduced: 10.12)
 @available(tvOS, introduced: 10.0)
 @available(watchOS, introduced: 3.0)
 extension SKWarpGeometryGrid {
diff --git a/stdlib/public/SDK/Vision/Vision.swift b/stdlib/public/SDK/Vision/Vision.swift
index 8a3cf62..a6e560b 100644
--- a/stdlib/public/SDK/Vision/Vision.swift
+++ b/stdlib/public/SDK/Vision/Vision.swift
@@ -19,7 +19,7 @@
 
 #if !os(watchOS)
 
-@available(OSX, introduced: 10.13)
+@available(macOS, introduced: 10.13)
 @available(iOS, introduced: 11.0)
 @available(tvOS, introduced: 11.0)
 extension VNFaceLandmarkRegion2D {
diff --git a/stdlib/public/SDK/os/os_log.swift b/stdlib/public/SDK/os/os_log.swift
index dae6f4a..3650198 100644
--- a/stdlib/public/SDK/os/os_log.swift
+++ b/stdlib/public/SDK/os/os_log.swift
@@ -14,7 +14,7 @@
 @_exported import os.log
 import _SwiftOSOverlayShims
 
-@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
 public func os_log(
   _ message: StaticString, 
   dso: UnsafeRawPointer? = #dsohandle,
@@ -39,30 +39,30 @@
 }
 
 extension OSLogType {
-  @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+  @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
   public static let `default` = __OS_LOG_TYPE_DEFAULT
 
-  @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+  @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
   public static let info = __OS_LOG_TYPE_INFO
 
-  @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+  @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
   public static let debug = __OS_LOG_TYPE_DEBUG
 
-  @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+  @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
   public static let error = __OS_LOG_TYPE_ERROR
 
-  @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+  @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
   public static let fault = __OS_LOG_TYPE_FAULT
 }
 
 extension OSLog {
-  @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+  @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
   public static let disabled = _swift_os_log_disabled()
 
-  @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+  @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
   public static let `default` = _swift_os_log_default()
 
-  @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+  @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
   public convenience init(subsystem: String, category: String) {
     self.init(__subsystem: subsystem, category: category)
   }
diff --git a/stdlib/public/SDK/simd/simd.swift.gyb b/stdlib/public/SDK/simd/simd.swift.gyb
index 1a18abe..64b7375 100644
--- a/stdlib/public/SDK/simd/simd.swift.gyb
+++ b/stdlib/public/SDK/simd/simd.swift.gyb
@@ -43,20 +43,20 @@
 @_alignment(${vecsize})
 public struct ${vectype} {
 
-  public var _vector: Builtin.${llvm_vectype}
+  public var _value: Builtin.${llvm_vectype}
 
 % for i in xrange(count):
   public var ${component[i]} : ${scalar} {
     @_transparent
     get {
-      let elt = Builtin.${extractelement}(_vector,
+      let elt = Builtin.${extractelement}(_value,
         (${i} as Int32)._value)
 
-      return ${scalar}(_bits: elt)
+      return ${scalar}(elt)
     }
     @_transparent
     set {
-      _vector = Builtin.${insertelement}(_vector,
+      _value = Builtin.${insertelement}(_value,
         newValue._value,
         (${i} as Int32)._value)
     }
@@ -68,8 +68,8 @@
   public init() { self.init(0) }
 
   @_transparent
-  public init(_bits: Builtin.${llvm_vectype}) {
-    _vector = _bits
+  public init(_ _value: Builtin.${llvm_vectype}) {
+    self._value = _value
   }
 
   /// Initialize a vector with the specified elements.
@@ -81,7 +81,7 @@
       ${component[i]}._value,
       (${i} as Int32)._value)
 % end
-    _vector = v
+    _value = v
   }
 
   /// Initialize a vector with the specified elements.
@@ -113,15 +113,15 @@
     get {
       _precondition(index >= 0, "Vector index out of range")
       _precondition(index < ${count}, "Vector index out of range")
-      let elt = Builtin.${extractelement}(_vector,
+      let elt = Builtin.${extractelement}(_value,
         Int32(index)._value)
-      return ${scalar}(_bits: elt)
+      return ${scalar}(elt)
     }
     @_transparent
     set(value) {
       _precondition(index >= 0, "Vector index out of range")
       _precondition(index < ${count}, "Vector index out of range")
-      _vector = Builtin.${insertelement}(_vector,
+      _value = Builtin.${insertelement}(_value,
         value._value,
         Int32(index)._value)
     }
@@ -183,15 +183,13 @@
   /// Vector (elementwise) sum of `lhs` and `rhs`.
   @_transparent
   public static func ${wrap}+(lhs: ${vectype}, rhs: ${vectype}) -> ${vectype} {
-    return ${vectype}(_bits:
-      Builtin.${prefix}add_${llvm_vectype}(lhs._vector, rhs._vector))
+    return ${vectype}(Builtin.${prefix}add_${llvm_vectype}(lhs._value, rhs._value))
   }
 
   /// Vector (elementwise) difference of `lhs` and `rhs`.
   @_transparent
   public static func ${wrap}-(lhs: ${vectype}, rhs: ${vectype}) -> ${vectype} {
-    return ${vectype}(_bits:
-      Builtin.${prefix}sub_${llvm_vectype}(lhs._vector, rhs._vector))
+    return ${vectype}(Builtin.${prefix}sub_${llvm_vectype}(lhs._value, rhs._value))
   }
 
   /// Negation of `rhs`.
@@ -204,8 +202,7 @@
   /// vector product).
   @_transparent
   public static func ${wrap}*(lhs: ${vectype}, rhs: ${vectype}) -> ${vectype} {
-    return ${vectype}(_bits:
-      Builtin.${prefix}mul_${llvm_vectype}(lhs._vector, rhs._vector))
+    return ${vectype}(Builtin.${prefix}mul_${llvm_vectype}(lhs._value, rhs._value))
   }
 
   /// Scalar-Vector product.
@@ -223,8 +220,7 @@
   /// Elementwise quotient of `lhs` and `rhs`.
   @_transparent
   public static func /(lhs: ${vectype}, rhs: ${vectype}) -> ${vectype} {
-    return ${vectype}(_bits:
-      Builtin.${divide}_${llvm_vectype}(lhs._vector, rhs._vector))
+    return ${vectype}(Builtin.${divide}_${llvm_vectype}(lhs._value, rhs._value))
   }
 
   /// Divide vector by scalar.
@@ -745,7 +741,7 @@
 %   if rows == cols:
   /// Inverse of the matrix if it exists, otherwise the contents of the
   /// resulting matrix are undefined.
-  @available(OSX 10.10, iOS 8.0, tvOS 10.0, watchOS 3.0, *)
+  @available(macOS 10.10, iOS 8.0, tvOS 10.0, watchOS 3.0, *)
   @_transparent
   public var inverse: ${mattype} {
     return simd_inverse(self)
@@ -849,7 +845,7 @@
 }
 
 @available(swift, deprecated: 4, message: "Use the .inverse property instead.")
-@available(OSX 10.10, iOS 8.0, tvOS 10.0, watchOS 3.0, *)
+@available(macOS 10.10, iOS 8.0, tvOS 10.0, watchOS 3.0, *)
 public func matrix_invert(_ x: ${mattype}) -> ${mattype} {
   return x.inverse
 }
diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h
index 4273e9a..8adbc2f 100644
--- a/stdlib/public/SwiftShims/RefCount.h
+++ b/stdlib/public/SwiftShims/RefCount.h
@@ -1276,12 +1276,11 @@
   // Return weak reference count.
   // Note that this is not equal to the number of outstanding weak pointers.
   uint32_t getWeakCount() const;
-
-
+  
   private:
   HeapObject *getHeapObject();
   
-  HeapObjectSideTableEntry* allocateSideTable();
+  HeapObjectSideTableEntry* allocateSideTable(bool failIfDeiniting);
 };
 
 typedef RefCounts<InlineRefCountBits> InlineRefCounts;
@@ -1464,6 +1463,10 @@
   uint32_t getWeakCount() const {
     return refCounts.getWeakCount();
   }
+  
+  void *getSideTable() {
+    return refCounts.getSideTable();
+  }
 };
 
 
diff --git a/stdlib/public/core/BuiltinMath.swift.gyb b/stdlib/public/core/BuiltinMath.swift.gyb
index ff8f4ae..71a24d6 100644
--- a/stdlib/public/core/BuiltinMath.swift.gyb
+++ b/stdlib/public/core/BuiltinMath.swift.gyb
@@ -67,7 +67,7 @@
 @_inlineable // FIXME(sil-serialize-all)
 @_transparent
 public func _${ufunc}(_ x: ${T}) -> ${T} {
-  return ${T}(_bits: Builtin.int_${ufunc}_FPIEEE${bits}(x._value))
+  return ${T}(Builtin.int_${ufunc}_FPIEEE${bits}(x._value))
 }
 %  if bits == 80:
 #endif
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 9e9cfae..5414725 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -47,6 +47,7 @@
   CString.swift
   CTypes.swift
   DebuggerSupport.swift
+  Dictionary.swift
   DoubleWidth.swift.gyb
   DropWhile.swift
   Dump.swift
@@ -61,7 +62,6 @@
   FloatingPointParsing.swift.gyb
   FloatingPointTypes.swift.gyb
   Hashable.swift
-  HashedCollections.swift.gyb
   # WORKAROUND: This file name is not sorted alphabetically in the list because
   # if we do so, the compiler crashes.
   AnyHashable.swift
@@ -111,6 +111,7 @@
   Sequence.swift
   SequenceAlgorithms.swift
   SequenceWrapper.swift
+  Set.swift
   SetAlgebra.swift
   ShadowProtocols.swift
   Shims.swift
diff --git a/stdlib/public/core/HashedCollections.swift.gyb b/stdlib/public/core/Dictionary.swift
similarity index 64%
rename from stdlib/public/core/HashedCollections.swift.gyb
rename to stdlib/public/core/Dictionary.swift
index 5b1367e..94a0081 100644
--- a/stdlib/public/core/HashedCollections.swift.gyb
+++ b/stdlib/public/core/Dictionary.swift
@@ -2,7 +2,7 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2018 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
@@ -12,9 +12,6 @@
 
 import SwiftShims
 
-// General Mutable, Value-Type Collections
-// =================================================
-//
 // Implementation notes
 // ====================
 //
@@ -206,1348 +203,6 @@
 // `Dictionary<Element, ()>`.
 //
 
-/// This protocol is only used for compile-time checks that
-/// every buffer type implements all required operations.
-internal protocol _HashBuffer {
-  associatedtype Key
-  associatedtype Value
-  associatedtype Index
-  associatedtype SequenceElement
-  associatedtype SequenceElementWithoutLabels
-  var startIndex: Index { get }
-  var endIndex: Index { get }
-
-  func index(after i: Index) -> Index
-
-  func formIndex(after i: inout Index)
-
-  func index(forKey key: Key) -> Index?
-
-  func assertingGet(_ i: Index) -> SequenceElement
-
-  func assertingGet(_ key: Key) -> Value
-
-  func maybeGet(_ key: Key) -> Value?
-
-  @discardableResult
-  mutating func updateValue(_ value: Value, forKey key: Key) -> Value?
-
-  @discardableResult
-  mutating func insert(
-    _ value: Value, forKey key: Key
-  ) -> (inserted: Bool, memberAfterInsert: Value)
-
-  @discardableResult
-  mutating func remove(at index: Index) -> SequenceElement
-
-  @discardableResult
-  mutating func removeValue(forKey key: Key) -> Value?
-
-  mutating func removeAll(keepingCapacity keepCapacity: Bool)
-
-  var count: Int { get }
-
-  static func fromArray(_ elements: [SequenceElementWithoutLabels]) -> Self
-}
-
-/// The inverse of the default hash table load factor.  Factored out so that it
-/// can be used in multiple places in the implementation and stay consistent.
-/// Should not be used outside `Dictionary` implementation.
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_transparent
-internal var _hashContainerDefaultMaxLoadFactorInverse: Double {
-  return 1.0 / 0.75
-}
-
-#if _runtime(_ObjC)
-/// Call `[lhs isEqual: rhs]`.
-///
-/// This function is part of the runtime because `Bool` type is bridged to
-/// `ObjCBool`, which is in Foundation overlay.
-/// FIXME(sil-serialize-all): this should be internal
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_stdlib_NSObject_isEqual")
-internal func _stdlib_NSObject_isEqual(_ lhs: AnyObject, _ rhs: AnyObject) -> Bool
-#endif
-
-
-/// A temporary view of an array of AnyObject as an array of Unmanaged<AnyObject>
-/// for fast iteration and transformation of the elements.
-///
-/// Accesses the underlying raw memory as Unmanaged<AnyObject> using untyped
-/// memory accesses. The memory remains bound to managed AnyObjects.
-@_fixed_layout // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-internal struct _UnmanagedAnyObjectArray {
-  /// Underlying pointer.
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: UnsafeMutableRawPointer
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal init(_ up: UnsafeMutablePointer<AnyObject>) {
-    self.value = UnsafeMutableRawPointer(up)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal init?(_ up: UnsafeMutablePointer<AnyObject>?) {
-    guard let unwrapped = up else { return nil }
-    self.init(unwrapped)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal subscript(i: Int) -> AnyObject {
-    get {
-      let unmanaged = value.load(
-        fromByteOffset: i * MemoryLayout<AnyObject>.stride,
-        as: Unmanaged<AnyObject>.self)
-      return unmanaged.takeUnretainedValue()
-    }
-    nonmutating set(newValue) {
-      let unmanaged = Unmanaged.passUnretained(newValue)
-      value.storeBytes(of: unmanaged,
-        toByteOffset: i * MemoryLayout<AnyObject>.stride,
-        as: Unmanaged<AnyObject>.self)
-    }
-  }
-}
-
-//===--- APIs unique to Set<Element> --------------------------------------===//
-
-/// An unordered collection of unique elements.
-///
-/// You use a set instead of an array when you need to test efficiently for
-/// membership and you aren't concerned with the order of the elements in the
-/// collection, or when you need to ensure that each element appears only once
-/// in a collection.
-///
-/// You can create a set with any element type that conforms to the `Hashable`
-/// protocol. By default, most types in the standard library are hashable,
-/// including strings, numeric and Boolean types, enumeration cases without
-/// associated values, and even sets themselves.
-///
-/// Swift makes it as easy to create a new set as to create a new array. Simply
-/// assign an array literal to a variable or constant with the `Set` type
-/// specified.
-///
-///     let ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
-///     if ingredients.contains("sugar") {
-///         print("No thanks, too sweet.")
-///     }
-///     // Prints "No thanks, too sweet."
-///
-/// Set Operations
-/// ==============
-///
-/// Sets provide a suite of mathematical set operations. For example, you can
-/// efficiently test a set for membership of an element or check its
-/// intersection with another set:
-///
-/// - Use the `contains(_:)` method to test whether a set contains a specific
-///   element.
-/// - Use the "equal to" operator (`==`) to test whether two sets contain the
-///   same elements.
-/// - Use the `isSubset(of:)` method to test whether a set contains all the
-///   elements of another set or sequence.
-/// - Use the `isSuperset(of:)` method to test whether all elements of a set
-///   are contained in another set or sequence.
-/// - Use the `isStrictSubset(of:)` and `isStrictSuperset(of:)` methods to test
-///   whether a set is a subset or superset of, but not equal to, another set.
-/// - Use the `isDisjoint(with:)` method to test whether a set has any elements
-///   in common with another set.
-///
-/// You can also combine, exclude, or subtract the elements of two sets:
-///
-/// - Use the `union(_:)` method to create a new set with the elements of a set
-///   and another set or sequence.
-/// - Use the `intersection(_:)` method to create a new set with only the
-///   elements common to a set and another set or sequence.
-/// - Use the `symmetricDifference(_:)` method to create a new set with the
-///   elements that are in either a set or another set or sequence, but not in
-///   both.
-/// - Use the `subtracting(_:)` method to create a new set with the elements of
-///   a set that are not also in another set or sequence.
-///
-/// You can modify a set in place by using these methods' mutating
-/// counterparts: `formUnion(_:)`, `formIntersection(_:)`,
-/// `formSymmetricDifference(_:)`, and `subtract(_:)`.
-///
-/// Set operations are not limited to use with other sets. Instead, you can
-/// perform set operations with another set, an array, or any other sequence
-/// type.
-///
-///     var primes: Set = [2, 3, 5, 7]
-///
-///     // Tests whether primes is a subset of a Range<Int>
-///     print(primes.isSubset(of: 0..<10))
-///     // Prints "true"
-///
-///     // Performs an intersection with an Array<Int>
-///     let favoriteNumbers = [5, 7, 15, 21]
-///     print(primes.intersection(favoriteNumbers))
-///     // Prints "[5, 7]"
-///
-/// Sequence and Collection Operations
-/// ==================================
-///
-/// In addition to the `Set` type's set operations, you can use any nonmutating
-/// sequence or collection methods with a set.
-///
-///     if primes.isEmpty {
-///         print("No primes!")
-///     } else {
-///         print("We have \(primes.count) primes.")
-///     }
-///     // Prints "We have 4 primes."
-///
-///     let primesSum = primes.reduce(0, +)
-///     // 'primesSum' == 17
-///
-///     let primeStrings = primes.sorted().map(String.init)
-///     // 'primeStrings' == ["2", "3", "5", "7"]
-///
-/// You can iterate through a set's unordered elements with a `for`-`in` loop.
-///
-///     for number in primes {
-///         print(number)
-///     }
-///     // Prints "5"
-///     // Prints "7"
-///     // Prints "2"
-///     // Prints "3"
-///
-/// Many sequence and collection operations return an array or a type-erasing
-/// collection wrapper instead of a set. To restore efficient set operations,
-/// create a new set from the result.
-///
-///     let morePrimes = primes.union([11, 13, 17, 19])
-///
-///     let laterPrimes = morePrimes.filter { $0 > 10 }
-///     // 'laterPrimes' is of type Array<Int>
-///
-///     let laterPrimesSet = Set(morePrimes.filter { $0 > 10 })
-///     // 'laterPrimesSet' is of type Set<Int>
-///
-/// Bridging Between Set and NSSet
-/// ==============================
-///
-/// You can bridge between `Set` and `NSSet` using the `as` operator. For
-/// bridging to be possible, the `Element` type of a set must be a class, an
-/// `@objc` protocol (a protocol imported from Objective-C or marked with the
-/// `@objc` attribute), or a type that bridges to a Foundation type.
-///
-/// Bridging from `Set` to `NSSet` always takes O(1) time and space. When the
-/// set's `Element` type is neither a class nor an `@objc` protocol, any
-/// required bridging of elements occurs at the first access of each element,
-/// so the first operation that uses the contents of the set (for example, a
-/// membership test) can take O(*n*).
-///
-/// Bridging from `NSSet` to `Set` first calls the `copy(with:)` method
-/// (`- copyWithZone:` in Objective-C) on the set to get an immutable copy and
-/// then performs additional Swift bookkeeping work that takes O(1) time. For
-/// instances of `NSSet` that are already immutable, `copy(with:)` returns the
-/// same set in constant time; otherwise, the copying performance is
-/// unspecified. The instances of `NSSet` and `Set` share buffer using the
-/// same copy-on-write optimization that is used when two instances of `Set`
-/// share buffer.
-@_fixed_layout
-public struct Set<Element : Hashable> {
-  internal typealias _VariantBuffer = _VariantSetBuffer<Element>
-  internal typealias _NativeBuffer = _NativeSetBuffer<Element>
-
-  @_versioned
-  internal var _variantBuffer: _VariantBuffer
-}
-
-extension Set {
-  /// Creates a new, empty set with at least the specified number of elements'
-  /// worth of buffer.
-  ///
-  /// Use this initializer to avoid repeated reallocations of a set's buffer
-  /// if you know you'll be adding elements to the set after creation. The
-  /// actual capacity of the created set will be the smallest power of 2 that
-  /// is greater than or equal to `minimumCapacity`.
-  ///
-  /// - Parameter minimumCapacity: The minimum number of elements that the
-  ///   newly created set should be able to store without reallocating its
-  ///   buffer.
-  @_inlineable // FIXME(sil-serialize-all)
-  public init(minimumCapacity: Int) {
-    _variantBuffer =
-      _VariantBuffer.native(
-        _NativeBuffer(minimumCapacity: minimumCapacity))
-  }
-
-  /// Private initializer.
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal init(_nativeBuffer: _NativeSetBuffer<Element>) {
-    _variantBuffer = _VariantBuffer.native(_nativeBuffer)
-  }
-
-  //
-  // All APIs below should dispatch to `_variantBuffer`, without doing any
-  // additional processing.
-  //
-
-#if _runtime(_ObjC)
-  /// Private initializer used for bridging.
-  ///
-  /// Only use this initializer when both conditions are true:
-  ///
-  /// * it is statically known that the given `NSSet` is immutable;
-  /// * `Element` is bridged verbatim to Objective-C (i.e.,
-  ///   is a reference type).
-  @_inlineable // FIXME(sil-serialize-all)
-  public init(_immutableCocoaSet: _NSSet) {
-    _sanityCheck(_isBridgedVerbatimToObjectiveC(Element.self),
-      "Set can be backed by NSSet _variantBuffer only when the member type can be bridged verbatim to Objective-C")
-    _variantBuffer = _VariantSetBuffer.cocoa(
-      _CocoaSetBuffer(cocoaSet: _immutableCocoaSet))
-  }
-#endif
-}
-
-extension Set : ExpressibleByArrayLiteral {
-
-  //
-  // `ExpressibleByArrayLiteral` conformance
-  //
-  /// Creates a set containing the elements of the given array literal.
-  ///
-  /// Do not call this initializer directly. It is used by the compiler when
-  /// you use an array literal. Instead, create a new set using an array
-  /// literal as its value by enclosing a comma-separated list of values in
-  /// square brackets. You can use an array literal anywhere a set is expected
-  /// by the type context.
-  ///
-  /// Here, a set of strings is created from an array literal holding only
-  /// strings.
-  ///
-  ///     let ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
-  ///     if ingredients.isSuperset(of: ["sugar", "salt"]) {
-  ///         print("Whatever it is, it's bound to be delicious!")
-  ///     }
-  ///     // Prints "Whatever it is, it's bound to be delicious!"
-  ///
-  /// - Parameter elements: A variadic list of elements of the new set.
-  @_inlineable // FIXME(sil-serialize-all)
-  public init(arrayLiteral elements: Element...) {
-    self.init(_nativeBuffer: _NativeSetBuffer.fromArray(elements))
-  }
-}
-
-extension Set : Sequence {
-  /// Returns an iterator over the members of the set.
-  @_inlineable // FIXME(sil-serialize-all)
-  @inline(__always)
-  public func makeIterator() -> SetIterator<Element> {
-    return _variantBuffer.makeIterator()
-  }
-
-  /// Returns a Boolean value that indicates whether the given element exists
-  /// in the set.
-  ///
-  /// This example uses the `contains(_:)` method to test whether an integer is
-  /// a member of a set of prime numbers.
-  ///
-  ///     let primes: Set = [2, 3, 5, 7]
-  ///     let x = 5
-  ///     if primes.contains(x) {
-  ///         print("\(x) is prime!")
-  ///     } else {
-  ///         print("\(x). Not prime.")
-  ///     }
-  ///     // Prints "5 is prime!"
-  ///
-  /// - Parameter member: An element to look for in the set.
-  /// - Returns: `true` if `member` exists in the set; otherwise, `false`.
-  ///
-  /// - Complexity: O(1)
-  @_inlineable // FIXME(sil-serialize-all)
-  public func contains(_ member: Element) -> Bool {
-    return _variantBuffer.maybeGet(member) != nil
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _customContainsEquatableElement(_ member: Element) -> Bool? {
-    return contains(member)
-  }
-}
-
-// This is not quite Sequence.filter, because that returns [Element], not Self
-// (RangeReplaceableCollection.filter returns Self, but Set isn't an RRC)
-extension Set {
-  /// Returns a new set containing the elements of the set that satisfy the
-  /// given predicate.
-  ///
-  /// In this example, `filter(_:)` is used to include only names shorter than
-  /// five characters.
-  ///
-  ///     let cast: Set = ["Vivien", "Marlon", "Kim", "Karl"]
-  ///     let shortNames = cast.filter { $0.count < 5 }
-  ///
-  ///     shortNames.isSubset(of: cast)
-  ///     // true
-  ///     shortNames.contains("Vivien")
-  ///     // false
-  ///
-  /// - Parameter isIncluded: A closure that takes an element as its argument
-  ///   and returns a Boolean value indicating whether the element should be
-  ///   included in the returned set.
-  /// - Returns: A set of the elements that `isIncluded` allows.
-  @_inlineable
-  @available(swift, introduced: 4.0)
-  public func filter(
-    _ isIncluded: (Element) throws -> Bool
-  ) rethrows -> Set {
-    var result = Set()
-    for element in self {
-      if try isIncluded(element) {
-        result.insert(element)
-      }
-    }
-    return result
-  }
-}
-
-extension Set : Collection {
-  /// The starting position for iterating members of the set.
-  ///
-  /// If the set is empty, `startIndex` is equal to `endIndex`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var startIndex: Index {
-    return _variantBuffer.startIndex
-  }
-
-  /// The "past the end" position for the set---that is, the position one
-  /// greater than the last valid subscript argument.
-  ///
-  /// If the set is empty, `endIndex` is equal to `startIndex`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var endIndex: Index {
-    return _variantBuffer.endIndex
-  }
-
-  /// Accesses the member at the given position.
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(position: Index) -> Element {
-    return _variantBuffer.assertingGet(position)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func index(after i: Index) -> Index {
-    return _variantBuffer.index(after: i)
-  }
-
-  // APINAMING: complexity docs are broadly missing in this file.
-
-  /// Returns the index of the given element in the set, or `nil` if the
-  /// element is not a member of the set.
-  ///
-  /// - Parameter member: An element to search for in the set.
-  /// - Returns: The index of `member` if it exists in the set; otherwise,
-  ///   `nil`.
-  ///
-  /// - Complexity: O(1)
-  @_inlineable // FIXME(sil-serialize-all)
-  public func index(of member: Element) -> Index? {
-    return _variantBuffer.index(forKey: member)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _customIndexOfEquatableElement(
-     _ member: Element
-    ) -> Index?? {
-    return Optional(index(of: member))
-  }
-
-  /// The number of elements in the set.
-  ///
-  /// - Complexity: O(1).
-  @_inlineable // FIXME(sil-serialize-all)
-  public var count: Int {
-    return _variantBuffer.count
-  }
-
-  /// A Boolean value that indicates whether the set is empty.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var isEmpty: Bool {
-    return count == 0
-  }
-
-  /// The first element of the set.
-  ///
-  /// The first element of the set is not necessarily the first element added
-  /// to the set. Don't expect any particular ordering of set elements.
-  ///
-  /// If the set is empty, the value of this property is `nil`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var first: Element? {
-    return count > 0 ? self[startIndex] : nil
-  }
-}
-  
-/// Check for both subset and equality relationship between
-/// a set and some sequence (which may itself be a `Set`).
-///
-/// (isSubset: lhs ⊂ rhs, isEqual: lhs ⊂ rhs and |lhs| = |rhs|)
-@_inlineable
-@_versioned
-internal func _compareSets<Element>(_ lhs: Set<Element>, _ rhs: Set<Element>)
-  -> (isSubset: Bool, isEqual: Bool) {
-  // FIXME(performance): performance could be better if we start by comparing
-  // counts.
-  for member in lhs {
-    if !rhs.contains(member) {
-      return (false, false)
-    }
-  }
-  return (true, lhs.count == rhs.count)
-}
-
-// FIXME: rdar://problem/23549059 (Optimize == for Set)
-// Look into initially trying to compare the two sets by directly comparing the
-// contents of both buffers in order. If they happen to have the exact same
-// ordering we can get the `true` response without ever hashing. If the two
-// buffers' contents differ at all then we have to fall back to hashing the
-// rest of the elements (but we don't need to hash any prefix that did match).
-extension Set : Equatable {
-  /// Returns a Boolean value indicating whether two sets have equal elements.
-  ///
-  /// - Parameters:
-  ///   - lhs: A set.
-  ///   - rhs: Another set.
-  /// - Returns: `true` if the `lhs` and `rhs` have the same elements; otherwise,
-  ///   `false`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public static func == (lhs: Set<Element>, rhs: Set<Element>) -> Bool {
-    switch (lhs._variantBuffer, rhs._variantBuffer) {
-    case (.native(let lhsNative), .native(let rhsNative)):
-
-      if lhsNative._storage === rhsNative._storage {
-        return true
-      }
-
-      if lhsNative.count != rhsNative.count {
-        return false
-      }
-
-      for member in lhs {
-        let (_, found) =
-          rhsNative._find(member, startBucket: rhsNative._bucket(member))
-        if !found {
-          return false
-        }
-      }
-      return true
-
-  #if _runtime(_ObjC)
-    case (_VariantSetBuffer.cocoa(let lhsCocoa),
-        _VariantSetBuffer.cocoa(let rhsCocoa)):
-      return _stdlib_NSObject_isEqual(lhsCocoa.cocoaSet, rhsCocoa.cocoaSet)
-
-    case (_VariantSetBuffer.native(let lhsNative),
-      _VariantSetBuffer.cocoa(let rhsCocoa)):
-
-      if lhsNative.count != rhsCocoa.count {
-        return false
-      }
-
-      let endIndex = lhsNative.endIndex
-      var i = lhsNative.startIndex
-      while i != endIndex {
-        let key = lhsNative.assertingGet(i)
-        let bridgedKey: AnyObject = _bridgeAnythingToObjectiveC(key)
-        let optRhsValue: AnyObject? = rhsCocoa.maybeGet(bridgedKey)
-        if let rhsValue = optRhsValue {
-          if key == _forceBridgeFromObjectiveC(rhsValue, Element.self) {
-            i = lhsNative.index(after: i)
-            continue
-          }
-        }
-        i = lhsNative.index(after: i)
-        return false
-      }
-      return true
-
-    case (_VariantSetBuffer.cocoa, _VariantSetBuffer.native):
-      return rhs == lhs
-  #endif
-    }
-  }
-}
-
-extension Set : Hashable {
-  /// The hash value for the set.
-  ///
-  /// Two sets that are equal will always have equal hash values.
-  ///
-  /// Hash values are not guaranteed to be equal across different executions of
-  /// your program. Do not save hash values to use during a future execution.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var hashValue: Int {
-    // FIXME(ABI)#177: <rdar://problem/18915294> Cache Set<T> hashValue
-    return _hashValue(for: self)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _hash(into hasher: inout _Hasher) {
-    var hash = 0
-    for member in self {
-      hash ^= _hashValue(for: member)
-    }
-    hasher.append(hash)
-  }
-}
-
-extension Set : SetAlgebra {
-
-  /// Inserts the given element in the set if it is not already present.
-  ///
-  /// If an element equal to `newMember` is already contained in the set, this
-  /// method has no effect. In the following example, a new element is
-  /// inserted into `classDays`, a set of days of the week. When an existing
-  /// element is inserted, the `classDays` set does not change.
-  ///
-  ///     enum DayOfTheWeek: Int {
-  ///         case sunday, monday, tuesday, wednesday, thursday,
-  ///             friday, saturday
-  ///     }
-  ///
-  ///     var classDays: Set<DayOfTheWeek> = [.wednesday, .friday]
-  ///     print(classDays.insert(.monday))
-  ///     // Prints "(true, .monday)"
-  ///     print(classDays)
-  ///     // Prints "[.friday, .wednesday, .monday]"
-  ///
-  ///     print(classDays.insert(.friday))
-  ///     // Prints "(false, .friday)"
-  ///     print(classDays)
-  ///     // Prints "[.friday, .wednesday, .monday]"
-  ///
-  /// - Parameter newMember: An element to insert into the set.
-  /// - Returns: `(true, newMember)` if `newMember` was not contained in the
-  ///   set. If an element equal to `newMember` was already contained in the
-  ///   set, the method returns `(false, oldMember)`, where `oldMember` is the
-  ///   element that was equal to `newMember`. In some cases, `oldMember` may
-  ///   be distinguishable from `newMember` by identity comparison or some
-  ///   other means.
-  @_inlineable // FIXME(sil-serialize-all)
-  @discardableResult
-  public mutating func insert(
-    _ newMember: Element
-  ) -> (inserted: Bool, memberAfterInsert: Element) {
-    return _variantBuffer.insert(newMember, forKey: newMember)
-  }
-
-  /// Inserts the given element into the set unconditionally.
-  ///
-  /// If an element equal to `newMember` is already contained in the set,
-  /// `newMember` replaces the existing element. In this example, an existing
-  /// element is inserted into `classDays`, a set of days of the week.
-  ///
-  ///     enum DayOfTheWeek: Int {
-  ///         case sunday, monday, tuesday, wednesday, thursday,
-  ///             friday, saturday
-  ///     }
-  ///
-  ///     var classDays: Set<DayOfTheWeek> = [.monday, .wednesday, .friday]
-  ///     print(classDays.update(with: .monday))
-  ///     // Prints "Optional(.monday)"
-  ///
-  /// - Parameter newMember: An element to insert into the set.
-  /// - Returns: An element equal to `newMember` if the set already contained
-  ///   such a member; otherwise, `nil`. In some cases, the returned element
-  ///   may be distinguishable from `newMember` by identity comparison or some
-  ///   other means.
-  @_inlineable // FIXME(sil-serialize-all)
-  @discardableResult
-  public mutating func update(with newMember: Element) -> Element? {
-    return _variantBuffer.updateValue(newMember, forKey: newMember)
-  }
-
-  /// Removes the specified element from the set.
-  ///
-  /// This example removes the element `"sugar"` from a set of ingredients.
-  ///
-  ///     var ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
-  ///     let toRemove = "sugar"
-  ///     if let removed = ingredients.remove(toRemove) {
-  ///         print("The recipe is now \(removed)-free.")
-  ///     }
-  ///     // Prints "The recipe is now sugar-free."
-  ///
-  /// - Parameter member: The element to remove from the set.
-  /// - Returns: The value of the `member` parameter if it was a member of the
-  ///   set; otherwise, `nil`.
-  @_inlineable // FIXME(sil-serialize-all)
-  @discardableResult
-  public mutating func remove(_ member: Element) -> Element? {
-    return _variantBuffer.removeValue(forKey: member)
-  }
-
-  /// Removes the element at the given index of the set.
-  ///
-  /// - Parameter position: The index of the member to remove. `position` must
-  ///   be a valid index of the set, and must not be equal to the set's end
-  ///   index.
-  /// - Returns: The element that was removed from the set.
-  @_inlineable // FIXME(sil-serialize-all)
-  @discardableResult
-  public mutating func remove(at position: Index) -> Element {
-    return _variantBuffer.remove(at: position)
-  }
-
-  /// Removes all members from the set.
-  ///
-  /// - Parameter keepingCapacity: If `true`, the set's buffer capacity is
-  ///   preserved; if `false`, the underlying buffer is released. The
-  ///   default is `false`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
-    _variantBuffer.removeAll(keepingCapacity: keepCapacity)
-  }
-
-  /// Removes the first element of the set.
-  ///
-  /// Because a set is not an ordered collection, the "first" element may not
-  /// be the first element that was added to the set. The set must not be
-  /// empty.
-  ///
-  /// - Complexity: Amortized O(1) if the set does not wrap a bridged `NSSet`.
-  ///   If the set wraps a bridged `NSSet`, the performance is unspecified.
-  ///
-  /// - Returns: A member of the set.
-  @_inlineable // FIXME(sil-serialize-all)
-  @discardableResult
-  public mutating func removeFirst() -> Element {
-    _precondition(!isEmpty, "Can't removeFirst from an empty Set")
-    return remove(at: startIndex)
-  }
-
-  //
-  // APIs below this comment should be implemented strictly in terms of
-  // *public* APIs above.  `_variantBuffer` should not be accessed directly.
-  //
-  // This separates concerns for testing.  Tests for the following APIs need
-  // not to concern themselves with testing correctness of behavior of
-  // underlying buffer (and different variants of it), only correctness of the
-  // API itself.
-  //
-
-  /// Creates an empty set.
-  ///
-  /// This is equivalent to initializing with an empty array literal. For
-  /// example:
-  ///
-  ///     var emptySet = Set<Int>()
-  ///     print(emptySet.isEmpty)
-  ///     // Prints "true"
-  ///
-  ///     emptySet = []
-  ///     print(emptySet.isEmpty)
-  ///     // Prints "true"
-  @_inlineable // FIXME(sil-serialize-all)
-  public init() {
-    self = Set<Element>(_nativeBuffer: _NativeBuffer())
-  }
-
-  /// Creates a new set from a finite sequence of items.
-  ///
-  /// Use this initializer to create a new set from an existing sequence, for
-  /// example, an array or a range.
-  ///
-  ///     let validIndices = Set(0..<7).subtracting([2, 4, 5])
-  ///     print(validIndices)
-  ///     // Prints "[6, 0, 1, 3]"
-  ///
-  /// This initializer can also be used to restore set methods after performing
-  /// sequence operations such as `filter(_:)` or `map(_:)` on a set. For
-  /// example, after filtering a set of prime numbers to remove any below 10,
-  /// you can create a new set by using this initializer.
-  ///
-  ///     let primes: Set = [2, 3, 5, 7, 11, 13, 17, 19, 23]
-  ///     let laterPrimes = Set(primes.lazy.filter { $0 > 10 })
-  ///     print(laterPrimes)
-  ///     // Prints "[17, 19, 23, 11, 13]"
-  ///
-  /// - Parameter sequence: The elements to use as members of the new set.
-  @_inlineable // FIXME(sil-serialize-all)
-  public init<Source : Sequence>(_ sequence: Source)
-    where Source.Element == Element {
-    self.init(minimumCapacity: sequence.underestimatedCount)
-    if let s = sequence as? Set<Element> {
-      // If this sequence is actually a native `Set`, then we can quickly
-      // adopt its native buffer and let COW handle uniquing only
-      // if necessary.
-      switch s._variantBuffer {
-        case .native(let buffer):
-          _variantBuffer = .native(buffer)
-#if _runtime(_ObjC)
-        case .cocoa(let owner):
-          _variantBuffer = .cocoa(owner)
-#endif
-      }
-    } else {
-      for item in sequence {
-        insert(item)
-      }
-    }
-  }
-
-  /// Returns a Boolean value that indicates whether the set is a subset of the
-  /// given sequence.
-  ///
-  /// Set *A* is a subset of another set *B* if every member of *A* is also a
-  /// member of *B*.
-  ///
-  ///     let employees = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
-  ///     print(attendees.isSubset(of: employees))
-  ///     // Prints "true"
-  ///
-  /// - Parameter possibleSuperset: A sequence of elements. `possibleSuperset`
-  ///   must be finite.
-  /// - Returns: `true` if the set is a subset of `possibleSuperset`;
-  ///   otherwise, `false`.
-  @_inlineable
-  public func isSubset<S : Sequence>(of possibleSuperset: S) -> Bool
-    where S.Element == Element {
-    // FIXME(performance): isEmpty fast path, here and elsewhere.
-    let other = Set(possibleSuperset)
-    return isSubset(of: other)
-  }
-
-  /// Returns a Boolean value that indicates whether the set is a strict subset
-  /// of the given sequence.
-  ///
-  /// Set *A* is a strict subset of another set *B* if every member of *A* is
-  /// also a member of *B* and *B* contains at least one element that is not a
-  /// member of *A*.
-  ///
-  ///     let employees = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
-  ///     print(attendees.isStrictSubset(of: employees))
-  ///     // Prints "true"
-  ///
-  ///     // A set is never a strict subset of itself:
-  ///     print(attendees.isStrictSubset(of: attendees))
-  ///     // Prints "false"
-  ///
-  /// - Parameter possibleStrictSuperset: A sequence of elements.
-  ///   `possibleStrictSuperset` must be finite.
-  /// - Returns: `true` is the set is strict subset of
-  ///   `possibleStrictSuperset`; otherwise, `false`.
-  @_inlineable
-  public func isStrictSubset<S : Sequence>(of possibleStrictSuperset: S) -> Bool
-    where S.Element == Element {
-    // FIXME: code duplication.
-    let other = Set(possibleStrictSuperset)
-    return isStrictSubset(of: other)
-  }
-
-  /// Returns a Boolean value that indicates whether the set is a superset of
-  /// the given sequence.
-  ///
-  /// Set *A* is a superset of another set *B* if every member of *B* is also a
-  /// member of *A*.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let attendees = ["Alicia", "Bethany", "Diana"]
-  ///     print(employees.isSuperset(of: attendees))
-  ///     // Prints "true"
-  ///
-  /// - Parameter possibleSubset: A sequence of elements. `possibleSubset` must
-  ///   be finite.
-  /// - Returns: `true` if the set is a superset of `possibleSubset`;
-  ///   otherwise, `false`.
-  @_inlineable
-  public func isSuperset<S : Sequence>(of possibleSubset: S) -> Bool
-    where S.Element == Element {
-    // FIXME(performance): Don't build a set; just ask if every element is in
-    // `self`.
-    let other = Set(possibleSubset)
-    return other.isSubset(of: self)
-  }
-
-  /// Returns a Boolean value that indicates whether the set is a strict
-  /// superset of the given sequence.
-  ///
-  /// Set *A* is a strict superset of another set *B* if every member of *B* is
-  /// also a member of *A* and *A* contains at least one element that is *not*
-  /// a member of *B*.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let attendees = ["Alicia", "Bethany", "Diana"]
-  ///     print(employees.isStrictSuperset(of: attendees))
-  ///     // Prints "true"
-  ///     print(employees.isStrictSuperset(of: employees))
-  ///     // Prints "false"
-  ///
-  /// - Parameter possibleStrictSubset: A sequence of elements.
-  ///   `possibleStrictSubset` must be finite.
-  /// - Returns: `true` if the set is a strict superset of
-  ///   `possibleStrictSubset`; otherwise, `false`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public func isStrictSuperset<S : Sequence>(of possibleStrictSubset: S) -> Bool
-    where S.Element == Element {
-    let other = Set(possibleStrictSubset)
-    return other.isStrictSubset(of: self)
-  }
-
-  /// Returns a Boolean value that indicates whether the set has no members in
-  /// common with the given sequence.
-  ///
-  /// In the following example, the `employees` set is disjoint with the
-  /// elements of the `visitors` array because no name appears in both.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let visitors = ["Marcia", "Nathaniel", "Olivia"]
-  ///     print(employees.isDisjoint(with: visitors))
-  ///     // Prints "true"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  /// - Returns: `true` if the set has no elements in common with `other`;
-  ///   otherwise, `false`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public func isDisjoint<S : Sequence>(with other: S) -> Bool
-    where S.Element == Element {
-    // FIXME(performance): Don't need to build a set.
-    let otherSet = Set(other)
-    return isDisjoint(with: otherSet)
-  }
-
-  /// Returns a new set with the elements of both this set and the given
-  /// sequence.
-  ///
-  /// In the following example, the `attendeesAndVisitors` set is made up
-  /// of the elements of the `attendees` set and the `visitors` array:
-  ///
-  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
-  ///     let visitors = ["Marcia", "Nathaniel"]
-  ///     let attendeesAndVisitors = attendees.union(visitors)
-  ///     print(attendeesAndVisitors)
-  ///     // Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"
-  ///
-  /// If the set already contains one or more elements that are also in
-  /// `other`, the existing members are kept. If `other` contains multiple
-  /// instances of equivalent elements, only the first instance is kept.
-  ///
-  ///     let initialIndices = Set(0..<5)
-  ///     let expandedIndices = initialIndices.union([2, 3, 6, 6, 7, 7])
-  ///     print(expandedIndices)
-  ///     // Prints "[2, 4, 6, 7, 0, 1, 3]"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  /// - Returns: A new set with the unique elements of this set and `other`.
-  @_inlineable
-  public func union<S : Sequence>(_ other: S) -> Set<Element>
-    where S.Element == Element {
-    var newSet = self
-    newSet.formUnion(other)
-    return newSet
-  }
-
-  /// Inserts the elements of the given sequence into the set.
-  ///
-  /// If the set already contains one or more elements that are also in
-  /// `other`, the existing members are kept. If `other` contains multiple
-  /// instances of equivalent elements, only the first instance is kept.
-  ///
-  ///     var attendees: Set = ["Alicia", "Bethany", "Diana"]
-  ///     let visitors = ["Diana", "Marcia", "Nathaniel"]
-  ///     attendees.formUnion(visitors)
-  ///     print(attendees)
-  ///     // Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  @_inlineable
-  public mutating func formUnion<S : Sequence>(_ other: S)
-    where S.Element == Element {
-    for item in other {
-      insert(item)
-    }
-  }
-
-  /// Returns a new set containing the elements of this set that do not occur
-  /// in the given sequence.
-  ///
-  /// In the following example, the `nonNeighbors` set is made up of the
-  /// elements of the `employees` set that are not elements of `neighbors`:
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
-  ///     let nonNeighbors = employees.subtracting(neighbors)
-  ///     print(nonNeighbors)
-  ///     // Prints "["Chris", "Diana", "Alicia"]"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  /// - Returns: A new set.
-  @_inlineable
-  public func subtracting<S : Sequence>(_ other: S) -> Set<Element>
-    where S.Element == Element {
-    return self._subtracting(other)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned
-  internal func _subtracting<S : Sequence>(_ other: S) -> Set<Element>
-    where S.Element == Element {
-    var newSet = self
-    newSet.subtract(other)
-    return newSet
-  }
-
-  /// Removes the elements of the given sequence from the set.
-  ///
-  /// In the following example, the elements of the `employees` set that are
-  /// also elements of the `neighbors` array are removed. In particular, the
-  /// names `"Bethany"` and `"Eric"` are removed from `employees`.
-  ///
-  ///     var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
-  ///     employees.subtract(neighbors)
-  ///     print(employees)
-  ///     // Prints "["Chris", "Diana", "Alicia"]"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func subtract<S : Sequence>(_ other: S)
-    where S.Element == Element {
-    _subtract(other)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal mutating func _subtract<S : Sequence>(_ other: S)
-    where S.Element == Element {
-    for item in other {
-      remove(item)
-    }
-  }
-
-  /// Returns a new set with the elements that are common to both this set and
-  /// the given sequence.
-  ///
-  /// In the following example, the `bothNeighborsAndEmployees` set is made up
-  /// of the elements that are in *both* the `employees` and `neighbors` sets.
-  /// Elements that are in only one or the other are left out of the result of
-  /// the intersection.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
-  ///     let bothNeighborsAndEmployees = employees.intersection(neighbors)
-  ///     print(bothNeighborsAndEmployees)
-  ///     // Prints "["Bethany", "Eric"]"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  /// - Returns: A new set.
-  @_inlineable
-  public func intersection<S : Sequence>(_ other: S) -> Set<Element>
-    where S.Element == Element {
-    let otherSet = Set(other)
-    return intersection(otherSet)
-  }
-
-  /// Removes the elements of the set that aren't also in the given sequence.
-  ///
-  /// In the following example, the elements of the `employees` set that are
-  /// not also members of the `neighbors` set are removed. In particular, the
-  /// names `"Alicia"`, `"Chris"`, and `"Diana"` are removed.
-  ///
-  ///     var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
-  ///     employees.formIntersection(neighbors)
-  ///     print(employees)
-  ///     // Prints "["Bethany", "Eric"]"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  @_inlineable
-  public mutating func formIntersection<S : Sequence>(_ other: S)
-    where S.Element == Element {
-    // Because `intersect` needs to both modify and iterate over
-    // the left-hand side, the index may become invalidated during
-    // traversal so an intermediate set must be created.
-    //
-    // FIXME(performance): perform this operation at a lower level
-    // to avoid invalidating the index and avoiding a copy.
-    let result = self.intersection(other)
-
-    // The result can only have fewer or the same number of elements.
-    // If no elements were removed, don't perform a reassignment
-    // as this may cause an unnecessary uniquing COW.
-    if result.count != count {
-      self = result
-    }
-  }
-
-  /// Returns a new set with the elements that are either in this set or in the
-  /// given sequence, but not in both.
-  ///
-  /// In the following example, the `eitherNeighborsOrEmployees` set is made up
-  /// of the elements of the `employees` and `neighbors` sets that are not in
-  /// both `employees` *and* `neighbors`. In particular, the names `"Bethany"`
-  /// and `"Eric"` do not appear in `eitherNeighborsOrEmployees`.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Diana", "Eric"]
-  ///     let neighbors = ["Bethany", "Eric", "Forlani"]
-  ///     let eitherNeighborsOrEmployees = employees.symmetricDifference(neighbors)
-  ///     print(eitherNeighborsOrEmployees)
-  ///     // Prints "["Diana", "Forlani", "Alicia"]"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  /// - Returns: A new set.
-  @_inlineable
-  public func symmetricDifference<S : Sequence>(_ other: S) -> Set<Element>
-    where S.Element == Element {
-    var newSet = self
-    newSet.formSymmetricDifference(other)
-    return newSet
-  }
-
-  /// Replace this set with the elements contained in this set or the given
-  /// set, but not both.
-  ///
-  /// In the following example, the elements of the `employees` set that are
-  /// also members of `neighbors` are removed from `employees`, while the
-  /// elements of `neighbors` that are not members of `employees` are added to
-  /// `employees`. In particular, the names `"Bethany"` and `"Eric"` are
-  /// removed from `employees` while the name `"Forlani"` is added.
-  ///
-  ///     var employees: Set = ["Alicia", "Bethany", "Diana", "Eric"]
-  ///     let neighbors = ["Bethany", "Eric", "Forlani"]
-  ///     employees.formSymmetricDifference(neighbors)
-  ///     print(employees)
-  ///     // Prints "["Diana", "Forlani", "Alicia"]"
-  ///
-  /// - Parameter other: A sequence of elements. `other` must be finite.
-  @_inlineable
-  public mutating func formSymmetricDifference<S : Sequence>(_ other: S)
-    where S.Element == Element {
-    let otherSet = Set(other)
-    formSymmetricDifference(otherSet)
-  }
-}
-
-extension Set : CustomStringConvertible, CustomDebugStringConvertible {
-  /// A string that represents the contents of the set.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var description: String {
-    return _makeCollectionDescription(for: self, withTypeName: nil)
-  }
-
-  /// A string that represents the contents of the set, suitable for debugging.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var debugDescription: String {
-    return _makeCollectionDescription(for: self, withTypeName: "Set")
-  }
-}
-
-#if _runtime(_ObjC)
-@_silgen_name("swift_stdlib_CFSetGetValues")
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-internal
-func _stdlib_CFSetGetValues(_ nss: _NSSet, _: UnsafeMutablePointer<AnyObject>)
-
-/// Equivalent to `NSSet.allObjects`, but does not leave objects on the
-/// autorelease pool.
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-internal func _stdlib_NSSet_allObjects(_ nss: _NSSet) ->
-  _HeapBuffer<Int, AnyObject> {
-  let count = nss.count
-  let storage = _HeapBuffer<Int, AnyObject>(
-    _HeapBufferStorage<Int, AnyObject>.self, count, count)
-  _stdlib_CFSetGetValues(nss, storage.baseAddress)
-  return storage
-}
-#endif
-
-//===--- Compiler conversion/casting entry points for Set<Element> --------===//
-
-/// Perform a non-bridged upcast that always succeeds.
-///
-/// - Precondition: `BaseValue` is a base class or base `@objc`
-///   protocol (such as `AnyObject`) of `DerivedValue`.
-@_inlineable // FIXME(sil-serialize-all)
-public func _setUpCast<DerivedValue, BaseValue>(_ source: Set<DerivedValue>)
-  -> Set<BaseValue> {
-  var builder = _SetBuilder<BaseValue>(count: source.count)
-  for x in source {
-    builder.add(member: x as! BaseValue)
-  }
-  return builder.take()
-}
-
-#if _runtime(_ObjC)
-
-/// Implements an unconditional upcast that involves bridging.
-///
-/// The cast can fail if bridging fails.
-///
-/// - Precondition: `SwiftValue` is bridged to Objective-C
-///   and requires non-trivial bridging.
-@_inlineable // FIXME(sil-serialize-all)
-public func _setBridgeToObjectiveC<SwiftValue, ObjCValue>(
-  _ source: Set<SwiftValue>
-) -> Set<ObjCValue> {
-  _sanityCheck(_isClassOrObjCExistential(ObjCValue.self))
-  _sanityCheck(!_isBridgedVerbatimToObjectiveC(SwiftValue.self))
-
-  var result = Set<ObjCValue>(minimumCapacity: source.count)
-  let valueBridgesDirectly =
-    _isBridgedVerbatimToObjectiveC(SwiftValue.self) ==
-    _isBridgedVerbatimToObjectiveC(ObjCValue.self)
-
-  for member in source {
-    var bridgedMember: ObjCValue
-    if valueBridgesDirectly {
-      bridgedMember = unsafeBitCast(member, to: ObjCValue.self)
-    } else {
-      let bridged: AnyObject = _bridgeAnythingToObjectiveC(member)
-      bridgedMember = unsafeBitCast(bridged, to: ObjCValue.self)
-    }
-    result.insert(bridgedMember)
-  }
-  return result
-}
-
-#endif
-
-/// Called by the casting machinery.
-@_silgen_name("_swift_setDownCastIndirect")
-internal func _setDownCastIndirect<SourceValue, TargetValue>(
-  _ source: UnsafePointer<Set<SourceValue>>,
-  _ target: UnsafeMutablePointer<Set<TargetValue>>) {
-  target.initialize(to: _setDownCast(source.pointee))
-}
-
-/// Implements a forced downcast.  This operation should have O(1) complexity.
-///
-/// The cast can fail if bridging fails.  The actual checks and bridging can be
-/// deferred.
-///
-/// - Precondition: `DerivedValue` is a subtype of `BaseValue` and both
-///   are reference types.
-@_inlineable // FIXME(sil-serialize-all)
-public func _setDownCast<BaseValue, DerivedValue>(_ source: Set<BaseValue>)
-  -> Set<DerivedValue> {
-
-#if _runtime(_ObjC)
-  if _isClassOrObjCExistential(BaseValue.self)
-  && _isClassOrObjCExistential(DerivedValue.self) {
-    switch source._variantBuffer {
-    case _VariantSetBuffer.native(let buffer):
-      return Set(_immutableCocoaSet: buffer.bridged())
-    case _VariantSetBuffer.cocoa(let cocoaBuffer):
-      return Set(_immutableCocoaSet: cocoaBuffer.cocoaSet)
-    }
-  }
-#endif
-  return _setDownCastConditional(source)!
-}
-
-/// Called by the casting machinery.
-@_silgen_name("_swift_setDownCastConditionalIndirect")
-internal func _setDownCastConditionalIndirect<SourceValue, TargetValue>(
-  _ source: UnsafePointer<Set<SourceValue>>,
-  _ target: UnsafeMutablePointer<Set<TargetValue>>
-) -> Bool {
-  if let result: Set<TargetValue> = _setDownCastConditional(source.pointee) {
-    target.initialize(to: result)
-    return true
-  }
-  return false
-}
-
-/// Implements a conditional downcast.
-///
-/// If the cast fails, the function returns `nil`.  All checks should be
-/// performed eagerly.
-///
-/// - Precondition: `DerivedValue` is a subtype of `BaseValue` and both
-///   are reference types.
-@_inlineable // FIXME(sil-serialize-all)
-public func _setDownCastConditional<BaseValue, DerivedValue>(
-  _ source: Set<BaseValue>
-) -> Set<DerivedValue>? {
-  var result = Set<DerivedValue>(minimumCapacity: source.count)
-  for member in source {
-    if let derivedMember = member as? DerivedValue {
-      result.insert(derivedMember)
-      continue
-    }
-    return nil
-  }
-  return result
-}
-
-#if _runtime(_ObjC)
-
-/// Implements an unconditional downcast that involves bridging.
-///
-/// - Precondition: At least one of `SwiftValue` is a bridged value
-///   type, and the corresponding `ObjCValue` is a reference type.
-@_inlineable // FIXME(sil-serialize-all)
-public func _setBridgeFromObjectiveC<ObjCValue, SwiftValue>(
-  _ source: Set<ObjCValue>
-) -> Set<SwiftValue> {
-  let result: Set<SwiftValue>? = _setBridgeFromObjectiveCConditional(source)
-  _precondition(result != nil, "This set cannot be bridged from Objective-C")
-  return result!
-}
-
-/// Implements a conditional downcast that involves bridging.
-///
-/// If the cast fails, the function returns `nil`.  All checks should be
-/// performed eagerly.
-///
-/// - Precondition: At least one of `SwiftValue` is a bridged value
-///   type, and the corresponding `ObjCValue` is a reference type.
-@_inlineable // FIXME(sil-serialize-all)
-public func _setBridgeFromObjectiveCConditional<
-  ObjCValue, SwiftValue
->(
-  _ source: Set<ObjCValue>
-) -> Set<SwiftValue>? {
-  _sanityCheck(_isClassOrObjCExistential(ObjCValue.self))
-  _sanityCheck(!_isBridgedVerbatimToObjectiveC(SwiftValue.self))
-
-  let valueBridgesDirectly =
-    _isBridgedVerbatimToObjectiveC(SwiftValue.self) ==
-      _isBridgedVerbatimToObjectiveC(ObjCValue.self)
-
-  var result = Set<SwiftValue>(minimumCapacity: source.count)
-  for value in source {
-    // Downcast the value.
-    var resultValue: SwiftValue
-    if valueBridgesDirectly {
-      if let bridgedValue = value as? SwiftValue {
-        resultValue = bridgedValue
-      } else {
-        return nil
-      }
-    } else {
-      if let bridgedValue = _conditionallyBridgeFromObjectiveC(
-          _reinterpretCastToAnyObject(value), SwiftValue.self) {
-        resultValue = bridgedValue
-      } else {
-        return nil
-      }
-    }
-    result.insert(resultValue)
-  }
-  return result
-}
-
-#endif
-
 //===--- APIs unique to Dictionary<Key, Value> ----------------------------===//
 
 /// A collection whose elements are key-value pairs.
@@ -1725,7 +380,7 @@
 /// optimization that is used when two instances of `Dictionary` share
 /// buffer.
 @_fixed_layout
-public struct Dictionary<Key : Hashable, Value> {
+public struct Dictionary<Key: Hashable, Value> {
 
   internal typealias _Self = Dictionary<Key, Value>
   internal typealias _VariantBuffer = _VariantDictionaryBuffer<Key, Value>
@@ -1906,7 +561,7 @@
 // additional processing.
 //
 
-extension Dictionary : Sequence {
+extension Dictionary: Sequence {
   /// Returns an iterator over the dictionary's key-value pairs.
   ///
   /// Iterating over a dictionary yields the key-value pairs as two-element
@@ -2036,6 +691,31 @@
   public subscript(position: Index) -> Element {
     return _variantBuffer.assertingGet(position)
   }
+
+  /// The number of key-value pairs in the dictionary.
+  ///
+  /// - Complexity: O(1).
+  @_inlineable // FIXME(sil-serialize-all)
+  public var count: Int {
+    return _variantBuffer.count
+  }
+
+  //
+  // `Sequence` conformance
+  //
+
+  /// A Boolean value that indicates whether the dictionary is empty.
+  ///
+  /// Dictionaries are empty when created with an initializer or an empty
+  /// dictionary literal.
+  ///
+  ///     var frequencies: [String: Int] = [:]
+  ///     print(frequencies.isEmpty)
+  ///     // Prints "true"
+  @_inlineable // FIXME(sil-serialize-all)
+  public var isEmpty: Bool {
+    return count == 0
+  }
 }
 
 extension Dictionary {
@@ -2100,35 +780,9 @@
       }
     }
   }
-  
-  
-  /// The number of key-value pairs in the dictionary.
-  ///
-  /// - Complexity: O(1).
-  @_inlineable // FIXME(sil-serialize-all)
-  public var count: Int {
-    return _variantBuffer.count
-  }
-
-  //
-  // `Sequence` conformance
-  //
-
-  /// A Boolean value that indicates whether the dictionary is empty.
-  ///
-  /// Dictionaries are empty when created with an initializer or an empty
-  /// dictionary literal.
-  ///
-  ///     var frequencies: [String: Int] = [:]
-  ///     print(frequencies.isEmpty)
-  ///     // Prints "true"
-  @_inlineable // FIXME(sil-serialize-all)
-  public var isEmpty: Bool {
-    return count == 0
-  }
 }
 
-extension Dictionary : ExpressibleByDictionaryLiteral {
+extension Dictionary: ExpressibleByDictionaryLiteral {
   /// Creates a dictionary initialized with a dictionary literal.
   ///
   /// Do not call this initializer directly. It is called by the compiler to
@@ -2474,7 +1128,7 @@
   public var keys: LazyMapCollection<[Key: Value], Key> {
     return self.lazy.map { $0.key }
   }
-  
+
   /// A collection containing just the values of the dictionary.
   ///
   /// When iterated over, values appear in this collection in the same order as
@@ -2719,9 +1373,9 @@
   }
 }
 
-extension Dictionary : Equatable where Value : Equatable {
+extension Dictionary: Equatable where Value: Equatable {
   @_inlineable // FIXME(sil-serialize-all)
-  public static func == (lhs: [Key : Value], rhs: [Key : Value]) -> Bool {
+  public static func == (lhs: [Key: Value], rhs: [Key: Value]) -> Bool {
     switch (lhs._variantBuffer, rhs._variantBuffer) {
     case (.native(let lhsNative), .native(let rhsNative)):
 
@@ -2787,12 +1441,12 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public static func != (lhs: [Key : Value], rhs: [Key : Value]) -> Bool {
+  public static func != (lhs: [Key: Value], rhs: [Key: Value]) -> Bool {
     return !(lhs == rhs)
   }
 }
 
-extension Dictionary : CustomStringConvertible, CustomDebugStringConvertible {
+extension Dictionary: CustomStringConvertible, CustomDebugStringConvertible {
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func _makeDescription() -> String {
@@ -2832,7 +1486,7 @@
 
 @_versioned // FIXME(sil-serialize-all)
 @_frozen // FIXME(sil-serialize-all)
-internal enum _MergeError : Error {
+internal enum _MergeError: Error {
   case keyCollision
 }
 
@@ -3093,49 +1747,10 @@
   return result
 }
 #endif
+
 //===--- APIs templated for Dictionary and Set ----------------------------===//
 
-%{
-# Tuple items:
-# Self: Class name
-#
-# a_self: Type name when using a generic noun
-#
-# element: English description of an element
-#
-# TypeParametersDecl: Generic parameters appearing in top-level declarations
-#
-# TypeParameters: Generic parameters appearing in typealiases, etc.
-#
-# AnyTypeParameters: Generic parameters where all variables are AnyObject
-#
-# Sequence: The type of things appearing in the collection as a sequence
-#                 e.g. dictionaries are a sequence of (Key, Value) pairs.
-# AnySequenceType: The same as Sequence but everything is an AnyObject.
-collections = [
-  ('Set',
-   'set',
-   'element',
-   'Element : Hashable',
-   'Element',
-   'AnyObject',
-   'Element',
-   'AnyObject'),
-
-  ('Dictionary',
-   'dictionary',
-   'key-value pair',
-   'Key : Hashable, Value',
-   'Key, Value',
-   'AnyObject, AnyObject',
-   '(key: Key, value: Value)',
-   '(AnyObject, AnyObject)'),
-]
-}%
-
-% for (Self, a_self, element, TypeParametersDecl, TypeParameters, AnyTypeParameters, Sequence, AnySequenceType) in collections:
-
-/// An instance of this class has all `${Self}` data tail-allocated.
+/// An instance of this class has all `Dictionary` data tail-allocated.
 /// Enough bytes are allocated to hold the bitmap for marking valid entries,
 /// keys, and values. The data layout starts with the bitmap, followed by the
 /// keys, followed by the values.
@@ -3143,15 +1758,15 @@
 // See the docs at the top of the file for more details on this type
 //
 // NOTE: The precise layout of this type is relied on in the runtime
-// to provide a statically allocated empty singleton. 
+// to provide a statically allocated empty singleton.
 // See stdlib/public/stubs/GlobalObjects.cpp for details.
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned // FIXME(sil-serialize-all)
 @_objc_non_lazy_realization
-internal class _RawNative${Self}Storage:
-  _SwiftNativeNS${Self}, _NS${Self}Core
+internal class _RawNativeDictionaryStorage
+  : _SwiftNativeNSDictionary, _NSDictionaryCore
 {
-  internal typealias RawStorage = _RawNative${Self}Storage
+  internal typealias RawStorage = _RawNativeDictionaryStorage
 
   @_versioned // FIXME(sil-serialize-all)
   @nonobjc
@@ -3166,11 +1781,9 @@
   @_versioned // FIXME(sil-serialize-all)
   @nonobjc
   internal final var keys: UnsafeMutableRawPointer
-% if Self == 'Dictionary':
   @_versioned // FIXME(sil-serialize-all)
   @nonobjc
   internal final var values: UnsafeMutableRawPointer
-% end
 
   @_versioned // FIXME(sil-serialize-all)
   internal final var seed: (UInt64, UInt64)
@@ -3192,7 +1805,7 @@
   @nonobjc
   internal static var empty: RawStorage {
     return Builtin.bridgeFromRawPointer(
-      Builtin.addressof(&_swiftEmpty${Self}Storage))
+      Builtin.addressof(&_swiftEmptyDictionaryStorage))
   }
 
   // This type is made with allocWithTailElems, so no init is ever called.
@@ -3206,18 +1819,18 @@
 
 #if _runtime(_ObjC)
   //
-  // NS${Self} implementation, assuming Self is the empty singleton
+  // NSDictionary implementation, assuming Self is the empty singleton
   //
 
   /// Get the NSEnumerator implementation for self.
-  /// _HashableTypedNative${Self}Storage overloads this to give 
+  /// _HashableTypedNativeDictionaryStorage overloads this to give
   /// _NativeSelfNSEnumerator proper type parameters.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @objc
   internal func enumerator() -> _NSEnumerator {
-    return _Native${Self}NSEnumerator<${AnyTypeParameters}>(
-        _Native${Self}Buffer(_storage: self))
+    return _NativeDictionaryNSEnumerator<AnyObject, AnyObject>(
+        _NativeDictionaryBuffer(_storage: self))
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -3236,7 +1849,7 @@
   ) -> Int {
     // Even though we never do anything in here, we need to update the
     // state so that callers know we actually ran.
-    
+
     var theState = state.pointee
     if theState.state == 0 {
       theState.state = 1 // Arbitrary non-zero value.
@@ -3244,35 +1857,10 @@
       theState.mutationsPtr = _fastEnumerationStorageMutationsPtr
     }
     state.pointee = theState
-    
+
     return 0
   }
 
-%if Self == 'Set':
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  internal required init(objects: UnsafePointer<AnyObject?>, count: Int) {
-    _sanityCheckFailure("don't call this designated initializer")
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  internal func member(_ object: AnyObject) -> AnyObject? {
-    return nil
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  internal func objectEnumerator() -> _NSEnumerator {
-    return enumerator()
-  }
-  
-%elif Self == 'Dictionary':
-
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @objc
@@ -3303,27 +1891,18 @@
     andKeys keys: UnsafeMutablePointer<AnyObject>?) {
     // Do nothing, we're empty
   }
-
-%end
 #endif
 }
 
 // See the docs at the top of this file for a description of this type
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned
-internal class _TypedNative${Self}Storage<${TypeParameters}> :
-  _RawNative${Self}Storage {
-
-%if Self == 'Set': # Set needs these to keep signatures simple.
-  internal typealias Key = ${TypeParameters}
-  internal typealias Value = ${TypeParameters}
-%end
+internal class _TypedNativeDictionaryStorage<Key, Value>
+  : _RawNativeDictionaryStorage {
 
   deinit {
     let keys = self.keys.assumingMemoryBound(to: Key.self)
-%if Self == 'Dictionary':
     let values = self.values.assumingMemoryBound(to: Value.self)
-%end
 
     if !_isPOD(Key.self) {
       for i in 0 ..< bucketCount {
@@ -3333,7 +1912,6 @@
       }
     }
 
-%if Self == 'Dictionary':
     if !_isPOD(Value.self) {
       for i in 0 ..< bucketCount {
         if initializedEntries[i] {
@@ -3341,7 +1919,6 @@
         }
       }
     }
-%end
     _fixLifetime(self)
   }
 
@@ -3355,14 +1932,6 @@
   }
 
 #if _runtime(_ObjC)
-%if Self == 'Set':
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  internal required init(objects: UnsafePointer<AnyObject?>, count: Int) {
-    _sanityCheckFailure("don't call this designated initializer")
-  }
-%elif Self == 'Dictionary':
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @objc
@@ -3373,19 +1942,17 @@
   ) {
     _sanityCheckFailure("don't call this designated initializer")
   }
-%end
 #endif
 }
 
-
 // See the docs at the top of this file for a description of this type
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned
-final internal class _HashableTypedNative${Self}Storage<${TypeParametersDecl}> :
-  _TypedNative${Self}Storage<${TypeParameters}> {
+final internal class _HashableTypedNativeDictionaryStorage<Key: Hashable, Value>
+  : _TypedNativeDictionaryStorage<Key, Value> {
 
-  internal typealias FullContainer = ${Self}<${TypeParameters}>
-  internal typealias Buffer = _Native${Self}Buffer<${TypeParameters}>
+  internal typealias FullContainer = Dictionary<Key, Value>
+  internal typealias Buffer = _NativeDictionaryBuffer<Key, Value>
 
   // This type is made with allocWithTailElems, so no init is ever called.
   // But we still need to have an init to satisfy the compiler.
@@ -3396,13 +1963,12 @@
     _sanityCheckFailure("Only create this by calling Buffer's inits'")
   }
 
-  
 #if _runtime(_ObjC)
-  // NS${Self} bridging:
+  // NSDictionary bridging:
 
   // All actual functionality comes from buffer/full, which are
-  // just wrappers around a RawNative${Self}Storage.
-  
+  // just wrappers around a RawNativeDictionaryStorage.
+
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal var buffer: Buffer {
@@ -3418,7 +1984,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal override func enumerator() -> _NSEnumerator {
-    return _Native${Self}NSEnumerator<${TypeParameters}>(
+    return _NativeDictionaryNSEnumerator<Key, Value>(
         Buffer(_storage: self))
   }
 
@@ -3445,7 +2011,7 @@
     }
 
     let unmanagedObjects = _UnmanagedAnyObjectArray(objects!)
-    var currIndex = _Native${Self}Index<${TypeParameters}>(
+    var currIndex = _NativeDictionaryIndex<Key, Value>(
         offset: Int(theState.extra.0))
     let endIndex = buffer.endIndex
     var stored = 0
@@ -3455,7 +2021,7 @@
       }
 
       unmanagedObjects[i] = buffer.bridgedKey(at: currIndex)
-      
+
       stored += 1
       buffer.formIndex(after: &currIndex)
     }
@@ -3471,7 +2037,7 @@
     guard let nativeKey = _conditionallyBridgeFromObjectiveC(aKey, Key.self)
     else { return nil }
 
-    let (i, found) = buffer._find(nativeKey, 
+    let (i, found) = buffer._find(nativeKey,
         startBucket: buffer._bucket(nativeKey))
 
     if found {
@@ -3480,24 +2046,6 @@
     return nil
   }
 
-%if Self == 'Set':
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  internal required init(objects: UnsafePointer<AnyObject?>, count: Int) {
-    _sanityCheckFailure("don't call this designated initializer")
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  override internal func member(_ object: AnyObject) -> AnyObject? {
-    return getObjectFor(object)
-  }
-
-%elif Self == 'Dictionary':
-  
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @objc
@@ -3547,36 +2095,28 @@
       }
     }
   }
-%end
 #endif
 }
 
-
-/// A wrapper around _RawNative${Self}Storage that provides most of the 
-/// implementation of ${Self}.
+/// A wrapper around _RawNativeDictionaryStorage that provides most of the
+/// implementation of Dictionary.
 ///
 /// This type and most of its functionality doesn't require Hashable at all.
 /// The reason for this is to support storing AnyObject for bridging
-/// with _SwiftDeferredNS${Self}. What functionality actually relies on
+/// with _SwiftDeferredNSDictionary. What functionality actually relies on
 /// Hashable can be found in an extension.
 @_versioned
 @_fixed_layout
-internal struct _Native${Self}Buffer<${TypeParameters}> {
+internal struct _NativeDictionaryBuffer<Key, Value> {
 
-  internal typealias RawStorage = _RawNative${Self}Storage
-  internal typealias TypedStorage = _TypedNative${Self}Storage<${TypeParameters}>
-  internal typealias Buffer = _Native${Self}Buffer<${TypeParameters}>
-  internal typealias Index = _Native${Self}Index<${TypeParameters}>
+  internal typealias RawStorage = _RawNativeDictionaryStorage
+  internal typealias TypedStorage = _TypedNativeDictionaryStorage<Key, Value>
+  internal typealias Buffer = _NativeDictionaryBuffer<Key, Value>
+  internal typealias Index = _NativeDictionaryIndex<Key, Value>
 
-%if Self == 'Set': # Set needs these to keep signatures simple.
-  internal typealias Key = ${TypeParameters}
-  internal typealias Value = ${TypeParameters}
-  internal typealias SequenceElementWithoutLabels = Element
-%else:
   internal typealias SequenceElementWithoutLabels = (Key, Value)
-%end
 
-  /// See this comments on _RawNative${Self}Storage and its subclasses to
+  /// See this comments on _RawNativeDictionaryStorage and its subclasses to
   /// understand why we store an untyped storage here.
   @_versioned // FIXME(sil-serialize-all)
   internal var _storage: RawStorage
@@ -3587,16 +2127,10 @@
   @_versioned // FIXME(sil-serialize-all)
   internal init(_exactBucketCount bucketCount: Int, unhashable: ()) {
     let bitmapWordCount = _UnsafeBitMap.sizeInWords(forSizeInBits: bucketCount)
-%if Self == 'Dictionary':
     let storage = Builtin.allocWithTailElems_3(TypedStorage.self,
         bitmapWordCount._builtinWordValue, UInt.self,
         bucketCount._builtinWordValue, Key.self,
         bucketCount._builtinWordValue, Value.self)
-%else:
-    let storage = Builtin.allocWithTailElems_2(TypedStorage.self,
-        bitmapWordCount._builtinWordValue, UInt.self,
-        bucketCount._builtinWordValue, Key.self)
-%end
     self.init(_exactBucketCount: bucketCount, storage: storage)
   }
 
@@ -3624,11 +2158,9 @@
     // Initialize header
     _storage.initializedEntries = initializedEntries
     _storage.keys = UnsafeMutableRawPointer(keysAddr)
-%if Self == 'Dictionary':
     let valuesAddr = Builtin.getTailAddr_Word(keysAddr,
         bucketCount._builtinWordValue, Key.self, Value.self)
     _storage.values = UnsafeMutableRawPointer(valuesAddr)
-%end
     // We assign a unique hash seed to each distinct hash table size, so that we
     // avoid certain copy operations becoming quadratic, without breaking value
     // semantics. (See https://bugs.swift.org/browse/SR-3268)
@@ -3677,14 +2209,12 @@
     return _storage.keys.assumingMemoryBound(to: Key.self)
   }
 
-%if Self == 'Dictionary':
   // This API is unsafe and needs a `_fixLifetime` in the caller.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
   internal var values: UnsafeMutablePointer<Value> {
     return _storage.values.assumingMemoryBound(to: Value.self)
   }
-%end
 
   /// Constructs a buffer adopting the given storage.
   @_inlineable // FIXME(sil-serialize-all)
@@ -3700,8 +2230,6 @@
     self._storage = RawStorage.empty
   }
 
-
-
   // Most of the implementation of the _HashBuffer protocol,
   // but only the parts that don't actually rely on hashing.
 
@@ -3756,56 +2284,10 @@
     defer { _fixLifetime(self) }
 
     (keys + i).deinitialize(count: 1)
-%if Self == 'Dictionary':
     (values + i).deinitialize(count: 1)
-%end
     _storage.initializedEntries[i] = false
   }
 
-%if Self == 'Set':
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @_transparent
-  internal func initializeKey(_ k: Key, at i: Int) {
-    _sanityCheck(!isInitializedEntry(at: i))
-    defer { _fixLifetime(self) }
-
-    (keys + i).initialize(to: k)
-    _storage.initializedEntries[i] = true
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @_transparent
-  internal func moveInitializeEntry(from: Buffer, at: Int, toEntryAt: Int) {
-    _sanityCheck(!isInitializedEntry(at: toEntryAt))
-
-    defer { _fixLifetime(self) }
-
-    (keys + toEntryAt).initialize(to: (from.keys + at).move())
-    from._storage.initializedEntries[at] = false
-    _storage.initializedEntries[toEntryAt] = true
-  }
-
-  /// Alias for key(at:) in Sets for better code reuse
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned
-  @_transparent
-  internal func value(at i: Int) -> Value {
-    return key(at: i)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal func setKey(_ key: Key, at i: Int) {
-    _sanityCheck(i >= 0 && i < bucketCount)
-    _sanityCheck(isInitializedEntry(at: i))
-    defer { _fixLifetime(self) }
-
-    (keys + i).pointee = key
-  }
-
-%elif Self == 'Dictionary':
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @_transparent
@@ -3852,8 +2334,6 @@
     (values + i).pointee = value
   }
 
-%end
-
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
   internal var startIndex: Index {
@@ -3886,36 +2366,30 @@
     i = index(after: i)
   }
 
-  
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func assertingGet(_ i: Index) -> SequenceElement {
     _precondition(i.offset >= 0 && i.offset < bucketCount)
     _precondition(
       isInitializedEntry(at: i.offset),
-      "Attempting to access ${Self} elements using an invalid Index")
+      "Attempting to access Dictionary elements using an invalid Index")
     let key = self.key(at: i.offset)
-%if Self == 'Set':
-    return key
-%elif Self == 'Dictionary':
     return (key, self.value(at: i.offset))
-%end
 
   }
 }
 
-extension _Native${Self}Buffer 
-  where ${'Key' if Self == 'Dictionary' else 'Element'} : Hashable
+extension _NativeDictionaryBuffer where Key: Hashable
 {
-  internal typealias HashTypedStorage = 
-    _HashableTypedNative${Self}Storage<${TypeParameters}>
-  internal typealias SequenceElement = ${Sequence}
+  internal typealias HashTypedStorage =
+    _HashableTypedNativeDictionaryStorage<Key, Value>
+  internal typealias SequenceElement = (key: Key, value: Value)
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @inline(__always)
   internal init(minimumCapacity: Int) {
-    let bucketCount = _Native${Self}Buffer.bucketCount(
+    let bucketCount = _NativeDictionaryBuffer.bucketCount(
       forCapacity: minimumCapacity,
       maxLoadFactorInverse: _hashContainerDefaultMaxLoadFactorInverse)
     self.init(bucketCount: bucketCount)
@@ -3938,41 +2412,35 @@
   @_versioned // FIXME(sil-serialize-all)
   internal init(_exactBucketCount bucketCount: Int) {
     let bitmapWordCount = _UnsafeBitMap.sizeInWords(forSizeInBits: bucketCount)
-%if Self == 'Dictionary':
     let storage = Builtin.allocWithTailElems_3(HashTypedStorage.self,
         bitmapWordCount._builtinWordValue, UInt.self,
         bucketCount._builtinWordValue, Key.self,
         bucketCount._builtinWordValue, Value.self)
-%else:
-    let storage = Builtin.allocWithTailElems_2(HashTypedStorage.self,
-        bitmapWordCount._builtinWordValue, UInt.self,
-        bucketCount._builtinWordValue, Key.self)
-%end
     self.init(_exactBucketCount: bucketCount, storage: storage)
   }
 
 #if _runtime(_ObjC)
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal func bridged() -> _NS${Self} {
+  internal func bridged() -> _NSDictionary {
     // We can zero-cost bridge if our keys are verbatim
     // or if we're the empty singleton.
 
     // Temporary var for SOME type safety before a cast.
-    let nsSet: _NS${Self}Core
+    let nsSet: _NSDictionaryCore
 
     if (_isBridgedVerbatimToObjectiveC(Key.self) &&
         _isBridgedVerbatimToObjectiveC(Value.self)) ||
         self._storage === RawStorage.empty {
       nsSet = self._storage
     } else {
-      nsSet = _SwiftDeferredNS${Self}(nativeBuffer: self)
+      nsSet = _SwiftDeferredNSDictionary(nativeBuffer: self)
     }
 
-    // Cast from "minimal NS${Self}" to "NS${Self}"
+    // Cast from "minimal NSDictionary" to "NSDictionary"
     // Note that if you actually ask Swift for this cast, it will fail.
     // Never trust a shadow protocol!
-    return unsafeBitCast(nsSet, to: _NS${Self}.self)
+    return unsafeBitCast(nsSet, to: _NSDictionary.self)
   }
 #endif
 
@@ -4064,22 +2532,8 @@
   }
 
   /// Buffer should be uniquely referenced.
-  /// The `key` should not be present in the ${Self}.
+  /// The `key` should not be present in the Dictionary.
   /// This function does *not* update `count`.
-
-%if Self == 'Set':
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal func unsafeAddNew(key newKey: Element) {
-    let (i, found) = _find(newKey, startBucket: _bucket(newKey))
-    _sanityCheck(
-      !found, "unsafeAddNew was called, but the key is already present")
-    initializeKey(newKey, at: i.offset)
-  }
-
-%elif Self == 'Dictionary':
-
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func unsafeAddNew(key newKey: Key, value: Value) {
@@ -4089,8 +2543,6 @@
     initializeKey(newKey, value: value, at: i.offset)
   }
 
-%end
-
   //
   // _HashBuffer conformance
   //
@@ -4107,17 +2559,12 @@
     return found ? i : nil
   }
 
-
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func assertingGet(_ key: Key) -> Value {
     let (i, found) = _find(key, startBucket: _bucket(key))
     _precondition(found, "Key not found")
-%if Self == 'Set':
-    return self.key(at: i.offset)
-%elif Self == 'Dictionary':
     return self.value(at: i.offset)
-%end
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -4131,11 +2578,7 @@
 
     let (i, found) = _find(key, startBucket: _bucket(key))
     if found {
-%if Self == 'Set':
-      return self.key(at: i.offset)
-%elif Self == 'Dictionary':
       return self.value(at: i.offset)
-%end
     }
     return nil
   }
@@ -4145,7 +2588,7 @@
   @discardableResult
   internal func updateValue(_ value: Value, forKey key: Key) -> Value? {
     _sanityCheckFailure(
-      "don't call mutating methods on _Native${Self}Buffer")
+      "don't call mutating methods on _NativeDictionaryBuffer")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -4155,7 +2598,7 @@
     _ value: Value, forKey key: Key
   ) -> (inserted: Bool, memberAfterInsert: Value) {
     _sanityCheckFailure(
-      "don't call mutating methods on _Native${Self}Buffer")
+      "don't call mutating methods on _NativeDictionaryBuffer")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -4163,7 +2606,7 @@
   @discardableResult
   internal func remove(at index: Index) -> SequenceElement {
     _sanityCheckFailure(
-      "don't call mutating methods on _Native${Self}Buffer")
+      "don't call mutating methods on _NativeDictionaryBuffer")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -4171,20 +2614,20 @@
   @discardableResult
   internal func removeValue(forKey key: Key) -> Value? {
     _sanityCheckFailure(
-      "don't call mutating methods on _Native${Self}Buffer")
+      "don't call mutating methods on _NativeDictionaryBuffer")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func removeAll(keepingCapacity keepCapacity: Bool) {
     _sanityCheckFailure(
-      "don't call mutating methods on _Native${Self}Buffer")
+      "don't call mutating methods on _NativeDictionaryBuffer")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
   internal static func fromArray(_ elements: [SequenceElementWithoutLabels])
-    -> Buffer 
+    -> Buffer
   {
     if elements.isEmpty {
       return Buffer()
@@ -4192,46 +2635,28 @@
 
     var nativeBuffer = Buffer(minimumCapacity: elements.count)
 
-%if Self == 'Set':
-
-    var count = 0
-    for key in elements {
-      let (i, found) =
-        nativeBuffer._find(key, startBucket: nativeBuffer._bucket(key))
-      if found {
-        continue
-      }
-      nativeBuffer.initializeKey(key, at: i.offset)
-      count += 1
-    }
-    nativeBuffer.count = count
-
-%elif Self == 'Dictionary':
-
     for (key, value) in elements {
       let (i, found) =
         nativeBuffer._find(key, startBucket: nativeBuffer._bucket(key))
-      _precondition(!found, "${Self} literal contains duplicate keys")
+      _precondition(!found, "Dictionary literal contains duplicate keys")
       nativeBuffer.initializeKey(key, value: value, at: i.offset)
     }
     nativeBuffer.count = elements.count
 
-%end
-
     return nativeBuffer
   }
 }
 
 #if _runtime(_ObjC)
-/// An NSEnumerator that works with any Native${Self}Buffer of
-/// verbatim bridgeable elements. Used by the various NS${Self} impls.
+/// An NSEnumerator that works with any NativeDictionaryBuffer of
+/// verbatim bridgeable elements. Used by the various NSDictionary impls.
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned // FIXME(sil-serialize-all)
-final internal class _Native${Self}NSEnumerator<${TypeParameters}>
+final internal class _NativeDictionaryNSEnumerator<Key, Value>
   : _SwiftNativeNSEnumerator, _NSEnumerator {
 
-  internal typealias Buffer = _Native${Self}Buffer<${TypeParameters}>
-  internal typealias Index = _Native${Self}Index<${TypeParameters}>
+  internal typealias Buffer = _NativeDictionaryBuffer<Key, Value>
+  internal typealias Index = _NativeDictionaryIndex<Key, Value>
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
@@ -4307,24 +2732,19 @@
 
 #if _runtime(_ObjC)
 /// This class exists for Objective-C bridging. It holds a reference to a
-/// Native${Self}Buffer, and can be upcast to NSSelf when bridging is necessary.
+/// NativeDictionaryBuffer, and can be upcast to NSSelf when bridging is necessary.
 /// This is the fallback implementation for situations where toll-free bridging
-/// isn't possible. On first access, a Native${Self}Buffer of AnyObject will be
+/// isn't possible. On first access, a NativeDictionaryBuffer of AnyObject will be
 /// constructed containing all the bridged elements.
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned // FIXME(sil-serialize-all)
-final internal class _SwiftDeferredNS${Self}<${TypeParametersDecl}>
-  : _SwiftNativeNS${Self}, _NS${Self}Core {
+final internal class _SwiftDeferredNSDictionary<Key: Hashable, Value>
+  : _SwiftNativeNSDictionary, _NSDictionaryCore {
 
-  internal typealias NativeBuffer = _Native${Self}Buffer<${TypeParameters}>
-  internal typealias BridgedBuffer = _Native${Self}Buffer<${AnyTypeParameters}>
-  internal typealias NativeIndex = _Native${Self}Index<${TypeParameters}>
-  internal typealias BridgedIndex = _Native${Self}Index<${AnyTypeParameters}>
-
-%if Self == 'Set':
-  internal typealias Key = Element
-  internal typealias Value = Element
-%end
+  internal typealias NativeBuffer = _NativeDictionaryBuffer<Key, Value>
+  internal typealias BridgedBuffer = _NativeDictionaryBuffer<AnyObject, AnyObject>
+  internal typealias NativeIndex = _NativeDictionaryIndex<Key, Value>
+  internal typealias BridgedIndex = _NativeDictionaryIndex<AnyObject, AnyObject>
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
@@ -4358,41 +2778,10 @@
   @objc(copyWithZone:)
   internal func copy(with zone: _SwiftNSZone?) -> AnyObject {
     // Instances of this class should be visible outside of standard library as
-    // having `NS${Self}` type, which is immutable.
+    // having `NSDictionary` type, which is immutable.
     return self
   }
 
-%if Self == 'Set':
-
-  //
-  // NSSet implementation.
-  //
-  // Do not call any of these methods from the standard library!  Use only
-  // `nativeBuffer`.
-  //
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  internal required init(objects: UnsafePointer<AnyObject?>, count: Int) {
-    _sanityCheckFailure("don't call this designated initializer")
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  internal func member(_ object: AnyObject) -> AnyObject? {
-    return bridgingObjectForKey(object)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @objc
-  internal func objectEnumerator() -> _NSEnumerator {
-    return enumerator()
-  }
-
-%elif Self == 'Dictionary':
   //
   // NSDictionary implementation.
   //
@@ -4438,7 +2827,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @objc(enumerateKeysAndObjectsWithOptions:usingBlock:)
-  internal func enumerateKeysAndObjects(options: Int, 
+  internal func enumerateKeysAndObjects(options: Int,
     using block: @convention(block) (Unmanaged<AnyObject>, Unmanaged<AnyObject>,
      UnsafeMutablePointer<UInt8>) -> Void) {
     bridgeEverything()
@@ -4446,17 +2835,16 @@
     var stop: UInt8 = 0
     for position in 0..<bucketCount {
       if bridgedBuffer.isInitializedEntry(at: position) {
-        block(Unmanaged.passUnretained(bridgedBuffer.key(at: position)), 
-          Unmanaged.passUnretained(bridgedBuffer.value(at: position)), 
+        block(Unmanaged.passUnretained(bridgedBuffer.key(at: position)),
+          Unmanaged.passUnretained(bridgedBuffer.value(at: position)),
           &stop)
       }
       if stop != 0 { return }
     }
   }
-%end
 
   /// Returns the pointer to the stored property, which contains bridged
-  /// ${Self} elements.
+  /// Dictionary elements.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @nonobjc
@@ -4465,12 +2853,11 @@
       to: Optional<AnyObject>.self)
   }
 
-  /// The buffer for bridged ${Self} elements, if present.
+  /// The buffer for bridged Dictionary elements, if present.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @nonobjc
-  internal var _bridgedStorage:
-    BridgedBuffer.RawStorage? {
+  internal var _bridgedStorage: BridgedBuffer.RawStorage? {
     get {
       if let ref = _stdlib_atomicLoadARCRef(object: _heapStorageBridgedPtr) {
         return unsafeDowncast(ref, to: BridgedBuffer.RawStorage.self)
@@ -4479,7 +2866,7 @@
     }
   }
 
-  /// Attach a buffer for bridged ${Self} elements.
+  /// Attach a buffer for bridged Dictionary elements.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @nonobjc
@@ -4488,7 +2875,7 @@
       object: _heapStorageBridgedPtr, desired: newStorage)
   }
 
-  /// Returns the bridged ${Self} values.
+  /// Returns the bridged Dictionary values.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal var bridgedBuffer: BridgedBuffer {
@@ -4517,12 +2904,8 @@
     for i in 0..<nativeBuffer.bucketCount {
       if nativeBuffer.isInitializedEntry(at: i) {
         let key = _bridgeAnythingToObjectiveC(nativeBuffer.key(at: i))
-%if Self == 'Set':
-        bridged.initializeKey(key, at: i)
-%elif Self == 'Dictionary':
         let val = _bridgeAnythingToObjectiveC(nativeBuffer.value(at: i))
         bridged.initializeKey(key, value: val, at: i)
-%end
       }
     }
 
@@ -4530,8 +2913,6 @@
     _initializeHeapStorageBridged(bridged._storage)
   }
 
-%if Self == 'Dictionary':
-
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @nonobjc
@@ -4578,8 +2959,6 @@
     }
   }
 
-%end
-
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @objc
@@ -4609,7 +2988,7 @@
   @objc
   internal func enumerator() -> _NSEnumerator {
     bridgeEverything()
-    return _Native${Self}NSEnumerator<${AnyTypeParameters}>(bridgedBuffer)
+    return _NativeDictionaryNSEnumerator<AnyObject, AnyObject>(bridgedBuffer)
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -4636,7 +3015,7 @@
     }
 
     let unmanagedObjects = _UnmanagedAnyObjectArray(objects!)
-    var currIndex = _Native${Self}Index<${TypeParameters}>(
+    var currIndex = _NativeDictionaryIndex<Key, Value>(
         offset: Int(theState.extra.0))
     let endIndex = nativeBuffer.endIndex
     var stored = 0
@@ -4645,7 +3024,7 @@
     if (currIndex != endIndex) {
       bridgeEverything()
     }
-    
+
     for i in 0..<count {
       if (currIndex == endIndex) {
         break
@@ -4664,25 +3043,25 @@
 #else
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned // FIXME(sil-serialize-all)
-final internal class _SwiftDeferredNS${Self}<${TypeParametersDecl}> { }
+final internal class _SwiftDeferredNSDictionary<Key: Hashable, Value> { }
 #endif
 
 #if _runtime(_ObjC)
 @_versioned
 @_fixed_layout
-internal struct _Cocoa${Self}Buffer : _HashBuffer {
+internal struct _CocoaDictionaryBuffer: _HashBuffer {
   @_versioned
-  internal var cocoa${Self}: _NS${Self}
+  internal var cocoaDictionary: _NSDictionary
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal init(cocoa${Self}: _NS${Self}) {
-    self.cocoa${Self} = cocoa${Self}
+  internal init(cocoaDictionary: _NSDictionary) {
+    self.cocoaDictionary = cocoaDictionary
   }
 
-  internal typealias Index = _Cocoa${Self}Index
-  internal typealias SequenceElement = ${AnySequenceType}
-  internal typealias SequenceElementWithoutLabels = ${AnySequenceType}
+  internal typealias Index = _CocoaDictionaryIndex
+  internal typealias SequenceElement = (AnyObject, AnyObject)
+  internal typealias SequenceElementWithoutLabels = (AnyObject, AnyObject)
 
   internal typealias Key = AnyObject
   internal typealias Value = AnyObject
@@ -4690,13 +3069,13 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal var startIndex: Index {
-    return Index(cocoa${Self}, startIndex: ())
+    return Index(cocoaDictionary, startIndex: ())
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal var endIndex: Index {
-    return Index(cocoa${Self}, endIndex: ())
+    return Index(cocoaDictionary, endIndex: ())
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -4723,11 +3102,7 @@
       return nil
     }
 
-%if Self == 'Set':
-    let allKeys = _stdlib_NSSet_allObjects(cocoaSet)
-%elif Self == 'Dictionary':
     let allKeys = _stdlib_NSDictionary_allKeys(cocoaDictionary)
-%end
     var keyIndex = -1
     for i in 0..<allKeys.value {
       if _stdlib_NSObject_isEqual(key, allKeys[i]) {
@@ -4737,36 +3112,24 @@
     }
     _sanityCheck(keyIndex >= 0,
         "Key was found in fast path, but not found later?")
-    return Index(cocoa${Self}, allKeys, keyIndex)
+    return Index(cocoaDictionary, allKeys, keyIndex)
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func assertingGet(_ i: Index) -> SequenceElement {
-%if Self == 'Set':
-    let value: Value? = i.allKeys[i.currentKeyIndex]
-    _sanityCheck(value != nil, "Item not found in underlying NS${Self}")
-    return value!
-%elif Self == 'Dictionary':
     let key: Key = i.allKeys[i.currentKeyIndex]
     let value: Value = i.cocoaDictionary.objectFor(key)!
     return (key, value)
-%end
 
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func assertingGet(_ key: Key) -> Value {
-%if Self == 'Set':
-    let value: Value? = cocoa${Self}.member(key)
-    _precondition(value != nil, "Member not found in underlying NS${Self}")
+    let value: Value? = cocoaDictionary.objectFor(key)
+    _precondition(value != nil, "Key not found in underlying NSDictionary")
     return value!
-%elif Self == 'Dictionary':
-    let value: Value? = cocoa${Self}.objectFor(key)
-    _precondition(value != nil, "Key not found in underlying NS${Self}")
-    return value!
-%end
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -4774,11 +3137,7 @@
   @inline(__always)
   internal func maybeGet(_ key: Key) -> Value? {
 
-%if Self == 'Set':
-  return cocoaSet.member(key)
-%elif Self == 'Dictionary':
   return cocoaDictionary.objectFor(key)
-%end
 
   }
 
@@ -4786,7 +3145,7 @@
   @_versioned // FIXME(sil-serialize-all)
   @discardableResult
   internal mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
-    _sanityCheckFailure("cannot mutate NS${Self}")
+    _sanityCheckFailure("cannot mutate NSDictionary")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -4795,39 +3154,39 @@
   internal mutating func insert(
     _ value: Value, forKey key: Key
   ) -> (inserted: Bool, memberAfterInsert: Value) {
-    _sanityCheckFailure("cannot mutate NS${Self}")
+    _sanityCheckFailure("cannot mutate NSDictionary")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @discardableResult
   internal mutating func remove(at index: Index) -> SequenceElement {
-    _sanityCheckFailure("cannot mutate NS${Self}")
+    _sanityCheckFailure("cannot mutate NSDictionary")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   @discardableResult
   internal mutating func removeValue(forKey key: Key) -> Value? {
-    _sanityCheckFailure("cannot mutate NS${Self}")
+    _sanityCheckFailure("cannot mutate NSDictionary")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal mutating func removeAll(keepingCapacity keepCapacity: Bool) {
-    _sanityCheckFailure("cannot mutate NS${Self}")
+    _sanityCheckFailure("cannot mutate NSDictionary")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal var count: Int {
-    return cocoa${Self}.count
+    return cocoaDictionary.count
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal static func fromArray(_ elements: [SequenceElementWithoutLabels])
-    -> _Cocoa${Self}Buffer {
+    -> _CocoaDictionaryBuffer {
 
     _sanityCheckFailure("this function should never be called")
   }
@@ -4836,21 +3195,16 @@
 
 @_versioned
 @_frozen
-internal enum _Variant${Self}Buffer<${TypeParametersDecl}> : _HashBuffer {
+internal enum _VariantDictionaryBuffer<Key: Hashable, Value>: _HashBuffer {
 
-  internal typealias NativeBuffer = _Native${Self}Buffer<${TypeParameters}>
-  internal typealias NativeIndex = _Native${Self}Index<${TypeParameters}>
+  internal typealias NativeBuffer = _NativeDictionaryBuffer<Key, Value>
+  internal typealias NativeIndex = _NativeDictionaryIndex<Key, Value>
 #if _runtime(_ObjC)
-  internal typealias CocoaBuffer = _Cocoa${Self}Buffer
+  internal typealias CocoaBuffer = _CocoaDictionaryBuffer
 #endif
-  internal typealias SequenceElement = ${Sequence}
-  internal typealias SequenceElementWithoutLabels = ${Sequence}
-  internal typealias SelfType = _Variant${Self}Buffer
-
-%if Self == 'Set':
-  internal typealias Key = ${TypeParameters}
-  internal typealias Value = ${TypeParameters}
-%end
+  internal typealias SequenceElement = (key: Key, value: Value)
+  internal typealias SequenceElementWithoutLabels = (key: Key, value: Value)
+  internal typealias SelfType = _VariantDictionaryBuffer
 
   case native(NativeBuffer)
 #if _runtime(_ObjC)
@@ -4920,7 +3274,7 @@
   internal var asCocoa: CocoaBuffer {
     switch self {
     case .native:
-      _sanityCheckFailure("internal error: not backed by NS${Self}")
+      _sanityCheckFailure("internal error: not backed by NSDictionary")
     case .cocoa(let cocoaBuffer):
       return cocoaBuffer
     }
@@ -4930,7 +3284,7 @@
   /// Return true if self is native.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal var _isNative : Bool {
+  internal var _isNative: Bool {
 #if _runtime(_ObjC)
     switch self {
     case .native:
@@ -4961,21 +3315,13 @@
       if oldNativeBuffer.isInitializedEntry(at: i) {
         if oldBucketCount == newBucketCount {
           let key = oldNativeBuffer.key(at: i)
-%if Self == 'Set':
-          newNativeBuffer.initializeKey(key, at: i)
-%elif Self == 'Dictionary':
           let value = oldNativeBuffer.value(at: i)
           newNativeBuffer.initializeKey(key, value: value , at: i)
-%end
         } else {
           let key = oldNativeBuffer.key(at: i)
-%if Self == 'Set':
-          newNativeBuffer.unsafeAddNew(key: key)
-%elif Self == 'Dictionary':
           newNativeBuffer.unsafeAddNew(
             key: key,
             value: oldNativeBuffer.value(at: i))
-%end
         }
       }
     }
@@ -5025,16 +3371,9 @@
     case .native:
       fatalError("This should have been handled earlier")
     case .cocoa(let cocoaBuffer):
-      let cocoa${Self} = cocoaBuffer.cocoa${Self}
+      let cocoaDictionary = cocoaBuffer.cocoaDictionary
       var newNativeBuffer = NativeBuffer(bucketCount: desiredBucketCount)
-      let oldCocoaIterator = _Cocoa${Self}Iterator(cocoa${Self})
-%if Self == 'Set':
-      while let key = oldCocoaIterator.next() {
-        newNativeBuffer.unsafeAddNew(
-            key: _forceBridgeFromObjectiveC(key, Value.self))
-      }
-
-%elif Self == 'Dictionary':
+      let oldCocoaIterator = _CocoaDictionaryIterator(cocoaDictionary)
 
       while let (key, value) = oldCocoaIterator.next() {
         newNativeBuffer.unsafeAddNew(
@@ -5042,8 +3381,7 @@
           value: _forceBridgeFromObjectiveC(value, Value.self))
       }
 
-%end
-      newNativeBuffer.count = cocoa${Self}.count
+      newNativeBuffer.count = cocoaDictionary.count
 
       self = .native(newNativeBuffer)
       return (reallocated: true, capacityChanged: true)
@@ -5058,11 +3396,11 @@
   @_versioned // FIXME(sil-serialize-all)
   @inline(never)
   internal mutating func migrateDataToNativeBuffer(
-    _ cocoaBuffer: _Cocoa${Self}Buffer
+    _ cocoaBuffer: _CocoaDictionaryBuffer
   ) {
     let allocated = ensureUniqueNativeBuffer(
       withCapacity: cocoaBuffer.count).reallocated
-    _sanityCheck(allocated, "failed to allocate native ${Self} buffer")
+    _sanityCheck(allocated, "failed to allocate native Dictionary buffer")
   }
 #endif
 
@@ -5099,7 +3437,7 @@
   // _HashBuffer conformance
   //
 
-  internal typealias Index = ${Self}Index<${TypeParameters}>
+  internal typealias Index = DictionaryIndex<Key, Value>
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
@@ -5199,17 +3537,11 @@
       return asNative.assertingGet(i._nativeIndex)
 #if _runtime(_ObjC)
     case .cocoa(let cocoaBuffer):
-%if Self == 'Set':
-      let anyObjectValue: AnyObject = cocoaBuffer.assertingGet(i._cocoaIndex)
-      let nativeValue = _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
-      return nativeValue
-%elif Self == 'Dictionary':
       let (anyObjectKey, anyObjectValue) =
           cocoaBuffer.assertingGet(i._cocoaIndex)
       let nativeKey = _forceBridgeFromObjectiveC(anyObjectKey, Key.self)
       let nativeValue = _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
       return (nativeKey, nativeValue)
-%end
 #endif
     }
   }
@@ -5239,7 +3571,7 @@
   @_versioned
   @inline(never)
   internal static func maybeGetFromCocoaBuffer(
-    _ cocoaBuffer : CocoaBuffer, forKey key: Key
+    _ cocoaBuffer: CocoaBuffer, forKey key: Key
   ) -> Value? {
     let anyObjectKey: AnyObject = _bridgeAnythingToObjectiveC(key)
     if let anyObjectValue = cocoaBuffer.maybeGet(anyObjectKey) {
@@ -5286,15 +3618,6 @@
       i = asNative._find(key, startBucket: asNative._bucket(key)).pos
     }
 
-%if Self == 'Set':
-    let oldValue: Value? = found ? asNative.key(at: i.offset) : nil
-    if found {
-      asNative.setKey(key, at: i.offset)
-    } else {
-      asNative.initializeKey(key, at: i.offset)
-      asNative.count += 1
-    }
-%elif Self == 'Dictionary':
     let oldValue: Value? = found ? asNative.value(at: i.offset) : nil
     if found {
       asNative.setKey(key, value: value, at: i.offset)
@@ -5302,7 +3625,6 @@
       asNative.initializeKey(key, value: value, at: i.offset)
       asNative.count += 1
     }
-%end
 
     return oldValue
   }
@@ -5329,7 +3651,6 @@
     }
   }
 
-%if Self == 'Dictionary':
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal mutating func nativePointerToValue(at i: Index)
@@ -5408,7 +3729,6 @@
     ensureNativeBuffer()
     return nativePointerToValue(forKey: key, insertingDefault: defaultValue)
   }
-%end
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
@@ -5418,11 +3738,7 @@
 
     var (i, found) = asNative._find(key, startBucket: asNative._bucket(key))
     if found {
-%if Self == 'Set':
-      return (inserted: false, memberAfterInsert: asNative.key(at: i.offset))
-%elif Self == 'Dictionary':
       return (inserted: false, memberAfterInsert: asNative.value(at: i.offset))
-%end
     }
 
     let minCapacity = asNative.count + 1
@@ -5433,13 +3749,8 @@
       i = asNative._find(key, startBucket: asNative._bucket(key)).pos
     }
 
-%if Self == 'Set':
-    asNative.initializeKey(key, at: i.offset)
-    asNative.count += 1
-%elif Self == 'Dictionary':
     asNative.initializeKey(key, value: value, at: i.offset)
     asNative.count += 1
-%end
 
     return (inserted: true, memberAfterInsert: value)
   }
@@ -5454,16 +3765,15 @@
     return nativeInsert(value, forKey: key)
   }
 
-%if Self == 'Dictionary':
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func nativeMapValues<T>(
     _ transform: (Value) throws -> T
-  ) rethrows -> _Variant${Self}Buffer<Key, T> {
-    var buffer = _Native${Self}Buffer<Key, T>(
+  ) rethrows -> _VariantDictionaryBuffer<Key, T> {
+    var buffer = _NativeDictionaryBuffer<Key, T>(
       _exactBucketCount: asNative.bucketCount)
 
-    // Because the keys in the current and new buffer are the same, we can 
+    // Because the keys in the current and new buffer are the same, we can
     // initialize to the same locations in the new buffer, skipping hash value
     // recalculations.
     var i = asNative.startIndex
@@ -5481,7 +3791,7 @@
   @_versioned // FIXME(sil-serialize-all)
   internal func mapValues<T>(
     _ transform: (Value) throws -> T
-  ) rethrows -> _Variant${Self}Buffer<Key, T> {
+  ) rethrows -> _VariantDictionaryBuffer<Key, T> {
     if _fastPath(guaranteedNative) {
       return try nativeMapValues(transform)
     }
@@ -5491,8 +3801,8 @@
       return try nativeMapValues(transform)
 #if _runtime(_ObjC)
     case .cocoa(let cocoaStorage):
-      var storage: _Variant${Self}Buffer<Key, T> = .native(
-        _Native${Self}Buffer<Key, T>(minimumCapacity: cocoaStorage.count))
+      var storage: _VariantDictionaryBuffer<Key, T> = .native(
+        _NativeDictionaryBuffer<Key, T>(minimumCapacity: cocoaStorage.count))
 
       var i = cocoaStorage.startIndex
       while i != cocoaStorage.endIndex {
@@ -5583,7 +3893,6 @@
       }
     }
   }
-%end
 
   /// - parameter idealBucket: The ideal bucket for the element being deleted.
   /// - parameter offset: The offset of the element that will be deleted.
@@ -5682,11 +3991,7 @@
       (index, found) = nativeBuffer._find(key, startBucket: idealBucket)
       _sanityCheck(found, "key was lost during buffer migration")
     }
-%if Self == 'Set':
-    let oldValue = nativeBuffer.key(at: index.offset)
-%elif Self == 'Dictionary':
     let oldValue = nativeBuffer.value(at: index.offset)
-%end
     nativeDelete(nativeBuffer, idealBucket: idealBucket,
       offset: index.offset)
     return oldValue
@@ -5712,11 +4017,7 @@
     let nativeBuffer = asNative
 
     let result = nativeBuffer.assertingGet(nativeIndex)
-%if Self == 'Set':
-    let key = result
-%elif Self == 'Dictionary':
     let key = result.0
-%end
 
     nativeDelete(nativeBuffer, idealBucket: nativeBuffer._bucket(key),
         offset: nativeIndex.offset)
@@ -5747,12 +4048,7 @@
       let key = _forceBridgeFromObjectiveC(anyObjectKey, Key.self)
       let value = nativeRemoveObject(forKey: key)
 
-%if Self == 'Set':
-      _sanityCheck(key == value, "bridging did not preserve equality")
-      return key
-%elif Self == 'Dictionary':
       return (key, value._unsafelyUnwrappedUnchecked)
-%end
 #endif
     }
   }
@@ -5850,14 +4146,14 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
   @inline(__always)
-  internal func makeIterator() -> ${Self}Iterator<${TypeParameters}> {
+  internal func makeIterator() -> DictionaryIterator<Key, Value> {
     switch self {
     case .native(let buffer):
       return ._native(
         start: asNative.startIndex, end: asNative.endIndex, buffer: buffer)
 #if _runtime(_ObjC)
     case .cocoa(let cocoaBuffer):
-      return ._cocoa(_Cocoa${Self}Iterator(cocoaBuffer.cocoa${Self}))
+      return ._cocoa(_CocoaDictionaryIterator(cocoaBuffer.cocoaDictionary))
 #endif
     }
   }
@@ -5865,19 +4161,15 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal static func fromArray(_ elements: [SequenceElement])
-    -> _Variant${Self}Buffer<${TypeParameters}> {
+    -> _VariantDictionaryBuffer<Key, Value> {
 
     _sanityCheckFailure("this function should never be called")
   }
 }
 
-%{
-  compareOperators = ["<", "<=", ">", ">=", "=="]
-}%
-
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned
-internal struct _Native${Self}Index<${TypeParameters}> : Comparable {
+internal struct _NativeDictionaryIndex<Key, Value>: Comparable {
   @_versioned
   internal var offset: Int
 
@@ -5888,35 +4180,63 @@
   }
 }
 
-extension _Native${Self}Index {
+extension _NativeDictionaryIndex {
 
-% for op in compareOperators:
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal static func ${op} (
-    lhs: _Native${Self}Index<${TypeParameters}>,
-    rhs: _Native${Self}Index<${TypeParameters}>
+  internal static func < (
+    lhs: _NativeDictionaryIndex<Key, Value>,
+    rhs: _NativeDictionaryIndex<Key, Value>
   ) -> Bool {
-    return lhs.offset ${op} rhs.offset
+    return lhs.offset < rhs.offset
   }
-% end
-
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func <= (
+    lhs: _NativeDictionaryIndex<Key, Value>,
+    rhs: _NativeDictionaryIndex<Key, Value>
+  ) -> Bool {
+    return lhs.offset <= rhs.offset
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func > (
+    lhs: _NativeDictionaryIndex<Key, Value>,
+    rhs: _NativeDictionaryIndex<Key, Value>
+  ) -> Bool {
+    return lhs.offset > rhs.offset
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func >= (
+    lhs: _NativeDictionaryIndex<Key, Value>,
+    rhs: _NativeDictionaryIndex<Key, Value>
+  ) -> Bool {
+    return lhs.offset >= rhs.offset
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func == (
+    lhs: _NativeDictionaryIndex<Key, Value>,
+    rhs: _NativeDictionaryIndex<Key, Value>
+  ) -> Bool {
+    return lhs.offset == rhs.offset
+  }
 }
 
-
 #if _runtime(_ObjC)
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned
-internal struct _Cocoa${Self}Index : Comparable {
+internal struct _CocoaDictionaryIndex: Comparable {
   // Assumption: we rely on NSDictionary.getObjects when being
   // repeatedly called on the same NSDictionary, returning items in the same
   // order every time.
   // Similarly, the same assumption holds for NSSet.allObjects.
 
-  /// A reference to the NS${Self}, which owns members in `allObjects`,
+  /// A reference to the NSDictionary, which owns members in `allObjects`,
   /// or `allKeys`, for NSSet and NSDictionary respectively.
   @_versioned // FIXME(sil-serialize-all)
-  internal let cocoa${Self}: _NS${Self}
+  internal let cocoaDictionary: _NSDictionary
   // FIXME: swift-3-indexing-model: try to remove the cocoa reference, but make
   // sure that we have a safety check for accessing `allKeys`.  Maybe move both
   // into the dictionary/set itself.
@@ -5931,35 +4251,27 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal init(_ cocoa${Self}: _NS${Self}, startIndex: ()) {
-    self.cocoa${Self} = cocoa${Self}
-%if Self == 'Set':
-    self.allKeys = _stdlib_NSSet_allObjects(cocoaSet)
-%elif Self == 'Dictionary':
+  internal init(_ cocoaDictionary: _NSDictionary, startIndex: ()) {
+    self.cocoaDictionary = cocoaDictionary
     self.allKeys = _stdlib_NSDictionary_allKeys(cocoaDictionary)
-%end
     self.currentKeyIndex = 0
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal init(_ cocoa${Self}: _NS${Self}, endIndex: ()) {
-    self.cocoa${Self} = cocoa${Self}
-%if Self == 'Set':
-    self.allKeys = _stdlib_NS${Self}_allObjects(cocoa${Self})
-%elif Self == 'Dictionary':
-    self.allKeys = _stdlib_NS${Self}_allKeys(cocoa${Self})
-%end
+  internal init(_ cocoaDictionary: _NSDictionary, endIndex: ()) {
+    self.cocoaDictionary = cocoaDictionary
+    self.allKeys = _stdlib_NSDictionary_allKeys(cocoaDictionary)
     self.currentKeyIndex = allKeys.value
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal init(_ cocoa${Self}: _NS${Self},
+  internal init(_ cocoaDictionary: _NSDictionary,
     _ allKeys: _HeapBuffer<Int, AnyObject>,
     _ currentKeyIndex: Int
   ) {
-    self.cocoa${Self} = cocoa${Self}
+    self.cocoaDictionary = cocoaDictionary
     self.allKeys = allKeys
     self.currentKeyIndex = currentKeyIndex
   }
@@ -5969,34 +4281,63 @@
   /// - Precondition: The next value is representable.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal func successor() -> _Cocoa${Self}Index {
+  internal func successor() -> _CocoaDictionaryIndex {
     // FIXME: swift-3-indexing-model: remove this method.
     _precondition(
       currentKeyIndex < allKeys.value, "Cannot increment endIndex")
-    return _Cocoa${Self}Index(cocoa${Self}, allKeys, currentKeyIndex + 1)
+    return _CocoaDictionaryIndex(cocoaDictionary, allKeys, currentKeyIndex + 1)
   }
 }
 
-extension _Cocoa${Self}Index {
+extension _CocoaDictionaryIndex {
 
-% for op in compareOperators:
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal static func ${op} (
-    lhs: _Cocoa${Self}Index,
-    rhs: _Cocoa${Self}Index
+  internal static func < (
+    lhs: _CocoaDictionaryIndex,
+    rhs: _CocoaDictionaryIndex
   ) -> Bool {
-    return lhs.currentKeyIndex ${op} rhs.currentKeyIndex
+    return lhs.currentKeyIndex < rhs.currentKeyIndex
   }
-% end
-
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func <= (
+    lhs: _CocoaDictionaryIndex,
+    rhs: _CocoaDictionaryIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex <= rhs.currentKeyIndex
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func > (
+    lhs: _CocoaDictionaryIndex,
+    rhs: _CocoaDictionaryIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex > rhs.currentKeyIndex
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func >= (
+    lhs: _CocoaDictionaryIndex,
+    rhs: _CocoaDictionaryIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex >= rhs.currentKeyIndex
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func == (
+    lhs: _CocoaDictionaryIndex,
+    rhs: _CocoaDictionaryIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex == rhs.currentKeyIndex
+  }
 }
 #endif
 
 @_frozen // FIXME(sil-serialize-all)
 @_versioned // FIXME(sil-serialize-all)
-internal enum ${Self}IndexRepresentation<${TypeParametersDecl}> {
-  typealias _Index = ${Self}Index<${TypeParameters}>
+internal enum DictionaryIndexRepresentation<Key: Hashable, Value> {
+  typealias _Index = DictionaryIndex<Key, Value>
   typealias _NativeIndex = _Index._NativeIndex
 #if _runtime(_ObjC)
   typealias _CocoaIndex = _Index._CocoaIndex
@@ -6008,113 +4349,99 @@
 #endif
 }
 
-extension ${Self} {
-%{
-if Self == 'Set':
-  SubscriptingWithIndexDoc = """\
-/// The position of an element in a set."""
-elif Self == 'Dictionary':
-  SubscriptingWithIndexDoc = """\
-/// The position of a key-value pair in a dictionary.
-///
-/// Dictionary has two subscripting interfaces:
-///
-/// 1. Subscripting with a key, yielding an optional value:
-///
-///        v = d[k]!
-///
-/// 2. Subscripting with an index, yielding a key-value pair:
-///
-///        (k, v) = d[i]"""
-}%
+extension Dictionary {
+  /// The position of a key-value pair in a dictionary.
+  ///
+  /// Dictionary has two subscripting interfaces:
+  ///
+  /// 1. Subscripting with a key, yielding an optional value:
+  ///
+  ///        v = d[k]!
+  ///
+  /// 2. Subscripting with an index, yielding a key-value pair:
+  ///
+  ///        (k, v) = d[i]
+  @_fixed_layout // FIXME(sil-serialize-all)
+  public struct Index: Comparable, Hashable {
+    // Index for native buffer is efficient.  Index for bridged NSDictionary is
+    // not, because neither NSEnumerator nor fast enumeration support moving
+    // backwards.  Even if they did, there is another issue: NSEnumerator does
+    // not support NSCopying, and fast enumeration does not document that it is
+    // safe to copy the state.  So, we cannot implement Index that is a value
+    // type for bridged NSDictionary in terms of Cocoa enumeration facilities.
 
-${SubscriptingWithIndexDoc}
-@_fixed_layout // FIXME(sil-serialize-all)
-public struct Index : Comparable, Hashable {
-  // Index for native buffer is efficient.  Index for bridged NS${Self} is
-  // not, because neither NSEnumerator nor fast enumeration support moving
-  // backwards.  Even if they did, there is another issue: NSEnumerator does
-  // not support NSCopying, and fast enumeration does not document that it is
-  // safe to copy the state.  So, we cannot implement Index that is a value
-  // type for bridged NS${Self} in terms of Cocoa enumeration facilities.
-
-  internal typealias _NativeIndex = _Native${Self}Index<${TypeParameters}>
+    internal typealias _NativeIndex = _NativeDictionaryIndex<Key, Value>
 #if _runtime(_ObjC)
-  internal typealias _CocoaIndex = _Cocoa${Self}Index
+    internal typealias _CocoaIndex = _CocoaDictionaryIndex
 #endif
 
-%if Self == 'Set':
-  internal typealias Key = ${TypeParameters}
-  internal typealias Value = ${TypeParameters}
-%end
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal init(_value: ${Self}IndexRepresentation<${TypeParameters}>) {
-    self._value = _value
-  }
-
-  @_versioned // FIXME(sil-serialize-all)
-  internal var _value: ${Self}IndexRepresentation<${TypeParameters}>
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned
-  internal static func _native(_ index: _NativeIndex) -> Index {
-    return ${Self}Index(_value: ._native(index))
-  }
-#if _runtime(_ObjC)
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned
-  internal static func _cocoa(_ index: _CocoaIndex) -> Index {
-    return ${Self}Index(_value: ._cocoa(index))
-  }
-#endif
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned
-  @_transparent
-  internal var _guaranteedNative: Bool {
-    return _canBeClass(Key.self) == 0 && _canBeClass(Value.self) == 0
-  }
-
-  @_versioned // FIXME(sil-serialize-all)
-  @_transparent
-  internal var _nativeIndex: _NativeIndex {
-    switch _value {
-    case ._native(let nativeIndex):
-      return nativeIndex
-#if _runtime(_ObjC)
-    case ._cocoa:
-      _sanityCheckFailure("internal error: does not contain a native index")
-#endif
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned // FIXME(sil-serialize-all)
+    internal init(_value: DictionaryIndexRepresentation<Key, Value>) {
+      self._value = _value
     }
-  }
+
+    @_versioned // FIXME(sil-serialize-all)
+    internal var _value: DictionaryIndexRepresentation<Key, Value>
+
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned
+    internal static func _native(_ index: _NativeIndex) -> Index {
+      return DictionaryIndex(_value: ._native(index))
+    }
 
 #if _runtime(_ObjC)
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  @_transparent
-  internal var _cocoaIndex: _CocoaIndex {
-    switch _value {
-    case ._native:
-      _sanityCheckFailure("internal error: does not contain a Cocoa index")
-    case ._cocoa(let cocoaIndex):
-      return cocoaIndex
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned
+    internal static func _cocoa(_ index: _CocoaIndex) -> Index {
+      return DictionaryIndex(_value: ._cocoa(index))
     }
-  }
 #endif
+
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned
+    @_transparent
+    internal var _guaranteedNative: Bool {
+      return _canBeClass(Key.self) == 0 && _canBeClass(Value.self) == 0
+    }
+
+    @_versioned // FIXME(sil-serialize-all)
+    @_transparent
+    internal var _nativeIndex: _NativeIndex {
+      switch _value {
+      case ._native(let nativeIndex):
+        return nativeIndex
+#if _runtime(_ObjC)
+      case ._cocoa:
+        _sanityCheckFailure("internal error: does not contain a native index")
+#endif
+      }
+    }
+
+#if _runtime(_ObjC)
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned // FIXME(sil-serialize-all)
+    @_transparent
+    internal var _cocoaIndex: _CocoaIndex {
+      switch _value {
+      case ._native:
+        _sanityCheckFailure("internal error: does not contain a Cocoa index")
+      case ._cocoa(let cocoaIndex):
+        return cocoaIndex
+      }
+    }
+#endif
+  }
 }
 
-}
+public typealias DictionaryIndex<Key: Hashable, Value> =
+  Dictionary<Key, Value>.Index
 
-public typealias ${Self}Index<${TypeParametersDecl}> =
-    ${Self}<${TypeParameters}>.Index
-
-extension ${Self}.Index {
+extension Dictionary.Index {
   @_inlineable // FIXME(sil-serialize-all)
   public static func == (
-    lhs: ${Self}<${TypeParameters}>.Index,
-    rhs: ${Self}<${TypeParameters}>.Index
+    lhs: Dictionary<Key, Value>.Index,
+    rhs: Dictionary<Key, Value>.Index
   ) -> Bool {
     if _fastPath(lhs._guaranteedNative) {
       return lhs._nativeIndex == rhs._nativeIndex
@@ -6134,8 +4461,8 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   public static func < (
-    lhs: ${Self}<${TypeParameters}>.Index,
-    rhs: ${Self}<${TypeParameters}>.Index
+    lhs: Dictionary<Key, Value>.Index,
+    rhs: Dictionary<Key, Value>.Index
   ) -> Bool {
     if _fastPath(lhs._guaranteedNative) {
       return lhs._nativeIndex < rhs._nativeIndex
@@ -6173,10 +4500,10 @@
 #if _runtime(_ObjC)
 @_fixed_layout // FIXME(sil-serialize-all)
 @_versioned
-final internal class _Cocoa${Self}Iterator : IteratorProtocol {
-  internal typealias Element = ${AnySequenceType}
+final internal class _CocoaDictionaryIterator: IteratorProtocol {
+  internal typealias Element = (AnyObject, AnyObject)
 
-  // Cocoa ${Self} iterator has to be a class, otherwise we cannot
+  // Cocoa Dictionary iterator has to be a class, otherwise we cannot
   // guarantee that the fast enumeration struct is pinned to a certain memory
   // location.
 
@@ -6192,7 +4519,7 @@
   internal var _fastEnumerationStackBuf = _CocoaFastEnumerationStackBuf()
 
   @_versioned // FIXME(sil-serialize-all)
-  internal let cocoa${Self}: _NS${Self}
+  internal let cocoaDictionary: _NSDictionary
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
@@ -6221,8 +4548,8 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
-  internal init(_ cocoa${Self}: _NS${Self}) {
-    self.cocoa${Self} = cocoa${Self}
+  internal init(_ cocoaDictionary: _NSDictionary) {
+    self.cocoaDictionary = cocoaDictionary
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -6231,14 +4558,14 @@
     if itemIndex < 0 {
       return nil
     }
-    let cocoa${Self} = self.cocoa${Self}
+    let cocoaDictionary = self.cocoaDictionary
     if itemIndex == itemCount {
       let stackBufCount = _fastEnumerationStackBuf.count
       // We can't use `withUnsafeMutablePointer` here to get pointers to
       // properties, because doing so might introduce a writeback storage, but
       // fast enumeration relies on the pointer identity of the enumeration
       // state struct.
-      itemCount = cocoa${Self}.countByEnumerating(
+      itemCount = cocoaDictionary.countByEnumerating(
         with: _fastEnumerationStatePtr,
         objects: UnsafeMutableRawPointer(_fastEnumerationStackBufPtr)
           .assumingMemoryBound(to: AnyObject.self),
@@ -6255,22 +4582,18 @@
     let itemsPtr = _UnmanagedAnyObjectArray(itemsPtrUP)
     let key: AnyObject = itemsPtr[itemIndex]
     itemIndex += 1
-%if Self == 'Set':
-    return key
-%elif Self == 'Dictionary':
-    let value: AnyObject = cocoa${Self}.objectFor(key)!
+    let value: AnyObject = cocoaDictionary.objectFor(key)!
     return (key, value)
-%end
   }
 }
 #endif
 
 @_versioned
 @_frozen // FIXME(sil-serialize-all)
-internal enum ${Self}IteratorRepresentation<${TypeParametersDecl}> {
-  internal typealias _Iterator = ${Self}Iterator<${TypeParameters}>
+internal enum DictionaryIteratorRepresentation<Key: Hashable, Value> {
+  internal typealias _Iterator = DictionaryIterator<Key, Value>
   internal typealias _NativeBuffer =
-    _Native${Self}Buffer<${TypeParameters}>
+    _NativeDictionaryBuffer<Key, Value>
   internal typealias _NativeIndex = _Iterator._NativeIndex
 
   // For native buffer, we keep two indices to keep track of the iteration
@@ -6282,17 +4605,17 @@
   case _native(
     start: _NativeIndex, end: _NativeIndex, buffer: _NativeBuffer)
 #if _runtime(_ObjC)
-  case _cocoa(_Cocoa${Self}Iterator)
+  case _cocoa(_CocoaDictionaryIterator)
 #endif
 }
 
-/// An iterator over the members of a `${Self}<${TypeParameters}>`.
+/// An iterator over the members of a `Dictionary<Key, Value>`.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct ${Self}Iterator<${TypeParametersDecl}> : IteratorProtocol {
-  // ${Self} has a separate IteratorProtocol and Index because of efficiency
+public struct DictionaryIterator<Key: Hashable, Value>: IteratorProtocol {
+  // Dictionary has a separate IteratorProtocol and Index because of efficiency
   // and implementability reasons.
   //
-  // Index for native buffer is efficient.  Index for bridged NS${Self} is
+  // Index for native buffer is efficient.  Index for bridged NSDictionary is
   // not.
   //
   // Even though fast enumeration is not suitable for implementing
@@ -6300,15 +4623,15 @@
   // IteratorProtocol, which is being consumed as iteration proceeds.
 
   internal typealias _NativeBuffer =
-    _Native${Self}Buffer<${TypeParameters}>
-  internal typealias _NativeIndex = _Native${Self}Index<${TypeParameters}>
+    _NativeDictionaryBuffer<Key, Value>
+  internal typealias _NativeIndex = _NativeDictionaryIndex<Key, Value>
 
   @_versioned
-  internal var _state: ${Self}IteratorRepresentation<${TypeParameters}>
+  internal var _state: DictionaryIteratorRepresentation<Key, Value>
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal init(_state: ${Self}IteratorRepresentation<${TypeParameters}>) {
+  internal init(_state: DictionaryIteratorRepresentation<Key, Value>) {
     self._state = _state
   }
 
@@ -6316,17 +4639,17 @@
   @_versioned
   internal static func _native(
     start: _NativeIndex, end: _NativeIndex, buffer: _NativeBuffer
-  ) -> ${Self}Iterator {
-    return ${Self}Iterator(
+  ) -> DictionaryIterator {
+    return DictionaryIterator(
       _state: ._native(start: start, end: end, buffer: buffer))
   }
 #if _runtime(_ObjC)
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
   internal static func _cocoa(
-    _ iterator: _Cocoa${Self}Iterator
-  ) -> ${Self}Iterator{
-    return ${Self}Iterator(_state: ._cocoa(iterator))
+    _ iterator: _CocoaDictionaryIterator
+  ) -> DictionaryIterator{
+    return DictionaryIterator(_state: ._cocoa(iterator))
   }
 #endif
 
@@ -6334,16 +4657,12 @@
   @_versioned
   @_transparent
   internal var _guaranteedNative: Bool {
-%if Self == 'Set':
-    return _canBeClass(Element.self) == 0
-%elif Self == 'Dictionary':
     return _canBeClass(Key.self) == 0 || _canBeClass(Value.self) == 0
-%end
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
-  internal mutating func _nativeNext() -> ${Sequence}? {
+  internal mutating func _nativeNext() -> (key: Key, value: Value)? {
     switch _state {
     case ._native(let startIndex, let endIndex, let buffer):
       if startIndex == endIndex {
@@ -6355,7 +4674,7 @@
       return result
 #if _runtime(_ObjC)
     case ._cocoa:
-      _sanityCheckFailure("internal error: not backed by NS${Self}")
+      _sanityCheckFailure("internal error: not backed by NSDictionary")
 #endif
     }
   }
@@ -6366,7 +4685,7 @@
   /// Once `nil` has been returned, all subsequent calls return `nil`.
   @_inlineable // FIXME(sil-serialize-all)
   @inline(__always)
-  public mutating func next() -> ${Sequence}? {
+  public mutating func next() -> (key: Key, value: Value)? {
     if _fastPath(_guaranteedNative) {
       return _nativeNext()
     }
@@ -6376,24 +4695,18 @@
       return _nativeNext()
 #if _runtime(_ObjC)
     case ._cocoa(let cocoaIterator):
-%if Self == 'Set':
-      if let anyObjectElement = cocoaIterator.next() {
-        return _forceBridgeFromObjectiveC(anyObjectElement, Element.self)
-      }
-%elif Self == 'Dictionary':
       if let (anyObjectKey, anyObjectValue) = cocoaIterator.next() {
         let nativeKey = _forceBridgeFromObjectiveC(anyObjectKey, Key.self)
         let nativeValue = _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
         return (nativeKey, nativeValue)
       }
-%end
       return nil
 #endif
     }
   }
 }
 
-extension ${Self}Iterator : CustomReflectable {
+extension DictionaryIterator: CustomReflectable {
   /// A mirror that reflects the iterator.
   @_inlineable // FIXME(sil-serialize-all)
   public var customMirror: Mirror {
@@ -6403,34 +4716,26 @@
   }
 }
 
-extension ${Self} : CustomReflectable {
-  /// A mirror that reflects the ${a_self}.
+extension Dictionary: CustomReflectable {
+  /// A mirror that reflects the dictionary.
   @_inlineable // FIXME(sil-serialize-all)
   public var customMirror: Mirror {
-%if Self == 'Set':
-    let style = Mirror.DisplayStyle.`set`
-%elif Self == 'Dictionary':
     let style = Mirror.DisplayStyle.dictionary
-%end
     return Mirror(self, unlabeledChildren: self, displayStyle: style)
   }
 }
 
-/// Initializes a `${Self}` from unique members.
+/// Initializes a `Dictionary` from unique members.
 ///
 /// Using a builder can be faster than inserting members into an empty
-/// `${Self}`.
+/// `Dictionary`.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct _${Self}Builder<${TypeParametersDecl}> {
-%if Self == 'Set':
-  public typealias Key = ${TypeParameters}
-  public typealias Value = ${TypeParameters}
-%end
+public struct _DictionaryBuilder<Key: Hashable, Value> {
 
   @_versioned // FIXME(sil-serialize-all)
-  internal var _result: ${Self}<${TypeParameters}>
+  internal var _result: Dictionary<Key, Value>
   @_versioned // FIXME(sil-serialize-all)
-  internal var _nativeBuffer: _Native${Self}Buffer<${TypeParameters}>
+  internal var _nativeBuffer: _NativeDictionaryBuffer<Key, Value>
   @_versioned // FIXME(sil-serialize-all)
   internal let _requestedCount: Int
   @_versioned // FIXME(sil-serialize-all)
@@ -6438,34 +4743,26 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   public init(count: Int) {
-    _result = ${Self}<${TypeParameters}>(minimumCapacity: count)
+    _result = Dictionary<Key, Value>(minimumCapacity: count)
     _nativeBuffer = _result._variantBuffer.asNative
     _requestedCount = count
     _actualCount = 0
   }
 
-%if Self == 'Set':
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func add(member newKey: Key) {
-    _nativeBuffer.unsafeAddNew(key: newKey)
-    _actualCount += 1
-  }
-%elif Self == 'Dictionary':
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func add(key newKey: Key, value: Value) {
     _nativeBuffer.unsafeAddNew(key: newKey, value: value)
     _actualCount += 1
   }
-%end
 
   @_inlineable // FIXME(sil-serialize-all)
-  public mutating func take() -> ${Self}<${TypeParameters}> {
+  public mutating func take() -> Dictionary<Key, Value> {
     _precondition(_actualCount >= 0,
       "Cannot take the result twice")
     _precondition(_actualCount == _requestedCount,
       "The number of members added does not match the promised count")
 
-    // Finish building the `${Self}`.
+    // Finish building the `Dictionary`.
     _nativeBuffer.count = _requestedCount
 
     // Prevent taking the result twice.
@@ -6474,15 +4771,7 @@
   }
 }
 
-extension ${Self} {
-%if Self == 'Set':
-  /// Removes and returns the first element of the set.
-  ///
-  /// Because a set is not an ordered collection, the "first" element may not
-  /// be the first element that was added to the set.
-  ///
-  /// - Returns: A member of the set. If the set is empty, returns `nil`.
-%elif Self == 'Dictionary':
+extension Dictionary {
   /// Removes and returns the first key-value pair of the dictionary if the
   /// dictionary isn't empty.
   ///
@@ -6493,7 +4782,6 @@
   ///   is not empty; otherwise, `nil`.
   ///
   /// - Complexity: Averages to O(1) over many calls to `popFirst()`.
-%end
   @_inlineable
   public mutating func popFirst() -> Element? {
     guard !isEmpty else { return nil }
@@ -6514,25 +4802,25 @@
     return result
   }
 
-  /// The total number of ${element}s that the ${a_self} can contain without
+  /// The total number of key-value pairs that the dictionary can contain without
   /// allocating new storage.
   @_inlineable // FIXME(sil-serialize-all)
   public var capacity: Int {
     return _variantBuffer.capacity
   }
 
-  /// Reserves enough space to store the specified number of ${element}s.
+  /// Reserves enough space to store the specified number of key-value pairs.
   ///
-  /// If you are adding a known number of ${element}s to a ${a_self}, use this
+  /// If you are adding a known number of key-value pairs to a dictionary, use this
   /// method to avoid multiple reallocations. This method ensures that the
-  /// ${a_self} has unique, mutable, contiguous storage, with space allocated
-  /// for at least the requested number of ${element}s.
+  /// dictionary has unique, mutable, contiguous storage, with space allocated
+  /// for at least the requested number of key-value pairs.
   ///
-  /// Calling the `reserveCapacity(_:)` method on a ${a_self} with bridged
+  /// Calling the `reserveCapacity(_:)` method on a dictionary with bridged
   /// storage triggers a copy to contiguous storage even if the existing
-  /// storage has room to store `minimumCapacity` ${element}s.
+  /// storage has room to store `minimumCapacity` key-value pairs.
   ///
-  /// - Parameter minimumCapacity: The requested number of ${element}s to
+  /// - Parameter minimumCapacity: The requested number of key-value pairs to
   ///   store.
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func reserveCapacity(_ minimumCapacity: Int) {
@@ -6544,14 +4832,14 @@
 //===--- Bridging ---------------------------------------------------------===//
 
 #if _runtime(_ObjC)
-extension ${Self} {
+extension Dictionary {
   @_inlineable // FIXME(sil-serialize-all)
-  public func _bridgeToObjectiveCImpl() -> _NS${Self}Core {
+  public func _bridgeToObjectiveCImpl() -> _NSDictionaryCore {
     switch _variantBuffer {
-    case _Variant${Self}Buffer.native(let buffer):
+    case _VariantDictionaryBuffer.native(let buffer):
       return buffer.bridged()
-    case _Variant${Self}Buffer.cocoa(let cocoaBuffer):
-      return cocoaBuffer.cocoa${Self}
+    case _VariantDictionaryBuffer.cocoa(let cocoaBuffer):
+      return cocoaBuffer.cocoaDictionary
     }
   }
 
@@ -6560,229 +4848,25 @@
   @_inlineable // FIXME(sil-serialize-all)
   public static func _bridgeFromObjectiveCAdoptingNativeStorageOf(
     _ s: AnyObject
-  ) -> ${Self}<${TypeParameters}>? {
+  ) -> Dictionary<Key, Value>? {
 
-    // Try all three NS${Self} impls that we currently provide.
+    // Try all three NSDictionary impls that we currently provide.
 
-    if let deferredBuffer = s as? _SwiftDeferredNS${Self}<${TypeParameters}> {
-      return ${Self}(_nativeBuffer: deferredBuffer.nativeBuffer)
+    if let deferredBuffer = s as? _SwiftDeferredNSDictionary<Key, Value> {
+      return Dictionary(_nativeBuffer: deferredBuffer.nativeBuffer)
     }
 
-    if let nativeStorage = s as? _HashableTypedNative${Self}Storage<${TypeParameters}> {
-      return ${Self}(_nativeBuffer: 
-          _Native${Self}Buffer(_storage: nativeStorage))
+    if let nativeStorage = s as? _HashableTypedNativeDictionaryStorage<Key, Value> {
+      return Dictionary(_nativeBuffer:
+          _NativeDictionaryBuffer(_storage: nativeStorage))
     }
 
-    if s === _RawNative${Self}Storage.empty {
-      return ${Self}()
+    if s === _RawNativeDictionaryStorage.empty {
+      return Dictionary()
     }
-    
+
     // FIXME: what if `s` is native storage, but for different key/value type?
     return nil
   }
 }
 #endif
-
-%end
-
-extension Set {
-  /// Removes the elements of the given set from this set.
-  ///
-  /// In the following example, the elements of the `employees` set that are
-  /// also members of the `neighbors` set are removed. In particular, the
-  /// names `"Bethany"` and `"Eric"` are removed from `employees`.
-  ///
-  ///     var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
-  ///     employees.subtract(neighbors)
-  ///     print(employees)
-  ///     // Prints "["Diana", "Chris", "Alicia"]"
-  ///
-  /// - Parameter other: Another set.
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func subtract(_ other: Set<Element>) {
-    _subtract(other)
-  }
-
-  /// Returns a Boolean value that indicates whether this set is a subset of
-  /// the given set.
-  ///
-  /// Set *A* is a subset of another set *B* if every member of *A* is also a
-  /// member of *B*.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
-  ///     print(attendees.isSubset(of: employees))
-  ///     // Prints "true"
-  ///
-  /// - Parameter other: Another set.
-  /// - Returns: `true` if the set is a subset of `other`; otherwise, `false`.
-  @_inlineable
-  public func isSubset(of other: Set<Element>) -> Bool {
-    let (isSubset, isEqual) = _compareSets(self, other)
-    return isSubset || isEqual
-  }
-
-  /// Returns a Boolean value that indicates whether this set is a superset of
-  /// the given set.
-  ///
-  /// Set *A* is a superset of another set *B* if every member of *B* is also a
-  /// member of *A*.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
-  ///     print(employees.isSuperset(of: attendees))
-  ///     // Prints "true"
-  ///
-  /// - Parameter other: Another set.
-  /// - Returns: `true` if the set is a superset of `other`; otherwise,
-  ///   `false`.
-  @_inlineable
-  public func isSuperset(of other: Set<Element>) -> Bool {
-    return other.isSubset(of: self)
-  }
-
-  /// Returns a Boolean value that indicates whether this set has no members in
-  /// common with the given set.
-  ///
-  /// In the following example, the `employees` set is disjoint with the
-  /// `visitors` set because no name appears in both sets.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let visitors: Set = ["Marcia", "Nathaniel", "Olivia"]
-  ///     print(employees.isDisjoint(with: visitors))
-  ///     // Prints "true"
-  ///
-  /// - Parameter other: Another set.
-  /// - Returns: `true` if the set has no elements in common with `other`;
-  ///   otherwise, `false`.
-  @_inlineable
-  public func isDisjoint(with other: Set<Element>) -> Bool {
-    for member in self {
-      if other.contains(member) {
-        return false
-      }
-    }
-    return true
-  }
-
-  /// Returns a new set containing the elements of this set that do not occur
-  /// in the given set.
-  ///
-  /// In the following example, the `nonNeighbors` set is made up of the
-  /// elements of the `employees` set that are not elements of `neighbors`:
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
-  ///     let nonNeighbors = employees.subtracting(neighbors)
-  ///     print(nonNeighbors)
-  ///     // Prints "["Diana", "Chris", "Alicia"]"
-  ///
-  /// - Parameter other: Another set.
-  /// - Returns: A new set.
-  @_inlineable
-  public func subtracting(_ other: Set<Element>) -> Set<Element> {
-    return self._subtracting(other)
-  }
-
-  /// Returns a Boolean value that indicates whether the set is a strict
-  /// superset of the given sequence.
-  ///
-  /// Set *A* is a strict superset of another set *B* if every member of *B* is
-  /// also a member of *A* and *A* contains at least one element that is *not*
-  /// a member of *B*.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
-  ///     print(employees.isStrictSuperset(of: attendees))
-  ///     // Prints "true"
-  ///     print(employees.isStrictSuperset(of: employees))
-  ///     // Prints "false"
-  ///
-  /// - Parameter other: Another set.
-  /// - Returns: `true` if the set is a strict superset of
-  ///   `other`; otherwise, `false`.
-  @_inlineable
-  public func isStrictSuperset(of other: Set<Element>) -> Bool {
-    return self.isSuperset(of: other) && self != other
-  }
-
-  /// Returns a Boolean value that indicates whether the set is a strict subset
-  /// of the given sequence.
-  ///
-  /// Set *A* is a strict subset of another set *B* if every member of *A* is
-  /// also a member of *B* and *B* contains at least one element that is not a
-  /// member of *A*.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
-  ///     print(attendees.isStrictSubset(of: employees))
-  ///     // Prints "true"
-  ///
-  ///     // A set is never a strict subset of itself:
-  ///     print(attendees.isStrictSubset(of: attendees))
-  ///     // Prints "false"
-  ///
-  /// - Parameter other: Another set.
-  /// - Returns: `true` if the set is a strict subset of
-  ///   `other`; otherwise, `false`.
-  @_inlineable
-  public func isStrictSubset(of other: Set<Element>) -> Bool {
-    return other.isStrictSuperset(of: self)
-  }
-
-  /// Returns a new set with the elements that are common to both this set and
-  /// the given sequence.
-  ///
-  /// In the following example, the `bothNeighborsAndEmployees` set is made up
-  /// of the elements that are in *both* the `employees` and `neighbors` sets.
-  /// Elements that are in only one or the other are left out of the result of
-  /// the intersection.
-  ///
-  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
-  ///     let bothNeighborsAndEmployees = employees.intersection(neighbors)
-  ///     print(bothNeighborsAndEmployees)
-  ///     // Prints "["Bethany", "Eric"]"
-  ///
-  /// - Parameter other: Another set.
-  /// - Returns: A new set.
-  @_inlineable
-  public func intersection(_ other: Set<Element>) -> Set<Element> {
-    var newSet = Set<Element>()
-    for member in self {
-      if other.contains(member) {
-        newSet.insert(member)
-      }
-    }
-    return newSet
-  }
-
-  /// Removes the elements of the set that are also in the given sequence and
-  /// adds the members of the sequence that are not already in the set.
-  ///
-  /// In the following example, the elements of the `employees` set that are
-  /// also members of `neighbors` are removed from `employees`, while the
-  /// elements of `neighbors` that are not members of `employees` are added to
-  /// `employees`. In particular, the names `"Alicia"`, `"Chris"`, and
-  /// `"Diana"` are removed from `employees` while the names `"Forlani"` and
-  /// `"Greta"` are added.
-  ///
-  ///     var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
-  ///     let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
-  ///     employees.formSymmetricDifference(neighbors)
-  ///     print(employees)
-  ///     // Prints "["Diana", "Chris", "Forlani", "Alicia", "Greta"]"
-  ///
-  /// - Parameter other: Another set.
-  @_inlineable
-  public mutating func formSymmetricDifference(_ other: Set<Element>) {
-    for member in other {
-      if contains(member) {
-        remove(member)
-      } else {
-        insert(member)
-      }
-    }
-  }
-}
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index ff9a700..cd794ac 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -74,8 +74,8 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public // @testable
-  init(_bits v: Builtin.FPIEEE${bits}) {
-    self._value = v
+  init(_ _value: Builtin.FPIEEE${bits}) {
+    self._value = _value
   }
 }
 
@@ -214,7 +214,7 @@
   /// - Parameter bitPattern: The integer encoding of a `${Self}` instance.
   @_inlineable // FIXME(sil-serialize-all)
   public init(bitPattern: UInt${bits}) {
-    self.init(_bits: Builtin.bitcast_Int${bits}_FPIEEE${bits}(bitPattern._value))
+    self.init(Builtin.bitcast_Int${bits}_FPIEEE${bits}(bitPattern._value))
   }
 
   /// The sign of the floating-point value.
@@ -1449,7 +1449,7 @@
   @_transparent
   public
   init(_builtinIntegerLiteral value: Builtin.Int${builtinIntLiteralBits}){
-    self = ${Self}(_bits: Builtin.itofp_with_overflow_Int${builtinIntLiteralBits}_FPIEEE${bits}(value))
+    self = ${Self}(Builtin.itofp_with_overflow_Int${builtinIntLiteralBits}_FPIEEE${bits}(value))
   }
 
   /// Creates a new value from the given integer literal.
@@ -1468,7 +1468,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public init(integerLiteral value: Int64) {
-    self = ${Self}(_bits: Builtin.sitofp_Int64_FPIEEE${bits}(value._value))
+    self = ${Self}(Builtin.sitofp_Int64_FPIEEE${bits}(value._value))
   }
 }
 
@@ -1483,9 +1483,9 @@
   public
   init(_builtinFloatLiteral value: Builtin.FPIEEE${builtinFloatLiteralBits}) {
 %   if bits == builtinFloatLiteralBits:
-    self = ${Self}(_bits: value)
+    self = ${Self}(value)
 %   elif bits < builtinFloatLiteralBits:
-    self = ${Self}(_bits: Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
+    self = ${Self}(Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
 %   else:
     // FIXME: This is actually losing precision <rdar://problem/14073102>.
     self = ${Self}(Builtin.fpext_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
@@ -1503,10 +1503,10 @@
   public
   init(_builtinFloatLiteral value: Builtin.FPIEEE${builtinFloatLiteralBits}) {
 %   if bits == builtinFloatLiteralBits:
-    self = ${Self}(_bits: value)
+    self = ${Self}(value)
 %   elif bits < builtinFloatLiteralBits:
     // FIXME: This can result in double rounding errors (SR-7124).
-    self = ${Self}(_bits: Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
+    self = ${Self}(Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
 %   else:
     // FIXME: This is actually losing precision <rdar://problem/14073102>.
     self = ${Self}(Builtin.fpext_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
@@ -1569,7 +1569,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public var magnitude: ${Self} {
-    return ${Self}(_bits: Builtin.int_fabs_FPIEEE${bits}(_value))
+    return ${Self}(Builtin.int_fabs_FPIEEE${bits}(_value))
   }
 }
 
@@ -1577,7 +1577,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public static prefix func - (x: ${Self}) -> ${Self} {
-    return ${Self}(_bits: Builtin.fneg_FPIEEE${bits}(x._value))
+    return ${Self}(Builtin.fneg_FPIEEE${bits}(x._value))
   }
 }
 
diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json
index 1549445..735a3ae 100644
--- a/stdlib/public/core/GroupInfo.json
+++ b/stdlib/public/core/GroupInfo.json
@@ -105,8 +105,9 @@
         "SliceBuffer.swift",
         "SwiftNativeNSArray.swift"],
       "HashedCollections": [
-        "HashedCollections.swift",
-        "HashedCollectionsAnyHashableExtensions.swift"
+        "Dictionary.swift",
+        "HashedCollectionsAnyHashableExtensions.swift",
+        "Set.swift",
       ]
     }
   ],
diff --git a/stdlib/public/core/Hashable.swift b/stdlib/public/core/Hashable.swift
index d92cad5..0be9f2d 100644
--- a/stdlib/public/core/Hashable.swift
+++ b/stdlib/public/core/Hashable.swift
@@ -83,7 +83,7 @@
 /// point's `x` property with the hash value of its `y` property multiplied by
 /// a prime constant.
 ///
-/// - Note: The above example above is a reasonably good hash function for a
+/// - Note: The example above is a reasonably good hash function for a
 ///   simple type. If you're writing a hash function for a custom type, choose
 ///   a hashing algorithm that is appropriate for the kinds of data your type
 ///   comprises. Set and dictionary performance depends on hash values that
diff --git a/stdlib/public/core/Hashing.swift b/stdlib/public/core/Hashing.swift
index 99c6432..ffa5b40 100644
--- a/stdlib/public/core/Hashing.swift
+++ b/stdlib/public/core/Hashing.swift
@@ -294,3 +294,113 @@
     return Int(truncatingIfNeeded: _core.finalize())
   }
 }
+
+/// This protocol is only used for compile-time checks that
+/// every buffer type implements all required operations.
+internal protocol _HashBuffer {
+  associatedtype Key
+  associatedtype Value
+  associatedtype Index
+  associatedtype SequenceElement
+  associatedtype SequenceElementWithoutLabels
+  var startIndex: Index { get }
+  var endIndex: Index { get }
+
+  func index(after i: Index) -> Index
+
+  func formIndex(after i: inout Index)
+
+  func index(forKey key: Key) -> Index?
+
+  func assertingGet(_ i: Index) -> SequenceElement
+
+  func assertingGet(_ key: Key) -> Value
+
+  func maybeGet(_ key: Key) -> Value?
+
+  @discardableResult
+  mutating func updateValue(_ value: Value, forKey key: Key) -> Value?
+
+  @discardableResult
+  mutating func insert(
+    _ value: Value, forKey key: Key
+  ) -> (inserted: Bool, memberAfterInsert: Value)
+
+  @discardableResult
+  mutating func remove(at index: Index) -> SequenceElement
+
+  @discardableResult
+  mutating func removeValue(forKey key: Key) -> Value?
+
+  mutating func removeAll(keepingCapacity keepCapacity: Bool)
+
+  var count: Int { get }
+
+  static func fromArray(_ elements: [SequenceElementWithoutLabels]) -> Self
+}
+
+/// The inverse of the default hash table load factor.  Factored out so that it
+/// can be used in multiple places in the implementation and stay consistent.
+/// Should not be used outside `Dictionary` implementation.
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_transparent
+internal var _hashContainerDefaultMaxLoadFactorInverse: Double {
+  return 1.0 / 0.75
+}
+
+#if _runtime(_ObjC)
+/// Call `[lhs isEqual: rhs]`.
+///
+/// This function is part of the runtime because `Bool` type is bridged to
+/// `ObjCBool`, which is in Foundation overlay.
+/// FIXME(sil-serialize-all): this should be internal
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_silgen_name("swift_stdlib_NSObject_isEqual")
+internal func _stdlib_NSObject_isEqual(_ lhs: AnyObject, _ rhs: AnyObject) -> Bool
+#endif
+
+
+/// A temporary view of an array of AnyObject as an array of Unmanaged<AnyObject>
+/// for fast iteration and transformation of the elements.
+///
+/// Accesses the underlying raw memory as Unmanaged<AnyObject> using untyped
+/// memory accesses. The memory remains bound to managed AnyObjects.
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal struct _UnmanagedAnyObjectArray {
+  /// Underlying pointer.
+  @_versioned // FIXME(sil-serialize-all)
+  internal var value: UnsafeMutableRawPointer
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_ up: UnsafeMutablePointer<AnyObject>) {
+    self.value = UnsafeMutableRawPointer(up)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init?(_ up: UnsafeMutablePointer<AnyObject>?) {
+    guard let unwrapped = up else { return nil }
+    self.init(unwrapped)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal subscript(i: Int) -> AnyObject {
+    get {
+      let unmanaged = value.load(
+        fromByteOffset: i * MemoryLayout<AnyObject>.stride,
+        as: Unmanaged<AnyObject>.self)
+      return unmanaged.takeUnretainedValue()
+    }
+    nonmutating set(newValue) {
+      let unmanaged = Unmanaged.passUnretained(newValue)
+      value.storeBytes(of: unmanaged,
+        toByteOffset: i * MemoryLayout<AnyObject>.stride,
+        as: Unmanaged<AnyObject>.self)
+    }
+  }
+}
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 53404cb..683d7ca 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -3290,14 +3290,6 @@
     self._value = _value
   }
 
-  // FIXME(integers): in order to remove this, the simd.swift.gyb should be
-  // updated
-  @_inlineable // FIXME(sil-serialize-all)
-  @_transparent
-  public init(_bits: Builtin.Int${bits}) {
-    self._value = _bits
-  }
-
 % for x in binaryBitwise:
 ${assignmentOperatorComment(x.operator, True)}
   @_inlineable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/Set.swift b/stdlib/public/core/Set.swift
new file mode 100644
index 0000000..b7fa38f
--- /dev/null
+++ b/stdlib/public/core/Set.swift
@@ -0,0 +1,4198 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import SwiftShims
+
+//===--- APIs unique to Set<Element> --------------------------------------===//
+
+/// An unordered collection of unique elements.
+///
+/// You use a set instead of an array when you need to test efficiently for
+/// membership and you aren't concerned with the order of the elements in the
+/// collection, or when you need to ensure that each element appears only once
+/// in a collection.
+///
+/// You can create a set with any element type that conforms to the `Hashable`
+/// protocol. By default, most types in the standard library are hashable,
+/// including strings, numeric and Boolean types, enumeration cases without
+/// associated values, and even sets themselves.
+///
+/// Swift makes it as easy to create a new set as to create a new array. Simply
+/// assign an array literal to a variable or constant with the `Set` type
+/// specified.
+///
+///     let ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
+///     if ingredients.contains("sugar") {
+///         print("No thanks, too sweet.")
+///     }
+///     // Prints "No thanks, too sweet."
+///
+/// Set Operations
+/// ==============
+///
+/// Sets provide a suite of mathematical set operations. For example, you can
+/// efficiently test a set for membership of an element or check its
+/// intersection with another set:
+///
+/// - Use the `contains(_:)` method to test whether a set contains a specific
+///   element.
+/// - Use the "equal to" operator (`==`) to test whether two sets contain the
+///   same elements.
+/// - Use the `isSubset(of:)` method to test whether a set contains all the
+///   elements of another set or sequence.
+/// - Use the `isSuperset(of:)` method to test whether all elements of a set
+///   are contained in another set or sequence.
+/// - Use the `isStrictSubset(of:)` and `isStrictSuperset(of:)` methods to test
+///   whether a set is a subset or superset of, but not equal to, another set.
+/// - Use the `isDisjoint(with:)` method to test whether a set has any elements
+///   in common with another set.
+///
+/// You can also combine, exclude, or subtract the elements of two sets:
+///
+/// - Use the `union(_:)` method to create a new set with the elements of a set
+///   and another set or sequence.
+/// - Use the `intersection(_:)` method to create a new set with only the
+///   elements common to a set and another set or sequence.
+/// - Use the `symmetricDifference(_:)` method to create a new set with the
+///   elements that are in either a set or another set or sequence, but not in
+///   both.
+/// - Use the `subtracting(_:)` method to create a new set with the elements of
+///   a set that are not also in another set or sequence.
+///
+/// You can modify a set in place by using these methods' mutating
+/// counterparts: `formUnion(_:)`, `formIntersection(_:)`,
+/// `formSymmetricDifference(_:)`, and `subtract(_:)`.
+///
+/// Set operations are not limited to use with other sets. Instead, you can
+/// perform set operations with another set, an array, or any other sequence
+/// type.
+///
+///     var primes: Set = [2, 3, 5, 7]
+///
+///     // Tests whether primes is a subset of a Range<Int>
+///     print(primes.isSubset(of: 0..<10))
+///     // Prints "true"
+///
+///     // Performs an intersection with an Array<Int>
+///     let favoriteNumbers = [5, 7, 15, 21]
+///     print(primes.intersection(favoriteNumbers))
+///     // Prints "[5, 7]"
+///
+/// Sequence and Collection Operations
+/// ==================================
+///
+/// In addition to the `Set` type's set operations, you can use any nonmutating
+/// sequence or collection methods with a set.
+///
+///     if primes.isEmpty {
+///         print("No primes!")
+///     } else {
+///         print("We have \(primes.count) primes.")
+///     }
+///     // Prints "We have 4 primes."
+///
+///     let primesSum = primes.reduce(0, +)
+///     // 'primesSum' == 17
+///
+///     let primeStrings = primes.sorted().map(String.init)
+///     // 'primeStrings' == ["2", "3", "5", "7"]
+///
+/// You can iterate through a set's unordered elements with a `for`-`in` loop.
+///
+///     for number in primes {
+///         print(number)
+///     }
+///     // Prints "5"
+///     // Prints "7"
+///     // Prints "2"
+///     // Prints "3"
+///
+/// Many sequence and collection operations return an array or a type-erasing
+/// collection wrapper instead of a set. To restore efficient set operations,
+/// create a new set from the result.
+///
+///     let morePrimes = primes.union([11, 13, 17, 19])
+///
+///     let laterPrimes = morePrimes.filter { $0 > 10 }
+///     // 'laterPrimes' is of type Array<Int>
+///
+///     let laterPrimesSet = Set(morePrimes.filter { $0 > 10 })
+///     // 'laterPrimesSet' is of type Set<Int>
+///
+/// Bridging Between Set and NSSet
+/// ==============================
+///
+/// You can bridge between `Set` and `NSSet` using the `as` operator. For
+/// bridging to be possible, the `Element` type of a set must be a class, an
+/// `@objc` protocol (a protocol imported from Objective-C or marked with the
+/// `@objc` attribute), or a type that bridges to a Foundation type.
+///
+/// Bridging from `Set` to `NSSet` always takes O(1) time and space. When the
+/// set's `Element` type is neither a class nor an `@objc` protocol, any
+/// required bridging of elements occurs at the first access of each element,
+/// so the first operation that uses the contents of the set (for example, a
+/// membership test) can take O(*n*).
+///
+/// Bridging from `NSSet` to `Set` first calls the `copy(with:)` method
+/// (`- copyWithZone:` in Objective-C) on the set to get an immutable copy and
+/// then performs additional Swift bookkeeping work that takes O(1) time. For
+/// instances of `NSSet` that are already immutable, `copy(with:)` returns the
+/// same set in constant time; otherwise, the copying performance is
+/// unspecified. The instances of `NSSet` and `Set` share buffer using the
+/// same copy-on-write optimization that is used when two instances of `Set`
+/// share buffer.
+@_fixed_layout
+public struct Set<Element: Hashable> {
+  internal typealias _VariantBuffer = _VariantSetBuffer<Element>
+  internal typealias _NativeBuffer = _NativeSetBuffer<Element>
+
+  @_versioned
+  internal var _variantBuffer: _VariantBuffer
+}
+
+extension Set {
+  /// Creates a new, empty set with at least the specified number of elements'
+  /// worth of buffer.
+  ///
+  /// Use this initializer to avoid repeated reallocations of a set's buffer
+  /// if you know you'll be adding elements to the set after creation. The
+  /// actual capacity of the created set will be the smallest power of 2 that
+  /// is greater than or equal to `minimumCapacity`.
+  ///
+  /// - Parameter minimumCapacity: The minimum number of elements that the
+  ///   newly created set should be able to store without reallocating its
+  ///   buffer.
+  @_inlineable // FIXME(sil-serialize-all)
+  public init(minimumCapacity: Int) {
+    _variantBuffer =
+      _VariantBuffer.native(
+        _NativeBuffer(minimumCapacity: minimumCapacity))
+  }
+
+  /// Private initializer.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_nativeBuffer: _NativeSetBuffer<Element>) {
+    _variantBuffer = _VariantBuffer.native(_nativeBuffer)
+  }
+
+  //
+  // All APIs below should dispatch to `_variantBuffer`, without doing any
+  // additional processing.
+  //
+
+#if _runtime(_ObjC)
+  /// Private initializer used for bridging.
+  ///
+  /// Only use this initializer when both conditions are true:
+  ///
+  /// * it is statically known that the given `NSSet` is immutable;
+  /// * `Element` is bridged verbatim to Objective-C (i.e.,
+  ///   is a reference type).
+  @_inlineable // FIXME(sil-serialize-all)
+  public init(_immutableCocoaSet: _NSSet) {
+    _sanityCheck(_isBridgedVerbatimToObjectiveC(Element.self),
+      "Set can be backed by NSSet _variantBuffer only when the member type can be bridged verbatim to Objective-C")
+    _variantBuffer = _VariantSetBuffer.cocoa(
+      _CocoaSetBuffer(cocoaSet: _immutableCocoaSet))
+  }
+#endif
+}
+
+extension Set: ExpressibleByArrayLiteral {
+
+  //
+  // `ExpressibleByArrayLiteral` conformance
+  //
+  /// Creates a set containing the elements of the given array literal.
+  ///
+  /// Do not call this initializer directly. It is used by the compiler when
+  /// you use an array literal. Instead, create a new set using an array
+  /// literal as its value by enclosing a comma-separated list of values in
+  /// square brackets. You can use an array literal anywhere a set is expected
+  /// by the type context.
+  ///
+  /// Here, a set of strings is created from an array literal holding only
+  /// strings.
+  ///
+  ///     let ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
+  ///     if ingredients.isSuperset(of: ["sugar", "salt"]) {
+  ///         print("Whatever it is, it's bound to be delicious!")
+  ///     }
+  ///     // Prints "Whatever it is, it's bound to be delicious!"
+  ///
+  /// - Parameter elements: A variadic list of elements of the new set.
+  @_inlineable // FIXME(sil-serialize-all)
+  public init(arrayLiteral elements: Element...) {
+    self.init(_nativeBuffer: _NativeSetBuffer.fromArray(elements))
+  }
+}
+
+extension Set: Sequence {
+  /// Returns an iterator over the members of the set.
+  @_inlineable // FIXME(sil-serialize-all)
+  @inline(__always)
+  public func makeIterator() -> SetIterator<Element> {
+    return _variantBuffer.makeIterator()
+  }
+
+  /// Returns a Boolean value that indicates whether the given element exists
+  /// in the set.
+  ///
+  /// This example uses the `contains(_:)` method to test whether an integer is
+  /// a member of a set of prime numbers.
+  ///
+  ///     let primes: Set = [2, 3, 5, 7]
+  ///     let x = 5
+  ///     if primes.contains(x) {
+  ///         print("\(x) is prime!")
+  ///     } else {
+  ///         print("\(x). Not prime.")
+  ///     }
+  ///     // Prints "5 is prime!"
+  ///
+  /// - Parameter member: An element to look for in the set.
+  /// - Returns: `true` if `member` exists in the set; otherwise, `false`.
+  ///
+  /// - Complexity: O(1)
+  @_inlineable // FIXME(sil-serialize-all)
+  public func contains(_ member: Element) -> Bool {
+    return _variantBuffer.maybeGet(member) != nil
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _customContainsEquatableElement(_ member: Element) -> Bool? {
+    return contains(member)
+  }
+}
+
+// This is not quite Sequence.filter, because that returns [Element], not Self
+// (RangeReplaceableCollection.filter returns Self, but Set isn't an RRC)
+extension Set {
+  /// Returns a new set containing the elements of the set that satisfy the
+  /// given predicate.
+  ///
+  /// In this example, `filter(_:)` is used to include only names shorter than
+  /// five characters.
+  ///
+  ///     let cast: Set = ["Vivien", "Marlon", "Kim", "Karl"]
+  ///     let shortNames = cast.filter { $0.count < 5 }
+  ///
+  ///     shortNames.isSubset(of: cast)
+  ///     // true
+  ///     shortNames.contains("Vivien")
+  ///     // false
+  ///
+  /// - Parameter isIncluded: A closure that takes an element as its argument
+  ///   and returns a Boolean value indicating whether the element should be
+  ///   included in the returned set.
+  /// - Returns: A set of the elements that `isIncluded` allows.
+  @_inlineable
+  @available(swift, introduced: 4.0)
+  public func filter(
+    _ isIncluded: (Element) throws -> Bool
+  ) rethrows -> Set {
+    var result = Set()
+    for element in self {
+      if try isIncluded(element) {
+        result.insert(element)
+      }
+    }
+    return result
+  }
+}
+
+extension Set: Collection {
+  /// The starting position for iterating members of the set.
+  ///
+  /// If the set is empty, `startIndex` is equal to `endIndex`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var startIndex: Index {
+    return _variantBuffer.startIndex
+  }
+
+  /// The "past the end" position for the set---that is, the position one
+  /// greater than the last valid subscript argument.
+  ///
+  /// If the set is empty, `endIndex` is equal to `startIndex`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var endIndex: Index {
+    return _variantBuffer.endIndex
+  }
+
+  /// Accesses the member at the given position.
+  @_inlineable // FIXME(sil-serialize-all)
+  public subscript(position: Index) -> Element {
+    return _variantBuffer.assertingGet(position)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(after i: Index) -> Index {
+    return _variantBuffer.index(after: i)
+  }
+
+  // APINAMING: complexity docs are broadly missing in this file.
+
+  /// Returns the index of the given element in the set, or `nil` if the
+  /// element is not a member of the set.
+  ///
+  /// - Parameter member: An element to search for in the set.
+  /// - Returns: The index of `member` if it exists in the set; otherwise,
+  ///   `nil`.
+  ///
+  /// - Complexity: O(1)
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(of member: Element) -> Index? {
+    return _variantBuffer.index(forKey: member)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _customIndexOfEquatableElement(
+     _ member: Element
+    ) -> Index?? {
+    return Optional(index(of: member))
+  }
+
+  /// The number of elements in the set.
+  ///
+  /// - Complexity: O(1).
+  @_inlineable // FIXME(sil-serialize-all)
+  public var count: Int {
+    return _variantBuffer.count
+  }
+
+  /// A Boolean value that indicates whether the set is empty.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var isEmpty: Bool {
+    return count == 0
+  }
+
+  /// The first element of the set.
+  ///
+  /// The first element of the set is not necessarily the first element added
+  /// to the set. Don't expect any particular ordering of set elements.
+  ///
+  /// If the set is empty, the value of this property is `nil`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var first: Element? {
+    return count > 0 ? self[startIndex] : nil
+  }
+}
+
+/// Check for both subset and equality relationship between
+/// a set and some sequence (which may itself be a `Set`).
+///
+/// (isSubset: lhs ⊂ rhs, isEqual: lhs ⊂ rhs and |lhs| = |rhs|)
+@_inlineable
+@_versioned
+internal func _compareSets<Element>(_ lhs: Set<Element>, _ rhs: Set<Element>)
+  -> (isSubset: Bool, isEqual: Bool) {
+  // FIXME(performance): performance could be better if we start by comparing
+  // counts.
+  for member in lhs {
+    if !rhs.contains(member) {
+      return (false, false)
+    }
+  }
+  return (true, lhs.count == rhs.count)
+}
+
+// FIXME: rdar://problem/23549059 (Optimize == for Set)
+// Look into initially trying to compare the two sets by directly comparing the
+// contents of both buffers in order. If they happen to have the exact same
+// ordering we can get the `true` response without ever hashing. If the two
+// buffers' contents differ at all then we have to fall back to hashing the
+// rest of the elements (but we don't need to hash any prefix that did match).
+extension Set: Equatable {
+  /// Returns a Boolean value indicating whether two sets have equal elements.
+  ///
+  /// - Parameters:
+  ///   - lhs: A set.
+  ///   - rhs: Another set.
+  /// - Returns: `true` if the `lhs` and `rhs` have the same elements; otherwise,
+  ///   `false`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func == (lhs: Set<Element>, rhs: Set<Element>) -> Bool {
+    switch (lhs._variantBuffer, rhs._variantBuffer) {
+    case (.native(let lhsNative), .native(let rhsNative)):
+
+      if lhsNative._storage === rhsNative._storage {
+        return true
+      }
+
+      if lhsNative.count != rhsNative.count {
+        return false
+      }
+
+      for member in lhs {
+        let (_, found) =
+          rhsNative._find(member, startBucket: rhsNative._bucket(member))
+        if !found {
+          return false
+        }
+      }
+      return true
+
+  #if _runtime(_ObjC)
+    case (_VariantSetBuffer.cocoa(let lhsCocoa),
+        _VariantSetBuffer.cocoa(let rhsCocoa)):
+      return _stdlib_NSObject_isEqual(lhsCocoa.cocoaSet, rhsCocoa.cocoaSet)
+
+    case (_VariantSetBuffer.native(let lhsNative),
+      _VariantSetBuffer.cocoa(let rhsCocoa)):
+
+      if lhsNative.count != rhsCocoa.count {
+        return false
+      }
+
+      let endIndex = lhsNative.endIndex
+      var i = lhsNative.startIndex
+      while i != endIndex {
+        let key = lhsNative.assertingGet(i)
+        let bridgedKey: AnyObject = _bridgeAnythingToObjectiveC(key)
+        let optRhsValue: AnyObject? = rhsCocoa.maybeGet(bridgedKey)
+        if let rhsValue = optRhsValue {
+          if key == _forceBridgeFromObjectiveC(rhsValue, Element.self) {
+            i = lhsNative.index(after: i)
+            continue
+          }
+        }
+        i = lhsNative.index(after: i)
+        return false
+      }
+      return true
+
+    case (_VariantSetBuffer.cocoa, _VariantSetBuffer.native):
+      return rhs == lhs
+  #endif
+    }
+  }
+}
+
+extension Set: Hashable {
+  /// The hash value for the set.
+  ///
+  /// Two sets that are equal will always have equal hash values.
+  ///
+  /// Hash values are not guaranteed to be equal across different executions of
+  /// your program. Do not save hash values to use during a future execution.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var hashValue: Int {
+    // FIXME(ABI)#177: <rdar://problem/18915294> Cache Set<T> hashValue
+    return _hashValue(for: self)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _hash(into hasher: inout _Hasher) {
+    var hash = 0
+    for member in self {
+      hash ^= _hashValue(for: member)
+    }
+    hasher.append(hash)
+  }
+}
+
+extension Set: SetAlgebra {
+
+  /// Inserts the given element in the set if it is not already present.
+  ///
+  /// If an element equal to `newMember` is already contained in the set, this
+  /// method has no effect. In the following example, a new element is
+  /// inserted into `classDays`, a set of days of the week. When an existing
+  /// element is inserted, the `classDays` set does not change.
+  ///
+  ///     enum DayOfTheWeek: Int {
+  ///         case sunday, monday, tuesday, wednesday, thursday,
+  ///             friday, saturday
+  ///     }
+  ///
+  ///     var classDays: Set<DayOfTheWeek> = [.wednesday, .friday]
+  ///     print(classDays.insert(.monday))
+  ///     // Prints "(true, .monday)"
+  ///     print(classDays)
+  ///     // Prints "[.friday, .wednesday, .monday]"
+  ///
+  ///     print(classDays.insert(.friday))
+  ///     // Prints "(false, .friday)"
+  ///     print(classDays)
+  ///     // Prints "[.friday, .wednesday, .monday]"
+  ///
+  /// - Parameter newMember: An element to insert into the set.
+  /// - Returns: `(true, newMember)` if `newMember` was not contained in the
+  ///   set. If an element equal to `newMember` was already contained in the
+  ///   set, the method returns `(false, oldMember)`, where `oldMember` is the
+  ///   element that was equal to `newMember`. In some cases, `oldMember` may
+  ///   be distinguishable from `newMember` by identity comparison or some
+  ///   other means.
+  @_inlineable // FIXME(sil-serialize-all)
+  @discardableResult
+  public mutating func insert(
+    _ newMember: Element
+  ) -> (inserted: Bool, memberAfterInsert: Element) {
+    return _variantBuffer.insert(newMember, forKey: newMember)
+  }
+
+  /// Inserts the given element into the set unconditionally.
+  ///
+  /// If an element equal to `newMember` is already contained in the set,
+  /// `newMember` replaces the existing element. In this example, an existing
+  /// element is inserted into `classDays`, a set of days of the week.
+  ///
+  ///     enum DayOfTheWeek: Int {
+  ///         case sunday, monday, tuesday, wednesday, thursday,
+  ///             friday, saturday
+  ///     }
+  ///
+  ///     var classDays: Set<DayOfTheWeek> = [.monday, .wednesday, .friday]
+  ///     print(classDays.update(with: .monday))
+  ///     // Prints "Optional(.monday)"
+  ///
+  /// - Parameter newMember: An element to insert into the set.
+  /// - Returns: An element equal to `newMember` if the set already contained
+  ///   such a member; otherwise, `nil`. In some cases, the returned element
+  ///   may be distinguishable from `newMember` by identity comparison or some
+  ///   other means.
+  @_inlineable // FIXME(sil-serialize-all)
+  @discardableResult
+  public mutating func update(with newMember: Element) -> Element? {
+    return _variantBuffer.updateValue(newMember, forKey: newMember)
+  }
+
+  /// Removes the specified element from the set.
+  ///
+  /// This example removes the element `"sugar"` from a set of ingredients.
+  ///
+  ///     var ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
+  ///     let toRemove = "sugar"
+  ///     if let removed = ingredients.remove(toRemove) {
+  ///         print("The recipe is now \(removed)-free.")
+  ///     }
+  ///     // Prints "The recipe is now sugar-free."
+  ///
+  /// - Parameter member: The element to remove from the set.
+  /// - Returns: The value of the `member` parameter if it was a member of the
+  ///   set; otherwise, `nil`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @discardableResult
+  public mutating func remove(_ member: Element) -> Element? {
+    return _variantBuffer.removeValue(forKey: member)
+  }
+
+  /// Removes the element at the given index of the set.
+  ///
+  /// - Parameter position: The index of the member to remove. `position` must
+  ///   be a valid index of the set, and must not be equal to the set's end
+  ///   index.
+  /// - Returns: The element that was removed from the set.
+  @_inlineable // FIXME(sil-serialize-all)
+  @discardableResult
+  public mutating func remove(at position: Index) -> Element {
+    return _variantBuffer.remove(at: position)
+  }
+
+  /// Removes all members from the set.
+  ///
+  /// - Parameter keepingCapacity: If `true`, the set's buffer capacity is
+  ///   preserved; if `false`, the underlying buffer is released. The
+  ///   default is `false`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
+    _variantBuffer.removeAll(keepingCapacity: keepCapacity)
+  }
+
+  /// Removes the first element of the set.
+  ///
+  /// Because a set is not an ordered collection, the "first" element may not
+  /// be the first element that was added to the set. The set must not be
+  /// empty.
+  ///
+  /// - Complexity: Amortized O(1) if the set does not wrap a bridged `NSSet`.
+  ///   If the set wraps a bridged `NSSet`, the performance is unspecified.
+  ///
+  /// - Returns: A member of the set.
+  @_inlineable // FIXME(sil-serialize-all)
+  @discardableResult
+  public mutating func removeFirst() -> Element {
+    _precondition(!isEmpty, "Can't removeFirst from an empty Set")
+    return remove(at: startIndex)
+  }
+
+  //
+  // APIs below this comment should be implemented strictly in terms of
+  // *public* APIs above.  `_variantBuffer` should not be accessed directly.
+  //
+  // This separates concerns for testing.  Tests for the following APIs need
+  // not to concern themselves with testing correctness of behavior of
+  // underlying buffer (and different variants of it), only correctness of the
+  // API itself.
+  //
+
+  /// Creates an empty set.
+  ///
+  /// This is equivalent to initializing with an empty array literal. For
+  /// example:
+  ///
+  ///     var emptySet = Set<Int>()
+  ///     print(emptySet.isEmpty)
+  ///     // Prints "true"
+  ///
+  ///     emptySet = []
+  ///     print(emptySet.isEmpty)
+  ///     // Prints "true"
+  @_inlineable // FIXME(sil-serialize-all)
+  public init() {
+    self = Set<Element>(_nativeBuffer: _NativeBuffer())
+  }
+
+  /// Creates a new set from a finite sequence of items.
+  ///
+  /// Use this initializer to create a new set from an existing sequence, for
+  /// example, an array or a range.
+  ///
+  ///     let validIndices = Set(0..<7).subtracting([2, 4, 5])
+  ///     print(validIndices)
+  ///     // Prints "[6, 0, 1, 3]"
+  ///
+  /// This initializer can also be used to restore set methods after performing
+  /// sequence operations such as `filter(_:)` or `map(_:)` on a set. For
+  /// example, after filtering a set of prime numbers to remove any below 10,
+  /// you can create a new set by using this initializer.
+  ///
+  ///     let primes: Set = [2, 3, 5, 7, 11, 13, 17, 19, 23]
+  ///     let laterPrimes = Set(primes.lazy.filter { $0 > 10 })
+  ///     print(laterPrimes)
+  ///     // Prints "[17, 19, 23, 11, 13]"
+  ///
+  /// - Parameter sequence: The elements to use as members of the new set.
+  @_inlineable // FIXME(sil-serialize-all)
+  public init<Source: Sequence>(_ sequence: Source)
+    where Source.Element == Element {
+    self.init(minimumCapacity: sequence.underestimatedCount)
+    if let s = sequence as? Set<Element> {
+      // If this sequence is actually a native `Set`, then we can quickly
+      // adopt its native buffer and let COW handle uniquing only
+      // if necessary.
+      switch s._variantBuffer {
+        case .native(let buffer):
+          _variantBuffer = .native(buffer)
+#if _runtime(_ObjC)
+        case .cocoa(let owner):
+          _variantBuffer = .cocoa(owner)
+#endif
+      }
+    } else {
+      for item in sequence {
+        insert(item)
+      }
+    }
+  }
+
+  /// Returns a Boolean value that indicates whether the set is a subset of the
+  /// given sequence.
+  ///
+  /// Set *A* is a subset of another set *B* if every member of *A* is also a
+  /// member of *B*.
+  ///
+  ///     let employees = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
+  ///     print(attendees.isSubset(of: employees))
+  ///     // Prints "true"
+  ///
+  /// - Parameter possibleSuperset: A sequence of elements. `possibleSuperset`
+  ///   must be finite.
+  /// - Returns: `true` if the set is a subset of `possibleSuperset`;
+  ///   otherwise, `false`.
+  @_inlineable
+  public func isSubset<S: Sequence>(of possibleSuperset: S) -> Bool
+    where S.Element == Element {
+    // FIXME(performance): isEmpty fast path, here and elsewhere.
+    let other = Set(possibleSuperset)
+    return isSubset(of: other)
+  }
+
+  /// Returns a Boolean value that indicates whether the set is a strict subset
+  /// of the given sequence.
+  ///
+  /// Set *A* is a strict subset of another set *B* if every member of *A* is
+  /// also a member of *B* and *B* contains at least one element that is not a
+  /// member of *A*.
+  ///
+  ///     let employees = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
+  ///     print(attendees.isStrictSubset(of: employees))
+  ///     // Prints "true"
+  ///
+  ///     // A set is never a strict subset of itself:
+  ///     print(attendees.isStrictSubset(of: attendees))
+  ///     // Prints "false"
+  ///
+  /// - Parameter possibleStrictSuperset: A sequence of elements.
+  ///   `possibleStrictSuperset` must be finite.
+  /// - Returns: `true` is the set is strict subset of
+  ///   `possibleStrictSuperset`; otherwise, `false`.
+  @_inlineable
+  public func isStrictSubset<S: Sequence>(of possibleStrictSuperset: S) -> Bool
+    where S.Element == Element {
+    // FIXME: code duplication.
+    let other = Set(possibleStrictSuperset)
+    return isStrictSubset(of: other)
+  }
+
+  /// Returns a Boolean value that indicates whether the set is a superset of
+  /// the given sequence.
+  ///
+  /// Set *A* is a superset of another set *B* if every member of *B* is also a
+  /// member of *A*.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let attendees = ["Alicia", "Bethany", "Diana"]
+  ///     print(employees.isSuperset(of: attendees))
+  ///     // Prints "true"
+  ///
+  /// - Parameter possibleSubset: A sequence of elements. `possibleSubset` must
+  ///   be finite.
+  /// - Returns: `true` if the set is a superset of `possibleSubset`;
+  ///   otherwise, `false`.
+  @_inlineable
+  public func isSuperset<S: Sequence>(of possibleSubset: S) -> Bool
+    where S.Element == Element {
+    // FIXME(performance): Don't build a set; just ask if every element is in
+    // `self`.
+    let other = Set(possibleSubset)
+    return other.isSubset(of: self)
+  }
+
+  /// Returns a Boolean value that indicates whether the set is a strict
+  /// superset of the given sequence.
+  ///
+  /// Set *A* is a strict superset of another set *B* if every member of *B* is
+  /// also a member of *A* and *A* contains at least one element that is *not*
+  /// a member of *B*.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let attendees = ["Alicia", "Bethany", "Diana"]
+  ///     print(employees.isStrictSuperset(of: attendees))
+  ///     // Prints "true"
+  ///     print(employees.isStrictSuperset(of: employees))
+  ///     // Prints "false"
+  ///
+  /// - Parameter possibleStrictSubset: A sequence of elements.
+  ///   `possibleStrictSubset` must be finite.
+  /// - Returns: `true` if the set is a strict superset of
+  ///   `possibleStrictSubset`; otherwise, `false`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public func isStrictSuperset<S: Sequence>(of possibleStrictSubset: S) -> Bool
+    where S.Element == Element {
+    let other = Set(possibleStrictSubset)
+    return other.isStrictSubset(of: self)
+  }
+
+  /// Returns a Boolean value that indicates whether the set has no members in
+  /// common with the given sequence.
+  ///
+  /// In the following example, the `employees` set is disjoint with the
+  /// elements of the `visitors` array because no name appears in both.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let visitors = ["Marcia", "Nathaniel", "Olivia"]
+  ///     print(employees.isDisjoint(with: visitors))
+  ///     // Prints "true"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  /// - Returns: `true` if the set has no elements in common with `other`;
+  ///   otherwise, `false`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public func isDisjoint<S: Sequence>(with other: S) -> Bool
+    where S.Element == Element {
+    // FIXME(performance): Don't need to build a set.
+    let otherSet = Set(other)
+    return isDisjoint(with: otherSet)
+  }
+
+  /// Returns a new set with the elements of both this set and the given
+  /// sequence.
+  ///
+  /// In the following example, the `attendeesAndVisitors` set is made up
+  /// of the elements of the `attendees` set and the `visitors` array:
+  ///
+  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
+  ///     let visitors = ["Marcia", "Nathaniel"]
+  ///     let attendeesAndVisitors = attendees.union(visitors)
+  ///     print(attendeesAndVisitors)
+  ///     // Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"
+  ///
+  /// If the set already contains one or more elements that are also in
+  /// `other`, the existing members are kept. If `other` contains multiple
+  /// instances of equivalent elements, only the first instance is kept.
+  ///
+  ///     let initialIndices = Set(0..<5)
+  ///     let expandedIndices = initialIndices.union([2, 3, 6, 6, 7, 7])
+  ///     print(expandedIndices)
+  ///     // Prints "[2, 4, 6, 7, 0, 1, 3]"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  /// - Returns: A new set with the unique elements of this set and `other`.
+  @_inlineable
+  public func union<S: Sequence>(_ other: S) -> Set<Element>
+    where S.Element == Element {
+    var newSet = self
+    newSet.formUnion(other)
+    return newSet
+  }
+
+  /// Inserts the elements of the given sequence into the set.
+  ///
+  /// If the set already contains one or more elements that are also in
+  /// `other`, the existing members are kept. If `other` contains multiple
+  /// instances of equivalent elements, only the first instance is kept.
+  ///
+  ///     var attendees: Set = ["Alicia", "Bethany", "Diana"]
+  ///     let visitors = ["Diana", "Marcia", "Nathaniel"]
+  ///     attendees.formUnion(visitors)
+  ///     print(attendees)
+  ///     // Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  @_inlineable
+  public mutating func formUnion<S: Sequence>(_ other: S)
+    where S.Element == Element {
+    for item in other {
+      insert(item)
+    }
+  }
+
+  /// Returns a new set containing the elements of this set that do not occur
+  /// in the given sequence.
+  ///
+  /// In the following example, the `nonNeighbors` set is made up of the
+  /// elements of the `employees` set that are not elements of `neighbors`:
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
+  ///     let nonNeighbors = employees.subtracting(neighbors)
+  ///     print(nonNeighbors)
+  ///     // Prints "["Chris", "Diana", "Alicia"]"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  /// - Returns: A new set.
+  @_inlineable
+  public func subtracting<S: Sequence>(_ other: S) -> Set<Element>
+    where S.Element == Element {
+    return self._subtracting(other)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func _subtracting<S: Sequence>(_ other: S) -> Set<Element>
+    where S.Element == Element {
+    var newSet = self
+    newSet.subtract(other)
+    return newSet
+  }
+
+  /// Removes the elements of the given sequence from the set.
+  ///
+  /// In the following example, the elements of the `employees` set that are
+  /// also elements of the `neighbors` array are removed. In particular, the
+  /// names `"Bethany"` and `"Eric"` are removed from `employees`.
+  ///
+  ///     var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
+  ///     employees.subtract(neighbors)
+  ///     print(employees)
+  ///     // Prints "["Chris", "Diana", "Alicia"]"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func subtract<S: Sequence>(_ other: S)
+    where S.Element == Element {
+    _subtract(other)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func _subtract<S: Sequence>(_ other: S)
+    where S.Element == Element {
+    for item in other {
+      remove(item)
+    }
+  }
+
+  /// Returns a new set with the elements that are common to both this set and
+  /// the given sequence.
+  ///
+  /// In the following example, the `bothNeighborsAndEmployees` set is made up
+  /// of the elements that are in *both* the `employees` and `neighbors` sets.
+  /// Elements that are in only one or the other are left out of the result of
+  /// the intersection.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
+  ///     let bothNeighborsAndEmployees = employees.intersection(neighbors)
+  ///     print(bothNeighborsAndEmployees)
+  ///     // Prints "["Bethany", "Eric"]"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  /// - Returns: A new set.
+  @_inlineable
+  public func intersection<S: Sequence>(_ other: S) -> Set<Element>
+    where S.Element == Element {
+    let otherSet = Set(other)
+    return intersection(otherSet)
+  }
+
+  /// Removes the elements of the set that aren't also in the given sequence.
+  ///
+  /// In the following example, the elements of the `employees` set that are
+  /// not also members of the `neighbors` set are removed. In particular, the
+  /// names `"Alicia"`, `"Chris"`, and `"Diana"` are removed.
+  ///
+  ///     var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
+  ///     employees.formIntersection(neighbors)
+  ///     print(employees)
+  ///     // Prints "["Bethany", "Eric"]"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  @_inlineable
+  public mutating func formIntersection<S: Sequence>(_ other: S)
+    where S.Element == Element {
+    // Because `intersect` needs to both modify and iterate over
+    // the left-hand side, the index may become invalidated during
+    // traversal so an intermediate set must be created.
+    //
+    // FIXME(performance): perform this operation at a lower level
+    // to avoid invalidating the index and avoiding a copy.
+    let result = self.intersection(other)
+
+    // The result can only have fewer or the same number of elements.
+    // If no elements were removed, don't perform a reassignment
+    // as this may cause an unnecessary uniquing COW.
+    if result.count != count {
+      self = result
+    }
+  }
+
+  /// Returns a new set with the elements that are either in this set or in the
+  /// given sequence, but not in both.
+  ///
+  /// In the following example, the `eitherNeighborsOrEmployees` set is made up
+  /// of the elements of the `employees` and `neighbors` sets that are not in
+  /// both `employees` *and* `neighbors`. In particular, the names `"Bethany"`
+  /// and `"Eric"` do not appear in `eitherNeighborsOrEmployees`.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Diana", "Eric"]
+  ///     let neighbors = ["Bethany", "Eric", "Forlani"]
+  ///     let eitherNeighborsOrEmployees = employees.symmetricDifference(neighbors)
+  ///     print(eitherNeighborsOrEmployees)
+  ///     // Prints "["Diana", "Forlani", "Alicia"]"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  /// - Returns: A new set.
+  @_inlineable
+  public func symmetricDifference<S: Sequence>(_ other: S) -> Set<Element>
+    where S.Element == Element {
+    var newSet = self
+    newSet.formSymmetricDifference(other)
+    return newSet
+  }
+
+  /// Replace this set with the elements contained in this set or the given
+  /// set, but not both.
+  ///
+  /// In the following example, the elements of the `employees` set that are
+  /// also members of `neighbors` are removed from `employees`, while the
+  /// elements of `neighbors` that are not members of `employees` are added to
+  /// `employees`. In particular, the names `"Bethany"` and `"Eric"` are
+  /// removed from `employees` while the name `"Forlani"` is added.
+  ///
+  ///     var employees: Set = ["Alicia", "Bethany", "Diana", "Eric"]
+  ///     let neighbors = ["Bethany", "Eric", "Forlani"]
+  ///     employees.formSymmetricDifference(neighbors)
+  ///     print(employees)
+  ///     // Prints "["Diana", "Forlani", "Alicia"]"
+  ///
+  /// - Parameter other: A sequence of elements. `other` must be finite.
+  @_inlineable
+  public mutating func formSymmetricDifference<S: Sequence>(_ other: S)
+    where S.Element == Element {
+    let otherSet = Set(other)
+    formSymmetricDifference(otherSet)
+  }
+}
+
+extension Set: CustomStringConvertible, CustomDebugStringConvertible {
+  /// A string that represents the contents of the set.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var description: String {
+    return _makeCollectionDescription(for: self, withTypeName: nil)
+  }
+
+  /// A string that represents the contents of the set, suitable for debugging.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var debugDescription: String {
+    return _makeCollectionDescription(for: self, withTypeName: "Set")
+  }
+}
+
+#if _runtime(_ObjC)
+@_silgen_name("swift_stdlib_CFSetGetValues")
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal
+func _stdlib_CFSetGetValues(_ nss: _NSSet, _: UnsafeMutablePointer<AnyObject>)
+
+/// Equivalent to `NSSet.allObjects`, but does not leave objects on the
+/// autorelease pool.
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal func _stdlib_NSSet_allObjects(_ nss: _NSSet) ->
+  _HeapBuffer<Int, AnyObject> {
+  let count = nss.count
+  let storage = _HeapBuffer<Int, AnyObject>(
+    _HeapBufferStorage<Int, AnyObject>.self, count, count)
+  _stdlib_CFSetGetValues(nss, storage.baseAddress)
+  return storage
+}
+#endif
+
+//===--- Compiler conversion/casting entry points for Set<Element> --------===//
+
+/// Perform a non-bridged upcast that always succeeds.
+///
+/// - Precondition: `BaseValue` is a base class or base `@objc`
+///   protocol (such as `AnyObject`) of `DerivedValue`.
+@_inlineable // FIXME(sil-serialize-all)
+public func _setUpCast<DerivedValue, BaseValue>(_ source: Set<DerivedValue>)
+  -> Set<BaseValue> {
+  var builder = _SetBuilder<BaseValue>(count: source.count)
+  for x in source {
+    builder.add(member: x as! BaseValue)
+  }
+  return builder.take()
+}
+
+#if _runtime(_ObjC)
+
+/// Implements an unconditional upcast that involves bridging.
+///
+/// The cast can fail if bridging fails.
+///
+/// - Precondition: `SwiftValue` is bridged to Objective-C
+///   and requires non-trivial bridging.
+@_inlineable // FIXME(sil-serialize-all)
+public func _setBridgeToObjectiveC<SwiftValue, ObjCValue>(
+  _ source: Set<SwiftValue>
+) -> Set<ObjCValue> {
+  _sanityCheck(_isClassOrObjCExistential(ObjCValue.self))
+  _sanityCheck(!_isBridgedVerbatimToObjectiveC(SwiftValue.self))
+
+  var result = Set<ObjCValue>(minimumCapacity: source.count)
+  let valueBridgesDirectly =
+    _isBridgedVerbatimToObjectiveC(SwiftValue.self) ==
+    _isBridgedVerbatimToObjectiveC(ObjCValue.self)
+
+  for member in source {
+    var bridgedMember: ObjCValue
+    if valueBridgesDirectly {
+      bridgedMember = unsafeBitCast(member, to: ObjCValue.self)
+    } else {
+      let bridged: AnyObject = _bridgeAnythingToObjectiveC(member)
+      bridgedMember = unsafeBitCast(bridged, to: ObjCValue.self)
+    }
+    result.insert(bridgedMember)
+  }
+  return result
+}
+#endif
+
+/// Called by the casting machinery.
+@_silgen_name("_swift_setDownCastIndirect")
+internal func _setDownCastIndirect<SourceValue, TargetValue>(
+  _ source: UnsafePointer<Set<SourceValue>>,
+  _ target: UnsafeMutablePointer<Set<TargetValue>>) {
+  target.initialize(to: _setDownCast(source.pointee))
+}
+
+/// Implements a forced downcast.  This operation should have O(1) complexity.
+///
+/// The cast can fail if bridging fails.  The actual checks and bridging can be
+/// deferred.
+///
+/// - Precondition: `DerivedValue` is a subtype of `BaseValue` and both
+///   are reference types.
+@_inlineable // FIXME(sil-serialize-all)
+public func _setDownCast<BaseValue, DerivedValue>(_ source: Set<BaseValue>)
+  -> Set<DerivedValue> {
+
+#if _runtime(_ObjC)
+  if _isClassOrObjCExistential(BaseValue.self)
+  && _isClassOrObjCExistential(DerivedValue.self) {
+    switch source._variantBuffer {
+    case _VariantSetBuffer.native(let buffer):
+      return Set(_immutableCocoaSet: buffer.bridged())
+    case _VariantSetBuffer.cocoa(let cocoaBuffer):
+      return Set(_immutableCocoaSet: cocoaBuffer.cocoaSet)
+    }
+  }
+#endif
+  return _setDownCastConditional(source)!
+}
+
+/// Called by the casting machinery.
+@_silgen_name("_swift_setDownCastConditionalIndirect")
+internal func _setDownCastConditionalIndirect<SourceValue, TargetValue>(
+  _ source: UnsafePointer<Set<SourceValue>>,
+  _ target: UnsafeMutablePointer<Set<TargetValue>>
+) -> Bool {
+  if let result: Set<TargetValue> = _setDownCastConditional(source.pointee) {
+    target.initialize(to: result)
+    return true
+  }
+  return false
+}
+
+/// Implements a conditional downcast.
+///
+/// If the cast fails, the function returns `nil`.  All checks should be
+/// performed eagerly.
+///
+/// - Precondition: `DerivedValue` is a subtype of `BaseValue` and both
+///   are reference types.
+@_inlineable // FIXME(sil-serialize-all)
+public func _setDownCastConditional<BaseValue, DerivedValue>(
+  _ source: Set<BaseValue>
+) -> Set<DerivedValue>? {
+  var result = Set<DerivedValue>(minimumCapacity: source.count)
+  for member in source {
+    if let derivedMember = member as? DerivedValue {
+      result.insert(derivedMember)
+      continue
+    }
+    return nil
+  }
+  return result
+}
+
+#if _runtime(_ObjC)
+
+/// Implements an unconditional downcast that involves bridging.
+///
+/// - Precondition: At least one of `SwiftValue` is a bridged value
+///   type, and the corresponding `ObjCValue` is a reference type.
+@_inlineable // FIXME(sil-serialize-all)
+public func _setBridgeFromObjectiveC<ObjCValue, SwiftValue>(
+  _ source: Set<ObjCValue>
+) -> Set<SwiftValue> {
+  let result: Set<SwiftValue>? = _setBridgeFromObjectiveCConditional(source)
+  _precondition(result != nil, "This set cannot be bridged from Objective-C")
+  return result!
+}
+
+/// Implements a conditional downcast that involves bridging.
+///
+/// If the cast fails, the function returns `nil`.  All checks should be
+/// performed eagerly.
+///
+/// - Precondition: At least one of `SwiftValue` is a bridged value
+///   type, and the corresponding `ObjCValue` is a reference type.
+@_inlineable // FIXME(sil-serialize-all)
+public func _setBridgeFromObjectiveCConditional<
+  ObjCValue, SwiftValue
+>(
+  _ source: Set<ObjCValue>
+) -> Set<SwiftValue>? {
+  _sanityCheck(_isClassOrObjCExistential(ObjCValue.self))
+  _sanityCheck(!_isBridgedVerbatimToObjectiveC(SwiftValue.self))
+
+  let valueBridgesDirectly =
+    _isBridgedVerbatimToObjectiveC(SwiftValue.self) ==
+      _isBridgedVerbatimToObjectiveC(ObjCValue.self)
+
+  var result = Set<SwiftValue>(minimumCapacity: source.count)
+  for value in source {
+    // Downcast the value.
+    var resultValue: SwiftValue
+    if valueBridgesDirectly {
+      if let bridgedValue = value as? SwiftValue {
+        resultValue = bridgedValue
+      } else {
+        return nil
+      }
+    } else {
+      if let bridgedValue = _conditionallyBridgeFromObjectiveC(
+          _reinterpretCastToAnyObject(value), SwiftValue.self) {
+        resultValue = bridgedValue
+      } else {
+        return nil
+      }
+    }
+    result.insert(resultValue)
+  }
+  return result
+}
+#endif
+
+extension Set {
+  /// Removes the elements of the given set from this set.
+  ///
+  /// In the following example, the elements of the `employees` set that are
+  /// also members of the `neighbors` set are removed. In particular, the
+  /// names `"Bethany"` and `"Eric"` are removed from `employees`.
+  ///
+  ///     var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
+  ///     employees.subtract(neighbors)
+  ///     print(employees)
+  ///     // Prints "["Diana", "Chris", "Alicia"]"
+  ///
+  /// - Parameter other: Another set.
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func subtract(_ other: Set<Element>) {
+    _subtract(other)
+  }
+
+  /// Returns a Boolean value that indicates whether this set is a subset of
+  /// the given set.
+  ///
+  /// Set *A* is a subset of another set *B* if every member of *A* is also a
+  /// member of *B*.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
+  ///     print(attendees.isSubset(of: employees))
+  ///     // Prints "true"
+  ///
+  /// - Parameter other: Another set.
+  /// - Returns: `true` if the set is a subset of `other`; otherwise, `false`.
+  @_inlineable
+  public func isSubset(of other: Set<Element>) -> Bool {
+    let (isSubset, isEqual) = _compareSets(self, other)
+    return isSubset || isEqual
+  }
+
+  /// Returns a Boolean value that indicates whether this set is a superset of
+  /// the given set.
+  ///
+  /// Set *A* is a superset of another set *B* if every member of *B* is also a
+  /// member of *A*.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
+  ///     print(employees.isSuperset(of: attendees))
+  ///     // Prints "true"
+  ///
+  /// - Parameter other: Another set.
+  /// - Returns: `true` if the set is a superset of `other`; otherwise,
+  ///   `false`.
+  @_inlineable
+  public func isSuperset(of other: Set<Element>) -> Bool {
+    return other.isSubset(of: self)
+  }
+
+  /// Returns a Boolean value that indicates whether this set has no members in
+  /// common with the given set.
+  ///
+  /// In the following example, the `employees` set is disjoint with the
+  /// `visitors` set because no name appears in both sets.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let visitors: Set = ["Marcia", "Nathaniel", "Olivia"]
+  ///     print(employees.isDisjoint(with: visitors))
+  ///     // Prints "true"
+  ///
+  /// - Parameter other: Another set.
+  /// - Returns: `true` if the set has no elements in common with `other`;
+  ///   otherwise, `false`.
+  @_inlineable
+  public func isDisjoint(with other: Set<Element>) -> Bool {
+    for member in self {
+      if other.contains(member) {
+        return false
+      }
+    }
+    return true
+  }
+
+  /// Returns a new set containing the elements of this set that do not occur
+  /// in the given set.
+  ///
+  /// In the following example, the `nonNeighbors` set is made up of the
+  /// elements of the `employees` set that are not elements of `neighbors`:
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
+  ///     let nonNeighbors = employees.subtracting(neighbors)
+  ///     print(nonNeighbors)
+  ///     // Prints "["Diana", "Chris", "Alicia"]"
+  ///
+  /// - Parameter other: Another set.
+  /// - Returns: A new set.
+  @_inlineable
+  public func subtracting(_ other: Set<Element>) -> Set<Element> {
+    return self._subtracting(other)
+  }
+
+  /// Returns a Boolean value that indicates whether the set is a strict
+  /// superset of the given sequence.
+  ///
+  /// Set *A* is a strict superset of another set *B* if every member of *B* is
+  /// also a member of *A* and *A* contains at least one element that is *not*
+  /// a member of *B*.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
+  ///     print(employees.isStrictSuperset(of: attendees))
+  ///     // Prints "true"
+  ///     print(employees.isStrictSuperset(of: employees))
+  ///     // Prints "false"
+  ///
+  /// - Parameter other: Another set.
+  /// - Returns: `true` if the set is a strict superset of
+  ///   `other`; otherwise, `false`.
+  @_inlineable
+  public func isStrictSuperset(of other: Set<Element>) -> Bool {
+    return self.isSuperset(of: other) && self != other
+  }
+
+  /// Returns a Boolean value that indicates whether the set is a strict subset
+  /// of the given sequence.
+  ///
+  /// Set *A* is a strict subset of another set *B* if every member of *A* is
+  /// also a member of *B* and *B* contains at least one element that is not a
+  /// member of *A*.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let attendees: Set = ["Alicia", "Bethany", "Diana"]
+  ///     print(attendees.isStrictSubset(of: employees))
+  ///     // Prints "true"
+  ///
+  ///     // A set is never a strict subset of itself:
+  ///     print(attendees.isStrictSubset(of: attendees))
+  ///     // Prints "false"
+  ///
+  /// - Parameter other: Another set.
+  /// - Returns: `true` if the set is a strict subset of
+  ///   `other`; otherwise, `false`.
+  @_inlineable
+  public func isStrictSubset(of other: Set<Element>) -> Bool {
+    return other.isStrictSuperset(of: self)
+  }
+
+  /// Returns a new set with the elements that are common to both this set and
+  /// the given sequence.
+  ///
+  /// In the following example, the `bothNeighborsAndEmployees` set is made up
+  /// of the elements that are in *both* the `employees` and `neighbors` sets.
+  /// Elements that are in only one or the other are left out of the result of
+  /// the intersection.
+  ///
+  ///     let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
+  ///     let bothNeighborsAndEmployees = employees.intersection(neighbors)
+  ///     print(bothNeighborsAndEmployees)
+  ///     // Prints "["Bethany", "Eric"]"
+  ///
+  /// - Parameter other: Another set.
+  /// - Returns: A new set.
+  @_inlineable
+  public func intersection(_ other: Set<Element>) -> Set<Element> {
+    var newSet = Set<Element>()
+    for member in self {
+      if other.contains(member) {
+        newSet.insert(member)
+      }
+    }
+    return newSet
+  }
+
+  /// Removes the elements of the set that are also in the given sequence and
+  /// adds the members of the sequence that are not already in the set.
+  ///
+  /// In the following example, the elements of the `employees` set that are
+  /// also members of `neighbors` are removed from `employees`, while the
+  /// elements of `neighbors` that are not members of `employees` are added to
+  /// `employees`. In particular, the names `"Alicia"`, `"Chris"`, and
+  /// `"Diana"` are removed from `employees` while the names `"Forlani"` and
+  /// `"Greta"` are added.
+  ///
+  ///     var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
+  ///     let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
+  ///     employees.formSymmetricDifference(neighbors)
+  ///     print(employees)
+  ///     // Prints "["Diana", "Chris", "Forlani", "Alicia", "Greta"]"
+  ///
+  /// - Parameter other: Another set.
+  @_inlineable
+  public mutating func formSymmetricDifference(_ other: Set<Element>) {
+    for member in other {
+      if contains(member) {
+        remove(member)
+      } else {
+        insert(member)
+      }
+    }
+  }
+}
+
+//===--- APIs templated for Dictionary and Set ----------------------------===//
+
+/// An instance of this class has all `Set` data tail-allocated.
+/// Enough bytes are allocated to hold the bitmap for marking valid entries,
+/// keys, and values. The data layout starts with the bitmap, followed by the
+/// keys, followed by the values.
+//
+// See the docs at the top of the file for more details on this type
+//
+// NOTE: The precise layout of this type is relied on in the runtime
+// to provide a statically allocated empty singleton.
+// See stdlib/public/stubs/GlobalObjects.cpp for details.
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_objc_non_lazy_realization
+internal class _RawNativeSetStorage:
+  _SwiftNativeNSSet, _NSSetCore
+{
+  internal typealias RawStorage = _RawNativeSetStorage
+
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal final var bucketCount: Int
+
+  @_versioned // FIXME(sil-serialize-all)
+  internal final var count: Int
+
+  @_versioned // FIXME(sil-serialize-all)
+  internal final var initializedEntries: _UnsafeBitMap
+
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal final var keys: UnsafeMutableRawPointer
+
+  @_versioned // FIXME(sil-serialize-all)
+  internal final var seed: (UInt64, UInt64)
+
+  // This API is unsafe and needs a `_fixLifetime` in the caller.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal final
+  var _initializedHashtableEntriesBitMapBuffer: UnsafeMutablePointer<UInt> {
+    return UnsafeMutablePointer(Builtin.projectTailElems(self, UInt.self))
+  }
+
+  /// The empty singleton that is used for every single Dictionary that is
+  /// created without any elements. The contents of the storage should never
+  /// be mutated.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal static var empty: RawStorage {
+    return Builtin.bridgeFromRawPointer(
+      Builtin.addressof(&_swiftEmptySetStorage))
+  }
+
+  // This type is made with allocWithTailElems, so no init is ever called.
+  // But we still need to have an init to satisfy the compiler.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal init(_doNotCallMe: ()) {
+    _sanityCheckFailure("Only create this by using the `empty` singleton")
+  }
+
+#if _runtime(_ObjC)
+  //
+  // NSSet implementation, assuming Self is the empty singleton
+  //
+
+  /// Get the NSEnumerator implementation for self.
+  /// _HashableTypedNativeSetStorage overloads this to give
+  /// _NativeSelfNSEnumerator proper type parameters.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal func enumerator() -> _NSEnumerator {
+    return _NativeSetNSEnumerator<AnyObject>(
+        _NativeSetBuffer(_storage: self))
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc(copyWithZone:)
+  internal func copy(with zone: _SwiftNSZone?) -> AnyObject {
+    return self
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc(countByEnumeratingWithState:objects:count:)
+  internal func countByEnumerating(
+    with state: UnsafeMutablePointer<_SwiftNSFastEnumerationState>,
+    objects: UnsafeMutablePointer<AnyObject>?, count: Int
+  ) -> Int {
+    // Even though we never do anything in here, we need to update the
+    // state so that callers know we actually ran.
+
+    var theState = state.pointee
+    if theState.state == 0 {
+      theState.state = 1 // Arbitrary non-zero value.
+      theState.itemsPtr = AutoreleasingUnsafeMutablePointer(objects)
+      theState.mutationsPtr = _fastEnumerationStorageMutationsPtr
+    }
+    state.pointee = theState
+
+    return 0
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal required init(objects: UnsafePointer<AnyObject?>, count: Int) {
+    _sanityCheckFailure("don't call this designated initializer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal func member(_ object: AnyObject) -> AnyObject? {
+    return nil
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal func objectEnumerator() -> _NSEnumerator {
+    return enumerator()
+  }
+#endif
+}
+
+// See the docs at the top of this file for a description of this type
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned
+internal class _TypedNativeSetStorage<Element>: _RawNativeSetStorage {
+
+  internal typealias Key = Element
+  internal typealias Value = Element
+
+  deinit {
+    let keys = self.keys.assumingMemoryBound(to: Key.self)
+
+    if !_isPOD(Key.self) {
+      for i in 0 ..< bucketCount {
+        if initializedEntries[i] {
+          (keys+i).deinitialize(count: 1)
+        }
+      }
+    }
+
+    _fixLifetime(self)
+  }
+
+  // This type is made with allocWithTailElems, so no init is ever called.
+  // But we still need to have an init to satisfy the compiler.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  override internal init(_doNotCallMe: ()) {
+    _sanityCheckFailure("Only create this by calling Buffer's inits")
+  }
+
+#if _runtime(_ObjC)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal required init(objects: UnsafePointer<AnyObject?>, count: Int) {
+    _sanityCheckFailure("don't call this designated initializer")
+  }
+#endif
+}
+
+// See the docs at the top of this file for a description of this type
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned
+final internal class _HashableTypedNativeSetStorage<Element: Hashable>
+  : _TypedNativeSetStorage<Element> {
+
+  internal typealias FullContainer = Set<Element>
+  internal typealias Buffer = _NativeSetBuffer<Element>
+
+  // This type is made with allocWithTailElems, so no init is ever called.
+  // But we still need to have an init to satisfy the compiler.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  override internal init(_doNotCallMe: ()) {
+    _sanityCheckFailure("Only create this by calling Buffer's inits'")
+  }
+
+#if _runtime(_ObjC)
+  // NSSet bridging:
+
+  // All actual functionality comes from buffer/full, which are
+  // just wrappers around a RawNativeSetStorage.
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var buffer: Buffer {
+    return Buffer(_storage: self)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var full: FullContainer {
+    return FullContainer(_nativeBuffer: buffer)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal override func enumerator() -> _NSEnumerator {
+    return _NativeSetNSEnumerator<Element>(
+        Buffer(_storage: self))
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc(countByEnumeratingWithState:objects:count:)
+  internal override func countByEnumerating(
+    with state: UnsafeMutablePointer<_SwiftNSFastEnumerationState>,
+    objects: UnsafeMutablePointer<AnyObject>?, count: Int
+  ) -> Int {
+    var theState = state.pointee
+    if theState.state == 0 {
+      theState.state = 1 // Arbitrary non-zero value.
+      theState.itemsPtr = AutoreleasingUnsafeMutablePointer(objects)
+      theState.mutationsPtr = _fastEnumerationStorageMutationsPtr
+      theState.extra.0 = CUnsignedLong(full.startIndex._nativeIndex.offset)
+    }
+
+    // Test 'objects' rather than 'count' because (a) this is very rare anyway,
+    // and (b) the optimizer should then be able to optimize away the
+    // unwrapping check below.
+    if _slowPath(objects == nil) {
+      return 0
+    }
+
+    let unmanagedObjects = _UnmanagedAnyObjectArray(objects!)
+    var currIndex = _NativeSetIndex<Element>(
+        offset: Int(theState.extra.0))
+    let endIndex = buffer.endIndex
+    var stored = 0
+    for i in 0..<count {
+      if (currIndex == endIndex) {
+        break
+      }
+
+      unmanagedObjects[i] = buffer.bridgedKey(at: currIndex)
+
+      stored += 1
+      buffer.formIndex(after: &currIndex)
+    }
+    theState.extra.0 = CUnsignedLong(currIndex.offset)
+    state.pointee = theState
+    return stored
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal func getObjectFor(_ aKey: AnyObject) -> AnyObject? {
+    guard let nativeKey = _conditionallyBridgeFromObjectiveC(aKey, Key.self)
+    else { return nil }
+
+    let (i, found) = buffer._find(nativeKey,
+        startBucket: buffer._bucket(nativeKey))
+
+    if found {
+      return buffer.bridgedValue(at: i)
+    }
+    return nil
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal required init(objects: UnsafePointer<AnyObject?>, count: Int) {
+    _sanityCheckFailure("don't call this designated initializer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  override internal func member(_ object: AnyObject) -> AnyObject? {
+    return getObjectFor(object)
+  }
+#endif
+}
+
+/// A wrapper around _RawNativeSetStorage that provides most of the
+/// implementation of Set.
+///
+/// This type and most of its functionality doesn't require Hashable at all.
+/// The reason for this is to support storing AnyObject for bridging
+/// with _SwiftDeferredNSSet. What functionality actually relies on
+/// Hashable can be found in an extension.
+@_versioned
+@_fixed_layout
+internal struct _NativeSetBuffer<Element> {
+
+  internal typealias RawStorage = _RawNativeSetStorage
+  internal typealias TypedStorage = _TypedNativeSetStorage<Element>
+  internal typealias Buffer = _NativeSetBuffer<Element>
+  internal typealias Index = _NativeSetIndex<Element>
+
+  internal typealias Key = Element
+  internal typealias Value = Element
+  internal typealias SequenceElementWithoutLabels = Element
+
+  /// See this comments on _RawNativeSetStorage and its subclasses to
+  /// understand why we store an untyped storage here.
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _storage: RawStorage
+
+  /// Creates a Buffer with a storage that is typed, but doesn't understand
+  /// Hashing. Mostly for bridging; prefer `init(minimumCapacity:)`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_exactBucketCount bucketCount: Int, unhashable: ()) {
+    let bitmapWordCount = _UnsafeBitMap.sizeInWords(forSizeInBits: bucketCount)
+    let storage = Builtin.allocWithTailElems_2(TypedStorage.self,
+        bitmapWordCount._builtinWordValue, UInt.self,
+        bucketCount._builtinWordValue, Key.self)
+    self.init(_exactBucketCount: bucketCount, storage: storage)
+  }
+
+  /// Given a bucket count and uninitialized RawStorage, completes the
+  /// initialization and returns a Buffer.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_exactBucketCount bucketCount: Int, storage: RawStorage) {
+    storage.bucketCount = bucketCount
+    storage.count = 0
+
+    self.init(_storage: storage)
+
+    let initializedEntries = _UnsafeBitMap(
+        storage: _initializedHashtableEntriesBitMapBuffer,
+        bitCount: bucketCount)
+    initializedEntries.initializeToZero()
+
+    // Compute all the array offsets now, so we don't have to later
+    let bitmapAddr = Builtin.projectTailElems(_storage, UInt.self)
+    let bitmapWordCount = _UnsafeBitMap.sizeInWords(forSizeInBits: bucketCount)
+    let keysAddr = Builtin.getTailAddr_Word(bitmapAddr,
+           bitmapWordCount._builtinWordValue, UInt.self, Key.self)
+
+    // Initialize header
+    _storage.initializedEntries = initializedEntries
+    _storage.keys = UnsafeMutableRawPointer(keysAddr)
+    // We assign a unique hash seed to each distinct hash table size, so that we
+    // avoid certain copy operations becoming quadratic, without breaking value
+    // semantics. (See https://bugs.swift.org/browse/SR-3268)
+    //
+    // We don't need to generate a brand new seed for each table size: it's
+    // enough to change a single bit in the global seed by XORing the bucket
+    // count to it. (The bucket count is always a power of two.)
+    //
+    // FIXME: Use an approximation of true per-instance seeding. We can't just
+    // use the base address, because COW copies need to share the same seed.
+    let seed = _Hasher._seed
+    let perturbation = bucketCount
+    _storage.seed = (seed.0 ^ UInt64(truncatingIfNeeded: perturbation), seed.1)
+  }
+
+  // Forwarding the individual fields of the storage in various forms
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal var bucketCount: Int {
+    return _assumeNonNegative(_storage.bucketCount)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal var count: Int {
+    set {
+      _storage.count = newValue
+    }
+    get {
+      return _assumeNonNegative(_storage.count)
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal
+  var _initializedHashtableEntriesBitMapBuffer: UnsafeMutablePointer<UInt> {
+    return _storage._initializedHashtableEntriesBitMapBuffer
+  }
+
+  // This API is unsafe and needs a `_fixLifetime` in the caller.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal var keys: UnsafeMutablePointer<Key> {
+    return _storage.keys.assumingMemoryBound(to: Key.self)
+  }
+
+  /// Constructs a buffer adopting the given storage.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_storage: RawStorage) {
+    self._storage = _storage
+  }
+
+  /// Constructs an instance from the empty singleton.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init() {
+    self._storage = RawStorage.empty
+  }
+
+  // Most of the implementation of the _HashBuffer protocol,
+  // but only the parts that don't actually rely on hashing.
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(__always)
+  internal func key(at i: Int) -> Key {
+    _sanityCheck(i >= 0 && i < bucketCount)
+    _sanityCheck(isInitializedEntry(at: i))
+    defer { _fixLifetime(self) }
+
+    let res = (keys + i).pointee
+    return res
+  }
+
+#if _runtime(_ObjC)
+  /// Returns the key at the given Index, bridged.
+  ///
+  /// Intended for use with verbatim bridgeable keys.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func bridgedKey(at index: Index) -> AnyObject {
+    let k = key(at: index.offset)
+    return _bridgeAnythingToObjectiveC(k)
+  }
+
+  /// Returns the value at the given Index, bridged.
+  ///
+  /// Intended for use with verbatim bridgeable keys.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func bridgedValue(at index: Index) -> AnyObject {
+    let v = value(at: index.offset)
+    return _bridgeAnythingToObjectiveC(v)
+  }
+#endif
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func isInitializedEntry(at i: Int) -> Bool {
+    _sanityCheck(i >= 0 && i < bucketCount)
+    defer { _fixLifetime(self) }
+
+    return _storage.initializedEntries[i]
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @_transparent
+  internal func destroyEntry(at i: Int) {
+    _sanityCheck(isInitializedEntry(at: i))
+    defer { _fixLifetime(self) }
+
+    (keys + i).deinitialize(count: 1)
+    _storage.initializedEntries[i] = false
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @_transparent
+  internal func initializeKey(_ k: Key, at i: Int) {
+    _sanityCheck(!isInitializedEntry(at: i))
+    defer { _fixLifetime(self) }
+
+    (keys + i).initialize(to: k)
+    _storage.initializedEntries[i] = true
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @_transparent
+  internal func moveInitializeEntry(from: Buffer, at: Int, toEntryAt: Int) {
+    _sanityCheck(!isInitializedEntry(at: toEntryAt))
+
+    defer { _fixLifetime(self) }
+
+    (keys + toEntryAt).initialize(to: (from.keys + at).move())
+    from._storage.initializedEntries[at] = false
+    _storage.initializedEntries[toEntryAt] = true
+  }
+
+  /// Alias for key(at:) in Sets for better code reuse
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @_transparent
+  internal func value(at i: Int) -> Value {
+    return key(at: i)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func setKey(_ key: Key, at i: Int) {
+    _sanityCheck(i >= 0 && i < bucketCount)
+    _sanityCheck(isInitializedEntry(at: i))
+    defer { _fixLifetime(self) }
+
+    (keys + i).pointee = key
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal var startIndex: Index {
+    // We start at "index after -1" instead of "0" because we need to find the
+    // first occupied slot.
+    return index(after: Index(offset: -1))
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal var endIndex: Index {
+    return Index(offset: bucketCount)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func index(after i: Index) -> Index {
+    _precondition(i != endIndex)
+    var idx = i.offset + 1
+    while idx < bucketCount && !isInitializedEntry(at: idx) {
+      idx += 1
+    }
+
+    return Index(offset: idx)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func formIndex(after i: inout Index) {
+    i = index(after: i)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func assertingGet(_ i: Index) -> SequenceElement {
+    _precondition(i.offset >= 0 && i.offset < bucketCount)
+    _precondition(
+      isInitializedEntry(at: i.offset),
+      "Attempting to access Set elements using an invalid Index")
+    let key = self.key(at: i.offset)
+    return key
+
+  }
+}
+
+extension _NativeSetBuffer where Element: Hashable
+{
+  internal typealias HashTypedStorage =
+    _HashableTypedNativeSetStorage<Element>
+  internal typealias SequenceElement = Element
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @inline(__always)
+  internal init(minimumCapacity: Int) {
+    let bucketCount = _NativeSetBuffer.bucketCount(
+      forCapacity: minimumCapacity,
+      maxLoadFactorInverse: _hashContainerDefaultMaxLoadFactorInverse)
+    self.init(bucketCount: bucketCount)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @inline(__always)
+  internal init(bucketCount: Int) {
+    // Actual bucket count is the next power of 2 greater than or equal to
+    // bucketCount. Make sure that is representable.
+    _sanityCheck(bucketCount <= (Int.max >> 1) + 1)
+    let buckets = 1 &<< ((Swift.max(bucketCount, 2) - 1)._binaryLogarithm() + 1)
+    self.init(_exactBucketCount: buckets)
+  }
+
+  /// Create a buffer instance with room for at least 'bucketCount' entries,
+  /// marking all entries invalid.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_exactBucketCount bucketCount: Int) {
+    let bitmapWordCount = _UnsafeBitMap.sizeInWords(forSizeInBits: bucketCount)
+    let storage = Builtin.allocWithTailElems_2(HashTypedStorage.self,
+        bitmapWordCount._builtinWordValue, UInt.self,
+        bucketCount._builtinWordValue, Key.self)
+    self.init(_exactBucketCount: bucketCount, storage: storage)
+  }
+
+#if _runtime(_ObjC)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func bridged() -> _NSSet {
+    // We can zero-cost bridge if our keys are verbatim
+    // or if we're the empty singleton.
+
+    // Temporary var for SOME type safety before a cast.
+    let nsSet: _NSSetCore
+
+    if (_isBridgedVerbatimToObjectiveC(Key.self) &&
+        _isBridgedVerbatimToObjectiveC(Value.self)) ||
+        self._storage === RawStorage.empty {
+      nsSet = self._storage
+    } else {
+      nsSet = _SwiftDeferredNSSet(nativeBuffer: self)
+    }
+
+    // Cast from "minimal NSSet" to "NSSet"
+    // Note that if you actually ask Swift for this cast, it will fail.
+    // Never trust a shadow protocol!
+    return unsafeBitCast(nsSet, to: _NSSet.self)
+  }
+#endif
+
+  /// A textual representation of `self`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var description: String {
+    var result = ""
+#if INTERNAL_CHECKS_ENABLED
+    for i in 0..<bucketCount {
+      if isInitializedEntry(at: i) {
+        let key = self.key(at: i)
+        result += "bucket \(i), ideal bucket = \(_bucket(key)), key = \(key)\n"
+      } else {
+        result += "bucket \(i), empty\n"
+      }
+    }
+#endif
+    return result
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _bucketMask: Int {
+    // The bucket count is not negative, therefore subtracting 1 will not
+    // overflow.
+    return bucketCount &- 1
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(__always) // For performance reasons.
+  internal func _bucket(_ k: Key) -> Int {
+    var hasher = _Hasher(seed: _storage.seed)
+    hasher.append(k)
+    return hasher.finalize() & _bucketMask
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func _index(after bucket: Int) -> Int {
+    // Bucket is within 0 and bucketCount. Therefore adding 1 does not overflow.
+    return (bucket &+ 1) & _bucketMask
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func _prev(_ bucket: Int) -> Int {
+    // Bucket is not negative. Therefore subtracting 1 does not overflow.
+    return (bucket &- 1) & _bucketMask
+  }
+
+  /// Search for a given key starting from the specified bucket.
+  ///
+  /// If the key is not present, returns the position where it could be
+  /// inserted.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(__always)
+  internal func _find(_ key: Key, startBucket: Int)
+    -> (pos: Index, found: Bool) {
+
+    var bucket = startBucket
+
+    // The invariant guarantees there's always a hole, so we just loop
+    // until we find one
+    while true {
+      let isHole = !isInitializedEntry(at: bucket)
+      if isHole {
+        return (Index(offset: bucket), false)
+      }
+      if self.key(at: bucket) == key {
+        return (Index(offset: bucket), true)
+      }
+      bucket = _index(after: bucket)
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @_transparent
+  internal static func bucketCount(
+    forCapacity capacity: Int,
+    maxLoadFactorInverse: Double
+  ) -> Int {
+    // `capacity + 1` below ensures that we don't fill in the last hole
+    return max(Int((Double(capacity) * maxLoadFactorInverse).rounded(.up)),
+               capacity + 1)
+  }
+
+  /// Buffer should be uniquely referenced.
+  /// The `key` should not be present in the Set.
+  /// This function does *not* update `count`.
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func unsafeAddNew(key newKey: Element) {
+    let (i, found) = _find(newKey, startBucket: _bucket(newKey))
+    _sanityCheck(
+      !found, "unsafeAddNew was called, but the key is already present")
+    initializeKey(newKey, at: i.offset)
+  }
+
+  //
+  // _HashBuffer conformance
+  //
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(__always)
+  internal func index(forKey key: Key) -> Index? {
+    if count == 0 {
+      // Fast path that avoids computing the hash of the key.
+      return nil
+    }
+    let (i, found) = _find(key, startBucket: _bucket(key))
+    return found ? i : nil
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func assertingGet(_ key: Key) -> Value {
+    let (i, found) = _find(key, startBucket: _bucket(key))
+    _precondition(found, "Key not found")
+    return self.key(at: i.offset)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(__always)
+  internal func maybeGet(_ key: Key) -> Value? {
+    if count == 0 {
+      // Fast path that avoids computing the hash of the key.
+      return nil
+    }
+
+    let (i, found) = _find(key, startBucket: _bucket(key))
+    if found {
+      return self.key(at: i.offset)
+    }
+    return nil
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal func updateValue(_ value: Value, forKey key: Key) -> Value? {
+    _sanityCheckFailure(
+      "don't call mutating methods on _NativeSetBuffer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal func insert(
+    _ value: Value, forKey key: Key
+  ) -> (inserted: Bool, memberAfterInsert: Value) {
+    _sanityCheckFailure(
+      "don't call mutating methods on _NativeSetBuffer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal func remove(at index: Index) -> SequenceElement {
+    _sanityCheckFailure(
+      "don't call mutating methods on _NativeSetBuffer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal func removeValue(forKey key: Key) -> Value? {
+    _sanityCheckFailure(
+      "don't call mutating methods on _NativeSetBuffer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func removeAll(keepingCapacity keepCapacity: Bool) {
+    _sanityCheckFailure(
+      "don't call mutating methods on _NativeSetBuffer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal static func fromArray(_ elements: [SequenceElementWithoutLabels])
+    -> Buffer
+  {
+    if elements.isEmpty {
+      return Buffer()
+    }
+
+    var nativeBuffer = Buffer(minimumCapacity: elements.count)
+
+    var count = 0
+    for key in elements {
+      let (i, found) =
+        nativeBuffer._find(key, startBucket: nativeBuffer._bucket(key))
+      if found {
+        continue
+      }
+      nativeBuffer.initializeKey(key, at: i.offset)
+      count += 1
+    }
+    nativeBuffer.count = count
+
+    return nativeBuffer
+  }
+}
+
+#if _runtime(_ObjC)
+/// An NSEnumerator that works with any NativeSetBuffer of
+/// verbatim bridgeable elements. Used by the various NSSet impls.
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+final internal class _NativeSetNSEnumerator<Element>
+  : _SwiftNativeNSEnumerator, _NSEnumerator {
+
+  internal typealias Buffer = _NativeSetBuffer<Element>
+  internal typealias Index = _NativeSetIndex<Element>
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal override required init() {
+    _sanityCheckFailure("don't call this designated initializer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_ buffer: Buffer) {
+    self.buffer = buffer
+    nextIndex = buffer.startIndex
+    endIndex = buffer.endIndex
+  }
+
+  @_versioned // FIXME(sil-serialize-all)
+  internal var buffer: Buffer
+  @_versioned // FIXME(sil-serialize-all)
+  internal var nextIndex: Index
+  @_versioned // FIXME(sil-serialize-all)
+  internal var endIndex: Index
+
+  //
+  // NSEnumerator implementation.
+  //
+  // Do not call any of these methods from the standard library!
+  //
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal func nextObject() -> AnyObject? {
+    if nextIndex == endIndex {
+      return nil
+    }
+    let key = buffer.bridgedKey(at: nextIndex)
+    buffer.formIndex(after: &nextIndex)
+    return key
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc(countByEnumeratingWithState:objects:count:)
+  internal func countByEnumerating(
+    with state: UnsafeMutablePointer<_SwiftNSFastEnumerationState>,
+    objects: UnsafeMutablePointer<AnyObject>,
+    count: Int
+  ) -> Int {
+    var theState = state.pointee
+    if theState.state == 0 {
+      theState.state = 1 // Arbitrary non-zero value.
+      theState.itemsPtr = AutoreleasingUnsafeMutablePointer(objects)
+      theState.mutationsPtr = _fastEnumerationStorageMutationsPtr
+    }
+
+    if nextIndex == endIndex {
+      state.pointee = theState
+      return 0
+    }
+
+    // Return only a single element so that code can start iterating via fast
+    // enumeration, terminate it, and continue via NSEnumerator.
+    let key = buffer.bridgedKey(at: nextIndex)
+    buffer.formIndex(after: &nextIndex)
+
+    let unmanagedObjects = _UnmanagedAnyObjectArray(objects)
+    unmanagedObjects[0] = key
+    state.pointee = theState
+    return 1
+  }
+}
+#endif
+
+#if _runtime(_ObjC)
+/// This class exists for Objective-C bridging. It holds a reference to a
+/// NativeSetBuffer, and can be upcast to NSSelf when bridging is necessary.
+/// This is the fallback implementation for situations where toll-free bridging
+/// isn't possible. On first access, a NativeSetBuffer of AnyObject will be
+/// constructed containing all the bridged elements.
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+final internal class _SwiftDeferredNSSet<Element: Hashable>
+  : _SwiftNativeNSSet, _NSSetCore {
+
+  internal typealias NativeBuffer = _NativeSetBuffer<Element>
+  internal typealias BridgedBuffer = _NativeSetBuffer<AnyObject>
+  internal typealias NativeIndex = _NativeSetIndex<Element>
+  internal typealias BridgedIndex = _NativeSetIndex<AnyObject>
+
+  internal typealias Key = Element
+  internal typealias Value = Element
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal init(bucketCount: Int = 2) {
+    nativeBuffer = NativeBuffer(bucketCount: bucketCount)
+    super.init()
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(nativeBuffer: NativeBuffer) {
+    self.nativeBuffer = nativeBuffer
+    super.init()
+  }
+
+  // This stored property should be stored at offset zero.  We perform atomic
+  // operations on it.
+  //
+  // Do not access this property directly.
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal var _heapStorageBridged_DoNotUse: AnyObject?
+
+  /// The unbridged elements.
+  @_versioned // FIXME(sil-serialize-all)
+  internal var nativeBuffer: NativeBuffer
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc(copyWithZone:)
+  internal func copy(with zone: _SwiftNSZone?) -> AnyObject {
+    // Instances of this class should be visible outside of standard library as
+    // having `NSSet` type, which is immutable.
+    return self
+  }
+
+  //
+  // NSSet implementation.
+  //
+  // Do not call any of these methods from the standard library!  Use only
+  // `nativeBuffer`.
+  //
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal required init(objects: UnsafePointer<AnyObject?>, count: Int) {
+    _sanityCheckFailure("don't call this designated initializer")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal func member(_ object: AnyObject) -> AnyObject? {
+    return bridgingObjectForKey(object)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal func objectEnumerator() -> _NSEnumerator {
+    return enumerator()
+  }
+
+  /// Returns the pointer to the stored property, which contains bridged
+  /// Set elements.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal var _heapStorageBridgedPtr: UnsafeMutablePointer<AnyObject?> {
+    return _getUnsafePointerToStoredProperties(self).assumingMemoryBound(
+      to: Optional<AnyObject>.self)
+  }
+
+  /// The buffer for bridged Set elements, if present.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal var _bridgedStorage:
+    BridgedBuffer.RawStorage? {
+    get {
+      if let ref = _stdlib_atomicLoadARCRef(object: _heapStorageBridgedPtr) {
+        return unsafeDowncast(ref, to: BridgedBuffer.RawStorage.self)
+      }
+      return nil
+    }
+  }
+
+  /// Attach a buffer for bridged Set elements.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal func _initializeHeapStorageBridged(_ newStorage: AnyObject) {
+    _stdlib_atomicInitializeARCRef(
+      object: _heapStorageBridgedPtr, desired: newStorage)
+  }
+
+  /// Returns the bridged Set values.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var bridgedBuffer: BridgedBuffer {
+    return BridgedBuffer(_storage: _bridgedStorage!)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal func bridgeEverything() {
+    if _fastPath(_bridgedStorage != nil) {
+      return
+    }
+
+    // FIXME: rdar://problem/19486139 (split bridged buffers for keys and values)
+    // We bridge keys and values unconditionally here, even if one of them
+    // actually is verbatim bridgeable (e.g. Dictionary<Int, AnyObject>).
+    // Investigate only allocating the buffer for a Set in this case.
+
+    // Create buffer for bridged data.
+    let bridged = BridgedBuffer(
+      _exactBucketCount: nativeBuffer.bucketCount,
+      unhashable: ())
+
+    // Bridge everything.
+    for i in 0..<nativeBuffer.bucketCount {
+      if nativeBuffer.isInitializedEntry(at: i) {
+        let key = _bridgeAnythingToObjectiveC(nativeBuffer.key(at: i))
+        bridged.initializeKey(key, at: i)
+      }
+    }
+
+    // Atomically put the bridged elements in place.
+    _initializeHeapStorageBridged(bridged._storage)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal var count: Int {
+    return nativeBuffer.count
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @nonobjc
+  internal func bridgingObjectForKey(_ aKey: AnyObject)
+    -> AnyObject? {
+    guard let nativeKey = _conditionallyBridgeFromObjectiveC(aKey, Key.self)
+    else { return nil }
+
+    let (i, found) = nativeBuffer._find(
+      nativeKey, startBucket: nativeBuffer._bucket(nativeKey))
+    if found {
+      bridgeEverything()
+      return bridgedBuffer.value(at: i.offset)
+    }
+    return nil
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc
+  internal func enumerator() -> _NSEnumerator {
+    bridgeEverything()
+    return _NativeSetNSEnumerator<AnyObject>(bridgedBuffer)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @objc(countByEnumeratingWithState:objects:count:)
+  internal func countByEnumerating(
+    with state: UnsafeMutablePointer<_SwiftNSFastEnumerationState>,
+    objects: UnsafeMutablePointer<AnyObject>?,
+    count: Int
+  ) -> Int {
+    var theState = state.pointee
+    if theState.state == 0 {
+      theState.state = 1 // Arbitrary non-zero value.
+      theState.itemsPtr = AutoreleasingUnsafeMutablePointer(objects)
+      theState.mutationsPtr = _fastEnumerationStorageMutationsPtr
+      theState.extra.0 = CUnsignedLong(nativeBuffer.startIndex.offset)
+    }
+
+    // Test 'objects' rather than 'count' because (a) this is very rare anyway,
+    // and (b) the optimizer should then be able to optimize away the
+    // unwrapping check below.
+    if _slowPath(objects == nil) {
+      return 0
+    }
+
+    let unmanagedObjects = _UnmanagedAnyObjectArray(objects!)
+    var currIndex = _NativeSetIndex<Element>(
+        offset: Int(theState.extra.0))
+    let endIndex = nativeBuffer.endIndex
+    var stored = 0
+
+    // Only need to bridge once, so we can hoist it out of the loop.
+    if (currIndex != endIndex) {
+      bridgeEverything()
+    }
+
+    for i in 0..<count {
+      if (currIndex == endIndex) {
+        break
+      }
+
+      let bridgedKey = bridgedBuffer.key(at: currIndex.offset)
+      unmanagedObjects[i] = bridgedKey
+      stored += 1
+      nativeBuffer.formIndex(after: &currIndex)
+    }
+    theState.extra.0 = CUnsignedLong(currIndex.offset)
+    state.pointee = theState
+    return stored
+  }
+}
+#else
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+final internal class _SwiftDeferredNSSet<Element: Hashable> { }
+#endif
+
+#if _runtime(_ObjC)
+@_versioned
+@_fixed_layout
+internal struct _CocoaSetBuffer: _HashBuffer {
+  @_versioned
+  internal var cocoaSet: _NSSet
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(cocoaSet: _NSSet) {
+    self.cocoaSet = cocoaSet
+  }
+
+  internal typealias Index = _CocoaSetIndex
+  internal typealias SequenceElement = AnyObject
+  internal typealias SequenceElementWithoutLabels = AnyObject
+
+  internal typealias Key = AnyObject
+  internal typealias Value = AnyObject
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var startIndex: Index {
+    return Index(cocoaSet, startIndex: ())
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var endIndex: Index {
+    return Index(cocoaSet, endIndex: ())
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func index(after i: Index) -> Index {
+    return i.successor()
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func formIndex(after i: inout Index) {
+    // FIXME: swift-3-indexing-model: optimize if possible.
+    i = i.successor()
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func index(forKey key: Key) -> Index? {
+    // Fast path that does not involve creating an array of all keys.  In case
+    // the key is present, this lookup is a penalty for the slow path, but the
+    // potential savings are significant: we could skip a memory allocation and
+    // a linear search.
+    if maybeGet(key) == nil {
+      return nil
+    }
+
+    let allKeys = _stdlib_NSSet_allObjects(cocoaSet)
+    var keyIndex = -1
+    for i in 0..<allKeys.value {
+      if _stdlib_NSObject_isEqual(key, allKeys[i]) {
+        keyIndex = i
+        break
+      }
+    }
+    _sanityCheck(keyIndex >= 0,
+        "Key was found in fast path, but not found later?")
+    return Index(cocoaSet, allKeys, keyIndex)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func assertingGet(_ i: Index) -> SequenceElement {
+    let value: Value? = i.allKeys[i.currentKeyIndex]
+    _sanityCheck(value != nil, "Item not found in underlying NSSet")
+    return value!
+
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func assertingGet(_ key: Key) -> Value {
+    let value: Value? = cocoaSet.member(key)
+    _precondition(value != nil, "Member not found in underlying NSSet")
+    return value!
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @inline(__always)
+  internal func maybeGet(_ key: Key) -> Value? {
+
+  return cocoaSet.member(key)
+
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
+    _sanityCheckFailure("cannot mutate NSSet")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal mutating func insert(
+    _ value: Value, forKey key: Key
+  ) -> (inserted: Bool, memberAfterInsert: Value) {
+    _sanityCheckFailure("cannot mutate NSSet")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal mutating func remove(at index: Index) -> SequenceElement {
+    _sanityCheckFailure("cannot mutate NSSet")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal mutating func removeValue(forKey key: Key) -> Value? {
+    _sanityCheckFailure("cannot mutate NSSet")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func removeAll(keepingCapacity keepCapacity: Bool) {
+    _sanityCheckFailure("cannot mutate NSSet")
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var count: Int {
+    return cocoaSet.count
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func fromArray(_ elements: [SequenceElementWithoutLabels])
+    -> _CocoaSetBuffer {
+
+    _sanityCheckFailure("this function should never be called")
+  }
+}
+#endif
+
+@_versioned
+@_frozen
+internal enum _VariantSetBuffer<Element: Hashable>: _HashBuffer {
+
+  internal typealias NativeBuffer = _NativeSetBuffer<Element>
+  internal typealias NativeIndex = _NativeSetIndex<Element>
+#if _runtime(_ObjC)
+  internal typealias CocoaBuffer = _CocoaSetBuffer
+#endif
+  internal typealias SequenceElement = Element
+  internal typealias SequenceElementWithoutLabels = Element
+  internal typealias SelfType = _VariantSetBuffer
+
+  internal typealias Key = Element
+  internal typealias Value = Element
+
+  case native(NativeBuffer)
+#if _runtime(_ObjC)
+  case cocoa(CocoaBuffer)
+#endif
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @_transparent
+  internal var guaranteedNative: Bool {
+    return _canBeClass(Key.self) == 0 || _canBeClass(Value.self) == 0
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func isUniquelyReferenced() -> Bool {
+    // Note that &self drills down through .native(NativeBuffer) to the first
+    // property in NativeBuffer, which is the reference to the storage.
+    if _fastPath(guaranteedNative) {
+      return _isUnique_native(&self)
+    }
+
+    switch self {
+    case .native:
+      return _isUnique_native(&self)
+#if _runtime(_ObjC)
+    case .cocoa:
+      // Don't consider Cocoa buffer mutable, even if it is mutable and is
+      // uniquely referenced.
+      return false
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal var asNative: NativeBuffer {
+    get {
+      switch self {
+      case .native(let buffer):
+        return buffer
+#if _runtime(_ObjC)
+      case .cocoa:
+        _sanityCheckFailure("internal error: not backed by native buffer")
+#endif
+      }
+    }
+    set {
+      self = .native(newValue)
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func ensureNativeBuffer() {
+#if _runtime(_ObjC)
+    if _fastPath(guaranteedNative) { return }
+    if case .cocoa(let cocoaBuffer) = self {
+      migrateDataToNativeBuffer(cocoaBuffer)
+    }
+#endif
+  }
+
+#if _runtime(_ObjC)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var asCocoa: CocoaBuffer {
+    switch self {
+    case .native:
+      _sanityCheckFailure("internal error: not backed by NSSet")
+    case .cocoa(let cocoaBuffer):
+      return cocoaBuffer
+    }
+  }
+#endif
+
+  /// Return true if self is native.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _isNative: Bool {
+#if _runtime(_ObjC)
+    switch self {
+    case .native:
+      return true
+    case .cocoa:
+      return false
+    }
+#else
+    return true
+#endif
+  }
+
+  @inline(__always)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func ensureUniqueNativeBufferNative(
+    withBucketCount desiredBucketCount: Int
+  ) -> (reallocated: Bool, capacityChanged: Bool) {
+    let oldBucketCount = asNative.bucketCount
+    if oldBucketCount >= desiredBucketCount && isUniquelyReferenced() {
+      return (reallocated: false, capacityChanged: false)
+    }
+
+    let oldNativeBuffer = asNative
+    var newNativeBuffer = NativeBuffer(bucketCount: desiredBucketCount)
+    let newBucketCount = newNativeBuffer.bucketCount
+    for i in 0..<oldBucketCount {
+      if oldNativeBuffer.isInitializedEntry(at: i) {
+        if oldBucketCount == newBucketCount {
+          let key = oldNativeBuffer.key(at: i)
+          newNativeBuffer.initializeKey(key, at: i)
+        } else {
+          let key = oldNativeBuffer.key(at: i)
+          newNativeBuffer.unsafeAddNew(key: key)
+        }
+      }
+    }
+    newNativeBuffer.count = oldNativeBuffer.count
+
+    self = .native(newNativeBuffer)
+    return (reallocated: true,
+      capacityChanged: oldBucketCount != newBucketCount)
+  }
+
+  @inline(__always)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func ensureUniqueNativeBuffer(
+    withCapacity minimumCapacity: Int
+  ) -> (reallocated: Bool, capacityChanged: Bool) {
+    let bucketCount = NativeBuffer.bucketCount(
+      forCapacity: minimumCapacity,
+      maxLoadFactorInverse: _hashContainerDefaultMaxLoadFactorInverse)
+    return ensureUniqueNativeBuffer(withBucketCount: bucketCount)
+  }
+
+  /// Ensure this we hold a unique reference to a native buffer
+  /// having at least `minimumCapacity` elements.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func ensureUniqueNativeBuffer(
+    withBucketCount desiredBucketCount: Int
+  ) -> (reallocated: Bool, capacityChanged: Bool) {
+#if _runtime(_ObjC)
+    // This is a performance optimization that was put in to ensure that we did
+    // not make a copy of self to call _isNative over the entire if region
+    // causing at -Onone the uniqueness check to fail. This code used to be:
+    //
+    //  if _isNative {
+    //    return ensureUniqueNativeBufferNative(
+    //      withBucketCount: desiredBucketCount)
+    //  }
+    //
+    // SR-6437
+    let n = _isNative
+    if n {
+      return ensureUniqueNativeBufferNative(withBucketCount: desiredBucketCount)
+    }
+
+    switch self {
+    case .native:
+      fatalError("This should have been handled earlier")
+    case .cocoa(let cocoaBuffer):
+      let cocoaSet = cocoaBuffer.cocoaSet
+      var newNativeBuffer = NativeBuffer(bucketCount: desiredBucketCount)
+      let oldCocoaIterator = _CocoaSetIterator(cocoaSet)
+      while let key = oldCocoaIterator.next() {
+        newNativeBuffer.unsafeAddNew(
+            key: _forceBridgeFromObjectiveC(key, Value.self))
+      }
+
+      newNativeBuffer.count = cocoaSet.count
+
+      self = .native(newNativeBuffer)
+      return (reallocated: true, capacityChanged: true)
+    }
+#else
+    return ensureUniqueNativeBufferNative(withBucketCount: desiredBucketCount)
+#endif
+  }
+
+#if _runtime(_ObjC)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @inline(never)
+  internal mutating func migrateDataToNativeBuffer(
+    _ cocoaBuffer: _CocoaSetBuffer
+  ) {
+    let allocated = ensureUniqueNativeBuffer(
+      withCapacity: cocoaBuffer.count).reallocated
+    _sanityCheck(allocated, "failed to allocate native Set buffer")
+  }
+#endif
+
+  /// Reserves enough space for the specified number of elements to be stored
+  /// without reallocating additional storage.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func reserveCapacity(_ capacity: Int) {
+    _ = ensureUniqueNativeBuffer(withCapacity: capacity)
+  }
+
+  /// The number of elements that can be stored without expanding the current
+  /// storage.
+  ///
+  /// For bridged storage, this is equal to the current count of the
+  /// collection, since any addition will trigger a copy of the elements into
+  /// newly allocated storage. For native storage, this is the element count
+  /// at which adding any more elements will exceed the load factor.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var capacity: Int {
+    switch self {
+    case .native:
+      return Int(Double(asNative.bucketCount) /
+        _hashContainerDefaultMaxLoadFactorInverse)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      return cocoaBuffer.count
+#endif
+    }
+  }
+
+  //
+  // _HashBuffer conformance
+  //
+
+  internal typealias Index = SetIndex<Element>
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var startIndex: Index {
+    if _fastPath(guaranteedNative) {
+      return ._native(asNative.startIndex)
+    }
+
+    switch self {
+    case .native:
+      return ._native(asNative.startIndex)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      return ._cocoa(cocoaBuffer.startIndex)
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var endIndex: Index {
+    if _fastPath(guaranteedNative) {
+      return ._native(asNative.endIndex)
+    }
+
+    switch self {
+    case .native:
+      return ._native(asNative.endIndex)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      return ._cocoa(cocoaBuffer.endIndex)
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func index(after i: Index) -> Index {
+    if _fastPath(guaranteedNative) {
+      return ._native(asNative.index(after: i._nativeIndex))
+    }
+
+    switch self {
+    case .native:
+      return ._native(asNative.index(after: i._nativeIndex))
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      return ._cocoa(cocoaBuffer.index(after: i._cocoaIndex))
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func formIndex(after i: inout Index) {
+    // FIXME: swift-3-indexing-model: optimize if possible.
+    i = index(after: i)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(__always)
+  internal func index(forKey key: Key) -> Index? {
+    if _fastPath(guaranteedNative) {
+      if let nativeIndex = asNative.index(forKey: key) {
+        return ._native(nativeIndex)
+      }
+      return nil
+    }
+
+    switch self {
+    case .native:
+      if let nativeIndex = asNative.index(forKey: key) {
+        return ._native(nativeIndex)
+      }
+      return nil
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      let anyObjectKey: AnyObject = _bridgeAnythingToObjectiveC(key)
+      if let cocoaIndex = cocoaBuffer.index(forKey: anyObjectKey) {
+        return ._cocoa(cocoaIndex)
+      }
+      return nil
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func assertingGet(_ i: Index) -> SequenceElement {
+    if _fastPath(guaranteedNative) {
+      return asNative.assertingGet(i._nativeIndex)
+    }
+
+    switch self {
+    case .native:
+      return asNative.assertingGet(i._nativeIndex)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      let anyObjectValue: AnyObject = cocoaBuffer.assertingGet(i._cocoaIndex)
+      let nativeValue = _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
+      return nativeValue
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func assertingGet(_ key: Key) -> Value {
+    if _fastPath(guaranteedNative) {
+      return asNative.assertingGet(key)
+    }
+
+    switch self {
+    case .native:
+      return asNative.assertingGet(key)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      // FIXME: This assumes that Key and Value are bridged verbatim.
+      let anyObjectKey: AnyObject = _bridgeAnythingToObjectiveC(key)
+      let anyObjectValue: AnyObject = cocoaBuffer.assertingGet(anyObjectKey)
+      return _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
+#endif
+    }
+  }
+
+#if _runtime(_ObjC)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(never)
+  internal static func maybeGetFromCocoaBuffer(
+    _ cocoaBuffer: CocoaBuffer, forKey key: Key
+  ) -> Value? {
+    let anyObjectKey: AnyObject = _bridgeAnythingToObjectiveC(key)
+    if let anyObjectValue = cocoaBuffer.maybeGet(anyObjectKey) {
+      return _forceBridgeFromObjectiveC(anyObjectValue, Value.self)
+    }
+    return nil
+  }
+#endif
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(__always)
+  internal func maybeGet(_ key: Key) -> Value? {
+    if _fastPath(guaranteedNative) {
+      return asNative.maybeGet(key)
+    }
+
+    switch self {
+    case .native:
+      return asNative.maybeGet(key)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      return SelfType.maybeGetFromCocoaBuffer(cocoaBuffer, forKey: key)
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func nativeUpdateValue(
+    _ value: Value, forKey key: Key
+  ) -> Value? {
+    var (i, found) = asNative._find(key, startBucket: asNative._bucket(key))
+
+    let minBuckets = found
+      ? asNative.bucketCount
+      : NativeBuffer.bucketCount(
+          forCapacity: asNative.count + 1,
+          maxLoadFactorInverse: _hashContainerDefaultMaxLoadFactorInverse)
+
+    let (_, capacityChanged) = ensureUniqueNativeBuffer(
+      withBucketCount: minBuckets)
+    if capacityChanged {
+      i = asNative._find(key, startBucket: asNative._bucket(key)).pos
+    }
+
+    let oldValue: Value? = found ? asNative.key(at: i.offset) : nil
+    if found {
+      asNative.setKey(key, at: i.offset)
+    } else {
+      asNative.initializeKey(key, at: i.offset)
+      asNative.count += 1
+    }
+
+    return oldValue
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal mutating func updateValue(
+    _ value: Value, forKey key: Key
+  ) -> Value? {
+
+    if _fastPath(guaranteedNative) {
+      return nativeUpdateValue(value, forKey: key)
+    }
+
+    switch self {
+    case .native:
+      return nativeUpdateValue(value, forKey: key)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      migrateDataToNativeBuffer(cocoaBuffer)
+      return nativeUpdateValue(value, forKey: key)
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func nativeInsert(
+    _ value: Value, forKey key: Key
+  ) -> (inserted: Bool, memberAfterInsert: Value) {
+
+    var (i, found) = asNative._find(key, startBucket: asNative._bucket(key))
+    if found {
+      return (inserted: false, memberAfterInsert: asNative.key(at: i.offset))
+    }
+
+    let minCapacity = asNative.count + 1
+    let (_, capacityChanged) = ensureUniqueNativeBuffer(
+      withCapacity: minCapacity)
+
+    if capacityChanged {
+      i = asNative._find(key, startBucket: asNative._bucket(key)).pos
+    }
+
+    asNative.initializeKey(key, at: i.offset)
+    asNative.count += 1
+
+    return (inserted: true, memberAfterInsert: value)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal mutating func insert(
+    _ value: Value, forKey key: Key
+  ) -> (inserted: Bool, memberAfterInsert: Value) {
+    ensureNativeBuffer()
+    return nativeInsert(value, forKey: key)
+  }
+
+  /// - parameter idealBucket: The ideal bucket for the element being deleted.
+  /// - parameter offset: The offset of the element that will be deleted.
+  /// Precondition: there should be an initialized entry at offset.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func nativeDelete(
+    _ nativeBuffer: NativeBuffer, idealBucket: Int, offset: Int
+  ) {
+    _sanityCheck(
+        nativeBuffer.isInitializedEntry(at: offset), "expected initialized entry")
+
+    var nativeBuffer = nativeBuffer
+
+    // remove the element
+    nativeBuffer.destroyEntry(at: offset)
+    nativeBuffer.count -= 1
+
+    // If we've put a hole in a chain of contiguous elements, some
+    // element after the hole may belong where the new hole is.
+    var hole = offset
+
+    // Find the first bucket in the contiguous chain
+    var start = idealBucket
+    while nativeBuffer.isInitializedEntry(at: nativeBuffer._prev(start)) {
+      start = nativeBuffer._prev(start)
+    }
+
+    // Find the last bucket in the contiguous chain
+    var lastInChain = hole
+    var b = nativeBuffer._index(after: lastInChain)
+    while nativeBuffer.isInitializedEntry(at: b) {
+      lastInChain = b
+      b = nativeBuffer._index(after: b)
+    }
+
+    // Relocate out-of-place elements in the chain, repeating until
+    // none are found.
+    while hole != lastInChain {
+      // Walk backwards from the end of the chain looking for
+      // something out-of-place.
+      var b = lastInChain
+      while b != hole {
+        let idealBucket = nativeBuffer._bucket(nativeBuffer.key(at: b))
+
+        // Does this element belong between start and hole?  We need
+        // two separate tests depending on whether [start, hole] wraps
+        // around the end of the storage
+        let c0 = idealBucket >= start
+        let c1 = idealBucket <= hole
+        if start <= hole ? (c0 && c1) : (c0 || c1) {
+          break // Found it
+        }
+        b = nativeBuffer._prev(b)
+      }
+
+      if b == hole { // No out-of-place elements found; we're done adjusting
+        break
+      }
+
+      // Move the found element into the hole
+      nativeBuffer.moveInitializeEntry(
+        from: nativeBuffer,
+        at: b,
+        toEntryAt: hole)
+      hole = b
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func nativeRemoveObject(forKey key: Key) -> Value? {
+    var idealBucket = asNative._bucket(key)
+    var (index, found) = asNative._find(key, startBucket: idealBucket)
+
+    // Fast path: if the key is not present, we will not mutate the set,
+    // so don't force unique buffer.
+    if !found {
+      return nil
+    }
+
+    // This is a performance optimization that was put in to ensure that we
+    // did not make a copy of self to call asNative.bucketCount over
+    // ensureUniqueNativeBefore causing at -Onone the uniqueness check to
+    // fail. This code used to be:
+    //
+    // ... = ensureUniqueNativeBuffer(withBucketCount: asNative.bucketCount)
+    //
+    // SR-6437
+    let bucketCount = asNative.bucketCount
+    let (_, capacityChanged) = ensureUniqueNativeBuffer(
+      withBucketCount: bucketCount)
+    let nativeBuffer = asNative
+    if capacityChanged {
+      idealBucket = nativeBuffer._bucket(key)
+      (index, found) = nativeBuffer._find(key, startBucket: idealBucket)
+      _sanityCheck(found, "key was lost during buffer migration")
+    }
+    let oldValue = nativeBuffer.key(at: index.offset)
+    nativeDelete(nativeBuffer, idealBucket: idealBucket,
+      offset: index.offset)
+    return oldValue
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func nativeRemove(
+    at nativeIndex: NativeIndex
+  ) -> SequenceElement {
+    // This is a performance optimization that was put in to ensure that we did
+    // not make a copy of self to call asNative.bucketCount over
+    // ensureUniqueNativeBefore causing at -Onone the uniqueness check to
+    // fail. This code used to be:
+    //
+    // _ = ensureUniqueNativeBuffer(withBucketCount: asNative.bucketCount)
+    //
+    // SR-6437
+    let bucketCount = asNative.bucketCount
+    // The provided index should be valid, so we will always mutating the
+    // set buffer.  Request unique buffer.
+    _ = ensureUniqueNativeBuffer(withBucketCount: bucketCount)
+    let nativeBuffer = asNative
+
+    let result = nativeBuffer.assertingGet(nativeIndex)
+    let key = result
+
+    nativeDelete(nativeBuffer, idealBucket: nativeBuffer._bucket(key),
+        offset: nativeIndex.offset)
+    return result
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal mutating func remove(at index: Index) -> SequenceElement {
+    if _fastPath(guaranteedNative) {
+      return nativeRemove(at: index._nativeIndex)
+    }
+
+    switch self {
+    case .native:
+      return nativeRemove(at: index._nativeIndex)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      // We have to migrate the data first.  But after we do so, the Cocoa
+      // index becomes useless, so get the key first.
+      //
+      // FIXME(performance): fuse data migration and element deletion into one
+      // operation.
+      let index = index._cocoaIndex
+      let anyObjectKey: AnyObject = index.allKeys[index.currentKeyIndex]
+      migrateDataToNativeBuffer(cocoaBuffer)
+      let key = _forceBridgeFromObjectiveC(anyObjectKey, Key.self)
+      let value = nativeRemoveObject(forKey: key)
+
+      _sanityCheck(key == value, "bridging did not preserve equality")
+      return key
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  @discardableResult
+  internal mutating func removeValue(forKey key: Key) -> Value? {
+    if _fastPath(guaranteedNative) {
+      return nativeRemoveObject(forKey: key)
+    }
+
+    switch self {
+    case .native:
+      return nativeRemoveObject(forKey: key)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      let anyObjectKey: AnyObject = _bridgeAnythingToObjectiveC(key)
+      if cocoaBuffer.maybeGet(anyObjectKey) == nil {
+        return nil
+      }
+      migrateDataToNativeBuffer(cocoaBuffer)
+      return nativeRemoveObject(forKey: key)
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func nativeRemoveAll() {
+    if !isUniquelyReferenced() {
+        asNative = NativeBuffer(_exactBucketCount: asNative.bucketCount)
+        return
+    }
+
+    // We have already checked for the empty dictionary case and unique
+    // reference, so we will always mutate the dictionary buffer.
+    var nativeBuffer = asNative
+
+    for b in 0..<nativeBuffer.bucketCount {
+      if nativeBuffer.isInitializedEntry(at: b) {
+        nativeBuffer.destroyEntry(at: b)
+      }
+    }
+    nativeBuffer.count = 0
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func removeAll(keepingCapacity keepCapacity: Bool) {
+    if count == 0 {
+      return
+    }
+
+    if !keepCapacity {
+      self = .native(NativeBuffer(bucketCount: 2))
+      return
+    }
+
+    if _fastPath(guaranteedNative) {
+      nativeRemoveAll()
+      return
+    }
+
+    switch self {
+    case .native:
+      nativeRemoveAll()
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      self = .native(NativeBuffer(minimumCapacity: cocoaBuffer.count))
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var count: Int {
+    if _fastPath(guaranteedNative) {
+      return asNative.count
+    }
+
+    switch self {
+    case .native:
+      return asNative.count
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      return cocoaBuffer.count
+#endif
+    }
+  }
+
+  /// Returns an iterator over the `(Key, Value)` pairs.
+  ///
+  /// - Complexity: O(1).
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @inline(__always)
+  internal func makeIterator() -> SetIterator<Element> {
+    switch self {
+    case .native(let buffer):
+      return ._native(
+        start: asNative.startIndex, end: asNative.endIndex, buffer: buffer)
+#if _runtime(_ObjC)
+    case .cocoa(let cocoaBuffer):
+      return ._cocoa(_CocoaSetIterator(cocoaBuffer.cocoaSet))
+#endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func fromArray(_ elements: [SequenceElement])
+    -> _VariantSetBuffer<Element> {
+
+    _sanityCheckFailure("this function should never be called")
+  }
+}
+
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned
+internal struct _NativeSetIndex<Element>: Comparable {
+  @_versioned
+  internal var offset: Int
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal init(offset: Int) {
+    self.offset = offset
+  }
+}
+
+extension _NativeSetIndex {
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func < (
+    lhs: _NativeSetIndex<Element>,
+    rhs: _NativeSetIndex<Element>
+  ) -> Bool {
+    return lhs.offset < rhs.offset
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func <= (
+    lhs: _NativeSetIndex<Element>,
+    rhs: _NativeSetIndex<Element>
+  ) -> Bool {
+    return lhs.offset <= rhs.offset
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func > (
+    lhs: _NativeSetIndex<Element>,
+    rhs: _NativeSetIndex<Element>
+  ) -> Bool {
+    return lhs.offset > rhs.offset
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func >= (
+    lhs: _NativeSetIndex<Element>,
+    rhs: _NativeSetIndex<Element>
+  ) -> Bool {
+    return lhs.offset >= rhs.offset
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func == (
+    lhs: _NativeSetIndex<Element>,
+    rhs: _NativeSetIndex<Element>
+  ) -> Bool {
+    return lhs.offset == rhs.offset
+  }
+}
+
+#if _runtime(_ObjC)
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned
+internal struct _CocoaSetIndex: Comparable {
+  // Assumption: we rely on NSDictionary.getObjects when being
+  // repeatedly called on the same NSDictionary, returning items in the same
+  // order every time.
+  // Similarly, the same assumption holds for NSSet.allObjects.
+
+  /// A reference to the NSSet, which owns members in `allObjects`,
+  /// or `allKeys`, for NSSet and NSDictionary respectively.
+  @_versioned // FIXME(sil-serialize-all)
+  internal let cocoaSet: _NSSet
+  // FIXME: swift-3-indexing-model: try to remove the cocoa reference, but make
+  // sure that we have a safety check for accessing `allKeys`.  Maybe move both
+  // into the dictionary/set itself.
+
+  /// An unowned array of keys.
+  @_versioned // FIXME(sil-serialize-all)
+  internal var allKeys: _HeapBuffer<Int, AnyObject>
+
+  /// Index into `allKeys`
+  @_versioned // FIXME(sil-serialize-all)
+  internal var currentKeyIndex: Int
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_ cocoaSet: _NSSet, startIndex: ()) {
+    self.cocoaSet = cocoaSet
+    self.allKeys = _stdlib_NSSet_allObjects(cocoaSet)
+    self.currentKeyIndex = 0
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_ cocoaSet: _NSSet, endIndex: ()) {
+    self.cocoaSet = cocoaSet
+    self.allKeys = _stdlib_NSSet_allObjects(cocoaSet)
+    self.currentKeyIndex = allKeys.value
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_ cocoaSet: _NSSet,
+    _ allKeys: _HeapBuffer<Int, AnyObject>,
+    _ currentKeyIndex: Int
+  ) {
+    self.cocoaSet = cocoaSet
+    self.allKeys = allKeys
+    self.currentKeyIndex = currentKeyIndex
+  }
+
+  /// Returns the next consecutive value after `self`.
+  ///
+  /// - Precondition: The next value is representable.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func successor() -> _CocoaSetIndex {
+    // FIXME: swift-3-indexing-model: remove this method.
+    _precondition(
+      currentKeyIndex < allKeys.value, "Cannot increment endIndex")
+    return _CocoaSetIndex(cocoaSet, allKeys, currentKeyIndex + 1)
+  }
+}
+
+extension _CocoaSetIndex {
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func < (
+    lhs: _CocoaSetIndex,
+    rhs: _CocoaSetIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex < rhs.currentKeyIndex
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func <= (
+    lhs: _CocoaSetIndex,
+    rhs: _CocoaSetIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex <= rhs.currentKeyIndex
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func > (
+    lhs: _CocoaSetIndex,
+    rhs: _CocoaSetIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex > rhs.currentKeyIndex
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func >= (
+    lhs: _CocoaSetIndex,
+    rhs: _CocoaSetIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex >= rhs.currentKeyIndex
+  }
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal static func == (
+    lhs: _CocoaSetIndex,
+    rhs: _CocoaSetIndex
+  ) -> Bool {
+    return lhs.currentKeyIndex == rhs.currentKeyIndex
+  }
+}
+#endif
+
+@_frozen // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal enum SetIndexRepresentation<Element: Hashable> {
+  typealias _Index = SetIndex<Element>
+  typealias _NativeIndex = _Index._NativeIndex
+#if _runtime(_ObjC)
+  typealias _CocoaIndex = _Index._CocoaIndex
+#endif
+
+  case _native(_NativeIndex)
+#if _runtime(_ObjC)
+  case _cocoa(_CocoaIndex)
+#endif
+}
+
+extension Set {
+  /// The position of an element in a set.
+  @_fixed_layout // FIXME(sil-serialize-all)
+  public struct Index: Comparable, Hashable {
+    // Index for native buffer is efficient.  Index for bridged NSSet is
+    // not, because neither NSEnumerator nor fast enumeration support moving
+    // backwards.  Even if they did, there is another issue: NSEnumerator does
+    // not support NSCopying, and fast enumeration does not document that it is
+    // safe to copy the state.  So, we cannot implement Index that is a value
+    // type for bridged NSSet in terms of Cocoa enumeration facilities.
+
+    internal typealias _NativeIndex = _NativeSetIndex<Element>
+#if _runtime(_ObjC)
+    internal typealias _CocoaIndex = _CocoaSetIndex
+#endif
+
+    internal typealias Key = Element
+    internal typealias Value = Element
+
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned // FIXME(sil-serialize-all)
+    internal init(_value: SetIndexRepresentation<Element>) {
+      self._value = _value
+    }
+
+    @_versioned // FIXME(sil-serialize-all)
+    internal var _value: SetIndexRepresentation<Element>
+
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned
+    internal static func _native(_ index: _NativeIndex) -> Index {
+      return SetIndex(_value: ._native(index))
+    }
+#if _runtime(_ObjC)
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned
+    internal static func _cocoa(_ index: _CocoaIndex) -> Index {
+      return SetIndex(_value: ._cocoa(index))
+    }
+#endif
+
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned
+    @_transparent
+    internal var _guaranteedNative: Bool {
+      return _canBeClass(Key.self) == 0 && _canBeClass(Value.self) == 0
+    }
+
+    @_versioned // FIXME(sil-serialize-all)
+    @_transparent
+    internal var _nativeIndex: _NativeIndex {
+      switch _value {
+      case ._native(let nativeIndex):
+        return nativeIndex
+#if _runtime(_ObjC)
+      case ._cocoa:
+        _sanityCheckFailure("internal error: does not contain a native index")
+#endif
+      }
+    }
+
+#if _runtime(_ObjC)
+    @_inlineable // FIXME(sil-serialize-all)
+    @_versioned // FIXME(sil-serialize-all)
+    @_transparent
+    internal var _cocoaIndex: _CocoaIndex {
+      switch _value {
+      case ._native:
+        _sanityCheckFailure("internal error: does not contain a Cocoa index")
+      case ._cocoa(let cocoaIndex):
+        return cocoaIndex
+      }
+    }
+#endif
+  }
+}
+
+public typealias SetIndex<Element: Hashable> = Set<Element>.Index
+
+extension Set.Index {
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func == (
+    lhs: Set<Element>.Index,
+    rhs: Set<Element>.Index
+  ) -> Bool {
+    if _fastPath(lhs._guaranteedNative) {
+      return lhs._nativeIndex == rhs._nativeIndex
+    }
+
+    switch (lhs._value, rhs._value) {
+    case (._native(let lhsNative), ._native(let rhsNative)):
+      return lhsNative == rhsNative
+  #if _runtime(_ObjC)
+    case (._cocoa(let lhsCocoa), ._cocoa(let rhsCocoa)):
+      return lhsCocoa == rhsCocoa
+    default:
+      _preconditionFailure("Comparing indexes from different sets")
+  #endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func < (
+    lhs: Set<Element>.Index,
+    rhs: Set<Element>.Index
+  ) -> Bool {
+    if _fastPath(lhs._guaranteedNative) {
+      return lhs._nativeIndex < rhs._nativeIndex
+    }
+
+    switch (lhs._value, rhs._value) {
+    case (._native(let lhsNative), ._native(let rhsNative)):
+      return lhsNative < rhsNative
+  #if _runtime(_ObjC)
+    case (._cocoa(let lhsCocoa), ._cocoa(let rhsCocoa)):
+      return lhsCocoa < rhsCocoa
+    default:
+      _preconditionFailure("Comparing indexes from different sets")
+  #endif
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public var hashValue: Int {
+    if _fastPath(_guaranteedNative) {
+      return _nativeIndex.offset
+    }
+
+    switch _value {
+    case ._native(let nativeIndex):
+      return nativeIndex.offset
+  #if _runtime(_ObjC)
+    case ._cocoa(let cocoaIndex):
+      return cocoaIndex.currentKeyIndex
+  #endif
+    }
+  }
+}
+
+#if _runtime(_ObjC)
+@_fixed_layout // FIXME(sil-serialize-all)
+@_versioned
+final internal class _CocoaSetIterator: IteratorProtocol {
+  internal typealias Element = AnyObject
+
+  // Cocoa Set iterator has to be a class, otherwise we cannot
+  // guarantee that the fast enumeration struct is pinned to a certain memory
+  // location.
+
+  // This stored property should be stored at offset zero.  There's code below
+  // relying on this.
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _fastEnumerationState: _SwiftNSFastEnumerationState =
+    _makeSwiftNSFastEnumerationState()
+
+  // This stored property should be stored right after `_fastEnumerationState`.
+  // There's code below relying on this.
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _fastEnumerationStackBuf = _CocoaFastEnumerationStackBuf()
+
+  @_versioned // FIXME(sil-serialize-all)
+  internal let cocoaSet: _NSSet
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _fastEnumerationStatePtr:
+    UnsafeMutablePointer<_SwiftNSFastEnumerationState> {
+    return _getUnsafePointerToStoredProperties(self).assumingMemoryBound(
+      to: _SwiftNSFastEnumerationState.self)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _fastEnumerationStackBufPtr:
+    UnsafeMutablePointer<_CocoaFastEnumerationStackBuf> {
+    return UnsafeMutableRawPointer(_fastEnumerationStatePtr + 1)
+      .assumingMemoryBound(to: _CocoaFastEnumerationStackBuf.self)
+  }
+
+  // These members have to be word-sized integers, they cannot be limited to
+  // Int8 just because our storage holds 16 elements: fast enumeration is
+  // allowed to return inner pointers to the container, which can be much
+  // larger.
+  @_versioned // FIXME(sil-serialize-all)
+  internal var itemIndex: Int = 0
+  @_versioned // FIXME(sil-serialize-all)
+  internal var itemCount: Int = 0
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal init(_ cocoaSet: _NSSet) {
+    self.cocoaSet = cocoaSet
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func next() -> Element? {
+    if itemIndex < 0 {
+      return nil
+    }
+    let cocoaSet = self.cocoaSet
+    if itemIndex == itemCount {
+      let stackBufCount = _fastEnumerationStackBuf.count
+      // We can't use `withUnsafeMutablePointer` here to get pointers to
+      // properties, because doing so might introduce a writeback storage, but
+      // fast enumeration relies on the pointer identity of the enumeration
+      // state struct.
+      itemCount = cocoaSet.countByEnumerating(
+        with: _fastEnumerationStatePtr,
+        objects: UnsafeMutableRawPointer(_fastEnumerationStackBufPtr)
+          .assumingMemoryBound(to: AnyObject.self),
+        count: stackBufCount)
+      if itemCount == 0 {
+        itemIndex = -1
+        return nil
+      }
+      itemIndex = 0
+    }
+    let itemsPtrUP =
+    UnsafeMutableRawPointer(_fastEnumerationState.itemsPtr!)
+      .assumingMemoryBound(to: AnyObject.self)
+    let itemsPtr = _UnmanagedAnyObjectArray(itemsPtrUP)
+    let key: AnyObject = itemsPtr[itemIndex]
+    itemIndex += 1
+    return key
+  }
+}
+#endif
+
+@_versioned
+@_frozen // FIXME(sil-serialize-all)
+internal enum SetIteratorRepresentation<Element: Hashable> {
+  internal typealias _Iterator = SetIterator<Element>
+  internal typealias _NativeBuffer =
+    _NativeSetBuffer<Element>
+  internal typealias _NativeIndex = _Iterator._NativeIndex
+
+  // For native buffer, we keep two indices to keep track of the iteration
+  // progress and the buffer owner to make the buffer non-uniquely
+  // referenced.
+  //
+  // Iterator is iterating over a frozen view of the collection
+  // state, so it should keep its own reference to the buffer.
+  case _native(
+    start: _NativeIndex, end: _NativeIndex, buffer: _NativeBuffer)
+#if _runtime(_ObjC)
+  case _cocoa(_CocoaSetIterator)
+#endif
+}
+
+/// An iterator over the members of a `Set<Element>`.
+@_fixed_layout // FIXME(sil-serialize-all)
+public struct SetIterator<Element: Hashable>: IteratorProtocol {
+  // Set has a separate IteratorProtocol and Index because of efficiency
+  // and implementability reasons.
+  //
+  // Index for native buffer is efficient.  Index for bridged NSSet is
+  // not.
+  //
+  // Even though fast enumeration is not suitable for implementing
+  // Index, which is multi-pass, it is suitable for implementing a
+  // IteratorProtocol, which is being consumed as iteration proceeds.
+
+  internal typealias _NativeBuffer =
+    _NativeSetBuffer<Element>
+  internal typealias _NativeIndex = _NativeSetIndex<Element>
+
+  @_versioned
+  internal var _state: SetIteratorRepresentation<Element>
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal init(_state: SetIteratorRepresentation<Element>) {
+    self._state = _state
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal static func _native(
+    start: _NativeIndex, end: _NativeIndex, buffer: _NativeBuffer
+  ) -> SetIterator {
+    return SetIterator(
+      _state: ._native(start: start, end: end, buffer: buffer))
+  }
+#if _runtime(_ObjC)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal static func _cocoa(
+    _ iterator: _CocoaSetIterator
+  ) -> SetIterator{
+    return SetIterator(_state: ._cocoa(iterator))
+  }
+#endif
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  @_transparent
+  internal var _guaranteedNative: Bool {
+    return _canBeClass(Element.self) == 0
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal mutating func _nativeNext() -> Element? {
+    switch _state {
+    case ._native(let startIndex, let endIndex, let buffer):
+      if startIndex == endIndex {
+        return nil
+      }
+      let result = buffer.assertingGet(startIndex)
+      _state =
+        ._native(start: buffer.index(after: startIndex), end: endIndex, buffer: buffer)
+      return result
+#if _runtime(_ObjC)
+    case ._cocoa:
+      _sanityCheckFailure("internal error: not backed by NSSet")
+#endif
+    }
+  }
+
+  /// Advances to the next element and returns it, or `nil` if no next element
+  /// exists.
+  ///
+  /// Once `nil` has been returned, all subsequent calls return `nil`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @inline(__always)
+  public mutating func next() -> Element? {
+    if _fastPath(_guaranteedNative) {
+      return _nativeNext()
+    }
+
+    switch _state {
+    case ._native:
+      return _nativeNext()
+#if _runtime(_ObjC)
+    case ._cocoa(let cocoaIterator):
+      if let anyObjectElement = cocoaIterator.next() {
+        return _forceBridgeFromObjectiveC(anyObjectElement, Element.self)
+      }
+      return nil
+#endif
+    }
+  }
+}
+
+extension SetIterator: CustomReflectable {
+  /// A mirror that reflects the iterator.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var customMirror: Mirror {
+    return Mirror(
+      self,
+      children: EmptyCollection<(label: String?, value: Any)>())
+  }
+}
+
+extension Set: CustomReflectable {
+  /// A mirror that reflects the set.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var customMirror: Mirror {
+    let style = Mirror.DisplayStyle.`set`
+    return Mirror(self, unlabeledChildren: self, displayStyle: style)
+  }
+}
+
+/// Initializes a `Set` from unique members.
+///
+/// Using a builder can be faster than inserting members into an empty
+/// `Set`.
+@_fixed_layout // FIXME(sil-serialize-all)
+public struct _SetBuilder<Element: Hashable> {
+  public typealias Key = Element
+  public typealias Value = Element
+
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _result: Set<Element>
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _nativeBuffer: _NativeSetBuffer<Element>
+  @_versioned // FIXME(sil-serialize-all)
+  internal let _requestedCount: Int
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _actualCount: Int
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public init(count: Int) {
+    _result = Set<Element>(minimumCapacity: count)
+    _nativeBuffer = _result._variantBuffer.asNative
+    _requestedCount = count
+    _actualCount = 0
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func add(member newKey: Key) {
+    _nativeBuffer.unsafeAddNew(key: newKey)
+    _actualCount += 1
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func take() -> Set<Element> {
+    _precondition(_actualCount >= 0,
+      "Cannot take the result twice")
+    _precondition(_actualCount == _requestedCount,
+      "The number of members added does not match the promised count")
+
+    // Finish building the `Set`.
+    _nativeBuffer.count = _requestedCount
+
+    // Prevent taking the result twice.
+    _actualCount = -1
+    return _result
+  }
+}
+
+extension Set {
+  /// Removes and returns the first element of the set.
+  ///
+  /// Because a set is not an ordered collection, the "first" element may not
+  /// be the first element that was added to the set.
+  ///
+  /// - Returns: A member of the set. If the set is empty, returns `nil`.
+  @_inlineable
+  public mutating func popFirst() -> Element? {
+    guard !isEmpty else { return nil }
+    return remove(at: startIndex)
+  }
+
+  @_inlineable
+  @available(swift, obsoleted: 4.0)
+  public func filter(
+    _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
+  ) rethrows -> [Element] {
+    var result: [Element] = []
+    for x in self {
+      if try isIncluded(x) {
+        result.append(x)
+      }
+    }
+    return result
+  }
+
+  /// The total number of elements that the set can contain without
+  /// allocating new storage.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var capacity: Int {
+    return _variantBuffer.capacity
+  }
+
+  /// Reserves enough space to store the specified number of elements.
+  ///
+  /// If you are adding a known number of elements to a set, use this
+  /// method to avoid multiple reallocations. This method ensures that the
+  /// set has unique, mutable, contiguous storage, with space allocated
+  /// for at least the requested number of elements.
+  ///
+  /// Calling the `reserveCapacity(_:)` method on a set with bridged
+  /// storage triggers a copy to contiguous storage even if the existing
+  /// storage has room to store `minimumCapacity` elements.
+  ///
+  /// - Parameter minimumCapacity: The requested number of elements to
+  ///   store.
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func reserveCapacity(_ minimumCapacity: Int) {
+    _variantBuffer.reserveCapacity(minimumCapacity)
+    _sanityCheck(self.capacity >= minimumCapacity)
+  }
+}
+
+//===--- Bridging ---------------------------------------------------------===//
+
+#if _runtime(_ObjC)
+extension Set {
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _bridgeToObjectiveCImpl() -> _NSSetCore {
+    switch _variantBuffer {
+    case _VariantSetBuffer.native(let buffer):
+      return buffer.bridged()
+    case _VariantSetBuffer.cocoa(let cocoaBuffer):
+      return cocoaBuffer.cocoaSet
+    }
+  }
+
+  /// Returns the native Dictionary hidden inside this NSDictionary;
+  /// returns nil otherwise.
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func _bridgeFromObjectiveCAdoptingNativeStorageOf(
+    _ s: AnyObject
+  ) -> Set<Element>? {
+
+    // Try all three NSSet impls that we currently provide.
+
+    if let deferredBuffer = s as? _SwiftDeferredNSSet<Element> {
+      return Set(_nativeBuffer: deferredBuffer.nativeBuffer)
+    }
+
+    if let nativeStorage = s as? _HashableTypedNativeSetStorage<Element> {
+      return Set(_nativeBuffer:
+          _NativeSetBuffer(_storage: nativeStorage))
+    }
+
+    if s === _RawNativeSetStorage.empty {
+      return Set()
+    }
+
+    // FIXME: what if `s` is native storage, but for different key/value type?
+    return nil
+  }
+}
+#endif
diff --git a/stdlib/public/core/StringGuts.swift b/stdlib/public/core/StringGuts.swift
index 8198126..99112f5 100644
--- a/stdlib/public/core/StringGuts.swift
+++ b/stdlib/public/core/StringGuts.swift
@@ -1413,3 +1413,36 @@
     return UnsafeMutablePointer(mutating: _unmanagedUTF16View.start)
   }
 }
+
+extension _StringGuts {
+  @available(*, deprecated)
+  public // SPI(Foundation)
+  var _isContiguousASCII: Bool {
+    return _object.isContiguousASCII
+  }
+
+  @available(*, deprecated)
+  public // SPI(Foundation)
+  var _isContiguousUTF16: Bool {
+    return _object.isContiguousUTF16
+  }
+
+  @available(*, deprecated)
+  public // SPI(Foundation)
+  func _withUnsafeUTF8CodeUnitsIfAvailable<Result>(
+    _ f: (UnsafeBufferPointer<UInt8>) throws -> Result
+  ) rethrows -> Result? {
+    guard _object.isContiguousASCII else { return nil }
+    return try f(_unmanagedASCIIView.buffer)
+  }
+
+  @available(*, deprecated)
+  public // SPI(Foundation)
+  func _withUnsafeUTF16CodeUnitsIfAvailable<Result>(
+    _ f: (UnsafeBufferPointer<UInt16>) throws -> Result
+  ) rethrows -> Result? {
+    guard _object.isContiguousUTF16 else { return nil }
+    return try f(_unmanagedUTF16View.buffer)
+  }
+}
+
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 6a034c1..076c62a 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -1845,10 +1845,11 @@
 /// Initialize the field offset vector for a dependent-layout class, using the
 /// "Universal" layout strategy.
 void
-swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
-                                                 size_t numFields,
-                                           const TypeLayout * const *fieldTypes,
-                                                 size_t *fieldOffsets) {
+swift::swift_initClassMetadata(ClassMetadata *self,
+                               ClassLayoutFlags layoutFlags,
+                               size_t numFields,
+                               const TypeLayout * const *fieldTypes,
+                               size_t *fieldOffsets) {
   _swift_initializeSuperclass(self);
 
   // Start layout by appending to a standard heap object header.
diff --git a/stdlib/public/runtime/RefCount.cpp b/stdlib/public/runtime/RefCount.cpp
index 09f4975..07e2476 100644
--- a/stdlib/public/runtime/RefCount.cpp
+++ b/stdlib/public/runtime/RefCount.cpp
@@ -89,7 +89,7 @@
 // Returns null if the object is deiniting.
 // SideTableRefCountBits specialization intentionally does not exist.
 template <>
-HeapObjectSideTableEntry* RefCounts<InlineRefCountBits>::allocateSideTable()
+HeapObjectSideTableEntry* RefCounts<InlineRefCountBits>::allocateSideTable(bool failIfDeiniting)
 {
   auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME);
   
@@ -98,7 +98,7 @@
     // Already have a side table. Return it.
     return oldbits.getSideTable();
   } 
-  else if (oldbits.getIsDeiniting()) {
+  else if (failIfDeiniting && oldbits.getIsDeiniting()) {
     // Already past the start of deinit. Do nothing.
     return nullptr;
   }
@@ -118,7 +118,7 @@
       delete side;
       return result;
     }
-    else if (oldbits.getIsDeiniting()) {
+    else if (failIfDeiniting && oldbits.getIsDeiniting()) {
       // Already past the start of deinit. Do nothing.
       return nullptr;
     }
@@ -136,7 +136,7 @@
 template <>
 HeapObjectSideTableEntry* RefCounts<InlineRefCountBits>::formWeakReference()
 {
-  auto side = allocateSideTable();
+  auto side = allocateSideTable(true);
   if (side)
     return side->incrementWeak();
   else
@@ -145,7 +145,7 @@
 
 template <typename RefCountBits>
 void RefCounts<RefCountBits>::incrementUnownedSlow(uint32_t n) {
-  auto side = allocateSideTable();
+  auto side = allocateSideTable(false);
   if (side)
     return side->incrementUnowned(n);
   // Overflow but side table allocation failed.
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
index af8b3b3..6b5e2ca 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
@@ -259,7 +259,7 @@
         SwiftName: multiVersionedGlobal45Notes_5
       - Name: multiVersionedGlobal45Both
         SwiftName: multiVersionedGlobal45Both_5
-  - Version: 4 # Versions are deliberately ordered as "3, 5, 4" to catch bugs.
+  - Version: 4 # Versions are deliberately ordered as "3, 5, 4.2, 4" to catch bugs.
     Globals:
       - Name: multiVersionedGlobal34
         SwiftName: multiVersionedGlobal34_4
@@ -293,3 +293,39 @@
         SwiftName: multiVersionedGlobal45Notes_4
       - Name: multiVersionedGlobal45Both
         SwiftName: multiVersionedGlobal45Both_4
+  - Version: 4.2
+    Globals:
+      - Name: multiVersionedGlobal34
+        SwiftName: multiVersionedGlobal34_4_2
+      - Name: multiVersionedGlobal34Header
+        SwiftName: multiVersionedGlobal34Header_4_2
+      - Name: multiVersionedGlobal34Notes
+        SwiftName: multiVersionedGlobal34Notes_4_2
+      - Name: multiVersionedGlobal34Both
+        SwiftName: multiVersionedGlobal34Both_4_2
+      - Name: multiVersionedGlobal345
+        SwiftName: multiVersionedGlobal345_4_2
+      - Name: multiVersionedGlobal345Header
+        SwiftName: multiVersionedGlobal345Header_4_2
+      - Name: multiVersionedGlobal345Notes
+        SwiftName: multiVersionedGlobal345Notes_4_2
+      - Name: multiVersionedGlobal345Both
+        SwiftName: multiVersionedGlobal345Both_4_2
+      - Name: multiVersionedGlobal4
+        SwiftName: multiVersionedGlobal4_4_2
+      - Name: multiVersionedGlobal4Header
+        SwiftName: multiVersionedGlobal4Header_4_2
+      - Name: multiVersionedGlobal4Notes
+        SwiftName: multiVersionedGlobal4Notes_4_2
+      - Name: multiVersionedGlobal4Both
+        SwiftName: multiVersionedGlobal4Both_4_2
+      - Name: multiVersionedGlobal45
+        SwiftName: multiVersionedGlobal45_4_2
+      - Name: multiVersionedGlobal45Header
+        SwiftName: multiVersionedGlobal45Header_4_2
+      - Name: multiVersionedGlobal45Notes
+        SwiftName: multiVersionedGlobal45Notes_4_2
+      - Name: multiVersionedGlobal45Both
+        SwiftName: multiVersionedGlobal45Both_4_2
+      - Name: multiVersionedGlobal34_4_2
+        SwiftName: multiVersionedGlobal34_4_2_not_5
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Globals.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Globals.h
index 059ecd7..e719726 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Globals.h
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Globals.h
@@ -20,4 +20,6 @@
 int multiVersionedGlobal345Header __attribute__((swift_name("multiVersionedGlobal345Header_NEW")));
 int multiVersionedGlobal345Both __attribute__((swift_name("multiVersionedGlobal345Both_OLD")));
 
+int multiVersionedGlobal34_4_2;
+
 #pragma clang assume_nonnull end
diff --git a/test/APINotes/versioned-multi.swift b/test/APINotes/versioned-multi.swift
index d479c3c..07bb138 100644
--- a/test/APINotes/versioned-multi.swift
+++ b/test/APINotes/versioned-multi.swift
@@ -4,6 +4,8 @@
 
 // RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -swift-version 4 | %FileCheck -check-prefix=CHECK-SWIFT-4 %s
 
+// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -swift-version 4.2 | %FileCheck -check-prefix=CHECK-SWIFT-4-2 %s
+
 // RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -swift-version 5 | %FileCheck -check-prefix=CHECK-SWIFT-5 %s
 
 // CHECK-SWIFT-3: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4_4")
@@ -101,6 +103,9 @@
 // CHECK-SWIFT-3: var multiVersionedGlobal345Both_4: Int32
 // CHECK-SWIFT-3: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Both_3")
 // CHECK-SWIFT-3: var multiVersionedGlobal345Both_5: Int32
+// CHECK-SWIFT-3: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34_4_2_not_5")
+// CHECK-SWIFT-3: var multiVersionedGlobal34_4_2: Int32
+// CHECK-SWIFT-3: var multiVersionedGlobal34_4_2_not_5: Int32
 
 
 // CHECK-SWIFT-4: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4_4")
@@ -198,6 +203,108 @@
 // CHECK-SWIFT-4: var multiVersionedGlobal345Both_4: Int32
 // CHECK-SWIFT-4: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Both_4")
 // CHECK-SWIFT-4: var multiVersionedGlobal345Both_5: Int32
+// CHECK-SWIFT-4: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34_4_2_not_5")
+// CHECK-SWIFT-4: var multiVersionedGlobal34_4_2: Int32
+// CHECK-SWIFT-4: var multiVersionedGlobal34_4_2_not_5: Int32
+
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Notes: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Notes_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal4Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Notes_NEW: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Header: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Header_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal4Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Header_NEW: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal4Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Both: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Both_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal4Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal4Both_NEW: Int32
+
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal34_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34_3: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Notes: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal34Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Notes_3: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Notes_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal34Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Notes_NEW: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Header: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal34Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Header_3: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Header_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal34Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Header_NEW: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Both: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal34Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Both_3: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Both_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal34Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34Both_NEW: Int32
+
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal45_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal45_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45_5: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal45Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Notes: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Notes_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal45Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Notes_5: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal45Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Header: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Header_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal45Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Header_5: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal45Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Both: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Both_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal45Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal45Both_5: Int32
+
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal345_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal345_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345_3: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345_5: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal345Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Notes: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal345Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Notes_3: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Notes_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Notes_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Notes_5: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal345Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Header: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal345Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Header_3: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Header_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Header_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Header_5: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal345Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Both: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 4, renamed: "multiVersionedGlobal345Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Both_3: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Both_4: Int32
+// CHECK-SWIFT-4-2: @available(swift, introduced: 5, renamed: "multiVersionedGlobal345Both_4_2")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal345Both_5: Int32
+// CHECK-SWIFT-4-2: @available(swift, obsoleted: 3, renamed: "multiVersionedGlobal34_4_2_not_5")
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34_4_2: Int32
+// CHECK-SWIFT-4-2: var multiVersionedGlobal34_4_2_not_5: Int32
 
 
 // CHECK-SWIFT-5: var multiVersionedGlobal4: Int32
@@ -295,3 +402,5 @@
 // CHECK-SWIFT-5: @available(swift, obsoleted: 5, renamed: "multiVersionedGlobal345Both_5")
 // CHECK-SWIFT-5: var multiVersionedGlobal345Both_4: Int32
 // CHECK-SWIFT-5: var multiVersionedGlobal345Both_5: Int32
+// CHECK-SWIFT-5: @available(swift, obsoleted: 5, renamed: "multiVersionedGlobal34_4_2")
+// CHECK-SWIFT-5: var multiVersionedGlobal34_4_2_not_5: Int32
diff --git a/test/Constraints/Inputs/disambiguate_iuo_param.h b/test/Constraints/Inputs/disambiguate_iuo_param.h
new file mode 100644
index 0000000..3048018
--- /dev/null
+++ b/test/Constraints/Inputs/disambiguate_iuo_param.h
@@ -0,0 +1,9 @@
+@import Foundation;
+
+@interface NSObject (NSMyTest)
+- (BOOL)isEqualTo:(nullable id)object;
+@end
+
+@interface Obj : NSObject
+- (BOOL)isEqualToObject:(id)value;
+@end
diff --git a/test/Constraints/disambiguate_iuo_param.swift b/test/Constraints/disambiguate_iuo_param.swift
new file mode 100644
index 0000000..85c43f2
--- /dev/null
+++ b/test/Constraints/disambiguate_iuo_param.swift
@@ -0,0 +1,11 @@
+// RUN: %empty-directory(%t)
+// RUN: %build-clang-importer-objc-overlays
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -import-objc-header %S/Inputs/disambiguate_iuo_param.h %s -emit-ir | %FileCheck %s
+// -module-name objc_ir -I %S/Inputs/custom-modules -emit-ir -g -o - -primary-file %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+// CHECK: define {{.*}} @main
+// CHECK: load {{.*}}, {{.*}}@"\01L_selector(isEqualToObject:)"
+let c = Obj()
+_ = c.isEqual(to: c)
diff --git a/test/DebugInfo/DumpDeclFromMangledName.swift b/test/DebugInfo/DumpDeclFromMangledName.swift
new file mode 100644
index 0000000..ae1f221
--- /dev/null
+++ b/test/DebugInfo/DumpDeclFromMangledName.swift
@@ -0,0 +1,28 @@
+// RUN: %empty-directory(%t)
+
+// %t.input: "A ---> B" ==> "A"
+// RUN: sed -ne '/--->/s/ *--->.*$//p' < %S/Inputs/decl-reconstr-names.txt > %t.input
+
+// %t.check: "A ---> B" ==> "B"
+// RUN: sed -ne '/--->/s/^.*---> *//p' < %S/Inputs/decl-reconstr-names.txt > %t.check
+
+// RUN: %target-build-swift -emit-executable %s -g -o %t/DeclReconstr -emit-module
+// RUN: %lldb-moduleimport-test %t/DeclReconstr -target-triple %target-triple \
+// RUN:   -decl-from-mangled=%t.input > %t.output 2>&1
+// RUN: diff %t.check %t.output
+
+// FIXME: rdar://38822524
+// REQUIRES: OS=macosx
+
+// REQUIRES: executable_test
+struct S {
+  init() {
+  }
+}
+
+func patatino() -> Int {
+  let s = S()
+  return 0
+}
+
+patatino()
diff --git a/test/DebugInfo/Inputs/decl-reconstr-names.txt b/test/DebugInfo/Inputs/decl-reconstr-names.txt
new file mode 100644
index 0000000..988e2ad
--- /dev/null
+++ b/test/DebugInfo/Inputs/decl-reconstr-names.txt
@@ -0,0 +1,2 @@
+$S12DeclReconstr8patatinoSiyF ---> func patatino() -> Int
+$S12DeclReconstr1SVACycfC ---> init()
diff --git a/test/DebugInfo/liverange-extension.swift b/test/DebugInfo/liverange-extension.swift
index e7d2bfe..a7ba868 100644
--- a/test/DebugInfo/liverange-extension.swift
+++ b/test/DebugInfo/liverange-extension.swift
@@ -1,27 +1,63 @@
 // RUN: %target-swift-frontend %s -g -emit-ir -o - | %FileCheck %s
 
+// REQUIRES: CPU=x86_64
+//
+// We require x86_64 to make the test easier to read. Without this,
+// writing check lines that ensure our asm gadgets match up with the
+// right values is painfully hard to do.
+
 func use<T>(_ x: T) {}
 
 func getInt32() -> Int32 { return -1 }
 
+// CHECK-LABEL: define {{.*}}rangeExtension
 public func rangeExtension(_ b: Bool) {
-  // CHECK: define {{.*}}rangeExtension
   let i = getInt32()
-  // CHECK: llvm.dbg.value(metadata i32 [[I:.*]], metadata {{.*}}, metadata
+  // CHECK: [[I:%.*]] = call swiftcc i32 @"{{.*}}getInt32
+  // CHECK-NEXT: [[I_ZEXT:%.*]] = zext i32 [[I]] to i64
+  // CHECK-NEXT: call void asm sideeffect "", "r"(i64 [[I_ZEXT]])
+  // CHECK-NEXT: llvm.dbg.value(metadata i32 [[I]], metadata [[MD_I:!.*]], metadata
+
   use(i)
+
+  // CHECK: br i1
+
   if b {
+    // CHECK: llvm.dbg.value(metadata i32 [[I]], metadata [[MD_I]]
+
     let j = getInt32()
-    // CHECK: llvm.dbg.value(metadata i32 [[I]], metadata {{.*}}, metadata
-    // CHECK: llvm.dbg.value(metadata i32 [[J:.*]], metadata {{.*}}, metadata
+    // CHECK: [[J:%.*]] = call swiftcc i32 @"{{.*}}getInt32
+    // CHECK-NEXT: [[J_ZEXT:%.*]] = zext i32 [[J]] to i64
+    // CHECK-NEXT: call void asm sideeffect "", "r"(i64 [[J_ZEXT]])
+    // CHECK: llvm.dbg.value(metadata i32 [[J]], metadata [[MD_J:!.*]], metadata
+
     use(j)
-    // CHECK-DAG: {{(asm sideeffect "", "r".*)|(zext i32)}} [[J]]
-    // CHECK-DAG: asm sideeffect "", "r"
+    // CHECK: call swiftcc void @"{{.*}}use
+
+    // CHECK: [[I_ZEXT:%.*]] = zext i32 [[I]] to i64
+    // CHECK-NEXT: call void asm sideeffect "", "r"(i64 [[I_ZEXT]])
+    // CHECK-NEXT: [[J_ZEXT:%.*]] = zext i32 [[J]] to i64
+    // CHECK-NEXT: call void asm sideeffect "", "r"(i64 [[J_ZEXT]])
+
+    // CHECK: br label
   }
+
+  // CHECK-NOT: llvm.dbg.value(metadata i32 [[J]]
+  // CHECK: llvm.dbg.value(metadata i32 [[I]]
+
   let z = getInt32()
+  // CHECK: [[Z:%.*]] = call swiftcc i32 @"{{.*}}getInt32
+  // CHECK: llvm.dbg.value(metadata i32 [[Z]], metadata [[MD_Z:!.*]], metadata
+
   use(z)
-  // CHECK-NOT: llvm.dbg.value(metadata i32 [[J]], metadata {{.*}}, metadata
-  // CHECK-DAG: llvm.dbg.value(metadata i32 [[I]], metadata {{.*}}, metadata
-  // CHECK-DAG: llvm.dbg.value(metadata i32 [[Z:.*]], metadata {{.*}}, metadata
-  // CHECK-DAG: {{(asm sideeffect "", "r".*)|(zext i32)}} [[I]]
-  // CHECK-DAG: asm sideeffect "", "r"
+  // CHECK: call swiftcc void @"{{.*}}use
+
+  // CHECK: [[I_ZEXT:%.*]] = zext i32 [[I]] to i64
+  // CHECK-NEXT: call void asm sideeffect "", "r"(i64 [[I_ZEXT]])
+  // CHECK-NEXT: [[Z_ZEXT:%.*]] = zext i32 [[Z]] to i64
+  // CHECK-NEXT: call void asm sideeffect "", "r"(i64 [[Z_ZEXT]])
 }
+
+// CHECK-DAG: [[MD_I]] = !DILocalVariable(name: "i"
+// CHECK-DAG: [[MD_J]] = !DILocalVariable(name: "j"
+// CHECK-DAG: [[MD_Z]] = !DILocalVariable(name: "z"
diff --git a/test/DebugInfo/vector.swift b/test/DebugInfo/vector.swift
index d83ee8c..cffef62 100644
--- a/test/DebugInfo/vector.swift
+++ b/test/DebugInfo/vector.swift
@@ -14,7 +14,7 @@
     get {
       let elt = Builtin.extractelement_Vec2xFPIEEE32_Int32(_vector,
         Int32(index)._value)
-      return Float(_bits: elt)
+      return Float(elt)
     }
   }
 }
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index 5b95a43..7f574cd 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -82,12 +82,12 @@
 _TTOFSC3fooFTSdSd_Sd ---> {T:_TFSC3fooFTSdSd_Sd} @nonobjc __C_Synthesized.foo(Swift.Double, Swift.Double) -> Swift.Double
 _T03foo3barC3basyAA3zimCAE_tFTo ---> {T:_T03foo3barC3basyAA3zimCAE_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
 _T0SC3fooS2d_SdtFTO ---> {T:_T0SC3fooS2d_SdtF} @nonobjc __C_Synthesized.foo(Swift.Double, Swift.Double) -> Swift.Double
-__$S3foo3barC3bas3zimyAaEC_tFTo ---> {T:_$S3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
-__$SSC3fooyS2d_SdtFTO ---> {T:_$SSC3fooyS2d_SdtF} @nonobjc __C_Synthesized.foo(Swift.Double, Swift.Double) -> Swift.Double
+_$s3foo3barC3bas3zimyAaEC_tFTo ---> {T:_$s3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
+_$sSC3fooyS2d_SdtFTO ---> {T:_$sSC3fooyS2d_SdtF} @nonobjc __C_Synthesized.foo(Swift.Double, Swift.Double) -> Swift.Double
 _$S3foo3barC3bas3zimyAaEC_tFTo ---> {T:_$S3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
 _$SSC3fooyS2d_SdtFTO ---> {T:_$SSC3fooyS2d_SdtF} @nonobjc __C_Synthesized.foo(Swift.Double, Swift.Double) -> Swift.Double
-$S3foo3barC3bas3zimyAaEC_tFTo ---> {T:$S3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
-$SSC3fooyS2d_SdtFTO ---> {T:$SSC3fooyS2d_SdtF} @nonobjc __C_Synthesized.foo(Swift.Double, Swift.Double) -> Swift.Double
+_$S3foo3barC3bas3zimyAaEC_tFTo ---> {T:_$S3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
+_$SSC3fooyS2d_SdtFTO ---> {T:_$SSC3fooyS2d_SdtF} @nonobjc __C_Synthesized.foo(Swift.Double, Swift.Double) -> Swift.Double
 _TTDFC3foo3bar3basfT3zimCS_3zim_T_ ---> dynamic foo.bar.bas(zim: foo.zim) -> ()
 _TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas(zim: foo.zim) -> ()
 _TF3foooi1pFTCS_3barVS_3bas_OS_3zim ---> foo.+ infix(foo.bar, foo.bas) -> foo.zim
diff --git a/test/Driver/batch_mode_bridging_pch.swift b/test/Driver/batch_mode_bridging_pch.swift
index e996aca..06cd9b0 100644
--- a/test/Driver/batch_mode_bridging_pch.swift
+++ b/test/Driver/batch_mode_bridging_pch.swift
@@ -5,6 +5,18 @@
 //
 // RUN: %swiftc_driver -enable-bridging-pch -v -import-objc-header %t/foo-bridging-header.h -enable-batch-mode -c -emit-module -module-name main -j 2 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/main.swift %s 2>&1 | %FileCheck %s
 //
+// Next we make a module map with an unknown attribute, which will cause an
+// AST-reader warning while (re)parsing the module map, while attaching a PCH.
+// We turn on serialized diagnostics in the frontends, and check that that
+// warning, issued before the batch-mode multi-file diagnostic multiplexor has
+// its file mappings established, does not crash the multiplexor.
+//
+// RUN: %empty-directory(%t/MyModule)
+// RUN: echo 'module MyModule [DefinitelyNotAnAttribute] { header "header.h" export * }' >%t/MyModule/module.modulemap
+// RUN: touch %t/MyModule/header.h
+// RUN: echo '#include "MyModule/header.h"' >>%t/foo-bridging-header.h
+// RUN: %swiftc_driver -enable-bridging-pch -v -I %t -import-objc-header %t/foo-bridging-header.h -enable-batch-mode -c -emit-module -module-name main -j 2 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/main.swift -serialize-diagnostics %s 2>&1 | %FileCheck %s
+//
 // CHECK: -emit-pch
 // CHECK: -primary-file {{.*}}/file-01.swift -primary-file {{.*}}/file-02.swift
 
diff --git a/test/Driver/swift-version.swift b/test/Driver/swift-version.swift
index 31ed2b4..612592f 100644
--- a/test/Driver/swift-version.swift
+++ b/test/Driver/swift-version.swift
@@ -14,7 +14,7 @@
 // RUN: not %target-swiftc_driver -swift-version 5 -typecheck %s 2>&1 | %FileCheck --check-prefix ERROR_5 %s
 
 // BAD: invalid value
-// BAD: note: valid arguments to '-swift-version' are '3', '4', '5'
+// BAD: note: valid arguments to '-swift-version' are '3', '4', '4.2', '5'
 
 // FIXIT_3: use major version, as in '-swift-version 3'
 // FIXIT_4: use major version, as in '-swift-version 4'
diff --git a/test/Frontend/Inputs/supplementary_output_filemap_missing_a_primary.yaml b/test/Frontend/Inputs/supplementary_output_filemap_missing_a_primary.yaml
new file mode 100644
index 0000000..9c4926f
--- /dev/null
+++ b/test/Frontend/Inputs/supplementary_output_filemap_missing_a_primary.yaml
@@ -0,0 +1,4 @@
+"main.swift":
+  object: "main.o"
+  dependencies: "main.d"
+  diagnostics: "main.dia"
diff --git a/test/Frontend/batch_mode_output_file_map_missing_primary.swift b/test/Frontend/batch_mode_output_file_map_missing_primary.swift
new file mode 100644
index 0000000..fdc9157
--- /dev/null
+++ b/test/Frontend/batch_mode_output_file_map_missing_primary.swift
@@ -0,0 +1,6 @@
+// RUN: %empty-directory(%t)
+// RUN: echo 'print("Hello, World!")' >%t/main.swift
+// RUN: touch %t/file-01.swift
+// RUN: (cd %t && not %target-swift-frontend -parse -primary-file main.swift -primary-file file-01.swift -supplementary-output-file-map %S/Inputs/supplementary_output_filemap_missing_a_primary.yaml >%t/errs.txt 2>&1)
+// RUN: %FileCheck %s <%t/errs.txt
+// CHECK: error: supplementary output file map '{{.*}}supplementary_output_filemap_missing_a_primary.yaml' is missing an entry for 'file-01.swift' (this likely indicates a compiler issue; please file a bug report)
diff --git a/test/IDE/complete_enum_elements.swift b/test/IDE/complete_enum_elements.swift
index 39a2dae..cd8fd57 100644
--- a/test/IDE/complete_enum_elements.swift
+++ b/test/IDE/complete_enum_elements.swift
@@ -66,6 +66,8 @@
 
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=WITH_INVALID_DOT_1 | %FileCheck %s -check-prefix=WITH_INVALID_DOT
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_1 | %FileCheck %s -check-prefix=UNRESOLVED_1
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_2 | %FileCheck %s -check-prefix=UNRESOLVED_2
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_3 | %FileCheck %s -check-prefix=UNRESOLVED_3
 
 //===---
 //===--- Test that we can complete enum elements.
@@ -381,3 +383,16 @@
 // UNRESOLVED_1-DAG:  Decl[EnumElement]/ExprSpecific:     Qux2[#QuxEnum#]; name=Qux2
 // UNRESOLVED_1-NOT:  Okay
 }
+
+func testUnqualified1(x: QuxEnum) {
+  _ = x == .Qux1 || x == .#^UNRESOLVED_2^#Qux2
+  // UNRESOLVED_2: Begin completions, 2 items
+  // UNRESOLVED_2-DAG: Decl[EnumElement]/ExprSpecific:     Qux1[#QuxEnum#]; name=Qux1
+  // UNRESOLVED_2-DAG: Decl[EnumElement]/ExprSpecific:     Qux2[#QuxEnum#]; name=Qux2
+  // UNRESOLVED_2: End completions
+
+  _ = (x == .Qux1#^UNRESOLVED_3^#)
+  // UNRESOLVED_3: Begin completions
+  // UNRESOLVED_3: End completions
+
+}
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index e6e49be..4d43183 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -323,7 +323,7 @@
 // CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, [[INT]] {{60|96}}, [[INT]] 4)
 // CHECK:             [[T0:%.*]] = call swiftcc %swift.metadata_response @"$S16resilient_struct4SizeVMa"([[INT]] 0)
 // CHECK-NEXT:        [[SIZE_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
-// CHECK:             call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 3, {{.*}})
+// CHECK:             call void @swift_initClassMetadata(%swift.type* [[METADATA]], [[INT]] 0, [[INT]] 3, {{.*}})
 // CHECK-native:      [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{12|15}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
@@ -341,7 +341,7 @@
 // CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, [[INT]] {{60|96}}, [[INT]] 3)
 // CHECK:             [[T0:%.*]] = call swiftcc %swift.metadata_response @"$S16resilient_struct9RectangleVMa"([[INT]] 0)
 // CHECK-NEXT:        [[RECTANGLE_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
-// CHECK:             call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 2, {{.*}})
+// CHECK:             call void @swift_initClassMetadata(%swift.type* [[METADATA]], [[INT]] 0, [[INT]] 2, {{.*}})
 // CHECK-native:      [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{11|14}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
@@ -369,7 +369,7 @@
 // CHECK:              [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience14ResilientChildCMo", i32 0, i32 0)
 // CHECK:              [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{12|24}}
 
-// CHECK:              call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 1, i8*** {{.*}}, [[INT]]* {{.*}})
+// CHECK:              call void @swift_initClassMetadata(%swift.type* [[METADATA]], [[INT]] 0, [[INT]] 1, i8*** {{.*}}, [[INT]]* {{.*}})
 
 // Initialize constructor vtable override...
 // CHECK:              [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
@@ -452,5 +452,5 @@
 // CHECK:              [[SUPER_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
 // CHECK:              store %swift.type* [[SUPER]], %swift.type** [[SUPER_ADDR]],
 
-// CHECK:              call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]],
+// CHECK:              call void @swift_initClassMetadata(%swift.type* [[METADATA]], [[INT]] 0,
 // CHECK:              ret %swift.metadata_response zeroinitializer
diff --git a/test/IRGen/concrete_inherits_generic_base.swift b/test/IRGen/concrete_inherits_generic_base.swift
index 2589619..f952ecb 100644
--- a/test/IRGen/concrete_inherits_generic_base.swift
+++ b/test/IRGen/concrete_inherits_generic_base.swift
@@ -80,6 +80,6 @@
 // CHECK:         [[TMP:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
 // CHECK-NEXT:    store %swift.type* [[TMP]], %swift.type** getelementptr inbounds ({{.*}} @"$S3foo12SuperDerivedCMf{{.*}}, i32 1), align
 // CHECK:         [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, [[INT]] {{60|96}}, [[INT]] 0)
-// CHECK:         call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 0, {{.*}})
+// CHECK:         call void @swift_initClassMetadata(%swift.type* [[METADATA]], [[INT]] 0, {{.*}})
 // CHECK:         store atomic %swift.type* [[METADATA]], %swift.type** @"$S3foo12SuperDerivedCML" release,
 // CHECK:         ret void
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index e629e9c..7e90ee2 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -1,6 +1,9 @@
 
 // RUN: %empty-directory(%t)
 // RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -emit-ir -enable-resilience -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift | %FileCheck %s --check-prefix=ENUM_RES
+// RUN: %target-swift-frontend -emit-ir -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift | %FileCheck %s --check-prefix=ENUM_NOT_RES
 // RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
 // RUN: %target-swift-frontend -module-name enum_resilience -I %t -emit-ir -enable-resilience %s | %FileCheck %s -DINT=i%target-ptrsize
 // RUN: %target-swift-frontend -module-name enum_resilience -I %t -emit-ir -enable-resilience -O %s
@@ -8,6 +11,16 @@
 import resilient_enum
 import resilient_struct
 
+// ENUM_RES: @"$S14resilient_enum6MediumO8PamphletyA2CcACmFWC" = {{.*}}constant i32 0
+// ENUM_RES: @"$S14resilient_enum6MediumO8PostcardyAC0A7_struct4SizeVcACmFWC" = {{.*}}constant i32 1
+// ENUM_RES: @"$S14resilient_enum6MediumO5PaperyA2CmFWC" = {{.*}}constant i32 2
+// ENUM_RES: @"$S14resilient_enum6MediumO6CanvasyA2CmFWC" = {{.*}}constant i32 3
+
+// ENUM_NOT_RES-NOT: @"$S14resilient_enum6MediumO8PamphletyA2CcACmFWC" =
+// ENUM_NOT_RES-NOT: @"$S14resilient_enum6MediumO8PostcardyAC0A7_struct4SizeVcACmFWC" =
+// ENUM_NOT_RES-NOT: @"$S14resilient_enum6MediumO5PaperyA2CmFWC" =
+// ENUM_NOT_RES-NOT: @"$S14resilient_enum6MediumO6CanvasyA2CmFWC" =
+
 // CHECK: %T15enum_resilience5ClassC = type <{ %swift.refcounted }>
 // CHECK: %T15enum_resilience9ReferenceV = type <{ %T15enum_resilience5ClassC* }>
 
diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil
index 7b13979..882b84d 100644
--- a/test/IRGen/generic_classes.sil
+++ b/test/IRGen/generic_classes.sil
@@ -345,7 +345,7 @@
 // CHECK-LABEL: define{{( protected)?}} internal swiftcc %swift.metadata_response @"$S15generic_classes11RootGenericCMr"
 // CHECK-SAME:    (%swift.type* [[METADATA:%.*]], i8*, i8**) {{.*}} {
 // -- initialize the dependent field offsets
-// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
+// CHECK:   call void @swift_initClassMetadata(%swift.type* [[METADATA]], i64 0, i64 3, i8*** {{%.*}}, i64* {{%.*}})
 // CHECK: }
 
 // CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S15generic_classes22RootGenericFixedLayoutCMi"(%swift.type_descriptor*, i8**, i8**) {{.*}} {
@@ -353,7 +353,7 @@
 
 // CHECK-LABEL: define{{( protected)?}} internal swiftcc %swift.metadata_response @"$S15generic_classes22RootGenericFixedLayoutCMr"
 // CHECK-SAME:    (%swift.type* [[METADATA:%.*]], i8*, i8**) {{.*}} {
-// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
+// CHECK:   call void @swift_initClassMetadata(%swift.type* [[METADATA]], i64 0, i64 3, i8*** {{%.*}}, i64* {{%.*}})
 // CHECK: }
 
 // CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S15generic_classes015GenericInheritsC0CMi"(%swift.type_descriptor*, i8**, i8**) {{.*}} {
@@ -383,7 +383,7 @@
 // CHECK:   [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
 // CHECK:   [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 0
 // CHECK:   store i8** [[T0]], i8*** [[T1]], align 8
-// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 1, i8*** [[FIELDS_ADDR]], i64* [[OFFSETS]])
+// CHECK:   call void @swift_initClassMetadata(%swift.type* [[METADATA]], i64 0, i64 1, i8*** [[FIELDS_ADDR]], i64* [[OFFSETS]])
 // CHECK:   ret %swift.metadata_response zeroinitializer
 // CHECK: }
 
diff --git a/test/IRGen/generic_vtable.swift b/test/IRGen/generic_vtable.swift
index c0febd8..f4a2520 100644
--- a/test/IRGen/generic_vtable.swift
+++ b/test/IRGen/generic_vtable.swift
@@ -108,7 +108,7 @@
 
 // CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$S14generic_vtable7DerivedCMr"
 // CHECK-SAME:    (%swift.type* [[METADATA:%.*]], i8*, i8**) {{.*}} {
-// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
+// CHECK: call void @swift_initClassMetadata(%swift.type* [[METADATA]], i64 0, {{.*}})
 
 // -- method override for 'm2()'
 // CHECK: [[WORDS:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
@@ -131,7 +131,7 @@
 // CHECK: [[SUPERCLASS:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
 // CHECK: store %swift.type* [[SUPERCLASS]], %swift.type** getelementptr inbounds {{.*}} @"$S14generic_vtable8ConcreteCMf"
 // CHECK: [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, i64 96, i64 1)
-// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
+// CHECK: call void @swift_initClassMetadata(%swift.type* [[METADATA]], i64 0, {{.*}})
 
 // -- method override for 'init()'
 // CHECK: store i8* bitcast (%T14generic_vtable8ConcreteC* (%T14generic_vtable8ConcreteC*)* @"$S14generic_vtable8ConcreteCACycfc" to i8*), i8**
diff --git a/test/IRGen/mixed_mode_class_with_unimportable_fields.swift b/test/IRGen/mixed_mode_class_with_unimportable_fields.swift
index 5198616..9bf183e 100644
--- a/test/IRGen/mixed_mode_class_with_unimportable_fields.swift
+++ b/test/IRGen/mixed_mode_class_with_unimportable_fields.swift
@@ -67,8 +67,8 @@
 }
 
 // CHECK-V3-LABEL: define private void @initialize_metadata_SubButtHolder
-// CHECK-V3:   call void @swift_initClassMetadata_UniversalStrategy
+// CHECK-V3:   call void @swift_initClassMetadata(
 
 // CHECK-V3-LABEL: define private void @initialize_metadata_SubSubButtHolder
-// CHECK-V3:   call void @swift_initClassMetadata_UniversalStrategy
+// CHECK-V3:   call void @swift_initClassMetadata(
 
diff --git a/test/IRGen/objc_class_export.swift.tmp b/test/IRGen/objc_class_export.swift.tmp
deleted file mode 100644
index e2766f6..0000000
--- a/test/IRGen/objc_class_export.swift.tmp
+++ /dev/null
@@ -1,107 +0,0 @@
-// RUN: %empty-directory(%t)
-// RUN: %build-irgen-test-overlays
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -sdk %S/Inputs -I %t -primary-file %s -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s
-
-// REQUIRES: CPU=x86_64
-// REQUIRES: objc_interop
-
-// CHECK: %swift.refcounted = type
-// CHECK: [[HOOZIT:%T17objc_class_export6HoozitC]] = type <{ [[REF:%swift.refcounted]] }>
-// CHECK: [[FOO:%T17objc_class_export3FooC]] = type <{ [[REF]], %TSi }>
-// CHECK: [[INT:%TSi]] = type <{ i64 }>
-// CHECK: [[DOUBLE:%TSd]] = type <{ double }>
-// CHECK: [[NSRECT:%TSC6NSRectV]] = type <{ %TSC7NSPointV, %TSC6NSSizeV }>
-// CHECK: [[NSPOINT:%TSC7NSPointV]] = type <{ %TSd, %TSd }>
-// CHECK: [[NSSIZE:%TSC6NSSizeV]] = type <{ %TSd, %TSd }>
-// CHECK: [[OBJC:%objc_object]] = type opaque
-
-// CHECK: @"OBJC_METACLASS_$__TtC17objc_class_export3Foo" = hidden global %objc_class {
-// CHECK:   %objc_class* @"OBJC_METACLASS_$__TtCs12_SwiftObject",
-// CHECK:   %objc_class* @"OBJC_METACLASS_$__TtCs12_SwiftObject",
-// CHECK:   %swift.opaque* @_objc_empty_cache,
-// CHECK:   %swift.opaque* null,
-// CHECK:   i64 ptrtoint ({{.*}}* @_METACLASS_DATA__TtC17objc_class_export3Foo to i64)
-// CHECK: }
-// CHECK: [[FOO_NAME:@.*]] = private unnamed_addr constant [28 x i8] c"_TtC17objc_class_export3Foo\00"
-// CHECK: @_METACLASS_DATA__TtC17objc_class_export3Foo = private constant {{.*\*}} } {
-// CHECK:   i32 129,
-// CHECK:   i32 40,
-// CHECK:   i32 40,
-// CHECK:   i32 0,
-// CHECK:   i8* null,
-// CHECK:   i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* [[FOO_NAME]], i64 0, i64 0),
-// CHECK:   @_CLASS_METHODS__TtC17objc_class_export3Foo,
-// CHECK:   i8* null,
-// CHECK:   i8* null,
-// CHECK:   i8* null,
-// CHECK:   i8* null
-// CHECK: }, section "__DATA, __objc_const", align 8
-// CHECK: @_DATA__TtC17objc_class_export3Foo = private constant {{.*\*}} } {
-// CHECK:   i32 128,
-// CHECK:   i32 16,
-// CHECK:   i32 24,
-// CHECK:   i32 0,
-// CHECK:   i8* null,
-// CHECK:   i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* [[FOO_NAME]], i64 0, i64 0),
-// CHECK:   { i32, i32, [6 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS__TtC17objc_class_export3Foo,
-// CHECK:   i8* null,
-// CHECK:   @_IVARS__TtC17objc_class_export3Foo,
-// CHECK:   i8* null,
-// CHECK:   _PROPERTIES__TtC17objc_class_export3Foo
-// CHECK: }, section "__DATA, __objc_const", align 8
-// CHECK: @"$S17objc_class_export3FooCMf" = internal global <{{.*i64}} }> <{
-// CHECK:   void ([[FOO]]*)* @"$S17objc_class_export3FooCfD",
-// CHECK:   i8** @"$SBOWV",
-// CHECK:   i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC17objc_class_export3Foo" to i64),
-// CHECK:   %objc_class* @"OBJC_CLASS_$__TtCs12_SwiftObject",
-// CHECK:   %swift.opaque* @_objc_empty_cache,
-// CHECK:   %swift.opaque* null,
-// CHECK:   i64 add (i64 ptrtoint ({{.*}}* @_DATA__TtC17objc_class_export3Foo to i64), i64 1),
-// CHECK:   [[FOO]]* (%swift.type*)* @"$S17objc_class_export3FooC6createACyFZ",
-// CHECK:   void (double, double, double, double, [[FOO]]*)* @"$S17objc_class_export3FooC10drawInRect5dirtyySC6NSRectV_tF"
-// CHECK: }>, section "__DATA,__objc_data, regular"
-// -- TODO: The OBJC_CLASS symbol should reflect the qualified runtime name of
-//    Foo.
-// CHECK: @"$S17objc_class_export3FooCN" = hidden alias %swift.type, bitcast (i64* getelementptr inbounds ({{.*}} @"$S17objc_class_export3FooCMf", i32 0, i32 2) to %swift.type*)
-// CHECK: @"OBJC_CLASS_$__TtC17objc_class_export3Foo" = hidden alias %swift.type, %swift.type* @"$S17objc_class_export3FooCN"
-
-import gizmo
-
-class Hoozit {}
-
-struct BigStructWithNativeObjects {
-  var x, y, w : Double
-  var h : Hoozit
-}
-
-@objc class Foo {
-  @objc var x = 0
-  @objc class func create() -> Foo {
-    return Foo()
-  }
-
-  @objc func drawInRect(dirty dirty: NSRect) {
-  }
-  // CHECK: define internal void @"$S17objc_class_export3FooC10drawInRectySC6NSRectV5dirty_tFTo"([[OPAQUE:%.*]]*, i8*, [[NSRECT]]* byval align 8) unnamed_addr {{.*}} {
-  // CHECK:   [[CAST:%[a-zA-Z0-9]+]] = bitcast [[OPAQUE]]* %0 to [[FOO]]*
-  // CHECK:   call swiftcc void @"$S17objc_class_export3FooC10drawInRectySC6NSRectV5dirty_tF"(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [[FOO]]* swiftself [[CAST]])
-  // CHECK: }
-
-  @objc func bounds() -> NSRect {
-    return NSRect(origin: NSPoint(x: 0, y: 0),
-                  size: NSSize(width: 0, height: 0))
-  }
-  // CHECK: define internal void @"$S17objc_class_export3FooC6boundsSC6NSRectVyFTo"([[NSRECT]]* noalias nocapture sret, [[OPAQUE4:%.*]]*, i8*) unnamed_addr {{.*}} {
-  // CHECK:   [[CAST:%[a-zA-Z0-9]+]] = bitcast [[OPAQUE4]]* %1 to [[FOO]]*
-  // CHECK:   call swiftcc { double, double, double, double } @"$S17objc_class_export3FooC6boundsSC6NSRectVyF"([[FOO]]* swiftself [[CAST]])
-
-  @objc func convertRectToBacking(r r: NSRect) -> NSRect {
-    return r
-  }
-  // CHECK: define internal void @"$S17objc_class_export3FooC20convertRectToBackingSC6NSRectVAF1r_tFTo"([[NSRECT]]* noalias nocapture sret, [[OPAQUE5:%.*]]*, i8*, [[NSRECT]]* byval align 8) unnamed_addr {{.*}} {
-  // CHECK:   [[CAST:%[a-zA-Z0-9]+]] = bitcast [[OPAQUE5]]* %1 to [[FOO]]*
-  // CHECK:   call swiftcc { double, double, double, double } @"$S17objc_class_export3FooC20convertRectToBackingSC6NSRectVAF1r_tF"(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [[FOO]]* swiftself [[CAST]])
-
-  func doStuffToSwiftSlice(f f: [Int]) {
-  }
-  // This function is not representable in Objective-C, so don't emit the objc entry point.
diff --git a/test/IRGen/property_descriptor.sil b/test/IRGen/property_descriptor.sil
new file mode 100644
index 0000000..75c25a3
--- /dev/null
+++ b/test/IRGen/property_descriptor.sil
@@ -0,0 +1,138 @@
+// RUN: %empty-directory(%t)
+// RUN: %utils/chex.py < %s > %t/property_descriptor.sil
+// RUN: %target-swift-frontend -emit-ir %t/property_descriptor.sil | %FileCheck --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK %t/property_descriptor.sil
+
+sil_stage canonical
+
+import Swift
+
+public struct ExternalGeneric<T: Comparable> {
+  public let ro: T
+  public var rw: T
+
+  public var computedRO: T { get }
+  public var computedRW: T { get set }
+
+  public subscript<U: Hashable>(_: U) -> T { get set }
+
+  init()
+}
+
+public struct External {
+  public let ro: Int
+  public var rw: Int
+
+  public var computedRO: Int { get }
+  public var computedRW: Int { get set }
+
+  public subscript(_: String) -> Int { get set }
+
+  init()
+}
+
+public struct ExternalReabstractions<T> {
+  public var ro: T
+  public var reabstracted: () -> ()
+}
+
+// -- 0xff_fffe - struct property, offset resolved from field offset vector in metadata
+// CHECK-64: @"$S19property_descriptor15ExternalGenericV2roxvpMV" ={{( protected)?}}{{( protected)?}} constant
+// CHECK-64-SAME: <{ <i32 0x00ff_fffe>, i32 32 }>, align 8
+// CHECK-32: @"$S19property_descriptor15ExternalGenericV2roxvpMV" ={{( protected)?}}{{( protected)?}} constant
+// CHECK-32-SAME: <{ <i32 0x00ff_fffe>, i32 16 }>, align 4
+sil_property #ExternalGeneric.ro <T: Comparable> (
+  stored_property #ExternalGeneric.ro : $T)
+// CHECK-64: @"$S19property_descriptor15ExternalGenericV2rwxvpMV" ={{( protected)?}}{{( protected)?}} constant
+// CHECK-64-SAME: <{ <i32 0x00ff_fffe>, i32 40 }>, align 8
+// CHECK-32: @"$S19property_descriptor15ExternalGenericV2rwxvpMV" ={{( protected)?}} constant
+// CHECK-32-SAME: <{ <i32 0x00ff_fffe>, i32 20 }>, align 4
+sil_property #ExternalGeneric.rw <T: Comparable> (
+  stored_property #ExternalGeneric.rw : $T)
+
+// CHECK: @"$S19property_descriptor15ExternalGenericV10computedROxvpMV" ={{( protected)?}} constant
+// -- 0x0108_0000 - computed, readonly, has arguments
+// CHECK-SAME:  <{ <i32 0x0108_0000>,
+// CHECK-SAME:     @id_computed, 
+// CHECK-SAME:     [[GET_COMPUTEDRO:@keypath_get[.0-9]*]],
+// CHECK-SAME:     [[GET_ARG_LAYOUT_COMPUTEDRO:@keypath_get_arg_layout[.0-9]*]],
+// CHECK-SAME:     @swift_keyPathGenericWitnessTable,
+// CHECK-SAME:     [[ARG_INIT_COMPUTEDRO:@keypath_arg_init[.0-9]*]] }>
+sil_property #ExternalGeneric.computedRO <T: Comparable> (
+  gettable_property $T,
+    id @id_computed : $@convention(thin) () -> (),
+    getter @get_computed_generic : $@convention(thin) <T: Comparable> (@in_guaranteed ExternalGeneric<T>) -> @out T)
+
+// CHECK: @"$S19property_descriptor15ExternalGenericV10computedRWxvpMV" ={{( protected)?}} constant
+// -- 0x01c8_0000 - computed, settable, mutating, has arguments
+// CHECK-SAME:  <{ <i32 0x01c8_0000>, 
+// CHECK-SAME:     @id_computed,
+// CHECK-SAME:     [[GET_COMPUTEDRW:@keypath_get[.0-9]*]],
+// CHECK-SAME:     [[SET_COMPUTEDRW:@keypath_set[.0-9]*]],
+// CHECK-SAME:     [[GET_ARG_LAYOUT_COMPUTEDRW:@keypath_get_arg_layout[.0-9]*]],
+// CHECK-SAME:     @swift_keyPathGenericWitnessTable,
+// CHECK-SAME:     [[ARG_INIT_COMPUTEDRW:@keypath_arg_init[.0-9]*]] }>
+sil_property #ExternalGeneric.computedRW <T: Comparable> (
+  settable_property $T,
+    id @id_computed : $@convention(thin) () -> (),
+    getter @get_computed_generic : $@convention(thin) <T: Comparable> (@in_guaranteed ExternalGeneric<T>) -> @out T,
+    setter @set_computed_generic : $@convention(thin) <T: Comparable> (@in_guaranteed T, @inout ExternalGeneric<T>) -> ())
+
+// CHECK: @"$S19property_descriptor15ExternalGenericVyxqd__cs8HashableRd__luipMV" ={{( protected)?}} constant
+// -- 0x01c8_0000 - computed, settable, mutating, has arguments
+// CHECK-SAME:  <{ <i32 0x01c8_0000>, 
+// CHECK-SAME:     @id_computed,
+// CHECK-SAME:     [[GET_SUBSCRIPT:@keypath_get[.0-9]*]],
+// CHECK-SAME:     [[SET_SUBSCRIPT:@keypath_set[.0-9]*]],
+// CHECK-SAME:     [[GET_ARG_LAYOUT_SUBSCRIPT:@keypath_get_arg_layout[.0-9]*]],
+// CHECK-SAME:     @swift_keyPathGenericWitnessTable,
+// CHECK-SAME:     [[ARG_INIT_SUBSCRIPT:@keypath_arg_init[.0-9]*]] }>
+sil_property #ExternalGeneric.subscript <T: Comparable><U: Hashable> (
+  settable_property $T,
+    id @id_computed : $@convention(thin) () -> (),
+    getter @get_computed_generic_subscript : $@convention(thin) <T: Comparable><U: Hashable> (@in_guaranteed ExternalGeneric<T>, UnsafeRawPointer) -> @out T,
+    setter @set_computed_generic_subscript : $@convention(thin) <T: Comparable><U: Hashable> (@in_guaranteed T, @inout ExternalGeneric<T>, UnsafeRawPointer) -> ())
+
+// CHECK: @"$S19property_descriptor8ExternalV2roSivpMV" ={{( protected)?}} constant <{ i32 }> zeroinitializer, align 4
+// CHECK-64: @"$S19property_descriptor8ExternalV2rwSivpMV" ={{( protected)?}} constant <{ i32 }> <{ i32 8 }>, align 4
+// CHECK-32: @"$S19property_descriptor8ExternalV2rwSivpMV" ={{( protected)?}} constant <{ i32 }> <{ i32 4 }>, align 4
+sil_property #External.ro (stored_property #External.ro : $Int)
+sil_property #External.rw (stored_property #External.rw : $Int)
+sil_property #External.computedRO (
+  gettable_property $Int,
+    id @id_computed : $@convention(thin) () -> (),
+    getter @get_computed : $@convention(thin) (@in_guaranteed External) -> @out Int)
+sil_property #External.computedRW (
+  settable_property $Int,
+    id @id_computed : $@convention(thin) () -> (),
+    getter @get_computed : $@convention(thin) (@in_guaranteed External) -> @out Int,
+    setter @set_computed : $@convention(thin) (@in_guaranteed Int, @inout External) -> ())
+sil_property #External.subscript (
+  settable_property $Int,
+    id @id_computed : $@convention(thin) () -> (),
+    getter @get_computed_subscript : $@convention(thin) (@in_guaranteed External, UnsafeRawPointer) -> @out Int,
+    setter @set_computed_subscript : $@convention(thin) (@in_guaranteed Int, @inout External, UnsafeRawPointer) -> ())
+
+sil_property #ExternalReabstractions.ro <T> (
+  stored_property #ExternalReabstractions.ro : $T)
+
+sil_property #ExternalReabstractions.reabstracted <T> (
+  settable_property $() -> (),
+    id ##ExternalReabstractions.reabstracted,
+    getter @get_reabstracted : $@convention(thin) <T> (@in_guaranteed ExternalReabstractions<T>) -> @out @callee_guaranteed (@in_guaranteed ()) -> @out (),
+    setter @set_reabstracted : $@convention(thin) <T> (@in_guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out (), @inout ExternalReabstractions<T>) -> ())
+
+sil @id_computed : $@convention(thin) () -> ()
+sil @get_computed : $@convention(thin) (@in_guaranteed External) -> @out Int
+sil @set_computed : $@convention(thin) (@in_guaranteed Int, @inout External) -> ()
+
+sil @get_computed_subscript : $@convention(thin) (@in_guaranteed External, UnsafeRawPointer) -> @out Int
+sil @set_computed_subscript : $@convention(thin) (@in_guaranteed Int, @inout External, UnsafeRawPointer) -> ()
+
+sil @get_computed_generic : $@convention(thin) <T: Comparable> (@in_guaranteed ExternalGeneric<T>) -> @out T
+sil @set_computed_generic : $@convention(thin) <T: Comparable> (@in_guaranteed T, @inout ExternalGeneric<T>) -> ()
+
+sil @get_computed_generic_subscript : $@convention(thin) <T: Comparable><U: Hashable> (@in_guaranteed ExternalGeneric<T>, UnsafeRawPointer) -> @out T
+sil @set_computed_generic_subscript : $@convention(thin) <T: Comparable><U: Hashable> (@in_guaranteed T, @inout ExternalGeneric<T>, UnsafeRawPointer) -> ()
+
+sil @get_reabstracted : $@convention(thin) <T> (@in_guaranteed ExternalReabstractions<T>) -> @out @callee_guaranteed (@in_guaranteed ()) -> @out ()
+sil @set_reabstracted : $@convention(thin) <T> (@in_guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out (), @inout ExternalReabstractions<T>) -> ()
diff --git a/test/IRGen/protocol_metadata.swift b/test/IRGen/protocol_metadata.swift
index 106d0ff..7d182f4 100644
--- a/test/IRGen/protocol_metadata.swift
+++ b/test/IRGen/protocol_metadata.swift
@@ -47,9 +47,9 @@
 // CHECK-SAME: @_PROTOCOL_METHOD_TYPES__TtP17protocol_metadata1O_
 // CHECK-SAME: }
 
-// CHECK: [[A_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0 }]
-// CHECK: [[B_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0 }]
-// CHECK: [[C_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0 }]
+// CHECK: [[A_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
+// CHECK: [[B_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
+// CHECK: [[C_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
 
 // -- @objc protocol OPT uses ObjC symbol mangling and layout
 // CHECK: @_PROTOCOL__TtP17protocol_metadata3OPT_ = private constant { {{.*}} i32, [4 x i8*]*, i8*, i8* } {
@@ -67,7 +67,7 @@
 // CHECK:   %swift.protocol* @"$S17protocol_metadata1AMp",
 // CHECK:   %swift.protocol* @"$S17protocol_metadata1BMp"
 // CHECK: }
-// CHECK: [[AB_REQTS:@.*]] = internal unnamed_addr constant [3 x %swift.protocol_requirement] [%swift.protocol_requirement zeroinitializer, %swift.protocol_requirement zeroinitializer, %swift.protocol_requirement { i32 17, i32 0 }]
+// CHECK: [[AB_REQTS:@.*]] = internal unnamed_addr constant [3 x %swift.protocol_requirement] [%swift.protocol_requirement zeroinitializer, %swift.protocol_requirement zeroinitializer, %swift.protocol_requirement { i32 17, i32 0, i32 0 }]
 // CHECK: @"$S17protocol_metadata2ABMp" = hidden constant %swift.protocol { 
 // CHECK-SAME:   [[AB_INHERITED]]
 // CHECK-SAME:   i32 72, i32 7,
@@ -92,17 +92,17 @@
 }
 
 // CHECK: [[COMPREHENSIVE_REQTS:@.*]] = internal unnamed_addr constant [11 x %swift.protocol_requirement]
-// CHECK-SAME:  [%swift.protocol_requirement { i32 6, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 7, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 2, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 17, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 1, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 19, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 20, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 21, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 3, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 4, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 5, i32 0 }]
+// CHECK-SAME:  [%swift.protocol_requirement { i32 6, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 7, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 2, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 17, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 1, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 19, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 20, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 21, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 3, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 4, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 5, i32 0, i32 0 }]
 
 // CHECK: [[COMPREHENSIVE_ASSOC_NAME:@.*]] = private constant [6 x i8] c"Assoc\00"
 
diff --git a/test/IRGen/protocol_resilience.sil b/test/IRGen/protocol_resilience.sil
index 58dcacc..38acaaf 100644
--- a/test/IRGen/protocol_resilience.sil
+++ b/test/IRGen/protocol_resilience.sil
@@ -15,13 +15,39 @@
 // Protocol is public -- needs resilient witness table
 
 // CHECK: [[RP_REQTS:@.*]] = internal unnamed_addr constant [8 x %swift.protocol_requirement]
-// CHECK-SAME:  [%swift.protocol_requirement { i32 6, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 7, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 17, i32 0 },
-// CHECK-SAME:   %swift.protocol_requirement { i32 17, i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.opaque*, %swift.type*, i8**)* @defaultC to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 4, i32 1) to [[INT]])){{ | to i32\) }}},
-// CHECK-SAME:   %swift.protocol_requirement { i32 17, i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.opaque*, %swift.type*, i8**)* @defaultD to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 5, i32 1) to [[INT]])){{ | to i32\) }}},
-// CHECK-SAME:   %swift.protocol_requirement { i32 1, i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.type*, %swift.type*, i8**)* @defaultE to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 6, i32 1) to [[INT]])){{ | to i32\) }}},
-// CHECK-SAME:   %swift.protocol_requirement { i32 1, i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.type*, %swift.type*, i8**)* @defaultF to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 7, i32 1) to [[INT]])){{ | to i32\) }}}]
+// CHECK-SAME:  [%swift.protocol_requirement { i32 6, i32 0, i32 0 },
+// CHECK-SAME:   %swift.protocol_requirement { i32 7, i32 0, i32 0 },
+
+// CHECK-SAME:   %swift.protocol_requirement { i32 17,
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.opaque*, %swift.type*, i8**)* @"$S19protocol_resilience17ResilientProtocolP10noDefaultAyyFTj" to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 2, i32 1) to [[INT]])){{,| to i32\),}}
+// CHECK-SAME:     i32 0
+// CHECK-SAME:   },
+
+// CHECK-SAME:   %swift.protocol_requirement { i32 17,
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.opaque*, %swift.type*, i8**)* @"$S19protocol_resilience17ResilientProtocolP10noDefaultByyFTj" to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 3, i32 1) to [[INT]])){{,| to i32\),}}
+// CHECK-SAME:     i32 0
+// CHECK-SAME:   },
+
+// CHECK-SAME:   %swift.protocol_requirement { i32 17,
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.opaque*, %swift.type*, i8**)* @"$S19protocol_resilience17ResilientProtocolP8defaultCyyFTj" to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 4, i32 1) to [[INT]])){{,| to i32\),}}
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.opaque*, %swift.type*, i8**)* @defaultC to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 4, i32 2) to [[INT]])){{ | to i32\) }}
+// CHECK-SAME:   },
+
+// CHECK-SAME:   %swift.protocol_requirement { i32 17,
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.opaque*, %swift.type*, i8**)* @"$S19protocol_resilience17ResilientProtocolP8defaultDyyFTj" to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 5, i32 1) to [[INT]])){{,| to i32\),}}
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.opaque*, %swift.type*, i8**)* @defaultD to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 5, i32 2) to [[INT]])){{ | to i32\) }}
+// CHECK-SAME:   },
+
+// CHECK-SAME:   %swift.protocol_requirement { i32 1,
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.type*, %swift.type*, i8**)* @"$S19protocol_resilience17ResilientProtocolP8defaultEyyFZTj" to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 6, i32 1) to [[INT]])){{,| to i32\),}}
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.type*, %swift.type*, i8**)* @defaultE to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 6, i32 2) to [[INT]])){{ | to i32\) }}
+// CHECK-SAME:   },
+
+// CHECK-SAME:   %swift.protocol_requirement { i32 1,
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.type*, %swift.type*, i8**)* @"$S19protocol_resilience17ResilientProtocolP8defaultFyyFZTj" to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 7, i32 1) to [[INT]])){{,| to i32\),}}
+// CHECK-SAME:     i32{{ | trunc \(i64 }}sub ([[INT]] ptrtoint (void (%swift.type*, %swift.type*, i8**)* @defaultF to [[INT]]), [[INT]] ptrtoint (i32* getelementptr inbounds ([8 x %swift.protocol_requirement], [8 x %swift.protocol_requirement]* [[RP_REQTS]], i32 0, i32 7, i32 2) to [[INT]])){{ | to i32\) }}
+// CHECK-SAME:   }
+// CHECK-SAME: ]
 
 // CHECK: @"$S19protocol_resilience17ResilientProtocolMp" = {{(protected )?}}constant %swift.protocol {
 // CHECK-SAME:   i32 1031,
diff --git a/test/Misc/serialized-diagnostics-batch-mode.swift b/test/Misc/serialized-diagnostics-batch-mode.swift
index 2b25fab..c1ecf6e 100644
--- a/test/Misc/serialized-diagnostics-batch-mode.swift
+++ b/test/Misc/serialized-diagnostics-batch-mode.swift
@@ -19,9 +19,9 @@
 // NEGATIVE-MAIN-NOT: serialized-diagnostics-batch-mode-helper.swift
 // NEGATIVE-HELPER-NOT: serialized-diagnostics-batch-mode.swift
 
-// CHECK-MAIN-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()' 
-// CHECK-HELPER-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()'
-// CHECK-STDERR-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()'
+// NEGATIVE-MAIN-NOT: invalid redeclaration of 'foo()'
+// NEGATIVE-HELPER-NOT: invalid redeclaration of 'foo()'
+// NEGATIVE-STDERR-NOT: invalid redeclaration of 'foo()'
 
 func test() {
   nonexistent() // CHECK-MAIN-DAG: serialized-diagnostics-batch-mode.swift:[[@LINE]]:3: error: use of unresolved identifier 'nonexistent'
diff --git a/test/NameBinding/Inputs/accessibility_other.swift b/test/NameBinding/Inputs/accessibility_other.swift
index 266e439..2193d59 100644
--- a/test/NameBinding/Inputs/accessibility_other.swift
+++ b/test/NameBinding/Inputs/accessibility_other.swift
@@ -26,4 +26,4 @@
 
 private func privateInBothFiles() {}
 func privateInPrimaryFile() {} // expected-note {{previously declared here}}
-private func privateInOtherFile() {} // expected-error {{invalid redeclaration}}
+private func privateInOtherFile() {}
diff --git a/test/NameBinding/accessibility.swift b/test/NameBinding/accessibility.swift
index c8bd2c4..bf1a6b8 100644
--- a/test/NameBinding/accessibility.swift
+++ b/test/NameBinding/accessibility.swift
@@ -126,7 +126,7 @@
 #if !ACCESS_DISABLED
 private func privateInBothFiles() {} // no-warning
 private func privateInPrimaryFile() {} // expected-error {{invalid redeclaration}}
-func privateInOtherFile() {} // expected-note {{previously declared here}}
+func privateInOtherFile() {}
 #endif
 
 
diff --git a/test/Parse/ConditionalCompilation/language_version_explicit.swift b/test/Parse/ConditionalCompilation/language_version_explicit.swift
index 83fd2da..a76963c 100644
--- a/test/Parse/ConditionalCompilation/language_version_explicit.swift
+++ b/test/Parse/ConditionalCompilation/language_version_explicit.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift -swift-version 4
+// RUN: %target-typecheck-verify-swift -swift-version 4.2
 
 #if swift(>=4)
   let w = 1
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index dd3f35f..f50f87f 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -324,40 +324,40 @@
 }
 
 enum DuplicateMembers1 {
-  case Foo // expected-note {{previous definition of 'Foo' is here}}
-  case Foo // expected-error {{duplicate definition of enum element}}
+  case Foo // expected-note {{'Foo' previously declared here}}
+  case Foo // expected-error {{invalid redeclaration of 'Foo'}}
 }
 
 enum DuplicateMembers2 {
-  case Foo, Bar // expected-note {{previous definition of 'Foo' is here}} expected-note {{previous definition of 'Bar' is here}}
-  case Foo // expected-error {{duplicate definition of enum element}}
-  case Bar // expected-error {{duplicate definition of enum element}}
+  case Foo, Bar // expected-note {{'Foo' previously declared here}} expected-note {{'Bar' previously declared here}}
+  case Foo // expected-error {{invalid redeclaration of 'Foo'}}
+  case Bar // expected-error {{invalid redeclaration of 'Bar'}}
 }
 
 enum DuplicateMembers3 {
-  case Foo // expected-note {{previous definition of 'Foo' is here}}
-  case Foo(Int) // expected-error {{duplicate definition of enum element}}
+  case Foo // expected-note {{'Foo' previously declared here}}
+  case Foo(Int) // expected-error {{invalid redeclaration of 'Foo'}}
 }
 
 enum DuplicateMembers4 : Int { // expected-error {{'DuplicateMembers4' declares raw type 'Int', but does not conform to RawRepresentable and conformance could not be synthesized}}
-  case Foo = 1 // expected-note {{previous definition of 'Foo' is here}}
-  case Foo = 2 // expected-error {{duplicate definition of enum element}}
+  case Foo = 1 // expected-note {{'Foo' previously declared here}}
+  case Foo = 2 // expected-error {{invalid redeclaration of 'Foo'}}
 }
 
 enum DuplicateMembers5 : Int { // expected-error {{'DuplicateMembers5' declares raw type 'Int', but does not conform to RawRepresentable and conformance could not be synthesized}}
-  case Foo = 1 // expected-note {{previous definition of 'Foo' is here}}
-  case Foo = 1 + 1 // expected-error {{duplicate definition of enum element}} expected-error {{raw value for enum case must be a literal}}
+  case Foo = 1 // expected-note {{'Foo' previously declared here}}
+  case Foo = 1 + 1 // expected-error {{invalid redeclaration of 'Foo'}} expected-error {{raw value for enum case must be a literal}}
 }
 
 enum DuplicateMembers6 {
-  case Foo // expected-note 2{{previous definition of 'Foo' is here}}
-  case Foo // expected-error {{duplicate definition of enum element}}
-  case Foo // expected-error {{duplicate definition of enum element}}
+  case Foo // expected-note 2{{'Foo' previously declared here}}
+  case Foo // expected-error {{invalid redeclaration of 'Foo'}}
+  case Foo // expected-error {{invalid redeclaration of 'Foo'}}
 }
 
 enum DuplicateMembers7 : String { // expected-error {{'DuplicateMembers7' declares raw type 'String', but does not conform to RawRepresentable and conformance could not be synthesized}}
-  case Foo // expected-note {{previous definition of 'Foo' is here}}
-  case Foo = "Bar" // expected-error {{duplicate definition of enum element}}
+  case Foo // expected-note {{'Foo' previously declared here}}
+  case Foo = "Bar" // expected-error {{invalid redeclaration of 'Foo'}}
 }
 
 // Refs to duplicated enum cases shouldn't crash the compiler.
diff --git a/test/SILGen/keypath_property_descriptors.swift b/test/SILGen/keypath_property_descriptors.swift
index ee63e8e..0d6cb1e 100644
--- a/test/SILGen/keypath_property_descriptors.swift
+++ b/test/SILGen/keypath_property_descriptors.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -enable-key-path-resilience %s | %FileCheck %s
 
 // TODO: globals should get descriptors
 public var a: Int = 0
diff --git a/test/SILOptimizer/pointer_conversion_objc.swift b/test/SILOptimizer/pointer_conversion_objc.swift
index 501d6ad..6c0d6d3 100644
--- a/test/SILOptimizer/pointer_conversion_objc.swift
+++ b/test/SILOptimizer/pointer_conversion_objc.swift
@@ -2,6 +2,7 @@
 
 // REQUIRES: optimized_stdlib
 // REQUIRES: objc_interop
+// REQUIRES: swift_stdlib_asserts
 
 // Opaque, unoptimizable functions to call.
 @_silgen_name("takesConstRawPointer")
diff --git a/test/Sema/type_join.swift b/test/Sema/type_join.swift
index 0a3db86..e3c15d1 100644
--- a/test/Sema/type_join.swift
+++ b/test/Sema/type_join.swift
@@ -34,6 +34,10 @@
 expectEqualType(Builtin.type_join(Any?.self, Any.self), Any?.self)
 expectEqualType(Builtin.type_join(Any.self, Any?.self), Any?.self)
 
+expectEqualType(Builtin.type_join(Builtin.Int1.self, Builtin.Int1.self), Builtin.Int1.self)
+expectEqualType(Builtin.type_join(Builtin.Int32.self, Builtin.Int1.self), Any.self)
+expectEqualType(Builtin.type_join(Builtin.Int1.self, Builtin.Int32.self), Any.self)
+
 func joinFunctions(
   _ escaping: @escaping () -> (),
   _ nonescaping: () -> ()
diff --git a/test/Serialization/Recovery/crash-recovery.swift b/test/Serialization/Recovery/crash-recovery.swift
index e198b5d..c110d97 100644
--- a/test/Serialization/Recovery/crash-recovery.swift
+++ b/test/Serialization/Recovery/crash-recovery.swift
@@ -2,7 +2,7 @@
 // RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules -swift-version 3 %s
 
 // RUN: echo 'import Lib; _ = Sub.disappearingMethod' | not --crash %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -swift-version 3 -disable-deserialization-recovery -Xcc -DBAD - 2>&1 | %FileCheck -check-prefix CHECK-CRASH -check-prefix CHECK-CRASH-3 %s
-// RUN: echo 'import Lib; _ = Sub.disappearingMethod' | not --crash %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -swift-version 4 -disable-deserialization-recovery -Xcc -DBAD - 2>&1 | %FileCheck -check-prefix CHECK-CRASH -check-prefix CHECK-CRASH-4 %s
+// RUN: echo 'import Lib; _ = Sub.disappearingMethod' | not --crash %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -swift-version 4.2 -disable-deserialization-recovery -Xcc -DBAD - 2>&1 | %FileCheck -check-prefix CHECK-CRASH -check-prefix CHECK-CRASH-4 %s
 
 // REQUIRES: objc_interop
 
diff --git a/test/Serialization/Recovery/types-4-to-3.swift b/test/Serialization/Recovery/types-4-to-3.swift
index f1e216f..0610786 100644
--- a/test/Serialization/Recovery/types-4-to-3.swift
+++ b/test/Serialization/Recovery/types-4-to-3.swift
@@ -16,8 +16,8 @@
 func requiresConformance(_: B_RequiresConformance<B_ConformsToProto>) {}
 func requiresConformance(_: B_RequiresConformance<C_RelyOnConformanceImpl.Assoc>) {}
 
-class Sub: Base {} // expected-error {{cannot inherit from class 'Base' (compiled with Swift 4.2) because it has overridable members that could not be loaded in Swift 3.4}}
-class Impl: Proto {} // expected-error {{type 'Impl' cannot conform to protocol 'Proto' (compiled with Swift 4.2) because it has requirements that could not be loaded in Swift 3.4}}
+class Sub: Base {} // expected-error {{cannot inherit from class 'Base' (compiled with Swift 4.1.50) because it has overridable members that could not be loaded in Swift 3.4}}
+class Impl: Proto {} // expected-error {{type 'Impl' cannot conform to protocol 'Proto' (compiled with Swift 4.1.50) because it has requirements that could not be loaded in Swift 3.4}}
 
 #else // TEST
 
diff --git a/test/SourceKit/InterfaceGen/gen_header.swift b/test/SourceKit/InterfaceGen/gen_header.swift
index df66be2..1355970 100644
--- a/test/SourceKit/InterfaceGen/gen_header.swift
+++ b/test/SourceKit/InterfaceGen/gen_header.swift
@@ -9,6 +9,15 @@
 // RUN: diff -u %s.header2.response %t.header2.response
 
 // RUN: echo '#include "header2.h"' > %t.m
-// RUN: %sourcekitd-test -req=interface-gen -header %S/Inputs/header2.h -swift-version=4 -- -fsyntax-only %t.m -I %S/Inputs > %t.header2.swift4.response
+// RUN: %sourcekitd-test -req=interface-gen -header %S/Inputs/header2.h -swift-version=3 -- -fsyntax-only %t.m -I %S/Inputs > %t.header2.response
+// RUN: diff -u %s.header2.response %t.header2.response
+
+// RUN: echo '#include "header2.h"' > %t.m
+// RUN: %sourcekitd-test -req=interface-gen -header %S/Inputs/header2.h -swift-version=4 -pass-version-as-string -- -fsyntax-only %t.m -I %S/Inputs > %t.header2.swift4.response
 // RUN: %FileCheck -input-file %t.header2.swift4.response %s -check-prefix=SWIFT4
 // SWIFT4: public func show_only_for_swift_4()
+
+// RUN: echo '#include "header2.h"' > %t.m
+// RUN: %sourcekitd-test -req=interface-gen -header %S/Inputs/header2.h -swift-version=4 -pass-version-as-string -- -fsyntax-only %t.m -I %S/Inputs > %t.header2.swift4.response
+// RUN: %FileCheck -input-file %t.header2.swift4.response %s -check-prefix=SWIFT4-STR
+// SWIFT4-STR: public func show_only_for_swift_4()
diff --git a/test/api-digester/Inputs/APINotesLeft/APINotesTest.h b/test/api-digester/Inputs/APINotesLeft/APINotesTest.h
index 90d5820..7b33a30 100644
--- a/test/api-digester/Inputs/APINotesLeft/APINotesTest.h
+++ b/test/api-digester/Inputs/APINotesLeft/APINotesTest.h
@@ -1,3 +1,4 @@
+#import <Foundation.h>
 extern int ANTGlobalValue;
 
 @interface NewType
@@ -16,3 +17,7 @@
   -(void) ProtMemberFunc2;
   -(void) ProtMemberFunc3;
 @end
+
+@interface AnimalStatusDescriptor
+- (nonnull AnimalStatusDescriptor *)animalStatusDescriptorByAddingAttributes:(nonnull NSDictionary<NSString*, id> *)attributes;
+@end
diff --git a/test/api-digester/Inputs/APINotesRight/APINotesTest.h b/test/api-digester/Inputs/APINotesRight/APINotesTest.h
index a500614..7e882af 100644
--- a/test/api-digester/Inputs/APINotesRight/APINotesTest.h
+++ b/test/api-digester/Inputs/APINotesRight/APINotesTest.h
@@ -1,3 +1,4 @@
+#import <objc_generics.h>
 extern int ANTGlobalValue;
 
 @interface NewType
@@ -14,3 +15,9 @@
 @protocol ObjcProt
   -(void) ProtMemberFunc;
 @end
+
+typedef NSString * AnimalAttributeName NS_STRING_ENUM;
+
+@interface AnimalStatusDescriptor
+- (nonnull AnimalStatusDescriptor *)animalStatusDescriptorByAddingAttributes:(nonnull NSDictionary<AnimalAttributeName, id> *)attributes;
+@end
diff --git a/test/api-digester/Inputs/cake.swift b/test/api-digester/Inputs/cake.swift
index 4644313..4cf3846 100644
--- a/test/api-digester/Inputs/cake.swift
+++ b/test/api-digester/Inputs/cake.swift
@@ -35,3 +35,5 @@
 public enum Number: Int {
   case one
 }
+
+public func foo3(_ a: [Int: String]) {}
\ No newline at end of file
diff --git a/test/api-digester/Outputs/apinotes-diags.txt b/test/api-digester/Outputs/apinotes-diags.txt
index 9cd3b42..f5f0cb6 100644
--- a/test/api-digester/Outputs/apinotes-diags.txt
+++ b/test/api-digester/Outputs/apinotes-diags.txt
@@ -11,5 +11,6 @@
 APINotesTest(APINotesTest.h): Protocol SwiftTypeWithMethodLeft has been renamed to Protocol SwiftTypeWithMethodRight
 
 /* Type Changes */
+APINotesTest(APINotesTest.h): Func AnimalStatusDescriptor.addingAttributes(_:) has parameter 0 type change from [String : Any] to [AnimalAttributeName : Any]
 
 /* Decl Attribute changes */
diff --git a/test/api-digester/Outputs/apinotes-migrator-gen.json b/test/api-digester/Outputs/apinotes-migrator-gen.json
index 86fd96d..c83b45f 100644
--- a/test/api-digester/Outputs/apinotes-migrator-gen.json
+++ b/test/api-digester/Outputs/apinotes-migrator-gen.json
@@ -2,6 +2,28 @@
   {
     "DiffItemKind": "CommonDiffItem",
     "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+    "LeftComment": "String",
+    "RightUsr": "",
+    "RightComment": "AnimalAttributeName",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
+    "NodeAnnotation": "TypeRewritten",
+    "ChildIndex": "1:0",
+    "LeftUsr": "c:objc(cs)AnimalStatusDescriptor(im)animalStatusDescriptorByAddingAttributes:",
+    "LeftComment": "String",
+    "RightUsr": "",
+    "RightComment": "AnimalAttributeName",
+    "ModuleName": "APINotesTest"
+  },
+  {
+    "DiffItemKind": "CommonDiffItem",
+    "NodeKind": "Function",
     "NodeAnnotation": "GetterToProperty",
     "ChildIndex": "0",
     "LeftUsr": "c:objc(pl)TypeWithMethod(im)getPropertyA",
diff --git a/test/api-digester/Outputs/cake.json b/test/api-digester/Outputs/cake.json
index 4960d67..27e1a01 100644
--- a/test/api-digester/Outputs/cake.json
+++ b/test/api-digester/Outputs/cake.json
@@ -43,6 +43,7 @@
               "kind": "TypeNominal",
               "name": "C0",
               "printedName": "C0<T1, T2, T3>",
+              "usr": "s:4cake2C0C",
               "children": [
                 {
                   "kind": "TypeNominal",
@@ -188,7 +189,8 @@
             {
               "kind": "TypeNominal",
               "name": "S1",
-              "printedName": "S1"
+              "printedName": "S1",
+              "usr": "s:4cake2S1V"
             }
           ]
         }
@@ -249,11 +251,13 @@
                   "kind": "TypeNominal",
                   "name": "Optional",
                   "printedName": "C1?",
+                  "usr": "s:Sq",
                   "children": [
                     {
                       "kind": "TypeNominal",
                       "name": "C1",
-                      "printedName": "C1"
+                      "printedName": "C1",
+                      "usr": "s:4cake2C1C"
                     }
                   ]
                 }
@@ -277,11 +281,13 @@
                   "kind": "TypeNominal",
                   "name": "Optional",
                   "printedName": "C1?",
+                  "usr": "s:Sq",
                   "children": [
                     {
                       "kind": "TypeNominal",
                       "name": "C1",
-                      "printedName": "C1"
+                      "printedName": "C1",
+                      "usr": "s:4cake2C1C"
                     }
                   ]
                 }
@@ -316,7 +322,8 @@
                 {
                   "kind": "TypeNominal",
                   "name": "C1",
-                  "printedName": "C1"
+                  "printedName": "C1",
+                  "usr": "s:4cake2C1C"
                 }
               ]
             },
@@ -337,7 +344,8 @@
                 {
                   "kind": "TypeNominal",
                   "name": "C1",
-                  "printedName": "C1"
+                  "printedName": "C1",
+                  "usr": "s:4cake2C1C"
                 }
               ]
             }
@@ -355,7 +363,8 @@
             {
               "kind": "TypeNominal",
               "name": "C1",
-              "printedName": "C1"
+              "printedName": "C1",
+              "usr": "s:4cake2C1C"
             }
           ]
         }
@@ -379,12 +388,14 @@
           "kind": "TypeNominal",
           "name": "Int",
           "printedName": "Int",
-          "hasDefaultArg": true
+          "hasDefaultArg": true,
+          "usr": "s:Si"
         },
         {
           "kind": "TypeNominal",
           "name": "S1",
-          "printedName": "S1"
+          "printedName": "S1",
+          "usr": "s:4cake2S1V"
         }
       ]
     },
@@ -406,12 +417,50 @@
           "kind": "TypeNominal",
           "name": "Int",
           "printedName": "Int",
-          "hasDefaultArg": true
+          "hasDefaultArg": true,
+          "usr": "s:Si"
         },
         {
           "kind": "TypeNominal",
           "name": "S1",
-          "printedName": "S1"
+          "printedName": "S1",
+          "usr": "s:4cake2S1V"
+        }
+      ]
+    },
+    {
+      "kind": "Function",
+      "name": "foo3",
+      "printedName": "foo3(_:)",
+      "declKind": "Func",
+      "usr": "s:4cake4foo3yys10DictionaryVySiSSGF",
+      "location": "",
+      "moduleName": "cake",
+      "children": [
+        {
+          "kind": "TypeNominal",
+          "name": "Void",
+          "printedName": "()"
+        },
+        {
+          "kind": "TypeNominal",
+          "name": "Dictionary",
+          "printedName": "[Int : String]",
+          "usr": "s:s10DictionaryV",
+          "children": [
+            {
+              "kind": "TypeNominal",
+              "name": "Int",
+              "printedName": "Int",
+              "usr": "s:Si"
+            },
+            {
+              "kind": "TypeNominal",
+              "name": "String",
+              "printedName": "String",
+              "usr": "s:SS"
+            }
+          ]
         }
       ]
     },
@@ -447,7 +496,8 @@
                 {
                   "kind": "TypeNominal",
                   "name": "Number",
-                  "printedName": "Number"
+                  "printedName": "Number",
+                  "usr": "s:4cake6NumberO"
                 },
                 {
                   "kind": "TypeNominal",
@@ -457,7 +507,8 @@
                     {
                       "kind": "TypeNominal",
                       "name": "Number",
-                      "printedName": "Number"
+                      "printedName": "Number",
+                      "usr": "s:4cake6NumberO"
                     }
                   ]
                 }
@@ -477,7 +528,8 @@
             {
               "kind": "TypeNominal",
               "name": "Int",
-              "printedName": "Int"
+              "printedName": "Int",
+              "usr": "s:Si"
             }
           ]
         },
@@ -493,7 +545,8 @@
             {
               "kind": "TypeNominal",
               "name": "Int",
-              "printedName": "Int"
+              "printedName": "Int",
+              "usr": "s:Si"
             },
             {
               "kind": "Getter",
@@ -507,7 +560,8 @@
                 {
                   "kind": "TypeNominal",
                   "name": "Int",
-                  "printedName": "Int"
+                  "printedName": "Int",
+                  "usr": "s:Si"
                 }
               ]
             }
@@ -526,18 +580,21 @@
               "kind": "TypeNominal",
               "name": "Optional",
               "printedName": "Number?",
+              "usr": "s:Sq",
               "children": [
                 {
                   "kind": "TypeNominal",
                   "name": "Number",
-                  "printedName": "Number"
+                  "printedName": "Number",
+                  "usr": "s:4cake6NumberO"
                 }
               ]
             },
             {
               "kind": "TypeNominal",
               "name": "Int",
-              "printedName": "Int"
+              "printedName": "Int",
+              "usr": "s:Si"
             }
           ]
         },
@@ -553,7 +610,8 @@
             {
               "kind": "TypeNominal",
               "name": "Int",
-              "printedName": "Int"
+              "printedName": "Int",
+              "usr": "s:Si"
             },
             {
               "kind": "Getter",
@@ -567,7 +625,8 @@
                 {
                   "kind": "TypeNominal",
                   "name": "Int",
-                  "printedName": "Int"
+                  "printedName": "Int",
+                  "usr": "s:Si"
                 }
               ]
             }
diff --git a/test/api-digester/apinotes-diags.swift b/test/api-digester/apinotes-diags.swift
index e6f22c2..56930a6 100644
--- a/test/api-digester/apinotes-diags.swift
+++ b/test/api-digester/apinotes-diags.swift
@@ -2,7 +2,7 @@
 // RUN: %empty-directory(%t.mod)
 // RUN: %empty-directory(%t.sdk)
 // RUN: %empty-directory(%t.module-cache)
-// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump1.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %S/Inputs/APINotesLeft
-// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump2.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %S/Inputs/APINotesRight
+// RUN: %api-digester %clang-importer-sdk-nosource -dump-sdk -module APINotesTest -o %t.dump1.json -module-cache-path %t.module-cache -swift-version 3 -I %S/Inputs/APINotesLeft
+// RUN: %api-digester %clang-importer-sdk-nosource -dump-sdk -module APINotesTest -o %t.dump2.json -module-cache-path %t.module-cache -swift-version 3 -I %S/Inputs/APINotesRight
 // RUN: %api-digester -diagnose-sdk -print-module -input-paths %t.dump1.json -input-paths %t.dump2.json > %t.result
 // RUN: diff -u %S/Outputs/apinotes-diags.txt %t.result
diff --git a/test/api-digester/apinotes-migrator-gen.swift b/test/api-digester/apinotes-migrator-gen.swift
index 24a93c2..df6a90d 100644
--- a/test/api-digester/apinotes-migrator-gen.swift
+++ b/test/api-digester/apinotes-migrator-gen.swift
@@ -2,7 +2,7 @@
 // RUN: %empty-directory(%t.mod)
 // RUN: %empty-directory(%t.sdk)
 // RUN: %empty-directory(%t.module-cache)
-// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump1.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %S/Inputs/APINotesLeft
-// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump2.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %S/Inputs/APINotesRight
+// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump1.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -swift-version 3 -I %S/Inputs/APINotesLeft
+// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump2.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -swift-version 3 -I %S/Inputs/APINotesRight
 // RUN: %api-digester -compare-sdk --input-paths %t.dump1.json -input-paths %t.dump2.json -o %t.result -json
 // RUN: diff -u %S/Outputs/apinotes-migrator-gen.json %t.result
diff --git a/test/api-digester/compare-dump.swift b/test/api-digester/compare-dump.swift
index 514a605..b6e5adf 100644
--- a/test/api-digester/compare-dump.swift
+++ b/test/api-digester/compare-dump.swift
@@ -1,9 +1,9 @@
 // RUN: %empty-directory(%t.mod)
 // RUN: %empty-directory(%t.sdk)
 // RUN: %empty-directory(%t.module-cache)
-// RUN: %swift -emit-module -o %t.mod/cake1.swiftmodule %S/Inputs/cake1.swift -parse-as-library -I %S/Inputs/APINotesLeft
-// RUN: %swift -emit-module -o %t.mod/cake2.swiftmodule %S/Inputs/cake2.swift -parse-as-library -I %S/Inputs/APINotesRight
-// RUN: %api-digester -dump-sdk -module cake1 -o %t.dump1.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %t.mod -I %S/Inputs/APINotesLeft
-// RUN: %api-digester -dump-sdk -module cake2 -o %t.dump2.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %t.mod -I %S/Inputs/APINotesRight
+// RUN: %swift -emit-module -o %t.mod/cake1.swiftmodule %S/Inputs/cake1.swift -parse-as-library -I %S/Inputs/APINotesLeft %clang-importer-sdk-nosource
+// RUN: %swift -emit-module -o %t.mod/cake2.swiftmodule %S/Inputs/cake2.swift -parse-as-library -I %S/Inputs/APINotesRight %clang-importer-sdk-nosource
+// RUN: %api-digester -dump-sdk -module cake1 -o %t.dump1.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -swift-version 3 -I %t.mod -I %S/Inputs/APINotesLeft
+// RUN: %api-digester -dump-sdk -module cake2 -o %t.dump2.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -swift-version 3 -I %t.mod -I %S/Inputs/APINotesRight
 // RUN: %api-digester -diagnose-sdk -print-module --input-paths %t.dump1.json -input-paths %t.dump2.json > %t.result
 // RUN: diff -u %S/Outputs/Cake.txt %t.result
diff --git a/test/decl/protocol/req/associated_type_inference.swift b/test/decl/protocol/req/associated_type_inference.swift
index 187b2d0..c4038ad 100644
--- a/test/decl/protocol/req/associated_type_inference.swift
+++ b/test/decl/protocol/req/associated_type_inference.swift
@@ -149,7 +149,7 @@
 
 struct XSubP0c : SubscriptP0 {
 // expected-error@-1 {{type 'XSubP0c' does not conform to protocol 'SubscriptP0'}}
-  subscript (i: Index) -> Element { get { } } // expected-error{{reference to invalid associated type 'Element' of type 'XSubP0c'}}
+  subscript (i: Index) -> Element { get { } }
 }
 
 struct XSubP0d : SubscriptP0 {
diff --git a/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift b/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift
index dafbc80..e0f4147 100644
--- a/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift
+++ b/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift
@@ -1,66 +1,61 @@
-// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -swift-version 4 %s 2>&1 | %FileCheck %s
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -swift-version 4 %s -verify
 
 // Codable class with non-Codable property.
 class C1 : Codable {
+  // expected-error@-1 {{type 'C1' does not conform to protocol 'Decodable'}}
+  // expected-error@-2 {{type 'C1' does not conform to protocol 'Encodable'}}
+
   class Nested {}
   var a: String = ""
   var b: Int = 0
   var c: Nested = Nested()
-
-  // CHECK: error: type 'C1' does not conform to protocol 'Decodable'
-  // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-  // CHECK: note: cannot automatically synthesize 'Decodable' because 'C1.Nested' does not conform to 'Decodable'
-
-  // CHECK: error: type 'C1' does not conform to protocol 'Encodable'
-  // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
-  // CHECK: note: cannot automatically synthesize 'Encodable' because 'C1.Nested' does not conform to 'Encodable'
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'C1.Nested' does not conform to 'Decodable'}}
+  // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'C1.Nested' does not conform to 'Encodable'}}
 }
 
 // Codable class with non-enum CodingKeys.
 class C2 : Codable {
+  // expected-error@-1 {{type 'C2' does not conform to protocol 'Decodable'}}
+  // expected-error@-2 {{type 'C2' does not conform to protocol 'Encodable'}}
+
   var a: String = ""
   var b: Int = 0
   var c: Double?
 
   struct CodingKeys : CodingKey {
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'CodingKeys' is not an enum}}
+  // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'CodingKeys' is not an enum}}
     var stringValue = ""
     var intValue = nil
+    // expected-error@-1 {{'nil' requires a contextual type}}
     init?(stringValue: String) {}
     init?(intValue: Int) {}
   }
-
-  // CHECK: error: type 'C2' does not conform to protocol 'Decodable'
-  // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-  // CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' is not an enum
-
-  // CHECK: error: type 'C2' does not conform to protocol 'Encodable'
-  // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
-  // CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' is not an enum
 }
 
 // Codable class with CodingKeys not conforming to CodingKey.
 class C3 : Codable {
+  // expected-error@-1 {{type 'C3' does not conform to protocol 'Decodable'}}
+  // expected-error@-2 {{type 'C3' does not conform to protocol 'Encodable'}}
+
   var a: String = ""
   var b: Int = 0
   var c: Double?
 
   enum CodingKeys : String {
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'CodingKeys' does not conform to CodingKey}}
+  // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'CodingKeys' does not conform to CodingKey}}
     case a
     case b
     case c
   }
-
-  // CHECK: error: type 'C3' does not conform to protocol 'Decodable'
-  // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-  // CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' does not conform to CodingKey
-
-  // CHECK: error: type 'C3' does not conform to protocol 'Encodable'
-  // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
-  // CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' does not conform to CodingKey
 }
 
 // Codable class with extraneous CodingKeys
 class C4 : Codable {
+  // expected-error@-1 {{type 'C4' does not conform to protocol 'Decodable'}}
+  // expected-error@-2 {{type 'C4' does not conform to protocol 'Encodable'}}
+
   var a: String = ""
   var b: Int = 0
   var c: Double?
@@ -68,48 +63,40 @@
   enum CodingKeys : String, CodingKey {
     case a
     case a2
+    // expected-note@-1 2{{CodingKey case 'a2' does not match any stored properties}}
     case b
     case b2
+    // expected-note@-1 2{{CodingKey case 'b2' does not match any stored properties}}
     case c
     case c2
+    // expected-note@-1 2{{CodingKey case 'c2' does not match any stored properties}}
   }
-
-  // CHECK: error: type 'C4' does not conform to protocol 'Decodable'
-  // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-  // CHECK: note: CodingKey case 'a2' does not match any stored properties
-  // CHECK: note: CodingKey case 'b2' does not match any stored properties
-  // CHECK: note: CodingKey case 'c2' does not match any stored properties
-
-  // CHECK: error: type 'C4' does not conform to protocol 'Encodable'
-  // CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
-  // CHECK: note: CodingKey case 'a2' does not match any stored properties
-  // CHECK: note: CodingKey case 'b2' does not match any stored properties
-  // CHECK: note: CodingKey case 'c2' does not match any stored properties
 }
 
 // Codable class with non-decoded property (which has no default value).
 class C5 : Codable {
+  // expected-error@-1 {{type 'C5' does not conform to protocol 'Decodable'}}
+  // expected-error@-2 {{class 'C5' has no initializers}}
+
   var a: String = ""
   var b: Int
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value}}
+  // expected-note@-2 {{stored property 'b' without initial value prevents synthesized initializers}}
   var c: Double?
 
   enum CodingKeys : String, CodingKey {
     case a
     case c
   }
-
-  // CHECK: error: type 'C5' does not conform to protocol 'Decodable'
-  // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-  // CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
-
-  // CHECK: error: class 'C5' has no initializers
-  // CHECK: note: stored property 'b' without initial value prevents synthesized initializers
 }
 
 // Codable class with non-decoded property (which has no default value).
 class C6 : Codable {
+  // expected-error@-1 {{type 'C6' does not conform to protocol 'Decodable'}}
+
   var a: String = ""
   var b: Int
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value}}
   var c: Double?
 
   enum CodingKeys : String, CodingKey {
@@ -120,14 +107,10 @@
   init() {
     b = 5
   }
-
-  // CHECK: error: type 'C6' does not conform to protocol 'Decodable'
-  // CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-  // CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
 }
 
 // Classes cannot yet synthesize Encodable or Decodable in extensions.
 class C7 {}
 extension C7 : Codable {}
-// CHECK: error: implementation of 'Decodable' cannot be automatically synthesized in an extension
-// CHECK: error: implementation of 'Encodable' cannot be automatically synthesized in an extension
+// expected-error@-1 {{implementation of 'Decodable' cannot be automatically synthesized in an extension}}
+// expected-error@-2 {{implementation of 'Encodable' cannot be automatically synthesized in an extension}}
diff --git a/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift b/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift
index 03da533..d9a07a5 100644
--- a/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift
+++ b/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift
@@ -1,20 +1,30 @@
-// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -swift-version 4 %s 2>&1 | %FileCheck %s
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -swift-version 4 %s -verify
 
 // Codable struct with non-Codable property.
 struct S1 : Codable {
+// expected-error@-1 {{type 'S1' does not conform to protocol 'Decodable'}}
+// expected-error@-2 {{type 'S1' does not conform to protocol 'Encodable'}}
+
   struct Nested {}
   var a: String = ""
   var b: Int = 0
   var c: Nested = Nested()
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'S1.Nested' does not conform to 'Decodable'}}
+  // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'S1.Nested' does not conform to 'Encodable'}}
 }
 
 // Codable struct with non-enum CodingKeys.
 struct S2 : Codable {
+// expected-error@-1 {{type 'S2' does not conform to protocol 'Decodable'}}
+// expected-error@-2 {{type 'S2' does not conform to protocol 'Encodable'}}
+
   var a: String = ""
   var b: Int = 0
   var c: Double?
 
   struct CodingKeys : CodingKey {
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'CodingKeys' is not an enum}}
+  // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'CodingKeys' is not an enum}}
     var stringValue: String = ""
     var intValue: Int? = nil
     init?(stringValue: String) {}
@@ -24,11 +34,16 @@
 
 // Codable struct with CodingKeys not conforming to CodingKey.
 struct S3 : Codable {
+// expected-error@-1 {{type 'S3' does not conform to protocol 'Decodable'}}
+// expected-error@-2 {{type 'S3' does not conform to protocol 'Encodable'}}
+
   var a: String = ""
   var b: Int = 0
   var c: Double?
 
   enum CodingKeys : String {
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'CodingKeys' does not conform to CodingKey}}
+  // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'CodingKeys' does not conform to CodingKey}}
     case a
     case b
     case c
@@ -37,6 +52,9 @@
 
 // Codable struct with extraneous CodingKeys
 struct S4 : Codable {
+// expected-error@-1 {{type 'S4' does not conform to protocol 'Decodable'}}
+// expected-error@-2 {{type 'S4' does not conform to protocol 'Encodable'}}
+
   var a: String = ""
   var b: Int = 0
   var c: Double?
@@ -44,17 +62,26 @@
   enum CodingKeys : String, CodingKey {
     case a
     case a2
+    // expected-note@-1 {{CodingKey case 'a2' does not match any stored properties}}
+    // expected-note@-2 {{CodingKey case 'a2' does not match any stored properties}}
     case b
     case b2
+    // expected-note@-1 {{CodingKey case 'b2' does not match any stored properties}}
+    // expected-note@-2 {{CodingKey case 'b2' does not match any stored properties}}
     case c
     case c2
+    // expected-note@-1 {{CodingKey case 'c2' does not match any stored properties}}
+    // expected-note@-2 {{CodingKey case 'c2' does not match any stored properties}}
   }
 }
 
 // Codable struct with non-decoded property (which has no default value).
 struct S5 : Codable {
+// expected-error@-1 {{type 'S5' does not conform to protocol 'Decodable'}}
+
   var a: String = ""
   var b: Int
+  // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value}}
   var c: Double?
 
   enum CodingKeys : String, CodingKey {
@@ -66,55 +93,5 @@
 // Structs cannot yet synthesize Encodable or Decodable in extensions.
 struct S6 {}
 extension S6 : Codable {}
-
-// Decodable diagnostics are output first here {
-
-// CHECK: error: type 'S1' does not conform to protocol 'Decodable'
-// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-// CHECK: note: cannot automatically synthesize 'Decodable' because 'S1.Nested' does not conform to 'Decodable'
-
-// CHECK: error: type 'S2' does not conform to protocol 'Decodable'
-// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-// CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' is not an enum
-
-// CHECK: error: type 'S3' does not conform to protocol 'Decodable'
-// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-// CHECK: note: cannot automatically synthesize 'Decodable' because 'CodingKeys' does not conform to CodingKey
-
-// CHECK: error: type 'S4' does not conform to protocol 'Decodable'
-// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-// CHECK: note: CodingKey case 'a2' does not match any stored properties
-// CHECK: note: CodingKey case 'b2' does not match any stored properties
-// CHECK: note: CodingKey case 'c2' does not match any stored properties
-
-// CHECK: error: type 'S5' does not conform to protocol 'Decodable'
-// CHECK: note: protocol requires initializer 'init(from:)' with type 'Decodable'
-// CHECK: note: cannot automatically synthesize 'Decodable' because 'b' does not have a matching CodingKey and does not have a default value
-
-// CHECK: error: implementation of 'Decodable' cannot be automatically synthesized in an extension
-
-// }
-
-// Encodable {
-
-// CHECK: error: type 'S1' does not conform to protocol 'Encodable'
-// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
-// CHECK: note: cannot automatically synthesize 'Encodable' because 'S1.Nested' does not conform to 'Encodable'
-
-// CHECK: error: type 'S2' does not conform to protocol 'Encodable'
-// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
-// CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' is not an enum
-
-// CHECK: error: type 'S3' does not conform to protocol 'Encodable'
-// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
-// CHECK: note: cannot automatically synthesize 'Encodable' because 'CodingKeys' does not conform to CodingKey
-
-// CHECK: error: type 'S4' does not conform to protocol 'Encodable'
-// CHECK: note: protocol requires function 'encode(to:)' with type 'Encodable'
-// CHECK: note: CodingKey case 'a2' does not match any stored properties
-// CHECK: note: CodingKey case 'b2' does not match any stored properties
-// CHECK: note: CodingKey case 'c2' does not match any stored properties
-
-// CHECK: error: implementation of 'Encodable' cannot be automatically synthesized in an extension
-
-// }
+// expected-error@-1 {{implementation of 'Decodable' cannot be automatically synthesized in an extension}}
+// expected-error@-2 {{implementation of 'Encodable' cannot be automatically synthesized in an extension}}
diff --git a/test/stdlib/DictionaryLiteral.swift b/test/stdlib/DictionaryLiteral.swift
index 8fc3c88..8d30e36 100644
--- a/test/stdlib/DictionaryLiteral.swift
+++ b/test/stdlib/DictionaryLiteral.swift
@@ -49,8 +49,5 @@
 var stringNSStringLet: DictionaryLiteral = [ "a": aString as NSString, "b": anNSString]
 expectType(DictionaryLiteral<String, NSString>.self, &stringNSStringLet)
 
-var hetero1: DictionaryLiteral = ["a": 1 as NSNumber, "b": "Foo" as NSString]
-expectType(DictionaryLiteral<String, NSObject>.self, &hetero1)
-
-var hetero2: DictionaryLiteral = ["a": 1 as NSNumber, "b": "Foo" as NSString]
-expectType(DictionaryLiteral<String, NSObject>.self, &hetero2)
+var hetero: DictionaryLiteral = ["a": 1 as NSNumber, "b": "Foo" as NSString]
+expectType(DictionaryLiteral<String, NSObject>.self, &hetero)
diff --git a/test/stdlib/FloatingPoint.swift.gyb b/test/stdlib/FloatingPoint.swift.gyb
index 6df78cb..d702e5e 100644
--- a/test/stdlib/FloatingPoint.swift.gyb
+++ b/test/stdlib/FloatingPoint.swift.gyb
@@ -49,7 +49,7 @@
       Builtin.zextOrBitCast_Int64_Int80((64 as Int64)._value))
     result = Builtin.or_Int80(
       result, Builtin.zextOrBitCast_Int64_Int80(bitPattern.significand._value))
-    self = Float80(_bits: Builtin.bitcast_Int80_FPIEEE80(result))
+    self = Float80(Builtin.bitcast_Int80_FPIEEE80(result))
   }
 }
 
diff --git a/test/stdlib/StringCompatibilityDiagnostics3.swift b/test/stdlib/StringCompatibilityDiagnostics3.swift
index c9358ac..a3edaa3 100644
--- a/test/stdlib/StringCompatibilityDiagnostics3.swift
+++ b/test/stdlib/StringCompatibilityDiagnostics3.swift
@@ -21,6 +21,7 @@
   dump(charSubView)
 
   var _ = String(str.utf8) ?? "" // expected-warning{{'init' is deprecated: Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)}}
-  var _: String = String(str.utf8) // expected-error{{'init' is unavailable: Please use failable String.init?(_:UTF8View) when in Swift 3.2 mode}}
+  var _ = String(str.utf8) // expected-warning{{'init' is deprecated: Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)}}
+  var _: String = String(str.utf8) // expected-error {{value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?}}
 }
 
diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
index 1b1b6ed..7c009cc 100644
--- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h
+++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
@@ -540,7 +540,7 @@
                                          ArrayRef<const char *> Args,
                                          bool UsingSwiftArgs,
                                          bool SynthesizedExtensions,
-                                         Optional<unsigned> swiftVersion) = 0;
+                                         StringRef swiftVersion) = 0;
 
   virtual void editorOpenSwiftSourceInterface(StringRef Name,
                                               StringRef SourceName,
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp
index b62e212..553e686 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp
@@ -805,7 +805,7 @@
                                                  ArrayRef<const char *> Args,
                                                  bool UsingSwiftArgs,
                                                  bool SynthesizedExtensions,
-                                              Optional<unsigned> swiftVersion) {
+                                                 StringRef swiftVersion) {
   CompilerInstance CI;
   // Display diagnostics to stderr.
   PrintingDiagnosticConsumer PrintDiags;
@@ -838,9 +838,12 @@
   }
 
   Invocation.getClangImporterOptions().ImportForwardDeclarations = true;
-  if (swiftVersion.hasValue()) {
-    auto swiftVer = version::Version({swiftVersion.getValue()});
-    Invocation.getLangOptions().EffectiveLanguageVersion = swiftVer;
+  if (!swiftVersion.empty()) {
+    auto swiftVer = version::Version::parseVersionString(swiftVersion,
+                                                         SourceLoc(), nullptr);
+    if (swiftVer.hasValue())
+      Invocation.getLangOptions().EffectiveLanguageVersion =
+          swiftVer.getValue();
   }
   auto IFaceGenRef = SwiftInterfaceGenContext::create(Name,
                                                       /*IsModule=*/false,
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
index 2b044de..a0eb348 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
@@ -418,7 +418,7 @@
                                  ArrayRef<const char *> Args,
                                  bool UsingSwiftArgs,
                                  bool SynthesizedExtensions,
-                                 Optional<unsigned> swiftVersion) override;
+                                 StringRef swiftVersion) override;
 
   void editorOpenSwiftSourceInterface(StringRef Name,
                                       StringRef SourceName,
diff --git a/tools/SourceKit/tools/sourcekitd-test/Options.td b/tools/SourceKit/tools/sourcekitd-test/Options.td
index 905fd9a..c5a239d 100644
--- a/tools/SourceKit/tools/sourcekitd-test/Options.td
+++ b/tools/SourceKit/tools/sourcekitd-test/Options.td
@@ -104,6 +104,9 @@
 def swift_version : Separate<["-"], "swift-version">, HelpText<"the swift version to use">;
 def swift_version_EQ : Joined<["-"], "swift-version=">, Alias<swift_version>;
 
+def pass_version_as_string : Flag<["-"], "pass-version-as-string">,
+  HelpText<"Pass swift-version as string">;
+
 def swift_name : Separate<["-"], "swift-name">,
   HelpText<"Swift name to translate from">;
 
diff --git a/tools/SourceKit/tools/sourcekitd-test/TestOptions.cpp b/tools/SourceKit/tools/sourcekitd-test/TestOptions.cpp
index 1c6dded..1e283a1 100644
--- a/tools/SourceKit/tools/sourcekitd-test/TestOptions.cpp
+++ b/tools/SourceKit/tools/sourcekitd-test/TestOptions.cpp
@@ -200,15 +200,13 @@
       break;
     }
 
-      case OPT_swift_version: {
-        unsigned ver;
-        if (StringRef(InputArg->getValue()).getAsInteger(10, ver)) {
-          llvm::errs() << "error: expected integer for 'swift-version'\n";
-          return true;
-        }
-        SwiftVersion = ver;
-        break;
-      }
+    case OPT_swift_version:
+      SwiftVersion = InputArg->getValue();
+      break;
+
+    case OPT_pass_version_as_string:
+      PassVersionAsString = true;
+      break;
 
     case OPT_line:
       if (StringRef(InputArg->getValue()).getAsInteger(10, Line)) {
diff --git a/tools/SourceKit/tools/sourcekitd-test/TestOptions.h b/tools/SourceKit/tools/sourcekitd-test/TestOptions.h
index a6e135d..61baf61 100644
--- a/tools/SourceKit/tools/sourcekitd-test/TestOptions.h
+++ b/tools/SourceKit/tools/sourcekitd-test/TestOptions.h
@@ -78,7 +78,8 @@
   unsigned EndCol = 0;
   unsigned Offset = 0;
   unsigned Length = 0;
-  llvm::Optional<unsigned> SwiftVersion;
+  std::string SwiftVersion;
+  bool PassVersionAsString = false;
   llvm::Optional<std::string> ReplaceText;
   std::string ModuleName;
   std::string HeaderPath;
diff --git a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp
index 0d007fc..dcf789e 100644
--- a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp
+++ b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp
@@ -743,9 +743,18 @@
                                             *Opts.CancelOnSubsequentRequest);
   }
 
-  if (Opts.SwiftVersion.hasValue()) {
-    sourcekitd_request_dictionary_set_int64(Req, KeySwiftVersion,
-                                             Opts.SwiftVersion.getValue());
+  if (!Opts.SwiftVersion.empty()) {
+    if (Opts.PassVersionAsString) {
+      sourcekitd_request_dictionary_set_string(Req, KeySwiftVersion,
+                                               Opts.SwiftVersion.c_str());
+    } else {
+      unsigned ver;
+      if (StringRef(Opts.SwiftVersion).getAsInteger(10, ver)) {
+        llvm::errs() << "error: expected integer for 'swift-version'\n";
+        return true;
+      }
+      sourcekitd_request_dictionary_set_int64(Req, KeySwiftVersion, ver);
+    }
   }
 
   if (Opts.PrintRequest)
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 78dc932..de6307f 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -163,7 +163,7 @@
                           ArrayRef<const char *> Args,
                           bool UsingSwiftArgs,
                           bool SynthesizedExtensions,
-                          Optional<unsigned> swiftVersion);
+                          StringRef swiftVersion);
 
 static void
 editorOpenSwiftSourceInterface(StringRef Name, StringRef SourceName,
@@ -498,10 +498,15 @@
     Req.getInt64(KeySynthesizedExtension, SynthesizedExtension,
                  /*isOptional=*/true);
     Optional<int64_t> UsingSwiftArgs = Req.getOptionalInt64(KeyUsingSwiftArgs);
-    Optional<int64_t> swiftVerVal = Req.getOptionalInt64(KeySwiftVersion);
-    Optional<unsigned> swiftVer;
-    if (swiftVerVal.hasValue())
-      swiftVer = *swiftVerVal;
+    std::string swiftVer;
+    Optional<StringRef> swiftVerValStr = Req.getString(KeySwiftVersion);
+    if (swiftVerValStr.hasValue()) {
+      swiftVer = swiftVerValStr.getValue();
+    } else {
+      Optional<int64_t> swiftVerVal = Req.getOptionalInt64(KeySwiftVersion);
+      if (swiftVerVal.hasValue())
+        swiftVer = std::to_string(*swiftVerVal);
+    }
     return Rec(editorOpenHeaderInterface(*Name, *HeaderName, Args,
                                          UsingSwiftArgs.getValueOr(false),
                                          SynthesizedExtension, swiftVer));
@@ -2151,7 +2156,7 @@
                           ArrayRef<const char *> Args,
                           bool UsingSwiftArgs,
                           bool SynthesizedExtensions,
-                          Optional<unsigned> swiftVersion) {
+                          StringRef swiftVersion) {
   SKEditorConsumer EditC(/*EnableSyntaxMap=*/true,
                          /*EnableStructure=*/true,
                          /*EnableDiagnostics=*/false,
diff --git a/tools/SwiftSyntax/Diagnostic.swift b/tools/SwiftSyntax/Diagnostic.swift
index e02596c..1fd2869 100644
--- a/tools/SwiftSyntax/Diagnostic.swift
+++ b/tools/SwiftSyntax/Diagnostic.swift
@@ -29,6 +29,12 @@
   /// The file in which this location resides.
   public let file: String
 
+  public init(file: String, position: AbsolutePosition) {
+    assert(position is UTF8Position, "must be utf8 position")
+    self.init(line: position.line, column: position.column,
+              offset: position.byteOffset, file: file)
+  }
+
   public init(line: Int, column: Int, offset: Int, file: String) {
     self.line = line
     self.column = column
diff --git a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp
index d8a9aa7..a162096 100644
--- a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp
+++ b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp
@@ -62,6 +62,48 @@
   }
 }
 
+static void resolveDeclFromMangledNameList(
+    swift::ASTContext &Ctx, llvm::ArrayRef<std::string> MangledNames) {
+  std::string Error;
+  for (auto &Mangled : MangledNames) {
+    swift::Decl *ResolvedDecl =
+        swift::ide::getDeclFromMangledSymbolName(Ctx, Mangled, Error);
+    if (!ResolvedDecl) {
+      llvm::errs() << "Can't resolve decl of " << Mangled << "\n";
+    } else {
+      ResolvedDecl->print(llvm::errs());
+      llvm::errs() << "\n";
+    }
+  }
+}
+
+static void resolveTypeFromMangledNameList(
+    swift::ASTContext &Ctx, llvm::ArrayRef<std::string> MangledNames) {
+  std::string Error;
+  for (auto &Mangled : MangledNames) {
+    swift::Type ResolvedType =
+        swift::ide::getTypeFromMangledSymbolname(Ctx, Mangled, Error);
+    if (!ResolvedType) {
+      llvm::errs() << "Can't resolve type of " << Mangled << "\n";
+    } else {
+      ResolvedType->print(llvm::errs());
+      llvm::errs() << "\n";
+    }
+  }
+}
+
+static void
+collectMangledNames(const std::string &FilePath,
+                    llvm::SmallVectorImpl<std::string> &MangledNames) {
+  std::string Name;
+  std::ifstream InputStream(FilePath);
+  while (std::getline(InputStream, Name)) {
+    if (Name.empty())
+      continue;
+    MangledNames.push_back(Name);
+  }
+}
+
 int main(int argc, char **argv) {
   PROGRAM_START(argc, argv);
   INITIALIZE_LLVM();
@@ -90,8 +132,15 @@
   llvm::cl::list<std::string> FrameworkPaths(
     "F", llvm::cl::desc("add a directory to the framework search path"));
 
+  llvm::cl::opt<std::string> DumpDeclFromMangled(
+      "decl-from-mangled", llvm::cl::desc("dump decl from mangled names list"));
+
   llvm::cl::opt<std::string> DumpTypeFromMangled(
-      "type-from-mangled", llvm::cl::desc("dump type from mangled name"));
+      "type-from-mangled", llvm::cl::desc("dump type from mangled names list"));
+
+  // FIXME: we should infer this from the module.
+  llvm::cl::opt<std::string> TargetTriple(
+      "target-triple", llvm::cl::desc("specify target triple"));
 
   llvm::cl::ParseCommandLineOptions(argc, argv);
   // Unregister our options so they don't interfere with the command line
@@ -103,6 +152,7 @@
   DumpTypeFromMangled.removeArgument();
   SDK.removeArgument();
   InputNames.removeArgument();
+  TargetTriple.removeArgument();
 
   // If no SDK was specified via -sdk, check environment variable SDKROOT.
   if (SDK.getNumOccurrences() == 0) {
@@ -121,7 +171,13 @@
           reinterpret_cast<void *>(&anchorForGetMainExecutable)));
 
   Invocation.setSDKPath(SDK);
-  Invocation.setTargetTriple(llvm::sys::getDefaultTargetTriple());
+
+  // FIXME: we should infer this from the module.
+  if (!TargetTriple.empty())
+    Invocation.setTargetTriple(TargetTriple);
+  else
+    Invocation.setTargetTriple(llvm::sys::getDefaultTargetTriple());
+
   Invocation.setModuleName("lldbtest");
   Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;
   Invocation.setImportSearchPaths(ImportPaths);
@@ -238,28 +294,14 @@
       }
     }
     if (!DumpTypeFromMangled.empty()) {
-      std::string Error;
-      std::string Name;
-      swift::ASTContext &Ctx = CI.getASTContext();
       llvm::SmallVector<std::string, 8> MangledNames;
-
-      std::ifstream InputStream(DumpTypeFromMangled);
-      while (std::getline(InputStream, Name)) {
-        if (Name.empty())
-          continue;
-        MangledNames.push_back(Name);
-      }
-
-      for (auto &Mangled : MangledNames) {
-        swift::Type ResolvedType = swift::ide::getTypeFromMangledSymbolname(
-            Ctx, Mangled, Error);
-        if (!ResolvedType) {
-          llvm::errs() << "Can't resolve type of " << Mangled << "\n";
-        } else {
-          ResolvedType->print(llvm::errs());
-          llvm::errs() << "\n";
-        }
-      }
+      collectMangledNames(DumpTypeFromMangled, MangledNames);
+      resolveTypeFromMangledNameList(CI.getASTContext(), MangledNames);
+    }
+    if (!DumpDeclFromMangled.empty()) {
+      llvm::SmallVector<std::string, 8> MangledNames;
+      collectMangledNames(DumpDeclFromMangled, MangledNames);
+      resolveDeclFromMangledNameList(CI.getASTContext(), MangledNames);
     }
   }
   return 0;
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index ec92d6d..cb79a86 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -511,9 +511,12 @@
 }
 
 class SDKNodeTypeNominal : public SDKNodeType {
+  StringRef USR;
 public:
   SDKNodeTypeNominal(SDKNodeInitInfo Info) : SDKNodeType(Info,
-    SDKNodeKind::TypeNominal) {}
+    SDKNodeKind::TypeNominal), USR(Info.USR) {}
+  // Get the usr of the correspoding nominal type decl.
+  StringRef getUsr() const { return USR; }
   static bool classof(const SDKNode *N);
 };
 
@@ -1286,6 +1289,10 @@
     TypeInfo(TypeInfo) {
   if (isFunctionTypeNoEscape(Ty))
     TypeAttrs.push_back(TypeAttrKind::TAK_noescape);
+  // If this is a nominal type, get its Usr.
+  if (auto *ND = Ty->getAnyNominal()) {
+    USR = calculateUsr(Ctx, ND);
+  }
 }
 
 SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD)
@@ -1760,6 +1767,12 @@
             out.mapRequired(getKeyContent(Ctx, KeyKind::KK_hasDefaultArg).data(),
                             HasDefault);
           }
+          // Serialize nominal type's USR.
+          if (auto NT = dyn_cast<SDKNodeTypeNominal>(value)) {
+            auto Usr = NT->getUsr();
+            if (!Usr.empty())
+              out.mapRequired(getKeyContent(Ctx, KeyKind::KK_usr).data(), Usr);
+          }
         }
         if (!value->isLeaf()) {
           ArrayRef<SDKNode *> Children = value->getChildren();
@@ -3424,7 +3437,7 @@
 
   llvm::errs() << "Dumping diff to " << DiffPath << '\n';
   std::vector<OverloadedFuncInfo> Overloads;
-  OverloadMemberFunctionEmitter::collectDiffItems(RightModule, Overloads);
+  // OverloadMemberFunctionEmitter::collectDiffItems(RightModule, Overloads);
 
   std::error_code EC;
   llvm::raw_fd_ostream Fs(DiffPath, EC, llvm::sys::fs::F_None);
diff --git a/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp
index 8fdbd85..00e2160 100644
--- a/tools/swift-demangle/swift-demangle.cpp
+++ b/tools/swift-demangle/swift-demangle.cpp
@@ -175,7 +175,7 @@
   // This doesn't handle Unicode symbols, but maybe that's okay.
   // Also accept the future mangling prefix.
   // TODO: remove the "_S" as soon as MANGLING_PREFIX_STR gets "_S".
-  llvm::Regex maybeSymbol("(_T|_*\\$S|" MANGLING_PREFIX_STR ")[_a-zA-Z0-9$.]+");
+  llvm::Regex maybeSymbol("(_T|_?\\$[Ss])[_a-zA-Z0-9$.]+");
 
   swift::Demangle::Context DCtx;
   for (std::string mangled; std::getline(std::cin, mangled);) {
@@ -213,7 +213,12 @@
   } else {
     swift::Demangle::Context DCtx;
     for (llvm::StringRef name : InputNames) {
-      demangle(llvm::outs(), name, DCtx, options);
+      if (name.startswith("S")) {
+        std::string correctedName = std::string("$") + name.str();
+        demangle(llvm::outs(), correctedName, DCtx, options);
+      } else {
+        demangle(llvm::outs(), name, DCtx, options);
+      }
       llvm::outs() << '\n';
     }
 
diff --git a/unittests/SwiftDemangle/DemangleTest.cpp b/unittests/SwiftDemangle/DemangleTest.cpp
index c495600..ee9f8b4 100644
--- a/unittests/SwiftDemangle/DemangleTest.cpp
+++ b/unittests/SwiftDemangle/DemangleTest.cpp
@@ -42,6 +42,7 @@
   char OutputBuffer[128];
 
   const char *FunctionName = "$S1a10run_MatMulyySiF";
+  const char *FunctionNameNew = "$s1a10run_MatMulyySiF";
   const char *DemangledName = "a.run_MatMul(Swift.Int) -> ()";
   const char *SimplifiedName = "run_MatMul(_:)";
 
@@ -51,6 +52,12 @@
   EXPECT_STREQ(DemangledName, OutputBuffer);
   EXPECT_EQ(Result, strlen(DemangledName));
 
+  Result = swift_demangle_getDemangledName(FunctionNameNew, OutputBuffer,
+                                           sizeof(OutputBuffer));
+
+  EXPECT_STREQ(DemangledName, OutputBuffer);
+  EXPECT_EQ(Result, strlen(DemangledName));
+
   Result = swift_demangle_getSimplifiedDemangledName(FunctionName, OutputBuffer,
                                                      sizeof(OutputBuffer));
 
diff --git a/unittests/runtime/LongTests/LongRefcounting.cpp b/unittests/runtime/LongTests/LongRefcounting.cpp
index 779ec0f..ec29b49 100644
--- a/unittests/runtime/LongTests/LongRefcounting.cpp
+++ b/unittests/runtime/LongTests/LongRefcounting.cpp
@@ -10,6 +10,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <functional>
+
 #include "swift/Runtime/HeapObject.h"
 #include "swift/Runtime/Metadata.h"
 #include "swift/Demangling/ManglingMacros.h"
@@ -42,8 +44,11 @@
   // On exit from deinit: is destroyed
   WeakReference *WeakRef;
   
+  // Callback invoked during the object's deinit.
+  std::function<void()> DeinitCallback;
+
   TestObject(size_t *addr, size_t value)
-    : Addr(addr), Value(value), CheckLifecycle(false), WeakRef(nullptr)
+    : Addr(addr), Value(value), CheckLifecycle(false), WeakRef(nullptr), DeinitCallback(nullptr)
   { }
 };
 
@@ -91,8 +96,13 @@
     }
   }
 
+  if (object->DeinitCallback != nullptr) {
+    object->DeinitCallback();
+  }
+
   *object->Addr = object->Value;
   object->Addr = nullptr;
+  object->~TestObject();
   swift_deallocObject(object, sizeof(TestObject), alignof(TestObject) - 1);
 }
 
@@ -230,8 +240,6 @@
 }
 
 // Maximum legal unowned retain count. 31 bits with no implicit +1.
-// (FIXME 32-bit architecture has 7 bit inline count;
-// that bound does not yet have its own tests.)
 const uint64_t maxURC = (1ULL << (32 - 1)) - 1;
 
 TEST(LongRefcountingTest, unowned_retain_max) {
@@ -1046,3 +1054,39 @@
   EXPECT_UNALLOCATED(side);
   EXPECT_EQ(0, weakValue);
 }
+
+TEST(LongRefcountingTest, lifecycle_live_deiniting_urc_overflow_to_side) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+
+  uint64_t urcOverflowCount;
+  switch(sizeof(void *)) {
+  // 32-bit has a 7-bit inline refcount that overflows into the side table.
+  case 4: urcOverflowCount = 1 << 7; break;
+
+  // 64-bit can't store any extra count in the side table, so there's nothing to test.
+  case 8: return;
+
+  // We should never see any other bitness.
+  default: FAIL(); break;
+  }
+
+  size_t deinited = 0;
+  auto object = allocTestObject(&deinited, 1);
+  HeapObjectSideTableEntry *side = nullptr;
+  object->DeinitCallback = [&]() {
+    for (uint64_t i = 0; i < urcOverflowCount; i++) {
+      swift_unownedRetain(object);
+    }
+
+    side = reinterpret_cast<HeapObjectSideTableEntry *>(object->refCounts.getSideTable());
+    EXPECT_ALLOCATED(side);
+
+    for (uint64_t i = 0; i < urcOverflowCount; i++) {
+      swift_unownedRelease(object);
+    }
+  };
+
+  swift_release(object);
+  EXPECT_UNALLOCATED(object);
+  EXPECT_UNALLOCATED(side);
+}
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 6b8ddfd..827355b 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -2864,7 +2864,7 @@
                         -E "${DOTEST_EXTRA}"
                 else
                     with_pushd "${results_dir}" \
-                        call env SWIFTCC="$(build_directory $LOCAL_HOST swift)/bin/swiftc" \
+                        call env SWIFTC="$(build_directory $LOCAL_HOST swift)/bin/swiftc" \
                         SWIFTLIBS="${swift_build_dir}/lib/swift" \
                         "${LLDB_SOURCE_DIR}"/test/dotest.py \
                         --executable "${lldb_executable}" \
diff --git a/utils/build-toolchain b/utils/build-toolchain
index ec0910a..f3d83c6 100755
--- a/utils/build-toolchain
+++ b/utils/build-toolchain
@@ -23,11 +23,9 @@
   echo "-n --dry-run"
   echo "Do a dry run."
   echo ""
-  if [[ "$(uname -s)" == "Linux" ]] ; then
-    echo "-t --test"
-    echo "Run tests."
-    echo ""
-  fi
+  echo "-t --test"
+  echo "Run tests."
+  echo ""
 }
 
 cd "$(dirname $0)/.." || exit
@@ -38,7 +36,7 @@
 BUNDLE_PREFIX=
 case $(uname -s) in
   Darwin)
-    SWIFT_PACKAGE=buildbot_osx_package
+    SWIFT_PACKAGE=buildbot_osx_package,no_test
   ;;
   Linux)
     SWIFT_PACKAGE=buildbot_linux,no_test
@@ -60,8 +58,7 @@
       if [ "$(uname -s)" == "Linux" ]; then
         SWIFT_PACKAGE=buildbot_linux
       else
-        echo "--test is not supported on \"$(uname -s)\". See --help"
-        exit 1
+        SWIFT_PACKAGE=buildbot_osx_package
       fi
   ;;
   -h|--help)
diff --git a/validation-test/IDE/crashers_2/0016-operator-unresolved-dot.swift b/validation-test/IDE/crashers_2/0016-operator-unresolved-dot.swift
deleted file mode 100644
index aaadffe..0000000
--- a/validation-test/IDE/crashers_2/0016-operator-unresolved-dot.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
-
-struct a { func b(c d: a) { b(c: d) == .#^A^#
diff --git a/validation-test/IDE/crashers_2_fixed/0016-operator-unresolved-dot.swift b/validation-test/IDE/crashers_2_fixed/0016-operator-unresolved-dot.swift
new file mode 100644
index 0000000..91f62ac
--- /dev/null
+++ b/validation-test/IDE/crashers_2_fixed/0016-operator-unresolved-dot.swift
@@ -0,0 +1,4 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+// REQUIRES: asserts
+
+struct a { func b(c d: a) { b(c: d) == .#^A^#
diff --git a/validation-test/compiler_crashers_2_fixed/0148-rdar35773761.swift b/validation-test/compiler_crashers_2_fixed/0148-rdar35773761.swift
new file mode 100644
index 0000000..effe05a
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0148-rdar35773761.swift
@@ -0,0 +1,4 @@
+// RUN: %target-typecheck-verify-swift %s
+
+let b: () -> Void = withoutActuallyEscaping({ print("hello crash") }, do: { $0() })
+// expected-error@-1 {{cannot convert value of type '()' to specified type '() -> Void'}}
diff --git a/validation-test/compiler_crashers/28757-conformance-getwitness-requirement-nullptr-getdecl-match-witness-deduced-differe.swift b/validation-test/compiler_crashers_fixed/28757-conformance-getwitness-requirement-nullptr-getdecl-match-witness-deduced-differe.swift
similarity index 83%
rename from validation-test/compiler_crashers/28757-conformance-getwitness-requirement-nullptr-getdecl-match-witness-deduced-differe.swift
rename to validation-test/compiler_crashers_fixed/28757-conformance-getwitness-requirement-nullptr-getdecl-match-witness-deduced-differe.swift
index f46373d..6624ef5 100644
--- a/validation-test/compiler_crashers/28757-conformance-getwitness-requirement-nullptr-getdecl-match-witness-deduced-differe.swift
+++ b/validation-test/compiler_crashers_fixed/28757-conformance-getwitness-requirement-nullptr-getdecl-match-witness-deduced-differe.swift
@@ -5,6 +5,6 @@
 // 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
+
+// RUN: not %target-swift-frontend %s -emit-ir
 @objc protocol P{{}func a}class a:P{{}func a{}func a
diff --git a/validation-test/compiler_crashers/28860-iscomplete-isinvalid-conformance-already-complete.swift b/validation-test/compiler_crashers_fixed/28860-iscomplete-isinvalid-conformance-already-complete.swift
similarity index 84%
rename from validation-test/compiler_crashers/28860-iscomplete-isinvalid-conformance-already-complete.swift
rename to validation-test/compiler_crashers_fixed/28860-iscomplete-isinvalid-conformance-already-complete.swift
index 28d7708..392f5e0 100644
--- a/validation-test/compiler_crashers/28860-iscomplete-isinvalid-conformance-already-complete.swift
+++ b/validation-test/compiler_crashers_fixed/28860-iscomplete-isinvalid-conformance-already-complete.swift
@@ -5,6 +5,6 @@
 // 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
+
+// RUN: not %target-swift-frontend %s -emit-ir
 {class a:P{let d=a}@objc protocol P{class a{}{}typealias a