Merge pull request #10732 from gottesmm/callee_unowned_can_accept_unowned

diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index d9971cd..ee5c0c5 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -48,6 +48,7 @@
     single-source/DropLast
     single-source/DropWhile
     single-source/ErrorHandling
+    single-source/Exclusivity
     single-source/ExistentialPerformance
     single-source/Fibonacci
     single-source/Hanoi
diff --git a/benchmark/single-source/Exclusivity.swift b/benchmark/single-source/Exclusivity.swift
new file mode 100644
index 0000000..368953a
--- /dev/null
+++ b/benchmark/single-source/Exclusivity.swift
@@ -0,0 +1,106 @@
+//===--- Exclusivity.swift -------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// A set of tests for measuring the enforcement overhead of memory access
+// exclusivity rules.
+//
+//===----------------------------------------------------------------------===//
+
+import TestsUtils
+
+// Initially these benchmarks only measure access checks at -Onone. In
+// the future, access checks will also be emitted at -O.
+
+// Measure memory access checks on a trivial global.
+// ---
+
+public var globalCounter: Int = 0
+
+// TODO:
+// - Merge begin/endAccess when no calls intervene (~2x speedup).
+// - Move Swift runtime into the OS  (~2x speedup).
+// - Whole module analysis can remove exclusivity checks (> 10x speedup now, 4x speedup with runtime in OS).
+//   (The global's "public" qualifier should make the benchmark immune to this optimization.)
+@inline(never)
+public func run_accessGlobal(_ N: Int) {
+  globalCounter = 0
+  for _ in 1...10000*N {
+    globalCounter += 1
+  }
+  CheckResults(globalCounter == 10000*N)
+}
+
+// Measure memory access checks on a class property.
+//
+// Note: The end_unpaired_access forces a callback on the property's
+// materializeForSet!
+// ---
+
+// Hopefully the optimizer will not see this as "final" and optimize away the
+// materializeForSet.
+public class C {
+  var counter = 0
+
+  func inc() {
+    counter += 1
+  }
+}
+
+// Thunk 
+@inline(never)
+func updateClass(_ c: C) {
+  c.inc()
+}
+
+// TODO: Replacing materializeForSet accessors with yield-once
+// accessors should make the callback overhead go away.
+@inline(never)
+public func run_accessInMatSet(_ N: Int) {
+  let c = C()
+  for _ in 1...10000*N {
+    updateClass(c)
+  }
+  CheckResults(c.counter == 10000*N)
+}
+
+// Measure nested access to independent objects.
+//
+// A single access set is still faster than hashing for up to four accesses.
+// ---
+
+struct Var {
+  var val = 0
+}
+
+@inline(never)
+func update(a: inout Var, b: inout Var, c: inout Var, d: inout Var) {
+  a.val += 1
+  b.val += 1
+  c.val += 1
+  d.val += 1
+}
+
+@inline(never)
+public func run_accessIndependent(_ N: Int) {
+  var a = Var()
+  var b = Var()
+  var c = Var()
+  var d = Var()
+  let updateVars = {
+    update(a: &a, b: &b, c: &c, d: &d)
+  }
+  for _ in 1...1000*N {
+    updateVars()
+  }
+  CheckResults(a.val == 1000*N && b.val == 1000*N && c.val == 1000*N
+    && d.val == 1000*N)
+}
diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift
index 6a4b6fe..6eda05c 100644
--- a/benchmark/utils/main.swift
+++ b/benchmark/utils/main.swift
@@ -53,6 +53,7 @@
 import DropLast
 import DropWhile
 import ErrorHandling
+import Exclusivity
 import ExistentialPerformance
 import Fibonacci
 import Hanoi
@@ -448,6 +449,9 @@
 addTo(&precommitTests, "UTF8Decode", run_UTF8Decode)
 addTo(&precommitTests, "Walsh", run_Walsh)
 addTo(&precommitTests, "XorLoop", run_XorLoop)
+addTo(&precommitTests, "accessGlobal", run_accessGlobal)
+addTo(&precommitTests, "accessInMatSet", run_accessInMatSet)
+addTo(&precommitTests, "accessIndependent", run_accessIndependent)
 
 // Other tests
 addTo(&otherTests, "Ackermann", run_Ackermann)
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 8609243..7fc2f52 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -318,9 +318,9 @@
     /// called 'static').
     unsigned IsStatic : 1;
 
-    /// \brief Whether this is a 'let' property, which can only be initialized
-    /// once (either in its declaration, or once later), making it immutable.
-    unsigned IsLet : 1;
+    /// \brief The specifier associated with this variable or parameter.  This
+    /// determines the storage semantics of the value e.g. mutability.
+    unsigned Specifier : 2;
 
     /// \brief Whether this declaration was an element of a capture list.
     unsigned IsCaptureList : 1;
@@ -335,7 +335,7 @@
     unsigned IsDebuggerVar : 1;
 
   };
-  enum { NumVarDeclBits = NumAbstractStorageDeclBits + 5 };
+  enum { NumVarDeclBits = NumAbstractStorageDeclBits + 6 };
   static_assert(NumVarDeclBits <= 32, "fits in an unsigned");
 
   class EnumElementDeclBitfields {
@@ -3501,7 +3501,7 @@
 
   /// The generic signature representing exactly the new requirements introduced
   /// by this protocol.
-  GenericSignature *RequirementSignature = nullptr;
+  const Requirement *RequirementSignature = nullptr;
 
   /// True if the protocol has requirements that cannot be satisfied (e.g.
   /// because they could not be imported from Objective-C).
@@ -3511,6 +3511,9 @@
   /// value, plus one. Otherwise, it will be 0.
   unsigned KnownProtocol : 6;
 
+  /// The number of requirements in the requirement signature.
+  unsigned NumRequirementsInSignature : 16;
+
   bool requiresClassSlow();
 
   bool existentialConformsToSelfSlow();
@@ -3687,8 +3690,6 @@
 
   /// Create the implicit generic parameter list for a protocol or
   /// extension thereof.
-  ///
-  /// FIXME: protocol extensions will introduce a where clause here as well.
   GenericParamList *createGenericParams(DeclContext *dc);
 
   /// Create the generic parameters of this protocol if the haven't been
@@ -3700,17 +3701,17 @@
     return TrailingWhere;
   }
 
-  /// Retrieve the generic signature representing the requirements introduced by
-  /// this protocol.
+  /// Retrieve the requirements that describe this protocol.
   ///
-  /// These are the requirements like any inherited protocols and conformances
-  /// for associated types that are mentioned literally in this
-  /// decl. Requirements implied via inheritance are not mentioned, nor is the
-  /// conformance of Self to this protocol.
-  GenericSignature *getRequirementSignature() const {
-    assert(RequirementSignature &&
+  /// These are the requirements including any inherited protocols
+  /// and conformances for associated types that are introduced in this
+  /// protocol. Requirements implied via any other protocol (e.g., inherited
+  /// protocols of the inherited protocols) are not mentioned. The conformance
+  /// requirements listed here become entries in the witness table.
+  ArrayRef<Requirement> getRequirementSignature() const {
+    assert(isRequirementSignatureComputed() &&
            "getting requirement signature before computing it");
-    return RequirementSignature;
+    return llvm::makeArrayRef(RequirementSignature, NumRequirementsInSignature);
   }
 
   /// Has the requirement signature been computed yet?
@@ -3720,9 +3721,7 @@
 
   void computeRequirementSignature();
 
-  void setRequirementSignature(GenericSignature *sig) {
-    RequirementSignature = sig;
-  }
+  void setRequirementSignature(ArrayRef<Requirement> requirements);
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
@@ -4325,15 +4324,28 @@
 
 /// VarDecl - 'var' and 'let' declarations.
 class VarDecl : public AbstractStorageDecl {
+public:
+  enum class Specifier : uint8_t {
+    // For Var Decls
+    
+    Let  = 0,
+    Var  = 1,
+    
+    // For Param Decls
+    
+    None  = Let,
+    InOut = 2,
+  };
+  
 protected:
   llvm::PointerUnion<PatternBindingDecl*, Stmt*> ParentPattern;
 
-  VarDecl(DeclKind Kind, bool IsStatic, bool IsLet, bool IsCaptureList,
+  VarDecl(DeclKind Kind, bool IsStatic, Specifier Sp, bool IsCaptureList,
           SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC)
     : AbstractStorageDecl(Kind, DC, Name, NameLoc)
   {
     VarDeclBits.IsStatic = IsStatic;
-    VarDeclBits.IsLet = IsLet;
+    VarDeclBits.Specifier = static_cast<unsigned>(Sp);
     VarDeclBits.IsCaptureList = IsCaptureList;
     VarDeclBits.IsDebuggerVar = false;
     VarDeclBits.HasNonPatternBindingInit = false;
@@ -4346,9 +4358,9 @@
   Type typeInContext;
 
 public:
-  VarDecl(bool IsStatic, bool IsLet, bool IsCaptureList, SourceLoc NameLoc,
+  VarDecl(bool IsStatic, Specifier Sp, bool IsCaptureList, SourceLoc NameLoc,
           Identifier Name, Type Ty, DeclContext *DC)
-    : VarDecl(DeclKind::Var, IsStatic, IsLet, IsCaptureList, NameLoc, Name, Ty,
+    : VarDecl(DeclKind::Var, IsStatic, Sp, IsCaptureList, NameLoc, Name, Ty,
               DC) {}
 
   SourceRange getSourceRange() const;
@@ -4448,6 +4460,11 @@
   /// Determine whether this declaration is an anonymous closure parameter.
   bool isAnonClosureParam() const;
 
+  /// Return the raw specifier value for this property or parameter.
+  Specifier getSpecifier() const {
+    return static_cast<Specifier>(VarDeclBits.Specifier);
+  }
+  
   /// Is this a type ('static') variable?
   bool isStatic() const { return VarDeclBits.IsStatic; }
   void setStatic(bool IsStatic) { VarDeclBits.IsStatic = IsStatic; }
@@ -4456,9 +4473,20 @@
   StaticSpellingKind getCorrectStaticSpelling() const;
 
   /// Is this an immutable 'let' property?
-  bool isLet() const { return VarDeclBits.IsLet; }
-  void setLet(bool IsLet) { VarDeclBits.IsLet = IsLet; }
-
+  bool isLet() const { return getSpecifier() == Specifier::Let; }
+  // FIXME: Remove this setter.
+  void setLet(bool immutable) {
+    auto specifier = VarDecl::Specifier::Let;
+    if (!immutable) {
+      if (getKind() == DeclKind::Param) {
+        specifier = VarDecl::Specifier::InOut;
+      } else {
+        specifier = VarDecl::Specifier::Var;
+      }
+    }
+    VarDeclBits.Specifier = static_cast<unsigned>(specifier);
+  }
+  
   /// Is this an element in a capture list?
   bool isCaptureList() const { return VarDeclBits.IsCaptureList; }
 
@@ -4509,7 +4537,7 @@
 class ParamDecl : public VarDecl {
   Identifier ArgumentName;
   SourceLoc ArgumentNameLoc;
-  SourceLoc LetVarInOutLoc;
+  SourceLoc SpecifierLoc;
 
   struct StoredDefaultArgument {
     Expr *DefaultArg = nullptr;
@@ -4530,7 +4558,8 @@
   DefaultArgumentKind defaultArgumentKind = DefaultArgumentKind::None;
   
 public:
-  ParamDecl(bool isLet, SourceLoc letVarInOutLoc, SourceLoc argumentNameLoc,
+  ParamDecl(VarDecl::Specifier specifier,
+            SourceLoc specifierLoc, SourceLoc argumentNameLoc,
             Identifier argumentName, SourceLoc parameterNameLoc,
             Identifier parameterName, Type ty, DeclContext *dc);
 
@@ -4548,7 +4577,7 @@
   /// was specified separately from the parameter name.
   SourceLoc getArgumentNameLoc() const { return ArgumentNameLoc; }
 
-  SourceLoc getLetVarInOutLoc() const { return LetVarInOutLoc; }
+  SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
 
   bool isTypeLocImplicit() const { return IsTypeLocImplicit; }
   void setIsTypeLocImplicit(bool val) { IsTypeLocImplicit = val; }
diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def
index b3d227b..e098c22 100644
--- a/include/swift/AST/DiagnosticsFrontend.def
+++ b/include/swift/AST/DiagnosticsFrontend.def
@@ -167,6 +167,17 @@
 ERROR(error_parse_input_file,none,
   "error parsing input file '%0' (%1)", (StringRef, StringRef))
 
+ERROR(error_write_index_unit,none,
+  "writing index unit file: %0", (StringRef))
+ERROR(error_create_index_dir,none,
+  "creating index directory: %0", (StringRef))
+ERROR(error_write_index_record,none,
+  "writing index record file: %0", (StringRef))
+ERROR(error_index_failed_status_check,none,
+  "failed file status check: %0", (StringRef))
+ERROR(error_index_inputs_more_than_outputs,none,
+  "index output filenames do not match input source files", ())
+
 ERROR(error_formatting_multiple_file_ranges,none,
   "file ranges don't support multiple input files", ())
 
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 350beb4..e20625b 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -814,8 +814,8 @@
 ERROR(parameter_inout_var_let_repeated,none,
       "parameter may not have multiple 'inout', 'var', or 'let' specifiers",
       ())
-ERROR(parameter_let_as_attr,none,
-      "'let' as a parameter attribute is not allowed", ())
+ERROR(parameter_let_var_as_attr,none,
+      "'%select{var|let}0' as a parameter attribute is not allowed", (unsigned))
 
 
 ERROR(expected_behavior_name,none,
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 649cf2a..7b4d9eb 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1006,10 +1006,6 @@
 ERROR(attribute_requires_single_argument,none,
       "'%0' requires a function with one argument", (StringRef))
 
-ERROR(var_parameter_not_allowed,none,
-      "parameters may not have the 'var' specifier", ())
-
-
 ERROR(mutating_invalid_global_scope,none,
       "'mutating' is only valid on methods", ())
 ERROR(mutating_invalid_classes,none,
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index 0f81c85..583aff7 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -63,10 +63,6 @@
 
 /// Determines how to resolve a dependent type to a potential archetype.
 enum class ArchetypeResolutionKind {
-  /// Always create a new potential archetype to describe this dependent type,
-  /// which might be invalid and may not provide complete information.
-  AlwaysPartial,
-
   /// Only create a potential archetype when it is well-formed (e.g., a nested
   /// type should exist) and make sure we have complete information about
   /// that potential archetype.
@@ -274,10 +270,6 @@
   GenericSignatureBuilder(const GenericSignatureBuilder &) = delete;
   GenericSignatureBuilder &operator=(const GenericSignatureBuilder &) = delete;
 
-  /// Record that the given potential archetype is unresolved, so we know to
-  /// resolve it later.
-  void recordUnresolvedType(PotentialArchetype *unresolvedPA);
-
   /// When a particular requirement cannot be resolved due to, e.g., a
   /// currently-unresolvable or nested type, this routine should be
   /// called to cope with the unresolved requirement.
@@ -315,10 +307,6 @@
                                              ProtocolDecl *Proto,
                                              const RequirementSource *Source);
 
-  /// Try to resolve the given unresolved potential archetype.
-  ConstraintResult resolveUnresolvedType(PotentialArchetype *pa,
-                                         bool allowTypoCorrection);
-
 public:
   /// \brief Add a new same-type requirement between two fully resolved types
   /// (output of \c GenericSignatureBuilder::resolve).
@@ -567,12 +555,6 @@
                 ArrayRef<GenericTypeParamType *> genericParams,
                 bool allowConcreteGenericParams=false);
 
-  /// Diagnose any remaining renames.
-  ///
-  /// \returns \c true if there were any remaining renames to diagnose.
-  bool diagnoseRemainingRenames(SourceLoc loc,
-                                ArrayRef<GenericTypeParamType *> genericParams);
-
   /// Process any delayed requirements that can be handled now.
   void processDelayedRequirements();
 
@@ -1294,21 +1276,14 @@
 
   /// The identifier describing this particular archetype.
   ///
-  /// \c parentOrBuilder determines whether we have a nested type vs. a root,
-  /// while `isUnresolvedNestedType` determines whether we have an unresolved
-  /// nested type (vs. a resolved one);
+  /// \c parentOrBuilder determines whether we have a nested type vs. a root.
   union PAIdentifier {
-    /// The name of an unresolved, nested type.
-    Identifier name;
-
     /// The associated type or typealias for a resolved nested type.
     TypeDecl *assocTypeOrConcrete;
 
     /// The generic parameter key for a root.
     GenericParamKey genericParam;
 
-    PAIdentifier(Identifier name) : name(name) { }
-
     PAIdentifier(AssociatedTypeDecl *assocType)
       : assocTypeOrConcrete(assocType) { }
 
@@ -1357,55 +1332,32 @@
   /// that share a name.
   llvm::MapVector<Identifier, StoredNestedType> NestedTypes;
 
-  /// Tracks the number of conformances that
-  unsigned numConformancesInNestedType = 0;
-
-  /// Whether this is an unresolved nested type.
-  unsigned isUnresolvedNestedType : 1;
-
   /// \brief Recursively conforms to itself.
   unsigned IsRecursive : 1;
 
-  /// Whether this potential archetype is invalid, e.g., because it could not
-  /// be resolved.
-  unsigned Invalid : 1;
-
-  /// Whether we have diagnosed a rename.
-  unsigned DiagnosedRename : 1;
-
-  /// If we have renamed this (nested) type due to typo correction,
-  /// the old name.
-  Identifier OrigName;
-
   /// \brief Construct a new potential archetype for an unresolved
   /// associated type.
   PotentialArchetype(PotentialArchetype *parent, Identifier name);
 
   /// \brief Construct a new potential archetype for an associated type.
   PotentialArchetype(PotentialArchetype *parent, AssociatedTypeDecl *assocType)
-    : parentOrBuilder(parent), identifier(assocType),
-      isUnresolvedNestedType(false), IsRecursive(false), Invalid(false),
-      DiagnosedRename(false)
+    : parentOrBuilder(parent), identifier(assocType), IsRecursive(false)
   {
     assert(parent != nullptr && "Not an associated type?");
   }
 
   /// \brief Construct a new potential archetype for a concrete declaration.
   PotentialArchetype(PotentialArchetype *parent, TypeDecl *concreteDecl)
-    : parentOrBuilder(parent), identifier(concreteDecl),
-      isUnresolvedNestedType(false),
-      IsRecursive(false), Invalid(false),
-      DiagnosedRename(false)
+    : parentOrBuilder(parent), identifier(concreteDecl), IsRecursive(false)
   {
     assert(parent != nullptr && "Not an associated type?");
   }
 
   /// \brief Construct a new potential archetype for a generic parameter.
-  PotentialArchetype(GenericSignatureBuilder *builder, GenericParamKey genericParam)
+  PotentialArchetype(GenericSignatureBuilder *builder,
+                     GenericParamKey genericParam)
     : parentOrBuilder(builder), identifier(genericParam),
-      isUnresolvedNestedType(false),
-      IsRecursive(false), Invalid(false),
-      DiagnosedRename(false)
+      IsRecursive(false)
   {
   }
 
@@ -1441,23 +1393,9 @@
   /// has been resolved.
   AssociatedTypeDecl *getResolvedAssociatedType() const {
     assert(getParent() && "Not an associated type");
-    if (isUnresolvedNestedType)
-      return nullptr;
-
     return dyn_cast<AssociatedTypeDecl>(identifier.assocTypeOrConcrete);
   }
 
-  /// Determine whether this PA is still unresolved.
-  bool isUnresolved() const { return isUnresolvedNestedType; }
-
-  /// Resolve the potential archetype to the given associated type.
-  void resolveAssociatedType(AssociatedTypeDecl *assocType,
-                             GenericSignatureBuilder &builder);
-
-  /// Resolve the potential archetype to the given typealias.
-  void resolveConcreteType(TypeDecl *concreteDecl,
-                           GenericSignatureBuilder &builder);
-
   /// Determine whether this is a generic parameter.
   bool isGenericParam() const {
     return parentOrBuilder.is<GenericSignatureBuilder *>();
@@ -1484,18 +1422,12 @@
   /// Retrieve the name of a nested potential archetype.
   Identifier getNestedName() const {
     assert(getParent() && "Not a nested type");
-    if (isUnresolvedNestedType)
-      return identifier.name;
-
     return identifier.assocTypeOrConcrete->getName();
   }
 
   /// Retrieve the concrete type declaration.
   TypeDecl *getConcreteTypeDecl() const {
     assert(getParent() && "not a nested type");
-    if (isUnresolvedNestedType)
-      return nullptr;
-
     if (isa<AssociatedTypeDecl>(identifier.assocTypeOrConcrete))
       return nullptr;
 
@@ -1649,12 +1581,7 @@
   ///
   /// \param genericParams The set of generic parameters to use in the resulting
   /// dependent type.
-  ///
-  /// \param allowUnresolved If true, allow the result to contain
-  /// \c DependentMemberType types with a name but no specific associated
-  /// type.
-  Type getDependentType(ArrayRef<GenericTypeParamType *> genericParams,
-                        bool allowUnresolved);
+  Type getDependentType(ArrayRef<GenericTypeParamType *> genericParams);
 
   /// True if the potential archetype has been bound by a concrete type
   /// constraint.
@@ -1676,32 +1603,6 @@
   void setIsRecursive() { IsRecursive = true; }
   bool isRecursive() const { return IsRecursive; }
 
-  bool isInvalid() const { return Invalid; }
-
-  void setInvalid() { Invalid = true; }
-
-  /// Determine whether this archetype was renamed due to typo
-  /// correction. If so, \c getName() retrieves the new name.
-  bool wasRenamed() const { return !OrigName.empty(); }
-
-  /// Note that this potential archetype was is going to be renamed (due to typo
-  /// correction), saving the old name.
-  void saveNameForRenaming() {
-    OrigName = getNestedName();
-  }
-
-  /// For a renamed potential archetype, retrieve the original name.
-  Identifier getOriginalName() const {
-    assert(wasRenamed());
-    return OrigName;
-  }
-
-  /// Whether we already diagnosed this rename.
-  bool alreadyDiagnosedRename() const { return DiagnosedRename; }
-
-  /// Note that we already diagnosed this rename.
-  void setAlreadyDiagnosedRename() { DiagnosedRename = true; }
-
   LLVM_ATTRIBUTE_DEPRECATED(
       void dump() const,
       "only for use within the debugger");
@@ -1725,9 +1626,6 @@
 
     /// A same-type requirement.
     SameType,
-
-    /// An unresolved potential archetype.
-    Unresolved,
   };
 
   Kind kind;
diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h
index 8486681..0f31173 100644
--- a/include/swift/AST/NameLookup.h
+++ b/include/swift/AST/NameLookup.h
@@ -288,7 +288,8 @@
                               Type BaseTy,
                               const DeclContext *CurrDC,
                               LazyResolver *typeResolver,
-                              bool includeInstanceMembers);
+                              bool includeInstanceMembers,
+                              GenericSignatureBuilder *GSB = nullptr);
 
 namespace namelookup {
 enum class ResolutionKind {
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 37d81e5..cbe1b71 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -469,6 +469,8 @@
   /// protocol, which line up with the conformance constraints in the
   /// protocol's requirement signature.
   ArrayRef<ProtocolConformanceRef> getSignatureConformances() const {
+    if (Resolver)
+      resolveLazyInfo();
     return SignatureConformances;
   }
 
diff --git a/include/swift/ClangImporter/ClangImporterOptions.h b/include/swift/ClangImporter/ClangImporterOptions.h
index 9704256..b3da68c 100644
--- a/include/swift/ClangImporter/ClangImporterOptions.h
+++ b/include/swift/ClangImporter/ClangImporterOptions.h
@@ -37,6 +37,9 @@
   /// Equivalent to Clang's -mcpu=.
   std::string TargetCPU;
 
+  /// The path to which we should store indexing data, if any.
+  std::string IndexStorePath;
+
   /// The bridging header or PCH that will be imported.
   std::string BridgingHeader;
 
diff --git a/include/swift/Driver/Types.def b/include/swift/Driver/Types.def
index 0306909..98cb9b3 100644
--- a/include/swift/Driver/Types.def
+++ b/include/swift/Driver/Types.def
@@ -61,6 +61,10 @@
 TYPE("tbd",             TBD,                "tbd",             "")
 TYPE("module-trace",    ModuleTrace,        "trace.json",      "")
 
+// BEGIN APPLE-ONLY OUTPUT TYPES
+TYPE("index-data",      IndexData,          "",                "")
+// END APPLE-ONLY OUTPUT TYPES
+
 // Misc types
 TYPE("pcm",             ClangModuleFile,    "pcm",             "")
 TYPE("pch",             PCH,                "pch",             "")
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 021e27b..92ce827 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -132,6 +132,12 @@
   /// The path to collect the group information for the compiled source files.
   std::string GroupInfoPath;
 
+  /// The path to which we should store indexing data, if any.
+  std::string IndexStorePath;
+
+  /// Emit index data for imported serialized swift system modules.
+  bool IndexSystemModules = false;
+
   /// If non-zero, warn when a function body takes longer than this many
   /// milliseconds to type-check.
   ///
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 356eb47..1a2c376 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -312,8 +312,8 @@
                                                 CanType associatedType,
                                                 ProtocolDecl *requirement) {
     unsigned index = 0;
-    for (auto &reqt : conformance->getProtocol()->getRequirementSignature()
-                                                ->getRequirements()) {
+    for (const auto &reqt :
+           conformance->getProtocol()->getRequirementSignature()) {
       if (reqt.getKind() == RequirementKind::Conformance &&
           reqt.getFirstType()->getCanonicalType() == associatedType &&
           reqt.getSecondType()->castTo<ProtocolType>()->getDecl() ==
@@ -328,9 +328,7 @@
   static std::pair<CanType, ProtocolDecl*>
   getAssociatedConformanceByIndex(const ProtocolConformance *conformance,
                                   unsigned index) {
-    auto &reqt =
-      conformance->getProtocol()->getRequirementSignature()
-                                ->getRequirements()[index];
+    auto &reqt = conformance->getProtocol()->getRequirementSignature()[index];
     assert(reqt.getKind() == RequirementKind::Conformance);
     return { reqt.getFirstType()->getCanonicalType(),
              reqt.getSecondType()->castTo<ProtocolType>()->getDecl() };
diff --git a/include/swift/Index/IndexRecord.h b/include/swift/Index/IndexRecord.h
new file mode 100644
index 0000000..8ddcb44
--- /dev/null
+++ b/include/swift/Index/IndexRecord.h
@@ -0,0 +1,83 @@
+//===--- IndexRecord.h - Entry point for recording index data ---*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_INDEX_INDEXRECORD_H
+#define SWIFT_INDEX_INDEXRECORD_H
+
+#include "swift/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace swift {
+class DependencyTracker;
+class ModuleDecl;
+class SourceFile;
+
+namespace index {
+
+/// Index the given source file and store the results to \p indexStorePath.
+///
+/// \param primarySourceFile The source file to index.
+///
+/// \param indexUnitToken A unique identifier for this translation unit in the
+/// form of a file path.
+///
+/// \param indexStorePath The location to write the indexing data to.
+///
+/// \param indexSystemModules If true, emit index data for imported serialized
+/// swift system modules.
+///
+/// \param isDebugCompilation true for non-optimized compiler invocation.
+///
+/// \param targetTriple The target for this compilation.
+///
+/// \param dependencyTracker The set of dependencies seen while building.
+bool indexAndRecord(SourceFile *primarySourceFile, StringRef indexUnitToken,
+                    StringRef indexStorePath, bool indexSystemModules,
+                    bool isDebugCompilation, StringRef targetTriple,
+                    const DependencyTracker &dependencyTracker);
+
+/// Index the given module and store the results to \p indexStorePath.
+///
+/// \param module The module to index.
+///
+/// \param indexUnitTokens A list of unique identifiers for the index units to
+/// be written. This may either be one unit per source file of \p module, or it
+/// may be a single unit, in which case all the index information will be
+/// combined into a single unit.
+///
+/// \param moduleUnitToken A unique identifier for this module unit in the form
+/// of a file path. Only used if \p indexUnitTokens are specified for each
+/// source file, otherwise the single \p indexUnitTokens value is used instead.
+///
+/// \param indexStorePath The location to write the indexing data to.
+///
+/// \param indexSystemModules If true, emit index data for imported serialized
+/// swift system modules.
+///
+/// \param isDebugCompilation true for non-optimized compiler invocation.
+///
+/// \param targetTriple The target for this compilation.
+///
+/// \param dependencyTracker The set of dependencies seen while building.
+bool indexAndRecord(ModuleDecl *module, ArrayRef<std::string> indexUnitTokens,
+                    StringRef moduleUnitToken, StringRef indexStorePath,
+                    bool indexSystemModules, bool isDebugCompilation,
+                    StringRef targetTriple,
+                    const DependencyTracker &dependencyTracker);
+// FIXME: indexUnitTokens could be StringRef, but that creates an impedance
+// mismatch in the caller.
+
+} // end namespace index
+} // end namespace swift
+
+#endif // SWIFT_INDEX_INDEXRECORD_H
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 4bc4968..d814367 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -414,6 +414,9 @@
     HelpText<"Use the pass pipeline defined by <pass_pipeline_file>">,
     MetaVarName<"<pass_pipeline_file>">;
 
+def index_system_modules : Flag<["-"], "index-system-modules">,
+  HelpText<"Emit index data for imported serialized swift system modules">;
+
 def dump_interface_hash : Flag<["-"], "dump-interface-hash">,
    HelpText<"Parse input file(s) and dump interface token hash(es)">,
    ModeOpt;
diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td
index 73b9261..2bdbe29 100644
--- a/include/swift/Option/Options.td
+++ b/include/swift/Option/Options.td
@@ -646,6 +646,18 @@
   HelpText<"Specify the type of coverage instrumentation for Sanitizers and"
   " additional options separated by commas">;
 
+def index_file : Flag<["-"], "index-file">,
+  HelpText<"Produce index data for a source file">, ModeOpt,
+  Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
+def index_file_path : Separate<["-"], "index-file-path">,
+  Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  HelpText<"Produce index data for file <path>">,
+  MetaVarName<"<path>">;
+
+def index_store_path : Separate<["-"], "index-store-path">,
+  Flags<[FrontendOption]>, MetaVarName<"<path>">,
+  HelpText<"Store indexing data to <path>">;
+
 def enforce_exclusivity_EQ : Joined<["-"], "enforce-exclusivity=">,
   Flags<[FrontendOption]>, MetaVarName<"<enforcement>">,
   HelpText<"Enforce law of exclusivity">;
diff --git a/include/swift/Option/SanitizerOptions.h b/include/swift/Option/SanitizerOptions.h
index f6d2360..2498b0e 100644
--- a/include/swift/Option/SanitizerOptions.h
+++ b/include/swift/Option/SanitizerOptions.h
@@ -28,7 +28,7 @@
 /// \brief Parses a -sanitize= argument's values.
 ///
 /// \param Diag If non null, the argument is used to diagnose invalid values.
-/// \param sanitizerRuntimeLibExists Function which checks for existance of a
+/// \param sanitizerRuntimeLibExists Function which checks for existence of a
 //         sanitizer dylib with a given name.
 /// \return Returns a SanitizerKind.
 SanitizerKind parseSanitizerArgValues(
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 2d7a40c..5cf71dc 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -977,15 +977,11 @@
     /// Any declaration attributes attached to the parameter.
     DeclAttributes Attrs;
 
-    /// The location of the 'let', 'var', or 'inout' keyword, if present.
-    SourceLoc LetVarInOutLoc;
-
-    enum SpecifierKindTy {
-      Let,
-      Var,
-      InOut
-    };
-    SpecifierKindTy SpecifierKind = Let; // Defaults to let.
+    /// The location of the 'inout' keyword, if present.
+    SourceLoc SpecifierLoc;
+    
+    /// The parsed specifier kind, if present.
+    VarDecl::Specifier SpecifierKind = VarDecl::Specifier::None;
 
     /// The location of the first name.
     ///
@@ -1097,7 +1093,8 @@
                                                        bool isExprBasic);
   
 
-  Pattern *createBindingFromPattern(SourceLoc loc, Identifier name, bool isLet);
+  Pattern *createBindingFromPattern(SourceLoc loc, Identifier name,
+                                    VarDecl::Specifier specifier);
   
 
   /// \brief Determine whether this token can only start a matching pattern
diff --git a/include/swift/SIL/SILWitnessVisitor.h b/include/swift/SIL/SILWitnessVisitor.h
index 0c86079..bffa77a 100644
--- a/include/swift/SIL/SILWitnessVisitor.h
+++ b/include/swift/SIL/SILWitnessVisitor.h
@@ -64,8 +64,7 @@
       }
     };
 
-    for (auto &reqt : protocol->getRequirementSignature()
-                              ->getCanonicalSignature()->getRequirements()) {
+    for (const auto &reqt : protocol->getRequirementSignature()) {
       switch (reqt.getKind()) {
       // These requirements don't show up in the witness table.
       case RequirementKind::Superclass:
@@ -74,10 +73,11 @@
         continue;
 
       case RequirementKind::Conformance: {
-        auto type = CanType(reqt.getFirstType());
+        auto type = reqt.getFirstType()->getCanonicalType();
         assert(type->isTypeParameter());
         auto requirement =
-          cast<ProtocolType>(CanType(reqt.getSecondType()))->getDecl();
+          cast<ProtocolType>(reqt.getSecondType()->getCanonicalType())
+            ->getDecl();
 
         // ObjC protocols do not have witnesses.
         if (!Lowering::TypeConverter::protocolRequiresWitnessTable(requirement))
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index a90a8d2..9910471 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
 /// in source control, you should also update the comment to briefly
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 347; // Last change: 'inout' on parameter types
+const uint16_t VERSION_MINOR = 348; // Last change: 'inout' in parameter decls.
 
 using DeclID = PointerEmbeddedInt<unsigned, 31>;
 using DeclIDField = BCFixed<31>;
@@ -191,6 +191,15 @@
 
 // These IDs must \em not be renumbered or reordered without incrementing
 // VERSION_MAJOR.
+enum class VarDeclSpecifier : uint8_t {
+  Let = 0,
+  Var,
+  InOut,
+};
+using VarDeclSpecifierField = BCFixed<2>;
+  
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
 enum class ParameterConvention : uint8_t {
   Indirect_In,
   Indirect_Inout,
@@ -227,7 +236,7 @@
   NotAddressor, Unsafe, Owning, NativeOwning, NativePinning
 };
 using AddressorKindField = BCFixed<3>;
-
+  
 /// Translates an operator DeclKind to a Serialization fixity, whose values are
 /// guaranteed to be stable.
 static inline OperatorKind getStableFixity(DeclKind kind) {
@@ -876,7 +885,7 @@
     BCFixed<1>,   // implicit?
     BCFixed<1>,   // explicitly objc?
     BCFixed<1>,   // static?
-    BCFixed<1>,   // isLet?
+    VarDeclSpecifierField,   // specifier
     BCFixed<1>,   // HasNonPatternBindingInit?
     StorageKindField,   // StorageKind
     TypeIDField,  // interface type
@@ -898,7 +907,7 @@
     IdentifierIDField, // argument name
     IdentifierIDField, // parameter name
     DeclContextIDField,  // context decl
-    BCFixed<1>,   // isLet?
+    VarDeclSpecifierField,   // specifier
     TypeIDField  // interface type
   >;
 
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index af4e858..75cc493 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -676,7 +676,9 @@
 
       OS << " requirement signature=";
       if (PD->isRequirementSignatureComputed()) {
-        OS << PD->getRequirementSignature()->getAsString();
+        OS << GenericSignature::get({PD->getProtocolSelfType()} ,
+                                    PD->getRequirementSignature())
+                ->getAsString();
       } else {
         OS << "<null>";
       }
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index b845ca2..c614e7f 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -1367,7 +1367,9 @@
   if (isa<AssociatedTypeDecl>(attachingTo))
     flags |= SwapSelfAndDependentMemberType;
   printGenericSignature(
-      proto->getRequirementSignature(), flags,
+      GenericSignature::get({proto->getProtocolSelfType()} ,
+                            proto->getRequirementSignature()),
+      flags,
       [&](const Requirement &req) {
         auto location = bestRequirementPrintLocation(proto, req);
         return location.AttachedTo == attachingTo && location.InWhereClause;
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 8bd66bc..72b71c7 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -2348,7 +2348,7 @@
       if (!normal->isInvalid()){
         auto conformances = normal->getSignatureConformances();
         unsigned idx = 0;
-        for (auto req : proto->getRequirementSignature()->getRequirements()) {
+        for (const auto &req : proto->getRequirementSignature()) {
           if (req.getKind() != RequirementKind::Conformance)
             continue;
 
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index c2f28ec..755517c 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -158,7 +158,7 @@
 
   SmallVector<ParamDecl*, 4> params;
   for (Type argType : argTypes) {
-    auto PD = new (Context) ParamDecl(/*IsLet*/true, SourceLoc(), SourceLoc(),
+    auto PD = new (Context) ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(),
                                       Identifier(), SourceLoc(),
                                       Identifier(), argType,
                                       DC);
@@ -217,7 +217,7 @@
   for (unsigned i = 0, e = ArgParamTypes.size(); i < e; i++) {
     auto paramType = ArgBodyTypes[i];
     auto paramIfaceType = ArgParamTypes[i].getType();
-    auto PD = new (Context) ParamDecl(/*IsLet*/true, SourceLoc(), SourceLoc(),
+    auto PD = new (Context) ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(),
                                       Identifier(), SourceLoc(),
                                       Identifier(), paramType, DC);
     PD->setInterfaceType(paramIfaceType);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 9857e63..cd3c392 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1681,7 +1681,7 @@
         if (auto funcTy = signature.InterfaceType->getAs<AnyFunctionType>()) {
           signature.InterfaceType
             = GenericFunctionType::get(genericSig,
-                                       funcTy->getInput(),
+                                       funcTy->getParams(),
                                        funcTy->getResult(),
                                        funcTy->getExtInfo())
                 ->getCanonicalType();
@@ -2861,10 +2861,11 @@
   ProtocolDeclBits.RequiresClass = false;
   ProtocolDeclBits.ExistentialConformsToSelfValid = false;
   ProtocolDeclBits.ExistentialConformsToSelf = false;
-  KnownProtocol = 0;
   ProtocolDeclBits.Circularity
     = static_cast<unsigned>(CircularityCheck::Unchecked);
   HasMissingRequirements = false;
+  KnownProtocol = 0;
+  NumRequirementsInSignature = 0;
 }
 
 llvm::TinyPtrVector<ProtocolDecl *>
@@ -2895,7 +2896,7 @@
 
   // Gather inherited protocols from the requirement signature.
   auto selfType = getProtocolSelfType();
-  for (auto req : getRequirementSignature()->getRequirements()) {
+  for (const auto &req : getRequirementSignature()) {
     if (req.getKind() == RequirementKind::Conformance &&
         req.getFirstType()->isEqual(selfType))
       result.push_back(req.getSecondType()->castTo<ProtocolType>()->getDecl());
@@ -3020,9 +3021,8 @@
   // Tuples preserve variance.
   if (auto tuple = type->getAs<TupleType>()) {
     auto kind = SelfReferenceKind::None();
-    for (auto &elt: tuple->getElements()) {
-      kind |= findProtocolSelfReferences(proto, elt.getType(),
-                                         skipAssocTypes);
+    for (auto &elt : tuple->getElements()) {
+      kind |= findProtocolSelfReferences(proto, elt.getType(), skipAssocTypes);
     }
     return kind;
   } 
@@ -3030,8 +3030,11 @@
   // Function preserve variance in the result type, and flip variance in
   // the parameter type.
   if (auto funcTy = type->getAs<AnyFunctionType>()) {
-    auto inputKind = findProtocolSelfReferences(proto, funcTy->getInput(),
-                                                skipAssocTypes);
+    auto inputKind = SelfReferenceKind::None();
+    for (auto &elt : funcTy->getParams()) {
+      inputKind |= findProtocolSelfReferences(proto, elt.getType(),
+                                              skipAssocTypes);
+    }
     auto resultKind = findProtocolSelfReferences(proto, funcTy->getResult(),
                                                  skipAssocTypes);
 
@@ -3299,8 +3302,23 @@
          GenericSignatureBuilder::RequirementSource
            ::forRequirementSignature(selfPA, this),
          nullptr);
-  
-  RequirementSignature = builder.computeGenericSignature(SourceLoc());
+
+  // Compute and record the signature.
+  auto requirementSig = builder.computeGenericSignature(SourceLoc());
+  RequirementSignature = requirementSig->getRequirements().data();
+  assert(RequirementSignature != nullptr);
+  NumRequirementsInSignature = requirementSig->getRequirements().size();
+}
+
+void ProtocolDecl::setRequirementSignature(ArrayRef<Requirement> requirements) {
+  assert(!RequirementSignature && "already computed requirement signature");
+  if (requirements.empty()) {
+    RequirementSignature = reinterpret_cast<Requirement *>(this + 1);
+    NumRequirementsInSignature = 0;
+  } else {
+    RequirementSignature = getASTContext().AllocateCopy(requirements).data();
+    NumRequirementsInSignature = requirements.size();
+  }
 }
 
 /// Returns the default witness for a requirement, or nullptr if there is
@@ -4113,25 +4131,27 @@
   }
 }
 
-ParamDecl::ParamDecl(bool isLet,
-                     SourceLoc letVarInOutLoc, SourceLoc argumentNameLoc,
+ParamDecl::ParamDecl(Specifier specifier,
+                     SourceLoc specifierLoc, SourceLoc argumentNameLoc,
                      Identifier argumentName, SourceLoc parameterNameLoc,
                      Identifier parameterName, Type ty, DeclContext *dc)
-  : VarDecl(DeclKind::Param, /*IsStatic*/false, /*IsLet*/isLet,
+  : VarDecl(DeclKind::Param, /*IsStatic*/false, specifier,
             /*IsCaptureList*/false, parameterNameLoc, parameterName, ty, dc),
   ArgumentName(argumentName), ArgumentNameLoc(argumentNameLoc),
-  LetVarInOutLoc(letVarInOutLoc) {
+  SpecifierLoc(specifierLoc) {
+    assert(specifier != Specifier::Var &&
+           "'var' cannot appear on parameters; you meant 'inout'");
 }
 
 /// Clone constructor, allocates a new ParamDecl identical to the first.
 /// Intentionally not defined as a copy constructor to avoid accidental copies.
 ParamDecl::ParamDecl(ParamDecl *PD)
-  : VarDecl(DeclKind::Param, /*IsStatic*/false, /*IsLet*/PD->isLet(),
+  : VarDecl(DeclKind::Param, /*IsStatic*/false, PD->getSpecifier(),
             /*IsCaptureList*/false, PD->getNameLoc(), PD->getName(),
             PD->hasType() ? PD->getType() : Type(), PD->getDeclContext()),
     ArgumentName(PD->getArgumentName()),
     ArgumentNameLoc(PD->getArgumentNameLoc()),
-    LetVarInOutLoc(PD->getLetVarInOutLoc()),
+    SpecifierLoc(PD->getSpecifierLoc()),
     DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()),
     IsTypeLocImplicit(PD->IsTypeLocImplicit),
     defaultArgumentKind(PD->defaultArgumentKind) {
@@ -4172,7 +4192,7 @@
 /// generic parameters.
 ParamDecl *ParamDecl::createUnboundSelf(SourceLoc loc, DeclContext *DC) {
   ASTContext &C = DC->getASTContext();
-  auto *selfDecl = new (C) ParamDecl(/*IsLet*/true, SourceLoc(), SourceLoc(),
+  auto *selfDecl = new (C) ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(),
                                      Identifier(), loc, C.Id_self, Type(), DC);
   selfDecl->setImplicit();
   return selfDecl;
@@ -4192,6 +4212,7 @@
   ASTContext &C = DC->getASTContext();
   auto selfType = DC->getSelfTypeInContext();
   auto selfInterfaceType = DC->getSelfInterfaceType();
+  auto specifier = VarDecl::Specifier::None;
   assert(selfType && selfInterfaceType);
 
   if (isStaticMethod) {
@@ -4202,9 +4223,10 @@
   if (isInOut) {
     selfType = InOutType::get(selfType);
     selfInterfaceType = InOutType::get(selfInterfaceType);
+    specifier = VarDecl::Specifier::InOut;
   }
 
-  auto *selfDecl = new (C) ParamDecl(/*IsLet*/!isInOut, SourceLoc(),SourceLoc(),
+  auto *selfDecl = new (C) ParamDecl(specifier, SourceLoc(),SourceLoc(),
                                      Identifier(), loc, C.Id_self, selfType,DC);
   selfDecl->setImplicit();
   selfDecl->setInterfaceType(selfInterfaceType);
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index 95bd2af..0ab5f82 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -105,14 +105,6 @@
 GenericTypeParamType *DeclContext::getProtocolSelfType() const {
   assert(getAsProtocolOrProtocolExtensionContext() && "not a protocol");
 
-  // FIXME: This comes up when the extension didn't resolve,
-  // and we have a protocol nested inside that extension
-  // (which is not allowed in the first place).
-  //
-  // Handle this more systematically elsewhere.
-  if (!isInnermostContextGeneric())
-    return nullptr;
-
   return getGenericParamsOfContext()->getParams().front()
       ->getDeclaredInterfaceType()
       ->castTo<GenericTypeParamType>();
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 5c5a50f..9870f8f 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -709,7 +709,7 @@
       return getCanonicalTypeInContext(rep->getConcreteType(), builder);
     }
 
-    return rep->getDependentType(getGenericParams(), /*allowUnresolved*/ false);
+    return rep->getDependentType(getGenericParams());
   });
   
   auto result = type->getCanonicalType();
@@ -793,13 +793,13 @@
 
 #ifndef NDEBUG
   // Local function to determine whether there is a conformance of the given
-  // subject type to the given protocol within the given generic signature's
-  // explicit requirements.
-  auto hasConformanceInSignature = [&](const GenericSignature *genericSig,
+  // subject type to the given protocol within the given set of explicit
+  // requirements.
+  auto hasConformanceInSignature = [&](ArrayRef<Requirement> requirements,
                                        Type subjectType,
                                        ProtocolDecl *proto) -> bool {
     // Make sure this requirement exists in the requirement signature.
-    for (const auto& req: genericSig->getRequirements()) {
+    for (const auto& req: requirements) {
       if (req.getKind() == RequirementKind::Conformance &&
           req.getFirstType()->isEqual(subjectType) &&
           req.getSecondType()->castTo<ProtocolType>()->getDecl()
@@ -814,16 +814,27 @@
 
   // Local function to construct the conformance access path from the
   // requirement.
-  std::function<void(GenericSignature *, const RequirementSource *,
-                     ProtocolDecl *, Type)> buildPath;
-  buildPath = [&](GenericSignature *sig, const RequirementSource *source,
-                  ProtocolDecl *conformingProto, Type rootType) {
+  std::function<void(ArrayRef<Requirement>, const RequirementSource *,
+                     ProtocolDecl *, Type, ProtocolDecl *)> buildPath;
+  buildPath = [&](ArrayRef<Requirement> reqs, const RequirementSource *source,
+                  ProtocolDecl *conformingProto, Type rootType,
+                  ProtocolDecl *requirementSignatureProto) {
     // Each protocol requirement is a step along the path.
     if (source->isProtocolRequirement()) {
+      // If we're expanding for a protocol that has no requirement signature
+      // (yet) and have hit the penultimate step, this is the last step
+      // that would occur in the requirement signature.
+      if (!source->parent->parent && requirementSignatureProto) {
+        Type subjectType = source->getStoredType()->getCanonicalType();
+        path.path.push_back({subjectType, conformingProto});
+        return;
+      }
+
       // Follow the rest of the path to derive the conformance into which
       // this particular protocol requirement step would look.
       auto inProtocol = source->getProtocolDecl();
-      buildPath(sig, source->parent, inProtocol, rootType);
+      buildPath(reqs, source->parent, inProtocol, rootType,
+                requirementSignatureProto);
       assert(path.path.back().second == inProtocol &&
              "path produces incorrect conformance");
 
@@ -857,11 +868,10 @@
                "missing signature");
       }
 
-      // Get a generic signature builder for the requirement signature. This has
-      // the requirement we need.
-      auto reqSig = inProtocol->getRequirementSignature();
-      auto &reqSigBuilder = *reqSig->getGenericSignatureBuilder(
-                                               *inProtocol->getModuleContext());
+      // Get a generic signature for the protocol's signature.
+      auto inProtoSig = inProtocol->getGenericSignature();
+      auto &inProtoSigBuilder = *inProtoSig->getGenericSignatureBuilder(
+                                                                *inProtocol->getModuleContext());
 
       // Retrieve the stored type, but erase all of the specific associated
       // type declarations; we don't want any details of the enclosing context
@@ -870,9 +880,9 @@
 
       // Dig out the potential archetype for this stored type.
       auto pa =
-        reqSigBuilder.resolveArchetype(
+        inProtoSigBuilder.resolveArchetype(
                                  storedType,
-                                 ArchetypeResolutionKind::AlwaysPartial);
+                                 ArchetypeResolutionKind::WellFormed);
       auto equivClass = pa->getOrCreateEquivalenceClass();
 
       // Find the conformance of this potential archetype to the protocol in
@@ -881,17 +891,17 @@
       assert(conforms != equivClass->conformsTo.end());
 
       // Compute the root type, canonicalizing it w.r.t. the protocol context.
-      auto inProtoSig = inProtocol->getGenericSignature();
       auto conformsSource = getBestRequirementSource(conforms->second);
+      assert(conformsSource != source || !requirementSignatureProto);
       Type localRootType = conformsSource->getRootPotentialArchetype()
-                             ->getDependentType(inProtoSig->getGenericParams(),
-                                                /*allowUnresolved*/true);
+                             ->getDependentType(inProtoSig->getGenericParams());
       localRootType = inProtoSig->getCanonicalTypeInContext(
                                                localRootType,
                                                *inProtocol->getModuleContext());
 
       // Build the path according to the requirement signature.
-      buildPath(reqSig, conformsSource, conformingProto, localRootType);
+      buildPath(inProtocol->getRequirementSignature(), conformsSource,
+                conformingProto, localRootType, inProtocol);
 
       // We're done.
       return;
@@ -899,7 +909,8 @@
 
     // If we still have a parent, keep going.
     if (source->parent) {
-      buildPath(sig, source->parent, conformingProto, rootType);
+      buildPath(reqs, source->parent, conformingProto, rootType,
+                requirementSignatureProto);
       return;
     }
 
@@ -914,7 +925,7 @@
         rootType->isEqual(conformingProto->getSelfInterfaceType()))
       return;
 
-    assert(hasConformanceInSignature(sig, rootType, conformingProto) &&
+    assert(hasConformanceInSignature(reqs, rootType, conformingProto) &&
            "missing explicit conformance in signature");
 
     // Add the root of the path, which starts at this explicit requirement.
@@ -925,11 +936,10 @@
   auto source = getBestRequirementSource(conforms->second);
   auto subjectPA = source->getRootPotentialArchetype();
   subjectPA = subjectPA->getArchetypeAnchor(*subjectPA->getBuilder());
-  Type rootType = subjectPA->getDependentType(getGenericParams(),
-                                              /*allowUnresolved=*/false);
+  Type rootType = subjectPA->getDependentType(getGenericParams());
 
   // Build the path.
-  buildPath(this, source, protocol, rootType);
+  buildPath(getRequirements(), source, protocol, rootType, nullptr);
 
   // Return the path; we're done!
   return path;
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 05574b7..981d26e 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -85,9 +85,6 @@
   /// The potential archetypes for the generic parameters in \c GenericParams.
   SmallVector<PotentialArchetype *, 4> PotentialArchetypes;
 
-  /// The nested types that have been renamed.
-  SmallVector<PotentialArchetype *, 4> RenamedNestedTypes;
-
   /// The requirement sources used in this generic signature builder.
   llvm::FoldingSet<RequirementSource> RequirementSources;
 
@@ -1100,16 +1097,6 @@
   return false;
 }
 
-PotentialArchetype::PotentialArchetype(PotentialArchetype *parent,
-                                       Identifier name)
-  : parentOrBuilder(parent), identifier(name), isUnresolvedNestedType(true),
-  IsRecursive(false), Invalid(false),
-  DiagnosedRename(false)
-{
-  assert(parent != nullptr && "Not an associated type?");
-  getBuilder()->recordUnresolvedType(this);
-}
-
 GenericSignatureBuilder::PotentialArchetype::~PotentialArchetype() {
   ++NumPotentialArchetypes;
 
@@ -1167,24 +1154,6 @@
   return Depth;
 }
 
-void GenericSignatureBuilder::PotentialArchetype::resolveAssociatedType(
-       AssociatedTypeDecl *assocType,
-       GenericSignatureBuilder &builder) {
-  assert(isUnresolvedNestedType && "associated type is already resolved");
-  isUnresolvedNestedType = false;
-  identifier.assocTypeOrConcrete = assocType;
-  assert(assocType->getName() == getNestedName());
-}
-
-void GenericSignatureBuilder::PotentialArchetype::resolveConcreteType(
-       TypeDecl *concreteDecl,
-       GenericSignatureBuilder &builder) {
-  assert(isUnresolvedNestedType && "nested type is already resolved");
-  isUnresolvedNestedType = false;
-  identifier.assocTypeOrConcrete = concreteDecl;
-  assert(concreteDecl->getName() == getNestedName());
-}
-
 Optional<ConcreteConstraint>
 EquivalenceClass::findAnyConcreteConstraintAsWritten(
                                       PotentialArchetype *preferredPA) const {
@@ -1281,13 +1250,6 @@
   dump(llvm::errs());
 }
 
-void GenericSignatureBuilder::recordUnresolvedType(
-                                          PotentialArchetype *unresolvedPA) {
-  Impl->DelayedRequirements.push_back(
-    {DelayedRequirement::Unresolved, unresolvedPA, RequirementRHS(),
-     FloatingRequirementSource::forAbstract()});
-}
-
 ConstraintResult GenericSignatureBuilder::handleUnresolvedRequirement(
                                    RequirementKind kind,
                                    UnresolvedType lhs,
@@ -1338,8 +1300,7 @@
 
   // Lookup the conformance of the concrete type to this protocol.
   auto conformance =
-    getLookupConformanceFn()(pa->getDependentType({ }, /*allowUnresolved=*/true)
-                               ->getCanonicalType(),
+    getLookupConformanceFn()(pa->getDependentType({ })->getCanonicalType(),
                              concrete,
                              proto->getDeclaredInterfaceType()
                               ->castTo<ProtocolType>());
@@ -1369,8 +1330,7 @@
 
   // Lookup the conformance of the superclass to this protocol.
   auto conformance =
-    getLookupConformanceFn()(pa->getDependentType({ }, /*allowUnresolved=*/true)
-                               ->getCanonicalType(),
+    getLookupConformanceFn()(pa->getDependentType({ })->getCanonicalType(),
                              superclass,
                              proto->getDeclaredInterfaceType()
                                ->castTo<ProtocolType>());
@@ -1643,17 +1603,6 @@
       return result;
   }
 
-  // Along the error path where one or both of the potential archetypes was
-  // renamed due to typo correction,
-  if (a->wasRenamed() || b->wasRenamed()) {
-    if (a->wasRenamed() != b->wasRenamed())
-      return a->wasRenamed() ? +1 : -1;
-
-    if (int compareNames = a->getOriginalName().str().compare(
-                                                    b->getOriginalName().str()))
-      return compareNames;
-  }
-
   llvm_unreachable("potential archetype total order failure");
 }
 
@@ -1895,38 +1844,7 @@
       resultPA = concreteDeclPA;
   }
 
-  if (resultPA)
-    return resultPA;
-
-  // Check whether we can add a missing nested type for this case.
-  switch (kind) {
-  case ArchetypeResolutionKind::AlwaysPartial:
-    break;
-
-  case ArchetypeResolutionKind::WellFormed:
-  case ArchetypeResolutionKind::CompleteWellFormed:
-  case ArchetypeResolutionKind::AlreadyKnown:
-    return nullptr;
-  }
-
-  // Build an unresolved type if we don't have one yet.
-  auto &nested = NestedTypes[name];
-  if (nested.empty()) {
-    nested.push_back(new PotentialArchetype(this, name));
-
-    auto rep = getRepresentative();
-    if (rep != this) {
-      auto existingPA = rep->getNestedType(name, kind, builder);
-
-      auto sameNamedSource =
-        RequirementSource::forNestedTypeNameMatch(existingPA);
-      builder.addSameTypeRequirement(
-                                 existingPA, nested.back(), sameNamedSource,
-                                 UnresolvedHandlingKind::GenerateConstraints);
-    }
-  }
-
-  return nested.front();
+  return resultPA;
 }
 
 
@@ -1987,20 +1905,6 @@
   auto &builder = *getBuilder();
   if (knownNestedTypes != NestedTypes.end()) {
     for (auto existingPA : knownNestedTypes->second) {
-      // Resolve an unresolved potential archetype.
-      if (existingPA->isUnresolvedNestedType) {
-        if (assocType) {
-          existingPA->resolveAssociatedType(assocType, builder);
-        } else {
-          existingPA->resolveConcreteType(concreteDecl, builder);
-        }
-
-        // We've resolved this nested type; nothing more to do.
-        resultPA = existingPA;
-        shouldUpdatePA = true;
-        break;
-      }
-
       // Do we have an associated-type match?
       if (assocType && existingPA->getResolvedAssociatedType() == assocType) {
         resultPA = existingPA;
@@ -2018,7 +1922,6 @@
   // If we don't have a result potential archetype yet, we may need to add one.
   if (!resultPA) {
     switch (kind) {
-    case ArchetypeResolutionKind::AlwaysPartial:
     case ArchetypeResolutionKind::CompleteWellFormed:
     case ArchetypeResolutionKind::WellFormed: {
       if (assocType)
@@ -2087,8 +1990,7 @@
           // Substitute in the type of the current PotentialArchetype in
           // place of 'Self' here.
           auto subMap = SubstitutionMap::getProtocolSubstitutions(
-            proto, getDependentType(/*genericParams=*/{},
-                                    /*allowUnresolved=*/true),
+            proto, getDependentType(/*genericParams=*/{}),
             ProtocolConformanceRef(proto));
           type = type.subst(subMap, SubstFlags::UseErrorType);
         } else {
@@ -2153,8 +2055,7 @@
     // If this has a recursive type, return an error type.
     auto equivClass = representative->getEquivalenceClassIfPresent();
     if (equivClass->recursiveConcreteType) {
-      return ErrorType::get(getDependentType(genericParams,
-                                             /*allowUnresolved=*/true));
+      return ErrorType::get(getDependentType(genericParams));
     }
 
     return genericEnv->mapTypeIntoContext(concreteType,
@@ -2181,8 +2082,7 @@
     // proper nested type.
     auto parentTy = parent->getTypeInContext(builder, genericEnv);
     if (!parentTy)
-      return ErrorType::get(getDependentType(genericParams,
-                                             /*allowUnresolved=*/true));
+      return ErrorType::get(getDependentType(genericParams));
 
     ParentArchetype = parentTy->getAs<ArchetypeType>();
     if (!ParentArchetype) {
@@ -2191,7 +2091,7 @@
       (void) resolver;
 
       // Resolve the member type.
-      auto type = getDependentType(genericParams, /*allowUnresolved=*/false);
+      auto type = getDependentType(genericParams);
       if (type->hasError())
         return type;
 
@@ -2270,8 +2170,7 @@
     // If we were unable to resolve this as an associated type, produce an
     // error type.
     if (!assocType) {
-      return ErrorType::get(getDependentType(genericParams,
-                                             /*allowUnresolved=*/true));
+      return ErrorType::get(getDependentType(genericParams));
     }
 
     // Create a nested archetype.
@@ -2316,11 +2215,9 @@
 }
 
 Type GenericSignatureBuilder::PotentialArchetype::getDependentType(
-                                ArrayRef<GenericTypeParamType *> genericParams,
-                                bool allowUnresolved) {
+                                ArrayRef<GenericTypeParamType *> genericParams){
   if (auto parent = getParent()) {
-    Type parentType = parent->getDependentType(genericParams,
-                                               allowUnresolved);
+    Type parentType = parent->getDependentType(genericParams);
     if (parentType->hasError())
       return parentType;
 
@@ -2328,11 +2225,6 @@
     if (auto assocType = getResolvedAssociatedType())
       return DependentMemberType::get(parentType, assocType);
 
-    // If we don't allow unresolved dependent member types, fail.
-    if (!allowUnresolved)
-      return ErrorType::get(getDependentType(genericParams,
-                                             /*allowUnresolved=*/true));
-
     return DependentMemberType::get(parentType, getNestedName());
   }
   
@@ -2530,7 +2422,7 @@
 
     // Determine what kind of resolution we want.
     ArchetypeResolutionKind resolutionKind =
-      ArchetypeResolutionKind::AlwaysPartial;
+      ArchetypeResolutionKind::WellFormed;
     if (!source.isExplicit() && source.isRecursive(type, *this))
       resolutionKind = ArchetypeResolutionKind::AlreadyKnown;
 
@@ -2620,7 +2512,7 @@
   if (!PAT->addConformance(Proto, Source, *this))
     return ConstraintResult::Resolved;
 
-  auto concreteSelf = PAT->getDependentType({}, /*allowUnresolved=*/true);
+  auto concreteSelf = PAT->getDependentType({});
   auto protocolSubMap = SubstitutionMap::getProtocolSubstitutions(
       Proto, concreteSelf, ProtocolConformanceRef(Proto));
 
@@ -2628,12 +2520,10 @@
   // cannot compute the requirement signature directly, because that may be
   // infinitely recursive: this code is also used to construct it.
   if (Proto->isRequirementSignatureComputed()) {
-    auto reqSig = Proto->getRequirementSignature();
-
     auto innerSource =
       FloatingRequirementSource::viaProtocolRequirement(Source, Proto,
                                                         /*inferred=*/false);
-    for (auto req : reqSig->getRequirements()) {
+    for (const auto &req : Proto->getRequirementSignature()) {
       auto reqResult = addRequirement(req, innerSource, nullptr,
                                       &protocolSubMap);
       if (isErrorResult(reqResult)) return reqResult;
@@ -2904,101 +2794,6 @@
   return ConstraintResult::Resolved;
 }
 
-/// Perform typo correction on the given nested type, producing the
-/// corrected name (if successful).
-static AssociatedTypeDecl *typoCorrectNestedType(
-                             GenericSignatureBuilder::PotentialArchetype *pa) {
-  StringRef name = pa->getNestedName().str();
-
-  // Look through all of the associated types of all of the protocols
-  // to which the parent conforms.
-  llvm::SmallVector<AssociatedTypeDecl *, 2> bestMatches;
-  unsigned bestEditDistance = UINT_MAX;
-  unsigned maxScore = (name.size() + 1) / 3;
-  for (auto proto : pa->getParent()->getConformsTo()) {
-    for (auto member : getProtocolMembers(proto)) {
-      auto assocType = dyn_cast<AssociatedTypeDecl>(member);
-      if (!assocType)
-        continue;
-
-      unsigned dist = name.edit_distance(assocType->getName().str(),
-                                         /*AllowReplacements=*/true,
-                                         maxScore);
-      assert(dist > 0 && "nested type should have matched associated type");
-      if (dist < bestEditDistance) {
-        maxScore = bestEditDistance = dist;
-        bestMatches.clear();
-      }
-      if (dist == bestEditDistance)
-        bestMatches.push_back(assocType);
-    }
-  }
-
-  // FIXME: Look through the superclass.
-
-  // If we didn't find any matches at all, fail.
-  if (bestMatches.empty())
-    return nullptr;
-
-  // Make sure that we didn't find more than one match at the best
-  // edit distance.
-  for (auto other : llvm::makeArrayRef(bestMatches).slice(1)) {
-    if (other != bestMatches.front())
-      return nullptr;
-  }
-
-  return bestMatches.front();
-}
-
-ConstraintResult GenericSignatureBuilder::resolveUnresolvedType(
-                                          PotentialArchetype *pa,
-                                          bool allowTypoCorrection) {
-  // If something else resolved this type, we're done.
-  if (!pa->isUnresolved())
-    return ConstraintResult::Resolved;
-
-  // If the parent isn't resolved, we can't resolve this now.
-  auto parentPA = pa->getParent();
-  if (parentPA->isUnresolved())
-    return ConstraintResult::Unresolved;
-
-  // Resolve this via its parent.
-  auto resolvedPA =
-    parentPA->getNestedArchetypeAnchor(
-                        pa->getNestedName(),
-                        *this,
-                        ArchetypeResolutionKind::WellFormed);
-  if (resolvedPA) {
-    assert(!pa->isUnresolved() && "This type must have been resolved");
-    return ConstraintResult::Resolved;
-  }
-
-  // If we aren't allowed to perform typo correction, we can't resolve the
-  // constraint.
-  if (!allowTypoCorrection)
-    return ConstraintResult::Unresolved;
-
-  // Try to typo correct to a nested type name.
-  auto correction = typoCorrectNestedType(pa);
-  if (!correction) {
-    pa->setInvalid();
-    return ConstraintResult::Conflicting;
-  }
-
-  // Note that this is being renamed.
-  pa->saveNameForRenaming();
-  Impl->RenamedNestedTypes.push_back(pa);
-
-  // Resolve the associated type and merge the potential archetypes.
-  auto replacement = pa->getParent()->getNestedType(correction, *this);
-  pa->resolveAssociatedType(correction, *this);
-  addSameTypeRequirement(pa, replacement,
-                         RequirementSource::forNestedTypeNameMatch(pa),
-                         UnresolvedHandlingKind::GenerateConstraints);
-
-  return ConstraintResult::Resolved;
-}
-
 ConstraintResult GenericSignatureBuilder::addLayoutRequirementDirect(
                                              PotentialArchetype *PAT,
                                              LayoutConstraint Layout,
@@ -3084,24 +2879,11 @@
     }
   };
 
-  // Local function to resolve nested types found in the superclass.
-  auto updateSuperclassNestedTypes = [&] {
-    for (auto &nested : T->getNestedTypes()) {
-      if (nested.second.empty()) continue;
-      if (nested.second.front()->isUnresolved()) {
-        (void)T->getNestedArchetypeAnchor(
-                                        nested.first, *this,
-                                        ArchetypeResolutionKind::AlreadyKnown);
-      }
-    }
-  };
-
   // If we haven't yet recorded a superclass constraint for this equivalence
   // class, do so now.
   if (!equivClass->superclass) {
     equivClass->superclass = superclass;
     updateSuperclassConformances();
-    updateSuperclassNestedTypes();
 
     // Presence of a superclass constraint implies a _Class layout
     // constraint.
@@ -3133,7 +2915,6 @@
 
     // We've strengthened the bound, so update superclass conformances.
     updateSuperclassConformances();
-    updateSuperclassNestedTypes();
     return;
   }
 
@@ -3180,9 +2961,7 @@
   if (auto constraintPA = resolvedConstraint->getPotentialArchetype()) {
     // The constraint type isn't a statically-known constraint.
     if (source.getLoc().isValid()) {
-      auto constraintType =
-        constraintPA->getDependentType(Impl->GenericParams,
-                                       /*allowUnresolved=*/true);
+      auto constraintType = constraintPA->getDependentType(Impl->GenericParams);
       Diags.diagnose(source.getLoc(), diag::requires_not_suitable_archetype,
                      1, TypeLoc::withoutLoc(constraintType), 0);
     }
@@ -3199,8 +2978,7 @@
       auto subjectType = subject.dyn_cast<Type>();
       if (!subjectType)
         subjectType = subject.get<PotentialArchetype *>()
-                        ->getDependentType(Impl->GenericParams,
-                                           /*allowUnresolved=*/true);
+                        ->getDependentType(Impl->GenericParams);
 
       Diags.diagnose(source.getLoc(), diag::requires_conformance_nonprotocol,
                      TypeLoc::withoutLoc(subjectType),
@@ -3399,7 +3177,7 @@
   }
 
   // Recursively merge the associated types of T2 into T1.
-  auto dependentT1 = T1->getDependentType({ }, /*allowUnresolved=*/true);
+  auto dependentT1 = T1->getDependentType({ });
   for (auto equivT2 : equivClass2Members) {
     for (auto T2Nested : equivT2->NestedTypes) {
       // If T1 is concrete but T2 is not, concretize the nested types of T2.
@@ -4118,8 +3896,7 @@
               equivClass->findAnyConcreteConstraintAsWritten()) {
           Diags.diagnose(constraint->source->getLoc(),
                          diag::recursive_same_type_constraint,
-                         archetype->getDependentType(genericParams,
-                                                     /*allowUnresolved=*/true),
+                         archetype->getDependentType(genericParams),
                          constraint->value);
         }
 
@@ -4135,9 +3912,7 @@
         if (auto source = equivClass->findAnySuperclassConstraintAsWritten()) {
           Diags.diagnose(source->source->getLoc(),
                          diag::recursive_superclass_constraint,
-                         source->archetype->getDependentType(
-                                                     genericParams,
-                                                     /*allowUnresolved=*/true),
+                         source->archetype->getDependentType(genericParams),
                          equivClass->superclass);
         }
 
@@ -4177,8 +3952,7 @@
         if (auto constraint = equivClass->findAnyConcreteConstraintAsWritten())
           Diags.diagnose(constraint->source->getLoc(),
                          diag::requires_generic_param_made_equal_to_concrete,
-                         rep->getDependentType(genericParams,
-                                               /*allowUnresolved=*/true));
+                         rep->getDependentType(genericParams));
         continue;
       }
 
@@ -4210,8 +3984,8 @@
         if (repConstraint && repConstraint->source->getLoc().isValid()) {
           Diags.diagnose(repConstraint->source->getLoc(),
                          diag::requires_generic_params_made_equal,
-                         pa->getDependentType(genericParams, true),
-                         other->getDependentType(genericParams, true));
+                         pa->getDependentType(genericParams),
+                         other->getDependentType(genericParams));
         }
         break;
       }
@@ -4219,24 +3993,6 @@
   }
 }
 
-bool GenericSignatureBuilder::diagnoseRemainingRenames(
-                              SourceLoc loc,
-                              ArrayRef<GenericTypeParamType *> genericParams) {
-  bool invalid = false;
-
-  for (auto pa : Impl->RenamedNestedTypes) {
-    if (pa->alreadyDiagnosedRename()) continue;
-
-    Diags.diagnose(loc, diag::invalid_member_type_suggest,
-                   pa->getParent()->getDependentType(genericParams,
-                                                     /*allowUnresolved=*/true),
-                   pa->getOriginalName(), pa->getNestedName());
-    invalid = true;
-  }
-
-  return invalid;
-}
-
 /// Turn a requirement right-hand side into an unresolved type.
 static GenericSignatureBuilder::UnresolvedType asUnresolvedType(
                                 GenericSignatureBuilder::RequirementRHS rhs) {
@@ -4248,17 +4004,12 @@
 
 void GenericSignatureBuilder::processDelayedRequirements() {
   bool anySolved = !Impl->DelayedRequirements.empty();
-  bool allowTypoCorrection = false;
   while (anySolved) {
     // Steal the delayed requirements so we can reprocess them.
     anySolved = false;
     auto delayed = std::move(Impl->DelayedRequirements);
     Impl->DelayedRequirements.clear();
 
-    // Whether we saw any unresolve type constraints that we couldn't
-    // resolve.
-    bool hasUnresolvedUnresolvedTypes = false;
-
     // Process delayed requirements.
     for (const auto &req : delayed) {
       // Reprocess the delayed requirement.
@@ -4281,12 +4032,6 @@
                                req.lhs, asUnresolvedType(req.rhs), req.source,
                                UnresolvedHandlingKind::ReturnUnresolved);
         break;
-
-      case DelayedRequirement::Unresolved:
-        reqResult = resolveUnresolvedType(
-                                      req.lhs.get<PotentialArchetype *>(),
-                                      allowTypoCorrection);
-        break;
       }
 
       // Update our state based on what happened.
@@ -4303,19 +4048,9 @@
       case ConstraintResult::Unresolved:
         // Add the requirement back.
         Impl->DelayedRequirements.push_back(req);
-
-        if (req.kind == DelayedRequirement::Unresolved)
-          hasUnresolvedUnresolvedTypes = true;
         break;
       }
     }
-
-    // If we didn't solve anything, but we did see some unresolved types,
-    // try again with typo correction enabled.
-    if (!anySolved && hasUnresolvedUnresolvedTypes && !allowTypoCorrection) {
-      allowTypoCorrection = true;
-      anySolved = true;
-    }
   }
 }
 
@@ -4418,7 +4153,7 @@
                    otherNoteDiag,
                    representativeConstraint->source->classifyDiagKind(),
                    representativeConstraint->archetype->
-                     getDependentType(genericParams, /*allowUnresolved=*/true),
+                     getDependentType(genericParams),
                    diagValue(representativeConstraint->value));
   };
 
@@ -4437,7 +4172,7 @@
       // diagnostic.
       auto getSubjectType =
         [&](PotentialArchetype *pa) -> std::pair<unsigned, Type> {
-          auto subjectType = pa->getDependentType(genericParams, true);
+          auto subjectType = pa->getDependentType(genericParams);
           unsigned kind;
           if (auto gp = subjectType->getAs<GenericTypeParamType>()) {
             if (gp->getDecl() &&
@@ -4495,8 +4230,7 @@
           constraint.source->getLoc().isValid()) {
         Diags.diagnose(constraint.source->getLoc(),
                        redundancyDiag,
-                       constraint.archetype->getDependentType(
-                         genericParams, /*allowUnresolved=*/true),
+                       constraint.archetype->getDependentType(genericParams),
                        diagValue(constraint.value));
 
         noteRepresentativeConstraint();
@@ -4801,10 +4535,8 @@
             constraint.source->getLoc().isValid()) {
           Diags.diagnose(constraint.source->getLoc(),
                          diag::redundant_same_type_constraint,
-                         constraint.archetype->getDependentType(
-                                                          genericParams, true),
-                         constraint.value->getDependentType(
-                                                          genericParams, true));
+                         constraint.archetype->getDependentType(genericParams),
+                         constraint.value->getDependentType(genericParams));
         }
 
         continue;
@@ -4871,7 +4603,7 @@
       diag::redundant_same_type_constraint,
       diag::previous_same_type_constraint,
       [&](PotentialArchetype *pa) {
-        return pa->getDependentType(genericParams, true);
+        return pa->getDependentType(genericParams);
       },
       /*removeSelfDerived=*/false);
   }
@@ -4906,16 +4638,14 @@
         Diags.diagnose(lhs.constraint.source->getLoc(),
                        diag::redundant_same_type_constraint,
                        lhs.constraint.archetype->getDependentType(
-                                                          genericParams, true),
-                       lhs.constraint.value->getDependentType(
-                                                          genericParams, true));
+                                                                genericParams),
+                       lhs.constraint.value->getDependentType(genericParams));
         Diags.diagnose(rhs.constraint.source->getLoc(),
                        diag::previous_same_type_constraint,
                        rhs.constraint.source->classifyDiagKind(),
                        rhs.constraint.archetype->getDependentType(
-                                                          genericParams, true),
-                       rhs.constraint.value->getDependentType(
-                                                          genericParams, true));
+                                                          genericParams),
+                       rhs.constraint.value->getDependentType(genericParams));
         return true;
       }),
     intercomponentEdges.end());
@@ -4938,17 +4668,17 @@
           Diags.diagnose(edge.constraint.source->getLoc(),
                          diag::redundant_same_type_constraint,
                          edge.constraint.archetype->getDependentType(
-                                                          genericParams, true),
+                                                          genericParams),
                          edge.constraint.value->getDependentType(
-                                                          genericParams, true));
+                                                          genericParams));
 
           Diags.diagnose(firstEdge.constraint.source->getLoc(),
                          diag::previous_same_type_constraint,
                          firstEdge.constraint.source->classifyDiagKind(),
                          firstEdge.constraint.archetype->getDependentType(
-                                                          genericParams, true),
+                                                          genericParams),
                          firstEdge.constraint.value->getDependentType(
-                                                          genericParams, true));
+                                                          genericParams));
         }
 
         continue;
@@ -4975,7 +4705,7 @@
       if (!pa)
         return ErrorType::get(depTy);
 
-      return pa->getDependentType({ }, /*allowUnresolved=*/false);
+      return pa->getDependentType({ });
     }
 
     return None;
@@ -5065,8 +4795,7 @@
                             representativeConstraint.archetype)) {
         Diags.diagnose(existing->source->getLoc(), diag::type_does_not_inherit,
                        existing->archetype->getDependentType(
-                                                   genericParams,
-                                                   /*allowUnresolved=*/true),
+                                                   genericParams),
                        existing->value, equivClass->superclass);
 
         // FIXME: Note the representative constraint.
@@ -5074,8 +4803,7 @@
         Diags.diagnose(representativeConstraint.source->getLoc(),
                        diag::type_does_not_inherit,
                        representativeConstraint.archetype->getDependentType(
-                                                    genericParams,
-                                                    /*allowUnresolved=*/true),
+                                                    genericParams),
                        equivClass->concreteType, equivClass->superclass);
       }
     } else if (representativeConstraint.source->getLoc().isValid()) {
@@ -5083,8 +4811,7 @@
       Diags.diagnose(representativeConstraint.source->getLoc(),
                      diag::redundant_superclass_constraint,
                      representativeConstraint.archetype->getDependentType(
-                                                  genericParams,
-                                                  /*allowUnresolved=*/true),
+                                                  genericParams),
                      representativeConstraint.value);
 
       if (auto existing = equivClass->findAnyConcreteConstraintAsWritten(
@@ -5092,9 +4819,7 @@
         Diags.diagnose(existing->source->getLoc(),
                        diag::same_type_redundancy_here,
                        existing->source->classifyDiagKind(),
-                       existing->archetype->getDependentType(
-                                                   genericParams,
-                                                   /*allowUnresolved=*/true),
+                       existing->archetype->getDependentType(genericParams),
                        existing->value);
       }
     }
@@ -5197,21 +4922,6 @@
     archetypes.push_back(archetype);
   });
 
-  // Remove any invalid potential archetypes or archetypes whose parents are
-  // concrete; they have no requirements.
-  archetypes.erase(
-    std::remove_if(archetypes.begin(), archetypes.end(),
-      [&](PotentialArchetype *archetype) -> bool {
-        // Invalid archetypes are never representatives in well-formed or
-        // corrected signature, so we don't need to visit them.
-        if (archetype->isInvalid())
-          return true;
-
-        // Keep it.
-        return false;
-      }),
-    archetypes.end());
-
   // Sort the archetypes in canonical order.
   llvm::array_pod_sort(archetypes.begin(), archetypes.end(),
                        compareDependentTypes);
@@ -5440,8 +5150,7 @@
           type.is<Type>()))
       return;
 
-    auto depTy = archetype->getDependentType(params,
-                                             /*allowUnresolved=*/false);
+    auto depTy = archetype->getDependentType(params);
 
     if (depTy->hasError())
       return;
@@ -5461,7 +5170,7 @@
     } else {
       // ...or to a dependent type.
       repTy = type.get<GenericSignatureBuilder::PotentialArchetype *>()
-          ->getDependentType(params, /*allowUnresolved=*/false);
+          ->getDependentType(params);
     }
 
     if (repTy->hasError())
diff --git a/lib/AST/LookupVisibleDecls.cpp b/lib/AST/LookupVisibleDecls.cpp
index b35593a..5dd50a4 100644
--- a/lib/AST/LookupVisibleDecls.cpp
+++ b/lib/AST/LookupVisibleDecls.cpp
@@ -17,6 +17,7 @@
 
 #include "NameLookupImpl.h"
 #include "swift/AST/ASTContext.h"
+#include "swift/AST/GenericSignatureBuilder.h"
 #include "swift/AST/Initializer.h"
 #include "swift/AST/NameLookup.h"
 #include "swift/AST/ProtocolConformance.h"
@@ -465,19 +466,22 @@
 lookupVisibleMemberDeclsImpl(Type BaseTy, VisibleDeclConsumer &Consumer,
                              const DeclContext *CurrDC, LookupState LS,
                              DeclVisibilityKind Reason,
-                             LazyResolver *TypeResolver, VisitedSet &Visited);
+                             LazyResolver *TypeResolver,
+                             GenericSignatureBuilder *GSB,
+                             VisitedSet &Visited);
 
 static void lookupVisibleProtocolMemberDecls(
     Type BaseTy, ProtocolType *PT, VisibleDeclConsumer &Consumer,
     const DeclContext *CurrDC, LookupState LS, DeclVisibilityKind Reason,
-    LazyResolver *TypeResolver, VisitedSet &Visited) {
+                                             LazyResolver *TypeResolver, GenericSignatureBuilder *GSB,
+    VisitedSet &Visited) {
   if (!Visited.insert(PT->getDecl()).second)
     return;
 
   for (auto Proto : PT->getDecl()->getInheritedProtocols())
     lookupVisibleProtocolMemberDecls(BaseTy, Proto->getDeclaredType(), Consumer, CurrDC,
                                  LS, getReasonForSuper(Reason), TypeResolver,
-                                 Visited);
+                                 GSB, Visited);
 
   lookupTypeMembers(BaseTy, PT, Consumer, CurrDC, LS, Reason, TypeResolver);
 }
@@ -485,7 +489,7 @@
 static void lookupVisibleMemberDeclsImpl(
     Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC,
     LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver,
-    VisitedSet &Visited) {
+    GenericSignatureBuilder *GSB, VisitedSet &Visited) {
   // Just look through l-valueness.  It doesn't affect name lookup.
   assert(BaseTy && "lookup into null type");
   assert(!BaseTy->hasLValueType());
@@ -507,7 +511,7 @@
     // functions, and can even look up non-static functions as well (thus
     // getting the address of the member).
     lookupVisibleMemberDeclsImpl(Ty, Consumer, CurrDC, subLS, Reason,
-                                 TypeResolver, Visited);
+                                 TypeResolver, GSB, Visited);
     return;
   }
 
@@ -531,7 +535,7 @@
   // If the base is a protocol, enumerate its members.
   if (ProtocolType *PT = BaseTy->getAs<ProtocolType>()) {
     lookupVisibleProtocolMemberDecls(BaseTy, PT, Consumer, CurrDC, LS, Reason,
-                                     TypeResolver, Visited);
+                                     TypeResolver, GSB, Visited);
     return;
   }
 
@@ -539,7 +543,7 @@
   if (auto PC = BaseTy->getAs<ProtocolCompositionType>()) {
     for (auto Member : PC->getMembers())
       lookupVisibleMemberDeclsImpl(Member, Consumer, CurrDC, LS, Reason,
-                                   TypeResolver, Visited);
+                                   TypeResolver, GSB, Visited);
     return;
   }
 
@@ -548,15 +552,43 @@
     for (auto Proto : Archetype->getConformsTo())
       lookupVisibleProtocolMemberDecls(
           BaseTy, Proto->getDeclaredType(), Consumer, CurrDC, LS,
-          getReasonForSuper(Reason), TypeResolver, Visited);
+          getReasonForSuper(Reason), TypeResolver, GSB, Visited);
 
     if (auto superclass = Archetype->getSuperclass())
       lookupVisibleMemberDeclsImpl(superclass, Consumer, CurrDC, LS,
                                    getReasonForSuper(Reason), TypeResolver,
-                                   Visited);
+                                   GSB, Visited);
     return;
   }
 
+  // If we're looking into a type parameter and we have a generic signature
+  // builder, use the GSB to resolve where we should look.
+  if (BaseTy->isTypeParameter() && GSB) {
+    auto PA = GSB->resolveArchetype(
+                BaseTy,
+                ArchetypeResolutionKind::CompleteWellFormed);
+    if (!PA) return;
+
+    if (auto Concrete = PA->getConcreteType()) {
+      BaseTy = Concrete;
+    } else {
+      // Conformances
+      for (auto Proto : PA->getConformsTo()) {
+        lookupVisibleProtocolMemberDecls(
+            BaseTy, Proto->getDeclaredType(), Consumer, CurrDC, LS,
+            getReasonForSuper(Reason), TypeResolver, GSB, Visited);
+      }
+
+      // Superclass.
+      if (auto Superclass = PA->getSuperclass()) {
+        lookupVisibleMemberDeclsImpl(Superclass, Consumer, CurrDC, LS,
+                                     getReasonForSuper(Reason), TypeResolver,
+                                     GSB, Visited);
+      }
+      return;
+    }
+  }
+
   llvm::SmallPtrSet<ClassDecl *, 8> Ancestors;
   do {
     NominalTypeDecl *CurNominal = BaseTy->getAnyNominal();
@@ -766,6 +798,13 @@
                         VD->getDeclContext()->isTypeContext());
     ModuleDecl *M = DC->getParentModule();
 
+    // Hack; we shouldn't be filtering at this level anyway.
+    if (!VD->hasInterfaceType()) {
+      FoundDecls[VD->getBaseName()].insert(VD);
+      DeclsToReport.insert(FoundDeclTy(VD, Reason));
+      return;
+    }
+
     auto FoundSignature = VD->getOverloadSignature();
     if (FoundSignature.InterfaceType && shouldSubst &&
         shouldSubstIntoDeclType(FoundSignature.InterfaceType)) {
@@ -777,7 +816,7 @@
     for (auto I = PossiblyConflicting.begin(), E = PossiblyConflicting.end();
          I != E; ++I) {
       auto *OtherVD = *I;
-      if (OtherVD->isInvalid()) {
+      if (OtherVD->isInvalid() || !OtherVD->hasInterfaceType()) {
         // For some invalid decls it might be impossible to compute the
         // signature, for example, if the types could not be resolved.
         continue;
@@ -821,11 +860,12 @@
 /// binding.
 static void lookupVisibleMemberDecls(
     Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC,
-    LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver) {
+    LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver,
+    GenericSignatureBuilder *GSB) {
   OverrideFilteringConsumer ConsumerWrapper(BaseTy, CurrDC, TypeResolver);
   VisitedSet Visited;
   lookupVisibleMemberDeclsImpl(BaseTy, ConsumerWrapper, CurrDC, LS, Reason,
-                               TypeResolver, Visited);
+                               TypeResolver, GSB, Visited);
 
   // Report the declarations we found to the real consumer.
   for (const auto &DeclAndReason : ConsumerWrapper.DeclsToReport)
@@ -903,7 +943,7 @@
 
     if (BaseDecl && ExtendedType) {
       ::lookupVisibleMemberDecls(ExtendedType, Consumer, DC, LS, Reason,
-                                 TypeResolver);
+                                 TypeResolver, nullptr);
     }
 
     // Check any generic parameters for something with the given name.
@@ -954,7 +994,8 @@
 void swift::lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, Type BaseTy,
                                      const DeclContext *CurrDC,
                                      LazyResolver *TypeResolver,
-                                     bool includeInstanceMembers) {
+                                     bool includeInstanceMembers,
+                                     GenericSignatureBuilder *GSB) {
   assert(CurrDC);
   LookupState ls = LookupState::makeQualified();
   if (includeInstanceMembers) {
@@ -963,5 +1004,5 @@
 
   ::lookupVisibleMemberDecls(BaseTy, Consumer, CurrDC, ls,
                              DeclVisibilityKind::MemberOfCurrentNominal,
-                             TypeResolver);
+                             TypeResolver, GSB);
 }
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 82c49ed..eccd064 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -311,7 +311,7 @@
 
 #if !NDEBUG
   unsigned idx = 0;
-  for (auto req : getProtocol()->getRequirementSignature()->getRequirements()) {
+  for (const auto &req : getProtocol()->getRequirementSignature()) {
     if (req.getKind() == RequirementKind::Conformance) {
       assert(idx < conformances.size());
       assert(conformances[idx].getRequirement() ==
@@ -596,8 +596,7 @@
          "signature conformances not yet computed");
 
   unsigned conformanceIndex = 0;
-  for (auto &reqt :
-         getProtocol()->getRequirementSignature()->getRequirements()) {
+  for (const auto &reqt : getProtocol()->getRequirementSignature()) {
     if (reqt.getKind() == RequirementKind::Conformance) {
       // Is this the conformance we're looking for?
       if (reqt.getFirstType()->isEqual(assocType) &&
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 32dab3c..0f13814 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -694,7 +694,7 @@
 
   // Determine the input and result types of this function.
   auto fnType = this->castTo<AnyFunctionType>();
-  Type inputType = fnType->getInput();
+  auto inputType = fnType->getParams();
   Type resultType =
     fnType->getResult()->replaceCovariantResultType(newResultType,
                                                     uncurryLevel - 1);
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 3ac1d7c..4343e1a 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -46,6 +46,7 @@
 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Index/IndexingAction.h"
 #include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "clang/Lex/Preprocessor.h"
@@ -705,6 +706,11 @@
     invocationArgStrs.push_back(overrideResourceDir);
   }
 
+  if (!importerOpts.IndexStorePath.empty()) {
+    invocationArgStrs.push_back("-index-store-path");
+    invocationArgStrs.push_back(importerOpts.IndexStorePath);
+  }
+
   for (auto extraArg : importerOpts.ExtraArgs) {
     invocationArgStrs.push_back(extraArg);
   }
@@ -1306,6 +1312,7 @@
   invocation->getFrontendOpts().Inputs.push_back(
       clang::FrontendInputFile(headerPath, clang::IK_ObjC));
   invocation->getFrontendOpts().OutputFile = outputPCHPath;
+  invocation->getFrontendOpts().ProgramAction = clang::frontend::GeneratePCH;
   invocation->getPreprocessorOpts().resetNonModularOptions();
 
   clang::CompilerInstance emitInstance(
@@ -1319,8 +1326,15 @@
   emitInstance.createSourceManager(fileManager);
   emitInstance.setTarget(&Impl.Instance->getTarget());
 
-  clang::GeneratePCHAction action;
-  emitInstance.ExecuteAction(action);
+  std::unique_ptr<clang::FrontendAction> action;
+  action.reset(new clang::GeneratePCHAction());
+  if (!emitInstance.getFrontendOpts().IndexStorePath.empty()) {
+    action = clang::index::
+      createIndexDataRecordingAction(emitInstance.getFrontendOpts(),
+                                     std::move(action));
+  }
+  emitInstance.ExecuteAction(*action);
+
   if (emitInstance.getDiagnostics().hasErrorOccurred()) {
     Impl.SwiftContext.Diags.diagnose({},
                                      diag::bridging_header_pch_error,
@@ -1407,6 +1421,17 @@
     auto importRAII = diagClient.handleImport(clangPath.front().first,
                                               importLoc);
 
+    std::string preservedIndexStorePathOption;
+    auto &clangFEOpts = Impl.Instance->getFrontendOpts();
+    if (!clangFEOpts.IndexStorePath.empty()) {
+      StringRef moduleName = path[0].first->getName();
+      // Ignore the SwiftShims module for the index data.
+      if (moduleName == Impl.SwiftContext.SwiftShimsModuleName.str()) {
+        preservedIndexStorePathOption = clangFEOpts.IndexStorePath;
+        clangFEOpts.IndexStorePath.clear();
+      }
+    }
+
     // FIXME: The source location here is completely bogus. It can't be
     // invalid, it can't be the same thing twice in a row, and it has to come
     // from an actual buffer, so we make a fake buffer and just use a counter.
@@ -1427,6 +1452,12 @@
     clang::ModuleLoadResult result =
         Impl.Instance->loadModule(clangImportLoc, path, visibility,
                                   /*IsInclusionDirective=*/false);
+
+    if (!preservedIndexStorePathOption.empty()) {
+      // Restore the -index-store-path option.
+      clangFEOpts.IndexStorePath = preservedIndexStorePathOption;
+    }
+
     if (result && makeVisible)
       Impl.getClangPreprocessor().makeModuleVisible(result, clangImportLoc);
     return result;
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 93c92fa..2e580e9 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -121,12 +121,12 @@
 /// it as a member
 static std::pair<VarDecl *, PatternBindingDecl *>
 createVarWithPattern(ASTContext &cxt, DeclContext *dc, Identifier name, Type ty,
-                     bool isLet, bool isImplicit,
+                     VarDecl::Specifier specifier, bool isImplicit,
                      Accessibility setterAccessibility) {
   // Create a variable to store the underlying value.
   auto var = new (cxt) VarDecl(
       /*IsStatic*/false,
-      /*IsLet*/isLet,
+      specifier,
       /*IsCaptureList*/false,
       SourceLoc(), name, dc->mapTypeIntoContext(ty), dc);
   if (isImplicit)
@@ -386,7 +386,7 @@
   auto selfDecl = ParamDecl::createSelf(SourceLoc(), enumDecl,
                                         /*static*/false, /*inout*/true);
 
-  auto param = new (C) ParamDecl(/*let*/ true, SourceLoc(),
+  auto param = new (C) ParamDecl(VarDecl::Specifier::None, SourceLoc(),
                                  SourceLoc(), C.Id_rawValue,
                                  SourceLoc(), C.Id_rawValue,
                                  enumDecl->getRawType(),
@@ -593,7 +593,8 @@
   auto &C = Impl.SwiftContext;
   auto selfDecl = ParamDecl::createSelf(SourceLoc(), importedDecl,
                                         /*isStatic*/false, /*isInOut*/true);
-  auto newValueDecl = new (C) ParamDecl(/*isLet */ true,SourceLoc(),SourceLoc(),
+  auto newValueDecl = new (C) ParamDecl(VarDecl::Specifier::None,
+                                        SourceLoc(), SourceLoc(),
                                         Identifier(), SourceLoc(), C.Id_value,
                                         importedFieldDecl->getType(),
                                         importedDecl);
@@ -1127,7 +1128,7 @@
 
     Identifier argName = generateParamName ? var->getName() : Identifier();
     auto param = new (context)
-        ParamDecl(/*IsLet*/ true, SourceLoc(), SourceLoc(), argName,
+        ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(), argName,
                   SourceLoc(), var->getName(), var->getType(), structDecl);
     param->setInterfaceType(var->getInterfaceType());
     valueParameters.push_back(param);
@@ -1281,9 +1282,12 @@
   // Create a variable to store the underlying value.
   VarDecl *var;
   PatternBindingDecl *patternBinding;
+  auto specifier = options.contains(MakeStructRawValuedFlags::IsLet)
+                 ? VarDecl::Specifier::Let
+                 : VarDecl::Specifier::Var;
   std::tie(var, patternBinding) = createVarWithPattern(
       cxt, structDecl, cxt.Id_rawValue, underlyingType,
-      options.contains(MakeStructRawValuedFlags::IsLet),
+      specifier,
       options.contains(MakeStructRawValuedFlags::IsImplicit),
       setterAccessibility);
 
@@ -1372,13 +1376,13 @@
   VarDecl *storedVar;
   PatternBindingDecl *storedPatternBinding;
   std::tie(storedVar, storedPatternBinding) = createVarWithPattern(
-      cxt, structDecl, storedVarName, storedUnderlyingType, /*isLet=*/false,
-      /*isImplicit=*/true, Accessibility::Private);
+      cxt, structDecl, storedVarName, storedUnderlyingType,
+      VarDecl::Specifier::Var, /*isImplicit=*/true, Accessibility::Private);
 
   //
   // Create a computed value variable
   auto computedVar = new (cxt) VarDecl(
-      /*IsStatic*/false, /*IsLet*/false, /*IsCaptureList*/false,
+      /*IsStatic*/false, VarDecl::Specifier::Var, /*IsCaptureList*/false,
       SourceLoc(), computedVarName, bridgedType, structDecl);
   computedVar->setInterfaceType(bridgedType);
   computedVar->setImplicit();
@@ -1430,7 +1434,7 @@
     return fnType;
 
   Type interfaceType = GenericFunctionType::get(
-      sig, fnType->getInput(), fnType->getResult(), AnyFunctionType::ExtInfo());
+      sig, fnType->getParams(), fnType->getResult(), AnyFunctionType::ExtInfo());
 
   return interfaceType;
 }
@@ -1497,8 +1501,9 @@
   auto elementTy = dc->mapTypeIntoContext(elementInterfaceTy);
 
   auto paramVarDecl =
-      new (C) ParamDecl(/*isLet=*/false, SourceLoc(), SourceLoc(), Identifier(),
-                        loc, valueIndex->get(0)->getName(), elementTy, dc);
+      new (C) ParamDecl(VarDecl::Specifier::InOut, SourceLoc(), SourceLoc(),
+                        Identifier(), loc, valueIndex->get(0)->getName(),
+                        elementTy, dc);
   paramVarDecl->setInterfaceType(elementInterfaceTy);
 
   auto valueIndicesPL = ParameterList::create(C, {paramVarDecl, index});
@@ -1547,9 +1552,7 @@
                          ->castTo<AnyFunctionType>()
                          ->getResult()
                          ->castTo<AnyFunctionType>()
-                         ->getInput()
-                         ->castTo<TupleType>()
-                         ->getElementType(0);
+                         ->getParams().front().getType();
   ParamDecl *keyDecl = PL->get(1);
 
   return {elementType, keyDecl};
@@ -1688,7 +1691,7 @@
 
   // Make the property decl
   auto errorDomainPropertyDecl = new (C) VarDecl(
-      /*IsStatic*/isStatic, /*IsLet*/false, /*IsCaptureList*/false,
+      /*IsStatic*/isStatic, VarDecl::Specifier::Var, /*IsCaptureList*/false,
       SourceLoc(), C.Id_nsErrorDomain, stringTy, swiftDecl);
   errorDomainPropertyDecl->setInterfaceType(stringTy);
   errorDomainPropertyDecl->setAccessibility(Accessibility::Public);
@@ -2483,7 +2486,8 @@
           // Create the _nsError member.
           //   public let _nsError: NSError
           auto nsErrorType = nsErrorDecl->getDeclaredInterfaceType();
-          auto nsErrorProp = new (C) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+          auto nsErrorProp = new (C) VarDecl(/*IsStatic*/false,
+                                             VarDecl::Specifier::Let,
                                              /*IsCaptureList*/false,
                                              loc, C.Id_nsError, nsErrorType,
                                              errorWrapper);
@@ -2550,7 +2554,8 @@
         auto rawValueConstructor = makeEnumRawValueConstructor(Impl, enumDecl);
 
         auto varName = C.Id_rawValue;
-        auto rawValue = new (C) VarDecl(/*IsStatic*/false, /*IsLet*/ false,
+        auto rawValue = new (C) VarDecl(/*IsStatic*/false,
+                                        VarDecl::Specifier::Var,
                                         /*IsCaptureList*/false,
                                         SourceLoc(), varName, underlyingType,
                                         enumDecl);
@@ -3164,7 +3169,8 @@
       // Map this indirect field to a Swift variable.
       auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
                        Accessibility::Public,
-                       /*IsStatic*/false, /*IsLet*/ false,
+                       /*IsStatic*/false,
+                       VarDecl::Specifier::Var,
                        /*IsCaptureList*/false,
                        Impl.importSourceLoc(decl->getLocStart()),
                        name, dc->mapTypeIntoContext(type), dc);
@@ -3385,7 +3391,8 @@
 
       auto result =
         Impl.createDeclWithClangNode<VarDecl>(decl, Accessibility::Public,
-                              /*IsStatic*/ false, /*IsLet*/ false,
+                              /*IsStatic*/ false,
+                              VarDecl::Specifier::Var,
                               /*IsCaptureList*/false,
                               Impl.importSourceLoc(decl->getLocation()),
                               name, dc->mapTypeIntoContext(type), dc);
@@ -3458,10 +3465,13 @@
       if (dc->isTypeContext())
         isStatic = true;
 
+      auto specifier = Impl.shouldImportGlobalAsLet(decl->getType())
+                     ? VarDecl::Specifier::Let
+                     : VarDecl::Specifier::Var;
       auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
                        Accessibility::Public,
                        /*IsStatic*/isStatic,
-                       /*IsLet*/Impl.shouldImportGlobalAsLet(decl->getType()),
+                       specifier,
                        /*IsCaptureList*/false,
                        Impl.importSourceLoc(decl->getLocation()),
                        name, dc->mapTypeIntoContext(type), dc);
@@ -4159,13 +4169,13 @@
       result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
       result->setCheckedInheritanceClause();
 
-      auto *env = Impl.buildGenericEnvironment(result->getGenericParams(), dc);
-      result->setGenericEnvironment(env);
-
       // Compute the requirement signature.
       if (!result->isRequirementSignatureComputed())
         result->computeRequirementSignature();
 
+      auto *env = Impl.buildGenericEnvironment(result->getGenericParams(), dc);
+      result->setGenericEnvironment(env);
+
       result->setMemberLoader(&Impl, 0);
 
       // Add the protocol decl to ExternalDefinitions so that IRGen can emit
@@ -4536,7 +4546,7 @@
 
       auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
           getOverridableAccessibility(dc),
-          /*IsStatic*/decl->isClassProperty(), /*IsLet*/false,
+          /*IsStatic*/decl->isClassProperty(), VarDecl::Specifier::Var,
           /*IsCaptureList*/false, Impl.importSourceLoc(decl->getLocation()),
           name, dc->mapTypeIntoContext(type), dc);
       result->setInterfaceType(type);
@@ -5212,7 +5222,7 @@
     // argument label
     auto *paramDecl =
         new (Impl.SwiftContext) ParamDecl(
-            /*isLet=*/true, SourceLoc(), SourceLoc(), argNames.front(),
+            VarDecl::Specifier::Let, SourceLoc(), SourceLoc(), argNames.front(),
             SourceLoc(), argNames.front(), Impl.SwiftContext.TheEmptyTupleType,
             dc);
     paramDecl->setInterfaceType(Impl.SwiftContext.TheEmptyTupleType);
@@ -5487,9 +5497,9 @@
     return nullptr;
 
   auto property = Impl.createDeclWithClangNode<VarDecl>(
-      getter, Accessibility::Public, /*IsStatic*/isStatic, /*isLet*/false,
-      /*IsCaptureList*/false, SourceLoc(), propertyName,
-      dc->mapTypeIntoContext(swiftPropertyType), dc);
+      getter, Accessibility::Public, /*IsStatic*/isStatic,
+      VarDecl::Specifier::Var, /*IsCaptureList*/false, SourceLoc(),
+      propertyName, dc->mapTypeIntoContext(swiftPropertyType), dc);
   property->setInterfaceType(swiftPropertyType);
 
   // Note that we've formed this property.
@@ -6348,7 +6358,8 @@
     auto conformance = ctx.getConformance(dc->getDeclaredTypeInContext(),
                                           protocols[i], SourceLoc(), dc,
                                           ProtocolConformanceState::Incomplete);
-    Impl.scheduleFinishProtocolConformance(conformance);
+    conformance->setLazyLoader(&Impl, /*context*/0);
+    conformance->setState(ProtocolConformanceState::Complete);
     conformances.push_back(conformance);
   }
 
@@ -7286,6 +7297,9 @@
 
 void ClangImporter::Implementation::finishPendingActions() {
   while (true) {
+    // The odd shape of this loop comes from previously having more than one
+    // possible kind of pending action. It's left this way to make it easy to
+    // add another one back in an `else if` clause.
     if (!RegisteredExternalDecls.empty()) {
       if (hasFinishedTypeChecking()) {
         RegisteredExternalDecls.clear();
@@ -7297,22 +7311,22 @@
             if (!nominal->hasDelayedMembers())
               typeResolver->resolveExternalDeclImplicitMembers(nominal);
       }
-    } else if (!DelayedProtocolConformances.empty()) {
-      NormalProtocolConformance *conformance =
-          DelayedProtocolConformances.pop_back_val();
-      finishProtocolConformance(conformance);
     } else {
       break;
     }
   }
 }
 
-/// Finish the given protocol conformance (for an imported type)
-/// by filling in any missing witnesses.
-void ClangImporter::Implementation::finishProtocolConformance(
-    NormalProtocolConformance *conformance) {
+void ClangImporter::Implementation::finishNormalConformance(
+    NormalProtocolConformance *conformance,
+    uint64_t unused) {
+  (void)unused;
   const ProtocolDecl *proto = conformance->getProtocol();
 
+  PrettyStackTraceType trace(SwiftContext, "completing conformance for",
+                             conformance->getType());
+  PrettyStackTraceDecl traceTo("... to", proto);
+
   // Create witnesses for requirements not already met.
   for (auto req : proto->getMembers()) {
     auto valueReq = dyn_cast<ValueDecl>(req);
@@ -7376,7 +7390,7 @@
 
   // Collect conformances for the requirement signature.
   SmallVector<ProtocolConformanceRef, 4> reqConformances;
-  for (auto req : proto->getRequirementSignature()->getRequirements()) {
+  for (const auto &req : proto->getRequirementSignature()) {
     if (req.getKind() != RequirementKind::Conformance)
       continue;
 
@@ -7740,12 +7754,12 @@
   VarDecl *var = nullptr;
   if (ClangN) {
     var = createDeclWithClangNode<VarDecl>(ClangN, Accessibility::Public,
-                                           /*IsStatic*/isStatic, /*IsLet*/false,
+                                           /*IsStatic*/isStatic, VarDecl::Specifier::Var,
                                            /*IsCaptureList*/false, SourceLoc(),
                                            name, dc->mapTypeIntoContext(type), dc);
   } else {
     var = new (SwiftContext)
-        VarDecl(/*IsStatic*/isStatic, /*IsLet*/false, /*IsCaptureList*/false,
+        VarDecl(/*IsStatic*/isStatic, VarDecl::Specifier::Var, /*IsCaptureList*/false,
                 SourceLoc(), name, dc->mapTypeIntoContext(type), dc);
   }
 
@@ -7852,7 +7866,7 @@
   // Create a new VarDecl with dummy type.
   auto var = createDeclWithClangNode<VarDecl>(ClangN, Accessibility::Public,
                                               /*IsStatic*/isStatic,
-                                              /*IsLet*/false,
+                                              VarDecl::Specifier::Var,
                                               /*IsCaptureList*/false,
                                               SourceLoc(), name, type, dc);
   var->setInterfaceType(type);
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index c195326..1550db2 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -1675,7 +1675,7 @@
     // imported header unit.
     auto paramInfo = createDeclWithClangNode<ParamDecl>(
         param, Accessibility::Private,
-        /*IsLet*/ true, SourceLoc(), SourceLoc(), name,
+        VarDecl::Specifier::None, SourceLoc(), SourceLoc(), name,
         importSourceLoc(param->getLocation()), bodyName,
         dc->mapTypeIntoContext(swiftParamTy),
         ImportedHeaderUnit);
@@ -1696,9 +1696,11 @@
         BoundGenericType::get(SwiftContext.getArrayDecl(), Type(),
                               {SwiftContext.TheAnyType});
     auto name = SwiftContext.getIdentifier("varargs");
-    auto param = new (SwiftContext)
-        ParamDecl(true, SourceLoc(), SourceLoc(), Identifier(), SourceLoc(),
-                  name, paramTy, ImportedHeaderUnit);
+    auto param = new (SwiftContext) ParamDecl(VarDecl::Specifier::None,
+                                              SourceLoc(), SourceLoc(),
+                                              Identifier(), SourceLoc(),
+                                              name, paramTy,
+                                              ImportedHeaderUnit);
     param->setInterfaceType(paramTy);
 
     param->setVariadic();
@@ -1995,7 +1997,7 @@
     // It doesn't actually matter which DeclContext we use, so just
     // use the imported header unit.
     auto type = TupleType::getEmpty(SwiftContext);
-    auto var = new (SwiftContext) ParamDecl(/*IsLet*/ true, SourceLoc(),
+    auto var = new (SwiftContext) ParamDecl(VarDecl::Specifier::None, SourceLoc(),
                                             SourceLoc(), argName,
                                             SourceLoc(), argName, type,
                                             ImportedHeaderUnit);
@@ -2113,7 +2115,7 @@
     // Set up the parameter info.
     auto paramInfo
       = createDeclWithClangNode<ParamDecl>(param, Accessibility::Private,
-                                           /*IsLet*/ true,
+                                           VarDecl::Specifier::None,
                                            SourceLoc(), SourceLoc(), name,
                                            importSourceLoc(param->getLocation()),
                                            bodyName,
@@ -2237,7 +2239,7 @@
     Identifier argLabel = functionName.getDeclName().getArgumentNames().front();
     auto paramInfo
       = createDeclWithClangNode<ParamDecl>(param, Accessibility::Private,
-                                           /*IsLet*/true,
+                                           VarDecl::Specifier::None,
                                            /*let loc*/SourceLoc(),
                                            /*label loc*/SourceLoc(),
                                            argLabel, nameLoc, bodyName,
diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h
index 25c964d..174e075 100644
--- a/lib/ClangImporter/ImporterImpl.h
+++ b/lib/ClangImporter/ImporterImpl.h
@@ -496,9 +496,6 @@
   /// External Decls that we have imported but not passed to the ASTContext yet.
   SmallVector<Decl *, 4> RegisteredExternalDecls;
 
-  /// Protocol conformances that may be missing witnesses.
-  SmallVector<NormalProtocolConformance *, 4> DelayedProtocolConformances;
-
   unsigned NumCurrentImportingEntities = 0;
 
   /// Mapping from delayed conformance IDs to the set of delayed
@@ -517,7 +514,6 @@
   void startedImportingEntity();
   void finishedImportingEntity();
   void finishPendingActions();
-  void finishProtocolConformance(NormalProtocolConformance *conformance);
 
   struct ImportingEntityRAII {
     Implementation &Impl;
@@ -567,10 +563,6 @@
     RegisteredExternalDecls.push_back(D);
   }
 
-  void scheduleFinishProtocolConformance(NormalProtocolConformance *C) {
-    DelayedProtocolConformances.push_back(C);
-  }
-
   /// \brief Retrieve the Clang AST context.
   clang::ASTContext &getClangASTContext() const {
     return Instance->getASTContext();
@@ -1115,6 +1107,9 @@
     const Decl *D, uint64_t contextData,
     SmallVectorImpl<ProtocolConformance *> &Conformances) override;
 
+  void finishNormalConformance(NormalProtocolConformance *conformance,
+                               uint64_t unused) override;
+
   template <typename DeclTy, typename ...Targs>
   DeclTy *createDeclWithClangNode(ClangNode ClangN, Accessibility access,
                                   Targs &&... Args) {
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index a9f4eba..ddb0bed 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1153,6 +1153,17 @@
       OI.CompilerMode = OutputInfo::Mode::SingleCompile;
       break;
 
+    // BEGIN APPLE-ONLY OUTPUT ACTIONS
+    case options::OPT_index_file:
+      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
+      OI.CompilerOutputType = types::TY_IndexData;
+      break;
+    // END APPLE-ONLY OUTPUT ACTIONS
+
+    case options::OPT_update_code:
+      OI.CompilerOutputType = types::TY_Remapping;
+      OI.LinkAction = LinkKind::None;
+      break;
     case options::OPT_parse:
     case options::OPT_typecheck:
     case options::OPT_dump_parse:
@@ -1449,6 +1460,7 @@
       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:
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index d54e990..9032dc3 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -231,6 +231,13 @@
     case types::TY_TBD:
       FrontendModeOption = "-emit-tbd";
       break;
+
+    // BEGIN APPLE-ONLY OUTPUT TYPES
+    case types::TY_IndexData:
+      FrontendModeOption = "-typecheck";
+      break;
+    // END APPLE-ONLY OUTPUT TYPES
+
     case types::TY_Remapping:
       FrontendModeOption = "-update-code";
       break;
@@ -311,6 +318,12 @@
     break;
   }
   case OutputInfo::Mode::SingleCompile: {
+    if (context.Output.getPrimaryOutputType() == types::TY_IndexData) {
+      if (Arg *A = context.Args.getLastArg(options::OPT_index_file_path)) {
+        Arguments.push_back("-primary-file");
+        Arguments.push_back(A->getValue());
+      }
+    }
     if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
         context.InputActions.size() > TOO_MANY_FILES) {
       Arguments.push_back("-filelist");
@@ -456,6 +469,11 @@
   if (context.Args.hasArg(options::OPT_embed_bitcode_marker))
     Arguments.push_back("-embed-bitcode-marker");
 
+  if (context.Args.hasArg(options::OPT_index_store_path)) {
+    context.Args.AddLastArg(Arguments, options::OPT_index_store_path);
+    Arguments.push_back("-index-system-modules");
+  }
+
   return II;
 }
 
@@ -541,6 +559,7 @@
     case types::TY_SIL:
     case types::TY_SIB:
     case types::TY_PCH:
+    case types::TY_IndexData:
       llvm_unreachable("Cannot be output from backend job");
     case types::TY_Swift:
     case types::TY_dSYM:
@@ -824,6 +843,7 @@
                         Arguments);
 
   addInputsOfType(Arguments, context.InputActions, types::TY_ObjCHeader);
+  context.Args.AddLastArg(Arguments, options::OPT_index_store_path);
 
   if (job.isPersistentPCH()) {
     Arguments.push_back("-emit-pch");
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index e6b87da..d0b60bc 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -92,6 +92,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
     return false;
   case types::TY_INVALID:
     llvm_unreachable("Invalid type ID.");
@@ -128,6 +129,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
   case types::TY_ModuleTrace:
     return false;
   case types::TY_INVALID:
@@ -165,6 +167,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
   case types::TY_ModuleTrace:
     return false;
   case types::TY_INVALID:
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 1f60276..a4f5d26 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -169,6 +169,11 @@
     Opts.GroupInfoPath = A->getValue();
   }
 
+  if (const Arg *A = Args.getLastArg(OPT_index_store_path)) {
+    Opts.IndexStorePath = A->getValue();
+  }
+  Opts.IndexSystemModules |= Args.hasArg(OPT_index_system_modules);
+
   Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
   Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil);
 
@@ -1143,6 +1148,9 @@
   if (const Arg *A = Args.getLastArg(OPT_target_cpu))
     Opts.TargetCPU = A->getValue();
 
+  if (const Arg *A = Args.getLastArg(OPT_index_store_path))
+    Opts.IndexStorePath = A->getValue();
+
   for (const Arg *A : make_range(Args.filtered_begin(OPT_Xcc),
                                  Args.filtered_end())) {
     Opts.ExtraArgs.push_back(A->getValue());
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 0704189..7075aa6 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -97,6 +97,12 @@
   if (!Invocation.getFrontendOptions().ModuleDocOutputPath.empty())
     Invocation.getLangOptions().AttachCommentsToDecls = true;
 
+  // If we are doing index-while-building, configure lexing and parsing to
+  // remember comments.
+  if (!Invocation.getFrontendOptions().IndexStorePath.empty()) {
+    Invocation.getLangOptions().AttachCommentsToDecls = true;
+  }
+
   Context.reset(new ASTContext(Invocation.getLangOptions(),
                                Invocation.getSearchPathOptions(),
                                SourceMgr, Diagnostics));
diff --git a/lib/FrontendTool/CMakeLists.txt b/lib/FrontendTool/CMakeLists.txt
index 1168a59..882b8ab 100644
--- a/lib/FrontendTool/CMakeLists.txt
+++ b/lib/FrontendTool/CMakeLists.txt
@@ -5,6 +5,7 @@
   TBD.cpp
   DEPENDS SwiftOptions
   LINK_LIBRARIES
+    swiftIndex
     swiftIDE
     swiftTBDGen swiftIRGen swiftSIL swiftSILGen swiftSILOptimizer
     swiftDemangling
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 45a5614..9e3d1de 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -48,6 +48,7 @@
 #include "swift/Frontend/PrintingDiagnosticConsumer.h"
 #include "swift/Frontend/SerializedDiagnosticConsumer.h"
 #include "swift/Immediate/Immediate.h"
+#include "swift/Index/IndexRecord.h"
 #include "swift/Option/Options.h"
 #include "swift/Migrator/FixitFilter.h"
 #include "swift/Migrator/Migrator.h"
@@ -368,6 +369,10 @@
   LLVM_BUILTIN_TRAP;
 }
 
+static bool emitIndexData(SourceFile *PrimarySourceFile,
+      const CompilerInvocation &Invocation,
+      CompilerInstance &Instance);
+
 static void countStatsPostSema(UnifiedStatsReporter &Stats,
                                CompilerInstance& Instance) {
   auto &C = Stats.getFrontendCounters();
@@ -646,8 +651,16 @@
     (void)emitLoadedModuleTrace(Context, *Instance.getDependencyTracker(),
                                 opts);
 
-  if (Context.hadError())
+  bool shouldIndex = !opts.IndexStorePath.empty();
+
+  if (Context.hadError()) {
+    if (shouldIndex) {
+      //  Emit the index store data even if there were compiler errors.
+      if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+        return true;
+    }
     return true;
+  }
 
   // FIXME: This is still a lousy approximation of whether the module file will
   // be externally consumed.
@@ -661,6 +674,10 @@
     if (!opts.ObjCHeaderOutputPath.empty())
       return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(),
                          opts.ImplicitObjCHeaderPath, moduleIsPublic);
+    if (shouldIndex) {
+      if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+        return true;
+    }
     return Context.hadError();
   }
 
@@ -858,8 +875,13 @@
       serialize(DC, serializationOpts, SM.get());
     }
 
-    if (Action == FrontendOptions::EmitModuleOnly)
+    if (Action == FrontendOptions::EmitModuleOnly) {
+      if (shouldIndex) {
+        if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+          return true;
+      }
       return Context.hadError();
+    }
   }
 
   assert(Action >= FrontendOptions::EmitSIL &&
@@ -918,6 +940,13 @@
                                    &HashGlobal);
   }
 
+  // Walk the AST for indexing after IR generation. Walking it before seems
+  // to cause miscompilation issues.
+  if (shouldIndex) {
+    if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+      return true;
+  }
+
   // Just because we had an AST error it doesn't mean we can't performLLVM.
   bool HadError = Instance.getASTContext().hadError();
   
@@ -975,6 +1004,52 @@
                   opts.getSingleOutputFilename(), Stats) || HadError;
 }
 
+static bool emitIndexData(SourceFile *PrimarySourceFile,
+      const CompilerInvocation &Invocation,
+      CompilerInstance &Instance) {
+  const FrontendOptions &opts = Invocation.getFrontendOptions();
+  assert(!opts.IndexStorePath.empty());
+  // FIXME: provide index unit token(s) explicitly and only use output file
+  // paths as a fallback.
+
+  bool isDebugCompilation;
+  switch (Invocation.getSILOptions().Optimization) {
+    case SILOptions::SILOptMode::NotSet:
+    case SILOptions::SILOptMode::None:
+    case SILOptions::SILOptMode::Debug:
+      isDebugCompilation = true;
+      break;
+    case SILOptions::SILOptMode::Optimize:
+    case SILOptions::SILOptMode::OptimizeUnchecked:
+      isDebugCompilation = false;
+      break;
+  }
+
+  if (PrimarySourceFile) {
+    if (index::indexAndRecord(
+            PrimarySourceFile, opts.getSingleOutputFilename(),
+            opts.IndexStorePath, opts.IndexSystemModules,
+            isDebugCompilation, Invocation.getTargetTriple(),
+            *Instance.getDependencyTracker())) {
+      return true;
+    }
+  } else {
+    StringRef moduleToken = opts.ModuleOutputPath;
+    if (moduleToken.empty())
+      moduleToken = opts.getSingleOutputFilename();
+
+    if (index::indexAndRecord(Instance.getMainModule(), opts.OutputFilenames,
+                              moduleToken, opts.IndexStorePath,
+                              opts.IndexSystemModules,
+                              isDebugCompilation, Invocation.getTargetTriple(),
+                              *Instance.getDependencyTracker())) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 /// Returns true if an error occurred.
 static bool dumpAPI(ModuleDecl *Mod, StringRef OutDir) {
   using namespace llvm::sys;
@@ -1231,6 +1306,7 @@
   DependencyTracker depTracker;
   if (!Invocation.getFrontendOptions().DependenciesFilePath.empty() ||
       !Invocation.getFrontendOptions().ReferenceDependenciesFilePath.empty() ||
+      !Invocation.getFrontendOptions().IndexStorePath.empty() ||
       !Invocation.getFrontendOptions().LoadedModuleTracePath.empty()) {
     Instance->setDependencyTracker(&depTracker);
   }
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index c3b92f6..18e3154 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -338,12 +338,7 @@
     NewProto = Builder.CreateCall(objc_allocateProtocol, protocolName);
     
     // Add the parent protocols.
-    auto *requirementSig = proto->getRequirementSignature();
-    auto conformsTo =
-      requirementSig->getConformsTo(proto->getSelfInterfaceType(),
-                                    *IGF.IGM.getSwiftModule());
-
-    for (auto parentProto : conformsTo) {
+    for (auto parentProto : proto->getInheritedProtocols()) {
       if (!parentProto->isObjC())
         continue;
       llvm::Value *parentRef = IGM.getAddrOfObjCProtocolRef(parentProto,
@@ -626,13 +621,8 @@
 
       std::function<void(ProtocolDecl*)> orderProtocol
         = [&](ProtocolDecl *proto) {
-          auto *requirementSig = proto->getRequirementSignature();
-          auto conformsTo = requirementSig->getConformsTo(
-              proto->getSelfInterfaceType(),
-              *getSwiftModule());
-
           // Recursively put parents first.
-          for (auto parent : conformsTo)
+          for (auto parent : proto->getInheritedProtocols())
             orderProtocol(parent);
 
           // Skip if we don't need to reify this protocol.
diff --git a/lib/IRGen/GenProto.h b/lib/IRGen/GenProto.h
index 85cafd0..721dcef 100644
--- a/lib/IRGen/GenProto.h
+++ b/lib/IRGen/GenProto.h
@@ -122,7 +122,7 @@
                                 WitnessMetadata *witnessMetadata,
                                 Explosion &args);
 
-  /// Bind the polymorphic paramater inside of a partial apply forwarding thunk.
+  /// Bind the polymorphic parameter inside of a partial apply forwarding thunk.
   void bindPolymorphicParameter(IRGenFunction &IGF,
                                 CanSILFunctionType &OrigFnType,
                                 CanSILFunctionType &SubstFnType,
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index b936bf1..539141f 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -814,9 +814,11 @@
     attrsUpdated = attrsUpdated.addAttribute(LLVMContext,
                      llvm::AttributeSet::FunctionIndex, "target-cpu", CPU);
 
-  std::vector<std::string> &Features = ClangOpts.Features;
+  std::vector<std::string> Features = ClangOpts.Features;
   if (!Features.empty()) {
     SmallString<64> allFeatures;
+    // Sort so that the target features string is canonical.
+    std::sort(Features.begin(), Features.end());
     interleave(Features, [&](const std::string &s) {
       allFeatures.append(s);
     }, [&]{
diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt
index d91c5a8..47aee9a 100644
--- a/lib/Index/CMakeLists.txt
+++ b/lib/Index/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_swift_library(swiftIndex STATIC
   Index.cpp
   IndexDataConsumer.cpp
+  IndexRecord.cpp
   IndexSymbol.cpp
   LINK_LIBRARIES
     swiftAST)
diff --git a/lib/Index/IndexRecord.cpp b/lib/Index/IndexRecord.cpp
new file mode 100644
index 0000000..91be812
--- /dev/null
+++ b/lib/Index/IndexRecord.cpp
@@ -0,0 +1,747 @@
+//===--- IndexRecord.cpp --------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Index/IndexRecord.h"
+#include "swift/AST/ASTContext.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/Expr.h"
+#include "swift/AST/Module.h"
+#include "swift/AST/ParameterList.h"
+#include "swift/AST/Pattern.h"
+#include "swift/AST/Stmt.h"
+#include "swift/AST/Types.h"
+#include "swift/AST/DiagnosticsFrontend.h"
+#include "swift/AST/ModuleLoader.h"
+#include "swift/ClangImporter/ClangModule.h"
+#include "swift/Index/Index.h"
+#include "swift/Strings.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Index/IndexRecordWriter.h"
+#include "clang/Index/IndexUnitWriter.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/Path.h"
+
+using namespace swift;
+using namespace swift::index;
+using clang::index::IndexUnitWriter;
+using clang::index::IndexRecordWriter;
+using clang::index::SymbolRole;
+using clang::index::SymbolRoleSet;
+
+//===----------------------------------------------------------------------===//
+// Index data collection and record writing
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SymbolTracker {
+public:
+  struct SymbolRelation {
+    size_t symbolIndex;
+    SymbolRoleSet roles;
+
+    llvm::hash_code hash() const { return llvm::hash_combine(symbolIndex, roles); }
+  };
+  struct SymbolOccurrence {
+    size_t symbolIndex;
+    SymbolRoleSet roles;
+    unsigned line;
+    unsigned column;
+    SmallVector<SymbolRelation, 3> related;
+
+    llvm::hash_code hash() const {
+      auto hash = llvm::hash_combine(symbolIndex, roles, line, column);
+      for (auto &relation : related) {
+        hash = llvm::hash_combine(hash, relation.hash());
+      }
+      return hash;
+    }
+  };
+  struct Symbol {
+    StringRef name;
+    StringRef USR;
+    StringRef group;
+
+    SymbolInfo symInfo;
+    unsigned isTestCandidate : 1;
+
+    llvm::hash_code hash() const {
+      return llvm::hash_combine(
+          name, USR, group,
+          static_cast<unsigned>(symInfo.Kind),
+          static_cast<unsigned>(symInfo.SubKind),
+          symInfo.Properties, isTestCandidate);
+    }
+  };
+
+  Symbol *getSymbol(size_t index) {
+    assert(index < symbols.size());
+    return &symbols[index];
+  }
+
+  ArrayRef<SymbolOccurrence> getOccurrences() {
+    if (!sorted) {
+      std::stable_sort(occurrences.begin(), occurrences.end(),
+          [](const SymbolOccurrence &a, const SymbolOccurrence& b) {
+        if (a.line < b.line)
+          return true;
+        if (b.line < a.line)
+          return false;
+        return a.column < b.column;
+      });
+      sorted = true;
+    }
+    return occurrences;
+  }
+
+  size_t addSymbol(const IndexRelation &indexSym) {
+    auto pair = USRToSymbol.insert(std::make_pair(indexSym.USR.data(),
+                                                  symbols.size()));
+    if (pair.second) {
+      Symbol symbol{indexSym.name,
+                    indexSym.USR,
+                    indexSym.group,
+                    indexSym.symInfo,
+                    0};
+      recordHash = llvm::hash_combine(recordHash, symbol.hash());
+      symbols.push_back(std::move(symbol));
+    }
+
+    return pair.first->second;
+  }
+
+  void addOccurrence(const IndexSymbol &indexOccur) {
+    sorted = false;
+
+    SmallVector<SymbolRelation, 3> relations;
+    for(IndexRelation indexRel: indexOccur.Relations) {
+      relations.push_back({addSymbol(indexRel), indexRel.roles});
+    }
+
+    occurrences.push_back({/*symbolIndex=*/addSymbol(indexOccur),
+                           indexOccur.roles,
+                           indexOccur.line,
+                           indexOccur.column,
+                           std::move(relations)});
+
+    recordHash = llvm::hash_combine(recordHash, occurrences.back().hash());
+  }
+
+  llvm::hash_code hashRecord() const { return recordHash; }
+
+private:
+  llvm::DenseMap<const char *, size_t> USRToSymbol;
+  std::vector<Symbol> symbols;
+  std::vector<SymbolOccurrence> occurrences;
+  bool sorted = false;
+  llvm::hash_code recordHash = 0;
+};
+
+class IndexRecordingConsumer : public IndexDataConsumer {
+  SymbolTracker record;
+  // Keep a USR map to uniquely identify Decls.
+  // FIXME: if we just passed the original Decl * through we could use that,
+  // which would also let us avoid producing the USR/Name/etc. for decls unless
+  // we actually need it (once per Decl instead of once per occurrence).
+  std::vector<IndexSymbol> symbolStack;
+
+  std::function<void(SymbolTracker &)> onFinish;
+
+public:
+  IndexRecordingConsumer(std::function<void(SymbolTracker &)> onFinish)
+      : onFinish(std::move(onFinish)) {}
+
+  void failed(StringRef error) override {
+    // FIXME: expose errors?
+  }
+
+  bool recordHash(StringRef hash, bool isKnown) override { return true; }
+  bool startDependency(StringRef name, StringRef path, bool isClangModule,
+                       bool isSystem, StringRef hash) override {
+    return true;
+  }
+  bool finishDependency(bool isClangModule) override { return true; }
+  Action startSourceEntity(const IndexSymbol &symbol) override {
+    symbolStack.push_back(symbol);
+    return Action::Continue;
+  }
+  bool finishSourceEntity(SymbolInfo sym, SymbolRoleSet roles) override {
+    IndexSymbol symbol = std::move(symbolStack.back());
+    symbolStack.pop_back();
+    assert(!symbol.USR.empty());
+    record.addOccurrence(symbol);
+    return true;
+  }
+
+  void finish() override { onFinish(record); }
+};
+
+class StdlibGroupsIndexRecordingConsumer : public IndexDataConsumer {
+  llvm::StringMap<std::unique_ptr<SymbolTracker>> TrackerByGroup;
+  // Keep a USR map to uniquely identify Decls.
+  // FIXME: if we just passed the original Decl * through we could use that,
+  // which would also let us avoid producing the USR/Name/etc. for decls unless
+  // we actually need it (once per Decl instead of once per occurrence).
+  std::vector<IndexSymbol> symbolStack;
+
+  std::function<bool(StringRef groupName, SymbolTracker &)> onFinish;
+
+public:
+  StdlibGroupsIndexRecordingConsumer(std::function<bool(StringRef groupName, SymbolTracker &)> onFinish)
+      : onFinish(std::move(onFinish)) {}
+
+  void failed(StringRef error) override {
+    // FIXME: expose errors?
+  }
+
+  bool recordHash(StringRef hash, bool isKnown) override { return true; }
+  bool startDependency(StringRef name, StringRef path, bool isClangModule,
+                       bool isSystem, StringRef hash) override {
+    return true;
+  }
+  bool finishDependency(bool isClangModule) override { return true; }
+  Action startSourceEntity(const IndexSymbol &symbol) override {
+    symbolStack.push_back(symbol);
+    return Action::Continue;
+  }
+  bool finishSourceEntity(SymbolInfo sym, SymbolRoleSet roles) override {
+    IndexSymbol symbol = std::move(symbolStack.back());
+    symbolStack.pop_back();
+    assert(!symbol.USR.empty());
+    StringRef groupName = findGroupForSymbol(symbol);
+    auto &tracker = TrackerByGroup[groupName];
+    if (!tracker) {
+      tracker = llvm::make_unique<SymbolTracker>();
+    }
+    tracker->addOccurrence(symbol);
+    return true;
+  }
+
+  void finish() override {
+    for (auto &pair : TrackerByGroup) {
+      StringRef groupName = pair.first();
+      SymbolTracker &tracker = *pair.second;
+      bool cont = onFinish(groupName, tracker);
+      if (!cont)
+        break;
+    }
+  }
+
+private:
+  StringRef findGroupForSymbol(const IndexSymbol &sym);
+
+};
+} // end anonymous namespace
+
+static StringRef findGroupNameForDecl(const Decl *D) {
+  if (!D || isa<ModuleDecl>(D) || isa<TopLevelCodeDecl>(D))
+    return StringRef();
+
+  auto groupNameOpt = D->getGroupName();
+  if (groupNameOpt)
+    return *groupNameOpt;
+
+  return findGroupNameForDecl(D->getDeclContext()->getInnermostDeclarationDeclContext());
+}
+
+StringRef StdlibGroupsIndexRecordingConsumer::findGroupForSymbol(const IndexSymbol &sym) {
+  bool isDeclOrDef = sym.roles & ((SymbolRoleSet)SymbolRole::Declaration | (SymbolRoleSet)SymbolRole::Definition);
+  if (isDeclOrDef) {
+    if (!sym.group.empty())
+      return sym.group;
+    return findGroupNameForDecl(sym.decl);
+  }
+
+  for (auto &rel : sym.Relations) {
+    if (!rel.group.empty())
+      return rel.group;
+    if (rel.decl)
+      return findGroupNameForDecl(rel.decl);
+  }
+  llvm_unreachable("did not find group name for reference");
+}
+
+static bool writeRecord(SymbolTracker &record, std::string Filename,
+                        std::string indexStorePath, DiagnosticEngine *diags,
+                        std::string &outRecordFile) {
+  if (record.getOccurrences().empty()) {
+    outRecordFile = std::string();
+    return false;
+  }
+
+  IndexRecordWriter recordWriter(indexStorePath);
+  std::string error;
+  auto result = recordWriter.beginRecord(
+      Filename, record.hashRecord(), error, &outRecordFile);
+  switch (result) {
+  case IndexRecordWriter::Result::Failure:
+    diags->diagnose(SourceLoc(), diag::error_write_index_record, error);
+    return true;
+  case IndexRecordWriter::Result::AlreadyExists:
+    return false;
+  case IndexRecordWriter::Result::Success:
+    break;
+  }
+
+  for (auto &occurrence : record.getOccurrences()) {
+    SmallVector<clang::index::writer::SymbolRelation, 3> relations;
+    for(SymbolTracker::SymbolRelation symbolRelation: occurrence.related) {
+      relations.push_back({record.getSymbol(symbolRelation.symbolIndex), symbolRelation.roles});
+    }
+
+    recordWriter.addOccurrence(
+        record.getSymbol(occurrence.symbolIndex), occurrence.roles,
+        occurrence.line, occurrence.column, relations);
+  }
+
+  result = recordWriter.endRecord(error,
+      [&](clang::index::writer::OpaqueDecl opaqueSymbol,
+          SmallVectorImpl<char> &scratch) {
+    auto *symbol = static_cast<const SymbolTracker::Symbol *>(opaqueSymbol);
+    clang::index::writer::Symbol result;
+    result.SymInfo = symbol->symInfo;
+    result.Name = symbol->name;
+    result.USR = symbol->USR;
+    result.CodeGenName = ""; // FIXME
+    return result;
+  });
+
+  if (result == IndexRecordWriter::Result::Failure) {
+    diags->diagnose(SourceLoc(), diag::error_write_index_record, error);
+    return true;
+  }
+
+  return false;
+}
+
+static std::unique_ptr<IndexRecordingConsumer>
+makeRecordingConsumer(std::string Filename, std::string indexStorePath,
+                      DiagnosticEngine *diags,
+                      std::string *outRecordFile,
+                      bool *outFailed) {
+  return llvm::make_unique<IndexRecordingConsumer>([=](SymbolTracker &record) {
+    *outFailed = writeRecord(record, Filename, indexStorePath, diags,
+                             *outRecordFile);
+  });
+}
+
+static bool
+recordSourceFile(SourceFile *SF, StringRef indexStorePath,
+                 DiagnosticEngine &diags,
+                 llvm::function_ref<void(StringRef, StringRef)> callback) {
+  std::string recordFile;
+  bool failed = false;
+  auto consumer = makeRecordingConsumer(SF->getFilename(), indexStorePath,
+                                        &diags, &recordFile, &failed);
+  indexSourceFile(SF, /*Hash=*/"", *consumer);
+
+  if (!failed && !recordFile.empty())
+    callback(recordFile, SF->getFilename());
+  return failed;
+}
+
+//===----------------------------------------------------------------------===//
+// Index unit file writing
+//===----------------------------------------------------------------------===//
+
+// Used to get std::string pointers to pass as writer::OpaqueModule.
+namespace {
+class StringScratchSpace {
+  std::vector<const std::string *> StrsCreated;
+
+public:
+  const std::string *createString(StringRef str) {
+    auto *s = new std::string(str);
+    StrsCreated.push_back(s);
+    return s;
+  }
+
+  ~StringScratchSpace() {
+    for (auto *str : StrsCreated)
+      delete str;
+  }
+};
+}
+
+static clang::index::writer::ModuleInfo
+getModuleInfoFromOpaqueModule(clang::index::writer::OpaqueModule mod,
+                              SmallVectorImpl<char> &Scratch) {
+  clang::index::writer::ModuleInfo info;
+  info.Name = *static_cast<const std::string*>(mod);
+  return info;
+}
+
+static bool
+emitDataForSwiftSerializedModule(ModuleDecl *module,
+                                 StringRef indexStorePath,
+                                 bool indexSystemModules,
+                                 StringRef targetTriple,
+                                 const clang::CompilerInstance &clangCI,
+                                 DiagnosticEngine &diags,
+                                 IndexUnitWriter &parentUnitWriter);
+
+static void addModuleDependencies(ArrayRef<ModuleDecl::ImportedModule> imports,
+                                  StringRef indexStorePath,
+                                  bool indexSystemModules,
+                                  StringRef targetTriple,
+                                  const clang::CompilerInstance &clangCI,
+                                  DiagnosticEngine &diags,
+                                  IndexUnitWriter &unitWriter,
+                                  StringScratchSpace &moduleNameScratch) {
+  auto &fileMgr = clangCI.getFileManager();
+
+  for (auto &import : imports) {
+    ModuleDecl *mod = import.second;
+    if (mod->getNameStr() == SWIFT_ONONE_SUPPORT)
+      continue; // ignore the Onone support library.
+    if (mod->isSwiftShimsModule())
+      continue;
+
+    for (auto *FU : mod->getFiles()) {
+      switch (FU->getKind()) {
+      case FileUnitKind::Source:
+      case FileUnitKind::Derived:
+      case FileUnitKind::Builtin:
+        break;
+      case FileUnitKind::SerializedAST:
+      case FileUnitKind::ClangModule: {
+        auto *LFU = cast<LoadedFile>(FU);
+        if (auto *F = fileMgr.getFile(LFU->getFilename())) {
+          std::string moduleName = mod->getNameStr();
+          bool withoutUnitName = true;
+          if (FU->getKind() == FileUnitKind::ClangModule) {
+            withoutUnitName = false;
+            auto clangModUnit = cast<ClangModuleUnit>(LFU);
+            if (auto clangMod = clangModUnit->getUnderlyingClangModule()) {
+              moduleName = clangMod->getTopLevelModuleName();
+              // FIXME: clang's -Rremarks do not seem to go through Swift's
+              // diagnostic emitter.
+              clang::index::emitIndexDataForModuleFile(clangMod,
+                                                       clangCI, unitWriter);
+            }
+          } else {
+            // Serialized AST file.
+            // Only index system modules (essentially stdlib and overlays).
+            // We don't officially support binary swift modules, so normally
+            // the index data for user modules would get generated while
+            // building them.
+            if (mod->isSystemModule() && indexSystemModules) {
+              emitDataForSwiftSerializedModule(mod, indexStorePath,
+                                               indexSystemModules,
+                                               targetTriple, clangCI, diags,
+                                               unitWriter);
+              withoutUnitName = false;
+            }
+          }
+          clang::index::writer::OpaqueModule opaqMod =
+              moduleNameScratch.createString(moduleName);
+          unitWriter.addASTFileDependency(F, mod->isSystemModule(), opaqMod,
+                                          withoutUnitName);
+        }
+        break;
+      }
+      }
+    }
+  }
+}
+
+/// \returns true if an error occurred.
+static bool
+emitDataForSwiftSerializedModule(ModuleDecl *module,
+                                 StringRef indexStorePath,
+                                 bool indexSystemModules,
+                                 StringRef targetTriple,
+                                 const clang::CompilerInstance &clangCI,
+                                 DiagnosticEngine &diags,
+                                 IndexUnitWriter &parentUnitWriter) {
+  StringRef filename = module->getModuleFilename();
+  std::string moduleName = module->getNameStr();
+
+  std::string error;
+  auto isUptodateOpt = parentUnitWriter.isUnitUpToDateForOutputFile(/*FilePath=*/filename,
+                                                                /*TimeCompareFilePath=*/filename, error);
+  if (!isUptodateOpt.hasValue()) {
+    diags.diagnose(SourceLoc(), diag::error_index_failed_status_check, error);
+    return true;
+  }
+  if (*isUptodateOpt)
+    return false;
+
+  // FIXME: Would be useful for testing if swift had clang's -Rremark system so
+  // we could output a remark here that we are going to create index data for
+  // a module file.
+
+  // Pairs of (recordFile, groupName).
+  std::vector<std::pair<std::string, std::string>> records;
+
+  if (!module->isStdlibModule()) {
+    std::string recordFile;
+    bool failed = false;
+    auto consumer = makeRecordingConsumer(filename, indexStorePath,
+                                          &diags, &recordFile, &failed);
+    indexModule(module, /*Hash=*/"", *consumer);
+
+    if (failed)
+      return true;
+
+    records.emplace_back(recordFile, moduleName);
+  } else {
+    // Record stdlib groups as if they were submodules.
+
+    auto makeSubmoduleNameFromGroupName = [](StringRef groupName, SmallString<128> &buf) {
+      buf += "Swift";
+      if (groupName.empty())
+        return;
+      buf += '.';
+      for (char ch : groupName) {
+        if (ch == '/')
+          buf += '.';
+        else if (ch == ' ' || ch == '-')
+          buf += '_';
+        else
+          buf += ch;
+      }
+    };
+    auto appendGroupNameForFilename = [](StringRef groupName, SmallString<256> &buf) {
+      if (groupName.empty())
+        return;
+      buf += '_';
+      for (char ch : groupName) {
+        if (ch == '/' || ch ==' ')
+          buf += '_';
+        else
+          buf += ch;
+      }
+    };
+
+    bool failed = false;
+    StdlibGroupsIndexRecordingConsumer groupIndexConsumer([&](StringRef groupName, SymbolTracker &tracker) -> bool {
+      SmallString<128> moduleName;
+      makeSubmoduleNameFromGroupName(groupName, moduleName);
+      SmallString<256> fileNameWithGroup = filename;
+      appendGroupNameForFilename(groupName, fileNameWithGroup);
+
+      std::string outRecordFile;
+      failed = failed || writeRecord(tracker, fileNameWithGroup.str(), indexStorePath, &diags, outRecordFile);
+      if (failed)
+        return false;
+      records.emplace_back(outRecordFile, moduleName.str());
+      return true;
+    });
+    indexModule(module, /*Hash=*/"", groupIndexConsumer);
+    if (failed)
+      return true;
+  }
+
+  auto &fileMgr = clangCI.getFileManager();
+  bool isSystem = module->isSystemModule();
+  // FIXME: Get real values for the following.
+  StringRef swiftVersion;
+  StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot;
+  std::string indexUnitToken = module->getModuleFilename();
+  // For indexing serialized modules 'debug compilation' is irrelevant, so
+  // set it to true by default.
+  bool isDebugCompilation = true;
+
+  IndexUnitWriter unitWriter(fileMgr, indexStorePath,
+    "swift", swiftVersion, indexUnitToken, moduleName,
+    /*MainFile=*/nullptr, isSystem, /*IsModuleUnit=*/true,
+    isDebugCompilation, targetTriple, sysrootPath, getModuleInfoFromOpaqueModule);
+
+  const clang::FileEntry *FE = fileMgr.getFile(filename);
+  bool isSystemModule = module->isSystemModule();
+  for (auto &pair : records) {
+    std::string &recordFile = pair.first;
+    std::string &groupName = pair.second;
+    if (recordFile.empty())
+      continue;
+    clang::index::writer::OpaqueModule mod = &groupName;
+    unitWriter.addRecordFile(recordFile, FE, isSystemModule, mod);
+  }
+
+  SmallVector<ModuleDecl::ImportedModule, 8> imports;
+  module->getImportedModules(imports, ModuleDecl::ImportFilter::All);
+  StringScratchSpace moduleNameScratch;
+  addModuleDependencies(imports, indexStorePath, indexSystemModules,
+                        targetTriple, clangCI, diags, unitWriter, moduleNameScratch);
+
+  if (unitWriter.write(error)) {
+    diags.diagnose(SourceLoc(), diag::error_write_index_unit, error);
+    return true;
+  }
+
+  return false;
+}
+
+static bool
+recordSourceFileUnit(SourceFile *primarySourceFile, StringRef indexUnitToken,
+                     StringRef indexStorePath, bool indexSystemModules,
+                     bool isDebugCompilation, StringRef targetTriple,
+                     ArrayRef<const clang::FileEntry *> fileDependencies,
+                     const clang::CompilerInstance &clangCI,
+                     DiagnosticEngine &diags) {
+  auto &fileMgr = clangCI.getFileManager();
+  auto *module = primarySourceFile->getParentModule();
+  bool isSystem = module->isSystemModule();
+  auto *mainFile = fileMgr.getFile(primarySourceFile->getFilename());
+  // FIXME: Get real values for the following.
+  StringRef swiftVersion;
+  StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot;
+
+  IndexUnitWriter unitWriter(fileMgr, indexStorePath,
+    "swift", swiftVersion, indexUnitToken, module->getNameStr(),
+    mainFile, isSystem, /*isModuleUnit=*/false, isDebugCompilation,
+    targetTriple, sysrootPath, getModuleInfoFromOpaqueModule);
+
+  // Module dependencies.
+  SmallVector<ModuleDecl::ImportedModule, 8> imports;
+  primarySourceFile->getImportedModules(imports, ModuleDecl::ImportFilter::All);
+  StringScratchSpace moduleNameScratch;
+  addModuleDependencies(imports, indexStorePath, indexSystemModules,
+                        targetTriple, clangCI, diags, unitWriter, moduleNameScratch);
+
+  // File dependencies.
+  for (auto *F : fileDependencies)
+    unitWriter.addFileDependency(F, /*FIXME:isSystem=*/false, /*Module=*/nullptr);
+
+  recordSourceFile(primarySourceFile, indexStorePath, diags,
+                   [&](StringRef recordFile, StringRef filename) {
+    unitWriter.addRecordFile(recordFile, fileMgr.getFile(filename),
+                             module->isSystemModule(), /*Module=*/nullptr);
+  });
+
+  std::string error;
+  if (unitWriter.write(error)) {
+    diags.diagnose(SourceLoc(), diag::error_write_index_unit, error);
+    return true;
+  }
+
+  return false;
+}
+
+// Not currently used, see related comments in the call sites.
+#if 0
+static void
+collectFileDependencies(llvm::SetVector<const clang::FileEntry *> &result,
+                        const DependencyTracker &dependencyTracker,
+                        ModuleDecl *module, clang::FileManager &fileMgr) {
+  for (auto *F : module->getFiles()) {
+    if (auto *SF = dyn_cast<SourceFile>(F)) {
+      if (auto *dep = fileMgr.getFile(SF->getFilename())) {
+        result.insert(dep);
+      }
+    }
+  }
+  for (StringRef filename : dependencyTracker.getDependencies()) {
+    if (auto *F = fileMgr.getFile(filename))
+      result.insert(F);
+  }
+}
+#endif
+
+//===----------------------------------------------------------------------===//
+// Indexing entry points
+//===----------------------------------------------------------------------===//
+
+bool index::indexAndRecord(SourceFile *primarySourceFile,
+                           StringRef indexUnitToken,
+                           StringRef indexStorePath,
+                           bool indexSystemModules,
+                           bool isDebugCompilation,
+                           StringRef targetTriple,
+                           const DependencyTracker &dependencyTracker) {
+  auto &astContext = primarySourceFile->getASTContext();
+  auto &clangCI = astContext.getClangModuleLoader()->getClangInstance();
+  auto &diags = astContext.Diags;
+
+  std::string error;
+  if (IndexUnitWriter::initIndexDirectory(indexStorePath, error)) {
+    diags.diagnose(SourceLoc(), diag::error_create_index_dir, error);
+    return true;
+  }
+
+  llvm::SetVector<const clang::FileEntry *> fileDependencies;
+  // FIXME: This is not desirable because:
+  // 1. It picks shim header files as file dependencies
+  // 2. Having all the other swift files of the module as file dependencies ends
+  //   up making all of them associated with all the other files as main files.
+  //   It's better to associate each swift file with the unit that recorded it
+  //   as the main one.
+  // Keeping the code in case we want to revisit.
+#if 0
+  auto *module = primarySourceFile->getParentModule();
+  collectFileDependencies(fileDependencies, dependencyTracker, module, fileMgr);
+#endif
+
+  return recordSourceFileUnit(primarySourceFile, indexUnitToken,
+                              indexStorePath, indexSystemModules,
+                              isDebugCompilation, targetTriple,
+                              fileDependencies.getArrayRef(),
+                              clangCI, diags);
+}
+
+bool index::indexAndRecord(ModuleDecl *module,
+                           ArrayRef<std::string> indexUnitTokens,
+                           StringRef moduleUnitToken,
+                           StringRef indexStorePath,
+                           bool indexSystemModules,
+                           bool isDebugCompilation,
+                           StringRef targetTriple,
+                           const DependencyTracker &dependencyTracker) {
+  auto &astContext = module->getASTContext();
+  auto &clangCI = astContext.getClangModuleLoader()->getClangInstance();
+  auto &diags = astContext.Diags;
+
+  std::string error;
+  if (IndexUnitWriter::initIndexDirectory(indexStorePath, error)) {
+    diags.diagnose(SourceLoc(), diag::error_create_index_dir, error);
+    return true;
+  }
+
+  // Add the current module's source files to the dependencies.
+  llvm::SetVector<const clang::FileEntry *> fileDependencies;
+  // FIXME: This is not desirable because:
+  // 1. It picks shim header files as file dependencies
+  // 2. Having all the other swift files of the module as file dependencies ends
+  //   up making all of them associated with all the other files as main files.
+  //   It's better to associate each swift file with the unit that recorded it
+  //   as the main one.
+  // Keeping the code in case we want to revisit.
+#if 0
+  collectFileDependencies(fileDependencies, dependencyTracker, module, fileMgr);
+#endif
+
+  // Write a unit for each source file.
+  unsigned unitIndex = 0;
+  for (auto *F : module->getFiles()) {
+    if (auto *SF = dyn_cast<SourceFile>(F)) {
+      if (unitIndex == indexUnitTokens.size()) {
+        diags.diagnose(SourceLoc(), diag::error_index_inputs_more_than_outputs);
+        return true;
+      }
+      if (recordSourceFileUnit(SF, indexUnitTokens[unitIndex],
+                               indexStorePath, indexSystemModules,
+                               isDebugCompilation, targetTriple,
+                               fileDependencies.getArrayRef(),
+                               clangCI, diags))
+        return true;
+      unitIndex += 1;
+    }
+  }
+
+  // In the case where inputs are swift modules, like in the merge-module step,
+  // ignore the inputs; associated unit files for the modules' source inputs
+  // should have been generated at swift module creation time.
+
+  return false;
+}
diff --git a/lib/Migrator/TupleSplatMigratorPass.cpp b/lib/Migrator/TupleSplatMigratorPass.cpp
index 8c77492..360cbe4 100644
--- a/lib/Migrator/TupleSplatMigratorPass.cpp
+++ b/lib/Migrator/TupleSplatMigratorPass.cpp
@@ -88,13 +88,7 @@
 
     FunctionType *FuncTy = FC->getType()->getAs<FunctionType>();
 
-    unsigned NativeArity = 0;
-    if (isa<ParenType>(FuncTy->getInput().getPointer())) {
-      NativeArity = 1;
-    } else if (auto TT = FuncTy->getInput()->getAs<TupleType>()) {
-      NativeArity = TT->getNumElements();
-    }
-
+    unsigned NativeArity = FuncTy->getParams().size();
     unsigned ClosureArity = Closure->getParameters()->size();
     if (NativeArity <= ClosureArity)
       return false;
@@ -149,10 +143,10 @@
       auto fnTy = E->getFn()->getType()->getAs<FunctionType>();
       if (!fnTy)
         return false;
-      auto parenT = dyn_cast<ParenType>(fnTy->getInput().getPointer());
-      if (!parenT)
+      if (!(fnTy->getParams().size() == 1 &&
+            fnTy->getParams().front().getLabel().empty()))
         return false;
-      auto inp = dyn_cast<TupleType>(parenT->getUnderlyingType().getPointer());
+      auto inp = fnTy->getParams().front().getType()->getAs<TupleType>();
       if (!inp)
         return false;
       if (inp->getNumElements() != 0)
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0d396c1..4b9789f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -3503,7 +3503,8 @@
     name = P.Context.getIdentifier(implName);
   }
 
-  auto result = new (P.Context) ParamDecl(/*IsLet*/true,SourceLoc(),SourceLoc(),
+  auto result = new (P.Context) ParamDecl(VarDecl::Specifier::None,
+                                          SourceLoc(),SourceLoc(),
                                           Identifier(), nameLoc, name,
                                           Type(), P.CurDeclContext);
   if (isNameImplicit)
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 13aac5b..1dd4a5c 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1474,8 +1474,10 @@
         peekToken().isNot(tok::period, tok::period_prefix, tok::l_paren)) {
       Identifier name;
       SourceLoc loc = consumeIdentifier(&name);
-      auto pattern = createBindingFromPattern(loc, name,
-                                              InVarOrLetPattern != IVOLP_InVar);
+      auto specifier = (InVarOrLetPattern != IVOLP_InVar)
+                     ? VarDecl::Specifier::Let
+                     : VarDecl::Specifier::Var;
+      auto pattern = createBindingFromPattern(loc, name, specifier);
       Result = makeParserResult(new (Context) UnresolvedPatternExpr(pattern));
       break;
     }
@@ -2319,8 +2321,11 @@
       // Create the VarDecl and the PatternBindingDecl for the captured
       // expression.  This uses the parent declcontext (not the closure) since
       // the initializer expression is evaluated before the closure is formed.
+      auto specifierKind = (ownershipKind != Ownership::Weak)
+                         ? VarDecl::Specifier::Let
+                         : VarDecl::Specifier::Var;
       auto *VD = new (Context) VarDecl(/*isStatic*/false,
-                                       /*isLet*/ownershipKind !=Ownership::Weak,
+                                       specifierKind,
                                        /*isCaptureList*/true,
                                        nameLoc, name, Type(), CurDeclContext);
 
@@ -2368,7 +2373,7 @@
 
         Identifier name = Tok.is(tok::identifier) ?
             Context.getIdentifier(Tok.getText()) : Identifier();
-        auto var = new (Context) ParamDecl(/*IsLet*/ true, SourceLoc(),
+        auto var = new (Context) ParamDecl(VarDecl::Specifier::None, SourceLoc(),
                                            SourceLoc(), Identifier(),
                                            Tok.getLoc(), name, Type(), nullptr);
         elements.push_back(var);
@@ -2667,7 +2672,7 @@
     StringRef varName = ("$" + Twine(nextIdx)).toStringRef(StrBuf);
     Identifier ident = Context.getIdentifier(varName);
     SourceLoc varLoc = leftBraceLoc;
-    auto *var = new (Context) ParamDecl(/*IsLet*/ true, SourceLoc(),SourceLoc(),
+    auto *var = new (Context) ParamDecl(VarDecl::Specifier::None, SourceLoc(),SourceLoc(),
                                         Identifier(), varLoc, ident, Type(),
                                         closure);
     var->setImplicit();
diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp
index 0091b62..2a5a5fc 100644
--- a/lib/Parse/ParsePattern.cpp
+++ b/lib/Parse/ParsePattern.cpp
@@ -184,20 +184,20 @@
     bool hasSpecifier = false;
     while (Tok.isAny(tok::kw_inout, tok::kw_let, tok::kw_var)) {
       if (!hasSpecifier) {
-        if (Tok.is(tok::kw_let)) {
-          diagnose(Tok, diag::parameter_let_as_attr)
-            .fixItRemove(Tok.getLoc());
+        if (Tok.is(tok::kw_inout)) {
+          // This case is handled later when mapping to ParamDecls for
+          // better fixits.
+          param.SpecifierKind = VarDecl::Specifier::InOut;
         } else {
-          // We handle the var error in sema for a better fixit and inout is
-          // handled later in this function for better fixits.
-          param.SpecifierKind = Tok.is(tok::kw_inout) ? ParsedParameter::InOut :
-                                                        ParsedParameter::Var;
+          diagnose(Tok, diag::parameter_let_var_as_attr,
+                   unsigned(Tok.is(tok::kw_let)))
+            .fixItRemove(Tok.getLoc());
         }
-        param.LetVarInOutLoc = consumeToken();
+        param.SpecifierLoc = consumeToken();
         hasSpecifier = true;
       } else {
-        // Redundant specifiers are fairly common, recognize, reject, and recover
-        // from this gracefully.
+        // Redundant specifiers are fairly common, recognize, reject, and
+        // recover from this gracefully.
         diagnose(Tok, diag::parameter_inout_var_let_repeated)
           .fixItRemove(Tok.getLoc());
         consumeToken();
@@ -341,9 +341,8 @@
                          Identifier argName, SourceLoc argNameLoc,
                          Identifier paramName, SourceLoc paramNameLoc)
   -> ParamDecl * {
-    auto specifierKind = paramInfo.SpecifierKind;
-    bool isLet = specifierKind == Parser::ParsedParameter::Let;
-    auto param = new (ctx) ParamDecl(isLet, paramInfo.LetVarInOutLoc,
+    auto param = new (ctx) ParamDecl(paramInfo.SpecifierKind,
+                                     paramInfo.SpecifierLoc,
                                      argNameLoc, argName,
                                      paramNameLoc, paramName, Type(),
                                      parser.CurDeclContext);
@@ -359,8 +358,8 @@
     // If a type was provided, create the type for the parameter.
     if (auto type = paramInfo.Type) {
       // If 'inout' was specified, turn the type into an in-out type.
-      if (specifierKind == Parser::ParsedParameter::InOut) {
-        auto InOutLoc = paramInfo.LetVarInOutLoc;
+      if (paramInfo.SpecifierKind == VarDecl::Specifier::InOut) {
+        auto InOutLoc = paramInfo.SpecifierLoc;
         if (isa<InOutTypeRepr>(type)) {
           parser.diagnose(InOutLoc, diag::parameter_inout_var_let_repeated)
             .fixItRemove(InOutLoc);
@@ -379,10 +378,10 @@
       
       param->getTypeLoc() = TypeLoc::withoutLoc(ErrorType::get(ctx));
       param->setInvalid();
-    } else if (specifierKind == Parser::ParsedParameter::InOut) {
-      parser.diagnose(paramInfo.LetVarInOutLoc, diag::inout_must_have_type);
-      paramInfo.LetVarInOutLoc = SourceLoc();
-      specifierKind = Parser::ParsedParameter::Let;
+    } else if (paramInfo.SpecifierKind == VarDecl::Specifier::InOut) {
+      parser.diagnose(paramInfo.SpecifierLoc, diag::inout_must_have_type);
+      paramInfo.SpecifierLoc = SourceLoc();
+      paramInfo.SpecifierKind = VarDecl::Specifier::None;
     }
     return param;
   };
@@ -797,12 +796,14 @@
   case tok::identifier: {
     Identifier name;
     SourceLoc loc = consumeIdentifier(&name);
-    bool isLet = InVarOrLetPattern != IVOLP_InVar;
-
+    bool isLet = (InVarOrLetPattern != IVOLP_InVar);
+    auto specifier = isLet
+                   ? VarDecl::Specifier::Let
+                   : VarDecl::Specifier::Var;
     if (Tok.isIdentifierOrUnderscore() && !Tok.isContextualDeclKeyword())
       diagnoseConsecutiveIDs(name.str(), loc, isLet ? "constant" : "variable");
 
-    return makeParserResult(createBindingFromPattern(loc, name, isLet));
+    return makeParserResult(createBindingFromPattern(loc, name, specifier));
   }
     
   case tok::code_complete:
@@ -856,8 +857,8 @@
 }
 
 Pattern *Parser::createBindingFromPattern(SourceLoc loc, Identifier name,
-                                          bool isLet) {
-  auto var = new (Context) VarDecl(/*IsStatic*/false, /*IsLet*/isLet,
+                                          VarDecl::Specifier specifier) {
+  auto var = new (Context) VarDecl(/*IsStatic*/false, specifier,
                                    /*IsCaptureList*/false, loc, name, Type(),
                                    CurDeclContext);
   return new (Context) NamedPattern(var);
diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp
index 821ee5e..7d2f8c6 100644
--- a/lib/Parse/ParseSIL.cpp
+++ b/lib/Parse/ParseSIL.cpp
@@ -5100,7 +5100,7 @@
   // This is only used for parsing associated conformances, so we can
   // go ahead and just search the requirement signature for something that
   // matches the path.
-  for (auto &reqt : proto->getRequirementSignature()->getRequirements()) {
+  for (auto &reqt : proto->getRequirementSignature()) {
     if (reqt.getKind() != RequirementKind::Conformance)
       continue;
     CanType assocType = reqt.getFirstType()->getCanonicalType();
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index fdf630c..10937cf 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -882,7 +882,8 @@
       P.Tok.isAny(tok::l_brace, tok::kw_where)) {
     auto loc = P.Tok.getLoc();
     auto errorName = P.Context.Id_error;
-    auto var = new (P.Context) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+    auto var = new (P.Context) VarDecl(/*IsStatic*/false,
+                                       VarDecl::Specifier::Let,
                                        /*IsCaptureList*/false, loc, errorName,
                                        Type(), P.CurDeclContext);
     var->setImplicit();
diff --git a/lib/PrintAsObjC/PrintAsObjC.cpp b/lib/PrintAsObjC/PrintAsObjC.cpp
index 096c24d..5f23538 100644
--- a/lib/PrintAsObjC/PrintAsObjC.cpp
+++ b/lib/PrintAsObjC/PrintAsObjC.cpp
@@ -1719,7 +1719,7 @@
     os << ")(";
     Type paramsTy = FT->getInput();
     if (auto tupleTy = paramsTy->getAs<TupleType>()) {
-      if (tupleTy->getNumElements() == 0) {
+      if (FT->getParams().empty()) {
         os << "void";
       } else {
         interleave(tupleTy->getElements(),
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index 4f2ab4e..8b445f6 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -1887,21 +1887,29 @@
     });
   }
 
-  // Make sure that we do not have any lifetime ending uses left to visit. If we
-  // do, then these non lifetime ending uses must be outside of our "alive"
-  // blocks implying a use-after free.
+  // Make sure that we do not have any lifetime ending uses left to visit that
+  // are not transitively unreachable blocks. If we do, then these non lifetime
+  // ending uses must be outside of our "alive" blocks implying a use-after
+  // free.
   if (!BlocksWithNonLifetimeEndingUses.empty()) {
-    return handleError([&] {
-      llvm::errs() << "Function: '" << Value->getFunction()->getName() << "'\n"
-                   << "Found use after free due to unvisited non lifetime "
-                      "ending uses?!\n"
-                   << "Value: " << *Value << "    Remaining Users:\n";
-      for (auto &Pair : BlocksWithNonLifetimeEndingUses) {
-        llvm::errs() << "User:" << *Pair.second << "Block: bb"
-                     << Pair.first->getDebugID() << "\n";
+    for (auto &Pair : BlocksWithNonLifetimeEndingUses) {
+      if (TUB.isUnreachable(Pair.first)) {
+        continue;
       }
-      llvm::errs() << "\n";
-    });
+
+      return handleError([&] {
+        llvm::errs() << "Function: '" << Value->getFunction()->getName()
+                     << "'\n"
+                     << "Found use after free due to unvisited non lifetime "
+                        "ending uses?!\n"
+                     << "Value: " << *Value << "    Remaining Users:\n";
+        for (auto &Pair : BlocksWithNonLifetimeEndingUses) {
+          llvm::errs() << "User:" << *Pair.second << "Block: bb"
+                       << Pair.first->getDebugID() << "\n";
+        }
+        llvm::errs() << "\n";
+      });
+    }
   }
 
   return true;
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 2f002ef..1007ee7 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -34,7 +34,7 @@
   Type metatype = ctor->getInterfaceType()->castTo<AnyFunctionType>()->getInput();
   auto *DC = ctor->getInnermostDeclContext();
   auto &AC = gen.getASTContext();
-  auto VD = new (AC) ParamDecl(/*IsLet*/ true, SourceLoc(), SourceLoc(),
+  auto VD = new (AC) ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(),
                                AC.getIdentifier("$metatype"), SourceLoc(),
                                AC.getIdentifier("$metatype"), Type(),
                                DC);
@@ -61,7 +61,7 @@
     return tuple;
   } else {
     auto &AC = gen.getASTContext();
-    auto VD = new (AC) ParamDecl(/*IsLet*/ true, SourceLoc(), SourceLoc(),
+    auto VD = new (AC) ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(),
                                  AC.getIdentifier("$implicit_value"),
                                  SourceLoc(),
                                  AC.getIdentifier("$implicit_value"), Type(),
@@ -88,7 +88,8 @@
   SILValue resultSlot;
   if (selfTy.isAddressOnly(gen.SGM.M) && gen.silConv.useLoweredAddresses()) {
     auto &AC = gen.getASTContext();
-    auto VD = new (AC) ParamDecl(/*IsLet*/ false, SourceLoc(), SourceLoc(),
+    auto VD = new (AC) ParamDecl(VarDecl::Specifier::InOut,
+                                 SourceLoc(), SourceLoc(),
                                  AC.getIdentifier("$return_value"),
                                  SourceLoc(),
                                  AC.getIdentifier("$return_value"), Type(),
@@ -369,7 +370,8 @@
   std::unique_ptr<Initialization> dest;
   if (enumTI.isAddressOnly() && silConv.useLoweredAddresses()) {
     auto &AC = getASTContext();
-    auto VD = new (AC) ParamDecl(/*IsLet*/ false, SourceLoc(), SourceLoc(),
+    auto VD = new (AC) ParamDecl(VarDecl::Specifier::InOut,
+                                 SourceLoc(), SourceLoc(),
                                  AC.getIdentifier("$return_value"),
                                  SourceLoc(),
                                  AC.getIdentifier("$return_value"), Type(),
diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp
index 3f3333d..fd32d55 100644
--- a/lib/SILGen/SILGenProlog.cpp
+++ b/lib/SILGen/SILGenProlog.cpp
@@ -484,7 +484,8 @@
     return;
   }
   auto &ctx = gen.getASTContext();
-  auto var = new (ctx) ParamDecl(/*IsLet*/ false, SourceLoc(), SourceLoc(),
+  auto var = new (ctx) ParamDecl(VarDecl::Specifier::InOut,
+                                 SourceLoc(), SourceLoc(),
                                  ctx.getIdentifier("$return_value"), SourceLoc(),
                                  ctx.getIdentifier("$return_value"), Type(),
                                  DC);
diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
index 89d186c..7f5b5c0 100644
--- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp
+++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
@@ -452,7 +452,7 @@
   for (auto resultTy : pass.loweredFnConv.getIndirectSILResultTypes()) {
     auto bodyResultTy = pass.F->mapTypeIntoContext(resultTy);
     auto var = new (ctx)
-        ParamDecl(/*IsLet*/ false, SourceLoc(), SourceLoc(),
+        ParamDecl(VarDecl::Specifier::InOut, SourceLoc(), SourceLoc(),
                   ctx.getIdentifier("$return_value"), SourceLoc(),
                   ctx.getIdentifier("$return_value"),
                   bodyResultTy.getSwiftRValueType(), pass.F->getDeclContext());
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 6fa592f..b71f1f2 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -6157,28 +6157,30 @@
       if (!fnType)
         return false;
 
-      auto expectedArgType = FunctionType::get(fnType->getInput(), resultType,
-                                               fnType->getExtInfo());
-
-      auto expectedType =
-          FunctionType::get(expectedArgType, CS->getContextualType());
-
       class ClosureCalleeListener : public ExprTypeCheckListener {
-        Type contextualType;
+        Type InputType;
+        Type ResultType;
 
       public:
-        explicit ClosureCalleeListener(Type contextualType)
-            : contextualType(contextualType) {}
+        explicit ClosureCalleeListener(Type inputType, Type resultType)
+            : InputType(inputType), ResultType(resultType) {}
 
         bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
+          if (!InputType || !ResultType)
+            return false;
+
+          auto expectedType = FunctionType::get(InputType, ResultType);
           cs.addConstraint(ConstraintKind::Conversion, cs.getType(expr),
-                           contextualType, cs.getConstraintLocator(expr),
+                           expectedType, cs.getConstraintLocator(expr),
                            /*isFavored*/ true);
           return false;
         }
       };
 
-      ClosureCalleeListener listener(expectedType);
+      auto expectedArgType = FunctionType::get(fnType->getInput(), resultType,
+                                               fnType->getExtInfo());
+
+      ClosureCalleeListener listener(expectedArgType, CS->getContextualType());
       return !typeCheckChildIndependently(callExpr->getFn(), Type(),
                                           CTP_CalleeResult, TCC_ForceRecheck,
                                           &listener);
@@ -6192,7 +6194,7 @@
   return false;
 }
 
-/// Check if there failure associated with expresssion is related
+/// Check if there failure associated with expression is related
 /// to given contextual type.
 bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
     ApplyExpr *callExpr, Type contextualType) {
@@ -7165,7 +7167,7 @@
                        !resultType->hasTypeVariable();
               };
 
-              // If there an expected result type but it hasn't been explictly
+              // If there an expected result type but it hasn't been explicitly
               // provided, let's add it to the argument.
               if (hasResult(resultType) && !CE->hasExplicitResultType()) {
                 nameOS << " -> ";
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 70ab7b2..cb3ace4 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -696,8 +696,7 @@
     auto fTy = VD->getInterfaceType()->getAs<AnyFunctionType>();
     assert(fTy && "attempting to count parameters of a non-function type");
     
-    auto inputTy = fTy->getInput();
-    size_t nOperands = getOperandCount(inputTy);
+    size_t nOperands = fTy->getParams().size();
     size_t nNoDefault = 0;
     
     if (auto AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index ede0a70..14a3d5b 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1175,7 +1175,7 @@
                                         ConstraintKind kind,
                                         TypeMatchOptions flags,
                                         ConstraintLocatorBuilder locator) {
-  // FIXME: Fees like a hack.
+  // FIXME: Feels like a hack.
   if (type1->is<InOutType>())
     return SolutionKind::Error;
 
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 9589abd..6ae4189 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -60,9 +60,9 @@
                                 StringRef name,
                                 Type type,
                                 Type interfaceType,
-                                bool isLet) {
+                                VarDecl::Specifier specifier) {
   auto &context = DC->getASTContext();
-  auto *param = new (context) ParamDecl(isLet, SourceLoc(), SourceLoc(),
+  auto *param = new (context) ParamDecl(specifier, SourceLoc(), SourceLoc(),
                                         Identifier(), loc,
                                         context.getIdentifier(name),
                                         type, DC);
@@ -75,7 +75,8 @@
                                    StringRef name,
                                    Type type,
                                    Type interfaceType) {
-  return buildArgument(loc, DC, name, type, interfaceType, /*isLet*/ true);
+  return buildArgument(loc, DC, name, type, interfaceType,
+                       VarDecl::Specifier::None);
 }
 
 static ParamDecl *buildInOutArgument(SourceLoc loc, DeclContext *DC,
@@ -86,7 +87,7 @@
       loc, DC, name,
       InOutType::get(type),
       InOutType::get(interfaceType),
-      /*isLet*/ false);
+      VarDecl::Specifier::InOut);
 }
 
 static Type getTypeOfStorage(AbstractStorageDecl *storage,
@@ -963,7 +964,7 @@
     Expr *OldValueExpr
       = createPropertyLoadOrCallSuperclassGetter(Set, VD, TC);
 
-    OldValue = new (Ctx) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+    OldValue = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Let,
                                  /*IsCaptureList*/false, SourceLoc(),
                                  Ctx.getIdentifier("tmp"), Type(), Set);
     OldValue->setImplicit();
@@ -1086,7 +1087,7 @@
   SmallVector<ASTNode, 6> Body;
 
   // Load the existing storage and store it into the 'tmp1' temporary.
-  auto *Tmp1VD = new (Ctx) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+  auto *Tmp1VD = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Let,
                                    /*IsCaptureList*/false, SourceLoc(),
                                    Ctx.getIdentifier("tmp1"), Type(), Get);
   Tmp1VD->setImplicit();
@@ -1124,7 +1125,7 @@
                                   /*implicit*/ true, Ctx));
 
 
-  auto *Tmp2VD = new (Ctx) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+  auto *Tmp2VD = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Let,
                                    /*IsCaptureList*/false, SourceLoc(),
                                    Ctx.getIdentifier("tmp2"), VD->getType(),
                                    Get);
@@ -1200,8 +1201,11 @@
   SmallString<64> NameBuf = VD->getName().str();
   NameBuf += ".storage";
   auto StorageName = Context.getIdentifier(NameBuf);
+  auto storageSpecifier = BehaviorStorage->isSettable(DC)
+                        ? VarDecl::Specifier::Var
+                        : VarDecl::Specifier::Let;
   auto *Storage = new (Context) VarDecl(
-      /*IsStatic*/VD->isStatic(), /*IsLet*/!BehaviorStorage->isSettable(DC),
+      /*IsStatic*/VD->isStatic(), storageSpecifier,
       /*IsCaptureList*/false, VD->getLoc(), StorageName, SubstStorageContextTy,
       DC);
   Storage->setInterfaceType(SubstStorageInterfaceTy);
@@ -1387,7 +1391,8 @@
       llvm::raw_svector_ostream names(ParamNameBuf);
       names << "%arg." << i;
     }
-    auto param = new (Context) ParamDecl(/*let*/ true, SourceLoc(), SourceLoc(),
+    auto param = new (Context) ParamDecl(VarDecl::Specifier::None,
+                                         SourceLoc(), SourceLoc(),
                                          Identifier(),
                                          SourceLoc(),
                                          Context.getIdentifier(ParamNameBuf),
@@ -1484,7 +1489,8 @@
     if (!fromMutating
         && toAccessor->getImplicitSelfDecl()->isSettable(toAccessor)) {
       selfExpr->setType(selfTy);
-      auto var = new (Context) VarDecl(/*IsStatic*/false, /*IsLet*/false,
+      auto var = new (Context) VarDecl(/*IsStatic*/false,
+                                       VarDecl::Specifier::Var,
                                        /*IsCaptureList*/false, SourceLoc(),
                                        Context.getIdentifier("tempSelf"),
                                        selfTy, fromAccessor);
@@ -1595,7 +1601,7 @@
   auto StorageTy = OptionalType::get(VD->getType());
   auto StorageInterfaceTy = OptionalType::get(VD->getInterfaceType());
 
-  auto *Storage = new (Context) VarDecl(/*IsStatic*/false, /*IsLet*/false,
+  auto *Storage = new (Context) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Var,
                                         /*IsCaptureList*/false, VD->getLoc(),
                                         StorageName, StorageTy,
                                         VD->getDeclContext());
@@ -1940,7 +1946,7 @@
       }
 
       // Create the parameter.
-      auto *arg = new (context) ParamDecl(/*IsLet*/true, SourceLoc(), 
+      auto *arg = new (context) ParamDecl(VarDecl::Specifier::None, SourceLoc(), 
                                           Loc, var->getName(),
                                           Loc, var->getName(), varType, decl);
       arg->setInterfaceType(varInterfaceType);
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index d5617a5..5b038a9 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -460,17 +460,17 @@
 ///
 /// \param keyType The key type to bind to the container type.
 ///
-/// \param isLet Whether to declare the variable as immutable.
+/// \param spec Whether to declare the variable as immutable.
 static VarDecl *createKeyedContainer(ASTContext &C, DeclContext *DC,
                                      NominalTypeDecl *keyedContainerDecl,
-                                     Type keyType, bool isLet) {
+                                     Type keyType, VarDecl::Specifier spec) {
   // Bind Keyed*Container to Keyed*Container<KeyType>
   Type boundType[1] = {keyType};
   auto containerType = BoundGenericType::get(keyedContainerDecl, Type(),
                                              C.AllocateCopy(boundType));
 
   // let container : Keyed*Container<KeyType>
-  auto *containerDecl = new (C) VarDecl(/*IsStatic=*/false, /*IsLet=*/isLet,
+  auto *containerDecl = new (C) VarDecl(/*IsStatic=*/false, spec,
                                         /*IsCaptureList=*/false, SourceLoc(),
                                         C.Id_container, containerType, DC);
   containerDecl->setImplicit();
@@ -495,7 +495,7 @@
                                             Expr *base, Type returnType,
                                             NominalTypeDecl *param) {
   // (keyedBy:)
-  auto *keyedByDecl = new (C) ParamDecl(/*IsLet=*/true, SourceLoc(),
+  auto *keyedByDecl = new (C) ParamDecl(VarDecl::Specifier::None, SourceLoc(),
                                         SourceLoc(), C.Id_keyedBy, SourceLoc(),
                                         C.Id_keyedBy, returnType, DC);
   keyedByDecl->setImplicit();
@@ -568,7 +568,8 @@
   auto codingKeysType = codingKeysEnum->getDeclaredType();
   auto *containerDecl = createKeyedContainer(C, funcDC,
                                              C.getKeyedEncodingContainerDecl(),
-                                             codingKeysType, /*isLet=*/false);
+                                             codingKeysType,
+                                             VarDecl::Specifier::Var);
 
   auto *containerExpr = new (C) DeclRefExpr(ConcreteDeclRef(containerDecl),
                                             DeclNameLoc(), /*Implicit=*/true,
@@ -736,7 +737,7 @@
 
   // Params: (self [implicit], Encoder)
   auto *selfDecl = ParamDecl::createSelf(SourceLoc(), target);
-  auto *encoderParam = new (C) ParamDecl(/*isLet=*/true, SourceLoc(),
+  auto *encoderParam = new (C) ParamDecl(VarDecl::Specifier::None, SourceLoc(),
                                          SourceLoc(), C.Id_to, SourceLoc(),
                                          C.Id_encoder, encoderType, target);
   encoderParam->setInterfaceType(encoderType);
@@ -833,7 +834,8 @@
   auto codingKeysType = codingKeysEnum->getDeclaredType();
   auto *containerDecl = createKeyedContainer(C, funcDC,
                                              C.getKeyedDecodingContainerDecl(),
-                                             codingKeysType, /*isLet=*/true);
+                                             codingKeysType,
+                                             VarDecl::Specifier::Let);
 
   auto *containerExpr = new (C) DeclRefExpr(ConcreteDeclRef(containerDecl),
                                             DeclNameLoc(), /*Implicit=*/true,
@@ -1036,7 +1038,8 @@
   auto *selfDecl = ParamDecl::createSelf(SourceLoc(), target,
                                          /*isStatic=*/false,
                                          /*isInOut=*/inOut);
-  auto *decoderParamDecl = new (C) ParamDecl(/*isLet=*/true, SourceLoc(),
+  auto *decoderParamDecl = new (C) ParamDecl(VarDecl::Specifier::None,
+                                             SourceLoc(),
                                              SourceLoc(), C.Id_from,
                                              SourceLoc(), C.Id_decoder,
                                              decoderType, target);
diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp
index 055b973..3117c88 100644
--- a/lib/Sema/DerivedConformanceCodingKey.cpp
+++ b/lib/Sema/DerivedConformanceCodingKey.cpp
@@ -74,7 +74,7 @@
                                              DeclNameLoc(), /*Implicit=*/true);
 
   // rawValue param to init(rawValue:)
-  auto *rawValueDecl = new (C) ParamDecl(/*IsLet=*/true, SourceLoc(),
+  auto *rawValueDecl = new (C) ParamDecl(VarDecl::Specifier::None, SourceLoc(),
                                          SourceLoc(), C.Id_rawValue,
                                          SourceLoc(), C.Id_rawValue,
                                          valueParam->getType(), parentDC);
@@ -124,7 +124,7 @@
   auto *parentDC = cast<DeclContext>(parentDecl);
 
   // rawValue
-  auto *rawDecl = new (C) ParamDecl(/*IsLet*/ true, SourceLoc(), SourceLoc(),
+  auto *rawDecl = new (C) ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(),
                                     paramName, SourceLoc(), paramName,
                                     paramType, parentDC);
   rawDecl->setInterfaceType(paramType);
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 6460bd3..c98fda2 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -70,7 +70,7 @@
   Type enumType = enumVarDecl->getType();
   Type intType = C.getIntDecl()->getDeclaredType();
 
-  auto indexVar = new (C) VarDecl(/*IsStatic*/false, /*IsLet*/false,
+  auto indexVar = new (C) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Var,
                                   /*IsCaptureList*/false, SourceLoc(),
                                   C.getIdentifier(indexName), intType,
                                   funcDecl);
@@ -217,7 +217,7 @@
   auto enumIfaceTy = parentDC->getDeclaredInterfaceType();
 
   auto getParamDecl = [&](StringRef s) -> ParamDecl* {
-    auto *param = new (C) ParamDecl(/*isLet*/true, SourceLoc(), SourceLoc(),
+    auto *param = new (C) ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(),
                                     Identifier(), SourceLoc(), C.getIdentifier(s),
                                     enumTy, parentDC);
     param->setInterfaceType(enumIfaceTy);
@@ -438,7 +438,7 @@
     tc.Context.addExternalDecl(getterDecl);
 
   // Create the property.
-  VarDecl *hashValueDecl = new (C) VarDecl(/*IsStatic*/false, /*IsLet*/false,
+  VarDecl *hashValueDecl = new (C) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Var,
                                            /*IsCaptureList*/false, SourceLoc(),
                                            C.Id_hashValue, intType, parentDC);
   hashValueDecl->setImplicit();
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index c4a6a14..7a904ac 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -267,7 +267,7 @@
   auto *selfDecl = ParamDecl::createSelf(SourceLoc(), parentDC,
                                          /*static*/false, /*inout*/true);
 
-  auto *rawDecl = new (C) ParamDecl(/*IsLet*/true, SourceLoc(), SourceLoc(),
+  auto *rawDecl = new (C) ParamDecl(VarDecl::Specifier::None, SourceLoc(), SourceLoc(),
                                     C.Id_rawValue, SourceLoc(),
                                     C.Id_rawValue, rawType, parentDC);
   rawDecl->setInterfaceType(rawInterfaceType);
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 0da7a06..5c890bb 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -195,7 +195,7 @@
   auto &C = tc.Context;
   auto parentDC = cast<DeclContext>(parentDecl);
 
-  VarDecl *propDecl = new (C) VarDecl(/*IsStatic*/isStatic, /*IsLet*/false,
+  VarDecl *propDecl = new (C) VarDecl(/*IsStatic*/isStatic, VarDecl::Specifier::Var,
                                       /*IsCaptureList*/false, SourceLoc(), name,
                                       propertyContextType, parentDC);
   propDecl->setImplicit();
diff --git a/lib/Sema/PCMacro.cpp b/lib/Sema/PCMacro.cpp
index 275c6ba..3aef650 100644
--- a/lib/Sema/PCMacro.cpp
+++ b/lib/Sema/PCMacro.cpp
@@ -479,7 +479,7 @@
     }
 
     VarDecl *VD =
-        new (Context) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+        new (Context) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Let,
                               /*IsCaptureList*/false, SourceLoc(),
                               Context.getIdentifier(NameBuf),
                               MaybeLoadInitExpr->getType(), TypeCheckDC);
diff --git a/lib/Sema/PlaygroundTransform.cpp b/lib/Sema/PlaygroundTransform.cpp
index c7d0abc..a9173c1 100644
--- a/lib/Sema/PlaygroundTransform.cpp
+++ b/lib/Sema/PlaygroundTransform.cpp
@@ -744,7 +744,7 @@
     }
 
     VarDecl *VD =
-        new (Context) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+        new (Context) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Let,
                               /*IsCaptureList*/false, SourceLoc(),
                               Context.getIdentifier(NameBuf),
                               MaybeLoadInitExpr->getType(), TypeCheckDC);
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 864e5a7..05917db0 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -2651,7 +2651,8 @@
   PrettyStackTracePattern stackTrace(Context, "type-checking", EP);
 
   // Create a 'let' binding to stand in for the RHS value.
-  auto *matchVar = new (Context) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+  auto *matchVar = new (Context) VarDecl(/*IsStatic*/false,
+                                         VarDecl::Specifier::Let,
                                          /*IsCaptureList*/false,
                                          EP->getLoc(),
                                          Context.getIdentifier("$match"),
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 16634bb..63fe3b1 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -4709,7 +4709,9 @@
     TC.checkDeclAttributes(PD);
 
     if (TC.Context.LangOpts.DebugGenericSignatures) {
-      auto requirementsSig = PD->getRequirementSignature();
+      auto requirementsSig =
+        GenericSignature::get({PD->getProtocolSelfType()},
+                              PD->getRequirementSignature());
 
       llvm::errs() << "Protocol requirement signature:\n";
       PD->dumpRef(llvm::errs());
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 14d3a99..0fb3173 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -131,76 +131,89 @@
                              ArchetypeResolutionKind::CompleteWellFormed);
   assert(basePA && "Missing potential archetype for base");
 
-  // Local function to produce an error "no such member type" and return.
-  auto invalidMemberType = [&] {
-    // Complain that there is no suitable type.
-    Identifier name = ref->getIdentifier();
-    SourceLoc nameLoc = ref->getIdLoc();
-    TC.diagnose(nameLoc, diag::invalid_member_type, name, baseTy)
-      .highlight(baseRange);
-    return ErrorType::get(TC.Context);
-  };
-
   // Retrieve the potential archetype for the nested type.
   auto nestedPA = basePA->getNestedType(ref->getIdentifier(),
                                         ArchetypeResolutionKind::WellFormed,
                                         Builder);
-  if (!nestedPA)
-    return invalidMemberType();
 
-  // If this potential archetype was renamed due to typo correction,
-  // complain and fix it.
-  if (nestedPA->wasRenamed()) {
-    auto newName = nestedPA->getNestedName();
+  // If there was no such nested type, produce an error.
+  if (!nestedPA) {
+    // Perform typo correction.
+    LookupResult corrections;
+    TC.performTypoCorrection(DC, DeclRefKind::Ordinary,
+                             MetatypeType::get(baseTy),
+                             ref->getIdentifier(), ref->getIdLoc(),
+                             NameLookupFlags::ProtocolMembers,
+                             corrections, &Builder);
+
+    // Filter out non-types.
+    corrections.filter([](const LookupResult::Result &result) {
+      return isa<TypeDecl>(result.Decl);
+    });
+
+    // Check whether we have a single type result.
+    auto singleType = corrections.getSingleTypeResult();
+
+    // If we don't have a single result, complain and fail.
+    if (!singleType) {
+      Identifier name = ref->getIdentifier();
+      SourceLoc nameLoc = ref->getIdLoc();
+      TC.diagnose(nameLoc, diag::invalid_member_type, name, baseTy)
+        .highlight(baseRange);
+      for (const auto &suggestion : corrections)
+        TC.noteTypoCorrection(name, DeclNameLoc(nameLoc), suggestion);
+
+      return ErrorType::get(TC.Context);
+    }
+
+    // We have a single type result. Suggest it.
     TC.diagnose(ref->getIdLoc(), diag::invalid_member_type_suggest,
-                baseTy, ref->getIdentifier(), newName)
-      .fixItReplace(ref->getIdLoc(), newName.str());
-    ref->overwriteIdentifier(newName);
-    nestedPA->setAlreadyDiagnosedRename();
-    
-    // Go get the actual nested type.
-    nestedPA = basePA->getNestedType(newName,
-                                     ArchetypeResolutionKind::WellFormed,
-                                     Builder);
-    assert(nestedPA && "Nested type should have been available");
-    assert(!nestedPA->wasRenamed());
+                baseTy, ref->getIdentifier(),
+                singleType->getBaseName().getIdentifier())
+      .fixItReplace(ref->getIdLoc(),
+                    singleType->getBaseName().userFacingName());
+
+    // Correct to the single type result.
+    ref->overwriteIdentifier(singleType->getBaseName().getIdentifier());
+    ref->setValue(singleType);
+  } else if (auto assocType = nestedPA->getResolvedAssociatedType()) {
+    ref->setValue(assocType);
+  } else {
+    assert(nestedPA->getConcreteTypeDecl());
+    ref->setValue(nestedPA->getConcreteTypeDecl());
   }
 
   // If the nested type has been resolved to an associated type, use it.
-  if (auto assocType = nestedPA->getResolvedAssociatedType()) {
-    ref->setValue(assocType);
+  if (auto assocType = dyn_cast<AssociatedTypeDecl>(ref->getBoundDecl())) {
     return DependentMemberType::get(baseTy, assocType);
   }
 
-  // If the nested type comes from a concrete type, substitute the base type
-  // into it.
-  if (auto concrete = nestedPA->getConcreteTypeDecl()) {
-    ref->setValue(concrete);
-
-    if (baseTy->isTypeParameter()) {
-      if (auto proto =
-            concrete->getDeclContext()
-              ->getAsProtocolOrProtocolExtensionContext()) {
-        TC.validateDecl(proto);
-        auto subMap = SubstitutionMap::getProtocolSubstitutions(
-                        proto, baseTy, ProtocolConformanceRef(proto));
-        return concrete->getDeclaredInterfaceType().subst(subMap);
-      }
-
-      if (auto superclass = basePA->getSuperclass()) {
-        return superclass->getTypeOfMember(
-                                         DC->getParentModule(), concrete,
-                                         concrete->getDeclaredInterfaceType());
-      }
-
-      llvm_unreachable("shouldn't have a concrete decl here");
+  // Otherwise, the nested type comes from a concrete tpye. Substitute the
+  // base type into it.
+  auto concrete = ref->getBoundDecl();
+  TC.validateDeclForNameLookup(concrete);
+  if (!concrete->hasInterfaceType())
+    return ErrorType::get(TC.Context);
+  if (baseTy->isTypeParameter()) {
+    if (auto proto =
+          concrete->getDeclContext()
+            ->getAsProtocolOrProtocolExtensionContext()) {
+      TC.validateDecl(proto);
+      auto subMap = SubstitutionMap::getProtocolSubstitutions(
+                      proto, baseTy, ProtocolConformanceRef(proto));
+      return concrete->getDeclaredInterfaceType().subst(subMap);
     }
 
-    return TC.substMemberTypeWithBase(DC->getParentModule(), concrete, baseTy);
+    if (auto superclass = basePA->getSuperclass()) {
+      return superclass->getTypeOfMember(
+                                       DC->getParentModule(), concrete,
+                                       concrete->getDeclaredInterfaceType());
+    }
+
+    llvm_unreachable("shouldn't have a concrete decl here");
   }
 
-  assert(nestedPA->isUnresolved() && "meaningless unresolved type");
-  return invalidMemberType();
+  return TC.substMemberTypeWithBase(DC->getParentModule(), concrete, baseTy);
 }
 
 bool CompleteGenericTypeResolver::areSameType(Type type1, Type type2) {
@@ -747,8 +760,6 @@
                                                allGenericParams);
   if (checkGenericFuncSignature(*this, nullptr, func, completeResolver))
     invalid = true;
-  if (builder.diagnoseRemainingRenames(func->getLoc(), allGenericParams))
-    invalid = true;
 
   // The generic function signature is complete and well-formed. Determine
   // the type of the generic function.
@@ -981,8 +992,6 @@
                                                allGenericParams);
   if (checkGenericSubscriptSignature(*this, nullptr, subscript, completeResolver))
     invalid = true;
-  if (builder.diagnoseRemainingRenames(subscript->getLoc(), allGenericParams))
-    invalid = true;
 
   // The generic subscript signature is complete and well-formed. Determine
   // the type of the generic subscript.
@@ -1124,10 +1133,6 @@
                           &completeResolver);
   }
 
-  // Complain about any other renamed references.
-  (void)builder.diagnoseRemainingRenames(genericParams->getSourceRange().Start,
-                                         allGenericParams);
-
   // Record the generic type parameter types and the requirements.
   auto sig = builder.getGenericSignature();
 
diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp
index 7dfa084..939b307 100644
--- a/lib/Sema/TypeCheckNameLookup.cpp
+++ b/lib/Sema/TypeCheckNameLookup.cpp
@@ -562,6 +562,7 @@
                                         SourceLoc nameLoc,
                                         NameLookupOptions lookupOptions,
                                         LookupResult &result,
+                                        GenericSignatureBuilder *gsb,
                                         unsigned maxResults) {
   // Disable typo-correction if we won't show the diagnostic anyway.
   if (getLangOpts().DisableTypoCorrection ||
@@ -602,7 +603,7 @@
   TypoCorrectionResolver resolver(*this, nameLoc);
   if (baseTypeOrNull) {
     lookupVisibleMemberDecls(consumer, baseTypeOrNull, DC, &resolver,
-                             /*include instance members*/ true);
+                             /*include instance members*/ true, gsb);
   } else {
     lookupVisibleDecls(consumer, DC, &resolver, /*top level*/ true, nameLoc);
   }
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index e3bfc9c..0556b0e 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -671,74 +671,6 @@
   return hadError;
 }
 
-static void diagnoseAndMigrateVarParameterToBody(ParamDecl *decl,
-                                                 AbstractFunctionDecl *func,
-                                                 TypeChecker &TC) {
-  if (!func || !func->hasBody()) {
-    // If there is no function body, just suggest removal.
-    TC.diagnose(decl->getLetVarInOutLoc(),
-                diag::var_parameter_not_allowed)
-      .fixItRemove(decl->getLetVarInOutLoc());
-    return;
-  }
-  // Insert the shadow copy. The computations that follow attempt to
-  // 'best guess' the indentation and new lines so that the user
-  // doesn't have to add any whitespace.
-  auto declBody = func->getBody();
-  
-  auto &SM = TC.Context.SourceMgr;
-  
-  SourceLoc insertionStartLoc;
-  std::string start;
-  std::string end;
-  
-  auto lBraceLine = SM.getLineNumber(declBody->getLBraceLoc());
-  auto rBraceLine = SM.getLineNumber(declBody->getRBraceLoc());
-
-  if (!declBody->getNumElements()) {
-    
-    // Empty function body.
-    insertionStartLoc = declBody->getRBraceLoc();
-    
-    if (lBraceLine == rBraceLine) {
-      // Same line braces, means we probably have something
-      // like {} as the func body. Insert directly into body with spaces.
-      start = " ";
-      end = " ";
-    } else {
-      // Different line braces, so use RBrace's indentation.
-      end = "\n" + Lexer::getIndentationForLine(SM, declBody->
-                                                getRBraceLoc()).str();
-      start = "    "; // Guess 4 spaces as extra indentation.
-    }
-  } else {
-    auto firstLine = declBody->getElement(0);
-    insertionStartLoc = firstLine.getStartLoc();
-    if (lBraceLine == SM.getLineNumber(firstLine.getStartLoc())) {
-      // Function on same line, insert with semi-colon. Not ideal but
-      // better than weird space alignment.
-      start = "";
-      end = "; ";
-    } else {
-      start = "";
-      end = "\n" + Lexer::getIndentationForLine(SM, firstLine.
-                                                getStartLoc()).str();
-    }
-  }
-  if (insertionStartLoc.isInvalid()) {
-    TC.diagnose(decl->getLetVarInOutLoc(),
-                diag::var_parameter_not_allowed)
-    .fixItRemove(decl->getLetVarInOutLoc());
-    return;
-  }
-  auto parameterName = decl->getNameStr().str();
-  TC.diagnose(decl->getLetVarInOutLoc(),
-              diag::var_parameter_not_allowed)
-  .fixItRemove(decl->getLetVarInOutLoc())
-  .fixItInsert(insertionStartLoc, start + "var " + parameterName + " = " +
-               parameterName + end);
-}
-
 static bool validateParameterType(ParamDecl *decl, DeclContext *DC,
                                   TypeResolutionOptions options,
                                   GenericTypeResolver &resolver,
@@ -772,7 +704,7 @@
 
   // If the user did not explicitly write 'let', 'var', or 'inout', we'll let
   // type inference figure out what went wrong in detail.
-  if (decl->getLetVarInOutLoc().isValid()) {
+  if (decl->getSpecifierLoc().isValid()) {
     // If the param is not a 'let' and it is not an 'inout'.
     // It must be a 'var'. Provide helpful diagnostics like a shadow copy
     // in the function body to fix the 'var' attribute.
@@ -780,8 +712,6 @@
         !decl->isImplicit() &&
         (Ty.isNull() || !Ty->is<InOutType>()) &&
         !hadError) {
-      auto func = dyn_cast_or_null<AbstractFunctionDecl>(DC);
-      diagnoseAndMigrateVarParameterToBody(decl, func, TC);
       decl->setInvalid();
       hadError = true;
     }
@@ -984,7 +914,8 @@
   }
 
   // Create a new match variable $match.
-  auto *matchVar = new (tc.Context) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+  auto *matchVar = new (tc.Context) VarDecl(/*IsStatic*/false,
+                                            VarDecl::Specifier::Let,
                                             /*IsCaptureList*/false,
                                             pattern->getLoc(),
                                             tc.Context.getIdentifier("$match"),
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index e8336d2..fc52a57 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -4338,7 +4338,9 @@
                                           Proto, Conformance->getType(),
                                           ProtocolConformanceRef(Conformance));
 
-      auto requirementSig = Proto->getRequirementSignature();
+      auto requirementSig =
+        GenericSignature::get({Proto->getProtocolSelfType()},
+                              Proto->getRequirementSignature());
       auto result =
         TC.checkGenericArguments(DC, SourceLoc(), SourceLoc(),
                                  Conformance->getType(), requirementSig,
@@ -5006,7 +5008,8 @@
 
   CheckedRequirementSignature = true;
 
-  auto reqSig = proto->getRequirementSignature();
+  auto reqSig = GenericSignature::get({proto->getProtocolSelfType()},
+                                      proto->getRequirementSignature());
 
   auto substitutions = SubstitutionMap::getProtocolSubstitutions(
       proto, Conformance->getType(), ProtocolConformanceRef(Conformance));
diff --git a/lib/Sema/TypeCheckREPL.cpp b/lib/Sema/TypeCheckREPL.cpp
index d4bb655..3ec7e36 100644
--- a/lib/Sema/TypeCheckREPL.cpp
+++ b/lib/Sema/TypeCheckREPL.cpp
@@ -229,7 +229,7 @@
   TopLevelCodeDecl *newTopLevel = new (Context) TopLevelCodeDecl(&SF);
 
   // Build function of type T->() which prints the operand.
-  auto *Arg = new (Context) ParamDecl(/*isLet=*/true, SourceLoc(),
+  auto *Arg = new (Context) ParamDecl(VarDecl::Specifier::None, SourceLoc(),
                                          SourceLoc(), Identifier(),
                                          Loc, Context.getIdentifier("arg"),
                                          E->getType(), /*DC*/ newTopLevel);
@@ -308,7 +308,8 @@
 
   // Create the meta-variable, let the typechecker name it.
   Identifier name = TC.getNextResponseVariableName(SF.getParentModule());
-  VarDecl *vd = new (Context) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+  VarDecl *vd = new (Context) VarDecl(/*IsStatic*/false,
+                                      VarDecl::Specifier::Let,
                                       /*IsCaptureList*/false, E->getStartLoc(),
                                       name, E->getType(), &SF);
   vd->setInterfaceType(E->getType());
@@ -381,7 +382,8 @@
 
     // Create the meta-variable, let the typechecker name it.
     Identifier name = TC.getNextResponseVariableName(SF.getParentModule());
-    VarDecl *vd = new (Context) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+    VarDecl *vd = new (Context) VarDecl(/*IsStatic*/false,
+                                        VarDecl::Specifier::Let,
                                         /*IsCaptureList*/false,
                                         PBD->getStartLoc(), name,
                                         pattern->getType(), &SF);
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 60633a6..da46efd 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -664,7 +664,7 @@
         name = "$"+np->getBoundName().str().str();
       name += "$generator";
       generator = new (TC.Context)
-        VarDecl(/*IsStatic*/false, /*IsLet*/false, /*IsCaptureList*/false,
+        VarDecl(/*IsStatic*/false, VarDecl::Specifier::Var, /*IsCaptureList*/false,
                 S->getInLoc(), TC.Context.getIdentifier(name), generatorTy, DC);
       generator->setInterfaceType(DC->mapTypeOutOfContext(generatorTy));
       generator->setImplicit();
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index bddca16..212a92c 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -2365,6 +2365,7 @@
                              SourceLoc lookupLoc,
                              NameLookupOptions lookupOptions,
                              LookupResult &result,
+                             GenericSignatureBuilder *gsb = nullptr,
                              unsigned maxResults = 4);
 
   void noteTypoCorrection(DeclName name, DeclNameLoc nameLoc,
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 5b53160..dc68761 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -654,16 +654,6 @@
   dc->getAsNominalTypeOrNominalTypeExtensionContext()
     ->registerProtocolConformance(conformance);
 
-  // Read requirement signature conformances.
-  SmallVector<ProtocolConformanceRef, 4> reqConformances;
-  for (auto req : proto->getRequirementSignature()->getRequirements()) {
-    if (req.getKind() == RequirementKind::Conformance) {
-      auto reqConformance = readConformance(DeclTypeCursor);
-      reqConformances.push_back(reqConformance);
-    }
-  }
-  conformance->setSignatureConformances(reqConformances);
-
   // If the conformance is complete, we're done.
   if (conformance->isComplete())
     return conformance;
@@ -2692,7 +2682,8 @@
   case decls_block::VAR_DECL: {
     IdentifierID nameID;
     DeclContextID contextID;
-    bool isImplicit, isObjC, isStatic, isLet, hasNonPatternBindingInit;
+    bool isImplicit, isObjC, isStatic, hasNonPatternBindingInit;
+    unsigned specifier;
     uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel;
     TypeID interfaceTypeID;
     DeclID getterID, setterID, materializeForSetID, willSetID, didSetID;
@@ -2700,7 +2691,7 @@
     ArrayRef<uint64_t> dependencyIDs;
 
     decls_block::VarLayout::readRecord(scratch, nameID, contextID,
-                                       isImplicit, isObjC, isStatic, isLet,
+                                       isImplicit, isObjC, isStatic, specifier,
                                        hasNonPatternBindingInit, storageKind,
                                        interfaceTypeID,
                                        getterID, setterID, materializeForSetID,
@@ -2729,7 +2720,8 @@
     if (declOrOffset.isComplete())
       return declOrOffset;
 
-    auto var = createDecl<VarDecl>(/*IsStatic*/isStatic, /*IsLet*/isLet,
+    auto var = createDecl<VarDecl>(/*IsStatic*/isStatic,
+                                   (VarDecl::Specifier)specifier,
                                    /*IsCaptureList*/false, SourceLoc(), name,
                                    Type(), DC);
     var->setHasNonPatternBindingInit(hasNonPatternBindingInit);
@@ -2774,17 +2766,18 @@
   case decls_block::PARAM_DECL: {
     IdentifierID argNameID, paramNameID;
     DeclContextID contextID;
-    bool isLet;
+    unsigned specifier;
     TypeID interfaceTypeID;
 
     decls_block::ParamLayout::readRecord(scratch, argNameID, paramNameID,
-                                         contextID, isLet, interfaceTypeID);
+                                         contextID, specifier, interfaceTypeID);
 
     auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
     if (declOrOffset.isComplete())
       return declOrOffset;
 
-    auto param = createDecl<ParamDecl>(isLet, SourceLoc(), SourceLoc(),
+    auto param = createDecl<ParamDecl>((VarDecl::Specifier)specifier,
+                                       SourceLoc(), SourceLoc(),
                                        getIdentifier(argNameID), SourceLoc(),
                                        getIdentifier(paramNameID), Type(), DC);
 
@@ -3066,9 +3059,7 @@
       proto->setImplicit();
     proto->computeType();
 
-    auto signature = GenericSignature::get(
-                               { proto->getProtocolSelfType() }, requirements);
-    proto->setRequirementSignature(signature);
+    proto->setRequirementSignature(requirements);
 
     proto->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo());
     proto->setCircularityCheck(CircularityCheck::Checked);
@@ -4596,13 +4587,16 @@
                                               typeCount,
                                               rawIDs);
 
-  // Skip requirement signature conformances.
-  auto proto = conformance->getProtocol();
-  for (auto req : proto->getRequirementSignature()->getRequirements()) {
+  // Read requirement signature conformances.
+  const ProtocolDecl *proto = conformance->getProtocol();
+  SmallVector<ProtocolConformanceRef, 4> reqConformances;
+  for (const auto &req : proto->getRequirementSignature()) {
     if (req.getKind() == RequirementKind::Conformance) {
-      (void)readConformance(DeclTypeCursor);
+      auto reqConformance = readConformance(DeclTypeCursor);
+      reqConformances.push_back(reqConformance);
     }
   }
+  conformance->setSignatureConformances(reqConformances);
 
   ArrayRef<uint64_t>::iterator rawIDIter = rawIDs.begin();
 
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index c78de3f..f43d585 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2291,6 +2291,20 @@
   llvm_unreachable("Unhandled ForeignErrorConvention in switch.");
 }
 
+/// Translate from the AST VarDeclSpecifier enum to the
+/// Serialization enum values, which are guaranteed to be stable.
+static uint8_t getRawStableVarDeclSpecifier(swift::VarDecl::Specifier sf) {
+  switch (sf) {
+  case swift::VarDecl::Specifier::Let:
+    return uint8_t(serialization::VarDeclSpecifier::Let);
+  case swift::VarDecl::Specifier::Var:
+    return uint8_t(serialization::VarDeclSpecifier::Var);
+  case swift::VarDecl::Specifier::InOut:
+    return uint8_t(serialization::VarDeclSpecifier::InOut);
+  }
+  llvm_unreachable("bad variable decl specifier kind");
+}
+
 void Serializer::writeForeignErrorConvention(const ForeignErrorConvention &fec){
   using namespace decls_block;
 
@@ -2807,7 +2821,7 @@
 
     writeGenericParams(proto->getGenericParams());
     writeGenericRequirements(
-        proto->getRequirementSignature()->getRequirements(), DeclTypeAbbrCodes);
+      proto->getRequirementSignature(), DeclTypeAbbrCodes);
     writeMembers(proto->getMembers(), true);
     writeDefaultWitnessTable(proto, DeclTypeAbbrCodes);
     break;
@@ -2818,7 +2832,7 @@
     verifyAttrSerializable(var);
 
     auto contextID = addDeclContextRef(var->getDeclContext());
-
+    
     Accessors accessors = getAccessors(var);
     uint8_t rawAccessLevel =
       getRawStableAccessibility(var->getFormalAccess());
@@ -2839,7 +2853,7 @@
                           var->isImplicit(),
                           var->isObjC(),
                           var->isStatic(),
-                          var->isLet(),
+                          getRawStableVarDeclSpecifier(var->getSpecifier()),
                           var->hasNonPatternBindingInit(),
                           (unsigned) accessors.Kind,
                           addTypeRef(ty),
@@ -2868,7 +2882,7 @@
                             addDeclBaseNameRef(param->getArgumentName()),
                             addDeclBaseNameRef(param->getName()),
                             contextID,
-                            param->isLet(),
+                            getRawStableVarDeclSpecifier(param->getSpecifier()),
                             addTypeRef(interfaceType));
 
     if (interfaceType->hasError()) {
diff --git a/stdlib/public/SDK/Foundation/JSONEncoder.swift b/stdlib/public/SDK/Foundation/JSONEncoder.swift
index c6367be..c7ee7cb 100644
--- a/stdlib/public/SDK/Foundation/JSONEncoder.swift
+++ b/stdlib/public/SDK/Foundation/JSONEncoder.swift
@@ -159,23 +159,23 @@
     // MARK: Properties
 
     /// The encoder's storage.
-    var storage: _JSONEncodingStorage
+    fileprivate var storage: _JSONEncodingStorage
 
     /// Options set on the top-level encoder.
-    let options: JSONEncoder._Options
+    fileprivate let options: JSONEncoder._Options
 
     /// The path to the current point in encoding.
-    var codingPath: [CodingKey?]
+    public var codingPath: [CodingKey?]
 
     /// Contextual user-provided information for use during encoding.
-    var userInfo: [CodingUserInfoKey : Any] {
+    public var userInfo: [CodingUserInfoKey : Any] {
         return self.options.userInfo
     }
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given top-level encoder options.
-    init(options: JSONEncoder._Options, codingPath: [CodingKey?] = []) {
+    fileprivate init(options: JSONEncoder._Options, codingPath: [CodingKey?] = []) {
         self.options = options
         self.storage = _JSONEncodingStorage()
         self.codingPath = codingPath
@@ -187,7 +187,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -197,7 +197,7 @@
     /// Returns whether a new element can be encoded at this coding path.
     ///
     /// `true` if an element has not yet been encoded at this coding path; `false` otherwise.
-    var canEncodeNewValue: Bool {
+    fileprivate var canEncodeNewValue: Bool {
         // Every time a new value gets encoded, the key it's encoded for is pushed onto the coding path (even if it's a nil key from an unkeyed container).
         // At the same time, every time a container is requested, a new value gets pushed onto the storage stack.
         // If there are more values on the storage stack than on the coding path, it means the value is requesting more than one container, which violates the precondition.
@@ -208,7 +208,7 @@
     }
 
     // MARK: - Encoder Methods
-    func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
+    public func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
         // If an existing keyed container was already requested, return that one.
         let topContainer: NSMutableDictionary
         if self.canEncodeNewValue {
@@ -226,7 +226,7 @@
         return KeyedEncodingContainer(container)
     }
 
-    func unkeyedContainer() -> UnkeyedEncodingContainer {
+    public func unkeyedContainer() -> UnkeyedEncodingContainer {
         // If an existing unkeyed container was already requested, return that one.
         let topContainer: NSMutableArray
         if self.canEncodeNewValue {
@@ -243,7 +243,7 @@
         return _JSONUnkeyedEncodingContainer(referencing: self, codingPath: self.codingPath, wrapping: topContainer)
     }
 
-    func singleValueContainer() -> SingleValueEncodingContainer {
+    public func singleValueContainer() -> SingleValueEncodingContainer {
         return self
     }
 }
@@ -255,36 +255,36 @@
 
     /// The container stack.
     /// Elements may be any one of the JSON types (NSNull, NSNumber, NSString, NSArray, NSDictionary).
-    private(set) var containers: [NSObject] = []
+    private(set) fileprivate var containers: [NSObject] = []
 
     // MARK: - Initialization
 
     /// Initializes `self` with no containers.
-    init() {}
+    fileprivate init() {}
 
     // MARK: - Modifying the Stack
 
-    var count: Int {
+    fileprivate var count: Int {
         return self.containers.count
     }
 
-    mutating func pushKeyedContainer() -> NSMutableDictionary {
+    fileprivate mutating func pushKeyedContainer() -> NSMutableDictionary {
         let dictionary = NSMutableDictionary()
         self.containers.append(dictionary)
         return dictionary
     }
 
-    mutating func pushUnkeyedContainer() -> NSMutableArray {
+    fileprivate mutating func pushUnkeyedContainer() -> NSMutableArray {
         let array = NSMutableArray()
         self.containers.append(array)
         return array
     }
 
-    mutating func push(container: NSObject) {
+    fileprivate mutating func push(container: NSObject) {
         self.containers.append(container)
     }
 
-    mutating func popContainer() -> NSObject {
+    fileprivate mutating func popContainer() -> NSObject {
         precondition(self.containers.count > 0, "Empty container stack.")
         return self.containers.popLast()!
     }
@@ -298,18 +298,18 @@
     // MARK: Properties
 
     /// A reference to the encoder we're writing to.
-    let encoder: _JSONEncoder
+    private let encoder: _JSONEncoder
 
     /// A reference to the container we're writing to.
-    let container: NSMutableDictionary
+    private let container: NSMutableDictionary
 
     /// The path of coding keys taken to get to this point in encoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given references.
-    init(referencing encoder: _JSONEncoder, codingPath: [CodingKey?], wrapping container: NSMutableDictionary) {
+    fileprivate init(referencing encoder: _JSONEncoder, codingPath: [CodingKey?], wrapping container: NSMutableDictionary) {
         self.encoder = encoder
         self.codingPath = codingPath
         self.container = container
@@ -321,7 +321,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -330,40 +330,41 @@
 
     // MARK: - KeyedEncodingContainerProtocol Methods
 
-    mutating func encode(_ value: Bool, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int, forKey key: Key)    throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int8, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int16, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int32, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int64, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt8, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encodeNil(forKey key: Key)               throws { self.container[key.stringValue] = NSNull() }
+    public mutating func encode(_ value: Bool, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int, forKey key: Key)    throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int8, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int16, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int32, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int64, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt8, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
 
-    mutating func encode(_ value: Float, forKey key: Key)  throws {
+    public mutating func encode(_ value: Float, forKey key: Key)  throws {
         // Since the float may be invalid and throw, the coding path needs to contain this key.
         try self.encoder.with(pushedKey: key) {
             self.container[key.stringValue] = try self.encoder.box(value)
         }
     }
 
-    mutating func encode(_ value: Double, forKey key: Key) throws {
+    public mutating func encode(_ value: Double, forKey key: Key) throws {
         // Since the double may be invalid and throw, the coding path needs to contain this key.
         try self.encoder.with(pushedKey: key) {
             self.container[key.stringValue] = try self.encoder.box(value)
         }
     }
 
-    mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
+    public mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
         try self.encoder.with(pushedKey: key) {
             self.container[key.stringValue] = try self.encoder.box(value)
         }
     }
 
-    mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
+    public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
         let dictionary = NSMutableDictionary()
         self.container[key.stringValue] = dictionary
 
@@ -373,7 +374,7 @@
         }
     }
 
-    mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
+    public mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
         let array = NSMutableArray()
         self.container[key.stringValue] = array
 
@@ -382,11 +383,11 @@
         }
     }
 
-    mutating func superEncoder() -> Encoder {
+    public mutating func superEncoder() -> Encoder {
         return _JSONReferencingEncoder(referencing: self.encoder, at: _JSONSuperKey.super, wrapping: self.container)
     }
 
-    mutating func superEncoder(forKey key: Key) -> Encoder {
+    public mutating func superEncoder(forKey key: Key) -> Encoder {
         return _JSONReferencingEncoder(referencing: self.encoder, at: key, wrapping: self.container)
     }
 }
@@ -395,18 +396,18 @@
     // MARK: Properties
 
     /// A reference to the encoder we're writing to.
-    let encoder: _JSONEncoder
+    private let encoder: _JSONEncoder
 
     /// A reference to the container we're writing to.
-    let container: NSMutableArray
+    private let container: NSMutableArray
 
     /// The path of coding keys taken to get to this point in encoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given references.
-    init(referencing encoder: _JSONEncoder, codingPath: [CodingKey?], wrapping container: NSMutableArray) {
+    fileprivate init(referencing encoder: _JSONEncoder, codingPath: [CodingKey?], wrapping container: NSMutableArray) {
         self.encoder = encoder
         self.codingPath = codingPath
         self.container = container
@@ -418,7 +419,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -427,40 +428,41 @@
 
     // MARK: - UnkeyedEncodingContainer Methods
 
-    mutating func encode(_ value: Bool)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int)    throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int8)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int16)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int32)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int64)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt8)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encodeNil()             throws { self.container.add(NSNull()) }
+    public mutating func encode(_ value: Bool)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int)    throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int8)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int16)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int32)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int64)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt8)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
 
-    mutating func encode(_ value: Float)  throws {
+    public mutating func encode(_ value: Float)  throws {
         // Since the float may be invalid and throw, the coding path needs to contain this key.
         try self.encoder.with(pushedKey: nil) {
             self.container.add(try self.encoder.box(value))
         }
     }
 
-    mutating func encode(_ value: Double) throws {
+    public mutating func encode(_ value: Double) throws {
         // Since the double may be invalid and throw, the coding path needs to contain this key.
         try self.encoder.with(pushedKey: nil) {
             self.container.add(try self.encoder.box(value))
         }
     }
 
-    mutating func encode<T : Encodable>(_ value: T) throws {
+    public mutating func encode<T : Encodable>(_ value: T) throws {
         try self.encoder.with(pushedKey: nil) {
             self.container.add(try self.encoder.box(value))
         }
     }
 
-    mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
+    public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
         let dictionary = NSMutableDictionary()
         self.container.add(dictionary)
 
@@ -470,7 +472,7 @@
         }
     }
 
-    mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
+    public mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
         let array = NSMutableArray()
         self.container.add(array)
 
@@ -479,7 +481,7 @@
         }
     }
 
-    mutating func superEncoder() -> Encoder {
+    public mutating func superEncoder() -> Encoder {
         return _JSONReferencingEncoder(referencing: self.encoder, at: self.container.count, wrapping: self.container)
     }
 }
@@ -487,86 +489,86 @@
 extension _JSONEncoder : SingleValueEncodingContainer {
     // MARK: - SingleValueEncodingContainer Methods
 
-    func assertCanEncodeNewValue() {
+    fileprivate func assertCanEncodeNewValue() {
         precondition(self.canEncodeNewValue, "Attempt to encode value through single value container when previously value already encoded.")
     }
 
-    func encodeNil() throws {
+    public func encodeNil() throws {
         assertCanEncodeNewValue()
         self.storage.push(container: NSNull())
     }
 
-    func encode(_ value: Bool) throws {
+    public func encode(_ value: Bool) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int) throws {
+    public func encode(_ value: Int) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int8) throws {
+    public func encode(_ value: Int8) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int16) throws {
+    public func encode(_ value: Int16) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int32) throws {
+    public func encode(_ value: Int32) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int64) throws {
+    public func encode(_ value: Int64) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt) throws {
+    public func encode(_ value: UInt) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt8) throws {
+    public func encode(_ value: UInt8) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt16) throws {
+    public func encode(_ value: UInt16) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt32) throws {
+    public func encode(_ value: UInt32) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt64) throws {
+    public func encode(_ value: UInt64) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: String) throws {
+    public func encode(_ value: String) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Float) throws {
+    public func encode(_ value: Float) throws {
         assertCanEncodeNewValue()
         try self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Double) throws {
+    public func encode(_ value: Double) throws {
         assertCanEncodeNewValue()
         try self.storage.push(container: box(value))
     }
 
-    func encode<T : Encodable>(_ value: T) throws {
+    public func encode<T : Encodable>(_ value: T) throws {
         assertCanEncodeNewValue()
         try self.storage.push(container: box(value))
     }
@@ -727,7 +729,7 @@
     // MARK: Reference types.
 
     /// The type of container we're referencing.
-    enum Reference {
+    private enum Reference {
         /// Referencing a specific index in an array container.
         case array(NSMutableArray, Int)
 
@@ -738,15 +740,15 @@
     // MARK: - Properties
 
     /// The encoder we're referencing.
-    let encoder: _JSONEncoder
+    fileprivate let encoder: _JSONEncoder
 
     /// The container reference itself.
-    let reference: Reference
+    private let reference: Reference
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given array container in the given encoder.
-    init(referencing encoder: _JSONEncoder, at index: Int, wrapping array: NSMutableArray) {
+    fileprivate init(referencing encoder: _JSONEncoder, at index: Int, wrapping array: NSMutableArray) {
         self.encoder = encoder
         self.reference = .array(array, index)
         super.init(options: encoder.options, codingPath: encoder.codingPath)
@@ -755,7 +757,7 @@
     }
 
     /// Initializes `self` by referencing the given dictionary container in the given encoder.
-    init(referencing encoder: _JSONEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
+    fileprivate init(referencing encoder: _JSONEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
         self.encoder = encoder
         self.reference = .dictionary(dictionary, key.stringValue)
         super.init(options: encoder.options, codingPath: encoder.codingPath)
@@ -765,7 +767,7 @@
 
     // MARK: - Coding Path Operations
 
-    override var canEncodeNewValue: Bool {
+    fileprivate override var canEncodeNewValue: Bool {
         // With a regular encoder, the storage and coding path grow together.
         // A referencing encoder, however, inherits its parents coding path, as well as the key it was created for.
         // We have to take this into account.
@@ -905,23 +907,23 @@
     // MARK: Properties
 
     /// The decoder's storage.
-    var storage: _JSONDecodingStorage
+    fileprivate var storage: _JSONDecodingStorage
 
     /// Options set on the top-level decoder.
-    let options: JSONDecoder._Options
+    fileprivate let options: JSONDecoder._Options
 
     /// The path to the current point in encoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     /// Contextual user-provided information for use during encoding.
-    var userInfo: [CodingUserInfoKey : Any] {
+    public var userInfo: [CodingUserInfoKey : Any] {
         return self.options.userInfo
     }
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given top-level container and options.
-    init(referencing container: Any, at codingPath: [CodingKey?] = [], options: JSONDecoder._Options) {
+    fileprivate init(referencing container: Any, at codingPath: [CodingKey?] = [], options: JSONDecoder._Options) {
         self.storage = _JSONDecodingStorage()
         self.storage.push(container: container)
         self.codingPath = codingPath
@@ -934,7 +936,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -943,7 +945,7 @@
 
     // MARK: - Decoder Methods
 
-    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
+    public func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
         guard !(self.storage.topContainer is NSNull) else {
             throw DecodingError.valueNotFound(KeyedDecodingContainer<Key>.self,
                                               DecodingError.Context(codingPath: self.codingPath,
@@ -958,7 +960,7 @@
         return KeyedDecodingContainer(container)
     }
 
-    func unkeyedContainer() throws -> UnkeyedDecodingContainer {
+    public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
         guard !(self.storage.topContainer is NSNull) else {
             throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
                                               DecodingError.Context(codingPath: self.codingPath,
@@ -972,7 +974,7 @@
         return _JSONUnkeyedDecodingContainer(referencing: self, wrapping: topContainer)
     }
 
-    func singleValueContainer() throws -> SingleValueDecodingContainer {
+    public func singleValueContainer() throws -> SingleValueDecodingContainer {
         return self
     }
 }
@@ -984,29 +986,29 @@
 
     /// The container stack.
     /// Elements may be any one of the JSON types (NSNull, NSNumber, String, Array, [String : Any]).
-    private(set) var containers: [Any] = []
+    private(set) fileprivate var containers: [Any] = []
 
     // MARK: - Initialization
 
     /// Initializes `self` with no containers.
-    init() {}
+    fileprivate init() {}
 
     // MARK: - Modifying the Stack
 
-    var count: Int {
+    fileprivate var count: Int {
         return self.containers.count
     }
 
-    var topContainer: Any {
+    fileprivate var topContainer: Any {
         precondition(self.containers.count > 0, "Empty container stack.")
         return self.containers.last!
     }
 
-    mutating func push(container: Any) {
+    fileprivate mutating func push(container: Any) {
         self.containers.append(container)
     }
 
-    mutating func popContainer() {
+    fileprivate mutating func popContainer() {
         precondition(self.containers.count > 0, "Empty container stack.")
         self.containers.removeLast()
     }
@@ -1020,18 +1022,18 @@
     // MARK: Properties
 
     /// A reference to the decoder we're reading from.
-    let decoder: _JSONDecoder
+    private let decoder: _JSONDecoder
 
     /// A reference to the container we're reading from.
-    let container: [String : Any]
+    private let container: [String : Any]
 
     /// The path of coding keys taken to get to this point in decoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given decoder and container.
-    init(referencing decoder: _JSONDecoder, wrapping container: [String : Any]) {
+    fileprivate init(referencing decoder: _JSONDecoder, wrapping container: [String : Any]) {
         self.decoder = decoder
         self.container = container
         self.codingPath = decoder.codingPath
@@ -1039,111 +1041,233 @@
 
     // MARK: - KeyedDecodingContainerProtocol Methods
 
-    var allKeys: [Key] {
+    public var allKeys: [Key] {
         return self.container.keys.flatMap { Key(stringValue: $0) }
     }
 
-    func contains(_ key: Key) -> Bool {
+    public func contains(_ key: Key) -> Bool {
         return self.container[key.stringValue] != nil
     }
 
-    func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
+    public func decodeNil(forKey key: Key) throws -> Bool {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
+        return entry is NSNull
+    }
+
+    public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Bool.self)
+            guard let value = try self.decoder.unbox(entry, as: Bool.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
+    public func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int.self)
+            guard let value = try self.decoder.unbox(entry, as: Int.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
+    public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int8.self)
+            guard let value = try self.decoder.unbox(entry, as: Int8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
+    public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int16.self)
+            guard let value = try self.decoder.unbox(entry, as: Int16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
+    public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int32.self)
+            guard let value = try self.decoder.unbox(entry, as: Int32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
+    public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int64.self)
+            guard let value = try self.decoder.unbox(entry, as: Int64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
+    public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
+    public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt8.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
+    public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt16.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
+    public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt32.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
+    public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt64.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
+    public func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Float.self)
+            guard let value = try self.decoder.unbox(entry, as: Float.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
+    public func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Double.self)
+            guard let value = try self.decoder.unbox(entry, as: Double.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
+    public func decode(_ type: String.Type, forKey key: Key) throws -> String {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: String.self)
+            guard let value = try self.decoder.unbox(entry, as: String.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Data.Type, forKey key: Key) throws -> Data? {
+    public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Data.self)
+            guard let value = try self.decoder.unbox(entry, as: T.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T? {
-        return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: T.self)
-        }
-    }
-
-    func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
+    public func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
         return try self.decoder.with(pushedKey: key) {
             guard let value = self.container[key.stringValue] else {
                 throw DecodingError.keyNotFound(key,
@@ -1160,7 +1284,7 @@
         }
     }
 
-    func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
+    public func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
         return try self.decoder.with(pushedKey: key) {
             guard let value = self.container[key.stringValue] else {
                 throw DecodingError.keyNotFound(key,
@@ -1176,23 +1300,18 @@
         }
     }
 
-    func _superDecoder(forKey key: CodingKey) throws -> Decoder {
-        return try self.decoder.with(pushedKey: key) {
-            guard let value = self.container[key.stringValue] else {
-                throw DecodingError.keyNotFound(key,
-                                                DecodingError.Context(codingPath: self.codingPath,
-                                                                      debugDescription: "Cannot get superDecoder() -- no value found for key \"\(key.stringValue)\""))
-            }
-
+    private func _superDecoder(forKey key: CodingKey) throws -> Decoder {
+        return self.decoder.with(pushedKey: key) {
+            let value: Any = self.container[key.stringValue] ?? NSNull()
             return _JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
         }
     }
 
-    func superDecoder() throws -> Decoder {
+    public func superDecoder() throws -> Decoder {
         return try _superDecoder(forKey: _JSONSuperKey.super)
     }
 
-    func superDecoder(forKey key: Key) throws -> Decoder {
+    public func superDecoder(forKey key: Key) throws -> Decoder {
         return try _superDecoder(forKey: key)
     }
 }
@@ -1201,21 +1320,21 @@
     // MARK: Properties
 
     /// A reference to the decoder we're reading from.
-    let decoder: _JSONDecoder
+    private let decoder: _JSONDecoder
 
     /// A reference to the container we're reading from.
-    let container: [Any]
+    private let container: [Any]
 
     /// The path of coding keys taken to get to this point in decoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     /// The index of the element we're about to decode.
-    var currentIndex: Int
+    private var currentIndex: Int
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given decoder and container.
-    init(referencing decoder: _JSONDecoder, wrapping container: [Any]) {
+    fileprivate init(referencing decoder: _JSONDecoder, wrapping container: [Any]) {
         self.decoder = decoder
         self.container = container
         self.codingPath = decoder.codingPath
@@ -1224,175 +1343,253 @@
 
     // MARK: - UnkeyedDecodingContainer Methods
 
-    var count: Int? {
+    public var count: Int? {
         return self.container.count
     }
 
-    var isAtEnd: Bool {
+    public var isAtEnd: Bool {
         return self.currentIndex >= self.count!
     }
 
-    mutating func decodeIfPresent(_ type: Bool.Type) throws -> Bool? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decodeNil() throws -> Bool {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(Any?.self, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
+
+        if self.container[self.currentIndex] is NSNull {
+            self.currentIndex += 1
+            return true
+        } else {
+            return false
+        }
+    }
+
+    public mutating func decode(_ type: Bool.Type) throws -> Bool {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int.Type) throws -> Int? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int.Type) throws -> Int {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int8.Type) throws -> Int8? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int8.Type) throws -> Int8 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int16.Type) throws -> Int16? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int16.Type) throws -> Int16 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int32.Type) throws -> Int32? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int32.Type) throws -> Int32 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int64.Type) throws -> Int64? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int64.Type) throws -> Int64 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt.Type) throws -> UInt? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt.Type) throws -> UInt {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt8.Type) throws -> UInt8? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt8.Type) throws -> UInt8 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt16.Type) throws -> UInt16? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt16.Type) throws -> UInt16 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt32.Type) throws -> UInt32? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt32.Type) throws -> UInt32 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt64.Type) throws -> UInt64? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt64.Type) throws -> UInt64 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Float.Type) throws -> Float? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Float.Type) throws -> Float {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Double.Type) throws -> Double? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Double.Type) throws -> Double {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: String.Type) throws -> String? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: String.Type) throws -> String {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Data.Type) throws -> Data? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode<T : Decodable>(_ type: T.Type) throws -> T {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Data.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent<T : Decodable>(_ type: T.Type) throws -> T? {
-        guard !self.isAtEnd else { return nil }
-
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self)
-            self.currentIndex += 1
-            return decoded
-        }
-    }
-
-    mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
+    public mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
         return try self.decoder.with(pushedKey: nil) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
@@ -1417,7 +1614,7 @@
         }
     }
 
-    mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
+    public mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
         return try self.decoder.with(pushedKey: nil) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
@@ -1441,7 +1638,7 @@
         }
     }
 
-    mutating func superDecoder() throws -> Decoder {
+    public mutating func superDecoder() throws -> Decoder {
         return try self.decoder.with(pushedKey: nil) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(Decoder.self,
@@ -1450,12 +1647,6 @@
             }
 
             let value = self.container[self.currentIndex]
-            guard !(value is NSNull) else {
-                throw DecodingError.valueNotFound(Decoder.self,
-                                                  DecodingError.Context(codingPath: self.codingPath,
-                                                                        debugDescription: "Cannot get superDecoder() -- found null value instead."))
-            }
-
             self.currentIndex += 1
             return _JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
         }
@@ -1465,159 +1656,89 @@
 extension _JSONDecoder : SingleValueDecodingContainer {
     // MARK: SingleValueDecodingContainer Methods
 
-    func decodeNil() -> Bool {
+    private func expectNonNull<T>(_ type: T.Type) throws {
+        guard !self.decodeNil() else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) but found null value instead."))
+        }
+    }
+
+    public func decodeNil() -> Bool {
         return self.storage.topContainer is NSNull
     }
 
-    // These all unwrap the result, since we couldn't have gotten a single value container if the topContainer was null.
-    func decode(_ type: Bool.Type) throws -> Bool {
-        guard let value = try self.unbox(self.storage.topContainer, as: Bool.self) else {
-            throw DecodingError.valueNotFound(Bool.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Bool but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Bool.Type) throws -> Bool {
+        try expectNonNull(Bool.self)
+        return try self.unbox(self.storage.topContainer, as: Bool.self)!
     }
 
-    func decode(_ type: Int.Type) throws -> Int {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int.self) else {
-            throw DecodingError.valueNotFound(Int.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int.Type) throws -> Int {
+        try expectNonNull(Int.self)
+        return try self.unbox(self.storage.topContainer, as: Int.self)!
     }
 
-    func decode(_ type: Int8.Type) throws -> Int8 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int8.self) else {
-            throw DecodingError.valueNotFound(Int8.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int8 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int8.Type) throws -> Int8 {
+        try expectNonNull(Int8.self)
+        return try self.unbox(self.storage.topContainer, as: Int8.self)!
     }
 
-    func decode(_ type: Int16.Type) throws -> Int16 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int16.self) else {
-            throw DecodingError.valueNotFound(Int16.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int16 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int16.Type) throws -> Int16 {
+        try expectNonNull(Int16.self)
+        return try self.unbox(self.storage.topContainer, as: Int16.self)!
     }
 
-    func decode(_ type: Int32.Type) throws -> Int32 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int32.self) else {
-            throw DecodingError.valueNotFound(Int32.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int32 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int32.Type) throws -> Int32 {
+        try expectNonNull(Int32.self)
+        return try self.unbox(self.storage.topContainer, as: Int32.self)!
     }
 
-    func decode(_ type: Int64.Type) throws -> Int64 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int64.self) else {
-            throw DecodingError.valueNotFound(Int64.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int64 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int64.Type) throws -> Int64 {
+        try expectNonNull(Int64.self)
+        return try self.unbox(self.storage.topContainer, as: Int64.self)!
     }
 
-    func decode(_ type: UInt.Type) throws -> UInt {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt.self) else {
-            throw DecodingError.valueNotFound(UInt.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt.Type) throws -> UInt {
+        try expectNonNull(UInt.self)
+        return try self.unbox(self.storage.topContainer, as: UInt.self)!
     }
 
-    func decode(_ type: UInt8.Type) throws -> UInt8 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt8.self) else {
-            throw DecodingError.valueNotFound(UInt8.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt8 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt8.Type) throws -> UInt8 {
+        try expectNonNull(UInt8.self)
+        return try self.unbox(self.storage.topContainer, as: UInt8.self)!
     }
 
-    func decode(_ type: UInt16.Type) throws -> UInt16 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt16.self) else {
-            throw DecodingError.valueNotFound(UInt16.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt16 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt16.Type) throws -> UInt16 {
+        try expectNonNull(UInt16.self)
+        return try self.unbox(self.storage.topContainer, as: UInt16.self)!
     }
 
-    func decode(_ type: UInt32.Type) throws -> UInt32 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt32.self) else {
-            throw DecodingError.valueNotFound(UInt32.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt32 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt32.Type) throws -> UInt32 {
+        try expectNonNull(UInt32.self)
+        return try self.unbox(self.storage.topContainer, as: UInt32.self)!
     }
 
-    func decode(_ type: UInt64.Type) throws -> UInt64 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt64.self) else {
-            throw DecodingError.valueNotFound(UInt64.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt64 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt64.Type) throws -> UInt64 {
+        try expectNonNull(UInt64.self)
+        return try self.unbox(self.storage.topContainer, as: UInt64.self)!
     }
 
-    func decode(_ type: Float.Type) throws -> Float {
-        guard let value = try self.unbox(self.storage.topContainer, as: Float.self) else {
-            throw DecodingError.valueNotFound(Float.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Float but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Float.Type) throws -> Float {
+        try expectNonNull(Float.self)
+        return try self.unbox(self.storage.topContainer, as: Float.self)!
     }
 
-    func decode(_ type: Double.Type) throws -> Double {
-        guard let value = try self.unbox(self.storage.topContainer, as: Double.self) else {
-            throw DecodingError.valueNotFound(Double.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Double but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Double.Type) throws -> Double {
+        try expectNonNull(Double.self)
+        return try self.unbox(self.storage.topContainer, as: Double.self)!
     }
 
-    func decode(_ type: String.Type) throws -> String {
-        guard let value = try self.unbox(self.storage.topContainer, as: String.self) else {
-            throw DecodingError.valueNotFound(String.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected String but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: String.Type) throws -> String {
+        try expectNonNull(String.self)
+        return try self.unbox(self.storage.topContainer, as: String.self)!
     }
 
-    func decode<T : Decodable>(_ type: T.Type) throws -> T {
-        guard let value = try self.unbox(self.storage.topContainer, as: T.self) else {
-            throw DecodingError.valueNotFound(T.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected \(T.self) but found null value instead."))
-        }
-
-        return value
+    public func decode<T : Decodable>(_ type: T.Type) throws -> T {
+        try expectNonNull(T.self)
+        return try self.unbox(self.storage.topContainer, as: T.self)!
     }
 }
 
@@ -1625,8 +1746,7 @@
 
 extension _JSONDecoder {
     /// Returns the given value unboxed from a container.
-    fileprivate func unbox(_ value: Any?, as type: Bool.Type) throws -> Bool? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Bool.Type) throws -> Bool? {
         guard !(value is NSNull) else { return nil }
 
         if let number = value as? NSNumber {
@@ -1647,8 +1767,7 @@
         throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int.Type) throws -> Int? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int.Type) throws -> Int? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1663,8 +1782,7 @@
         return int
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int8.Type) throws -> Int8? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int8.Type) throws -> Int8? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1679,8 +1797,7 @@
         return int8
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int16.Type) throws -> Int16? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int16.Type) throws -> Int16? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1695,8 +1812,7 @@
         return int16
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int32.Type) throws -> Int32? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int32.Type) throws -> Int32? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1711,8 +1827,7 @@
         return int32
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int64.Type) throws -> Int64? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int64.Type) throws -> Int64? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1727,8 +1842,7 @@
         return int64
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt.Type) throws -> UInt? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt.Type) throws -> UInt? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1743,8 +1857,7 @@
         return uint
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt8.Type) throws -> UInt8? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt8.Type) throws -> UInt8? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1759,8 +1872,7 @@
         return uint8
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt16.Type) throws -> UInt16? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt16.Type) throws -> UInt16? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1775,8 +1887,7 @@
         return uint16
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt32.Type) throws -> UInt32? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt32.Type) throws -> UInt32? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1791,8 +1902,7 @@
         return uint32
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt64.Type) throws -> UInt64? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt64.Type) throws -> UInt64? {
         guard !(value is NSNull) else { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1807,8 +1917,7 @@
         return uint64
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Float.Type) throws -> Float? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Float.Type) throws -> Float? {
         guard !(value is NSNull) else { return nil }
 
         if let number = value as? NSNumber {
@@ -1854,8 +1963,7 @@
         throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
     }
 
-    func unbox(_ value: Any?, as type: Double.Type) throws -> Double? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Double.Type) throws -> Double? {
         guard !(value is NSNull) else { return nil }
 
         if let number = value as? NSNumber {
@@ -1890,8 +1998,7 @@
         throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
     }
 
-    func unbox(_ value: Any?, as type: String.Type) throws -> String? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: String.Type) throws -> String? {
         guard !(value is NSNull) else { return nil }
 
         guard let string = value as? String else {
@@ -1901,8 +2008,7 @@
         return string
     }
 
-    func unbox(_ value: Any?, as type: Date.Type) throws -> Date? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Date.Type) throws -> Date? {
         guard !(value is NSNull) else { return nil }
 
         switch self.options.dateDecodingStrategy {
@@ -1948,8 +2054,7 @@
         }
     }
 
-    func unbox(_ value: Any?, as type: Data.Type) throws -> Data? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Data.Type) throws -> Data? {
         guard !(value is NSNull) else { return nil }
 
         switch self.options.dataDecodingStrategy {
@@ -1978,8 +2083,7 @@
         }
     }
 
-    func unbox(_ value: Any?, as type: Decimal.Type) throws -> Decimal? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Decimal.Type) throws -> Decimal? {
         guard !(value is NSNull) else { return nil }
 
         // Attempt to bridge from NSDecimalNumber.
@@ -1991,15 +2095,14 @@
         }
     }
 
-    func unbox<T : Decodable>(_ value: Any?, as type: T.Type) throws -> T? {
-        guard let value = value else { return nil }
-        guard !(value is NSNull) else { return nil }
-
+    fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
         let decoded: T
         if T.self == Date.self {
-            decoded = (try self.unbox(value, as: Date.self) as! T)
+            guard let date = try self.unbox(value, as: Date.self) else { return nil }
+            decoded = date as! T
         } else if T.self == Data.self {
-            decoded = (try self.unbox(value, as: Data.self) as! T)
+            guard let data = try self.unbox(value, as: Data.self) else { return nil }
+            decoded = data as! T
         } else if T.self == URL.self {
             guard let urlString = try self.unbox(value, as: String.self) else {
                 return nil
@@ -2012,7 +2115,8 @@
 
             decoded = (url as! T)
         } else if T.self == Decimal.self {
-            decoded = (try self.unbox(value, as: Decimal.self) as! T)
+            guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil }
+            decoded = decimal as! T
         } else {
             self.storage.push(container: value)
             decoded = try T(from: self)
diff --git a/stdlib/public/SDK/Foundation/PlistEncoder.swift b/stdlib/public/SDK/Foundation/PlistEncoder.swift
index f5514ff..404ca71 100644
--- a/stdlib/public/SDK/Foundation/PlistEncoder.swift
+++ b/stdlib/public/SDK/Foundation/PlistEncoder.swift
@@ -88,23 +88,23 @@
     // MARK: Properties
 
     /// The encoder's storage.
-    var storage: _PlistEncodingStorage
+    fileprivate var storage: _PlistEncodingStorage
 
     /// Options set on the top-level encoder.
-    let options: PropertyListEncoder._Options
+    fileprivate let options: PropertyListEncoder._Options
 
     /// The path to the current point in encoding.
-    var codingPath: [CodingKey?]
+    fileprivate(set) public var codingPath: [CodingKey?]
 
     /// Contextual user-provided information for use during encoding.
-    var userInfo: [CodingUserInfoKey : Any] {
+    public var userInfo: [CodingUserInfoKey : Any] {
         return self.options.userInfo
     }
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given top-level encoder options.
-    init(options: PropertyListEncoder._Options, codingPath: [CodingKey?] = []) {
+    fileprivate init(options: PropertyListEncoder._Options, codingPath: [CodingKey?] = []) {
         self.options = options
         self.storage = _PlistEncodingStorage()
         self.codingPath = codingPath
@@ -116,7 +116,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -126,7 +126,7 @@
     /// Returns whether a new element can be encoded at this coding path.
     ///
     /// `true` if an element has not yet been encoded at this coding path; `false` otherwise.
-    var canEncodeNewValue: Bool {
+    fileprivate var canEncodeNewValue: Bool {
         // Every time a new value gets encoded, the key it's encoded for is pushed onto the coding path (even if it's a nil key from an unkeyed container).
         // At the same time, every time a container is requested, a new value gets pushed onto the storage stack.
         // If there are more values on the storage stack than on the coding path, it means the value is requesting more than one container, which violates the precondition.
@@ -137,7 +137,7 @@
     }
 
     // MARK: - Encoder Methods
-    func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
+    public func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
         // If an existing keyed container was already requested, return that one.
         let topContainer: NSMutableDictionary
         if self.canEncodeNewValue {
@@ -155,7 +155,7 @@
         return KeyedEncodingContainer(container)
     }
 
-    func unkeyedContainer() -> UnkeyedEncodingContainer {
+    public func unkeyedContainer() -> UnkeyedEncodingContainer {
         // If an existing unkeyed container was already requested, return that one.
         let topContainer: NSMutableArray
         if self.canEncodeNewValue {
@@ -172,7 +172,7 @@
         return _PlistUnkeyedEncodingContainer(referencing: self, codingPath: self.codingPath, wrapping: topContainer)
     }
 
-    func singleValueContainer() -> SingleValueEncodingContainer {
+    public func singleValueContainer() -> SingleValueEncodingContainer {
         return self
     }
 }
@@ -184,36 +184,36 @@
 
     /// The container stack.
     /// Elements may be any one of the plist types (NSNumber, NSString, NSDate, NSArray, NSDictionary).
-    private(set) var containers: [NSObject] = []
+    private(set) fileprivate var containers: [NSObject] = []
 
     // MARK: - Initialization
 
     /// Initializes `self` with no containers.
-    init() {}
+    fileprivate init() {}
 
     // MARK: - Modifying the Stack
 
-    var count: Int {
+    fileprivate var count: Int {
         return self.containers.count
     }
 
-    mutating func pushKeyedContainer() -> NSMutableDictionary {
+    fileprivate mutating func pushKeyedContainer() -> NSMutableDictionary {
         let dictionary = NSMutableDictionary()
         self.containers.append(dictionary)
         return dictionary
     }
 
-    mutating func pushUnkeyedContainer() -> NSMutableArray {
+    fileprivate mutating func pushUnkeyedContainer() -> NSMutableArray {
         let array = NSMutableArray()
         self.containers.append(array)
         return array
     }
 
-    mutating func push(container: NSObject) {
+    fileprivate mutating func push(container: NSObject) {
         self.containers.append(container)
     }
 
-    mutating func popContainer() -> NSObject {
+    fileprivate mutating func popContainer() -> NSObject {
         precondition(self.containers.count > 0, "Empty container stack.")
         return self.containers.popLast()!
     }
@@ -227,18 +227,18 @@
     // MARK: Properties
 
     /// A reference to the encoder we're writing to.
-    let encoder: _PlistEncoder
+    private let encoder: _PlistEncoder
 
     /// A reference to the container we're writing to.
-    let container: NSMutableDictionary
+    private let container: NSMutableDictionary
 
     /// The path of coding keys taken to get to this point in encoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given references.
-    init(referencing encoder: _PlistEncoder, codingPath: [CodingKey?], wrapping container: NSMutableDictionary) {
+    fileprivate init(referencing encoder: _PlistEncoder, codingPath: [CodingKey?], wrapping container: NSMutableDictionary) {
         self.encoder = encoder
         self.codingPath = codingPath
         self.container = container
@@ -250,7 +250,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -259,28 +259,29 @@
 
     // MARK: - KeyedEncodingContainerProtocol Methods
 
-    mutating func encode(_ value: Bool, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int, forKey key: Key)    throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int8, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int16, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int32, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Int64, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt8, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Float, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
-    mutating func encode(_ value: Double, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encodeNil(forKey key: Key)               throws { self.container[key.stringValue] = _plistNullNSString }
+    public mutating func encode(_ value: Bool, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int, forKey key: Key)    throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int8, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int16, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int32, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Int64, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt, forKey key: Key)   throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt8, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Float, forKey key: Key)  throws { self.container[key.stringValue] = self.encoder.box(value) }
+    public mutating func encode(_ value: Double, forKey key: Key) throws { self.container[key.stringValue] = self.encoder.box(value) }
 
-    mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
+    public mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
         try self.encoder.with(pushedKey: key) {
             self.container[key.stringValue] = try self.encoder.box(value)
         }
     }
 
-    mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
+    public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
         let dictionary = NSMutableDictionary()
         self.container[key.stringValue] = dictionary
 
@@ -290,7 +291,7 @@
         }
     }
 
-    mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
+    public mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
         let array = NSMutableArray()
         self.container[key.stringValue] = array
 
@@ -299,11 +300,11 @@
         }
     }
 
-    mutating func superEncoder() -> Encoder {
+    public mutating func superEncoder() -> Encoder {
         return _PlistReferencingEncoder(referencing: self.encoder, at: _PlistSuperKey.super, wrapping: self.container)
     }
 
-    mutating func superEncoder(forKey key: Key) -> Encoder {
+    public mutating func superEncoder(forKey key: Key) -> Encoder {
         return _PlistReferencingEncoder(referencing: self.encoder, at: key, wrapping: self.container)
     }
 }
@@ -312,18 +313,18 @@
     // MARK: Properties
 
     /// A reference to the encoder we're writing to.
-    let encoder: _PlistEncoder
+    private let encoder: _PlistEncoder
 
     /// A reference to the container we're writing to.
-    let container: NSMutableArray
+    private let container: NSMutableArray
 
     /// The path of coding keys taken to get to this point in encoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given references.
-    init(referencing encoder: _PlistEncoder, codingPath: [CodingKey?], wrapping container: NSMutableArray) {
+    fileprivate init(referencing encoder: _PlistEncoder, codingPath: [CodingKey?], wrapping container: NSMutableArray) {
         self.encoder = encoder
         self.codingPath = codingPath
         self.container = container
@@ -335,7 +336,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -344,28 +345,29 @@
 
     // MARK: - UnkeyedEncodingContainer Methods
 
-    mutating func encode(_ value: Bool)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int)    throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int8)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int16)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int32)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Int64)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt)   throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt8)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Float)  throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: Double) throws { self.container.add(self.encoder.box(value)) }
-    mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encodeNil()             throws { self.container.add(_plistNullNSString) }
+    public mutating func encode(_ value: Bool)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int)    throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int8)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int16)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int32)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Int64)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt)   throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt8)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Float)  throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: Double) throws { self.container.add(self.encoder.box(value)) }
+    public mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
 
-    mutating func encode<T : Encodable>(_ value: T) throws {
+    public mutating func encode<T : Encodable>(_ value: T) throws {
         try self.encoder.with(pushedKey: nil) {
             self.container.add(try self.encoder.box(value))
         }
     }
 
-    mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
+    public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
         let dictionary = NSMutableDictionary()
         self.container.add(dictionary)
 
@@ -375,7 +377,7 @@
         }
     }
 
-    mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
+    public mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
         let array = NSMutableArray()
         self.container.add(array)
 
@@ -384,7 +386,7 @@
         }
     }
 
-    mutating func superEncoder() -> Encoder {
+    public mutating func superEncoder() -> Encoder {
         return _PlistReferencingEncoder(referencing: self.encoder, at: self.container.count, wrapping: self.container)
     }
 }
@@ -392,86 +394,86 @@
 extension _PlistEncoder : SingleValueEncodingContainer {
     // MARK: - SingleValueEncodingContainer Methods
 
-    func assertCanEncodeNewValue() {
+    private func assertCanEncodeNewValue() {
         precondition(self.canEncodeNewValue, "Attempt to encode value through single value container when previously value already encoded.")
     }
 
-    func encodeNil() throws {
+    public func encodeNil() throws {
         assertCanEncodeNewValue()
         self.storage.push(container: _plistNullNSString)
     }
 
-    func encode(_ value: Bool) throws {
+    public func encode(_ value: Bool) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int) throws {
+    public func encode(_ value: Int) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int8) throws {
+    public func encode(_ value: Int8) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int16) throws {
+    public func encode(_ value: Int16) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int32) throws {
+    public func encode(_ value: Int32) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Int64) throws {
+    public func encode(_ value: Int64) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt) throws {
+    public func encode(_ value: UInt) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt8) throws {
+    public func encode(_ value: UInt8) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt16) throws {
+    public func encode(_ value: UInt16) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt32) throws {
+    public func encode(_ value: UInt32) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: UInt64) throws {
+    public func encode(_ value: UInt64) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: String) throws {
+    public func encode(_ value: String) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Float) throws {
+    public func encode(_ value: Float) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode(_ value: Double) throws {
+    public func encode(_ value: Double) throws {
         assertCanEncodeNewValue()
         self.storage.push(container: box(value))
     }
 
-    func encode<T : Encodable>(_ value: T) throws {
+    public func encode<T : Encodable>(_ value: T) throws {
         assertCanEncodeNewValue()
         try self.storage.push(container: box(value))
     }
@@ -529,7 +531,7 @@
     // MARK: Reference types.
 
     /// The type of container we're referencing.
-    enum Reference {
+    private enum Reference {
         /// Referencing a specific index in an array container.
         case array(NSMutableArray, Int)
 
@@ -540,15 +542,15 @@
     // MARK: - Properties
 
     /// The encoder we're referencing.
-    let encoder: _PlistEncoder
+    private let encoder: _PlistEncoder
 
     /// The container reference itself.
-    let reference: Reference
+    private let reference: Reference
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given array container in the given encoder.
-    init(referencing encoder: _PlistEncoder, at index: Int, wrapping array: NSMutableArray) {
+    fileprivate init(referencing encoder: _PlistEncoder, at index: Int, wrapping array: NSMutableArray) {
         self.encoder = encoder
         self.reference = .array(array, index)
         super.init(options: encoder.options, codingPath: encoder.codingPath)
@@ -557,7 +559,7 @@
     }
 
     /// Initializes `self` by referencing the given dictionary container in the given encoder.
-    init(referencing encoder: _PlistEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
+    fileprivate init(referencing encoder: _PlistEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
         self.encoder = encoder
         self.reference = .dictionary(dictionary, key.stringValue)
         super.init(options: encoder.options, codingPath: encoder.codingPath)
@@ -567,7 +569,7 @@
 
     // MARK: - Coding Path Operations
 
-    override var canEncodeNewValue: Bool {
+    fileprivate override var canEncodeNewValue: Bool {
         // With a regular encoder, the storage and coding path grow together.
         // A referencing encoder, however, inherits its parents coding path, as well as the key it was created for.
         // We have to take this into account.
@@ -661,23 +663,23 @@
     // MARK: Properties
 
     /// The decoder's storage.
-    var storage: _PlistDecodingStorage
+    fileprivate var storage: _PlistDecodingStorage
 
     /// Options set on the top-level decoder.
-    let options: PropertyListDecoder._Options
+    fileprivate let options: PropertyListDecoder._Options
 
     /// The path to the current point in encoding.
-    var codingPath: [CodingKey?]
+    fileprivate(set) public var codingPath: [CodingKey?]
 
     /// Contextual user-provided information for use during encoding.
-    var userInfo: [CodingUserInfoKey : Any] {
+    public var userInfo: [CodingUserInfoKey : Any] {
         return self.options.userInfo
     }
 
     // MARK: - Initialization
 
     /// Initializes `self` with the given top-level container and options.
-    init(referencing container: Any, at codingPath: [CodingKey?] = [], options: PropertyListDecoder._Options) {
+    fileprivate init(referencing container: Any, at codingPath: [CodingKey?] = [], options: PropertyListDecoder._Options) {
         self.storage = _PlistDecodingStorage()
         self.storage.push(container: container)
         self.codingPath = codingPath
@@ -690,7 +692,7 @@
     ///
     /// - parameter key: The key to push. May be nil for unkeyed containers.
     /// - parameter work: The work to perform with the key in the path.
-    func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
+    fileprivate func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
         self.codingPath.append(key)
         let ret: T = try work()
         self.codingPath.removeLast()
@@ -699,7 +701,7 @@
 
     // MARK: - Decoder Methods
 
-    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
+    public func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
         guard !(self.storage.topContainer is NSNull) else {
             throw DecodingError.valueNotFound(KeyedDecodingContainer<Key>.self,
                                               DecodingError.Context(codingPath: self.codingPath,
@@ -714,7 +716,7 @@
         return KeyedDecodingContainer(container)
     }
 
-    func unkeyedContainer() throws -> UnkeyedDecodingContainer {
+    public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
         guard !(self.storage.topContainer is NSNull) else {
             throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
                                               DecodingError.Context(codingPath: self.codingPath,
@@ -728,7 +730,7 @@
         return _PlistUnkeyedDecodingContainer(referencing: self, wrapping: topContainer)
     }
 
-    func singleValueContainer() throws -> SingleValueDecodingContainer {
+    public func singleValueContainer() throws -> SingleValueDecodingContainer {
         return self
     }
 }
@@ -740,29 +742,29 @@
 
     /// The container stack.
     /// Elements may be any one of the plist types (NSNumber, Date, String, Array, [String : Any]).
-    private(set) var containers: [Any] = []
+    private(set) fileprivate var containers: [Any] = []
 
     // MARK: - Initialization
 
     /// Initializes `self` with no containers.
-    init() {}
+    fileprivate init() {}
 
     // MARK: - Modifying the Stack
 
-    var count: Int {
+    fileprivate var count: Int {
         return self.containers.count
     }
 
-    var topContainer: Any {
+    fileprivate var topContainer: Any {
         precondition(self.containers.count > 0, "Empty container stack.")
         return self.containers.last!
     }
 
-    mutating func push(container: Any) {
+    fileprivate mutating func push(container: Any) {
         self.containers.append(container)
     }
 
-    mutating func popContainer() {
+    fileprivate mutating func popContainer() {
         precondition(self.containers.count > 0, "Empty container stack.")
         self.containers.removeLast()
     }
@@ -776,18 +778,18 @@
     // MARK: Properties
 
     /// A reference to the decoder we're reading from.
-    let decoder: _PlistDecoder
+    private let decoder: _PlistDecoder
 
     /// A reference to the container we're reading from.
-    let container: [String : Any]
+    private let container: [String : Any]
 
     /// The path of coding keys taken to get to this point in decoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given decoder and container.
-    init(referencing decoder: _PlistDecoder, wrapping container: [String : Any]) {
+    fileprivate init(referencing decoder: _PlistDecoder, wrapping container: [String : Any]) {
         self.decoder = decoder
         self.container = container
         self.codingPath = decoder.codingPath
@@ -795,111 +797,237 @@
 
     // MARK: - KeyedDecodingContainerProtocol Methods
 
-    var allKeys: [Key] {
+    public var allKeys: [Key] {
         return self.container.keys.flatMap { Key(stringValue: $0) }
     }
 
-    func contains(_ key: Key) -> Bool {
+    public func contains(_ key: Key) -> Bool {
         return self.container[key.stringValue] != nil
     }
 
-    func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
+    public func decodeNil(forKey key: Key) throws -> Bool {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
+        guard let value = entry as? String else {
+            return false
+        }
+
+        return value == _plistNull
+    }
+
+    public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Bool.self)
+            guard let value = try self.decoder.unbox(entry, as: Bool.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
+    public func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int.self)
+            guard let value = try self.decoder.unbox(entry, as: Int.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
+    public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int8.self)
+            guard let value = try self.decoder.unbox(entry, as: Int8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
+    public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int16.self)
+            guard let value = try self.decoder.unbox(entry, as: Int16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
+    public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int32.self)
+            guard let value = try self.decoder.unbox(entry, as: Int32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
+    public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Int64.self)
+            guard let value = try self.decoder.unbox(entry, as: Int64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
+    public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
+    public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt8.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
+    public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt16.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
+    public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt32.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
+    public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: UInt64.self)
+            guard let value = try self.decoder.unbox(entry, as: UInt64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
+    public func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Float.self)
+            guard let value = try self.decoder.unbox(entry, as: Float.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
+    public func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Double.self)
+            guard let value = try self.decoder.unbox(entry, as: Double.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
+    public func decode(_ type: String.Type, forKey key: Key) throws -> String {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: String.self)
+            guard let value = try self.decoder.unbox(entry, as: String.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent(_ type: Data.Type, forKey key: Key) throws -> Data? {
+    public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
+        guard let entry = self.container[key.stringValue] else {
+            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+        }
+
         return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: Data.self)
+            guard let value = try self.decoder.unbox(entry, as: T.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+            }
+
+            return value
         }
     }
 
-    func decodeIfPresent<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T? {
-        return try self.decoder.with(pushedKey: key) {
-            return try self.decoder.unbox(self.container[key.stringValue], as: T.self)
-        }
-    }
-
-    func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
+    public func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
         return try self.decoder.with(pushedKey: key) {
             guard let value = self.container[key.stringValue] else {
                 throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
@@ -916,7 +1044,7 @@
         }
     }
 
-    func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
+    public func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
         return try self.decoder.with(pushedKey: key) {
             guard let value = self.container[key.stringValue] else {
                 throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
@@ -932,23 +1060,18 @@
         }
     }
 
-    func _superDecoder(forKey key: CodingKey) throws -> Decoder {
-        return try self.decoder.with(pushedKey: key) {
-            guard let value = self.container[key.stringValue] else {
-                throw DecodingError.valueNotFound(Decoder.self,
-                                                  DecodingError.Context(codingPath: self.codingPath,
-                                                          debugDescription: "Cannot get superDecoder() -- no value found for key \"\(key.stringValue)\""))
-            }
-
+    private func _superDecoder(forKey key: CodingKey) throws -> Decoder {
+        return self.decoder.with(pushedKey: key) {
+            let value: Any = self.container[key.stringValue] ?? NSNull()
             return _PlistDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
         }
     }
 
-    func superDecoder() throws -> Decoder {
+    public func superDecoder() throws -> Decoder {
         return try _superDecoder(forKey: _PlistSuperKey.super)
     }
 
-    func superDecoder(forKey key: Key) throws -> Decoder {
+    public func superDecoder(forKey key: Key) throws -> Decoder {
         return try _superDecoder(forKey: key)
     }
 }
@@ -957,21 +1080,21 @@
     // MARK: Properties
 
     /// A reference to the decoder we're reading from.
-    let decoder: _PlistDecoder
+    private let decoder: _PlistDecoder
 
     /// A reference to the container we're reading from.
-    let container: [Any]
+    private let container: [Any]
 
     /// The path of coding keys taken to get to this point in decoding.
-    var codingPath: [CodingKey?]
+    private(set) public var codingPath: [CodingKey?]
 
     /// The index of the element we're about to decode.
-    var currentIndex: Int
+    private var currentIndex: Int
 
     // MARK: - Initialization
 
     /// Initializes `self` by referencing the given decoder and container.
-    init(referencing decoder: _PlistDecoder, wrapping container: [Any]) {
+    fileprivate init(referencing decoder: _PlistDecoder, wrapping container: [Any]) {
         self.decoder = decoder
         self.container = container
         self.codingPath = decoder.codingPath
@@ -980,175 +1103,253 @@
 
     // MARK: - UnkeyedDecodingContainer Methods
 
-    var count: Int? {
+    public var count: Int? {
         return self.container.count
     }
 
-    var isAtEnd: Bool {
+    public var isAtEnd: Bool {
         return self.currentIndex >= self.count!
     }
 
-    mutating func decodeIfPresent(_ type: Bool.Type) throws -> Bool? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decodeNil() throws -> Bool {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(Any?.self, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
+
+        if self.container[self.currentIndex] is NSNull {
+            self.currentIndex += 1
+            return true
+        } else {
+            return false
+        }
+    }
+
+    public mutating func decode(_ type: Bool.Type) throws -> Bool {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int.Type) throws -> Int? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int.Type) throws -> Int {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int8.Type) throws -> Int8? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int8.Type) throws -> Int8 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int16.Type) throws -> Int16? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int16.Type) throws -> Int16 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int32.Type) throws -> Int32? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int32.Type) throws -> Int32 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Int64.Type) throws -> Int64? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Int64.Type) throws -> Int64 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt.Type) throws -> UInt? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt.Type) throws -> UInt {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt8.Type) throws -> UInt8? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt8.Type) throws -> UInt8 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt16.Type) throws -> UInt16? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt16.Type) throws -> UInt16 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt32.Type) throws -> UInt32? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt32.Type) throws -> UInt32 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: UInt64.Type) throws -> UInt64? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: UInt64.Type) throws -> UInt64 {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Float.Type) throws -> Float? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Float.Type) throws -> Float {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Double.Type) throws -> Double? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: Double.Type) throws -> Double {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: String.Type) throws -> String? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode(_ type: String.Type) throws -> String {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent(_ type: Data.Type) throws -> Data? {
-        guard !self.isAtEnd else { return nil }
+    public mutating func decode<T : Decodable>(_ type: T.Type) throws -> T {
+        guard !self.isAtEnd else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
+        }
 
         return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Data.self)
+            guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+                throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
+            }
+
             self.currentIndex += 1
             return decoded
         }
     }
 
-    mutating func decodeIfPresent<T : Decodable>(_ type: T.Type) throws -> T? {
-        guard !self.isAtEnd else { return nil }
-
-        return try self.decoder.with(pushedKey: nil) {
-            let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self)
-            self.currentIndex += 1
-            return decoded
-        }
-    }
-
-    mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
+    public mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
         return try self.decoder.with(pushedKey: nil) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
@@ -1173,7 +1374,7 @@
         }
     }
 
-    mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
+    public mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
         return try self.decoder.with(pushedKey: nil) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
@@ -1197,7 +1398,7 @@
         }
     }
 
-    mutating func superDecoder() throws -> Decoder {
+    public mutating func superDecoder() throws -> Decoder {
         return try self.decoder.with(pushedKey: nil) {
             guard !self.isAtEnd else {
                 throw DecodingError.valueNotFound(Decoder.self, DecodingError.Context(codingPath: self.codingPath,
@@ -1205,12 +1406,6 @@
             }
 
             let value = self.container[self.currentIndex]
-            guard !(value is NSNull) else {
-                throw DecodingError.valueNotFound(Decoder.self,
-                                                  DecodingError.Context(codingPath: self.codingPath,
-                                                          debugDescription: "Cannot get superDecoder() -- found null value instead."))
-            }
-
             self.currentIndex += 1
             return _PlistDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
         }
@@ -1220,7 +1415,13 @@
 extension _PlistDecoder : SingleValueDecodingContainer {
     // MARK: SingleValueDecodingContainer Methods
 
-    func decodeNil() -> Bool {
+    private func expectNonNull<T>(_ type: T.Type) throws {
+        guard !self.decodeNil() else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) but found null value instead."))
+        }
+    }
+
+    public func decodeNil() -> Bool {
         guard let string = self.storage.topContainer as? String else {
             return false
         }
@@ -1228,155 +1429,79 @@
         return string == _plistNull
     }
 
-    // These all unwrap the result, since we couldn't have gotten a single value container if the topContainer was null.
-    func decode(_ type: Bool.Type) throws -> Bool {
-        guard let value = try self.unbox(self.storage.topContainer, as: Bool.self) else {
-            throw DecodingError.valueNotFound(Bool.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Bool but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Bool.Type) throws -> Bool {
+        try expectNonNull(Bool.self)
+        return try self.unbox(self.storage.topContainer, as: Bool.self)!
     }
 
-    func decode(_ type: Int.Type) throws -> Int {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int.self) else {
-            throw DecodingError.valueNotFound(Int.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int.Type) throws -> Int {
+        try expectNonNull(Int.self)
+        return try self.unbox(self.storage.topContainer, as: Int.self)!
     }
 
-    func decode(_ type: Int8.Type) throws -> Int8 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int8.self) else {
-            throw DecodingError.valueNotFound(Int8.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int8 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int8.Type) throws -> Int8 {
+        try expectNonNull(Int8.self)
+        return try self.unbox(self.storage.topContainer, as: Int8.self)!
     }
 
-    func decode(_ type: Int16.Type) throws -> Int16 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int16.self) else {
-            throw DecodingError.valueNotFound(Int16.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int16 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int16.Type) throws -> Int16 {
+        try expectNonNull(Int16.self)
+        return try self.unbox(self.storage.topContainer, as: Int16.self)!
     }
 
-    func decode(_ type: Int32.Type) throws -> Int32 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int32.self) else {
-            throw DecodingError.valueNotFound(Int32.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int32 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int32.Type) throws -> Int32 {
+        try expectNonNull(Int32.self)
+        return try self.unbox(self.storage.topContainer, as: Int32.self)!
     }
 
-    func decode(_ type: Int64.Type) throws -> Int64 {
-        guard let value = try self.unbox(self.storage.topContainer, as: Int64.self) else {
-            throw DecodingError.valueNotFound(Int64.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Int64 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Int64.Type) throws -> Int64 {
+        try expectNonNull(Int64.self)
+        return try self.unbox(self.storage.topContainer, as: Int64.self)!
     }
 
-    func decode(_ type: UInt.Type) throws -> UInt {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt.self) else {
-            throw DecodingError.valueNotFound(UInt.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt.Type) throws -> UInt {
+        try expectNonNull(UInt.self)
+        return try self.unbox(self.storage.topContainer, as: UInt.self)!
     }
 
-    func decode(_ type: UInt8.Type) throws -> UInt8 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt8.self) else {
-            throw DecodingError.valueNotFound(UInt8.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt8 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt8.Type) throws -> UInt8 {
+        try expectNonNull(UInt8.self)
+        return try self.unbox(self.storage.topContainer, as: UInt8.self)!
     }
 
-    func decode(_ type: UInt16.Type) throws -> UInt16 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt16.self) else {
-            throw DecodingError.valueNotFound(UInt16.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt16 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt16.Type) throws -> UInt16 {
+        try expectNonNull(UInt16.self)
+        return try self.unbox(self.storage.topContainer, as: UInt16.self)!
     }
 
-    func decode(_ type: UInt32.Type) throws -> UInt32 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt32.self) else {
-            throw DecodingError.valueNotFound(UInt32.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt32 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt32.Type) throws -> UInt32 {
+        try expectNonNull(UInt32.self)
+        return try self.unbox(self.storage.topContainer, as: UInt32.self)!
     }
 
-    func decode(_ type: UInt64.Type) throws -> UInt64 {
-        guard let value = try self.unbox(self.storage.topContainer, as: UInt64.self) else {
-            throw DecodingError.valueNotFound(UInt64.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected UInt64 but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: UInt64.Type) throws -> UInt64 {
+        try expectNonNull(UInt64.self)
+        return try self.unbox(self.storage.topContainer, as: UInt64.self)!
     }
 
-    func decode(_ type: Float.Type) throws -> Float {
-        guard let value = try self.unbox(self.storage.topContainer, as: Float.self) else {
-            throw DecodingError.valueNotFound(Float.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Float but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Float.Type) throws -> Float {
+        try expectNonNull(Float.self)
+        return try self.unbox(self.storage.topContainer, as: Float.self)!
     }
 
-    func decode(_ type: Double.Type) throws -> Double {
-        guard let value = try self.unbox(self.storage.topContainer, as: Double.self) else {
-            throw DecodingError.valueNotFound(Double.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected Double but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: Double.Type) throws -> Double {
+        try expectNonNull(Double.self)
+        return try self.unbox(self.storage.topContainer, as: Double.self)!
     }
 
-    func decode(_ type: String.Type) throws -> String {
-        guard let value = try self.unbox(self.storage.topContainer, as: String.self) else {
-            throw DecodingError.valueNotFound(String.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected String but found null value instead."))
-        }
-
-        return value
+    public func decode(_ type: String.Type) throws -> String {
+        try expectNonNull(String.self)
+        return try self.unbox(self.storage.topContainer, as: String.self)!
     }
 
-    func decode<T : Decodable>(_ type: T.Type) throws -> T {
-        guard let value = try self.unbox(self.storage.topContainer, as: T.self) else {
-            throw DecodingError.valueNotFound(T.self,
-                                              DecodingError.Context(codingPath: self.codingPath,
-                                                                    debugDescription: "Expected \(T.self) but found null value instead."))
-        }
-
-        return value
+    public func decode<T : Decodable>(_ type: T.Type) throws -> T {
+        try expectNonNull(T.self)
+        return try self.unbox(self.storage.topContainer, as: T.self)!
     }
 }
 
@@ -1384,8 +1509,7 @@
 
 extension _PlistDecoder {
     /// Returns the given value unboxed from a container.
-    fileprivate func unbox(_ value: Any?, as type: Bool.Type) throws -> Bool? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Bool.Type) throws -> Bool? {
         if let string = value as? String, string == _plistNull { return nil }
 
         if let number = value as? NSNumber {
@@ -1406,8 +1530,7 @@
         throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int.Type) throws -> Int? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int.Type) throws -> Int? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1422,8 +1545,7 @@
         return int
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int8.Type) throws -> Int8? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int8.Type) throws -> Int8? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1438,8 +1560,7 @@
         return int8
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int16.Type) throws -> Int16? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int16.Type) throws -> Int16? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1454,8 +1575,7 @@
         return int16
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int32.Type) throws -> Int32? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int32.Type) throws -> Int32? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1470,8 +1590,7 @@
         return int32
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Int64.Type) throws -> Int64? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Int64.Type) throws -> Int64? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1486,8 +1605,7 @@
         return int64
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt.Type) throws -> UInt? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt.Type) throws -> UInt? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1502,8 +1620,7 @@
         return uint
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt8.Type) throws -> UInt8? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt8.Type) throws -> UInt8? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1518,8 +1635,7 @@
         return uint8
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt16.Type) throws -> UInt16? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt16.Type) throws -> UInt16? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1534,8 +1650,7 @@
         return uint16
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt32.Type) throws -> UInt32? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt32.Type) throws -> UInt32? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1550,8 +1665,7 @@
         return uint32
     }
 
-    fileprivate func unbox(_ value: Any?, as type: UInt64.Type) throws -> UInt64? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: UInt64.Type) throws -> UInt64? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1566,8 +1680,7 @@
         return uint64
     }
 
-    fileprivate func unbox(_ value: Any?, as type: Float.Type) throws -> Float? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Float.Type) throws -> Float? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1582,8 +1695,7 @@
         return float
     }
 
-    func unbox(_ value: Any?, as type: Double.Type) throws -> Double? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Double.Type) throws -> Double? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let number = value as? NSNumber else {
@@ -1598,9 +1710,7 @@
         return double
     }
 
-    func unbox(_ value: Any?, as type: String.Type) throws -> String? {
-        guard let value = value else { return nil }
-
+    fileprivate func unbox(_ value: Any, as type: String.Type) throws -> String? {
         guard let string = value as? String else {
             throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
         }
@@ -1608,8 +1718,7 @@
         return string == _plistNull ? nil : string
     }
 
-    func unbox(_ value: Any?, as type: Date.Type) throws -> Date? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Date.Type) throws -> Date? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let date = value as? Date else {
@@ -1619,8 +1728,7 @@
         return date
     }
 
-    func unbox(_ value: Any?, as type: Data.Type) throws -> Data? {
-        guard let value = value else { return nil }
+    fileprivate func unbox(_ value: Any, as type: Data.Type) throws -> Data? {
         if let string = value as? String, string == _plistNull { return nil }
 
         guard let data = value as? Data else {
@@ -1630,15 +1738,14 @@
         return data
     }
 
-    func unbox<T : Decodable>(_ value: Any?, as type: T.Type) throws -> T? {
-        guard let value = value else { return nil }
-        if let string = value as? String, string == _plistNull { return nil }
-
+    fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
         let decoded: T
         if T.self == Date.self {
-            decoded = (try self.unbox(value, as: Date.self) as! T)
+            guard let date = try self.unbox(value, as: Date.self) else { return nil }
+            decoded = date as! T
         } else if T.self == Data.self {
-            decoded = (try self.unbox(value, as: Data.self) as! T)
+            guard let data = try self.unbox(value, as: Data.self) else { return nil }
+            decoded = data as! T
         } else {
             self.storage.push(container: value)
             decoded = try T(from: self)
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 4e8683b..005e0bf 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -55,6 +55,7 @@
   ErrorType.swift
   Existential.swift
   Filter.swift.gyb
+  FixedArray.swift.gyb
   FlatMap.swift
   Flatten.swift.gyb
   FloatingPoint.swift.gyb
diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift
index 8f5b5a0..1cd4209 100644
--- a/stdlib/public/core/Codable.swift
+++ b/stdlib/public/core/Codable.swift
@@ -149,6 +149,12 @@
     /// A `nil` value indicates an unkeyed container.
     var codingPath: [CodingKey?] { get }
 
+    /// Encodes a null value for the given key.
+    ///
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if a null value is invalid in the current context for this format.
+    mutating func encodeNil(forKey key: Key) throws
+
     /// Encodes the given value for the given key.
     ///
     /// - parameter value: The value to encode.
@@ -421,6 +427,14 @@
         return _box.codingPath
     }
 
+    /// Encodes a null value for the given key.
+    ///
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if a null value is invalid in the current context for this format.
+    public mutating func encodeNil(forKey key: Key) throws {
+        try _box.encodeNil(forKey: key)
+    }
+
     /// Encodes the given value for the given key.
     ///
     /// - parameter value: The value to encode.
@@ -567,6 +581,141 @@
         try _box.encodeWeak(object, forKey: key)
     }
 
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: Int?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: Int8?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: Int16?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: Int32?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: Int64?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: UInt?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent(_ value: String?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
+    /// Encodes the given value for the given key if it is not `nil`.
+    ///
+    /// - parameter value: The value to encode.
+    /// - parameter key: The key to associate the value with.
+    /// - throws: `EncodingError.invalidValue` if the given value is invalid in the current context for this format.
+    public mutating func encodeIfPresent<T : Encodable>(_ value: T?, forKey key: Key) throws {
+        try _box.encodeIfPresent(value, forKey: key)
+    }
+
     /// Stores a keyed encoding container for the given key and returns it.
     ///
     /// - parameter keyType: The key type to use for the container.
@@ -627,6 +776,13 @@
     /// - returns: Whether the `Decoder` has an entry for the given key.
     func contains(_ key: Key) -> Bool
 
+    /// Decodes a null value for the given key.
+    ///
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: Whether the encountered value was null.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    func decodeNil(forKey key: Key) throws -> Bool
+
     /// Decodes a value of the given type for the given key.
     ///
     /// - parameter type: The type of value to decode.
@@ -1001,6 +1157,195 @@
         return _box.contains(key)
     }
 
+    /// Decodes a null value for the given key.
+    ///
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: Whether the encountered value was null.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    public func decodeNil(forKey key: Key) throws -> Bool {
+        return try _box.decodeNil(forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+        return try _box.decode(Bool.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+        return try _box.decode(Int.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+        return try _box.decode(Int8.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+        return try _box.decode(Int16.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+        return try _box.decode(Int32.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+        return try _box.decode(Int64.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+        return try _box.decode(UInt.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+        return try _box.decode(UInt8.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+        return try _box.decode(UInt16.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+        return try _box.decode(UInt32.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+        return try _box.decode(UInt64.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+        return try _box.decode(Float.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+        return try _box.decode(Double.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode(_ type: String.Type, forKey key: Key) throws -> String {
+        return try _box.decode(String.self, forKey: key)
+    }
+
+    /// Decodes a value of the given type for the given key.
+    ///
+    /// - parameter type: The type of value to decode.
+    /// - parameter key: The key that the decoded value is associated with.
+    /// - returns: A value of the requested type, if present for the given key and convertible to the requested type.
+    /// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
+    /// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
+    /// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
+    public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
+        return try _box.decode(T.self, forKey: key)
+    }
+
     /// Decodes a value of the given type for the given key, if present.
     ///
     /// This method returns `nil` if the container does not have a value associated with `key`, or if the value is null. The difference between these states can be distinguished with a `contains(_:)` call.
@@ -1235,6 +1580,11 @@
     /// A `nil` value indicates an unkeyed container.
     var codingPath: [CodingKey?] { get }
 
+    /// Encodes a null value.
+    ///
+    /// - throws: `EncodingError.invalidValue` if a null value is invalid in the current context for this format.
+    mutating func encodeNil() throws
+
     /// Encodes the given value.
     ///
     /// - parameter value: The value to encode.
@@ -1458,6 +1808,12 @@
     /// Returns whether there are no more elements left to be decoded in the container.
     var isAtEnd: Bool { get }
 
+    /// Decodes a null value.
+    ///
+    /// - returns: Whether the encountered value was null.
+    /// - throws: `DecodingError.valueNotFound` if there are no more values to decode.
+    mutating func decodeNil() throws -> Bool
+
     /// Decodes a value of the given type.
     ///
     /// - parameter type: The type of value to decode.
@@ -2240,6 +2596,12 @@
 
     @_inlineable
     @_versioned
+    internal func encodeNil(forKey key: Key) throws {
+        fatalError("_KeyedEncodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
     internal func encode(_ value: Bool, forKey key: Key) throws {
         fatalError("_KeyedEncodingContainerBase cannot be used directly.")
     }
@@ -2471,6 +2833,12 @@
 
     @_inlineable
     @_versioned
+    override internal func encodeNil(forKey key: Key) throws {
+        try concrete.encodeNil(forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
     override internal func encode(_ value: Bool, forKey key: Key) throws {
         try concrete.encode(value, forKey: key)
     }
@@ -2703,6 +3071,102 @@
 
     @_inlineable
     @_versioned
+    internal func decodeNil(forKey key: Key) throws -> Bool {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode(_ type: String.Type, forKey key: Key) throws -> String {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
+    internal func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
+        fatalError("_KeyedDecodingContainerBase cannot be used directly.")
+    }
+
+    @_inlineable
+    @_versioned
     internal func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
         fatalError("_KeyedDecodingContainerBase cannot be used directly.")
     }
@@ -2850,6 +3314,102 @@
 
     @_inlineable
     @_versioned
+    override internal func decodeNil(forKey key: Key) throws -> Bool {
+        return try concrete.decodeNil(forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+        return try concrete.decode(Bool.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+        return try concrete.decode(Int.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+        return try concrete.decode(Int8.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+        return try concrete.decode(Int16.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+        return try concrete.decode(Int32.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+        return try concrete.decode(Int64.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+        return try concrete.decode(UInt.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+        return try concrete.decode(UInt8.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+        return try concrete.decode(UInt16.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+        return try concrete.decode(UInt32.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+        return try concrete.decode(UInt64.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+        return try concrete.decode(Float.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+        return try concrete.decode(Double.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode(_ type: String.Type, forKey key: Key) throws -> String {
+        return try concrete.decode(String.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
+    override internal func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
+        return try concrete.decode(T.self, forKey: key)
+    }
+
+    @_inlineable
+    @_versioned
     override internal func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
         return try concrete.decodeIfPresent(Bool.self, forKey: key)
     }
@@ -3618,14 +4178,14 @@
 // Convenience Default Implementations
 //===----------------------------------------------------------------------===//
 
-// Default implementation for encodeWeak(_:forKey:) in terms of encode(_:forKey:)
+// Default implementation of encodeWeak(_:forKey:) in terms of encode(_:forKey:)
 public extension KeyedEncodingContainerProtocol {
     public mutating func encodeWeak<T : AnyObject & Encodable>(_ object: T, forKey key: Key) throws {
         try encode(object, forKey: key)
     }
 }
 
-// Default implementation for encodeIfPresent(_:forKey:) in terms of encode(_:forKey:)
+// Default implementation of encodeIfPresent(_:forKey:) in terms of encode(_:forKey:)
 public extension KeyedEncodingContainerProtocol {
     public mutating func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
         guard let value = value else { return }
@@ -3703,371 +4263,255 @@
     }
 }
 
-// Default implementations for decode(_:forKey:) in terms of decodeIfPresent(_:forKey:)
+// Default implementation of decodeIfPresent(_:forKey:) in terms of decode(_:forKey:) and decodeNil(forKey:)
 public extension KeyedDecodingContainerProtocol {
-    @_semantics("optimize.sil.specialize.generic.never")
-    @_semantics("optimize.sil.specialize.generic.partial.never")
-    @inline(never)
-    internal func _errorInDecoding<T: Decodable>(_ type: T.Type, forKey key: Key) -> DecodingError {
-        if contains(key) {
-            var path = codingPath
-            path.append(key)
-            return DecodingError.valueNotFound(type, DecodingError.Context(codingPath: path, debugDescription: "Found null value when expecting non-optional type \(type) for coding key \"\(key)\""))
-        } else {
-            var path = codingPath
-            path.append(key)
-            return DecodingError.keyNotFound(key, DecodingError.Context(codingPath: path, debugDescription: "Key not found when expecting non-optional type \(type) for coding key \"\(key)\""))
-        }
+    public func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(Bool.self, forKey: key)
     }
 
-    public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
-        if let value = try decodeIfPresent(Bool.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(Int.self, forKey: key)
     }
 
-    public func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
-        if let value = try decodeIfPresent(Int.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(Int8.self, forKey: key)
     }
 
-    public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
-        if let value = try decodeIfPresent(Int8.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(Int16.self, forKey: key)
     }
 
-    public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
-        if let value = try decodeIfPresent(Int16.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(Int32.self, forKey: key)
     }
 
-    public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
-        if let value = try decodeIfPresent(Int32.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(Int64.self, forKey: key)
     }
 
-    public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
-        if let value = try decodeIfPresent(Int64.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(UInt.self, forKey: key)
     }
 
-    public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
-        if let value = try decodeIfPresent(UInt.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(UInt8.self, forKey: key)
     }
 
-    public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
-        if let value = try decodeIfPresent(UInt8.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(UInt16.self, forKey: key)
     }
 
-    public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
-        if let value = try decodeIfPresent(UInt16.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(UInt32.self, forKey: key)
     }
 
-    public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
-        if let value = try decodeIfPresent(UInt32.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(UInt64.self, forKey: key)
     }
 
-    public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
-        if let value = try decodeIfPresent(UInt64.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(Float.self, forKey: key)
     }
 
-    public func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
-        if let value = try decodeIfPresent(Float.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(Double.self, forKey: key)
     }
 
-    public func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
-        if let value = try decodeIfPresent(Double.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(String.self, forKey: key)
     }
 
-    public func decode(_ type: String.Type, forKey key: Key) throws -> String {
-        if let value = try decodeIfPresent(String.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
-    }
-
-    public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
-        if let value = try decodeIfPresent(T.self, forKey: key) {
-            return value
-        } else {
-            throw _errorInDecoding(type, forKey: key)
-        }
+    public func decodeIfPresent<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T? {
+        guard try self.contains(key) && !self.decodeNil(forKey: key) else { return nil }
+        return try self.decode(T.self, forKey: key)
     }
 }
 
 // Default implementation of encodeWeak(_:) in terms of encode(_:), and encode(contentsOf:) in terms of encode(_:) loop.
 public extension UnkeyedEncodingContainer {
     public mutating func encodeWeak<T : AnyObject & Encodable>(_ object: T) throws {
-        try encode(object)
+        try self.encode(object)
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == Bool {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == Int {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == Int8 {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == Int16 {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == Int32 {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == Int64 {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == UInt {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == UInt8 {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == UInt16 {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == UInt32 {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == UInt64 {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == Float {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == Double {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element == String {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 
     public mutating func encode<T : Sequence>(contentsOf sequence: T) throws where T.Iterator.Element : Encodable {
         for element in sequence {
-            try encode(element)
+            try self.encode(element)
         }
     }
 }
 
-// Default implementations for decode(_:) in terms of decodeIfPresent(_:)
+// Default implementation of decodeIfPresent(_:) in terms of decode(_:) and decodeNil()
 public extension UnkeyedDecodingContainer {
-    @_semantics("optimize.sil.specialize.generic.never")
-    @_semantics("optimize.sil.specialize.generic.partial.never")
-    @inline(never)
-    internal func _errorInDecoding<T: Decodable>(_ type: T.Type) -> DecodingError {
-        if !isAtEnd {
-            return DecodingError.valueNotFound(type, DecodingError.Context(codingPath: codingPath, debugDescription: "Found null value when expecting non-optional type \(type)"))
-        } else {
-            return DecodingError.valueNotFound(type, DecodingError.Context(codingPath: codingPath, debugDescription: "No remaining elements when expecting non-optional type \(type)"))
-        }
+    mutating func decodeIfPresent(_ type: Bool.Type) throws -> Bool? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(Bool.self)
     }
 
-    mutating func decode(_ type: Bool.Type) throws -> Bool {
-        if let value = try decodeIfPresent(Bool.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: Int.Type) throws -> Int? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(Int.self)
     }
 
-    mutating func decode(_ type: Int.Type) throws -> Int {
-        if let value = try decodeIfPresent(Int.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: Int8.Type) throws -> Int8? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(Int8.self)
     }
 
-    mutating func decode(_ type: Int8.Type) throws -> Int8 {
-        if let value = try decodeIfPresent(Int8.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: Int16.Type) throws -> Int16? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(Int16.self)
     }
 
-    mutating func decode(_ type: Int16.Type) throws -> Int16 {
-        if let value = try decodeIfPresent(Int16.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: Int32.Type) throws -> Int32? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(Int32.self)
     }
 
-    mutating func decode(_ type: Int32.Type) throws -> Int32 {
-        if let value = try decodeIfPresent(Int32.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: Int64.Type) throws -> Int64? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(Int64.self)
     }
 
-    mutating func decode(_ type: Int64.Type) throws -> Int64 {
-        if let value = try decodeIfPresent(Int64.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: UInt.Type) throws -> UInt? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(UInt.self)
     }
 
-    mutating func decode(_ type: UInt.Type) throws -> UInt {
-        if let value = try decodeIfPresent(UInt.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: UInt8.Type) throws -> UInt8? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(UInt8.self)
     }
 
-    mutating func decode(_ type: UInt8.Type) throws -> UInt8 {
-        if let value = try decodeIfPresent(UInt8.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: UInt16.Type) throws -> UInt16? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(UInt16.self)
     }
 
-    mutating func decode(_ type: UInt16.Type) throws -> UInt16 {
-        if let value = try decodeIfPresent(UInt16.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: UInt32.Type) throws -> UInt32? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(UInt32.self)
     }
 
-    mutating func decode(_ type: UInt32.Type) throws -> UInt32 {
-        if let value = try decodeIfPresent(UInt32.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: UInt64.Type) throws -> UInt64? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(UInt64.self)
     }
 
-    mutating func decode(_ type: UInt64.Type) throws -> UInt64 {
-        if let value = try decodeIfPresent(UInt64.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: Float.Type) throws -> Float? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(Float.self)
     }
 
-    mutating func decode(_ type: Float.Type) throws -> Float {
-        if let value = try decodeIfPresent(Float.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: Double.Type) throws -> Double? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(Double.self)
     }
 
-    mutating func decode(_ type: Double.Type) throws -> Double {
-        if let value = try decodeIfPresent(Double.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent(_ type: String.Type) throws -> String? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(String.self)
     }
 
-    mutating func decode(_ type: String.Type) throws -> String {
-        if let value = try decodeIfPresent(String.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
-    }
-
-    mutating func decode<T : Decodable>(_ type: T.Type) throws -> T {
-        if let value = try decodeIfPresent(T.self) {
-            return value
-        } else {
-            throw _errorInDecoding(type)
-        }
+    mutating func decodeIfPresent<T : Decodable>(_ type: T.Type) throws -> T? {
+        guard try !self.isAtEnd && !self.decodeNil() else { return nil }
+        return try self.decode(T.self)
     }
 }
diff --git a/stdlib/public/core/FixedArray.swift.gyb b/stdlib/public/core/FixedArray.swift.gyb
new file mode 100644
index 0000000..4fa02db
--- /dev/null
+++ b/stdlib/public/core/FixedArray.swift.gyb
@@ -0,0 +1,113 @@
+//===--- FixedArray.swift.gyb ---------------------------------*- swift -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+//  A helper struct to provide fixed-sized array like functionality
+//
+//===----------------------------------------------------------------------===//
+
+%{
+  # The sizes to generate code for.
+  sizes = [16]
+}%
+
+% for N in sizes:
+
+internal struct _FixedArray${N}<T> {
+  // ABI TODO: The has assumptions about tuple layout in the ABI, namely that
+  // they are laid out contiguously and individually addressable (i.e. strided).
+  //
+  internal var storage: (
+    // A ${N}-wide tuple of type T
+% for i in range(0, N-1):
+    T,
+% end
+    T
+  )
+
+  static var _arraySize : Int { return ${N} }
+}
+
+extension _FixedArray${N} : RandomAccessCollection, MutableCollection {
+  internal typealias Index = Int
+  internal typealias IndexDistance = Int
+
+  internal var startIndex : Index {
+    return 0
+  }
+
+  internal var endIndex : Index {
+    return _FixedArray${N}._arraySize
+  }
+
+  internal var count : IndexDistance { return _FixedArray${N}._arraySize }
+
+  internal subscript(i: Index) -> T {
+    @_versioned
+    @inline(__always)
+    get {
+      var copy = storage
+      let res: T = withUnsafeBytes(of: &copy) {
+        (rawPtr : UnsafeRawBufferPointer) -> T in
+        let stride = MemoryLayout<T>.stride
+        _sanityCheck(rawPtr.count == ${N}*stride, "layout mismatch?")
+        let bufPtr = UnsafeBufferPointer(
+          start: rawPtr.baseAddress!.assumingMemoryBound(to: T.self),
+          count: count)
+        return bufPtr[i]
+      }
+      return res
+    }
+    @_versioned
+    @inline(__always)
+    set {
+      withUnsafeBytes(of: &storage) {
+        (rawPtr : UnsafeRawBufferPointer) -> () in
+        let rawPtr = UnsafeMutableRawBufferPointer(mutating: rawPtr)
+        let stride = MemoryLayout<T>.stride
+        _sanityCheck(rawPtr.count == ${N}*stride, "layout mismatch?")
+        let bufPtr = UnsafeMutableBufferPointer(
+          start: rawPtr.baseAddress!.assumingMemoryBound(to: T.self),
+          count: count)
+        bufPtr[i] = newValue
+      }
+    }
+  }
+
+  @_versioned
+  @inline(__always)
+  internal func index(after i: Index) -> Index {
+    return i+1
+  }
+
+  @_versioned
+  @inline(__always)
+  internal func index(before i: Index) -> Index {
+    return i-1
+  }
+
+  // TODO: Any customization hooks it's profitable to override, e.g. append?
+
+}
+
+extension _FixedArray${N} where T: IntegerLiteralConvertible {
+  @inline(__always)
+  internal init(allZeros:()) {
+    self.storage = (
+% for i in range(0, N-1):
+    0,
+% end
+    0
+    )
+  }
+}
+
+% end
diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json
index c4c41db..f816522 100644
--- a/stdlib/public/core/GroupInfo.json
+++ b/stdlib/public/core/GroupInfo.json
@@ -92,6 +92,7 @@
         "Arrays.swift",
         "CocoaArray.swift",
         "ContiguousArrayBuffer.swift",
+        "FixedArray.swift",
         "SliceBuffer.swift",
         "SwiftNativeNSArray.swift"],
       "HashedCollections": [
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index debf0ba..13169af 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -15,8 +15,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-// FIXME(ABI)#70 : The character string view should have a custom iterator type to
-// allow performance optimizations of linear traversals.
+// FIXME(ABI)#70 : The character string view should have a custom iterator type
+// to allow performance optimizations of linear traversals.
 
 /// CR and LF are common special cases in grapheme breaking logic
 @_versioned internal var _CR: UInt8 { return 0x0d }
@@ -102,7 +102,8 @@
   /// of the string.
   ///
   ///     var str = "All this happened, more or less."
-  ///     let afterSpace = str.withMutableCharacters { chars -> String.CharacterView in
+  ///     let afterSpace = str.withMutableCharacters {
+  ///         chars -> String.CharacterView in
   ///         if let i = chars.index(of: " ") {
   ///             let result = chars[chars.index(after: i)...]
   ///             chars.removeSubrange(i...)
@@ -364,128 +365,130 @@
   internal func _measureExtendedGraphemeClusterForward(
     from start: UnicodeScalarView.Index
   ) -> Int {
-    let end = unicodeScalars.endIndex
-    if start == end {
+    let startPosition = start._position
+    let endPosition = unicodeScalars.endIndex._position
+
+    // No more graphemes
+    if startPosition == endPosition {
       return 0
     }
 
-    // Our relative position (offset). If our _core is not a substring, this is
-    // the same as start._position.
-    let relativeOffset = start._position - _coreOffset
+    // Last code unit means final grapheme length of 1
+    if startPosition == endPosition - 1 {
+      return 1
+    }
+
+    // Our relative offset from the _StringCore's baseAddress pointer. If our
+    // _core is not a substring, this is the same as start._position. Otherwise,
+    // it is the code unit relative offset into the substring and not the
+    // absolute offset into the outer string.
+    let startOffset = startPosition - _coreOffset
 
     // Grapheme breaking is much simpler if known ASCII
     if _core.isASCII {
       _onFastPath() // Please aggressively inline
       let asciiBuffer = _core.asciiBuffer._unsafelyUnwrappedUnchecked
+      _sanityCheck(startOffset+1 < asciiBuffer.endIndex, 
+        "Already checked for last code unit")
 
       // With the exception of CR-LF, ASCII graphemes are single-scalar. Check
       // for that one exception.
       if _slowPath(
-        asciiBuffer[relativeOffset] == _CR &&
-        relativeOffset+1 < asciiBuffer.endIndex &&
-        asciiBuffer[relativeOffset+1] == _LF
+        asciiBuffer[startOffset] == _CR &&
+        asciiBuffer[startOffset+1] == _LF
       ) {
         return 2
       }
 
       return 1
-    } else {
-      // TODO: Check for (potentially non-contiguous) ASCII NSStrings,
-      // especially small tagged pointers.
     }
     
-    let startIndexUTF16 = start._position
-
-    // Last scalar is its own grapheme
-    if (startIndexUTF16+1 == end._position) {
+    // Perform a quick single-code-unit grapheme check.
+    if _fastPath(String.CharacterView._quickCheckGraphemeBreakBetween(
+        _core[startOffset],
+        _core[startOffset+1])
+    ) {
       return 1
     }
 
-    // Perform a quick single-code-unit grapheme check
-    if _core._baseAddress != nil {
-      if String.CharacterView._quickCheckGraphemeBreakBetween(
-        _core._nthContiguous(relativeOffset),
-        _core._nthContiguous(relativeOffset+1)
-      ) {
-        return 1
-      }
-    } else {
-      // TODO: Check for (potentially non-contiguous) UTF16 NSStrings,
-      // especially small tagged pointers
-    }
-    return _measureExtendedGraphemeClusterForwardSlow(
-      relativeOffset: relativeOffset,
-      start: start,
-      end: end,
-      startIndexUTF16: startIndexUTF16
-    )
+    return _measureExtendedGraphemeClusterForwardSlow(startOffset: startOffset)
   }
   
   @inline(never)
   @_versioned
   func _measureExtendedGraphemeClusterForwardSlow(
-    relativeOffset: Int,
-    start: String.UnicodeScalarView.Index,
-    end: String.UnicodeScalarView.Index,
-    startIndexUTF16: Int
+    startOffset: Int
   ) -> Int {
-    if _core._baseAddress != nil {
+    let endOffset = unicodeScalars.endIndex._position - _coreOffset
+    let numCodeUnits = endOffset - startOffset
+    _sanityCheck(numCodeUnits >= 2, "should have at least two code units")
+
+    // The vast majority of time, we can get a pointer and a length directly
+    if _fastPath(_core._baseAddress != nil) {
       _onFastPath() // Please aggressively inline
       let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: _core)
-      let ubrkFollowing = __swift_stdlib_ubrk_following(
-        breakIterator, Int32(relativeOffset)
+      let ubrkFollowingOffset = __swift_stdlib_ubrk_following(
+        breakIterator, Int32(startOffset)
       )
       // ubrk_following may return UBRK_DONE (-1). Treat that as the rest of the
       // string.
-      let nextPosition =
-        ubrkFollowing == -1 ? end._position : Int(ubrkFollowing)
-      return nextPosition - relativeOffset
-    } else {
-      // TODO: See if we can get fast character contents.
+      if _slowPath(ubrkFollowingOffset == -1) {
+        return numCodeUnits
+      }
+      _sanityCheck(startOffset != Int(ubrkFollowingOffset), 
+        "zero-sized grapheme?")
+      return Int(ubrkFollowingOffset) - startOffset
     }
 
-    // FIXME: Need to handle the general case correctly with Unicode 9+
-    // semantics, as opposed to this legacy Unicode 8 path. This gets hit for
-    // e.g. non-contiguous NSStrings. In such cases, there may be an alternative
-    // CFString API available, or worst case we can map over it via UTextFuncs.
-
-    return legacyGraphemeForward(
-      start: start, end: end, startIndexUTF16: startIndexUTF16
-    )
-  }
-
-  @inline(never)
-  func legacyGraphemeForward(
-    start: UnicodeScalarView.Index,
-    end: UnicodeScalarView.Index,
-    startIndexUTF16: Int
-  ) -> Int {
-    var start = start
-    let graphemeClusterBreakProperty =
-      _UnicodeGraphemeClusterBreakPropertyTrie()
-    let segmenter = _UnicodeExtendedGraphemeClusterSegmenter()
-    
-    var gcb0 = graphemeClusterBreakProperty.getPropertyRawValue(
-      unicodeScalars[start].value)
-    unicodeScalars.formIndex(after: &start)
-    
-    while start != end {
-      // FIXME(performance): consider removing this "fast path".  A branch
-      // that is hard to predict could be worse for performance than a few
-      // loads from cache to fetch the property 'gcb1'.
-      if segmenter.isBoundaryAfter(gcb0) {
-        break
-      }
-      let gcb1 = graphemeClusterBreakProperty.getPropertyRawValue(
-        unicodeScalars[start].value)
-      if segmenter.isBoundary(gcb0, gcb1) {
-        break
-      }
-      gcb0 = gcb1
-      unicodeScalars.formIndex(after: &start)
+    // We have a non-contiguous string. Pull out some code units into a fixed
+    // array and try to perform grapheme breaking on that. If even that's not
+    // sufficient (i.e. very pathological) then copy into an Array.
+    var codeUnitBuffer = _FixedArray16<UInt16>(allZeros:())
+    let maxBufferCount = codeUnitBuffer.count
+    let bufferCount = Swift.min(maxBufferCount, numCodeUnits)
+    for i in 0..<bufferCount {
+      codeUnitBuffer[i] = _core[startOffset+i]
     }
-    
-    return start._position - startIndexUTF16
+
+    return withUnsafeBytes(of: &codeUnitBuffer.storage) {
+      (rawPtr : UnsafeRawBufferPointer) -> Int in
+      let bufPtr = UnsafeBufferPointer(
+        start: rawPtr.baseAddress!.assumingMemoryBound(to: UInt16.self),
+        count: bufferCount)
+
+      let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: bufPtr)
+      let ubrkFollowingOffset = __swift_stdlib_ubrk_following(
+        breakIterator, Int32(0))
+
+      if _fastPath(
+        bufferCount < maxBufferCount ||
+        (ubrkFollowingOffset != -1 && ubrkFollowingOffset != maxBufferCount)
+      ) {
+        // The offset into our buffer *is* the distance.
+        _sanityCheck(ubrkFollowingOffset != 0, "zero-sized grapheme?")
+        return Int(ubrkFollowingOffset)
+      }
+
+      // Nuclear option: copy out the rest of the string into an array
+      var codeUnits = Array<UInt16>()
+      codeUnits.reserveCapacity(numCodeUnits)
+      for i in startOffset..<endOffset {
+        codeUnits.append(_core[i])
+      }
+      return codeUnits.withUnsafeBufferPointer { bufPtr -> Int in
+        let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: bufPtr)
+        let ubrkFollowingOffset = __swift_stdlib_ubrk_following(
+          breakIterator, Int32(0)
+        )
+        // ubrk_following may return UBRK_DONE (-1). Treat that as the rest of
+        // the string.
+        if _slowPath(ubrkFollowingOffset == -1) {
+          return numCodeUnits
+        }
+        _sanityCheck(ubrkFollowingOffset != 0, "zero-sized grapheme?")
+        return Int(ubrkFollowingOffset)
+      }
+    }
   }
 
   // NOTE: Because this function is inlineable, it should contain only the fast
@@ -498,14 +501,25 @@
   internal func _measureExtendedGraphemeClusterBackward(
     from end: UnicodeScalarView.Index
   ) -> Int {
-    let start = unicodeScalars.startIndex
-    if start == end {
+    let startPosition = unicodeScalars.startIndex._position
+    let endPosition = end._position
+
+    // No more graphemes
+    if startPosition == endPosition {
       return 0
     }
 
-    // The relative position (offset) to the last code unit.
-    let lastOffset = end._position - _coreOffset - 1
-    // The relative position (offset) that is one-past-the-last
+    // Last code unit means final grapheme length of 1
+    if startPosition == endPosition - 1 {
+      return 1
+    }
+
+    // The relative offset from the _StringCore's baseAddress pointer for the
+    // one-past-the-end and the last code unit under consideration.  If our
+    // _core is not a substring, these are the same as positions. Otherwise,
+    // these are code unit relative offsets into the substring and not the
+    // absolute positions into the outer string.
+    let lastOffset = endPosition - _coreOffset - 1
     let endOffset = lastOffset + 1
 
     // Grapheme breaking is much simpler if known ASCII
@@ -513,15 +527,14 @@
       _onFastPath() // Please aggressively inline
       let asciiBuffer = _core.asciiBuffer._unsafelyUnwrappedUnchecked
       _sanityCheck(
-        lastOffset >= asciiBuffer.startIndex,
-        "should of been caught in earlier start-of-scalars check")
+        lastOffset-1 >= asciiBuffer.startIndex,
+        "should of been caught in earlier trivially-sized checks")
 
       // With the exception of CR-LF, ASCII graphemes are single-scalar. Check
       // for that one exception.
       if _slowPath(
-        asciiBuffer[lastOffset] == _LF &&
-        lastOffset-1 >= asciiBuffer.startIndex &&
-        asciiBuffer[lastOffset-1] == _CR
+        asciiBuffer[lastOffset-1] == _CR &&
+        asciiBuffer[lastOffset] == _LF
       ) {
         return 2
       }
@@ -529,92 +542,94 @@
       return 1
     }
     
-    let endIndexUTF16 = end._position
-
-    // First scalar is its own grapheme
-    if (endIndexUTF16-1 == start._position) {
+    // Perform a quick single-code-unit grapheme check
+    if _fastPath(String.CharacterView._quickCheckGraphemeBreakBetween(
+      _core[lastOffset-1], _core[lastOffset])
+    ) {
       return 1
     }
 
-    // Perform a quick single-code-unit grapheme check
-    if _core._baseAddress != nil {
-      if String.CharacterView._quickCheckGraphemeBreakBetween(
-        _core._nthContiguous(lastOffset-1),
-        _core._nthContiguous(lastOffset)
-      ) {
-        return 1
-      }
-    }
-    return _measureExtendedGraphemeClusterBackwardSlow(
-      endOffset: endOffset, start: start, end: end, endIndexUTF16: endIndexUTF16
-    )
+    return _measureExtendedGraphemeClusterBackwardSlow(endOffset: endOffset)
   }
   
   @inline(never)
   @_versioned
   func _measureExtendedGraphemeClusterBackwardSlow(
-    endOffset: Int,
-    start: String.UnicodeScalarView.Index,
-    end: String.UnicodeScalarView.Index,
-    endIndexUTF16: Int
+    endOffset: Int
   ) -> Int {
-    if _core._baseAddress != nil {
-      _onFastPath() // Please aggressively inline
-      let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: _core)
-      let ubrkPreceding = __swift_stdlib_ubrk_preceding(
-        breakIterator, Int32(endOffset)
-      )
+    let startOffset = 0
+    let numCodeUnits = endOffset - startOffset
+    _sanityCheck(unicodeScalars.startIndex._position - _coreOffset == 0,
+      "position/offset mismatch in _StringCore as a substring")
+    _sanityCheck(numCodeUnits >= 2,
+      "should have at least two code units")
+
+    func measureFromUBreakOffset(_ ubrkOffset: Int32) -> Int {
       // ubrk_following may return UBRK_DONE (-1). Treat that as the rest of the
       // string.
-      let priorPosition =
-        ubrkPreceding == -1 ? start._position : Int(ubrkPreceding)
-      return endOffset - priorPosition
-    } else {
-      // TODO: See if we can get fast character contents.
-    }
-
-    // FIXME: Need to handle the general case correctly with Unicode 9+
-    // semantics, as opposed to this legacy Unicode 8 path. This gets hit for
-    // e.g. non-contiguous NSStrings. In such cases, there may be an alternative
-    // CFString API available, or worst case we can map over it via UTextFuncs.
-
-    return legacyGraphemeBackward(
-      start: start, end: end, endIndexUTF16: endIndexUTF16
-    )
-  }
-
-  @inline(never)
-  func legacyGraphemeBackward(
-    start: UnicodeScalarView.Index,
-    end: UnicodeScalarView.Index,
-    endIndexUTF16: Int
-  ) -> Int {
-    let graphemeClusterBreakProperty =
-      _UnicodeGraphemeClusterBreakPropertyTrie()
-    let segmenter = _UnicodeExtendedGraphemeClusterSegmenter()
-    
-    var graphemeClusterStart = end
-    
-    unicodeScalars.formIndex(before: &graphemeClusterStart)
-    var gcb0 = graphemeClusterBreakProperty.getPropertyRawValue(
-      unicodeScalars[graphemeClusterStart].value)
-    
-    var graphemeClusterStartUTF16 = graphemeClusterStart._position
-    
-    while graphemeClusterStart != start {
-      unicodeScalars.formIndex(before: &graphemeClusterStart)
-      let gcb1 = graphemeClusterBreakProperty.getPropertyRawValue(
-        unicodeScalars[graphemeClusterStart].value)
-      if segmenter.isBoundary(gcb1, gcb0) {
-        break
+      if _slowPath(ubrkOffset == -1) {
+        return numCodeUnits
       }
-      gcb0 = gcb1
-      graphemeClusterStartUTF16 = graphemeClusterStart._position
+      _sanityCheck(endOffset > Int(ubrkOffset), "zero-sized grapheme?")
+      return endOffset - Int(ubrkOffset)
     }
-    
-    return endIndexUTF16 - graphemeClusterStartUTF16
+
+    // The vast majority of time, we can get a pointer and a length directly
+    if _fastPath(_core._baseAddress != nil) {
+      _onFastPath() // Please aggressively inline
+      let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: _core)
+      let ubrkPrecedingOffset = __swift_stdlib_ubrk_preceding(
+        breakIterator, Int32(endOffset)
+      )
+      return measureFromUBreakOffset(ubrkPrecedingOffset)
+    }
+
+    // We have a non-contiguous string. Pull out some code units into a fixed
+    // array and try to perform grapheme breaking on that. If even that's not
+    // sufficient (i.e. very pathological) then copy into an Array.
+    var codeUnitBuffer = _FixedArray16<UInt16>(allZeros:())
+    let maxBufferCount = codeUnitBuffer.count
+    let coreStartIdx = Swift.max(startOffset, endOffset - maxBufferCount)
+    let bufferCount = Swift.min(maxBufferCount, numCodeUnits)
+    for i in 0..<bufferCount {
+      codeUnitBuffer[i] = _core[coreStartIdx+i]
+    }
+
+    return withUnsafeBytes(of: &codeUnitBuffer.storage) {
+      (rawPtr : UnsafeRawBufferPointer) -> Int in
+      let bufPtr = UnsafeBufferPointer(
+        start: rawPtr.baseAddress!.assumingMemoryBound(to: UInt16.self),
+        count: bufferCount)
+
+      let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: bufPtr)
+      let ubrkPrecedingOffset = __swift_stdlib_ubrk_preceding(
+        breakIterator, Int32(bufferCount)
+      )
+
+      if _fastPath(numCodeUnits < maxBufferCount || ubrkPrecedingOffset > 1) {
+        // There was a grapheme break within our buffer.
+        _sanityCheck(ubrkPrecedingOffset < bufferCount, "offset mismatch")
+        return bufferCount - Int(ubrkPrecedingOffset)
+      }
+
+      // Nuclear option: copy out the prefix of the string into an array
+      var codeUnits = Array<UInt16>()
+      codeUnits.reserveCapacity(numCodeUnits)
+      for i in startOffset..<endOffset {
+        codeUnits.append(_core[i])
+      }
+      return codeUnits.withUnsafeBufferPointer { bufPtr -> Int in
+        let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: bufPtr)
+        let ubrkPrecedingOffset = __swift_stdlib_ubrk_preceding(
+          breakIterator, Int32(endOffset)
+        )
+        // No need to adjust ubrkPrecedingOffset as we copied the prefix: it is
+        // the position in the original string
+        return measureFromUBreakOffset(ubrkPrecedingOffset)
+      }
+    }    
   }
-  
+
   /// Accesses the character at the given position.
   ///
   /// The following example searches a string's character view for a capital
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 6add01c..8bb704f 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -283,8 +283,11 @@
     let wholeCore = _slice._base._core
     let subCore : _StringCore = wholeCore[
       startIndex._base._position..<endIndex._base._position]
-    // check that we haven't allocated a new buffer for the result
-    _sanityCheck(subCore._owner === wholeCore._owner)
+    // Check that we haven't allocated a new buffer for the result, if we have
+    // contiguous storage.
+    _sanityCheck(
+      subCore._owner === wholeCore._owner || !wholeCore.hasContiguousStorage)
+
     return String(subCore)
   }
 }
diff --git a/stdlib/public/core/ThreadLocalStorage.swift b/stdlib/public/core/ThreadLocalStorage.swift
index cb213d5..2c09ac3 100644
--- a/stdlib/public/core/ThreadLocalStorage.swift
+++ b/stdlib/public/core/ThreadLocalStorage.swift
@@ -74,20 +74,25 @@
   }
 
   // Retrieve our thread's local uBreakIterator and set it up for the given
-  // StringCore. Checks our TLS cache to avoid excess text resetting.
+  // StringCore.
   static internal func getUBreakIterator(
     for core: _StringCore
   ) -> OpaquePointer {
+    _sanityCheck(core._owner != nil || core._baseAddress != nil,
+      "invalid StringCore")
+    let corePtr: UnsafeMutablePointer<UTF16.CodeUnit> = core.startUTF16
+    return getUBreakIterator(
+      for: UnsafeBufferPointer(start: corePtr, count: core.count))
+  }
+  static internal func getUBreakIterator(
+    for bufPtr: UnsafeBufferPointer<UTF16.CodeUnit>
+  ) -> OpaquePointer {
     let tlsPtr = getPointer()
     let brkIter = tlsPtr[0].uBreakIterator
 
-    _sanityCheck(core._owner != nil || core._baseAddress != nil,
-      "invalid StringCore")
-
     var err = __swift_stdlib_U_ZERO_ERROR
-    let corePtr: UnsafeMutablePointer<UTF16.CodeUnit>
-    corePtr = core.startUTF16
-    __swift_stdlib_ubrk_setText(brkIter, corePtr, Int32(core.count), &err)
+    __swift_stdlib_ubrk_setText(
+      brkIter, bufPtr.baseAddress!, Int32(bufPtr.count), &err)
     _precondition(err.isSuccess, "unexpected ubrk_setUText failure")
 
     return brkIter
diff --git a/stdlib/public/runtime/Exclusivity.cpp b/stdlib/public/runtime/Exclusivity.cpp
index f144698..7c89d92 100644
--- a/stdlib/public/runtime/Exclusivity.cpp
+++ b/stdlib/public/runtime/Exclusivity.cpp
@@ -226,24 +226,6 @@
   }
 };
 
-/// A set of independent access sets.  This is not designed to put
-/// the access sets on different cache lines, so it's fine for
-/// thread-local sets and probably not fine for concurrent sets.
-class AccessSets {
-  enum { NumAccessSets = 8 };
-  AccessSet Sets[NumAccessSets];
-
-public:
-  constexpr AccessSets() = default;
-  AccessSets(const AccessSets &) = delete;
-  AccessSets &operator=(const AccessSets &) = delete;
-
-  AccessSet &get(void *pointer) {
-    size_t index = std::hash<void*>()(pointer) % NumAccessSets;
-    return Sets[index];
-  }
-};
-
 } // end anonymous namespace
 
 // Each of these cases should define a function with this prototype:
@@ -253,10 +235,10 @@
 // Use direct language support for thread-locals.
 
 static_assert(LLVM_ENABLE_THREADS, "LLVM_THREAD_LOCAL will use a global?");
-static LLVM_THREAD_LOCAL AccessSets ExclusivityAccessSets;
+static LLVM_THREAD_LOCAL AccessSet ExclusivityAccessSet;
 
-static AccessSets &getAllSets() {
-  return ExclusivityAccessSets;
+static AccessSet &getAccessSet() {
+  return ExclusivityAccessSet;
 }
 
 #elif SWIFT_EXCLUSIVITY_USE_PTHREAD_SPECIFIC
@@ -265,7 +247,7 @@
 static pthread_key_t createAccessSetPthreadKey() {
   pthread_key_t key;
   int result = pthread_key_create(&key, [](void *pointer) {
-    delete static_cast<AccessSets*>(pointer);
+    delete static_cast<AccessSet*>(pointer);
   });
 
   if (result != 0) {
@@ -275,15 +257,15 @@
   return key;
 }
 
-static AccessSets &getAllSets() {
+static AccessSet &getAccessSet() {
   static pthread_key_t key = createAccessSetPthreadKey();
 
-  AccessSets *sets = static_cast<AccessSets*>(pthread_getspecific(key));
-  if (!sets) {
-    sets = new AccessSets();
-    pthread_setspecific(key, sets);
+  AccessSet *set = static_cast<AccessSet*>(pthread_getspecific(key));
+  if (!set) {
+    set = new AccessSet();
+    pthread_setspecific(key, set);
   }
-  return *sets;
+  return *set;
 }
 
 /** An access set accessed via pthread_get_specific. *************************/
@@ -291,11 +273,6 @@
 #error No implementation chosen for exclusivity!
 #endif
 
-/// Return the right access set for the given pointer.
-static AccessSet &getAccessSet(void *pointer) {
-  return getAllSets().get(pointer);
-}
-
 /// Begin tracking a dynamic access.
 ///
 /// This may cause a runtime failure if an incompatible access is
@@ -315,7 +292,7 @@
 
   if (!pc) pc = get_return_address();
 
-  getAccessSet(pointer).insert(access, pc, pointer, flags);
+  getAccessSet().insert(access, pc, pointer, flags);
 }
 
 /// End tracking a dynamic access.
@@ -329,5 +306,5 @@
     return;
   }
 
-  getAccessSet(pointer).remove(access);
+  getAccessSet().remove(access);
 }
diff --git a/test/ClangImporter/Inputs/SwiftPrivateAttr.txt b/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
index 6ea47fa..590c5e9 100644
--- a/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
+++ b/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
@@ -107,7 +107,7 @@
   static var __PrivA: NSOptions { get }
   static var B: NSOptions { get }
 }
-class __PrivCFType : _CFObject {
+class __PrivCFType {
 }
 @available(swift, obsoleted: 3, renamed: "__PrivCFType")
 typealias __PrivCFTypeRef = __PrivCFType
diff --git a/test/ClangImporter/Inputs/custom-modules/Protocols.h b/test/ClangImporter/Inputs/custom-modules/Protocols.h
index 43ad828..552adbd 100644
--- a/test/ClangImporter/Inputs/custom-modules/Protocols.h
+++ b/test/ClangImporter/Inputs/custom-modules/Protocols.h
@@ -9,3 +9,12 @@
 Class <FooProto, AnotherProto> _Nonnull processComboType(Class <FooProto, AnotherProto> _Nonnull);
 Class <AnotherProto, FooProto> _Nonnull processComboType2(Class <AnotherProto, FooProto> _Nonnull);
 
+
+@protocol SubProto <FooProto>
+@end
+
+@interface ProtocolTestingBase
+@end
+
+@interface SubProtoImpl: ProtocolTestingBase <SubProto>
+@end
diff --git a/test/ClangImporter/Inputs/frameworks/Simple.framework/Headers/Simple.h b/test/ClangImporter/Inputs/frameworks/Simple.framework/Headers/Simple.h
new file mode 100644
index 0000000..8e399ab
--- /dev/null
+++ b/test/ClangImporter/Inputs/frameworks/Simple.framework/Headers/Simple.h
@@ -0,0 +1,6 @@
+@interface SimpleInterface
+@end
+
+@protocol SimpleProtocol
+- (void)foo:(SimpleInterface *)foo;
+@end
diff --git a/test/ClangImporter/Inputs/frameworks/Simple.framework/Modules/module.modulemap b/test/ClangImporter/Inputs/frameworks/Simple.framework/Modules/module.modulemap
new file mode 100644
index 0000000..0a72a6d
--- /dev/null
+++ b/test/ClangImporter/Inputs/frameworks/Simple.framework/Modules/module.modulemap
@@ -0,0 +1,7 @@
+framework module Simple {
+  umbrella header "Simple.h"
+  export *
+  module * {
+    export *
+  }
+}
diff --git a/test/ClangImporter/Inputs/frameworks/Simple.framework/Simple b/test/ClangImporter/Inputs/frameworks/Simple.framework/Simple
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/ClangImporter/Inputs/frameworks/Simple.framework/Simple
diff --git a/test/ClangImporter/Inputs/other.swift b/test/ClangImporter/Inputs/other.swift
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/ClangImporter/Inputs/other.swift
diff --git a/test/ClangImporter/Inputs/pch-bridging-header-with-non-modular-import.h b/test/ClangImporter/Inputs/pch-bridging-header-with-non-modular-import.h
new file mode 100644
index 0000000..228a1cf
--- /dev/null
+++ b/test/ClangImporter/Inputs/pch-bridging-header-with-non-modular-import.h
@@ -0,0 +1,4 @@
+// This is probably intended as a modular import, but it's compiled in an
+// environment in which it can also be (and is) interpreted as a non-modular
+// import.
+#import <Simple/Simple.h>
diff --git a/test/ClangImporter/pch-bridging-header-vs-modular-interface-defn.swift b/test/ClangImporter/pch-bridging-header-vs-modular-interface-defn.swift
new file mode 100644
index 0000000..01e96a5
--- /dev/null
+++ b/test/ClangImporter/pch-bridging-header-vs-modular-interface-defn.swift
@@ -0,0 +1,87 @@
+//
+// Scenario for this test (this actually occurs in the wild):
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+//   1. A header for module M, in include-path, that defines @interface Foo
+//      and a @protocol Bar that references Foo in one of its methods.
+//
+//   2. A symlink in include-path that links into M's (modular) header dir,
+//      which effectively makes a "second definition" of the same interface
+//      and protocol pair, but in a non-modular context.
+//
+//   3. A bridging header that imports the (non-modular)
+//      header-defining-Foo-and-Bar
+//
+//   4. A swift file that imports M and implements Bar (thus referencing Foo).
+//
+//   5. Another swift file that does nothing special, but makes for a multi-file
+//      compilation (requiring a merge-module step).
+//
+//
+// What was previously going wrong (that we're testing for):
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+//   1. Module M gets compiled into a PCM file with a local defn for M.Foo and
+//      M.Bar referencing M.Foo.
+//
+//   2. The bridging header gets precompiled to a PCH with a non-modular
+//      definition of Foo and Bar (because of the order we pass -Xcc includes
+//      to the clang importer, they are preferred over frameworks).
+//
+//   3. Every time swift asks clang to import a defn -- modular or non-modular
+//      -- clang reads _both_ definitions: first the one requested, then the
+//      other one as a completion of its view of the set of defns for the
+//      symbol. This wouldn't normally be a huge problem _except_ that in clang
+//      rev 2ba19793, the rules for interfaces and protocols diverged:
+//      interfaces became first-read-wins, protocols remained last-read-wins.
+//
+//   4. This means that when swift looks up (protocol) Bar, the non-modular
+//      definition is found in the PCH, clang completes it with a modular defn,
+//      and (since it's a protocol) last-read-wins: the modular M.Bar defn
+//      sticks.  Swift then does a load-all-members on M.Bar and gets the
+//      (directly-referenced) M.Foo defn, but since Foo is an interface, M.Foo
+//      is the first-read and it sticks (ignoring the non-modular Foo read
+//      immediately-after from the PCH). So Swift emits an XRef to M.Foo into
+//      the partial .swiftmodule.
+//
+//   5. Later, the merge-modules step executes and reloads the .swiftmodule
+//      file, reading the XRef to M.Foo. Unfortunately when it's run with a
+//      textual bridging header, the textual, non-modular defn of Foo is fed
+//      directly into the compiler by the preprocessor, so it sticks before any
+//      lookups get started. This makes the modular XRef lookup of M.Foo fail.
+//
+//
+// Why disabling bridging PCH fixes this
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// The first-read defn of Foo is fed into clang early, which sticks (as in
+// the merge-modules step). This makes the serialized XRef have the form
+// __ObjC.Foo, which succeeds when performed the second time in merge-modules.
+//
+//
+// How to fix it:
+// ~~~~~~~~~~~~~~
+//
+// One might hope that this can be fixed by having the merge-modules step take a
+// PCH as well as other steps in the compilation. That unfortuantely only
+// inverts the problem, which resurfaces in the definition-order of Bar itself:
+// an XRef to __ObjC.Bar gets serialized, and then _it_ can't be found during
+// merge-modules, because the *last-read* defn of Bar -- the modular one, M.Bar
+// -- wins during lookup.
+//
+// So while we _do_ propose to have the merge-modules step use the PCH, we also
+// put a patch into clang to apply the first-read-wins logic to protocols as
+// well as interfaces.
+//
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/Headers/Simple
+// RUN: ln -s %S/Inputs/frameworks/Simple.framework/Headers/Simple.h %t/Headers/Simple/Simple.h
+// RUN: %target-build-swift -emit-module -module-name test -Xfrontend -disable-deserialization-recovery -v -F %S/Inputs/frameworks -Xcc "-I%t/Headers" -module-cache-path %t/clang-module-cache -import-objc-header %S/Inputs/pch-bridging-header-with-non-modular-import.h %S/Inputs/other.swift %s
+// REQUIRES: objc_interop
+
+import Simple
+class Foo: SimpleProtocol {
+    func foo(_ bar: SimpleInterface) {
+    }
+}
diff --git a/test/ClangImporter/protocol-conformance-in-extension.swift b/test/ClangImporter/protocol-conformance-in-extension.swift
new file mode 100644
index 0000000..69a4c83
--- /dev/null
+++ b/test/ClangImporter/protocol-conformance-in-extension.swift
@@ -0,0 +1,21 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t/a~partial.swiftmodule -I %S/Inputs/custom-modules -module-name TEST -primary-file %s
+// RUN: %target-swift-frontend -emit-module -o %t/test.swiftmodule -I %S/Inputs/custom-modules -module-name TEST %t/a~partial.swiftmodule
+
+// REQUIRES: objc_interop
+
+import TestProtocols
+
+// The protocol in the extension has to refine something that the base class
+// conforms to to trigger the error in rdar://problem/32346184.
+protocol SomeSwiftProto: Equatable {}
+extension ProtocolTestingBase: Equatable {
+  public static func ==(left: ProtocolTestingBase, right: ProtocolTestingBase) -> Bool {
+    return left === right
+  }
+}
+
+// The extension going through the typealias also makes a difference.
+typealias SpecialObject = SubProtoImpl
+extension SpecialObject: SomeSwiftProto {
+}
diff --git a/test/Generics/associated_type_typo.swift b/test/Generics/associated_type_typo.swift
index 8a5dc06..f023418 100644
--- a/test/Generics/associated_type_typo.swift
+++ b/test/Generics/associated_type_typo.swift
@@ -14,7 +14,7 @@
 protocol P3 { }
 protocol P4 { }
 
-// expected-error@+1{{'assoc' is not a member type of 'T'}}
+// expected-error@+1{{'T' does not have a member type named 'assoc'; did you mean 'Assoc'?}}
 func typoAssoc1<T : P1>(x: T.assoc, _: T) { } 
 
 // expected-error@+2{{'T' does not have a member type named 'assoc'; did you mean 'Assoc'?}}{{53-58=Assoc}}
@@ -22,7 +22,7 @@
 func typoAssoc2<T : P1, U : P1>(_: T, _: U) where T.assoc == U.assoc {}
 
 // CHECK-GENERIC-LABEL: .typoAssoc2
-// CHECK-GENERIC: Generic signature: <T, U where T : P1, U : P1, T.Assoc == U.Assoc>
+// CHECK-GENERIC: Generic signature: <T, U where T : P1, U : P1>
 
 // expected-error@+3{{'T.AssocP2' does not have a member type named 'assoc'; did you mean 'Assoc'?}}{{42-47=Assoc}}
 // expected-error@+2{{'U.AssocP2' does not have a member type named 'assoc'; did you mean 'Assoc'?}}{{19-24=Assoc}}
@@ -30,9 +30,8 @@
   where U.AssocP2.assoc : P3,  T.AssocP2.assoc : P4,
         T.AssocP2 == U.AssocP2 {}
 
-// expected-error@+3{{'T.AssocP2' does not have a member type named 'assoc'; did you mean 'Assoc'?}}
-// expected-error@+2{{'T' does not have a member type named 'Assocp2'; did you mean 'AssocP2'?}}{{39-46=AssocP2}}
-// expected-error@+1{{'assoc' is not a member type of 'T.AssocP2'}}
+// expected-error@+2{{'T.AssocP2' does not have a member type named 'assoc'; did you mean 'Assoc'?}}
+// expected-error@+1{{'T' does not have a member type named 'Assocp2'; did you mean 'AssocP2'?}}{{39-46=AssocP2}}
 func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
 
 
@@ -40,7 +39,6 @@
 // CHECK-GENERIC-NEXT: Requirements:
 // CHECK-GENERIC-NEXT:   τ_0_0 : P2 [τ_0_0: Explicit @ {{.*}}:21]
 // CHECK-GENERIC-NEXT:   τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (via Self.AssocP2 in P2)
-// CHECK-GENERIC-NEXT:   τ_0_0[.P2].AssocP2[.P1].Assoc : P3 [τ_0_0[.P2].AssocP2[.P1].Assoc: Explicit @ {{.*}}:53]
 // CHECK-GENERIC-NEXT: Potential archetypes
 
 // <rdar://problem/19620340>
@@ -75,3 +73,17 @@
   where Element_<C> == Element
   , Element_<C.Slice> == Element
 }
+
+class C {
+  typealias SomeElement = Int
+}
+
+func typoSuperclass1<T : C>(_: T) where T.someElement: P3 { }
+// expected-error@-1{{'T' does not have a member type named 'someElement'; did you mean 'SomeElement'?}}{{43-54=SomeElement}}
+
+class D {
+  typealias AElement = Int // expected-note{{did you mean 'AElement'?}}
+  typealias BElement = Int // expected-note{{did you mean 'BElement'?}}
+}
+
+func typoSuperclass2<T : D>(_: T, _: T.Element) { } // expected-error{{'Element' is not a member type of 'T'}}
diff --git a/test/IDE/complete_member_decls_from_parent_decl_context.swift b/test/IDE/complete_member_decls_from_parent_decl_context.swift
index 7d93383..bda9d39 100644
--- a/test/IDE/complete_member_decls_from_parent_decl_context.swift
+++ b/test/IDE/complete_member_decls_from_parent_decl_context.swift
@@ -234,11 +234,11 @@
   func testInstanceFunc() {
     struct NestedInnerA {
       mutating
-      func aTestInstaceFunc() {
+      func aTestInstanceFunc() {
         #^NESTED_NOMINAL_DECL_A_1^#
 // NESTED_NOMINAL_DECL_A_1: Begin completions
 // NESTED_NOMINAL_DECL_A_1-DAG: Decl[LocalVar]/Local:             self[#NestedInnerA#]{{; name=.+$}}
-// NESTED_NOMINAL_DECL_A_1-DAG: Decl[InstanceMethod]/CurrNominal: aTestInstaceFunc()[#Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_A_1-DAG: Decl[InstanceMethod]/CurrNominal: aTestInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_1-DAG: Decl[InstanceVar]/CurrNominal:    aInstanceVar[#Int#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_1-DAG: Decl[InstanceMethod]/CurrNominal: aInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_1-DAG: Decl[Struct]/CurrNominal:         NestedInnerAStruct[#NestedInnerA.NestedInnerAStruct#]{{; name=.+$}}
@@ -259,7 +259,7 @@
         #^NESTED_NOMINAL_DECL_A_2^#
 // NESTED_NOMINAL_DECL_A_2: Begin completions
 // NESTED_NOMINAL_DECL_A_2-DAG: Decl[LocalVar]/Local:             self[#NestedInnerA.Type#]{{; name=.+$}}
-// NESTED_NOMINAL_DECL_A_2-DAG: Decl[InstanceMethod]/CurrNominal: aTestInstaceFunc({#self: &NestedInnerA#})[#() -> Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_A_2-DAG: Decl[InstanceMethod]/CurrNominal: aTestInstanceFunc({#self: &NestedInnerA#})[#() -> Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_2-DAG: Decl[StaticMethod]/CurrNominal:   aTestStaticFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_2-DAG: Decl[InstanceMethod]/CurrNominal: aInstanceFunc({#self: &NestedInnerA#})[#() -> Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_2-DAG: Decl[StaticVar]/CurrNominal:      aStaticVar[#Int#]{{; name=.+$}}
@@ -325,7 +325,7 @@
 
     NestedInnerA()#^NESTED_NOMINAL_DECL_A_5^#
 // NESTED_NOMINAL_DECL_A_5: Begin completions, 4 items
-// NESTED_NOMINAL_DECL_A_5-NEXT: Decl[InstanceMethod]/CurrNominal: .aTestInstaceFunc()[#Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_A_5-NEXT: Decl[InstanceMethod]/CurrNominal: .aTestInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_5-NEXT: Decl[InstanceVar]/CurrNominal:    .aInstanceVar[#Int#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_5-NEXT: Decl[InstanceMethod]/CurrNominal: .aInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_A_5-NEXT: Decl[Subscript]/CurrNominal:      [{#Int#}][#Double#]{{; name=.+$}}
@@ -335,11 +335,11 @@
   static func testStaticFunc() {
     struct NestedInnerB {
       mutating
-      func bTestInstaceFunc() {
+      func bTestInstanceFunc() {
         #^NESTED_NOMINAL_DECL_B_1^#
 // NESTED_NOMINAL_DECL_B_1: Begin completions
 // NESTED_NOMINAL_DECL_B_1-DAG: Decl[LocalVar]/Local:             self[#NestedInnerB#]{{; name=.+$}}
-// NESTED_NOMINAL_DECL_B_1-DAG: Decl[InstanceMethod]/CurrNominal: bTestInstaceFunc()[#Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_B_1-DAG: Decl[InstanceMethod]/CurrNominal: bTestInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_1-DAG: Decl[InstanceVar]/CurrNominal:    bInstanceVar[#Int#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_1-DAG: Decl[InstanceMethod]/CurrNominal: bInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_1-DAG: Decl[Struct]/CurrNominal:         NestedInnerBStruct[#NestedInnerB.NestedInnerBStruct#]{{; name=.+$}}
@@ -363,7 +363,7 @@
         #^NESTED_NOMINAL_DECL_B_2^#
 // NESTED_NOMINAL_DECL_B_2: Begin completions
 // NESTED_NOMINAL_DECL_B_2-DAG: Decl[LocalVar]/Local:             self[#NestedInnerB.Type#]{{; name=.+$}}
-// NESTED_NOMINAL_DECL_B_2-DAG: Decl[InstanceMethod]/CurrNominal: bTestInstaceFunc({#self: &NestedInnerB#})[#() -> Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_B_2-DAG: Decl[InstanceMethod]/CurrNominal: bTestInstanceFunc({#self: &NestedInnerB#})[#() -> Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_2-DAG: Decl[StaticMethod]/CurrNominal:   bTestStaticFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_2-DAG: Decl[InstanceMethod]/CurrNominal: bInstanceFunc({#self: &NestedInnerB#})[#() -> Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_2-DAG: Decl[StaticVar]/CurrNominal:      bStaticVar[#Int#]{{; name=.+$}}
@@ -434,7 +434,7 @@
 
     NestedInnerB()#^NESTED_NOMINAL_DECL_B_5^#
 // NESTED_NOMINAL_DECL_B_5: Begin completions, 4 items
-// NESTED_NOMINAL_DECL_B_5-DAG: Decl[InstanceMethod]/CurrNominal: .bTestInstaceFunc()[#Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_B_5-DAG: Decl[InstanceMethod]/CurrNominal: .bTestInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_5-DAG: Decl[InstanceVar]/CurrNominal:    .bInstanceVar[#Int#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_5-DAG: Decl[InstanceMethod]/CurrNominal: .bInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_B_5-DAG: Decl[Subscript]/CurrNominal:      [{#Int#}][#Double#]{{; name=.+$}}
@@ -452,11 +452,11 @@
 func testOuterC() {
   struct NestedInnerC {
     mutating
-    func cTestInstaceFunc() {
+    func cTestInstanceFunc() {
       #^NESTED_NOMINAL_DECL_C_1^#
 // NESTED_NOMINAL_DECL_C_1: Begin completions
 // NESTED_NOMINAL_DECL_C_1-DAG: Decl[LocalVar]/Local:             self[#NestedInnerC#]{{; name=.+$}}
-// NESTED_NOMINAL_DECL_C_1-DAG: Decl[InstanceMethod]/CurrNominal: cTestInstaceFunc()[#Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_C_1-DAG: Decl[InstanceMethod]/CurrNominal: cTestInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_1-DAG: Decl[InstanceVar]/CurrNominal:    cInstanceVar[#Int#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_1-DAG: Decl[InstanceMethod]/CurrNominal: cInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_1-DAG: Decl[Struct]/CurrNominal:         NestedInnerCStruct[#NestedInnerC.NestedInnerCStruct#]{{; name=.+$}}
@@ -472,7 +472,7 @@
       #^NESTED_NOMINAL_DECL_C_2^#
 // NESTED_NOMINAL_DECL_C_2: Begin completions
 // NESTED_NOMINAL_DECL_C_2-DAG: Decl[LocalVar]/Local:             self[#NestedInnerC.Type#]{{; name=.+$}}
-// NESTED_NOMINAL_DECL_C_2-DAG: Decl[InstanceMethod]/CurrNominal: cTestInstaceFunc({#self: &NestedInnerC#})[#() -> Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_C_2-DAG: Decl[InstanceMethod]/CurrNominal: cTestInstanceFunc({#self: &NestedInnerC#})[#() -> Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_2-DAG: Decl[StaticMethod]/CurrNominal:   cTestStaticFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_2-DAG: Decl[InstanceMethod]/CurrNominal: cInstanceFunc({#self: &NestedInnerC#})[#() -> Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_2-DAG: Decl[StaticVar]/CurrNominal:      cStaticVar[#Int#]{{; name=.+$}}
@@ -525,7 +525,7 @@
 
   NestedInnerC()#^NESTED_NOMINAL_DECL_C_5^#
 // NESTED_NOMINAL_DECL_C_5: Begin completions, 4 items
-// NESTED_NOMINAL_DECL_C_5-NEXT: Decl[InstanceMethod]/CurrNominal: .cTestInstaceFunc()[#Void#]{{; name=.+$}}
+// NESTED_NOMINAL_DECL_C_5-NEXT: Decl[InstanceMethod]/CurrNominal: .cTestInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_5-NEXT: Decl[InstanceVar]/CurrNominal:    .cInstanceVar[#Int#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_5-NEXT: Decl[InstanceMethod]/CurrNominal: .cInstanceFunc()[#Void#]{{; name=.+$}}
 // NESTED_NOMINAL_DECL_C_5-NEXT: Decl[Subscript]/CurrNominal:      [{#Int#}][#Double#]{{; name=.+$}}
diff --git a/test/IRGen/ordering_x86.sil b/test/IRGen/ordering_x86.sil
index ddae69d..c83e803 100644
--- a/test/IRGen/ordering_x86.sil
+++ b/test/IRGen/ordering_x86.sil
@@ -2,6 +2,7 @@
 // RUN: %swift -target i386-apple-ios7.1 %s -module-name main -emit-ir -o - | %FileCheck %s
 // RUN: %swift -target x86_64-apple-ios7.1 %s -module-name main -emit-ir -o - | %FileCheck %s
 // RUN: %swift -target x86_64-unknown-linux-gnu -disable-objc-interop %s -module-name main -emit-ir -o - | %FileCheck %s
+// RUN: %swift -target x86_64-apple-macosx10.9 -module-name main %s -emit-ir -o - | %FileCheck %s --check-prefix=X86_64
 
 // REQUIRES: CODEGENERATOR=X86
 
@@ -34,3 +35,10 @@
 // CHECK: define{{( protected)?}} swiftcc void @foo
 // CHECK: define{{( protected)?}} swiftcc void @bar
 // CHECK: define{{( protected)?}} swiftcc void @baz
+
+// Make sure that the target features are ordered. We care because function
+// merging does not identify two otherwise identical functions as the same if
+// the order of features differs.
+
+// X86_64: define{{( protected)?}} swiftcc void @baz{{.*}}#0
+// X86_64: #0 = {{.*}}"target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3,+x87"
diff --git a/test/Index/Store/Inputs/ClangModuleA.h b/test/Index/Store/Inputs/ClangModuleA.h
new file mode 100644
index 0000000..ea06ce2
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleA.h
@@ -0,0 +1 @@
+void funcA(void);
diff --git a/test/Index/Store/Inputs/ClangModuleB.h b/test/Index/Store/Inputs/ClangModuleB.h
new file mode 100644
index 0000000..ce316e2
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleB.h
@@ -0,0 +1,2 @@
+@import ClangModuleA;
+void funcB(void);
diff --git a/test/Index/Store/Inputs/ClangModuleCSub1.h b/test/Index/Store/Inputs/ClangModuleCSub1.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleCSub1.h
diff --git a/test/Index/Store/Inputs/ClangModuleCSub2.h b/test/Index/Store/Inputs/ClangModuleCSub2.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleCSub2.h
diff --git a/test/Index/Store/Inputs/SwiftModuleA.swift b/test/Index/Store/Inputs/SwiftModuleA.swift
new file mode 100644
index 0000000..59e7758
--- /dev/null
+++ b/test/Index/Store/Inputs/SwiftModuleA.swift
@@ -0,0 +1 @@
+public func funcSwiftA() {}
diff --git a/test/Index/Store/Inputs/SwiftModuleB.swift b/test/Index/Store/Inputs/SwiftModuleB.swift
new file mode 100644
index 0000000..b12db68
--- /dev/null
+++ b/test/Index/Store/Inputs/SwiftModuleB.swift
@@ -0,0 +1,2 @@
+import SwiftModuleA
+public func funcSwiftB() { funcSwiftA() }
diff --git a/test/Index/Store/Inputs/bridge-head.h b/test/Index/Store/Inputs/bridge-head.h
new file mode 100644
index 0000000..b25d652
--- /dev/null
+++ b/test/Index/Store/Inputs/bridge-head.h
@@ -0,0 +1 @@
+#include "bridge-include.h"
diff --git a/test/Index/Store/Inputs/bridge-include.h b/test/Index/Store/Inputs/bridge-include.h
new file mode 100644
index 0000000..55a0722
--- /dev/null
+++ b/test/Index/Store/Inputs/bridge-include.h
@@ -0,0 +1,2 @@
+int includedFunc(int a);
+int MY_CONST = 2;
\ No newline at end of file
diff --git a/test/Index/Store/Inputs/module.modulemap b/test/Index/Store/Inputs/module.modulemap
new file mode 100644
index 0000000..a25324f
--- /dev/null
+++ b/test/Index/Store/Inputs/module.modulemap
@@ -0,0 +1,20 @@
+module ClangModuleA {
+  header "ClangModuleA.h"
+  export *
+}
+module ClangModuleB {
+  header "ClangModuleB.h"
+  export *
+}
+
+module ClangModuleC {
+  module Sub1 {
+    header "ClangModuleCSub1.h"
+    export *
+  }
+
+  module Sub2 {
+    header "ClangModuleCSub2.h"
+    export *
+  }
+}
diff --git a/test/Index/Store/driver-index.swift b/test/Index/Store/driver-index.swift
new file mode 100644
index 0000000..b8007d0
--- /dev/null
+++ b/test/Index/Store/driver-index.swift
@@ -0,0 +1,2 @@
+// RUN: %swiftc_driver -driver-print-jobs -index-file -index-file-path %s %S/Inputs/SwiftModuleA.swift %s -o %t.output_for_index -index-store-path %t.index_store -module-name driver_index 2>&1 | %FileCheck %s
+// CHECK: {{.*}}swift -frontend -typecheck {{.*}}-primary-file {{.*}}driver-index.swift {{.*}}SwiftModuleA.swift {{.*}}driver-index.swift {{.*}}-o {{.*}}.output_for_index {{.*}}-index-store-path {{.*}}.index_store -index-system-modules
diff --git a/test/Index/Store/output-failure.swift b/test/Index/Store/output-failure.swift
new file mode 100644
index 0000000..24167e3
--- /dev/null
+++ b/test/Index/Store/output-failure.swift
@@ -0,0 +1,41 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir %t/idx
+
+// Before indexing, do a dry-run to ensure any clang modules are cached. We
+// want to isolate the error that comes from swift's indexing support, not
+// any failures indexing a clang module.
+// RUN: %target-swift-frontend %s -typecheck
+
+// RUN: chmod -w %t/idx
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/dir.txt || chmod +w %t/idx
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx
+// RUN: %FileCheck %s -check-prefix=DIR_ERR < %t/dir.txt
+// DIR_ERR: error: creating index directory
+
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o
+// test -s %t/idx/*/units/oof.o*
+
+// RUN: chmod -w %t/idx/*/units
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/file.txt || chmod +w %t/idx/*/units
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx/*/units
+// RUN: %FileCheck %s -check-prefix=FILE_ERR < %t/file.txt
+// FILE_ERR: error: writing index unit file
+
+// RUN: rm -rf %t/idx/*/records/*
+// RUN: chmod -x %t/idx/*/records
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/record.txt || chmod +x %t/idx/*/records
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +x %t/idx/*/records
+// RUN: %FileCheck %s -check-prefix=RECORD_ERR < %t/record.txt
+// RECORD_ERR: error: writing index record file
+
+// RUN: rm -rf %t/idx/*/records/*
+// RUN: chmod -w %t/idx/*/records
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/record2.txt || chmod +w %t/idx/*/records
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx/*/records
+// RUN: %FileCheck %s -check-prefix=RECORD_ERR < %t/record2.txt
+
+func foo() {}
diff --git a/test/Index/Store/record-comments.swift b/test/Index/Store/record-comments.swift
new file mode 100644
index 0000000..5d356f1
--- /dev/null
+++ b/test/Index/Store/record-comments.swift
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t.o -typecheck %s
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s
+
+// XFAIL: linux
+
+// CHECK: record-comments.swift
+// CHECK: ------------
+// CHECK: comment-tag/Swift | <no-name> | t:this_is_a_tag | <no-cgname> | Def -
+// CHECK: comment-tag/Swift | <no-name> | t:and_another | <no-cgname> | Def -
+// CHECK: ------------
+
+/// Hello
+/// - Tag: this_is_a_tag
+/// - Tag: and_another
+func foo() {}
+// CHECK: [[@LINE-3]]:5 | comment-tag/Swift | t:this_is_a_tag | Def | rel: 0
+// CHECK: [[@LINE-3]]:5 | comment-tag/Swift | t:and_another | Def | rel: 0
+// CHECK: [[@LINE-3]]:6 | function/Swift |
diff --git a/test/Index/Store/record-dependency.swift b/test/Index/Store/record-dependency.swift
new file mode 100644
index 0000000..6c3777b
--- /dev/null
+++ b/test/Index/Store/record-dependency.swift
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// CHECK: DEPEND START
+// CHECK: Record | user | {{.*}}record-dependency.swift | record-dependency.swift-
+// CHECK: DEPEND END
+
+// RUN: echo 'func bar() {}' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx2 -emit-module -module-name main -emit-module-path %t/main.swiftmodule %s %t/s2.swift -o %t/file.o -o %t/s2.o
+// RUN: c-index-test core -print-unit %t/idx2 | %FileCheck %s -check-prefix=TWO_RECORDS
+// TWO_RECORDS: file.o-
+// TWO_RECORDS: DEPEND START
+// TWO_RECORDS: Record | user | {{.*}}record-dependency.swift | record-dependency.swift-
+// TWO_RECORDS: DEPEND END
+// TWO_RECORDS: s2.o-
+// TWO_RECORDS: DEPEND START
+// TWO_RECORDS: Record | user | {{.*}}s2.swift | s2.swift-
+// TWO_RECORDS: DEPEND END
+
+// XFAIL: linux
+
+func foo() {}
diff --git a/test/Index/Store/record-empty.swift b/test/Index/Store/record-empty.swift
new file mode 100644
index 0000000..c7bdd9e
--- /dev/null
+++ b/test/Index/Store/record-empty.swift
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck -primary-file %s
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// CHECK-NOT: Record{{.*}}record-empty
+
+// XFAIL: linux
diff --git a/test/Index/Store/record-hashing.swift b/test/Index/Store/record-hashing.swift
new file mode 100644
index 0000000..665d4a3
--- /dev/null
+++ b/test/Index/Store/record-hashing.swift
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: echo "func foo() {}" > %t/theinput.swift
+
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: ls %t/idx/*/records/* | grep "theinput.swift" | count 1
+// RUN: cp -r %t/idx %t/idx-orig
+
+// RUN: touch %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// No change in record.
+
+// RUN: echo '// Comment.' >> %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// No change in record.
+
+// RUN: echo 'func goo() {}' >> %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: not diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// RUN: ls %t/idx/*/records/* | grep "theinput.swift" | count 2
+// Changed!  Wrote a new record.
diff --git a/test/Index/Store/record-sourcefile.swift b/test/Index/Store/record-sourcefile.swift
new file mode 100644
index 0000000..129f7cc
--- /dev/null
+++ b/test/Index/Store/record-sourcefile.swift
@@ -0,0 +1,155 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx1 -o %t/file.o -typecheck %s
+// RUN: %target-swift-frontend -index-store-path %t/idx2 -o %t/file.o -typecheck -primary-file %s
+// RUN: c-index-test core -print-record %t/idx1 | %FileCheck %s
+// RUN: c-index-test core -print-record %t/idx2 | %FileCheck %s
+
+// XFAIL: linux
+
+// CHECK: record-sourcefile.swift
+// CHECK: ------------
+// CHECK: struct/Swift | S1 | s:4file2S1V | <no-cgname> | Def,Ref,RelCont -
+// CHECK: instance-method/acc-get/Swift | getter:property | s:4file2S1V8propertySifg | <no-cgname> | Def,Ref,Call,Impl,RelChild,RelRec,RelCall,RelAcc,RelCont - 
+// CHECK: instance-property/Swift | property | [[property_USR:s:4file2S1V8propertySiv]] | <no-cgname> | Def,Ref,Read,RelChild,RelCont -
+// CHECK: static-method/acc-get/Swift | getter:staticProperty | s:4file2S1V14staticPropertySifg | <no-cgname> | Def,Ref,Call,Impl,RelChild,RelRec,RelCall,RelAcc,RelCont -
+// CHECK: static-property/Swift | staticProperty | s:{{.*}} | <no-cgname> | Def,Ref,Read,RelChild,RelCont -
+// CHECK: instance-property/Swift | computedPropertyGetSet | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: struct/Swift | Int | s:Si | <no-cgname> | Ref -
+// CHECK: instance-method/acc-get/Swift | getter:computedPropertyGetSet | s:4file2S1V22computedPropertyGetSetSifg | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-set/Swift | setter:computedPropertyGetSet | s:4file2S1V22computedPropertyGetSetSifs | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-property/Swift | computedPropertyWillDid | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-willset/Swift | willSet:computedPropertyWillDid | s:4file2S1V23computedPropertyWillDidSifw | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-didset/Swift | didSet:computedPropertyWillDid | s:4file2S1V23computedPropertyWillDidSifW | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-property/Swift | computedPropertyAddressor | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-addr/Swift | <no-name> | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-mutaddr/Swift | <no-name> | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: static-method/Swift | staticMethod() | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-property/subscript/Swift | subscript(_:) | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-get/Swift | getter:subscript(_:) | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: protocol/Swift | P1 | s:{{.*}} | <no-cgname> | Def -
+// CHECK: type-alias/associated-type/Swift | AT | s:{{.*}} | <no-cgname> | Def,Ref,RelChild -
+// CHECK: type-alias/Swift | TA | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: class/Swift | C1 | s:{{.*}} | <no-cgname> | Def,Ref,RelBase,RelCont -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,Ref,Call,Dyn,RelChild,RelRec,RelCall,RelCont -
+// CHECK: class/Swift | C2 | s:{{.*}} | <no-cgname> | Def -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,Dyn,RelChild,RelOver -
+// CHECK: function/Swift | takeC1(x:) | s:{{.*}} | <no-cgname> | Def -
+// CHECK: instance-method(test)/Swift | testFoo() | s:{{.*}} | <no-cgname> | Def,Dyn,RelChild -
+// CHECK: ------------
+
+// CHECK: [[@LINE+1]]:8 | struct/Swift | [[S1_USR:s:.*]] | Def | rel: 0
+struct S1 {
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[property_USR]] | Def,RelChild | rel: 1
+// CHECK-NEXT:  RelChild | [[S1_USR]]
+  let property = 1
+// CHECK: [[@LINE+2]]:14 | static-property/Swift | [[staticProperty_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  static let staticProperty = 2
+
+// CHECK: [[@LINE+3]]:7 | instance-property/Swift | [[computedPropertyGetSet_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+// CHECK: [[@LINE+1]]:31 | struct/Swift | s:Si | Ref | rel: 0
+  var computedPropertyGetSet: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-get/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyGetSet_USR]]
+    get { return 1 }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-set/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyGetSet_USR]]
+    set { }
+  }
+
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[computedPropertyWillDid_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  var computedPropertyWillDid: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-willset/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyWillDid_USR]]
+    willSet { }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-didset/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyWillDid_USR]]
+    didSet { }
+  }
+
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[computedPropertyAddressor_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  var computedPropertyAddressor: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-addr/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyAddressor_USR]]
+    unsafeAddress { }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-mutaddr/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyAddressor_USR]]
+    unsafeMutableAddress { }
+  }
+
+// CHECK: [[@LINE+2]]:8 | instance-method/Swift | [[method_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  func method() {
+    _ = self
+// CHECK: [[@LINE+4]]:9 | instance-method/acc-get/Swift | s:{{.*}} | Ref,Call,Impl,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[method_USR]]
+// CHECK-NEXT: RelRec | [[S1_USR]]
+// CHECK: [[@LINE+1]]:9 | instance-property/Swift | s:{{.*}} | Ref,Read,RelCont | rel: 1
+    _ = property
+  }
+
+// CHECK: [[@LINE+2]]:15 | static-method/Swift | [[staticMethod_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  static func staticMethod() {
+// CHECK: [[@LINE+5]]:9 | struct/Swift | s:{{.*}} | Ref,RelCont | rel: 1
+// CHECK: [[@LINE+4]]:12 | static-method/acc-get/Swift | s:{{.*}} | Ref,Call,Impl,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[staticMethod_USR]]
+// CHECK-NEXT: RelRec | [[S1_USR]]
+// CHECK: [[@LINE+1]]:12 | static-property/Swift | s:{{.*}} | Ref,Read,RelCont | rel: 1
+    _ = S1.staticProperty
+  }
+
+// CHECK: [[@LINE+4]]:3 | instance-property/subscript/Swift | [[S1_subscript_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+// CHECK: [[@LINE+2]]:28 | instance-method/acc-get/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[S1_subscript_USR]]
+  subscript(x: Int) -> Int { return 1 }
+}
+
+// CHECK: [[@LINE+1]]:10 | protocol/Swift | [[P1_USR:s:.*]] | Def | rel: 0
+protocol P1 {
+// CHECK: [[@LINE+2]]:18 | type-alias/associated-type/Swift | s:{{.*}} | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[P1_USR]]
+  associatedtype AT
+// CHECK: [[@LINE+3]]:13 | type-alias/Swift | s:{{.*}} | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[P1_USR]]
+// CHECK: [[@LINE+1]]:18 | type-alias/associated-type/Swift | s:{{.*}} | Ref | rel: 0
+  typealias TA = AT
+}
+
+// CHECK: [[@LINE+1]]:7 | class/Swift | [[C1_USR:s:.*]] | Def | rel: 0
+class C1 {
+// CHECK: [[@LINE+2]]:8 | instance-method/Swift | [[C1_foo_USR:s:.*]] | Def,Dyn,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[C1_USR]]
+  func method() {}
+}
+// CHECK: [[@LINE+3]]:7 | class/Swift | [[C2_USR:s:.*]] | Def | rel: 0
+// CHECK: [[@LINE+2]]:12 | class/Swift | [[C1_USR]] | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | [[C2_USR]]
+class C2 : C1 {
+// CHECK: [[@LINE+3]]:17 | instance-method/Swift | s:{{.*}} | Def,Dyn,RelChild,RelOver | rel: 2
+// CHECK-NEXT: RelOver | [[C1_foo_USR]]
+// CHECK-NEXT: RelChild | [[C2_USR]]
+  override func method() {}
+}
+
+// CHECK: [[@LINE+2]]:6 | function/Swift | [[takeC1_USR:s:.*]] | Def | rel: 0
+// CHECK: [[@LINE+1]]:16 | class/Swift | s:{{.*}} | Ref,RelCont | rel: 1
+func takeC1(x: C1) {
+// CHECK: [[@LINE+3]]:5 | instance-method/Swift | s:{{.*}} | Ref,Call,Dyn,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[takeC1_USR]]
+// CHECK-NEXT: RelRec | [[C1_USR]]
+  x.method()
+}
+
+func test1() {}
+class XCTestCase {}
+class MyTestCase: XCTestCase {
+// CHECK: [[@LINE+2]]:8 | instance-method(test)/Swift | s:{{.*}} | Def,Dyn,RelChild | rel: 1
+// CHECK-NEXT: RelChild | s:4file10MyTestCaseC
+  func testFoo() { test1() }
+}
diff --git a/test/Index/Store/record-with-compile-error.swift b/test/Index/Store/record-with-compile-error.swift
new file mode 100644
index 0000000..0cb017d
--- /dev/null
+++ b/test/Index/Store/record-with-compile-error.swift
@@ -0,0 +1,12 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s -verify
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s
+
+// CHECK: function/Swift | test1() | [[TEST1_FUNC:.*]] | <no-cgname> | Def
+// CHECK: [[@LINE+1]]:6 | function/Swift | [[TEST1_FUNC]]
+func test1() {
+  unresolved() // expected-error {{use of unresolved identifier}}
+}
diff --git a/test/Index/Store/unit-from-compile.swift b/test/Index/Store/unit-from-compile.swift
new file mode 100644
index 0000000..2ddfb6e
--- /dev/null
+++ b/test/Index/Store/unit-from-compile.swift
@@ -0,0 +1,24 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend -c -index-store-path %t/idx %s -o %t/file1.o -module-name some_module_test
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// RUN: %target-swift-frontend -c -index-store-path %t/idx_opt %s -o %t/file1.o -module-name some_module_test -O
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=OPT
+
+// CHECK: file1.o
+// CHECK: provider: swift
+// CHECK: is-system: 0
+// CHECK: is-module: 0
+// CHECK: module-name: some_module_test
+// CHECK: has-main: 1
+// CHECK: main-path: {{.*}}/unit-from-compile.swift
+// CHECK: out-file: {{.*}}/file1.o
+// CHECK: is-debug: 1
+
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}/Swift.swiftmodule |
+// CHECK: DEPEND END (1)
+
+// OPT: is-debug: 1
diff --git a/test/Index/Store/unit-multiple-sourcefiles.swift b/test/Index/Store/unit-multiple-sourcefiles.swift
new file mode 100644
index 0000000..a35350b
--- /dev/null
+++ b/test/Index/Store/unit-multiple-sourcefiles.swift
@@ -0,0 +1,33 @@
+// XFAIL: linux
+
+//===--- Building source files separately with a module merge at the end
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s1.swift %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %t/s1.swift %t/s2.swift -o %t/s1.o -c -module-name main -emit-module -emit-module-path %t/s1.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swift -primary-file %t/s2.swift -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/s2.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swiftmodule %t/s2.swiftmodule -emit-module -o %t/main.swiftmodule -module-name main
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+//===--- Building source files together (e.g. WMO)
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s1.swift %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swift %t/s2.swift -o %t/s1.o -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/main.swiftmodule
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+// CHECK-NOT: main.swiftmodule-{{[A-Z0-9]*}}
+
+// CHECK: s1.o-{{[A-Z0-9]*}}
+// CHECK: --------
+// CHECK: out-file: {{.*}}s1.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: s2.o-{{[A-Z0-9]*}}
+// CHECK: --------
+// CHECK: out-file: {{.*}}s2.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
diff --git a/test/Index/Store/unit-one-file-multi-file-invocation.swift b/test/Index/Store/unit-one-file-multi-file-invocation.swift
new file mode 100644
index 0000000..65d08c0
--- /dev/null
+++ b/test/Index/Store/unit-one-file-multi-file-invocation.swift
@@ -0,0 +1,23 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: %swiftc_driver -index-file -index-file-path %s %s %S/Inputs/SwiftModuleA.swift -module-name unit_one_test -o %t.output_for_index -index-store-path %t/idx
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=UNIT
+
+// UNIT-NOT: SwiftShims
+
+// UNIT: [[SWIFT:Swift.swiftmodule-[A-Z0-9]*]]
+// UNIT: DEPEND START
+// UNIT: Record | system | Swift.Math.Floating | {{.*}}Swift.swiftmodule | Swift.swiftmodule_Math_Floating-{{.*}}
+// UNIT: Record | system | Swift.String | {{.*}}Swift.swiftmodule | Swift.swiftmodule_String-{{.*}}
+// UNIT: DEPEND END
+
+// UNIT: unit-one-file-multi-file-invocation{{.*}}.output_for_index
+// UNIT: DEPEND START
+// UNIT: Unit | system |{{.*}}/Swift.swiftmodule | [[SWIFT]]
+// UNIT: Record | user |{{.*}}/unit-one-file-multi-file-invocation.swift |
+// UNIT: DEPEND END (2)
+
+func test1() {
+  funcSwiftA()
+}
diff --git a/test/Index/Store/unit-one-sourcefile.swift b/test/Index/Store/unit-one-sourcefile.swift
new file mode 100644
index 0000000..d0acc59
--- /dev/null
+++ b/test/Index/Store/unit-one-sourcefile.swift
@@ -0,0 +1,29 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -o %t/file1.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s %t/s2.swift -o %t/file1.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -primary-file %t/s2.swift -o %t/file2.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE2
+
+// FILE1: file1.o-{{[A-Z0-9]*}}
+// FILE1: --------
+// FILE1: out-file: {{.*}}file1.o
+// FILE1: DEPEND START
+// FILE1: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE1: DEPEND END
+
+// FILE2: file2.o-{{[A-Z0-9]*}}
+// FILE2: --------
+// FILE2: out-file: {{.*}}file2.o
+// FILE2: DEPEND START
+// FILE2: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE2: DEPEND END
diff --git a/test/Index/Store/unit-pcm-dependency.swift b/test/Index/Store/unit-pcm-dependency.swift
new file mode 100644
index 0000000..c9721ba
--- /dev/null
+++ b/test/Index/Store/unit-pcm-dependency.swift
@@ -0,0 +1,79 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s -o %t/s1.o -I %S/Inputs -typecheck -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// If the module cache already exists, the pcm gets indexed.
+// RUN: rm -rf %t/idx
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s -o %t/s1.o -I %S/Inputs -typecheck -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// FIXME: index the bridging header!
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: echo 'import ClangModuleA' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s %t/s2.swift -o %t/s1.o -o %t/s2.o -I %S/Inputs -c -emit-module -module-name main -emit-module-path %t/main.swiftmodule -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx > %t/both.txt
+// RUN: %FileCheck %s -check-prefix=FILE1 < %t/both.txt
+// RUN: %FileCheck %s -check-prefix=FILE2 < %t/both.txt
+
+
+// XFAIL: linux
+
+import ClangModuleB
+import ClangModuleC.Sub1
+import ClangModuleC.Sub2
+
+func test() {
+  funcA()
+  funcB()
+}
+
+// FILE1: ClangModuleA-
+// FILE1: --------
+// FILE1: is-system: 0
+// FILE1: has-main: 0
+// FILE1: DEPEND START
+// FILE1: Record | user | {{.*}}ClangModuleA.h | ClangModuleA.h-
+// FILE1: DEPEND END
+
+// FILE1: ClangModuleB-
+// FILE1: --------
+// FILE1: is-system: 0
+// FILE1: has-main: 0
+// FILE1: DEPEND START
+// FILE1: Unit | user | ClangModuleA | {{.*}}ClangModuleA-{{.*}}.pcm | ClangModuleA-{{.*}}.pcm-
+// FILE1: Record | user | {{.*}}ClangModuleB.h | ClangModuleB.h-
+// FILE1: DEPEND END
+
+// FILE1: s1.o-
+// FILE1: --------
+// FILE1: has-main: 1
+// FILE1: DEPEND START
+// FILE1-NOT: ClangModuleA.h
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Unit | system | Swift | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Unit | user | ClangModuleB | {{.*}}ClangModuleB-{{[A-Z0-9]*}}.pcm | ClangModuleB-{{[A-Z0-9]*}}.pcm-
+// FILE1: Unit | user | ClangModuleC | {{.*}}ClangModuleC-{{[A-Z0-9]*}}.pcm | ClangModuleC-{{[A-Z0-9]*}}.pcm-
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Record | user | {{.*}}unit-pcm-dependency.swift | unit-pcm-dependency.swift-
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: DEPEND END (4)
+
+// FILE2-NOT: main.swiftmodule-
+
+// FILE2: s2.o-
+// FILE2: --------
+// FILE2: has-main: 1
+// FILE2: out-file: {{.*}}s2.o
+// FILE2: DEPEND START
+// FILE2-NOT: ClangModuleB.h
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: Unit | system | Swift | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: Unit | user | ClangModuleA | {{.*}}ClangModuleA-{{[A-Z0-9]*}}.pcm | ClangModuleA-{{[A-Z0-9]*}}.pcm-
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: DEPEND END
diff --git a/test/Index/Store/unit-swiftmodule-dependency.swift b/test/Index/Store/unit-swiftmodule-dependency.swift
new file mode 100644
index 0000000..df54f92
--- /dev/null
+++ b/test/Index/Store/unit-swiftmodule-dependency.swift
@@ -0,0 +1,57 @@
+// RUN: rm -rf %t && mkdir %t
+
+// RUN: %target-swift-frontend -index-store-path %t/idx %S/Inputs/SwiftModuleA.swift -emit-module -o %t/SwiftModuleA.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %S/Inputs/SwiftModuleB.swift -emit-module -o %t/SwiftModuleB.swiftmodule -I %t
+
+// RUN: echo 'import SwiftModuleA' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s %t/s2.swift -c -o %t/s1.o -o %t/s2.o -I %t -emit-module -module-name main -emit-module-path %t/main.swiftmodule
+
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+// XFAIL: linux
+
+import SwiftModuleA
+import SwiftModuleB
+
+func test() {
+  funcSwiftA()
+  funcSwiftB()
+}
+
+// CHECK: [[MODA:SwiftModuleA.swiftmodule-[A-Z0-9]*]]
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/SwiftModuleA.swiftmodule
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: [[MODB:SwiftModuleB.swiftmodule-[A-Z0-9]*]]
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/SwiftModuleB.swiftmodule
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK-NOT: main.swiftmodule-
+
+// CHECK: s1.o-
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/s1.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleB | {{.*}}/SwiftModuleB.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: s2.o-
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/s2.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
diff --git a/test/Index/Store/unit-with-bridging-header.swift b/test/Index/Store/unit-with-bridging-header.swift
new file mode 100644
index 0000000..f335802
--- /dev/null
+++ b/test/Index/Store/unit-with-bridging-header.swift
@@ -0,0 +1,49 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-pch -index-store-path %t/idx -o %t/bridge-head.pch %S/Inputs/bridge-head.h
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %t/bridge-head.pch -primary-file %s -o %t/s1.o -index-store-path %t/idx
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s --check-prefix=PCH-RECORD
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s --check-prefix=PCH-UNIT
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %S/Inputs/bridge-head.h -primary-file %s -o %t/s1.o -index-store-path %t/idx2
+// RUN: c-index-test core -print-unit %t/idx2 | %FileCheck --check-prefix=TEXTUAL-UNIT %s
+
+// PCH-RECORD: bridge-include.h
+// PCH-RECORD: ------------
+// PCH-RECORD: function/C | includedFunc | {{.*}} | <no-cgname> | Decl - 
+// PCH-RECORD: variable/C | MY_CONST | {{.*}} | <no-cgname> | Def - 
+// PCH-RECORD: ------------
+// PCH-RECORD: 1:5 | function/C | {{.*}} | Decl | rel: 0
+// PCH-RECORD: 2:5 | variable/C | {{.*}} | Def | rel: 0
+
+// PCH-UNIT: bridge-head.pch-
+// PCH-UNIT: --------
+// PCH-UNIT: has-main: 0
+// PCH-UNIT: DEPEND START
+// PCH-UNIT: Record | user | {{.*}}bridge-include.h | bridge-include.h-
+// PCH-UNIT: File | user | {{.*}}bridge-head.h |
+// PCH-UNIT: File | user | {{.*}}module.modulemap |
+// PCH-UNIT: DEPEND END (3)
+// PCH-UNIT: INCLUDE START
+// PCH-UNIT: {{.*}}bridge-head.h:1 | {{.*}}bridge-include.h
+// PCH-UNIT: INCLUDE END (1)
+
+// PCH-UNIT: s1.o-
+// PCH-UNIT: --------
+// PCH-UNIT: has-main: 1
+// PCH-UNIT: DEPEND START
+// PCH-UNIT: Unit | system | {{.*}}Swift.swiftmodule |
+// PCH-UNIT: Unit | user | {{.*}}bridge-head.pch | bridge-head.pch-
+// PCH-UNIT: Record | user | {{.*}}unit-with-bridging-header.swift | unit-with-bridging-header.swift-
+// PCH-UNIT: DEPEND END (3)
+
+// TEXTUAL-UNIT: s1.o-
+// TEXTUAL-UNIT: --------
+// TEXTUAL-UNIT: has-main: 1
+// TEXTUAL-UNIT: DEPEND START
+// TEXTUAL-UNIT: Unit | system | {{.*}}Swift.swiftmodule |
+// TEXTUAL-UNIT: Record | user | {{.*}}unit-with-bridging-header.swift | unit-with-bridging-header.swift-
+// TEXTUAL-UNIT: DEPEND END (2)
+
+func test() {}
diff --git a/test/Parse/invalid.swift b/test/Parse/invalid.swift
index bf21c14..9ff219f 100644
--- a/test/Parse/invalid.swift
+++ b/test/Parse/invalid.swift
@@ -82,18 +82,18 @@
 // expected-error @-1 {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{17-21=}}
 func SR979e(inout x: inout String) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{13-18=}}
 func SR979f(var inout x : Int) { // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{17-23=}}
-// expected-error @-1 {{parameters may not have the 'var' specifier}} {{13-16=}}{{3-3=var x = x\n  }} 
-  x += 10
+// expected-error @-1 {{'var' as a parameter attribute is not allowed}}
+  x += 10     // expected-error {{left side of mutating operator isn't mutable: 'x' is a 'let' constant}}
 }
 func SR979g(inout i: inout Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{13-18=}}
 func SR979h(let inout x : Int) {}  // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{17-23=}}
 // expected-error @-1 {{'let' as a parameter attribute is not allowed}}
 class VarTester {
-  init(var a: Int, var b: Int) {} // expected-error {{parameters may not have the 'var' specifier}} {{8-11=}} {{33-33= var a = a }}
-  // expected-error @-1 {{parameters may not have the 'var' specifier}} {{20-24=}} {{33-33= var b = b }}
-    func x(var b: Int) { //expected-error {{parameters may not have the 'var' specifier}} {{12-15=}} {{9-9=var b = b\n        }}
-        b += 10
-    }
+  init(var a: Int, var b: Int) {} // expected-error {{'var' as a parameter attribute is not allowed}}
+  // expected-error @-1 {{'var' as a parameter attribute is not allowed}}
+  func x(var b: Int) { //expected-error {{'var' as a parameter attribute is not allowed}}
+    b += 10 // expected-error {{left side of mutating operator isn't mutable: 'b' is a 'let' constant}}
+  }
 }
 
 func repeat() {}
diff --git a/test/SIL/ownership-verifier/unreachable_code.sil b/test/SIL/ownership-verifier/unreachable_code.sil
index fbe963d..4d88955 100644
--- a/test/SIL/ownership-verifier/unreachable_code.sil
+++ b/test/SIL/ownership-verifier/unreachable_code.sil
@@ -128,3 +128,22 @@
   %9999 = tuple()
   return %9999 : $()
 }
+
+sil @test7 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : @owned $Builtin.NativeObject):
+  %1 = begin_borrow %0 : $Builtin.NativeObject
+  cond_br undef, bb1, bb2
+
+bb1:
+  end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
+  destroy_value %0 : $Builtin.NativeObject
+  %9999 = tuple()
+  return %9999 : $()
+
+bb2:
+  end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
+  br bb3
+
+bb3:
+  unreachable
+}
diff --git a/test/SILOptimizer/capture_promotion_ownership.sil b/test/SILOptimizer/capture_promotion_ownership.sil
index b970e1d..601a0e4 100644
--- a/test/SILOptimizer/capture_promotion_ownership.sil
+++ b/test/SILOptimizer/capture_promotion_ownership.sil
@@ -335,7 +335,7 @@
 }
 
 // This test makes sure that we properly handle non load uses of
-// struct_element_addr that always have load users with the load occuring before
+// struct_element_addr that always have load users with the load occurring before
 // and after the element in the use list.
 
 sil @mutate_int : $@convention(thin) (@inout Int) -> ()
diff --git a/test/SILOptimizer/eager_specialize.sil b/test/SILOptimizer/eager_specialize.sil
index 0dfc62a..d9d66a4 100644
--- a/test/SILOptimizer/eager_specialize.sil
+++ b/test/SILOptimizer/eager_specialize.sil
@@ -394,7 +394,7 @@
 // CHECK:  %11 = builtin "cmp_eq_Word"(%9 : $Builtin.Word, %10 : $Builtin.Word) : $Builtin.Int1
 // CHECK:  cond_br %11, bb4, bb2
 
-// None of the constraint checks was successfull, perform a generic copy.
+// None of the constraint checks was successful, perform a generic copy.
 // CHECK: bb2:
 // CHECK:  copy_addr %2 to [initialization] %0 : $*S
 // CHECK:  destroy_addr %1 : $*S
@@ -470,7 +470,7 @@
 // CHECK:  %4 = builtin "ispod"<S>(%3 : $@thick S.Type) : $Builtin.Int1
 // CHECK:  cond_br %4, bb3, bb1
 
-// None of the constraint checks was successfull, perform a generic copy.
+// None of the constraint checks was successful, perform a generic copy.
 // CHECK: bb1:
 // CHECK:  copy_addr %2 to [initialization] %0 : $*S
 // CHECK:  destroy_addr %1 : $*S
@@ -620,7 +620,7 @@
 // CHECK:   %6 = builtin "cmp_eq_Word"(%4 : $Builtin.Word, %5 : $Builtin.Word) : $Builtin.Int1
 // CHECK:   cond_br %6, bb3, bb1
 
-// Type dispatch was not successfull.
+// Type dispatch was not successful.
 // CHECK: bb1:
 // CHECK:   destroy_addr %1 : $*S
 // CHECK:   destroy_addr %0 : $*T
diff --git a/test/SILOptimizer/specialize.sil b/test/SILOptimizer/specialize.sil
index 7b3a2a6..77db10d 100644
--- a/test/SILOptimizer/specialize.sil
+++ b/test/SILOptimizer/specialize.sil
@@ -7,7 +7,7 @@
 
 // CHECK-LABEL: sil @exp1 : $@convention(thin) () -> () {
 // CHECK-NOT: apply
-// Call of specialized intializer: <Int32>
+// Call of specialized initializer: <Int32>
 // CHECK: [[CTOR:%[0-9]+]] = function_ref @_T08XXX_inits5Int32V_Tg5
 // CHECK: apply [[CTOR]]
 // CHECK: [[ACCEPTS_INT:%[0-9]+]] = function_ref @acceptsInt
diff --git a/test/Sema/immutability.swift b/test/Sema/immutability.swift
index be0e092..c7825f4 100644
--- a/test/Sema/immutability.swift
+++ b/test/Sema/immutability.swift
@@ -348,11 +348,11 @@
 func invalid_inout(inout var x : Int) { // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{26-30=}}
 // expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}}{{20-25=}}{{34-34=inout }}
 }
-func invalid_var(var x: Int) { // expected-error {{parameters may not have the 'var' specifier}}{{18-21=}} {{1-1=    var x = x\n}}
+func invalid_var(var x: Int) { // expected-error {{'var' as a parameter attribute is not allowed}}
   
 }
 func takesClosure(_: (Int) -> Int) {
-  takesClosure { (var d) in d } // expected-error {{parameters may not have the 'var' specifier}}
+  takesClosure { (var d) in d } // expected-error {{'var' as a parameter attribute is not allowed}}
 }
 
 func updateInt(_ x : inout Int) {}
diff --git a/test/decl/class/override.swift b/test/decl/class/override.swift
index 2396c86..852d672 100644
--- a/test/decl/class/override.swift
+++ b/test/decl/class/override.swift
@@ -169,8 +169,8 @@
 
   func manyA(_: AnyObject, _: AnyObject) {}
   func manyB(_ a: AnyObject, b: AnyObject) {}
-  func manyC(var a: AnyObject,  // expected-error {{parameters may not have the 'var' specifier}} {{14-17=}}
-             var b: AnyObject) {} // expected-error {{parameters may not have the 'var' specifier}} {{14-18=}}
+  func manyC(var a: AnyObject,  // expected-error {{'var' as a parameter attribute is not allowed}}
+             var b: AnyObject) {} // expected-error {{'var' as a parameter attribute is not allowed}}
 
   func result() -> AnyObject? { return nil }
   func both(_ x: AnyObject) -> AnyObject? { return x }
diff --git a/test/decl/var/usage.swift b/test/decl/var/usage.swift
index 904290b..b6236f8 100644
--- a/test/decl/var/usage.swift
+++ b/test/decl/var/usage.swift
@@ -12,10 +12,10 @@
   return y
 }
 
-func mutableParameter(_ a : Int, h : Int, var i : Int, j: Int, g: Int) -> Int { // expected-error {{parameters may not have the 'var' specifier}}
-  i += 1
+func mutableParameter(_ a : Int, h : Int, var i : Int, j: Int, g: Int) -> Int { // expected-error {{'var' as a parameter attribute is not allowed}}
+  i += 1 // expected-error {{left side of mutating operator isn't mutable: 'i' is a 'let' constant}}
   var j = j
-  swap(&i, &j)
+  swap(&i, &j) // expected-error {{cannot pass immutable value as inout argument: 'i' is a 'let' constant}}
   return i+g
 }
 
diff --git a/test/stdlib/Inputs/NSSlowString/NSSlowString.h b/test/stdlib/Inputs/NSSlowString/NSSlowString.h
new file mode 100644
index 0000000..548939c
--- /dev/null
+++ b/test/stdlib/Inputs/NSSlowString/NSSlowString.h
@@ -0,0 +1,10 @@
+#import <Foundation/NSString.h>
+
+// An NSString whose _fastCharacterContents always returns nil
+@interface NSSlowString : NSString
+
+@property (nonatomic, strong) id myProperty;
+
+- (void *) _fastCharacterContents;
+
+@end
diff --git a/test/stdlib/Inputs/NSSlowString/NSSlowString.m b/test/stdlib/Inputs/NSSlowString/NSSlowString.m
new file mode 100644
index 0000000..5f38447
--- /dev/null
+++ b/test/stdlib/Inputs/NSSlowString/NSSlowString.m
@@ -0,0 +1,37 @@
+#import "NSSlowString.h"
+
+
+@interface NSSlowString ()
+
+@property (nonatomic, strong) NSString *stringHolder;
+
+@end
+
+@implementation NSSlowString
+
+- (instancetype)initWithString:(NSString *)name {
+	self = [super init];
+	if (self == nil) {
+		return nil;
+	}
+	self.stringHolder = name;
+	return self;
+}
+
+- (NSUInteger)length {
+    return self.stringHolder.length;
+}
+
+- (id)copy {
+	return self;
+}
+
+- (unichar)characterAtIndex:(NSUInteger)index {
+    return [self.stringHolder characterAtIndex:index];
+}
+
+- (void *) _fastCharacterContents {
+  return nil;
+}
+
+@end
\ No newline at end of file
diff --git a/test/stdlib/Inputs/NSSlowString/module.map b/test/stdlib/Inputs/NSSlowString/module.map
new file mode 100644
index 0000000..60ce0d3
--- /dev/null
+++ b/test/stdlib/Inputs/NSSlowString/module.map
@@ -0,0 +1,3 @@
+module NSSlowString {
+  header "NSSlowString.h"
+}
diff --git a/test/stdlib/NSSlowString.swift b/test/stdlib/NSSlowString.swift
new file mode 100644
index 0000000..5c649bd
--- /dev/null
+++ b/test/stdlib/NSSlowString.swift
@@ -0,0 +1,79 @@
+// RUN: mkdir -p %t
+// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o
+// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -o %t/a.out
+// RUN: %target-run %t/a.out
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import Foundation
+import NSSlowString
+import Swift
+
+import StdlibUnittest
+
+let tests = TestSuite("NonContiguousStrings")
+
+// Perform expected test checks
+func checkSingleForm<S: StringProtocol>(
+	_ s: S, expectedCount: Int, expectedCodeUnitCount: Int?
+) {
+	expectEqual(expectedCount, Int(s.count))
+	if let cuCount = expectedCodeUnitCount {
+		expectEqual(cuCount, Int(s.utf16.count))
+	}
+
+	// Now check various reversed properties
+	let reversedCharacters = Array<Character>(s.reversed())
+
+	expectEqual(Int(s.count), reversedCharacters.count)
+	expectEqualSequence(s.reversed(), reversedCharacters)
+	expectEqual(String(s), String(reversedCharacters.reversed()))
+}
+func check(
+	_ s: String, expectedCount count: Int, expectedCodeUnitCount cuCount: Int
+) {
+	checkSingleForm(s, expectedCount: count, expectedCodeUnitCount: cuCount)
+
+	// Substring tests
+	checkSingleForm(s[...], expectedCount: count, expectedCodeUnitCount: cuCount)
+	checkSingleForm(s.dropFirst(), expectedCount: count-1, expectedCodeUnitCount: nil)
+	checkSingleForm(s.dropLast(), expectedCount: count-1, expectedCodeUnitCount: nil)
+	checkSingleForm(s.dropLast().dropFirst(), expectedCount: count-2, expectedCodeUnitCount: nil)
+}
+
+tests.test("Unicode 9 grapheme breaking") {
+
+	// Test string lengths that correspond to smaller than our fixed size code
+	// unit buffer, larger than it, and exactly it.
+	let strSmall = NSSlowString(string: "aπŸ‘πŸ‘©‍πŸ‘©‍πŸ‘§‍πŸ‘¦")
+	let strBig = NSSlowString(string: "abcdefgπŸ‘πŸ‘©‍πŸ‘©‍πŸ‘§‍πŸ‘¦")
+	let strJustRight = NSSlowString(string: "abcπŸ‘πŸ‘©‍πŸ‘©‍πŸ‘§‍πŸ‘¦")
+	check(strSmall as String, expectedCount: 3, expectedCodeUnitCount: 14)
+	check(strBig as String, expectedCount: 9, expectedCodeUnitCount: 20)
+	check(strJustRight as String, expectedCount: 5, expectedCodeUnitCount: 16)
+}
+
+tests.test("Zalgo") {
+	// Check that we handle absurdly long graphemes
+	var zalgo = "aπŸ‘©‍πŸ‘©‍πŸ‘§‍πŸ‘¦c"
+	for combo in 0x300...0x36f {
+		zalgo.append(String(UnicodeScalar(combo)!))
+	}
+	check(
+		NSSlowString(string: zalgo) as String, 
+		expectedCount: 3, 
+		expectedCodeUnitCount: 125
+	)
+
+	// Check for interspersed zalgo and emoji
+	var megaZalgo = zalgo + zalgo + zalgo + zalgo
+	check(
+		NSSlowString(string: megaZalgo) as String,
+		expectedCount: megaZalgo.count,
+		expectedCodeUnitCount: megaZalgo.utf16.count
+	)
+}
+
+runAllTests()
+
diff --git a/test/stdlib/NewString.swift b/test/stdlib/NewString.swift
index ec4c586..da620a5 100644
--- a/test/stdlib/NewString.swift
+++ b/test/stdlib/NewString.swift
@@ -129,6 +129,8 @@
   var nsASCII = NSString(utf8String: "foobar")!
   // CHECK-NEXT: has UTF-16: false
   print("has UTF-16: \(CFStringGetCharactersPtr(unsafeBitCast(nsASCII, to: CFString.self)) != nil)")
+  print("has ASCII pointer: \(CFStringGetCStringPtr(unsafeBitCast(nsASCII, to: CFString.self), 0x0600) != nil)")
+  print("has ASCII pointer: \(CFStringGetCStringPtr(unsafeBitCast(nsASCII, to: CFString.self), 0x08000100) != nil)")
 
   // CHECK: --- ASCII basic round-tripping ---
   print("--- ASCII basic round-tripping ---")
diff --git a/test/stdlib/TestData.swift b/test/stdlib/TestData.swift
index 55297fa..4d46703 100644
--- a/test/stdlib/TestData.swift
+++ b/test/stdlib/TestData.swift
@@ -1034,19 +1034,19 @@
     
     func test_splittingHttp() {
         func split(_ data: Data, on delimiter: String) -> [Data] {
-            let dataDelimeter = delimiter.data(using: .utf8)!
+            let dataDelimiter = delimiter.data(using: .utf8)!
             var found = [Data]()
             let start = data.startIndex
-            let end = data.endIndex.advanced(by: -dataDelimeter.count)
+            let end = data.endIndex.advanced(by: -dataDelimiter.count)
             guard end >= start else { return [data] }
             var index = start
             var previousIndex = index
             while index < end {
-                let slice = data[index..<index.advanced(by: dataDelimeter.count)]
+                let slice = data[index..<index.advanced(by: dataDelimiter.count)]
                 
-                if slice == dataDelimeter {
+                if slice == dataDelimiter {
                     found.append(data[previousIndex..<index])
-                    previousIndex = index + dataDelimeter.count
+                    previousIndex = index + dataDelimiter.count
                 }
                 
                 index = index.advanced(by: 1)
diff --git a/test/stdlib/TestJSONEncoder.swift b/test/stdlib/TestJSONEncoder.swift
index 5a8a4a8..4882858 100644
--- a/test/stdlib/TestJSONEncoder.swift
+++ b/test/stdlib/TestJSONEncoder.swift
@@ -92,6 +92,17 @@
     _testRoundTrip(of: employee)
   }
 
+  func testEncodingTopLevelNullableType() {
+    // EnhancedBool is a type which encodes either as a Bool or as nil.
+    _testEncodeFailure(of: EnhancedBool.true)
+    _testEncodeFailure(of: EnhancedBool.false)
+    _testEncodeFailure(of: EnhancedBool.fileNotFound)
+
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.true), expectedJSON: "{\"value\":true}".data(using: .utf8)!)
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.false), expectedJSON: "{\"value\":false}".data(using: .utf8)!)
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.fileNotFound), expectedJSON: "{\"value\":null}".data(using: .utf8)!)
+  }
+
   // MARK: - Output Formatting Tests
   func testEncodingOutputFormattingDefault() {
     let expectedJSON = "{\"name\":\"Johnny Appleseed\",\"email\":\"appleseed@apple.com\"}".data(using: .utf8)!
@@ -661,61 +672,30 @@
   }
 }
 
-// MARK: - Helper Types
-
-/// Wraps a type T so that it can be encoded at the top level of a payload.
-fileprivate struct TopLevelWrapper<T> : Codable, Equatable where T : Codable, T : Equatable {
-  let value: T
-
-  init(_ value: T) {
-    self.value = value
-  }
-
-  static func ==(_ lhs: TopLevelWrapper<T>, _ rhs: TopLevelWrapper<T>) -> Bool {
-    return lhs.value == rhs.value
-  }
-}
-
-fileprivate struct FloatNaNPlaceholder : Codable, Equatable {
-  init() {}
-
-  func encode(to encoder: Encoder) throws {
-    var container = encoder.singleValueContainer()
-    try container.encode(Float.nan)
-  }
+/// An enum type which decodes from Bool?.
+fileprivate enum EnhancedBool : Codable {
+  case `true`
+  case `false`
+  case fileNotFound
 
   init(from decoder: Decoder) throws {
     let container = try decoder.singleValueContainer()
-    let float = try container.decode(Float.self)
-    if !float.isNaN {
-      throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Couldn't decode NaN."))
+    if container.decodeNil() {
+      self = .fileNotFound
+    } else {
+      let value = try container.decode(Bool.self)
+      self = value ? .true : .false
     }
   }
 
-  static func ==(_ lhs: FloatNaNPlaceholder, _ rhs: FloatNaNPlaceholder) -> Bool {
-    return true
-  }
-}
-
-fileprivate struct DoubleNaNPlaceholder : Codable, Equatable {
-  init() {}
-
   func encode(to encoder: Encoder) throws {
     var container = encoder.singleValueContainer()
-    try container.encode(Double.nan)
-  }
-
-  init(from decoder: Decoder) throws {
-    let container = try decoder.singleValueContainer()
-    let double = try container.decode(Double.self)
-    if !double.isNaN {
-      throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Couldn't decode NaN."))
+    switch self {
+    case .true: try container.encode(true)
+    case .false: try container.encode(false)
+    case .fileNotFound: try container.encodeNil()
     }
   }
-
-  static func ==(_ lhs: DoubleNaNPlaceholder, _ rhs: DoubleNaNPlaceholder) -> Bool {
-    return true
-  }
 }
 
 /// A type which encodes as an array directly through a single value container.
@@ -864,6 +844,63 @@
   }
 }
 
+// MARK: - Helper Types
+
+/// Wraps a type T so that it can be encoded at the top level of a payload.
+fileprivate struct TopLevelWrapper<T> : Codable, Equatable where T : Codable, T : Equatable {
+  let value: T
+
+  init(_ value: T) {
+    self.value = value
+  }
+
+  static func ==(_ lhs: TopLevelWrapper<T>, _ rhs: TopLevelWrapper<T>) -> Bool {
+    return lhs.value == rhs.value
+  }
+}
+
+fileprivate struct FloatNaNPlaceholder : Codable, Equatable {
+  init() {}
+
+  func encode(to encoder: Encoder) throws {
+    var container = encoder.singleValueContainer()
+    try container.encode(Float.nan)
+  }
+
+  init(from decoder: Decoder) throws {
+    let container = try decoder.singleValueContainer()
+    let float = try container.decode(Float.self)
+    if !float.isNaN {
+      throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Couldn't decode NaN."))
+    }
+  }
+
+  static func ==(_ lhs: FloatNaNPlaceholder, _ rhs: FloatNaNPlaceholder) -> Bool {
+    return true
+  }
+}
+
+fileprivate struct DoubleNaNPlaceholder : Codable, Equatable {
+  init() {}
+
+  func encode(to encoder: Encoder) throws {
+    var container = encoder.singleValueContainer()
+    try container.encode(Double.nan)
+  }
+
+  init(from decoder: Decoder) throws {
+    let container = try decoder.singleValueContainer()
+    let double = try container.decode(Double.self)
+    if !double.isNaN {
+      throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Couldn't decode NaN."))
+    }
+  }
+
+  static func ==(_ lhs: DoubleNaNPlaceholder, _ rhs: DoubleNaNPlaceholder) -> Bool {
+    return true
+  }
+}
+
 // MARK: - Run Tests
 
 #if !FOUNDATION_XCTEST
@@ -879,6 +916,7 @@
 JSONEncoderTests.test("testEncodingTopLevelStructuredSingleClass") { TestJSONEncoder().testEncodingTopLevelStructuredSingleClass() }
 JSONEncoderTests.test("testEncodingTopLevelDeepStructuredType") { TestJSONEncoder().testEncodingTopLevelDeepStructuredType()}
 JSONEncoderTests.test("testEncodingClassWhichSharesEncoderWithSuper") { TestJSONEncoder().testEncodingClassWhichSharesEncoderWithSuper() }
+JSONEncoderTests.test("testEncodingTopLevelNullableType") { TestJSONEncoder().testEncodingTopLevelNullableType() }
 JSONEncoderTests.test("testEncodingOutputFormattingDefault") { TestJSONEncoder().testEncodingOutputFormattingDefault() }
 JSONEncoderTests.test("testEncodingOutputFormattingPrettyPrinted") { TestJSONEncoder().testEncodingOutputFormattingPrettyPrinted() }
 JSONEncoderTests.test("testEncodingOutputFormattingSortedKeys") { TestJSONEncoder().testEncodingOutputFormattingSortedKeys() }
diff --git a/test/stdlib/TestPlistEncoder.swift b/test/stdlib/TestPlistEncoder.swift
index 2ae6377..9f55f38 100644
--- a/test/stdlib/TestPlistEncoder.swift
+++ b/test/stdlib/TestPlistEncoder.swift
@@ -111,6 +111,24 @@
     _testRoundTrip(of: employee, in: .xml)
   }
 
+  func testEncodingTopLevelNullableType() {
+    // EnhancedBool is a type which encodes either as a Bool or as nil.
+    _testEncodeFailure(of: EnhancedBool.true, in: .binary)
+    _testEncodeFailure(of: EnhancedBool.true, in: .xml)
+    _testEncodeFailure(of: EnhancedBool.false, in: .binary)
+    _testEncodeFailure(of: EnhancedBool.false, in: .xml)
+    _testEncodeFailure(of: EnhancedBool.fileNotFound, in: .binary)
+    _testEncodeFailure(of: EnhancedBool.fileNotFound, in: .xml)
+
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.true), in: .binary)
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.true), in: .xml)
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.false), in: .binary)
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.false), in: .xml)
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.fileNotFound), in: .binary)
+    _testRoundTrip(of: TopLevelWrapper(EnhancedBool.fileNotFound), in: .xml)
+  }
+
+
   // MARK: - Encoder Features
   func testNestedContainerCodingPaths() {
     let encoder = JSONEncoder()
@@ -438,6 +456,32 @@
   }
 }
 
+/// An enum type which decodes from Bool?.
+fileprivate enum EnhancedBool : Codable {
+  case `true`
+  case `false`
+  case fileNotFound
+
+  init(from decoder: Decoder) throws {
+    let container = try decoder.singleValueContainer()
+    if container.decodeNil() {
+      self = .fileNotFound
+    } else {
+      let value = try container.decode(Bool.self)
+      self = value ? .true : .false
+    }
+  }
+
+  func encode(to encoder: Encoder) throws {
+    var container = encoder.singleValueContainer()
+    switch self {
+    case .true: try container.encode(true)
+    case .false: try container.encode(false)
+    case .fileNotFound: try container.encodeNil()
+    }
+  }
+}
+
 /// A type which encodes as an array directly through a single value container.
 struct Numbers : Codable, Equatable {
   let values = [4, 8, 15, 16, 23, 42]
@@ -614,6 +658,7 @@
 PropertyListEncoderTests.test("testEncodingTopLevelStructuredSingleClass") { TestPropertyListEncoder().testEncodingTopLevelStructuredSingleClass() }
 PropertyListEncoderTests.test("testEncodingTopLevelDeepStructuredType") { TestPropertyListEncoder().testEncodingTopLevelDeepStructuredType() }
 PropertyListEncoderTests.test("testEncodingClassWhichSharesEncoderWithSuper") { TestPropertyListEncoder().testEncodingClassWhichSharesEncoderWithSuper() }
+PropertyListEncoderTests.test("testEncodingTopLevelNullableType") { TestPropertyListEncoder().testEncodingTopLevelNullableType() }
 PropertyListEncoderTests.test("testNestedContainerCodingPaths") { TestPropertyListEncoder().testNestedContainerCodingPaths() }
 PropertyListEncoderTests.test("testSuperEncoderCodingPaths") { TestPropertyListEncoder().testSuperEncoderCodingPaths() }
 runAllTests()
diff --git a/unittests/AST/SourceLocTests.cpp b/unittests/AST/SourceLocTests.cpp
index 617469e..1ce40ec 100644
--- a/unittests/AST/SourceLocTests.cpp
+++ b/unittests/AST/SourceLocTests.cpp
@@ -151,7 +151,8 @@
                         .addMemBufferCopy("if let x = Optional.some(1) { }");
   SourceLoc start = C.Ctx.SourceMgr.getLocForBufferStart(bufferID);
   
-  auto vardecl = new (C.Ctx) VarDecl(/*IsStatic*/false, /*IsLet*/true,
+  auto vardecl = new (C.Ctx) VarDecl(/*IsStatic*/false,
+                                     VarDecl::Specifier::Let,
                                      /*IsCaptureList*/false,
                                      start.getAdvancedLoc(7)
                                     , C.Ctx.getIdentifier("x")
diff --git a/unittests/runtime/Metadata.cpp b/unittests/runtime/Metadata.cpp
index 9e3a8c5..869cbf3 100644
--- a/unittests/runtime/Metadata.cpp
+++ b/unittests/runtime/Metadata.cpp
@@ -874,7 +874,7 @@
   // The existential's box reference should be copied.
   EXPECT_EQ(buf1.buffer.PrivateData[0], buf2.buffer.PrivateData[0]);
 
-  // Ownership of the box should have been transfered.
+  // Ownership of the box should have been transferred.
   auto *reference = reinterpret_cast<HeapObject *>(buf2.buffer.PrivateData[0]);
   EXPECT_TRUE(swift_isUniquelyReferencedOrPinned_nonNull_native(reference));
 
diff --git a/utils/symbolicate-linux-fatal b/utils/symbolicate-linux-fatal
index 86f77ad..565ace8 100755
--- a/utils/symbolicate-linux-fatal
+++ b/utils/symbolicate-linux-fatal
@@ -79,6 +79,45 @@
 known_memmap = {}
 
 
+def check_base_address(dynlib_path, dynlib_baseaddr, memmap):
+    global known_memmap
+    if dynlib_path in memmap or dynlib_path in known_memmap:
+        if dynlib_path in memmap:
+            existing_baseaddr = memmap[dynlib_path]
+        else:
+            existing_baseaddr = known_memmap[dynlib_path]
+        if existing_baseaddr != dynlib_baseaddr:
+            error_msg = "Mismatched base address for: {0:s}, " \
+                        "had: {1:x}, now got {2:x}"
+            error_msg = error_msg.format(
+                dynlib_path, existing_baseaddr, dynlib_baseaddr)
+            raise Exception(error_msg)
+
+
+def symbolicate_one(frame_addr, frame_idx, dynlib_fname):
+    global lldb_target
+    so_addr = lldb_target.ResolveLoadAddress(frame_addr - 1)
+    sym_ctx = so_addr.GetSymbolContext(lldb.eSymbolContextEverything)
+    frame_fragment = "{0: <4d} {1:20s} 0x{2:016x}".format(
+        frame_idx, dynlib_fname, frame_addr)
+    symbol = sym_ctx.GetSymbol()
+    if not symbol.IsValid():
+        raise Exception("symbol isn't valid")
+
+    symbol_base = symbol.GetStartAddress().GetLoadAddress(lldb_target)
+    symbol_fragment = "{0:s} + {1:d}".format(
+        symbol.GetName(), frame_addr - symbol_base)
+    line_entry = sym_ctx.GetLineEntry()
+    if line_entry.IsValid():
+        line_fragment = "at {0:s}:{1:d}".format(
+            line_entry.GetFileSpec().GetFilename(), line_entry.GetLine())
+    else:
+        line_fragment = ""
+
+    return "{0:s}    {1:s} {2:s}".format(
+           frame_fragment, symbol_fragment, line_fragment)
+
+
 def process_stack(binary, dyn_libs, stack):
     global lldb_target
     global known_memmap
@@ -96,26 +135,20 @@
         else:
             dynlib_path = None
 
-        if "<unavailable>" in stack_tokens[3]:
+        try:
             framePC = int(stack_tokens[2], 16)
             symbol_offset = int(stack_tokens[-1], 10)
+        except:
+            full_stack.append({"line": line, "framePC": 0, "dynlib_fname": ""})
+            continue
+
+        if "<unavailable>" in stack_tokens[3]:
             dynlib_baseaddr = framePC - symbol_offset
-            if dynlib_path in memmap or dynlib_path in known_memmap:
-                if dynlib_path in memmap:
-                    existing_baseaddr = memmap[dynlib_path]
-                else:
-                    existing_baseaddr = known_memmap[dynlib_path]
-                if existing_baseaddr != dynlib_baseaddr:
-                    error_msg = "Mismatched base address for: {0:s}, " \
-                                "had: {1:x}, now got {2:x}"
-                    error_msg = error_msg.format(
-                        dynlib_path, existing_baseaddr, dynlib_baseaddr)
-                    raise Exception(error_msg)
-            else:
-                known_memmap[dynlib_path] = dynlib_baseaddr
-                memmap[dynlib_path] = dynlib_baseaddr
+            check_base_address(dynlib_path, dynlib_baseaddr, memmap)
+            known_memmap[dynlib_path] = dynlib_baseaddr
+            memmap[dynlib_path] = dynlib_baseaddr
         else:
-            framePC = int(stack_tokens[2], 16) + int(stack_tokens[-1], 10)
+            framePC = framePC + symbol_offset
         full_stack.append(
             {"line": line, "framePC": framePC, "dynlib_fname": dynlib_fname})
 
@@ -125,32 +158,13 @@
         add_lldb_target_modules(lldb_target, memmap)
     frame_idx = 0
     for frame in full_stack:
-        use_orig_line = True
         frame_addr = frame["framePC"]
         dynlib_fname = frame["dynlib_fname"]
-        so_addr = lldb_target.ResolveLoadAddress(frame_addr - 1)
-        sym_ctx = so_addr.GetSymbolContext(lldb.eSymbolContextEverything)
-        frame_fragment = "{0: <4d} {1:20s} 0x{2:016x}".format(
-            frame_idx, dynlib_fname, frame_addr)
-        symbol = sym_ctx.GetSymbol()
-        if symbol.IsValid():
-            symbol_base = symbol.GetStartAddress().GetLoadAddress(lldb_target)
-            symbol_fragment = "{0:s} + {1:d}".format(
-                symbol.GetName(), frame_addr - symbol_base)
-            use_orig_line = False
-        else:
-            symbol_fragment = "<unavailable>"
-        line_entry = sym_ctx.GetLineEntry()
-        if line_entry.IsValid():
-            line_fragment = "at {0:s}:{1:d}".format(
-                line_entry.GetFileSpec().GetFilename(), line_entry.GetLine())
-        else:
-            line_fragment = ""
-        if use_orig_line:
+        try:
+            sym_line = symbolicate_one(frame_addr, frame_idx, dynlib_fname)
+            print(sym_line)
+        except:
             print(frame["line"].rstrip())
-        else:
-            print("{0:s}    {1:s} {2:s}".format(
-                frame_fragment, symbol_fragment, line_fragment))
         frame_idx = frame_idx + 1
 
 
diff --git a/validation-test/compiler_crashers_2/0074-rdar28544316.swift b/validation-test/compiler_crashers_2_fixed/0074-rdar28544316.swift
similarity index 93%
rename from validation-test/compiler_crashers_2/0074-rdar28544316.swift
rename to validation-test/compiler_crashers_2_fixed/0074-rdar28544316.swift
index f967f8d..5349cfc 100644
--- a/validation-test/compiler_crashers_2/0074-rdar28544316.swift
+++ b/validation-test/compiler_crashers_2_fixed/0074-rdar28544316.swift
@@ -1,4 +1,4 @@
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 // REQUIRES: asserts
 
 class PropertyDataSource<O: PropertyHosting> {
diff --git a/validation-test/compiler_crashers_2_fixed/0111-rdar33067102.swift b/validation-test/compiler_crashers_2_fixed/0111-rdar33067102.swift
new file mode 100644
index 0000000..3d349e9
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0111-rdar33067102.swift
@@ -0,0 +1,5 @@
+// RUN: not %target-swift-frontend -swift-version 4 %s -typecheck
+
+func flatterMap(_ records: [(Int)]) -> [Int] {
+  records.flatMap { _ in return 1 } // expected-note {{}}
+}
diff --git a/validation-test/stdlib/Lazy.swift.gyb b/validation-test/stdlib/Lazy.swift.gyb
index 1c8f6bd..b91833b 100644
--- a/validation-test/stdlib/Lazy.swift.gyb
+++ b/validation-test/stdlib/Lazy.swift.gyb
@@ -12,7 +12,6 @@
 // RUN: %target-run-simple-swiftgyb
 // REQUIRES: executable_test
 
-// REQUIRES: radar_31897334
 
 import StdlibUnittest
 import StdlibCollectionUnittest
@@ -276,7 +275,10 @@
   .forEach(in: [-1 ..< -1, -1..<0, -1..<1, 0..<1, 1..<1] as [Range<Int>]) {
   r in
   var c = EmptyCollection<OpaqueValue<Int>>()
-  expectCrashLater()
+  // Access is guarded by a _debugPrecondition in EmptyCollection
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
   ${operation}
 }
 
@@ -296,7 +298,10 @@
   ]) {
   (i, offset) in
   let c = EmptyCollection<OpaqueValue<Int>>()
-  expectCrashLater()
+  // Access is guarded by a _debugPrecondition in EmptyCollection
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
   _ = c.index(i, offsetBy: offset)
 }
 
@@ -313,7 +318,10 @@
   ]) {
   (i, offset, limit) in
   let c = EmptyCollection<OpaqueValue<Int>>()
-  expectCrashLater()
+  // Access is guarded by a _debugPrecondition in EmptyCollection
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
   _ = c.index(i, offsetBy: offset, limitedBy: limit)
 }
 
@@ -340,7 +348,10 @@
   ]) {
   (start, end) in
   let c = EmptyCollection<OpaqueValue<Int>>()
-  expectCrashLater()
+  // Access is guarded by a _debugPrecondition in EmptyCollection
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
   _ = c.distance(from: start, to: end)
 }