Merge pull request #17604 from Azoy/moar-random-improvements

[stdlib] Remove _random() customization point
diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake
index 6be8b08..04e9b27 100644
--- a/cmake/modules/SwiftSource.cmake
+++ b/cmake/modules/SwiftSource.cmake
@@ -257,9 +257,9 @@
                             "-Xfrontend" "${GROUP_INFO_JSON_FILE}")
   endif()
 
-  # Force swift 3 compatibility mode for Standard Library.
+  # Force swift 4 compatibility mode for Standard Library.
   if (SWIFTFILE_IS_STDLIB)
-    list(APPEND swift_flags "-swift-version" "3")
+    list(APPEND swift_flags "-swift-version" "4")
   endif()
   
   # Force swift 4 compatibility mode for overlays.
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index bb8d6bd..ab3cb49 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -3168,6 +3168,21 @@
 
   llvm::ArrayRef<GenericParamDescriptor> getGenericParams() const;
 
+  bool isSynthesizedRelatedEntity() const {
+    return getTypeContextDescriptorFlags().isSynthesizedRelatedEntity();
+  }
+
+  /// Return the tag used to discriminate declarations synthesized by the
+  /// Clang importer and give them stable identities.
+  StringRef getSynthesizedDeclRelatedEntityTag() const {
+    if (!isSynthesizedRelatedEntity())
+      return {};
+    // The tag name comes after the null terminator for the name.
+    const char *nameBegin = Name.get();
+    auto *nameEnd = nameBegin + strlen(nameBegin) + 1;
+    return nameEnd;
+  }
+
   /// Return the offset of the start of generic arguments in the nominal
   /// type's metadata. The returned value is measured in sizeof(void*).
   int32_t getGenericArgumentOffset() const;
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 0a82e16..e59acda 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -1189,6 +1189,12 @@
     ///
     /// Meaningful for all type-descriptor kinds.
     IsReflectable = 2,
+    
+    /// Set if the type is a Clang-importer-synthesized related entity. After
+    /// the null terminator for the type name is another null-terminated string
+    /// containing the tag that discriminates the entity from other synthesized
+    /// declarations associated with the same declaration.
+    IsSynthesizedRelatedEntity = 3,
 
     /// Set if the context descriptor is includes metadata for dynamically
     /// constructing a class's vtables at metadata instantiation time.
@@ -1221,6 +1227,10 @@
   FLAGSET_DEFINE_FLAG_ACCESSORS(IsCTypedef, isCTypedef, setIsCTypedef)
   FLAGSET_DEFINE_FLAG_ACCESSORS(IsReflectable, isReflectable, setIsReflectable)
 
+  FLAGSET_DEFINE_FLAG_ACCESSORS(IsSynthesizedRelatedEntity,
+                                isSynthesizedRelatedEntity,
+                                setIsSynthesizedRelatedEntity)
+
   FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasVTable,
                                 class_hasVTable,
                                 class_setHasVTable)
diff --git a/include/swift/AST/ASTWalker.h b/include/swift/AST/ASTWalker.h
index b112e72..69519f8 100644
--- a/include/swift/AST/ASTWalker.h
+++ b/include/swift/AST/ASTWalker.h
@@ -201,6 +201,16 @@
   /// params in AbstractFunctionDecl and NominalTypeDecl.
   virtual bool shouldWalkIntoGenericParams() { return false; }
 
+  /// This method configures whether the walker should walk into the
+  /// initializers of lazy variables.  These initializers are semantically
+  /// different from other initializers in their context and so sometimes
+  /// should not be visited.
+  ///
+  /// Note that visiting the body of the lazy getter will find a
+  /// LazyInitializerExpr with the initializer as its sub-expression.
+  /// However, ASTWalker does not walk into LazyInitializerExprs on its own.
+  virtual bool shouldWalkIntoLazyInitializers() { return true; }
+
   /// walkToParameterListPre - This method is called when first visiting a
   /// ParameterList, before walking into its parameters.  If it returns false,
   /// the subtree is skipped.
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 553f334..f8b6fc2 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -27,6 +27,7 @@
 #include "swift/AST/GenericParamKey.h"
 #include "swift/AST/IfConfigClause.h"
 #include "swift/AST/LayoutConstraint.h"
+#include "swift/AST/StorageImpl.h"
 #include "swift/AST/TypeAlignments.h"
 #include "swift/AST/TypeWalker.h"
 #include "swift/AST/Witness.h"
@@ -306,7 +307,7 @@
     NumElements : 32
   );
 
-  SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1,
+  SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1+1+1,
     AlreadyInLookupTable : 1,
 
     /// Whether we have already checked whether this declaration is a 
@@ -315,10 +316,16 @@
 
     /// Whether the decl can be accessed by swift users; for instance,
     /// a.storage for lazy var a is a decl that cannot be accessed.
-    IsUserAccessible : 1
+    IsUserAccessible : 1,
+
+    /// Whether the "IsObjC" bit has been computed yet.
+    IsObjCComputed : 1,
+
+    /// Whether this declaration is exposed to Objective-C.
+    IsObjC : 1
   );
 
-  SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1+1+1+4,
+  SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1+1+1+1+1,
     /// Whether we are overridden later
     Overridden : 1,
 
@@ -328,11 +335,14 @@
     /// Whether the setter is mutating.
     IsSetterMutating : 1,
 
-    /// The storage kind.
-    StorageKind : 4
+    /// Whether this represents physical storage.
+    HasStorage : 1,
+
+    /// Whether this storage supports semantic mutation in some way.
+    SupportsMutation : 1
   );
 
-  SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+4+1+1+1,
+  SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+4+1+1+1+1,
     /// \brief Whether this property is a type property (currently unfortunately
     /// called 'static').
     IsStatic : 1,
@@ -351,7 +361,11 @@
 
     /// \brief Whether this is a property used in expressions in the debugger.
     /// It is up to the debugger to instruct SIL how to access this variable.
-    IsDebuggerVar : 1
+    IsDebuggerVar : 1,
+
+    /// \brief Whether this is a property defined in the debugger's REPL.
+    /// FIXME: Remove this once LLDB has proper support for resilience.
+    IsREPLVar : 1
   );
 
   SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1 + NumDefaultArgumentKindBits,
@@ -450,14 +464,7 @@
     HasStubImplementation : 1
   );
 
-  SWIFT_INLINE_BITFIELD(TypeDecl, ValueDecl, 1,
-    /// Whether we have already checked the inheritance clause.
-    ///
-    /// FIXME: Is this too fine-grained?
-    CheckedInheritanceClause : 1
-  );
-
-  SWIFT_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, TypeDecl);
+  SWIFT_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, ValueDecl);
 
   SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, AbstractTypeParamDecl, 16+16,
     : NumPadBits,
@@ -466,7 +473,7 @@
     Index : 16
   );
 
-  SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl);
+  SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, ValueDecl);
 
   SWIFT_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1+1,
     /// Whether the typealias forwards perfectly to its underlying type.
@@ -581,7 +588,7 @@
     Associativity : 2
   );
 
-  SWIFT_INLINE_BITFIELD(AssociatedTypeDecl, TypeDecl, 1+1,
+  SWIFT_INLINE_BITFIELD(AssociatedTypeDecl, ValueDecl, 1+1,
     ComputedOverridden : 1,
     HasOverridden : 1
   );
@@ -593,7 +600,7 @@
     NumPathElements : 8
   );
 
-  SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1+1,
+  SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1,
     /// An encoding of the default and maximum access level for this extension.
     ///
     /// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)),
@@ -601,11 +608,6 @@
     /// default, and 'private' is never used. 0 represents an uncomputed value.
     DefaultAndMaxAccessLevel : 3,
 
-    /// Whether we have already checked the inheritance clause.
-    ///
-    /// FIXME: Is this too fine-grained?
-    CheckedInheritanceClause : 1,
-
     /// Whether there is are lazily-loaded conformances for this extension.
     HasLazyConformances : 1
   );
@@ -1673,16 +1675,6 @@
     return hasValidationStarted() && !isBeingValidated();
   }
 
-  /// Whether we already type-checked the inheritance clause.
-  bool checkedInheritanceClause() const {
-    return Bits.ExtensionDecl.CheckedInheritanceClause;
-  }
-
-  /// Note that we have already type-checked the inheritance clause.
-  void setCheckedInheritanceClause(bool checked = true) {
-    Bits.ExtensionDecl.CheckedInheritanceClause = checked;
-  }
-
   bool hasDefaultAccessLevel() const {
     return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0;
   }
@@ -1814,13 +1806,14 @@
 
   enum class Flags {
     Checked = 1 << 0,
-    Removed = 1 << 1
+    Removed = 1 << 1,
+    Lazy    = 1 << 2,
   };
 
   // When the initializer is removed we don't actually clear the pointer
   // because we might need to get initializer's source range. Since the
   // initializer is ASTContext-allocated it is safe.
-  llvm::PointerIntPair<Expr *, 2, OptionSet<Flags>> InitCheckedAndRemoved;
+  llvm::PointerIntPair<Expr *, 3, OptionSet<Flags>> InitAndFlags;
 
   /// The initializer context used for this pattern binding entry.
   DeclContext *InitContext = nullptr;
@@ -1829,26 +1822,35 @@
 
 public:
   PatternBindingEntry(Pattern *P, Expr *E, DeclContext *InitContext)
-    : ThePattern(P), InitCheckedAndRemoved(E, {}), InitContext(InitContext) {}
+    : ThePattern(P), InitAndFlags(E, {}), InitContext(InitContext) {}
 
   Pattern *getPattern() const { return ThePattern; }
   void setPattern(Pattern *P) { ThePattern = P; }
   Expr *getInit() const {
-    return (InitCheckedAndRemoved.getInt().contains(Flags::Removed))
-      ? nullptr : InitCheckedAndRemoved.getPointer();
+    return (InitAndFlags.getInt().contains(Flags::Removed))
+      ? nullptr : InitAndFlags.getPointer();
+  }
+  Expr *getNonLazyInit() const {
+    return isInitializerLazy() ? nullptr : getInit();
   }
   SourceRange getOrigInitRange() const;
   void setInit(Expr *E);
 
   /// Retrieve the initializer as it was written in the source.
-  Expr *getInitAsWritten() const { return InitCheckedAndRemoved.getPointer(); }
+  Expr *getInitAsWritten() const { return InitAndFlags.getPointer(); }
 
   bool isInitializerChecked() const {
-    return InitCheckedAndRemoved.getInt().contains(Flags::Checked);
+    return InitAndFlags.getInt().contains(Flags::Checked);
   }
   void setInitializerChecked() {
-    InitCheckedAndRemoved.setInt(
-      InitCheckedAndRemoved.getInt() | Flags::Checked);
+    InitAndFlags.setInt(InitAndFlags.getInt() | Flags::Checked);
+  }
+
+  bool isInitializerLazy() const {
+    return InitAndFlags.getInt().contains(Flags::Lazy);
+  }
+  void setInitializerLazy() {
+    InitAndFlags.setInt(InitAndFlags.getInt() | Flags::Lazy);
   }
 
   // Return the first variable initialized by this pattern.
@@ -1929,6 +1931,9 @@
   Expr *getInit(unsigned i) const {
     return getPatternList()[i].getInit();
   }
+  Expr *getNonLazyInit(unsigned i) const {
+    return getPatternList()[i].getNonLazyInit();
+  }
   
   SourceRange getOrigInitRange(unsigned i) const {
     return getPatternList()[i].getOrigInitRange();
@@ -1966,6 +1971,14 @@
   void setInitializerChecked(unsigned i) {
     getMutablePatternList()[i].setInitializerChecked();
   }
+
+  bool isInitializerLazy(unsigned i) const {
+    return getPatternList()[i].isInitializerLazy();
+  }
+
+  void setInitializerLazy(unsigned i) {
+    getMutablePatternList()[i].setInitializerLazy();
+  }
   
   /// Does this binding declare something that requires storage?
   bool hasStorage() const;
@@ -2170,6 +2183,8 @@
     Bits.ValueDecl.AlreadyInLookupTable = false;
     Bits.ValueDecl.CheckedRedeclaration = false;
     Bits.ValueDecl.IsUserAccessible = true;
+    Bits.ValueDecl.IsObjCComputed = false;
+    Bits.ValueDecl.IsObjC = false;
   }
 
   // MemberLookupTable borrows a bit from this type
@@ -2190,7 +2205,7 @@
   /// Determine whether we have already checked whether this
   /// declaration is a redeclaration.
   bool alreadyCheckedRedeclaration() const { 
-    return Bits.ValueDecl.CheckedRedeclaration; 
+    return Bits.ValueDecl.CheckedRedeclaration;
   }
 
   /// Set whether we have already checked this declaration as a
@@ -2405,10 +2420,9 @@
   /// This can be true even if there is no 'objc' attribute on the declaration.
   /// In that case it was inferred by the type checker and set with a call to
   /// markAsObjC().
-  bool isObjC() const {
-    return getAttrs().hasAttribute<ObjCAttr>();
-  }
-  
+  bool isObjC() const;
+
+  /// Note whether this declaration is known to be exposed to Objective-C.
   void setIsObjC(bool Value);
 
   /// Is this declaration marked with 'final'?
@@ -2477,10 +2491,7 @@
   TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
            Identifier name, SourceLoc NameLoc,
            MutableArrayRef<TypeLoc> inherited) :
-    ValueDecl(K, context, name, NameLoc), Inherited(inherited)
-  {
-    Bits.TypeDecl.CheckedInheritanceClause = false;
-  }
+    ValueDecl(K, context, name, NameLoc), Inherited(inherited) {}
 
 public:
   Identifier getName() const { return getFullName().getBaseIdentifier(); }
@@ -2504,16 +2515,6 @@
   /// Retrieve one of the types listed in the "inherited" clause.
   Type getInheritedType(unsigned index) const;
 
-  /// Whether we already type-checked the inheritance clause.
-  bool checkedInheritanceClause() const {
-    return Bits.TypeDecl.CheckedInheritanceClause;
-  }
-
-  /// Note that we have already type-checked the inheritance clause.
-  void setCheckedInheritanceClause(bool checked = true) {
-    Bits.TypeDecl.CheckedInheritanceClause = checked;
-  }
-
   void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }
 
   static bool classof(const Decl *D) {
@@ -3726,6 +3727,15 @@
 
   bool existentialTypeSupportedSlow(LazyResolver *resolver);
 
+  struct {
+    /// The superclass type and a bit to indicate whether the
+    /// superclass was computed yet or not.
+    llvm::PointerIntPair<Type, 1, bool> Superclass;
+  } LazySemanticInfo;
+
+  friend class SuperclassTypeRequest;
+  friend class TypeChecker;
+
 public:
   ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc,
                Identifier Name, MutableArrayRef<TypeLoc> Inherited,
@@ -3736,6 +3746,19 @@
   /// Retrieve the set of protocols inherited from this protocol.
   llvm::TinyPtrVector<ProtocolDecl *> getInheritedProtocols() const;
 
+  /// Determine whether this protocol has a superclass.
+  bool hasSuperclass() const { return (bool)getSuperclass(); }
+
+  /// Retrieve the superclass of this protocol, or null if there is no superclass.
+  Type getSuperclass() const;
+
+  /// Retrieve the ClassDecl for the superclass of this protocol, or null if there
+  /// is no superclass.
+  ClassDecl *getSuperclassDecl() const;
+
+  /// Set the superclass of this protocol.
+  void setSuperclass(Type superclass);
+
   /// Retrieve the set of AssociatedTypeDecl members of this protocol; this
   /// saves loading the set of members in cases where there's no possibility of
   /// a protocol having nested types (ObjC protocols).
@@ -3953,71 +3976,6 @@
   }
 };
 
-// Note that the values of these enums line up with %select values in
-// diagnostics.
-enum class AccessorKind {
-#define ACCESSOR(ID) ID,
-#define LAST_ACCESSOR(ID) Last = ID
-#include "swift/AST/AccessorKinds.def"
-};
-
-const unsigned NumAccessorKinds = unsigned(AccessorKind::Last) + 1;
-
-static inline IntRange<AccessorKind> allAccessorKinds() {
-  return IntRange<AccessorKind>(AccessorKind(0),
-                                AccessorKind(NumAccessorKinds));
-}
-
-/// The safety semantics of this addressor.
-enum class AddressorKind : uint8_t {
-  /// \brief This is not an addressor.
-  NotAddressor,
-  /// \brief This is an unsafe addressor; it simply returns an address.
-  Unsafe,
-  /// \brief This is an owning addressor; it returns an AnyObject
-  /// which should be released when the caller is done with the object.
-  Owning,
-  /// \brief This is an owning addressor; it returns a Builtin.NativeObject
-  /// which should be released when the caller is done with the object.
-  NativeOwning,
-  /// \brief This is a pinning addressor; it returns a Builtin.NativeObject?
-  /// which should be unpinned when the caller is done with the object.
-  NativePinning,
-};
-
-/// Whether an access to storage is for reading, writing, or both.
-enum class AccessKind : uint8_t {
-  /// The access is just to read the current value.
-  Read,
-
-  /// The access is just to overwrite the current value.
-  Write,
-
-  /// The access may require either reading or writing the current value.
-  ReadWrite
-};
-
-/// The way to actually evaluate an access to storage.
-enum class AccessStrategy : uint8_t {
-  /// The decl is a VarDecl with its own backing storage; evaluate its
-  /// address directly.
-  Storage,
-
-  /// The decl is a VarDecl with storage defined by a property behavior;
-  /// this access may initialize or reassign the storage based on dataflow.
-  BehaviorStorage,
-
-  /// The decl has addressors; call the appropriate addressor for the
-  /// access kind.  These calls are currently always direct.
-  Addressor,
-
-  /// Directly call the getter, setter, or materializeForSet accessor.
-  DirectToAccessor,
-
-  /// Indirectly call the getter, setter, or materializeForSet accessor.
-  DispatchToAccessor,
-};
-
 /// Information about a behavior instantiated by a storage declaration.
 ///
 /// TODO: Accessors, composed behaviors
@@ -4054,75 +4012,6 @@
 /// SubscriptDecl, representing potentially settable memory locations.
 class AbstractStorageDecl : public ValueDecl {
 public:
-  enum StorageKindTy {
-    /// There are bits stored in memory for this object, and they are accessed
-    /// directly.  This is not valid for a SubscriptDecl.
-    Stored,
-    
-    /// This is a stored property with trivial accessors which simply get and
-    /// set the underlying storage.  This is not valid for a SubscriptDecl.
-    ///
-    /// These accessors are used for several different purposes:
-    ///   1) In an @objc variable, these accessors are dynamically dispatched
-    ///      to and may be overridden.
-    ///   2) When a stored property satisfies a protocol requirement, these
-    ///      accessors end up as entries in the witness table.
-    ///   3) When a stored property is accessed outside of the storage
-    ///      declaration's resilience domain, when the owning type or
-    ///      global variable is resilient.
-    StoredWithTrivialAccessors,
-
-    /// This is a stored property with either a didSet specifier or a
-    /// willSet specifier (or both).  Sema synthesizes a setter which
-    /// calls them at the appropriate points.
-    StoredWithObservers,
-
-    /// There are bits stored in memory for this object, but they are
-    /// not allocated directly within the container; instead, there
-    /// are accessors which return the address of the memory.  The
-    /// value is accessed directly through the returned address.
-    ///
-    /// This is legal on both VarDecls and SubscriptDecls.
-    ///
-    /// There is always at least an 'address' accessor; if the object
-    /// is mutable, there will also be a 'mutableAddress' accessor.
-    Addressed,
-    
-    /// Like Addressed, this object has address accessors.  Like
-    /// StoredWithTrivialAccessors, accessors have been synthesized
-    /// which simply read and write through the addresses returned by
-    /// the addressors.
-    AddressedWithTrivialAccessors,
-
-    /// Like Addressed, this object has address accessors.  Like
-    /// StoredWithObservers, it also has either a willSet specifier or
-    /// a didSet specifier.  Accessors have been synthesized, like
-    /// with StoredWithObservers but using the address returned from
-    /// the appropriate accessor instead.
-    AddressedWithObservers,
-
-    /// This is an override of an object which adds either a didSet
-    /// specifier or a willSet specifier (or both).  Sema synthesizes
-    /// a setter which calls them at the appropriate points around
-    /// delegating to the superclass's setter.
-    InheritedWithObservers,
-
-    /// There is no memory associated with this decl anywhere.  It is
-    /// accessed by calling a getter and setter.  If the setter is
-    /// absent, then the value is only loadable, but not storable.
-    Computed,
-
-    /// This object was specified with non-trivial getter and
-    /// mutableAddress accessors.  If it is accessed in a read-only
-    /// manner, the getter is called; otherwise, mutableAddress is
-    /// called.
-    ///
-    /// This turns out to the be the right thing for certain core data
-    /// structures which, when they store a bridged object, cannot
-    /// return the address at which the object is stored.
-    ComputedWithMutableAddress,
-  };
-
   static const size_t MaxNumAccessors = 255;
 private:
   AbstractStorageDecl *OverriddenDecl;
@@ -4135,7 +4024,14 @@
     using AccessorIndex = uint8_t;
     static const AccessorIndex InvalidIndex = 0;
 
+    /// The range of the braces around the accessor clause.
     SourceRange Braces;
+
+    /// The implementation info for the accessors.  If there's no
+    /// AccessorRecord for a storage decl, the decl is just stored.
+    StorageImplInfo ImplInfo;
+
+    /// The number of accessors currently stored in this record.
     AccessorIndex NumAccessors;
 
     /// The storage capacity of this record for accessors.  Always includes
@@ -4148,14 +4044,19 @@
     /// or the index+1 of the accessor in the accessors array.
     AccessorIndex AccessorIndices[NumAccessorKinds];
 
-    AccessorRecord(SourceRange braces, ArrayRef<AccessorDecl*> accessors,
+    AccessorRecord(SourceRange braces, StorageImplInfo implInfo,
+                   ArrayRef<AccessorDecl*> accessors,
                    AccessorIndex accessorsCapacity);
   public:
     static AccessorRecord *create(ASTContext &ctx, SourceRange braces,
+                                  StorageImplInfo implInfo,
                                   ArrayRef<AccessorDecl*> accessors);
 
     SourceRange getBracesRange() const { return Braces; }
 
+    const StorageImplInfo &getImplInfo() const { return ImplInfo; }
+    void overwriteImplInfo(StorageImplInfo newInfo) { ImplInfo = newInfo; }
+
     inline AccessorDecl *getAccessor(AccessorKind kind) const;
 
     ArrayRef<AccessorDecl *> getAllAccessors() const {
@@ -4176,21 +4077,33 @@
   llvm::PointerIntPair<BehaviorRecord*, 3, OptionalEnum<AccessLevel>>
     BehaviorInfo;
 
-  void setStorageKind(StorageKindTy K) {
-    Bits.AbstractStorageDecl.StorageKind = unsigned(K);
-  }
-
   void configureAccessor(AccessorDecl *accessor);
+  void setFieldsFromImplInfo(StorageImplInfo implInfo) {
+    Bits.AbstractStorageDecl.HasStorage = implInfo.hasStorage();
+    Bits.AbstractStorageDecl.SupportsMutation = implInfo.supportsMutation();
+  }
 
 protected:
   AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name,
-                      SourceLoc NameLoc)
+                      SourceLoc NameLoc, bool supportsMutation)
     : ValueDecl(Kind, DC, Name, NameLoc), OverriddenDecl(nullptr) {
-    Bits.AbstractStorageDecl.StorageKind = Stored;
+    Bits.AbstractStorageDecl.HasStorage = true;
+    Bits.AbstractStorageDecl.SupportsMutation = supportsMutation;
     Bits.AbstractStorageDecl.IsGetterMutating = false;
     Bits.AbstractStorageDecl.IsSetterMutating = true;
     Bits.AbstractStorageDecl.Overridden = false;
   }
+
+  void setSupportsMutationIfStillStored(bool supportsMutation) {
+    if (auto ptr = Accessors.getPointer()) {
+      auto impl = ptr->getImplInfo();
+      if (!impl.isSimpleStored()) return;
+      impl = StorageImplInfo::getSimpleStored(supportsMutation);
+      ptr->overwriteImplInfo(impl);
+    }
+    Bits.AbstractStorageDecl.SupportsMutation = supportsMutation;
+  }
+
 public:
 
   /// \brief Should this declaration be treated as if annotated with transparent
@@ -4201,113 +4114,49 @@
   /// is a member.  Currently only variables can be static.
   inline bool isStatic() const; // defined in this header
 
-  /// \brief Determine whether this variable is computed, which means it
-  /// has no storage but does have a user-defined getter or setter.
-  ///
-  StorageKindTy getStorageKind() const {
-    return (StorageKindTy) Bits.AbstractStorageDecl.StorageKind;
+  /// \brief Determine how this storage is implemented.
+  StorageImplInfo getImplInfo() const {
+    if (auto ptr = Accessors.getPointer())
+      return ptr->getImplInfo();
+    return StorageImplInfo::getSimpleStored(supportsMutation());
   }
 
+  ReadImplKind getReadImpl() const {
+    return getImplInfo().getReadImpl();
+  }
+  WriteImplKind getWriteImpl() const {
+    return getImplInfo().getWriteImpl();
+  }
+  ReadWriteImplKind getReadWriteImpl() const {
+    return getImplInfo().getReadWriteImpl();
+  }
+
+  /// Overwrite the registered implementation-info.  This should be
+  /// used carefully.
+  void overwriteImplInfo(StorageImplInfo implInfo);
+
   /// \brief Return true if this is a VarDecl that has storage associated with
   /// it.
   bool hasStorage() const {
-    switch (getStorageKind()) {
-    case Stored:
-    case StoredWithTrivialAccessors:
-    case StoredWithObservers:
-      return true;
-    case InheritedWithObservers:
-    case Computed:
-    case ComputedWithMutableAddress:
-    case Addressed:
-    case AddressedWithTrivialAccessors:
-    case AddressedWithObservers:
-      return false;
-    }
-    llvm_unreachable("bad storage kind");
+    return Bits.AbstractStorageDecl.HasStorage;
   }
 
-  /// \brief Return true if this is a VarDecl that has storage associated with
-  /// it which can be trivially accessed.
-  bool hasTrivialStorage() const {
-    switch (getStorageKind()) {
-    case Stored:
-    case StoredWithTrivialAccessors:
-      return true;
-    case StoredWithObservers:
-    case InheritedWithObservers:
-    case Computed:
-    case ComputedWithMutableAddress:
-    case Addressed:
-    case AddressedWithTrivialAccessors:
-    case AddressedWithObservers:
-      return false;
-    }
-    llvm_unreachable("bad storage kind");
-  }
-
-  /// \brief Return true if this object has a getter (and, if mutable,
-  /// a setter and a materializeForSet).
-  bool hasAccessorFunctions() const {
-    switch (getStorageKind()) {
-    case Addressed:
-    case Stored:
-      return false;
-    case StoredWithTrivialAccessors:
-    case StoredWithObservers:
-    case InheritedWithObservers:
-    case Computed:
-    case ComputedWithMutableAddress:
-    case AddressedWithTrivialAccessors:
-    case AddressedWithObservers:
-      return true;
-    }
-    llvm_unreachable("bad storage kind");
-  }
-
-  /// \brief Return true if this object has observing accessors.
+  /// \brief Return true if this storage has the basic accessors/capability
+  /// to be mutated.  This is generally constant after the accessors are
+  /// installed by the parser/importer/whatever.
   ///
-  /// It's generally not appropriate to use this predicate directly in
-  /// a condition; instead, you should be switching on the storage kind.
-  bool hasObservers() const {
-    switch (getStorageKind()) {
-    case Stored:
-    case StoredWithTrivialAccessors:
-    case Computed:
-    case ComputedWithMutableAddress:
-    case Addressed:
-    case AddressedWithTrivialAccessors:
-      return false;
-    case StoredWithObservers:
-    case InheritedWithObservers:
-    case AddressedWithObservers:
-      return true;
-    }
-    llvm_unreachable("bad storage kind");
+  /// Note that this is different from the mutability of the declaration
+  /// in the user language: sometimes we can assign to declarations that
+  /// don't support mutation (e.g. to initialize them), and sometimes we
+  /// can't mutate things that do support mutation (e.g. because their
+  /// setter is private).
+  bool supportsMutation() const {
+    return Bits.AbstractStorageDecl.SupportsMutation;
   }
 
-  /// \brief Return true if this object has either an addressor or a
-  /// mutable addressor.
-  ///
-  /// It's generally not appropriate to use this predicate directly in
-  /// a condition; instead, you should be switching on the storage
-  /// kind.  Only use this for diagnostic, AST exploration, or
-  /// assertion purposes.
-  bool hasAddressors() const {
-    switch (getStorageKind()) {
-    case Stored:
-    case StoredWithTrivialAccessors:
-    case StoredWithObservers:
-    case InheritedWithObservers:
-    case Computed:
-      return false;
-    case ComputedWithMutableAddress:
-    case Addressed:
-    case AddressedWithTrivialAccessors:
-    case AddressedWithObservers:
-      return true;
-    }
-    llvm_unreachable("bad storage kind");
+  /// Are there any accessors for this declaration, including implicit ones?
+  bool hasAnyAccessors() const {
+    return !getAllAccessors().empty();
   }
   
   /// \brief Return true if reading this storage requires the ability to
@@ -4328,26 +4177,22 @@
     Bits.AbstractStorageDecl.IsSetterMutating = isMutating;
   }
 
-  AccessorDecl *getAccessorFunction(AccessorKind kind) const {
+  AccessorDecl *getAccessor(AccessorKind kind) const {
     if (auto info = Accessors.getPointer())
       return info->getAccessor(kind);
     return nullptr;
   }
 
-  ArrayRef<AccessorDecl*> getAllAccessorFunctions() const {
+  ArrayRef<AccessorDecl*> getAllAccessors() const {
     if (const auto *info = Accessors.getPointer())
       return info->getAllAccessors();
     return {};
   }
 
-  void setAccessors(StorageKindTy storageKind,
+  void setAccessors(StorageImplInfo storageImpl,
                     SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
                     SourceLoc rbraceLoc);
 
-  /// \brief Add trivial accessors to this Stored or Addressed object.
-  void addTrivialAccessors(AccessorDecl *Get, AccessorDecl *Set,
-                           AccessorDecl *MaterializeForSet);
-
   /// \brief Add a setter to an existing Computed var.
   ///
   /// This should only be used by the ClangImporter.
@@ -4356,10 +4201,14 @@
   /// \brief Add a behavior to a property.
   void addBehavior(TypeRepr *Type, Expr *Param);
 
-  /// \brief Set a materializeForSet accessor for this declaration.
-  ///
-  /// This should only be used by Sema.
-  void setMaterializeForSetFunc(AccessorDecl *materializeForSet);
+  /// \brief Add a synthesized getter.
+  void setSynthesizedGetter(AccessorDecl *getter);
+
+  /// \brief Add a synthesized setter.
+  void setSynthesizedSetter(AccessorDecl *setter);
+
+  /// \brief Add a synthesized materializeForSet accessor.
+  void setSynthesizedMaterializeForSet(AccessorDecl *materializeForSet);
 
   SourceRange getBracesRange() const {
     if (auto info = Accessors.getPointer())
@@ -4369,12 +4218,12 @@
 
   /// \brief Retrieve the getter used to access the value of this variable.
   AccessorDecl *getGetter() const {
-    return getAccessorFunction(AccessorKind::Get);
+    return getAccessor(AccessorKind::Get);
   }
   
   /// \brief Retrieve the setter used to mutate the value of this variable.
   AccessorDecl *getSetter() const {
-    return getAccessorFunction(AccessorKind::Set);
+    return getAccessor(AccessorKind::Set);
   }
 
   AccessLevel getSetterFormalAccess() const {
@@ -4393,18 +4242,18 @@
   /// \brief Retrieve the materializeForSet function, if this
   /// declaration has one.
   AccessorDecl *getMaterializeForSetFunc() const {
-    return getAccessorFunction(AccessorKind::MaterializeForSet);
+    return getAccessor(AccessorKind::MaterializeForSet);
   }
 
   /// \brief Return the decl for the immutable addressor if it exists.
   AccessorDecl *getAddressor() const {
-    return getAccessorFunction(AccessorKind::Address);
+    return getAccessor(AccessorKind::Address);
   }
 
   /// \brief Return the decl for the 'mutableAddress' accessors if
   /// it exists; this is only valid on a declaration with addressors.
   AccessorDecl *getMutableAddressor() const {
-    return getAccessorFunction(AccessorKind::MutableAddress);
+    return getAccessor(AccessorKind::MutableAddress);
   }
 
   /// \brief Return the appropriate addressor for the given access kind.
@@ -4417,13 +4266,13 @@
   /// \brief Return the decl for the willSet specifier if it exists, this is
   /// only valid on a declaration with Observing storage.
   AccessorDecl *getWillSetFunc() const {
-    return getAccessorFunction(AccessorKind::WillSet);
+    return getAccessor(AccessorKind::WillSet);
   }
 
   /// \brief Return the decl for the didSet specifier if it exists, this is
   /// only valid on a declaration with Observing storage.
   AccessorDecl *getDidSetFunc() const {
-    return getAccessorFunction(AccessorKind::DidSet);
+    return getAccessor(AccessorKind::DidSet);
   }
 
   /// Given that this is an Objective-C property or subscript declaration,
@@ -4550,12 +4399,13 @@
 
   VarDecl(DeclKind Kind, bool IsStatic, Specifier Sp, bool IsCaptureList,
           SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC)
-    : AbstractStorageDecl(Kind, DC, Name, NameLoc)
+    : AbstractStorageDecl(Kind, DC, Name, NameLoc, !isImmutableSpecifier(Sp))
   {
     Bits.VarDecl.IsStatic = IsStatic;
     Bits.VarDecl.Specifier = static_cast<unsigned>(Sp);
     Bits.VarDecl.IsCaptureList = IsCaptureList;
     Bits.VarDecl.IsDebuggerVar = false;
+    Bits.VarDecl.IsREPLVar = false;
     Bits.VarDecl.HasNonPatternBindingInit = false;
     setType(Ty);
   }
@@ -4669,9 +4519,7 @@
   Specifier getSpecifier() const {
     return static_cast<Specifier>(Bits.VarDecl.Specifier);
   }
-  void setSpecifier(Specifier Spec) {
-    Bits.VarDecl.Specifier = static_cast<unsigned>(Spec);
-  }
+  void setSpecifier(Specifier Spec);
   
   /// Is the type of this parameter 'inout'?
   ///
@@ -4692,7 +4540,10 @@
   StaticSpellingKind getCorrectStaticSpelling() const;
 
   bool isImmutable() const {
-    switch (getSpecifier()) {
+    return isImmutableSpecifier(getSpecifier());
+  }
+  static bool isImmutableSpecifier(Specifier sp) {
+    switch (sp) {
     case Specifier::Let:
     case Specifier::Shared:
     case Specifier::Owned:
@@ -4742,6 +4593,13 @@
   void setDebuggerVar(bool IsDebuggerVar) {
     Bits.VarDecl.IsDebuggerVar = IsDebuggerVar;
   }
+  
+  /// Is this a special debugger REPL variable?
+  /// FIXME: Remove this once LLDB has proper support for resilience.
+  bool isREPLVar() const { return Bits.VarDecl.IsREPLVar; }
+  void setREPLVar(bool IsREPLVar) {
+    Bits.VarDecl.IsREPLVar = IsREPLVar;
+  }
 
   /// Return the Objective-C runtime name for this property.
   Identifier getObjCPropertyName() const;
@@ -4934,7 +4792,8 @@
                 SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
                 GenericParamList *GenericParams)
     : GenericContext(DeclContextKind::SubscriptDecl, Parent),
-      AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
+      AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc,
+                          /*supports mutation (will be overwritten)*/ true),
       ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) {
     setIndices(Indices);
     setGenericParams(GenericParams);
diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def
index 8246eab..4c33af6 100644
--- a/include/swift/AST/DiagnosticsCommon.def
+++ b/include/swift/AST/DiagnosticsCommon.def
@@ -93,6 +93,24 @@
 ERROR(function_type_no_parens,none,
       "single argument function types require parentheses", ())
 
+//------------------------------------------------------------------------------
+// MARK: Circular reference diagnostics
+//------------------------------------------------------------------------------
+ERROR(circular_reference, none,
+      "circular reference", ())
+
+ERROR(redundant_type_alias_define, none,
+      "redundant type alias declaration", ())
+
+NOTE(circular_reference_through, none,
+     "through reference here", ())
+
+ERROR(circular_class_inheritance,none,
+      "%0 inherits from itself", (Identifier))
+
+ERROR(circular_enum_inheritance,none,
+      "%0 has a raw type that depends on itself", (Identifier))
+
 #ifndef DIAG_NO_UNDEF
 # if defined(DIAG)
 #  undef DIAG
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index cc6ba01..ef58c27 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -283,9 +283,9 @@
 ERROR(observingproperty_with_getset,none,
       "%select{willSet|didSet}0 variable must not also have a "
       "%select{get|set}1 specifier", (unsigned, unsigned))
-ERROR(observingproperty_without_mutableaddress,none,
-      "%select{willSet|didSet}0 variable with addressor must provide a "
-      "'mutableAddress' accessor", (unsigned))
+ERROR(observingproperty_with_address,none,
+      "variable with addressor may not have %select{willSet|didSet}0",
+      (unsigned))
 ERROR(observingproperty_in_subscript,none,
       "%select{willSet|didSet}0 is not allowed in subscripts", (unsigned))
 ERROR(getset_init,none,
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 5fd05de..a461fae 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1826,7 +1826,7 @@
       "generic parameter base", (Identifier))
 
 ERROR(circular_protocol_def,none,
-      "circular protocol inheritance %0", (StringRef))
+      "protocol %0 refines itself", (Identifier))
 ERROR(objc_protocol_inherits_non_objc_protocol,none,
       "@objc protocol %0 cannot refine non-@objc protocol %1", (Type, Type))
 WARNING(protocol_composition_with_postfix,none,
@@ -2155,8 +2155,6 @@
 NOTE(superclass_here,none,"superclass is declared here", ())
 ERROR(superclass_of_open_not_open,none,
   "superclass %0 of open class must be open", (Type))
-ERROR(circular_class_inheritance,none,
-      "circular class inheritance %0", (StringRef))
 ERROR(inheritance_from_final_class,none,
       "inheritance from a final class %0", (Identifier))
 ERROR(inheritance_from_unspecialized_objc_generic_class,none,
@@ -2199,8 +2197,6 @@
 // Enum raw types
 ERROR(multiple_enum_raw_types,none,
   "multiple enum raw types %0 and %1", (Type, Type))
-ERROR(circular_enum_inheritance,none,
-      "circular enum raw types %0", (StringRef))
 ERROR(raw_type_not_first,none,
   "raw type %0 must appear first in the enum inheritance clause", (Type))
 ERROR(raw_type_not_literal_convertible,none,
@@ -2799,12 +2795,19 @@
 // Partial application of foreign functions not supported
 ERROR(partial_application_of_function_invalid,none,
       "partial application of %select{"
-        "function with 'inout' parameters|"
         "'mutating' method|"
         "'super.init' initializer chain|"
         "'self.init' initializer delegation"
       "}0 is not allowed",
       (unsigned))
+WARNING(partial_application_of_function_invalid_swift4,none,
+      "partial application of %select{"
+        "'mutating' method|"
+        "'super.init' initializer chain|"
+        "'self.init' initializer delegation"
+      "}0 is not allowed; calling the function has undefined behavior and will "
+      "be an error in future Swift versions",
+      (unsigned))
 
 ERROR(self_assignment_var,none,
       "assigning a variable to itself", ())
@@ -4062,18 +4065,6 @@
         (Identifier, unsigned))
 
 //------------------------------------------------------------------------------
-// MARK: Circular reference diagnostics
-//------------------------------------------------------------------------------
-ERROR(circular_reference, none,
-      "circular reference", ())
-
-ERROR(redundant_type_alias_define, none,
-      "redundant type alias declaration", ())
-
-NOTE(circular_reference_through, none,
-     "through reference here", ())
-
-//------------------------------------------------------------------------------
 // MARK: Debug diagnostics
 //------------------------------------------------------------------------------
 
diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h
index 985b4c7..78cb3ce 100644
--- a/include/swift/AST/Evaluator.h
+++ b/include/swift/AST/Evaluator.h
@@ -37,12 +37,23 @@
 
 namespace swift {
 
+using llvm::ArrayRef;
 using llvm::Optional;
 using llvm::None;
 
 class DiagnosticEngine;
+class Evaluator;
 class UnifiedStatsReporter;
 
+/// An "abstract" request function pointer, which is the storage type
+/// used for each of the
+using AbstractRequestFunction = void(void);
+
+/// Form the specific request function for the given request type.
+template<typename Request>
+using RequestFunction =
+    typename Request::OutputType(const Request &, Evaluator &);
+
 /// Pretty stack trace handler for an arbitrary request.
 template<typename Request>
 class PrettyStackTraceRequest : public llvm::PrettyStackTraceEntry {
@@ -59,7 +70,7 @@
 };
 
 /// Report that a request of the given kind is being evaluated, so it
-/// can be recoded by the stats reporter.
+/// can be recorded by the stats reporter.
 template<typename Request>
 void reportEvaluatedRequest(UnifiedStatsReporter &stats,
                             const Request &request) { }
@@ -138,6 +149,18 @@
   /// non-null.
   UnifiedStatsReporter *stats = nullptr;
 
+  /// A vector containing the abstract request functions that can compute
+  /// the result of a particular request within a given zone. The
+  /// \c uint8_t is the zone number of the request, and the array is
+  /// indexed by the index of the request type within that zone. Each
+  /// entry is a function pointer that will be reinterpret_cast'd to
+  ///
+  ///   RequestType::OutputType (*)(const RequestType &request,
+  ///                               Evaluator &evaluator);
+  /// and called to satisfy the request.
+  std::vector<std::pair<uint8_t, ArrayRef<AbstractRequestFunction *>>>
+    requestFunctionsByZone;
+
   /// A vector containing all of the active evaluation requests, which
   /// is treated as a stack and is used to detect cycles.
   llvm::SetVector<AnyRequest> activeRequests;
@@ -156,6 +179,19 @@
   /// so all clients must cope with cycles.
   llvm::DenseMap<AnyRequest, std::vector<AnyRequest>> dependencies;
 
+  /// Retrieve the request function for the given zone and request IDs.
+  AbstractRequestFunction *getAbstractRequestFunction(uint8_t zoneID,
+                                                      uint8_t requestID) const;
+
+  /// Retrieve the request function for the given request type.
+  template<typename Request>
+  auto getRequestFunction() const -> RequestFunction<Request> * {
+    auto abstractFn = getAbstractRequestFunction(TypeID<Request>::zoneID,
+                                                 TypeID<Request>::localID);
+    assert(abstractFn && "No request function for request");
+    return reinterpret_cast<RequestFunction<Request> *>(abstractFn);
+  }
+
 public:
   /// Construct a new evaluator that can emit cyclic-dependency
   /// diagnostics through the given diagnostics engine.
@@ -165,6 +201,13 @@
   /// statistics will be recorded.
   void setStatsReporter(UnifiedStatsReporter *stats) { this->stats = stats; }
 
+  /// Register the set of request functions for the given zone.
+  ///
+  /// These functions will be called to evaluate any requests within that
+  /// zone.
+  void registerRequestFunctions(uint8_t zoneID,
+                                ArrayRef<AbstractRequestFunction *> functions);
+
   /// Evaluate the given request and produce its result,
   /// consulting/populating the cache as required.
   template<typename Request>
@@ -247,7 +290,7 @@
     /// Update statistics.
     if (stats) reportEvaluatedRequest(*stats, request);
 
-    return request(*this);
+    return getRequestFunction<Request>()(request, *this);
   }
 
   /// Get the result of a request, consulting an external cache
@@ -260,17 +303,8 @@
     if (auto cached = request.getCachedResult())
       return *cached;
 
-    // Clear out the dependencies on this request; we're going to recompute
-    // them now anyway.
-    dependencies[request].clear();
-
-    PrettyStackTraceRequest<Request> prettyStackTrace(request);
-
-    /// Update statistics.
-    if (stats) reportEvaluatedRequest(*stats, request);
-
-    // Service the request.
-    auto result = request(*this);
+    // Compute the result.
+    auto result = getResultUncached(request);
 
     // Cache the result.
     request.cacheResult(result);
@@ -293,12 +327,8 @@
       return known->second.castTo<typename Request::OutputType>();
     }
 
-    // Clear out the dependencies on this request; we're going to recompute
-    // them now anyway.
-    dependencies[request].clear();
-
-    // Evaluate the request.
-    auto result = request(*this);
+    // Compute the result.
+    auto result = getResultUncached(request);
 
     // Cache the result.
     cache.insert({anyRequest, result});
@@ -314,7 +344,7 @@
                          llvm::raw_ostream &out,
                          llvm::DenseSet<AnyRequest> &visitedAnywhere,
                          llvm::SmallVectorImpl<AnyRequest> &visitedAlongPath,
-                         llvm::ArrayRef<AnyRequest> highlightPath,
+                         ArrayRef<AnyRequest> highlightPath,
                          std::string &prefixStr,
                          bool lastChild) const;
 
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index 7ae0df4..edfa810 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -104,15 +104,19 @@
   Last_CheckedCastKind = Swift3BridgingDowncast,
 };
 
+/// What are the high-level semantics of this access?
 enum class AccessSemantics : uint8_t {
-  /// On a property or subscript reference, this is a direct access to
-  /// the underlying storage.  On a function reference, this is a
-  /// non-polymorphic access to a particular implementation.
+  /// On a storage reference, this is a direct access to the underlying
+  /// physical storage, bypassing any observers.  The declaration must be 
+  /// a variable with storage.
+  ///
+  /// On a function reference, this is a non-polymorphic access to a
+  /// particular implementation.
   DirectToStorage,
 
-  /// On a property or subscript reference, this is a direct,
-  /// non-polymorphic access to the getter/setter accessors.
-  DirectToAccessor,
+  /// On a storage reference, this is a direct access to the concrete
+  /// implementation of this storage, bypassing any possibility of override.
+  DirectToImplementation,
 
   /// On a property or subscript reference, this is an access to a property
   /// behavior that may be an initialization. Reads always go through the
@@ -4612,6 +4616,28 @@
   void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
 };
 
+/// A LazyInitializerExpr is used to embed an existing typechecked
+/// expression --- like the initializer of a lazy variable --- into an
+/// untypechecked AST.
+class LazyInitializerExpr : public Expr {
+  Expr *SubExpr;
+public:
+  LazyInitializerExpr(Expr *subExpr)
+    : Expr(ExprKind::LazyInitializer, /*implicit*/ true),
+      SubExpr(subExpr) {}
+
+  SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
+  SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); }
+  SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }
+  SourceLoc getLoc() const { return SubExpr->getLoc(); }
+
+  Expr *getSubExpr() const { return SubExpr; }
+
+  static bool classof(const Expr *E) {
+    return E->getKind() == ExprKind::LazyInitializer;
+  }
+};
+
 /// Produces the Objective-C selector of the referenced method.
 ///
 /// \code
diff --git a/include/swift/AST/ExprNodes.def b/include/swift/AST/ExprNodes.def
index 30b3c9f..9dd9137 100644
--- a/include/swift/AST/ExprNodes.def
+++ b/include/swift/AST/ExprNodes.def
@@ -182,6 +182,7 @@
 EXPR(Assign, Expr)
 EXPR(CodeCompletion, Expr)
 UNCHECKED_EXPR(UnresolvedPattern, Expr)
+EXPR(LazyInitializer, Expr)
 EXPR(EditorPlaceholder, Expr)
 EXPR(ObjCSelector, Expr)
 EXPR(KeyPath, Expr)
diff --git a/include/swift/AST/Initializer.h b/include/swift/AST/Initializer.h
index c3ce60d..754056a 100644
--- a/include/swift/AST/Initializer.h
+++ b/include/swift/AST/Initializer.h
@@ -99,6 +99,11 @@
 
   unsigned getBindingIndex() const { return SpareBits; }
 
+  /// If this initializes a single @lazy variable, return it.
+  VarDecl *getInitializedLazyVar() const;
+
+  /// If this initializes a single @lazy variable, lazily create a self
+  /// declaration for it to refer to.
   ParamDecl *getImplicitSelfDecl();
 
   static bool classof(const DeclContext *DC) {
diff --git a/include/swift/AST/LazyResolver.h b/include/swift/AST/LazyResolver.h
index a630968..560b9c5 100644
--- a/include/swift/AST/LazyResolver.h
+++ b/include/swift/AST/LazyResolver.h
@@ -71,17 +71,6 @@
   /// Resolve the "is Objective-C" bit for the given declaration.
   virtual void resolveIsObjC(ValueDecl *VD) = 0;
 
-  /// Retrieve the superclass of the given class.
-  virtual Type getSuperclass(const ClassDecl *classDecl) = 0;
-
-  /// Resolve the raw type of the given enum.
-  virtual Type getRawType(EnumDecl *enumDecl) = 0;
-
-  /// Get a specific inherited type from the given declaration.
-  virtual Type getInheritedType(
-                        llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
-                        unsigned index) = 0;
-
   /// Resolve the trailing where clause of the given protocol in-place.
   virtual void resolveTrailingWhereClause(ProtocolDecl *proto) = 0;
 
diff --git a/include/swift/AST/SimpleRequest.h b/include/swift/AST/SimpleRequest.h
index cf41659..4b483b1 100644
--- a/include/swift/AST/SimpleRequest.h
+++ b/include/swift/AST/SimpleRequest.h
@@ -56,7 +56,7 @@
 /// important one takes an evaluator and the input values, then computes the
 /// final result:
 /// \code
-///   Output operator()(Evaluator &evaluator, Inputs...) const;
+///   Output evaluate(Evaluator &evaluator, Inputs...) const;
 /// \endcode
 ///
 /// The \c Derived class will also need to implement an operation to break a
@@ -105,8 +105,8 @@
   template<size_t ...Indices>
   Output callDerived(Evaluator &evaluator,
                      llvm::index_sequence<Indices...>) const {
-    static_assert(sizeof...(Indices) > 0, "Subclass must define operator()");
-    return asDerived()(evaluator, std::get<Indices>(storage)...);
+    static_assert(sizeof...(Indices) > 0, "Subclass must define evaluate()");
+    return asDerived().evaluate(evaluator, std::get<Indices>(storage)...);
   }
 
   template<size_t ...Indices>
@@ -130,8 +130,11 @@
   explicit SimpleRequest(const Inputs& ...inputs)
     : storage(inputs...) { }
 
-  OutputType operator()(Evaluator &evaluator) const {
-    return callDerived(evaluator, llvm::index_sequence_for<Inputs...>());
+  /// Request evaluation function that will be registered with the evaluator.
+  static OutputType evaluateRequest(const Derived &request,
+                                    Evaluator &evaluator) {
+    return request.callDerived(evaluator,
+                               llvm::index_sequence_for<Inputs...>());
   }
 
   void diagnoseCycle(DiagnosticEngine &diags) const {
diff --git a/include/swift/AST/StorageImpl.h b/include/swift/AST/StorageImpl.h
new file mode 100644
index 0000000..ee4097d
--- /dev/null
+++ b/include/swift/AST/StorageImpl.h
@@ -0,0 +1,362 @@
+//===--- StorageImpl.h - Storage declaration access impl --------*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines types for describing the implementation of an
+// AbstractStorageDecl.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_STORAGEIMPL_H
+#define SWIFT_STORAGEIMPL_H
+
+#include "swift/Basic/Range.h"
+
+namespace swift {
+
+// Note that the values of these enums line up with %select values in
+// diagnostics.
+enum class AccessorKind {
+#define ACCESSOR(ID) ID,
+#define LAST_ACCESSOR(ID) Last = ID
+#include "swift/AST/AccessorKinds.def"
+};
+
+const unsigned NumAccessorKinds = unsigned(AccessorKind::Last) + 1;
+
+static inline IntRange<AccessorKind> allAccessorKinds() {
+  return IntRange<AccessorKind>(AccessorKind(0),
+                                AccessorKind(NumAccessorKinds));
+}
+
+/// The safety semantics of this addressor.
+enum class AddressorKind : uint8_t {
+  /// \brief This is not an addressor.
+  NotAddressor,
+  /// \brief This is an unsafe addressor; it simply returns an address.
+  Unsafe,
+  /// \brief This is an owning addressor; it returns an AnyObject
+  /// which should be released when the caller is done with the object.
+  Owning,
+  /// \brief This is an owning addressor; it returns a Builtin.NativeObject
+  /// which should be released when the caller is done with the object.
+  NativeOwning,
+  /// \brief This is a pinning addressor; it returns a Builtin.NativeObject?
+  /// which should be unpinned when the caller is done with the object.
+  NativePinning,
+};
+
+/// Whether an access to storage is for reading, writing, or both.
+enum class AccessKind : uint8_t {
+  /// The access is just to read the current value.
+  Read,
+
+  /// The access is just to overwrite the current value.
+  Write,
+
+  /// The access may require either reading or writing the current value.
+  ReadWrite
+};
+
+/// Produce the aggregate access kind of the combination of two accesses.
+inline AccessKind combineAccessKinds(AccessKind a, AccessKind b) {
+  // If they're the same, use that; otherwise, all combinations combine
+  // ReadWrite.
+  return (a == b ? a : AccessKind::ReadWrite);
+}
+
+class AccessStrategy {
+public:
+  enum Kind : uint8_t {
+    /// The declaration is a VarDecl with its own physical storage; access
+    /// that storage directly.
+    Storage,
+
+    /// The decl is a VarDecl with storage defined by a property behavior;
+    /// this access may initialize or reassign the storage based on dataflow.
+    BehaviorStorage,
+
+    /// Directly call an accessor of some sort.  The strategy includes
+    /// an accessor kind.
+    DirectToAccessor,
+
+    /// Dispatch to an accessor of some sort.  The strategy includes an
+    /// accessor kind.
+    DispatchToAccessor,
+
+    /// The access is a ReadWrite access and should be implemented by
+    /// separately performing a Read into a temporary variable followed by
+    /// a Write access back into the storage.
+    MaterializeToTemporary,
+  };
+
+private:
+  Kind TheKind;
+  Kind FirstKind;
+  AccessorKind FirstAccessor;
+  Kind SecondKind;
+  AccessorKind SecondAccessor;
+
+  AccessStrategy(Kind kind)
+    : TheKind(kind) {
+    assert(kind == Storage || kind == BehaviorStorage);
+  }
+
+  AccessStrategy(Kind kind, AccessorKind accessor)
+    : TheKind(kind), FirstAccessor(accessor) {
+    // Generally used for one of the accessor strategies, but also used
+    // for constructing a first or second strategy.
+  }
+
+  AccessStrategy(AccessStrategy readStrategy, AccessStrategy writeStrategy)
+    : TheKind(MaterializeToTemporary),
+      FirstKind(readStrategy.TheKind),
+      FirstAccessor(readStrategy.FirstAccessor),
+      SecondKind(writeStrategy.TheKind),
+      SecondAccessor(writeStrategy.FirstAccessor) {
+    assert(readStrategy.TheKind != MaterializeToTemporary);
+    assert(writeStrategy.TheKind != MaterializeToTemporary);
+  }
+
+public:
+  static AccessStrategy getStorage() {
+    return { Storage };
+  }
+
+  static AccessStrategy getBehaviorStorage() {
+    return { BehaviorStorage };
+  }
+
+  static AccessStrategy getAccessor(AccessorKind accessor, bool dispatched) {
+    return { dispatched ? DispatchToAccessor : DirectToAccessor, accessor };
+  }
+
+  static AccessStrategy getMaterializeToTemporary(AccessStrategy read,
+                                                  AccessStrategy write) {
+    return { read, write };
+  }
+
+  Kind getKind() const { return TheKind; }
+
+  AccessorKind getAccessor() const {
+    assert(TheKind == DirectToAccessor || TheKind == DispatchToAccessor);
+    return FirstAccessor;
+  }
+
+  AccessStrategy getReadStrategy() const {
+    assert(TheKind == MaterializeToTemporary);
+    return { FirstKind, FirstAccessor };
+  }
+  AccessStrategy getWriteStrategy() const {
+    assert(TheKind == MaterializeToTemporary);
+    return { SecondKind, SecondAccessor };
+  }
+};
+
+/// How are read accesses implemented?
+enum class ReadImplKind {
+  /// There's storage.
+  Stored,
+
+  /// The superclass's read implementation is directly inherited.
+  Inherited,
+
+  /// There's a getter.
+  Get,
+
+  /// There's an immutable addressor.
+  Address,
+};
+enum { NumReadImplKindBits = 2 };
+
+StringRef getReadImplKindName(ReadImplKind kind);
+
+/// How are simple write accesses implemented?
+enum class WriteImplKind {
+  /// It's immutable.
+  Immutable,
+
+  /// There's storage.
+  Stored,
+
+  /// There are observers on top of the storage.
+  /// TODO: maybe add a StoredWithDidSet here and to ReadWriteImplKind?
+  StoredWithObservers,
+
+  /// There are observers on top of the superclass's write implementation.
+  InheritedWithObservers,
+
+  /// There's a setter.
+  Set,
+
+  /// There's a mutable addressor.
+  MutableAddress,
+};
+enum { NumWriteImplKindBits = 3 };
+
+StringRef getWriteImplKindName(WriteImplKind kind);
+
+/// How are read-write accesses implemented?
+enum class ReadWriteImplKind {
+  /// It's immutable.
+  Immutable,
+
+  /// There's storage.
+  Stored,
+
+  /// There's a materializeForSet.  (This is currently only used for opaque
+  /// declarations.)
+  MaterializeForSet,
+
+  /// There's a mutable addressor.
+  MutableAddress,
+
+  /// Do a read into a temporary and then a write back.
+  MaterializeToTemporary,
+};
+enum { NumReadWriteImplKindBits = 3 };
+
+StringRef getReadWriteImplKindName(ReadWriteImplKind kind);
+
+class StorageImplInfo {
+  using IntType = uint16_t;
+  static_assert(NumReadImplKindBits + NumWriteImplKindBits
+                  + NumReadWriteImplKindBits <= 16,
+                "bit count exceeds IntType range");
+  IntType Read : NumReadImplKindBits;
+  IntType Write : NumWriteImplKindBits;
+  IntType ReadWrite : NumReadWriteImplKindBits;
+
+public:
+  /// A convenience constructor for building immutable storage.
+  StorageImplInfo(ReadImplKind readImpl)
+    : StorageImplInfo(readImpl, WriteImplKind::Immutable,
+                      ReadWriteImplKind::Immutable) {}
+
+  /// The primary constructor.
+  StorageImplInfo(ReadImplKind readImpl,
+                  WriteImplKind writeImpl,
+                  ReadWriteImplKind readWriteImpl)
+    : Read(IntType(readImpl)),
+      Write(IntType(writeImpl)),
+      ReadWrite(IntType(readWriteImpl)) {
+#ifndef NDEBUG
+    assert((writeImpl == WriteImplKind::Immutable)
+             == (readWriteImpl == ReadWriteImplKind::Immutable) &&
+           "write and read-write disagree about immutability");
+
+    switch (writeImpl) {
+    case WriteImplKind::Immutable:
+      // No other consistency checks are required if the storage is immutable.
+      return;
+
+    case WriteImplKind::Stored:
+      assert(readImpl == ReadImplKind::Stored);
+      assert(readWriteImpl == ReadWriteImplKind::Stored);
+      return;
+
+    case WriteImplKind::StoredWithObservers:
+      assert(readImpl == ReadImplKind::Stored);
+      assert(readWriteImpl == ReadWriteImplKind::MaterializeToTemporary);
+      return;
+
+    case WriteImplKind::InheritedWithObservers:
+      assert(readImpl == ReadImplKind::Inherited);
+      assert(readWriteImpl == ReadWriteImplKind::MaterializeToTemporary);
+      return;
+
+    case WriteImplKind::Set:
+      assert(readImpl == ReadImplKind::Get);
+      assert(readWriteImpl == ReadWriteImplKind::MaterializeToTemporary ||
+             readWriteImpl == ReadWriteImplKind::MaterializeForSet);
+      return;
+
+    case WriteImplKind::MutableAddress:
+      assert(readImpl == ReadImplKind::Get ||
+             readImpl == ReadImplKind::Address);
+      assert(readWriteImpl == ReadWriteImplKind::MutableAddress);
+      return;
+    }
+    llvm_unreachable("bad write impl kind");
+#endif
+  }
+
+  static StorageImplInfo getSimpleStored(bool supportsMutation) {
+    return { ReadImplKind::Stored,
+             supportsMutation ? WriteImplKind::Stored
+                              : WriteImplKind::Immutable,
+             supportsMutation ? ReadWriteImplKind::Stored
+                              : ReadWriteImplKind::Immutable };
+  }
+
+  static StorageImplInfo getOpaque(bool supportsMutation) {
+    return (supportsMutation ? getMutableOpaque() : getImmutableOpaque());
+  }
+
+  /// Describe the implementation of a immutable property implemented opaquely.
+  static StorageImplInfo getImmutableOpaque() {
+    return { ReadImplKind::Get };
+  }
+
+  /// Describe the implementation of a mutable property implemented opaquely.
+  static StorageImplInfo getMutableOpaque() {
+    return { ReadImplKind::Get, WriteImplKind::Set,
+             ReadWriteImplKind::MaterializeForSet };
+  }
+
+  static StorageImplInfo getComputed(bool supportsMutation) {
+    return (supportsMutation ? getMutableComputed() : getImmutableComputed());
+  }
+
+  /// Describe the implementation of an immutable property implemented
+  /// with just a getter.
+  static StorageImplInfo getImmutableComputed() {
+    return { ReadImplKind::Get };
+  }
+
+  /// Describe the implementation of a mutable property implemented with
+  /// getter and setter.
+  static StorageImplInfo getMutableComputed() {
+    return { ReadImplKind::Get, WriteImplKind::Set,
+             ReadWriteImplKind::MaterializeToTemporary };
+  }
+
+  /// Does this implementation description require storage?
+  bool hasStorage() const {
+    return getReadImpl() == ReadImplKind::Stored;
+  }
+
+  /// Does this describe a simply-stored variable?
+  bool isSimpleStored() const {
+    return getReadImpl() == ReadImplKind::Stored &&
+           (getWriteImpl() == WriteImplKind::Stored ||
+            getWriteImpl() == WriteImplKind::Immutable);
+  }
+
+  /// Does this describe storage that supports mutation?
+  bool supportsMutation() const {
+    return getWriteImpl() != WriteImplKind::Immutable;
+  }
+
+  ReadImplKind getReadImpl() const {
+    return ReadImplKind(Read);
+  }
+  WriteImplKind getWriteImpl() const {
+    return WriteImplKind(Write);
+  }
+  ReadWriteImplKind getReadWriteImpl() const {
+    return ReadWriteImplKind(ReadWrite);
+  }
+};
+
+} // end namespace swift
+
+#endif
diff --git a/include/swift/Sema/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h
similarity index 86%
rename from include/swift/Sema/TypeCheckRequests.h
rename to include/swift/AST/TypeCheckRequests.h
index 2da1459..f2400b9 100644
--- a/include/swift/Sema/TypeCheckRequests.h
+++ b/include/swift/AST/TypeCheckRequests.h
@@ -46,15 +46,14 @@
 
 public:
   using SimpleRequest::SimpleRequest;
-  using SimpleRequest::operator();
 
 private:
   friend class SimpleRequest;
 
   // Evaluation.
-  Type operator()(Evaluator &evaluator,
-                  llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
-                  unsigned index) const;
+  Type evaluate(Evaluator &evaluator,
+                llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
+                unsigned index) const;
 
 public:
   // Cycle handling
@@ -73,16 +72,15 @@
     public SimpleRequest<SuperclassTypeRequest,
                          CacheKind::SeparatelyCached,
                          Type,
-                         ClassDecl *> {
+                         NominalTypeDecl *> {
 public:
   using SimpleRequest::SimpleRequest;
-  using SimpleRequest::operator();
 
 private:
   friend class SimpleRequest;
 
   // Evaluation.
-  Type operator()(Evaluator &evaluator, ClassDecl *classDecl) const;
+  Type evaluate(Evaluator &evaluator, NominalTypeDecl *classDecl) const;
 
 public:
   // Cycle handling
@@ -104,13 +102,12 @@
                          EnumDecl *> {
 public:
   using SimpleRequest::SimpleRequest;
-  using SimpleRequest::operator();
 
 private:
   friend class SimpleRequest;
 
   // Evaluation.
-  Type operator()(Evaluator &evaluator, EnumDecl *enumDecl) const;
+  Type evaluate(Evaluator &evaluator, EnumDecl *enumDecl) const;
 
 public:
   // Cycle handling
@@ -124,8 +121,11 @@
   void cacheResult(Type value) const;
 };
 
-#define SWIFT_TYPEID_ZONE 10
-#define SWIFT_TYPEID_HEADER "swift/Sema/TypeCheckerTypeIDZone.def"
+/// The zone number for the type checker.
+#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10
+
+#define SWIFT_TYPEID_ZONE SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE
+#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
 #include "swift/Basic/DefineTypeIDZone.h"
 
 // Set up reporting of evaluated requests.
@@ -135,7 +135,7 @@
                             const RequestType &request) {        \
   ++stats.getFrontendCounters().RequestType;                     \
 }
-#include "swift/Sema/TypeCheckerTypeIDZone.def"
+#include "swift/AST/TypeCheckerTypeIDZone.def"
 #undef SWIFT_TYPEID
 
 } // end namespace swift
diff --git a/include/swift/Sema/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def
similarity index 92%
rename from include/swift/Sema/TypeCheckerTypeIDZone.def
rename to include/swift/AST/TypeCheckerTypeIDZone.def
index f931845..44732e6 100644
--- a/include/swift/Sema/TypeCheckerTypeIDZone.def
+++ b/include/swift/AST/TypeCheckerTypeIDZone.def
@@ -1,4 +1,4 @@
-//===--- ArithmeticEvaluatorTypeIDZone.def - --------------------*- C++ -*-===//
+//===--- TypeCheckerTypeIDZone.def ------------------------------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/include/swift/Basic/DefineTypeIDZone.h b/include/swift/Basic/DefineTypeIDZone.h
index fe23539..734505b 100644
--- a/include/swift/Basic/DefineTypeIDZone.h
+++ b/include/swift/Basic/DefineTypeIDZone.h
@@ -46,15 +46,15 @@
 };
 
 // Second pass: create specializations of TypeID for these types.
-#define SWIFT_TYPEID_NAMED(Type, Name)                    \
-template<> struct TypeID<Type> {                          \
-  static const uint64_t value =                           \
-    formTypeID(SWIFT_TYPEID_ZONE,                         \
-               TypeIDZoneTypes<SWIFT_TYPEID_ZONE>::Name); \
-                                                          \
-  static llvm::StringRef getName() {                      \
-    return #Name;                                         \
-  }                                                       \
+#define SWIFT_TYPEID_NAMED(Type, Name)                       \
+template<> struct TypeID<Type> {                             \
+  static const uint8_t zoneID = SWIFT_TYPEID_ZONE;           \
+  static const uint8_t localID =                             \
+    TypeIDZoneTypes<SWIFT_TYPEID_ZONE>::Name;                \
+                                                             \
+  static const uint64_t value = formTypeID(zoneID, localID); \
+                                                             \
+  static llvm::StringRef getName() { return #Name; }         \
 };
 
 #define SWIFT_TYPEID_TEMPLATE1_NAMED(Template, Name, Param1, Arg1)    \
diff --git a/include/swift/Basic/Statistics.def b/include/swift/Basic/Statistics.def
index ad90a8a..1337cf3 100644
--- a/include/swift/Basic/Statistics.def
+++ b/include/swift/Basic/Statistics.def
@@ -197,7 +197,7 @@
 
 /// All type check requests go into the Sema area.
 #define SWIFT_TYPEID(NAME) FRONTEND_STATISTIC(Sema, NAME)
-#include "swift/Sema/TypeCheckerTypeIDZone.def"
+#include "swift/AST/TypeCheckerTypeIDZone.def"
 #undef SWIFT_TYPEID
 
 /// The next 10 statistics count 5 kinds of SIL entities present
diff --git a/include/swift/IDE/DigesterEnums.def b/include/swift/IDE/DigesterEnums.def
index bb0cfc9..ec3327d 100644
--- a/include/swift/IDE/DigesterEnums.def
+++ b/include/swift/IDE/DigesterEnums.def
@@ -172,6 +172,7 @@
 SPECIAL_CASE_ID(NSOpenGLGetVersion)
 SPECIAL_CASE_ID(ToIntMax)
 SPECIAL_CASE_ID(ToUIntMax)
+SPECIAL_CASE_ID(UIApplicationMain)
 
 #undef SPECIAL_CASE_ID
 #undef DIFF_ITEM_KEY_KIND_INT
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 3d5feef..b4cf170 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -889,7 +889,7 @@
                 TypeLoc elementTy, ParameterList *indices,
                 SmallVectorImpl<Decl *> &decls);
 
-    AbstractStorageDecl::StorageKindTy
+    StorageImplInfo
     classify(Parser &P, AbstractStorageDecl *storage, bool invalid,
              ParseDeclOptions flags, SourceLoc staticLoc,
              const DeclAttributes &attrs,
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index 2173e25..a87f538 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -1138,12 +1138,13 @@
   Demangle::NodePointer
   buildNominalTypeMangling(ContextDescriptorRef descriptor,
                            Demangle::NodeFactory &nodeFactory) {
-    std::vector<std::pair<Demangle::Node::Kind, std::string>>
+    std::vector<std::pair<Demangle::Node::Kind, Demangle::NodePointer>>
       nameComponents;
     ContextDescriptorRef parent = descriptor;
     
     while (parent) {
       std::string nodeName;
+      std::string relatedTag;
       Demangle::Node::Kind nodeKind;
       
       auto getTypeName = [&]() -> bool {
@@ -1151,7 +1152,16 @@
           reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
             (parent.getLocalBuffer());
         auto nameAddress = resolveRelativeField(parent, typeBuffer->Name);
-        return Reader->readString(RemoteAddress(nameAddress), nodeName);
+        if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
+          return false;
+        
+        if (typeBuffer->isSynthesizedRelatedEntity()) {
+          nameAddress += nodeName.size() + 1;
+          if (!Reader->readString(RemoteAddress(nameAddress), relatedTag))
+            return false;
+        }
+        
+        return true;
       };
       
       bool isTypeContext = false;
@@ -1210,8 +1220,17 @@
         else if (typeFlags.isCTypedef())
           nodeKind = Demangle::Node::Kind::TypeAlias;
       }
+      
+      auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
+                                             nodeName);
+      if (!relatedTag.empty()) {
+        auto relatedNode =
+          nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
+        relatedNode->addChild(nameNode, nodeFactory);
+        nameNode = relatedNode;
+      }
 
-      nameComponents.emplace_back(nodeKind, nodeName);
+      nameComponents.emplace_back(nodeKind, nameNode);
       
       parent = readParentContextDescriptor(parent);
     }
@@ -1224,13 +1243,11 @@
     auto moduleInfo = std::move(nameComponents.back());
     nameComponents.pop_back();
     auto demangling =
-      nodeFactory.createNode(Node::Kind::Module, moduleInfo.second);
+      nodeFactory.createNode(Node::Kind::Module, moduleInfo.second->getText());
     for (auto &component : reversed(nameComponents)) {
-      auto name = nodeFactory.createNode(Node::Kind::Identifier,
-                                         component.second);
       auto parent = nodeFactory.createNode(component.first);
       parent->addChild(demangling, nodeFactory);
-      parent->addChild(name, nodeFactory);
+      parent->addChild(component.second, nodeFactory);
       demangling = parent;
     }
     
diff --git a/include/swift/SIL/MemAccessUtils.h b/include/swift/SIL/MemAccessUtils.h
index 3cc5dca..d493cf7 100644
--- a/include/swift/SIL/MemAccessUtils.h
+++ b/include/swift/SIL/MemAccessUtils.h
@@ -357,7 +357,8 @@
 /// through any Nested access to find the original storage.
 ///
 /// This is identical to findAccessedStorage(), but never returns Nested
-/// storage.
+/// storage and may return invalid storage for nested access when the outer
+/// access has Unsafe enforcement.
 AccessedStorage findAccessedStorageNonNested(SILValue sourceAddr);
 
 /// Return true if the given address operand is used by a memory operation that
@@ -368,6 +369,8 @@
 /// Return true if the given address producer may be the source of a formal
 /// access (a read or write of a potentially aliased, user visible variable).
 ///
+/// `storage` must be a valid AccessedStorage object.
+///
 /// If this returns false, then the address can be safely accessed without
 /// a begin_access marker. To determine whether to emit begin_access:
 ///   storage = findAccessedStorage(address)
diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def
index 91c37b9..f75c361 100644
--- a/include/swift/SILOptimizer/PassManager/Passes.def
+++ b/include/swift/SILOptimizer/PassManager/Passes.def
@@ -58,6 +58,8 @@
      "Access Enforcement Optimization")
 PASS(AccessEnforcementSelection, "access-enforcement-selection",
      "Access Enforcement Selection")
+PASS(AccessEnforcementWMO, "access-enforcement-wmo",
+     "Access Enforcement Whole Module Optimization")
 PASS(AccessSummaryDumper, "access-summary-dump",
      "Dump Address Parameter Access Summary")
 PASS(AccessedStorageDumper, "accessed-storage-dump",
diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h
index 9f05f11..6a42f50 100644
--- a/include/swift/Sema/IDETypeChecking.h
+++ b/include/swift/Sema/IDETypeChecking.h
@@ -36,9 +36,7 @@
   class DeclName;
 
   /// \brief Typecheck a declaration parsed during code completion.
-  ///
-  /// \returns true on success, false on error.
-  bool typeCheckCompletionDecl(Decl *D);
+  void typeCheckCompletionDecl(Decl *D);
 
   /// \brief Check if T1 is convertible to T2.
   ///
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 8585e61..ff747b1 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -575,7 +575,9 @@
 
   /// Sets the accessors for \p storage based on \p rawStorageKind.
   void configureStorage(AbstractStorageDecl *storage,
-                        unsigned rawStorageKind,
+                        uint8_t rawReadImpl,
+                        uint8_t rawWriteImpl,
+                        uint8_t rawReadWriteImpl,
                         AccessorRecord &accessors);
 
 public:
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 108f1d5..9e194af 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
 /// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 422; // Last change: {strong_retain,copy}_unowned
+const uint16_t VERSION_MINOR = 425; // Last change: access impls
 
 using DeclIDField = BCFixed<31>;
 
@@ -112,13 +112,38 @@
 using FileSizeField = BCVBR<16>;
 using FileModTimeField = BCVBR<16>;
 
-enum class StorageKind : uint8_t {
-  Stored, StoredWithTrivialAccessors, StoredWithObservers,
-  InheritedWithObservers,
-  Computed, ComputedWithMutableAddress,
-  Addressed, AddressedWithTrivialAccessors, AddressedWithObservers,
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
+enum class ReadImplKind : uint8_t {
+  Stored = 0,
+  Get,
+  Inherited,
+  Address
 };
-using StorageKindField = BCFixed<4>;
+using ReadImplKindField = BCFixed<3>;
+
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
+enum class WriteImplKind : uint8_t {
+  Immutable = 0,
+  Stored,
+  StoredWithObservers,
+  InheritedWithObservers,
+  Set,
+  MutableAddress,
+};
+using WriteImplKindField = BCFixed<3>;
+
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
+enum class ReadWriteImplKind : uint8_t {
+  Immutable = 0,
+  Stored,
+  MaterializeForSet,
+  MutableAddress,
+  MaterializeToTemporary,
+};
+using ReadWriteImplKindField = BCFixed<3>;
 
 // These IDs must \em not be renumbered or reordered without incrementing
 // VERSION_MAJOR.
@@ -861,8 +886,9 @@
     IdentifierIDField,      // name
     DeclContextIDField,     // context decl
     BCFixed<1>,             // implicit flag
+    BCFixed<1>,             // isObjC
     GenericEnvironmentIDField, // generic environment
-    AccessLevelField, // access level
+    AccessLevelField,       // access level
     BCVBR<4>,               // number of conformances
     BCArray<TypeIDField>    // inherited types
     // Trailed by the generic parameters (if any), the members record, and
@@ -874,9 +900,10 @@
     IdentifierIDField,      // name
     DeclContextIDField,     // context decl
     BCFixed<1>,             // implicit flag
+    BCFixed<1>,             // isObjC
     GenericEnvironmentIDField, // generic environment
     TypeIDField,            // raw type
-    AccessLevelField, // access level
+    AccessLevelField,       // access level
     BCVBR<4>,               // number of conformances
     BCVBR<4>,               // number of inherited types
     BCArray<TypeIDField>    // inherited types, followed by dependency types
@@ -886,15 +913,15 @@
 
   using ClassLayout = BCRecordLayout<
     CLASS_DECL,
-    IdentifierIDField, // name
-    DeclContextIDField,// context decl
-    BCFixed<1>,        // implicit?
-    BCFixed<1>,        // explicitly objc?
-    BCFixed<1>,        // requires stored property initial values?
-    BCFixed<1>,        // inherits convenience initializers from its superclass?
+    IdentifierIDField,      // name
+    DeclContextIDField,     // context decl
+    BCFixed<1>,             // implicit?
+    BCFixed<1>,             // explicitly objc?
+    BCFixed<1>,             // requires stored property initial values?
+    BCFixed<1>,             // inherits convenience initializers from its superclass?
     GenericEnvironmentIDField, // generic environment
-    TypeIDField,       // superclass
-    AccessLevelField, // access level
+    TypeIDField,            // superclass
+    AccessLevelField,       // access level
     BCVBR<4>,               // number of conformances
     BCArray<TypeIDField>    // inherited types
     // Trailed by the generic parameters (if any), the members record, and
@@ -910,7 +937,8 @@
     BCFixed<1>,             // objc?
     BCFixed<1>,             // existential-type-supported?
     GenericEnvironmentIDField, // generic environment
-    AccessLevelField, // access level
+    TypeIDField,            // superclass
+    AccessLevelField,       // access level
     BCArray<DeclIDField>    // inherited types
     // Trailed by the generic parameters (if any), the members record, and
     // the default witness table record
@@ -957,7 +985,9 @@
     BCFixed<1>,   // HasNonPatternBindingInit?
     BCFixed<1>,   // is getter mutating?
     BCFixed<1>,   // is setter mutating?
-    StorageKindField,   // StorageKind
+    ReadImplKindField,   // read implementation
+    WriteImplKindField,   // write implementation
+    ReadWriteImplKindField,   // read-write implementation
     AccessorCountField, // number of accessors
     TypeIDField,  // interface type
     DeclIDField,  // overridden decl
@@ -981,7 +1011,7 @@
     BCFixed<1>,   // implicit?
     BCFixed<1>,   // is 'static' or 'class'?
     StaticSpellingKindField, // spelling of 'static' or 'class'
-    BCFixed<1>,   // explicitly objc?
+    BCFixed<1>,   // isObjC?
     SelfAccessKindField,   // self access kind
     BCFixed<1>,   // has dynamic self?
     BCFixed<1>,   // has forced static dispatch?
@@ -1010,7 +1040,7 @@
     BCFixed<1>,   // implicit?
     BCFixed<1>,   // is 'static' or 'class'?
     StaticSpellingKindField, // spelling of 'static' or 'class'
-    BCFixed<1>,   // explicitly objc?
+    BCFixed<1>,   // isObjC?
     SelfAccessKindField,   // self access kind
     BCFixed<1>,   // has dynamic self?
     BCFixed<1>,   // has forced static dispatch?
@@ -1094,7 +1124,9 @@
     BCFixed<1>,  // objc?
     BCFixed<1>,   // is getter mutating?
     BCFixed<1>,   // is setter mutating?
-    StorageKindField,   // StorageKind
+    ReadImplKindField,   // read implementation
+    WriteImplKindField,   // write implementation
+    ReadWriteImplKindField,   // read-write implementation
     AccessorCountField, // number of accessors
     GenericEnvironmentIDField, // generic environment
     TypeIDField, // interface type
diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h
index 1bb3d80..abe7243 100644
--- a/include/swift/Subsystems.h
+++ b/include/swift/Subsystems.h
@@ -46,6 +46,7 @@
   class DelayedParsingCallbacks;
   class DiagnosticConsumer;
   class DiagnosticEngine;
+  class Evaluator;
   class FileUnit;
   class GenericEnvironment;
   class GenericParamList;
@@ -342,6 +343,13 @@
     struct Implementation;
     Implementation &Impl;
   };
+
+  /// Register the type checker's request functions with the evaluator.
+  ///
+  /// Clients that form an ASTContext and will perform any semantic
+  /// queries should call this function after forming the ASTContext.
+  void registerTypeCheckerRequestFunctions(Evaluator &evaluator);
+
 } // end namespace swift
 
 #endif // SWIFT_SUBSYSTEMS_H
diff --git a/include/swift/Syntax/RawSyntax.h b/include/swift/Syntax/RawSyntax.h
index 9961d5b..c8c8bf6 100644
--- a/include/swift/Syntax/RawSyntax.h
+++ b/include/swift/Syntax/RawSyntax.h
@@ -48,17 +48,17 @@
 
 #ifndef NDEBUG
 #define syntax_assert_child_kind(Raw, Cursor, ExpectedKind)                    \
-  ({                                                                           \
+  do {                                                                         \
     if (auto &__Child = Raw->getChild(Cursor))                                 \
       assert(__Child->getKind() == ExpectedKind);                              \
-  })
+  } while (false)
 #else
-#define syntax_assert_child_kind(Raw, Cursor, ExpectedKind) ({});
+#define syntax_assert_child_kind(Raw, Cursor, ExpectedKind)
 #endif
 
 #ifndef NDEBUG
 #define syntax_assert_child_token(Raw, CursorName, ...)                        \
-  ({                                                                           \
+  do {                                                                         \
     bool __Found = false;                                                      \
     if (auto &__Token = Raw->getChild(Cursor::CursorName)) {                   \
       assert(__Token->isToken());                                              \
@@ -73,14 +73,14 @@
                           ", expected one of {" #__VA_ARGS__ "}");             \
       }                                                                        \
     }                                                                          \
-  })
+  } while (false)
 #else
-#define syntax_assert_child_token(Raw, CursorName, ...) ({});
+#define syntax_assert_child_token(Raw, CursorName, ...)
 #endif
 
 #ifndef NDEBUG
 #define syntax_assert_child_token_text(Raw, CursorName, TokenKind, ...)        \
-  ({                                                                           \
+  do {                                                                         \
     bool __Found = false;                                                      \
     if (auto &__Child = Raw->getChild(Cursor::CursorName)) {                   \
       assert(__Child->isToken());                                              \
@@ -96,19 +96,19 @@
                           ", expected one of {" #__VA_ARGS__ "}");             \
       }                                                                        \
     }                                                                          \
-  })
+  } while (false)
 #else
-#define syntax_assert_child_token_text(Raw, CursorName, TokenKind, ...) ({});
+#define syntax_assert_child_token_text(Raw, CursorName, TokenKind, ...)
 #endif
 
 #ifndef NDEBUG
 #define syntax_assert_token_is(Tok, Kind, Text)                                \
-  ({                                                                           \
+  do {                                                                         \
     assert(Tok.getTokenKind() == Kind);                                        \
     assert(Tok.getText() == Text);                                             \
-  })
+  } while (false)
 #else
-#define syntax_assert_token_is(Tok, Kind, Text) ({});
+#define syntax_assert_token_is(Tok, Kind, Text)
 #endif
 
 namespace swift {
@@ -222,7 +222,7 @@
   friend TrailingObjects;
 
   union {
-    uint64_t Clear;
+    uint64_t OpaqueBits;
     struct {
       /// The kind of syntax this node represents.
       unsigned Kind : bitmax(NumSyntaxKindBits, 8);
@@ -231,7 +231,7 @@
       /// Whether this piece of syntax was constructed with manually managed
       /// memory.
       unsigned ManualMemory : 1;
-    };
+    } Common;
     enum { NumRawSyntaxBits = bitmax(NumSyntaxKindBits, 8) + 1 + 1 };
 
     // For "layout" nodes.
@@ -243,7 +243,7 @@
       unsigned NumChildren : 32;
       /// Number of bytes this node takes up spelled out in the source code
       unsigned TextLength : 32;
-    };
+    } Layout;
 
     // For "token" nodes.
     struct {
@@ -256,17 +256,19 @@
       unsigned NumLeadingTrivia : 16;
       /// Number of trailing trivia pieces.
       unsigned NumTrailingTrivia : 16;
-    };
+    } Token;
   } Bits;
 
   size_t numTrailingObjects(OverloadToken<RC<RawSyntax>>) const {
-    return isToken() ? 0 : Bits.NumChildren;
+    return isToken() ? 0 : Bits.Layout.NumChildren;
   }
   size_t numTrailingObjects(OverloadToken<OwnedString>) const {
     return isToken() ? 1 : 0;
   }
   size_t numTrailingObjects(OverloadToken<TriviaPiece>) const {
-    return isToken() ? Bits.NumLeadingTrivia + Bits.NumTrailingTrivia : 0;
+    return isToken()
+             ? Bits.Token.NumLeadingTrivia + Bits.Token.NumTrailingTrivia
+             : 0;
   }
 
   /// Constructor for creating layout nodes
@@ -282,12 +284,12 @@
   ~RawSyntax();
 
   void Release() const {
-    if (Bits.ManualMemory)
+    if (Bits.Common.ManualMemory)
       return;
     return llvm::ThreadSafeRefCountedBase<RawSyntax>::Release();
   }
   void Retain() const {
-    if (Bits.ManualMemory)
+    if (Bits.Common.ManualMemory)
       return;
     return llvm::ThreadSafeRefCountedBase<RawSyntax>::Retain();
   }
@@ -326,10 +328,12 @@
   /// @}
 
   SourcePresence getPresence() const {
-    return static_cast<SourcePresence>(Bits.Presence);
+    return static_cast<SourcePresence>(Bits.Common.Presence);
   }
 
-  SyntaxKind getKind() const { return static_cast<SyntaxKind>(Bits.Kind); }
+  SyntaxKind getKind() const {
+    return static_cast<SyntaxKind>(Bits.Common.Kind);
+  }
 
   /// Returns true if the node is "missing" in the source (i.e. it was
   /// expected (or optional) but not written.
@@ -365,7 +369,7 @@
   /// Get the kind of the token.
   tok getTokenKind() const {
     assert(isToken());
-    return static_cast<tok>(Bits.TokenKind);
+    return static_cast<tok>(Bits.Token.TokenKind);
   }
 
   /// Return the text of the token.
@@ -377,13 +381,13 @@
   /// Return the leading trivia list of the token.
   ArrayRef<TriviaPiece> getLeadingTrivia() const {
     assert(isToken());
-    return {getTrailingObjects<TriviaPiece>(), Bits.NumLeadingTrivia};
+    return {getTrailingObjects<TriviaPiece>(), Bits.Token.NumLeadingTrivia};
   }
   /// Return the trailing trivia list of the token.
   ArrayRef<TriviaPiece> getTrailingTrivia() const {
     assert(isToken());
-    return {getTrailingObjects<TriviaPiece>() + Bits.NumLeadingTrivia,
-            Bits.NumTrailingTrivia};
+    return {getTrailingObjects<TriviaPiece>() + Bits.Token.NumLeadingTrivia,
+            Bits.Token.NumTrailingTrivia};
   }
 
   /// Return \c true if this is the given kind of token.
@@ -427,13 +431,13 @@
   ArrayRef<RC<RawSyntax>> getLayout() const {
     if (isToken())
       return {};
-    return {getTrailingObjects<RC<RawSyntax>>(), Bits.NumChildren};
+    return {getTrailingObjects<RC<RawSyntax>>(), Bits.Layout.NumChildren};
   }
 
   size_t getNumChildren() const {
     if (isToken())
       return 0;
-    return Bits.NumChildren;
+    return Bits.Layout.NumChildren;
   }
 
   /// Get a child based on a particular node's "Cursor", indicating
@@ -454,7 +458,7 @@
       accumulateAbsolutePosition(Pos);
       return Pos.getOffset();
     } else {
-      return Bits.TextLength;
+      return Bits.Layout.TextLength;
     }
   }
 
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index a27148e..37166e6 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -213,31 +213,55 @@
 
   llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
 }
-static StringRef
-getAbstractStorageDeclKindString(AbstractStorageDecl::StorageKindTy value) {
-  switch (value) {
-  case AbstractStorageDecl::Stored:
-    return "stored";
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
-    return "stored_with_trivial_accessors";
-  case AbstractStorageDecl::StoredWithObservers:
-    return "stored_with_observers";
-  case AbstractStorageDecl::InheritedWithObservers:
-    return "inherited_with_observers";
-  case AbstractStorageDecl::Addressed:
-    return "addressed";
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-    return "addressed_with_trivial_accessors";
-  case AbstractStorageDecl::AddressedWithObservers:
-    return "addressed_with_observers";
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-    return "computed_with_mutable_address";
-  case AbstractStorageDecl::Computed:
-    return "computed";
-  }
 
-  llvm_unreachable("Unhandled AbstractStorageDecl in switch.");
+StringRef swift::getReadImplKindName(ReadImplKind kind) {
+  switch (kind) {
+  case ReadImplKind::Stored:
+    return "stored";
+  case ReadImplKind::Inherited:
+    return "inherited";
+  case ReadImplKind::Get:
+    return "getter";
+  case ReadImplKind::Address:
+    return "addressor";
+  }
+  llvm_unreachable("bad kind");
 }
+
+StringRef swift::getWriteImplKindName(WriteImplKind kind) {
+  switch (kind) {
+  case WriteImplKind::Immutable:
+    return "immutable";
+  case WriteImplKind::Stored:
+    return "stored";
+  case WriteImplKind::StoredWithObservers:
+    return "stored_with_observers";
+  case WriteImplKind::InheritedWithObservers:
+    return "inherited_with_observers";
+  case WriteImplKind::Set:
+    return "setter";
+  case WriteImplKind::MutableAddress:
+    return "mutable_addressor";
+  }
+  llvm_unreachable("bad kind");
+}
+
+StringRef swift::getReadWriteImplKindName(ReadWriteImplKind kind) {
+  switch (kind) {
+  case ReadWriteImplKind::Immutable:
+    return "immutable";
+  case ReadWriteImplKind::Stored:
+    return "stored";
+  case ReadWriteImplKind::MaterializeForSet:
+    return "materialize_for_set";
+  case ReadWriteImplKind::MutableAddress:
+    return "mutable_addressor";
+  case ReadWriteImplKind::MaterializeToTemporary:
+    return "materialize_to_temporary";
+  }
+  llvm_unreachable("bad kind");
+}
+
 static StringRef getImportKindString(ImportKind value) {
   switch (value) {
   case ImportKind::Module: return "module";
@@ -339,7 +363,7 @@
   switch (value) {
     case AccessSemantics::Ordinary: return "ordinary";
     case AccessSemantics::DirectToStorage: return "direct_to_storage";
-    case AccessSemantics::DirectToAccessor: return "direct_to_accessor";
+    case AccessSemantics::DirectToImplementation: return "direct_to_impl";
     case AccessSemantics::BehaviorInitialization: return "behavior_init";
   }
 
@@ -794,48 +818,35 @@
         PrintWithColorRAII(OS, DeclModifierColor) << " let";
       if (VD->hasNonPatternBindingInit())
         PrintWithColorRAII(OS, DeclModifierColor) << " non_pattern_init";
-      PrintWithColorRAII(OS, DeclModifierColor)
-        << " storage_kind="
-        << getAbstractStorageDeclKindString(VD->getStorageKind());
       if (VD->getAttrs().hasAttribute<LazyAttr>())
         PrintWithColorRAII(OS, DeclModifierColor) << " lazy";
-
+      printStorageImpl(VD);
       printAccessors(VD);
       PrintWithColorRAII(OS, ParenthesisColor) << ')';
     }
 
+    void printStorageImpl(AbstractStorageDecl *D) {
+      auto impl = D->getImplInfo();
+      PrintWithColorRAII(OS, DeclModifierColor)
+        << " readImpl="
+        << getReadImplKindName(impl.getReadImpl());
+      if (!impl.supportsMutation()) {
+        PrintWithColorRAII(OS, DeclModifierColor)
+          << " immutable";
+      } else {
+        PrintWithColorRAII(OS, DeclModifierColor)
+          << " writeImpl="
+          << getWriteImplKindName(impl.getWriteImpl());
+        PrintWithColorRAII(OS, DeclModifierColor)
+          << " readWriteImpl="
+          << getReadWriteImplKindName(impl.getReadWriteImpl());
+      }
+    }
+
     void printAccessors(AbstractStorageDecl *D) {
-      if (FuncDecl *Get = D->getGetter()) {
+      for (auto accessor : D->getAllAccessors()) {
         OS << "\n";
-        printRec(Get);
-      }
-      if (FuncDecl *Set = D->getSetter()) {
-        OS << "\n";
-        printRec(Set);
-      }
-      if (FuncDecl *MaterializeForSet = D->getMaterializeForSetFunc()) {
-        OS << "\n";
-        printRec(MaterializeForSet);
-      }
-      if (D->hasObservers()) {
-        if (FuncDecl *WillSet = D->getWillSetFunc()) {
-          OS << "\n";
-          printRec(WillSet);
-        }
-        if (FuncDecl *DidSet = D->getDidSetFunc()) {
-          OS << "\n";
-          printRec(DidSet);
-        }
-      }
-      if (D->hasAddressors()) {
-        if (FuncDecl *addressor = D->getAddressor()) {
-          OS << "\n";
-          printRec(addressor);
-        }
-        if (FuncDecl *mutableAddressor = D->getMutableAddressor()) {
-          OS << "\n";
-          printRec(mutableAddressor);
-        }
+        printRec(accessor);
       }
     }
 
@@ -907,8 +918,7 @@
 
     void visitSubscriptDecl(SubscriptDecl *SD) {
       printCommon(SD, "subscript_decl");
-      OS << " storage_kind="
-         << getAbstractStorageDeclKindString(SD->getStorageKind());
+      printStorageImpl(SD);
       printAccessors(SD);
       PrintWithColorRAII(OS, ParenthesisColor) << ')';
     }
@@ -2514,6 +2524,11 @@
     printSemanticExpr(E->getSemanticExpr());
     PrintWithColorRAII(OS, ParenthesisColor) << ')';
   }
+  void visitLazyInitializerExpr(LazyInitializerExpr *E) {
+    printCommon(E, "lazy_initializer_expr") << '\n';
+    printRec(E->getSubExpr());
+    PrintWithColorRAII(OS, ParenthesisColor) << ')';
+  }
   void visitObjCSelectorExpr(ObjCSelectorExpr *E) {
     printCommon(E, "objc_selector_expr");
     OS << " kind=" << getObjCSelectorExprKindString(E->getSelectorKind());
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 749a60f..7429005 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -740,6 +740,16 @@
     Options.ExcludeAttrList.push_back(DAK_Final);
   }
 
+  // If the declaration is implicitly @objc, print the attribute now.
+  if (Options.PrintImplicitAttrs) {
+    if (auto VD = dyn_cast<ValueDecl>(D)) {
+      if (VD->isObjC() && !VD->getAttrs().hasAttribute<ObjCAttr>()) {
+        Printer.printAttrName("@objc");
+        Printer << " ";
+      }
+    }
+  }
+
   D->getAttrs().print(Printer, Options, D);
 
   Options.ExcludeAttrList.resize(originalExcludeAttrCount);
@@ -1400,57 +1410,54 @@
   llvm_unreachable("bad addressor kind");
 }
 
-static StringRef getAddressorLabel(AccessorDecl *addressor) {
-  switch (addressor->getAddressorKind()) {
-  case AddressorKind::NotAddressor:
-    llvm_unreachable("addressor claims not to be an addressor");
-  case AddressorKind::Unsafe:
-    return "unsafeAddress";
-  case AddressorKind::Owning:
-    return "addressWithOwner";
-  case AddressorKind::NativeOwning:
-    return "addressWithNativeOwner";
-  case AddressorKind::NativePinning:
-    return "addressWithPinnedNativeOwner";
-  }
-  llvm_unreachable("bad addressor kind");
-}
+static StringRef getAccessorLabel(AccessorDecl *accessor) {
+  switch (accessor->getAccessorKind()) {
+#define SINGLETON_ACCESSOR(ID, KEYWORD) \
+  case AccessorKind::ID: return #KEYWORD;
+#define ACCESSOR(ID)
+#include "swift/AST/AccessorKinds.def"
 
-static StringRef getMutableAddressorLabel(AccessorDecl *addressor) {
-  switch (addressor->getAddressorKind()) {
-  case AddressorKind::NotAddressor:
-    llvm_unreachable("addressor claims not to be an addressor");
-  case AddressorKind::Unsafe:
-    return "unsafeMutableAddress";
-  case AddressorKind::Owning:
-    return "mutableAddressWithOwner";
-  case AddressorKind::NativeOwning:
-    return "mutableAddressWithNativeOwner";
-  case AddressorKind::NativePinning:
-    return "mutableAddressWithPinnedNativeOwner";
+  case AccessorKind::Address:
+    switch (accessor->getAddressorKind()) {
+    case AddressorKind::NotAddressor: llvm_unreachable("bad combination");
+#define IMMUTABLE_ADDRESSOR(ID, KEYWORD) \
+    case AddressorKind::ID: return #KEYWORD;
+#define ACCESSOR(ID)
+#include "swift/AST/AccessorKinds.def"
+    }
+    llvm_unreachable("bad addressor kind");
+
+  case AccessorKind::MutableAddress:
+    switch (accessor->getAddressorKind()) {
+    case AddressorKind::NotAddressor: llvm_unreachable("bad combination");
+#define MUTABLE_ADDRESSOR(ID, KEYWORD) \
+    case AddressorKind::ID: return #KEYWORD;
+#define ACCESSOR(ID)
+#include "swift/AST/AccessorKinds.def"
+    }
+    llvm_unreachable("bad addressor kind");
   }
-  llvm_unreachable("bad addressor kind");
+  llvm_unreachable("bad accessor kind");
 }
 
 void PrintAST::printAccessors(AbstractStorageDecl *ASD) {
   if (isa<VarDecl>(ASD) && !Options.PrintPropertyAccessors)
     return;
 
-  auto storageKind = ASD->getStorageKind();
-
   // Never print anything for stored properties.
-  if (storageKind == AbstractStorageDecl::Stored)
+  if (ASD->getAllAccessors().empty())
     return;
 
+  auto impl = ASD->getImplInfo();
+
   // Treat StoredWithTrivialAccessors the same as Stored unless
   // we're printing for SIL, in which case we want to distinguish it
   // from a pure stored property.
-  if (storageKind == AbstractStorageDecl::StoredWithTrivialAccessors) {
-    if (!Options.PrintForSIL) return;
-
-    // Don't print an accessor for a let; the parser can't handle it.
-    if (isa<VarDecl>(ASD) && cast<VarDecl>(ASD)->isLet())
-      return;
+  if (impl.isSimpleStored()) {
+    if (Options.PrintForSIL) {
+      Printer << " { get " << (impl.supportsMutation() ? "set }" : "}");
+    }
+    return;
   }
 
   // We sometimes want to print the accessors abstractly
@@ -1496,22 +1503,23 @@
 
   // Honor !Options.PrintGetSetOnRWProperties in the only remaining
   // case where we could end up printing { get set }.
-  if (storageKind == AbstractStorageDecl::StoredWithTrivialAccessors ||
-      storageKind == AbstractStorageDecl::Computed) {
-    if (!Options.PrintGetSetOnRWProperties &&
-        !Options.FunctionDefinitions &&
-        ASD->getSetter() &&
-        !ASD->getGetter()->isMutating() &&
-        !ASD->getSetter()->isExplicitNonMutating()) {
-      return;
-    }
+  if ((impl.getReadImpl() == ReadImplKind::Stored ||
+       impl.getReadImpl() == ReadImplKind::Get) &&
+      (impl.getWriteImpl() == WriteImplKind::Stored ||
+       impl.getWriteImpl() == WriteImplKind::Set) &&
+      (impl.getReadWriteImpl() == ReadWriteImplKind::MaterializeToTemporary) &&
+      !Options.PrintGetSetOnRWProperties &&
+      !Options.FunctionDefinitions &&
+      !ASD->getGetter()->isMutating() &&
+      !ASD->getSetter()->isExplicitNonMutating()) {
+    return;
   }
 
   // Otherwise, print all the concrete defining accessors.
 
   bool PrintAccessorBody = Options.FunctionDefinitions || Options.FunctionBody;
 
-  auto PrintAccessor = [&](AccessorDecl *Accessor, StringRef Label) {
+  auto PrintAccessor = [&](AccessorDecl *Accessor) {
     if (!Accessor)
       return;
     if (!PrintAccessorBody) {
@@ -1527,7 +1535,7 @@
         }
       }
       Printer << " ";
-      Printer.printKeyword(Label); // Contextual keyword get, set, ...
+      Printer.printKeyword(getAccessorLabel(Accessor));
     } else {
       Printer.printNewline();
       IndentRAII IndentMore(*this);
@@ -1536,59 +1544,49 @@
     }
   };
 
-  auto PrintAddressor = [&](AccessorDecl *accessor) {
-    if (!accessor) return;
-    PrintAccessor(accessor, getAddressorLabel(accessor));
-  };
-
-  auto PrintMutableAddressor = [&](AccessorDecl *accessor) {
-    if (!accessor) return;
-    PrintAccessor(accessor, getMutableAddressorLabel(accessor));
-  };
-
   Printer << " {";
-  switch (storageKind) {
-  case AbstractStorageDecl::Stored:
-    llvm_unreachable("filtered out above!");
-
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
-  case AbstractStorageDecl::Computed:
-    if (ASD->getGetter() && !ASD->getSetter() && PrintAccessorBody &&
-          !Options.FunctionDefinitions) {
-      // Omit the 'get' keyword. Directly print getter
-      if (auto BodyFunc = Options.FunctionBody) {
-        Printer.printNewline();
-        IndentRAII IndentBody(*this);
-        indent();
-        Printer << BodyFunc(ASD->getGetter());
-      }
-    } else {
-      PrintAccessor(ASD->getGetter(), "get");
-      PrintAccessor(ASD->getSetter(), "set");
+  if (impl.getReadImpl() == ReadImplKind::Get && ASD->getGetter() &&
+      !ASD->supportsMutation() &&
+      PrintAccessorBody && !Options.FunctionDefinitions) {
+    // Omit the 'get' keyword. Directly print getter
+    if (auto BodyFunc = Options.FunctionBody) {
+      Printer.printNewline();
+      IndentRAII IndentBody(*this);
+      indent();
+      Printer << BodyFunc(ASD->getGetter());
+    }    
+  } else {
+    switch (impl.getReadImpl()) {
+    case ReadImplKind::Stored:
+    case ReadImplKind::Inherited:
+      break;
+    case ReadImplKind::Get:
+      PrintAccessor(ASD->getGetter());
+      break;
+    case ReadImplKind::Address:
+      PrintAccessor(ASD->getAddressor());
+      break;
     }
-    break;
-
-  case AbstractStorageDecl::StoredWithObservers:
-  case AbstractStorageDecl::InheritedWithObservers:
-    PrintAccessor(ASD->getWillSetFunc(), "willSet");
-    PrintAccessor(ASD->getDidSetFunc(), "didSet");
-    break;
-
-  case AbstractStorageDecl::Addressed:
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-  case AbstractStorageDecl::AddressedWithObservers:
-    PrintAddressor(ASD->getAddressor());
-    PrintMutableAddressor(ASD->getMutableAddressor());
-    if (ASD->hasObservers()) {
-      PrintAccessor(ASD->getWillSetFunc(), "willSet");
-      PrintAccessor(ASD->getDidSetFunc(), "didSet");
+    switch (impl.getWriteImpl()) {
+    case WriteImplKind::Immutable:
+      break;
+    case WriteImplKind::Stored:
+      llvm_unreachable("simply-stored variable should have been filtered out");
+    case WriteImplKind::StoredWithObservers:
+    case WriteImplKind::InheritedWithObservers:
+      PrintAccessor(ASD->getWillSetFunc());
+      PrintAccessor(ASD->getDidSetFunc());
+      break;
+    case WriteImplKind::Set:
+      PrintAccessor(ASD->getSetter());
+      // FIXME: ReadWriteImplKind::Modify
+      break;
+    case WriteImplKind::MutableAddress:
+      PrintAccessor(ASD->getMutableAddressor());
+      PrintAccessor(ASD->getWillSetFunc());
+      PrintAccessor(ASD->getDidSetFunc());
+      break;
     }
-    break;
-
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-    PrintAccessor(ASD->getGetter(), "get");
-    PrintMutableAddressor(ASD->getMutableAddressor());
-    break;
   }
   if (PrintAccessorBody) {
     Printer.printNewline();
@@ -2403,22 +2401,12 @@
   switch (auto kind = decl->getAccessorKind()) {
   case AccessorKind::Get:
   case AccessorKind::Address:
-    recordDeclLoc(decl,
-      [&]{
-        Printer << (kind == AccessorKind::Get
-                      ? "get" : getAddressorLabel(decl));
-      });
-    Printer << " {";
-    break;
   case AccessorKind::DidSet:
   case AccessorKind::MaterializeForSet:
   case AccessorKind::MutableAddress:
     recordDeclLoc(decl,
       [&]{
-        Printer << (kind == AccessorKind::DidSet ? "didSet" :
-                    kind == AccessorKind::MaterializeForSet
-                      ? "materializeForSet"
-                      : getMutableAddressorLabel(decl));
+        Printer << getAccessorLabel(decl);
       });
     Printer << " {";
     break;
@@ -2426,7 +2414,7 @@
   case AccessorKind::WillSet:
     recordDeclLoc(decl,
       [&]{
-        Printer << (decl->isSetter() ? "set" : "willSet");
+        Printer << getAccessorLabel(decl);
 
         auto params = decl->getParameterLists().back();
         if (params->size() != 0 && !params->get(0)->isImplicit()) {
@@ -3018,20 +3006,18 @@
     // Stored variables in Swift source will be picked up by the
     // PatternBindingDecl.
     if (auto *VD = dyn_cast<VarDecl>(this)) {
-      if (!VD->hasClangNode() && VD->hasStorage() &&
-          VD->getStorageKind() != VarDecl::StoredWithObservers)
+      if (!VD->hasClangNode() && VD->getImplInfo().isSimpleStored())
         return false;
     }
 
-    // Skip pattern bindings that consist of just one computed variable.
+    // Skip pattern bindings that consist of just one variable with
+    // interesting accessors.
     if (auto pbd = dyn_cast<PatternBindingDecl>(this)) {
       if (pbd->getPatternList().size() == 1) {
         auto pattern =
           pbd->getPatternList()[0].getPattern()->getSemanticsProvidingPattern();
         if (auto named = dyn_cast<NamedPattern>(pattern)) {
-          auto StorageKind = named->getDecl()->getStorageKind();
-          if (StorageKind == VarDecl::Computed ||
-              StorageKind == VarDecl::StoredWithObservers)
+          if (!named->getDecl()->getImplInfo().isSimpleStored())
             return false;
         }
       }
diff --git a/lib/AST/ASTScope.cpp b/lib/AST/ASTScope.cpp
index 50e589d..b13f137 100644
--- a/lib/AST/ASTScope.cpp
+++ b/lib/AST/ASTScope.cpp
@@ -171,22 +171,7 @@
 
 /// Determine whether the given abstract storage declaration has accessors.
 static bool hasAccessors(AbstractStorageDecl *asd) {
-  switch (asd->getStorageKind()) {
-  case AbstractStorageDecl::Addressed:
-  case AbstractStorageDecl::AddressedWithObservers:
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-  case AbstractStorageDecl::Computed:
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-  case AbstractStorageDecl::InheritedWithObservers:
-  case AbstractStorageDecl::StoredWithObservers:
-    return asd->getBracesRange().isValid();
-
-  case AbstractStorageDecl::Stored:
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
-    return false;
-  }
-
-  llvm_unreachable("Unhandled ContinuationKind in switch.");
+  return asd->getBracesRange().isValid();
 }
 
 void ASTScope::expand() const {
@@ -561,39 +546,12 @@
 
   case ASTScopeKind::Accessors: {
     // Add children for all of the explicitly-written accessors.
-    SmallVector<ASTScope *, 4> accessors;
-    auto addAccessor = [&](FuncDecl *accessor) {
-      if (!accessor) return;
-      if (accessor->isImplicit()) return;
-      if (accessor->getStartLoc().isInvalid()) return;
-
+    for (auto accessor : abstractStorageDecl->getAllAccessors()) {
+      if (accessor->isImplicit() || accessor->getStartLoc().isInvalid())
+        continue;
       if (auto accessorChild = createIfNeeded(this, accessor))
-        accessors.push_back(accessorChild);
-    };
-
-    addAccessor(abstractStorageDecl->getGetter());
-    addAccessor(abstractStorageDecl->getSetter());
-    addAccessor(abstractStorageDecl->getMaterializeForSetFunc());
-    if (abstractStorageDecl->hasAddressors()) {
-      addAccessor(abstractStorageDecl->getAddressor());
-      addAccessor(abstractStorageDecl->getMutableAddressor());
+        addChild(accessorChild);
     }
-    if (abstractStorageDecl->hasObservers()) {
-      addAccessor(abstractStorageDecl->getDidSetFunc());
-      addAccessor(abstractStorageDecl->getWillSetFunc());
-    }
-
-    // Sort the accessors, because they can come in any order.
-    std::sort(accessors.begin(), accessors.end(),
-      [&](ASTScope *s1, ASTScope *s2) {
-        return ctx.SourceMgr.isBeforeInBuffer(s1->getSourceRange().Start,
-                                              s2->getSourceRange().Start);
-    });
-
-    // Add the accessors.
-    for (auto accessor : accessors)
-      addChild(accessor);
-
     break;
   }
 
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 3ba4ae2..4b70ec6 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -1624,7 +1624,7 @@
       if (auto *baseIOT = E->getBase()->getType()->getAs<InOutType>()) {
         if (!baseIOT->getObjectType()->is<ArchetypeType>()) {
           auto *VD = dyn_cast<VarDecl>(E->getMember().getDecl());
-          if (!VD || !VD->hasAccessorFunctions()) {
+          if (!VD || VD->getAllAccessors().empty()) {
             Out << "member_ref_expr on value of inout type\n";
             E->dump(Out);
             abort();
@@ -2151,6 +2151,13 @@
       verifyCheckedBase(VD);
     }
 
+    bool shouldWalkIntoLazyInitializers() override {
+      // We don't want to walk into lazy initializers because they should
+      // have been reparented to their synthesized getter, which will
+      // invalidate various invariants.
+      return false;
+    }
+
     void verifyChecked(PatternBindingDecl *binding) {
       // Look at all of the VarDecls being bound.
       for (auto entry : binding->getPatternList())
@@ -2194,20 +2201,18 @@
           abort();
         }
       }
-      if (ASD->hasAddressors()) {
-        if (auto addressor = ASD->getAddressor()) {
-          if (addressor->isMutating() != ASD->isGetterMutating()) {
-            Out << "AbstractStorageDecl::isGetterMutating is out of sync"
-                   " with whether immutable addressor is mutating";
-            abort();
-          }
+      if (auto addressor = ASD->getAddressor()) {
+        if (addressor->isMutating() != ASD->isGetterMutating()) {
+          Out << "AbstractStorageDecl::isGetterMutating is out of sync"
+                 " with whether immutable addressor is mutating";
+          abort();
         }
-        if (auto addressor = ASD->getMutableAddressor()) {
-          if (addressor->isMutating() != ASD->isSetterMutating()) {
-            Out << "AbstractStorageDecl::isSetterMutating is out of sync"
-                   " with whether mutable addressor is mutating";
-            abort();
-          }
+      }
+      if (auto addressor = ASD->getMutableAddressor()) {
+        if (addressor->isMutating() != ASD->isSetterMutating()) {
+          Out << "AbstractStorageDecl::isSetterMutating is out of sync"
+                 " with whether mutable addressor is mutating";
+          abort();
         }
       }
 
@@ -2958,8 +2963,7 @@
         }
       }
 
-      auto storedAccessor =
-        storageDecl->getAccessorFunction(FD->getAccessorKind());
+      auto storedAccessor = storageDecl->getAccessor(FD->getAccessorKind());
       if (storedAccessor != FD) {
         Out << "storage declaration has different accessor for this kind\n";
         abort();
diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp
index 4fedbe7..8a6f844 100644
--- a/lib/AST/ASTWalker.cpp
+++ b/lib/AST/ASTWalker.cpp
@@ -158,7 +158,9 @@
         PBD->setPattern(idx, Pat, entry.getInitContext());
       else
         return true;
-      if (entry.getInit()) {
+      if (entry.getInit() &&
+          (!entry.isInitializerLazy() ||
+           Walker.shouldWalkIntoLazyInitializers())) {
 #ifndef NDEBUG
         PrettyStackTraceDecl debugStack("walking into initializer for", PBD);
 #endif
@@ -942,6 +944,11 @@
     return E;
   }
 
+  Expr *visitLazyInitializerExpr(LazyInitializerExpr *E) {
+    // Initializer is totally opaque for most visitation purposes.
+    return E;
+  }
+
   Expr *visitObjCSelectorExpr(ObjCSelectorExpr *E) {
     Expr *sub = doIt(E->getSubExpr());
     if (!sub) return nullptr;
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 0d4e183..7ad584b 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -52,6 +52,7 @@
   SubstitutionMap.cpp
   SwiftNameTranslation.cpp
   Type.cpp
+  TypeCheckRequests.cpp
   TypeJoinMeet.cpp
   TypeRefinementContext.cpp
   TypeRepr.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index fb393e3..17b0e75 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -35,6 +35,7 @@
 #include "swift/AST/ProtocolConformance.h"
 #include "swift/AST/ResilienceExpansion.h"
 #include "swift/AST/Stmt.h"
+#include "swift/AST/TypeCheckRequests.h"
 #include "swift/AST/TypeLoc.h"
 #include "swift/AST/SwiftNameTranslation.h"
 #include "clang/Lex/MacroInfo.h"
@@ -909,7 +910,6 @@
     ExtendedType(extendedType),
     Inherited(inherited)
 {
-  Bits.ExtensionDecl.CheckedInheritanceClause = false;
   Bits.ExtensionDecl.DefaultAndMaxAccessLevel = 0;
   Bits.ExtensionDecl.HasLazyConformances = false;
   setTrailingWhereClause(trailingWhereClause);
@@ -959,12 +959,8 @@
 
 Type ExtensionDecl::getInheritedType(unsigned index) const {
   ASTContext &ctx = getASTContext();
-  if (auto lazyResolver = ctx.getLazyResolver()) {
-    return lazyResolver->getInheritedType(const_cast<ExtensionDecl *>(this),
-                                          index);
-  }
-
-  return getInherited()[index].getType();
+  return ctx.evaluator(InheritedTypeRequest{const_cast<ExtensionDecl *>(this),
+                                            index});
 }
 
 bool ExtensionDecl::isConstrainedExtension() const {
@@ -1073,10 +1069,9 @@
   if (SelfParam)
     return SelfParam;
 
-  if (auto singleVar = getBinding()->getSingleVar()) {
-    auto *DC = singleVar->getDeclContext();
-    if (singleVar->getAttrs().hasAttribute<LazyAttr>() &&
-        DC->isTypeContext()) {
+  if (auto singleVar = getInitializedLazyVar()) {
+    auto DC = singleVar->getDeclContext();
+    if (DC->isTypeContext()) {
       bool isInOut = !DC->getDeclaredInterfaceType()->hasReferenceSemantics();
       SelfParam = ParamDecl::createSelf(SourceLoc(), DC,
                                         singleVar->isStatic(),
@@ -1088,6 +1083,14 @@
   return SelfParam;
 }
 
+VarDecl *PatternBindingInitializer::getInitializedLazyVar() const {
+  if (auto var = getBinding()->getSingleVar()) {
+    if (var->getAttrs().hasAttribute<LazyAttr>())
+      return var;
+  }
+  return nullptr;
+}
+
 static bool patternContainsVarDeclBinding(const Pattern *P, const VarDecl *VD) {
   bool Result = false;
   P->forEachVariable([&](VarDecl *FoundVD) {
@@ -1118,17 +1121,17 @@
 }
 
 SourceRange PatternBindingEntry::getOrigInitRange() const {
-  auto Init = InitCheckedAndRemoved.getPointer();
+  auto Init = InitAndFlags.getPointer();
   return Init ? Init->getSourceRange() : SourceRange();
 }
 
 void PatternBindingEntry::setInit(Expr *E) {
-  auto F = InitCheckedAndRemoved.getInt();
+  auto F = InitAndFlags.getInt();
   if (E) {
-    InitCheckedAndRemoved.setInt(F - Flags::Removed);
-    InitCheckedAndRemoved.setPointer(E);
+    InitAndFlags.setInt(F - Flags::Removed);
+    InitAndFlags.setPointer(E);
   } else {
-    InitCheckedAndRemoved.setInt(F | Flags::Removed);
+    InitAndFlags.setInt(F | Flags::Removed);
   }
 }
 
@@ -1343,135 +1346,173 @@
 AccessSemantics
 ValueDecl::getAccessSemanticsFromContext(const DeclContext *UseDC,
                                          bool isAccessOnSelf) const {
-  // If we're inside a @_transparent function, use the most conservative
-  // access pattern, since we may be inlined from a different resilience
-  // domain.
-  ResilienceExpansion expansion = UseDC->getResilienceExpansion();
+  // All accesses have ordinary semantics except those to variables
+  // with storage from within their own accessors.  In Swift 5 and later,
+  // the access must also be a member access on 'self'.
 
-  if (auto *var = dyn_cast<AbstractStorageDecl>(this)) {
-    auto isMember = var->getDeclContext()->isTypeContext();
-    if (isAccessOnSelf)
-      assert(isMember && "Access on self, but var isn't a member");
-
-    // Within a variable's own didSet/willSet specifier, access its storage
-    // directly if either:
-    // 1) It's a 'plain variable' (i.e a variable that's not a member).
-    // 2) It's an access to the member on the implicit 'self' declaration.
-    //    If it's a member access on some other base, we want to call the setter
-    //    as we might be accessing the member on a *different* instance.
-    // 3) We're not in Swift 5 mode (or higher), as in earlier versions of Swift
-    //    we always performed direct accesses.
-    // This prevents assignments from becoming infinite loops in most cases.
-    if (!isMember || isAccessOnSelf ||
-        !UseDC->getASTContext().isSwiftVersionAtLeast(5))
-      if (auto *UseFD = dyn_cast<AccessorDecl>(UseDC))
-        if (var->hasStorage() && var->hasAccessorFunctions() &&
-            UseFD->getStorage() == var)
-          return AccessSemantics::DirectToStorage;
-
-    // "StoredWithTrivialAccessors" are generally always accessed indirectly,
-    // but if we know that the trivial accessor will always produce the same
-    // thing as the getter/setter (i.e., it can't be overridden), then just do a
-    // direct access.
-    //
-    // This is true in structs and for final properties.
-    // TODO: What about static properties?
-    switch (var->getStorageKind()) {
-    case AbstractStorageDecl::Stored:
-    case AbstractStorageDecl::Addressed:
-      // The storage is completely trivial. Always do direct access.
-      return AccessSemantics::DirectToStorage;
-
-    case AbstractStorageDecl::StoredWithTrivialAccessors:
-    case AbstractStorageDecl::AddressedWithTrivialAccessors: {
-      // If the property is defined in a non-final class or a protocol, the
-      // accessors are dynamically dispatched, and we cannot do direct access.
-      if (isPolymorphic(var))
-        return AccessSemantics::Ordinary;
-
-      // If the property is resilient from the given context,
-      // we cannot do direct access.
-      if (var->isResilient(UseDC->getParentModule(), expansion))
-        return AccessSemantics::Ordinary;
-
-      // We know enough about the property to perform direct access.
-      return AccessSemantics::DirectToStorage;
-    }
-
-    case AbstractStorageDecl::StoredWithObservers:
-    case AbstractStorageDecl::InheritedWithObservers:
-    case AbstractStorageDecl::Computed:
-    case AbstractStorageDecl::ComputedWithMutableAddress:
-    case AbstractStorageDecl::AddressedWithObservers:
-      // Property is not trivially backed by storage, do not perform
-      // direct access.
-      break;
+  // The condition most likely to fast-path us is not being in an accessor,
+  // so we check that first.
+  if (auto *accessor = dyn_cast<AccessorDecl>(UseDC)) {
+    if (auto *var = dyn_cast<VarDecl>(this)) {
+      if (accessor->getStorage() == var && var->hasStorage() &&
+          (isAccessOnSelf || !var->getDeclContext()->isTypeContext() ||
+           !var->getASTContext().isSwiftVersionAtLeast(5)))
+        return AccessSemantics::DirectToStorage;
     }
   }
 
+  // Otherwise, it's a semantically normal access.  The client should be
+  // able to figure out the most efficient way to do this access.
   return AccessSemantics::Ordinary;
 }
 
+static AccessStrategy
+getDirectReadAccessStrategy(const AbstractStorageDecl *storage) {
+  switch (storage->getReadImpl()) {
+  case ReadImplKind::Stored:
+    return AccessStrategy::getStorage();
+  case ReadImplKind::Inherited:
+    // TODO: maybe add a specific strategy for this?
+    return AccessStrategy::getAccessor(AccessorKind::Get,
+                                       /*dispatch*/ false);
+  case ReadImplKind::Get:
+    return AccessStrategy::getAccessor(AccessorKind::Get,
+                                       /*dispatch*/ false);
+  case ReadImplKind::Address:
+    return AccessStrategy::getAccessor(AccessorKind::Address,
+                                       /*dispatch*/ false);
+  }
+  llvm_unreachable("bad impl kind");
+}
+
+static AccessStrategy
+getDirectWriteAccessStrategy(const AbstractStorageDecl *storage) {
+  switch (storage->getWriteImpl()) {
+  case WriteImplKind::Immutable:
+    assert(isa<VarDecl>(storage) && cast<VarDecl>(storage)->isLet() &&
+           "mutation of a immutable variable that isn't a let");
+    return AccessStrategy::getStorage();
+  case WriteImplKind::Stored:
+    return AccessStrategy::getStorage();
+  case WriteImplKind::StoredWithObservers:
+    // TODO: maybe add a specific strategy for this?
+    return AccessStrategy::getAccessor(AccessorKind::Set,
+                                       /*dispatch*/ false);
+  case WriteImplKind::InheritedWithObservers:
+    // TODO: maybe add a specific strategy for this?
+    return AccessStrategy::getAccessor(AccessorKind::Set,
+                                       /*dispatch*/ false);
+  case WriteImplKind::Set:
+    return AccessStrategy::getAccessor(AccessorKind::Set,
+                                       /*dispatch*/ false);
+  case WriteImplKind::MutableAddress:
+    return AccessStrategy::getAccessor(AccessorKind::MutableAddress,
+                                       /*dispatch*/ false);
+  }
+  llvm_unreachable("bad impl kind");
+}
+
+static AccessStrategy
+getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) {
+  switch (storage->getReadWriteImpl()) {
+  case ReadWriteImplKind::Immutable:
+    assert(isa<VarDecl>(storage) && cast<VarDecl>(storage)->isLet() &&
+           "mutation of a immutable variable that isn't a let");
+    return AccessStrategy::getStorage();
+  case ReadWriteImplKind::Stored:
+    return AccessStrategy::getStorage();
+  case ReadWriteImplKind::MaterializeForSet:
+    return AccessStrategy::getAccessor(AccessorKind::MaterializeForSet,
+                                       /*dispatch*/ false);
+  case ReadWriteImplKind::MutableAddress:
+    return AccessStrategy::getAccessor(AccessorKind::MutableAddress,
+                                       /*dispatch*/ false);
+  case ReadWriteImplKind::MaterializeToTemporary:
+    return AccessStrategy::getMaterializeToTemporary(
+                                       getDirectReadAccessStrategy(storage),
+                                       getDirectWriteAccessStrategy(storage));
+  }
+  llvm_unreachable("bad impl kind");
+}
+
+static AccessStrategy
+getOpaqueReadAccessStrategy(const AbstractStorageDecl *storage, bool dispatch) {
+  return AccessStrategy::getAccessor(AccessorKind::Get, dispatch);
+}
+
+static AccessStrategy
+getOpaqueWriteAccessStrategy(const AbstractStorageDecl *storage, bool dispatch){
+  return AccessStrategy::getAccessor(AccessorKind::Set, dispatch);
+}
+
+static bool hasDispatchedMaterializeForSet(const AbstractStorageDecl *storage) {
+  // If the declaration is dynamic, there's no materializeForSet.
+  if (storage->isDynamic())
+    return false;
+
+  // If the declaration was imported from C, we won't gain anything
+  // from using materializeForSet, and furthermore, it might not
+  // exist.
+  if (storage->hasClangNode())
+    return false;
+
+  // If the declaration is not in type context, there's no
+  // materializeForSet.
+  auto dc = storage->getDeclContext();
+  if (!dc->isTypeContext())
+    return false;
+
+  // @objc protocols count also don't have materializeForSet declarations.
+  if (auto proto = dyn_cast<ProtocolDecl>(dc)) {
+    if (proto->isObjC())
+      return false;
+  }
+
+  // Otherwise it should have a materializeForSet if we might be
+  // accessing it opaquely.
+  return true;
+}
+
+static AccessStrategy
+getOpaqueAccessStrategy(const AbstractStorageDecl *storage,
+                        AccessKind accessKind, bool dispatch) {
+  switch (accessKind) {
+  case AccessKind::Read:
+    return getOpaqueReadAccessStrategy(storage, dispatch);
+  case AccessKind::Write:
+    return getOpaqueWriteAccessStrategy(storage, dispatch);
+  case AccessKind::ReadWrite:
+    if (hasDispatchedMaterializeForSet(storage))
+      return AccessStrategy::getAccessor(AccessorKind::MaterializeForSet,
+                                         dispatch);
+    return AccessStrategy::getMaterializeToTemporary(
+             getOpaqueReadAccessStrategy(storage, dispatch),
+             getOpaqueWriteAccessStrategy(storage, dispatch));
+  }
+  llvm_unreachable("bad access kind");
+}
+
 AccessStrategy
 AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
                                        AccessKind accessKind,
                                        DeclContext *accessFromDC) const {
   switch (semantics) {
   case AccessSemantics::DirectToStorage:
-    switch (getStorageKind()) {
-    case Stored:
-    case StoredWithTrivialAccessors:
-    case StoredWithObservers:
-      return AccessStrategy::Storage;
-
-    case Addressed:
-    case AddressedWithTrivialAccessors:
-    case AddressedWithObservers:
-    case ComputedWithMutableAddress:
-      return AccessStrategy::Addressor;
-
-    case InheritedWithObservers:
-    case Computed:
-      llvm_unreachable("cannot have direct-to-storage access to "
-                       "computed storage");
-    }
-    llvm_unreachable("bad storage kind");
-
-  case AccessSemantics::DirectToAccessor:
-    assert(hasAccessorFunctions() &&
-           "direct-to-accessors access to storage without accessors?");
-    return AccessStrategy::DirectToAccessor;
+    assert(hasStorage());
+    return AccessStrategy::getStorage();
 
   case AccessSemantics::Ordinary:
-    switch (auto storageKind = getStorageKind()) {
-    case Stored:
-      return AccessStrategy::Storage;
-    case Addressed:
-      return AccessStrategy::Addressor;
-
-    case StoredWithObservers:
-    case InheritedWithObservers:
-    case AddressedWithObservers:
-      // An observing property backed by its own storage (i.e. which
-      // doesn't override anything) has a trivial getter implementation,
-      // but its setter is interesting.
-      if (accessKind != AccessKind::Read ||
-          storageKind == InheritedWithObservers) {
-        if (isPolymorphic(this))
-          return AccessStrategy::DispatchToAccessor;
-        return AccessStrategy::DirectToAccessor;
-      }
-
-      // Fall through to the trivial-implementation case.
-      LLVM_FALLTHROUGH;
-
-    case StoredWithTrivialAccessors:
-    case AddressedWithTrivialAccessors: {
+    // Skip these checks for local variables, both because they're unnecessary
+    // and because we won't necessarily have computed access.
+    if (!getDeclContext()->isLocalContext()) {
       // If the property is defined in a non-final class or a protocol, the
       // accessors are dynamically dispatched, and we cannot do direct access.
       if (isPolymorphic(this))
-        return AccessStrategy::DispatchToAccessor;
+        return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ true);
 
+      // If the storage is resilient to the given use DC (perhaps because
+      // it's @_transparent and we have to be careful about it being inlined
+      // across module lines), we cannot use direct access.
       // If we end up here with a stored property of a type that's resilient
       // from some resilience domain, we cannot do direct access.
       //
@@ -1485,46 +1526,38 @@
       bool resilient;
       if (accessFromDC)
         resilient = isResilient(accessFromDC->getParentModule(),
-                                ResilienceExpansion::Maximal);
+                                accessFromDC->getResilienceExpansion());
       else
         resilient = isResilient();
-      
+
       if (resilient)
-        return AccessStrategy::DirectToAccessor;
-
-      if (storageKind == StoredWithObservers ||
-          storageKind == StoredWithTrivialAccessors) {
-        return AccessStrategy::Storage;
-      } else {
-        assert(storageKind == AddressedWithObservers ||
-               storageKind == AddressedWithTrivialAccessors);
-        return AccessStrategy::Addressor;
-      }
+        return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ false);
     }
 
-    case ComputedWithMutableAddress:
-      if (isPolymorphic(this))
-        return AccessStrategy::DispatchToAccessor;
-      if (accessKind == AccessKind::Read)
-        return AccessStrategy::DirectToAccessor;
-      return AccessStrategy::Addressor;
+    LLVM_FALLTHROUGH;
 
-    case Computed:
-      if (isPolymorphic(this))
-        return AccessStrategy::DispatchToAccessor;
-      return AccessStrategy::DirectToAccessor;
+  case AccessSemantics::DirectToImplementation:
+    switch (accessKind) {
+    case AccessKind::Read:
+      return getDirectReadAccessStrategy(this);
+    case AccessKind::Write:
+      return getDirectWriteAccessStrategy(this);
+    case AccessKind::ReadWrite:
+      return getDirectReadWriteAccessStrategy(this);
     }
-    llvm_unreachable("bad storage kind");
+    llvm_unreachable("bad access kind");
+
   case AccessSemantics::BehaviorInitialization:
     // Behavior initialization writes to the property as if it has storage.
     // SIL definite initialization will introduce the logical accesses.
-    // Reads or inouts still go through the getter.
+    // Reads or inouts go through the ordinary path.
     switch (accessKind) {
     case AccessKind::Write:
-      return AccessStrategy::BehaviorStorage;
-    case AccessKind::ReadWrite:
+      return AccessStrategy::getBehaviorStorage();
     case AccessKind::Read:
-      return AccessStrategy::DispatchToAccessor;
+    case AccessKind::ReadWrite:
+      return getAccessStrategy(AccessSemantics::Ordinary,
+                               accessKind, accessFromDC);
     }
   }
   llvm_unreachable("bad access semantics");
@@ -1946,19 +1979,25 @@
   return CanType();
 }
 
-void ValueDecl::setIsObjC(bool Value) {
-  bool CurrentValue = isObjC();
-  if (CurrentValue == Value)
-    return;
+bool ValueDecl::isObjC() const {
+  if (Bits.ValueDecl.IsObjCComputed)
+    return Bits.ValueDecl.IsObjC;
 
-  if (!Value) {
-    for (auto *Attr : getAttrs()) {
-      if (auto *OA = dyn_cast<ObjCAttr>(Attr))
-        OA->setInvalid();
-    }
-  } else {
-    getAttrs().add(ObjCAttr::createUnnamedImplicit(getASTContext()));
+  // Fallback: look for an @objc attribute.
+  // FIXME: This should become an error, eventually.
+  return getAttrs().hasAttribute<ObjCAttr>();
+}
+
+void ValueDecl::setIsObjC(bool value) {
+  assert(!Bits.ValueDecl.IsObjCComputed || Bits.ValueDecl.IsObjC == value);
+
+  if (Bits.ValueDecl.IsObjCComputed) {
+    assert(Bits.ValueDecl.IsObjC == value);
+    return;
   }
+
+  Bits.ValueDecl.IsObjCComputed = true;
+  Bits.ValueDecl.IsObjC = value;
 }
 
 bool ValueDecl::canBeAccessedByDynamicLookup() const {
@@ -2323,12 +2362,8 @@
 
 Type TypeDecl::getInheritedType(unsigned index) const {
   ASTContext &ctx = getASTContext();
-  if (auto lazyResolver = ctx.getLazyResolver()) {
-    return lazyResolver->getInheritedType(const_cast<TypeDecl *>(this),
-                                          index);
-  }
-
-  return getInherited()[index].getType();
+  return ctx.evaluator(InheritedTypeRequest{const_cast<TypeDecl *>(this),
+                                            index});
 }
 
 Type TypeDecl::getDeclaredInterfaceType() const {
@@ -2823,11 +2858,7 @@
 
 Type EnumDecl::getRawType() const {
   ASTContext &ctx = getASTContext();
-  if (auto lazyResolver = ctx.getLazyResolver()) {
-    return lazyResolver->getRawType(const_cast<EnumDecl *>(this));
-  }
-
-  return LazySemanticInfo.RawType.getPointer();
+  return ctx.evaluator(EnumRawTypeRequest{const_cast<EnumDecl *>(this)});
 }
 
 StructDecl::StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
@@ -2888,8 +2919,9 @@
   DD->setGenericEnvironment(getGenericEnvironmentOfContext());
 
   // Mark DD as ObjC, as all dtors are.
-  DD->setIsObjC(true);
-  recordObjCMethod(DD);
+  DD->setIsObjC(getASTContext().LangOpts.EnableObjCInterop);
+  if (getASTContext().LangOpts.EnableObjCInterop)
+    recordObjCMethod(DD);
 
   // Assign DD the interface type (Self) -> () -> ()
   ArrayRef<AnyFunctionType::Param> noParams;
@@ -3277,6 +3309,23 @@
   return result;
 }
 
+Type ProtocolDecl::getSuperclass() const {
+  ASTContext &ctx = getASTContext();
+  return ctx.evaluator(SuperclassTypeRequest{const_cast<ProtocolDecl *>(this)});
+}
+
+ClassDecl *ProtocolDecl::getSuperclassDecl() const {
+  if (auto superclass = getSuperclass())
+    return superclass->getClassOrBoundGenericClass();
+  return nullptr;
+}
+
+void ProtocolDecl::setSuperclass(Type superclass) {
+  assert((!superclass || !superclass->hasArchetype())
+         && "superclass must be interface type");
+  LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
+}
+
 bool ProtocolDecl::walkInheritedProtocols(
               llvm::function_ref<TypeWalker::Action(ProtocolDecl *)> fn) const {
   auto self = const_cast<ProtocolDecl *>(this);
@@ -3728,18 +3777,16 @@
   llvm_unreachable("bad accessor kind");
 }
 
-void AbstractStorageDecl::setAccessors(StorageKindTy storageKind,
+void AbstractStorageDecl::overwriteImplInfo(StorageImplInfo implInfo) {
+  setFieldsFromImplInfo(implInfo);
+  Accessors.getPointer()->overwriteImplInfo(implInfo);
+}
+
+void AbstractStorageDecl::setAccessors(StorageImplInfo implInfo,
                                        SourceLoc lbraceLoc,
                                        ArrayRef<AccessorDecl *> accessors,
                                        SourceLoc rbraceLoc) {
-  assert(getStorageKind() == Stored && "StorageKind already set");
-
-  // The only situation where we allow the incoming storage kind to be
-  // Stored is when there are no accessors.  This happens when the program
-  // has {} as the accessor clause (or unparsable contents).
-  assert((storageKind != Stored || accessors.empty()) &&
-         "cannot combine Stored storage kind with any accessors");
-  setStorageKind(storageKind);
+  setFieldsFromImplInfo(implInfo);
 
   // This method is called after we've already recorded an accessors clause
   // only on recovery paths and only when that clause was empty.
@@ -3752,7 +3799,7 @@
   } else {
     record = AccessorRecord::create(getASTContext(),
                                     SourceRange(lbraceLoc, rbraceLoc),
-                                    accessors);
+                                    implInfo, accessors);
     Accessors.setPointer(record);
   }
 
@@ -3772,6 +3819,7 @@
 AbstractStorageDecl::AccessorRecord *
 AbstractStorageDecl::AccessorRecord::create(ASTContext &ctx,
                                             SourceRange braces,
+                                            StorageImplInfo storageInfo,
                                             ArrayRef<AccessorDecl*> accessors) {
   // Silently cap the number of accessors we store at a number that should
   // be easily sufficient for all the valid cases, including space for adding
@@ -3811,13 +3859,15 @@
   auto accessorsCapacity = AccessorIndex(accessors.size() + numMissingOpaque);
   void *mem = ctx.Allocate(totalSizeToAlloc<AccessorDecl*>(accessorsCapacity),
                            alignof(AccessorRecord));
-  return new (mem) AccessorRecord(braces, accessors, accessorsCapacity);
+  return new (mem) AccessorRecord(braces, storageInfo,
+                                  accessors, accessorsCapacity);
 }
 
 AbstractStorageDecl::AccessorRecord::AccessorRecord(SourceRange braces,
+                                           StorageImplInfo implInfo,
                                            ArrayRef<AccessorDecl *> accessors,
                                            AccessorIndex accessorsCapacity)
-    : Braces(braces), NumAccessors(accessors.size()),
+    : Braces(braces), ImplInfo(implInfo), NumAccessors(accessors.size()),
       AccessorsCapacity(accessorsCapacity), AccessorIndices{} {
 
   // Copy the complete accessors list into place.
@@ -3860,57 +3910,55 @@
 }
 
 void AbstractStorageDecl::setComputedSetter(AccessorDecl *setter) {
-  assert(getStorageKind() == Computed && "Not a computed variable");
+  assert(getImplInfo().getReadImpl() == ReadImplKind::Get);
+  assert(!getImplInfo().supportsMutation());
   assert(getGetter() && "sanity check: missing getter");
   assert(!getSetter() && "already has a setter");
   assert(hasClangNode() && "should only be used for ObjC properties");
   assert(isAccessor(setter, AccessorKind::Set, this));
   assert(setter && "should not be called for readonly properties");
 
+  overwriteImplInfo(StorageImplInfo::getMutableComputed());
   Accessors.getPointer()->addOpaqueAccessor(setter);
   configureAccessor(setter);
 }
 
-void AbstractStorageDecl::setMaterializeForSetFunc(AccessorDecl *accessor) {
-  assert(hasAccessorFunctions() && "No accessors for declaration!");
-  assert(getSetter() && "declaration is not settable");
-  assert(!getMaterializeForSetFunc() && "already has a materializeForSet");
-  assert(isAccessor(accessor, AccessorKind::MaterializeForSet, this));
+void
+AbstractStorageDecl::setSynthesizedGetter(AccessorDecl *accessor) {
+  assert(!getGetter() && "declaration doesn't already have getter!");
+  assert(isAccessor(accessor, AccessorKind::Get, this));
+
+  auto accessors = Accessors.getPointer();
+  if (!accessors) {
+    accessors = AccessorRecord::create(getASTContext(), SourceRange(),
+                                       getImplInfo(), {});
+    Accessors.setPointer(accessors);
+  }
+
+  accessors->addOpaqueAccessor(accessor);
+  configureAccessor(accessor);
+}
+
+void
+AbstractStorageDecl::setSynthesizedSetter(AccessorDecl *accessor) {
+  assert(getGetter() && "declaration doesn't already have getter!");
+  assert(supportsMutation() && "adding setter to immutable storage");
+  assert(isAccessor(accessor, AccessorKind::Set, this));
 
   Accessors.getPointer()->addOpaqueAccessor(accessor);
   configureAccessor(accessor);
 }
 
-/// \brief Turn this into a StoredWithTrivialAccessors var, specifying the
-/// accessors (getter and setter) that go with it.
-void AbstractStorageDecl::addTrivialAccessors(AccessorDecl *getter,
-                                              AccessorDecl *setter,
-                                              AccessorDecl *materializeForSet) {
-  assert((getStorageKind() == Stored ||
-          getStorageKind() == Addressed) && "StorageKind already set");
-  assert(getter);
+void
+AbstractStorageDecl::setSynthesizedMaterializeForSet(AccessorDecl *accessor) {
+  assert(getGetter() && "declaration doesn't already have getter!");
+  assert(getSetter() && "declaration doesn't already have setter!");
+  assert(supportsMutation() && "adding materializeForSet to immutable storage");
+  assert(!getMaterializeForSetFunc() && "already has a materializeForSet");
+  assert(isAccessor(accessor, AccessorKind::MaterializeForSet, this));
 
-  if (getStorageKind() == Addressed) {
-    setStorageKind(AddressedWithTrivialAccessors);
-  } else {
-    setStorageKind(StoredWithTrivialAccessors);
-    if (!Accessors.getPointer()) {
-      Accessors.setPointer(AccessorRecord::create(getASTContext(),
-                                                  SourceRange(), {}));
-    }
-  }
-
-  auto record = Accessors.getPointer();
-  assert(record);
-
-  auto collect = [&](AccessorDecl *accessor) {
-    record->addOpaqueAccessor(accessor);
-    configureAccessor(accessor);
-  };
-
-  collect(getter);
-  if (setter) collect(setter);
-  if (materializeForSet) collect(materializeForSet);
+  Accessors.getPointer()->addOpaqueAccessor(accessor);
+  configureAccessor(accessor);
 }
 
 void AbstractStorageDecl::addBehavior(TypeRepr *Type,
@@ -4020,30 +4068,6 @@
   return SourceLoc();
 }
 
-static bool isSettable(const AbstractStorageDecl *decl) {
-  switch (decl->getStorageKind()) {
-  case AbstractStorageDecl::Stored:
-    return true;
-
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
-    return decl->getSetter() != nullptr;
-
-  case AbstractStorageDecl::Addressed:
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-    return decl->getMutableAddressor() != nullptr;
-
-  case AbstractStorageDecl::StoredWithObservers:
-  case AbstractStorageDecl::InheritedWithObservers:
-  case AbstractStorageDecl::AddressedWithObservers:
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-    return true;
-
-  case AbstractStorageDecl::Computed:
-    return decl->getSetter() != nullptr;
-  }
-  llvm_unreachable("bad storage kind");
-}
-
 Type VarDecl::getType() const {
   if (!typeInContext) {
     const_cast<VarDecl *>(this)->typeInContext =
@@ -4076,7 +4100,7 @@
   // If this is a 'var' decl, then we're settable if we have storage or a
   // setter.
   if (!isImmutable())
-    return ::isSettable(this);
+    return supportsMutation();
 
   // If the decl has a value bound to it but has no PBD, then it is
   // initialized.
@@ -4139,7 +4163,7 @@
 }
 
 bool SubscriptDecl::isSettable() const {
-  return ::isSettable(this);
+  return supportsMutation();
 }
 
 SourceRange VarDecl::getSourceRange() const {
@@ -4230,6 +4254,11 @@
   return false;
 }
 
+void VarDecl::setSpecifier(Specifier specifier) {
+  Bits.VarDecl.Specifier = static_cast<unsigned>(specifier);
+  setSupportsMutationIfStillStored(!isImmutableSpecifier(specifier));
+}
+
 bool VarDecl::isAnonClosureParam() const {
   auto name = getName();
   if (name.empty())
@@ -5670,11 +5699,7 @@
 
 Type ClassDecl::getSuperclass() const {
   ASTContext &ctx = getASTContext();
-  if (auto lazyResolver = ctx.getLazyResolver()) {
-    return lazyResolver->getSuperclass(this);
-  }
-
-  return LazySemanticInfo.Superclass.getPointer();
+  return ctx.evaluator(SuperclassTypeRequest{const_cast<ClassDecl *>(this)});
 }
 
 ClassDecl *ClassDecl::getSuperclassDecl() const {
diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp
index 93f5ba7..12d4aa5 100644
--- a/lib/AST/Evaluator.cpp
+++ b/lib/AST/Evaluator.cpp
@@ -32,6 +32,32 @@
   return result;
 }
 
+AbstractRequestFunction *
+Evaluator::getAbstractRequestFunction(uint8_t zoneID, uint8_t requestID) const {
+  for (const auto &zone : requestFunctionsByZone) {
+    if (zone.first == zoneID) {
+      if (requestID < zone.second.size())
+        return zone.second[requestID];
+
+      return nullptr;
+    }
+  }
+
+  return nullptr;
+}
+
+void Evaluator::registerRequestFunctions(
+                               uint8_t zoneID,
+                               ArrayRef<AbstractRequestFunction *> functions) {
+#ifndef NDEBUG
+  for (const auto &zone : requestFunctionsByZone) {
+    assert(zone.first != zoneID);
+  }
+#endif
+
+  requestFunctionsByZone.push_back({zoneID, functions});
+}
+
 Evaluator::Evaluator(DiagnosticEngine &diags,
                      CycleDiagnosticKind shouldDiagnoseCycles)
   : diags(diags), shouldDiagnoseCycles(shouldDiagnoseCycles) { }
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 5ec9569..683bcd6 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -379,6 +379,7 @@
     NON_LVALUE_EXPR(ObjCSelector)
     NON_LVALUE_EXPR(KeyPath)
     NON_LVALUE_EXPR(EnumIsCase)
+    NON_LVALUE_EXPR(LazyInitializer)
 
 #define UNCHECKED_EXPR(KIND, BASE) \
     NON_LVALUE_EXPR(KIND)
@@ -413,6 +414,7 @@
   NO_REFERENCE(ObjectLiteral);
   NO_REFERENCE(MagicIdentifierLiteral);
   NO_REFERENCE(DiscardAssignment);
+  NO_REFERENCE(LazyInitializer);
 
   SIMPLE_REFERENCE(DeclRef, getDeclRef);
   SIMPLE_REFERENCE(SuperRef, getSelf);
@@ -684,6 +686,7 @@
   switch (getKind()) {
   case ExprKind::Error:
   case ExprKind::CodeCompletion:
+  case ExprKind::LazyInitializer:
     return false;
 
   case ExprKind::NilLiteral:
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 9c4511c..7e5d364 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -130,12 +130,6 @@
                                              ProtocolConformanceRef conformance,
                                              Identifier name,
                                              LazyResolver *resolver) {
-  // For an archetype, retrieve the nested type with the appropriate
-  // name. There are no conformance tables.
-  if (auto archetype = type->getAs<ArchetypeType>()) {
-    return archetype->getNestedType(name);
-  }
-
   // Find the named requirement.
   AssociatedTypeDecl *assocType = nullptr;
   auto members = conformance.getRequirement()->lookupDirect(name);
@@ -149,8 +143,15 @@
   if (!assocType)
     return nullptr;
 
-  if (conformance.isAbstract())
+  if (conformance.isAbstract()) {
+    // For an archetype, retrieve the nested type with the appropriate
+    // name. There are no conformance tables.
+    if (auto archetype = type->getAs<ArchetypeType>()) {
+      return archetype->getNestedType(name);
+    }
+
     return DependentMemberType::get(type, assocType);
+  }
 
   auto concrete = conformance.getConcrete();
   if (!concrete->hasTypeWitness(assocType, resolver)) {
diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp
new file mode 100644
index 0000000..ba9f13f
--- /dev/null
+++ b/lib/AST/TypeCheckRequests.cpp
@@ -0,0 +1,147 @@
+//===--- TypeCheckRequests.cpp - Type Checking Requests ------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+#include "swift/AST/TypeCheckRequests.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/DiagnosticsCommon.h"
+#include "swift/AST/TypeLoc.h"
+#include "swift/AST/Types.h"
+
+using namespace swift;
+
+namespace swift {
+// Implement the type checker type zone (zone 10).
+#define SWIFT_TYPEID_ZONE 10
+#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
+#include "swift/Basic/ImplementTypeIDZone.h"
+
+}
+
+void swift::simple_display(
+       llvm::raw_ostream &out,
+       const llvm::PointerUnion<TypeDecl *, ExtensionDecl *> &value) {
+  if (auto type = value.dyn_cast<TypeDecl *>()) {
+    type->dumpRef(out);
+    return;
+  }
+
+  auto ext = value.get<ExtensionDecl *>();
+  out << "extension of ";
+  ext->getAsNominalTypeOrNominalTypeExtensionContext()->dumpRef(out);
+}
+
+//----------------------------------------------------------------------------//
+// Inherited type computation.
+//----------------------------------------------------------------------------//
+
+TypeLoc &InheritedTypeRequest::getTypeLoc(
+                        llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
+                        unsigned index) const {
+  if (auto typeDecl = decl.dyn_cast<TypeDecl *>())
+    return typeDecl->getInherited()[index];
+
+  return decl.get<ExtensionDecl *>()->getInherited()[index];
+}
+
+void InheritedTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+  const auto &storage = getStorage();
+  auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
+  diags.diagnose(typeLoc.getLoc(), diag::circular_reference);
+}
+
+void InheritedTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
+  const auto &storage = getStorage();
+  auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
+  diags.diagnose(typeLoc.getLoc(), diag::circular_reference_through);
+}
+
+Optional<Type> InheritedTypeRequest::getCachedResult() const {
+  const auto &storage = getStorage();
+  auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
+  if (typeLoc.wasValidated())
+    return typeLoc.getType();
+
+  return None;
+}
+
+void InheritedTypeRequest::cacheResult(Type value) const {
+  const auto &storage = getStorage();
+  auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
+  typeLoc.setType(value);
+}
+
+//----------------------------------------------------------------------------//
+// Superclass computation.
+//----------------------------------------------------------------------------//
+void SuperclassTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+  // FIXME: Improve this diagnostic.
+  auto nominalDecl = std::get<0>(getStorage());
+  diags.diagnose(nominalDecl, diag::circular_class_inheritance,
+                 nominalDecl->getName());
+}
+
+void SuperclassTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
+  auto nominalDecl = std::get<0>(getStorage());
+  // FIXME: Customize this further.
+  diags.diagnose(nominalDecl, diag::circular_reference_through);
+}
+
+Optional<Type> SuperclassTypeRequest::getCachedResult() const {
+  auto nominalDecl = std::get<0>(getStorage());
+
+  if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
+    if (classDecl->LazySemanticInfo.Superclass.getInt())
+      return classDecl->LazySemanticInfo.Superclass.getPointer();
+
+  if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
+    if (protocolDecl->LazySemanticInfo.Superclass.getInt())
+      return protocolDecl->LazySemanticInfo.Superclass.getPointer();
+
+  return None;
+}
+
+void SuperclassTypeRequest::cacheResult(Type value) const {
+  auto nominalDecl = std::get<0>(getStorage());
+
+  if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
+    classDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
+
+  if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
+    protocolDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
+}
+
+//----------------------------------------------------------------------------//
+// Enum raw type computation.
+//----------------------------------------------------------------------------//
+void EnumRawTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+  // FIXME: Improve this diagnostic.
+  auto enumDecl = std::get<0>(getStorage());
+  diags.diagnose(enumDecl, diag::circular_enum_inheritance, enumDecl->getName());
+}
+
+void EnumRawTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
+  auto enumDecl = std::get<0>(getStorage());
+  // FIXME: Customize this further.
+  diags.diagnose(enumDecl, diag::circular_reference_through);
+}
+
+Optional<Type> EnumRawTypeRequest::getCachedResult() const {
+  auto enumDecl = std::get<0>(getStorage());
+  if (enumDecl->LazySemanticInfo.RawType.getInt())
+    return enumDecl->LazySemanticInfo.RawType.getPointer();
+
+  return None;
+}
+
+void EnumRawTypeRequest::cacheResult(Type value) const {
+  auto enumDecl = std::get<0>(getStorage());
+  enumDecl->LazySemanticInfo.RawType.setPointerAndInt(value, true);
+}
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 699c756..fcb21b1 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -188,10 +188,13 @@
 static void makeComputed(AbstractStorageDecl *storage,
                          AccessorDecl *getter, AccessorDecl *setter) {
   assert(getter);
-  AccessorDecl *buffer[] = { getter, setter };
-  auto accessors = llvm::makeArrayRef(buffer).slice(0, setter ? 2 : 1);
-  storage->setAccessors(AbstractStorageDecl::Computed,
-                        SourceLoc(), accessors, SourceLoc());
+  if (setter) {
+    storage->setAccessors(StorageImplInfo::getMutableComputed(),
+                          SourceLoc(), {getter, setter}, SourceLoc());
+  } else {
+    storage->setAccessors(StorageImplInfo::getImmutableComputed(),
+                          SourceLoc(), {getter}, SourceLoc());
+  }
 }
 
 #ifndef NDEBUG
@@ -1198,6 +1201,7 @@
 
   auto call = CallExpr::createImplicit(context, zeroInitializerRef, {}, {});
   call->setType(selfType);
+  call->setThrows(false);
 
   auto assign = new (context) AssignExpr(lhs, SourceLoc(), call,
                                          /*implicit*/ true);
@@ -1423,7 +1427,7 @@
   auto varGetter = makeStructRawValueGetter(
       Impl, structDecl, var, var);
 
-  var->addTrivialAccessors(varGetter, nullptr, nullptr);
+  var->setSynthesizedGetter(varGetter);
   assert(var->hasStorage());
 
   // Create constructors to initialize that value from a value of the
@@ -1641,9 +1645,9 @@
 
   thunk->setAccess(getOverridableAccessLevel(dc));
 
-  auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>();
-  assert(objcAttr);
-  thunk->getAttrs().add(objcAttr->clone(C));
+  if (auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>())
+    thunk->getAttrs().add(objcAttr->clone(C));
+  thunk->setIsObjC(getter->isObjC());
   // FIXME: Should we record thunks?
 
   return thunk;
@@ -1711,9 +1715,9 @@
 
   thunk->setAccess(getOverridableAccessLevel(dc));
 
-  auto objcAttr = setter->getAttrs().getAttribute<ObjCAttr>();
-  assert(objcAttr);
-  thunk->getAttrs().add(objcAttr->clone(C));
+  if (auto objcAttr = setter->getAttrs().getAttribute<ObjCAttr>())
+    thunk->getAttrs().add(objcAttr->clone(C));
+  thunk->setIsObjC(setter->isObjC());
 
   return thunk;
 }
@@ -2634,7 +2638,6 @@
         auto structDecl = Impl.createDeclWithClangNode<StructDecl>(decl,
           AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
         structDecl->computeType();
-        structDecl->setCheckedInheritanceClause();
         structDecl->setAddedImplicitInitializers();
 
         auto options = getDefaultMakeStructRawValuedOptions();
@@ -2776,7 +2779,6 @@
         SmallVector<TypeLoc, 2> inheritedTypes;
         inheritedTypes.push_back(TypeLoc::withoutLoc(underlyingType));
         enumDecl->setInherited(C.AllocateCopy(inheritedTypes));
-        enumDecl->setCheckedInheritanceClause();
 
         if (errorWrapper) {
           addSynthesizedProtocolAttrs(Impl, enumDecl,
@@ -3811,7 +3813,11 @@
     /// The importer should use this rather than adding the attribute directly.
     void addObjCAttribute(ValueDecl *decl, Optional<ObjCSelector> name) {
       auto &ctx = Impl.SwiftContext;
-      decl->getAttrs().add(ObjCAttr::create(ctx, name, /*implicitName=*/true));
+      if (name) {
+        decl->getAttrs().add(ObjCAttr::create(ctx, name,
+                                              /*implicitName=*/true));
+      }
+      decl->setIsObjC(true);
 
       // If the declaration we attached the 'objc' attribute to is within a
       // class, record it in the class.
@@ -4378,7 +4384,6 @@
                           inheritedTypes);
       result->setValidationStarted();
       result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
-      result->setCheckedInheritanceClause();
       result->setMemberLoader(&Impl, 0);
 
       return result;
@@ -4516,7 +4521,6 @@
       importObjCProtocols(result, decl->getReferencedProtocols(),
                           inheritedTypes);
       result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
-      result->setCheckedInheritanceClause();
 
       // Compute the requirement signature.
       if (!result->isRequirementSignatureComputed())
@@ -4563,7 +4567,6 @@
         Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
         result->setCircularityCheck(CircularityCheck::Checked);
         result->setSuperclass(Type());
-        result->setCheckedInheritanceClause();
         result->setAddedImplicitInitializers(); // suppress all initializers
         addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
         result->addImplicitDestructor();
@@ -4720,7 +4723,6 @@
       importObjCProtocols(result, decl->getReferencedProtocols(),
                           inheritedTypes);
       result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
-      result->setCheckedInheritanceClause();
 
       // Add inferred attributes.
 #define INFERRED_ATTRIBUTES(ModuleName, ClassName, AttributeSet)               \
@@ -5144,7 +5146,6 @@
     SmallVector<TypeLoc, 4> inheritedTypes;
     inheritedTypes.push_back(TypeLoc::withoutLoc(superclass));
     theClass->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
-    theClass->setCheckedInheritanceClause();
   }
 
   addSynthesizedProtocolAttrs(Impl, theClass, {KnownProtocolKind::CFObject});
@@ -5305,7 +5306,6 @@
   auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
       decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
   structDecl->computeType();
-  structDecl->setCheckedInheritanceClause();
   structDecl->setAddedImplicitInitializers();
 
   // Import the type of the underlying storage
@@ -5584,7 +5584,6 @@
   auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
       decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
   structDecl->computeType();
-  structDecl->setCheckedInheritanceClause();
   structDecl->setAddedImplicitInitializers();
 
   makeStructRawValued(Impl, structDecl, underlyingType,
@@ -6515,7 +6514,8 @@
       auto swiftSel = Impl.importSelector(sel);
       for (auto found : classDecl->lookupDirect(swiftSel, true)) {
         if (auto foundFunc = dyn_cast<FuncDecl>(found))
-          return foundFunc;
+          if (foundFunc->hasClangNode())
+            return foundFunc;
       }
     }
 
@@ -8224,7 +8224,6 @@
   auto ext = ExtensionDecl::create(SwiftContext, SourceLoc(), swiftTyLoc, {},
                                    getClangModuleForDecl(decl), nullptr);
   ext->setValidationStarted();
-  ext->setCheckedInheritanceClause();
   ext->setMemberLoader(this, reinterpret_cast<uintptr_t>(declSubmodule));
 
   if (auto protoDecl = ext->getAsProtocolExtensionContext()) {
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 0784305..3c34aec 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -152,6 +152,7 @@
   Context.reset(ASTContext::get(Invocation.getLangOptions(),
                                 Invocation.getSearchPathOptions(), SourceMgr,
                                 Diagnostics));
+  registerTypeCheckerRequestFunctions(Context->evaluator);
 
   if (setUpModuleLoaders())
     return true;
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 89ff552..95aeda1 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -1338,14 +1338,12 @@
   /// to the \c Consumer.
   bool DeliveredResults = false;
 
-  bool typecheckContext(DeclContext *DC) {
+  void typeCheckContext(DeclContext *DC) {
     // Nothing to type check in module context.
     if (DC->isModuleScopeContext())
-      return true;
+      return;
 
-    // Type check the parent context.
-    if (!typecheckContext(DC->getParent()))
-      return false;
+    typeCheckContext(DC->getParent());
 
     // Type-check this context.
     switch (DC->getContextKind()) {
@@ -1353,31 +1351,38 @@
     case DeclContextKind::Initializer:
     case DeclContextKind::Module:
     case DeclContextKind::SerializedLocal:
+    case DeclContextKind::TopLevelCodeDecl:
       // Nothing to do for these.
-      return true;
+      break;
 
-    case DeclContextKind::AbstractFunctionDecl:
-      return typeCheckAbstractFunctionBodyUntil(
-                                  cast<AbstractFunctionDecl>(DC),
+    case DeclContextKind::AbstractFunctionDecl: {
+      auto *AFD = cast<AbstractFunctionDecl>(DC);
+
+      // FIXME: This shouldn't be necessary, but we crash otherwise.
+      if (auto *AD = dyn_cast<AccessorDecl>(AFD))
+        typeCheckCompletionDecl(AD->getStorage());
+
+      typeCheckAbstractFunctionBodyUntil(
+                                  AFD,
                                   P.Context.SourceMgr.getCodeCompletionLoc());
+      break;
+    }
 
     case DeclContextKind::ExtensionDecl:
-      return typeCheckCompletionDecl(cast<ExtensionDecl>(DC));
+      typeCheckCompletionDecl(cast<ExtensionDecl>(DC));
+      break;
 
     case DeclContextKind::GenericTypeDecl:
-      return typeCheckCompletionDecl(cast<GenericTypeDecl>(DC));
+      typeCheckCompletionDecl(cast<GenericTypeDecl>(DC));
+      break;
 
     case DeclContextKind::FileUnit:
       llvm_unreachable("module scope context handled above");
 
     case DeclContextKind::SubscriptDecl:
-      return typeCheckCompletionDecl(cast<SubscriptDecl>(DC));
-
-    case DeclContextKind::TopLevelCodeDecl:
-      return typeCheckTopLevelCodeDecl(cast<TopLevelCodeDecl>(DC));
+      typeCheckCompletionDecl(cast<SubscriptDecl>(DC));
+      break;
     }
-
-    llvm_unreachable("Unhandled DeclContextKind in switch.");
   }
 
   Optional<std::pair<Type, ConcreteDeclRef>> typeCheckParsedExpr() {
@@ -5186,8 +5191,16 @@
       CurDeclContext = DC;
   }
 
-  if (!typecheckContext(CurDeclContext))
-    return;
+  // The only time we have to explicitly check a TopLevelCodeDecl
+  // is when we're directly inside of one. In this case,
+  // performTypeChecking() did not type check it for us.
+  auto *DC = CurDeclContext;
+  while (isa<AbstractClosureExpr>(DC))
+    DC = DC->getParent();
+  if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(DC))
+    typeCheckTopLevelCodeDecl(TLCD);
+  else
+    typeCheckContext(CurDeclContext);
 
   Optional<Type> ExprType;
   ConcreteDeclRef ReferencedDecl = nullptr;
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index 36ee0b7..f6bbaa6 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -1612,7 +1612,7 @@
       return false;
 
     if (auto ASD = dyn_cast<AbstractStorageDecl>(D)) {
-      auto accessors = ASD->getAllAccessorFunctions();
+      auto accessors = ASD->getAllAccessors();
       Found.insert(accessors.begin(), accessors.end());
     }
     return true;
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index 03f149e..61b2c02 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -801,9 +801,9 @@
     else
       SR = VD->getSourceRange();
     SN.Range = charSourceRangeFromSourceRange(SM, SR);
-    if (VD->hasAccessorFunctions())
-      SN.BodyRange = innerCharSourceRangeFromSourceRange(SM,
-                                                         VD->getBracesRange());
+    auto bracesRange = VD->getBracesRange();
+    if (bracesRange.isValid())
+      SN.BodyRange = innerCharSourceRangeFromSourceRange(SM, bracesRange);
     SourceLoc NRStart = VD->getNameLoc();
     SourceLoc NREnd = NRStart.getAdvancedLoc(VD->getName().getLength());
     SN.NameRange = CharSourceRange(SM, NRStart, NREnd);
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index 257c601..1b900bd 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -2250,7 +2250,7 @@
                                            /*generics*/ nullptr,
                                            Context.TheBuiltinModule);
   SwiftRootClass->computeType();
-  SwiftRootClass->setIsObjC(true);
+  SwiftRootClass->setIsObjC(Context.LangOpts.EnableObjCInterop);
   SwiftRootClass->getAttrs().add(ObjCAttr::createNullary(Context, objcName,
     /*isNameImplicit=*/true));
   SwiftRootClass->setImplicit();
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index e0ee36d..0fce67f 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -2136,6 +2136,12 @@
   bool inFixedBuffer = false;
   bool indirectForDebugInfo = false;
 
+  // FIXME: Remove this once LLDB has proper support for resilience.
+  bool isREPLVar = false;
+  if (auto *decl = var->getDecl())
+    if (decl->isREPLVar())
+      isREPLVar = true;
+
   if (var->isInitializedObject()) {
     assert(ti.isFixedSize(expansion));
     StructLayout *Layout = StaticObjectLayouts[var].get();
@@ -2155,7 +2161,7 @@
     fixedSize = Layout->getSize();
     fixedAlignment = Layout->getAlignment();
     assert(fixedAlignment >= TargetInfo.HeapObjectAlignment);
-  } else if (ti.isFixedSize(expansion)) {
+  } else if (isREPLVar || ti.isFixedSize(expansion)) {
     // Allocate static storage.
     auto &fixedTI = cast<FixedTypeInfo>(ti);
     storageType = fixedTI.getStorageType();
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 3f9cdda..6ec7f07 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -481,11 +481,21 @@
     }
     
     void addName() {
+      SmallString<32> nameBuf;
       StringRef name;
-      
+
+      // Use the original name with tag for synthesized decls. The tag comes
+      // after the null terminator for the name.
+      if (auto *synthesizedTypeAttr =
+            Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+        nameBuf.append(synthesizedTypeAttr->originalTypeName);
+        nameBuf.push_back('\0');
+        nameBuf.append(synthesizedTypeAttr->getManglingName());
+        
+        name = nameBuf;
       // Try to use the Clang name if there is one.
-      if (auto namedClangDecl =
-                             Mangle::ASTMangler::getClangDeclForMangling(Type)) {
+      } else if (auto namedClangDecl =
+                            Mangle::ASTMangler::getClangDeclForMangling(Type)) {
         name = namedClangDecl->getName();
       } else {
         name = Type->getName().str();
@@ -565,22 +575,18 @@
     /// Flags to indicate Clang-imported declarations so we mangle them
     /// consistently at runtime.
     void getClangImportedFlags(TypeContextDescriptorFlags &flags) const {
-      auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type);
-      if (!clangDecl)
-        return;
-      
-      if (isa<clang::TagDecl>(clangDecl)) {
-        flags.setIsCTag(true);
-        return;
+      if (Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+        flags.setIsSynthesizedRelatedEntity(true);
       }
       
-      if (isa<clang::TypedefNameDecl>(clangDecl)
-          || isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
-        flags.setIsCTypedef(true);
-        return;
+      if (auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type)) {
+        if (isa<clang::TagDecl>(clangDecl)) {
+          flags.setIsCTag(true);
+        } else if (isa<clang::TypedefNameDecl>(clangDecl)
+                   || isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
+          flags.setIsCTypedef(true);
+        }
       }
-      
-      return;
     }
 
     // Subclasses should provide:
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index a9f6fc0..4553214 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -1859,9 +1859,15 @@
 
   auto expansion = IGM.getResilienceExpansionForLayout(var);
 
+  // FIXME: Remove this once LLDB has proper support for resilience.
+  bool isREPLVar = false;
+  if (auto *decl = var->getDecl())
+    if (decl->isREPLVar())
+      isREPLVar = true;
+
   // If the global is fixed-size in all resilience domains that can see it,
   // we allocated storage for it statically, and there's nothing to do.
-  if (ti.isFixedSize(expansion))
+  if (isREPLVar || ti.isFixedSize(expansion))
     return;
 
   // Otherwise, the static storage for the global consists of a fixed-size
@@ -1889,9 +1895,15 @@
   Address addr = IGM.getAddrOfSILGlobalVariable(var, ti,
                                                 NotForDefinition);
 
+  // FIXME: Remove this once LLDB has proper support for resilience.
+  bool isREPLVar = false;
+  if (auto *decl = var->getDecl())
+    if (decl->isREPLVar())
+      isREPLVar = true;
+
   // If the global is fixed-size in all resilience domains that can see it,
   // we allocated storage for it statically, and there's nothing to do.
-  if (ti.isFixedSize(expansion)) {
+  if (isREPLVar || ti.isFixedSize(expansion)) {
     setLoweredAddress(i, addr);
     return;
   }
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 3bccbb5..154447a 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -871,8 +871,11 @@
       auto isNullOrImplicit = [](const Decl *D) -> bool {
         return !D || D->isImplicit();
       };
+
+      bool usedPseudoAccessors = false;
       if (isa<VarDecl>(D) && isNullOrImplicit(StoreD->getGetter()) &&
           isNullOrImplicit(StoreD->getSetter())) {
+        usedPseudoAccessors = true;
         auto VarD = cast<VarDecl>(D);
         // No actual getter or setter, pass 'pseudo' accessors.
         // We create accessor entities so we can implement the functionality
@@ -885,33 +888,19 @@
           return false;
         if (!reportPseudoSetterDecl(VarD))
           return false;
-      } else {
-        if (auto FD = StoreD->getGetter())
-          SourceEntityWalker::walk(cast<Decl>(FD));
+      } 
+
+      for (auto accessor : StoreD->getAllAccessors()) {
+        // Don't include the implicit getter and setter if we added pseudo
+        // accessors above.
+        if (usedPseudoAccessors &&
+            (accessor->getAccessorKind() == AccessorKind::Get ||
+             accessor->getAccessorKind() == AccessorKind::Set))
+          continue;
+
+        SourceEntityWalker::walk(cast<Decl>(accessor));
         if (Cancelled)
           return false;
-        if (auto FD = StoreD->getSetter())
-          SourceEntityWalker::walk(cast<Decl>(FD));
-        if (Cancelled)
-          return false;
-      }
-      if (StoreD->hasObservers()) {
-        if (auto FD = StoreD->getWillSetFunc())
-          SourceEntityWalker::walk(cast<Decl>(FD));
-        if (Cancelled)
-          return false;
-        if (auto FD = StoreD->getDidSetFunc())
-          SourceEntityWalker::walk(cast<Decl>(FD));
-        if (Cancelled)
-          return false;
-      }
-      if (StoreD->hasAddressors()) {
-        if (auto FD = StoreD->getAddressor())
-          SourceEntityWalker::walk(cast<Decl>(FD));
-        if (Cancelled)
-          return false;
-        if (auto FD = StoreD->getMutableAddressor())
-          SourceEntityWalker::walk(cast<Decl>(FD));
       }
     } else if (auto NTD = dyn_cast<NominalTypeDecl>(D)) {
       if (!reportInheritedTypeRefs(NTD->getInherited(), NTD))
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 39dbb03..c507d36 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -675,6 +675,23 @@
       }
       return false;
     }
+    case SpecialCaseId::UIApplicationMain: {
+      // If the first argument is CommandLine.argc, replace the second argument
+      // with CommandLine.unsafeArgv
+      CallArgInfo &FirstArg = AllArgs[0];
+      // handle whitespace/line splits around the first arg when matching
+      auto FirstArgSplit =
+        SM.extractText(FirstArg.getEntireCharRange(SM)).rsplit('.');
+      if (!FirstArgSplit.second.empty() &&
+          FirstArgSplit.first.trim() == "CommandLine" &&
+          FirstArgSplit.second.trim() == "argc") {
+        CallArgInfo &SecondArg = AllArgs[1];
+        Editor.replace(SecondArg.getEntireCharRange(SM),
+                       "CommandLine.unsafeArgv");
+        return true;
+      }
+      return false;
+    }
     }
   }
 
diff --git a/lib/Migrator/overlay3.json b/lib/Migrator/overlay3.json
index 19c5d66..d0820c4 100644
--- a/lib/Migrator/overlay3.json
+++ b/lib/Migrator/overlay3.json
@@ -1316,4 +1316,9 @@
     "RightComment": "compactMap",
     "ModuleName": "Swift"
   },
+  {
+    "DiffItemKind": "SpecialCaseDiffItem",
+    "Usr": "c:@F@UIApplicationMain",
+    "SpecialCaseId": "UIApplicationMain"
+  }
 ]
diff --git a/lib/Migrator/overlay4.json b/lib/Migrator/overlay4.json
index 19c5d66..d0820c4 100644
--- a/lib/Migrator/overlay4.json
+++ b/lib/Migrator/overlay4.json
@@ -1316,4 +1316,9 @@
     "RightComment": "compactMap",
     "ModuleName": "Swift"
   },
+  {
+    "DiffItemKind": "SpecialCaseDiffItem",
+    "Usr": "c:@F@UIApplicationMain",
+    "SpecialCaseId": "UIApplicationMain"
+  }
 ]
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index acf9390..2e5b7f0 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -4540,7 +4540,7 @@
   storage->setAccessors(storageKind, LBLoc, Accessors, RBLoc);
 }
 
-AbstractStorageDecl::StorageKindTy
+StorageImplInfo
 Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
                                   bool invalid, ParseDeclOptions flags,
                                   SourceLoc staticLoc,
@@ -4631,6 +4631,18 @@
     }
   }
 
+  // Disallow observers with addressors.
+  if (Address || MutableAddress) {
+    if (WillSet) {
+      P.diagnose(WillSet->getLoc(), diag::observingproperty_with_address, 0);
+      ignoreInvalidAccessor(WillSet);
+    }
+    if (DidSet) {
+      P.diagnose(DidSet->getLoc(), diag::observingproperty_with_address, 1);
+      ignoreInvalidAccessor(DidSet);
+    }
+  }
+
   // If this is a willSet/didSet observing property, record this and we're done.
   if (WillSet || DidSet) {
     if (Get) {
@@ -4644,23 +4656,6 @@
       ignoreInvalidAccessor(Set);
     }
 
-    AbstractStorageDecl::StorageKindTy storageKind;
-    if (Address) {
-      if (!MutableAddress) {
-        P.diagnose(WillSet ? WillSet->getLoc() : DidSet->getLoc(),
-                   diag::observingproperty_without_mutableaddress,
-                   bool(DidSet));
-        createImplicitAccessor(AccessorKind::MutableAddress,
-                               AddressorKind::Unsafe, nullptr);
-      }
-
-      storageKind = AbstractStorageDecl::AddressedWithObservers;
-    } else if (attrs.hasAttribute<OverrideAttr>()) {
-      storageKind = AbstractStorageDecl::InheritedWithObservers;
-    } else {
-      storageKind = AbstractStorageDecl::StoredWithObservers;
-    }
-
     // Observing properties will have getters and setters synthesized by sema.
     // Create their prototypes now.
     createImplicitAccessor(AccessorKind::Get,
@@ -4675,13 +4670,27 @@
     createImplicitAccessor(AccessorKind::Set,
                            AddressorKind::NotAddressor, argList);
 
-    return storageKind;
+    if (attrs.hasAttribute<OverrideAttr>()) {
+      return StorageImplInfo(ReadImplKind::Inherited,
+                             WriteImplKind::InheritedWithObservers,
+                             ReadWriteImplKind::MaterializeToTemporary);
+    } else {
+      return StorageImplInfo(ReadImplKind::Stored,
+                             WriteImplKind::StoredWithObservers,
+                             ReadWriteImplKind::MaterializeToTemporary);
+    }
   }
 
   // If we have addressors, at this point mark it as addressed.
   if (Address) {
     assert(!Get && !Set);
-    return AbstractStorageDecl::Addressed;
+    if (MutableAddress) {
+      return StorageImplInfo(ReadImplKind::Address,
+                             WriteImplKind::MutableAddress,
+                             ReadWriteImplKind::MutableAddress);
+    } else {
+      return StorageImplInfo(ReadImplKind::Address);
+    }
   }
 
   // If this is a get+mutableAddress property, synthesize an implicit
@@ -4695,7 +4704,9 @@
     createImplicitAccessor(AccessorKind::Set,
                            AddressorKind::NotAddressor, argList);
 
-    return AbstractStorageDecl::ComputedWithMutableAddress;
+    return StorageImplInfo(ReadImplKind::Get,
+                           WriteImplKind::MutableAddress,
+                           ReadWriteImplKind::MutableAddress);
   }
 
   // Otherwise, this must be a get/set property.  The set is optional,
@@ -4718,17 +4729,19 @@
     }
   }
 
+  assert(!Set || Get);
+
   if (Set || Get) {
     if (attrs.hasAttribute<SILStoredAttr>())
       // Turn this into a stored property with trivial accessors.
-      return AbstractStorageDecl::StoredWithTrivialAccessors;
+      return StorageImplInfo::getSimpleStored(Set != nullptr);
     else
       // Turn this into a computed variable.
-      return AbstractStorageDecl::Computed;
+      return StorageImplInfo::getComputed(Set != nullptr);
   } else {
     // Otherwise this decl is invalid and the accessors have been rejected above.
     // Make sure to at least record the braces range in the AST.
-    return AbstractStorageDecl::Stored;
+    return StorageImplInfo::getSimpleStored(/*mutable*/ true);
   }
 }
 
@@ -4925,6 +4938,11 @@
       // global, record it.
       PBDEntries.back().setInitContext(initContext);
 
+      // If the attributes include @lazy, flag that on each initializer.
+      if (Attributes.hasAttribute<LazyAttr>()) {
+        PBDEntries.back().setInitializerLazy();
+      }
+
       // If we are doing second pass of code completion, we don't want to
       // suddenly cut off parsing and throw away the declaration.
       if (init.hasCodeCompletion() && isCodeCompletionFirstPass()) {
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index d3f0714..2522604 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -1301,7 +1301,7 @@
                  (accessorKind = getAccessorKind(Id.str())).hasValue()) {
         auto storageDecl = dyn_cast<AbstractStorageDecl>(VD);
         auto accessor = (storageDecl
-                           ? storageDecl->getAccessorFunction(*accessorKind)
+                           ? storageDecl->getAccessor(*accessorKind)
                            : nullptr);
         if (!accessor) {
           P.diagnose(IdLoc, diag::referenced_value_no_accessor, 0);
@@ -1312,8 +1312,7 @@
         // Update values for this accessor kind.
         for (unsigned I = 0, E = values.size(); I < E; I++)
           if (auto otherDecl = dyn_cast<AbstractStorageDecl>(values[I]))
-            if (auto otherAccessor =
-                  otherDecl->getAccessorFunction(*accessorKind))
+            if (auto otherAccessor = otherDecl->getAccessor(*accessorKind))
               values[I] = otherAccessor;
         ParseState = 1;
       } else if (!ParseState && Id.str() == "allocator") {
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index a70ccab..fc54291 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -754,7 +754,17 @@
       if (HadError) return;
       if (decl == Result) return;
       if (!Result) {
-        Result = cast<NominalTypeDecl>(decl);
+        // A synthesized type from the Clang importer may resolve to a
+        // compatibility alias.
+        if (auto resultAlias = dyn_cast<TypeAliasDecl>(decl)) {
+          if (resultAlias->isCompatibilityAlias()) {
+            Result = resultAlias->getUnderlyingTypeLoc().getType()
+                                ->getAnyNominal();
+          }
+        } else {
+          Result = dyn_cast<NominalTypeDecl>(decl);
+        }
+        HadError |= !Result;
       } else {
         HadError = true;
         Result = nullptr;
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 6c61fa5..cc07bc9 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -775,6 +775,10 @@
   if (isThunk() || isForeign)
     return SubclassScope::NotApplicable;
 
+  // Default arg generators only need to be visible in Swift 3.
+  if (isDefaultArgGenerator() && !context->getASTContext().isSwiftVersion3())
+    return SubclassScope::NotApplicable;
+
   auto *classType = context->getAsClassOrClassExtensionContext();
   if (!classType || classType->isFinal())
     return SubclassScope::NotApplicable;
diff --git a/lib/SIL/SILProfiler.cpp b/lib/SIL/SILProfiler.cpp
index 1509b15..f32b86f 100644
--- a/lib/SIL/SILProfiler.cpp
+++ b/lib/SIL/SILProfiler.cpp
@@ -140,8 +140,8 @@
                                     ASTWalker &Walker) {
   if (PBD && !PBD->isStatic())
     for (auto E : PBD->getPatternList())
-      if (E.getInit())
-        E.getInit()->walk(Walker);
+      if (auto init = E.getNonLazyInit())
+        init->walk(Walker);
 }
 
 /// Special logic for handling closure visitation.
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 5fc4e78..df4a5a7 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -216,19 +216,7 @@
     require(fieldTy == componentTy,
             "property decl should be a member of the base with the same type "
             "as the component");
-    switch (property->getStorageKind()) {
-    case AbstractStorageDecl::Stored:
-    case AbstractStorageDecl::StoredWithObservers:
-    case AbstractStorageDecl::StoredWithTrivialAccessors:
-      break;
-    case AbstractStorageDecl::Addressed:
-    case AbstractStorageDecl::AddressedWithObservers:
-    case AbstractStorageDecl::AddressedWithTrivialAccessors:
-    case AbstractStorageDecl::Computed:
-    case AbstractStorageDecl::ComputedWithMutableAddress:
-    case AbstractStorageDecl::InheritedWithObservers:
-      require(false, "property must be stored");
-    }
+    require(property->hasStorage(), "property must be stored");
     auto propertyTy = loweredBaseTy.getFieldType(property, M);
     require(propertyTy.getObjectType()
               == loweredComponentTy.getObjectType(),
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index 416ea7e..244f018 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -89,60 +89,35 @@
 CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture) {
   auto decl = capture.getDecl();
   if (auto *var = dyn_cast<VarDecl>(decl)) {
-    switch (var->getStorageKind()) {
-    case VarDecl::StoredWithTrivialAccessors:
-      llvm_unreachable("stored local variable with trivial accessors?");
+    assert(var->hasStorage() &&
+           "should not have attempted to directly capture this variable");
 
-    case VarDecl::InheritedWithObservers:
-      llvm_unreachable("inherited local variable?");
+    // If this is a non-address-only stored 'let' constant, we can capture it
+    // by value.  If it is address-only, then we can't load it, so capture it
+    // by its address (like a var) instead.
+    if (var->isImmutable() &&
+        (!SILModuleConventions(M).useLoweredAddresses() ||
+         !getTypeLowering(var->getType()).isAddressOnly()))
+      return CaptureKind::Constant;
 
-    case VarDecl::Computed:
-      llvm_unreachable("computed captured property should have been lowered "
-                       "away");
-
-    case VarDecl::StoredWithObservers:
-    case VarDecl::Addressed:
-    case VarDecl::AddressedWithTrivialAccessors:
-    case VarDecl::AddressedWithObservers:
-    case VarDecl::ComputedWithMutableAddress:
-      // Computed captures should have been lowered away.
-      assert(capture.isDirect()
-             && "computed captured property should have been lowered away");
-
-      // If captured directly, the variable is captured by box or pointer.
-      assert(var->hasStorage());
-      return capture.isNoEscape() ?
-        CaptureKind::StorageAddress : CaptureKind::Box;
-
-    case VarDecl::Stored:
-      // If this is a non-address-only stored 'let' constant, we can capture it
-      // by value.  If it is address-only, then we can't load it, so capture it
-      // by its address (like a var) instead.
-      if (var->isImmutable() &&
-          (!SILModuleConventions(M).useLoweredAddresses() ||
-           !getTypeLowering(var->getType()).isAddressOnly()))
-        return CaptureKind::Constant;
-
-      // In-out parameters are captured by address.
-      if (var->isInOut()) {
-        return CaptureKind::StorageAddress;
-      }
-
-      // Reference storage types can appear in a capture list, which means
-      // we might allocate boxes to store the captures. However, those boxes
-      // have the same lifetime as the closure itself, so we must capture
-      // the box itself and not the payload, even if the closure is noescape,
-      // otherwise they will be destroyed when the closure is formed.
-      if (var->getType()->is<ReferenceStorageType>()) {
-        return CaptureKind::Box;
-      }
-
-      // If we're capturing into a non-escaping closure, we can generally just
-      // capture the address of the value as no-escape.
-      return capture.isNoEscape() ?
-        CaptureKind::StorageAddress : CaptureKind::Box;
+    // In-out parameters are captured by address.
+    if (var->isInOut()) {
+      return CaptureKind::StorageAddress;
     }
-    llvm_unreachable("bad storage kind");
+
+    // Reference storage types can appear in a capture list, which means
+    // we might allocate boxes to store the captures. However, those boxes
+    // have the same lifetime as the closure itself, so we must capture
+    // the box itself and not the payload, even if the closure is noescape,
+    // otherwise they will be destroyed when the closure is formed.
+    if (var->getType()->is<ReferenceStorageType>()) {
+      return CaptureKind::Box;
+    }
+
+    // If we're capturing into a non-escaping closure, we can generally just
+    // capture the address of the value as no-escape.
+    return capture.isNoEscape() ?
+      CaptureKind::StorageAddress : CaptureKind::Box;
   }
   
   // "Captured" local types require no context.
@@ -2080,57 +2055,76 @@
       // If the capture is of a computed property, grab the transitive captures
       // of its accessors.
       if (auto capturedVar = dyn_cast<VarDecl>(capture.getDecl())) {
-        switch (capturedVar->getStorageKind()) {
-        case VarDecl::StoredWithTrivialAccessors:
-          llvm_unreachable("stored local variable with trivial accessors?");
+        if (!capture.isDirect()) {
+          auto impl = capturedVar->getImplInfo();
 
-        case VarDecl::InheritedWithObservers:
-          llvm_unreachable("inherited local variable?");
-
-        case VarDecl::StoredWithObservers:
-        case VarDecl::Addressed:
-        case VarDecl::AddressedWithTrivialAccessors:
-        case VarDecl::AddressedWithObservers:
-        case VarDecl::ComputedWithMutableAddress:
-          // Directly capture storage if we're supposed to.
-          if (capture.isDirect())
-            goto capture_value;
-
-          // Otherwise, transitively capture the accessors.
-          LLVM_FALLTHROUGH;
-
-        case VarDecl::Computed: {
-          collectFunctionCaptures(capturedVar->getGetter());
-          if (auto setter = capturedVar->getSetter())
-            collectFunctionCaptures(setter);
-          continue;
-        }
-
-        case VarDecl::Stored: {
-          // We can always capture the storage in these cases.
-          Type captureType = capturedVar->getType();
-          if (auto *metatypeType = captureType->getAs<MetatypeType>())
-            captureType = metatypeType->getInstanceType();
-
-          if (auto *selfType = captureType->getAs<DynamicSelfType>()) {
-            captureType = selfType->getSelfType();
-
-            // We're capturing a 'self' value with dynamic 'Self' type;
-            // handle it specially.
-            if (!selfCapture &&
-                captureType->getClassOrBoundGenericClass()) {
-              selfCapture = capture;
-              continue;
-            }
+          switch (impl.getReadImpl()) {
+          case ReadImplKind::Stored:
+            // Will capture storage later.
+            break;
+          case ReadImplKind::Address:
+            collectFunctionCaptures(capturedVar->getAddressor());
+            break;
+          case ReadImplKind::Get:
+            collectFunctionCaptures(capturedVar->getGetter());
+            break;
+          case ReadImplKind::Inherited:
+            llvm_unreachable("inherited local variable?");
           }
 
-          // Otherwise just fall through.
-          goto capture_value;
+          switch (impl.getWriteImpl()) {
+          case WriteImplKind::Immutable:
+          case WriteImplKind::Stored:
+            break;
+          case WriteImplKind::StoredWithObservers:
+          case WriteImplKind::Set:
+            collectFunctionCaptures(capturedVar->getSetter());
+            break;
+          case WriteImplKind::MutableAddress:
+            collectFunctionCaptures(capturedVar->getMutableAddressor());
+            break;
+          case WriteImplKind::InheritedWithObservers:
+            llvm_unreachable("inherited local variable");
+          }
+
+          switch (impl.getReadWriteImpl()) {
+          case ReadWriteImplKind::Immutable:
+          case ReadWriteImplKind::Stored:
+            break;
+          case ReadWriteImplKind::MaterializeToTemporary:
+            // We've already processed the read and write operations.
+            break;
+          case ReadWriteImplKind::MutableAddress:
+            collectFunctionCaptures(capturedVar->getMutableAddressor());
+            break;
+          case ReadWriteImplKind::MaterializeForSet:
+            llvm_unreachable("local variable with materializeForSet?");
+          }
         }
+
+        if (!capturedVar->hasStorage())
+          continue;
+
+        // We can always capture the storage in these cases.
+        Type captureType = capturedVar->getType();
+        if (auto *metatypeType = captureType->getAs<MetatypeType>())
+          captureType = metatypeType->getInstanceType();
+
+        if (auto *selfType = captureType->getAs<DynamicSelfType>()) {
+          captureType = selfType->getSelfType();
+
+          // We're capturing a 'self' value with dynamic 'Self' type;
+          // handle it specially.
+          if (!selfCapture &&
+              captureType->getClassOrBoundGenericClass()) {
+            selfCapture = capture;
+            continue;
+          }
         }
+
+        // Fall through to capture the storage.
       }
       
-    capture_value:
       // Collect non-function captures.
       captures.insert(capture);
     }
diff --git a/lib/SILGen/ASTVisitor.h b/lib/SILGen/ASTVisitor.h
index 1012b0f..72553ab 100644
--- a/lib/SILGen/ASTVisitor.h
+++ b/lib/SILGen/ASTVisitor.h
@@ -65,6 +65,11 @@
     return static_cast<ImplClass*>(this)->visit(E->getSubExpr(),
                                                 std::forward<Args>(AA)...);
   }
+
+  ExprRetTy visitLazyInitializerExpr(LazyInitializerExpr *E, Args...AA) {
+    return static_cast<ImplClass*>(this)->visit(E->getSubExpr(),
+                                                std::forward<Args>(AA)...);
+  }
 };
 
 template <typename ImplClass,
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index daf92b9..9039c3d 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -16,6 +16,7 @@
 #include "swift/Strings.h"
 #include "swift/AST/DiagnosticsSIL.h"
 #include "swift/AST/GenericEnvironment.h"
+#include "swift/AST/Initializer.h"
 #include "swift/AST/NameLookup.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/PrettyStackTrace.h"
@@ -731,9 +732,9 @@
       PrettyStackTraceSILFunction X("silgen emitFunction", f);
       auto accessor = dyn_cast<AccessorDecl>(fd);
       if (accessor && accessor->isMaterializeForSet())
-        SILGenFunction(*this, *f).emitMaterializeForSet(accessor);
+        SILGenFunction(*this, *f, accessor).emitMaterializeForSet(accessor);
       else
-        SILGenFunction(*this, *f).emitFunction(fd);
+        SILGenFunction(*this, *f, fd).emitFunction(fd);
       postEmitFunction(constant, f);
     }, /*forceEmission=*/ForCoverageMapping);
   }
@@ -772,7 +773,7 @@
         *this, constant, [this, constant, decl](SILFunction *f) {
           preEmitFunction(constant, decl, f, decl);
           PrettyStackTraceSILFunction X("silgen emitConstructor", f);
-          SILGenFunction(*this, *f).emitClassConstructorAllocator(decl);
+          SILGenFunction(*this, *f, decl).emitClassConstructorAllocator(decl);
           postEmitFunction(constant, f);
         });
 
@@ -788,7 +789,8 @@
                                           initF);
             initF->setProfiler(
                 getOrCreateProfilerForConstructors(declCtx, decl));
-            SILGenFunction(*this, *initF).emitClassConstructorInitializer(decl);
+            SILGenFunction(*this, *initF, decl)
+              .emitClassConstructorInitializer(decl);
             postEmitFunction(initConstant, initF);
           },
           /*forceEmission=*/ForCoverageMapping);
@@ -800,7 +802,7 @@
           preEmitFunction(constant, decl, f, decl);
           PrettyStackTraceSILFunction X("silgen emitConstructor", f);
           f->setProfiler(getOrCreateProfilerForConstructors(declCtx, decl));
-          SILGenFunction(*this, *f).emitValueConstructor(decl);
+          SILGenFunction(*this, *f, decl).emitValueConstructor(decl);
           postEmitFunction(constant, f);
         });
   }
@@ -813,7 +815,7 @@
   SILFunction *f = getFunction(constant, ForDefinition);
   preEmitFunction(constant, decl, f, decl);
   PrettyStackTraceSILFunction X("silgen enum constructor", f);
-  SILGenFunction(*this, *f).emitEnumConstructor(decl);
+  SILGenFunction(*this, *f, decl->getDeclContext()).emitEnumConstructor(decl);
   postEmitFunction(constant, f);
 }
 
@@ -832,7 +834,7 @@
 
   preEmitFunction(constant, ce, f, ce);
   PrettyStackTraceSILFunction X("silgen closureexpr", f);
-  SILGenFunction(*this, *f).emitClosure(ce);
+  SILGenFunction(*this, *f, ce).emitClosure(ce);
   postEmitFunction(constant, f);
   return f;
 }
@@ -848,7 +850,7 @@
     if (!pbd) continue;
 
     for (auto entry : pbd->getPatternList())
-      if (entry.getInit())
+      if (entry.getNonLazyInit())
         return true;
   }
 
@@ -887,7 +889,7 @@
     preEmitFunction(dealloc, dd, f, dd);
     PrettyStackTraceSILFunction X("silgen emitDestructor -dealloc", f);
     f->createProfiler(dd, ForDefinition);
-    SILGenFunction(*this, *f).emitObjCDestructor(dealloc);
+    SILGenFunction(*this, *f, dd).emitObjCDestructor(dealloc);
     postEmitFunction(dealloc, f);
   }
 
@@ -903,7 +905,7 @@
     SILFunction *f = getFunction(ivarInitializer, ForDefinition);
     preEmitFunction(ivarInitializer, dd, f, dd);
     PrettyStackTraceSILFunction X("silgen emitDestructor ivar initializer", f);
-    SILGenFunction(*this, *f).emitIVarInitializer(ivarInitializer);
+    SILGenFunction(*this, *f, cd).emitIVarInitializer(ivarInitializer);
     postEmitFunction(ivarInitializer, f);
   }
 
@@ -914,7 +916,7 @@
     SILFunction *f = getFunction(ivarDestroyer, ForDefinition);
     preEmitFunction(ivarDestroyer, dd, f, dd);
     PrettyStackTraceSILFunction X("silgen emitDestructor ivar destroyer", f);
-    SILGenFunction(*this, *f).emitIVarDestroyer(ivarDestroyer);
+    SILGenFunction(*this, *f, cd).emitIVarDestroyer(ivarDestroyer);
     postEmitFunction(ivarDestroyer, f);
   }
 }
@@ -928,7 +930,7 @@
     SILFunction *f = getFunction(ivarDestroyer, ForDefinition);
     preEmitFunction(ivarDestroyer, dd, f, dd);
     PrettyStackTraceSILFunction X("silgen emitDestructor ivar destroyer", f);
-    SILGenFunction(*this, *f).emitIVarDestroyer(ivarDestroyer);
+    SILGenFunction(*this, *f, dd).emitIVarDestroyer(ivarDestroyer);
     postEmitFunction(ivarDestroyer, f);
   }
 
@@ -945,7 +947,7 @@
     SILFunction *f = getFunction(destroyer, ForDefinition);
     preEmitFunction(destroyer, dd, f, dd);
     PrettyStackTraceSILFunction X("silgen emitDestroyingDestructor", f);
-    SILGenFunction(*this, *f).emitDestroyingDestructor(dd);
+    SILGenFunction(*this, *f, dd).emitDestroyingDestructor(dd);
     f->setDebugScope(new (M) SILDebugScope(dd, f));
     postEmitFunction(destroyer, f);
   }
@@ -957,14 +959,15 @@
     preEmitFunction(deallocator, dd, f, dd);
     PrettyStackTraceSILFunction X("silgen emitDeallocatingDestructor", f);
     f->createProfiler(dd, ForDefinition);
-    SILGenFunction(*this, *f).emitDeallocatingDestructor(dd);
+    SILGenFunction(*this, *f, dd).emitDeallocatingDestructor(dd);
     f->setDebugScope(new (M) SILDebugScope(dd, f));
     postEmitFunction(deallocator, f);
   }
 }
 
 void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, Expr *arg,
-                                           DefaultArgumentKind kind) {
+                                           DefaultArgumentKind kind,
+                                           DeclContext *initDC) {
   switch (kind) {
   case DefaultArgumentKind::None:
     llvm_unreachable("No default argument here?");
@@ -986,10 +989,11 @@
     return;
   }
 
-  emitOrDelayFunction(*this, constant, [this,constant,arg](SILFunction *f) {
+  emitOrDelayFunction(*this, constant,
+      [this,constant,arg,initDC](SILFunction *f) {
     preEmitFunction(constant, arg, f, arg);
     PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
-    SILGenFunction SGF(*this, *f);
+    SILGenFunction SGF(*this, *f, initDC);
     SGF.emitGeneratorFunction(constant, arg);
     postEmitFunction(constant, f);
   });
@@ -1000,9 +1004,12 @@
   const PatternBindingEntry &pbdEntry = pbd->getPatternList()[i];
   auto *var = pbdEntry.getAnchoringVarDecl();
   auto *init = pbdEntry.getInit();
+  auto *initDC = pbdEntry.getInitContext();
+  assert(!pbdEntry.isInitializerLazy());
 
   SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
-  emitOrDelayFunction(*this, constant, [this,constant,init,var](SILFunction *f) {
+  emitOrDelayFunction(*this, constant,
+                      [this,constant,init,initDC,var](SILFunction *f) {
     preEmitFunction(constant, init, f, init);
     PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
 
@@ -1010,7 +1017,7 @@
     f->setProfiler(
         getOrCreateProfilerForConstructors(var->getDeclContext(), nullptr));
 
-    SILGenFunction(*this, *f).emitGeneratorFunction(constant, init);
+    SILGenFunction(*this, *f, initDC).emitGeneratorFunction(constant, init);
     postEmitFunction(constant, f);
   });
 }
@@ -1033,7 +1040,8 @@
                        SILLocation(binding), IsNotBare, IsNotTransparent,
                        IsNotSerialized);
   f->setDebugScope(new (M) SILDebugScope(RegularLocation(binding), f));
-  SILGenFunction(*this, *f).emitLazyGlobalInitializer(binding, pbdEntry);
+  auto dc = binding->getDeclContext();
+  SILGenFunction(*this, *f, dc).emitLazyGlobalInitializer(binding, pbdEntry);
   f->verify();
 
   return f;
@@ -1047,7 +1055,7 @@
                       [this,accessor,global,onceToken,onceFunc](SILFunction *f){
     preEmitFunction(accessor, global, f, global);
     PrettyStackTraceSILFunction X("silgen emitGlobalAccessor", f);
-    SILGenFunction(*this, *f)
+    SILGenFunction(*this, *f, global->getDeclContext())
       .emitGlobalAccessor(global, onceToken, onceFunc);
     postEmitFunction(accessor, f);
   });
@@ -1059,7 +1067,8 @@
   for (auto param : *paramList) {
     if (auto defaultArg = param->getDefaultValue())
       emitDefaultArgGenerator(SILDeclRef::getDefaultArgGenerator(decl, index),
-                              defaultArg, param->getDefaultArgumentKind());
+                              defaultArg, param->getDefaultArgumentKind(),
+                              param->getDefaultArgumentInitContext());
     ++index;
   }
 }
@@ -1078,7 +1087,7 @@
   PrettyStackTraceSILFunction X("silgen emitObjCMethodThunk", f);
   f->setBare(IsBare);
   f->setThunk(IsThunk);
-  SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
+  SILGenFunction(*this, *f, method).emitNativeToForeignThunk(thunk);
   postEmitFunction(thunk, f);
 }
 
@@ -1104,7 +1113,8 @@
     PrettyStackTraceSILFunction X("silgen objc property getter thunk", f);
     f->setBare(IsBare);
     f->setThunk(IsThunk);
-    SILGenFunction(*this, *f).emitNativeToForeignThunk(getter);
+    SILGenFunction(*this, *f, prop->getGetter())
+      .emitNativeToForeignThunk(getter);
     postEmitFunction(getter, f);
   }
 
@@ -1120,7 +1130,7 @@
   PrettyStackTraceSILFunction X("silgen objc property setter thunk", f);
   f->setBare(IsBare);
   f->setThunk(IsThunk);
-  SILGenFunction(*this, *f).emitNativeToForeignThunk(setter);
+  SILGenFunction(*this, *f, prop->getSetter()).emitNativeToForeignThunk(setter);
   postEmitFunction(setter, f);
 }
 
@@ -1139,7 +1149,7 @@
   PrettyStackTraceSILFunction X("silgen objc constructor thunk", f);
   f->setBare(IsBare);
   f->setThunk(IsThunk);
-  SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
+  SILGenFunction(*this, *f, constructor).emitNativeToForeignThunk(thunk);
   postEmitFunction(thunk, f);
 }
 
@@ -1155,14 +1165,14 @@
   PrettyStackTraceSILFunction X("silgen objc destructor thunk", f);
   f->setBare(IsBare);
   f->setThunk(IsThunk);
-  SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
+  SILGenFunction(*this, *f, destructor).emitNativeToForeignThunk(thunk);
   postEmitFunction(thunk, f);
 }
 
 void SILGenModule::visitPatternBindingDecl(PatternBindingDecl *pd) {
   assert(!TopLevelSGF && "script mode PBDs should be in TopLevelCodeDecls");
   for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i)
-    if (pd->getInit(i))
+    if (pd->getNonLazyInit(i))
       emitGlobalInitialization(pd, i);
 }
 
@@ -1173,13 +1183,15 @@
   if (vd->hasStorage())
     addGlobalVariable(vd);
 
-  if (vd->getStorageKind() == AbstractStorageDecl::StoredWithTrivialAccessors) {
+  if (vd->getImplInfo().isSimpleStored()) {
     // If the global variable has storage, it might also have synthesized
     // accessors. Emit them here, since they won't appear anywhere else.
     if (auto getter = vd->getGetter())
       emitFunction(getter);
     if (auto setter = vd->getSetter())
       emitFunction(setter);
+    if (auto materializeForSet = vd->getMaterializeForSetFunc())
+      emitFunction(materializeForSet);
   }
   
   tryEmitPropertyDescriptor(vd);
@@ -1187,9 +1199,12 @@
 
 bool
 TypeConverter::canStorageUseStoredKeyPathComponent(AbstractStorageDecl *decl) {
-  switch (auto strategy = decl->getAccessStrategy(AccessSemantics::Ordinary,
-                                                  AccessKind::ReadWrite,
-                                                  M.getSwiftModule())) {
+  auto strategy = decl->getAccessStrategy(AccessSemantics::Ordinary,
+                                          decl->supportsMutation()
+                                            ? AccessKind::ReadWrite
+                                            : AccessKind::Read,
+                                          M.getSwiftModule());
+  switch (strategy.getKind()) {
   case AccessStrategy::Storage: {
     // If the stored value would need to be reabstracted in fully opaque
     // context, then we have to treat the component as computed.
@@ -1208,9 +1223,9 @@
     
     return storageTy.getAddressType() == opaqueTy.getAddressType();
   }
-  case AccessStrategy::Addressor:
   case AccessStrategy::DirectToAccessor:
   case AccessStrategy::DispatchToAccessor:
+  case AccessStrategy::MaterializeToTemporary:
     return false;
   case AccessStrategy::BehaviorStorage:
     llvm_unreachable("should not occur");
@@ -1488,7 +1503,7 @@
       // Assign a debug scope pointing into the void to the top level function.
       toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc, toplevel));
 
-      sgm.TopLevelSGF = new SILGenFunction(sgm, *toplevel);
+      sgm.TopLevelSGF = new SILGenFunction(sgm, *toplevel, sf);
       sgm.TopLevelSGF->MagicFunctionName = sgm.SwiftModule->getName();
       auto moduleCleanupLoc = CleanupLocation::getModuleCleanupLocation();
       sgm.TopLevelSGF->prepareEpilog(Type(), true, moduleCleanupLoc);
@@ -1599,7 +1614,7 @@
       toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc, toplevel));
 
       // Create the argc and argv arguments.
-      SILGenFunction SGF(sgm, *toplevel);
+      SILGenFunction SGF(sgm, *toplevel, sf);
       auto entry = SGF.B.getInsertionBB();
       auto paramTypeIter =
           SGF.F.getConventions().getParameterSILTypes().begin();
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index e00ec3a..a6e61ee 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -248,7 +248,7 @@
 
   /// Emits the default argument generator with the given expression.
   void emitDefaultArgGenerator(SILDeclRef constant, Expr *arg,
-                               DefaultArgumentKind kind);
+                               DefaultArgumentKind kind, DeclContext *DC);
 
   /// Emits the stored property initializer for the given pattern.
   void emitStoredPropertyInitialization(PatternBindingDecl *pd, unsigned i);
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 0410c0f..db9437f 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -5298,7 +5298,7 @@
   if (auto genericFnType = dyn_cast<GenericFunctionType>(origAccessType))
     genericSig = genericFnType.getGenericSignature();
 
-  return MaterializedLValue(ManagedValue::forUnmanaged(address),
+  return MaterializedLValue(ManagedValue::forLValue(address),
                             origSelfType, genericSig,
                             optionalCallback, callbackStorage);
 }
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 9575a81..68bbb0e 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -584,7 +584,7 @@
   // Build it if necessary.
   if (thunk->empty()) {
     thunk->setGenericEnvironment(genericEnv);
-    SILGenFunction thunkSGF(SGM, *thunk);
+    SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
     auto loc = RegularLocation::getAutoGeneratedLocation();
     // Not retaining the closure in the reabstraction thunk is safe if we hold
     // another reference for the is_escaping sentinel.
@@ -938,7 +938,7 @@
 
   // Build it if necessary.
   if (thunk->empty()) {
-    SILGenFunction thunkSGF(SGM, *thunk);
+    SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
     thunk->setGenericEnvironment(genericEnv);
     auto loc = RegularLocation::getAutoGeneratedLocation();
     buildBlockToFuncThunkBody(thunkSGF, loc, blockType, funcType,
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 9d37d5b..e1358da 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -940,7 +940,7 @@
       if (pbd->isStatic()) continue;
 
       for (auto entry : pbd->getPatternList()) {
-        auto init = entry.getInit();
+        auto init = entry.getNonLazyInit();
         if (!init) continue;
 
         // Cleanup after this initialization.
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index 6045189..e816a99 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -1141,7 +1141,7 @@
 
   // If an initial value expression was specified by the decl, emit it into
   // the initialization. Otherwise, mark it uninitialized for DI to resolve.
-  if (auto *Init = entry.getInit()) {
+  if (auto *Init = entry.getNonLazyInit()) {
     FullExpr Scope(Cleanups, CleanupLocation(Init));
     emitExprInto(Init, initialization.get(), SILLocation(PBD));
   } else {
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 703d4aa..14dc138 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -708,22 +708,29 @@
     return ManagedValue();
   }
 
-  switch (var->getAccessStrategy(semantics, accessKind)) {
+  auto strategy = var->getAccessStrategy(semantics, accessKind, FunctionDC);
+
+  switch (strategy.getKind()) {
   case AccessStrategy::Storage:
     // The only kind of stored variable that should make it to here is
     // a global variable.  Just invoke its accessor function to get its
     // address.
     return emitGlobalVariableRef(loc, var);
 
-  case AccessStrategy::Addressor: {
+  case AccessStrategy::DirectToAccessor:
+  case AccessStrategy::DispatchToAccessor: {
+    auto accessor = strategy.getAccessor();
+    if (accessor != AccessorKind::Address &&
+        accessor != AccessorKind::MutableAddress)
+      return ManagedValue();
+
     LValue lvalue =
       emitLValueForAddressedNonMemberVarDecl(loc, var, formalRValueType,
                                              accessKind, semantics);
     return emitAddressOfLValue(loc, std::move(lvalue), accessKind);
   }
 
-  case AccessStrategy::DirectToAccessor:
-  case AccessStrategy::DispatchToAccessor:
+  case AccessStrategy::MaterializeToTemporary:
     return ManagedValue();
     
   case AccessStrategy::BehaviorStorage:
@@ -1047,7 +1054,7 @@
                       ? Result : Result.copyUnmanaged(*this, loc));
     }
 
-    assert(var->hasAccessorFunctions() && "Unknown rvalue case");
+    assert(var->getGetter() && "Unknown rvalue case");
 
     SILDeclRef getter = SGM.getGetterDeclRef(var);
 
@@ -1074,7 +1081,8 @@
       selfSource = ArgumentSource(loc, std::move(metatypeRV));
     }
 
-    bool isDirectAccessorUse = (semantics == AccessSemantics::DirectToAccessor);
+    bool isDirectAccessorUse =
+      (semantics == AccessSemantics::DirectToImplementation);
     return emitGetAccessor(loc, getter,
                            SGM.getNonMemberVarDeclSubstitutions(var),
                            std::move(selfSource),
@@ -1109,19 +1117,27 @@
 static SILDeclRef getRValueAccessorDeclRef(SILGenFunction &SGF,
                                            AbstractStorageDecl *storage,
                                            AccessStrategy strategy) {
-  switch (strategy) {
+  switch (strategy.getKind()) {
   case AccessStrategy::BehaviorStorage:
     llvm_unreachable("shouldn't load an rvalue via behavior storage!");
   
   case AccessStrategy::Storage:
     llvm_unreachable("should already have been filtered out!");
 
-  case AccessStrategy::DirectToAccessor:
-  case AccessStrategy::DispatchToAccessor:
-    return SGF.SGM.getGetterDeclRef(storage);
+  case AccessStrategy::MaterializeToTemporary:
+    llvm_unreachable("never used for read accesses");    
 
-  case AccessStrategy::Addressor:
-    return SGF.SGM.getAddressorDeclRef(storage, AccessKind::Read);
+  case AccessStrategy::DirectToAccessor:
+  case AccessStrategy::DispatchToAccessor: {
+    auto accessor = strategy.getAccessor();
+    assert(accessor == AccessorKind::Get || accessor == AccessorKind::Address);
+    if (accessor == AccessorKind::Get) {
+      return SGF.SGM.getGetterDeclRef(storage);
+    } else {
+      return SGF.SGM.getAddressorDeclRef(storage, AccessKind::Read);  
+    }
+  }
+
   }
   llvm_unreachable("should already have been filtered out!");
 }
@@ -1136,26 +1152,18 @@
                        AbstractionPattern origFormalType,
                        CanType substFormalType,
                        SGFContext C) {
-  bool isDirectUse = (strategy == AccessStrategy::DirectToAccessor);
-
-  switch (strategy) {
-  case AccessStrategy::BehaviorStorage:
-    llvm_unreachable("shouldn't load an rvalue via behavior storage!");
-  
-  case AccessStrategy::Storage:
-    llvm_unreachable("should already have been filtered out!");
+  assert(strategy.getKind() == AccessStrategy::DirectToAccessor ||
+         strategy.getKind() == AccessStrategy::DispatchToAccessor);
+  bool isDirectUse = (strategy.getKind() == AccessStrategy::DirectToAccessor);
 
   // The easy path here is if we don't need to use an addressor.
-  case AccessStrategy::DirectToAccessor:
-  case AccessStrategy::DispatchToAccessor: {
+  if (strategy.getAccessor() == AccessorKind::Get) {
     return SGF.emitGetAccessor(loc, accessor, substitutions,
                                std::move(baseRV), isSuper, isDirectUse,
                                std::move(subscriptRV), C);
   }
 
-  case AccessStrategy::Addressor:
-    break;
-  }
+  assert(strategy.getAccessor() == AccessorKind::Address);
 
   auto &storageTL = SGF.getTypeLowering(origFormalType, substFormalType);
   SILType storageType = storageTL.getLoweredType().getAddressType();
@@ -1208,10 +1216,10 @@
     AccessSemantics semantics, Type propTy, SGFContext C,
     bool isBaseGuaranteed) {
   AccessStrategy strategy =
-    storage->getAccessStrategy(semantics, AccessKind::Read);
+    storage->getAccessStrategy(semantics, AccessKind::Read, FunctionDC);
 
   // If we should call an accessor of some kind, do so.
-  if (strategy != AccessStrategy::Storage) {
+  if (strategy.getKind() != AccessStrategy::Storage) {
     auto accessor = getRValueAccessorDeclRef(*this, storage, strategy);
     ArgumentSource baseRV = prepareAccessorBaseArg(loc, base,
                                                    baseFormalType,
@@ -2471,8 +2479,9 @@
 
     // Check that we have a stored access strategy. If we don't bail.
     AccessStrategy strategy =
-      Field->getAccessStrategy(Expr->getAccessSemantics(), AccessKind::Read);
-    if (strategy != AccessStrategy::Storage)
+      Field->getAccessStrategy(Expr->getAccessSemantics(), AccessKind::Read,
+                               SGF.FunctionDC);
+    if (strategy.getKind() != AccessStrategy::Storage)
       return None;
 
     if (isa<StructDecl>(Base))
@@ -3102,7 +3111,6 @@
                          SILLocation loc,
                          AbstractStorageDecl *property,
                          SubstitutionMap subs,
-                         AccessStrategy strategy,
                          GenericEnvironment *genericEnv,
                          ArrayRef<IndexTypePair> indexes,
                          CanType baseType,
@@ -3171,7 +3179,7 @@
     thunk->setGenericEnvironment(genericEnv);
   }
   
-  SILGenFunction subSGF(SGM, *thunk);
+  SILGenFunction subSGF(SGM, *thunk, SGM.SwiftModule);
   auto entry = thunk->begin();
   auto resultArgTy = result.getSILStorageType();
   auto baseArgTy = params[0].getSILStorageType();
@@ -3216,11 +3224,10 @@
   return thunk;
 }
 
-SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
+static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
                           SILLocation loc,
                           AbstractStorageDecl *property,
                           SubstitutionMap subs,
-                          AccessStrategy strategy,
                           GenericEnvironment *genericEnv,
                           ArrayRef<IndexTypePair> indexes,
                           CanType baseType,
@@ -3297,7 +3304,7 @@
     thunk->setGenericEnvironment(genericEnv);
   }
   
-  SILGenFunction subSGF(SGM, *thunk);
+  SILGenFunction subSGF(SGM, *thunk, SGM.SwiftModule);
   auto entry = thunk->begin();
   auto valueArgTy = params[0].getSILStorageType();
   auto baseArgTy = params[1].getSILStorageType();
@@ -3356,16 +3363,19 @@
     }
   }
 
+  auto semantics = AccessSemantics::Ordinary;
+  auto strategy = property->getAccessStrategy(semantics, AccessKind::Write);
+
   LValueOptions lvOptions;
   if (auto var = dyn_cast<VarDecl>(property)) {
     lv.addMemberVarComponent(subSGF, loc, var, subs, lvOptions,
                              /*super*/ false, AccessKind::Write,
-                             AccessSemantics::Ordinary, strategy, propertyType);
+                             semantics, strategy, propertyType);
   } else {
     auto sub = cast<SubscriptDecl>(property);
     lv.addMemberSubscriptComponent(subSGF, loc, sub, subs, lvOptions,
                                    /*super*/ false, AccessKind::Write,
-                                   AccessSemantics::Ordinary, strategy, propertyType,
+                                   semantics, strategy, propertyType,
                                    std::move(indexValue));
   }
 
@@ -3453,7 +3463,7 @@
       return;
     }
     
-    SILGenFunction subSGF(SGM, *equals);
+    SILGenFunction subSGF(SGM, *equals, SGM.SwiftModule);
     equals->setGenericEnvironment(genericEnv);
     auto entry = equals->begin();
     auto lhsPtr = entry->createFunctionArgument(params[0].getSILStorageType());
@@ -3617,7 +3627,7 @@
       return;
     }
     
-    SILGenFunction subSGF(SGM, *hash);
+    SILGenFunction subSGF(SGM, *hash, SGM.SwiftModule);
     hash->setGenericEnvironment(genericEnv);
     auto entry = hash->begin();
     auto indexPtr = entry->createFunctionArgument(params[0].getSILStorageType());
@@ -3709,11 +3719,19 @@
 getIdForKeyPathComponentComputedProperty(SILGenModule &SGM,
                                          AbstractStorageDecl *storage,
                                          AccessStrategy strategy) {
-  switch (strategy) {
+  switch (strategy.getKind()) {
   case AccessStrategy::Storage:
     // Identify reabstracted stored properties by the property itself.
     return cast<VarDecl>(storage);
-  case AccessStrategy::Addressor:
+  case AccessStrategy::MaterializeToTemporary:
+    // Use the read strategy.  But try to avoid turning e.g. an
+    // observed property into a stored property.
+    strategy = strategy.getReadStrategy();
+    if (strategy.getKind() != AccessStrategy::Storage ||
+        !storage->getGetter()) {
+      return getIdForKeyPathComponentComputedProperty(SGM, storage, strategy);
+    }
+    LLVM_FALLTHROUGH;
   case AccessStrategy::DirectToAccessor: {
     // Identify the property using its (unthunked) getter. For a
     // computed property, this should be stable ABI; for a resilient public
@@ -3799,8 +3817,9 @@
                                 CanType baseTy,
                                 bool forPropertyDescriptor) {
   auto strategy = storage->getAccessStrategy(AccessSemantics::Ordinary,
-                                          AccessKind::ReadWrite,
-                                          M.getSwiftModule());
+                                             storage->supportsMutation()
+                                               ? AccessKind::ReadWrite
+                                               : AccessKind::Read);
 
   if (auto var = dyn_cast<VarDecl>(storage)) {
     CanType componentTy;
@@ -3818,12 +3837,35 @@
   
     if (Types.canStorageUseStoredKeyPathComponent(var)) {
       return KeyPathPatternComponent::forStoredProperty(var, componentTy);
-    } else {
+    }
+
+    switch (strategy.getKind()) {
+    case AccessStrategy::BehaviorStorage:
+      llvm_unreachable("key path for behavior storage?");
+    case AccessStrategy::Storage: {
+      // If the stored value would need to be reabstracted in fully opaque
+      // context, then we have to treat the component as computed.
+      auto componentObjTy = componentTy->getWithoutSpecifierType();
+      if (genericEnv)
+        componentObjTy = genericEnv->mapTypeIntoContext(componentObjTy);
+      auto storageTy = Types.getSubstitutedStorageType(var, componentObjTy);
+      auto opaqueTy = Types
+        .getLoweredType(AbstractionPattern::getOpaque(), componentObjTy);
+      
+      if (storageTy.getAddressType() == opaqueTy.getAddressType()) {
+        return KeyPathPatternComponent::forStoredProperty(var, componentTy);
+      }
+      LLVM_FALLTHROUGH;
+    }
+    case AccessStrategy::MaterializeToTemporary:
+    case AccessStrategy::DirectToAccessor:
+    case AccessStrategy::DispatchToAccessor: {
+      // We need thunks to bring the getter and setter to the right signature
+      // expected by the key path runtime.
       auto id = getIdForKeyPathComponentComputedProperty(*this, var,
                                                          strategy);
       auto getter = getOrCreateKeyPathGetter(*this, loc,
                var, subs,
-               strategy,
                needsGenericContext ? genericEnv : nullptr,
                {},
                baseTy, componentTy);
@@ -3831,7 +3873,6 @@
       if (var->isSettable(var->getDeclContext())) {
         auto setter = getOrCreateKeyPathSetter(*this, loc,
                var, subs,
-               strategy,
                needsGenericContext ? genericEnv : nullptr,
                {},
                baseTy, componentTy);
@@ -3842,6 +3883,7 @@
             getter, {}, nullptr, nullptr, componentTy);
       }
     }
+    }
   }
   
   if (auto decl = dyn_cast<SubscriptDecl>(storage)) {
@@ -3875,7 +3917,6 @@
     auto id = getIdForKeyPathComponentComputedProperty(*this, decl, strategy);
     auto getter = getOrCreateKeyPathGetter(*this, loc,
              decl, subs,
-             strategy,
              needsGenericContext ? genericEnv : nullptr,
              indexTypes,
              baseTy, componentTy);
@@ -3884,7 +3925,6 @@
     if (decl->isSettable()) {
       auto setter = getOrCreateKeyPathSetter(*this, loc,
              decl, subs,
-             strategy,
              needsGenericContext ? genericEnv : nullptr,
              indexTypes,
              baseTy, componentTy);
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 3590262..d0d5b89 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -30,10 +30,12 @@
 // SILGenFunction Class implementation
 //===----------------------------------------------------------------------===//
 
-SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F)
-    : SGM(SGM), F(F), silConv(SGM.M), StartOfPostmatter(F.end()),
-      B(*this), OpenedArchetypesTracker(&F),
+SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F,
+                               DeclContext *DC)
+    : SGM(SGM), F(F), silConv(SGM.M), FunctionDC(DC),
+      StartOfPostmatter(F.end()), B(*this), OpenedArchetypesTracker(&F),
       CurrentSILLoc(F.getLocation()), Cleanups(*this) {
+  assert(DC && "creating SGF without a DeclContext?");
   B.setInsertionPoint(createBasicBlock());
   B.setCurrentDebugScope(F.getDebugScope());
   B.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 50c389f..d7c69d8 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -167,6 +167,9 @@
   /// The SILModuleConventions for this SIL module.
   SILModuleConventions silConv;
 
+  /// The DeclContext corresponding to the function currently being emitted.
+  DeclContext * const FunctionDC;
+
   /// The name of the function currently being emitted, as presented to user
   /// code by #function.
   DeclName MagicFunctionName;
@@ -380,7 +383,7 @@
   /// Get the PGO node's parent.
   Optional<ASTNode> getPGOParent(ASTNode Node) const;
 
-  SILGenFunction(SILGenModule &SGM, SILFunction &F);
+  SILGenFunction(SILGenModule &SGM, SILFunction &F, DeclContext *DC);
   ~SILGenFunction();
   
   /// Return a stable reference to the current cleanup.
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index e2afa61..f85301f 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -490,6 +490,15 @@
   return addr;
 }
 
+static ManagedValue enterAccessScope(SILGenFunction &SGF, SILLocation loc,
+                                     ManagedValue addr, LValueTypeData typeData,
+                                     AccessKind accessKind,
+                                     SILAccessEnforcement enforcement) {
+  return ManagedValue::forLValue(
+           enterAccessScope(SGF, loc, addr.getLValueAddress(), typeData,
+                            accessKind, enforcement));
+}
+
 // Find the base of the formal access at `address`. If the base requires an
 // access marker, then create a begin_access on `address`. Return the
 // address to be used for the access.
@@ -503,11 +512,8 @@
     return address;
 
   const AccessedStorage &storage = findAccessedStorage(address);
-  if (!storage) {
-    llvm::dbgs() << "Bad memory access source: " << address;
-    llvm_unreachable("Unexpected access source.");
-  }
-  if (!isPossibleFormalAccessBase(storage, &SGF.F))
+  // Unsafe access may have invalid storage (e.g. a RawPointer).
+  if (storage && !isPossibleFormalAccessBase(storage, &SGF.F))
     return address;
 
   auto BAI =
@@ -979,7 +985,7 @@
 
 static LValueOptions getBaseOptions(LValueOptions options,
                                     AccessStrategy strategy) {
-  return (strategy == AccessStrategy::Storage
+  return (strategy.getKind() == AccessStrategy::Storage
             ? options.forProjectedBaseLValue()
             : options.forComputedBaseLValue());
 }
@@ -1310,11 +1316,15 @@
         // of whether the base is trivial because even a trivial base
         // may be value-dependent on something non-trivial.
         if (base) {
-          SILValue temporary = materialized.temporary.getValue();
-          materialized.temporary = ManagedValue::forUnmanaged(
+          SILValue temporary = materialized.temporary.getLValueAddress();
+          materialized.temporary = ManagedValue::forLValue(
               SGF.B.createMarkDependence(loc, temporary, base.getValue()));
         }
       }
+      // Enter an access scope for the temporary.
+      materialized.temporary =
+        enterAccessScope(SGF, loc, materialized.temporary, getTypeData(),
+                         accessKind, SILAccessEnforcement::Unsafe);
 
       // TODO: maybe needsWriteback should be a thin function pointer
       // to which we pass the base?  That would let us use direct
@@ -1487,22 +1497,15 @@
       // It could be overridden by a computed property in a subclass, but
       // that's not likely enough to be worth the strictness here.
       if (auto storage = dyn_cast<AbstractStorageDecl>(decl)) {
-        switch (storage->getStorageKind()) {
-        case AbstractStorageDecl::Stored:
-        case AbstractStorageDecl::StoredWithTrivialAccessors:
-        case AbstractStorageDecl::Addressed:
-        case AbstractStorageDecl::AddressedWithTrivialAccessors:
-          return;
+        auto impl = storage->getImplInfo();
         // TODO: Stored properties with didSet accessors that don't look at the
         // oldValue could also be addressed.
-        case AbstractStorageDecl::StoredWithObservers:
-        case AbstractStorageDecl::AddressedWithObservers:
-          break;
-          
-        case AbstractStorageDecl::InheritedWithObservers:
-        case AbstractStorageDecl::Computed:
-        case AbstractStorageDecl::ComputedWithMutableAddress:
-          break;
+        if ((impl.getReadImpl() == ReadImplKind::Stored ||
+             impl.getReadImpl() == ReadImplKind::Address) &&
+            (impl.getWriteImpl() == WriteImplKind::Immutable ||
+             impl.getWriteImpl() == WriteImplKind::Stored ||
+             impl.getWriteImpl() == WriteImplKind::MutableAddress)) {
+          return;
         }
       }
       
@@ -1628,6 +1631,7 @@
             IsSuper,
             IsDirectAccessorUse, std::move(args.subscripts), SubstFieldType);
       }
+
       switch (cast<AccessorDecl>(addressor.getDecl())->getAddressorKind()) {
       case AddressorKind::NotAddressor:
         llvm_unreachable("not an addressor!");
@@ -1635,13 +1639,13 @@
       // For unsafe addressors, we have no owner pointer to manage.
       case AddressorKind::Unsafe:
         assert(!result.second);
-        return result.first;
+        break;
 
       // For owning addressors, we can just let the owner get released
       // at an appropriate point.
       case AddressorKind::Owning:
       case AddressorKind::NativeOwning:
-        return result.first;
+        break;
 
       // For pinning addressors, we have to push a writeback.
       case AddressorKind::NativePinning: {
@@ -1649,10 +1653,16 @@
           component(new UnpinPseudoComponent(getTypeData()));
         pushWriteback(SGF, loc, std::move(component), result.second,
                       MaterializedLValue());
-        return result.first;
+        break;
       }
       }
-      llvm_unreachable("bad addressor kind");
+
+      // Enter an unsafe access scope for the access.
+      auto addr = result.first;
+      addr = enterAccessScope(SGF, loc, addr, getTypeData(), accessKind,
+                              SILAccessEnforcement::Unsafe);
+
+      return addr;
     }
 
     void dump(raw_ostream &OS, unsigned indent) const override {
@@ -2285,13 +2295,22 @@
                                             AccessSemantics semantics) {
   LValue lv;
 
-  switch (var->getAccessStrategy(semantics, accessKind)) {
+  auto strategy = var->getAccessStrategy(semantics, accessKind, SGF.FunctionDC);
+  switch (strategy.getKind()) {
 
   case AccessStrategy::DispatchToAccessor:
     llvm_unreachable("can't polymorphically access non-member variable");
 
   // If it's a computed variable, push a reference to the getter and setter.
-  case AccessStrategy::DirectToAccessor: {
+  case AccessStrategy::DirectToAccessor:
+    if (strategy.getAccessor() == AccessorKind::Address ||
+        strategy.getAccessor() == AccessorKind::MutableAddress) {
+      addNonMemberVarDeclAddressorComponent(SGF.SGM, var, formalRValueType, lv);
+      break;
+    }
+    LLVM_FALLTHROUGH;
+  case AccessStrategy::MaterializeToTemporary: {
+    // FIXME: this is not correct for all materialization-based strategies.
     auto typeData = getLogicalStorageTypeData(SGF.SGM, formalRValueType);
     lv.add<GetterSetterComponent>(var, /*isSuper=*/false, /*direct*/ true,
                                   SGF.SGM.getNonMemberVarDeclSubstitutions(var),
@@ -2299,11 +2318,6 @@
     break;
   }
 
-  case AccessStrategy::Addressor: {
-    addNonMemberVarDeclAddressorComponent(SGF.SGM, var, formalRValueType, lv);
-    break;
-  }
-
   case AccessStrategy::Storage: {
     // If it's a physical value (e.g. a local variable in memory), push its
     // address.
@@ -2421,23 +2435,31 @@
 static AccessKind getBaseAccessKind(AbstractStorageDecl *member,
                                     AccessKind accessKind,
                                     AccessStrategy strategy) {
-  switch (strategy) {
+  switch (strategy.getKind()) {
   // Assume that the member only partially projects the enclosing value.
   case AccessStrategy::Storage:
     return (accessKind == AccessKind::Read
               ? AccessKind::Read : AccessKind::ReadWrite);
 
-  case AccessStrategy::Addressor:
-    return getBaseAccessKindForAccessor(
-                           member->getAddressorForAccess(accessKind));
+  case AccessStrategy::MaterializeToTemporary: {
+    assert(accessKind == AccessKind::ReadWrite);
+    auto writeBaseKind = getBaseAccessKind(member, AccessKind::Write,
+                                           strategy.getWriteStrategy());
+
+    // Fast path for the common case that the write will need to mutate
+    // the base.
+    if (writeBaseKind == AccessKind::ReadWrite)
+      return writeBaseKind;
+
+    auto readBaseKind = getBaseAccessKind(member, AccessKind::Read,
+                                          strategy.getReadStrategy());
+    return combineAccessKinds(readBaseKind, writeBaseKind);
+  }
 
   case AccessStrategy::DirectToAccessor:
   case AccessStrategy::DispatchToAccessor:
-    if (accessKind == AccessKind::Read) {
-      return getBaseAccessKindForAccessor(member->getGetter());
-    } else {
-      return getBaseAccessKindForAccessor(member->getSetter());
-    }
+    return getBaseAccessKindForAccessor(
+             member->getAccessor(strategy.getAccessor()));
     
   case AccessStrategy::BehaviorStorage:
     // We should only access the behavior storage for initialization purposes.
@@ -2454,7 +2476,7 @@
   // that can be an lvalue is a VarDecl.
   VarDecl *var = cast<VarDecl>(e->getMember().getDecl());
   AccessStrategy strategy =
-    var->getAccessStrategy(e->getAccessSemantics(), accessKind);
+    var->getAccessStrategy(e->getAccessSemantics(), accessKind, SGF.FunctionDC);
 
   LValue lv = visitRec(e->getBase(),
                        getBaseAccessKind(var, accessKind, strategy),
@@ -2470,6 +2492,38 @@
   return lv;
 }
 
+static bool isDirectAccessorUse(AccessStrategy strategy) {
+  switch (strategy.getKind()) {
+  case AccessStrategy::Storage:
+  case AccessStrategy::BehaviorStorage:
+    // This is only necessary to support because of the recursive use in
+    // MaterializeToTemporary.
+    //llvm_unreachable("not an accessor use");
+    return false;
+
+  case AccessStrategy::MaterializeToTemporary:
+    // FIXME: this case should never be handled this way.
+    return isDirectAccessorUse(strategy.getReadStrategy()) ||
+           isDirectAccessorUse(strategy.getWriteStrategy());
+
+  case AccessStrategy::DirectToAccessor:
+    return true;
+
+  case AccessStrategy::DispatchToAccessor:
+    return false;
+  }
+  llvm_unreachable("bad access strategy");
+}
+
+static AccessorKind getRepresentativeAccessor(AccessStrategy strategy) {
+  // HACK: this is only necessary because we don't do the generally-correct
+  // thing yet for MaterializeToTemporary.
+  if (strategy.getKind() == AccessStrategy::MaterializeToTemporary)
+    return AccessorKind::MaterializeForSet;
+
+  return strategy.getAccessor();
+}
+
 void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
                                    VarDecl *var,
                                    SubstitutionMap subs,
@@ -2481,66 +2535,79 @@
                                    CanType formalRValueType) {
   CanType baseFormalType = getSubstFormalType();
 
-  // Use the property accessors if the variable has accessors and this isn't a
-  // direct access to underlying storage.
-  if (strategy == AccessStrategy::DirectToAccessor ||
-      strategy == AccessStrategy::DispatchToAccessor) {
+  switch (strategy.getKind()) {
+  case AccessStrategy::Storage: {
+    // For static variables, emit a reference to the global variable backing
+    // them.
+    // FIXME: This has to be dynamically looked up for classes, and
+    // dynamically instantiated for generics.
+    if (var->isStatic()) {
+      // FIXME: this implicitly drops the earlier components, but maybe
+      // we ought to evaluate them for side-effects even during the
+      // formal access?
+      *this = emitLValueForNonMemberVarDecl(SGF, loc, var,
+                                            formalRValueType, accessKind,
+                                            options, accessSemantics);
+      return;
+    }
+
+    // Otherwise, it's a physical member.
+    SILType varStorageType =
+      SGF.SGM.Types.getSubstitutedStorageType(var, formalRValueType);
+    auto typeData = getPhysicalStorageTypeData(SGF.SGM, var, formalRValueType);
+
+    if (baseFormalType->mayHaveSuperclass()) {
+      add<RefElementComponent>(var, options, varStorageType, typeData);
+    } else {
+      assert(baseFormalType->getStructOrBoundGenericStruct());
+      add<StructElementComponent>(var, varStorageType, typeData);
+    }
+    
+    // If the member has weak or unowned storage, convert it away.
+    if (varStorageType.is<ReferenceStorageType>()) {
+      add<OwnershipComponent>(typeData);
+    }
+    return;
+  }
+
+  case AccessStrategy::MaterializeToTemporary: // FIXME
+  case AccessStrategy::DirectToAccessor:
+  case AccessStrategy::DispatchToAccessor: {
+    auto accessor = getRepresentativeAccessor(strategy);
+
+    if (accessor == AccessorKind::Address ||
+        accessor == AccessorKind::MutableAddress) {
+      SILType varStorageType =
+        SGF.SGM.Types.getSubstitutedStorageType(var, formalRValueType);
+      auto typeData = getPhysicalStorageTypeData(SGF.SGM, var, formalRValueType);
+
+      add<AddressorComponent>(var, isSuper, /*direct*/ true, subs,
+                              baseFormalType, typeData, varStorageType);
+      return;
+    }
+
+    // Use the property accessors if the variable has accessors and this isn't a
+    // direct access to underlying storage.
+    bool isDirect = isDirectAccessorUse(strategy);
     auto typeData = getLogicalStorageTypeData(SGF.SGM, formalRValueType);
-    add<GetterSetterComponent>(var, isSuper,
-                               strategy == AccessStrategy::DirectToAccessor,
+    add<GetterSetterComponent>(var, isSuper, isDirect,
                                subs, baseFormalType, typeData);
     return;
   }
 
-  assert(strategy == AccessStrategy::Addressor ||
-         strategy == AccessStrategy::Storage ||
-         strategy == AccessStrategy::BehaviorStorage);
-
-  // Otherwise, the lvalue access is performed with a fragile element reference.
-  // Find the substituted storage type.
-  SILType varStorageType =
-    SGF.SGM.Types.getSubstitutedStorageType(var, formalRValueType);
-    
-  // For static variables, emit a reference to the global variable backing
-  // them.
-  // FIXME: This has to be dynamically looked up for classes, and
-  // dynamically instantiated for generics.
-  if (strategy == AccessStrategy::Storage && var->isStatic()) {
-    // FIXME: this implicitly drops the earlier components, but maybe
-    // we ought to evaluate them for side-effects even during the
-    // formal access?
-    *this = emitLValueForNonMemberVarDecl(SGF, loc, var,
-                                          formalRValueType, accessKind,
-                                          options, accessSemantics);
-    return;
-  }
-
-  auto typeData = getPhysicalStorageTypeData(SGF.SGM, var, formalRValueType);
-
   // For behavior initializations, we should have set up a marking proxy that
   // replaces the access path.
-  if (strategy == AccessStrategy::BehaviorStorage) {
+  case AccessStrategy::BehaviorStorage: {
     auto addr = SGF.VarLocs.find(var);
     assert(addr != SGF.VarLocs.end() && addr->second.value);
     Path.clear();
+    auto typeData = getPhysicalStorageTypeData(SGF.SGM, var, formalRValueType);
     add<ValueComponent>(ManagedValue::forUnmanaged(addr->second.value),
                         None, typeData);
-  // For member variables, this access is done w.r.t. a base computation that
-  // was already emitted.  This member is accessed off of it.
-  } else if (strategy == AccessStrategy::Addressor) {
-    add<AddressorComponent>(var, isSuper, /*direct*/ true, subs,
-                            baseFormalType, typeData, varStorageType);
-  } else if (baseFormalType->mayHaveSuperclass()) {
-    add<RefElementComponent>(var, options, varStorageType, typeData);
-  } else {
-    assert(baseFormalType->getStructOrBoundGenericStruct());
-    add<StructElementComponent>(var, varStorageType, typeData);
+    return;
   }
-  
-  // If the member has weak or unowned storage, convert it away.
-  if (varStorageType.is<ReferenceStorageType>()) {
-    add<OwnershipComponent>(typeData);
   }
+  llvm_unreachable("bad access strategy");
 }
 
 LValue SILGenLValue::visitSubscriptExpr(SubscriptExpr *e,
@@ -2549,7 +2616,8 @@
   auto decl = cast<SubscriptDecl>(e->getDecl().getDecl());
 
   auto accessSemantics = e->getAccessSemantics();
-  auto strategy = decl->getAccessStrategy(accessSemantics, accessKind);
+  auto strategy =
+    decl->getAccessStrategy(accessSemantics, accessKind, SGF.FunctionDC);
   
   LValue lv = visitRec(e->getBase(),
                        getBaseAccessKind(decl, accessKind, strategy),
@@ -2627,22 +2695,36 @@
                                          Expr *indexExprForDiagnostics) {
   CanType baseFormalType = getSubstFormalType();
 
-  if (strategy == AccessStrategy::DirectToAccessor ||
-      strategy == AccessStrategy::DispatchToAccessor) {
-    auto typeData = getLogicalStorageTypeData(SGF.SGM, formalRValueType);
-    add<GetterSetterComponent>(decl, isSuper,
-                               strategy == AccessStrategy::DirectToAccessor,
-                               subs, baseFormalType, typeData,
-                               indexExprForDiagnostics, &indices);
-  } else {
-    assert(strategy == AccessStrategy::Addressor);
-    auto typeData = getPhysicalStorageTypeData(SGF.SGM, decl, formalRValueType);
-    auto storageType = 
-      SGF.SGM.Types.getSubstitutedStorageType(decl, formalRValueType);
-    add<AddressorComponent>(decl, isSuper, /*direct*/ true,
-                            subs, baseFormalType, typeData, storageType,
-                            indexExprForDiagnostics, &indices);
+  switch (strategy.getKind()) {
+  case AccessStrategy::Storage:
+    llvm_unreachable("subscripts never have storage");
+
+  case AccessStrategy::BehaviorStorage:
+    llvm_unreachable("subscripts never have behaviors");
+
+  case AccessStrategy::MaterializeToTemporary:
+  case AccessStrategy::DirectToAccessor:
+  case AccessStrategy::DispatchToAccessor: {
+    auto accessor = getRepresentativeAccessor(strategy);
+    if (accessor == AccessorKind::Address ||
+        accessor == AccessorKind::MutableAddress) {
+      auto typeData = getPhysicalStorageTypeData(SGF.SGM, decl, formalRValueType);
+      auto storageType = 
+        SGF.SGM.Types.getSubstitutedStorageType(decl, formalRValueType);
+      add<AddressorComponent>(decl, isSuper, /*direct*/ true,
+                              subs, baseFormalType, typeData, storageType,
+                              indexExprForDiagnostics, &indices);
+    } else {
+      bool isDirect = isDirectAccessorUse(strategy);
+      auto typeData = getLogicalStorageTypeData(SGF.SGM, formalRValueType);
+      add<GetterSetterComponent>(decl, isSuper, isDirect,
+                                 subs, baseFormalType, typeData,
+                                 indexExprForDiagnostics, &indices);
+    }
+    return;
   }
+  }
+  llvm_unreachable("bad access strategy");
 }
 
 bool LValue::isObviouslyNonConflicting(const LValue &other,
@@ -2786,49 +2868,62 @@
     ->getCanonicalType();
 
   AccessStrategy strategy =
-    ivar->getAccessStrategy(semantics, accessKind);
+    ivar->getAccessStrategy(semantics, accessKind, FunctionDC);
 
 
   // Use the property accessors if the variable has accessors and this
   // isn't a direct access to underlying storage.
-  if (strategy == AccessStrategy::DirectToAccessor ||
-      strategy == AccessStrategy::DispatchToAccessor) {
-    auto typeData = getLogicalStorageTypeData(SGM, substFormalType);
-    lv.add<GetterSetterComponent>(ivar, /*super*/ false,
-                                  strategy == AccessStrategy::DirectToAccessor,
-                                  subMap, baseFormalType, typeData);
+  switch (strategy.getKind()) {
+  case AccessStrategy::Storage: {
+    // Find the substituted storage type.
+    SILType varStorageType =
+      SGM.Types.getSubstitutedStorageType(ivar, substFormalType);
+    auto typeData = getPhysicalStorageTypeData(SGM, ivar, substFormalType);
+
+    if (baseFormalType->hasReferenceSemantics()) {
+      lv.add<RefElementComponent>(ivar, options, varStorageType, typeData);
+    } else {
+      lv.add<StructElementComponent>(ivar, varStorageType, typeData);
+    }
+
+    if (varStorageType.is<ReferenceStorageType>()) {
+      auto formalRValueType =
+        ivar->getDeclContext()->mapTypeIntoContext(ivar->getInterfaceType())
+            ->getReferenceStorageReferent()
+            ->getCanonicalType();
+      auto typeData =
+        getPhysicalStorageTypeData(SGM, ivar, formalRValueType);
+      lv.add<OwnershipComponent>(typeData);
+    }
     return lv;
   }
 
-  assert(strategy == AccessStrategy::Addressor ||
-         strategy == AccessStrategy::Storage);
+  case AccessStrategy::DirectToAccessor:
+  case AccessStrategy::DispatchToAccessor:
+  case AccessStrategy::MaterializeToTemporary: {
+    auto accessor = getRepresentativeAccessor(strategy);
+    bool isDirect = isDirectAccessorUse(strategy);
+    if (accessor == AccessorKind::Address ||
+        accessor == AccessorKind::MutableAddress) {
+      SILType varStorageType =
+        SGM.Types.getSubstitutedStorageType(ivar, substFormalType);
+      auto typeData = getPhysicalStorageTypeData(SGM, ivar, substFormalType);
 
-  // Find the substituted storage type.
-  SILType varStorageType =
-    SGM.Types.getSubstitutedStorageType(ivar, substFormalType);
-
-  auto typeData = getPhysicalStorageTypeData(SGM, ivar, substFormalType);
-
-  if (strategy == AccessStrategy::Addressor) {
-    lv.add<AddressorComponent>(ivar, /*super*/ false, /*direct*/ true,
-                               subMap, baseFormalType, typeData, varStorageType);
-  } else if (baseFormalType->hasReferenceSemantics()) {
-    lv.add<RefElementComponent>(ivar, options, varStorageType, typeData);
-  } else {
-    lv.add<StructElementComponent>(ivar, varStorageType, typeData);
+      lv.add<AddressorComponent>(ivar, /*super*/ false, isDirect,
+                                 subMap, baseFormalType, typeData,
+                                 varStorageType);
+    } else {
+      auto typeData = getLogicalStorageTypeData(SGM, substFormalType);
+      lv.add<GetterSetterComponent>(ivar, /*super*/ false, isDirect,
+                                    subMap, baseFormalType, typeData);
+    }
+    return lv;
   }
 
-  if (varStorageType.is<ReferenceStorageType>()) {
-    auto formalRValueType =
-      ivar->getDeclContext()->mapTypeIntoContext(ivar->getInterfaceType())
-          ->getReferenceStorageReferent()
-          ->getCanonicalType();
-    auto typeData =
-      getPhysicalStorageTypeData(SGM, ivar, formalRValueType);
-    lv.add<OwnershipComponent>(typeData);
+  case AccessStrategy::BehaviorStorage:
+    llvm_unreachable("behaviors not expected here?");
   }
-
-  return lv;
+  llvm_unreachable("bad kind");
 }
 
 // This is emitLoad that will handle re-abstraction and bridging for the client.
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index 0f3f90b..2d4b300 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -345,18 +345,16 @@
     emitter.RequirementStoragePattern = emitter.WitnessStoragePattern;
     emitter.RequirementStorageType = emitter.WitnessStorageType;
 
-    // When we're emitting a standard implementation, use direct semantics.
-    // If we used TheAccessSemantics::Ordinary here, the only downside would
-    // be unnecessary vtable dispatching for class materializeForSets.
-    if (!emitter.WitnessStorage->hasObservers() &&
-        (emitter.WitnessStorage->hasStorage() ||
-         emitter.WitnessStorage->hasAddressors()))
-      emitter.TheAccessSemantics = AccessSemantics::DirectToStorage;
-    else if (emitter.WitnessStorage->hasClangNode() ||
-             emitter.WitnessStorage->isDynamic())
+    if (emitter.WitnessStorage->hasClangNode() ||
+        emitter.WitnessStorage->isDynamic()) {
       emitter.TheAccessSemantics = AccessSemantics::Ordinary;
-    else
-      emitter.TheAccessSemantics = AccessSemantics::DirectToAccessor;
+
+    // When we're emitting a standard implementation, use direct semantics.
+    // If we used AccessSemantics::Ordinary here, the only downside would
+    // be unnecessary vtable dispatching for class materializeForSets.
+    } else {
+      emitter.TheAccessSemantics = AccessSemantics::DirectToImplementation;
+    }
 
     emitter.CallbackName = getMaterializeForSetCallbackName(
         /*conformance=*/None, witness);
@@ -491,7 +489,8 @@
     LValue lv = buildSelfLValue(SGF, loc, self);
 
     auto strategy =
-      WitnessStorage->getAccessStrategy(TheAccessSemantics, accessKind);
+      WitnessStorage->getAccessStrategy(TheAccessSemantics, accessKind,
+                                        SGF.FunctionDC);
 
     // Drill down to the member storage.
     lv.addMemberComponent(SGF, loc, WitnessStorage, WitnessSubs,
@@ -557,14 +556,22 @@
 
   // If there's an abstraction difference, we always need to use the
   // get/set pattern.
-  AccessStrategy strategy;
-  if (WitnessStorage->getInterfaceType()->is<ReferenceStorageType>() ||
-      (RequirementStorageType != WitnessStorageType)) {
-    strategy = AccessStrategy::DispatchToAccessor;
-  } else {
-    strategy = WitnessStorage->getAccessStrategy(TheAccessSemantics,
-                                                 AccessKind::ReadWrite);
-  }
+  AccessStrategy strategy = [&] {
+    if (WitnessStorage->getInterfaceType()->is<ReferenceStorageType>() ||
+        (RequirementStorageType != WitnessStorageType)) {
+      return AccessStrategy::getMaterializeToTemporary(
+               WitnessStorage->getAccessStrategy(TheAccessSemantics,
+                                                 AccessKind::Read,
+                                                 SGF.FunctionDC),
+               WitnessStorage->getAccessStrategy(TheAccessSemantics,
+                                                 AccessKind::Write,
+                                                 SGF.FunctionDC));
+    } else {
+      return WitnessStorage->getAccessStrategy(TheAccessSemantics,
+                                               AccessKind::ReadWrite,
+                                               SGF.FunctionDC);
+    }
+  }();
 
   // Handle the indices.
   RValue indicesRV;
@@ -579,7 +586,7 @@
   // Choose the right implementation.
   SILValue address;
   SILFunction *callbackFn = nullptr;
-  switch (strategy) {
+  switch (strategy.getKind()) {
   case AccessStrategy::BehaviorStorage:
     llvm_unreachable("materializeForSet should never engage in behavior init");
   
@@ -588,13 +595,15 @@
                                callbackBuffer, callbackFn);
     break;
 
-  case AccessStrategy::Addressor:
-    address = emitUsingAddressor(SGF, loc, self, std::move(indicesRV),
-                                 callbackBuffer, callbackFn);
-    break;
-
   case AccessStrategy::DirectToAccessor:
   case AccessStrategy::DispatchToAccessor:
+    if (strategy.getAccessor() == AccessorKind::MutableAddress) {
+      address = emitUsingAddressor(SGF, loc, self, std::move(indicesRV),
+                                   callbackBuffer, callbackFn);
+      break;      
+    }
+    LLVM_FALLTHROUGH;
+  case AccessStrategy::MaterializeToTemporary:
     address = emitUsingGetterSetter(SGF, loc, self, std::move(indicesRV),
                                     resultBuffer, callbackBuffer, callbackFn);
     break;
@@ -719,7 +728,8 @@
 
   PrettyStackTraceSILFunction X("silgen materializeForSet callback", callback);
   {
-    SILGenFunction SGF(SGM, *callback);
+    SILGenFunction SGF(SGM, *callback,
+                       WitnessStorage->getMaterializeForSetFunc());
 
     auto makeParam = [&](unsigned index) -> SILArgument * {
       SILType type = SGF.F.mapTypeIntoContext(
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 612a875..3d884bb 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -2901,7 +2901,7 @@
   // Build it if necessary.
   if (thunk->empty()) {
     thunk->setGenericEnvironment(genericEnv);
-    SILGenFunction thunkSGF(SGF.SGM, *thunk);
+    SILGenFunction thunkSGF(SGF.SGM, *thunk, SGF.FunctionDC);
     auto loc = RegularLocation::getAutoGeneratedLocation();
     buildThunkBody(thunkSGF, loc,
                    inputOrigType,
@@ -3011,7 +3011,7 @@
 
   if (thunk->empty()) {
     thunk->setGenericEnvironment(genericEnv);
-    SILGenFunction thunkSGF(SGM, *thunk);
+    SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
     buildWithoutActuallyEscapingThunkBody(thunkSGF);
   }
 
@@ -3623,7 +3623,7 @@
                                                  canonicalTy, F.isSerialized());
   if (thunk->empty()) {
     thunk->setGenericEnvironment(genericEnv);
-    SILGenFunction thunkSGF(SGM, *thunk);
+    SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
     auto loc = RegularLocation::getAutoGeneratedLocation();
     buildCanonicalFunctionThunkBody(thunkSGF, loc, nonCanonicalTy, canonicalTy);
   }
diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp
index 88990d7..57cdc4f 100644
--- a/lib/SILGen/SILGenThunk.cpp
+++ b/lib/SILGen/SILGenThunk.cpp
@@ -58,7 +58,7 @@
     // Currently a dynamic thunk looks just like a foreign-to-native thunk around
     // an ObjC method. This would change if we introduced a native
     // runtime-hookable mechanism.
-    SILGenFunction SGF(*this, *F);
+    SILGenFunction SGF(*this, *F, SwiftModule);
     SGF.emitForeignToNativeThunk(constant);
   }
 
@@ -201,7 +201,7 @@
   preEmitFunction(constant, fd, f, fd);
   PrettyStackTraceSILFunction X("silgen emitCurryThunk", f);
 
-  SILGenFunction(*this, *f).emitCurryThunk(constant);
+  SILGenFunction(*this, *f, SwiftModule).emitCurryThunk(constant);
   postEmitFunction(constant, f);
 }
 
@@ -214,7 +214,7 @@
     f->setSerialized(IsSerializable);
   preEmitFunction(thunk, thunk.getDecl(), f, thunk.getDecl());
   PrettyStackTraceSILFunction X("silgen emitForeignToNativeThunk", f);
-  SILGenFunction(*this, *f).emitForeignToNativeThunk(thunk);
+  SILGenFunction(*this, *f, SwiftModule).emitForeignToNativeThunk(thunk);
   postEmitFunction(thunk, f);
 }
 
@@ -231,7 +231,7 @@
   PrettyStackTraceSILFunction X("silgen emitNativeToForeignThunk", f);
   f->setBare(IsBare);
   f->setThunk(IsThunk);
-  SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
+  SILGenFunction(*this, *f, SwiftModule).emitNativeToForeignThunk(thunk);
   postEmitFunction(thunk, f);
 }
 
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index aea67a9..21210c6 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -138,7 +138,7 @@
                        IsNotTransparent, IsNotSerialized);
   thunk->setDebugScope(new (M) SILDebugScope(loc, thunk));
 
-  SILGenFunction(*this, *thunk)
+  SILGenFunction(*this, *thunk, theClass)
     .emitVTableThunk(derived, implFn, basePattern,
                      overrideInfo.LoweredType,
                      derivedInfo.LoweredType);
@@ -341,7 +341,7 @@
 
     auto witnessStorage = cast<AbstractStorageDecl>(witness.getDecl());
     auto witnessAccessor =
-      witnessStorage->getAccessorFunction(reqAccessor->getAccessorKind());
+      witnessStorage->getAccessor(reqAccessor->getAccessorKind());
     if (!witnessAccessor)
       return asDerived().addMissingMethod(requirementRef);
 
@@ -676,7 +676,7 @@
   PrettyStackTraceSILFunction trace("generating protocol witness thunk", f);
 
   // Create the witness.
-  SILGenFunction SGF(*this, *f);
+  SILGenFunction SGF(*this, *f, SwiftModule);
 
   // Substitutions mapping the generic parameters of the witness to
   // archetypes of the witness thunk generic environment.
@@ -864,7 +864,7 @@
   void visitPatternBindingDecl(PatternBindingDecl *pd) {
     // Emit initializers.
     for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i) {
-      if (pd->getInit(i)) {
+      if (pd->getNonLazyInit(i)) {
         if (pd->isStatic())
           SGM.emitGlobalInitialization(pd, i);
         else
@@ -955,7 +955,7 @@
   void visitPatternBindingDecl(PatternBindingDecl *pd) {
     // Emit initializers for static variables.
     for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i) {
-      if (pd->getInit(i)) {
+      if (pd->getNonLazyInit(i)) {
         assert(pd->isStatic() && "stored property in extension?!");
         SGM.emitGlobalInitialization(pd, i);
       }
diff --git a/lib/SILOptimizer/Analysis/AccessedStorageAnalysis.cpp b/lib/SILOptimizer/Analysis/AccessedStorageAnalysis.cpp
index 4948288..32695b3 100644
--- a/lib/SILOptimizer/Analysis/AccessedStorageAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/AccessedStorageAnalysis.cpp
@@ -174,7 +174,7 @@
   for (auto &rawStorageInfo : otherStorageAccesses) {
     const StorageAccessInfo &otherStorageInfo =
       transformStorage(rawStorageInfo);
-    // transformStorage() returns invalid storage object for local storage
+    // If transformStorage() returns invalid storage object for local storage,
     // that should not be merged with the caller.
     if (!otherStorageInfo)
       continue;
@@ -272,7 +272,9 @@
     SILValue argVal = getCallerArg(fullApply, storage.getParamIndex());
     if (argVal) {
       // Remap the argument source value and inherit the old storage info.
-      return StorageAccessInfo(findAccessedStorageNonNested(argVal), storage);
+      auto calleeStorage = findAccessedStorageNonNested(argVal);
+      if (calleeStorage)
+        return StorageAccessInfo(calleeStorage, storage);
     }
     // If the argument can't be transformed, demote it to an unidentified
     // access.
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 5156bdd..e2dfc57 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -678,6 +678,10 @@
     auto *GetterRef = B.createFunctionRef(Call->getLoc(), GetterF);
     auto *NewAI = B.createApply(Call->getLoc(), GetterRef, Args, false);
 
+    // FIXME: This is asserting that a specific SIL sequence follows an
+    // addressor! SIL passes should never do this without first specifying a
+    // structural SIL property independent of the SILOptimizer and enforced by
+    // the SILVerifier.
     for (auto Use : Call->getUses()) {
       auto *PTAI = dyn_cast<PointerToAddressInst>(Use->getUser());
       assert(PTAI && "All uses should be pointer_to_address");
diff --git a/lib/SILOptimizer/LoopTransforms/LICM.cpp b/lib/SILOptimizer/LoopTransforms/LICM.cpp
index d9556ed..285e456 100644
--- a/lib/SILOptimizer/LoopTransforms/LICM.cpp
+++ b/lib/SILOptimizer/LoopTransforms/LICM.cpp
@@ -203,6 +203,17 @@
   LoopNestSummary(LoopNestSummary &&) = delete;
 };
 
+static unsigned getEdgeIndex(SILBasicBlock *BB, SILBasicBlock *ExitingBB) {
+  auto Succs = ExitingBB->getSuccessors();
+  for (unsigned EdgeIdx = 0; EdgeIdx < Succs.size(); ++EdgeIdx) {
+    SILBasicBlock *CurrBB = Succs[EdgeIdx];
+    if (CurrBB == BB) {
+      return EdgeIdx;
+    }
+  }
+  llvm_unreachable("BB is not a Successor");
+}
+
 static bool sinkInstruction(DominanceInfo *DT,
                             std::unique_ptr<LoopNestSummary> &LoopSummary,
                             SILInstruction *Inst, SILLoopInfo *LI) {
@@ -216,14 +227,20 @@
 
   bool Changed = false;
   for (auto *ExitingBB : ExitingBBs) {
+    SmallVector<SILBasicBlock *, 8> BBSuccessors;
     auto Succs = ExitingBB->getSuccessors();
     for (unsigned EdgeIdx = 0; EdgeIdx < Succs.size(); ++EdgeIdx) {
       SILBasicBlock *BB = Succs[EdgeIdx];
+      BBSuccessors.push_back(BB);
+    }
+    while (!BBSuccessors.empty()) {
+      SILBasicBlock *BB = BBSuccessors.pop_back_val();
       if (std::find(NewExitBBs.begin(), NewExitBBs.end(), BB) !=
           NewExitBBs.end()) {
         // Already got a copy there
         continue;
       }
+      auto EdgeIdx = getEdgeIndex(BB, ExitingBB);
       SILBasicBlock *OutsideBB = nullptr;
       if (std::find(ExitBBs.begin(), ExitBBs.end(), BB) != ExitBBs.end()) {
         auto *SplitBB =
@@ -472,8 +489,18 @@
     return false;
   }
 
+  // We can’t hoist everything that is hoist-able
+  // The canHoist method does not do all the required analysis
+  // Some of the work is done at COW Array Opt
+  // TODO: Refactor COW Array Opt + canHoist - radar 41601468
   ArraySemanticsCall semCall(inst);
-  return semCall.canHoist(Preheader->getTerminator(), DT);
+  switch (semCall.getKind()) {
+  case ArrayCallKind::kGetCount:
+  case ArrayCallKind::kGetCapacity:
+    return semCall.canHoist(Preheader->getTerminator(), DT);
+  default:
+    return false;
+  }
 }
 
 // Check If all the end accesses of the given begin do not prevent hoisting
diff --git a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
index c477e27..a2cb57a 100644
--- a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
@@ -30,10 +30,10 @@
 using namespace swift;
 
 // This temporary option allows markers during optimization passes. Enabling
-// this flag causes this pass to preserve only dynamic checks when dynamic
-// checking is enabled. Otherwise, this pass removes all checks.
+// this flag causes this pass to preserve all access markers. Otherwise, it only
+// preserved "dynamic" markers.
 llvm::cl::opt<bool> EnableOptimizedAccessMarkers(
-    "sil-optimized-access-markers", llvm::cl::init(true),
+    "sil-optimized-access-markers", llvm::cl::init(false),
     llvm::cl::desc("Enable memory access markers during optimization passes."));
 
 namespace {
@@ -70,8 +70,8 @@
 
 bool AccessMarkerElimination::shouldPreserveAccess(
     SILAccessEnforcement enforcement) {
-  if (!EnableOptimizedAccessMarkers)
-    return false;
+  if (EnableOptimizedAccessMarkers || Mod->getOptions().VerifyExclusivity)
+    return true;
 
   switch (enforcement) {
   case SILAccessEnforcement::Static:
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
index 93a9c79..53517d5 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
@@ -734,6 +734,8 @@
     SILValue Argument = Apply.getArgument(ArgumentIndex);
     assert(Argument->getType().isAddress());
 
+    // A valid AccessedStorage should alway sbe found because Unsafe accesses
+    // are not tracked by AccessSummaryAnalysis.
     const AccessedStorage &Storage = findValidAccessedStorage(Argument);
     auto AccessIt = State.Accesses->find(Storage);
 
@@ -817,6 +819,9 @@
     SILAccessKind Kind = BAI->getAccessKind();
     const AccessedStorage &Storage =
       findValidAccessedStorage(BAI->getSource());
+    // Storage may be associated with a nested access where the outer access is
+    // "unsafe". That's ok because the outer access can itself be treated like a
+    // valid source, as long as we don't ask for its source.
     AccessInfo &Info = (*State.Accesses)[Storage];
     const IndexTrieNode *SubPath = State.ASA->findSubPathAccessed(BAI);
     if (auto Conflict = shouldReportAccess(Info, Kind, SubPath)) {
@@ -1071,7 +1076,16 @@
   // initialization, not a formal memory access. The strength of
   // verification rests on the completeness of the opcode list inside
   // findAccessedStorage.
-  if (!storage || !isPossibleFormalAccessBase(storage, memInst->getFunction()))
+  //
+  // For the purpose of verification, an unidentified access is
+  // unenforced. These occur in cases like global addressors and local buffers
+  // that make use of RawPointers.
+  if (!storage || storage.getKind() == AccessedStorage::Unidentified)
+    return;
+
+  // Some identifiable addresses can also be recognized as local initialization
+  // or other patterns that don't qualify as formal access.
+  if (!isPossibleFormalAccessBase(storage, memInst->getFunction()))
     return;
 
   // A box or stack variable may represent lvalues, but they can only conflict
diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp
index e837dc4..22529ce 100644
--- a/lib/SILOptimizer/PassManager/PassPipeline.cpp
+++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp
@@ -479,6 +479,7 @@
 static void addLastChanceOptPassPipeline(SILPassPipelinePlan &P) {
   // Optimize access markers for improved IRGen after all other optimizations.
   P.addAccessEnforcementOpts();
+  P.addAccessEnforcementWMO();
 
   // Only has an effect if the -assume-single-thread option is specified.
   P.addAssumeSingleThreaded();
diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp
index 9b47513..dcef0b3 100644
--- a/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp
+++ b/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp
@@ -285,7 +285,7 @@
   }
   bool hasConflictFreeAccess() const {
     NoNestedConflictIterator iterator(*this);
-    return iterator.next() == nullptr;
+    return iterator.next() != nullptr;
   }
 
   bool hasInScopeAccess() const {
@@ -624,6 +624,9 @@
     if (F->empty())
       return;
 
+    DEBUG(llvm::dbgs() << "Running local AccessEnforcementOpts on "
+                       << F->getName() << "\n");
+
     PostOrderFunctionInfo *PO = getAnalysis<PostOrderAnalysis>()->get(F);
     AccessedStorageAnalysis *ASA = getAnalysis<AccessedStorageAnalysis>();
     auto result = AccessConflictAnalysis(F, PO, ASA).analyze();
diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp
new file mode 100644
index 0000000..3440a83
--- /dev/null
+++ b/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp
@@ -0,0 +1,277 @@
+//===--- AccessEnforcementWMO.cpp - Whole-module access enforcement opt ---===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+///
+/// This module pass removes dynamic access enforcement based on whole module
+/// information.
+///
+/// This maps each access of identified storage onto a disjoint access
+/// location. Local accesses (Box and Stack) already have unique AccessedStorage
+/// and should be removed by an earlier function pass. This pass handles Class
+/// and Global access by partitioning their non-unique AccessedStorage objects
+/// into unique DisjointAccessLocations. These disjoint access locations may be
+/// accessed across multiple functions, so a module pass is required to identify
+/// and optimize them.
+///
+/// Class accesses are partitioned by their fully qualified property
+/// name. Global accesses are partitioned by the global variable name. Argument
+/// accesses are ignored because they are considered an access in the caller,
+/// while Class and Global access always occurs in the callee. Note that a SIL
+/// function argument value may be the source of a either a Class-kind
+/// AccessedStorage or an Argument-kind AccessedStorage. When the argument is
+/// used to access a class, it will always be identified as a Class-kind
+/// AccessedStorage even though its source is an argument.
+///
+/// For each function, discover the disjointly accessed locations. Each location
+/// is optimistically mapped to a `noNestedConflict` flag (if a location has not
+/// been mapped, then it is assumed not to have nested conflict). Each location
+/// without any nested conflict maps to a set of accesses that the optimization
+/// may be able to remove.
+///
+/// After analyzing all functions in the module, disable any class property and
+/// global variable access that still have not seen any nested conflicts by
+/// giving them static enforcement.
+///
+/// Warning: This is only sound when unidentified accesses can never alias with
+/// Class/Global access. To enforce this, the SILVerifier calls
+/// findAccessedStorage() for every access, which asserts that any Unidentified
+/// access belongs to a know pattern that cannot originate from Class or Global
+/// accesses.
+///
+/// Note: This optimization must be aware of all possible access to a Class or
+/// Global address. This includes unpaired access instructions and keypath
+/// instructions. Ignoring any access pattern would weaken enforcement.
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "access-enforcement-wmo"
+
+#include "swift/SIL/DebugUtils.h"
+#include "swift/SIL/MemAccessUtils.h"
+#include "swift/SIL/SILFunction.h"
+#include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/SILOptimizer/Utils/Local.h"
+
+using namespace swift;
+
+using llvm::DenseMap;
+using llvm::SmallDenseSet;
+
+// Get the VarDecl that represents the DisjointAccessLocation for the given
+// AccessedStorage. Returns nullptr for any storage that can't be partitioned
+// into a disjoint location.
+//
+// findAccessedStorage may only return Unidentified storage for a global
+// variable access if the global is defined in a different module.
+VarDecl *getDisjointAccessLocation(const AccessedStorage &storage) {
+  switch (storage.getKind()) {
+  case AccessedStorage::Global:
+    // A global variable may return a null decl. These variables are
+    // implementation details that aren't formally accessed.
+    return storage.getGlobal()->getDecl();
+  case AccessedStorage::Class: {
+    const ObjectProjection &objProj = storage.getObjectProjection();
+    return objProj.getProjection().getVarDecl(objProj.getObject()->getType());
+  }
+  case AccessedStorage::Box:
+  case AccessedStorage::Stack:
+  case AccessedStorage::Argument:
+  case AccessedStorage::Unidentified:
+    return nullptr;
+  case AccessedStorage::Nested:
+    llvm_unreachable("Unexpected Nested access.");
+  }
+}
+
+namespace {
+// Implements an optimization to remove access markers on disjoint memory
+// locations that are never reentrantly accessed. For a given memory location,
+// if there are no potential nested conflicts, then enforcement must succeed for
+// any access to that location.
+//
+// The existence of unidentified access complicates this problem. For this
+// optimization to be valid, Global and Class property access must always be
+// identifiable. findAccessedStorage() in MemAccessUtils enforces a short list
+// of unidentified producers (non-address PHIArgument, PointerToAddress, Undef,
+// & local-init). We cannot allow the address of a global variable or class
+// property to be exposed via one of these instructions, unless the declaration
+// is considered "visible externally".
+//
+// Note: This assumes that PointerToAddress is never used to access a global or
+// class property unless it's done via an Unsafe API that doesn't need
+// enforcement.
+//
+// FIXME: Tail-allocated heap storage is currently categorized as
+// Unidentified. This is conservatively safe because it can't also be accessed
+// as a class property. However, it is inconsistent with the general rule that
+// only local storage is unidentified, and we can probably remove a lot of
+// accesses by being more precise here (OTOH, if this is known CoW storage, we
+// should eventually add an even stronger optimization to remove exclusivity
+// checks).
+class GlobalAccessRemoval {
+  SILModule &module;
+
+  using BeginAccessSet = SmallDenseSet<BeginAccessInst *, 8>;
+
+  /// Information for an access location that, if it is valid, must be disjoint
+  /// from all other access locations.
+  struct DisjointAccessLocationInfo {
+    AccessedStorage::Kind accessKind = AccessedStorage::Unidentified;
+    // False if any nested conflict has been seen at this location.
+    bool noNestedConflict = true;
+    BeginAccessSet beginAccessSet;
+  };
+
+  DenseMap<VarDecl *, DisjointAccessLocationInfo> disjointAccessMap;
+
+public:
+  GlobalAccessRemoval(SILModule &module) : module(module) {}
+
+  void perform();
+
+protected:
+  void visitInstruction(SILInstruction *I);
+  void recordAccess(SILInstruction *beginAccess, VarDecl *decl,
+                    AccessedStorage::Kind storageKind,
+                    bool hasNoNestedConflict);
+  void removeNonreentrantAccess();
+};
+} // namespace
+
+/// Process all begin_access instructions in the module, recording their
+/// DisjointAccessLocation. Ignore accesses at call sites because Arguments and
+/// Unidentified access can only local storage.
+void GlobalAccessRemoval::perform() {
+  for (auto &F : module) {
+    if (F.empty())
+      continue;
+
+    for (auto &BB : F) {
+      for (auto &I : BB)
+        visitInstruction(&I);
+    }
+  }
+  removeNonreentrantAccess();
+}
+
+void GlobalAccessRemoval::visitInstruction(SILInstruction *I) {
+  if (auto *BAI = dyn_cast<BeginAccessInst>(I)) {
+    AccessedStorage storage = findAccessedStorageNonNested(BAI->getSource());
+    VarDecl *decl = getDisjointAccessLocation(storage);
+    recordAccess(BAI, decl, storage.getKind(), BAI->hasNoNestedConflict());
+    return;
+  }
+  if (auto *BUAI = dyn_cast<BeginUnpairedAccessInst>(I)) {
+    AccessedStorage storage = findAccessedStorageNonNested(BUAI->getSource());
+    VarDecl *decl = getDisjointAccessLocation(storage);
+    recordAccess(BUAI, decl, storage.getKind(), BUAI->hasNoNestedConflict());
+    return;
+  }
+  if (auto *KPI = dyn_cast<KeyPathInst>(I)) {
+    for (const KeyPathPatternComponent &component :
+         KPI->getPattern()->getComponents()) {
+      switch (component.getKind()) {
+      case KeyPathPatternComponent::Kind::StoredProperty:
+        recordAccess(KPI, component.getStoredPropertyDecl(),
+                     AccessedStorage::Class, /*hasNoNestedConflict=*/false);
+        break;
+      case KeyPathPatternComponent::Kind::GettableProperty:
+      case KeyPathPatternComponent::Kind::SettableProperty:
+      case KeyPathPatternComponent::Kind::External:
+      case KeyPathPatternComponent::Kind::OptionalChain:
+      case KeyPathPatternComponent::Kind::OptionalForce:
+      case KeyPathPatternComponent::Kind::OptionalWrap:
+        break;
+      }
+    }
+    return;
+  }
+}
+
+// Record an access in the disjointAccessMap.
+//
+// `beginAccess` is any instruction that represents a potential access,
+// including key_path. One of the following conditions must be true for every
+// begin_[unpaired_]access instructions:
+// - it is guaranteed to access local memory, not a class property or global.
+// - it has an identifiable source.
+// - is is generated from a Builtin, which is assumed to have an associated
+// key_path instruction somewhere else in the same module (or it must be dead
+// code, or only access public properties).
+//
+// `decl` may be nullptr if the declaration can't be determined from the
+// access. This is only legal when the access is known to be a local access, not
+// a class property or global.
+void GlobalAccessRemoval::recordAccess(SILInstruction *beginAccess,
+                                       VarDecl *decl,
+                                       AccessedStorage::Kind storageKind,
+                                       bool hasNoNestedConflict) {
+  if (!decl || module.isVisibleExternally(decl))
+    return;
+
+  DEBUG(if (!hasNoNestedConflict) llvm::dbgs()
+        << "Nested conflict on " << decl->getName() << " at" << *beginAccess
+        << "\n");
+
+  auto accessLocIter = disjointAccessMap.find(decl);
+  if (accessLocIter != disjointAccessMap.end()) {
+    // Add this begin_access to an existing DisjointAccessLocationInfo.
+    DisjointAccessLocationInfo &info = accessLocIter->second;
+    assert(info.accessKind == storageKind);
+    info.noNestedConflict &= hasNoNestedConflict;
+    // Don't currently optimize unpaired access.
+    if (auto *BAI = dyn_cast<BeginAccessInst>(beginAccess))
+      info.beginAccessSet.insert(BAI);
+    return;
+  }
+
+  // Create the first DisjointAccessLocationInfo for this begin_access.
+  DisjointAccessLocationInfo info;
+  info.accessKind = storageKind;
+  info.noNestedConflict = hasNoNestedConflict;
+  if (auto *BA = dyn_cast<BeginAccessInst>(beginAccess))
+    info.beginAccessSet.insert(BA);
+  disjointAccessMap.insert(std::make_pair(decl, info));
+}
+
+// For each unique storage within this function that is never reentrantly
+// accessed, promote all access checks for that storage to static enforcement.
+void GlobalAccessRemoval::removeNonreentrantAccess() {
+  for (auto &declAndInfo : disjointAccessMap) {
+    const DisjointAccessLocationInfo &info = declAndInfo.second;
+    if (!info.noNestedConflict)
+      continue;
+
+    VarDecl *decl = declAndInfo.first;
+    DEBUG(llvm::dbgs() << "Eliminating all formal access on " << decl->getName()
+                       << "\n");
+    assert(!module.isVisibleExternally(decl));
+    (void)decl;
+
+    // Non-deterministic iteration, only used to set a flag.
+    for (BeginAccessInst *beginAccess : info.beginAccessSet) {
+      DEBUG(llvm::dbgs() << "  Disabling access marker " << *beginAccess);
+      beginAccess->setEnforcement(SILAccessEnforcement::Static);
+    }
+  }
+}
+
+namespace {
+struct AccessEnforcementWMO : public SILModuleTransform {
+  void run() override {
+    GlobalAccessRemoval eliminationPass(*getModule());
+    eliminationPass.perform();
+  }
+};
+}
+
+SILTransform *swift::createAccessEnforcementWMO() {
+  return new AccessEnforcementWMO();
+}
diff --git a/lib/SILOptimizer/Transforms/CMakeLists.txt b/lib/SILOptimizer/Transforms/CMakeLists.txt
index e4d6c74..1e14f2c 100644
--- a/lib/SILOptimizer/Transforms/CMakeLists.txt
+++ b/lib/SILOptimizer/Transforms/CMakeLists.txt
@@ -1,6 +1,7 @@
 silopt_register_sources(
   ARCCodeMotion.cpp
   AccessEnforcementOpts.cpp
+  AccessEnforcementWMO.cpp
   AllocBoxToStack.cpp
   ArrayCountPropagation.cpp
   ArrayElementValuePropagation.cpp
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 3dbce08..17fe8f3 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -1409,6 +1409,10 @@
 /// The sequence is traversed inside out, i.e.
 /// starting with the innermost struct_element_addr
 /// Move into utils.
+///
+/// FIXME: this utility does not make sense as an API. How can the caller
+/// guarantee that the only uses of `I` are struct_element_addr and
+/// tuple_element_addr?
 void swift::replaceLoadSequence(SILInstruction *I,
                                 SILValue Value,
                                 SILBuilder &B) {
@@ -1434,6 +1438,18 @@
     return;
   }
 
+  if (auto *BA = dyn_cast<BeginAccessInst>(I)) {
+    for (auto Use : BA->getUses()) {
+      replaceLoadSequence(Use->getUser(), Value, B);
+    }
+    return;
+  }
+
+  // Incidental uses of an addres are meaningless with regard to the loaded
+  // value.
+  if (isIncidentalUse(I) || isa<BeginUnpairedAccessInst>(I))
+    return;
+
   llvm_unreachable("Unknown instruction sequence for reading from a global");
 }
 
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 8ee176a..2e9e1d5 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -48,7 +48,7 @@
   TypeCheckProtocol.cpp
   TypeCheckProtocolInference.cpp
   TypeCheckREPL.cpp
-  TypeCheckRequests.cpp
+  TypeCheckRequestFunctions.cpp
   TypeCheckStmt.cpp
   TypeCheckSwitchStmt.cpp
   TypeCheckType.cpp
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 2b4fc2f..5712e1f 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -4000,6 +4000,12 @@
       // Should already be type-checked.
       return simplifyExprType(expr);
     }
+
+    Expr *visitLazyInitializerExpr(LazyInitializerExpr *expr) {
+      simplifyExprType(expr);
+      assert(expr->getType()->isEqual(expr->getSubExpr()->getType()));
+      return expr;
+    }
     
     Expr *visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
       simplifyExprType(E);
@@ -7031,8 +7037,12 @@
 
   // If we're calling an accessor, keep the base as an inout type, because the
   // getter may be mutating.
-  if (SD->hasAccessorFunctions() && baseTy->is<InOutType>() &&
-      semantics != AccessSemantics::DirectToStorage)
+  auto strategy = SD->getAccessStrategy(semantics,
+                                        isSettableFromHere
+                                          ? AccessKind::ReadWrite
+                                          : AccessKind::Read,
+                                        UseDC);
+  if (baseTy->is<InOutType>() && strategy.getKind() != AccessStrategy::Storage)
     return InOutType::get(baseObjectTy);
 
   // Accesses to non-function members in value types are done through an @lvalue
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index d64ae88..172568d 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -2810,6 +2810,10 @@
       return CS.getASTContext().getBoolDecl()->getDeclaredType();
     }
 
+    Type visitLazyInitializerExpr(LazyInitializerExpr *expr) {
+      return expr->getType();
+    }
+
     Type visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
       if (E->getTypeLoc().isNull()) {
         auto locator = CS.getConstraintLocator(E);
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 7f017f6..30c30e6 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -34,6 +34,24 @@
 
 const bool IsImplicit = true;
 
+/// Should a particular accessor for the given storage be synthesized
+/// on-demand, or is it always defined eagerly in the file that declared
+/// the storage?
+static bool isOnDemandAccessor(AbstractStorageDecl *storage,
+                               AccessorKind kind) {
+  assert(kind == AccessorKind::Get || kind == AccessorKind::Set);
+
+  // Currently this only applies to imported declarations because we
+  // eagerly create accessors for all other member storage (except
+  // sometimes materializeForSet, but materializeForSet never needs a
+  // definition in the AST).
+  //
+  // Note that we can't just use hasClangNode() because the importer
+  // sometimes synthesizes things that lack clang nodes.
+  auto *mod = storage->getDeclContext()->getModuleScopeContext();
+  return (cast<FileUnit>(mod)->getKind() == FileUnitKind::ClangModule);
+}
+
 /// Insert the specified decl into the DeclContext's member list.  If the hint
 /// decl is specified, the new decl is inserted next to the hint.
 static void addMemberToContextIfNeeded(Decl *D, DeclContext *DC,
@@ -120,25 +138,37 @@
   return ParameterList::create(context, elements);
 }
 
-static AccessorDecl *createGetterPrototype(AbstractStorageDecl *storage,
-                                           TypeChecker &TC) {
+static AccessorDecl *createGetterPrototype(TypeChecker &TC,
+                                           AbstractStorageDecl *storage) {
+  assert(!storage->getGetter());
+
   SourceLoc loc = storage->getLoc();
 
   // Create the parameter list for the getter.
   SmallVector<ParameterList*, 2> getterParams;
 
+  GenericEnvironment *genericEnvironmentOfLazyAccessor = nullptr;
+
   // The implicit 'self' argument if in a type context.
   if (storage->getDeclContext()->isTypeContext()) {
     ParamDecl *selfDecl;
 
     // For lazy properties, steal the 'self' from the initializer context.
     if (storage->getAttrs().hasAttribute<LazyAttr>()) {
+      // The getter is considered mutating if it's on a value type.
+      if (!storage->getDeclContext()->getAsClassOrClassExtensionContext() &&
+          !storage->isStatic()) {
+        storage->setIsGetterMutating(true);
+      }
+
       auto *varDecl = cast<VarDecl>(storage);
       auto *bindingDecl = varDecl->getParentPatternBinding();
       auto *bindingInit = cast<PatternBindingInitializer>(
         bindingDecl->getPatternEntryForVarDecl(varDecl).getInitContext());
 
       selfDecl = bindingInit->getImplicitSelfDecl();
+      genericEnvironmentOfLazyAccessor =
+        bindingInit->getGenericEnvironmentOfContext();
     } else {
       selfDecl = ParamDecl::createSelf(loc,
                                        storage->getDeclContext(),
@@ -169,6 +199,18 @@
       storage->getDeclContext());
   getter->setImplicit();
 
+  // We need to install the generic environment here because:
+  // 1) validating the getter will change the implicit self decl's DC to it,
+  // 2) it's likely that the initializer will be type-checked before the
+  //    accessor (and therefore before the normal installation happens), and
+  // 3) type-checking a reference to the self decl will map its type into
+  //    its context, which requires an environment to be installed on that
+  //    context.
+  // We can safely use the enclosing environment because properties are never
+  // differently generic.
+  if (genericEnvironmentOfLazyAccessor)
+    getter->setGenericEnvironment(genericEnvironmentOfLazyAccessor);
+
   if (storage->isGetterMutating())
     getter->setSelfAccessKind(SelfAccessKind::Mutating);
 
@@ -179,12 +221,18 @@
     if (auto *overriddenAccessor = overridden->getGetter())
       getter->setOverriddenDecl(overriddenAccessor);
 
+  // Always add the getter to the context immediately after the storage.
+  addMemberToContextIfNeeded(getter, storage->getDeclContext(), storage);
+
   return getter;
 }
 
-static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
-                                           ParamDecl *&valueDecl,
-                                           TypeChecker &TC) {
+static AccessorDecl *createSetterPrototype(TypeChecker &TC,
+                                           AbstractStorageDecl *storage,
+                                           AccessorDecl *getter = nullptr) {
+  assert(!storage->getSetter());
+  assert(storage->supportsMutation());
+
   SourceLoc loc = storage->getLoc();
 
   // Create the parameter list for the setter.
@@ -204,9 +252,9 @@
   // Add a "(value : T, indices...)" argument list.
   auto storageType = getTypeOfStorage(storage, false);
   auto storageInterfaceType = getTypeOfStorage(storage, true);
-  valueDecl = buildArgument(storage->getLoc(), storage->getDeclContext(),
-                            "value", storageType, storageInterfaceType,
-                            VarDecl::Specifier::Default);
+  auto valueDecl = buildArgument(storage->getLoc(), storage->getDeclContext(),
+                                 "value", storageType, storageInterfaceType,
+                                 VarDecl::Specifier::Default);
   params.push_back(buildIndexForwardingParamList(storage, valueDecl));
 
   Type setterRetTy = TupleType::getEmpty(TC.Context);
@@ -233,6 +281,11 @@
     }
   }
 
+  // Always add the setter to the context immediately after the getter.
+  if (!getter) getter = storage->getGetter();
+  assert(getter && "always synthesize setter prototype after getter");
+  addMemberToContextIfNeeded(setter, storage->getDeclContext(), getter);
+
   return setter;
 }
 
@@ -254,10 +307,8 @@
 /// If the storage is for a global stored property or a stored property of a
 /// resilient type, we are synthesizing accessors to present a resilient
 /// interface to the storage and they should not be transparent.
-static void maybeMarkTransparent(FuncDecl *accessor,
-                                 AbstractStorageDecl *storage,
-                                 TypeChecker &TC) {
-  auto *DC = storage->getDeclContext();
+static void maybeMarkTransparent(TypeChecker &TC, AccessorDecl *accessor) {
+  auto *DC = accessor->getDeclContext();
   auto *nominalDecl = DC->getAsNominalTypeOrNominalTypeExtensionContext();
 
   // Global variable accessors are not @_transparent.
@@ -265,7 +316,13 @@
     return;
 
   // Accessors for resilient properties are not @_transparent.
-  if (storage->isResilient())
+  if (accessor->getStorage()->isResilient())
+    return;
+
+  // Setters for lazy properties are not @_transparent (because the storage
+  // is not ABI-exposed).
+  if (accessor->getStorage()->getAttrs().hasAttribute<LazyAttr>() &&
+      accessor->getAccessorKind() == AccessorKind::Set)
     return;
 
   // Accessors for protocol storage requirements are never @_transparent
@@ -284,6 +341,19 @@
   accessor->getAttrs().add(new (TC.Context) TransparentAttr(IsImplicit));
 }
 
+template <class... Args>
+static void triggerSynthesis(TypeChecker &TC, FuncDecl *fn, Args... args) {
+  if (fn->hasBody()) return;
+
+  auto synthesisRecord = SynthesizedFunction(fn, args...);
+  TC.FunctionsToSynthesize.insert({ fn, synthesisRecord });
+}
+
+static void finishSynthesis(TypeChecker &TC, FuncDecl *fn) {  
+  TC.Context.addSynthesizedDecl(fn);
+  TC.DeclsToFinalize.insert(fn);
+}
+
 static AccessorDecl *
 createMaterializeForSetPrototype(AbstractStorageDecl *storage,
                                  FuncDecl *getter,
@@ -383,30 +453,17 @@
     asAvailableAs.push_back(setter);
   }
 
-  maybeMarkTransparent(materializeForSet, storage, TC);
+  maybeMarkTransparent(TC, materializeForSet);
 
   AvailabilityInference::applyInferredAvailableAttrs(materializeForSet,
                                                      asAvailableAs, ctx);
 
-  TC.Context.addSynthesizedDecl(materializeForSet);
-  TC.DeclsToFinalize.insert(materializeForSet);
-  
+  addMemberToContextIfNeeded(materializeForSet, DC, setter);
+
+  finishSynthesis(TC, materializeForSet);
   return materializeForSet;
 }
 
-static void convertStoredVarInProtocolToComputed(VarDecl *VD, TypeChecker &TC) {
-  auto *Get = createGetterPrototype(VD, TC);
-  
-  // Okay, we have the getter; make the VD computed.
-  VD->setAccessors(AbstractStorageDecl::Computed,
-                   SourceLoc(), {Get}, SourceLoc());
-  
-  // We've added some members to our containing class, add them to the members
-  // list.
-  addMemberToContextIfNeeded(Get, VD->getDeclContext(), VD);
-}
-
-
 /// Build an expression that evaluates the specified parameter list as a tuple
 /// or paren expr, suitable for use in an applyexpr.
 ///
@@ -526,34 +583,64 @@
       return buildSubscriptIndexReference(ctx, Accessor);
     }
   };
+
+  enum class TargetImpl {
+    /// We're referencing the physical storage created for the storage.
+    Storage,
+    /// We're referencing this specific implementation of the storage, not
+    /// an override of it.
+    Implementation,
+    /// We're referencing the superclass's implementation of the storage.
+    Super
+  };
 } // end anonymous namespace
 
 /// Build an l-value for the storage of a declaration.
 static Expr *buildStorageReference(
                              const StorageReferenceContext &referenceContext,
                                    AbstractStorageDecl *storage,
-                                   AccessSemantics semantics,
-                                   SelfAccessorKind selfAccessorKind,
+                                   TargetImpl target,
                                    TypeChecker &TC) {
   ASTContext &ctx = TC.Context;
 
+  AccessSemantics semantics;
+  SelfAccessorKind selfAccessKind;
+  switch (target) {
+  case TargetImpl::Storage:
+    semantics = AccessSemantics::DirectToStorage;
+    selfAccessKind = SelfAccessorKind::Peer;
+    break;
+
+  case TargetImpl::Implementation:
+    semantics = AccessSemantics::DirectToImplementation;
+    selfAccessKind = SelfAccessorKind::Peer;
+    break;
+
+  case TargetImpl::Super:
+    // If this really is an override, use a super-access.
+    if (auto override = storage->getOverriddenDecl()) {
+      semantics = AccessSemantics::Ordinary;
+      selfAccessKind = SelfAccessorKind::Super;
+      storage = override;
+
+    // Otherwise do a self-reference, which is dynamically bogus but
+    // should be statically valid.  This should only happen in invalid cases.    
+    } else {
+      assert(storage->isInvalid());
+      semantics = AccessSemantics::Ordinary;
+      selfAccessKind = SelfAccessorKind::Peer;
+    }
+    break;
+  }
+
   VarDecl *selfDecl = referenceContext.getSelfDecl();
   if (!selfDecl) {
+    assert(target != TargetImpl::Super);
     return new (ctx) DeclRefExpr(storage, DeclNameLoc(), IsImplicit, semantics);
   }
 
-  // If we should use a super access if applicable, and we have an
-  // overridden decl, then use ordinary access to it.
-  if (selfAccessorKind == SelfAccessorKind::Super) {
-    if (auto overridden = storage->getOverriddenDecl()) {
-      storage = overridden;
-      semantics = AccessSemantics::Ordinary;
-    } else {
-      selfAccessorKind = SelfAccessorKind::Peer;
-    }
-  }
-
-  Expr *selfDRE = buildSelfReference(selfDecl, selfAccessorKind, TC);
+  Expr *selfDRE =
+    buildSelfReference(selfDecl, selfAccessKind, TC);
 
   if (auto subscript = dyn_cast<SubscriptDecl>(storage)) {
     Expr *indices = referenceContext.getIndexRefExpr(ctx, subscript);
@@ -570,21 +657,19 @@
 
 static Expr *buildStorageReference(AccessorDecl *accessor,
                                    AbstractStorageDecl *storage,
-                                   AccessSemantics semantics,
-                                   SelfAccessorKind selfAccessorKind,
+                                   TargetImpl target,
                                    TypeChecker &TC) {
   return buildStorageReference(AccessorStorageReferenceContext(accessor),
-                               storage, semantics, selfAccessorKind, TC);
+                               storage, target, TC);
 }
 
 /// Load the value of VD.  If VD is an @override of another value, we call the
 /// superclass getter.  Otherwise, we do a direct load of the value.
 static Expr *createPropertyLoadOrCallSuperclassGetter(AccessorDecl *accessor,
                                               AbstractStorageDecl *storage,
+                                              TargetImpl target,
                                                       TypeChecker &TC) {
-  return buildStorageReference(accessor, storage,
-                               AccessSemantics::DirectToStorage,
-                               SelfAccessorKind::Super, TC);
+  return buildStorageReference(accessor, storage, target, TC);
 }
 
 /// Look up the NSCopying protocol from the Foundation module, if present.
@@ -609,7 +694,31 @@
   return dyn_cast<ProtocolDecl>(results.front());
 }
 
+static bool checkConformanceToNSCopying(TypeChecker &TC, VarDecl *var,
+                                        Type type) {
+  auto dc = var->getDeclContext();
+  auto proto = getNSCopyingProtocol(TC, dc);
+  if (!proto || !TC.conformsToProtocol(type, proto, dc, None)) {
+    TC.diagnose(var->getLoc(), diag::nscopying_doesnt_conform);
+    return true;
+  }
+  return false;
+}
 
+static std::pair<Type, bool> getUnderlyingTypeOfVariable(VarDecl *var) {
+  Type type = var->getType()->getReferenceStorageReferent();
+
+  if (Type objectType = type->getOptionalObjectType()) {
+    return {objectType, true};
+  } else {
+    return {type, false};
+  }
+}
+
+bool TypeChecker::checkConformanceToNSCopying(VarDecl *var) {
+  Type type = getUnderlyingTypeOfVariable(var).first;
+  return ::checkConformanceToNSCopying(*this, var, type);
+}
 
 /// Synthesize the code to store 'Val' to 'VD', given that VD has an @NSCopying
 /// attribute on it.  We know that VD is a stored property in a class, so we
@@ -621,20 +730,13 @@
 
   // We support @NSCopying on class types (which conform to NSCopying),
   // protocols which conform, and option types thereof.
-  Type UnderlyingType = VD->getType()->getReferenceStorageReferent();
-
-  bool isOptional = false;
-  if (Type optionalEltTy = UnderlyingType->getOptionalObjectType()) {
-    UnderlyingType = optionalEltTy;
-    isOptional = true;
-  }
+  auto underlyingTypeAndIsOptional = getUnderlyingTypeOfVariable(VD);
+  auto underlyingType = underlyingTypeAndIsOptional.first;
+  auto isOptional = underlyingTypeAndIsOptional.second;
 
   // The element type must conform to NSCopying.  If not, emit an error and just
   // recovery by synthesizing without the copy call.
-  auto *CopyingProto = getNSCopyingProtocol(TC, VD->getDeclContext());
-  if (!CopyingProto || !TC.conformsToProtocol(UnderlyingType, CopyingProto,
-                                              VD->getDeclContext(), None)) {
-    TC.diagnose(VD->getLoc(), diag::nscopying_doesnt_conform);
+  if (checkConformanceToNSCopying(TC, VD, underlyingType)) {
     return Val;
   }
 
@@ -664,7 +766,7 @@
   // If we're working with non-optional types, we're forcing the cast.
   if (!isOptional) {
     Call = new (Ctx) ForcedCheckedCastExpr(Call, SourceLoc(), SourceLoc(),
-                                           TypeLoc::withoutLoc(UnderlyingType));
+                                           TypeLoc::withoutLoc(underlyingType));
     Call->setImplicit();
     return Call;
   }
@@ -672,7 +774,7 @@
   // We're working with optional types, so perform a conditional checked
   // downcast.
   Call = new (Ctx) ConditionalCheckedCastExpr(Call, SourceLoc(), SourceLoc(),
-                                           TypeLoc::withoutLoc(UnderlyingType));
+                                           TypeLoc::withoutLoc(underlyingType));
   Call->setImplicit();
 
   // Use OptionalEvaluationExpr to evaluate the "?".
@@ -686,6 +788,7 @@
 static void createPropertyStoreOrCallSuperclassSetter(AccessorDecl *accessor,
                                                       Expr *value,
                                                AbstractStorageDecl *storage,
+                                               TargetImpl target,
                                                SmallVectorImpl<ASTNode> &body,
                                                       TypeChecker &TC) {
   // If the storage is an @NSCopying property, then we store the
@@ -699,134 +802,139 @@
   //   (assign (decl_ref_expr(VD)), decl_ref_expr(value))
   // or:
   //   (assign (member_ref_expr(decl_ref_expr(self), VD)), decl_ref_expr(value))
-  Expr *dest = buildStorageReference(accessor, storage,
-                                     AccessSemantics::DirectToStorage,
-                                     SelfAccessorKind::Super, TC);
+  Expr *dest = buildStorageReference(accessor, storage, target, TC);
 
   body.push_back(new (TC.Context) AssignExpr(dest, SourceLoc(), value,
                                              IsImplicit));
 }
 
+static bool isSynthesizedComputedProperty(AbstractStorageDecl *storage) {
+  return (storage->getAttrs().hasAttribute<LazyAttr>() ||
+          storage->getAttrs().hasAttribute<NSManagedAttr>());
+}
+
 /// Synthesize the body of a trivial getter.  For a non-member vardecl or one
 /// which is not an override of a base class property, it performs a direct
 /// storage load.  For an override of a base member property, it chains up to
 /// super.
-static void synthesizeTrivialGetter(AccessorDecl *getter,
-                                    AbstractStorageDecl *storage,
-                                    TypeChecker &TC) {
+static void synthesizeTrivialGetterBody(TypeChecker &TC, AccessorDecl *getter,
+                                        TargetImpl target) {
+  auto storage = getter->getStorage();
+  assert(!storage->getAttrs().hasAttribute<LazyAttr>() &&
+         !storage->getAttrs().hasAttribute<NSManagedAttr>());
+
   auto &ctx = TC.Context;
-  
-  Expr *result = createPropertyLoadOrCallSuperclassGetter(getter, storage, TC);
+  SourceLoc loc = storage->getLoc();
+
+  Expr *result =
+    createPropertyLoadOrCallSuperclassGetter(getter, storage, target, TC);
   ASTNode returnStmt = new (ctx) ReturnStmt(SourceLoc(), result, IsImplicit);
 
-  SourceLoc loc = storage->getLoc();
   getter->setBody(BraceStmt::create(ctx, loc, returnStmt, loc, true));
 
-  TC.Context.addSynthesizedDecl(getter);
-  TC.DeclsToFinalize.insert(getter);
+  finishSynthesis(TC, getter);
+
+  maybeMarkTransparent(TC, getter);
 }
 
-/// Synthesize the body of a trivial setter.
-static void synthesizeTrivialSetter(AccessorDecl *setter,
-                                    AbstractStorageDecl *storage,
-                                    VarDecl *valueVar,
-                                    TypeChecker &TC) {
-  auto &ctx = TC.Context;
-  SourceLoc loc = storage->getLoc();
+/// Synthesize the body of a getter which just directly accesses the
+/// underlying storage.
+static void synthesizeTrivialGetterBody(TypeChecker &TC, AccessorDecl *getter) {
+  assert(getter->getStorage()->hasStorage());
+  synthesizeTrivialGetterBody(TC, getter, TargetImpl::Storage);
+}
 
-  auto *valueDRE = new (ctx) DeclRefExpr(valueVar, DeclNameLoc(), IsImplicit);
+/// Synthesize the body of a getter which just delegates to its superclass
+/// implementation.
+static void synthesizeInheritedGetterBody(TypeChecker &TC,
+                                          AccessorDecl *getter) {
+  // This should call the superclass getter.
+  synthesizeTrivialGetterBody(TC, getter, TargetImpl::Super);
+}
+
+/// Synthesize the body of a getter which just delegates to an addressor.
+static void synthesizeAddressedGetterBody(TypeChecker &TC,
+                                          AccessorDecl *getter) {
+  assert(getter->getStorage()->getAddressor());
+
+  // This should call the addressor.
+  synthesizeTrivialGetterBody(TC, getter, TargetImpl::Implementation);
+}
+
+/// Synthesize the body of a setter which just stores to the given storage
+/// declaration (which doesn't have to be the storage for the setter).
+static void synthesizeTrivialSetterBodyWithStorage(TypeChecker &TC,
+                                                   AccessorDecl *setter,
+                                                   TargetImpl target,
+                                           AbstractStorageDecl *storageToUse) {
+  auto &ctx = TC.Context;
+  SourceLoc loc = setter->getStorage()->getLoc();
+
+  VarDecl *valueParamDecl = getFirstParamDecl(setter);
+
+  auto *valueDRE =
+    new (ctx) DeclRefExpr(valueParamDecl, DeclNameLoc(), IsImplicit);
   SmallVector<ASTNode, 1> setterBody;
-  createPropertyStoreOrCallSuperclassSetter(setter, valueDRE, storage,
-                                            setterBody, TC);
+  createPropertyStoreOrCallSuperclassSetter(setter, valueDRE, storageToUse,
+                                            target, setterBody, TC);
   setter->setBody(BraceStmt::create(ctx, loc, setterBody, loc, true));
 
-  TC.Context.addSynthesizedDecl(setter);
-  TC.DeclsToFinalize.insert(setter);
+  finishSynthesis(TC, setter);
+
+  maybeMarkTransparent(TC, setter);
 }
 
-/// Does a storage decl currently lacking accessor functions require a
-/// setter to be synthesized?
-static bool doesStorageNeedSetter(AbstractStorageDecl *storage) {
-  assert(!storage->hasAccessorFunctions());
-  switch (storage->getStorageKind()) {
-  // Add a setter to a stored variable unless it's a let.
-  case AbstractStorageDecl::Stored:
-    return !cast<VarDecl>(storage)->isLet();
+static void synthesizeTrivialSetterBody(TypeChecker &TC, AccessorDecl *setter) {
+  auto storage = setter->getStorage();
+  assert(!isSynthesizedComputedProperty(storage));
+  synthesizeTrivialSetterBodyWithStorage(TC, setter, TargetImpl::Storage,
+                                         storage);
+}
 
-  // Addressed storage gets a setter if it has a mutable addressor.
-  case AbstractStorageDecl::Addressed:
-    return storage->getMutableAddressor() != nullptr;
+static void addGetterToStorage(TypeChecker &TC, AbstractStorageDecl *storage) {
+  auto getter = createGetterPrototype(TC, storage);
 
-  // These should already have accessor functions.
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
-  case AbstractStorageDecl::StoredWithObservers:
-  case AbstractStorageDecl::InheritedWithObservers:
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-  case AbstractStorageDecl::AddressedWithObservers:
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-    llvm_unreachable("already has accessor functions");
+  // Install the prototype.
+  storage->setSynthesizedGetter(getter);
+}
 
-  case AbstractStorageDecl::Computed:
-    llvm_unreachable("not stored");
-  }
-  llvm_unreachable("bad storage kind");
+static void addSetterToStorage(TypeChecker &TC, AbstractStorageDecl *storage) {
+  auto setter = createSetterPrototype(TC, storage);
+
+  // Install the prototype.
+  storage->setSynthesizedSetter(setter);
 }
 
 /// Add trivial accessors to a Stored or Addressed property.
 static void addTrivialAccessorsToStorage(AbstractStorageDecl *storage,
                                          TypeChecker &TC) {
-  assert(!storage->hasAccessorFunctions() && "already has accessors?");
-  assert(!storage->getAttrs().hasAttribute<LazyAttr>());
-  assert(!storage->getAttrs().hasAttribute<NSManagedAttr>());
+  assert(!isSynthesizedComputedProperty(storage));
 
-  auto *DC = storage->getDeclContext();
+  if (!storage->getGetter())
+    addGetterToStorage(TC, storage);
 
-  // Create the getter.
-  AccessorDecl *getter = createGetterPrototype(storage, TC);
+  if (storage->supportsMutation()) {
+    if (!storage->getSetter())
+      addSetterToStorage(TC, storage);
 
-  // Create the setter.
-  AccessorDecl *setter = nullptr;
-  ParamDecl *setterValueParam = nullptr;
-  if (doesStorageNeedSetter(storage))
-    setter = createSetterPrototype(storage, setterValueParam, TC);
-
-  // Okay, we have both the getter and setter.  Set them in VD.
-  storage->addTrivialAccessors(getter, setter, nullptr);
-
-  // Synthesize the body of the getter.
-  synthesizeTrivialGetter(getter, storage, TC);
-  maybeMarkTransparent(getter, storage, TC);
-
-  if (setter) {
-    // Synthesize the body of the setter.
-    synthesizeTrivialSetter(setter, storage, setterValueParam, TC);
-    maybeMarkTransparent(setter, storage, TC);
+    if (!storage->getMaterializeForSetFunc())
+      maybeAddMaterializeForSet(storage, TC);
   }
-
-  // We've added some members to our containing context, add them to
-  // the right list.
-  addMemberToContextIfNeeded(getter, DC, storage);
-  if (setter)
-    addMemberToContextIfNeeded(setter, DC, getter);
-
-  maybeAddMaterializeForSet(storage, TC);
 }
 
-/// Add a trivial setter and materializeForSet to a
-/// ComputedWithMutableAddress storage decl.
-void swift::
-synthesizeSetterForMutableAddressedStorage(AbstractStorageDecl *storage,
-                                           TypeChecker &TC) {
-  auto setter = storage->getSetter();
-  assert(setter);
-  if (setter->getBody()) return;
-  assert(storage->getStorageKind() ==
-           AbstractStorageDecl::ComputedWithMutableAddress);
+static void convertStoredVarInProtocolToComputed(VarDecl *VD, TypeChecker &TC) {
+  if (!VD->getGetter()) {
+    addGetterToStorage(TC, VD);
+  }
 
-  // Synthesize the body of the setter.
-  VarDecl *valueParamDecl = getFirstParamDecl(setter);
-  synthesizeTrivialSetter(setter, storage, valueParamDecl, TC);
-  maybeMarkTransparent(setter, storage, TC);
+  // Okay, we have the getter; make the VD computed.
+  VD->overwriteImplInfo(StorageImplInfo::getImmutableComputed());
+}
+
+static void synthesizeMutableAddressSetterBody(TypeChecker &TC,
+                                               AccessorDecl *setter) {
+  synthesizeTrivialSetterBodyWithStorage(TC, setter, TargetImpl::Implementation,
+                                         setter->getStorage());
 }
 
 /// Add a materializeForSet accessor to the given declaration.
@@ -839,30 +947,37 @@
 
   auto materializeForSet = createMaterializeForSetPrototype(
       storage, storage->getGetter(), storage->getSetter(), TC);
-  addMemberToContextIfNeeded(materializeForSet, storage->getDeclContext(),
-                             storage->getSetter());
-  storage->setMaterializeForSetFunc(materializeForSet);
+
+  // Install the prototype.
+  storage->setSynthesizedMaterializeForSet(materializeForSet);
 
   return materializeForSet;
 }
 
 static void convertNSManagedStoredVarToComputed(VarDecl *VD, TypeChecker &TC) {
-  assert(VD->getStorageKind() == AbstractStorageDecl::Stored);
+  // If it's not still stored, just bail out.
+  if (!VD->getImplInfo().isSimpleStored())
+    return;
+
+  // We might already have synthesized the getter and setter declarations
+  // from e.g. type-checking a conformance, or just from an invalid earlier
+  // declaration.
+
+  // Creating these this way will not trigger synthesis of implementations
+  // because of the NSManaged attribute.
 
   // Create the getter.
-  auto *Get = createGetterPrototype(VD, TC);
+  if (!VD->getGetter()) {
+    addGetterToStorage(TC, VD);
+  }
 
   // Create the setter.
-  ParamDecl *SetValueDecl = nullptr;
-  auto *Set = createSetterPrototype(VD, SetValueDecl, TC);
+  if (!VD->getSetter()) {
+    addSetterToStorage(TC, VD);
+  }
 
-  // Okay, we have both the getter and setter.  Set them in VD.
-  VD->setAccessors(VarDecl::Computed, SourceLoc(), {Get, Set}, SourceLoc());
-
-  // We've added some members to our containing class/extension, add them to
-  // the members list.
-  addMemberToContextIfNeeded(Get, VD->getDeclContext(), VD);
-  addMemberToContextIfNeeded(Set, VD->getDeclContext(), Get);
+  // Okay, we have both a getter and setter; overwrite the impl info.
+  VD->overwriteImplInfo(StorageImplInfo::getMutableComputed());
 
   maybeAddMaterializeForSet(VD, TC);
 }
@@ -873,17 +988,31 @@
 void TypeChecker::synthesizeWitnessAccessorsForStorage(
                                              AbstractStorageDecl *requirement,
                                              AbstractStorageDecl *storage) {
-  // If the decl is stored, convert it to StoredWithTrivialAccessors
-  // by synthesizing the full set of accessors.
-  if (!storage->hasAccessorFunctions()) {
-    // Don't do this if the declaration is lazy or NSManaged.
-    // This must be a re-entrant attempt to synthesize accessors
-    // before validateDecl has finished.
-    if (storage->getAttrs().hasAttribute<LazyAttr>() ||
-        storage->getAttrs().hasAttribute<NSManagedAttr>())
-      return;
+  bool addedAccessor = false;
+  auto flagAddedAccessor = [&](AccessorDecl *accessor,
+                               Optional<SynthesizedFunction::Kind> kind) {
+    addedAccessor = true;
 
-    addTrivialAccessorsToStorage(storage, *this);
+    // Synthesize a trivial body when we create an on-demand accessor.
+    if (kind && isOnDemandAccessor(accessor->getStorage(),
+                                   accessor->getAccessorKind())) {
+      triggerSynthesis(*this, accessor, *kind);
+    }
+  };
+
+  // Synthesize a getter.
+  if (!storage->getGetter()) {
+    addGetterToStorage(*this, storage);
+    flagAddedAccessor(storage->getGetter(), SynthesizedFunction::Getter);
+  }
+
+  // Synthesize a setter if the storage is mutable and the requirement
+  // needs it.
+  if (!storage->getSetter() &&
+      storage->supportsMutation() &&
+      requirement->supportsMutation()) {
+    addSetterToStorage(*this, storage);
+    flagAddedAccessor(storage->getSetter(), SynthesizedFunction::Setter);
   }
 
   // @objc protocols don't need a materializeForSet since ObjC doesn't
@@ -892,34 +1021,32 @@
     !requirement->isObjC() && requirement->getSetter();
 
   // If we want wantMaterializeForSet, create it now.
-  if (wantMaterializeForSet && !storage->getMaterializeForSetFunc())
+  if (wantMaterializeForSet && !storage->getMaterializeForSetFunc()) {
     addMaterializeForSet(storage, *this);
+    flagAddedAccessor(storage->getMaterializeForSetFunc(), None);
+  }
+
+  // Cue (delayed) validation of any accessors we just added, just
+  // in case this is coming after the normal delayed validation finished.
+  if (addedAccessor) {
+    DeclsToFinalize.insert(storage);
+  }
 }
 
 /// Given a VarDecl with a willSet: and/or didSet: specifier, synthesize the
-/// (trivial) getter and the setter, which calls these.
-void swift::synthesizeObservingAccessors(VarDecl *VD, TypeChecker &TC) {
-  assert(VD->hasObservers());
-  assert(VD->getGetter() && VD->getSetter());
-  
+/// setter which calls them.
+static void synthesizeObservedSetterBody(TypeChecker &TC, AccessorDecl *Set,
+                                         TargetImpl target) {
+  auto VD = cast<VarDecl>(Set->getStorage());
+
   auto &Ctx = VD->getASTContext();
   SourceLoc Loc = VD->getLoc();
 
   // We have to be paranoid about the accessors already having bodies
   // because there might be an (invalid) existing definition.
   
-  // The getter is always trivial: just perform a (direct!) load of storage, or
-  // a call of a superclass getter if this is an override.
-  auto *Get = VD->getGetter();
-  if (!Get->hasBody()) {
-    synthesizeTrivialGetter(Get, VD, TC);
-    maybeMarkTransparent(Get, VD, TC);
-  }
-
   // Okay, the getter is done, create the setter now.  Start by finding the
   // decls for 'self' and 'value'.
-  auto *Set = VD->getSetter();
-  if (Set->hasBody()) return;
   auto *SelfDecl = Set->getImplicitSelfDecl();
   VarDecl *ValueDecl = Set->getParameterLists().back()->get(0);
 
@@ -934,7 +1061,7 @@
   VarDecl *OldValue = nullptr;
   if (VD->getDidSetFunc()) {
     Expr *OldValueExpr
-      = createPropertyLoadOrCallSuperclassGetter(Set, VD, TC);
+      = createPropertyLoadOrCallSuperclassGetter(Set, VD, target, TC);
 
     OldValue = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Let,
                                  /*IsCaptureList*/false, SourceLoc(),
@@ -967,16 +1094,12 @@
     }
     SetterBody.push_back(CallExpr::createImplicit(Ctx, Callee, { ValueDRE },
                                                   { Identifier() }));
-
-    // Make sure the didSet/willSet accessors are marked final if in a class.
-    if (!willSet->isFinal() &&
-        VD->getDeclContext()->getAsClassOrClassExtensionContext())
-      makeFinal(Ctx, willSet);
   }
   
   // Create an assignment into the storage or call to superclass setter.
   auto *ValueDRE = new (Ctx) DeclRefExpr(ValueDecl, DeclNameLoc(), true);
-  createPropertyStoreOrCallSuperclassSetter(Set, ValueDRE, VD, SetterBody, TC);
+  createPropertyStoreOrCallSuperclassSetter(Set, ValueDRE, VD, target,
+                                            SetterBody, TC);
 
   // Create:
   //   (call_expr (dot_syntax_call_expr (decl_ref_expr(didSet)),
@@ -995,14 +1118,21 @@
     }
     SetterBody.push_back(CallExpr::createImplicit(Ctx, Callee, { OldValueExpr },
                                                   { Identifier() }));
-
-    // Make sure the didSet/willSet accessors are marked final if in a class.
-    if (!didSet->isFinal() &&
-        VD->getDeclContext()->getAsClassOrClassExtensionContext())
-      makeFinal(Ctx, didSet);
   }
 
   Set->setBody(BraceStmt::create(Ctx, Loc, SetterBody, Loc, true));
+
+  finishSynthesis(TC, Set);
+}
+
+static void synthesizeStoredWithObserversSetterBody(TypeChecker &TC,
+                                                    AccessorDecl *setter) {
+  synthesizeObservedSetterBody(TC, setter, TargetImpl::Storage);
+}
+
+static void synthesizeInheritedWithObserversSetterBody(TypeChecker &TC,
+                                                       AccessorDecl *setter) {
+  synthesizeObservedSetterBody(TC, setter, TargetImpl::Super);
 }
 
 namespace {
@@ -1039,9 +1169,12 @@
 
 /// Synthesize the getter for a lazy property with the specified storage
 /// vardecl.
-static FuncDecl *completeLazyPropertyGetter(VarDecl *VD, VarDecl *Storage,
-                                            TypeChecker &TC) {
-  auto &Ctx = VD->getASTContext();
+static void synthesizeLazyGetterBody(TypeChecker &TC, AccessorDecl *Get,
+                                     VarDecl *Storage) {
+  auto &Ctx = TC.Context;
+
+  // The lazy var itself.
+  auto VD = cast<VarDecl>(Get->getStorage());
 
   // The getter checks the optional, storing the initial value in if nil.  The
   // specific pattern we generate is:
@@ -1054,8 +1187,6 @@
   //     storage = tmp2
   //     return tmp2
   //   }
-  auto *Get = VD->getGetter();
-
   SmallVector<ASTNode, 6> Body;
 
   // Load the existing storage and store it into the 'tmp1' temporary.
@@ -1065,7 +1196,9 @@
   Tmp1VD->setImplicit();
 
   auto *Tmp1PBDPattern = new (Ctx) NamedPattern(Tmp1VD, /*implicit*/true);
-  auto *Tmp1Init = createPropertyLoadOrCallSuperclassGetter(Get, Storage, TC);
+  auto *Tmp1Init =
+    createPropertyLoadOrCallSuperclassGetter(Get, Storage,
+                                             TargetImpl::Storage, TC);
   auto *Tmp1PBD = PatternBindingDecl::create(Ctx, /*StaticLoc*/SourceLoc(),
                                              StaticSpellingKind::None,
                                              /*VarLoc*/SourceLoc(),
@@ -1110,13 +1243,22 @@
   auto *InitValue = VD->getParentInitializer();
   auto PBD = VD->getParentPatternBinding();
   unsigned entryIndex = PBD->getPatternEntryIndexForVarDecl(VD);
-  PBD->setInit(entryIndex, nullptr);
+  assert(PBD->isInitializerLazy(entryIndex));
+  bool wasInitializerChecked = PBD->isInitializerChecked(entryIndex);
   PBD->setInitializerChecked(entryIndex);
 
   // Recontextualize any closure declcontexts nested in the initializer to
   // realize that they are in the getter function.
   InitValue->walk(RecontextualizeClosures(Get));
 
+  // Wrap the initializer in a LazyInitializerExpr to avoid problems with
+  // re-typechecking it if it was already type-checked.
+  // FIXME: we should really have stronger invariants than this.  Leaving it
+  // unwrapped may expose both expressions to naive walkers
+  if (wasInitializerChecked) {
+    InitValue = new (Ctx) LazyInitializerExpr(InitValue);
+  }
+
   Pattern *Tmp2PBDPattern = new (Ctx) NamedPattern(Tmp2VD, /*implicit*/true);
   Tmp2PBDPattern = new (Ctx) TypedPattern(Tmp2PBDPattern,
                                           TypeLoc::withoutLoc(VD->getType()),
@@ -1132,7 +1274,8 @@
   // Assign tmp2 into storage.
   auto Tmp2DRE = new (Ctx) DeclRefExpr(Tmp2VD, DeclNameLoc(), /*Implicit*/true,
                                        AccessSemantics::DirectToStorage);
-  createPropertyStoreOrCallSuperclassSetter(Get, Tmp2DRE, Storage, Body, TC);
+  createPropertyStoreOrCallSuperclassSetter(Get, Tmp2DRE, Storage,
+                                            TargetImpl::Storage, Body, TC);
 
   // Return tmp2.
   Tmp2DRE = new (Ctx) DeclRefExpr(Tmp2VD, DeclNameLoc(), /*Implicit*/true,
@@ -1143,7 +1286,13 @@
   Get->setBody(BraceStmt::create(Ctx, VD->getLoc(), Body, VD->getLoc(),
                                  /*implicit*/true));
 
-  return Get;
+  finishSynthesis(TC, Get);
+}
+
+static void synthesizeLazySetterBody(TypeChecker &TC, AccessorDecl *setter,
+                                     VarDecl *underlyingStorage) {
+  synthesizeTrivialSetterBodyWithStorage(TC, setter, TargetImpl::Storage,
+                                         underlyingStorage);
 }
 
 void TypeChecker::completePropertyBehaviorStorage(VarDecl *VD,
@@ -1553,8 +1702,8 @@
 
 void TypeChecker::completeLazyVarImplementation(VarDecl *VD) {
   assert(VD->getAttrs().hasAttribute<LazyAttr>());
-  assert(VD->getStorageKind() == AbstractStorageDecl::Computed &&
-         "variable not validated yet");
+  assert(VD->getReadImpl() == ReadImplKind::Get);
+  assert(VD->getWriteImpl() == WriteImplKind::Set);
   assert(!VD->isStatic() && "Static vars are already lazy on their own");
 
   // Create the storage property as an optional of VD's type.
@@ -1586,15 +1735,12 @@
   PBD->setImplicit();
   addMemberToContextIfNeeded(PBD, VD->getDeclContext(), VD);
 
-  // Now that we've got the storage squared away, synthesize the getter.
-  completeLazyPropertyGetter(VD, Storage, *this);
-
-  // The setter just forwards on to storage without materializing the initial
-  // value.
-  auto *Set = VD->getSetter();
-  VarDecl *SetValueDecl = getFirstParamDecl(Set);
-  // FIXME: This is wrong for observed properties.
-  synthesizeTrivialSetter(Set, Storage, SetValueDecl, *this);
+  // Now that we've got the storage squared away, enqueue the getter and
+  // setter to be synthesized.
+  triggerSynthesis(*this, VD->getGetter(),
+                   SynthesizedFunction::LazyGetter, Storage);
+  triggerSynthesis(*this, VD->getSetter(),
+                   SynthesizedFunction::LazySetter, Storage);
 
   // Mark the vardecl to be final, implicit, and private.  In a class, this
   // prevents it from being dynamically dispatched.  Note that we do this after
@@ -1611,7 +1757,7 @@
 /// decl (which has accessors).
 void swift::maybeAddMaterializeForSet(AbstractStorageDecl *storage,
                                       TypeChecker &TC) {
-  assert(storage->hasAccessorFunctions());
+  assert(storage->getGetter());
 
   // Be idempotent.  There are a bunch of places where we want to
   // ensure that there's a materializeForSet accessor.
@@ -1639,209 +1785,247 @@
   addMaterializeForSet(storage, TC);
 }
 
-void swift::maybeAddAccessorsToVariable(VarDecl *var, TypeChecker &TC) {
+void swift::triggerAccessorSynthesis(TypeChecker &TC,
+                                     AbstractStorageDecl *storage) {
+  auto VD = dyn_cast<VarDecl>(storage);
+
+  // Synthesize accessors for lazy, all checking already been performed.
+  if (VD && VD->getAttrs().hasAttribute<LazyAttr>() && !VD->isStatic() &&
+      !VD->getGetter()->hasBody())
+    TC.completeLazyVarImplementation(VD);
+
+  switch (storage->getReadImpl()) {
+  case ReadImplKind::Get:
+    break;
+
+  // Synthesize the getter override for an inherited observed property.
+  case ReadImplKind::Stored:
+  case ReadImplKind::Inherited:
+  case ReadImplKind::Address:
+    if (auto getter = storage->getGetter())
+      triggerSynthesis(TC, getter, SynthesizedFunction::Getter);
+    break;
+  }
+
+  switch (storage->getWriteImpl()) {
+  case WriteImplKind::Immutable:
+  case WriteImplKind::Set:
+    break;
+
+  // Synthesize the setter for an observed property.
+  case WriteImplKind::Stored:
+  case WriteImplKind::StoredWithObservers:
+  case WriteImplKind::InheritedWithObservers:
+  case WriteImplKind::MutableAddress:
+    if (auto setter = storage->getSetter())
+      triggerSynthesis(TC, setter, SynthesizedFunction::Setter);
+    break;
+  }
+}
+
+static void maybeAddAccessorsToBehaviorStorage(TypeChecker &TC, VarDecl *var) {
+  // If there's already a getter, we're done.
   if (var->getGetter())
     return;
 
   auto *dc = var->getDeclContext();
 
-  assert(!var->hasAccessorFunctions());
+  assert(!var->getBehavior()->Conformance.hasValue());
+  
+  // The property should be considered computed by the time we're through.
+  SWIFT_DEFER {
+    assert(!var->hasStorage() && "behavior var was not made computed");
+  };
+  
+  auto behavior = var->getMutableBehavior();
+  NormalProtocolConformance *conformance = nullptr;
+  VarDecl *valueProp = nullptr;
 
-  // Introduce accessors for a property with behaviors.
-  if (var->hasBehavior()) {
-    assert(!var->getBehavior()->Conformance.hasValue());
-    
-    // The property should be considered computed by the time we're through.
-    SWIFT_DEFER {
-      assert(!var->hasStorage() && "behavior var was not made computed");
-    };
-    
-    auto behavior = var->getMutableBehavior();
-    NormalProtocolConformance *conformance = nullptr;
-    VarDecl *valueProp = nullptr;
+  bool mightBeMutating = dc->isTypeContext()
+    && !var->isStatic()
+    && !dc->getDeclaredInterfaceType()->hasReferenceSemantics();
 
-    bool mightBeMutating = dc->isTypeContext()
-      && !var->isStatic()
-      && !dc->getDeclaredInterfaceType()->hasReferenceSemantics();
+  auto makeBehaviorAccessors = [&]{
+    AccessorDecl *getter;
+    AccessorDecl *setter = nullptr;
+    if (valueProp && valueProp->getGetter()) {
+      getter = createGetterPrototype(TC, var);
+      // The getter is mutating if the behavior implementation is, unless
+      // we're in a class or non-instance context.
+      if (mightBeMutating && valueProp->isGetterMutating())
+        getter->setSelfAccessKind(SelfAccessKind::Mutating);
 
-    auto makeBehaviorAccessors = [&]{
-      AccessorDecl *getter;
-      AccessorDecl *setter = nullptr;
-      if (valueProp && valueProp->getGetter()) {
-        getter = createGetterPrototype(var, TC);
-        // The getter is mutating if the behavior implementation is, unless
-        // we're in a class or non-instance context.
-        if (mightBeMutating && valueProp->isGetterMutating())
-          getter->setSelfAccessKind(SelfAccessKind::Mutating);
+      getter->setAccess(var->getFormalAccess());
 
-        getter->setAccess(var->getFormalAccess());
-
-        // Make a setter if the behavior property has one.
-        if (valueProp->getSetter()) {
-          ParamDecl *newValueParam = nullptr;
-          setter = createSetterPrototype(var, newValueParam, TC);
-          if (mightBeMutating && valueProp->isSetterMutating())
-            setter->setSelfAccessKind(SelfAccessKind::Mutating);
-          // TODO: max of property and implementation setter visibility?
-          setter->setAccess(var->getFormalAccess());
-        }
-      } else {
-        // Even if we couldn't find a value property, still make up a stub
-        // getter and setter, so that subsequent diagnostics make sense for a
-        // computed-ish property.
-        getter = createGetterPrototype(var, TC);
-        getter->setAccess(var->getFormalAccess());
-        ParamDecl *newValueParam = nullptr;
-        setter = createSetterPrototype(var, newValueParam, TC);
-        setter->setSelfAccessKind(SelfAccessKind::NonMutating);
+      // Make a setter if the behavior property has one.
+      if (valueProp->getSetter()) {
+        setter = createSetterPrototype(TC, var, getter);
+        if (mightBeMutating && valueProp->isSetterMutating())
+          setter->setSelfAccessKind(SelfAccessKind::Mutating);
+        // TODO: max of property and implementation setter visibility?
         setter->setAccess(var->getFormalAccess());
       }
+    } else {
+      // Even if we couldn't find a value property, still make up a stub
+      // getter and setter, so that subsequent diagnostics make sense for a
+      // computed-ish property.
+      getter = createGetterPrototype(TC, var);
+      getter->setAccess(var->getFormalAccess());
+      setter = createSetterPrototype(TC, var, getter);
+      setter->setSelfAccessKind(SelfAccessKind::NonMutating);
+      setter->setAccess(var->getFormalAccess());
+    }
 
-      SmallVector<AccessorDecl*, 2> accessors;
-      accessors.push_back(getter);
-      if (setter) accessors.push_back(setter);
-      var->setAccessors(VarDecl::Computed, SourceLoc(), accessors, SourceLoc());
-      
-      // Save the conformance and 'value' decl for later type checking.
-      behavior->Conformance = conformance;
-      behavior->ValueDecl = valueProp;
+    SmallVector<AccessorDecl*, 2> accessors;
+    accessors.push_back(getter);
+    if (setter) accessors.push_back(setter);
+    var->setAccessors(StorageImplInfo::getComputed(setter != nullptr),
+                      SourceLoc(), accessors, SourceLoc());
+    
+    // Save the conformance and 'value' decl for later type checking.
+    behavior->Conformance = conformance;
+    behavior->ValueDecl = valueProp;
+  };
 
-      addMemberToContextIfNeeded(getter, dc, var);
-      if (setter)
-        addMemberToContextIfNeeded(setter, dc, getter);
-    };
+  // Try to resolve the behavior to a protocol.
+  auto behaviorType = TC.resolveType(behavior->ProtocolName, dc,
+                                     TypeResolutionOptions());
+  if (!behaviorType) {
+    return makeBehaviorAccessors();
+  }
+  
+  {
+    // The type must refer to a protocol.
+    auto behaviorProtoTy = behaviorType->getAs<ProtocolType>();
+    if (!behaviorProtoTy) {
+      TC.diagnose(behavior->getLoc(),
+                  diag::property_behavior_not_protocol);
+      behavior->Conformance = (NormalProtocolConformance*)nullptr;
+      return makeBehaviorAccessors();
+    }
+    auto behaviorProto = behaviorProtoTy->getDecl();
 
-    // Try to resolve the behavior to a protocol.
-    auto behaviorType = TC.resolveType(behavior->ProtocolName, dc,
-                                       TypeResolutionOptions());
-    if (!behaviorType) {
+    // Validate the behavior protocol and all its extensions so we can do
+    // name lookup.
+    TC.validateDecl(behaviorProto);
+    for (auto ext : behaviorProto->getExtensions()) {
+      TC.validateExtension(ext);
+    }
+    
+    // Look up the behavior protocol's "value" property, or bail if it doesn't
+    // have one. The property's accessors will decide whether the getter
+    // is mutating, and whether there's a setter. We'll type-check to make
+    // sure the property type matches later after validation.
+    auto lookup = TC.lookupMember(dc, behaviorProtoTy, TC.Context.Id_value);
+    for (auto found : lookup) {
+      if (auto foundVar = dyn_cast<VarDecl>(found.getValueDecl())) {
+        if (valueProp) {
+          TC.diagnose(behavior->getLoc(),
+                      diag::property_behavior_protocol_reqt_ambiguous,
+                      TC.Context.Id_value);
+          TC.diagnose(valueProp->getLoc(), diag::identifier_declared_here,
+                      TC.Context.Id_value);
+          TC.diagnose(foundVar->getLoc(), diag::identifier_declared_here,
+                      TC.Context.Id_value);
+          break;
+        }
+          
+        valueProp = foundVar;
+      }
+    }
+    
+    if (!valueProp) {
+      TC.diagnose(behavior->getLoc(),
+                  diag::property_behavior_protocol_no_value);
       return makeBehaviorAccessors();
     }
     
-    {
-      // The type must refer to a protocol.
-      auto behaviorProtoTy = behaviorType->getAs<ProtocolType>();
-      if (!behaviorProtoTy) {
-        TC.diagnose(behavior->getLoc(),
-                    diag::property_behavior_not_protocol);
-        behavior->Conformance = (NormalProtocolConformance*)nullptr;
-        return makeBehaviorAccessors();
-      }
-      auto behaviorProto = behaviorProtoTy->getDecl();
-
-      // Validate the behavior protocol and all its extensions so we can do
-      // name lookup.
-      TC.validateDecl(behaviorProto);
-      for (auto ext : behaviorProto->getExtensions()) {
-        TC.validateExtension(ext);
-      }
-      
-      // Look up the behavior protocol's "value" property, or bail if it doesn't
-      // have one. The property's accessors will decide whether the getter
-      // is mutating, and whether there's a setter. We'll type-check to make
-      // sure the property type matches later after validation.
-      auto lookup = TC.lookupMember(dc, behaviorProtoTy, TC.Context.Id_value);
-      for (auto found : lookup) {
-        if (auto foundVar = dyn_cast<VarDecl>(found.getValueDecl())) {
-          if (valueProp) {
-            TC.diagnose(behavior->getLoc(),
-                        diag::property_behavior_protocol_reqt_ambiguous,
-                        TC.Context.Id_value);
-            TC.diagnose(valueProp->getLoc(), diag::identifier_declared_here,
-                        TC.Context.Id_value);
-            TC.diagnose(foundVar->getLoc(), diag::identifier_declared_here,
-                        TC.Context.Id_value);
-            break;
-          }
-            
-          valueProp = foundVar;
-        }
-      }
-      
-      if (!valueProp) {
-        TC.diagnose(behavior->getLoc(),
-                    diag::property_behavior_protocol_no_value);
-        return makeBehaviorAccessors();
-      }
-      
-      TC.validateDecl(valueProp);
-      var->setIsGetterMutating(mightBeMutating &&
-                               valueProp->isGetterMutating());
-      var->setIsSetterMutating(mightBeMutating &&
-                               valueProp->isSetterMutating());
-      
-      // Set up a conformance to represent the behavior instantiation.
-      // The conformance will be on the containing 'self' type, or '()' if the
-      // property is in a non-type context.
-      Type behaviorSelf;
-      if (dc->isTypeContext()) {
-        behaviorSelf = dc->getSelfInterfaceType();
-        assert(behaviorSelf && "type context doesn't have self type?!");
-        if (var->isStatic())
-          behaviorSelf = MetatypeType::get(behaviorSelf);
-      } else {
-        behaviorSelf = TC.Context.TheEmptyTupleType;
-      }
-      
-      conformance = TC.Context.getBehaviorConformance(behaviorSelf,
-                                            behaviorProto,
-                                            behavior->getLoc(), var,
-                                            ProtocolConformanceState::Checking);
+    TC.validateDecl(valueProp);
+    var->setIsGetterMutating(mightBeMutating &&
+                             valueProp->isGetterMutating());
+    var->setIsSetterMutating(mightBeMutating &&
+                             valueProp->isSetterMutating());
+    
+    // Set up a conformance to represent the behavior instantiation.
+    // The conformance will be on the containing 'self' type, or '()' if the
+    // property is in a non-type context.
+    Type behaviorSelf;
+    if (dc->isTypeContext()) {
+      behaviorSelf = dc->getSelfInterfaceType();
+      assert(behaviorSelf && "type context doesn't have self type?!");
+      if (var->isStatic())
+        behaviorSelf = MetatypeType::get(behaviorSelf);
+    } else {
+      behaviorSelf = TC.Context.TheEmptyTupleType;
     }
-    return makeBehaviorAccessors();
+    
+    conformance = TC.Context.getBehaviorConformance(behaviorSelf,
+                                          behaviorProto,
+                                          behavior->getLoc(), var,
+                                          ProtocolConformanceState::Checking);
+  }
+  return makeBehaviorAccessors();
+}
+
+static void maybeAddAccessorsToLazyVariable(TypeChecker &TC, VarDecl *var) {
+  // If there are already accessors, something is invalid; bail out.
+  if (!var->getImplInfo().isSimpleStored())
+    return;
+
+  if (!var->getGetter()) {
+    addGetterToStorage(TC, var);
+  }
+
+  if (!var->getSetter()) {
+    addSetterToStorage(TC, var);
+  }
+
+  var->overwriteImplInfo(StorageImplInfo::getMutableComputed());
+
+  maybeAddMaterializeForSet(var, TC);
+}
+
+/// Try to add the appropriate accessors required a storage declaration.
+/// This needs to be idempotent.
+///
+/// Note that the parser synthesizes accessors in some cases:
+///   - it synthesizes a getter and setter for an observing property
+///   - it synthesizes a setter for get+mutableAddress
+void swift::maybeAddAccessorsToStorage(TypeChecker &TC,
+                                       AbstractStorageDecl *storage) {
+  // Introduce accessors for a property with behaviors.
+  if (storage->hasBehavior()) {
+    maybeAddAccessorsToBehaviorStorage(TC, cast<VarDecl>(storage));
+    return;
   }
 
   // Lazy properties require special handling.
-  if (var->getAttrs().hasAttribute<LazyAttr>()) {
-    auto *getter = createGetterPrototype(var, TC);
-    // lazy getters are mutating on an enclosing value type.
-    if (!dc->getAsClassOrClassExtensionContext()) {
-      getter->setSelfAccessKind(SelfAccessKind::Mutating);
-      var->setIsGetterMutating(true);
-    }
-    getter->setAccess(var->getFormalAccess());
-
-    ParamDecl *newValueParam = nullptr;
-    auto *setter = createSetterPrototype(var, newValueParam, TC);
-
-    AccessorDecl *materializeForSet = nullptr;
-    if (dc->getAsNominalTypeOrNominalTypeExtensionContext()) {
-      materializeForSet = createMaterializeForSetPrototype(var,
-                                                           getter, setter,
-                                                           TC);
-    }
-
-    SmallVector<AccessorDecl *, 3> accessors;
-    accessors.push_back(getter);
-    accessors.push_back(setter);
-    if (materializeForSet) accessors.push_back(materializeForSet);
-    var->setAccessors(VarDecl::Computed, SourceLoc(), accessors, SourceLoc());
-
-    addMemberToContextIfNeeded(getter, dc, var);
-    addMemberToContextIfNeeded(setter, dc, getter);
-    if (materializeForSet)
-      addMemberToContextIfNeeded(materializeForSet, dc, setter);
+  if (storage->getAttrs().hasAttribute<LazyAttr>()) {
+    maybeAddAccessorsToLazyVariable(TC, cast<VarDecl>(storage));
     return;
   }
 
+  auto *dc = storage->getDeclContext();
+
   // Local variables don't otherwise get accessors.
   if (dc->isLocalContext())
     return;
 
   // Implicit properties don't get accessors.
-  if (var->isImplicit())
+  if (storage->isImplicit())
     return;
 
   if (!dc->isTypeContext()) {
     // Fixed-layout global variables don't get accessors.
-    if (!var->isResilient())
+    if (!storage->isResilient())
       return;
 
   // In a protocol context, variables written as just "var x : Int" or
   // "let x : Int" are errors and recovered by building a computed property
   // with just a getter. Diagnose this and create the getter decl now.
   } else if (isa<ProtocolDecl>(dc)) {
-    if (var->hasStorage()) {
+    if (storage->hasStorage()) {
+      auto var = cast<VarDecl>(storage);
       if (var->isLet())
         TC.diagnose(var->getLoc(),
                     diag::protocol_property_must_be_computed_var);
@@ -1850,11 +2034,14 @@
 
       convertStoredVarInProtocolToComputed(var, TC);
     }
+
+    maybeAddMaterializeForSet(storage, TC);
     return;
 
   // NSManaged properties on classes require special handling.
   } else if (dc->getAsClassOrClassExtensionContext()) {
-    if (var->getAttrs().hasAttribute<NSManagedAttr>()) {
+    auto var = dyn_cast<VarDecl>(storage);
+    if (var && var->getAttrs().hasAttribute<NSManagedAttr>()) {
       convertNSManagedStoredVarToComputed(var, TC);
       return;
     }
@@ -1866,12 +2053,88 @@
   }
 
   // Stored properties in SIL mode don't get accessors.
+  // But they might get a materializeForSet.
   if (auto sourceFile = dc->getParentSourceFile())
-    if (sourceFile->Kind == SourceFileKind::SIL)
+    if (sourceFile->Kind == SourceFileKind::SIL) {
+      if (storage->getGetter() && storage->getSetter()) {
+        maybeAddMaterializeForSet(storage, TC);
+      }
       return;
+    }
 
-  // Everything else gets accessors.
-  addTrivialAccessorsToStorage(var, TC);
+  // Everything else gets mandatory accessors.
+  addTrivialAccessorsToStorage(storage, TC);
+}
+
+static void synthesizeGetterBody(TypeChecker &TC, AccessorDecl *getter) {
+  switch (getter->getStorage()->getReadImpl()) {
+  case ReadImplKind::Stored:
+    synthesizeTrivialGetterBody(TC, getter);
+    return;
+
+  case ReadImplKind::Get:
+    llvm_unreachable("synthesizing getter that already exists?");
+
+  case ReadImplKind::Inherited:
+    synthesizeInheritedGetterBody(TC, getter);
+    return;
+
+  case ReadImplKind::Address:
+    synthesizeAddressedGetterBody(TC, getter);
+    return;
+  }
+  llvm_unreachable("bad ReadImplKind");
+}
+
+static void synthesizeSetterBody(TypeChecker &TC, AccessorDecl *setter) {
+  switch (setter->getStorage()->getWriteImpl()) {
+  case WriteImplKind::Immutable:
+    llvm_unreachable("synthesizing setter from immutable storage");
+
+  case WriteImplKind::Stored:
+    return synthesizeTrivialSetterBody(TC, setter);
+
+  case WriteImplKind::StoredWithObservers:
+    return synthesizeStoredWithObserversSetterBody(TC, setter);
+
+  case WriteImplKind::InheritedWithObservers:
+    return synthesizeInheritedWithObserversSetterBody(TC, setter);
+
+  case WriteImplKind::Set:
+    llvm_unreachable("synthesizing setter for unknown reason?");  
+
+  case WriteImplKind::MutableAddress:
+    return synthesizeMutableAddressSetterBody(TC, setter);
+  }
+  llvm_unreachable("bad ReadImplKind");
+}
+
+void TypeChecker::synthesizeFunctionBody(SynthesizedFunction fn) {
+  switch (fn.getKind()) {
+  case SynthesizedFunction::Getter:
+    synthesizeGetterBody(*this, cast<AccessorDecl>(fn.getDecl()));
+    return;
+
+  case SynthesizedFunction::Setter:
+    synthesizeSetterBody(*this, cast<AccessorDecl>(fn.getDecl()));
+    return;
+
+  case SynthesizedFunction::MaterializeForSet:
+    llvm_unreachable("not used right now?");
+    //synthesizeMaterializeForSetBody(*this, cast<AccessorDecl>(fn.getDecl()));
+    return;
+
+  case SynthesizedFunction::LazyGetter:
+    synthesizeLazyGetterBody(*this, cast<AccessorDecl>(fn.getDecl()),
+                             fn.getLazyTargetVariable());
+    return;
+
+  case SynthesizedFunction::LazySetter:
+    synthesizeLazySetterBody(*this, cast<AccessorDecl>(fn.getDecl()),
+                             fn.getLazyTargetVariable());
+    return;
+  }
+  llvm_unreachable("bad synthesized function kind");
 }
 
 /// \brief Create an implicit struct or class constructor.
diff --git a/lib/Sema/CodeSynthesis.h b/lib/Sema/CodeSynthesis.h
index 1b7103e..c307cb4 100644
--- a/lib/Sema/CodeSynthesis.h
+++ b/lib/Sema/CodeSynthesis.h
@@ -19,6 +19,7 @@
 #define SWIFT_TYPECHECKING_CODESYNTHESIS_H
 
 #include "swift/AST/ForeignErrorConvention.h"
+#include "swift/Basic/ExternalUnion.h"
 #include "swift/Basic/LLVM.h"
 #include "llvm/ADT/Optional.h"
 
@@ -40,6 +41,57 @@
 
 enum class ObjCReason;
 
+/// A function which needs to have its body synthesized.
+///
+/// This class exists in expectation that someone will need to add more
+/// information to it.
+class SynthesizedFunction {
+public:
+  enum Kind {
+    Getter,
+    Setter,
+    MaterializeForSet,
+    LazyGetter,
+    LazySetter,
+  };
+
+private:
+  FuncDecl *Fn;
+  Kind K;
+
+  using Members = ExternalUnionMembers<void, VarDecl*>;
+  static Members::Index getIndexForKind(Kind kind) {
+    switch (kind) {
+    case Kind::Getter:
+    case Kind::Setter:
+    case Kind::MaterializeForSet:
+      return Members::indexOf<void>();
+    case Kind::LazyGetter:
+    case Kind::LazySetter:
+      return Members::indexOf<VarDecl*>();
+    }
+    llvm_unreachable("bad kind");
+  };
+  ExternalUnion<Kind, Members, getIndexForKind> Extra;
+  static_assert(decltype(Extra)::union_is_trivially_copyable,
+                "expected all members to be trivial");
+
+public:
+  SynthesizedFunction(FuncDecl *fn, Kind kind) : Fn(fn), K(kind) {
+    assert(getIndexForKind(kind) == Members::indexOf<void>() &&
+           "this storage kind requires extra data");
+  }
+
+  SynthesizedFunction(FuncDecl *fn, Kind kind, VarDecl *var) : Fn(fn), K(kind) {
+    Extra.emplace<VarDecl*>(K, var);
+  }
+
+  FuncDecl *getDecl() const { return Fn; }
+  Kind getKind() const { return K; }
+
+  VarDecl *getLazyTargetVariable() const { return Extra.get<VarDecl*>(K); }
+};
+
 // These are implemented in TypeCheckDecl.cpp.
 void makeFinal(ASTContext &ctx, ValueDecl *D);
 void makeDynamic(ASTContext &ctx, ValueDecl *D);
@@ -49,12 +101,11 @@
 bool checkOverrides(TypeChecker &TC, ValueDecl *decl);
 
 // These are implemented in CodeSynthesis.cpp.
-void synthesizeObservingAccessors(VarDecl *VD, TypeChecker &TC);
-void synthesizeSetterForMutableAddressedStorage(AbstractStorageDecl *storage,
-                                                TypeChecker &TC);
 void maybeAddMaterializeForSet(AbstractStorageDecl *storage,
                                TypeChecker &TC);
-void maybeAddAccessorsToVariable(VarDecl *var, TypeChecker &TC);
+void maybeAddAccessorsToStorage(TypeChecker &TC, AbstractStorageDecl *storage);
+
+void triggerAccessorSynthesis(TypeChecker &TC, AbstractStorageDecl *storage);
 
 /// \brief Describes the kind of implicit constructor that will be
 /// generated.
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index b5fba35..eafa3d2 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -1087,8 +1087,8 @@
   hashValueDecl->setImplicit();
   hashValueDecl->setInterfaceType(intType);
   hashValueDecl->setValidationStarted();
-  hashValueDecl->setAccessors(VarDecl::Computed, SourceLoc(), {getterDecl},
-                              SourceLoc());
+  hashValueDecl->setAccessors(StorageImplInfo::getImmutableComputed(),
+                              SourceLoc(), {getterDecl}, SourceLoc());
   hashValueDecl->copyFormalAccessFrom(derived.Nominal,
                                       /*sourceIsParentContext*/ true);
 
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index c646d4c..ce59bb4 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -272,7 +272,7 @@
   auto getter =
     declareDerivedPropertyGetter(tc, property, propertyContextType);
 
-  property->setAccessors(VarDecl::Computed,
+  property->setAccessors(StorageImplInfo::getImmutableComputed(),
                          SourceLoc(), {getter}, SourceLoc());
 
   return getter;
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index dab83ec..4ca4449 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -87,13 +87,16 @@
     // message.
     struct PartialApplication {
       enum : unsigned {
-        Function,
         MutatingMethod,
         SuperInit,
         SelfInit,
       };
-      // 'kind' before 'level' is better for code gen.
-      unsigned kind : 3;
+      enum : unsigned {
+        Error,
+        CompatibilityWarning,
+      };
+      unsigned compatibilityWarning: 1;
+      unsigned kind : 2;
       unsigned level : 29;
     };
 
@@ -105,49 +108,18 @@
     ~DiagnoseWalker() override {
       for (auto &unapplied : InvalidPartialApplications) {
         unsigned kind = unapplied.second.kind;
-        TC.diagnose(unapplied.first->getLoc(),
-                    diag::partial_application_of_function_invalid,
-                    kind);
+        if (unapplied.second.compatibilityWarning) {
+          TC.diagnose(unapplied.first->getLoc(),
+                      diag::partial_application_of_function_invalid_swift4,
+                      kind);
+        } else {
+          TC.diagnose(unapplied.first->getLoc(),
+                      diag::partial_application_of_function_invalid,
+                      kind);
+        }
       }
     }
 
-    /// If this is an application of a function that cannot be partially
-    /// applied, arrange for us to check that it gets fully applied.
-    void recordUnsupportedPartialApply(ApplyExpr *expr, Expr *fnExpr) {
-
-      if (isa<OtherConstructorDeclRefExpr>(fnExpr)) {
-        auto kind = expr->getArg()->isSuperExpr()
-                  ? PartialApplication::SuperInit
-                  : PartialApplication::SelfInit;
-
-        // Partial applications of delegated initializers aren't allowed, and
-        // don't really make sense to begin with.
-        InvalidPartialApplications.insert({ expr, {kind, 1} });
-        return;
-      }
-
-      auto fnDeclRef = dyn_cast<DeclRefExpr>(fnExpr);
-      if (!fnDeclRef)
-        return;
-
-      auto fn = dyn_cast<FuncDecl>(fnDeclRef->getDecl());
-      if (!fn)
-        return;
-
-      unsigned kind =
-        fn->isInstanceMember() ? PartialApplication::MutatingMethod
-                               : PartialApplication::Function;
-      
-      // Functions with inout parameters cannot be partially applied.
-      if (!expr->getArg()->getType()->isMaterializable()) {
-        // We need to apply all argument clauses.
-        InvalidPartialApplications.insert({
-          fnExpr, {kind, fn->getNumParameterLists()}
-        });
-      }
-    }
-
-    /// This method is called in post-order over the AST to validate that
     /// methods are fully applied when they can't support partial application.
     void checkInvalidPartialApplication(Expr *E) {
       if (auto AE = dyn_cast<ApplyExpr>(E)) {
@@ -158,8 +130,18 @@
           fnExpr = dotSyntaxExpr->getRHS();
 
         // Check to see if this is a potentially unsupported partial
-        // application.
-        recordUnsupportedPartialApply(AE, fnExpr);
+        // application of a constructor delegation.
+        if (isa<OtherConstructorDeclRefExpr>(fnExpr)) {
+          auto kind = AE->getArg()->isSuperExpr()
+                    ? PartialApplication::SuperInit
+                    : PartialApplication::SelfInit;
+
+          // Partial applications of delegated initializers aren't allowed, and
+          // don't really make sense to begin with.
+          InvalidPartialApplications.insert(
+            {E, {PartialApplication::Error, kind, 1}});
+          return;
+        }
 
         // If this is adding a level to an active partial application, advance
         // it to the next level.
@@ -173,11 +155,36 @@
         InvalidPartialApplications.erase(foundApplication);
         if (level > 1) {
           // We have remaining argument clauses.
-          InvalidPartialApplications.insert({ AE, {kind, level - 1} });
+          // Partial applications were always diagnosed in Swift 4 and before,
+          // so there's no need to preserve the compatibility warning bit.
+          InvalidPartialApplications.insert(
+            {AE, {PartialApplication::Error, kind, level - 1}});
         }
         return;
       }
+      
+      /// If this is a reference to a mutating method, it cannot be partially
+      /// applied or even referenced without full application, so arrange for
+      /// us to check that it gets fully applied.
+      auto fnDeclRef = dyn_cast<DeclRefExpr>(E);
+      if (!fnDeclRef)
+        return;
 
+      auto fn = dyn_cast<FuncDecl>(fnDeclRef->getDecl());
+      if (!fn || !fn->isInstanceMember() || !fn->isMutating())
+        return;
+
+      // Swift 4 and earlier failed to diagnose a reference to a mutating method
+      // without any applications at all, which would get miscompiled into a
+      // function with undefined behavior. Warn for source compatibility.
+      auto errorBehavior = TC.Context.LangOpts.isSwiftVersionAtLeast(5)
+        ? PartialApplication::Error
+        : PartialApplication::CompatibilityWarning;
+
+      InvalidPartialApplications.insert(
+        {fnDeclRef, {errorBehavior,
+                     PartialApplication::MutatingMethod,
+                     fn->getNumParameterLists()}});
     }
 
     // Not interested in going outside a basic expression.
@@ -1586,7 +1593,7 @@
       if (auto *DRE = dyn_cast<DeclRefExpr>(subExpr)) {
         if (DRE->getDecl() == Var) {
           // Handle local and top-level computed variables.
-          if (DRE->getAccessSemantics() != AccessSemantics::DirectToStorage) {
+          if (DRE->getAccessSemantics() == AccessSemantics::Ordinary) {
             bool shouldDiagnose = false;
             // Warn about any property access in the getter.
             if (Accessor->isGetter())
@@ -1623,7 +1630,7 @@
             isa<DeclRefExpr>(MRE->getBase()) &&
             isImplicitSelfUse(MRE->getBase())) {
           
-          if (MRE->getAccessSemantics() != AccessSemantics::DirectToStorage) {
+          if (MRE->getAccessSemantics() == AccessSemantics::Ordinary) {
             bool shouldDiagnose = false;
             // Warn about any property access in the getter.
             if (Accessor->isGetter())
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 629b39d..1fad540 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -542,8 +542,8 @@
   };
 
   // @NSManaged properties must be written as stored.
-  switch (VD->getStorageKind()) {
-  case AbstractStorageDecl::Stored:
+  auto impl = VD->getImplInfo();
+  if (impl.isSimpleStored()) {
     // @NSManaged properties end up being computed; complain if there is
     // an initializer.
     if (VD->getParentInitializer()) {
@@ -553,21 +553,14 @@
       PBD->setInit(PBD->getPatternEntryIndexForVarDecl(VD), nullptr);
     }
     // Otherwise, ok.
-    break;
-
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
-    llvm_unreachable("Already created accessors?");
-
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-  case AbstractStorageDecl::Computed:
+  } else if (impl.getReadImpl() == ReadImplKind::Address ||
+             impl.getWriteImpl() == WriteImplKind::MutableAddress) {
+    return diagnoseNotStored(/*addressed*/ 2);    
+  } else if (impl.getWriteImpl() == WriteImplKind::StoredWithObservers ||
+             impl.getWriteImpl() == WriteImplKind::InheritedWithObservers) {
+    return diagnoseNotStored(/*observing*/ 1);    
+  } else {
     return diagnoseNotStored(/*computed*/ 0);
-  case AbstractStorageDecl::StoredWithObservers:
-  case AbstractStorageDecl::InheritedWithObservers:
-    return diagnoseNotStored(/*observing*/ 1);
-  case AbstractStorageDecl::Addressed:
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-  case AbstractStorageDecl::AddressedWithObservers:
-    return diagnoseNotStored(/*addressed*/ 2);
   }
 
   // @NSManaged properties cannot be @NSCopying
@@ -630,24 +623,13 @@
 
 
   // TODO: Lazy properties can't yet be observed.
-  switch (VD->getStorageKind()) {
-  case AbstractStorageDecl::Stored:
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
-    break;
-
-  case AbstractStorageDecl::StoredWithObservers:
+  auto impl = VD->getImplInfo();
+  if (impl.isSimpleStored()) {
+    // ok
+  } else if (VD->hasStorage()) {
     diagnoseAndRemoveAttr(attr, diag::lazy_not_observable);
-    break;
-
-  case AbstractStorageDecl::InheritedWithObservers:
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-  case AbstractStorageDecl::Computed:
-  case AbstractStorageDecl::Addressed:
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-  case AbstractStorageDecl::AddressedWithObservers:
-    assert(!VD->hasStorage() && "Non-stored AbstractStorageDecl has storage?");
+  } else {
     diagnoseAndRemoveAttr(attr, diag::lazy_not_on_computed);
-    break;
   }
 }
 
@@ -1286,6 +1268,13 @@
     return;
   }
 
+  if (VD->hasInterfaceType()) {
+    if (TC.checkConformanceToNSCopying(VD)) {
+      attr->setInvalid();
+      return;
+    }
+  }
+
   assert(VD->getOverriddenDecl() == nullptr &&
          "Can't have value with storage that is an override");
 
diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp
index 9abe9d4..09e002f 100644
--- a/lib/Sema/TypeCheckAvailability.cpp
+++ b/lib/Sema/TypeCheckAvailability.cpp
@@ -179,7 +179,7 @@
     // when we process the accessor, we can use this TRC as the
     // parent.
     if (auto *StorageDecl = dyn_cast<AbstractStorageDecl>(D)) {
-      if (StorageDecl->hasAccessorFunctions()) {
+      if (StorageDecl->hasAnyAccessors()) {
         StorageContexts[StorageDecl] = NewTRC;
       }
     }
@@ -228,7 +228,7 @@
       // locations and have callers of that method provide appropriate source
       // locations.
       SourceLoc BracesEnd = storageDecl->getBracesRange().End;
-      if (storageDecl->hasAccessorFunctions() && BracesEnd.isValid()) {
+      if (storageDecl->hasAnyAccessors() && BracesEnd.isValid()) {
         return SourceRange(storageDecl->getStartLoc(),
                            BracesEnd);
       }
@@ -2433,11 +2433,14 @@
     if (!D)
       return;
 
-    if (!D->hasAccessorFunctions()) {
+    if (!D->hasAnyAccessors()) {
       return;
     }
     
-    // Check availability of accessor functions
+    // Check availability of accessor functions.
+    // TODO: if we're talking about an inlineable storage declaration,
+    // this probably needs to be refined to not assume that the accesses are
+    // specifically using the getter/setter.
     switch (AccessContext) {
     case MemberAccessContext::Getter:
       diagAccessorAvailability(D->getGetter(), ReferenceRange, ReferenceDC,
diff --git a/lib/Sema/TypeCheckCaptures.cpp b/lib/Sema/TypeCheckCaptures.cpp
index 20df65a..3ee4622 100644
--- a/lib/Sema/TypeCheckCaptures.cpp
+++ b/lib/Sema/TypeCheckCaptures.cpp
@@ -19,6 +19,7 @@
 #include "swift/AST/ASTVisitor.h"
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/Decl.h"
+#include "swift/AST/Initializer.h"
 #include "swift/AST/ForeignErrorConvention.h"
 #include "swift/AST/GenericSignature.h"
 #include "swift/AST/ParameterList.h"
@@ -227,6 +228,13 @@
     }
   }
 
+  bool shouldWalkIntoLazyInitializers() override {
+    // We don't want to walk into lazy initializers because they're not
+    // really present at this level.  We'll catch them when processing
+    // the getter.
+    return false;
+  }
+
   std::pair<bool, Expr *> walkToDeclRefExpr(DeclRefExpr *DRE) {
     auto *D = DRE->getDecl();
 
@@ -262,6 +270,22 @@
         if (TmpDC == DC)
           break;
 
+        // The initializer of a lazy property will eventually get
+        // recontextualized into it, so treat it as if it's already there.
+        if (auto init = dyn_cast<PatternBindingInitializer>(TmpDC)) {
+          if (auto lazyVar = init->getInitializedLazyVar()) {
+            // Referring to the 'self' parameter is fine.
+            if (D == init->getImplicitSelfDecl())
+              return { false, DRE };
+
+            // Otherwise, act as if we're in the getter.
+            auto getter = lazyVar->getGetter();
+            assert(getter && "lazy variable without getter");
+            TmpDC = getter;
+            continue;
+          }
+        }
+
         // We have an intervening nominal type context that is not the
         // declaration context, and the declaration context is not global.
         // This is not supported since nominal types cannot capture values.
@@ -382,8 +406,14 @@
 
     // If this is a direct reference to underlying storage, then this is a
     // capture of the storage address - not a capture of the getter/setter.
-    if (DRE->getAccessSemantics() == AccessSemantics::DirectToStorage)
-      Flags |= CapturedValue::IsDirect;
+    if (auto var = dyn_cast<VarDecl>(D)) {
+      if (var->getAccessStrategy(DRE->getAccessSemantics(),
+                                 var->supportsMutation()
+                                   ? AccessKind::ReadWrite : AccessKind::Read,
+                                 AFR.getAsDeclContext())
+          .getKind() == AccessStrategy::Storage)
+        Flags |= CapturedValue::IsDirect;
+    }
 
     // If the closure is noescape, then we can capture the decl as noescape.
     if (AFR.isKnownNoEscape())
@@ -619,6 +649,12 @@
     if (auto *DRE = dyn_cast<DeclRefExpr>(E))
       return walkToDeclRefExpr(DRE);
 
+    // Look into lazy initializers.
+    if (auto *LIE = dyn_cast<LazyInitializerExpr>(E)) {
+      LIE->getSubExpr()->walk(*this);
+      return { true, E };
+    }
+
     // When we see a reference to the 'super' expression, capture 'self' decl.
     if (auto *superE = dyn_cast<SuperRefExpr>(E)) {
       auto CurDC = AFR.getAsDeclContext();
@@ -721,9 +757,13 @@
         if (!PBD) continue;
         // Walk the initializers for all properties declared in the type with
         // an initializer.
-        for (auto &elt : PBD->getPatternList())
+        for (auto &elt : PBD->getPatternList()) {
+          if (elt.isInitializerLazy())
+            continue;
+
           if (auto *init = elt.getInit())
             init->walk(finder);
+        }
       }
     }
   }
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 4250dd8..d47fc74 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -40,7 +40,7 @@
 #include "swift/Parse/Parser.h"
 #include "swift/Serialization/SerializedModuleLoader.h"
 #include "swift/Strings.h"
-#include "swift/Sema/TypeCheckRequests.h"
+#include "swift/AST/TypeCheckRequests.h"
 #include "swift/Basic/Defer.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APInt.h"
@@ -233,21 +233,6 @@
 /// Check that the declaration attributes are ok.
 static void validateAttributes(TypeChecker &TC, Decl *D);
 
-Type TypeChecker::getSuperclass(const ClassDecl *classDecl) {
-  return Context.evaluator(
-           SuperclassTypeRequest(const_cast<ClassDecl *>(classDecl)));
-}
-
-Type TypeChecker::getRawType(EnumDecl *enumDecl) {
-  return Context.evaluator(EnumRawTypeRequest(enumDecl));
-}
-
-Type TypeChecker::getInheritedType(
-                         llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
-                         unsigned index) {
-  return Context.evaluator(InheritedTypeRequest(decl, index));
-}
-
 void TypeChecker::resolveTrailingWhereClause(ProtocolDecl *proto) {
   ProtocolRequirementTypeResolver resolver;
   validateWhereClauses(proto, &resolver);
@@ -327,25 +312,15 @@
 
   MutableArrayRef<TypeLoc> inheritedClause;
 
-  // If we already checked the inheritance clause, don't do so again.
   if (auto type = dyn_cast<TypeDecl>(decl)) {
-    if (type->checkedInheritanceClause())
-      return;
-
-    // This breaks infinite recursion, which will be diagnosed separately.
-    type->setCheckedInheritanceClause();
     inheritedClause = type->getInherited();
   } else {
     auto ext = cast<ExtensionDecl>(decl);
 
     validateExtension(ext);
-
-    if (ext->isInvalid() ||
-        ext->checkedInheritanceClause())
+    if (ext->isInvalid())
       return;
 
-    // This breaks infinite recursion, which will be diagnosed separately.
-    ext->setCheckedInheritanceClause();
     inheritedClause = ext->getInherited();
 
     // Protocol extensions cannot have inheritance clauses.
@@ -624,7 +599,7 @@
     for (unsigned i = 0, n = allProtocols.size(); i != n; /*in loop*/) {
       if (allProtocols[i] == proto || allProtocols[i]->inheritsFrom(proto)) {
         if (!diagnosedCircularity) {
-          diagnose(proto, diag::circular_protocol_def, proto->getName().str());
+          diagnose(proto, diag::circular_protocol_def, proto->getName());
           diagnosedCircularity = true;
         }
 
@@ -643,17 +618,16 @@
 getInheritedForCycleCheck(TypeChecker &tc,
                           ProtocolDecl *proto,
                           ProtocolDecl **scratch) {
-  return tc.getDirectConformsTo(proto);
+  tc.resolveInheritedProtocols(proto);
+  return proto->getInheritedProtocols();
 }
 
 /// Retrieve the superclass of the given class.
 static ArrayRef<ClassDecl *> getInheritedForCycleCheck(TypeChecker &tc,
                                                        ClassDecl *classDecl,
                                                        ClassDecl **scratch) {
-  tc.checkInheritanceClause(classDecl);
-
   if (classDecl->hasSuperclass()) {
-    *scratch = classDecl->getSuperclass()->getClassOrBoundGenericClass();
+    *scratch = classDecl->getSuperclassDecl();
     return *scratch;
   }
   return { };
@@ -663,8 +637,6 @@
 static ArrayRef<EnumDecl *> getInheritedForCycleCheck(TypeChecker &tc,
                                                       EnumDecl *enumDecl,
                                                       EnumDecl **scratch) {
-  tc.checkInheritanceClause(enumDecl);
-  
   if (enumDecl->hasRawType()) {
     *scratch = enumDecl->getRawType()->getEnumOrBoundGenericEnum();
     return *scratch ? ArrayRef<EnumDecl*>(*scratch) : ArrayRef<EnumDecl*>{};
@@ -692,7 +664,7 @@
 /// Check for circular inheritance.
 template<typename T>
 static void checkCircularity(TypeChecker &tc, T *decl,
-                             Diag<StringRef> circularDiag,
+                             Diag<Identifier> circularDiag,
                              DescriptiveDeclKind declKind,
                              SmallVectorImpl<T *> &path) {
   switch (decl->getCircularityCheck()) {
@@ -716,7 +688,7 @@
     if (path.end() - cycleStart == 1) {
       tc.diagnose(path.back()->getLoc(),
                   circularDiag,
-                  path.back()->getName().str());
+                  path.back()->getName());
 
       decl->setInvalid();
       decl->setInterfaceType(ErrorType::get(tc.Context));
@@ -724,17 +696,9 @@
       break;
     }
 
-    // Form the textual path illustrating the cycle.
-    llvm::SmallString<128> pathStr;
-    for (auto i = cycleStart, iEnd = path.end(); i != iEnd; ++i) {
-      if (!pathStr.empty())
-        pathStr += " -> ";
-      pathStr += ("'" + (*i)->getName().str() + "'").str();
-    }
-    pathStr += (" -> '" + decl->getName().str() + "'").str();
-
     // Diagnose the cycle.
-    tc.diagnose(decl->getLoc(), circularDiag, pathStr);
+    tc.diagnose(decl->getLoc(), circularDiag,
+                (*cycleStart)->getName());
     for (auto i = cycleStart + 1, iEnd = path.end(); i != iEnd; ++i) {
       tc.diagnose(*i, diag::kind_identifier_declared_here,
                   declKind, (*i)->getName());
@@ -1164,10 +1128,12 @@
   // If the pattern didn't get a type or if it contains an unbound generic type,
   // we'll need to check the initializer.
   if (!pattern->hasType() || pattern->getType()->hasUnboundGenericType()) {
+    // We used to not apply the solution to lazy bindings here, but that's
+    // unnecessary: the code for building lazy getters already has to handle
+    // initializers which have had solutions applied, and not applying the
+    // solution blocks other diagnostics if we decide not to synthesize the
+    // getter.
     bool skipApplyingSolution = false;
-    if (auto var = binding->getSingleVar())
-      skipApplyingSolution = var->getAttrs().hasAttribute<LazyAttr>();
-
     if (tc.typeCheckPatternBinding(binding, entryNumber, skipApplyingSolution))
       return;
   }
@@ -1192,8 +1158,9 @@
 
   // If we have any type-adjusting attributes, apply them here.
   assert(binding->getPattern(entryNumber)->hasType() && "Type missing?");
-  if (auto var = binding->getSingleVar())
+  if (auto var = binding->getSingleVar()) {
     tc.checkTypeModifyingDeclAttributes(var);
+  }
 }
 
 /// Validate the entries in the given pattern binding declaration.
@@ -1565,8 +1532,21 @@
   if (isa<DestructorDecl>(decl))
     return;
 
+  assert(decl->isObjC() && "Must be known to be @objc");
   auto attr = decl->getAttrs().getAttribute<ObjCAttr>();
-  assert(attr && "should only be called on decls already marked @objc");
+
+  /// Set the @objc name.
+  auto setObjCName = [&](ObjCSelector selector) {
+    // If there already is an @objc attribute, update its name.
+    if (attr) {
+      const_cast<ObjCAttr *>(attr)->setName(selector, /*implicit=*/true);
+      return;
+    }
+
+    // Otherwise, create an @objc attribute with the implicit name.
+    attr = ObjCAttr::create(tc.Context, selector, /*implicitName=*/true);
+    decl->getAttrs().add(attr);
+  };
 
   // If this declaration overrides an @objc declaration, use its name.
   if (auto overridden = decl->getOverriddenDecl()) {
@@ -1577,8 +1557,8 @@
         ObjCSelector overriddenSelector = overriddenFunc->getObjCSelector();
 
         // Determine whether there is a name conflict.
-        bool shouldFixName = !attr->hasName();
-        if (attr->hasName() && *attr->getName() != overriddenSelector) {
+        bool shouldFixName = !attr || !attr->hasName();
+        if (attr && attr->hasName() && *attr->getName() != overriddenSelector) {
           // If the user explicitly wrote the incorrect name, complain.
           if (!attr->isNameImplicit()) {
             {
@@ -1598,8 +1578,7 @@
         // If we have to set the name, do so.
         if (shouldFixName) {
           // Override the name on the attribute.
-          const_cast<ObjCAttr *>(attr)->setName(overriddenSelector,
-                                                /*implicit=*/true);
+          setObjCName(overriddenSelector);
         }
         return;
       }
@@ -1610,8 +1589,9 @@
         ObjCSelector overriddenNameAsSel(tc.Context, 0, overriddenName);
 
         // Determine whether there is a name conflict.
-        bool shouldFixName = !attr->hasName();
-        if (attr->hasName() && *attr->getName() != overriddenNameAsSel) {
+        bool shouldFixName = !attr || !attr->hasName();
+        if (attr && attr->hasName() &&
+            *attr->getName() != overriddenNameAsSel) {
           // If the user explicitly wrote the wrong name, complain.
           if (!attr->isNameImplicit()) {
             tc.diagnose(attr->AtLoc,
@@ -1629,8 +1609,7 @@
 
         // Fix the name, if needed.
         if (shouldFixName) {
-          const_cast<ObjCAttr *>(attr)->setName(overriddenNameAsSel,
-                                                /*implicit=*/true);
+          setObjCName(overriddenNameAsSel);
         }
         return;
       }
@@ -1639,7 +1618,7 @@
 
   // If the decl already has a name, do nothing; the protocol conformance
   // checker will handle any mismatches.
-  if (attr->hasName()) return;
+  if (attr && attr->hasName()) return;
 
   // When no override determined the Objective-C name, look for
   // requirements for which this declaration is a witness.
@@ -1683,8 +1662,7 @@
 
   // If we have a name, install it via an @objc attribute.
   if (requirementObjCName) {
-    const_cast<ObjCAttr *>(attr)->setName(*requirementObjCName,
-                                          /*implicit=*/true);
+    setObjCName(*requirementObjCName);
   }
 }
 
@@ -1832,6 +1810,10 @@
     // Mark the attribute as having used Swift 3 inference, or create an
     // implicit @objc for that purpose.
     auto attr = D->getAttrs().getAttribute<ObjCAttr>();
+    if (!attr) {
+      attr = ObjCAttr::createUnnamedImplicit(TC.Context);
+      D->getAttrs().add(attr);
+    }
     attr->setSwift3Inferred();
   }
 }
@@ -2796,50 +2778,40 @@
 
 static bool computeIsGetterMutating(TypeChecker &TC,
                                     AbstractStorageDecl *storage) {
-  switch (storage->getStorageKind()) {
-  case AbstractStorageDecl::Stored:
+  switch (storage->getReadImpl()) {
+  case ReadImplKind::Stored:
     return false;
 
-  case AbstractStorageDecl::StoredWithObservers:
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
-  case AbstractStorageDecl::InheritedWithObservers:
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-  case AbstractStorageDecl::Computed:
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-  case AbstractStorageDecl::AddressedWithObservers:
+  case ReadImplKind::Get:
+  case ReadImplKind::Inherited:
     return validateAccessorIsMutating(TC, storage->getGetter());
 
-  case AbstractStorageDecl::Addressed:
+  case ReadImplKind::Address:
     return validateAccessorIsMutating(TC, storage->getAddressor());
   }
 
-  llvm_unreachable("bad storage kind");
+  llvm_unreachable("bad impl kind");
 }
 
 static bool computeIsSetterMutating(TypeChecker &TC,
                                     AbstractStorageDecl *storage) {
-  switch (storage->getStorageKind()) {
-  case AbstractStorageDecl::Stored:
-  case AbstractStorageDecl::StoredWithTrivialAccessors:
+  switch (storage->getWriteImpl()) {
+  case WriteImplKind::Immutable:
+  case WriteImplKind::Stored:
     // Instance member setters are mutating; static property setters and
     // top-level setters are not.
+    // It's important that we use this logic for "immutable" storage
+    // in order to handle initialization of let-properties.
     return storage->isInstanceMember() &&
            doesContextHaveValueSemantics(storage->getDeclContext());
 
-  case AbstractStorageDecl::StoredWithObservers:
-  case AbstractStorageDecl::InheritedWithObservers:
-  case AbstractStorageDecl::Computed:
-    if (auto setter = storage->getSetter())
-      return validateAccessorIsMutating(TC, setter);
-    return false;
+  case WriteImplKind::StoredWithObservers:
+  case WriteImplKind::InheritedWithObservers:
+  case WriteImplKind::Set:
+    return validateAccessorIsMutating(TC, storage->getSetter());
 
-  case AbstractStorageDecl::Addressed:
-  case AbstractStorageDecl::AddressedWithTrivialAccessors:
-  case AbstractStorageDecl::AddressedWithObservers:
-  case AbstractStorageDecl::ComputedWithMutableAddress:
-    if (auto addressor = storage->getMutableAddressor())
-      return validateAccessorIsMutating(TC, addressor);
-    return false;
+  case WriteImplKind::MutableAddress:
+    return validateAccessorIsMutating(TC, storage->getMutableAddressor());
   }
   llvm_unreachable("bad storage kind");
 }
@@ -2851,6 +2823,9 @@
   storage->setIsGetterMutating(computeIsGetterMutating(TC, storage));
   storage->setIsSetterMutating(computeIsSetterMutating(TC, storage));
 
+  // Add any mandatory accessors now.
+  maybeAddAccessorsToStorage(TC, storage);
+
   // We can't delay validation of getters and setters on @objc properties,
   // because if they never get validated at all then conformance checkers
   // will complain about selector mismatches.
@@ -2861,31 +2836,16 @@
       TC.validateDecl(setter);
   }
 
-  // Create a materializeForSet function if necessary.  This needs to
-  // happen immediately so that subclass materializeForSet functions
-  // will be properly marked as overriding it.
-  if (storage->hasAccessorFunctions())
-    maybeAddMaterializeForSet(storage, TC);
-  if (storage->isFinal())
-    makeFinal(TC.Context, storage->getMaterializeForSetFunc());
-
   // Everything else about the accessors can wait until finalization.
+  // This will validate all the accessors.
   TC.DeclsToFinalize.insert(storage);
 }
 
 static void finalizeAbstractStorageDecl(TypeChecker &TC,
                                         AbstractStorageDecl *storage) {
-  if (auto getter = storage->getGetter())
-    TC.validateDecl(getter);
-  if (auto setter = storage->getSetter())
-    TC.validateDecl(setter);
-  if (auto materializeForSet = storage->getMaterializeForSetFunc())
-    TC.validateDecl(materializeForSet);
-  if (storage->hasAddressors()) {
-    if (auto addressor = storage->getAddressor())
-      TC.validateDecl(addressor);
-    if (auto addressor = storage->getMutableAddressor())
-      TC.validateDecl(addressor);
+  for (auto accessor : storage->getAllAccessors()) {
+    // Are there accessors we can safely ignore here, like maybe observers?
+    TC.validateDecl(accessor);
   }
 }
 
@@ -3082,7 +3042,7 @@
     // allowed.
     if (VD->hasStorage()) {
       // Stored properties in protocols are diagnosed in
-      // maybeAddAccessorsToVariable(), to ensure they run when a
+      // maybeAddAccessorsToStorage(), to ensure they run when a
       // protocol requirement is validated but not type checked.
 
       // Enums and extensions cannot have stored instance properties.
@@ -3138,37 +3098,9 @@
       }
     }
 
-    // Synthesize accessors for lazy, all checking already been performed.
-    if (VD->getAttrs().hasAttribute<LazyAttr>() && !VD->isStatic() &&
-        !VD->getGetter()->hasBody())
-      TC.completeLazyVarImplementation(VD);
-
-    // If this is a willSet/didSet property, synthesize the getter and setter
-    // decl.
-    if (VD->hasObservers() &&
-        (!VD->getGetter()->getBody() || !VD->getSetter()->getBody()))
-      synthesizeObservingAccessors(VD, TC);
-
-    // If this is a get+mutableAddress property, synthesize the setter body.
-    if (VD->getStorageKind() == VarDecl::ComputedWithMutableAddress &&
-        !VD->getSetter()->getBody()) {
-      synthesizeSetterForMutableAddressedStorage(VD, TC);
-    }
-
-    // Typecheck any accessors that were previously synthesized
-    // (that were previously only validated at point of synthesis)
-    if (auto getter = VD->getGetter()) {
-      if (getter->hasBody()) {
-        TC.typeCheckDecl(getter);
-      }
-    }
-    if (auto setter = VD->getSetter()) {
-      if (setter->hasBody()) {
-        TC.typeCheckDecl(setter);
-      }
-    }
-
     TC.checkDeclAttributes(VD);
+
+    triggerAccessorSynthesis(TC, VD);
   }
 
 
@@ -3251,7 +3183,7 @@
         auto *varDC = var->getDeclContext();
 
         // Non-member observing properties need an initializer.
-        if (var->getStorageKind() == VarDecl::StoredWithObservers &&
+        if (var->getWriteImpl() == WriteImplKind::StoredWithObservers &&
             !isTypeContext && !var->isInvalid() && !PBD->isInvalid()) {
           TC.diagnose(var->getLoc(), diag::observingprop_requires_initializer);
           PBD->setInvalid();
@@ -3310,6 +3242,8 @@
 
     AccessControlChecker::checkAccessControl(TC, SD);
     UsableFromInlineChecker::checkUsableFromInline(TC, SD);
+
+    triggerAccessorSynthesis(TC, SD);
   }
 
   void visitTypeAliasDecl(TypeAliasDecl *TAD) {
@@ -3325,6 +3259,8 @@
   void visitAssociatedTypeDecl(AssociatedTypeDecl *AT) {
     TC.validateDecl(AT);
 
+    TC.checkInheritanceClause(AT);
+
     auto *proto = AT->getProtocol();
     if (proto->isObjC()) {
       TC.diagnose(AT->getLoc(),
@@ -3403,6 +3339,8 @@
 
     TC.checkDeclAttributes(ED);
 
+    TC.checkInheritanceClause(ED);
+
     AccessControlChecker::checkAccessControl(TC, ED);
     UsableFromInlineChecker::checkUsableFromInline(TC, ED);
 
@@ -3434,6 +3372,8 @@
 
     TC.checkDeclAttributes(SD);
 
+    TC.checkInheritanceClause(SD);
+
     AccessControlChecker::checkAccessControl(TC, SD);
     UsableFromInlineChecker::checkUsableFromInline(TC, SD);
 
@@ -3667,6 +3607,8 @@
 
     TC.checkDeclAttributes(CD);
 
+    TC.checkInheritanceClause(CD);
+
     AccessControlChecker::checkAccessControl(TC, CD);
     UsableFromInlineChecker::checkUsableFromInline(TC, CD);
 
@@ -4858,8 +4800,8 @@
     // Returns true if we will already diagnose a bad override
     // on the property's accessor of the given kind.
     auto accessorOverrideAlreadyDiagnosed = [&](AccessorKind kind) {
-      FuncDecl *overrideAccessor = overrideASD->getAccessorFunction(kind);
-      FuncDecl *baseAccessor = baseASD->getAccessorFunction(kind);
+      FuncDecl *overrideAccessor = overrideASD->getAccessor(kind);
+      FuncDecl *baseAccessor = baseASD->getAccessor(kind);
       if (overrideAccessor && baseAccessor &&
           !TC.isAvailabilitySafeForOverride(overrideAccessor, baseAccessor)) {
         return true;
@@ -4920,7 +4862,8 @@
       auto *overrideASD = cast<AbstractStorageDecl>(override);
       
       // Make sure that the overriding property doesn't have storage.
-      if (overrideASD->hasStorage() && !overrideASD->hasObservers()) {
+      if (overrideASD->hasStorage() &&
+          !(overrideASD->getWillSetFunc() || overrideASD->getDidSetFunc())) {
         bool downgradeToWarning = false;
         if (!TC.Context.isSwiftVersionAtLeast(5) &&
             overrideASD->getAttrs().hasAttribute<LazyAttr>()) {
@@ -4947,7 +4890,8 @@
         baseIsSettable =
            baseASD->isSetterAccessibleFrom(overrideASD->getDeclContext());
       }
-      if (overrideASD->hasObservers() && !baseIsSettable) {
+      if (overrideASD->getWriteImpl() == WriteImplKind::InheritedWithObservers
+          && !baseIsSettable) {
         TC.diagnose(overrideASD, diag::observing_readonly_property,
                     overrideASD->getBaseName().getIdentifier());
         TC.diagnose(baseASD, diag::property_override_here);
@@ -5075,13 +5019,13 @@
       overridingASD->setOverriddenDecl(baseASD);
 
       // Make sure we get consistent overrides for the accessors as well.
-      assert(baseASD->hasAccessorFunctions());
+      assert(baseASD->getGetter());
 
       auto recordAccessorOverride = [&](AccessorKind kind) {
         // We need the same accessor on both.
-        auto baseAccessor = baseASD->getAccessorFunction(kind);
+        auto baseAccessor = baseASD->getAccessor(kind);
         if (!baseAccessor) return;
-        auto overridingAccessor = overridingASD->getAccessorFunction(kind);
+        auto overridingAccessor = overridingASD->getAccessor(kind);
         if (!overridingAccessor) return;
 
         // For setter accessors, we need the base's setter to be
@@ -5797,7 +5741,6 @@
     SWIFT_DEFER { assocType->setIsBeingValidated(false); };
 
     checkDeclAttributesEarly(assocType);
-    checkInheritanceClause(assocType);
 
     // Check the default definition, if there is one.
     TypeLoc &defaultDefinition = assocType->getDefaultDefinitionLoc();
@@ -5851,8 +5794,6 @@
     validateGenericTypeSignature(nominal);
     nominal->setIsBeingValidated(false);
 
-    checkInheritanceClause(D);
-
     validateAttributes(*this, D);
 
     if (auto CD = dyn_cast<ClassDecl>(nominal)) {
@@ -5933,6 +5874,7 @@
 
     // Record inherited protocols.
     resolveInheritedProtocols(proto);
+    resolveTrailingWhereClause(proto);
 
     validateAttributes(*this, D);
 
@@ -6098,9 +6040,6 @@
     // Perform accessor-related validation.
     validateAbstractStorageDecl(*this, VD);
 
-    // Synthesize accessors as necessary.
-    maybeAddAccessorsToVariable(VD, *this);
-
     break;
   }
 
@@ -6203,6 +6142,13 @@
       // to the value type.
       case AccessorKind::DidSet:
       case AccessorKind::WillSet:
+        // Make sure that observing accessors are marked final if in a class.
+        if (!accessor->isFinal() &&
+            accessor->getDeclContext()->getAsClassOrClassExtensionContext()) {
+          makeFinal(Context, accessor);
+        }
+        LLVM_FALLTHROUGH;
+
       case AccessorKind::Set: {
         auto newValueParam = valueParams->get(0);
         newValueParam->setType(valueTy);
@@ -6357,12 +6303,13 @@
           if (!isObjC) {
             // Make this accessor @objc because its property is @objc.
             isObjC = ObjCReason::Accessor;
-          } else {
+          } else if (auto storageObjCAttr =
+                       storage->getAttrs().getAttribute<ObjCAttr>()) {
             // If @objc on the storage declaration was inferred using a
             // deprecated rule, but this accessor is @objc in its own right,
             // complain.
-            auto storageObjCAttr = storage->getAttrs().getAttribute<ObjCAttr>();
-            if (storageObjCAttr->isSwift3Inferred() &&
+            ;
+            if (storageObjCAttr && storageObjCAttr->isSwift3Inferred() &&
                 shouldDiagnoseObjCReason(*isObjC, Context)) {
               diagnose(storage, diag::accessor_swift3_objc_inference,
                        storage->getDescriptiveKind(), storage->getFullName(),
@@ -6636,7 +6583,10 @@
 
     // Destructors are always @objc, because their Objective-C entry point is
     // -dealloc.
-    markAsObjC(*this, DD, ObjCReason::ImplicitlyObjC);
+    if (Context.LangOpts.EnableObjCInterop)
+      markAsObjC(*this, DD, ObjCReason::ImplicitlyObjC);
+    else
+      DD->setIsObjC(false);
 
     break;
   }
@@ -6735,12 +6685,6 @@
     // Perform accessor-related validation.
     validateAbstractStorageDecl(*this, SD);
 
-    // If this is a get+mutableAddress property, synthesize the setter body.
-    if (SD->getStorageKind() == SubscriptDecl::ComputedWithMutableAddress &&
-        !SD->getSetter()->getBody()) {
-      synthesizeSetterForMutableAddressedStorage(SD, *this);
-    }
-
     break;
   }
 
@@ -6840,6 +6784,7 @@
 
     // Record inherited protocols.
     resolveInheritedProtocols(proto);
+    resolveTrailingWhereClause(proto);
 
     for (auto ATD : proto->getAssociatedTypeMembers()) {
       validateDeclForNameLookup(ATD);
@@ -7363,12 +7308,6 @@
   assert(!nominal->isGenericContext());
 }
 
-llvm::TinyPtrVector<ProtocolDecl *>
-TypeChecker::getDirectConformsTo(ProtocolDecl *proto) {
-  resolveInheritedProtocols(proto);
-  return proto->getInheritedProtocols();
-}
-
 /// Build a default initializer string for the given pattern.
 ///
 /// This string is suitable for display in diagnostics.
@@ -8049,7 +7988,7 @@
   // default-initializable.
   if (isa<ClassDecl>(decl)) {
     // We need to look for a default constructor.
-    if (auto superTy = getSuperClassOf(decl->getDeclaredInterfaceType())) {
+    if (auto superTy = decl->getDeclaredInterfaceType()->getSuperclass()) {
       // If there are no default ctors for our supertype, we can't do anything.
       auto ctors = lookupConstructors(decl, superTy);
       if (!ctors)
diff --git a/lib/Sema/TypeCheckError.cpp b/lib/Sema/TypeCheckError.cpp
index 6cf8938..deab8f6 100644
--- a/lib/Sema/TypeCheckError.cpp
+++ b/lib/Sema/TypeCheckError.cpp
@@ -134,6 +134,9 @@
         fn = conversion->getSubExpr()->getValueProvidingExpr();
       } else if (auto conversion = dyn_cast<BindOptionalExpr>(fn)) {
         fn = conversion->getSubExpr()->getValueProvidingExpr();
+      // Look through optional injections
+      } else if (auto injection = dyn_cast<InjectIntoOptionalExpr>(fn)) {
+        fn = injection->getSubExpr()->getValueProvidingExpr();
       // Look through function conversions.
       } else if (auto conversion = dyn_cast<FunctionConversionExpr>(fn)) {
         fn = conversion->getSubExpr()->getValueProvidingExpr();
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index d3f9486..7cc8154 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -461,7 +461,6 @@
 void TypeChecker::revertGenericParamList(GenericParamList *genericParams) {
   // Revert the inherited clause of the generic parameter list.
   for (auto param : *genericParams) {
-    param->setCheckedInheritanceClause(false);
     for (auto &inherited : param->getInherited())
       revertDependentTypeLoc(inherited);
   }
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index f3c8185..d3a8308 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -206,38 +206,6 @@
   return std::make_tuple(reqtType, witnessType, optAdjustment);
 }
 
-// Given that we're looking at a stored property, should we use the
-// mutating rules for the setter or the getter when trying to match
-// the given requirement?
-static bool shouldUseSetterRequirements(AccessorKind reqtKind) {
-  // We have cases for addressors here because we might reasonably
-  // allow them as protocol requirements someday.
-
-  switch (reqtKind) {
-  case AccessorKind::Get:
-  case AccessorKind::Address:
-    return false;
-
-  case AccessorKind::Set:
-  case AccessorKind::MutableAddress:
-  case AccessorKind::MaterializeForSet:
-    return true;
-
-  case AccessorKind::WillSet:
-  case AccessorKind::DidSet:
-    llvm_unreachable("willSet/didSet protocol requirement?");
-  }
-  llvm_unreachable("bad accessor kind");
-}
-
-static AccessorDecl *getAddressorForRequirement(AbstractStorageDecl *witness,
-                                                AccessorKind reqtKind) {
-  assert(witness->hasAddressors());
-  if (shouldUseSetterRequirements(reqtKind))
-    return witness->getMutableAddressor();
-  return witness->getAddressor();
-}
-
 // Verify that the mutating bit is correct between a protocol requirement and a
 // witness.  This returns true on invalid.
 static bool checkMutating(FuncDecl *requirement, FuncDecl *witness,
@@ -257,31 +225,70 @@
   else {
     auto reqtAsAccessor = cast<AccessorDecl>(requirement);
     auto storage = cast<AbstractStorageDecl>(witnessDecl);
-    switch (storage->getStorageKind()) {
 
-    // A stored property on a value type will have a mutating setter
-    // and a non-mutating getter.
-    case AbstractStorageDecl::Stored:
-      witnessMutating = reqtAsAccessor->isInstanceMember() &&
-        shouldUseSetterRequirements(reqtAsAccessor->getAccessorKind());
+    auto isReadMutating = [&] {
+      switch (storage->getReadImpl()) {
+      case ReadImplKind::Stored:
+        return false;
+      case ReadImplKind::Address:
+        return storage->getAddressor()->isMutating();
+      case ReadImplKind::Inherited:
+      case ReadImplKind::Get:
+        llvm_unreachable("should have a getter");
+      }
+    };
+
+    auto isStoredSetterMutating = [&] {
+      // A stored property on a value type will have a mutating setter
+      // and a non-mutating getter.
+      return reqtAsAccessor->isInstanceMember();
+    };
+
+    auto isWriteMutating = [&] {
+      switch (storage->getWriteImpl()) {
+      case WriteImplKind::Stored:
+        return isStoredSetterMutating();
+      case WriteImplKind::MutableAddress:
+        return storage->getMutableAddressor()->isMutating();
+      case WriteImplKind::Immutable:
+        llvm_unreachable("asking for setter for immutable storage");
+      case WriteImplKind::Set:
+      case WriteImplKind::StoredWithObservers:
+      case WriteImplKind::InheritedWithObservers:
+        llvm_unreachable("should have a setter");
+      }
+    };
+
+    auto isReadWriteMutating = [&] {
+      switch (storage->getReadWriteImpl()) {
+      case ReadWriteImplKind::Stored:
+        return isStoredSetterMutating();
+      case ReadWriteImplKind::MutableAddress:
+        return storage->getMutableAddressor()->isMutating();
+      case ReadWriteImplKind::MaterializeToTemporary:
+        return isReadMutating() || isWriteMutating();
+      case ReadWriteImplKind::Immutable:
+        llvm_unreachable("asking for setter for immutable storage");
+      case ReadWriteImplKind::MaterializeForSet:
+        llvm_unreachable("should have a materializeForSet");
+      }
+    };
+
+    switch (reqtAsAccessor->getAccessorKind()) {
+    case AccessorKind::Get:
+      witnessMutating = isReadMutating();
       break;
 
-    // For an addressed property, consider the appropriate addressor.
-    case AbstractStorageDecl::Addressed: {
-      AccessorDecl *addressor =
-        getAddressorForRequirement(storage, reqtAsAccessor->getAccessorKind());
-      witnessMutating = addressor->isMutating();
+    case AccessorKind::Set:
+      witnessMutating = isWriteMutating();
       break;
-    }
 
-    case AbstractStorageDecl::StoredWithObservers:
-    case AbstractStorageDecl::StoredWithTrivialAccessors:
-    case AbstractStorageDecl::InheritedWithObservers:
-    case AbstractStorageDecl::AddressedWithTrivialAccessors:
-    case AbstractStorageDecl::AddressedWithObservers:
-    case AbstractStorageDecl::ComputedWithMutableAddress:
-    case AbstractStorageDecl::Computed:
-      llvm_unreachable("missing witness reference for kind with accessors");
+    case AccessorKind::MaterializeForSet:
+      witnessMutating = isReadWriteMutating();
+      break;
+
+    default:
+      llvm_unreachable("unexpected accessor requirement");
     }
   }
 
@@ -343,6 +350,48 @@
   return subscript->getIndices();
 }
 
+// Find a standin declaration to place the diagnostic at for the
+// given accessor kind.
+static ValueDecl *getStandinForAccessor(AbstractStorageDecl *witnessStorage,
+                                        AccessorKind requirementKind) {
+  auto getExplicitAccessor = [&](AccessorKind kind) -> AccessorDecl* {
+    if (auto accessor = witnessStorage->getAccessor(kind)) {
+      if (!accessor->isImplicit())
+        return accessor;
+    }
+    return nullptr;
+  };
+
+  // If the storage actually explicitly provides that accessor, great.
+  if (auto accessor = getExplicitAccessor(requirementKind))
+    return accessor;
+
+  // If it didn't, check to see if it provides something else that corresponds
+  // to the requirement.
+  switch (requirementKind) {
+  case AccessorKind::Get:
+    if (auto addressor = getExplicitAccessor(AccessorKind::Address))
+      return addressor;
+    break;
+
+  case AccessorKind::MaterializeForSet:
+    if (auto setter = getExplicitAccessor(AccessorKind::Set))
+      return setter;
+    LLVM_FALLTHROUGH;
+
+  case AccessorKind::Set:
+    if (auto addressor = getExplicitAccessor(AccessorKind::MutableAddress))
+      return addressor;
+    break;
+
+  default:
+    break;
+  }
+
+  // Otherwise, just diagnose starting at the storage declaration itself.
+  return witnessStorage;
+}
+
 RequirementMatch
 swift::matchWitness(
              TypeChecker &tc,
@@ -420,34 +469,15 @@
         !witness->isSettable(witness->getDeclContext()))
       return RequirementMatch(witness, MatchKind::SettableConflict);
 
-    // Find a standin declaration to place the diagnostic at for the
-    // given accessor kind.
-    auto getStandinForAccessor = [&](AccessorKind kind) -> ValueDecl* {
-      // If the witness actually explicitly provided that accessor,
-      // then great.
-      if (auto accessor = witnessASD->getAccessorFunction(kind))
-        if (!accessor->isImplicit())
-          return accessor;
-
-      // If it didn't, check to see if it provides something else.
-      if (witnessASD->hasAddressors()) {
-        return getAddressorForRequirement(witnessASD, kind);
-      }
-
-      // Otherwise, just diagnose starting at the storage declaration
-      // itself.
-      return witnessASD;
-    };
-    
     // Validate that the 'mutating' bit lines up for getters and setters.
     if (checkMutating(reqASD->getGetter(), witnessASD->getGetter(),
                       witnessASD))
-      return RequirementMatch(getStandinForAccessor(AccessorKind::Get),
+      return RequirementMatch(getStandinForAccessor(witnessASD, AccessorKind::Get),
                               MatchKind::MutatingConflict);
     
     if (req->isSettable(req->getDeclContext()) &&
         checkMutating(reqASD->getSetter(), witnessASD->getSetter(), witnessASD))
-      return RequirementMatch(getStandinForAccessor(AccessorKind::Set),
+      return RequirementMatch(getStandinForAccessor(witnessASD, AccessorKind::Set),
                               MatchKind::MutatingConflict);
 
     // Decompose the parameters for subscript declarations.
@@ -3115,7 +3145,7 @@
   for (auto candidate : candidates) {
     // Skip nested generic types.
     if (auto *genericDecl = dyn_cast<GenericTypeDecl>(candidate.Member))
-      if (genericDecl->getGenericParams())
+      if (genericDecl->isGeneric())
         continue;
 
     // Skip typealiases with an unbound generic type as their underlying type.
@@ -4924,7 +4954,7 @@
             auto *storageReq = dyn_cast<AbstractStorageDecl>(req);
             if (!storageReq)
               continue;
-            req = storageReq->getAccessorFunction(*accessorKind);
+            req = storageReq->getAccessor(*accessorKind);
             if (!req)
               continue;
           }
@@ -4942,10 +4972,10 @@
         auto *storageFound = dyn_cast_or_null<AbstractStorageDecl>(found);
         if (!storageReq || !storageFound)
           continue;
-        req = storageReq->getAccessorFunction(*accessorKind);
+        req = storageReq->getAccessor(*accessorKind);
         if (!req)
           continue;
-        found = storageFound->getAccessorFunction(*accessorKind);
+        found = storageFound->getAccessor(*accessorKind);
       }
 
       // Determine whether the witness for this conformance is in fact
diff --git a/lib/Sema/TypeCheckRequestFunctions.cpp b/lib/Sema/TypeCheckRequestFunctions.cpp
new file mode 100644
index 0000000..699a560
--- /dev/null
+++ b/lib/Sema/TypeCheckRequestFunctions.cpp
@@ -0,0 +1,153 @@
+//===--- TypeCheckRequests.cpp - Type Checking Requests ------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+#include "GenericTypeResolver.h"
+#include "TypeChecker.h"
+#include "swift/AST/TypeCheckRequests.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/ExistentialLayout.h"
+#include "swift/AST/TypeLoc.h"
+#include "swift/AST/Types.h"
+#include "swift/Subsystems.h"
+
+using namespace swift;
+
+Type InheritedTypeRequest::evaluate(
+                        Evaluator &evaluator,
+                        llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
+                        unsigned index) const {
+  // Figure out how to resolve types.
+  TypeResolutionOptions options;
+  DeclContext *dc;
+  if (auto typeDecl = decl.dyn_cast<TypeDecl *>()) {
+    if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) {
+      dc = nominal;
+      options |= TypeResolutionFlags::GenericSignature;
+      options |= TypeResolutionFlags::InheritanceClause;
+      options |= TypeResolutionFlags::AllowUnavailableProtocol;
+    } else {
+      dc = typeDecl->getDeclContext();
+
+      if (isa<GenericTypeParamDecl>(typeDecl)) {
+        // For generic parameters, we want name lookup to look at just the
+        // signature of the enclosing entity.
+        if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
+          dc = nominal;
+          options |= TypeResolutionFlags::GenericSignature;
+        } else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
+          dc = ext;
+          options |= TypeResolutionFlags::GenericSignature;
+        } else if (auto func = dyn_cast<AbstractFunctionDecl>(dc)) {
+          dc = func;
+          options |= TypeResolutionFlags::GenericSignature;
+        } else if (!dc->isModuleScopeContext()) {
+          // Skip the generic parameter's context entirely.
+          dc = dc->getParent();
+        }
+      }
+    }
+  } else {
+    auto ext = decl.get<ExtensionDecl *>();
+    dc = ext;
+    options |= TypeResolutionFlags::GenericSignature;
+    options |= TypeResolutionFlags::InheritanceClause;
+    options |= TypeResolutionFlags::AllowUnavailableProtocol;
+  }
+
+  ProtocolRequirementTypeResolver protoResolver;
+  GenericTypeToArchetypeResolver archetypeResolver(dc);
+  GenericTypeResolver *resolver;
+  if (isa<ProtocolDecl>(dc)) {
+    resolver = &protoResolver;
+  } else {
+    resolver = &archetypeResolver;
+  }
+
+  // FIXME: Hack for calls through here when we have no type checker.
+  auto lazyResolver = dc->getASTContext().getLazyResolver();
+  if (!lazyResolver) return ErrorType::get(dc->getASTContext());
+
+  TypeChecker &tc = *static_cast<TypeChecker *>(lazyResolver);
+  TypeLoc &typeLoc = getTypeLoc(decl, index);
+
+  Type inheritedType =
+    tc.resolveType(typeLoc.getTypeRepr(), dc, options, resolver);
+  if (inheritedType && !isa<ProtocolDecl>(dc))
+    inheritedType = inheritedType->mapTypeOutOfContext();
+  return inheritedType ? inheritedType : ErrorType::get(tc.Context);
+}
+
+Type SuperclassTypeRequest::evaluate(Evaluator &evaluator,
+                                     NominalTypeDecl *nominalDecl) const {
+  assert(isa<ClassDecl>(nominalDecl) || isa<ProtocolDecl>(nominalDecl));
+
+  for (unsigned int idx : indices(nominalDecl->getInherited())) {
+    Type inheritedType = evaluator(InheritedTypeRequest{nominalDecl, idx});
+    if (!inheritedType) continue;
+
+    // If we found a class, return it.
+    if (inheritedType->getClassOrBoundGenericClass()) {
+      if (inheritedType->hasArchetype())
+        return inheritedType->mapTypeOutOfContext();
+
+      return inheritedType;
+    }
+
+    // If we found an existential with a superclass bound, return it.
+    if (inheritedType->isExistentialType()) {
+      if (auto superclassType =
+            inheritedType->getExistentialLayout().superclass) {
+        if (superclassType->getClassOrBoundGenericClass()) {
+          if (superclassType->hasArchetype())
+            return superclassType->mapTypeOutOfContext();
+
+          return superclassType;
+        }
+      }
+    }
+  }
+
+  // No superclass.
+  return Type();
+}
+
+Type EnumRawTypeRequest::evaluate(Evaluator &evaluator,
+                                  EnumDecl *enumDecl) const {
+  for (unsigned int idx : indices(enumDecl->getInherited())) {
+    Type inheritedType = evaluator(InheritedTypeRequest{enumDecl, idx});
+    if (!inheritedType) continue;
+
+    // Skip existential types.
+    if (inheritedType->isExistentialType()) continue;
+
+    // We found a raw type; return it.
+    if (inheritedType->hasArchetype())
+      return inheritedType->mapTypeOutOfContext();
+
+    return inheritedType;
+  }
+
+  // No raw type.
+  return Type();
+}
+
+// Define request evaluation functions for each of the type checker requests.
+static AbstractRequestFunction *typeCheckerRequestFunctions[] = {
+#define SWIFT_TYPEID(Name)                                    \
+  reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
+#include "swift/AST/TypeCheckerTypeIDZone.def"
+#undef SWIFT_TYPEID
+};
+
+void swift::registerTypeCheckerRequestFunctions(Evaluator &evaluator) {
+  evaluator.registerRequestFunctions(SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE,
+                                     typeCheckerRequestFunctions);
+}
diff --git a/lib/Sema/TypeCheckRequests.cpp b/lib/Sema/TypeCheckRequests.cpp
deleted file mode 100644
index 079537c..0000000
--- a/lib/Sema/TypeCheckRequests.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-//===--- TypeCheckRequests.cpp - Type Checking Requests ------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-#include "GenericTypeResolver.h"
-#include "TypeChecker.h"
-#include "swift/Sema/TypeCheckRequests.h"
-#include "swift/AST/Decl.h"
-#include "swift/AST/ExistentialLayout.h"
-#include "swift/AST/TypeLoc.h"
-#include "swift/AST/Types.h"
-using namespace swift;
-
-namespace swift {
-// Implement the type checker type zone (zone 10).
-#define SWIFT_TYPEID_ZONE 10
-#define SWIFT_TYPEID_HEADER "swift/Sema/TypeCheckerTypeIDZone.def"
-#include "swift/Basic/ImplementTypeIDZone.h"
-
-}
-
-void swift::simple_display(
-       llvm::raw_ostream &out,
-       const llvm::PointerUnion<TypeDecl *, ExtensionDecl *> &value) {
-  if (auto type = value.dyn_cast<TypeDecl *>()) {
-    type->dumpRef(out);
-    return;
-  }
-
-  auto ext = value.get<ExtensionDecl *>();
-  out << "extension of ";
-  ext->getAsNominalTypeOrNominalTypeExtensionContext()->dumpRef(out);
-}
-
-//----------------------------------------------------------------------------//
-// Inherited type computation.
-//----------------------------------------------------------------------------//
-
-TypeLoc &InheritedTypeRequest::getTypeLoc(
-                        llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
-                        unsigned index) const {
-  if (auto typeDecl = decl.dyn_cast<TypeDecl *>())
-    return typeDecl->getInherited()[index];
-
-  return decl.get<ExtensionDecl *>()->getInherited()[index];
-}
-
-Type InheritedTypeRequest::operator()(
-                        Evaluator &evaluator,
-                        llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
-                        unsigned index) const {
-  // Figure out how to resolve types.
-  TypeResolutionOptions options;
-  DeclContext *dc;
-  if (auto typeDecl = decl.dyn_cast<TypeDecl *>()) {
-    if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) {
-      dc = nominal;
-      options |= TypeResolutionFlags::GenericSignature;
-      options |= TypeResolutionFlags::InheritanceClause;
-      options |= TypeResolutionFlags::AllowUnavailableProtocol;
-    } else {
-      dc = typeDecl->getDeclContext();
-
-      if (isa<GenericTypeParamDecl>(typeDecl)) {
-        // For generic parameters, we want name lookup to look at just the
-        // signature of the enclosing entity.
-        if (auto nominal = dyn_cast<NominalTypeDecl>(dc)) {
-          dc = nominal;
-          options |= TypeResolutionFlags::GenericSignature;
-        } else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
-          dc = ext;
-          options |= TypeResolutionFlags::GenericSignature;
-        } else if (auto func = dyn_cast<AbstractFunctionDecl>(dc)) {
-          dc = func;
-          options |= TypeResolutionFlags::GenericSignature;
-        } else if (!dc->isModuleScopeContext()) {
-          // Skip the generic parameter's context entirely.
-          dc = dc->getParent();
-        }
-      }
-    }
-  } else {
-    auto ext = decl.get<ExtensionDecl *>();
-    dc = ext;
-    options |= TypeResolutionFlags::GenericSignature;
-    options |= TypeResolutionFlags::InheritanceClause;
-    options |= TypeResolutionFlags::AllowUnavailableProtocol;
-  }
-
-  ProtocolRequirementTypeResolver protoResolver;
-  GenericTypeToArchetypeResolver archetypeResolver(dc);
-  GenericTypeResolver *resolver;
-  if (isa<ProtocolDecl>(dc)) {
-    resolver = &protoResolver;
-  } else {
-    resolver = &archetypeResolver;
-  }
-
-  // FIXME: Hack for calls through here when we have no type checker.
-  auto lazyResolver = dc->getASTContext().getLazyResolver();
-  if (!lazyResolver) return ErrorType::get(dc->getASTContext());
-
-  TypeChecker &tc = *static_cast<TypeChecker *>(lazyResolver);
-  TypeLoc &typeLoc = getTypeLoc(decl, index);
-
-  Type inheritedType =
-    tc.resolveType(typeLoc.getTypeRepr(), dc, options, resolver);
-  if (inheritedType && !isa<ProtocolDecl>(dc))
-    inheritedType = inheritedType->mapTypeOutOfContext();
-  return inheritedType ? inheritedType : ErrorType::get(tc.Context);
-}
-
-void InheritedTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
-  const auto &storage = getStorage();
-  auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
-  diags.diagnose(typeLoc.getLoc(), diag::circular_reference);
-}
-
-void InheritedTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
-  const auto &storage = getStorage();
-  auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
-  diags.diagnose(typeLoc.getLoc(), diag::circular_reference_through);
-}
-
-Optional<Type> InheritedTypeRequest::getCachedResult() const {
-  const auto &storage = getStorage();
-  auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
-  if (typeLoc.wasValidated())
-    return typeLoc.getType();
-
-  return None;
-}
-
-void InheritedTypeRequest::cacheResult(Type value) const {
-  const auto &storage = getStorage();
-  auto &typeLoc = getTypeLoc(std::get<0>(storage), std::get<1>(storage));
-  typeLoc.setType(value);
-}
-
-//----------------------------------------------------------------------------//
-// Superclass computation.
-//----------------------------------------------------------------------------//
-Type SuperclassTypeRequest::operator()(Evaluator &evaluator,
-                                       ClassDecl *classDecl) const {
-  for (unsigned int idx : indices(classDecl->getInherited())) {
-    Type inheritedType = evaluator(InheritedTypeRequest{classDecl, idx});
-    if (!inheritedType) continue;
-
-    // If we found a class, return it.
-    if (inheritedType->getClassOrBoundGenericClass()) {
-      if (inheritedType->hasArchetype())
-        return inheritedType->mapTypeOutOfContext();
-
-      return inheritedType;
-    }
-
-    // If we found an existential with a superclass bound, return it.
-    if (inheritedType->isExistentialType()) {
-      if (auto superclassType =
-            inheritedType->getExistentialLayout().superclass) {
-        if (superclassType->getClassOrBoundGenericClass()) {
-          if (superclassType->hasArchetype())
-            return superclassType->mapTypeOutOfContext();
-
-          return superclassType;
-        }
-      }
-    }
-  }
-
-  // No superclass.
-  return Type();
-}
-
-void SuperclassTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
-  // FIXME: Improve this diagnostic.
-  auto classDecl = std::get<0>(getStorage());
-  std::string className = "'" + std::string(classDecl->getNameStr()) + "'";
-  diags.diagnose(classDecl, diag::circular_class_inheritance, className);
-}
-
-void SuperclassTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
-  auto classDecl = std::get<0>(getStorage());
-  // FIXME: Customize this further.
-  diags.diagnose(classDecl, diag::circular_reference_through);
-}
-
-Optional<Type> SuperclassTypeRequest::getCachedResult() const {
-  auto classDecl = std::get<0>(getStorage());
-  if (classDecl->LazySemanticInfo.Superclass.getInt())
-    return classDecl->LazySemanticInfo.Superclass.getPointer();
-
-  return None;
-}
-
-void SuperclassTypeRequest::cacheResult(Type value) const {
-  auto classDecl = std::get<0>(getStorage());
-  classDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
-}
-
-//----------------------------------------------------------------------------//
-// Enum raw type computation.
-//----------------------------------------------------------------------------//
-Type EnumRawTypeRequest::operator()(Evaluator &evaluator,
-                                    EnumDecl *enumDecl) const {
-  for (unsigned int idx : indices(enumDecl->getInherited())) {
-    Type inheritedType = evaluator(InheritedTypeRequest{enumDecl, idx});
-    if (!inheritedType) continue;
-
-    // Skip existential types.
-    if (inheritedType->isExistentialType()) continue;
-
-    // We found a raw type; return it.
-    if (inheritedType->hasArchetype())
-      return inheritedType->mapTypeOutOfContext();
-
-    return inheritedType;
-  }
-
-  // No raw type.
-  return Type();
-}
-
-void EnumRawTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
-  // FIXME: Improve this diagnostic.
-  auto enumDecl = std::get<0>(getStorage());
-  std::string className = "'" + std::string(enumDecl->getNameStr()) + "'";
-  diags.diagnose(enumDecl, diag::circular_enum_inheritance, className);
-}
-
-void EnumRawTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
-  auto enumDecl = std::get<0>(getStorage());
-  // FIXME: Customize this further.
-  diags.diagnose(enumDecl, diag::circular_reference_through);
-}
-
-Optional<Type> EnumRawTypeRequest::getCachedResult() const {
-  auto enumDecl = std::get<0>(getStorage());
-  if (enumDecl->LazySemanticInfo.RawType.getInt())
-    return enumDecl->LazySemanticInfo.RawType.getPointer();
-
-  return None;
-}
-
-void EnumRawTypeRequest::cacheResult(Type value) const {
-  auto enumDecl = std::get<0>(getStorage());
-  enumDecl->LazySemanticInfo.RawType.setPointerAndInt(value, true);
-}
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 4045d5a..cbfa4eb 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -954,7 +954,7 @@
         auto decl = parentType->getAnyNominal();
         if (decl) {
           tc.diagnose(decl->getLoc(), diag::circular_class_inheritance,
-                      decl->getNameStr());
+                      decl->getName());
           return ErrorType::get(tc.Context);
         }
       }
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index 0bd9268..3ad3629 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -17,6 +17,7 @@
 
 #include "swift/Subsystems.h"
 #include "TypeChecker.h"
+#include "CodeSynthesis.h"
 #include "MiscDiagnostics.h"
 #include "GenericTypeResolver.h"
 #include "swift/AST/ASTWalker.h"
@@ -484,6 +485,17 @@
       TC.validateDecl(decl);
     }
 
+    // Synthesize any necessary function bodies.
+    // FIXME: If we're not planning to run SILGen, this is wasted effort.
+    while (!TC.FunctionsToSynthesize.empty()) {
+      auto function = TC.FunctionsToSynthesize.back().second;
+      TC.FunctionsToSynthesize.pop_back();
+      if (function.getDecl()->isInvalid() || TC.Context.hadError())
+        continue;
+
+      TC.synthesizeFunctionBody(function);
+    }
+
     // Validate any referenced declarations for SIL's purposes.
     // Note: if we ever start putting extension members in vtables, we'll need
     // to validate those members too.
@@ -523,6 +535,7 @@
   } while (currentFunctionIdx < TC.definedFunctions.size() ||
            currentExternalDef < TC.Context.ExternalDefinitions.size() ||
            currentSynthesizedDecl < SF.SynthesizedDecls.size() ||
+           !TC.FunctionsToSynthesize.empty() ||
            !TC.DeclsToFinalize.empty() ||
            !TC.ConformanceContexts.empty() ||
            !TC.DelayedRequirementSignatures.empty() ||
@@ -789,7 +802,7 @@
   return TypeChecker(Ctx).handleSILGenericParams(genericParams, DC);
 }
 
-bool swift::typeCheckCompletionDecl(Decl *D) {
+void swift::typeCheckCompletionDecl(Decl *D) {
   auto &Ctx = D->getASTContext();
 
   // Set up a diagnostics engine that swallows diagnostics.
@@ -799,8 +812,7 @@
   if (auto ext = dyn_cast<ExtensionDecl>(D))
     TC.validateExtension(ext);
   else
-    TC.typeCheckDecl(D);
-  return true;
+    TC.validateDecl(cast<ValueDecl>(D));
 }
 
 static Optional<Type> getTypeOfCompletionContextExpr(
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 2da25c8..c30e3a9 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -43,6 +43,7 @@
 class TypeChecker;
 class TypoCorrectionResults;
 class ExprPattern;
+class SynthesizedFunction;
 
 namespace constraints {
   enum class ConstraintKind : char;
@@ -744,6 +745,9 @@
   /// we can hand them off to SILGen etc.
   llvm::SetVector<ValueDecl *> DeclsToFinalize;
 
+  /// The list of functions that need to have their bodies synthesized.
+  llvm::MapVector<FuncDecl*, SynthesizedFunction> FunctionsToSynthesize;
+
   /// The list of protocols that need their requirement signatures computed,
   /// because they were first validated by validateDeclForNameLookup(),
   /// which skips this step.
@@ -1371,7 +1375,6 @@
 
   virtual void resolveExtension(ExtensionDecl *ext) override {
     validateExtension(ext);
-    checkInheritanceClause(ext);
   }
   virtual void resolveExtensionForConformanceConstruction(
       ExtensionDecl *ext,
@@ -1544,12 +1547,6 @@
       GenericRequirementsCheckListener *listener = nullptr,
       SubstOptions options = None);
 
-  /// Get the superclass of the given class.
-  Type getSuperclass(const ClassDecl *classDecl) override;
-
-  /// Get the raw type of the given enum.
-  Type getRawType(EnumDecl *enumDecl) override;
-
   /// Resolve the inherited protocols of a given protocol.
   void resolveInheritedProtocols(ProtocolDecl *protocol);
 
@@ -1558,19 +1555,12 @@
   void validateWhereClauses(ProtocolDecl *protocol,
                             GenericTypeResolver *resolver);
 
-  /// Get a specific inherited type from the given declaration.
-  Type getInheritedType(llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl,
-                        unsigned index) override;
-
   void resolveTrailingWhereClause(ProtocolDecl *proto) override;
 
   /// Check the inheritance clause of the given declaration.
   void checkInheritanceClause(Decl *decl,
                               GenericTypeResolver *resolver = nullptr);
 
-  /// Retrieve the set of inherited protocols for this protocol type.
-  llvm::TinyPtrVector<ProtocolDecl *> getDirectConformsTo(ProtocolDecl *proto);
-
   /// Diagnose if the class has no designated initializers.
   void maybeDiagnoseClassWithoutInitializers(ClassDecl *classDecl);
 
@@ -1590,6 +1580,8 @@
   void synthesizeWitnessAccessorsForStorage(AbstractStorageDecl *requirement,
                                             AbstractStorageDecl *storage);
 
+  void synthesizeFunctionBody(SynthesizedFunction fn);
+
   /// Provide storage and accessor implementations for the given property,
   /// which must be lazy.
   void completeLazyVarImplementation(VarDecl *lazyVar);
@@ -2079,6 +2071,11 @@
   void checkConformancesInContext(DeclContext *dc,
                                   IterableDeclContext *idc);
 
+  /// Check that the type of the given property conforms to NSCopying.
+  ///
+  /// Return true if there was an error.
+  bool checkConformanceToNSCopying(VarDecl *var);
+
   /// Find the @objc requirement that are witnessed by the given
   /// declaration.
   ///
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index cd0f9ee..3e018e6 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2119,31 +2119,67 @@
   return None;
 }
 
-static Optional<AbstractStorageDecl::StorageKindTy>
-getActualStorageKind(unsigned raw) {
-  switch (serialization::StorageKind(raw)) {
-#define CASE(KIND)                       \
-  case serialization::StorageKind::KIND: \
-    return AbstractStorageDecl::KIND;
+static Optional<swift::ReadImplKind>
+getActualReadImplKind(unsigned rawKind) {
+  switch (serialization::ReadImplKind(rawKind)) {
+#define CASE(KIND)                        \
+  case serialization::ReadImplKind::KIND: \
+    return swift::ReadImplKind::KIND;
   CASE(Stored)
-  CASE(StoredWithTrivialAccessors)
+  CASE(Get)
+  CASE(Inherited)
+  CASE(Address)
+#undef CASE
+  }
+  return None;
+}
+
+static Optional<swift::WriteImplKind>
+getActualWriteImplKind(unsigned rawKind) {
+  switch (serialization::WriteImplKind(rawKind)) {
+#define CASE(KIND)                         \
+  case serialization::WriteImplKind::KIND: \
+    return swift::WriteImplKind::KIND;
+  CASE(Immutable)
+  CASE(Stored)
+  CASE(Set)
   CASE(StoredWithObservers)
   CASE(InheritedWithObservers)
-  CASE(Computed)
-  CASE(ComputedWithMutableAddress)
-  CASE(Addressed)
-  CASE(AddressedWithTrivialAccessors)
-  CASE(AddressedWithObservers)
+  CASE(MutableAddress)
+#undef CASE
+  }
+  return None;
+}
+
+static Optional<swift::ReadWriteImplKind>
+getActualReadWriteImplKind(unsigned rawKind) {
+  switch (serialization::ReadWriteImplKind(rawKind)) {
+#define CASE(KIND)                             \
+  case serialization::ReadWriteImplKind::KIND: \
+    return swift::ReadWriteImplKind::KIND;
+  CASE(Immutable)
+  CASE(Stored)
+  CASE(MaterializeForSet)
+  CASE(MutableAddress)
+  CASE(MaterializeToTemporary)
 #undef CASE
   }
   return None;
 }
 
 void ModuleFile::configureStorage(AbstractStorageDecl *decl,
-                                  unsigned rawStorageKind,
+                                  uint8_t rawReadImplKind,
+                                  uint8_t rawWriteImplKind,
+                                  uint8_t rawReadWriteImplKind,
                                   AccessorRecord &rawIDs) {
-  auto storageKind = getActualStorageKind(rawStorageKind);
-  if (!storageKind) return;
+  auto readImpl = getActualReadImplKind(rawReadImplKind);
+  if (!readImpl) return;
+
+  auto writeImpl = getActualWriteImplKind(rawWriteImplKind);
+  if (!writeImpl) return;
+
+  auto readWriteImpl = getActualReadWriteImplKind(rawReadWriteImplKind);
+  if (!readWriteImpl) return;
 
   SmallVector<AccessorDecl*, 8> accessors;
   for (DeclID id : rawIDs.IDs) {
@@ -2152,13 +2188,14 @@
     accessors.push_back(accessor);
   }
 
-  if (*storageKind == AbstractStorageDecl::Stored && accessors.empty())
+  auto implInfo = StorageImplInfo(*readImpl, *writeImpl, *readWriteImpl);
+  if (implInfo.isSimpleStored() && accessors.empty())
     return;
 
   // We currently don't serialize these locations.
   SourceLoc beginLoc, endLoc;
 
-  decl->setAccessors(*storageKind, beginLoc, accessors, endLoc);
+  decl->setAccessors(implInfo, beginLoc, accessors, endLoc);
 }
 
 template <typename T, typename ...Args>
@@ -2301,7 +2338,6 @@
          tl = TypeLoc::withoutLoc(getType(rawID));
       });
       nominal->setInherited(inheritedTypes);
-      nominal->setCheckedInheritanceClause();
   };
 
   while (true) {
@@ -2590,7 +2626,6 @@
     if (isImplicit)
       alias->setImplicit();
 
-    alias->setCheckedInheritanceClause();
     break;
   }
 
@@ -2662,8 +2697,6 @@
     if (isImplicit)
       assocType->setImplicit();
 
-    assocType->setCheckedInheritanceClause();
-
     // Overridden associated types.
     SmallVector<AssociatedTypeDecl *, 2> overriddenAssocTypes;
     for (auto overriddenID : rawOverriddenIDs) {
@@ -2681,13 +2714,14 @@
     IdentifierID nameID;
     DeclContextID contextID;
     bool isImplicit;
+    bool isObjC;
     GenericEnvironmentID genericEnvID;
     uint8_t rawAccessLevel;
     unsigned numConformances;
     ArrayRef<uint64_t> rawInheritedIDs;
 
     decls_block::StructLayout::readRecord(scratch, nameID, contextID,
-                                          isImplicit, genericEnvID,
+                                          isImplicit, isObjC, genericEnvID,
                                           rawAccessLevel,
                                           numConformances,
                                           rawInheritedIDs);
@@ -2717,6 +2751,7 @@
 
     if (isImplicit)
       theStruct->setImplicit();
+    theStruct->setIsObjC(isObjC);
 
     theStruct->computeType();
 
@@ -2856,6 +2891,7 @@
 
     if (isImplicit)
       ctor->setImplicit();
+    ctor->setIsObjC(isObjC);
     if (hasStubImplementation)
       ctor->setStubImplementation(true);
     if (initKind.hasValue())
@@ -2882,7 +2918,8 @@
     bool isImplicit, isObjC, isStatic, hasNonPatternBindingInit;
     bool isGetterMutating, isSetterMutating;
     unsigned rawSpecifier, numAccessors;
-    uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel;
+    uint8_t readImpl, writeImpl, readWriteImpl;
+    uint8_t rawAccessLevel, rawSetterAccessLevel;
     TypeID interfaceTypeID;
     AccessorRecord accessors;
     DeclID overriddenID;
@@ -2892,7 +2929,8 @@
                                        isImplicit, isObjC, isStatic, rawSpecifier,
                                        hasNonPatternBindingInit,
                                        isGetterMutating, isSetterMutating,
-                                       storageKind, numAccessors,
+                                       readImpl, writeImpl, readWriteImpl,
+                                       numAccessors,
                                        interfaceTypeID,
                                        overriddenID,
                                        rawAccessLevel, rawSetterAccessLevel,
@@ -2920,20 +2958,9 @@
         DeclDeserializationError::Flags flags;
         
         if (!isStatic) {
-          switch ((StorageKind)storageKind) {
-          case StorageKind::Stored:
-          case StorageKind::StoredWithObservers:
-          case StorageKind::StoredWithTrivialAccessors:
+          auto actualReadImpl = getActualReadImplKind(readImpl);
+          if (actualReadImpl && *actualReadImpl == ReadImplKind::Stored) {
             flags |= DeclDeserializationError::Flag::NeedsFieldOffsetVectorEntry;
-            break;
-            
-          case StorageKind::Addressed:
-          case StorageKind::AddressedWithObservers:
-          case StorageKind::AddressedWithTrivialAccessors:
-          case StorageKind::Computed:
-          case StorageKind::ComputedWithMutableAddress:
-          case StorageKind::InheritedWithObservers:
-            break;
           }
         }
         
@@ -2968,7 +2995,7 @@
       AddAttribute(
           new (ctx) ReferenceOwnershipAttr(referenceStorage->getOwnership()));
 
-    configureStorage(var, storageKind, accessors);
+    configureStorage(var, readImpl, writeImpl, readWriteImpl, accessors);
 
     if (auto accessLevel = getActualAccessLevel(rawAccessLevel)) {
       var->setAccess(*accessLevel);
@@ -2988,6 +3015,7 @@
 
     if (isImplicit)
       var->setImplicit();
+    var->setIsObjC(isObjC);
 
     if (auto overriddenVar = cast_or_null<VarDecl>(overridden.get())) {
       var->setOverriddenDecl(overriddenVar);
@@ -3123,7 +3151,7 @@
       // into this code.  When we come out, don't create the accessor twice.
       // TODO: find some better way of breaking this cycle, like lazily
       // deserializing the accessors.
-      if (auto accessor = storage->getAccessorFunction(accessorKind))
+      if (auto accessor = storage->getAccessor(accessorKind))
         return accessor;
     }
 
@@ -3258,6 +3286,7 @@
     fn->setStatic(isStatic);
     if (isImplicit)
       fn->setImplicit();
+    fn->setIsObjC(isObjC);
     fn->setDynamicSelf(hasDynamicSelf);
     fn->setForcedStaticDispatch(hasForcedStaticDispatch);
     fn->setNeedsNewVTableEntry(needsNewVTableEntry);
@@ -3336,14 +3365,15 @@
     DeclContextID contextID;
     bool isImplicit, isClassBounded, isObjC, existentialTypeSupported;
     GenericEnvironmentID genericEnvID;
+    TypeID superclassID;
     uint8_t rawAccessLevel;
     ArrayRef<uint64_t> rawInheritedIDs;
 
     decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
                                             isImplicit, isClassBounded, isObjC,
                                             existentialTypeSupported,
-                                            genericEnvID, rawAccessLevel,
-                                            rawInheritedIDs);
+                                            genericEnvID, superclassID,
+                                            rawAccessLevel, rawInheritedIDs);
 
     auto DC = getDeclContext(contextID);
     if (declOrOffset.isComplete())
@@ -3354,6 +3384,7 @@
                                           /*TrailingWhere=*/nullptr);
     declOrOffset = proto;
 
+    proto->setSuperclass(getType(superclassID));
     proto->setRequiresClass(isClassBounded);
     proto->setExistentialTypeSupported(existentialTypeSupported);
 
@@ -3374,6 +3405,8 @@
 
     if (isImplicit)
       proto->setImplicit();
+    proto->setIsObjC(isObjC);
+
     proto->computeType();
 
     proto->setCircularityCheck(CircularityCheck::Checked);
@@ -3555,6 +3588,7 @@
     theClass->setAddedImplicitInitializers();
     if (isImplicit)
       theClass->setImplicit();
+    theClass->setIsObjC(isObjC);
     theClass->setSuperclass(getType(superclassID));
     if (requiresStoredPropertyInits)
       theClass->setRequiresStoredPropertyInits(true);
@@ -3581,6 +3615,7 @@
     IdentifierID nameID;
     DeclContextID contextID;
     bool isImplicit;
+    bool isObjC;
     GenericEnvironmentID genericEnvID;
     TypeID rawTypeID;
     uint8_t rawAccessLevel;
@@ -3588,8 +3623,8 @@
     ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
 
     decls_block::EnumLayout::readRecord(scratch, nameID, contextID,
-                                        isImplicit, genericEnvID, rawTypeID,
-                                        rawAccessLevel,
+                                        isImplicit, isObjC, genericEnvID,
+                                        rawTypeID, rawAccessLevel,
                                         numConformances, numInheritedTypes,
                                         rawInheritedAndDependencyIDs);
 
@@ -3627,6 +3662,8 @@
 
     if (isImplicit)
       theEnum->setImplicit();
+    theEnum->setIsObjC(isObjC);
+
     theEnum->setRawType(getType(rawTypeID));
 
     theEnum->computeType();
@@ -3737,14 +3774,15 @@
     AccessorRecord accessors;
     DeclID overriddenID;
     uint8_t rawAccessLevel, rawSetterAccessLevel;
-    uint8_t rawStorageKind;
+    uint8_t readImpl, writeImpl, readWriteImpl;
     unsigned numArgNames, numAccessors;
     ArrayRef<uint64_t> argNameAndDependencyIDs;
 
     decls_block::SubscriptLayout::readRecord(scratch, contextID,
                                              isImplicit, isObjC,
                                              isGetterMutating, isSetterMutating,
-                                             rawStorageKind, numAccessors,
+                                             readImpl, writeImpl, readWriteImpl,
+                                             numAccessors,
                                              genericEnvID,
                                              interfaceTypeID,
                                              overriddenID, rawAccessLevel,
@@ -3796,7 +3834,7 @@
 
     subscript->setIndices(readParameterList());
 
-    configureStorage(subscript, rawStorageKind, accessors);
+    configureStorage(subscript, readImpl, writeImpl, readWriteImpl, accessors);
 
     if (auto accessLevel = getActualAccessLevel(rawAccessLevel)) {
       subscript->setAccess(*accessLevel);
@@ -3819,6 +3857,7 @@
 
     if (isImplicit)
       subscript->setImplicit();
+    subscript->setIsObjC(isObjC);
     if (auto overriddenSub = cast_or_null<SubscriptDecl>(overridden.get())) {
       subscript->setOverriddenDecl(overriddenSub);
       AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
@@ -3880,7 +3919,6 @@
       tl = TypeLoc::withoutLoc(getType(rawID));
     });
     extension->setInherited(inheritedTypes);
-    extension->setCheckedInheritanceClause();
 
     extension->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo());
     skipRecord(DeclTypeCursor, decls_block::MEMBERS);
@@ -3940,6 +3978,7 @@
 
     if (isImplicit)
       dtor->setImplicit();
+    dtor->setIsObjC(isObjC);
 
     break;
   }
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 5d608cb..5f788f4 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -481,32 +481,63 @@
 
 namespace {
   struct Accessors {
-    StorageKind Kind;
+    uint8_t ReadImpl, WriteImpl, ReadWriteImpl;
     SmallVector<AccessorDecl *, 8> Decls;
   };
 } // end anonymous namespace
 
-static StorageKind getRawStorageKind(AbstractStorageDecl::StorageKindTy kind) {
+static uint8_t getRawReadImplKind(swift::ReadImplKind kind) {
   switch (kind) {
-#define CASE(KIND) case AbstractStorageDecl::KIND: return StorageKind::KIND
-  CASE(Stored);
-  CASE(StoredWithTrivialAccessors);
-  CASE(StoredWithObservers);
-  CASE(InheritedWithObservers);
-  CASE(Computed);
-  CASE(ComputedWithMutableAddress);
-  CASE(Addressed);
-  CASE(AddressedWithTrivialAccessors);
-  CASE(AddressedWithObservers);
+#define CASE(KIND)                                     \
+  case swift::ReadImplKind::KIND:                      \
+    return uint8_t(serialization::ReadImplKind::KIND);
+  CASE(Stored)
+  CASE(Get)
+  CASE(Inherited)
+  CASE(Address)
 #undef CASE
   }
-  llvm_unreachable("bad storage kind");
+  llvm_unreachable("bad kind");
+}
+
+static unsigned getRawWriteImplKind(swift::WriteImplKind kind) {
+  switch (kind) {
+#define CASE(KIND)                                      \
+  case swift::WriteImplKind::KIND:                      \
+    return uint8_t(serialization::WriteImplKind::KIND);
+  CASE(Immutable)
+  CASE(Stored)
+  CASE(Set)
+  CASE(StoredWithObservers)
+  CASE(InheritedWithObservers)
+  CASE(MutableAddress)
+#undef CASE
+  }
+  llvm_unreachable("bad kind");
+}
+
+static unsigned getRawReadWriteImplKind(swift::ReadWriteImplKind kind) {
+  switch (kind) {
+#define CASE(KIND)                                          \
+  case swift::ReadWriteImplKind::KIND:                      \
+    return uint8_t(serialization::ReadWriteImplKind::KIND);
+  CASE(Immutable)
+  CASE(Stored)
+  CASE(MaterializeForSet)
+  CASE(MutableAddress)
+  CASE(MaterializeToTemporary)
+#undef CASE
+  }
+  llvm_unreachable("bad kind");
 }
 
 static Accessors getAccessors(const AbstractStorageDecl *storage) {
   Accessors accessors;
-  accessors.Kind = getRawStorageKind(storage->getStorageKind());
-  auto decls = storage->getAllAccessorFunctions();
+  auto impl = storage->getImplInfo();
+  accessors.ReadImpl = getRawReadImplKind(impl.getReadImpl());
+  accessors.WriteImpl = getRawWriteImplKind(impl.getWriteImpl());
+  accessors.ReadWriteImpl = getRawReadWriteImplKind(impl.getReadWriteImpl());
+  auto decls = storage->getAllAccessors();
   accessors.Decls.append(decls.begin(), decls.end());
   return accessors;
 }
@@ -2952,6 +2983,7 @@
                              addDeclBaseNameRef(theStruct->getName()),
                              contextID,
                              theStruct->isImplicit(),
+                             theStruct->isObjC(),
                              addGenericEnvironmentRef(
                                             theStruct->getGenericEnvironment()),
                              rawAccessLevel,
@@ -3002,6 +3034,7 @@
                             addDeclBaseNameRef(theEnum->getName()),
                             contextID,
                             theEnum->isImplicit(),
+                            theEnum->isObjC(),
                             addGenericEnvironmentRef(
                                              theEnum->getGenericEnvironment()),
                             addTypeRef(theEnum->getRawType()),
@@ -3084,6 +3117,7 @@
                                  /*resolver=*/nullptr),
                                addGenericEnvironmentRef(
                                                 proto->getGenericEnvironment()),
+                               addTypeRef(proto->getSuperclass()),
                                rawAccessLevel,
                                inherited);
 
@@ -3126,7 +3160,9 @@
                           var->hasNonPatternBindingInit(),
                           var->isGetterMutating(),
                           var->isSetterMutating(),
-                          (unsigned) accessors.Kind,
+                          accessors.ReadImpl,
+                          accessors.WriteImpl,
+                          accessors.ReadWriteImpl,
                           accessors.Decls.size(),
                           addTypeRef(ty),
                           addDeclRef(var->getOverriddenDecl()),
@@ -3351,7 +3387,9 @@
                                 subscript->isObjC(),
                                 subscript->isGetterMutating(),
                                 subscript->isSetterMutating(),
-                                (unsigned) accessors.Kind,
+                                accessors.ReadImpl,
+                                accessors.WriteImpl,
+                                accessors.ReadWriteImpl,
                                 accessors.Decls.size(),
                                 addGenericEnvironmentRef(
                                             subscript->getGenericEnvironment()),
diff --git a/lib/Syntax/RawSyntax.cpp b/lib/Syntax/RawSyntax.cpp
index 9955594..f8dddb9 100644
--- a/lib/Syntax/RawSyntax.cpp
+++ b/lib/Syntax/RawSyntax.cpp
@@ -71,16 +71,16 @@
                      SourcePresence Presence, bool ManualMemory) {
   assert(Kind != SyntaxKind::Token &&
          "'token' syntax node must be constructed with dedicated constructor");
-  Bits.Kind = unsigned(Kind);
-  Bits.Presence = unsigned(Presence);
-  Bits.ManualMemory = unsigned(ManualMemory);
-  Bits.NumChildren = Layout.size();
+  Bits.Common.Kind = unsigned(Kind);
+  Bits.Common.Presence = unsigned(Presence);
+  Bits.Common.ManualMemory = unsigned(ManualMemory);
+  Bits.Layout.NumChildren = Layout.size();
 
   // Compute the text length
-  Bits.TextLength = 0;
+  Bits.Layout.TextLength = 0;
   for (const auto ChildNode : Layout) {
     if (ChildNode && !ChildNode->isMissing()) {
-      Bits.TextLength += ChildNode->getTextLength();
+      Bits.Layout.TextLength += ChildNode->getTextLength();
     }
   }
 
@@ -93,12 +93,12 @@
                      ArrayRef<TriviaPiece> LeadingTrivia,
                      ArrayRef<TriviaPiece> TrailingTrivia,
                      SourcePresence Presence, bool ManualMemory) {
-  Bits.Kind = unsigned(SyntaxKind::Token);
-  Bits.Presence = unsigned(Presence);
-  Bits.ManualMemory = unsigned(ManualMemory);
-  Bits.TokenKind = unsigned(TokKind);
-  Bits.NumLeadingTrivia = LeadingTrivia.size();
-  Bits.NumTrailingTrivia = TrailingTrivia.size();
+  Bits.Common.Kind = unsigned(SyntaxKind::Token);
+  Bits.Common.Presence = unsigned(Presence);
+  Bits.Common.ManualMemory = unsigned(ManualMemory);
+  Bits.Token.TokenKind = unsigned(TokKind);
+  Bits.Token.NumLeadingTrivia = LeadingTrivia.size();
+  Bits.Token.NumTrailingTrivia = TrailingTrivia.size();
 
   // Initialize token text.
   ::new (static_cast<void *>(getTrailingObjects<OwnedString>()))
@@ -109,7 +109,7 @@
   // Initialize trailing trivia.
   std::uninitialized_copy(TrailingTrivia.begin(), TrailingTrivia.end(),
                           getTrailingObjects<TriviaPiece>() +
-                              Bits.NumLeadingTrivia);
+                              Bits.Token.NumLeadingTrivia);
 }
 
 RawSyntax::~RawSyntax() {
diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp
index 917ca68..3177c37 100644
--- a/lib/TBDGen/TBDGen.cpp
+++ b/lib/TBDGen/TBDGen.cpp
@@ -46,7 +46,7 @@
     auto *var = entry.getAnchoringVarDecl();
 
     // Non-global variables might have an explicit initializer symbol.
-    if (entry.getInit() && !isGlobalOrStaticVar(var)) {
+    if (entry.getNonLazyInit() && !isGlobalOrStaticVar(var)) {
       auto declRef =
           SILDeclRef(var, SILDeclRef::Kind::StoredPropertyInitializer);
       // Stored property initializers for public properties are currently
@@ -164,7 +164,7 @@
 
 void TBDGenVisitor::visitAbstractStorageDecl(AbstractStorageDecl *ASD) {
   // Explicitly look at each accessor here: see visitAccessorDecl.
-  for (auto accessor : ASD->getAllAccessorFunctions()) {
+  for (auto accessor : ASD->getAllAccessors()) {
     visitAbstractFunctionDecl(accessor);
   }
 }
diff --git a/stdlib/private/StdlibUnittest/MinimalTypes.swift b/stdlib/private/StdlibUnittest/MinimalTypes.swift
index ad03648..e538e19 100644
--- a/stdlib/private/StdlibUnittest/MinimalTypes.swift
+++ b/stdlib/private/StdlibUnittest/MinimalTypes.swift
@@ -220,7 +220,7 @@
     fatalError("GenericMinimalHashableValue_equalImpl is not set yet")
   })
 public var GenericMinimalHashableValue_hashIntoImpl =
-  ResettableValue<(Any, inout Hasher) -> Void>({ _ in
+  ResettableValue<(Any, inout Hasher) -> Void>({ (_,_) in
     fatalError("GenericMinimalHashableValue_hashIntoImpl is not set yet")
   })
 
@@ -276,7 +276,7 @@
     fatalError("GenericMinimalHashableClass_equalImpl is not set yet")
   })
 public var GenericMinimalHashableClass_hashIntoImpl =
-  ResettableValue<(Any, inout Hasher) -> Void>({ _ in
+  ResettableValue<(Any, inout Hasher) -> Void>({ (_,_) in
     fatalError("GenericMinimalHashableClass_hashIntoImpl is not set yet")
   })
 
diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift b/stdlib/private/StdlibUnittest/StdlibUnittest.swift
index 99798f3..f27cebf 100644
--- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift
+++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift
@@ -1775,15 +1775,15 @@
 }
 
 func _getOSVersion() -> OSVersion {
-#if os(iOS) && (arch(i386) || arch(x86_64))
+#if os(iOS) && targetEnvironment(simulator)
   // On simulator, the plist file that we try to read turns out to be host's
   // plist file, which indicates OS X.
   //
   // FIXME: how to get the simulator version *without* UIKit?
   return .iOSSimulator
-#elseif os(tvOS) && (arch(i386) || arch(x86_64))
+#elseif os(tvOS) && targetEnvironment(simulator)
   return .tvOSSimulator
-#elseif os(watchOS) && (arch(i386) || arch(x86_64))
+#elseif os(watchOS) && targetEnvironment(simulator)
   return .watchOSSimulator
 #elseif os(Linux)
   return .linux
@@ -2410,6 +2410,33 @@
   return hasher.finalize()
 }
 
+/// Test that the elements of `groups` consist of instances that satisfy the
+/// semantic requirements of `Hashable`, with each group defining a distinct
+/// equivalence class under `==`.
+public func checkHashableGroups<Groups: Collection>(
+  _ groups: Groups,
+  _ message: @autoclosure () -> String = "",
+  stackTrace: SourceLocStack = SourceLocStack(),
+  showFrame: Bool = true,
+  file: String = #file, line: UInt = #line
+) where Groups.Element: Collection, Groups.Element.Element: Hashable {
+  let instances = groups.flatMap { $0 }
+  // groupIndices[i] is the index of the element in groups that contains
+  // instances[i].
+  let groupIndices =
+    zip(0..., groups).flatMap { i, group in group.map { _ in i } }
+  func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
+    return groupIndices[lhs] == groupIndices[rhs]
+  }
+  checkHashable(
+    instances,
+    equalityOracle: equalityOracle,
+    hashEqualityOracle: equalityOracle,
+    allowBrokenTransitivity: false,
+    stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
+    showFrame: false)
+}
+
 /// Test that the elements of `instances` satisfy the semantic requirements of
 /// `Hashable`, using `equalityOracle` to generate equality and hashing
 /// expectations from pairs of positions in `instances`.
diff --git a/stdlib/public/SDK/AppKit/AppKit.swift b/stdlib/public/SDK/AppKit/AppKit.swift
index ffb9f7d..a716201 100644
--- a/stdlib/public/SDK/AppKit/AppKit.swift
+++ b/stdlib/public/SDK/AppKit/AppKit.swift
@@ -13,7 +13,7 @@
 import Foundation
 @_exported import AppKit
 
-extension NSCursor : _DefaultCustomPlaygroundQuickLookable {
+extension NSCursor : __DefaultCustomPlaygroundQuickLookable {
   @available(*, deprecated, message: "NSCursor._defaultCustomPlaygroundQuickLook will be removed in a future Swift version")
   public var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
     return .image(image)
@@ -24,7 +24,7 @@
   static var views = Set<NSView>()
 }
 
-extension NSView : _DefaultCustomPlaygroundQuickLookable {
+extension NSView : __DefaultCustomPlaygroundQuickLookable {
   @available(*, deprecated, message: "NSView._defaultCustomPlaygroundQuickLook will be removed in a future Swift version")
   public var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
     // if you set NSView.needsDisplay, you can get yourself in a recursive scenario where the same view
diff --git a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
index 1ce4f6b..69623cd 100644
--- a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
+++ b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
@@ -228,11 +228,13 @@
   }
 }
 
-extension CGPoint : CustomReflectable, CustomPlaygroundQuickLookable {
+extension CGPoint : CustomReflectable {
   public var customMirror: Mirror {
     return Mirror(self, children: ["x": x, "y": y], displayStyle: .`struct`)
   }
+}
 
+extension CGPoint : _CustomPlaygroundQuickLookable {
   @available(*, deprecated, message: "CGPoint.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .point(Double(x), Double(y))
@@ -293,14 +295,16 @@
   }
 }
 
-extension CGSize : CustomReflectable, CustomPlaygroundQuickLookable {
+extension CGSize : CustomReflectable {
   public var customMirror: Mirror {
     return Mirror(
       self,
       children: ["width": width, "height": height],
       displayStyle: .`struct`)
   }
+}
 
+extension CGSize : _CustomPlaygroundQuickLookable {
   @available(*, deprecated, message: "CGSize.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .size(Double(width), Double(height))
@@ -431,14 +435,16 @@
   public var y: CGFloat { return minY }
 }
 
-extension CGRect : CustomReflectable, CustomPlaygroundQuickLookable {
+extension CGRect : CustomReflectable {
   public var customMirror: Mirror {
     return Mirror(
       self,
       children: ["origin": origin, "size": size],
       displayStyle: .`struct`)
   }
+}
 
+extension CGRect : _CustomPlaygroundQuickLookable {
   @available(*, deprecated, message: "CGRect.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .rectangle(
diff --git a/stdlib/public/SDK/Foundation/Date.swift b/stdlib/public/SDK/Foundation/Date.swift
index 967b158..7231a6d 100644
--- a/stdlib/public/SDK/Foundation/Date.swift
+++ b/stdlib/public/SDK/Foundation/Date.swift
@@ -272,7 +272,7 @@
     }
 }
 
-extension Date : CustomPlaygroundQuickLookable {
+extension Date : _CustomPlaygroundQuickLookable {
     var summary: String {
         let df = DateFormatter()
         df.dateStyle = .medium
diff --git a/stdlib/public/SDK/Foundation/NSCoder.swift b/stdlib/public/SDK/Foundation/NSCoder.swift
index 0086f9f..8c57d1a 100644
--- a/stdlib/public/SDK/Foundation/NSCoder.swift
+++ b/stdlib/public/SDK/Foundation/NSCoder.swift
@@ -172,7 +172,7 @@
   @available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *)
   public static func unarchivedObject<DecodedObjectType>(ofClass cls: DecodedObjectType.Type, from data: Data) throws -> DecodedObjectType? where DecodedObjectType : NSCoding, DecodedObjectType : NSObject {
     var error: NSError?
-    let result = __NSKeyedUnarchiverSecureUnarchiveObjectOfClass(cls as! AnyClass, data, &error)
+    let result = __NSKeyedUnarchiverSecureUnarchiveObjectOfClass(cls as AnyClass, data, &error)
     try resolveError(error)
     return result as? DecodedObjectType
   }
diff --git a/stdlib/public/SDK/Foundation/NSDate.swift b/stdlib/public/SDK/Foundation/NSDate.swift
index 4896e9d..2c4a0be 100644
--- a/stdlib/public/SDK/Foundation/NSDate.swift
+++ b/stdlib/public/SDK/Foundation/NSDate.swift
@@ -12,7 +12,7 @@
 
 @_exported import Foundation // Clang module
 
-extension NSDate : CustomPlaygroundQuickLookable {
+extension NSDate : _CustomPlaygroundQuickLookable {
   @nonobjc
   var summary: String {
     let df = DateFormatter()
diff --git a/stdlib/public/SDK/Foundation/NSRange.swift b/stdlib/public/SDK/Foundation/NSRange.swift
index 85228fc..f4943c0 100644
--- a/stdlib/public/SDK/Foundation/NSRange.swift
+++ b/stdlib/public/SDK/Foundation/NSRange.swift
@@ -197,7 +197,7 @@
     }
 }
 
-extension NSRange : CustomPlaygroundQuickLookable {
+extension NSRange : _CustomPlaygroundQuickLookable {
     @available(*, deprecated, message: "NSRange.customPlaygroundQuickLook will be removed in a future Swift version")
     public var customPlaygroundQuickLook: PlaygroundQuickLook {
         return .range(Int64(location), Int64(length))
diff --git a/stdlib/public/SDK/Foundation/NSString.swift b/stdlib/public/SDK/Foundation/NSString.swift
index d04e178..9bff141 100644
--- a/stdlib/public/SDK/Foundation/NSString.swift
+++ b/stdlib/public/SDK/Foundation/NSString.swift
@@ -107,7 +107,7 @@
   }
 }
 
-extension NSString : CustomPlaygroundQuickLookable {
+extension NSString : _CustomPlaygroundQuickLookable {
   @available(*, deprecated, message: "NSString.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .text(self as String)
diff --git a/stdlib/public/SDK/Foundation/NSURL.swift b/stdlib/public/SDK/Foundation/NSURL.swift
index 6cf6522..6dacb8b 100644
--- a/stdlib/public/SDK/Foundation/NSURL.swift
+++ b/stdlib/public/SDK/Foundation/NSURL.swift
@@ -12,7 +12,7 @@
 
 @_exported import Foundation // Clang module
 
-extension NSURL : CustomPlaygroundQuickLookable {
+extension NSURL : _CustomPlaygroundQuickLookable {
   @available(*, deprecated, message: "NSURL.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     guard let str = absoluteString else { return .text("Unknown URL") }
diff --git a/stdlib/public/SDK/Foundation/URL.swift b/stdlib/public/SDK/Foundation/URL.swift
index f176a9f..b4bf0f1 100644
--- a/stdlib/public/SDK/Foundation/URL.swift
+++ b/stdlib/public/SDK/Foundation/URL.swift
@@ -412,6 +412,26 @@
     @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
     public var volumeSupportsCompression : Bool? { return _get(.volumeSupportsCompressionKey) }
     
+    /// true if the volume supports clonefile(2).
+    @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+    public var volumeSupportsFileCloning : Bool? { return _get(.volumeSupportsFileCloningKey) }
+    
+    /// true if the volume supports renamex_np(2)'s RENAME_SWAP option.
+    @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+    public var volumeSupportsSwapRenaming : Bool? { return _get(.volumeSupportsSwapRenamingKey) }
+    
+    /// true if the volume supports renamex_np(2)'s RENAME_EXCL option.
+    @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+    public var volumeSupportsExclusiveRenaming : Bool? { return _get(.volumeSupportsExclusiveRenamingKey) }
+    
+    /// true if the volume supports making files immutable with isUserImmutable or isSystemImmutable.
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+    public var volumeSupportsImmutableFiles : Bool? { return _get(.volumeSupportsImmutableFilesKey) }
+    
+    /// true if the volume supports setting POSIX access permissions with fileSecurity.
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+    public var volumeSupportsAccessPermissions : Bool? { return _get(.volumeSupportsAccessPermissionsKey) }
+    
     /// true if this item is synced to the cloud, false if it is only a local file. 
     public var isUbiquitousItem : Bool? { return _get(.isUbiquitousItemKey) }
 
@@ -1210,7 +1230,7 @@
     }
 }
 
-extension URL : CustomPlaygroundQuickLookable {
+extension URL : _CustomPlaygroundQuickLookable {
     @available(*, deprecated, message: "URL.customPlaygroundQuickLook will be removed in a future Swift version")
     public var customPlaygroundQuickLook: PlaygroundQuickLook {
         return .url(absoluteString)
diff --git a/stdlib/public/SDK/Foundation/URLComponents.swift b/stdlib/public/SDK/Foundation/URLComponents.swift
index 95f9cb7..28f71dc 100644
--- a/stdlib/public/SDK/Foundation/URLComponents.swift
+++ b/stdlib/public/SDK/Foundation/URLComponents.swift
@@ -291,6 +291,15 @@
         set { _applyMutation { $0.queryItems = newValue } }
     }
     
+    /// Returns an array of query items for this `URLComponents`, in the order in which they appear in the original query string. Any percent-encoding in a query item name or value is retained
+    ///
+    /// The setter combines an array containing any number of `URLQueryItem`s, each of which represents a single key-value pair, into a query string and sets the `URLComponents` query property. This property assumes the query item names and values are already correctly percent-encoded, and that the query item names do not contain the query item delimiter characters '&' and '='. Attempting to set an incorrectly percent-encoded query item or a query item name with the query item delimiter characters '&' and '=' will cause a `fatalError`.
+    @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+    public var percentEncodedQueryItems: [URLQueryItem]? {
+        get { return _handle.map { $0.percentEncodedQueryItems } }
+        set { _applyMutation { $0.percentEncodedQueryItems = newValue } }
+    }
+	
     public var hashValue: Int {
         return _handle.map { $0.hash }
     }
diff --git a/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb b/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
index 5a0893b..69a7aeb 100644
--- a/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
+++ b/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
@@ -14,7 +14,7 @@
 
 % for Self in ['SKShapeNode', 'SKSpriteNode', 'SKTextureAtlas', 'SKTexture']:
 
-extension ${Self} : CustomPlaygroundQuickLookable {
+extension ${Self} : _CustomPlaygroundQuickLookable {
   @available(*, deprecated, message: "${Self}.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     let data = (self as AnyObject)._copyImageData?() as Data?
diff --git a/stdlib/public/core/Algorithm.swift b/stdlib/public/core/Algorithm.swift
index df836fe..72bf086 100644
--- a/stdlib/public/core/Algorithm.swift
+++ b/stdlib/public/core/Algorithm.swift
@@ -158,6 +158,3 @@
     return Iterator(_base: _base.makeIterator())
   }
 }
-
-@available(*, deprecated: 4.2, renamed: "EnumeratedSequence.Iterator")
-public typealias EnumeratedIterator<T: Sequence> = EnumeratedSequence<T>.Iterator
diff --git a/stdlib/public/core/AnyHashable.swift b/stdlib/public/core/AnyHashable.swift
index 45c4700..a0b6d4c 100644
--- a/stdlib/public/core/AnyHashable.swift
+++ b/stdlib/public/core/AnyHashable.swift
@@ -39,20 +39,29 @@
 
 @usableFromInline // FIXME(sil-serialize-all)
 internal protocol _AnyHashableBox {
-  func _unbox<T : Hashable>() -> T?
+  var _canonicalBox: _AnyHashableBox { get }
 
   /// Determine whether values in the boxes are equivalent.
   ///
+  /// - Precondition: `self` and `box` are in canonical form.
   /// - Returns: `nil` to indicate that the boxes store different types, so
   ///   no comparison is possible. Otherwise, contains the result of `==`.
-  func _isEqual(to: _AnyHashableBox) -> Bool?
+  func _isEqual(to box: _AnyHashableBox) -> Bool?
   var _hashValue: Int { get }
   func _hash(into hasher: inout Hasher)
+  func _rawHashValue(_seed: (UInt64, UInt64)) -> Int
 
   var _base: Any { get }
+  func _unbox<T: Hashable>() -> T?
   func _downCastConditional<T>(into result: UnsafeMutablePointer<T>) -> Bool
 }
 
+extension _AnyHashableBox {
+  var _canonicalBox: _AnyHashableBox {
+    return self
+  }
+}
+
 @_fixed_layout // FIXME(sil-serialize-all)
 @usableFromInline // FIXME(sil-serialize-all)
 internal struct _ConcreteHashableBox<Base : Hashable> : _AnyHashableBox {
@@ -88,6 +97,11 @@
   }
 
   @inlinable // FIXME(sil-serialize-all)
+  func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+    return _baseHashable._rawHashValue(seed: _seed)
+  }
+
+  @inlinable // FIXME(sil-serialize-all)
   internal var _base: Any {
     return _baseHashable
   }
@@ -101,19 +115,6 @@
   }
 }
 
-#if _runtime(_ObjC)
-// Retrieve the custom AnyHashable representation of the value after it
-// has been bridged to Objective-C. This mapping to Objective-C and back
-// turns a non-custom representation into a custom one, which is used as
-// the lowest-common-denominator for comparisons.
-@inlinable // FIXME(sil-serialize-all)
-internal func _getBridgedCustomAnyHashable<T>(_ value: T) -> AnyHashable? {
-  let bridgedValue = _bridgeAnythingToObjectiveC(value)
-  return (bridgedValue as?
-    _HasCustomAnyHashableRepresentation)?._toCustomAnyHashable()
-}
-#endif
-
 /// A type-erased hashable value.
 ///
 /// The `AnyHashable` type forwards equality comparisons and hashing operations
@@ -137,8 +138,11 @@
 public struct AnyHashable {
   @usableFromInline // FIXME(sil-serialize-all)
   internal var _box: _AnyHashableBox
-  @usableFromInline // FIXME(sil-serialize-all)
-  internal var _usedCustomRepresentation: Bool
+
+  @inlinable // FIXME(sil-serialize-all)
+  internal init(_box box: _AnyHashableBox) {
+    self._box = box
+  }
 
   /// Creates a type-erased hashable value that wraps the given instance.
   ///
@@ -160,15 +164,13 @@
   /// - Parameter base: A hashable value to wrap.
   @inlinable // FIXME(sil-serialize-all)
   public init<H : Hashable>(_ base: H) {
-    if let customRepresentation =
+    if let custom =
       (base as? _HasCustomAnyHashableRepresentation)?._toCustomAnyHashable() {
-      self = customRepresentation
-      self._usedCustomRepresentation = true
+      self = custom
       return
     }
 
-    self._box = _ConcreteHashableBox(0 as Int)
-    self._usedCustomRepresentation = false
+    self.init(_box: _ConcreteHashableBox(false)) // Dummy value
     _makeAnyHashableUpcastingToHashableBaseType(
       base,
       storingResultInto: &self)
@@ -177,7 +179,6 @@
   @inlinable // FIXME(sil-serialize-all)
   internal init<H : Hashable>(_usingDefaultRepresentationOf base: H) {
     self._box = _ConcreteHashableBox(base)
-    self._usedCustomRepresentation = false
   }
 
   /// The value wrapped by this instance.
@@ -206,13 +207,11 @@
     if _box._downCastConditional(into: result) { return true }
 
     #if _runtime(_ObjC)
-    // If we used a custom representation, bridge to Objective-C and then
-    // attempt the cast from there.
-    if _usedCustomRepresentation {
-      if let value = _bridgeAnythingToObjectiveC(_box._base) as? T {
-        result.initialize(to: value)
-        return true
-      }
+    // Bridge to Objective-C and then attempt the cast from there.
+    // FIXME: This should also work without the Objective-C runtime.
+    if let value = _bridgeAnythingToObjectiveC(_box._base) as? T {
+      result.initialize(to: value)
+      return true
     }
     #endif
 
@@ -248,34 +247,7 @@
   ///   - rhs: Another type-erased hashable value.
   @inlinable // FIXME(sil-serialize-all)
   public static func == (lhs: AnyHashable, rhs: AnyHashable) -> Bool {
-    // If they're equal, we're done.
-    if let result = lhs._box._isEqual(to: rhs._box) { return result }
-
-    #if _runtime(_ObjC)
-    // If one used a custom representation but the other did not, bridge
-    // the one that did *not* use the custom representation to Objective-C:
-    // if the bridged result has a custom representation, compare those custom
-    // custom representations.
-    if lhs._usedCustomRepresentation != rhs._usedCustomRepresentation {
-      // If the lhs used a custom representation, try comparing against the
-      // custom representation of the bridged rhs (if there is one).
-      if lhs._usedCustomRepresentation {
-        if let customRHS = _getBridgedCustomAnyHashable(rhs._box._base) {
-          return lhs._box._isEqual(to: customRHS._box) ?? false
-        }
-        return false
-      }
-
-      // Otherwise, try comparing the rhs against the custom representation of
-      // the bridged lhs (if there is one).
-      if let customLHS = _getBridgedCustomAnyHashable(lhs._box._base) {
-        return customLHS._box._isEqual(to: rhs._box) ?? false
-      }
-      return false
-    }
-    #endif
-
-    return false
+    return lhs._box._canonicalBox._isEqual(to: rhs._box._canonicalBox) ?? false
   }
 }
 
@@ -283,7 +255,7 @@
   /// The hash value.
   @inlinable
   public var hashValue: Int {
-    return _box._hashValue
+    return _box._canonicalBox._hashValue
   }
 
   /// Hashes the essential components of this value by feeding them into the
@@ -293,7 +265,12 @@
   ///   of this instance.
   @inlinable
   public func hash(into hasher: inout Hasher) {
-    _box._hash(into: &hasher)
+    _box._canonicalBox._hash(into: &hasher)
+  }
+
+  @inlinable // FIXME(sil-serialize-all)
+  public func _rawHashValue(seed: (UInt64, UInt64)) -> Int {
+    return _box._canonicalBox._rawHashValue(_seed: seed)
   }
 }
 
diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift
index 2fd1057..a23c6d1 100644
--- a/stdlib/public/core/Array.swift
+++ b/stdlib/public/core/Array.swift
@@ -1758,3 +1758,76 @@
   }
 }
 #endif
+
+extension Array: _HasCustomAnyHashableRepresentation
+  where Element: Hashable {
+  public func _toCustomAnyHashable() -> AnyHashable? {
+    return AnyHashable(_box: _ArrayAnyHashableBox(self))
+  }
+}
+
+internal protocol _ArrayAnyHashableProtocol: _AnyHashableBox {
+  var count: Int { get }
+  subscript(index: Int) -> AnyHashable { get }
+}
+
+internal struct _ArrayAnyHashableBox<Element: Hashable>
+  : _ArrayAnyHashableProtocol {
+  internal let _value: [Element]
+
+  internal init(_ value: [Element]) {
+    self._value = value
+  }
+
+  internal var _base: Any {
+    return _value
+  }
+
+  internal var count: Int {
+    return _value.count
+  }
+
+  internal subscript(index: Int) -> AnyHashable {
+    return _value[index] as AnyHashable
+  }
+
+  func _isEqual(to other: _AnyHashableBox) -> Bool? {
+    guard let other = other as? _ArrayAnyHashableProtocol else { return nil }
+    guard _value.count == other.count else { return false }
+    for i in 0 ..< _value.count {
+      if self[i] != other[i] { return false }
+    }
+    return true
+  }
+
+  var _hashValue: Int {
+    var hasher = Hasher()
+    _hash(into: &hasher)
+    return hasher.finalize()
+  }
+
+  func _hash(into hasher: inout Hasher) {
+    hasher.combine(_value.count) // discriminator
+    for i in 0 ..< _value.count {
+      hasher.combine(self[i])
+    }
+  }
+
+  func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+    var hasher = Hasher(_seed: _seed)
+    self._hash(into: &hasher)
+    return hasher._finalize()
+  }
+
+  internal func _unbox<T : Hashable>() -> T? {
+    return _value as? T
+  }
+
+  internal func _downCastConditional<T>(
+    into result: UnsafeMutablePointer<T>
+  ) -> Bool {
+    guard let value = _value as? T else { return false }
+    result.initialize(to: value)
+    return true
+  }
+}
diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift
index 3665c56..b2c83bc 100644
--- a/stdlib/public/core/BidirectionalCollection.swift
+++ b/stdlib/public/core/BidirectionalCollection.swift
@@ -10,15 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-/// A type that provides subscript access to its elements, with bidirectional
-/// index traversal.
-///
-/// In most cases, it's best to ignore this protocol and use the
-/// `BidirectionalCollection` protocol instead, because it has a more complete
-/// interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0.  Please use 'BidirectionalCollection' instead")
-public typealias BidirectionalIndexable = BidirectionalCollection
-
 /// A collection that supports backward as well as forward traversal.
 ///
 /// Bidirectional collections offer traversal backward from any valid index,
diff --git a/stdlib/public/core/BridgeObjectiveC.swift b/stdlib/public/core/BridgeObjectiveC.swift
index 38c8b31..5c66c58 100644
--- a/stdlib/public/core/BridgeObjectiveC.swift
+++ b/stdlib/public/core/BridgeObjectiveC.swift
@@ -788,7 +788,7 @@
   var done = false
   var result: AnyObject!
   
-  var source: Any = x
+  let source: Any = x
   
   if let dynamicSource = _extractDynamicValue(x) {
     result = dynamicSource as AnyObject
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 41545b5..e17f92a 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -73,7 +73,6 @@
   Hashing.swift
   HeapBuffer.swift
   ICU.swift
-  ImplicitlyUnwrappedOptional.swift
   Indices.swift
   InputStream.swift
   IntegerParsing.swift
@@ -123,7 +122,6 @@
   Sort.swift.gyb
   StaticString.swift
   Stride.swift.gyb
-  StringCharacterView.swift # ORDER DEPENDENCY: Must precede String.swift
   StringHashable.swift  # ORDER DEPENDENCY: Must precede String.swift
   String.swift
   StringBridge.swift
@@ -168,6 +166,7 @@
   StringGraphemeBreaking.swift # ORDER DEPENDENCY: Must follow UTF16.swift
   ValidUTF8Buffer.swift
   WriteBackMutableSlice.swift
+  MigrationSupport.swift
   )
 
 # The complete list of sources in the core standard library.  Includes
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index 7b4cf52..f7a80c0 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -459,16 +459,7 @@
   }
 }
 
-extension ClosedRange where Bound: Strideable, Bound.Stride : SignedInteger {
-  /// Now that Range is conditionally a collection when Bound: Strideable,
-  /// CountableRange is no longer needed. This is a deprecated initializer
-  /// for any remaining uses of Range(countableRange).
-  @available(*,deprecated: 4.2, 
-    message: "CountableRange is now Range. No need to convert any more.")
-  public init(_ other: ClosedRange<Bound>) {
-    self = other
-  }  
-  
+extension ClosedRange where Bound: Strideable, Bound.Stride : SignedInteger {  
   /// Creates an instance equivalent to the given `Range`.
   ///
   /// - Parameter other: A `Range` to convert to a `ClosedRange` instance.
@@ -495,8 +486,7 @@
   }
 }
 
-@available(*, deprecated, renamed: "ClosedRange.Index")
-public typealias ClosedRangeIndex<T> = ClosedRange<T>.Index where T: Strideable, T.Stride: SignedInteger
-
+// Note: this is not for compatibility only, it is considered a useful
+// shorthand. TODO: Add documentation
 public typealias CountableClosedRange<Bound: Strideable> = ClosedRange<Bound>
   where Bound.Stride : SignedInteger
diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift
index 879625c..acb38c8 100644
--- a/stdlib/public/core/Collection.swift
+++ b/stdlib/public/core/Collection.swift
@@ -10,22 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-/// A type that provides subscript access to its elements, with forward
-/// index traversal.
-///
-/// In most cases, it's best to ignore this protocol and use the `Collection`
-/// protocol instead, because it has a more complete interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0.  Please use 'Collection' instead")
-public typealias IndexableBase = Collection
-
-/// A type that provides subscript access to its elements, with forward index
-/// traversal.
-///
-/// In most cases, it's best to ignore this protocol and use the `Collection`
-/// protocol instead, because it has a more complete interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0.  Please use 'Collection' instead")
-public typealias Indexable = Collection
-
 /// A type that iterates over a collection using its indices.
 ///
 /// The `IndexingIterator` type is the default iterator for any collection that
@@ -349,6 +333,11 @@
 /// the number of contained elements, accessing its `count` property is an
 /// O(*n*) operation.
 public protocol Collection: Sequence where SubSequence: Collection {
+  // FIXME: ideally this would be in MigrationSupport.swift, but it needs
+  // to be on the protocol instead of as an extension
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+  typealias IndexDistance = Int  
+
   // FIXME(ABI): Associated type inference requires this.
   associatedtype Element
 
@@ -807,28 +796,6 @@
   /// - Parameter i: A valid index of the collection. `i` must be less than
   ///   `endIndex`.
   func formIndex(after i: inout Index)
-
-  /// Returns a random element of the collection, using the given generator as
-  /// a source for randomness.
-  ///
-  /// You use this method to select a random element from a collection when you
-  /// are using a custom random number generator. For example, call
-  /// `randomElement(using:)` to select a random element from an array of names.
-  ///
-  ///     let names = ["Zoey", "Chloe", "Amani", "Amaia"]
-  ///     let randomName = names.randomElement(using: &myGenerator)!
-  ///     // randomName == "Amani"
-  ///
-  /// - Parameter generator: The random number generator to use when choosing
-  ///   a random element.
-  /// - Returns: A random element from the collection. If the collection is
-  ///   empty, the method returns `nil`.
-  __consuming func randomElement<T: RandomNumberGenerator>(
-    using generator: inout T
-  ) -> Element?
-
-  @available(*, deprecated, message: "all index distances are now of type Int")
-  typealias IndexDistance = Int
 }
 
 /// Default implementation for forward collections.
@@ -1803,35 +1770,3 @@
     return try preprocess()
   }
 }
-
-extension Collection {
-  // FIXME: <rdar://problem/34142121>
-  // This typealias should be removed as it predates the source compatibility
-  // guarantees of Swift 3, but it cannot due to a bug.
-  @available(*, unavailable, renamed: "Iterator")
-  public typealias Generator = Iterator
-
-  @available(swift, deprecated: 3.2, renamed: "Element")
-  public typealias _Element = Element
-
-  @available(*, deprecated, message: "all index distances are now of type Int")
-  public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T) -> Index {
-    return index(i, offsetBy: Int(n))
-  }
-  @available(*, deprecated, message: "all index distances are now of type Int")
-  public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T) {
-    return formIndex(&i, offsetBy: Int(n))
-  }
-  @available(*, deprecated, message: "all index distances are now of type Int")
-  public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T, limitedBy limit: Index) -> Index? {
-    return index(i, offsetBy: Int(n), limitedBy: limit)
-  }
-  @available(*, deprecated, message: "all index distances are now of type Int")
-  public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T, limitedBy limit: Index) -> Bool {
-    return formIndex(&i, offsetBy: Int(n), limitedBy: limit)
-  }
-  @available(*, deprecated, message: "all index distances are now of type Int")
-  public func distance<T: BinaryInteger>(from start: Index, to end: Index) -> T {
-    return numericCast(distance(from: start, to: end) as Int)
-  }
-}
diff --git a/stdlib/public/core/CollectionOfOne.swift b/stdlib/public/core/CollectionOfOne.swift
index 2fd1ca4..575ff5f 100644
--- a/stdlib/public/core/CollectionOfOne.swift
+++ b/stdlib/public/core/CollectionOfOne.swift
@@ -170,6 +170,3 @@
     return Mirror(self, children: ["element": _element])
   }
 }
-
-@available(*,deprecated: 4.2,renamed: "CollectionOfOne.Iterator")
-public typealias IteratorOverOne<T> = CollectionOfOne<T>.Iterator
\ No newline at end of file
diff --git a/stdlib/public/core/CompilerProtocols.swift b/stdlib/public/core/CompilerProtocols.swift
index d49be2c..3bd0b9f 100644
--- a/stdlib/public/core/CompilerProtocols.swift
+++ b/stdlib/public/core/CompilerProtocols.swift
@@ -723,7 +723,7 @@
 ///
 /// The `ExpressibleByStringInterpolation` protocol is deprecated. Do not add
 /// new conformances to the protocol.
-@available(*, deprecated, message: "it will be replaced or redesigned in Swift 4.0.  Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'")
+@available(*, deprecated, message: "it will be replaced or redesigned in Swift 5.0.  Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'")
 public typealias ExpressibleByStringInterpolation = _ExpressibleByStringInterpolation
 public protocol _ExpressibleByStringInterpolation {
   /// Creates an instance by concatenating the given values.
@@ -773,18 +773,6 @@
   init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float)
 }
 
-extension _ExpressibleByColorLiteral {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, obsoleted: 4.0,
-    message: "This initializer is only meant to be used by color literals")
-  public init(
-    colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float
-  ) {
-    self.init(
-      _colorLiteralRed: red, green: green, blue: blue, alpha: alpha)
-  }
-}
-
 /// A type that can be initialized using an image literal (e.g.
 /// `#imageLiteral(resourceName: "hi.png")`).
 public protocol _ExpressibleByImageLiteral {
@@ -819,67 +807,3 @@
 /// then Array would no longer be a _DestructorSafeContainer.
 public protocol _DestructorSafeContainer {
 }
-
-// Deprecated by SE-0115.
-
-@available(*, deprecated, renamed: "ExpressibleByNilLiteral")
-public typealias NilLiteralConvertible
-  = ExpressibleByNilLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinIntegerLiteral")
-public typealias _BuiltinIntegerLiteralConvertible
-  = _ExpressibleByBuiltinIntegerLiteral
-@available(*, deprecated, renamed: "ExpressibleByIntegerLiteral")
-public typealias IntegerLiteralConvertible
-  = ExpressibleByIntegerLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinFloatLiteral")
-public typealias _BuiltinFloatLiteralConvertible
-  = _ExpressibleByBuiltinFloatLiteral
-@available(*, deprecated, renamed: "ExpressibleByFloatLiteral")
-public typealias FloatLiteralConvertible
-  = ExpressibleByFloatLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinBooleanLiteral")
-public typealias _BuiltinBooleanLiteralConvertible
-  = _ExpressibleByBuiltinBooleanLiteral
-@available(*, deprecated, renamed: "ExpressibleByBooleanLiteral")
-public typealias BooleanLiteralConvertible
-  = ExpressibleByBooleanLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinUnicodeScalarLiteral")
-public typealias _BuiltinUnicodeScalarLiteralConvertible
-  = _ExpressibleByBuiltinUnicodeScalarLiteral
-@available(*, deprecated, renamed: "ExpressibleByUnicodeScalarLiteral")
-public typealias UnicodeScalarLiteralConvertible
-  = ExpressibleByUnicodeScalarLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinExtendedGraphemeClusterLiteral")
-public typealias _BuiltinExtendedGraphemeClusterLiteralConvertible
-  = _ExpressibleByBuiltinExtendedGraphemeClusterLiteral
-@available(*, deprecated, renamed: "ExpressibleByExtendedGraphemeClusterLiteral")
-public typealias ExtendedGraphemeClusterLiteralConvertible
-  = ExpressibleByExtendedGraphemeClusterLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinStringLiteral")
-public typealias _BuiltinStringLiteralConvertible
-  = _ExpressibleByBuiltinStringLiteral
-@available(*, deprecated, renamed: "_ExpressibleByBuiltinUTF16StringLiteral")
-public typealias _BuiltinUTF16StringLiteralConvertible
-  = _ExpressibleByBuiltinUTF16StringLiteral
-@available(*, deprecated, renamed: "ExpressibleByStringLiteral")
-public typealias StringLiteralConvertible
-  = ExpressibleByStringLiteral
-@available(*, deprecated, renamed: "ExpressibleByArrayLiteral")
-public typealias ArrayLiteralConvertible
-  = ExpressibleByArrayLiteral
-@available(*, deprecated, renamed: "ExpressibleByDictionaryLiteral")
-public typealias DictionaryLiteralConvertible
-  = ExpressibleByDictionaryLiteral
-@available(*, deprecated, message: "it will be replaced or redesigned in Swift 4.0.  Instead of conforming to 'StringInterpolationConvertible', consider adding an 'init(_:String)'")
-public typealias StringInterpolationConvertible
-  = ExpressibleByStringInterpolation
-@available(*, deprecated, renamed: "_ExpressibleByColorLiteral")
-public typealias _ColorLiteralConvertible
-  = _ExpressibleByColorLiteral
-@available(*, deprecated, renamed: "_ExpressibleByImageLiteral")
-public typealias _ImageLiteralConvertible
-  = _ExpressibleByImageLiteral
-@available(*, deprecated, renamed: "_ExpressibleByFileReferenceLiteral")
-public typealias _FileReferenceLiteralConvertible
-  = _ExpressibleByFileReferenceLiteral
-
diff --git a/stdlib/public/core/Dictionary.swift b/stdlib/public/core/Dictionary.swift
index 2a4bdb3..d3589b7 100644
--- a/stdlib/public/core/Dictionary.swift
+++ b/stdlib/public/core/Dictionary.swift
@@ -1153,53 +1153,6 @@
   }
 }
 
-// Maintain old `keys` and `values` types in Swift 3 mode.
-
-extension Dictionary {
-  /// A collection containing just the keys of the dictionary.
-  ///
-  /// When iterated over, keys appear in this collection in the same order as
-  /// they occur in the dictionary's key-value pairs. Each key in the keys
-  /// collection has a unique value.
-  ///
-  ///     let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
-  ///     print(countryCodes)
-  ///     // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
-  ///
-  ///     for k in countryCodes.keys {
-  ///         print(k)
-  ///     }
-  ///     // Prints "BR"
-  ///     // Prints "JP"
-  ///     // Prints "GH"
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4.0)
-  public var keys: LazyMapCollection<[Key: Value], Key> {
-    return self.lazy.map { $0.key }
-  }
-
-  /// A collection containing just the values of the dictionary.
-  ///
-  /// When iterated over, values appear in this collection in the same order as
-  /// they occur in the dictionary's key-value pairs.
-  ///
-  ///     let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
-  ///     print(countryCodes)
-  ///     // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
-  ///
-  ///     for v in countryCodes.values {
-  ///         print(v)
-  ///     }
-  ///     // Prints "Brazil"
-  ///     // Prints "Japan"
-  ///     // Prints "Ghana"
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4.0)
-  public var values: LazyMapCollection<[Key: Value], Value> {
-    return self.lazy.map { $0.value }
-  }
-}
-
 extension Dictionary {
   /// A collection containing just the keys of the dictionary.
   ///
@@ -1518,6 +1471,65 @@
   }
 }
 
+extension Dictionary: _HasCustomAnyHashableRepresentation
+where Value: Hashable {
+  public func _toCustomAnyHashable() -> AnyHashable? {
+    return AnyHashable(_box: _DictionaryAnyHashableBox(self))
+  }
+}
+
+internal struct _DictionaryAnyHashableBox<Key: Hashable, Value: Hashable>
+  : _AnyHashableBox {
+  internal let _value: Dictionary<Key, Value>
+  internal let _canonical: Dictionary<AnyHashable, AnyHashable>
+
+  internal init(_ value: Dictionary<Key, Value>) {
+    self._value = value
+    self._canonical = value as Dictionary<AnyHashable, AnyHashable>
+  }
+
+  internal var _base: Any {
+    return _value
+  }
+
+  internal var _canonicalBox: _AnyHashableBox {
+    return _DictionaryAnyHashableBox<AnyHashable, AnyHashable>(_canonical)
+  }
+
+  internal func _isEqual(to other: _AnyHashableBox) -> Bool? {
+    guard
+      let other = other as? _DictionaryAnyHashableBox<AnyHashable, AnyHashable>
+    else {
+      return nil
+    }
+    return _canonical == other._value
+  }
+
+  internal var _hashValue: Int {
+    return _canonical.hashValue
+  }
+
+  internal func _hash(into hasher: inout Hasher) {
+    _canonical.hash(into: &hasher)
+  }
+
+  internal func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+    return _canonical._rawHashValue(seed: _seed)
+  }
+
+  internal func _unbox<T: Hashable>() -> T? {
+    return _value as? T
+  }
+
+  internal func _downCastConditional<T>(
+    into result: UnsafeMutablePointer<T>
+  ) -> Bool {
+    guard let value = _value as? T else { return false }
+    result.initialize(to: value)
+    return true
+  }
+}
+
 extension Dictionary: CustomStringConvertible, CustomDebugStringConvertible {
   @inlinable // FIXME(sil-serialize-all)
   internal func _makeDescription() -> String {
@@ -4736,20 +4748,6 @@
     return remove(at: startIndex)
   }
 
-  @inlinable
-  @available(swift, obsoleted: 4.0)
-  public func filter(
-    _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
-  ) rethrows -> [Element] {
-    var result: [Element] = []
-    for x in self {
-      if try isIncluded(x) {
-        result.append(x)
-      }
-    }
-    return result
-  }
-
   /// The total number of key-value pairs that the dictionary can contain without
   /// allocating new storage.
   @inlinable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/DropWhile.swift b/stdlib/public/core/DropWhile.swift
index bc7538e..8c78847 100644
--- a/stdlib/public/core/DropWhile.swift
+++ b/stdlib/public/core/DropWhile.swift
@@ -256,10 +256,3 @@
   }
 }
 
-@available(*, deprecated, renamed: "LazyDropWhileSequence.Iterator")
-public typealias LazyDropWhileIterator<T> = LazyDropWhileSequence<T>.Iterator where T: Sequence
-@available(*, deprecated, renamed: "LazyDropWhileCollection.Index")
-public typealias LazyDropWhileIndex<T> = LazyDropWhileCollection<T>.Index where T: Collection
-@available(*, deprecated, renamed: "LazyDropWhileCollection")
-public typealias LazyDropWhileBidirectionalCollection<T> = LazyDropWhileCollection<T> where T: BidirectionalCollection
-
diff --git a/stdlib/public/core/EmptyCollection.swift b/stdlib/public/core/EmptyCollection.swift
index 5bd6312..d4605fe 100644
--- a/stdlib/public/core/EmptyCollection.swift
+++ b/stdlib/public/core/EmptyCollection.swift
@@ -172,6 +172,3 @@
     return true
   }
 }
-
-@available(*, deprecated: 4.2, renamed: "EmptyCollection.Iterator")
-public typealias EmptyIterator<T> = EmptyCollection<T>.Iterator
diff --git a/stdlib/public/core/Filter.swift b/stdlib/public/core/Filter.swift
index 8ccee84..edff25e 100644
--- a/stdlib/public/core/Filter.swift
+++ b/stdlib/public/core/Filter.swift
@@ -408,11 +408,3 @@
     }
   }
 }
-
-// @available(*, deprecated, renamed: "LazyFilterSequence.Iterator")
-public typealias LazyFilterIterator<T: Sequence> = LazyFilterSequence<T>.Iterator
-// @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use Base.Index")
-public typealias LazyFilterIndex<Base: Collection> = Base.Index
-@available(*, deprecated, renamed: "LazyFilterCollection")
-public typealias LazyFilterBidirectionalCollection<T> = LazyFilterCollection<T> where T : BidirectionalCollection
-
diff --git a/stdlib/public/core/FlatMap.swift b/stdlib/public/core/FlatMap.swift
index 1c40708..3ece0b8 100644
--- a/stdlib/public/core/FlatMap.swift
+++ b/stdlib/public/core/FlatMap.swift
@@ -48,29 +48,6 @@
   > {
     return self.map(transform).filter { $0 != nil }.map { $0! }
   }
-
-  /// Returns the non-`nil` results of mapping the given transformation over
-  /// this sequence.
-  ///
-  /// Use this method to receive a sequence of nonoptional values when your
-  /// transformation produces an optional value.
-  ///
-  /// - Parameter transform: A closure that accepts an element of this sequence
-  ///   as its argument and returns an optional value.
-  ///
-  /// - Complexity: O(1)
-  @inline(__always)
-  @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
-    message: "Please use compactMap(_:) for the case where closure returns an optional value")
-  public func flatMap<ElementOfResult>(
-    _ transform: @escaping (Elements.Element) -> ElementOfResult?
-  ) -> LazyMapSequence<
-    LazyFilterSequence<
-      LazyMapSequence<Elements, ElementOfResult?>>,
-    ElementOfResult
-  > {
-    return self.compactMap(transform)
-  }
 }
 
 extension LazyCollectionProtocol {
@@ -113,27 +90,4 @@
   > {
     return self.map(transform).filter { $0 != nil }.map { $0! }
   }
-
-  /// Returns the non-`nil` results of mapping the given transformation over
-  /// this collection.
-  ///
-  /// Use this method to receive a collection of nonoptional values when your
-  /// transformation produces an optional value.
-  ///
-  /// - Parameter transform: A closure that accepts an element of this
-  ///   collection as its argument and returns an optional value.
-  ///
-  /// - Complexity: O(1)
-  @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
-    message: "Please use compactMap(_:) for the case where closure returns an optional value")
-  @inlinable // FIXME(sil-serialize-all)
-  public func flatMap<ElementOfResult>(
-    _ transform: @escaping (Elements.Element) -> ElementOfResult?
-  ) -> LazyMapCollection<
-    LazyFilterCollection<
-      LazyMapCollection<Elements, ElementOfResult?>>,
-    ElementOfResult
-  > {
-    return self.map(transform).filter { $0 != nil }.map { $0! }
-  }
 }
diff --git a/stdlib/public/core/Flatten.swift b/stdlib/public/core/Flatten.swift
index 4ec2081..09b217d 100644
--- a/stdlib/public/core/Flatten.swift
+++ b/stdlib/public/core/Flatten.swift
@@ -525,10 +525,3 @@
     return FlattenCollection(elements).lazy
   }
 }
-
-// @available(*, deprecated, renamed: "FlattenCollection.Index")
-public typealias FlattenCollectionIndex<T> = FlattenCollection<T>.Index where T : Collection, T.Element : Collection
-@available(*, deprecated, renamed: "FlattenCollection.Index")
-public typealias FlattenBidirectionalCollectionIndex<T> = FlattenCollection<T>.Index where T : BidirectionalCollection, T.Element : BidirectionalCollection
-@available(*, deprecated, renamed: "FlattenCollection")
-public typealias FlattenBidirectionalCollection<T> = FlattenCollection<T> where T : BidirectionalCollection, T.Element : BidirectionalCollection
diff --git a/stdlib/public/core/FloatingPoint.swift.gyb b/stdlib/public/core/FloatingPoint.swift.gyb
index b4419c8..2fb08da 100644
--- a/stdlib/public/core/FloatingPoint.swift.gyb
+++ b/stdlib/public/core/FloatingPoint.swift.gyb
@@ -2501,93 +2501,6 @@
 
 % end
 
-extension FloatingPoint {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public func negated() -> Self {
-    return -self
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public func adding(_ other: Self) -> Self {
-    return self + other
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public mutating func add(_ other: Self) {
-    self += other
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public func subtracting(_ other: Self) -> Self {
-    return self - other
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public mutating func subtract(_ other: Self) {
-    self -= other
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public func multiplied(by other: Self) -> Self {
-    return self * other
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public mutating func multiply(by other: Self) {
-    self *= other
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public func divided(by other: Self) -> Self {
-    return self / other
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use operators instead.")
-  public mutating func divide(by other: Self) {
-    self /= other
-  }
-}
-
-extension FloatingPoint {
-  @available(*, unavailable, message: "Use bitPattern property instead")
-  public func _toBitPattern() -> UInt {
-    fatalError("unavailable")
-  }
-
-  @available(*, unavailable, message: "Use init(bitPattern:) instead")
-  public static func _fromBitPattern(_ bits: UInt) -> Self {
-    fatalError("unavailable")
-  }
-}
-
-extension BinaryFloatingPoint {
-  @available(*, unavailable, renamed: "isSignalingNaN")
-  public var isSignaling: Bool {
-    fatalError("unavailable")
-  }
-
-  @available(*, unavailable, renamed: "nan")
-  public var NaN: Bool {
-    fatalError("unavailable")
-  }
-  @available(*, unavailable, renamed: "nan")
-  public var quietNaN: Bool {
-    fatalError("unavailable")
-  }
-}
-
-@available(*, unavailable, renamed: "FloatingPoint")
-public typealias FloatingPointType = FloatingPoint
-
 // ${'Local Variables'}:
 // eval: (read-only-mode 1)
 // End:
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index d780d6c..a2a76e7 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -1559,6 +1559,13 @@
   }
 }
 
+extension ${Self}: _HasCustomAnyHashableRepresentation {
+  // Not @inlinable
+  public func _toCustomAnyHashable() -> AnyHashable? {
+    return AnyHashable(_box: _${Self}AnyHashableBox(self))
+  }
+}
+
 extension ${Self} {
   /// The magnitude of this value.
   ///
@@ -1810,43 +1817,90 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Deprecated operators
+// AnyHashable
 //===----------------------------------------------------------------------===//
 
-@_transparent
-@available(*, unavailable, message: "use += 1")
-@discardableResult
-public prefix func ++ (rhs: inout ${Self}) -> ${Self} {
-  fatalError("++ is not available")
-}
-@_transparent
-@available(*, unavailable, message: "use -= 1")
-@discardableResult
-public prefix func -- (rhs: inout ${Self}) -> ${Self} {
-  fatalError("-- is not available")
-}
-@_transparent
-@available(*, unavailable, message: "use += 1")
-@discardableResult
-public postfix func ++ (lhs: inout ${Self}) -> ${Self} {
-  fatalError("++ is not available")
-}
-@_transparent
-@available(*, unavailable, message: "use -= 1")
-@discardableResult
-public postfix func -- (lhs: inout ${Self}) -> ${Self} {
-  fatalError("-- is not available")
-}
+internal struct _${Self}AnyHashableBox: _AnyHashableBox {
+  internal typealias Base = ${Self}
+  internal let _value: Base
 
-extension ${Self} {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Please use the `abs(_:)` free function")
-  @_transparent
-  public static func abs(_ x: ${Self}) -> ${Self} {
-    return x.magnitude
+  internal init(_ value: Base) {
+    self._value = value
+  }
+
+  internal var _canonicalBox: _AnyHashableBox {
+    // Float and Double are bridged with NSNumber, so we have to follow
+    // NSNumber's rules for equality.  I.e., we need to make sure equal
+    // numerical values end up in identical boxes after canonicalization, so
+    // that _isEqual will consider them equal and they're hashed the same way.
+    //
+    // Note that these AnyHashable boxes don't currently feed discriminator bits
+    // to the hasher, so we allow repeatable collisions. E.g., -1 will always
+    // collide with UInt64.max.
+    if _value < 0 {
+      if let i = Int64(exactly: _value) {
+        return _IntegerAnyHashableBox(i)
+      }
+    } else {
+      if let i = UInt64(exactly: _value) {
+        return _IntegerAnyHashableBox(i)
+      }
+    }
+    if let d = Double(exactly: _value) {
+      return _DoubleAnyHashableBox(d)
+    }
+    // If a value can't be represented by a Double, keep it in its original
+    // representation so that it won't compare equal to approximations. (So that
+    // we don't round off Float80 values.)
+    return self
+  }
+
+  internal func _isEqual(to box: _AnyHashableBox) -> Bool? {
+    _sanityCheck(Int64(exactly: _value) == nil, "self isn't canonical")
+    _sanityCheck(UInt64(exactly: _value) == nil, "self isn't canonical")
+    if let box = box as? _${Self}AnyHashableBox {
+      return _value == box._value
+    }
+    return nil
+  }
+
+  internal var _hashValue: Int {
+    return _rawHashValue(_seed: Hasher._seed)
+  }
+
+  internal func _hash(into hasher: inout Hasher) {
+    _sanityCheck(Int64(exactly: _value) == nil, "self isn't canonical")
+    _sanityCheck(UInt64(exactly: _value) == nil, "self isn't canonical")
+    hasher.combine(_value)
+  }
+
+  internal func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+    var hasher = Hasher(_seed: _seed)
+    _hash(into: &hasher)
+    return hasher.finalize()
+  }
+
+  internal var _base: Any {
+    return _value
+  }
+
+  internal func _unbox<T: Hashable>() -> T? {
+    return _value as? T
+  }
+
+  internal func _downCastConditional<T>(
+    into result: UnsafeMutablePointer<T>
+  ) -> Bool {
+    guard let value = _value as? T else { return false }
+    result.initialize(to: value)
+    return true
   }
 }
 
+//===----------------------------------------------------------------------===//
+// Deprecated operators
+//===----------------------------------------------------------------------===//
+
 % if bits == 80:
 #else
 
diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json
index 09dfc6b..73acf81 100644
--- a/stdlib/public/core/GroupInfo.json
+++ b/stdlib/public/core/GroupInfo.json
@@ -14,7 +14,6 @@
     "StaticString.swift",
     "String.swift",
     "StringBridge.swift",
-    "StringCharacterView.swift",
     "StringComparable.swift",
     "StringComparison.swift",
     "StringObject.swift",
@@ -145,7 +144,6 @@
       "FloatingPointTypes.swift"]}
   ],
   "Optional": [
-    "ImplicitlyUnwrappedOptional.swift",
     "Optional.swift"
   ],
   "Pointer": [
@@ -193,6 +191,7 @@
     "Equatable.swift",
     "Comparable.swift",
     "Hashable.swift",
-    "Codable.swift"
+    "Codable.swift",
+    "MigrationSupport.swift"
   ]
 }
diff --git a/stdlib/public/core/Hasher.swift b/stdlib/public/core/Hasher.swift
index 0aaf1a1..5e48f11 100644
--- a/stdlib/public/core/Hasher.swift
+++ b/stdlib/public/core/Hasher.swift
@@ -437,6 +437,7 @@
     seed: (UInt64, UInt64),
     bytes value: UInt64,
     count: Int) -> Int {
+    _sanityCheck(count >= 0 && count < 8)
     var core = RawCore(seed: seed)
     let tbc = _HasherTailBuffer(tail: value, byteCount: count)
     return Int(truncatingIfNeeded: core.finalize(tailAndByteCount: tbc.value))
diff --git a/stdlib/public/core/ImplicitlyUnwrappedOptional.swift b/stdlib/public/core/ImplicitlyUnwrappedOptional.swift
deleted file mode 100644
index 289a0d1..0000000
--- a/stdlib/public/core/ImplicitlyUnwrappedOptional.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-/// An optional type that allows implicit member access.
-///
-/// The `ImplicitlyUnwrappedOptional` type is deprecated. To create an optional
-/// value that is implicitly unwrapped, place an exclamation mark (`!`) after
-/// the type that you want to denote as optional.
-///
-///     // An implicitly unwrapped optional integer
-///     let guaranteedNumber: Int! = 6
-///
-///     // An optional integer
-///     let possibleNumber: Int? = 5
-@available(*, unavailable, renamed: "Optional")
-public typealias ImplicitlyUnwrappedOptional<Wrapped> = Optional<Wrapped>
diff --git a/stdlib/public/core/Indices.swift b/stdlib/public/core/Indices.swift
index 018c19e..0a45f88 100644
--- a/stdlib/public/core/Indices.swift
+++ b/stdlib/public/core/Indices.swift
@@ -127,8 +127,3 @@
       endIndex: self.endIndex)
   }
 }
-
-@available(*, deprecated, renamed: "DefaultIndices")
-public typealias DefaultBidirectionalIndices<T> = DefaultIndices<T> where T : BidirectionalCollection
-@available(*, deprecated, renamed: "DefaultIndices")
-public typealias DefaultRandomAccessIndices<T> = DefaultIndices<T> where T : RandomAccessCollection
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 9562cd7..99ad000 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -2270,7 +2270,7 @@
 /// methods, the standard library provides default implementations for all
 /// other arithmetic methods and operators.
 public protocol FixedWidthInteger :
-  BinaryInteger, LosslessStringConvertible, _BitwiseOperations
+  BinaryInteger, LosslessStringConvertible
   where Magnitude : FixedWidthInteger
 {
   /// The number of bits used for the underlying binary representation of
@@ -2424,11 +2424,6 @@
 }
 
 extension FixedWidthInteger {
-  /// The empty bitset.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0")
-  public static var allZeros: Self { return 0 }
-
   /// The number of bits in the binary representation of this value.
   @inlinable
   public var bitWidth: Int { return Self.bitWidth }
@@ -2536,93 +2531,6 @@
 % for Range in ['Range', 'ClosedRange']:
 %   exampleRange = '1..<100' if Range == 'Range' else '1...100'
 
-extension ${Range}
-  where Bound: FixedWidthInteger, Bound.Stride : SignedInteger,
-  Bound.Magnitude: UnsignedInteger
-{
-      
-  /// Returns a random element of the range, using the given generator as
-  /// a source for randomness.
-  ///
-  /// You can use this method to select a random element of a range when you
-  /// are using a custom random number generator. If you're generating a random
-  /// number, in most cases, you should prefer using the `random(in:using:)`
-  /// static method of the desired numeric type. That static method is available
-  /// for both integer and floating point types, and returns a non-optional
-  /// value.
-  ///
-  /// - Parameter generator: The random number generator to use when choosing
-  ///   a random element.
-  /// - Returns: A random element of the range.
-%   if 'Closed' not in Range:
-  ///   If the range is empty, the method returns `nil`.
-%   else:
-  ///   This method never returns `nil`.
-%   end
-  @inlinable
-  public func randomElement<T: RandomNumberGenerator>(
-    using generator: inout T
-  ) -> Element? {
-    guard !isEmpty else {
-      return nil
-    }
-    // Compute delta, the distance between the lower and upper bounds. This
-    // value may not representable by the type Bound if Bound is signed, but
-    // is always representable as Bound.Magnitude.
-%   if 'Closed' in Range:
-    var delta = Bound.Magnitude(truncatingIfNeeded: upperBound &- lowerBound)
-%   else:
-    let delta = Bound.Magnitude(truncatingIfNeeded: upperBound &- lowerBound)
-%   end
-%   if 'Closed' in Range:
-    // Subtle edge case: if the range is the whole set of representable values,
-    // then adding one to delta to account for a closed range will overflow.
-    // If we used &+ instead, the result would be zero, which isn't helpful,
-    // so we actually need to handle this case separately.
-    if delta == Bound.Magnitude.max {
-      return Bound(truncatingIfNeeded: generator.next() as Bound.Magnitude)
-    }
-    // Need to widen delta to account for the right-endpoint of a closed range.
-    delta += 1
-%   end
-    // The mathematical result we want is lowerBound plus a random value in
-    // 0 ..< delta. We need to be slightly careful about how we do this
-    // arithmetic; the Bound type cannot generally represent the random value,
-    // so we use a wrapping addition on Bound.Magnitude. This will often
-    // overflow, but produces the correct bit pattern for the result when
-    // converted back to Bound.
-    return Bound(truncatingIfNeeded:
-      Bound.Magnitude(truncatingIfNeeded: lowerBound) &+
-      generator.next(upperBound: delta)
-    )
-  }
-  
-  /// Returns a random element of the range, using the given generator as
-  /// a source for randomness.
-  ///
-  /// You can use this method to select a random element of a range when you
-  /// are using a custom random number generator. If you're generating a random
-  /// number, in most cases, you should prefer using the `random(in:)`
-  /// static method of the desired numeric type. That static method is available
-  /// for both integer and floating point types, and returns a non-optional
-  /// value.
-  ///
-  /// This method uses the default random generator, `Random.default`. Calling
-  /// `(${exampleRange}).randomElement()` is equivalent to calling
-  /// `(${exampleRange}).randomElement(using: &Random.default)`.
-  ///
-  /// - Returns: A random element of the range.
-%   if 'Closed' not in Range:
-  ///   If the range is empty, the method returns `nil`.
-%   else:
-  ///   This method never returns `nil`.
-%   end
-  @inlinable
-  public func randomElement() -> Element? {
-    return randomElement(using: &Random.default)
-  }
-}
-
 extension FixedWidthInteger
 where Self.Stride : SignedInteger,
       Self.Magnitude : UnsignedInteger {
@@ -2658,7 +2566,36 @@
       !range.isEmpty,
       "Can't get random value with an empty range"
     )
-    return range.randomElement(using: &generator)!
+
+    // Compute delta, the distance between the lower and upper bounds. This
+    // value may not representable by the type Bound if Bound is signed, but
+    // is always representable as Bound.Magnitude.
+%   if 'Closed' in Range:
+    var delta = Magnitude(truncatingIfNeeded: range.upperBound &- range.lowerBound)
+%   else:
+    let delta = Magnitude(truncatingIfNeeded: range.upperBound &- range.lowerBound)
+%   end
+%   if 'Closed' in Range:
+    // Subtle edge case: if the range is the whole set of representable values,
+    // then adding one to delta to account for a closed range will overflow.
+    // If we used &+ instead, the result would be zero, which isn't helpful,
+    // so we actually need to handle this case separately.
+    if delta == Magnitude.max {
+      return Self(truncatingIfNeeded: generator.next() as Magnitude)
+    }
+    // Need to widen delta to account for the right-endpoint of a closed range.
+    delta += 1
+%   end
+    // The mathematical result we want is lowerBound plus a random value in
+    // 0 ..< delta. We need to be slightly careful about how we do this
+    // arithmetic; the Bound type cannot generally represent the random value,
+    // so we use a wrapping addition on Bound.Magnitude. This will often
+    // overflow, but produces the correct bit pattern for the result when
+    // converted back to Bound.
+    return Self(truncatingIfNeeded:
+      Magnitude(truncatingIfNeeded: range.lowerBound) &+
+      generator.next(upperBound: delta)
+    )
   }
   
   /// Returns a random value within the specified range.
@@ -3882,41 +3819,31 @@
   ///   of this instance.
   @inlinable
   public func hash(into hasher: inout Hasher) {
-    // FIXME(hasher): To correctly bridge `Set`s/`Dictionary`s containing
-    // `AnyHashable`-boxed integers, all integer values are currently required
-    // to hash exactly the same way as the corresponding (U)Int64 value.  To fix
-    // this, we should introduce a custom AnyHashable box for integer values
-    // that sign-extends values to 64 bits.
-    % if bits <= word_bits:
-    hasher._combine(_lowWord)
-    % elif bits == 2 * word_bits:
-    if let word = ${"" if signed else "U"}Int(exactly: self) {
-      hasher._combine(word._lowWord)
-    } else {
-      hasher._combine(UInt64(_value))
-    }
-    % else:
-    fatalError("Unsupported integer width")
-    % end
+    hasher._combine(${U}${Self}(_value))
   }
 
   @inlinable
   public func _rawHashValue(seed: (UInt64, UInt64)) -> Int {
-    // FIXME(hasher): Note that the AnyHashable concern applies here too,
-    // because hashValue uses top-level hashing.
-    % if bits <= word_bits:
-    return Hasher._hash(seed: seed, _lowWord)
-    % elif bits == 2 * word_bits:
-    if let word = ${"" if signed else "U"}Int(exactly: self) {
-      return Hasher._hash(seed: seed, word._lowWord)
-    }
+    % if bits == 64:
     return Hasher._hash(seed: seed, UInt64(_value))
+    % elif bits == word_bits:
+    return Hasher._hash(seed: seed, UInt(_value))
     % else:
-    fatalError("Unsupported integer width")
+    return Hasher._hash(
+      seed: seed,
+      bytes: UInt64(truncatingIfNeeded: ${U}${Self}(_value)),
+      count: ${bits / 8})
     % end
   }
 }
 
+extension ${Self} : _HasCustomAnyHashableRepresentation {
+  // Not @inlinable
+  public func _toCustomAnyHashable() -> AnyHashable? {
+    return AnyHashable(_box: _IntegerAnyHashableBox(self))
+  }
+}
+
 
 // Create an ambiguity when indexing or slicing
 // Range[OfStrideable]<${Self}> outside a generic context.  See
@@ -4095,48 +4022,6 @@
 #endif
 }
 
-// Swift 3 compatibility APIs
-
-@available(swift, obsoleted: 4, renamed: "BinaryInteger")
-public typealias Integer = BinaryInteger
-
-@available(swift, obsoleted: 4, renamed: "BinaryInteger")
-public typealias IntegerArithmetic = BinaryInteger
-
-@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
-public typealias SignedNumber = SignedNumeric & Comparable
-
-@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
-public typealias AbsoluteValuable = SignedNumeric & Comparable
-
-@available(swift, obsoleted: 4, renamed: "SignedInteger")
-public typealias _SignedInteger = SignedInteger
-
-extension SignedNumeric where Self : Comparable {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "Please use the 'abs(_:)' free function.")
-  @_transparent
-  public static func abs(_ x: Self) -> Self {
-    return Swift.abs(x)
-  }
-}
-
-extension BinaryInteger {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public func toIntMax() -> Int64 {
-    return Int64(self)
-  }
-}
-
-extension UnsignedInteger {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public func toUIntMax() -> UInt64 {
-    return UInt64(self)
-  }
-}
-
 // FIXME(integers): These overloads allow expressions like the following in
 // Swift 3 compatibility mode:
 //    let x = 1 << i32
@@ -4256,6 +4141,73 @@
 %   end
 }
 
+internal struct _IntegerAnyHashableBox<
+  Base: FixedWidthInteger
+>: _AnyHashableBox {
+  internal let _value: Base
+
+  internal init(_ value: Base) {
+    self._value = value
+  }
+
+  internal var _canonicalBox: _AnyHashableBox {
+    // We need to follow NSNumber semantics here; the AnyHashable forms of
+    // integer types holding the same mathematical value should compare equal.
+    // Sign-extend value to a 64-bit integer. This will generate hash conflicts
+    // between, say -1 and UInt.max, but that's fine.
+    if _value < 0 {
+      return _IntegerAnyHashableBox<Int64>(Int64(truncatingIfNeeded: _value))
+    }
+    return _IntegerAnyHashableBox<UInt64>(UInt64(truncatingIfNeeded: _value))
+  }
+
+  internal func _isEqual(to box: _AnyHashableBox) -> Bool? {
+    if Base.self == UInt64.self {
+      guard let box = box as? _IntegerAnyHashableBox<UInt64> else { return nil }
+      return _value == box._value
+    }
+    if Base.self == Int64.self {
+      guard let box = box as? _IntegerAnyHashableBox<Int64> else { return nil }
+      return _value == box._value
+    }
+    _preconditionFailure("self isn't canonical")
+  }
+
+  internal var _hashValue: Int {
+    _sanityCheck(Base.self == UInt64.self || Base.self == Int64.self,
+      "self isn't canonical")
+    return _value.hashValue
+  }
+
+  internal func _hash(into hasher: inout Hasher) {
+    _sanityCheck(Base.self == UInt64.self || Base.self == Int64.self,
+      "self isn't canonical")
+    _value.hash(into: &hasher)
+  }
+
+  internal func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+    _sanityCheck(Base.self == UInt64.self || Base.self == Int64.self,
+      "self isn't canonical")
+    return _value._rawHashValue(seed: _seed)
+  }
+
+  internal var _base: Any {
+    return _value
+  }
+
+  internal func _unbox<T: Hashable>() -> T? {
+    return _value as? T
+  }
+
+  internal func _downCastConditional<T>(
+    into result: UnsafeMutablePointer<T>
+  ) -> Bool {
+    guard let value = _value as? T else { return false }
+    result.initialize(to: value)
+    return true
+  }
+}
+
 // ${'Local Variables'}:
 // eval: (read-only-mode 1)
 // End:
diff --git a/stdlib/public/core/Join.swift b/stdlib/public/core/Join.swift
index 4dbc3b5..b17908a 100644
--- a/stdlib/public/core/Join.swift
+++ b/stdlib/public/core/Join.swift
@@ -191,6 +191,3 @@
     return JoinedSequence(base: self, separator: separator)
   }
 }
-
-// @available(*, deprecated, renamed: "JoinedSequence.Iterator")
-public typealias JoinedIterator<T: Sequence> = JoinedSequence<T>.Iterator where T.Element: Sequence
diff --git a/stdlib/public/core/LazyCollection.swift b/stdlib/public/core/LazyCollection.swift
index d5dd497..b9ce84e 100644
--- a/stdlib/public/core/LazyCollection.swift
+++ b/stdlib/public/core/LazyCollection.swift
@@ -263,8 +263,3 @@
 extension Slice: LazyCollectionProtocol where Base: LazyCollectionProtocol { }
 extension ReversedCollection: LazySequenceProtocol where Base: LazySequenceProtocol { }
 extension ReversedCollection: LazyCollectionProtocol where Base: LazyCollectionProtocol { }
-
-@available(*, deprecated, renamed: "LazyCollection")
-public typealias LazyBidirectionalCollection<T> = LazyCollection<T> where T : BidirectionalCollection
-@available(*, deprecated, renamed: "LazyCollection")
-public typealias LazyRandomAccessCollection<T> = LazyCollection<T> where T : RandomAccessCollection
diff --git a/stdlib/public/core/Map.swift b/stdlib/public/core/Map.swift
index 9f2ef4c..9ca87ec 100644
--- a/stdlib/public/core/Map.swift
+++ b/stdlib/public/core/Map.swift
@@ -257,22 +257,6 @@
   }
 }
 
-extension LazyMapCollection {
-  // This overload is needed to re-enable Swift 3 source compatibility related
-  // to a bugfix in ranking behavior of the constraint solver.
-  @available(swift, obsoleted: 4.0)
-  public static func + <
-    Other : LazyCollectionProtocol
-  >(lhs: LazyMapCollection, rhs: Other) -> [Element]
-  where Other.Element == Element {
-    var result: [Element] = []
-    result.reserveCapacity(numericCast(lhs.count + rhs.count))
-    result.append(contentsOf: lhs)
-    result.append(contentsOf: rhs)
-    return result
-  }
-}
-
 extension LazyMapSequence {
   @inlinable
   @available(swift, introduced: 5)
@@ -296,10 +280,3 @@
       transform: {transform(self._transform($0))})
   }
 }
-
-// @available(*, deprecated, renamed: "LazyMapSequence.Iterator")
-public typealias LazyMapIterator<T, E> = LazyMapSequence<T, E>.Iterator where T: Sequence
-@available(*, deprecated, renamed: "LazyMapCollection")
-public typealias LazyMapBidirectionalCollection<T, E> = LazyMapCollection<T, E> where T : BidirectionalCollection
-@available(*, deprecated, renamed: "LazyMapCollection")
-public typealias LazyMapRandomAccessCollection<T, E> = LazyMapCollection<T, E> where T : RandomAccessCollection
diff --git a/stdlib/public/core/MigrationSupport.swift b/stdlib/public/core/MigrationSupport.swift
new file mode 100644
index 0000000..9f9e8ad
--- /dev/null
+++ b/stdlib/public/core/MigrationSupport.swift
@@ -0,0 +1,1288 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+// This file contains only support for types deprecated from previous versions
+// of Swift
+
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "BidirectionalCollection", message: "it will be removed in Swift 5.0.  Please use 'BidirectionalCollection' instead")
+public typealias BidirectionalIndexable = BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Collection", message: "it will be removed in Swift 5.0.  Please use 'Collection' instead")
+public typealias IndexableBase = Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Collection", message: "it will be removed in Swift 5.0.  Please use 'Collection' instead")
+public typealias Indexable = Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "MutableCollection", message: "it will be removed in Swift 5.0.  Please use 'MutableCollection' instead")
+public typealias MutableIndexable = MutableCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "RandomAccessCollection", message: "it will be removed in Swift 5.0.  Please use 'RandomAccessCollection' instead")
+public typealias RandomAccessIndexable = RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "RangeReplaceableIndexable", message: "it will be removed in Swift 5.0.  Please use 'RangeReplaceableCollection' instead")
+public typealias RangeReplaceableIndexable = RangeReplaceableCollection
+@available(*, deprecated: 4.2, renamed: "EnumeratedSequence.Iterator")
+public typealias EnumeratedIterator<T: Sequence> = EnumeratedSequence<T>.Iterator
+@available(*,deprecated: 4.2/*, obsoleted: 5.0*/, renamed: "CollectionOfOne.Iterator")
+public typealias IteratorOverOne<T> = CollectionOfOne<T>.Iterator
+@available(*, deprecated: 4.2/*, obsoleted: 5.0*/, renamed: "EmptyCollection.Iterator")
+public typealias EmptyIterator<T> = EmptyCollection<T>.Iterator
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyFilterSequence.Iterator")
+public typealias LazyFilterIterator<T: Sequence> = LazyFilterSequence<T>.Iterator
+@available(swift, deprecated: 3.1/*, obsoleted: 5.0*/, message: "Use Base.Index")
+public typealias LazyFilterIndex<Base: Collection> = Base.Index
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileSequence.Iterator")
+public typealias LazyDropWhileIterator<T> = LazyDropWhileSequence<T>.Iterator where T: Sequence
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileCollection.Index")
+public typealias LazyDropWhileIndex<T> = LazyDropWhileCollection<T>.Index where T: Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileCollection")
+public typealias LazyDropWhileBidirectionalCollection<T> = LazyDropWhileCollection<T> where T: BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyFilterCollection")
+public typealias LazyFilterBidirectionalCollection<T> = LazyFilterCollection<T> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyMapSequence.Iterator")
+public typealias LazyMapIterator<T, E> = LazyMapSequence<T, E>.Iterator where T: Sequence
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyMapCollection")
+public typealias LazyMapBidirectionalCollection<T, E> = LazyMapCollection<T, E> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyMapCollection")
+public typealias LazyMapRandomAccessCollection<T, E> = LazyMapCollection<T, E> where T : RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyCollection")
+public typealias LazyBidirectionalCollection<T> = LazyCollection<T> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyCollection")
+public typealias LazyRandomAccessCollection<T> = LazyCollection<T> where T : RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "FlattenCollection.Index")
+public typealias FlattenCollectionIndex<T> = FlattenCollection<T>.Index where T : Collection, T.Element : Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "FlattenCollection.Index")
+public typealias FlattenBidirectionalCollectionIndex<T> = FlattenCollection<T>.Index where T : BidirectionalCollection, T.Element : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "FlattenCollection")
+public typealias FlattenBidirectionalCollection<T> = FlattenCollection<T> where T : BidirectionalCollection, T.Element : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "JoinedSequence.Iterator")
+public typealias JoinedIterator<T: Sequence> = JoinedSequence<T>.Iterator where T.Element: Sequence
+@available(*, deprecated: 4.2/*, obsoleted: 5.0*/, renamed: "Zip2Sequence.Iterator")
+public typealias Zip2Iterator<T, U> = Zip2Sequence<T, U>.Iterator where T: Sequence, U: Sequence
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileSequence.Iterator")
+public typealias LazyPrefixWhileIterator<T> = LazyPrefixWhileSequence<T>.Iterator where T: Sequence
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyDropWhileCollection.Index")
+public typealias LazyPrefixWhileIndex<T> = LazyPrefixWhileCollection<T>.Index where T: Collection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "LazyPrefixWhileCollection")
+public typealias LazyPrefixWhileBidirectionalCollection<T> = LazyPrefixWhileCollection<T> where T: BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ReversedCollection")
+public typealias ReversedRandomAccessCollection<T: RandomAccessCollection> = ReversedCollection<T>
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ReversedCollection.Index")
+public typealias ReversedIndex<T: BidirectionalCollection> = ReversedCollection<T>
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias BidirectionalSlice<T> = Slice<T> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias RandomAccessSlice<T> = Slice<T> where T : RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias RangeReplaceableSlice<T> = Slice<T> where T : RangeReplaceableCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias RangeReplaceableBidirectionalSlice<T> = Slice<T> where T : RangeReplaceableCollection & BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias RangeReplaceableRandomAccessSlice<T> = Slice<T> where T : RangeReplaceableCollection & RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableSlice<T> = Slice<T> where T : MutableCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableRangeReplaceableSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableRangeReplaceableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Slice")
+public typealias MutableRangeReplaceableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & RandomAccessCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "DefaultIndices")
+public typealias DefaultBidirectionalIndices<T> = DefaultIndices<T> where T : BidirectionalCollection
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "DefaultIndices")
+public typealias DefaultRandomAccessIndices<T> = DefaultIndices<T> where T : RandomAccessCollection
+
+// Deprecated by SE-0115.
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByNilLiteral")
+public typealias NilLiteralConvertible = ExpressibleByNilLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinIntegerLiteral")
+public typealias _BuiltinIntegerLiteralConvertible = _ExpressibleByBuiltinIntegerLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByIntegerLiteral")
+public typealias IntegerLiteralConvertible = ExpressibleByIntegerLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinFloatLiteral")
+public typealias _BuiltinFloatLiteralConvertible = _ExpressibleByBuiltinFloatLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByFloatLiteral")
+public typealias FloatLiteralConvertible = ExpressibleByFloatLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinBooleanLiteral")
+public typealias _BuiltinBooleanLiteralConvertible = _ExpressibleByBuiltinBooleanLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByBooleanLiteral")
+public typealias BooleanLiteralConvertible = ExpressibleByBooleanLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinUnicodeScalarLiteral")
+public typealias _BuiltinUnicodeScalarLiteralConvertible = _ExpressibleByBuiltinUnicodeScalarLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByUnicodeScalarLiteral")
+public typealias UnicodeScalarLiteralConvertible = ExpressibleByUnicodeScalarLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinExtendedGraphemeClusterLiteral")
+public typealias _BuiltinExtendedGraphemeClusterLiteralConvertible = _ExpressibleByBuiltinExtendedGraphemeClusterLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByExtendedGraphemeClusterLiteral")
+public typealias ExtendedGraphemeClusterLiteralConvertible = ExpressibleByExtendedGraphemeClusterLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinStringLiteral")
+public typealias _BuiltinStringLiteralConvertible = _ExpressibleByBuiltinStringLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByBuiltinUTF16StringLiteral")
+public typealias _BuiltinUTF16StringLiteralConvertible = _ExpressibleByBuiltinUTF16StringLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByStringLiteral")
+public typealias StringLiteralConvertible = ExpressibleByStringLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByArrayLiteral")
+public typealias ArrayLiteralConvertible = ExpressibleByArrayLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "ExpressibleByDictionaryLiteral")
+public typealias DictionaryLiteralConvertible = ExpressibleByDictionaryLiteral
+@available(*, deprecated, message: "it will be replaced or redesigned in Swift 4.0.  Instead of conforming to 'StringInterpolationConvertible', consider adding an 'init(_:String)'")
+public typealias StringInterpolationConvertible = ExpressibleByStringInterpolation
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByColorLiteral")
+public typealias _ColorLiteralConvertible = _ExpressibleByColorLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByImageLiteral")
+public typealias _ImageLiteralConvertible = _ExpressibleByImageLiteral
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "_ExpressibleByFileReferenceLiteral")
+public typealias _FileReferenceLiteralConvertible = _ExpressibleByFileReferenceLiteral
+
+@available(*, deprecated, obsoleted: 5.0, renamed: "ClosedRange.Index")
+public typealias ClosedRangeIndex<T> = ClosedRange<T>.Index where T: Strideable, T.Stride: SignedInteger
+
+/// An optional type that allows implicit member access.
+///
+/// The `ImplicitlyUnwrappedOptional` type is deprecated. To create an optional
+/// value that is implicitly unwrapped, place an exclamation mark (`!`) after
+/// the type that you want to denote as optional.
+///
+///     // An implicitly unwrapped optional integer
+///     let guaranteedNumber: Int! = 6
+///
+///     // An optional integer
+///     let possibleNumber: Int? = 5
+@available(*, unavailable, renamed: "Optional")
+public typealias ImplicitlyUnwrappedOptional<Wrapped> = Optional<Wrapped>
+
+@available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use FixedWidthInteger protocol instead")
+public typealias BitwiseOperations = _BitwiseOperations
+
+public protocol _BitwiseOperations {
+  static func & (lhs: Self, rhs: Self) -> Self
+  static func | (lhs: Self, rhs: Self) -> Self
+  static func ^ (lhs: Self, rhs: Self) -> Self
+  static prefix func ~ (x: Self) -> Self
+  static var allZeros: Self { get }
+}
+
+extension _BitwiseOperations {  
+    @available(swift, obsoleted: 4.1)
+    public static func |= (lhs: inout Self, rhs: Self) {
+      lhs = lhs | rhs
+    }
+
+    @available(swift, obsoleted: 4.1)
+    public static func &= (lhs: inout Self, rhs: Self) {
+      lhs = lhs & rhs
+    }
+
+    @available(swift, obsoleted: 4.1)
+    public static func ^= (lhs: inout Self, rhs: Self) {
+      lhs = lhs ^ rhs
+    }
+}
+
+extension FloatingPoint {
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public func negated() -> Self {
+    return -self
+  }
+
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public func adding(_ other: Self) -> Self {
+    return self + other
+  }
+
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public mutating func add(_ other: Self) {
+    self += other
+  }
+
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public func subtracting(_ other: Self) -> Self {
+    return self - other
+  }
+
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public mutating func subtract(_ other: Self) {
+    self -= other
+  }
+
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public func multiplied(by other: Self) -> Self {
+    return self * other
+  }
+
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public mutating func multiply(by other: Self) {
+    self *= other
+  }
+
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public func divided(by other: Self) -> Self {
+    return self / other
+  }
+
+  @available(swift, obsoleted: 4, message: "Please use operators instead.")
+  public mutating func divide(by other: Self) {
+    self /= other
+  }
+}
+
+extension FloatingPoint {
+  @available(*, unavailable, message: "Use bitPattern property instead")
+  public func _toBitPattern() -> UInt {
+    fatalError("unavailable")
+  }
+
+  @available(*, unavailable, message: "Use init(bitPattern:) instead")
+  public static func _fromBitPattern(_ bits: UInt) -> Self {
+    fatalError("unavailable")
+  }
+}
+
+extension BinaryFloatingPoint {
+  @available(*, unavailable, renamed: "isSignalingNaN")
+  public var isSignaling: Bool {
+    fatalError("unavailable")
+  }
+
+  @available(*, unavailable, renamed: "nan")
+  public var NaN: Bool {
+    fatalError("unavailable")
+  }
+  @available(*, unavailable, renamed: "nan")
+  public var quietNaN: Bool {
+    fatalError("unavailable")
+  }
+}
+
+@available(*, unavailable, renamed: "FloatingPoint")
+public typealias FloatingPointType = FloatingPoint
+
+// Swift 3 compatibility APIs
+@available(swift, obsoleted: 4, renamed: "BinaryInteger")
+public typealias Integer = BinaryInteger
+
+@available(swift, obsoleted: 4, renamed: "BinaryInteger")
+public typealias IntegerArithmetic = BinaryInteger
+
+@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
+public typealias SignedNumber = SignedNumeric & Comparable
+
+@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
+public typealias AbsoluteValuable = SignedNumeric & Comparable
+
+@available(swift, obsoleted: 4, renamed: "SignedInteger")
+public typealias _SignedInteger = SignedInteger
+
+extension SignedNumeric where Self : Comparable {
+  @available(swift, obsoleted: 4, message: "Please use the 'abs(_:)' free function.")
+  @_transparent
+  public static func abs(_ x: Self) -> Self {
+    return Swift.abs(x)
+  }
+}
+
+extension BinaryInteger {
+  @available(swift, obsoleted: 4)
+  public func toIntMax() -> Int64 {
+    return Int64(self)
+  }
+}
+
+extension UnsignedInteger {
+  @available(swift, obsoleted: 4)
+  public func toUIntMax() -> UInt64 {
+    return UInt64(self)
+  }
+}
+
+extension Range where Bound: Strideable, Bound.Stride : SignedInteger {
+  /// Now that Range is conditionally a collection when Bound: Strideable,
+  /// CountableRange is no longer needed. This is a deprecated initializer
+  /// for any remaining uses of Range(countableRange).
+  @available(*, deprecated: 4.2/*, obsoleted: 5.0*/, message: "CountableRange is now a Range. No need to convert any more.")
+  public init(_ other: Range<Bound>) {
+    self = other
+  }  
+}
+
+extension ClosedRange where Bound: Strideable, Bound.Stride : SignedInteger {
+  /// Now that Range is conditionally a collection when Bound: Strideable,
+  /// CountableRange is no longer needed. This is a deprecated initializer
+  /// for any remaining uses of Range(countableRange).
+  @available(*, deprecated: 4.2/*, obsoleted: 5.0*/, message: "CountableClosedRange is now a ClosedRange. No need to convert any more.")
+  public init(_ other: ClosedRange<Bound>) {
+    self = other
+  }  
+}
+
+extension _ExpressibleByColorLiteral {
+  @available(swift, deprecated: 3.2, obsoleted: 4.0, message: "This initializer is only meant to be used by color literals")
+  public init(colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) {
+    self.init(_colorLiteralRed: red, green: green, blue: blue, alpha: alpha)
+  }
+}
+
+extension LazySequenceProtocol {
+  /// Returns the non-`nil` results of mapping the given transformation over
+  /// this sequence.
+  ///
+  /// Use this method to receive a sequence of nonoptional values when your
+  /// transformation produces an optional value.
+  ///
+  /// - Parameter transform: A closure that accepts an element of this sequence
+  ///   as its argument and returns an optional value.
+  ///
+  /// - Complexity: O(1)
+  @available(swift, deprecated: 4.1, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
+  public func flatMap<ElementOfResult>(
+    _ transform: @escaping (Elements.Element) -> ElementOfResult?
+  ) -> LazyMapSequence<
+    LazyFilterSequence<
+      LazyMapSequence<Elements, ElementOfResult?>>,
+    ElementOfResult
+  > {
+    return self.compactMap(transform)
+  }
+}
+
+extension LazyMapCollection {
+  // This overload is needed to re-enable Swift 3 source compatibility related
+  // to a bugfix in ranking behavior of the constraint solver.
+  @available(swift, obsoleted: 4.0)
+  public static func + <
+    Other : LazyCollectionProtocol
+  >(lhs: LazyMapCollection, rhs: Other) -> [Element]
+  where Other.Element == Element {
+    var result: [Element] = []
+    result.reserveCapacity(numericCast(lhs.count + rhs.count))
+    result.append(contentsOf: lhs)
+    result.append(contentsOf: rhs)
+    return result
+  }
+}
+
+@available(*, unavailable, message: "use += 1")
+@discardableResult
+public prefix func ++ <F: FloatingPoint>(rhs: inout F) -> F {
+  fatalError("++ is not available")
+}
+@available(*, unavailable, message: "use -= 1")
+@discardableResult
+public prefix func -- <F: FloatingPoint>(rhs: inout F) -> F {
+  fatalError("-- is not available")
+}
+@available(*, unavailable, message: "use += 1")
+@discardableResult
+public postfix func ++ <F: FloatingPoint>(lhs: inout F) -> F {
+  fatalError("++ is not available")
+}
+@available(*, unavailable, message: "use -= 1")
+@discardableResult
+public postfix func -- <F: FloatingPoint>(lhs: inout F) -> F {
+  fatalError("-- is not available")
+}
+
+extension FloatingPoint {
+  @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Please use the `abs(_:)` free function")
+  public static func abs(_ x: Self) -> Self {
+    return x.magnitude
+  }
+}
+
+extension FixedWidthInteger {
+  /// The empty bitset.
+  @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0")
+  public static var allZeros: Self { return 0 }
+}
+
+extension LazyCollectionProtocol {
+  /// Returns the non-`nil` results of mapping the given transformation over
+  /// this collection.
+  ///
+  /// Use this method to receive a collection of nonoptional values when your
+  /// transformation produces an optional value.
+  ///
+  /// - Parameter transform: A closure that accepts an element of this
+  ///   collection as its argument and returns an optional value.
+  ///
+  /// - Complexity: O(1)
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "compactMap(_:)",
+    message: "Please use compactMap(_:) for the case where closure returns an optional value")
+  public func flatMap<ElementOfResult>(
+    _ transform: @escaping (Elements.Element) -> ElementOfResult?
+  ) -> LazyMapCollection<
+    LazyFilterCollection<
+      LazyMapCollection<Elements, ElementOfResult?>>,
+    ElementOfResult
+  > {
+    return self.map(transform).filter { $0 != nil }.map { $0! }
+  }
+}
+
+extension String {
+  /// A view of a string's contents as a collection of characters.
+  ///
+  /// Previous versions of Swift provided this view since String
+  /// itself was not a collection. String is now a collection of
+  /// characters, so this type is now just an alias for String.
+  @available(swift, deprecated: 3.2, obsoleted: 5.0, message: "Please use String directly")
+  public typealias CharacterView = String
+
+  /// A view of the string's contents as a collection of characters.
+  ///
+  /// Previous versions of Swift provided this view since String
+  /// itself was not a collection. String is now a collection of
+  /// characters, so this type is now just an alias for String.
+  @available(swift, deprecated: 3.2, obsoleted: 5.0, message: "Please use String directly")
+  public var characters: String {
+    get {
+      return self
+    }
+    set {
+      self = newValue
+    }
+  }
+
+  /// Applies the given closure to a mutable view of the string's characters.
+  ///
+  /// Previous versions of Swift provided this view since String
+  /// itself was not a collection. String is now a collection of
+  /// characters, so this type is now just an alias for String.
+  @available(swift, deprecated: 3.2/*, obsoleted: 5.0*/, message: "Please mutate the String directly")
+  public mutating func withMutableCharacters<R>(
+    _ body: (inout String) -> R
+  ) -> R {
+    return body(&self)
+  }
+
+  @available(swift, deprecated: 3.2, obsoleted: 4.0)
+  public init?(_ utf16: UTF16View) {
+    // Attempt to recover the whole string, the better to implement the actual
+    // Swift 3.1 semantics, which are not as documented above!  Full Swift 3.1
+    // semantics may be impossible to preserve in the case of string literals,
+    // since we no longer have access to the length of the original string when
+    // there is no owner and elements are dropped from the end.
+    let wholeString = String(utf16._guts)
+    guard
+      let start = UTF16Index(encodedOffset: utf16._offset)
+        .samePosition(in: wholeString),
+      let end = UTF16Index(encodedOffset: utf16._offset + utf16._length)
+        .samePosition(in: wholeString)
+      else
+    {
+        return nil
+    }
+    self = String(wholeString[start..<end])
+  }
+  
+  @available(swift, deprecated: 3.2, message: "Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)")
+  @available(swift, obsoleted: 4.0, message: "Please use non-failable String.init(_:UTF8View) instead")
+  public init?(_ utf8: UTF8View) {
+    if utf8.startIndex.transcodedOffset != 0
+      || utf8.endIndex.transcodedOffset != 0
+      || utf8._legacyPartialCharacters.start
+      || utf8._legacyPartialCharacters.end {
+      return nil
+    }
+    self = String(utf8._guts)
+  }
+}
+
+extension String { // RangeReplaceableCollection
+  // The defaulted argument prevents this initializer from satisfies the
+  // LosslessStringConvertible conformance.  You can satisfy a protocol
+  // requirement with something that's not yet available, but not with
+  // something that has become unavailable. Without this, the code won't
+  // compile as Swift 4.
+  @available(swift, obsoleted: 4, message: "String.init(_:String) is no longer failable")
+  public init?(_ other: String, obsoletedInSwift4: () = ()) {
+    self.init(other._guts)
+  }
+}
+
+extension String.UnicodeScalarView : _CustomPlaygroundQuickLookable {
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnicodeScalarView.customPlaygroundQuickLook will be removed in Swift 5.0")
+  public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+    return .text(description)
+  }
+}
+
+// backward compatibility for index interchange.
+extension String.UnicodeScalarView {
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public func index(after i: Index?) -> Index {
+    return index(after: i!)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public func index(_ i: Index?,  offsetBy n: Int) -> Index {
+    return index(i!, offsetBy: n)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+  public func distance(from i: Index?, to j: Index?) -> Int {
+    return distance(from: i!, to: j!)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public subscript(i: Index?) -> Unicode.Scalar {
+    return self[i!]
+  }
+}
+
+// backward compatibility for index interchange.
+extension String.UTF16View {
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public func index(after i: Index?) -> Index {
+    return index(after: i!)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public func index(_ i: Index?, offsetBy n: Int) -> Index {
+    return index(i!, offsetBy: n)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+  public func distance(from i: Index?, to j: Index?) -> Int {
+    return distance(from: i!, to: j!)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public subscript(i: Index?) -> Unicode.UTF16.CodeUnit {
+    return self[i!]
+  }
+}
+
+// backward compatibility for index interchange.
+extension String.UTF8View {
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public func index(after i: Index?) -> Index {
+    return index(after: i!)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public func index(_ i: Index?, offsetBy n: Int) -> Index {
+    return index(i!, offsetBy: n)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+  public func distance(from i: Index?, to j: Index?) -> Int {
+    return distance(from: i!, to: j!)
+  }
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
+  public subscript(i: Index?) -> Unicode.UTF8.CodeUnit {
+    return self[i!]
+  }
+}
+
+//===--- String/Substring Slicing Support ---------------------------------===//
+/// In Swift 3.2, in the absence of type context,
+///
+///     someString[someString.startIndex..<someString.endIndex]
+///
+/// was deduced to be of type `String`.  Therefore have a more-specific
+/// Swift-3-only `subscript` overload on `String` (and `Substring`) that
+/// continues to produce `String`.
+extension String {
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: Range<Index>) -> String {
+    _boundsCheck(bounds)
+    return String(Substring(_slice: Slice(base: self, bounds: bounds)))
+  }
+
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: ClosedRange<Index>) -> String {
+    let r = bounds.relative(to: self)
+    _boundsCheck(r)
+    return String(Substring(_slice: Slice(
+          base: self,
+          bounds: r)))
+  }
+}
+
+
+//===--- Slicing Support --------------------------------------------------===//
+// In Swift 3.2, in the absence of type context,
+//
+//   someString.unicodeScalars[
+//     someString.unicodeScalars.startIndex
+//     ..< someString.unicodeScalars.endIndex]
+//
+// was deduced to be of type `String.UnicodeScalarView`.  Provide a
+// more-specific Swift-3-only `subscript` overload that continues to produce
+// `String.UnicodeScalarView`.
+extension String.UnicodeScalarView {
+  private subscript(_bounds bounds: Range<Index>) -> String.UnicodeScalarView {
+    let rawSubRange: Range<Int> =
+      _toCoreIndex(bounds.lowerBound)..<_toCoreIndex(bounds.upperBound)
+    return String.UnicodeScalarView(
+      _guts._extractSlice(rawSubRange),
+      coreOffset: bounds.lowerBound.encodedOffset)
+  }
+
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: Range<Index>) -> String.UnicodeScalarView {
+    return self[_bounds: bounds]
+  }
+
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: ClosedRange<Index>) -> String.UnicodeScalarView {
+    return self[_bounds: bounds.relative(to: self)]
+  }
+}
+
+//===--- Slicing Support --------------------------------------------------===//
+// In Swift 3.2, in the absence of type context,
+//
+//   someString.utf16[someString.utf16.startIndex..<someString.utf16.endIndex]
+//
+// was deduced to be of type `String.UTF16View`.  Provide a more-specific
+// Swift-3-only `subscript` overload that continues to produce
+// `String.UTF16View`.
+extension String.UTF16View {
+  private subscript(_bounds bounds: Range<Index>) -> String.UTF16View {
+    return String.UTF16View(
+      _guts,
+      offset: _internalIndex(at: bounds.lowerBound.encodedOffset),
+      length: bounds.upperBound.encodedOffset - bounds.lowerBound.encodedOffset)
+  }
+
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: Range<Index>) -> String.UTF16View {
+    return self[_bounds: bounds]
+  }
+
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: ClosedRange<Index>) -> String.UTF16View {
+    return self[_bounds: bounds.relative(to: self)]
+  }
+}
+
+//===--- Slicing Support --------------------------------------------------===//
+/// In Swift 3.2, in the absence of type context,
+///
+///   someString.utf8[someString.utf8.startIndex..<someString.utf8.endIndex]
+///
+/// was deduced to be of type `String.UTF8View`.  Provide a more-specific
+/// Swift-3-only `subscript` overload that continues to produce
+/// `String.UTF8View`.
+extension String.UTF8View {
+  private subscript(_bounds bounds: Range<Index>) -> String.UTF8View {
+    let wholeString = String(_guts)
+    let legacyPartialCharacters = (
+      (self._legacyPartialCharacters.start &&
+        bounds.lowerBound.encodedOffset == 0) ||
+      bounds.lowerBound.samePosition(in: wholeString) == nil,
+      (self._legacyPartialCharacters.end &&
+        bounds.upperBound.encodedOffset == _guts.count) ||
+      bounds.upperBound.samePosition(in: wholeString) == nil)
+
+    if bounds.upperBound.transcodedOffset == 0 {
+      return String.UTF8View(
+        _guts._extractSlice(
+        bounds.lowerBound.encodedOffset..<bounds.upperBound.encodedOffset),
+        legacyOffsets: (bounds.lowerBound.transcodedOffset, 0),
+        legacyPartialCharacters: legacyPartialCharacters)
+    }
+
+    let b0 = bounds.upperBound.utf8Buffer!.first!
+    let scalarLength8 = (~b0).leadingZeroBitCount
+    let scalarLength16 = scalarLength8 == 4 ? 2 : 1
+    let coreEnd = bounds.upperBound.encodedOffset + scalarLength16
+    return String.UTF8View(
+      _guts._extractSlice(bounds.lowerBound.encodedOffset..<coreEnd),
+      legacyOffsets: (
+        bounds.lowerBound.transcodedOffset,
+        bounds.upperBound.transcodedOffset - scalarLength8),
+      legacyPartialCharacters: legacyPartialCharacters)
+  }
+  
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: Range<Index>) -> String.UTF8View {
+    return self[_bounds: bounds]
+  }
+  
+
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: ClosedRange<Index>) -> String.UTF8View {
+    return self[_bounds: bounds.relative(to: self)]
+  }
+}
+
+@available(swift,deprecated: 5.0, renamed: "Unicode.UTF8")
+public typealias UTF8 = Unicode.UTF8
+@available(swift, deprecated: 5.0, renamed: "Unicode.UTF16")
+public typealias UTF16 = Unicode.UTF16
+@available(swift, deprecated: 5.0, renamed: "Unicode.UTF32")
+public typealias UTF32 = Unicode.UTF32
+@available(swift, obsoleted: 5.0, renamed: "Unicode.Scalar")
+public typealias UnicodeScalar = Unicode.Scalar
+
+
+// popFirst() is only present when a collection is its own subsequence. This was
+// dropped in Swift 4.
+extension String {
+  @available(swift, deprecated: 3.2, obsoleted: 4, message: "Please use 'first', 'dropFirst()', or 'Substring.popFirst()'.")
+  public mutating func popFirst() -> String.Element? {
+    guard !isEmpty else { return nil }
+    let element = first!
+    let nextIdx = self.index(after: self.startIndex)
+    self = String(self[nextIdx...])
+    return element
+  }
+}
+
+extension String.UnicodeScalarView {
+  @available(swift, deprecated: 3.2, obsoleted: 4, message: "Please use 'first', 'dropFirst()', or 'Substring.UnicodeScalarView.popFirst()'.")
+  public mutating func popFirst() -> String.UnicodeScalarView.Element? {
+    guard !isEmpty else { return nil }
+    let element = first!
+    let nextIdx = self.index(after: self.startIndex)
+    self = String(self[nextIdx...]).unicodeScalars
+    return element
+  }
+}
+
+extension String.UTF16View : _CustomPlaygroundQuickLookable {
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "UTF16View.customPlaygroundQuickLook will be removed in Swift 5.0")
+  public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+    return .text(description)
+  }
+}
+
+extension String.UTF8View : _CustomPlaygroundQuickLookable {
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "UTF8View.customPlaygroundQuickLook will be removed in Swift 5.0")
+  public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+    return .text(description)
+  }
+}
+
+extension StringProtocol {
+  @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UTF8View.Index")
+  public typealias UTF8Index = UTF8View.Index
+  @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UTF16View.Index")
+  public typealias UTF16Index = UTF16View.Index
+  @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UnicodeScalarView.Index")
+  public typealias UnicodeScalarIndex = UnicodeScalarView.Index
+}
+
+extension Substring {
+  /// A view of a string's contents as a collection of characters.
+  ///
+  /// Previous versions of Swift provided this view since String
+  /// itself was not a collection. String is now a collection of
+  /// characters, so this type is now just an alias for String.
+  @available(swift, deprecated: 3.2, obsoleted: 5.0, message: "Please use Substring directly")
+  public typealias CharacterView = Substring
+
+  /// A view of the string's contents as a collection of characters.
+  @available(swift, deprecated: 3.2, obsoleted: 5.0, message: "Please use Substring directly")
+  public var characters: Substring {
+    get {
+      return self
+    }
+    set {
+      self = newValue
+    }
+  }
+
+  /// Applies the given closure to a mutable view of the string's characters.
+  ///
+  /// Previous versions of Swift provided this view since String
+  /// itself was not a collection. String is now a collection of
+  /// characters, so this type is now just an alias for String.
+  @available(swift, deprecated: 3.2/*, obsoleted: 5.0*/, message: "Please mutate the Substring directly")
+  public mutating func withMutableCharacters<R>(
+    _ body: (inout Substring) -> R
+  ) -> R {
+    return body(&self)
+  }
+  
+  private func _boundsCheck(_ range: Range<Index>) {
+    _precondition(range.lowerBound >= startIndex,
+      "String index range is out of bounds")
+    _precondition(range.upperBound <= endIndex,
+      "String index range is out of bounds")
+  }
+  
+  @available(swift, obsoleted: 4)
+  public subscript(bounds: ClosedRange<Index>) -> String {
+    return String(self[bounds.relative(to: self)])
+  }
+}
+
+extension Substring : _CustomPlaygroundQuickLookable {
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "Substring.customPlaygroundQuickLook will be removed in Swift 5.0")
+  public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+    return String(self).customPlaygroundQuickLook
+  }
+}
+
+extension Collection {
+  // FIXME: <rdar://problem/34142121>
+  // This typealias should be removed as it predates the source compatibility
+  // guarantees of Swift 3, but it cannot due to a bug.
+  @available(*, unavailable, renamed: "Iterator")
+  public typealias Generator = Iterator
+
+  @available(swift, deprecated: 3.2, obsoleted: 5.0, renamed: "Element")
+  public typealias _Element = Element
+
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+  public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T) -> Index {
+    return index(i, offsetBy: Int(n))
+  }
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+  public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T) {
+    return formIndex(&i, offsetBy: Int(n))
+  }
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+  public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T, limitedBy limit: Index) -> Index? {
+    return index(i, offsetBy: Int(n), limitedBy: limit)
+  }
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+  public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T, limitedBy limit: Index) -> Bool {
+    return formIndex(&i, offsetBy: Int(n), limitedBy: limit)
+  }
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int")
+  public func distance<T: BinaryInteger>(from start: Index, to end: Index) -> T {
+    return numericCast(distance(from: start, to: end) as Int)
+  }
+}
+
+
+extension UnsafeMutablePointer {
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "initialize(repeating:count:)")
+  public func initialize(to newValue: Pointee, count: Int = 1) { 
+    initialize(repeating: newValue, count: count)
+  }
+
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, message: "the default argument to deinitialize(count:) has been removed, please specify the count explicitly") 
+  @discardableResult
+  public func deinitialize() -> UnsafeMutableRawPointer {
+    return deinitialize(count: 1)
+  }
+  
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
+  public func deallocate(capacity _: Int) { 
+    self.deallocate()
+  }
+
+  /// Initializes memory starting at this pointer's address with the elements
+  /// of the given collection.
+  ///
+  /// The region of memory starting at this pointer and covering `source.count`
+  /// instances of the pointer's `Pointee` type must be uninitialized or
+  /// `Pointee` must be a trivial type. After calling `initialize(from:)`, the
+  /// region is initialized.
+  ///
+  /// - Parameter source: A collection of elements of the pointer's `Pointee`
+  ///   type.
+  // This is fundamentally unsafe since collections can underreport their count.
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "it will be removed in Swift 5.0.  Please use 'UnsafeMutableBufferPointer.initialize(from:)' instead")
+  public func initialize<C : Collection>(from source: C)
+    where C.Element == Pointee {
+    let buf = UnsafeMutableBufferPointer(start: self, count: numericCast(source.count))
+    var (remainders,writtenUpTo) = source._copyContents(initializing: buf)
+    // ensure that exactly rhs.count elements were written
+    _precondition(remainders.next() == nil, "rhs underreported its count")
+    _precondition(writtenUpTo == buf.endIndex, "rhs overreported its count")
+  }
+}
+
+extension UnsafeRawPointer : _CustomPlaygroundQuickLookable {
+  internal var summary: String {
+    let ptrValue = UInt64(
+      bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
+    return ptrValue == 0
+    ? "UnsafeRawPointer(nil)"
+    : "UnsafeRawPointer(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
+  }
+
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnsafeRawPointer.customPlaygroundQuickLook will be removed in a future Swift version")
+  public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+    return .text(summary)
+  }
+}
+
+extension UnsafeMutableRawPointer : _CustomPlaygroundQuickLookable {
+  private var summary: String {
+    let ptrValue = UInt64(
+      bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
+    return ptrValue == 0
+    ? "UnsafeMutableRawPointer(nil)"
+    : "UnsafeMutableRawPointer(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
+  }
+
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnsafeMutableRawPointer.customPlaygroundQuickLook will be removed in a future Swift version")
+  public var customPlaygroundQuickLook: _PlaygroundQuickLook {
+    return .text(summary)
+  }
+}
+
+extension UnsafePointer: _CustomPlaygroundQuickLookable {
+  private var summary: String {
+    let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
+    return ptrValue == 0 
+    ? "UnsafePointer(nil)" 
+    : "UnsafePointer(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
+  }
+
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnsafePointer.customPlaygroundQuickLook will be removed in a future Swift version")
+  public var customPlaygroundQuickLook: PlaygroundQuickLook {
+    return .text(summary)
+  }
+}
+
+extension UnsafeMutablePointer: _CustomPlaygroundQuickLookable {
+  private var summary: String {
+    let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
+    return ptrValue == 0 
+    ? "UnsafeMutablePointer(nil)" 
+    : "UnsafeMutablePointer(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
+  }
+
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "UnsafeMutablePointer.customPlaygroundQuickLook will be removed in a future Swift version")
+  public var customPlaygroundQuickLook: PlaygroundQuickLook {
+    return .text(summary)
+  }
+}
+
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "UnsafeBufferPointer.Iterator")
+public typealias UnsafeBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "UnsafeRawBufferPointer.Iterator")
+public typealias UnsafeRawBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
+@available(*, deprecated/*, obsoleted: 5.0*/, renamed: "UnsafeRawBufferPointer.Iterator")
+public typealias UnsafeMutableRawBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
+
+extension UnsafeMutableRawPointer {
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "allocate(byteCount:alignment:)")
+  public static func allocate(
+    bytes size: Int, alignedTo alignment: Int
+  ) -> UnsafeMutableRawPointer {
+    return UnsafeMutableRawPointer.allocate(byteCount: size, alignment: alignment)
+  }
+  
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "deallocate()", message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
+  public func deallocate(bytes _: Int, alignedTo _: Int) { 
+    self.deallocate()
+  }
+
+  @available(swift, deprecated: 4.1, obsoleted: 5.0, renamed: "copyMemory(from:byteCount:)")
+  public func copyBytes(from source: UnsafeRawPointer, count: Int) {
+    copyMemory(from: source, byteCount: count)
+  }
+
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "initializeMemory(as:repeating:count:)")
+  @discardableResult
+  public func initializeMemory<T>(
+    as type: T.Type, at offset: Int = 0, count: Int = 1, to repeatedValue: T
+  ) -> UnsafeMutablePointer<T> { 
+    return (self + offset * MemoryLayout<T>.stride).initializeMemory(
+      as: type, repeating: repeatedValue, count: count)
+  }
+
+  @available(*, deprecated/*, obsoleted: 5.0*/, message: "it will be removed in Swift 5.0.  Please use 'UnsafeMutableRawBufferPointer.initialize(from:)' instead")
+  @discardableResult
+  public func initializeMemory<C : Collection>(
+    as type: C.Element.Type, from source: C
+  ) -> UnsafeMutablePointer<C.Element> {
+    // TODO: Optimize where `C` is a `ContiguousArrayBuffer`.
+    // Initialize and bind each element of the container.
+    var ptr = self
+    for element in source {
+      ptr.initializeMemory(as: C.Element.self, repeating: element, count: 1)
+      ptr += MemoryLayout<C.Element>.stride
+    }
+    return UnsafeMutablePointer(_rawValue)
+  }
+}
+
+extension UnsafeMutableRawBufferPointer {
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "allocate(byteCount:alignment:)")
+  public static func allocate(count: Int) -> UnsafeMutableRawBufferPointer { 
+    return UnsafeMutableRawBufferPointer.allocate(
+      byteCount: count, alignment: MemoryLayout<UInt>.alignment)
+  }
+
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "copyMemory(from:)")
+  public func copyBytes(from source: UnsafeRawBufferPointer) {
+    copyMemory(from: source)
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// The following overloads of flatMap are carefully crafted to allow the code
+// like the following:
+//   ["hello"].flatMap { $0 }
+// return an array of strings without any type context in Swift 3 mode, at the
+// same time allowing the following code snippet to compile:
+//   [0, 1].flatMap { x in
+//     if String(x) == "foo" { return "bar" } else { return nil }
+//   }
+// Note that the second overload is declared on a more specific protocol.
+// See: test/stdlib/StringFlatMap.swift for tests.
+extension Sequence {
+  @available(swift, deprecated: 4.1/*, obsoleted: 5.0*/, renamed: "compactMap(_:)",
+    message: "Please use compactMap(_:) for the case where closure returns an optional value")
+  public func flatMap<ElementOfResult>(
+    _ transform: (Element) throws -> ElementOfResult?
+  ) rethrows -> [ElementOfResult] {
+    return try _compactMap(transform)
+  }
+
+  @available(swift, obsoleted: 4)
+  public func flatMap(
+    _ transform: (Element) throws -> String
+  ) rethrows -> [String] {
+    return try map(transform)
+  }
+}
+
+extension Collection {
+  @available(swift, deprecated: 4.1, obsoleted: 5.0, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
+  public func flatMap(
+    _ transform: (Element) throws -> String?
+  ) rethrows -> [String] {
+    return try _compactMap(transform)
+  }
+}
+
+extension String.Index {
+  @available(swift, deprecated: 3.2, obsoleted: 4.0)
+  public init(_position: Int) {
+    self.init(encodedOffset: _position)
+  }
+
+  @available(swift, deprecated: 3.2, obsoleted: 4.0)
+  public init(_codeUnitOffset: Int) {
+    self.init(encodedOffset: _codeUnitOffset)
+  }
+
+  @available(swift, deprecated: 3.2, obsoleted: 4.0)
+  public var _utf16Index: Int {
+    return self.encodedOffset
+  }
+
+  @available(swift, deprecated: 3.2, obsoleted: 4.0)
+  public var _offset: Int {
+    return self.encodedOffset
+  }
+}
+
+// backward compatibility for index interchange.
+extension Optional where Wrapped == String.Index {
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+  public static func ..<(
+    lhs: String.Index?, rhs: String.Index?
+  ) -> Range<String.Index> {
+    return lhs! ..< rhs!
+  }
+
+  @available(swift, obsoleted: 4.0, message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
+  public static func ...(
+    lhs: String.Index?, rhs: String.Index?
+  ) -> ClosedRange<String.Index> {
+    return lhs! ... rhs!
+  }
+}
+
+extension Zip2Sequence {
+  @available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Sequence1.Iterator")
+  public typealias Stream1 = Sequence1.Iterator
+  @available(*, deprecated/*, obsoleted: 5.0*/, renamed: "Sequence2.Iterator")
+  public typealias Stream2 = Sequence2.Iterator
+}
+
+
+//===--- QuickLooks -------------------------------------------------------===//
+
+/// The sum of types that can be used as a Quick Look representation.
+///
+/// The `PlaygroundQuickLook` protocol is deprecated, and will be removed from
+/// the standard library in a future Swift release. To customize the logging of
+/// your type in a playground, conform to the
+/// `CustomPlaygroundDisplayConvertible` protocol, which does not use the
+/// `PlaygroundQuickLook` enum.
+///
+/// If you need to provide a customized playground representation in Swift 4.0
+/// or Swift 3.2 or earlier, use a conditional compilation block:
+///
+///     #if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
+///         // With Swift 4.1 and later (including Swift 3.3 and later), use
+///         // the CustomPlaygroundDisplayConvertible protocol.
+///     #else
+///         // With Swift 4.0 and Swift 3.2 and earlier, use PlaygroundQuickLook
+///         // and the CustomPlaygroundQuickLookable protocol.
+///     #endif
+@available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
+public typealias PlaygroundQuickLook = _PlaygroundQuickLook
+
+@_frozen // rdar://problem/38719739 - needed by LLDB
+public enum _PlaygroundQuickLook {
+  case text(String)
+  case int(Int64)
+  case uInt(UInt64)
+  case float(Float32)
+  case double(Float64)
+  case image(Any)
+  case sound(Any)
+  case color(Any)
+  case bezierPath(Any)
+  case attributedString(Any)
+  case rectangle(Float64, Float64, Float64, Float64)
+  case point(Float64, Float64)
+  case size(Float64, Float64)
+  case bool(Bool)
+  case range(Int64, Int64)
+  case view(Any)
+  case sprite(Any)
+  case url(String)
+  case _raw([UInt8], String)
+}
+
+// Maintain old `keys` and `values` types in Swift 3 mode.
+extension Dictionary {
+  /// A collection containing just the keys of the dictionary.
+  ///
+  /// When iterated over, keys appear in this collection in the same order as
+  /// they occur in the dictionary's key-value pairs. Each key in the keys
+  /// collection has a unique value.
+  ///
+  ///     let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
+  ///     print(countryCodes)
+  ///     // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
+  ///
+  ///     for k in countryCodes.keys {
+  ///         print(k)
+  ///     }
+  ///     // Prints "BR"
+  ///     // Prints "JP"
+  ///     // Prints "GH"
+  @available(swift, obsoleted: 4.0)
+  public var keys: LazyMapCollection<[Key: Value], Key> {
+    return self.lazy.map { $0.key }
+  }
+
+  /// A collection containing just the values of the dictionary.
+  ///
+  /// When iterated over, values appear in this collection in the same order as
+  /// they occur in the dictionary's key-value pairs.
+  ///
+  ///     let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
+  ///     print(countryCodes)
+  ///     // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
+  ///
+  ///     for v in countryCodes.values {
+  ///         print(v)
+  ///     }
+  ///     // Prints "Brazil"
+  ///     // Prints "Japan"
+  ///     // Prints "Ghana"
+  @available(swift, obsoleted: 4.0)
+  public var values: LazyMapCollection<[Key: Value], Value> {
+    return self.lazy.map { $0.value }
+  }
+
+  @available(swift, obsoleted: 4.0)
+  public func filter(
+    _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
+  ) rethrows -> [Element] {
+    var result: [Element] = []
+    for x in self {
+      if try isIncluded(x) {
+        result.append(x)
+      }
+    }
+    return result
+  }
+}
+
+extension Set {
+  @available(swift, obsoleted: 4.0)
+  public func filter(
+    _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
+  ) rethrows -> [Element] {
+    var result: [Element] = []
+    for x in self {
+      if try isIncluded(x) {
+        result.append(x)
+      }
+    }
+    return result
+  }  
+}
+
+extension _PlaygroundQuickLook {
+  /// Creates a new Quick Look for the given instance.
+  ///
+  /// If the dynamic type of `subject` conforms to
+  /// `CustomPlaygroundQuickLookable`, the result is found by calling its
+  /// `customPlaygroundQuickLook` property. Otherwise, the result is
+  /// synthesized by the language. In some cases, the synthesized result may
+  /// be `.text(String(reflecting: subject))`.
+  ///
+  /// - Note: If the dynamic type of `subject` has value semantics, subsequent
+  ///   mutations of `subject` will not observable in the Quick Look. In
+  ///   general, though, the observability of such mutations is unspecified.
+  ///
+  /// - Parameter subject: The instance to represent with the resulting Quick
+  ///   Look.
+  @available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version.")
+  public init(reflecting subject: Any) {
+    if let customized = subject as? CustomPlaygroundQuickLookable {
+      self = customized.customPlaygroundQuickLook
+    }
+    else if let customized = subject as? _DefaultCustomPlaygroundQuickLookable {
+      self = customized._defaultCustomPlaygroundQuickLook
+    }
+    else {
+      if let q = Mirror.quickLookObject(subject) {
+        self = q
+      }
+      else {
+        self = .text(String(reflecting: subject))
+      }
+    }
+  }
+}
+
+/// A type that explicitly supplies its own playground Quick Look.
+///
+/// The `CustomPlaygroundQuickLookable` protocol is deprecated, and will be
+/// removed from the standard library in a future Swift release. To customize
+/// the logging of your type in a playground, conform to the
+/// `CustomPlaygroundDisplayConvertible` protocol.
+///
+/// If you need to provide a customized playground representation in Swift 4.0
+/// or Swift 3.2 or earlier, use a conditional compilation block:
+///
+///     #if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
+///         // With Swift 4.1 and later (including Swift 3.3 and later),
+///         // conform to CustomPlaygroundDisplayConvertible.
+///         extension MyType: CustomPlaygroundDisplayConvertible { /*...*/ }
+///     #else
+///         // Otherwise, on Swift 4.0 and Swift 3.2 and earlier,
+///         // conform to CustomPlaygroundQuickLookable.
+///         extension MyType: CustomPlaygroundQuickLookable { /*...*/ }
+///     #endif
+@available(*, deprecated/*, obsoleted: 5.0*/, message: "CustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
+public typealias CustomPlaygroundQuickLookable = _CustomPlaygroundQuickLookable
+
+public protocol _CustomPlaygroundQuickLookable {
+  /// A custom playground Quick Look for this instance.
+  ///
+  /// If this type has value semantics, the `PlaygroundQuickLook` instance
+  /// should be unaffected by subsequent mutations.
+  var customPlaygroundQuickLook: _PlaygroundQuickLook { get }
+}
+
+// Double-underscored real version allows us to keep using this in AppKit while
+// warning for non-SDK use. This is probably overkill but it doesn't cost
+// anything.
+@available(*, deprecated/*, obsoleted: 5.0*/, message: "_DefaultCustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
+public typealias _DefaultCustomPlaygroundQuickLookable = __DefaultCustomPlaygroundQuickLookable
+
+public protocol __DefaultCustomPlaygroundQuickLookable {
+  var _defaultCustomPlaygroundQuickLook: _PlaygroundQuickLook { get }
+}
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index 2d500fd..68397a4 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -459,168 +459,6 @@
   }
 }
 
-//===--- QuickLooks -------------------------------------------------------===//
-
-/// The sum of types that can be used as a Quick Look representation.
-///
-/// The `PlaygroundQuickLook` protocol is deprecated, and will be removed from
-/// the standard library in a future Swift release. To customize the logging of
-/// your type in a playground, conform to the
-/// `CustomPlaygroundDisplayConvertible` protocol, which does not use the
-/// `PlaygroundQuickLook` enum.
-///
-/// If you need to provide a customized playground representation in Swift 4.0
-/// or Swift 3.2 or earlier, use a conditional compilation block:
-///
-///     #if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
-///         // With Swift 4.1 and later (including Swift 3.3 and later), use
-///         // the CustomPlaygroundDisplayConvertible protocol.
-///     #else
-///         // With Swift 4.0 and Swift 3.2 and earlier, use PlaygroundQuickLook
-///         // and the CustomPlaygroundQuickLookable protocol.
-///     #endif
-@_frozen // rdar://problem/38719739 - needed by LLDB
-@available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
-public enum PlaygroundQuickLook {
-  /// Plain text.
-  case text(String)
-
-  /// An integer numeric value.
-  case int(Int64)
-
-  /// An unsigned integer numeric value.
-  case uInt(UInt64)
-
-  /// A single precision floating-point numeric value.
-  case float(Float32)
-
-  /// A double precision floating-point numeric value.
-  case double(Float64)
-
-  // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
-  /// An image.
-  case image(Any)
-
-  // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
-  /// A sound.
-  case sound(Any)
-
-  // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
-  /// A color.
-  case color(Any)
-
-  // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
-  /// A bezier path.
-  case bezierPath(Any)
-
-  // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
-  /// An attributed string.
-  case attributedString(Any)
-
-  // FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
-  /// A rectangle.
-  case rectangle(Float64, Float64, Float64, Float64)
-
-  // FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
-  /// A point.
-  case point(Float64, Float64)
-
-  // FIXME: Uses explicit coordinates to avoid coupling a particular Cocoa type.
-  /// A size.
-  case size(Float64, Float64)
-
-  /// A boolean value.
-  case bool(Bool)
-
-  // FIXME: Uses explicit values to avoid coupling a particular Cocoa type.
-  /// A range.
-  case range(Int64, Int64)
-
-  // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
-  /// A GUI view.
-  case view(Any)
-
-  // FIXME: Uses an Any to avoid coupling a particular Cocoa type.
-  /// A graphical sprite.
-  case sprite(Any)
-
-  /// A Uniform Resource Locator.
-  case url(String)
-
-  /// Raw data that has already been encoded in a format the IDE understands.
-  case _raw([UInt8], String)
-}
-
-extension PlaygroundQuickLook {
-  /// Creates a new Quick Look for the given instance.
-  ///
-  /// If the dynamic type of `subject` conforms to
-  /// `CustomPlaygroundQuickLookable`, the result is found by calling its
-  /// `customPlaygroundQuickLook` property. Otherwise, the result is
-  /// synthesized by the language. In some cases, the synthesized result may
-  /// be `.text(String(reflecting: subject))`.
-  ///
-  /// - Note: If the dynamic type of `subject` has value semantics, subsequent
-  ///   mutations of `subject` will not observable in the Quick Look. In
-  ///   general, though, the observability of such mutations is unspecified.
-  ///
-  /// - Parameter subject: The instance to represent with the resulting Quick
-  ///   Look.
-  @available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version.")
-  public init(reflecting subject: Any) {
-    if let customized = subject as? CustomPlaygroundQuickLookable {
-      self = customized.customPlaygroundQuickLook
-    }
-    else if let customized = subject as? _DefaultCustomPlaygroundQuickLookable {
-      self = customized._defaultCustomPlaygroundQuickLook
-    }
-    else {
-      if let q = Mirror.quickLookObject(subject) {
-        self = q
-      }
-      else {
-        self = .text(String(reflecting: subject))
-      }
-    }
-  }
-}
-
-/// A type that explicitly supplies its own playground Quick Look.
-///
-/// The `CustomPlaygroundQuickLookable` protocol is deprecated, and will be
-/// removed from the standard library in a future Swift release. To customize
-/// the logging of your type in a playground, conform to the
-/// `CustomPlaygroundDisplayConvertible` protocol.
-///
-/// If you need to provide a customized playground representation in Swift 4.0
-/// or Swift 3.2 or earlier, use a conditional compilation block:
-///
-///     #if swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
-///         // With Swift 4.1 and later (including Swift 3.3 and later),
-///         // conform to CustomPlaygroundDisplayConvertible.
-///         extension MyType: CustomPlaygroundDisplayConvertible { /*...*/ }
-///     #else
-///         // Otherwise, on Swift 4.0 and Swift 3.2 and earlier,
-///         // conform to CustomPlaygroundQuickLookable.
-///         extension MyType: CustomPlaygroundQuickLookable { /*...*/ }
-///     #endif
-@available(*, deprecated, message: "CustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
-public protocol CustomPlaygroundQuickLookable {
-  /// A custom playground Quick Look for this instance.
-  ///
-  /// If this type has value semantics, the `PlaygroundQuickLook` instance
-  /// should be unaffected by subsequent mutations.
-  var customPlaygroundQuickLook: PlaygroundQuickLook { get }
-}
-
-
-// A workaround for <rdar://problem/26182650>
-// FIXME(ABI)#50 (Dynamic Dispatch for Class Extensions) though not if it moves out of stdlib.
-@available(*, deprecated, message: "_DefaultCustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
-public protocol _DefaultCustomPlaygroundQuickLookable {
-  var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook { get }
-}
-
 //===--- General Utilities ------------------------------------------------===//
 // This component could stand alone, but is used in Mirror's public interface.
 
diff --git a/stdlib/public/core/Mirrors.swift.gyb b/stdlib/public/core/Mirrors.swift.gyb
index 3c23082..26414ae 100644
--- a/stdlib/public/core/Mirrors.swift.gyb
+++ b/stdlib/public/core/Mirrors.swift.gyb
@@ -44,11 +44,11 @@
   }
 }
 
-extension ${Type[0]} : CustomPlaygroundQuickLookable {
+extension ${Type[0]} : _CustomPlaygroundQuickLookable {
   /// A custom playground Quick Look for the `${Type[0]}` instance.
   @inlinable // FIXME(sil-serialize-all)
   @available(*, deprecated, message: "${Type[0]}.customPlaygroundQuickLook will be removed in a future Swift version")
-  public var customPlaygroundQuickLook: PlaygroundQuickLook {
+  public var customPlaygroundQuickLook: _PlaygroundQuickLook {
     return ${Type[1]}(${Type[2]})
   }
 }
diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift
index dc1f10b..5eceea4 100644
--- a/stdlib/public/core/MutableCollection.swift
+++ b/stdlib/public/core/MutableCollection.swift
@@ -10,14 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-/// A type that provides subscript access to its elements.
-///
-/// In most cases, it's best to ignore this protocol and use the
-/// `MutableCollection` protocol instead, because it has a more complete
-/// interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0.  Please use 'MutableCollection' instead")
-public typealias MutableIndexable = MutableCollection
-
 /// A collection that supports subscript assignment.
 ///
 /// Collections that conform to `MutableCollection` gain the ability to
diff --git a/stdlib/public/core/NewtypeWrapper.swift b/stdlib/public/core/NewtypeWrapper.swift
index 5024c9d..c9493a5 100644
--- a/stdlib/public/core/NewtypeWrapper.swift
+++ b/stdlib/public/core/NewtypeWrapper.swift
@@ -13,9 +13,10 @@
 /// An implementation detail used to implement support importing
 /// (Objective-)C entities marked with the swift_newtype Clang
 /// attribute.
-public protocol _SwiftNewtypeWrapper : RawRepresentable { }
+public protocol _SwiftNewtypeWrapper
+: RawRepresentable, _HasCustomAnyHashableRepresentation { }
 
-extension _SwiftNewtypeWrapper where Self: Hashable, Self.RawValue : Hashable {
+extension _SwiftNewtypeWrapper where Self: Hashable, Self.RawValue: Hashable {
   /// The hash value.
   @inlinable
   public var hashValue: Int {
@@ -31,6 +32,70 @@
   public func hash(into hasher: inout Hasher) {
     hasher.combine(rawValue)
   }
+
+  @inlinable // FIXME(sil-serialize-all)
+  public func _rawHashValue(seed: (UInt64, UInt64)) -> Int {
+    return rawValue._rawHashValue(seed: seed)
+  }
+}
+
+extension _SwiftNewtypeWrapper {
+  public func _toCustomAnyHashable() -> AnyHashable? {
+    return nil
+  }
+}
+
+extension _SwiftNewtypeWrapper where Self: Hashable, Self.RawValue: Hashable {
+  public func _toCustomAnyHashable() -> AnyHashable? {
+    return AnyHashable(_box: _NewtypeWrapperAnyHashableBox(self))
+  }
+}
+
+internal struct _NewtypeWrapperAnyHashableBox<Base>: _AnyHashableBox
+where Base: _SwiftNewtypeWrapper & Hashable, Base.RawValue: Hashable {
+  var _value: Base
+
+  init(_ value: Base) {
+    self._value = value
+  }
+
+  var _canonicalBox: _AnyHashableBox {
+    return (_value.rawValue as AnyHashable)._box._canonicalBox
+  }
+
+  func _isEqual(to other: _AnyHashableBox) -> Bool? {
+    _preconditionFailure("_isEqual called on non-canonical AnyHashable box")
+  }
+
+  var _hashValue: Int {
+    _preconditionFailure("_hashValue called on non-canonical AnyHashable box")
+  }
+
+  func _hash(into hasher: inout Hasher) {
+    _preconditionFailure("_hash(into:) called on non-canonical AnyHashable box")
+  }
+
+  func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+    _preconditionFailure("_rawHashValue(_seed:) called on non-canonical AnyHashable box")
+  }
+
+  var _base: Any { return _value }
+
+  func _unbox<T: Hashable>() -> T? {
+    return _value as? T ?? _value.rawValue as? T
+  }
+
+  func _downCastConditional<T>(into result: UnsafeMutablePointer<T>) -> Bool {
+    if let value = _value as? T {
+      result.initialize(to: value)
+      return true
+    }
+    if let value = _value.rawValue as? T {
+      result.initialize(to: value)
+      return true
+    }
+    return false
+  }
 }
 
 #if _runtime(_ObjC)
diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift
index 327cdde..4c7787a 100644
--- a/stdlib/public/core/Policy.swift
+++ b/stdlib/public/core/Policy.swift
@@ -283,221 +283,6 @@
 ///     // Prints "nil"
 public typealias AnyClass = AnyObject.Type
 
-/// A type that supports standard bitwise arithmetic operators.
-///
-/// Types that conform to the `BitwiseOperations` protocol implement operators
-/// for bitwise arithmetic. The integer types in the standard library all
-/// conform to `BitwiseOperations` by default. When you use bitwise operators
-/// with an integer, you perform operations on the raw data bits that store
-/// the integer's value.
-///
-/// In the following examples, the binary representation of any values are
-/// shown in a comment to the right, like this:
-///
-///     let x: UInt8 = 5        // 0b00000101
-///
-/// Here are the required operators for the `BitwiseOperations` protocol:
-///
-/// - The bitwise OR operator (`|`) returns a value that has each bit set to
-///   `1` where *one or both* of its arguments had that bit set to `1`. This
-///   is equivalent to the union of two sets. For example:
-///
-///         let x: UInt8 = 5        // 0b00000101
-///         let y: UInt8 = 14       // 0b00001110
-///         let z = x | y           // 0b00001111
-///
-///   Performing a bitwise OR operation with a value and `allZeros` always
-///   returns the same value.
-///
-///         print(x | .allZeros)    // 0b00000101
-///         // Prints "5"
-///
-/// - The bitwise AND operator (`&`) returns a value that has each bit set to
-///   `1` where *both* of its arguments had that bit set to `1`. This is
-///   equivalent to the intersection of two sets. For example:
-///
-///         let x: UInt8 = 5        // 0b00000101
-///         let y: UInt8 = 14       // 0b00001110
-///         let z = x & y           // 0b00000100
-///
-///   Performing a bitwise AND operation with a value and `allZeros` always
-///   returns `allZeros`.
-///
-///         print(x & .allZeros)    // 0b00000000
-///         // Prints "0"
-///
-/// - The bitwise XOR operator (`^`), or exclusive OR operator, returns a value
-///   that has each bit set to `1` where *one or the other but not both* of
-///   its operators has that bit set to `1`. This is equivalent to the
-///   symmetric difference of two sets. For example:
-///
-///         let x: UInt8 = 5        // 0b00000101
-///         let y: UInt8 = 14       // 0b00001110
-///         let z = x ^ y           // 0b00001011
-///
-///   Performing a bitwise XOR operation with a value and `allZeros` always
-///   returns the same value.
-///
-///         print(x ^ .allZeros)    // 0b00000101
-///         // Prints "5"
-///
-/// - The bitwise NOT operator (`~`) is a prefix operator that returns a value
-///   where all the bits of its argument are flipped: Bits that are `1` in the
-///   argument are `0` in the result, and bits that are `0` in the argument
-///   are `1` in the result. This is equivalent to the inverse of a set. For
-///   example:
-///
-///         let x: UInt8 = 5        // 0b00000101
-///         let notX = ~x           // 0b11111010
-///
-///   Performing a bitwise NOT operation on `allZeros` returns a value with
-///   every bit set to `1`.
-///
-///         let allOnes = ~UInt8.allZeros   // 0b11111111
-///
-/// The `OptionSet` protocol uses a raw value that conforms to
-/// `BitwiseOperations` to provide mathematical set operations like
-/// `union(_:)`, `intersection(_:)` and `contains(_:)` with O(1) performance.
-///
-/// Conforming to the BitwiseOperations Protocol
-/// ============================================
-///
-/// To make your custom type conform to `BitwiseOperations`, add a static
-/// `allZeros` property and declare the four required operator functions. Any
-/// type that conforms to `BitwiseOperations`, where `x` is an instance of the
-/// conforming type, must satisfy the following conditions:
-///
-/// - `x | Self.allZeros == x`
-/// - `x ^ Self.allZeros == x`
-/// - `x & Self.allZeros == .allZeros`
-/// - `x & ~Self.allZeros == x`
-/// - `~x == x ^ ~Self.allZeros`
-@available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use FixedWidthInteger protocol instead")
-public typealias BitwiseOperations = _BitwiseOperations
-
-public protocol _BitwiseOperations {
-  /// Returns the intersection of bits set in the two arguments.
-  ///
-  /// The bitwise AND operator (`&`) returns a value that has each bit set to
-  /// `1` where *both* of its arguments had that bit set to `1`. This is
-  /// equivalent to the intersection of two sets. For example:
-  ///
-  ///     let x: UInt8 = 5        // 0b00000101
-  ///     let y: UInt8 = 14       // 0b00001110
-  ///     let z = x & y           // 0b00000100
-  ///
-  /// Performing a bitwise AND operation with a value and `allZeros` always
-  /// returns `allZeros`.
-  ///
-  ///     print(x & .allZeros)    // 0b00000000
-  ///     // Prints "0"
-  ///
-  /// - Complexity: O(1).
-  static func & (lhs: Self, rhs: Self) -> Self
-
-  /// Returns the union of bits set in the two arguments.
-  ///
-  /// The bitwise OR operator (`|`) returns a value that has each bit set to
-  /// `1` where *one or both* of its arguments had that bit set to `1`. For
-  /// example:
-  ///
-  ///     let x: UInt8 = 5        // 0b00000101
-  ///     let y: UInt8 = 14       // 0b00001110
-  ///     let z = x | y           // 0b00001111
-  ///
-  /// Performing a bitwise OR operation with a value and `allZeros` always
-  /// returns the same value.
-  ///
-  ///     print(x | .allZeros)    // 0b00000101
-  ///     // Prints "5"
-  ///
-  /// - Complexity: O(1).
-  static func | (lhs: Self, rhs: Self) -> Self
-
-  /// Returns the bits that are set in exactly one of the two arguments.
-  ///
-  /// The bitwise XOR operator (`^`), or exclusive OR operator, returns a value
-  /// that has each bit set to `1` where *one or the other but not both* of
-  /// its operators has that bit set to `1`. This is equivalent to the
-  /// symmetric difference of two sets. For example:
-  ///
-  ///     let x: UInt8 = 5        // 0b00000101
-  ///     let y: UInt8 = 14       // 0b00001110
-  ///     let z = x ^ y           // 0b00001011
-  ///
-  /// Performing a bitwise XOR with a value and `allZeros` always returns the
-  /// same value:
-  ///
-  ///     print(x ^ .allZeros)    // 0b00000101
-  ///     // Prints "5"
-  ///
-  /// - Complexity: O(1).
-  static func ^ (lhs: Self, rhs: Self) -> Self
-
-  /// Returns the inverse of the bits set in the argument.
-  ///
-  /// The bitwise NOT operator (`~`) is a prefix operator that returns a value
-  /// in which all the bits of its argument are flipped: Bits that are `1` in the
-  /// argument are `0` in the result, and bits that are `0` in the argument
-  /// are `1` in the result. This is equivalent to the inverse of a set. For
-  /// example:
-  ///
-  ///     let x: UInt8 = 5        // 0b00000101
-  ///     let notX = ~x           // 0b11111010
-  ///
-  /// Performing a bitwise NOT operation on `allZeros` returns a value with
-  /// every bit set to `1`.
-  ///
-  ///     let allOnes = ~UInt8.allZeros   // 0b11111111
-  ///
-  /// - Complexity: O(1).
-  static prefix func ~ (x: Self) -> Self
-
-  /// The empty bitset.
-  @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0 or init() of a type conforming to FixedWidthInteger")
-  static var allZeros: Self { get }
-}
-
-extension _BitwiseOperations {
-  /// Calculates the union of bits sets in the two arguments and stores the result
-  /// in the first argument.
-  ///
-  /// - Parameters:
-  ///   - lhs: A value to update with the union of bits set in the two arguments.
-  ///   - rhs: Another value.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4.1)
-  public static func |= (lhs: inout Self, rhs: Self) {
-    lhs = lhs | rhs
-  }
-
-  /// Calculates the intersections of bits sets in the two arguments and stores
-  /// the result in the first argument.
-  ///
-  /// - Parameters:
-  ///   - lhs: A value to update with the intersections of bits set in the two
-  ///     arguments.
-  ///   - rhs: Another value.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4.1)
-  public static func &= (lhs: inout Self, rhs: Self) {
-    lhs = lhs & rhs
-  }
-
-  /// Calculates the bits that are set in exactly one of the two arguments and
-  /// stores the result in the first argument.
-  ///
-  /// - Parameters:
-  ///   - lhs: A value to update with the bits that are set in exactly one of the
-  ///     two arguments.
-  ///   - rhs: Another value.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4.1)
-  public static func ^= (lhs: inout Self, rhs: Self) {
-    lhs = lhs ^ rhs
-  }
-}
-
 //===----------------------------------------------------------------------===//
 // Standard pattern matching forms
 //===----------------------------------------------------------------------===//
diff --git a/stdlib/public/core/PrefixWhile.swift b/stdlib/public/core/PrefixWhile.swift
index a05419f..4c80aac 100644
--- a/stdlib/public/core/PrefixWhile.swift
+++ b/stdlib/public/core/PrefixWhile.swift
@@ -311,10 +311,3 @@
       _base: self.elements, predicate: predicate)
   }
 }
-
-@available(*, deprecated, renamed: "LazyDropWhileSequence.Iterator")
-public typealias LazyPrefixWhileIterator<T> = LazyPrefixWhileSequence<T>.Iterator where T: Sequence
-@available(*, deprecated, renamed: "LazyDropWhileCollection.Index")
-public typealias LazyPrefixWhileIndex<T> = LazyPrefixWhileCollection<T>.Index where T: Collection
-@available(*, deprecated, renamed: "LazyPrefixWhileCollection")
-public typealias LazyPrefixWhileBidirectionalCollection<T> = LazyPrefixWhileCollection<T> where T: BidirectionalCollection
diff --git a/stdlib/public/core/Random.swift b/stdlib/public/core/Random.swift
index 1dea1b4..97398e0 100644
--- a/stdlib/public/core/Random.swift
+++ b/stdlib/public/core/Random.swift
@@ -90,13 +90,14 @@
   /// Returns a random value that is less than the given upper bound.
   ///
   /// - Parameter upperBound: The upper bound for the randomly generated value.
+  ///   Must be non-zero.
   /// - Returns: A random value of `T` in the range `0..<upperBound`. Every
   ///   value in the range `0..<upperBound` is equally likely to be returned.
   @inlinable
   public mutating func next<T: FixedWidthInteger & UnsignedInteger>(
     upperBound: T
   ) -> T {
-    guard upperBound != 0 else { return 0 }
+    _precondition(upperBound != 0, "upperBound cannot be zero.")
     let tmp = (T.max % upperBound) + 1
     let range = tmp == upperBound ? 0 : tmp
     var random: T = 0
diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift
index 8e9f34e..8a28a20 100644
--- a/stdlib/public/core/RandomAccessCollection.swift
+++ b/stdlib/public/core/RandomAccessCollection.swift
@@ -12,14 +12,6 @@
 
 /// A collection that supports efficient random-access index traversal.
 ///
-/// In most cases, it's best to ignore this protocol and use the
-/// `RandomAccessCollection` protocol instead, because it has a more complete
-/// interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0.  Please use 'RandomAccessCollection' instead")
-public typealias RandomAccessIndexable = RandomAccessCollection
-
-/// A collection that supports efficient random-access index traversal.
-///
 /// Random-access collections can move indices any distance and 
 /// measure the distance between indices in O(1) time. Therefore, the
 /// fundamental difference between random-access and bidirectional collections
diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift
index 7993857..1741c5a 100644
--- a/stdlib/public/core/Range.swift
+++ b/stdlib/public/core/Range.swift
@@ -278,16 +278,7 @@
   }
 }
 
-extension Range where Bound: Strideable, Bound.Stride : SignedInteger {
-  /// Now that Range is conditionally a collection when Bound: Strideable,
-  /// CountableRange is no longer needed. This is a deprecated initializer
-  /// for any remaining uses of Range(countableRange).
-  @available(*,deprecated: 4.2, 
-    message: "CountableRange is now Range. No need to convert any more.")
-  public init(_ other: Range<Bound>) {
-    self = other
-  }  
-  
+extension Range where Bound: Strideable, Bound.Stride : SignedInteger {  
   /// Creates an instance equivalent to the given `ClosedRange`.
   ///
   /// - Parameter other: A closed range to convert to a `Range` instance.
@@ -849,6 +840,7 @@
     return self[startIndex...]
   }
 }
+
 extension MutableCollection {
   @inlinable
   public subscript<R: RangeExpression>(r: R) -> SubSequence
@@ -907,8 +899,12 @@
   }
 }
 
+// Note: this is not for compatibility only, it is considered a useful
+// shorthand. TODO: Add documentation
 public typealias CountableRange<Bound: Strideable> = Range<Bound>
   where Bound.Stride : SignedInteger
 
+// Note: this is not for compatibility only, it is considered a useful
+// shorthand. TODO: Add documentation
 public typealias CountablePartialRangeFrom<Bound: Strideable> = PartialRangeFrom<Bound>
   where Bound.Stride : SignedInteger
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift b/stdlib/public/core/RangeReplaceableCollection.swift
index 367647c..5b6b259 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift
+++ b/stdlib/public/core/RangeReplaceableCollection.swift
@@ -14,15 +14,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-/// A type that supports replacement of an arbitrary subrange of elements with
-/// the elements of another collection.
-///
-/// In most cases, it's best to ignore this protocol and use the
-/// `RangeReplaceableCollection` protocol instead, because it has a more
-/// complete interface.
-@available(*, deprecated, message: "it will be removed in Swift 4.0.  Please use 'RandomAccessCollection' instead")
-public typealias RangeReplaceableIndexable = RangeReplaceableCollection
-
 /// A collection that supports replacement of an arbitrary subrange of elements
 /// with the elements of another collection.
 ///
diff --git a/stdlib/public/core/ReflectionMirror.swift b/stdlib/public/core/ReflectionMirror.swift
index 4806ae6..6e516f4 100644
--- a/stdlib/public/core/ReflectionMirror.swift
+++ b/stdlib/public/core/ReflectionMirror.swift
@@ -55,7 +55,7 @@
 
 internal func _getClassPlaygroundQuickLook(
   _ object: AnyObject
-) -> PlaygroundQuickLook? {
+) -> _PlaygroundQuickLook? {
   if _is(object, kindOf: "NSNumber") {
     let number: _NSNumber = unsafeBitCast(object, to: _NSNumber.self)
     switch UInt8(number.objCType[0]) {
@@ -149,7 +149,7 @@
     self._defaultDescendantRepresentation = .generated
   }
   
-  internal static func quickLookObject(_ subject: Any) -> PlaygroundQuickLook? {
+  internal static func quickLookObject(_ subject: Any) -> _PlaygroundQuickLook? {
 #if _runtime(_ObjC)
     let object = _getQuickLookObject(subject)
     return object.flatMap(_getClassPlaygroundQuickLook)
diff --git a/stdlib/public/core/Reverse.swift b/stdlib/public/core/Reverse.swift
index b40bcae..4ba2e82 100644
--- a/stdlib/public/core/Reverse.swift
+++ b/stdlib/public/core/Reverse.swift
@@ -307,9 +307,3 @@
     return ReversedCollection(_base: elements).lazy
   }
 }
-
-// @available(*, deprecated, renamed: "ReversedCollection")
-public typealias ReversedRandomAccessCollection<T: RandomAccessCollection> = ReversedCollection<T>
-
-// @available(*, deprecated, renamed: "ReversedCollection.Index")
-public typealias ReversedIndex<T: BidirectionalCollection> = ReversedCollection<T>
diff --git a/stdlib/public/core/SequenceAlgorithms.swift b/stdlib/public/core/SequenceAlgorithms.swift
index 9850b26..583f071 100644
--- a/stdlib/public/core/SequenceAlgorithms.swift
+++ b/stdlib/public/core/SequenceAlgorithms.swift
@@ -749,39 +749,6 @@
     return try _compactMap(transform)
   }
 
-  /// Returns an array containing the non-`nil` results of calling the given
-  /// transformation with each element of this sequence.
-  ///
-  /// Use this method to receive an array of nonoptional values when your
-  /// transformation produces an optional value.
-  ///
-  /// In this example, note the difference in the result of using `map` and
-  /// `flatMap` with a transformation that returns an optional `Int` value.
-  ///
-  ///     let possibleNumbers = ["1", "2", "three", "///4///", "5"]
-  ///
-  ///     let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
-  ///     // [1, 2, nil, nil, 5]
-  ///
-  ///     let flatMapped: [Int] = possibleNumbers.flatMap { str in Int(str) }
-  ///     // [1, 2, 5]
-  ///
-  /// - Parameter transform: A closure that accepts an element of this
-  ///   sequence as its argument and returns an optional value.
-  /// - Returns: An array of the non-`nil` results of calling `transform`
-  ///   with each element of the sequence.
-  ///
-  /// - Complexity: O(*m* + *n*), where *m* is the length of this sequence
-  ///   and *n* is the length of the result.
-  @inline(__always)
-  @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
-    message: "Please use compactMap(_:) for the case where closure returns an optional value")
-  public func flatMap<ElementOfResult>(
-    _ transform: (Element) throws -> ElementOfResult?
-  ) rethrows -> [ElementOfResult] {
-    return try _compactMap(transform)
-  }
-
   // The implementation of flatMap accepting a closure with an optional result.
   // Factored out into a separate functions in order to be used in multiple
   // overloads.
diff --git a/stdlib/public/core/Set.swift b/stdlib/public/core/Set.swift
index 7551284..40b4258 100644
--- a/stdlib/public/core/Set.swift
+++ b/stdlib/public/core/Set.swift
@@ -503,6 +503,61 @@
   }
 }
 
+extension Set: _HasCustomAnyHashableRepresentation {
+  public func _toCustomAnyHashable() -> AnyHashable? {
+    return AnyHashable(_box: _SetAnyHashableBox(self))
+  }
+}
+
+internal struct _SetAnyHashableBox<Element: Hashable>: _AnyHashableBox {
+  internal let _value: Set<Element>
+  internal let _canonical: Set<AnyHashable>
+
+  internal init(_ value: Set<Element>) {
+    self._value = value
+    self._canonical = value as Set<AnyHashable>
+  }
+
+  internal var _base: Any {
+    return _value
+  }
+
+  internal var _canonicalBox: _AnyHashableBox {
+    return _SetAnyHashableBox<AnyHashable>(_canonical)
+  }
+
+  internal func _isEqual(to other: _AnyHashableBox) -> Bool? {
+    guard let other = other as? _SetAnyHashableBox<AnyHashable> else {
+      return nil
+    }
+    return _canonical == other._value
+  }
+
+  internal var _hashValue: Int {
+    return _canonical.hashValue
+  }
+
+  internal func _hash(into hasher: inout Hasher) {
+    _canonical.hash(into: &hasher)
+  }
+
+  func _rawHashValue(_seed: (UInt64, UInt64)) -> Int {
+    return _canonical._rawHashValue(seed: _seed)
+  }
+
+  internal func _unbox<T: Hashable>() -> T? {
+    return _value as? T
+  }
+
+  internal func _downCastConditional<T>(
+    into result: UnsafeMutablePointer<T>
+  ) -> Bool {
+    guard let value = _value as? T else { return false }
+    result.initialize(to: value)
+    return true
+  }
+}
+
 extension Set: SetAlgebra {
 
   /// Inserts the given element in the set if it is not already present.
@@ -4003,20 +4058,6 @@
     return remove(at: startIndex)
   }
 
-  @inlinable
-  @available(swift, obsoleted: 4.0)
-  public func filter(
-    _ isIncluded: (Element) throws -> Bool, obsoletedInSwift4: () = ()
-  ) rethrows -> [Element] {
-    var result: [Element] = []
-    for x in self {
-      if try isIncluded(x) {
-        result.append(x)
-      }
-    }
-    return result
-  }
-
   /// The total number of elements that the set can contain without
   /// allocating new storage.
   @inlinable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/Slice.swift b/stdlib/public/core/Slice.swift
index 57c8f54..139a52b 100644
--- a/stdlib/public/core/Slice.swift
+++ b/stdlib/public/core/Slice.swift
@@ -467,27 +467,3 @@
     }
   }
 }
-
-@available(*, deprecated, renamed: "Slice")
-public typealias BidirectionalSlice<T> = Slice<T> where T : BidirectionalCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias RandomAccessSlice<T> = Slice<T> where T : RandomAccessCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias RangeReplaceableSlice<T> = Slice<T> where T : RangeReplaceableCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias RangeReplaceableBidirectionalSlice<T> = Slice<T> where T : RangeReplaceableCollection & BidirectionalCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias RangeReplaceableRandomAccessSlice<T> = Slice<T> where T : RangeReplaceableCollection & RandomAccessCollection
-
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableSlice<T> = Slice<T> where T : MutableCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & BidirectionalCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RandomAccessCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableRangeReplaceableSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableRangeReplaceableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & BidirectionalCollection
-@available(*, deprecated, renamed: "Slice")
-public typealias MutableRangeReplaceableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & RandomAccessCollection
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
deleted file mode 100644
index d2baf42..0000000
--- a/stdlib/public/core/StringCharacterView.swift
+++ /dev/null
@@ -1,97 +0,0 @@
-//===--- StringCharacterView.swift - String's Collection of Characters ----===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-//  String is-not-a Sequence or Collection, but it exposes a
-//  collection of characters.
-//
-//===----------------------------------------------------------------------===//
-
-// FIXME(ABI)#70 : The character string view should have a custom iterator type
-// to allow performance optimizations of linear traversals.
-
-import SwiftShims
-
-extension String {
-  /// A view of a string's contents as a collection of characters.
-  ///
-  /// Previous versions of Swift provided this view since String
-  /// itself was not a collection. String is now a collection of
-  /// characters, so this type is now just an alias for String.
-  @available(swift, deprecated: 3.2, obsoleted: 5.0, 
-    message: "Please use String directly")
-  public typealias CharacterView = String
-
-  /// A view of the string's contents as a collection of characters.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, obsoleted: 5.0, 
-    message: "Please use String directly")
-  public var characters: String {
-    get {
-      return self
-    }
-    set {
-      self = newValue
-    }
-  }
-
-  /// Applies the given closure to a mutable view of the string's characters.
-  ///
-  /// Previous versions of Swift provided this view since String
-  /// itself was not a collection. String is now a collection of
-  /// characters, so this type is now just an alias for String.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, obsoleted: 5.0, 
-    message: "Please mutate the String directly")
-  public mutating func withMutableCharacters<R>(
-    _ body: (inout String) -> R
-  ) -> R {
-    return body(&self)
-  }
-}
-
-extension Substring {
-  /// A view of a string's contents as a collection of characters.
-  ///
-  /// Previous versions of Swift provided this view since String
-  /// itself was not a collection. String is now a collection of
-  /// characters, so this type is now just an alias for String.
-  @available(swift, deprecated: 3.2, obsoleted: 5.0, 
-    message: "Please use Substring directly")
-  public typealias CharacterView = Substring
-
-  /// A view of the string's contents as a collection of characters.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, obsoleted: 5.0,
-    message: "Please use Substring directly")
-  public var characters: Substring {
-    get {
-      return self
-    }
-    set {
-      self = newValue
-    }
-  }
-
-  /// Applies the given closure to a mutable view of the string's characters.
-  ///
-  /// Previous versions of Swift provided this view since String
-  /// itself was not a collection. String is now a collection of
-  /// characters, so this type is now just an alias for String.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, obsoleted: 5.0, 
-    message: "Please mutate the Substring directly")
-  public mutating func withMutableCharacters<R>(
-    _ body: (inout Substring) -> R
-  ) -> R {
-    return body(&self)
-  }
-}
diff --git a/stdlib/public/core/StringGraphemeBreaking.swift b/stdlib/public/core/StringGraphemeBreaking.swift
index 9a021ad..2f4c67b 100644
--- a/stdlib/public/core/StringGraphemeBreaking.swift
+++ b/stdlib/public/core/StringGraphemeBreaking.swift
@@ -255,7 +255,7 @@
 
     // Nuclear option: copy out the rest of the string into a contiguous buffer.
     let longStart = UnsafeMutablePointer<UInt16>.allocate(capacity: count)
-    defer { longStart.deallocate(capacity: count) }
+    defer { longStart.deallocate() }
     self._copy(into: UnsafeMutableBufferPointer(start: longStart, count: count))
     return UTF16._measureFirstExtendedGraphemeCluster(
       in: UnsafeBufferPointer(start: longStart, count: count))
@@ -282,7 +282,7 @@
 
     // Nuclear option: copy out the rest of the string into a contiguous buffer.
     let longStart = UnsafeMutablePointer<UInt16>.allocate(capacity: count)
-    defer { longStart.deallocate(capacity: count) }
+    defer { longStart.deallocate() }
     self._copy(into: UnsafeMutableBufferPointer(start: longStart, count: count))
     return UTF16._measureLastExtendedGraphemeCluster(
       in: UnsafeBufferPointer(start: longStart, count: count))
diff --git a/stdlib/public/core/StringIndex.swift b/stdlib/public/core/StringIndex.swift
index 39c6f62..6a45ed9 100644
--- a/stdlib/public/core/StringIndex.swift
+++ b/stdlib/public/core/StringIndex.swift
@@ -139,64 +139,3 @@
     return Int(truncatingIfNeeded: _compoundOffset & 0x3)
   }
 }
-
-// SPI for Foundation
-extension String.Index {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2)
-  @available(swift, obsoleted: 4.0)
-  public // SPI(Foundation)
-  init(_position: Int) {
-    self.init(encodedOffset: _position)
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2)
-  @available(swift, obsoleted: 4.0)
-  public // SPI(Foundation)
-  init(_codeUnitOffset: Int) {
-    self.init(encodedOffset: _codeUnitOffset)
-  }
-
-  /// The integer offset of this index in UTF-16 code units.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2)
-  @available(swift, obsoleted: 4.0)
-  public // SPI(Foundation)
-  var _utf16Index: Int {
-    return self.encodedOffset
-  }
-
-  /// The integer offset of this index in UTF-16 code units.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2)
-  @available(swift, obsoleted: 4.0)
-  public // SPI(Foundation)
-  var _offset: Int {
-    return self.encodedOffset
-  }
-}
-
-
-// backward compatibility for index interchange.
-extension Optional where Wrapped == String.Index {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
-  public static func ..<(
-    lhs: String.Index?, rhs: String.Index?
-  ) -> Range<String.Index> {
-    return lhs! ..< rhs!
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
-  public static func ...(
-    lhs: String.Index?, rhs: String.Index?
-  ) -> ClosedRange<String.Index> {
-    return lhs! ... rhs!
-  }
-}
diff --git a/stdlib/public/core/StringProtocol.swift b/stdlib/public/core/StringProtocol.swift
index 0dacf5a..8842115 100644
--- a/stdlib/public/core/StringProtocol.swift
+++ b/stdlib/public/core/StringProtocol.swift
@@ -126,18 +126,6 @@
   }
 }
 
-extension StringProtocol {
-  //@available(swift, deprecated: 3.2, obsoleted: 4.0, message: "Please use the StringProtocol itself")
-  //public var characters: Self { return self }
-
-  @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UTF8View.Index")
-  public typealias UTF8Index = UTF8View.Index
-  @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UTF16View.Index")
-  public typealias UTF16Index = UTF16View.Index
-  @available(swift, deprecated: 3.2, obsoleted: 4.0, renamed: "UnicodeScalarView.Index")
-  public typealias UnicodeScalarIndex = UnicodeScalarView.Index
-}
-
 /// A protocol that provides fast access to a known representation of String.
 ///
 /// Can be used to specialize generic functions that would otherwise end up
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift b/stdlib/public/core/StringRangeReplaceableCollection.swift
index 000ac08..f943a22 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift
@@ -65,17 +65,6 @@
     self = other.description
   }
 
-  // The defaulted argument prevents this initializer from satisfies the
-  // LosslessStringConvertible conformance.  You can satisfy a protocol
-  // requirement with something that's not yet available, but not with
-  // something that has become unavailable. Without this, the code won't
-  // compile as Swift 4.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4, message: "String.init(_:String) is no longer failable")
-  public init?(_ other: String, obsoletedInSwift4: () = ()) {
-    self.init(other._guts)
-  }
-
   /// The position of the first character in a nonempty string.
   ///
   /// In an empty string, `startIndex` is equal to `endIndex`.
@@ -522,37 +511,6 @@
 }
 
 //===----------------------------------------------------------------------===//
-// The following overloads of flatMap are carefully crafted to allow the code
-// like the following:
-//   ["hello"].flatMap { $0 }
-// return an array of strings without any type context in Swift 3 mode, at the
-// same time allowing the following code snippet to compile:
-//   [0, 1].flatMap { x in
-//     if String(x) == "foo" { return "bar" } else { return nil }
-//   }
-// Note that the second overload is declared on a more specific protocol.
-// See: test/stdlib/StringFlatMap.swift for tests.
-extension Sequence {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public func flatMap(
-    _ transform: (Element) throws -> String
-  ) rethrows -> [String] {
-    return try map(transform)
-  }
-}
-
-extension Collection {
-  @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
-    message: "Please use compactMap(_:) for the case where closure returns an optional value")
-  @inline(__always)
-  public func flatMap(
-    _ transform: (Element) throws -> String?
-  ) rethrows -> [String] {
-    return try _compactMap(transform)
-  }
-}
-//===----------------------------------------------------------------------===//
 
 extension Sequence where Element == String {
   @available(*, unavailable, message: "Operator '+' cannot be used to append a String to a sequence of strings")
diff --git a/stdlib/public/core/StringUTF16.swift b/stdlib/public/core/StringUTF16.swift
index e8d31e9..8c8c1f1 100644
--- a/stdlib/public/core/StringUTF16.swift
+++ b/stdlib/public/core/StringUTF16.swift
@@ -294,45 +294,6 @@
   }
 
   /// Creates a string corresponding to the given sequence of UTF-16 code units.
-  ///
-  /// If `utf16` contains unpaired UTF-16 surrogates, the result is `nil`.
-  ///
-  /// You can use this initializer to create a new string from a slice of
-  /// another string's `utf16` view.
-  ///
-  ///     let picnicGuest = "Deserving porcupine"
-  ///     if let i = picnicGuest.utf16.firstIndex(of: 32) {
-  ///         let adjective = String(picnicGuest.utf16[..<i])
-  ///         print(adjective)
-  ///     }
-  ///     // Prints "Optional(Deserving)"
-  ///
-  /// The `adjective` constant is created by calling this initializer with a
-  /// slice of the `picnicGuest.utf16` view.
-  ///
-  /// - Parameter utf16: A UTF-16 code sequence.
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, obsoleted: 4.0)
-  public init?(_ utf16: UTF16View) {
-    // Attempt to recover the whole string, the better to implement the actual
-    // Swift 3.1 semantics, which are not as documented above!  Full Swift 3.1
-    // semantics may be impossible to preserve in the case of string literals,
-    // since we no longer have access to the length of the original string when
-    // there is no owner and elements are dropped from the end.
-    let wholeString = String(utf16._guts)
-    guard
-      let start = UTF16Index(encodedOffset: utf16._offset)
-        .samePosition(in: wholeString),
-      let end = UTF16Index(encodedOffset: utf16._offset + utf16._length)
-        .samePosition(in: wholeString)
-      else
-    {
-        return nil
-    }
-    self = wholeString[start..<end]
-  }
-
-  /// Creates a string corresponding to the given sequence of UTF-16 code units.
   @inlinable // FIXME(sil-serialize-all)
   @available(swift, introduced: 4.0)
   public init(_ utf16: UTF16View) {
@@ -434,14 +395,6 @@
   }
 }
 
-extension String.UTF16View : CustomPlaygroundQuickLookable {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(*, deprecated, message: "UTF16View.customPlaygroundQuickLook will be removed in a future Swift version")
-  public var customPlaygroundQuickLook: PlaygroundQuickLook {
-    return .text(description)
-  }
-}
-
 extension String.UTF16View.Indices : BidirectionalCollection {
   public typealias Index = String.UTF16View.Index
   public typealias Indices = String.UTF16View.Indices
@@ -534,39 +487,6 @@
   }
 }
 
-// backward compatibility for index interchange.
-extension String.UTF16View {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public func index(after i: Index?) -> Index {
-    return index(after: i!)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public func index(
-    _ i: Index?, offsetBy n: Int) -> Index {
-    return index(i!, offsetBy: n)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
-  public func distance(from i: Index?, to j: Index?) -> Int {
-    return distance(from: i!, to: j!)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public subscript(i: Index?) -> Unicode.UTF16.CodeUnit {
-    return self[i!]
-  }
-}
-
 //===--- Slicing Support --------------------------------------------------===//
 /// In Swift 3.2, in the absence of type context,
 ///
@@ -580,22 +500,7 @@
 
   @inlinable // FIXME(sil-serialize-all)
   @available(swift, introduced: 4)
-  public subscript(r: Range<Index>) -> String.UTF16View.SubSequence {
-    return String.UTF16View.SubSequence(self, _bounds: r)
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public subscript(bounds: Range<Index>) -> String.UTF16View {
-    return String.UTF16View(
-      _guts,
-      offset: _internalIndex(at: bounds.lowerBound.encodedOffset),
-      length: bounds.upperBound.encodedOffset - bounds.lowerBound.encodedOffset)
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public subscript(bounds: ClosedRange<Index>) -> String.UTF16View {
-    return self[bounds.relative(to: self)]
+  public subscript(bounds: Range<Index>) -> String.UTF16View.SubSequence {
+    return String.UTF16View.SubSequence(self, _bounds: bounds)
   }
 }
diff --git a/stdlib/public/core/StringUTF8.swift b/stdlib/public/core/StringUTF8.swift
index ab76cd2..65b155b 100644
--- a/stdlib/public/core/StringUTF8.swift
+++ b/stdlib/public/core/StringUTF8.swift
@@ -178,7 +178,7 @@
         _guts, range: (n..<count, performBoundsCheck: true),
         ascii: { _ in
           Builtin.unreachable()
-          return Index._UTF8Buffer() },
+          /* return Index._UTF8Buffer() */ },
         utf16: { utf16 in
           var i = utf16.makeIterator()
           return UTF8View._fillBuffer(from: &i) },
@@ -451,38 +451,6 @@
   }
 
   /// Creates a string corresponding to the given sequence of UTF-8 code units.
-  ///
-  /// If `utf8` is an ill-formed UTF-8 code sequence, the result is `nil`.
-  ///
-  /// You can use this initializer to create a new string from a slice of
-  /// another string's `utf8` view.
-  ///
-  ///     let picnicGuest = "Deserving porcupine"
-  ///     if let i = picnicGuest.utf8.firstIndex(of: 32) {
-  ///         let adjective = String(picnicGuest.utf8[..<i])
-  ///         print(adjective)
-  ///     }
-  ///     // Prints "Optional(Deserving)"
-  ///
-  /// The `adjective` constant is created by calling this initializer with a
-  /// slice of the `picnicGuest.utf8` view.
-  ///
-  /// - Parameter utf8: A UTF-8 code sequence.
-  @available(swift, deprecated: 3.2,
-    message: "Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)")
-  @available(swift, obsoleted: 4.0,
-    message: "Please use non-failable String.init(_:UTF8View) instead")
-  public init?(_ utf8: UTF8View) {
-    if utf8.startIndex.transcodedOffset != 0
-      || utf8.endIndex.transcodedOffset != 0
-      || utf8._legacyPartialCharacters.start
-      || utf8._legacyPartialCharacters.end {
-      return nil
-    }
-    self = String(utf8._guts)
-  }
-
-  /// Creates a string corresponding to the given sequence of UTF-8 code units.
   @inlinable // FIXME(sil-serialize-all)
   @available(swift, introduced: 4.0, message:
     "Please use failable String.init?(_:UTF8View) when in Swift 3.2 mode")
@@ -722,47 +690,6 @@
   }
 }
 
-extension String.UTF8View : CustomPlaygroundQuickLookable {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(*, deprecated, message: "UTF8View.customPlaygroundQuickLook will be removed in a future Swift version")
-  public var customPlaygroundQuickLook: PlaygroundQuickLook {
-    return .text(description)
-  }
-}
-
-// backward compatibility for index interchange.
-extension String.UTF8View {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public func index(after i: Index?) -> Index {
-    return index(after: i!)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public func index(_ i: Index?, offsetBy n: Int) -> Index {
-    return index(i!, offsetBy: n)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
-  public func distance(
-    from i: Index?, to j: Index?) -> Int {
-    return distance(from: i!, to: j!)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public subscript(i: Index?) -> Unicode.UTF8.CodeUnit {
-    return self[i!]
-  }
-}
-
 //===--- Slicing Support --------------------------------------------------===//
 /// In Swift 3.2, in the absence of type context,
 ///
@@ -779,42 +706,6 @@
   public subscript(r: Range<Index>) -> String.UTF8View.SubSequence {
     return String.UTF8View.SubSequence(self, _bounds: r)
   }
-
-  @available(swift, obsoleted: 4)
-  public subscript(r: Range<Index>) -> String.UTF8View {
-    let wholeString = String(_guts)
-    let legacyPartialCharacters = (
-      (self._legacyPartialCharacters.start &&
-        r.lowerBound.encodedOffset == 0) ||
-      r.lowerBound.samePosition(in: wholeString) == nil,
-      (self._legacyPartialCharacters.end &&
-        r.upperBound.encodedOffset == _guts.count) ||
-      r.upperBound.samePosition(in: wholeString) == nil)
-
-    if r.upperBound.transcodedOffset == 0 {
-      return String.UTF8View(
-        _guts._extractSlice(
-        r.lowerBound.encodedOffset..<r.upperBound.encodedOffset),
-        legacyOffsets: (r.lowerBound.transcodedOffset, 0),
-        legacyPartialCharacters: legacyPartialCharacters)
-    }
-
-    let b0 = r.upperBound.utf8Buffer!.first!
-    let scalarLength8 = (~b0).leadingZeroBitCount
-    let scalarLength16 = scalarLength8 == 4 ? 2 : 1
-    let coreEnd = r.upperBound.encodedOffset + scalarLength16
-    return String.UTF8View(
-      _guts._extractSlice(r.lowerBound.encodedOffset..<coreEnd),
-      legacyOffsets: (
-        r.lowerBound.transcodedOffset,
-        r.upperBound.transcodedOffset - scalarLength8),
-      legacyPartialCharacters: legacyPartialCharacters)
-  }
-
-  @available(swift, obsoleted: 4)
-  public subscript(bounds: ClosedRange<Index>) -> String.UTF8View {
-    return self[bounds.relative(to: self)]
-  }
 }
 
 extension String.UTF8View {
diff --git a/stdlib/public/core/StringUnicodeScalarView.swift b/stdlib/public/core/StringUnicodeScalarView.swift
index 586a9da..b0c047d 100644
--- a/stdlib/public/core/StringUnicodeScalarView.swift
+++ b/stdlib/public/core/StringUnicodeScalarView.swift
@@ -124,7 +124,7 @@
     public func index(after i: Index) -> Index {
       let offset = _toCoreIndex(i)
       let length: Int = _visitGuts(_guts, args: offset,
-        ascii: { _ -> Int in return 1 },
+        ascii: { (_,_) -> Int in return 1 },
         utf16: { utf16, offset in
           return utf16.unicodeScalarWidth(startingAt: offset) },
         opaque: { opaque, offset in
@@ -140,7 +140,7 @@
     public func index(before i: Index) -> Index {
       let offset = _toCoreIndex(i)
       let length: Int = _visitGuts(_guts, args: offset,
-        ascii: { _ -> Int in return 1 },
+        ascii: { (_,_) -> Int in return 1 },
         utf16: { utf16, offset in
           return utf16.unicodeScalarWidth(endingAt: offset) },
         opaque: { opaque, offset in
@@ -554,46 +554,6 @@
   }
 }
 
-extension String.UnicodeScalarView : CustomPlaygroundQuickLookable {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(*, deprecated, message: "UnicodeScalarView.customPlaygroundQuickLook will be removed in a future Swift version")
-  public var customPlaygroundQuickLook: PlaygroundQuickLook {
-    return .text(description)
-  }
-}
-
-// backward compatibility for index interchange.
-extension String.UnicodeScalarView {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public func index(after i: Index?) -> Index {
-    return index(after: i!)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public func index(_ i: Index?,  offsetBy n: Int) -> Index {
-    return index(i!, offsetBy: n)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
-  public func distance(from i: Index?, to j: Index?) -> Int {
-    return distance(from: i!, to: j!)
-  }
-  @inlinable // FIXME(sil-serialize-all)
-  @available(
-    swift, obsoleted: 4.0,
-    message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public subscript(i: Index?) -> Unicode.Scalar {
-    return self[i!]
-  }
-}
-
 //===--- Slicing Support --------------------------------------------------===//
 /// In Swift 3.2, in the absence of type context,
 ///
@@ -609,35 +569,7 @@
 
   @inlinable // FIXME(sil-serialize-all)
   @available(swift, introduced: 4)
-  public subscript(r: Range<Index>) -> String.UnicodeScalarView.SubSequence {
-    return String.UnicodeScalarView.SubSequence(self, _bounds: r)
-  }
-
-  /// Accesses the Unicode scalar values in the given range.
-  ///
-  /// The example below uses this subscript to access the scalar values up
-  /// to, but not including, the first comma (`","`) in the string.
-  ///
-  ///     let str = "All this happened, more or less."
-  ///     let i = str.unicodeScalars.firstIndex(of: ",")!
-  ///     let substring = str.unicodeScalars[str.unicodeScalars.startIndex ..< i]
-  ///     print(String(substring))
-  ///     // Prints "All this happened"
-  ///
-  /// - Complexity: O(*n*) if the underlying string is bridged from
-  ///   Objective-C, where *n* is the length of the string; otherwise, O(1).
-  @available(swift, obsoleted: 4)
-  public subscript(r: Range<Index>) -> String.UnicodeScalarView {
-    let rawSubRange: Range<Int> =
-      _toCoreIndex(r.lowerBound)..<_toCoreIndex(r.upperBound)
-    return String.UnicodeScalarView(
-      _guts._extractSlice(rawSubRange),
-      coreOffset: r.lowerBound.encodedOffset)
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public subscript(bounds: ClosedRange<Index>) -> String.UnicodeScalarView {
-    return self[bounds.relative(to: self)]
+  public subscript(bounds: Range<Index>) -> String.UnicodeScalarView.SubSequence {
+    return String.UnicodeScalarView.SubSequence(self, _bounds: bounds)
   }
 }
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index f9038b0..2bd5684 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -330,14 +330,6 @@
   }
 }
 
-extension Substring : CustomPlaygroundQuickLookable {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(*, deprecated, message: "Substring.customPlaygroundQuickLook will be removed in a future Swift version")
-  public var customPlaygroundQuickLook: PlaygroundQuickLook {
-    return String(self).customPlaygroundQuickLook
-  }
-}
-
 extension Substring : CustomStringConvertible {
   @inlinable // FIXME(sil-serialize-all)
   public var description: String {
@@ -622,22 +614,6 @@
     return Substring(
       _slice: Slice(base: self, bounds: r))
   }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public subscript(bounds: Range<Index>) -> String {
-    _boundsCheck(bounds)
-    return String(Substring(_slice: Slice(base: self, bounds: bounds)))
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public subscript(bounds: ClosedRange<Index>) -> String {
-    _boundsCheck(bounds)
-    return String(Substring(_slice: Slice(
-          base: self,
-          bounds: bounds.relative(to: self))))
-  }
 }
 
 extension Substring {
@@ -646,46 +622,6 @@
   public subscript(r: Range<Index>) -> Substring {
     return Substring(_slice: _slice[r])
   }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public subscript(bounds: Range<Index>) -> String {
-    return String(Substring(_slice: _slice[bounds]))
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, obsoleted: 4)
-  public subscript(bounds: ClosedRange<Index>) -> String {
-    return self[bounds.relative(to: self)]
-  }
-}
-//===----------------------------------------------------------------------===//
-
-// popFirst() is only present when a collection is its own subsequence. This was
-// dropped in Swift 4.
-extension String {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, obsoleted: 4, message:
-    "Please use 'first', 'dropFirst()', or 'Substring.popFirst()'.")
-  public mutating func popFirst() -> String.Element? {
-    guard !isEmpty else { return nil }
-    let element = first!
-    let nextIdx = self.index(after: self.startIndex)
-    self = String(self[nextIdx...])
-    return element
-  }
-}
-extension String.UnicodeScalarView {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, obsoleted: 4, message:
-    "Please use 'first', 'dropFirst()', or 'Substring.UnicodeScalarView.popFirst()'.")
-  public mutating func popFirst() -> String.UnicodeScalarView.Element? {
-    guard !isEmpty else { return nil }
-    let element = first!
-    let nextIdx = self.index(after: self.startIndex)
-    self = String(self[nextIdx...]).unicodeScalars
-    return element
-  }
 }
 
 // ${'Local Variables'}:
diff --git a/stdlib/public/core/Unicode.swift b/stdlib/public/core/Unicode.swift
index 64ca5d1..768ec85 100644
--- a/stdlib/public/core/Unicode.swift
+++ b/stdlib/public/core/Unicode.swift
@@ -314,9 +314,6 @@
   }
 }
 
-// @available(swift, obsoleted: 4.0, renamed: "Unicode.UTF8")
-public typealias UTF8 = Unicode.UTF8
-
 /// A codec for translating between Unicode scalar values and UTF-16 code
 /// units.
 extension Unicode.UTF16 : UnicodeCodec {
@@ -428,8 +425,6 @@
     processCodeUnit(UInt16(truncatingIfNeeded: s))
   }
 }
-// @available(swift, obsoleted: 4.0, renamed: "Unicode.UTF16")
-public typealias UTF16 = Unicode.UTF16
 
 /// A codec for translating between Unicode scalar values and UTF-32 code
 /// units.
@@ -523,8 +518,6 @@
     processCodeUnit(UInt32(input))
   }
 }
-// @available(swift, obsoleted: 4.0, renamed: "Unicode.UTF32")
-public typealias UTF32 = Unicode.UTF32
 
 /// Translates the given input from one Unicode encoding to another by calling
 /// the given closure.
diff --git a/stdlib/public/core/UnicodeScalar.swift b/stdlib/public/core/UnicodeScalar.swift
index 7d095f6..9691523 100644
--- a/stdlib/public/core/UnicodeScalar.swift
+++ b/stdlib/public/core/UnicodeScalar.swift
@@ -466,6 +466,3 @@
     Builtin.unreachable()
   }
 }
-
-// @available(swift, obsoleted: 4.0, renamed: "Unicode.Scalar")
-public typealias UnicodeScalar = Unicode.Scalar
diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
index f6c7cf7..13c8031 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -667,9 +667,6 @@
   }
 }
 
-@available(*, deprecated, renamed: "UnsafeBufferPointer.Iterator")
-public typealias UnsafeBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
-
 // ${'Local Variables'}:
 // eval: (read-only-mode 1)
 // End:
diff --git a/stdlib/public/core/UnsafePointer.swift.gyb b/stdlib/public/core/UnsafePointer.swift.gyb
index 51d619d..bd9584f 100644
--- a/stdlib/public/core/UnsafePointer.swift.gyb
+++ b/stdlib/public/core/UnsafePointer.swift.gyb
@@ -436,12 +436,6 @@
     Builtin.bindMemory(rawPtr, count._builtinWordValue, Pointee.self)
     return UnsafeMutablePointer(rawPtr)
   }
-  
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
-  public func deallocate(capacity _: Int) { 
-    self.deallocate()
-  }
-
 %  end
 
   /// Deallocates the memory block previously allocated at this pointer.
@@ -485,11 +479,6 @@
   }
 
 %  if mutable:
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "initialize(repeating:count:)")
-  public func initialize(to newValue: Pointee, count: Int = 1) { 
-    initialize(repeating: newValue, count: count)
-  }
-
   /// Initializes this pointer's memory with the specified number of
   /// consecutive copies of the given value.
   ///
@@ -683,28 +672,6 @@
     // }
   }
 
-  /// Initializes memory starting at this pointer's address with the elements
-  /// of the given collection.
-  ///
-  /// The region of memory starting at this pointer and covering `source.count`
-  /// instances of the pointer's `Pointee` type must be uninitialized or
-  /// `Pointee` must be a trivial type. After calling `initialize(from:)`, the
-  /// region is initialized.
-  ///
-  /// - Parameter source: A collection of elements of the pointer's `Pointee`
-  ///   type.
-  // This is fundamentally unsafe since collections can underreport their count.
-  @inlinable
-  @available(*, deprecated, message: "it will be removed in Swift 4.0.  Please use 'UnsafeMutableBufferPointer.initialize(from:)' instead")
-  public func initialize<C : Collection>(from source: C)
-    where C.Element == Pointee {
-    let buf = UnsafeMutableBufferPointer(start: self, count: numericCast(source.count))
-    var (remainders,writtenUpTo) = source._copyContents(initializing: buf)
-    // ensure that exactly rhs.count elements were written
-    _precondition(remainders.next() == nil, "rhs underreported its count")
-    _precondition(writtenUpTo == buf.endIndex, "rhs overreported its count")
-  }
-
   /// Replaces the memory referenced by this pointer with the values
   /// starting at the given pointer, leaving the source memory uninitialized.
   ///
@@ -735,13 +702,6 @@
     // }
   }
   
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, message: "the default argument to deinitialize(count:) has been removed, please specify the count explicitly") 
-  @inlinable
-  @discardableResult
-  public func deinitialize() -> UnsafeMutableRawPointer {
-    return deinitialize(count: 1)
-  }
-  
   /// Deinitializes the specified number of values starting at this pointer.
   ///
   /// The region of memory starting at this pointer and covering `count`
@@ -999,21 +959,6 @@
   }
 }
 
-extension ${Self} : CustomPlaygroundQuickLookable {
-  @inlinable // FIXME(sil-serialize-all)
-  internal var summary: String {
-    let selfType = "${Self}"
-    let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
-    return ptrValue == 0 ? "\(selfType)(nil)" : "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  @available(*, deprecated, message: "${Self}.customPlaygroundQuickLook will be removed in a future Swift version")
-  public var customPlaygroundQuickLook: PlaygroundQuickLook {
-    return .text(summary)
-  }
-}
-
 extension Int {
   /// Creates a new value with the bit pattern of the given pointer.
   ///
diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
index 7abe817..cb3b501 100644
--- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
@@ -263,12 +263,6 @@
 
 extension Unsafe${Mutable}RawBufferPointer {
 %  if mutable:
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "allocate(byteCount:alignment:)")
-  public static func allocate(count: Int) -> UnsafeMutableRawBufferPointer { 
-    return UnsafeMutableRawBufferPointer.allocate(
-      byteCount: count, alignment: MemoryLayout<UInt>.alignment)
-  }
-
   /// Returns a newly allocated buffer with the given size, in bytes.
   ///
   /// The memory referenced by the new buffer is allocated, but not
@@ -374,10 +368,6 @@
     baseAddress!.storeBytes(of: value, toByteOffset: offset, as: T.self)
   }
 
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "copyMemory(from:)")
-  public func copyBytes(from source: UnsafeRawBufferPointer) {
-    copyMemory(from: source)
-  }
   /// Copies the bytes from the given buffer to this buffer's memory.
   ///
   /// If the `source.count` bytes of memory referenced by this buffer are bound
@@ -814,12 +804,6 @@
   return try body(buffer)
 }
 
-// @available(*, deprecated, renamed: "UnsafeRawBufferPointer.Iterator")
-public typealias UnsafeRawBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
-
-// @available(*, deprecated, renamed: "UnsafeRawBufferPointer.Iterator")
-public typealias UnsafeMutableRawBufferPointerIterator<T> = UnsafeBufferPointer<T>.Iterator
-
 // ${'Local Variables'}:
 // eval: (read-only-mode 1)
 // End:
diff --git a/stdlib/public/core/UnsafeRawPointer.swift.gyb b/stdlib/public/core/UnsafeRawPointer.swift.gyb
index 5fc78d8..e52a332 100644
--- a/stdlib/public/core/UnsafeRawPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawPointer.swift.gyb
@@ -426,15 +426,6 @@
 %  end # !mutable
 
 %  if mutable:
-
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "allocate(byteCount:alignment:)")
-  @inlinable
-  public static func allocate(
-    bytes size: Int, alignedTo alignment: Int
-  ) -> UnsafeMutableRawPointer {
-    return UnsafeMutableRawPointer.allocate(byteCount: size, alignment: alignment)
-  }
-
   /// Allocates uninitialized memory with the specified size and alignment.
   ///
   /// You are in charge of managing the allocated memory. Be sure to deallocate
@@ -460,11 +451,6 @@
   }
 %  end # mutable
 
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
-  public func deallocate(bytes _: Int, alignedTo _: Int) { 
-    self.deallocate()
-  }
-
   /// Deallocates the previously allocated memory block referenced by this pointer.
   ///
   /// The memory to be deallocated must be uninitialized or initialized to a
@@ -537,17 +523,7 @@
     return Unsafe${Mutable}Pointer<T>(_rawValue)
   }
 
-%  if mutable:
-
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "initializeMemory(as:repeating:count:)")
-  @discardableResult
-  public func initializeMemory<T>(
-    as type: T.Type, at offset: Int = 0, count: Int = 1, to repeatedValue: T
-  ) -> UnsafeMutablePointer<T> { 
-    return (self + offset * MemoryLayout<T>.stride).initializeMemory(
-      as: type, repeating: repeatedValue, count: count)
-  }
-  
+%  if mutable:  
   /// Initializes the memory referenced by this pointer with the given value,
   /// binds the memory to the value's type, and returns a typed pointer to the
   /// initialized memory.
@@ -665,62 +641,6 @@
     return UnsafeMutablePointer(_rawValue)
   }
 
-  /// Initializes the memory referenced by this pointer with the values of the
-  /// given collection, binds the memory to the values' type, and returns a
-  /// typed pointer to the initialized memory.
-  ///
-  /// The memory referenced by this pointer must be uninitialized or
-  /// initialized to a trivial type, and must be properly aligned for
-  /// accessing `T`.
-  ///
-  /// The following example allocates enough raw memory to hold four instances
-  /// of `Int8`, and then uses the `initializeMemory(as:from:)` method to
-  /// initialize the allocated memory.
-  ///
-  ///     let count = 4
-  ///     let bytesPointer = UnsafeMutableRawPointer.allocate(
-  ///             bytes: count * MemoryLayout<Int8>.stride,
-  ///             alignedTo: MemoryLayout<Int8>.alignment)
-  ///     let values: [Int8] = [1, 2, 3, 4]
-  ///     let int8Pointer = bytesPointer.initializeMemory(
-  ///             as: Int8.self,
-  ///             from: values)
-  ///     // int8Pointer.pointee == 1
-  ///     // (int8Pointer + 3).pointee == 4
-  ///
-  ///     // After using 'int8Pointer':
-  ///     int8Pointer.deallocate(count)
-  ///
-  /// After calling this method on a raw pointer `p`, the region starting at
-  /// `p` and continuing up to `p + count * MemoryLayout<T>.stride` is bound
-  /// to type `T` and initialized. If `T` is a nontrivial type, you must
-  /// eventually deinitialize or move from the values in this region to avoid
-  /// leaks.
-  ///
-  /// - Parameters:
-  ///   - type: The type to bind this memory to.
-  ///   - source: A pointer to the values to copy. If `source` is an
-  ///     `UnsafeBufferPointer` or `UnsafeMutableBufferPointer` instance, the
-  ///     memory region referenced by `source` must not overlap the
-  ///     destination region.
-  /// - Returns: A typed pointer to the memory referenced by this raw pointer.
-  // This is fundamentally unsafe since collections can underreport their count.
-  @inlinable
-  @available(*, deprecated, message: "it will be removed in Swift 4.0.  Please use 'UnsafeMutableRawBufferPointer.initialize(from:)' instead")
-  @discardableResult
-  public func initializeMemory<C : Collection>(
-    as type: C.Element.Type, from source: C
-  ) -> UnsafeMutablePointer<C.Element> {
-    // TODO: Optimize where `C` is a `ContiguousArrayBuffer`.
-    // Initialize and bind each element of the container.
-    var ptr = self
-    for element in source {
-      ptr.initializeMemory(as: C.Element.self, repeating: element, count: 1)
-      ptr += MemoryLayout<C.Element>.stride
-    }
-    return UnsafeMutablePointer(_rawValue)
-  }
-
   /// Initializes the memory referenced by this pointer with the values
   /// starting at the given pointer, binds the memory to the values' type,
   /// deinitializes the source memory, and returns a typed pointer to the
@@ -864,11 +784,6 @@
         /*volatile:*/ false._value)
     }
   }
-
-  @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "copyMemory(from:byteCount:)")
-  public func copyBytes(from source: UnsafeRawPointer, count: Int) {
-    copyMemory(from: source, byteCount: count)
-  }
   
   /// Copies the specified number of bytes from the given raw pointer's memory
   /// into this pointer's memory.
@@ -991,24 +906,6 @@
   }
 }
 
-extension Unsafe${Mutable}RawPointer : CustomPlaygroundQuickLookable {
-  @inlinable // FIXME(sil-serialize-all)
-  @available(*, deprecated, message: "Unsafe${Mutable}RawPointer.customPlaygroundQuickLook will be removed in a future Swift version")
-  internal var summary: String {
-    let selfType = "${Self}"
-    let ptrValue = UInt64(
-      bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
-    return ptrValue == 0
-    ? "\(selfType)(nil)"
-    : "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
-  }
-
-  @inlinable // FIXME(sil-serialize-all)
-  public var customPlaygroundQuickLook: PlaygroundQuickLook {
-    return .text(summary)
-  }
-}
-
 extension OpaquePointer {
   @inlinable
   public init(_ from: Unsafe${Mutable}RawPointer) {
diff --git a/stdlib/public/core/Zip.swift b/stdlib/public/core/Zip.swift
index eb6a6c8..5bb3dc5 100644
--- a/stdlib/public/core/Zip.swift
+++ b/stdlib/public/core/Zip.swift
@@ -74,11 +74,6 @@
   @usableFromInline // FIXME(sil-serialize-all)
   internal let _sequence2: Sequence2
 
-  @available(*, deprecated, renamed: "Sequence1.Iterator")
-  public typealias Stream1 = Sequence1.Iterator
-  @available(*, deprecated, renamed: "Sequence2.Iterator")
-  public typealias Stream2 = Sequence2.Iterator
-
   /// Creates an instance that makes pairs of elements from `sequence1` and
   /// `sequence2`.
   @inlinable // FIXME(sil-serialize-all)
@@ -151,6 +146,3 @@
       _sequence2.makeIterator())
   }
 }
-
-@available(*, deprecated: 4.2, renamed: "Zip2Sequence.Iterator")
-public typealias Zip2Iterator<T, U> = Zip2Sequence<T, U>.Iterator where T: Sequence, U: Sequence
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 626e18f..32c7440 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -2941,6 +2941,12 @@
       return true;
     }
   }
+  // Try to bridge NSError to Error.
+  if (tryDynamicCastNSErrorObjectToValue(sourceValue, destValue, nativeType,
+                                         DynamicCastFlags::Default)) {
+    return true;
+  }
+
   
   return false;
 }
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 07fb3fe..55aeb92 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -160,8 +160,14 @@
         
         auto typeNode = Dem.createNode(nodeKind);
         typeNode->addChild(node, Dem);
-        auto identifier = Dem.createNode(Node::Kind::Identifier, name);
-        typeNode->addChild(identifier, Dem);
+        auto nameNode = Dem.createNode(Node::Kind::Identifier, name);
+        if (type->isSynthesizedRelatedEntity()) {
+          auto relatedName = Dem.createNode(Node::Kind::RelatedEntityDeclName,
+                                    type->getSynthesizedDeclRelatedEntityTag());
+          relatedName->addChild(nameNode, Dem);
+          nameNode = relatedName;
+        }
+        typeNode->addChild(nameNode, Dem);
         node = typeNode;
         
         // Apply generic arguments if the context is generic.
diff --git a/stdlib/public/runtime/ErrorObject.h b/stdlib/public/runtime/ErrorObject.h
index 43358f0..8d4cdfe 100644
--- a/stdlib/public/runtime/ErrorObject.h
+++ b/stdlib/public/runtime/ErrorObject.h
@@ -223,8 +223,17 @@
 SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_SPI
 id _swift_stdlib_bridgeErrorToNSError(SwiftError *errorObject);
 
+/// Attempt to dynamically cast an NSError object to a Swift ErrorType
+/// implementation using the _ObjectiveCBridgeableErrorType protocol or by
+/// putting it directly into an Error existential.
+bool tryDynamicCastNSErrorObjectToValue(HeapObject *object,
+                                        OpaqueValue *dest,
+                                        const Metadata *destType,
+                                        DynamicCastFlags flags);
+
 /// Attempt to dynamically cast an NSError instance to a Swift ErrorType
-/// implementation using the _ObjectiveCBridgeableErrorType protocol.
+/// implementation using the _ObjectiveCBridgeableErrorType protocol or by
+/// putting it directly into an Error existential.
 ///
 /// srcType must be some kind of class metadata.
 bool tryDynamicCastNSErrorToValue(OpaqueValue *dest,
diff --git a/stdlib/public/runtime/ErrorObject.mm b/stdlib/public/runtime/ErrorObject.mm
index d67b4cd..e5b3a39 100644
--- a/stdlib/public/runtime/ErrorObject.mm
+++ b/stdlib/public/runtime/ErrorObject.mm
@@ -462,47 +462,27 @@
 extern "C" const ProtocolDescriptor PROTOCOL_DESCR_SYM(s5Error);
 
 bool
-swift::tryDynamicCastNSErrorToValue(OpaqueValue *dest,
-                                    OpaqueValue *src,
-                                    const Metadata *srcType,
-                                    const Metadata *destType,
-                                    DynamicCastFlags flags) {
+swift::tryDynamicCastNSErrorObjectToValue(HeapObject *object,
+                                          OpaqueValue *dest,
+                                          const Metadata *destType,
+                                          DynamicCastFlags flags) {
   Class NSErrorClass = getNSErrorClass();
-  auto CFErrorTypeID = SWIFT_LAZY_CONSTANT(CFErrorGetTypeID());
 
-  NSError *srcInstance;
-
-  // Is the input type an NSError?
-  switch (srcType->getKind()) {
-  case MetadataKind::Class:
-  case MetadataKind::ObjCClassWrapper:
-    // Native class or ObjC class should be an NSError subclass.
-    if (![srcType->getObjCClassObject() isSubclassOfClass: NSErrorClass])
-      return false;
-    
-    srcInstance = *reinterpret_cast<NSError * const*>(src);
-    
-    // A _SwiftNativeNSError box can always be unwrapped to cast the value back
-    // out as an Error existential.
-    if (!reinterpret_cast<SwiftError*>(srcInstance)->isPureNSError()) {
-      auto theErrorProtocol = &PROTOCOL_DESCR_SYM(s5Error);
-      auto theErrorTy =
-        swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
-                                         nullptr, 1, &theErrorProtocol);
-      return swift_dynamicCast(dest, src, theErrorTy, destType, flags);
-    }
-    
-    break;
-  case MetadataKind::ForeignClass: {
-    // Foreign class should be CFError.
-    CFTypeRef srcInstance = *reinterpret_cast<CFTypeRef *>(src);
-    if (CFGetTypeID(srcInstance) != CFErrorTypeID)
-      return false;
-    break;
-  }
-  // Not a class.
-  default:
+  // The object must be an NSError subclass.
+  if (![reinterpret_cast<id>(object) isKindOfClass: NSErrorClass])
     return false;
+
+  NSError *srcInstance = reinterpret_cast<NSError *>(object);
+
+  // A _SwiftNativeNSError box can always be unwrapped to cast the value back
+  // out as an Error existential.
+  if (!reinterpret_cast<SwiftError*>(srcInstance)->isPureNSError()) {
+    auto theErrorProtocol = &PROTOCOL_DESCR_SYM(s5Error);
+    auto theErrorTy =
+      swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
+                                       nullptr, 1, &theErrorProtocol);
+    return swift_dynamicCast(dest, reinterpret_cast<OpaqueValue *>(&object),
+                             theErrorTy, destType, flags);
   }
 
   // public func Foundation._bridgeNSErrorToError<
@@ -521,19 +501,47 @@
   auto witness = swift_conformsToProtocol(destType,
                                           TheObjectiveCBridgeableError);
 
-  if (!witness)
-    return false;
+  if (witness) {
+    // If so, attempt the bridge.
+    if (bridgeNSErrorToError(srcInstance, dest, destType, witness)) {
+      if (flags & DynamicCastFlags::TakeOnSuccess)
+        objc_release(srcInstance);
+      return true;
+    }
+  }
 
-  // If so, attempt the bridge.
-  SWIFT_CC_PLUSONE_GUARD(objc_retain(srcInstance));
-  if (bridgeNSErrorToError(srcInstance, dest, destType, witness)) {
-    if (flags & DynamicCastFlags::TakeOnSuccess)
-      objc_release(srcInstance);
+  // If the destination is just an Error then we can bridge directly.
+  auto *destTypeExistential = dyn_cast<ExistentialTypeMetadata>(destType);
+  if (destTypeExistential &&
+      destTypeExistential->getRepresentation() == ExistentialTypeRepresentation::Error) {
+    auto destBoxAddr = reinterpret_cast<NSError**>(dest);
+    *destBoxAddr = objc_retain(srcInstance);
     return true;
   }
+
   return false;
 }
 
+bool
+swift::tryDynamicCastNSErrorToValue(OpaqueValue *dest,
+                                    OpaqueValue *src,
+                                    const Metadata *srcType,
+                                    const Metadata *destType,
+                                    DynamicCastFlags flags) {
+  // NSError instances must be class instances, anything else automatically fails.
+  switch (srcType->getKind()) {
+  case MetadataKind::Class:
+  case MetadataKind::ObjCClassWrapper:
+  case MetadataKind::ForeignClass:
+    return tryDynamicCastNSErrorObjectToValue(*reinterpret_cast<HeapObject **>(src),
+                                              dest, destType, flags);
+
+  // Not a class.
+  default:
+    return false;
+  }
+}
+
 SwiftError *
 swift::swift_errorRetain(SwiftError *error) {
   // For now, SwiftError is always objc-refcounted.
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 903511d..70b3580 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -1473,7 +1473,20 @@
         && kind <= ContextDescriptorKind::Type_Last) {
       auto typeA = cast<TypeContextDescriptor>(a);
       auto typeB = cast<TypeContextDescriptor>(b);
-      return strcmp(typeA->Name.get(), typeB->Name.get()) == 0;
+      if (strcmp(typeA->Name.get(), typeB->Name.get()) != 0)
+        return false;
+      
+      // A synthesized entity has to match the related entity tag too.
+      if (typeA->isSynthesizedRelatedEntity()) {
+        if (!typeB->isSynthesizedRelatedEntity())
+          return false;
+        
+        if (typeA->getSynthesizedDeclRelatedEntityTag()
+            != typeB->getSynthesizedDeclRelatedEntityTag())
+          return false;
+      }
+      
+      return true;
     }
     
     // Otherwise, this runtime doesn't know anything about this context kind.
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index a239b0b..be28b62 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -264,14 +264,31 @@
         }
 
         auto nameNode = node->getChild(1);
-        if (nameNode->getKind() == Demangle::Node::Kind::PrivateDeclName)
-          return false;
-
-        if (nameNode->getText() != type->Name.get())
-          return false;
         
-        node = node->getChild(0);
-        break;
+        // Declarations synthesized by the Clang importer get a small tag
+        // string in addition to their name.
+        if (nameNode->getKind() == Demangle::Node::Kind::RelatedEntityDeclName){
+          if (nameNode->getText() != type->getSynthesizedDeclRelatedEntityTag())
+            return false;
+          
+          nameNode = nameNode->getChild(0);
+        } else if (type->isSynthesizedRelatedEntity()) {
+          return false;
+        }
+        
+        // We should only match public or internal declarations with stable
+        // names. The runtime metadata for private declarations would be
+        // anonymized.
+        if (nameNode->getKind() == Demangle::Node::Kind::Identifier) {
+          if (nameNode->getText() != type->Name.get())
+            return false;
+          
+          node = node->getChild(0);
+          break;
+        }
+        
+        return false;
+
       }
       
       // We don't know about this kind of context, or it doesn't have a stable
@@ -1166,7 +1183,7 @@
     if (typeInfo == nullptr) {
       typeInfo = TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {});
       warning(0, "SWIFT RUNTIME BUG: unable to demangle type of field '%*s'. "
-                 "mangled type name is '%*s'",
+                 "mangled type name is '%*s'\n",
                  (int)name.size(), name.data(),
                  (int)typeName.size(), typeName.data());
     }
@@ -1214,6 +1231,17 @@
         return;
     }
   }
+
+  // If we failed to find the field descriptor metadata for the type, fall
+  // back to returning an empty tuple as a standin.
+  auto typeName = swift_getTypeName(base, /*qualified*/ true);
+  warning(0, "SWIFT RUNTIME BUG: unable to find field metadata for type '%*s'\n",
+             (int)typeName.length, typeName.data);
+  callback("unknown",
+           FieldType()
+             .withType(TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {}))
+             .withIndirect(false)
+             .withWeak(false));
 }
 
 #define OVERRIDE_METADATALOOKUP COMPATIBILITY_OVERRIDE
diff --git a/test/Compatibility/lazy_properties.swift b/test/Compatibility/lazy_properties.swift
index c621521..313011b 100644
--- a/test/Compatibility/lazy_properties.swift
+++ b/test/Compatibility/lazy_properties.swift
@@ -4,7 +4,7 @@
   lazy var refs = (i, f())
   // expected-error@-1 {{cannot use instance member 'i' within property initializer; property initializers run before 'self' is available}}
   lazy var trefs: (Int, Int) = (i, f())
-  // expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
+  // expected-error@-1 {{cannot use instance member 'i' within property initializer; property initializers run before 'self' is available}}
 
   lazy var qrefs = (self.i, self.f())
   lazy var qtrefs: (Int, Int) = (self.i, self.f())
@@ -53,5 +53,5 @@
 
   static var i = 42
   static func f() -> Int { return 0 }
-  // expected-note@-1 {{did you mean 'f'?}}
+  // expected-note@-1 2 {{did you mean 'f'?}}
 }
diff --git a/test/Compatibility/members.swift b/test/Compatibility/members.swift
index 1805106..6af2274 100644
--- a/test/Compatibility/members.swift
+++ b/test/Compatibility/members.swift
@@ -7,5 +7,4 @@
 
 func g0(_: (inout X) -> (Float) -> ()) {}
 
-// This becomes an error in Swift 4 mode -- probably a bug
-g0(X.f1)
+g0(X.f1) // expected-warning{{partial application of 'mutating' method}}
diff --git a/test/Constraints/generic_super_constraint.swift b/test/Constraints/generic_super_constraint.swift
index c227519..4f46e93 100644
--- a/test/Constraints/generic_super_constraint.swift
+++ b/test/Constraints/generic_super_constraint.swift
@@ -17,3 +17,11 @@
   // expected-error@+1{{cannot convert return expression}}
   return (x, y)
 }
+
+// SR-7551 captures a crash on this code.
+class IntegerClass : ExpressibleByIntegerLiteral, Equatable {
+  required init(integerLiteral value: Int) { }
+  static func ==(lhs: IntegerClass, rhs: IntegerClass) -> Bool { return true }
+}
+
+func foo<T: IntegerClass>(_ num: T) { let _ =  num != 0 }
diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift
index 752e33a..4192a11 100644
--- a/test/Constraints/members.swift
+++ b/test/Constraints/members.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift -swift-version 4
+// RUN: %target-typecheck-verify-swift -swift-version 5
 
 ////
 // Members of structs
@@ -28,7 +28,7 @@
 _ = x.f0(i)
 x.f0(i).f1(i)
 
-g0(X.f1)
+g0(X.f1) // expected-error{{partial application of 'mutating' method}}
 
 _ = x.f0(x.f2(1))
 _ = x.f0(1).f2(i)
diff --git a/test/Constraints/mutating_members.swift b/test/Constraints/mutating_members.swift
new file mode 100644
index 0000000..dea386b
--- /dev/null
+++ b/test/Constraints/mutating_members.swift
@@ -0,0 +1,22 @@
+// RUN: %target-swift-frontend -typecheck -verify -swift-version 5 %s
+
+struct Foo {
+  mutating func boom() {}
+}
+
+let x = Foo.boom // expected-error{{partial application of 'mutating' method}}
+var y = Foo()
+let z0 = y.boom // expected-error{{partial application of 'mutating' method}}
+let z1 = Foo.boom(&y) // expected-error{{partial application of 'mutating' method}}
+
+func fromLocalContext() -> (inout Foo) -> () -> () {
+  return Foo.boom // expected-error{{partial application of 'mutating' method}}
+}
+func fromLocalContext2(x: inout Foo, y: Bool) -> () -> () {
+  if y {
+    return x.boom // expected-error{{partial application of 'mutating' method}}
+  } else {
+    return Foo.boom(&x) // expected-error{{partial application of 'mutating' method}}
+  }
+}
+
diff --git a/test/Constraints/mutating_members_compat.swift b/test/Constraints/mutating_members_compat.swift
new file mode 100644
index 0000000..e29fd34
--- /dev/null
+++ b/test/Constraints/mutating_members_compat.swift
@@ -0,0 +1,22 @@
+// RUN: %target-swift-frontend -typecheck -verify -swift-version 4 %s
+
+struct Foo {
+  mutating func boom() {}
+}
+
+let x = Foo.boom // expected-warning{{partial application of 'mutating' method}}
+var y = Foo()
+let z0 = y.boom // expected-error{{partial application of 'mutating' method}}
+let z1 = Foo.boom(&y) // expected-error{{partial application of 'mutating' method}}
+
+func fromLocalContext() -> (inout Foo) -> () -> () {
+  return Foo.boom // expected-warning{{partial application of 'mutating' method}}
+}
+func fromLocalContext2(x: inout Foo, y: Bool) -> () -> () {
+  if y {
+    return x.boom // expected-error{{partial application of 'mutating' method}}
+  } else {
+    return Foo.boom(&x) // expected-error{{partial application of 'mutating' method}}
+  }
+}
+
diff --git a/test/IDE/print_ast_tc_decls.swift b/test/IDE/print_ast_tc_decls.swift
index 8d031d2..3c9c4e5 100644
--- a/test/IDE/print_ast_tc_decls.swift
+++ b/test/IDE/print_ast_tc_decls.swift
@@ -529,7 +529,7 @@
 // PASS_COMMON-LABEL: {{^}}@objc class d0180_TestIBAttrs {{{$}}
 
   @IBAction func anAction(_: AnyObject) {}
-// PASS_COMMON-NEXT: {{^}}  @IBAction @objc func anAction(_: AnyObject){{$}}
+// PASS_COMMON-NEXT: {{^}}  @objc @IBAction func anAction(_: AnyObject){{$}}
 
   @IBDesignable
   class ADesignableClass {}
@@ -541,13 +541,13 @@
 // PASS_EXPLODE_PATTERN-LABEL: {{^}}@objc class d0181_TestIBAttrs {{{$}}
 
   @IBOutlet weak var anOutlet: d0181_TestIBAttrs!
-// PASS_EXPLODE_PATTERN-NEXT: {{^}}  @IBOutlet @_implicitly_unwrapped_optional @objc weak var anOutlet: @sil_weak d0181_TestIBAttrs!{{$}}
+// PASS_EXPLODE_PATTERN-NEXT: {{^}}  @objc @IBOutlet @_implicitly_unwrapped_optional weak var anOutlet: @sil_weak d0181_TestIBAttrs!{{$}}
 
   @IBInspectable var inspectableProp: Int = 0
-// PASS_EXPLODE_PATTERN-NEXT: {{^}}  @IBInspectable @objc var inspectableProp: Int{{$}}
+// PASS_EXPLODE_PATTERN-NEXT: {{^}}  @objc @IBInspectable var inspectableProp: Int{{$}}
 
   @GKInspectable var inspectableProp2: Int = 0
-// PASS_EXPLODE_PATTERN-NEXT: {{^}}  @GKInspectable @objc var inspectableProp2: Int{{$}}
+// PASS_EXPLODE_PATTERN-NEXT: {{^}}  @objc @GKInspectable var inspectableProp2: Int{{$}}
 }
 
 struct d0190_LetVarDecls {
diff --git a/test/Migrator/Inputs/MyAppKit.swift b/test/Migrator/Inputs/MyAppKit.swift
index ed93508..818f136 100644
--- a/test/Migrator/Inputs/MyAppKit.swift
+++ b/test/Migrator/Inputs/MyAppKit.swift
@@ -2,3 +2,4 @@
 public class NSOpenGLOption {}
 public func NSOpenGLGetOption(_ c : NSOpenGLOption, _ p :UnsafePointer<Int>) {}
 public func NSOpenGLSetOption(_ c : NSOpenGLOption, _ p : Int) {}
+public func UIApplicationMain(_ a: Int32, _ b: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>, _ c: String?, _ d: String?) -> Int32 { return 0 }
\ No newline at end of file
diff --git a/test/Migrator/Inputs/SpecialCaseAPI.json b/test/Migrator/Inputs/SpecialCaseAPI.json
index 26c4a98..1518592 100644
--- a/test/Migrator/Inputs/SpecialCaseAPI.json
+++ b/test/Migrator/Inputs/SpecialCaseAPI.json
@@ -13,5 +13,10 @@
     "DiffItemKind": "SpecialCaseDiffItem",
     "Usr": "s:7MySwift0A6DoubleV3absyS2dFZ",
     "SpecialCaseId": "StaticAbsToSwiftAbs"
+  },
+  {
+    "DiffItemKind": "SpecialCaseDiffItem",
+    "Usr": "s:8MyAppKit17UIApplicationMainys5Int32VAD_SpySpys4Int8VGGSSSgAItF",
+    "SpecialCaseId": "UIApplicationMain"
   }
 ]
diff --git a/test/Migrator/api-special-cases.swift b/test/Migrator/api-special-cases.swift
index ad30ca8..821543b 100644
--- a/test/Migrator/api-special-cases.swift
+++ b/test/Migrator/api-special-cases.swift
@@ -8,10 +8,16 @@
 import MyAppKit
 import MySwift
 
-func foo(_ Opt: NSOpenGLOption) {
+func foo(_ Opt: NSOpenGLOption, _ pointer: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) {
   var Value = 1
   NSOpenGLSetOption(Opt, 1)
   NSOpenGLGetOption(Opt, &Value)
+  UIApplicationMain(CommandLine.argc, pointer, "", "")
+  UIApplicationMain(
+    CommandLine.argc, pointer, "", "")
+  UIApplicationMain( CommandLine . 
+    argc, pointer, "", "")
+  UIApplicationMain(10, pointer, "", "")
 }
 
 do {
diff --git a/test/Migrator/api-special-cases.swift.expected b/test/Migrator/api-special-cases.swift.expected
index e2fd657..70424e8 100644
--- a/test/Migrator/api-special-cases.swift.expected
+++ b/test/Migrator/api-special-cases.swift.expected
@@ -8,10 +8,16 @@
 import MyAppKit
 import MySwift
 
-func foo(_ Opt: NSOpenGLOption) {
+func foo(_ Opt: NSOpenGLOption, _ pointer: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) {
   var Value = 1
   Opt.globalValue = 1
   Value = Opt.globalValue
+  UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, "", "")
+  UIApplicationMain(
+    CommandLine.argc, CommandLine.unsafeArgv, "", "")
+  UIApplicationMain( CommandLine . 
+    argc, CommandLine.unsafeArgv, "", "")
+  UIApplicationMain(10, pointer, "", "")
 }
 
 do {
diff --git a/test/Migrator/ui-application-main.swift b/test/Migrator/ui-application-main.swift
new file mode 100644
index 0000000..d0ebd8c
--- /dev/null
+++ b/test/Migrator/ui-application-main.swift
@@ -0,0 +1,14 @@
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/ui-application-main.swift.result -emit-remap-file-path %t/ui-application-main.swift.remap -o /dev/null -swift-version 3
+// RUN: diff -u %S/ui-application-main.swift.expected %t/ui-application-main.swift.result
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/ui-application-main.swift.result -emit-remap-file-path %t/ui-application-main.swift.remap -o /dev/null -swift-version 4
+// RUN: diff -u %S/ui-application-main.swift.expected %t/ui-application-main.swift.result
+
+// REQUIRES: OS=ios
+// REQUIRES: objc_interop
+
+import UIKit
+
+func foo(pointer: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) {
+	UIApplicationMain(CommandLine.argc, pointer, "", "")
+	UIApplicationMain(2, pointer, "", "")
+}
diff --git a/test/Migrator/ui-application-main.swift.expected b/test/Migrator/ui-application-main.swift.expected
new file mode 100644
index 0000000..69fd82c
--- /dev/null
+++ b/test/Migrator/ui-application-main.swift.expected
@@ -0,0 +1,14 @@
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/ui-application-main.swift.result -emit-remap-file-path %t/ui-application-main.swift.remap -o /dev/null -swift-version 3
+// RUN: diff -u %S/ui-application-main.swift.expected %t/ui-application-main.swift.result
+// RUN: %empty-directory(%t) && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/ui-application-main.swift.result -emit-remap-file-path %t/ui-application-main.swift.remap -o /dev/null -swift-version 4
+// RUN: diff -u %S/ui-application-main.swift.expected %t/ui-application-main.swift.result
+
+// REQUIRES: OS=ios
+// REQUIRES: objc_interop
+
+import UIKit
+
+func foo(pointer: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) {
+	UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, "", "")
+	UIApplicationMain(2, pointer, "", "")
+}
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index 3b201d4..214b201 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -148,7 +148,7 @@
   case Ladd, Elliott, Sixteenth, Harrison
 }
 
-enum RawTypeCircularityA : RawTypeCircularityB, ExpressibleByIntegerLiteral { // expected-error {{circular enum raw types 'RawTypeCircularityA' -> 'RawTypeCircularityB' -> 'RawTypeCircularityA'}} FIXME: expected-error{{RawRepresentable}}
+enum RawTypeCircularityA : RawTypeCircularityB, ExpressibleByIntegerLiteral { // expected-error {{'RawTypeCircularityA' has a raw type that depends on itself}}
   case Morrison, Belmont, Madison, Hawthorne
 
   init(integerLiteral value: Int) {
diff --git a/test/Runtime/Inputs/synthesized_decl_uniqueness.swift b/test/Runtime/Inputs/synthesized_decl_uniqueness.swift
new file mode 100644
index 0000000..5157acc
--- /dev/null
+++ b/test/Runtime/Inputs/synthesized_decl_uniqueness.swift
@@ -0,0 +1,9 @@
+import CoreLocation
+
+public func getCLError() -> Any.Type {
+  return CLError.self
+}
+
+public func getCLErrorCode() -> Any.Type {
+  return CLError.Code.self
+}
diff --git a/test/Runtime/demangleToMetadataObjC.swift b/test/Runtime/demangleToMetadataObjC.swift
index 2712138..2b5b920 100644
--- a/test/Runtime/demangleToMetadataObjC.swift
+++ b/test/Runtime/demangleToMetadataObjC.swift
@@ -5,6 +5,7 @@
 import StdlibUnittest
 import Foundation
 import CoreFoundation
+import CoreLocation
 
 let DemangleToMetadataTests = TestSuite("DemangleToMetadataObjC")
 
@@ -74,5 +75,15 @@
   expectNil(_typeByMangledName("4main3CG4CyAA1DCAA1DCG"))
 }
 
+DemangleToMetadataTests.test("synthesized declarations") {
+  expectEqual(CLError.self, _typeByMangledName("SC7CLErrorLeV")!)
+  expectNil(_typeByMangledName("SC7CLErrorV"))
+  expectEqual(CLError.Code.self, _typeByMangledName("So7CLErrorV")!)
+
+  let error = NSError(domain: NSCocoaErrorDomain, code: 0)
+  let reflectionString = String(reflecting: CLError(_nsError: error))
+  expectTrue(reflectionString.hasPrefix("__C_Synthesized.related decl 'e' for CLError(_nsError:"))
+}
+
 runAllTests()
 
diff --git a/test/Runtime/synthesized_decl_uniqueness.swift b/test/Runtime/synthesized_decl_uniqueness.swift
new file mode 100644
index 0000000..e47aea0
--- /dev/null
+++ b/test/Runtime/synthesized_decl_uniqueness.swift
@@ -0,0 +1,21 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -parse-as-library -force-single-frontend-invocation %S/Inputs/synthesized_decl_uniqueness.swift -emit-object -o %t/A.o -module-name A -emit-module-path %t/A.swiftmodule
+// RUN: %target-build-swift -parse-as-library -force-single-frontend-invocation %S/Inputs/synthesized_decl_uniqueness.swift -emit-object -o %t/B.o -module-name B -emit-module-path %t/B.swiftmodule
+// RUN: %target-build-swift -I %t %s %t/A.o %t/B.o -o %t/a.out
+// RUN: %target-run %t/a.out
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import StdlibUnittest
+import A
+import B
+
+var tests = TestSuite("metadata identity for synthesized types")
+
+tests.test("synthesized type identity across modules") {
+  expectEqual(A.getCLError(), B.getCLError())
+  expectEqual(A.getCLErrorCode(), B.getCLErrorCode())
+}
+
+runAllTests()
diff --git a/test/SILGen/access_marker_gen.swift b/test/SILGen/access_marker_gen.swift
index 174881c..188226a 100644
--- a/test/SILGen/access_marker_gen.swift
+++ b/test/SILGen/access_marker_gen.swift
@@ -150,5 +150,6 @@
 // CHECK:     bb0([[D:%.*]] : @guaranteed $D
 // CHECK:       [[METHOD:%.*]] = class_method [[D]] : $D, #D.x!materializeForSet.1
 // CHECK:       apply [[METHOD]]({{.*}}, [[D]])
+// CHECK:       begin_access [modify] [unsafe]
 // CHECK-NOT:   begin_access
 
diff --git a/test/SILGen/accessors.swift b/test/SILGen/accessors.swift
index e4ea9c5..be4fb40 100644
--- a/test/SILGen/accessors.swift
+++ b/test/SILGen/accessors.swift
@@ -58,9 +58,10 @@
 // CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
 // CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*OrdinarySub on [[ARG]] : $A
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*OrdinarySub
 // CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.setter : (Swift.Int) -> Swift.Int
 // CHECK-NEXT: [[SETTER:%.*]] = function_ref @$S9accessors11OrdinarySubVyS2icis
-// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ADDR]])
+// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ACCESS]])
 // CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
 
 // CHECK:    [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
@@ -68,12 +69,13 @@
 // CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $A
 // CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*A
 // CHECK-NEXT: [[T0:%.*]] = metatype $@thick A.Type
-// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*OrdinarySub to $Builtin.RawPointer
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ACCESS]] : $*OrdinarySub to $Builtin.RawPointer
 // CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[TEMP2]], [[T0]])
 // CHECK-NEXT: dealloc_stack [[TEMP2]]
 // CHECK-NEXT: br [[CONT]]
 
 // CHECK:    [[CONT]]:
+// CHECK-NEXT: end_access [[ACCESS]] : $*OrdinarySub
 // CHECK-NEXT: dealloc_stack [[BUFFER]]
 // CHECK-NEXT: dealloc_stack [[STORAGE]]
 // CHECK-NEXT: dealloc_stack [[TEMP]]
@@ -114,9 +116,10 @@
 // CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
 // CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[ARG]] : $B
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*MutatingSub
 // CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.getter : (Swift.Int) -> Swift.Int
 // CHECK-NEXT: [[T0:%.*]] = function_ref @$S9accessors11MutatingSubVyS2icig : $@convention(method) (Int, @inout MutatingSub) -> Int
-// CHECK-NEXT: [[VALUE:%.*]] = apply [[T0]]([[INDEX1]], [[ADDR]])
+// CHECK-NEXT: [[VALUE:%.*]] = apply [[T0]]([[INDEX1]], [[ACCESS]])
 // CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
 //
 // CHECK:    [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
@@ -124,13 +127,14 @@
 // CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
 // CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*B
 // CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
-// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*MutatingSub to $Builtin.RawPointer
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ACCESS]] : $*MutatingSub to $Builtin.RawPointer
 // CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[TEMP2]], [[T0]])
 // CHECK-NEXT: dealloc_stack [[TEMP2]]
 // CHECK-NEXT: br [[CONT]]
 //
 // CHECK:    [[CONT]]:
 //   Formal access to LHS.
+// CHECK-NEXT: end_access [[ACCESS]] : $*MutatingSub
 // CHECK-NEXT: [[STORAGE2:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
 // CHECK-NEXT: [[BUFFER2:%.*]] = alloc_stack $MutatingSub
 // CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER2]]
@@ -140,9 +144,10 @@
 // CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
 // CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[ARG]] : $B
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*MutatingSub
 // CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.setter : (Swift.Int) -> Swift.Int
 // CHECK-NEXT: [[SETTER:%.*]] = function_ref @$S9accessors11MutatingSubVyS2icis : $@convention(method) (Int, Int, @inout MutatingSub) -> ()
-// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ADDR]])
+// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ACCESS]])
 // CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
 //
 // CHECK:    [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
@@ -150,12 +155,13 @@
 // CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
 // CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*B
 // CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
-// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*MutatingSub to $Builtin.RawPointer
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ACCESS]] : $*MutatingSub to $Builtin.RawPointer
 // CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE2]], [[TEMP2]], [[T0]])
 // CHECK-NEXT: dealloc_stack [[TEMP2]]
 // CHECK-NEXT: br [[CONT]]
 //
 // CHECK:    [[CONT]]:
+// CHECK-NEXT: end_access [[ACCESS]] : $*MutatingSub
 // CHECK-NEXT: dealloc_stack [[BUFFER2]]
 // CHECK-NEXT: dealloc_stack [[STORAGE2]]
 // CHECK-NEXT: dealloc_stack [[BUFFER]]
diff --git a/test/SILGen/addressors.swift b/test/SILGen/addressors.swift
index d49ce81..27119c5 100644
--- a/test/SILGen/addressors.swift
+++ b/test/SILGen/addressors.swift
@@ -59,7 +59,8 @@
 // CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[AVAL]])
 // CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
 // CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK: [[Z:%.*]] = load [[T3]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T3]] : $*Int32
+// CHECK: [[Z:%.*]] = load [[ACCESS]] : $*Int32
   let z = a[10]
 
 // CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[A]] : $*A
@@ -67,9 +68,10 @@
 // CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
 // CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
 // CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T3]] : $*Int32
 // CHECK: load
 // CHECK: sadd_with_overflow_Int{{32|64}}
-// CHECK: store {{%.*}} to [[T3]]
+// CHECK: store {{%.*}} to [[ACCESS]]
   a[5] += z
 
 // CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[A]] : $*A
@@ -77,7 +79,8 @@
 // CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
 // CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
 // CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK: store {{%.*}} to [[T3]]
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T3]] : $*Int32
+// CHECK: store {{%.*}} to [[ACCESS]]
   a[3] = 6
 }
 
@@ -90,7 +93,8 @@
 // CHECK: [[PTR:%.*]] = apply [[ACCESSOR]]({{%.*}}, [[A]]) : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
 // CHECK: [[T0:%.*]] = struct_extract [[PTR]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
 // CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK: [[T2:%.*]] = load [[T1]] : $*Int32
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T1]] : $*Int32
+// CHECK: [[T2:%.*]] = load [[ACCESS]] : $*Int32
 // CHECK: return [[T2]] : $Int32
   return A()[0]
 }
@@ -116,7 +120,8 @@
 // CHECK:   [[T1:%.*]] = apply [[T0]]() : $@convention(thin) () -> UnsafePointer<Int32>
 // CHECK:   [[T2:%.*]] = struct_extract [[T1]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
 // CHECK:   [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK:   [[T4:%.*]] = load [[T3]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T3]] : $*Int32
+// CHECK:   [[T4:%.*]] = load [[ACCESS]] : $*Int32
 // CHECK:   return [[T4]] : $Int32
 
 // Test that having generated trivial accessors for something because
@@ -142,11 +147,12 @@
 // CHECK:   [[PTR:%.*]] = apply [[T0]]([[INDEX]], [[WRITE]])
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]] : $UnsafeMutablePointer<Int32>,
 // CHECK:   [[ADDR:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*Int32
 // Accept either of struct_extract+load or load+struct_element_addr.
 // CHECK:   load
 // CHECK:   [[T1:%.*]] = builtin "or_Int32"
 // CHECK:   [[T2:%.*]] = struct $Int32 ([[T1]] : $Builtin.Int32)
-// CHECK:   store [[T2]] to [[ADDR]] : $*Int32
+// CHECK:   store [[T2]] to [[ACCESS]] : $*Int32
 func test_B(_ b: inout B) {
   b[0] |= 7
 }
@@ -170,7 +176,8 @@
 // CHECK:   [[T1:%.*]] = apply [[T0]]<(Int32) -> Int32>({{%.*}}, [[WRITE]])
 // CHECK:   [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<(Int32) -> Int32>, #UnsafeMutablePointer._rawValue
 // CHECK:   [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
-// CHECK:   store {{%.*}} to [[T3]] :
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T3]] : $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
+// CHECK:   store {{%.*}} to [[ACCESS]] :
   array[0] = id_int
 
 // CHECK:   [[READ:%.*]] = begin_access [read] [static] [[ARRAY]] : $*CArray<(Int32) -> Int32>
@@ -179,7 +186,8 @@
 // CHECK:   [[T2:%.*]] = apply [[T1]]<(Int32) -> Int32>({{%.*}}, [[T0]])
 // CHECK:   [[T3:%.*]] = struct_extract [[T2]] : $UnsafePointer<(Int32) -> Int32>, #UnsafePointer._rawValue
 // CHECK:   [[T4:%.*]] = pointer_to_address [[T3]] : $Builtin.RawPointer to [strict] $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
-// CHECK:   [[T5:%.*]] = load [[T4]]
+// CHECK:   [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T4]] : $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
+// CHECK:   [[T5:%.*]] = load [[ACCESS]]
   return array[1](5)
 }
 
@@ -196,12 +204,13 @@
 // SILGEN:   debug_value [[VALUE]] : $Int32
 // SILGEN:   debug_value [[I]] : $Int32
 // SILGEN:   debug_value_addr [[SELF]]
-// SILGEN:   [[ACCESS:%.*]] = begin_access [modify] [unknown] [[SELF]] : $*D   // users: %12, %8
+// SILGEN:   [[ACCESS:%.*]] = begin_access [modify] [unknown] [[SELF]] : $*D
 // SILGEN:   [[T0:%.*]] = function_ref @$S10addressors1DVys5Int32VAEciau{{.*}}
 // SILGEN:   [[PTR:%.*]] = apply [[T0]]([[I]], [[ACCESS]])
 // SILGEN:   [[T0:%.*]] = struct_extract [[PTR]] : $UnsafeMutablePointer<Int32>,
 // SILGEN:   [[ADDR:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
-// SILGEN:   assign [[VALUE]] to [[ADDR]] : $*Int32
+// SILGEN:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*Int32
+// SILGEN:   assign [[VALUE]] to [[ACCESS]] : $*Int32
 
 // materializeForSet.
 // SILGEN-LABEL: sil hidden [transparent] @$S10addressors1DVys5Int32VAEcim
@@ -228,7 +237,8 @@
 // CHECK:   [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
 // CHECK:   [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>,
 // CHECK:   [[ADDR:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
-// CHECK:   store [[V]] to [[ADDR]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*Int32
+// CHECK:   store [[V]] to [[ACCESS]] : $*Int32
   array[0] = make_int()
 
 // CHECK:   [[WRITE:%.*]] = begin_access [modify] [static] [[ARRAY]] : $*D
@@ -236,8 +246,9 @@
 // CHECK:   [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
 // CHECK:   [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>,
 // CHECK:   [[ADDR:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*Int32
 // CHECK:   [[FN:%.*]] = function_ref @$S10addressors14take_int_inoutyys5Int32VzF
-// CHECK:   apply [[FN]]([[ADDR]])
+// CHECK:   apply [[FN]]([[ACCESS]])
   take_int_inout(&array[1])
 
 // CHECK:   [[READ:%.*]] = begin_access [read] [static] [[ARRAY]] : $*D
@@ -261,7 +272,8 @@
 // CHECK:   [[T1:%.*]] = apply [[T0]]([[E]])
 // CHECK:   [[T2:%.*]] = struct_extract [[T1]]
 // CHECK:   [[T3:%.*]] = pointer_to_address [[T2]]
-// CHECK:   store {{%.*}} to [[T3]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T3]] : $*Int32
+// CHECK:   store {{%.*}} to [[ACCESS]] : $*Int32
 func test_e(_ e: E) {
   e.value = 0
 }
@@ -294,7 +306,8 @@
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]]
 // CHECK:   [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
 // CHECK:   [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
-// CHECK:   [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T2]] : $*Int32
+// CHECK:   [[VALUE:%.*]] = load [[ACCESS]] : $*Int32
 // CHECK:   strong_release [[OWNER]] : $Builtin.NativeObject
 // CHECK-NOT:   strong_release [[SELF]] : $F
 // CHECK:   return [[VALUE]] : $Int32
@@ -313,7 +326,8 @@
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]]
 // CHECK:   [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
 // CHECK:   [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
-// CHECK:   store [[VALUE]] to [[T2]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Int32
+// CHECK:   store [[VALUE]] to [[ACCESS]] : $*Int32
 // CHECK:   strong_release [[OWNER]] : $Builtin.NativeObject
 // CHECK-NOT:   strong_release [[SELF]] : $F
 
@@ -338,7 +352,8 @@
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]]
 // CHECK:   [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
 // CHECK:   [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
-// CHECK:   [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T2]] : $*Int32
+// CHECK:   [[VALUE:%.*]] = load [[ACCESS]] : $*Int32
 // CHECK:   strong_release [[OWNER]] : $Builtin.NativeObject
 // CHECK:   return [[VALUE]] : $Int32
 
@@ -351,7 +366,8 @@
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]]
 // CHECK:   [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
 // CHECK:   [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
-// CHECK:   store [[VALUE]] to [[T2]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Int32
+// CHECK:   store [[VALUE]] to [[ACCESS]] : $*Int32
 // CHECK:   strong_release [[OWNER]] : $Builtin.NativeObject
 
 //   materializeForSet callback for G.value
@@ -415,7 +431,8 @@
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]]
 // CHECK:   [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
 // CHECK:   [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK:   [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T2]] : $*Int32
+// CHECK:   [[VALUE:%.*]] = load [[ACCESS]] : $*Int32
 // CHECK:   strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
 // CHECK-NOT:   strong_release [[SELF]] : $H
 // CHECK:   return [[VALUE]] : $Int32
@@ -434,7 +451,8 @@
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]]
 // CHECK:   [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
 // CHECK:   [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK:   store [[VALUE]] to [[T2]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Int32
+// CHECK:   store [[VALUE]] to [[ACCESS]] : $*Int32
 // CHECK:   strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
 // CHECK-NOT:   strong_release [[SELF]] : $H
 
@@ -459,7 +477,8 @@
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]]
 // CHECK:   [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
 // CHECK:   [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK:   [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T2]] : $*Int32
+// CHECK:   [[VALUE:%.*]] = load [[ACCESS]] : $*Int32
 // CHECK:   strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
 // CHECK:   return [[VALUE]] : $Int32
 
@@ -472,7 +491,8 @@
 // CHECK:   [[T0:%.*]] = struct_extract [[PTR]]
 // CHECK:   [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
 // CHECK:   [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK:   store [[VALUE]] to [[T2]] : $*Int32
+// CHECK:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Int32
+// CHECK:   store [[VALUE]] to [[ACCESS]] : $*Int32
 // CHECK:   strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
 
 //   materializeForSet callback for I.value
diff --git a/test/SILGen/errors.swift b/test/SILGen/errors.swift
index d6c00f4..a84f825 100644
--- a/test/SILGen/errors.swift
+++ b/test/SILGen/errors.swift
@@ -541,8 +541,9 @@
 // CHECK: [[CALLBACK:%.*]] = tuple_extract [[T1]] : {{.*}}, 1
 // CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*B.Structure
 // CHECK: [[T4:%.*]] = mark_dependence [[T3]] : $*B.Structure on [[BASE]] : $*B
+// CHECK: [[T5:%.*]] = begin_access [modify] [unsafe] [[T4]] : $*B.Structure
 // CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
-// CHECK: try_apply [[SUPPORT]]<B.Structure>([[T4]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
+// CHECK: try_apply [[SUPPORT]]<B.Structure>([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 
 // CHECK: [[BB_NORMAL]]
 // CHECK: switch_enum [[CALLBACK]]
@@ -577,8 +578,9 @@
 // CHECK:   [[CALLBACK:%.*]] = tuple_extract [[T1]] : {{.*}}, 1
 // CHECK:   [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*B.Structure
 // CHECK:   [[T4:%.*]] = mark_dependence [[T3]] : $*B.Structure on [[BASE]] : $*B
+// CHECK:   [[T5:%.*]] = begin_access [modify] [unsafe] [[T4]] : $*B.Structure
 // CHECK:   [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
-// CHECK:   try_apply [[SUPPORT]]<B.Structure>([[T4]]) : $@convention(witness_method: Supportable) <τ_0_0 where τ_0_0 : Supportable> (@inout τ_0_0) -> @error Error, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
+// CHECK:   try_apply [[SUPPORT]]<B.Structure>([[T5]]) : $@convention(witness_method: Supportable) <τ_0_0 where τ_0_0 : Supportable> (@inout τ_0_0) -> @error Error, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 
 // CHECK: [[BB_NORMAL]]
 // CHECK:   switch_enum [[CALLBACK]] : ${{.*}}, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
@@ -691,15 +693,18 @@
 // CHECK-NEXT: [[T3:%.*]] = struct_extract [[T1]]
 // CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT: [[T5:%.*]] = mark_dependence [[T4]] : $*Pylon on [[OWNER]]
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T5]] : $*Pylon
 // CHECK:      [[SUPPORT:%.*]] = function_ref @$S6errors5PylonV7supportyyKF
-// CHECK-NEXT: try_apply [[SUPPORT]]([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
+// CHECK-NEXT: try_apply [[SUPPORT]]([[ACCESS]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 // CHECK:    [[BB_NORMAL]]
+// CHECK-NEXT: end_access [[ACCESS]] : $*Pylon
 // CHECK-NEXT: end_access [[WRITE]]
 // CHECK-NEXT: destroy_value [[OWNER]] : $AnyObject
 // CHECK-NEXT: destroy_value [[ARG2_COPY]] : $String
 // CHECK-NEXT: tuple ()
 // CHECK-NEXT: return
 // CHECK:    [[BB_ERROR]]([[ERROR:%.*]] : @owned $Error):
+// CHECK-NEXT: end_access [[ACCESS]] : $*Pylon
 // CHECK-NEXT: destroy_value [[OWNER]] : $AnyObject
 // CHECK-NEXT: end_access [[WRITE]]
 // CHECK-NEXT: destroy_value [[ARG2_COPY]] : $String
@@ -734,15 +739,18 @@
 // CHECK-NEXT:   [[T3:%.*]] = struct_extract [[T1]]
 // CHECK-NEXT:   [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT:   [[T5:%.*]] = mark_dependence [[T4]] : $*Pylon on [[OWNER]]
+// CHECK-NEXT:   [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[T5]] : $*Pylon
 // CHECK:        [[SUPPORT:%.*]] = function_ref @$S6errors5PylonV7supportyyKF
-// CHECK-NEXT:   try_apply [[SUPPORT]]([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
+// CHECK-NEXT:   try_apply [[SUPPORT]]([[ACCESS]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 // CHECK:      [[BB_NORMAL]]
+// CHECK-NEXT:   end_access [[ACCESS]] : $*Pylon
 // CHECK-NEXT:   strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
 // CHECK-NEXT:   end_access [[WRITE]]
 // CHECK-NEXT:   destroy_value [[ARG2_COPY]] : $String
 // CHECK-NEXT:   tuple ()
 // CHECK-NEXT:   return
 // CHECK:      [[BB_ERROR]]([[ERROR:%.*]] : @owned $Error):
+// CHECK-NEXT:   end_access [[ACCESS]] : $*Pylon
 // CHECK-NEXT:   [[OWNER_COPY:%.*]] = copy_value [[OWNER]]
 // CHECK-NEXT:   strong_unpin [[OWNER_COPY]] : $Optional<Builtin.NativeObject>
 // CHECK-NEXT:   destroy_value [[OWNER]]
diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift
index cac4901..0eb53ce 100644
--- a/test/SILGen/materializeForSet.swift
+++ b/test/SILGen/materializeForSet.swift
@@ -309,9 +309,11 @@
 // CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet012HasStoredDidC0C6storedSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasStoredDidSet) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
 // CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasStoredDidSet):
 // CHECK:   [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
-// CHECK:   [[T0:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivg
-// CHECK:   [[T1:%.*]] = apply [[T0]]([[SELF]])
-// CHECK:   store [[T1]] to [trivial] [[T2]] : $*Int
+// CHECK:   [[T0:%.*]] = ref_element_addr [[SELF]] : $HasStoredDidSet, #HasStoredDidSet.stored
+// CHECK:   [[T1:%.*]] = begin_access [read] [dynamic] [[T0]] : $*Int
+// CHECK:   [[VALUE:%.*]] = load [trivial] [[T1]] : $*Int
+// CHECK:   end_access [[T1]] : $*Int
+// CHECK:   store [[VALUE]] to [trivial] [[T2]] : $*Int
 // CHECK:   [[BUFFER:%.*]] = address_to_pointer [[T2]]
 // CHECK:   [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed HasStoredDidSet, @thick HasStoredDidSet.Type) -> ()
 // CHECK:   [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
diff --git a/test/SILGen/objc_properties.swift b/test/SILGen/objc_properties.swift
index 6916e03..b0a8148 100644
--- a/test/SILGen/objc_properties.swift
+++ b/test/SILGen/objc_properties.swift
@@ -201,9 +201,10 @@
   // CHECK: [[RAW_POINTER:%.*]] = tuple_extract [[TUPLE]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 0
   // CHECK: [[OBJECT:%.*]] = pointer_to_address [[RAW_POINTER]] : $Builtin.RawPointer to [strict] $*NSObject
   // CHECK: [[OBJECT_DEP:%.*]] = mark_dependence [[OBJECT]] : $*NSObject on [[ARG]]
-  // CHECK: [[LOADED_OBJECT:%.*]] = load_borrow [[OBJECT_DEP]]
+  // CHECK: [[OBJECT_ACCESS:%.*]] = begin_access [modify] [unsafe] [[OBJECT_DEP]] : $*NSObject
+  // CHECK: [[LOADED_OBJECT:%.*]] = load_borrow [[OBJECT_ACCESS]]
   // CHECK: [[UNMANAGED_OBJECT:%.*]] = ref_to_unmanaged [[LOADED_OBJECT]] : $NSObject to $@sil_unmanaged NSObject
-  // CHECK: end_borrow [[LOADED_OBJECT]] from [[OBJECT_DEP]]
+  // CHECK: end_borrow [[LOADED_OBJECT]] from [[OBJECT_ACCESS]]
   func useProperty() {
     useAutoreleasingUnsafeMutablePointer(&property)
   }
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index 748cc83..8f3fc4c 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -209,8 +209,9 @@
   // CHECK: [[T0:%.*]] = tuple_extract [[MAT_RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 0
   // CHECK: [[OPT_CALLBACK:%.*]] = tuple_extract [[MAT_RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 1  
   // CHECK: [[T1:%[0-9]+]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Val
-  // CHECK: [[VAL_REF_VAL_PROP_MAT:%.*]] = mark_dependence [[T1]] : $*Val on [[VAL_REF]]
+  // CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Val on [[VAL_REF]]
   // CHECK: end_borrow [[VAL_REF_BORROWED]] from [[VAL_REF]]
+  // CHECK: [[VAL_REF_VAL_PROP_MAT:%.*]] = begin_access [modify] [unsafe] [[T2]] : $*Val
   // -- val.ref.val_prop.z_tuple
   // CHECK: [[V_R_VP_Z_TUPLE_MAT:%[0-9]+]] = alloc_stack $(Int, Int)
   // CHECK: [[LD:%[0-9]+]] = load_borrow [[VAL_REF_VAL_PROP_MAT]]
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index f38954c..42a477b 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -407,13 +407,14 @@
 // CHECK:      [[CALLBACK:%.*]] = tuple_extract [[RESULT]]
 // CHECK:      [[TEMPORARY_ADDR_TMP:%.*]] = pointer_to_address [[TEMPORARY]] : $Builtin.RawPointer to [strict] $*Int
 // CHECK:      [[TEMPORARY_ADDR:%.*]] = mark_dependence [[TEMPORARY_ADDR_TMP]] : $*Int on [[WRITE]] : $*T
+// CHECK:      [[TEMPORARY_ACCESS:%.*]] = begin_access [modify] [unsafe] [[TEMPORARY_ADDR]] : $*Int
 // CHECK:      [[MODIFY_FN:%.*]] = function_ref @$S9protocols6modifyyySizF
-// CHECK:      apply [[MODIFY_FN]]([[TEMPORARY_ADDR]])
+// CHECK:      apply [[MODIFY_FN]]([[TEMPORARY_ACCESS]])
 // CHECK:      switch_enum [[CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2
 // CHECK:    bb1([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
 // CHECK:      [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]]
 // CHECK:      [[METATYPE:%.*]] = metatype $@thick T.Type
-// CHECK:      [[TEMPORARY:%.*]] = address_to_pointer [[TEMPORARY_ADDR]] : $*Int to $Builtin.RawPointer
+// CHECK:      [[TEMPORARY:%.*]] = address_to_pointer [[TEMPORARY_ACCESS]] : $*Int to $Builtin.RawPointer
 // CHECK:      apply [[CALLBACK]]<T>
 
 public struct Val {
diff --git a/test/SILGen/tsan_instrumentation.swift b/test/SILGen/tsan_instrumentation.swift
index 989ff62..a601766 100644
--- a/test/SILGen/tsan_instrumentation.swift
+++ b/test/SILGen/tsan_instrumentation.swift
@@ -57,9 +57,10 @@
 // CHECK:  [[BUFFER_ADDRESS:%.*]] = pointer_to_address [[TEMPORARY_BUFFER]] : $Builtin.RawPointer to [strict] $*Int
 // CHECK:  [[BUFFER_ADDRESS_DEPENDENCE:%.*]] = mark_dependence [[BUFFER_ADDRESS]] : $*Int on [[LOADED_CLASS]] : $MyClass
 // CHECK:  end_borrow [[BORROWED_CLASS]] from [[LOADED_CLASS]] : $MyClass, $MyClass
-// CHECK:  {{%.*}} builtin "tsanInoutAccess"([[BUFFER_ADDRESS_DEPENDENCE]] : $*Int) : $()
+// CHECK:  [[BUFFER_ADDRESS_ACCESS:%.*]] = begin_access [modify] [unsafe] [[BUFFER_ADDRESS_DEPENDENCE]]
+// CHECK:  {{%.*}} builtin "tsanInoutAccess"([[BUFFER_ADDRESS_ACCESS]] : $*Int) : $()
 // CHECK:  [[TAKES_INOUT_FUNC:%.*]] = function_ref @$S20tsan_instrumentation10takesInoutyySizF : $@convention(thin) (@inout Int) -> ()
-// CHECK:  {{%.*}} apply [[TAKES_INOUT_FUNC]]([[BUFFER_ADDRESS_DEPENDENCE]]) : $@convention(thin) (@inout Int) -> ()
+// CHECK:  {{%.*}} apply [[TAKES_INOUT_FUNC]]([[BUFFER_ADDRESS_ACCESS]]) : $@convention(thin) (@inout Int) -> ()
 func inoutGlobalClassStoredProperty() {
   // This generates two TSan inout instrumentations. One for the value
   // buffer that is passed inout to materializeForSet and one for the
diff --git a/test/SILOptimizer/Inputs/access_wmo_def.swift b/test/SILOptimizer/Inputs/access_wmo_def.swift
new file mode 100644
index 0000000..e23e758
--- /dev/null
+++ b/test/SILOptimizer/Inputs/access_wmo_def.swift
@@ -0,0 +1,15 @@
+// Input for access-enforcement-wmo multi-file test cases.
+
+var internalGlobal: Int = 0
+
+public var publicGlobal: Int = 0
+
+public class C {
+  var setterProp: Int = 0 // Only modified via setter.
+  final var finalProp: Int = 0 // modified directly.
+  var inlinedProp: Int = 0 // modification via materializeForSet inlined.
+  var internalProp: Int = 0 // modified opaquely via materializeForSet.
+  var keyPathProp: Int = 0 // modified via a keypath.
+  final var finalKeyPathProp: Int = 0 // modified via a keypath.
+  public var publicProp: Int = 0
+}
diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift
index 58a7198..edea97a 100644
--- a/test/SILOptimizer/access_marker_verify.swift
+++ b/test/SILOptimizer/access_marker_verify.swift
@@ -575,8 +575,8 @@
 // CHECK:   apply
 // CHECK:   struct_extract
 // CHECK:   [[ADR:%.*]] = pointer_to_address
-// CHECK-NOT: begin_access
-// CHECK:   load [trivial] [[ADR]] : $*Int
+// CHECK:   [[ACCESS:%.*]] = begin_access [read] [unsafe] [[ADR]] : $*Int
+// CHECK:   load [trivial] [[ACCESS]] : $*Int
 // CHECK:   return
 // CHECK-LABEL: } // end sil function '$S20access_marker_verify13testAddressor1pSiSPySiG_tF'
 
@@ -992,8 +992,8 @@
 // CHECK: [[POINTEE:%.*]] = apply %{{.*}}<Int>(%1) : $@convention(method) <τ_0_0> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
 // CHECK: [[RAWPTR:%.*]] = struct_extract [[POINTEE]] : $UnsafeMutablePointer<Int>, #UnsafeMutablePointer._rawValue
 // CHECK: [[ADR:%.*]] = pointer_to_address [[RAWPTR]] : $Builtin.RawPointer to [strict] $*Int
-// CHECK-NOT: begin_access
-// CHECK: assign %0 to [[ADR]] : $*Int
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[ADR]] : $*Int
+// CHECK: assign %0 to [[ACCESS]] : $*Int
 // CHECK-LABEL: } // end sil function '$S20access_marker_verify15testPointerInit1x1yySi_SpySiGtF'
 
 // Verification should ignore the address operand of init_existential_addr.
@@ -1022,3 +1022,22 @@
 // CHECK: store %{{.*}} to [trivial] [[PROJ]] : $*SomeError
 // CHECK: throw [[BOXALLOC]] : $Error
 // CHECK-LABEL: } // end sil function '$S20access_marker_verify11testInitBoxyyKF'
+
+public final class HasStaticProp {
+  public static let empty: HasStaticProp = HasStaticProp()
+}
+
+// A global addressor produces an unenforced RawPointer. This looke
+// like an Unidentified access with no access marker. Ensure that
+// verification doesn't assert.
+public func getStaticProp() -> HasStaticProp {
+  return .empty
+}
+
+// CHECK-LABEL: sil @$S20access_marker_verify13getStaticPropAA03HaseF0CyF : $@convention(thin) () -> @owned HasStaticProp {
+// function_ref HasStaticProp.empty.unsafeMutableAddressor
+// CHECK: [[F:%.*]] = function_ref @$S20access_marker_verify13HasStaticPropC5emptyACvau : $@convention(thin) () -> Builtin.RawPointer
+// CHECK: [[RP:%.*]] = apply [[F]]() : $@convention(thin) () -> Builtin.RawPointer
+// CHECK: [[ADR:%.*]] = pointer_to_address [[RP]] : $Builtin.RawPointer to [strict] $*HasStaticProp
+// CHECK: load [copy] [[ADR]] : $*HasStaticProp
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify13getStaticPropAA03HaseF0CyF'
diff --git a/test/SILOptimizer/access_wmo.sil b/test/SILOptimizer/access_wmo.sil
new file mode 100644
index 0000000..26f7102
--- /dev/null
+++ b/test/SILOptimizer/access_wmo.sil
@@ -0,0 +1,338 @@
+// RUN: %target-sil-opt -wmo -access-enforcement-wmo -assume-parsing-unqualified-ownership-sil %s -enable-sil-verify-all | %FileCheck %s
+//
+// Test the AccessEnforcementWMO pass in isolation. This ensures that
+// no upstream passes have removed SIL-level access markers that are
+// required to ensure the pass is not overly optimistic. It also
+// checks generated getters and setters are handled as expected.
+
+sil_stage canonical
+
+import Builtin
+import Swift
+import SwiftShims
+
+var internalGlobal: Int64
+
+public var publicGlobal: Int64
+
+public class C {
+  @sil_stored var setterProp: Int64 { get set }
+  @sil_stored final var finalProp: Int64 { get set }
+  @sil_stored var inlinedProp: Int64 { get set }
+  @sil_stored var internalProp: Int64 { get set }
+  @sil_stored var keyPathProp: Int64 { get set }
+  @sil_stored final var finalKeyPathProp: Int64 { get set }
+  @sil_stored public var publicProp: Int64 { get set }
+  init()
+  deinit
+}
+
+// internalGlobal
+sil_global hidden @$S10access_wmo14internalGlobalSivp : $Int64 = {
+  %0 = integer_literal $Builtin.Int64, 0          // user: %1
+  %initval = struct $Int64 (%0 : $Builtin.Int64)
+}
+
+
+// publicGlobal
+sil_global @$S10access_wmo12publicGlobalSivp : $Int64 = {
+  %0 = integer_literal $Builtin.Int64, 0          // user: %1
+  %initval = struct $Int64 (%0 : $Builtin.Int64)
+}
+
+// readGlobal()
+// CHECK-LABEL: sil @$S10access_wmo10readGlobalSiyF : $@convention(thin) () -> Int64 {
+//
+// The internal global is promoted to static.
+// CHECK: [[G1:%.]] = global_addr @$S10access_wmo14internalGlobalSivp : $*Int64
+// CHECK: begin_access [read] [static] [no_nested_conflict] [[G1]] : $*Int64
+//
+// The public global remains dynamic.
+// CHECK: [[G2:%.*]] = global_addr @$S10access_wmo12publicGlobalSivp : $*Int
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[G2]] : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo10readGlobalSiyF'
+sil @$S10access_wmo10readGlobalSiyF : $@convention(thin) () -> Int64 {
+bb0:
+  %0 = global_addr @$S10access_wmo14internalGlobalSivp : $*Int64
+  %1 = begin_access [read] [dynamic] [no_nested_conflict] %0 : $*Int64
+  %2 = struct_element_addr %1 : $*Int64, #Int64._value
+  %3 = load %2 : $*Builtin.Int64
+  end_access %1 : $*Int64
+  %5 = global_addr @$S10access_wmo12publicGlobalSivp : $*Int64
+  %6 = begin_access [read] [dynamic] [no_nested_conflict] %5 : $*Int64
+  %7 = struct_element_addr %6 : $*Int64, #Int64._value
+  %8 = load %7 : $*Builtin.Int64
+  end_access %6 : $*Int64
+  %10 = integer_literal $Builtin.Int1, -1
+  %11 = builtin "sadd_with_overflow_Int64"(%3 : $Builtin.Int64, %8 : $Builtin.Int64, %10 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+  %12 = tuple_extract %11 : $(Builtin.Int64, Builtin.Int1), 0
+  %13 = tuple_extract %11 : $(Builtin.Int64, Builtin.Int1), 1
+  cond_fail %13 : $Builtin.Int1
+  %15 = struct $Int64 (%12 : $Builtin.Int64)
+  return %15 : $Int64
+} // end sil function '$S10access_wmo10readGlobalSiyF'
+
+// setInt(_:_:)
+sil [noinline] @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int64, Int64) -> ()
+
+// testAccessGlobal(v:)
+// CHECK-LABEL: sil @$S10access_wmo16testAccessGlobal1vySi_tF : $@convention(thin) (Int64) -> () {
+// CHECK: [[G1:%.*]] = global_addr @$S10access_wmo14internalGlobalSivp : $*Int64
+// CHECK: begin_access [modify] [static] [no_nested_conflict] [[G1]] : $*Int64
+// CHECK: [[G2:%.*]] = global_addr @$S10access_wmo12publicGlobalSivp : $*Int64
+// CHECK: begin_access [modify] [dynamic] [no_nested_conflict] [[G2]] : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo16testAccessGlobal1vySi_tF'
+sil @$S10access_wmo16testAccessGlobal1vySi_tF : $@convention(thin) (Int64) -> () {
+// %0                                             // users: %9, %5, %1
+bb0(%0 : $Int64):
+  %1 = global_addr @$S10access_wmo14internalGlobalSivp : $*Int64
+  %2 = begin_access [modify] [dynamic] [no_nested_conflict] %1 : $*Int64
+  // function_ref setInt(_:_:)
+  %3 = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int64, Int64) -> ()
+  %4 = apply %3(%2, %0) : $@convention(thin) (@inout Int64, Int64) -> ()
+  end_access %2 : $*Int64
+  %6 = global_addr @$S10access_wmo12publicGlobalSivp : $*Int64
+  %7 = begin_access [modify] [dynamic] [no_nested_conflict] %6 : $*Int64
+  %8 = apply %3(%7, %0) : $@convention(thin) (@inout Int64, Int64) -> ()
+  end_access %7 : $*Int64
+  %10 = tuple ()
+  return %10 : $()
+} // end sil function '$S10access_wmo16testAccessGlobal1vySi_tF'
+
+// setKeyPath(_:_:_:)
+sil [noinline] @$S10access_wmo10setKeyPathyyAA1CC_s017ReferenceWritabledE0CyADSiGSitF : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int64>, Int64) -> ()
+
+// readProp(c:)
+//
+// See the explanation in access_wmo.swift for why some non-public
+// properties cannot currently be promoted to static enforcement.
+//
+// CHECK-LABEL: sil @$S10access_wmo8readProp1cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
+// CHECK: [[E1:%.*]] = ref_element_addr %0 : $C, #C.setterProp
+// CHECK: begin_access [read] [static] [no_nested_conflict] [[E1]] : $*Int64
+// CHECK: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// CHECK: begin_access [read] [static] [no_nested_conflict] [[E2]] : $*Int64
+// CHECK: [[E3:%.*]] = ref_element_addr %0 : $C, #C.inlinedProp
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[E3]] : $*Int64
+// CHECK: [[E4:%.*]] = ref_element_addr %0 : $C, #C.internalProp
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[E4]] : $*Int64
+// CHECK: [[E5:%.*]] = ref_element_addr %0 : $C, #C.keyPathProp
+// CHECK: begin_access [read] [static] [no_nested_conflict] [[E5]] : $*Int64
+// CHECK: [[E5:%.*]] = ref_element_addr %0 : $C, #C.finalKeyPathProp
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[E5]] : $*Int64
+// CHECK: [[E6:%.*]] = ref_element_addr %0 : $C, #C.publicProp
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[E6]] : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo8readProp1cyAA1CC_tF'
+sil @$S10access_wmo8readProp1cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
+// %0
+bb0(%0 : $C):
+  %1 = ref_element_addr %0 : $C, #C.setterProp
+  %2 = begin_access [read] [dynamic] [no_nested_conflict] %1 : $*Int64
+  %3 = struct_element_addr %2 : $*Int64, #Int64._value
+  %4 = load %3 : $*Builtin.Int64
+  end_access %2 : $*Int64
+  %6 = ref_element_addr %0 : $C, #C.finalProp
+  %7 = begin_access [read] [dynamic] [no_nested_conflict] %6 : $*Int64
+  %8 = struct_element_addr %7 : $*Int64, #Int64._value
+  %9 = load %8 : $*Builtin.Int64
+  end_access %7 : $*Int64
+  %11 = ref_element_addr %0 : $C, #C.inlinedProp
+  %12 = begin_access [read] [dynamic] [no_nested_conflict] %11 : $*Int64
+  %13 = struct_element_addr %12 : $*Int64, #Int64._value
+  %14 = load %13 : $*Builtin.Int64
+  end_access %12 : $*Int64
+  %16 = ref_element_addr %0 : $C, #C.internalProp
+  %17 = begin_access [read] [dynamic] [no_nested_conflict] %16 : $*Int64
+  %18 = struct_element_addr %17 : $*Int64, #Int64._value
+  %19 = load %18 : $*Builtin.Int64
+  end_access %17 : $*Int64
+  %21 = ref_element_addr %0 : $C, #C.keyPathProp
+  %22 = begin_access [read] [dynamic] [no_nested_conflict] %21 : $*Int64
+  %23 = struct_element_addr %22 : $*Int64, #Int64._value
+  %24 = load %23 : $*Builtin.Int64
+  end_access %22 : $*Int64
+  %26 = ref_element_addr %0 : $C, #C.finalKeyPathProp
+  %27 = begin_access [read] [dynamic] [no_nested_conflict] %26 : $*Int64
+  %28 = struct_element_addr %27 : $*Int64, #Int64._value
+  %29 = load %28 : $*Builtin.Int64
+  end_access %27 : $*Int64
+  %31 = ref_element_addr %0 : $C, #C.publicProp
+  %32 = begin_access [read] [dynamic] [no_nested_conflict] %31 : $*Int64
+  %33 = struct_element_addr %32 : $*Int64, #Int64._value
+  %34 = load %33 : $*Builtin.Int64
+  end_access %32 : $*Int64
+  %36 = tuple ()
+  return %36 : $()
+} // end sil function '$S10access_wmo8readProp1cyAA1CC_tF'
+
+// testAccessProp(c:v:)
+// CHECK-LABEL: sil @$S10access_wmo14testAccessProp1c1vyAA1CC_SitF : $@convention(thin) (@guaranteed C, Int64) -> () {
+// CHECK: bb0(%0 : $C, %1 : $Int64):
+// CHECK: [[E1:%.*]] = ref_element_addr %0 : $C, #C.setterProp
+// CHECK: begin_access [modify] [static] [no_nested_conflict] [[E1]] : $*Int64
+// CHECK: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// CHECK: begin_access [modify] [static] [no_nested_conflict] [[E2]] : $*Int64
+// CHECK: [[E3:%.*]] = ref_element_addr %0 : $C, #C.inlinedProp
+// CHECK: begin_unpaired_access [modify] [dynamic] [[E3]] : $*Int64, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// CHECK: [[E4:%.*]] = ref_element_addr %0 : $C, #C.internalProp
+// CHECK: begin_unpaired_access [modify] [dynamic] [[E4]] : $*Int64, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// CHECK: keypath $ReferenceWritableKeyPath<C, Int64>, (root $C; settable_property $Int64,  id #C.keyPathProp!getter.1 : (C) -> () -> Int64, getter @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int64, setter @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int64, @in_guaranteed C) -> ())
+// CHECK: keypath $ReferenceWritableKeyPath<C, Int64>, (root $C; stored_property #C.finalKeyPathProp : $Int64)
+// CHECK: [[E5:%.*]] = ref_element_addr %0 : $C, #C.publicProp
+// CHECK: begin_unpaired_access [modify] [dynamic] [[E5]] : $*Int64, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// CHECK-LABEL: } // end sil function '$S10access_wmo14testAccessProp1c1vyAA1CC_SitF'
+sil @$S10access_wmo14testAccessProp1c1vyAA1CC_SitF : $@convention(thin) (@guaranteed C, Int64) -> () {
+bb0(%0 : $C, %1 : $Int64):
+  %2 = ref_element_addr %0 : $C, #C.setterProp
+  %3 = begin_access [modify] [dynamic] [no_nested_conflict] %2 : $*Int64
+  store %1 to %3 : $*Int64
+  end_access %3 : $*Int64
+  %6 = ref_element_addr %0 : $C, #C.finalProp
+  %7 = begin_access [modify] [dynamic] [no_nested_conflict] %6 : $*Int64
+  // function_ref setInt(_:_:)
+  %8 = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int64, Int64) -> ()
+  %9 = apply %8(%7, %1) : $@convention(thin) (@inout Int64, Int64) -> ()
+  end_access %7 : $*Int64
+  %11 = alloc_stack $Builtin.UnsafeValueBuffer
+  %12 = ref_element_addr %0 : $C, #C.inlinedProp
+  begin_unpaired_access [modify] [dynamic] %12 : $*Int64, %11 : $*Builtin.UnsafeValueBuffer
+  %14 = mark_dependence %12 : $*Int64 on %0 : $C
+  store %1 to %14 : $*Int64
+  end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer
+  dealloc_stack %11 : $*Builtin.UnsafeValueBuffer
+  %18 = alloc_stack $Builtin.UnsafeValueBuffer
+  %19 = ref_element_addr %0 : $C, #C.internalProp
+  begin_unpaired_access [modify] [dynamic] %19 : $*Int64, %18 : $*Builtin.UnsafeValueBuffer
+  %21 = mark_dependence %19 : $*Int64 on %0 : $C
+  %22 = apply %8(%21, %1) : $@convention(thin) (@inout Int64, Int64) -> ()
+  end_unpaired_access [dynamic] %18 : $*Builtin.UnsafeValueBuffer
+  dealloc_stack %18 : $*Builtin.UnsafeValueBuffer
+  %25 = keypath $ReferenceWritableKeyPath<C, Int64>, (root $C; settable_property $Int64,  id #C.keyPathProp!getter.1 : (C) -> () -> Int64, getter @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int64, setter @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int64, @in_guaranteed C) -> ())
+  // function_ref setKeyPath(_:_:_:)
+  %26 = function_ref @$S10access_wmo10setKeyPathyyAA1CC_s017ReferenceWritabledE0CyADSiGSitF : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int64>, Int64) -> ()
+  %27 = apply %26(%0, %25, %1) : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int64>, Int64) -> ()
+  strong_release %25 : $ReferenceWritableKeyPath<C, Int64>
+  %29 = keypath $ReferenceWritableKeyPath<C, Int64>, (root $C; stored_property #C.finalKeyPathProp : $Int64)
+  %30 = apply %26(%0, %29, %1) : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int64>, Int64) -> ()
+  strong_release %29 : $ReferenceWritableKeyPath<C, Int64>
+  %32 = alloc_stack $Builtin.UnsafeValueBuffer
+  %33 = ref_element_addr %0 : $C, #C.publicProp
+  begin_unpaired_access [modify] [dynamic] %33 : $*Int64, %32 : $*Builtin.UnsafeValueBuffer
+  %35 = mark_dependence %33 : $*Int64 on %0 : $C
+  %36 = apply %8(%35, %1) : $@convention(thin) (@inout Int64, Int64) -> ()
+  end_unpaired_access [dynamic] %32 : $*Builtin.UnsafeValueBuffer
+  dealloc_stack %32 : $*Builtin.UnsafeValueBuffer
+  %39 = tuple ()
+  return %39 : $()
+} // end sil function '$S10access_wmo14testAccessProp1c1vyAA1CC_SitF'
+
+// key path getter for C.keyPathProp : C
+//
+// CHECK-LABEL: sil shared [thunk] @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int64 {
+// CHECK: begin_access [read] [static] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC11keyPathPropSivpACTK'
+sil shared [thunk] @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int64 {
+bb0(%0 : $*Int64, %1 : $*C):
+  %2 = load %1 : $*C                              // user: %3
+  %3 = ref_element_addr %2 : $C, #C.keyPathProp   // user: %4
+  %4 = begin_access [read] [dynamic] [no_nested_conflict] %3 : $*Int64 // users: %6, %5
+  %5 = load %4 : $*Int64                          // user: %7
+  end_access %4 : $*Int64                         // id: %6
+  store %5 to %0 : $*Int64                        // id: %7
+  %8 = tuple ()                                   // user: %9
+  return %8 : $()                                 // id: %9
+} // end sil function '$S10access_wmo1CC11keyPathPropSivpACTK'
+
+// key path setter for C.keyPathProp : C
+//
+// CHECK-LABEL: sil shared [thunk] @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int64, @in_guaranteed C) -> () {
+// CHECK: begin_access [modify] [static] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC11keyPathPropSivpACTk'
+sil shared [thunk] @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int64, @in_guaranteed C) -> () {
+bb0(%0 : $*Int64, %1 : $*C):
+  %2 = load %0 : $*Int64                          // user: %6
+  %3 = load %1 : $*C                              // user: %4
+  %4 = ref_element_addr %3 : $C, #C.keyPathProp   // user: %5
+  %5 = begin_access [modify] [dynamic] [no_nested_conflict] %4 : $*Int64 // users: %7, %6
+  store %2 to %5 : $*Int64                        // id: %6
+  end_access %5 : $*Int64                         // id: %7
+  %8 = tuple ()                                   // user: %9
+  return %8 : $()                                 // id: %9
+} // end sil function '$S10access_wmo1CC11keyPathPropSivpACTk'
+
+// C.keyPathProp.getter
+// CHECK-LABEL: sil hidden [transparent] @$S10access_wmo1CC11keyPathPropSivg : $@convention(method) (@guaranteed C) -> Int64 {
+// CHECK: begin_access [read] [static] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC11keyPathPropSivg'
+sil hidden [transparent] @$S10access_wmo1CC11keyPathPropSivg : $@convention(method) (@guaranteed C) -> Int64 {
+// %0
+bb0(%0 : $C):
+  %1 = ref_element_addr %0 : $C, #C.keyPathProp   // user: %2
+  %2 = begin_access [read] [dynamic] [no_nested_conflict] %1 : $*Int64 // users: %4, %3
+  %3 = load %2 : $*Int64                          // user: %5
+  end_access %2 : $*Int64                         // id: %4
+  return %3 : $Int64                              // id: %5
+} // end sil function '$S10access_wmo1CC11keyPathPropSivg'
+
+// variable initialization expression of C.publicProp
+sil [transparent] @$S10access_wmo1CC10publicPropSivpfi : $@convention(thin) () -> Int64 {
+bb0:
+  %0 = integer_literal $Builtin.Int64, 0
+  %1 = struct $Int64 (%0 : $Builtin.Int64)
+  return %1 : $Int64
+} // end sil function '$S10access_wmo1CC10publicPropSivpfi'
+
+// C.publicProp.getter
+//
+// CHECK-LABEL: sil [transparent] @$S10access_wmo1CC10publicPropSivg : $@convention(method) (@guaranteed C) -> Int64 {
+// CHECK: begin_access [read] [dynamic] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC10publicPropSivg'
+sil [transparent] @$S10access_wmo1CC10publicPropSivg : $@convention(method) (@guaranteed C) -> Int64 {
+// %0
+bb0(%0 : $C):
+  %1 = ref_element_addr %0 : $C, #C.publicProp    // user: %2
+  %2 = begin_access [read] [dynamic] [no_nested_conflict] %1 : $*Int64 // users: %4, %3
+  %3 = load %2 : $*Int64                          // user: %5
+  end_access %2 : $*Int64                         // id: %4
+  return %3 : $Int64                              // id: %5
+} // end sil function '$S10access_wmo1CC10publicPropSivg'
+
+// C.publicProp.setter
+// CHECK-LABEL: sil [transparent] @$S10access_wmo1CC10publicPropSivs : $@convention(method) (Int64, @guaranteed C) -> () {
+// CHECK: bb0(%0 : $Int64, %1 : $C):
+// CHECK: begin_access [modify] [dynamic] [no_nested_conflict] %{{.*}} : $*Int64
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC10publicPropSivs'
+sil [transparent] @$S10access_wmo1CC10publicPropSivs : $@convention(method) (Int64, @guaranteed C) -> () {
+bb0(%0 : $Int64, %1 : $C):
+  %2 = ref_element_addr %1 : $C, #C.publicProp    // user: %3
+  %3 = begin_access [modify] [dynamic] [no_nested_conflict] %2 : $*Int64 // users: %5, %4
+  store %0 to %3 : $*Int64                        // id: %4
+  end_access %3 : $*Int64                         // id: %5
+  %6 = tuple ()                                   // user: %7
+  return %6 : $()                                 // id: %7
+} // end sil function '$S10access_wmo1CC10publicPropSivs'
+
+// closure #1 in C.publicProp.materializeForSet
+sil shared [transparent] @$S10access_wmo1CC10publicPropSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed C, @thick C.Type) -> () {
+bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*C, %3 : $@thick C.Type):
+  end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
+  %5 = tuple ()
+  return %5 : $()
+} // end sil function '$S10access_wmo1CC10publicPropSivmytfU_'
+
+// C.publicProp.materializeForSet
+// CHECK-LABEL: sil [transparent] @$S10access_wmo1CC10publicPropSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed C) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: begin_unpaired_access [modify] [dynamic] %{{.*}} : $*Int64, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// CHECK-LABEL: } // end sil function '$S10access_wmo1CC10publicPropSivm'
+sil [transparent] @$S10access_wmo1CC10publicPropSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed C) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $C):
+  %3 = ref_element_addr %2 : $C, #C.publicProp
+  begin_unpaired_access [modify] [dynamic] %3 : $*Int64, %1 : $*Builtin.UnsafeValueBuffer
+  %5 = address_to_pointer %3 : $*Int64 to $Builtin.RawPointer
+  // function_ref closure #1 in C.publicProp.materializeForSet
+  %6 = function_ref @$S10access_wmo1CC10publicPropSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed C, @thick C.Type) -> ()
+  %7 = thin_function_to_pointer %6 : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed C, @thick C.Type) -> () to $Builtin.RawPointer
+  %8 = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, %7 : $Builtin.RawPointer
+  %9 = tuple (%5 : $Builtin.RawPointer, %8 : $Optional<Builtin.RawPointer>)
+  return %9 : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+} // end sil function '$S10access_wmo1CC10publicPropSivm'
diff --git a/test/SILOptimizer/access_wmo.swift b/test/SILOptimizer/access_wmo.swift
new file mode 100644
index 0000000..d9612b4
--- /dev/null
+++ b/test/SILOptimizer/access_wmo.swift
@@ -0,0 +1,242 @@
+// RUN: %target-swift-frontend -parse-as-library -emit-sil -enforce-exclusivity=checked -O -primary-file %s %S/Inputs/access_wmo_def.swift | %FileCheck %s --check-prefix=PRIMARY
+// RUN: %target-swift-frontend -parse-as-library -emit-sil -enforce-exclusivity=checked -O %s %S/Inputs/access_wmo_def.swift | %FileCheck %s --check-prefix=WMO
+
+// ===---------------------------------------------------------------------===//
+// testAccessGlobal: Access a global defined in another file.
+//
+// In -primary-file mode, all begin_access markers remain dynamic.
+//
+// With WMO, only the begin_access markers for the internal global should be
+// promoted to static.
+// ===---------------------------------------------------------------------===//
+
+// readGlobal():
+// PRIMARY-LABEL: sil @$S10access_wmo10readGlobalSiyF : $@convention(thin) () -> Int {
+// function_ref internalGlobal.unsafeMutableAddressor
+// PRIMARY: [[F1:%.*]] = function_ref @$S10access_wmo14internalGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[G1:%.*]] = apply [[F1]]() : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[P1:%.*]] = pointer_to_address [[G1]] : $Builtin.RawPointer to [strict] $*Int
+// PRIMARY: [[A1:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[P1]] : $*Int
+// PRIMARY: end_access [[A1]] : $*Int
+// function_ref publicGlobal.unsafeMutableAddressor
+// PRIMARY: [[F2:%.*]] = function_ref @$S10access_wmo12publicGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[G2:%.*]] = apply [[F2]]() : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[P2:%.*]] = pointer_to_address [[G2]] : $Builtin.RawPointer to [strict] $*Int
+// PRIMARY: [[A2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[P2]] : $*Int
+// PRIMARY: end_access [[A2]] : $*Int
+// PRIMARY-LABEL: } // end sil function '$S10access_wmo10readGlobalSiyF'
+//
+// WMO-LABEL: sil @$S10access_wmo10readGlobalSiyF : $@convention(thin) () -> Int {
+// WMO: [[G1:%.*]] = global_addr @$S10access_wmo14internalGlobalSivp : $*Int
+// WMO: [[A1:%.*]] = begin_access [read] [static] [no_nested_conflict] [[G1]] : $*Int
+// WMO: end_access [[A1]] : $*Int
+// WMO: [[G2:%.*]] = global_addr @$S10access_wmo12publicGlobalSivp : $*Int
+// WMO: [[A2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[G2]] : $*Int
+// WMO: end_access [[A2]] : $*Int
+// WMO-LABEL: } // end sil function '$S10access_wmo10readGlobalSiyF'
+public func readGlobal() -> Int {
+  return internalGlobal + publicGlobal
+}
+
+@inline(never)
+func setInt(_ i: inout Int, _ v: Int) {
+  i = v
+}
+
+func inlinedSetInt(_ i: inout Int, _ v: Int) {
+  i = v
+}
+
+// testAccessGlobal(v:)
+// PRIMARY-LABEL: sil @$S10access_wmo16testAccessGlobal1vySi_tF : $@convention(thin) (Int) -> () {
+// PRIMARY: bb0(%0 : $Int):
+//
+// function_ref internalGlobal.unsafeMutableAddressor
+// PRIMARY: [[F1:%.*]] = function_ref @$S10access_wmo14internalGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[G1:%.*]] = apply [[F1]]() : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[P1:%.*]] = pointer_to_address [[G1]] : $Builtin.RawPointer to [strict] $*Int
+// PRIMARY: [[A1:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[P1]] : $*Int
+// function_ref setInt(_:_:)
+// PRIMARY: [[F2:%.*]] = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: apply [[F2]]([[A1]], %0) : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: end_access [[A1]] : $*Int
+//
+// function_ref publicGlobal.unsafeMutableAddressor
+// PRIMARY: [[F3:%.*]] = function_ref @$S10access_wmo12publicGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[G2:%.*]] = apply [[F3]]() : $@convention(thin) () -> Builtin.RawPointer
+// PRIMARY: [[P2:%.*]] = pointer_to_address [[G2]] : $Builtin.RawPointer to [strict] $*Int
+// PRIMARY: [[A2:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[P2]] : $*Int
+// PRIMARY: apply [[F2]]([[A2]], %0) : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: end_access [[A2]] : $*Int
+// PRIMARY-LABEL: } // end sil function '$S10access_wmo16testAccessGlobal1vySi_tF'
+//
+// WMO-LABEL: sil @$S10access_wmo16testAccessGlobal1vySi_tF : $@convention(thin) (Int) -> () {
+// WMO: bb0(%0 : $Int):
+// WMO: [[G1:%.*]] = global_addr @$S10access_wmo14internalGlobalSivp : $*Int
+// WMO: [[A1:%.*]] = begin_access [modify] [static] [no_nested_conflict] [[G1]] : $*Int
+// function_ref setInt(_:_:)
+// WMO: [[F:%.*]] = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: apply [[F]]([[A1]], %0) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_access [[A1]] : $*Int
+//
+// WMO: [[G2:%.*]] = global_addr @$S10access_wmo12publicGlobalSivp : $*Int
+// WMO: [[A2:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[G2]] : $*Int
+// function_ref setInt(_:_:)
+// WMO: apply [[F]]([[A2]], %0) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_access [[A2]] : $*Int
+// WMO-LABEL: } // end sil function '$S10access_wmo16testAccessGlobal1vySi_tF'
+public func testAccessGlobal(v: Int) {
+  setInt(&internalGlobal, v)
+  setInt(&publicGlobal, v)
+}
+
+@inline(never)
+func setKeyPath(_ c: C, _ kp: ReferenceWritableKeyPath<C, Int>, _ v: Int) {
+  c[keyPath: kp] = v
+}
+
+// ===---------------------------------------------------------------------===//
+// testAccessProp: Access a class property defined in another file.
+//
+// In -primary-file mode, all nonfinal access is behind
+// getter, setter, or materializeForSet calls. The final access remains
+// dynamic because the property is "visibleExternally". i.e. the compiler can't
+// see how other files are using it.
+// 
+// With WMO...
+//
+// access to setterProp and finalProp are promoted to static.
+// setterProp is a setter call, and finalProp is non-polymorphic.
+//
+// inlinedProp and internalProp could be also be promoted to static, but are
+// accessed via begin_unpaired_access in materializeForSet. (When the class
+// definition is in another file, the compiler unfortunately and unnecessarilly
+// generates materializeForSet calls even in "wmo" mode). These unpaired access
+// cannot (easily) be marked [no_nested_conflict]. Failing to mark the modify
+// as [no_nested_access] in turn inhibits optimization of the property reads.
+// Rather than teach the WMO to handle unpaired access, better solutions would
+// be either:
+//
+// - The inlinedProp case could be handled with a separate pass that promotes
+//   obvious unpaired access patterns to regular scoped access.
+//
+// - To handle internalProp SILGen could stop using materializeForSet for
+//   stored properties:
+//
+// See <rdar://problem/41302183> [exclusivity] Optimize formal access from
+// inlined materializeForSet.
+//
+// keyPathProp is promoted to static enforcement because a settable_property
+// keypath can only be formally accessed within the getter and setter, which
+// the compiler can already see.
+//
+// Perversely, finalKeyPathProp *cannot* be promoted to static enforcement
+// because a storedProperty keypath is formed. The compiler does not currently
+// attempt to track down all uses of a storedProperty keypath. The actual
+// access occurs via a Builtin that takes a RawPointer. The formation of a
+// stored_property keypath is always conservatively considered a possible
+// nested access.
+// ===---------------------------------------------------------------------===//
+public func readProp(c: C) -> Int {
+  return c.setterProp + c.finalProp + c.inlinedProp + c.internalProp
+  + c.keyPathProp + c.finalKeyPathProp + c.publicProp
+}
+public func testAccessProp(c: C, v: Int) {
+  c.setterProp = v
+  setInt(&c.finalProp, v)
+  inlinedSetInt(&c.inlinedProp, v)
+  setInt(&c.internalProp, v)
+  setKeyPath(c, \C.keyPathProp, v)
+  setKeyPath(c, \C.finalKeyPathProp, v)
+  setInt(&c.publicProp, v)
+}
+
+// PRIMARY-LABEL: sil @$S10access_wmo8readProp1cSiAA1CC_tF : $@convention(thin) (@guaranteed C) -> Int {
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY: [[E1:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// PRIMARY: [[A1:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E1]] : $*Int
+// PRIMARY: end_access [[A1]] : $*Int
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalKeyPathProp
+// PRIMARY: [[A2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E2]] : $*Int
+// PRIMARY: end_access [[A2]] : $*Int
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY-LABEL:  } // end sil function '$S10access_wmo8readProp1cSiAA1CC_tF'
+//
+// WMO-LABEL: sil @$S10access_wmo8readProp1cSiAA1CC_tF : $@convention(thin) (@guaranteed C) -> Int {
+// WMO: [[E1:%.*]] = ref_element_addr %0 : $C, #C.setterProp
+// WMO: [[A1:%.*]] = begin_access [read] [static] [no_nested_conflict] [[E1]] : $*Int
+// WMO: end_access [[A1]] : $*Int
+//
+// WMO: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// WMO: [[A2:%.*]] = begin_access [read] [static] [no_nested_conflict] [[E2]] : $*Int
+// WMO: end_access [[A2]] : $*Int
+//
+// WMO: [[E3:%.*]] = ref_element_addr %0 : $C, #C.inlinedProp
+// WMO: [[A3:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E3]] : $*Int
+// WMO: end_access [[A3]] : $*Int
+//
+// WMO: [[E4:%.*]] = ref_element_addr %0 : $C, #C.internalProp
+// WMO: [[A4:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E4]] : $*Int
+// WMO: end_access [[A4]] : $*Int
+//
+// WMO: [[E5:%.*]] = ref_element_addr %0 : $C, #C.keyPathProp
+// WMO: [[A5:%.*]] = begin_access [read] [static] [no_nested_conflict] [[E5]] : $*Int
+// WMO: end_access [[A5]] : $*Int
+//
+// WMO: [[E6:%.*]] = ref_element_addr %0 : $C, #C.finalKeyPathProp
+// WMO: [[A6:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E6]] : $*Int
+// WMO: end_access [[A6]] : $*Int
+//
+// WMO: [[E7:%.*]] = ref_element_addr %0 : $C, #C.publicProp
+// WMO: [[A7:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[E7]] : $*Int
+// WMO: end_access [[A7]] : $*Int
+// WMO-LABEL: } // end sil function '$S10access_wmo8readProp1cSiAA1CC_tF'
+
+// PRIMARY-LABEL: sil @$S10access_wmo14testAccessProp1c1vyAA1CC_SitF : $@convention(thin) (@guaranteed C, Int) -> () {
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY: [[E1:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// PRIMARY: [[A1:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[E1]] : $*Int
+// function_ref setInt(_:_:)
+// PRIMARY: [[F1:%.*]] = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: apply [[F1]]([[A1]], %1) : $@convention(thin) (@inout Int, Int) -> ()
+// PRIMARY: end_access [[A1]] : $*Int
+// PRIMARY-NOT: begin_{{.*}}access
+// PRIMARY-LABEL: } // end sil function '$S10access_wmo14testAccessProp1c1vyAA1CC_SitF'
+
+// WMO-LABEL: sil @$S10access_wmo14testAccessProp1c1vyAA1CC_SitF : $@convention(thin) (@guaranteed C, Int) -> () {
+// WMO: [[E1:%.*]] = ref_element_addr %0 : $C, #C.setterProp
+// WMO: [[A1:%.*]] = begin_access [modify] [static] [no_nested_conflict] [[E1]] : $*Int
+// WMO: end_access [[A1]] : $*Int
+//
+// WMO: [[E2:%.*]] = ref_element_addr %0 : $C, #C.finalProp
+// WMO: [[A2:%.*]] = begin_access [modify] [static] [no_nested_conflict] [[E2]] : $*Int
+// function_ref setInt(_:_:)
+// WMO: [[F1:%.*]] = function_ref @$S10access_wmo6setIntyySiz_SitF : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: apply [[F1]]([[A2]], %1) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_access [[A2]] : $*Int
+//
+// WMO: [[E3:%.*]] = ref_element_addr %0 : $C, #C.inlinedProp
+// WMO: begin_unpaired_access [modify] [dynamic] [[E3]] : $*Int, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// WMO: end_unpaired_access [dynamic] %{{.*}} : $*Builtin.UnsafeValueBuffer
+//
+// WMO: [[E4:%.*]] = ref_element_addr %0 : $C, #C.internalProp
+// WMO: begin_unpaired_access [modify] [dynamic] [[E4]] : $*Int, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// WMO: [[D4:%.*]] = mark_dependence [[E4]] : $*Int on %0 : $C
+// WMO: apply [[F1]]([[D4]], %1) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_unpaired_access [dynamic] %{{.*}} : $*Builtin.UnsafeValueBuffer
+//
+// WMO: [[KP:%.*]] = keypath $ReferenceWritableKeyPath<C, Int>, (root $C; settable_property $Int,  id #C.keyPathProp!getter.1 : (C) -> () -> Int, getter @$S10access_wmo1CC11keyPathPropSivpACTK : $@convention(thin) (@in_guaranteed C) -> @out Int, setter @$S10access_wmo1CC11keyPathPropSivpACTk : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ())
+// function_ref setKeyPath(_:_:_:)
+// WMO: [[F2:%.*]] = function_ref @$S10access_wmo10setKeyPathyyAA1CC_s017ReferenceWritabledE0CyADSiGSitF : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int>, Int) -> ()
+// WMO: apply [[F2]](%0, [[KP]], %1) : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int>, Int) -> ()
+//
+// WMO: [[FKP:%.*]] = keypath $ReferenceWritableKeyPath<C, Int>, (root $C; stored_property #C.finalKeyPathProp : $Int)
+// WMO: apply [[F2]](%0, [[FKP]], %1) : $@convention(thin) (@guaranteed C, @guaranteed ReferenceWritableKeyPath<C, Int>, Int) -> ()
+//
+// WMO: [[E4:%.*]] = ref_element_addr %0 : $C, #C.publicProp
+// WMO: begin_unpaired_access [modify] [dynamic] [[E4]] : $*Int, %{{.*}} : $*Builtin.UnsafeValueBuffer
+// WMO: [[D4:%.*]] = mark_dependence [[E4]] : $*Int on %0 : $C
+// WMO: apply [[F1]]([[D4]], %1) : $@convention(thin) (@inout Int, Int) -> ()
+// WMO: end_unpaired_access [dynamic] %{{.*}} : $*Builtin.UnsafeValueBuffer
+// WMO-LABEL: } // end sil function '$S10access_wmo14testAccessProp1c1vyAA1CC_SitF'
diff --git a/test/SILOptimizer/access_wmo_diagnose.swift b/test/SILOptimizer/access_wmo_diagnose.swift
new file mode 100644
index 0000000..018bdcd
--- /dev/null
+++ b/test/SILOptimizer/access_wmo_diagnose.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend -parse-as-library -emit-sil -enforce-exclusivity=checked -primary-file %s -o /dev/null -verify
+
+// AccessEnforcementWMO assumes that the only way to address a global or static
+// property is via a formal begin_access. If we ever allow keypaths for static
+// properties, which I think is conceivable, then this test will fail to produce
+// a diagnostic error and AccessEnforcementWMO must be fixed to handle "meta"
+// keypaths.
+public class C {
+  public static var globalProp: Int = 0
+}
+
+public func testGlobalProp() {
+  let a: AnyKeyPath = \C.globalProp // expected-error{{type of expression is ambiguous without more context}}
+}
diff --git a/test/SILOptimizer/array_mutable_assertonly.swift b/test/SILOptimizer/array_mutable_assertonly.swift
index cddf041..013cd3b0 100644
--- a/test/SILOptimizer/array_mutable_assertonly.swift
+++ b/test/SILOptimizer/array_mutable_assertonly.swift
@@ -87,6 +87,7 @@
 // TEST6-LABEL: COW Array Opts in Func {{.*}}test2DArrayLoop{{.*}}
 // TEST6:        Array Opts in Loop Loop at depth 2
 // TEST6-NOT:   COW Array Opts in
+// TEST6:        Hoisting make_mutable
 // TEST6:        Array Opts in Loop Loop at depth 1
 // TEST6-NOT:   COW Array Opts in
 // TEST6:        Hoisting make_mutable
diff --git a/test/SILOptimizer/exclusivity_static_diagnostics.sil b/test/SILOptimizer/exclusivity_static_diagnostics.sil
index 4bb8a33..81b8a22 100644
--- a/test/SILOptimizer/exclusivity_static_diagnostics.sil
+++ b/test/SILOptimizer/exclusivity_static_diagnostics.sil
@@ -1022,3 +1022,25 @@
   %9999 = tuple()
   return %9999 : $()
 }
+
+sil @addressor : $@convention(thin) () -> UnsafeMutablePointer<Int32>
+
+// An addressor produces an unsafely accessed RawPointer. Pass the
+// address to an inout can result in an enforced (unknown) access on
+// the unsafe address. We need to handle this case without asserting.
+sil @addressorAccess : $@convention(thin) (@guaranteed ClassWithStoredProperty, Int32) -> () {
+bb0(%0 : $ClassWithStoredProperty, %1 : $Int32):
+  %f = function_ref @addressor : $@convention(thin) () -> UnsafeMutablePointer<Int32>
+  %up = apply %f() : $@convention(thin) () -> UnsafeMutablePointer<Int32>
+  %o = unchecked_ref_cast %0 : $ClassWithStoredProperty to $Builtin.NativeObject
+  %ptr = struct_extract %up : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
+  %adr = pointer_to_address %ptr : $Builtin.RawPointer to [strict] $*Int32
+  %dep = mark_dependence %adr : $*Int32 on %o : $Builtin.NativeObject
+  %a1 = begin_access [modify] [unsafe] %dep : $*Int32
+  %a2 = begin_access [modify] [static] %a1 : $*Int32
+  store %1 to [trivial] %a2 : $*Int32
+  end_access %a2 : $*Int32
+  end_access %a1 : $*Int32
+  %v = tuple ()
+  return %v : $()
+}
diff --git a/test/SILOptimizer/licm_exclusivity.swift b/test/SILOptimizer/licm_exclusivity.swift
index 335b738..93cbc9c 100644
--- a/test/SILOptimizer/licm_exclusivity.swift
+++ b/test/SILOptimizer/licm_exclusivity.swift
@@ -1,7 +1,7 @@
 // RUN: %target-swift-frontend -O -enforce-exclusivity=checked -emit-sil -Xllvm -debug-only=sil-licm -primary-file %s 2>&1 | %FileCheck %s --check-prefix=TEST1
 // RUN: %target-swift-frontend -O -enforce-exclusivity=checked -emit-sil -Xllvm -debug-only=sil-licm  -primary-file %s 2>&1 | %FileCheck %s --check-prefix=TEST2
 // RUN: %target-swift-frontend -O -enforce-exclusivity=checked -emit-sil  -primary-file %s | %FileCheck %s --check-prefix=TESTSIL
-// REQUIRES: optimized_stdlib
+// REQUIRES: optimized_stdlib,asserts
 
 // TEST1-LABEL: Processing loops in {{.*}}run_ReversedArray{{.*}}
 // TEST1: Hoist and Sink pairs attempt
diff --git a/test/Sema/diag_ownership_lazy.swift b/test/Sema/diag_ownership_lazy.swift
index 3c07322..bffa394 100644
--- a/test/Sema/diag_ownership_lazy.swift
+++ b/test/Sema/diag_ownership_lazy.swift
@@ -6,7 +6,13 @@
 
   lazy weak var weakValue = LazyReferenceClass()
   // expected-error@-1 {{lazy properties cannot be 'weak'}}
+  // expected-warning@-2 {{instance will be immediately deallocated because property 'weakValue' is 'weak'}}
+  // expected-note@-3 {{'weakValue' declared here}}
+  // expected-note@-4 {{a strong reference is required to prevent the instance from being deallocated}}
 
   unowned lazy var unownedValue = LazyReferenceClass()
   // expected-error@-1 {{lazy properties cannot be 'unowned'}}
+  // expected-warning@-2 {{instance will be immediately deallocated because property 'unownedValue' is 'unowned'}}
+  // expected-note@-3 {{'unownedValue' declared here}}
+  // expected-note@-4 {{a strong reference is required to prevent the instance from being deallocated}}
 }
diff --git a/test/TBD/class.swift b/test/TBD/class.swift
index 5c1a750..d7e77cf 100644
--- a/test/TBD/class.swift
+++ b/test/TBD/class.swift
@@ -1,24 +1,29 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -O %s
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -O %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
 
 open class OpenNothing {}
 
 open class OpenInit {
     public init() {}
-    public init(public_: Int) {}
+    public init(public_: Int, default_: Int = 0) {}
 
-    internal init(internal_: Int) {}
+    internal init(internal_: Int, default_: Int = 0) {}
 
     deinit {}
 }
 
 open class OpenMethods {
     public init() {}
-    public func publicMethod() {}
-    internal func internalMethod() {}
-    private func privateMethod() {}
+    public func publicMethod(default_: Int = 0) {}
+    internal func internalMethod(default_: Int = 0) {}
+    private func privateMethod(default_: Int = 0) {}
 }
 
 open class OpenProperties {
@@ -49,9 +54,9 @@
 }
 
 open class OpenStatics {
-    public static func publicStaticFunc() {}
-    internal static func internalStaticFunc() {}
-    private static func privateStaticFunc() {}
+    public static func publicStaticFunc(default_: Int = 0) {}
+    internal static func internalStaticFunc(default_: Int = 0) {}
+    private static func privateStaticFunc(default_: Int = 0) {}
 
     public static let publicLet: Int = 0
     internal static let internalLet: Int = 0
@@ -107,18 +112,18 @@
 
 public class PublicInit {
     public init() {}
-    public init(public_: Int) {}
+    public init(public_: Int, default_: Int = 0) {}
     
-    internal init(internal_: Int) {}
+    internal init(internal_: Int, default_: Int = 0) {}
 
     deinit {}
 }
 
 public class PublicMethods {
     public init() {}
-    public func publicMethod() {}
-    internal func internalMethod() {}
-    private func privateMethod() {}
+    public func publicMethod(default_: Int = 0) {}
+    internal func internalMethod(default_: Int = 0) {}
+    private func privateMethod(default_: Int = 0) {}
 }
 
 public class PublicProperties {
@@ -149,9 +154,9 @@
 }
 
 public class PublicStatics {
-    public static func publicStaticFunc() {}
-    internal static func internalStaticFunc() {}
-    private static func privateStaticFunc() {}
+    public static func publicStaticFunc(default_: Int = 0) {}
+    internal static func internalStaticFunc(default_: Int = 0) {}
+    private static func privateStaticFunc(default_: Int = 0) {}
 
     public static let publicLet: Int = 0
     internal static let internalLet: Int = 0
@@ -188,19 +193,19 @@
   internal var internalVarConcrete: Int = 0
   private var privateVarConcrete: Int = 0
 
-  public init<S>(t: T, u: U, v: V, _: S) {
+  public init<S>(t: T, u: U, v: V, _: S, default_: Int = 0) {
     publicVar = t
     internalVar = u
     privateVar = v
   }
 
-  public func publicGeneric<A>(_: A) {}
-  internal func internalGeneric<A>(_: A) {}
-  private func privateGeneric<A>(_: A) {}
+  public func publicGeneric<A>(_: A, default_: Int = 0) {}
+  internal func internalGeneric<A>(_: A, default_: Int = 0) {}
+  private func privateGeneric<A>(_: A, default_: Int = 0) {}
 
-  public static func publicStaticGeneric<A>(_: A) {}
-  internal static func internalStaticGeneric<A>(_: A) {}
-  private static func privateStaticGeneric<A>(_: A) {}
+  public static func publicStaticGeneric<A>(_: A, default_: Int = 0) {}
+  internal static func internalStaticGeneric<A>(_: A, default_: Int = 0) {}
+  private static func privateStaticGeneric<A>(_: A, default_: Int = 0) {}
 }
 
 
@@ -208,14 +213,14 @@
 
 internal class InternalInit {
     internal init() {}
-    internal init(internal_: Int) {}
-    private init(private_: Int) {}
+    internal init(internal_: Int, default_: Int = 0) {}
+    private init(private_: Int, default_: Int = 0) {}
 }
 
 internal class InternalMethods {
     internal init() {}
-    internal func internalMethod() {}
-    private func privateMethod() {}
+    internal func internalMethod(default_: Int = 0) {}
+    private func privateMethod(default_: Int = 0) {}
 }
 
 internal class InternalProperties {
@@ -239,8 +244,8 @@
 }
 
 internal class InternalStatics {
-    internal static func internalStaticFunc() {}
-    private static func privateStaticFunc() {}
+    internal static func internalStaticFunc(default_: Int = 0) {}
+    private static func privateStaticFunc(default_: Int = 0) {}
 
     internal static let internalLet: Int = 0
     private static let privateLet: Int = 0
@@ -268,16 +273,16 @@
   internal var internalVarConcrete: Int = 0
   private var privateVarConcrete: Int = 0
 
-  internal init<S>(t: T, u: U, v: V, _: S) {
+  internal init<S>(t: T, u: U, v: V, _: S, default_: Int = 0) {
     internalVar = u
     privateVar = v
   }
 
-  internal func internalGeneric<A>(_: A) {}
-  private func privateGeneric<A>(_: A) {}
+  internal func internalGeneric<A>(_: A, default_: Int = 0) {}
+  private func privateGeneric<A>(_: A, default_: Int = 0) {}
 
-  internal static func internalStaticGeneric<A>(_: A) {}
-  private static func privateStaticGeneric<A>(_: A) {}
+  internal static func internalStaticGeneric<A>(_: A, default_: Int = 0) {}
+  private static func privateStaticGeneric<A>(_: A, default_: Int = 0) {}
 }
 
 
@@ -285,12 +290,12 @@
 
 private class PrivateInit {
     private init() {}
-    private init(private_: Int) {}
+    private init(private_: Int, default_: Int = 0) {}
 }
 
 private class PrivateMethods {
     private init() {}
-    private func privateMethod() {}
+    private func privateMethod(default_: Int = 0) {}
 }
 
 private class PrivateProperties {
@@ -307,7 +312,7 @@
 }
 
 private class PrivateStatics {
-    private static func privateStaticFunc() {}
+    private static func privateStaticFunc(default_: Int = 0) {}
 
     private static let privateLet: Int = 0
 
@@ -326,11 +331,11 @@
 
   private var privateVarConcrete: Int = 0
 
-  private init<S>(t: T, u: U, v: V, _: S) {
+  private init<S>(t: T, u: U, v: V, _: S, default_: Int = 0) {
     privateVar = v
   }
 
-  private func privateGeneric<A>(_: A) {}
+  private func privateGeneric<A>(_: A, default_: Int = 0) {}
 
-  private static func privateStaticGeneric<A>(_: A) {}
+  private static func privateStaticGeneric<A>(_: A, default_: Int = 0) {}
 }
diff --git a/test/TBD/class_objc.swift.gyb b/test/TBD/class_objc.swift.gyb
index ecc1277..61f59df 100644
--- a/test/TBD/class_objc.swift.gyb
+++ b/test/TBD/class_objc.swift.gyb
@@ -1,15 +1,23 @@
 // RUN: %empty-directory(%t)
 // RUN: %gyb %s > %t/main.swift
 
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module
 
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module -O
+
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module -O
 
 // With -enable-testing:
 
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing
 
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing -O
+
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=all %t/main.swift -disable-objc-attr-requires-foundation-module -enable-testing -O
 
 // REQUIRES: objc_interop
 
diff --git a/test/TBD/enum.swift b/test/TBD/enum.swift
index 28d49d5..c08f7a7 100644
--- a/test/TBD/enum.swift
+++ b/test/TBD/enum.swift
@@ -1,17 +1,25 @@
 // Swift 3:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
 // Swift 4:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -O
 
 // With -enable-testing:
 // Swift 3:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
 // Swift 4:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -swift-version 4 -enable-testing -O
 
 public protocol P {}
 
diff --git a/test/TBD/extension.swift.gyb b/test/TBD/extension.swift.gyb
index 23676d4..ac251e1 100644
--- a/test/TBD/extension.swift.gyb
+++ b/test/TBD/extension.swift.gyb
@@ -6,22 +6,30 @@
 // RUN: %target-build-swift %S/Inputs/extension_types.swift -module-name ExtensionTypes -emit-module -emit-module-path %t/types/ExtensionTypes.swiftmodule
 // This module is both not resilient:
 // RUN: %target-swift-frontend -emit-ir -o%t/not_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift
+// RUN: %target-swift-frontend -emit-ir -o%t/not_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -O
 // ... and resilient:
 // RUN: %target-swift-frontend -emit-ir -o%t/not_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-resilience
+// RUN: %target-swift-frontend -emit-ir -o%t/not_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-resilience -O
 // The same, but with -enable-testing:
 // RUN: %target-swift-frontend -emit-ir -o%t/not_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o%t/not_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-testing -O
 // RUN: %target-swift-frontend -emit-ir -o%t/not_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-resilience -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o%t/not_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=all -I %t/types %t/main.swift -enable-resilience -enable-testing -O
 
 // Other module is resilient:
 // RUN: %empty-directory(%t/types)
 // RUN: %target-build-swift %S/Inputs/extension_types.swift -module-name ExtensionTypes -emit-module -emit-module-path %t/types/ExtensionTypes.swiftmodule -Xfrontend -enable-resilience
 // This module is both not resilient:
 // RUN: %target-swift-frontend -emit-ir -o%t/resilient_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift
+// RUN: %target-swift-frontend -emit-ir -o%t/resilient_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -O
 // ... and resilient:
 // RUN: %target-swift-frontend -emit-ir -o%t/resilient_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-resilience
+// RUN: %target-swift-frontend -emit-ir -o%t/resilient_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-resilience -O
 // The same but with -enable-testing:
 // RUN: %target-swift-frontend -emit-ir -o%t/resilient_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o%t/resilient_not.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-testing -O
 // RUN: %target-swift-frontend -emit-ir -o%t/resilient_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-resilience -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o%t/resilient_resilient.ll -parse-as-library -module-name test -validate-tbd-against-ir=missing -I %t/types %t/main.swift -enable-resilience -enable-testing -O
 
 
 import ExtensionTypes
diff --git a/test/TBD/function.swift b/test/TBD/function.swift
index aed48e2..fda9187 100644
--- a/test/TBD/function.swift
+++ b/test/TBD/function.swift
@@ -1,7 +1,11 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s -enable-testing
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 3 %s -enable-testing -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=all -swift-version 4 %s -enable-testing -O
 
 public func publicNoArgs() {}
 public func publicSomeArgs(_: Int, x: Int) {}
diff --git a/test/TBD/global.swift b/test/TBD/global.swift
index 0a206c4..7866677 100644
--- a/test/TBD/global.swift
+++ b/test/TBD/global.swift
@@ -1,7 +1,11 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience -enable-testing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience -enable-testing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing -enable-resilience -enable-testing %s -O
 
 public let publicLet: Int = 0
 internal let internalLet: Int = 0
diff --git a/test/TBD/main.swift b/test/TBD/main.swift
index e62c8c0..b86b01b 100644
--- a/test/TBD/main.swift
+++ b/test/TBD/main.swift
@@ -1,3 +1,4 @@
-// RUN: %target-swift-frontend -emit-ir -o- -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -module-name test -validate-tbd-against-ir=all %s -O
 
 // Top-level code (i.e. implicit `main`) should be handled
diff --git a/test/TBD/protocol.swift b/test/TBD/protocol.swift
index a4b13e3..b7b752f 100644
--- a/test/TBD/protocol.swift
+++ b/test/TBD/protocol.swift
@@ -1,7 +1,12 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
 
 public protocol Public {
     func publicMethod()
diff --git a/test/TBD/struct.swift b/test/TBD/struct.swift
index fb7415a..893f0b2 100644
--- a/test/TBD/struct.swift
+++ b/test/TBD/struct.swift
@@ -1,7 +1,11 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-testing -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %s -enable-resilience -enable-testing -O
 
 public struct PublicNothing {}
 
diff --git a/test/TBD/subclass.swift.gyb b/test/TBD/subclass.swift.gyb
index 48406e3..4637400 100644
--- a/test/TBD/subclass.swift.gyb
+++ b/test/TBD/subclass.swift.gyb
@@ -2,27 +2,41 @@
 // RUN: %gyb %s > %t/main.swift
 
 // Same-module superclass, both resilient and not, and enable-testing and not:
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -DSAME_MODULE -enable-testing -O
 
 
 // Other-module superclass is not resilient:
 // RUN: %empty-directory(%t/super)
 // RUN: %target-build-swift %S/Inputs/subclass_super.swift -emit-library -emit-module -o %t/super/subclass_super.%target-dylib-extension
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing -O
 
 // Other-module superclass is resilient:
 // RUN: %empty-directory(%t/super)
 // RUN: %target-build-swift %S/Inputs/subclass_super.swift -emit-library -emit-module -o %t/super/subclass_super.%target-dylib-extension -Xfrontend -enable-resilience
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
-// RUN: %target-swift-frontend -enable-resilience -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing
+
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -O
+// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing -O
+// RUN: %target-swift-frontend -enable-resilience -emit-ir -o/dev/null -parse-as-library -module-name test -validate-tbd-against-ir=missing %t/main.swift -I %t/super -enable-testing -O
 
 #if SAME_MODULE
 open class Super {
diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift
index 5dd01c9..da83057 100644
--- a/test/attr/attr_objc.swift
+++ b/test/attr/attr_objc.swift
@@ -1655,7 +1655,7 @@
   init() {}
 
   @IBOutlet weak var goodOutlet: Class_ObjC1!
-  // CHECK-LABEL: {{^}} @IBOutlet @_implicitly_unwrapped_optional @objc weak var goodOutlet: @sil_weak Class_ObjC1!
+  // CHECK-LABEL: {{^}} @objc @IBOutlet @_implicitly_unwrapped_optional weak var goodOutlet: @sil_weak Class_ObjC1!
 
   @IBOutlet var badOutlet: PlainStruct
   // expected-error@-1 {{@IBOutlet property cannot have non-object type 'PlainStruct'}} {{3-13=}}
@@ -1672,7 +1672,7 @@
 // CHECK-LABEL: {{^}}class HasIBAction {
 class HasIBAction {
   @IBAction func goodAction(_ sender: AnyObject?) { }
-  // CHECK: {{^}}  @IBAction @objc func goodAction(_ sender: AnyObject?) {
+  // CHECK: {{^}}  @objc @IBAction func goodAction(_ sender: AnyObject?) {
 
   @IBAction func badAction(_ sender: PlainStruct?) { }
   // expected-error@-1{{argument to @IBAction method cannot have non-object type 'PlainStruct?'}}
@@ -1686,7 +1686,7 @@
 // CHECK-LABEL: {{^}}class HasIBInspectable {
 class HasIBInspectable {
   @IBInspectable var goodProperty: AnyObject?
-  // CHECK: {{^}}  @IBInspectable @objc var goodProperty: AnyObject?
+  // CHECK: {{^}}  @objc @IBInspectable var goodProperty: AnyObject?
 }
 
 //===---
@@ -1696,7 +1696,7 @@
 // CHECK-LABEL: {{^}}class HasGKInspectable {
 class HasGKInspectable {
   @GKInspectable var goodProperty: AnyObject?
-  // CHECK: {{^}}  @GKInspectable @objc var goodProperty: AnyObject?
+  // CHECK: {{^}}  @objc @GKInspectable var goodProperty: AnyObject?
 }
 
 //===---
@@ -1710,7 +1710,7 @@
 
   @NSManaged
   var goodManaged: Class_ObjC1
-  // CHECK-LABEL: {{^}}  @NSManaged @objc dynamic var goodManaged: Class_ObjC1
+  // CHECK-LABEL: {{^}}  @objc @NSManaged dynamic var goodManaged: Class_ObjC1
 
   @NSManaged
   var badManaged: PlainStruct
diff --git a/test/decl/class/circular_inheritance.swift b/test/decl/class/circular_inheritance.swift
index f75e56c..642b2f9 100644
--- a/test/decl/class/circular_inheritance.swift
+++ b/test/decl/class/circular_inheritance.swift
@@ -8,19 +8,6 @@
 // Check that we produced superclass type requests.
 // RUN: %{python} %utils/process-stats-dir.py --evaluate 'SuperclassTypeRequest == 16' %t/stats-dir
 
-class C : B { } // expected-error{{circular class inheritance 'C' -> 'B' -> 'A' -> 'C'}}
-class B : A { } // expected-note{{class 'B' declared here}}
-class A : C { } // expected-note{{class 'A' declared here}}
-
-class TrivialCycle : TrivialCycle {} // expected-error{{circular class inheritance TrivialCycle}}
-protocol P : P {} // expected-error {{circular protocol inheritance P}}
-
-class Isomorphism : Automorphism { }
-class Automorphism : Automorphism { } // expected-error{{circular class inheritance Automorphism}}
-
-// FIXME: Useless error
-let _ = A() // expected-error{{'A' cannot be constructed because it has no accessible initializers}}
-
 class Left
     : Right.Hand {
   class Hand {}
@@ -31,6 +18,19 @@
   class Hand {}
 }
 
+class C : B { } // expected-error{{'C' inherits from itself}}
+class B : A { } // expected-note{{class 'B' declared here}}
+class A : C { } // expected-note{{class 'A' declared here}}
+
+class TrivialCycle : TrivialCycle {} // expected-error{{'TrivialCycle' inherits from itself}}
+protocol P : P {} // expected-error {{protocol 'P' refines itself}}
+
+class Isomorphism : Automorphism { }
+class Automorphism : Automorphism { } // expected-error{{'Automorphism' inherits from itself}}
+
+// FIXME: Useless error
+let _ = A() // expected-error{{'A' cannot be constructed because it has no accessible initializers}}
+
 class Outer {
   class Inner : Outer {}
 }
diff --git a/test/decl/inherit/inherit.swift b/test/decl/inherit/inherit.swift
index 938a35e..b9df433 100644
--- a/test/decl/inherit/inherit.swift
+++ b/test/decl/inherit/inherit.swift
@@ -8,6 +8,9 @@
 
 // Duplicate inheritance from protocol
 class B2 : P, P { } // expected-error{{duplicate inheritance from 'P'}}{{13-16=}}
+// FIXME: These are unnecessary
+// expected-note@-2 {{'B2' declares conformance to protocol 'P' here}}
+// expected-error@-3 {{redundant conformance of 'B2' to protocol 'P'}}
 
 // Multiple inheritance
 class C : B, A { } // expected-error{{multiple inheritance from classes 'B' and 'A'}}
diff --git a/test/decl/nested/type_in_function.swift b/test/decl/nested/type_in_function.swift
index ab62acb..509dcf8 100644
--- a/test/decl/nested/type_in_function.swift
+++ b/test/decl/nested/type_in_function.swift
@@ -130,7 +130,7 @@
   // expected-error@-1 {{type 'First' cannot be nested in generic function 'genericFunction(t:)'}}
   class Second<T> : Second { }
   // expected-error@-1 {{type 'Second' cannot be nested in generic function 'genericFunction(t:)'}}
-  // expected-error@-2 2 {{circular class inheritance Second}}
+  // expected-error@-2 2 {{'Second' inherits from itself}}
 }
 
 // Spurious "Self or associated type requirements" diagnostic.
diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift
index 15439ee..2e7dc74 100644
--- a/test/decl/protocol/protocols.swift
+++ b/test/decl/protocol/protocols.swift
@@ -98,16 +98,15 @@
 
 // Circular protocols
 
-protocol CircleMiddle : CircleStart { func circle_middle() } // expected-error  {{circular protocol inheritance CircleMiddle}}
-// expected-error@-1{{circular protocol inheritance 'CircleMiddle' -> 'CircleStart' -> 'CircleEnd' -> 'CircleMiddle'}}
+protocol CircleMiddle : CircleStart { func circle_middle() } // expected-error 2 {{protocol 'CircleMiddle' refines itself}}
 protocol CircleStart : CircleEnd { func circle_start() }
 // expected-note@-1{{protocol 'CircleStart' declared here}}
-// expected-error@-2{{circular protocol inheritance CircleStart}}
+// expected-error@-2{{protocol 'CircleStart' refines itself}}
 protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note{{protocol 'CircleEnd' declared here}}
-// expected-error@-1{{circular protocol inheritance CircleEnd}}
+// expected-error@-1{{protocol 'CircleEnd' refines itself}}
 
 protocol CircleEntry : CircleTrivial { }
-protocol CircleTrivial : CircleTrivial { } // expected-error 2{{circular protocol inheritance CircleTrivial}}
+protocol CircleTrivial : CircleTrivial { } // expected-error 2{{protocol 'CircleTrivial' refines itself}}
 
 struct Circle {
   func circle_start() {}
diff --git a/test/decl/var/lazy_properties.swift b/test/decl/var/lazy_properties.swift
index a435ed4..f908eac 100644
--- a/test/decl/var/lazy_properties.swift
+++ b/test/decl/var/lazy_properties.swift
@@ -86,7 +86,7 @@
 // property type and also as part of the getter
 class WeShouldNotReTypeCheckStatements {
   lazy var firstCase = {
-    _ = nil // expected-error {{'nil' requires a contextual type}}
+    _ = nil // expected-error{{'nil' requires a contextual type}}
     _ = ()
   }
 
diff --git a/test/expr/capture/dynamic_self.swift b/test/expr/capture/dynamic_self.swift
index c37fbf3..f1dda7b 100644
--- a/test/expr/capture/dynamic_self.swift
+++ b/test/expr/capture/dynamic_self.swift
@@ -4,7 +4,7 @@
 
 class Android {
   func clone() -> Self {
-    // CHECK: closure_expr type='() -> Self' {{.*}} discriminator=0 captures=(<dynamic_self> self)
+    // CHECK: closure_expr type='() -> Self' {{.*}} discriminator=0 captures=(<dynamic_self> self<direct>)
     let fn = { return self }
     return fn()
   }
diff --git a/test/expr/capture/generic_params.swift b/test/expr/capture/generic_params.swift
index 135b51a..bea2d55 100644
--- a/test/expr/capture/generic_params.swift
+++ b/test/expr/capture/generic_params.swift
@@ -6,16 +6,16 @@
 
 func outerGeneric<T>(t: T, x: AnyObject) {
   // Simple case -- closure captures outer generic parameter
-  // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=0 captures=(<generic> t) escaping  single-expression
+  // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=0 captures=(<generic> t<direct>) escaping  single-expression
   _ = { doSomething(t) }
 
   // Special case -- closure does not capture outer generic parameters
-  // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=1 captures=(x) escaping single-expression
+  // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=1 captures=(x<direct>) escaping single-expression
   _ = { doSomething(x) }
 
   // Special case -- closure captures outer generic parameter, but it does not
   // appear as the type of any expression
-  // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=2 captures=(<generic> x)
+  // CHECK: closure_expr type='() -> ()' {{.*}} discriminator=2 captures=(<generic> x<direct>)
   _ = { if x is T {} }
 
   // Nested generic functions always capture outer generic parameters, even if
diff --git a/test/expr/capture/nested.swift b/test/expr/capture/nested.swift
index 6d4790a..dd6b021 100644
--- a/test/expr/capture/nested.swift
+++ b/test/expr/capture/nested.swift
@@ -4,7 +4,7 @@
 func foo2(_ x: Int) -> (Int) -> (Int) -> Int {
   // CHECK: closure_expr type='(Int) -> (Int) -> Int' {{.*}} discriminator=0 captures=(x)
   return {(bar: Int) -> (Int) -> Int in
-    // CHECK: closure_expr type='(Int) -> Int' {{.*}} discriminator=0 captures=(x, bar)
+    // CHECK: closure_expr type='(Int) -> Int' {{.*}} discriminator=0 captures=(x<direct>, bar<direct>)
     return {(bas: Int) -> Int in
       return x + bar + bas
     }
diff --git a/test/expr/capture/top-level-guard.swift b/test/expr/capture/top-level-guard.swift
index 744c896..bb1f1f9 100644
--- a/test/expr/capture/top-level-guard.swift
+++ b/test/expr/capture/top-level-guard.swift
@@ -32,7 +32,7 @@
 // CHECK: location={{.*}}top-level-guard.swift:[[@LINE+5]]
 // CHECK: (closure_expr
 // CHECK: location={{.*}}top-level-guard.swift:[[@LINE+3]]
-// CHECK: captures=(x)
+// CHECK: captures=(x<direct>)
 // CHECK: (var_decl{{.*}}"closureCapture"
 let closureCapture: () -> Void = { [x] in
   _ = x
diff --git a/test/stdlib/AnyHashableCasts.swift.gyb b/test/stdlib/AnyHashableCasts.swift.gyb
index 4eaaf50..3a6f81f 100644
--- a/test/stdlib/AnyHashableCasts.swift.gyb
+++ b/test/stdlib/AnyHashableCasts.swift.gyb
@@ -1,10 +1,10 @@
 // RUN: %empty-directory(%t)
 //
 // RUN: %gyb %s -o %t/AnyHashableCasts.swift
-// RUN: %target-build-swift -g -module-name a %t/AnyHashableCasts.swift -o %t.out
-// RUN: %target-run %t.out
-// RUN: %target-build-swift -g -O -module-name a %t/AnyHashableCasts.swift -o %t.out.optimized
-// RUN: %target-run %t.out.optimized
+// RUN: %line-directive %t/AnyHashableCasts.swift -- %target-build-swift -g -module-name a %t/AnyHashableCasts.swift -o %t.out
+// RUN: %line-directive %t/AnyHashableCasts.swift -- %target-run %t.out
+// RUN: %line-directive %t/AnyHashableCasts.swift -- %target-build-swift -g -O -module-name a %t/AnyHashableCasts.swift -o %t.out.optimized
+// RUN: %line-directive %t/AnyHashableCasts.swift -- %target-run %t.out.optimized
 // REQUIRES: executable_test
 
 import StdlibUnittest
@@ -117,34 +117,129 @@
 % end
 
 #if _runtime(_ObjC)
+// A wrapper type around Int that bridges to NSNumber.
+struct IntWrapper1: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+  let rawValue: Int
+}
+
+// A wrapper type around Int that bridges to NSNumber.
+struct IntWrapper2: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+  let rawValue: Int
+}
+
+AnyHashableCasts.test("Wrappers around bridged integers") {
+  let wrapper1: AnyHashable = IntWrapper1(rawValue: 42)
+  let wrapper2: AnyHashable = IntWrapper2(rawValue: 42)
+  let integer: AnyHashable = 42 as Int
+  let byte: AnyHashable = 42 as UInt8
+  let double: AnyHashable = 42.0 as Double
+  let number: AnyHashable = 42 as NSNumber
+
+  // Wrappers compare equal to their wrapped value as AnyHashable.
+  expectEqual(wrapper1, wrapper2)
+  expectEqual(wrapper1, integer)
+  expectEqual(wrapper1, byte)
+  expectEqual(wrapper1, double)
+  expectEqual(wrapper1, number)
+
+  // Original types are preserved in the base property.
+  expectTrue(wrapper1.base is IntWrapper1)
+  expectTrue(wrapper2.base is IntWrapper2)
+  expectTrue(integer.base is Int)
+  expectTrue(byte.base is UInt8)
+  expectTrue(double.base is Double)
+  expectTrue(number.base is NSNumber) // Through bridging
+
+  // AnyHashable forms can be casted to any standard numeric type that can hold
+  // their value.
+  expectNotNil(wrapper1 as? IntWrapper1)
+  expectNotNil(wrapper1 as? IntWrapper2)
+  expectNotNil(wrapper1 as? Int)
+  expectNotNil(wrapper1 as? UInt8)
+  expectNotNil(wrapper1 as? Double)
+  expectNotNil(wrapper1 as? NSNumber)
+
+  expectNotNil(byte as? IntWrapper1)
+  expectNotNil(byte as? IntWrapper2)
+  expectNotNil(byte as? Int)
+  expectNotNil(byte as? UInt8)
+  expectNotNil(byte as? Double)
+  expectNotNil(byte as? NSNumber)
+
+  expectNotNil(integer as? IntWrapper1)
+  expectNotNil(integer as? IntWrapper2)
+  expectNotNil(integer as? Int)
+  expectNotNil(integer as? UInt8)
+  expectNotNil(integer as? Double)
+  expectNotNil(integer as? NSNumber)
+
+  expectNotNil(double as? IntWrapper1)
+  expectNotNil(double as? IntWrapper2)
+  expectNotNil(double as? Int)
+  expectNotNil(double as? UInt8)
+  expectNotNil(double as? Double)
+  expectNotNil(double as? NSNumber)
+
+  expectNotNil(number as? IntWrapper1)
+  expectNotNil(number as? IntWrapper2)
+  expectNotNil(number as? Int)
+  expectNotNil(number as? UInt8)
+  expectNotNil(number as? Double)
+  expectNotNil(number as? NSNumber)
+
+  // We can't cast to a numeric type that can't hold the value.
+  let big: AnyHashable = Int32.max
+  expectNotNil(big as? IntWrapper1)
+  expectNotNil(big as? IntWrapper2)
+  expectNotNil(big as? Int)
+  expectNil(big as? UInt8) // <--
+  expectNotNil(big as? Double)
+  expectNotNil(big as? NSNumber)
+}
+
 // A wrapper type around a String that bridges to NSString.
-struct StringWrapper1 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+struct StringWrapper1: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
   let rawValue: String
 }
 
 // A wrapper type around a String that bridges to NSString.
-struct StringWrapper2 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+struct StringWrapper2: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
   let rawValue: String
 }
 
-AnyHashableCasts.test("Wrappers around bridged types") {
+AnyHashableCasts.test("Wrappers around bridged strings") {
   let wrapper1Hello: AnyHashable = StringWrapper1(rawValue: "hello")
+  let wrapper2Hello: AnyHashable = StringWrapper2(rawValue: "hello")
   let stringHello: AnyHashable = "hello" as String
   let nsStringHello: AnyHashable = "hello" as NSString
 
-  // Casting from Swift wrapper maintains type identity
+  // Wrappers compare equal to their wrapped value as AnyHashable.
+  expectEqual(wrapper1Hello, wrapper2Hello)
+  expectEqual(wrapper1Hello, stringHello)
+  expectEqual(wrapper1Hello, nsStringHello)
+  expectEqual(wrapper2Hello, stringHello)
+  expectEqual(wrapper2Hello, nsStringHello)
+  expectEqual(stringHello, nsStringHello)
+
+  // Type identity is maintained through the base property.
+  expectTrue(wrapper1Hello.base is StringWrapper1)
+  expectTrue(wrapper2Hello.base is StringWrapper2)
+  expectTrue(stringHello.base is String)
+  expectTrue(nsStringHello.base is NSString) // Through bridging
+
+  // Swift wrapper's AnyHashable form doesn't enfore type identity.
   expectNotNil(wrapper1Hello as? StringWrapper1)
-  expectNil(wrapper1Hello as? StringWrapper2)
-  expectNil(wrapper1Hello as? String)
+  expectNotNil(wrapper1Hello as? StringWrapper2)
+  expectNotNil(wrapper1Hello as? String)
   expectNotNil(wrapper1Hello as? NSString)
 
-  // Casting from String maintains type identity
-  expectNil(stringHello as? StringWrapper1)
-  expectNil(stringHello as? StringWrapper2)
+  // String's AnyHashable form doesn't enfore type identity.
+  expectNotNil(stringHello as? StringWrapper1)
+  expectNotNil(stringHello as? StringWrapper2)
   expectNotNil(stringHello as? String)
   expectNotNil(stringHello as? NSString)
 
-  // Casting form NSString works with anything.
+  // NSString's AnyHashable form doesn't enfore type identity.
   expectNotNil(nsStringHello as? StringWrapper1)
   expectNotNil(nsStringHello as? StringWrapper2)
   expectNotNil(nsStringHello as? String)
diff --git a/test/stdlib/BinaryIntegerRequirements.swift b/test/stdlib/BinaryIntegerRequirements.swift
index 4436295..cb238bd 100644
--- a/test/stdlib/BinaryIntegerRequirements.swift
+++ b/test/stdlib/BinaryIntegerRequirements.swift
@@ -1,9 +1,6 @@
 // RUN: %target-typecheck-verify-swift -swift-version 4
 
 struct MyInt: FixedWidthInteger { // expected-error {{type 'MyInt' does not conform to protocol 'BinaryInteger'}}
-  // expected-error@-1 {{unavailable operator function '&=' was used to satisfy a requirement of protocol 'BinaryInteger'}}
-  // expected-error@-2 {{unavailable operator function '|=' was used to satisfy a requirement of protocol 'BinaryInteger'}}
-  // expected-error@-3 {{unavailable operator function '^=' was used to satisfy a requirement of protocol 'BinaryInteger'}}
   typealias IntegerLiteralType = Int
   static let isSigned = false
   init(integerLiteral value: Int) { fatalError() }
diff --git a/test/stdlib/Character.swift b/test/stdlib/Character.swift
index 1924f04..12649db 100644
--- a/test/stdlib/Character.swift
+++ b/test/stdlib/Character.swift
@@ -202,6 +202,9 @@
   // Only run it on ObjC platforms. Supported Linux versions do not have a
   // recent enough ICU for Unicode 9 support.
 #if _runtime(_ObjC)
+  // Check for Unicode 9 or later
+  guard #available(iOS 10.0, macOS 10.12, *) else { return }
+
   let flags = "🇺🇸🇨🇦🇩🇰🏳️‍🌈"
   expectEqual(4, flags.count)
   expectEqual(flags.reversed().count, flags.count)
diff --git a/test/stdlib/CodableTests.swift b/test/stdlib/CodableTests.swift
index 566398c..2a7b60a 100644
--- a/test/stdlib/CodableTests.swift
+++ b/test/stdlib/CodableTests.swift
@@ -22,7 +22,7 @@
 #endif
 
 // MARK: - Helper Functions
-@available(OSX 10.11, iOS 9.0, *)
+@available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *)
 func makePersonNameComponents(namePrefix: String? = nil,
                               givenName: String? = nil,
                               middleName: String? = nil,
@@ -220,7 +220,7 @@
             #line : CGAffineTransform(a: 0.498, b: -0.284, c: -0.742, d: 0.3248, tx: 12, ty: 44)
         ]
 
-        if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+        if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
             values[#line] = CGAffineTransform(rotationAngle: .pi / 2)
         }
 
@@ -246,7 +246,7 @@
             #line : CGPoint(x: 10, y: 20)
         ]
 
-        if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+        if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
             // Limit on magnitude in JSON. See rdar://problem/12717407
             values[#line] = CGPoint(x: CGFloat.greatestFiniteMagnitude,
                                     y: CGFloat.greatestFiniteMagnitude)
@@ -274,7 +274,7 @@
             #line : CGSize(width: 30, height: 40)
         ]
 
-        if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+        if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
             // Limit on magnitude in JSON. See rdar://problem/12717407
             values[#line] = CGSize(width: CGFloat.greatestFiniteMagnitude,
                                    height: CGFloat.greatestFiniteMagnitude)
@@ -303,7 +303,7 @@
             #line : CGRect(x: 10, y: 20, width: 30, height: 40)
         ]
 
-        if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+        if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
             // Limit on magnitude in JSON. See rdar://problem/12717407
             values[#line] = CGRect.infinite
         }
@@ -330,7 +330,7 @@
             #line : CGVector(dx: 0.0, dy: -9.81)
         ]
 
-        if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
+        if #available(macOS 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) {
             // Limit on magnitude in JSON. See rdar://problem/12717407
             values[#line] = CGVector(dx: CGFloat.greatestFiniteMagnitude,
                                      dy: CGFloat.greatestFiniteMagnitude)
@@ -371,7 +371,7 @@
     }
 
     // MARK: - DateInterval
-    @available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *)
+    @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
     lazy var dateIntervalValues: [Int : DateInterval] = [
         #line : DateInterval(),
         #line : DateInterval(start: Date.distantPast, end: Date()),
@@ -379,14 +379,14 @@
         #line : DateInterval(start: Date.distantPast, end: Date.distantFuture)
     ]
 
-    @available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *)
+    @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
     func test_DateInterval_JSON() {
         for (testLine, interval) in dateIntervalValues {
             expectRoundTripEqualityThroughJSON(for: interval, lineNumber: testLine)
         }
     }
 
-    @available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *)
+    @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
     func test_DateInterval_Plist() {
         for (testLine, interval) in dateIntervalValues {
             expectRoundTripEqualityThroughPlist(for: interval, lineNumber: testLine)
@@ -482,21 +482,21 @@
     }
 
     // MARK: - Measurement
-    @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+    @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
     lazy var unitValues: [Int : Dimension] = [
         #line : UnitAcceleration.metersPerSecondSquared,
         #line : UnitMass.kilograms,
         #line : UnitLength.miles
     ]
 
-    @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+    @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
     func test_Measurement_JSON() {
         for (testLine, unit) in unitValues {
             expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: unit), lineNumber: testLine)
         }
     }
 
-    @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+    @available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
     func test_Measurement_Plist() {
         for (testLine, unit) in unitValues {
             expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: unit), lineNumber: testLine)
@@ -523,21 +523,21 @@
     }
 
     // MARK: - PersonNameComponents
-    @available(OSX 10.11, iOS 9.0, *)
+    @available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *)
     lazy var personNameComponentsValues: [Int : PersonNameComponents] = [
         #line : makePersonNameComponents(givenName: "John", familyName: "Appleseed"),
         #line : makePersonNameComponents(givenName: "John", familyName: "Appleseed", nickname: "Johnny"),
         #line : makePersonNameComponents(namePrefix: "Dr.", givenName: "Jane", middleName: "A.", familyName: "Appleseed", nameSuffix: "Esq.", nickname: "Janie")
     ]
 
-    @available(OSX 10.11, iOS 9.0, *)
+    @available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *)
     func test_PersonNameComponents_JSON() {
         for (testLine, components) in personNameComponentsValues {
             expectRoundTripEqualityThroughJSON(for: components, lineNumber: testLine)
         }
     }
 
-    @available(OSX 10.11, iOS 9.0, *)
+    @available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *)
     func test_PersonNameComponents_Plist() {
         for (testLine, components) in personNameComponentsValues {
             expectRoundTripEqualityThroughPlist(for: components, lineNumber: testLine)
@@ -572,7 +572,7 @@
             #line : URL(string: "documentation", relativeTo: URL(string: "http://swift.org")!)!
         ]
 
-        if #available(OSX 10.11, iOS 9.0, *) {
+        if #available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *) {
             values[#line] = URL(fileURLWithPath: "bin/sh", relativeTo: URL(fileURLWithPath: "/"))
         }
 
@@ -770,8 +770,6 @@
     "test_TimeZone_Plist" : TestCodable.test_TimeZone_Plist,
     "test_URL_JSON" : TestCodable.test_URL_JSON,
     "test_URL_Plist" : TestCodable.test_URL_Plist,
-    "test_URLComponents_JSON" : TestCodable.test_URLComponents_JSON,
-    "test_URLComponents_Plist" : TestCodable.test_URLComponents_Plist,
     "test_UUID_JSON" : TestCodable.test_UUID_JSON,
     "test_UUID_Plist" : TestCodable.test_UUID_Plist,
 ]
@@ -781,18 +779,23 @@
     tests["test_AffineTransform_Plist"] = TestCodable.test_AffineTransform_Plist
 #endif
 
-if #available(OSX 10.11, iOS 9.0, *) {
+if #available(macOS 10.11, iOS 9.0, watchOS 2.0, tvOS 9.0, *) {
     tests["test_PersonNameComponents_JSON"] = TestCodable.test_PersonNameComponents_JSON
     tests["test_PersonNameComponents_Plist"] = TestCodable.test_PersonNameComponents_Plist
 }
 
-if #available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *) {
+if #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) {
     // tests["test_DateInterval_JSON"] = TestCodable.test_DateInterval_JSON
     tests["test_DateInterval_Plist"] = TestCodable.test_DateInterval_Plist
     // tests["test_Measurement_JSON"] = TestCodable.test_Measurement_JSON
     // tests["test_Measurement_Plist"] = TestCodable.test_Measurement_Plist
 }
 
+if #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) {
+    tests["test_URLComponents_JSON"] = TestCodable.test_URLComponents_JSON
+    tests["test_URLComponents_Plist"] = TestCodable.test_URLComponents_Plist
+}
+
 var CodableTests = TestSuite("TestCodable")
 for (name, test) in tests {
     CodableTests.test(name) { test(TestCodable())() }
diff --git a/test/stdlib/ErrorBridged.swift b/test/stdlib/ErrorBridged.swift
index dcce4ae..05121d1 100644
--- a/test/stdlib/ErrorBridged.swift
+++ b/test/stdlib/ErrorBridged.swift
@@ -276,6 +276,16 @@
   expectEqual(NoisyErrorDeathCount, NoisyErrorLifeCount)
 }
 
+ErrorBridgingTests.test("NSError-to-error bridging in bridged container") {
+  autoreleasepool {
+    let error = NSError(domain: "domain", code: 42, userInfo: nil)
+    let nsdictionary = ["error": error] as NSDictionary
+    let dictionary = nsdictionary as? Dictionary<String, Error>
+    expectNotNil(dictionary)
+    expectEqual(error, dictionary?["error"] as NSError?)
+  }
+}
+
 ErrorBridgingTests.test("enum-to-NSError round trip") {
   autoreleasepool {
     // Emulate throwing an error from Objective-C.
diff --git a/test/stdlib/IndexDistanceRemoval.swift b/test/stdlib/IndexDistanceRemoval.swift
index 5c81ccf..3922d6c 100644
--- a/test/stdlib/IndexDistanceRemoval.swift
+++ b/test/stdlib/IndexDistanceRemoval.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -swift-version 4
 
 struct Int64Distance<Element>: Collection {
   let _storage: [Element]
diff --git a/test/stdlib/StringCompatibility.swift b/test/stdlib/StringCompatibility.swift
index 22c68d1..1251d25 100644
--- a/test/stdlib/StringCompatibility.swift
+++ b/test/stdlib/StringCompatibility.swift
@@ -279,8 +279,10 @@
   var sub = s[s.startIndex ..< s.endIndex]
   var subsub = sub[s.startIndex ..< s.endIndex]
 
-  expectType(ExpectedConcreteSlice.self, &sub)
-  expectType(ExpectedConcreteSlice.self, &subsub)
+  // slicing a String in Swift 3 produces a String
+  // but slicing a Substring should still produce a Substring
+  expectType(Substring.self, &sub)
+  expectType(Substring.self, &subsub)
 }
 
 Tests.test("Substring/ClosedRange/Slice/ExpectedType/\(swift)") {
diff --git a/test/stdlib/TestURL.swift b/test/stdlib/TestURL.swift
index 8c0128c..21f9205 100644
--- a/test/stdlib/TestURL.swift
+++ b/test/stdlib/TestURL.swift
@@ -178,8 +178,8 @@
     
     func testURLComponents() {
         // Not meant to be a test of all URL components functionality, just some basic bridging stuff
-        let s = "http://www.apple.com/us/search/ipad?src=globalnav"
-        let components = URLComponents(string: s)!
+        let s = "http://www.apple.com/us/search/ipad?src=global%7Cnav"
+        var components = URLComponents(string: s)!
         expectNotNil(components)
         
         expectNotNil(components.host)
@@ -201,7 +201,45 @@
             
             expectEqual("src", first.name)
             expectNotNil(first.value)
-            expectEqual("globalnav", first.value)
+            expectEqual("global|nav", first.value)
+        }
+
+        if #available(OSX 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) {
+            components.percentEncodedQuery = "name1%E2%80%A2=value1%E2%80%A2&name2%E2%80%A2=value2%E2%80%A2"
+            var qi = components.queryItems!
+            expectNotNil(qi)
+            
+            expectEqual(2, qi.count)
+            
+            expectEqual("name1•", qi[0].name)
+            expectNotNil(qi[0].value)
+            expectEqual("value1•", qi[0].value)
+            
+            expectEqual("name2•", qi[1].name)
+            expectNotNil(qi[1].value)
+            expectEqual("value2•", qi[1].value)
+            
+            qi = components.percentEncodedQueryItems!
+            expectNotNil(qi)
+            
+            expectEqual(2, qi.count)
+            
+            expectEqual("name1%E2%80%A2", qi[0].name)
+            expectNotNil(qi[0].value)
+            expectEqual("value1%E2%80%A2", qi[0].value)
+            
+            expectEqual("name2%E2%80%A2", qi[1].name)
+            expectNotNil(qi[0].value)
+            expectEqual("value2%E2%80%A2", qi[1].value)
+            
+            qi[0].name = "%E2%80%A2name1"
+            qi[0].value = "%E2%80%A2value1"
+            qi[1].name = "%E2%80%A2name2"
+            qi[1].value = "%E2%80%A2value2"
+            
+            components.percentEncodedQueryItems = qi
+            
+            expectEqual("%E2%80%A2name1=%E2%80%A2value1&%E2%80%A2name2=%E2%80%A2value2", components.percentEncodedQuery)
         }
     }
     
diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
index 7c009cc..9bb3fcf 100644
--- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h
+++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
@@ -190,7 +190,6 @@
 
 class EditorConsumer {
   virtual void anchor();
-
 public:
   virtual ~EditorConsumer() { }
 
@@ -518,7 +517,6 @@
   codeCompleteSetCustom(ArrayRef<CustomCompletionInfo> completions) = 0;
 
   virtual void editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
-                          bool EnableSyntaxMap,
                           EditorConsumer &Consumer,
                           ArrayRef<const char *> Args) = 0;
 
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 23d9ba8..7a0d175 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -2027,7 +2027,6 @@
 //===----------------------------------------------------------------------===//
 
 void SwiftLangSupport::editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
-                                  bool EnableSyntaxMap,
                                   EditorConsumer &Consumer,
                                   ArrayRef<const char *> Args) {
 
@@ -2084,7 +2083,8 @@
 // EditorReplaceText
 //===----------------------------------------------------------------------===//
 
-void SwiftLangSupport::editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf,
+void SwiftLangSupport::editorReplaceText(StringRef Name,
+                                         llvm::MemoryBuffer *Buf,
                                          unsigned Offset, unsigned Length,
                                          EditorConsumer &Consumer) {
   auto EditorDoc = EditorDocuments.getByUnresolvedName(Name);
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
index b1bf255..b90d5b6 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h
@@ -397,7 +397,7 @@
   void
   codeCompleteSetCustom(ArrayRef<CustomCompletionInfo> completions) override;
 
-  void editorOpen(StringRef Name, llvm::MemoryBuffer *Buf, bool EnableSyntaxMap,
+  void editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
                   EditorConsumer &Consumer,
                   ArrayRef<const char *> Args) override;
 
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 740f99f..d88d0f4 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -68,6 +68,15 @@
     return StringRef(Name);
   }
 };
+
+struct SKEditorConsumerOptions {
+  bool EnableSyntaxMap = false;
+  bool EnableStructure = false;
+  bool EnableDiagnostics = false;
+  bool EnableSyntaxTree = false;
+  bool SyntacticOnly = false;
+};
+
 } // anonymous namespace
 
 #define REQUEST(NAME, CONTENT) static LazySKDUID Request##NAME(CONTENT);
@@ -151,9 +160,8 @@
 static sourcekitd_response_t codeCompleteClose(StringRef name, int64_t Offset);
 
 static sourcekitd_response_t
-editorOpen(StringRef Name, llvm::MemoryBuffer *Buf, bool EnableSyntaxMap,
-           bool EnableStructure, bool EnableDiagnostics, bool EnableSyntaxTree,
-           bool SyntacticOnly, ArrayRef<const char *> Args);
+editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
+           SKEditorConsumerOptions Opts, ArrayRef<const char *> Args);
 
 static sourcekitd_response_t
 editorOpenInterface(StringRef Name, StringRef ModuleName,
@@ -186,9 +194,7 @@
 
 static sourcekitd_response_t
 editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf, unsigned Offset,
-                  unsigned Length, bool EnableSyntaxMap, bool EnableStructure,
-                  bool EnableDiagnostics, bool EnableSyntaxTree,
-                  bool SyntacticOnly);
+                  unsigned Length, SKEditorConsumerOptions Opts);
 
 static void
 editorApplyFormatOptions(StringRef Name, RequestDict &FmtOptions);
@@ -429,9 +435,14 @@
     Req.getInt64(KeyEnableSyntaxTree, EnableSyntaxTree, /*isOptional=*/true);
     int64_t SyntacticOnly = false;
     Req.getInt64(KeySyntacticOnly, SyntacticOnly, /*isOptional=*/true);
-    return Rec(editorOpen(*Name, InputBuf.get(), EnableSyntaxMap, EnableStructure,
-                          EnableDiagnostics, EnableSyntaxTree, SyntacticOnly,
-                          Args));
+
+    SKEditorConsumerOptions Opts;
+    Opts.EnableSyntaxMap = EnableSyntaxMap;
+    Opts.EnableStructure = EnableStructure;
+    Opts.EnableDiagnostics = EnableDiagnostics;
+    Opts.EnableSyntaxTree = EnableSyntaxTree;
+    Opts.SyntacticOnly = SyntacticOnly;
+    return Rec(editorOpen(*Name, InputBuf.get(), Opts, Args));
   }
   if (ReqUID == RequestEditorClose) {
     Optional<StringRef> Name = Req.getString(KeyName);
@@ -465,10 +476,15 @@
     Req.getInt64(KeyEnableSyntaxTree, EnableSyntaxTree, /*isOptional=*/true);
     int64_t SyntacticOnly = false;
     Req.getInt64(KeySyntacticOnly, SyntacticOnly, /*isOptional=*/true);
-    return Rec(editorReplaceText(*Name, InputBuf.get(), Offset, Length,
-                                 EnableSyntaxMap, EnableStructure,
-                                 EnableDiagnostics, EnableSyntaxTree,
-                                 SyntacticOnly));
+
+    SKEditorConsumerOptions Opts;
+    Opts.EnableSyntaxMap = EnableSyntaxMap;
+    Opts.EnableStructure = EnableStructure;
+    Opts.EnableDiagnostics = EnableDiagnostics;
+    Opts.EnableSyntaxTree = EnableSyntaxTree;
+    Opts.SyntacticOnly = SyntacticOnly;
+
+    return Rec(editorReplaceText(*Name, InputBuf.get(), Offset, Length, Opts));
   }
   if (ReqUID == RequestEditorFormatText) {
     Optional<StringRef> Name = Req.getString(KeyName);
@@ -1984,35 +2000,22 @@
   ResponseBuilder::Array Diags;
   sourcekitd_response_t Error = nullptr;
 
-  bool EnableSyntaxMap;
-  bool EnableStructure;
-  bool EnableDiagnostics;
-  bool EnableSyntaxTree;
-  bool SyntacticOnly;
+  SKEditorConsumerOptions Opts;
 
 public:
-  SKEditorConsumer(bool EnableSyntaxMap, bool EnableStructure,
-                   bool EnableDiagnostics, bool EnableSyntaxTree,
-                   bool SyntacticOnly)
-      : EnableSyntaxMap(EnableSyntaxMap), EnableStructure(EnableStructure),
-        EnableDiagnostics(EnableDiagnostics), EnableSyntaxTree(EnableSyntaxTree),
-        SyntacticOnly(SyntacticOnly) {
-
+  SKEditorConsumer(SKEditorConsumerOptions Opts) : Opts(Opts) {
     Dict = RespBuilder.getDictionary();
   }
 
-  SKEditorConsumer(ResponseReceiver RespReceiver, bool EnableSyntaxMap,
-                   bool EnableStructure, bool EnableDiagnostics,
-                   bool EnableSyntaxTree, bool SyntacticOnly)
-  : SKEditorConsumer(EnableSyntaxMap, EnableStructure,
-                     EnableDiagnostics, EnableSyntaxTree, SyntacticOnly) {
+  SKEditorConsumer(ResponseReceiver RespReceiver, SKEditorConsumerOptions Opts)
+      : SKEditorConsumer(Opts) {
     this->RespReceiver = RespReceiver;
   }
 
   sourcekitd_response_t createResponse();
 
   bool needsSemanticInfo() override {
-    return !SyntacticOnly && !isSemanticEditorDisabled();
+    return !Opts.SyntacticOnly && !isSemanticEditorDisabled();
   }
 
   void handleRequestError(const char *Description) override;
@@ -2056,7 +2059,7 @@
 
   bool handleSourceText(StringRef Text) override;
   bool handleSerializedSyntaxTree(StringRef Text) override;
-  virtual bool syntaxTreeEnabled() override;
+  bool syntaxTreeEnabled() override { return Opts.EnableSyntaxTree; }
   void finished() override {
     if (RespReceiver)
       RespReceiver(createResponse());
@@ -2066,13 +2069,11 @@
 } // end anonymous namespace
 
 static sourcekitd_response_t
-editorOpen(StringRef Name, llvm::MemoryBuffer *Buf, bool EnableSyntaxMap,
-           bool EnableStructure, bool EnableDiagnostics, bool EnableSyntaxTree,
-           bool SyntacticOnly, ArrayRef<const char *> Args) {
-  SKEditorConsumer EditC(EnableSyntaxMap, EnableStructure,
-                         EnableDiagnostics, EnableSyntaxTree, SyntacticOnly);
+editorOpen(StringRef Name, llvm::MemoryBuffer *Buf, SKEditorConsumerOptions Opts,
+           ArrayRef<const char *> Args) {
+  SKEditorConsumer EditC(Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
-  Lang.editorOpen(Name, Buf, EnableSyntaxMap, EditC, Args);
+  Lang.editorOpen(Name, Buf, EditC, Args);
   return EditC.createResponse();
 }
 
@@ -2081,11 +2082,10 @@
                     Optional<StringRef> Group, ArrayRef<const char *> Args,
                     bool SynthesizedExtensions,
                     Optional<StringRef> InterestedUSR) {
-  SKEditorConsumer EditC(/*EnableSyntaxMap=*/true,
-                         /*EnableStructure=*/true,
-                         /*EnableDiagnostics=*/false,
-                         /*EnableSyntaxTree=*/false,
-                         /*SyntacticOnly=*/false);
+  SKEditorConsumerOptions Opts;
+  Opts.EnableSyntaxMap = true;
+  Opts.EnableStructure = true;
+  SKEditorConsumer EditC(Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorOpenInterface(EditC, Name, ModuleName, Group, Args,
                            SynthesizedExtensions, InterestedUSR);
@@ -2099,12 +2099,10 @@
 editorOpenSwiftSourceInterface(StringRef Name, StringRef HeaderName,
                                ArrayRef<const char *> Args,
                                ResponseReceiver Rec) {
-  auto EditC = std::make_shared<SKEditorConsumer>(Rec,
-                                                  /*EnableSyntaxMap=*/true,
-                                                  /*EnableStructure=*/true,
-                                                  /*EnableDiagnostics=*/false,
-                                                  /*EnableSyntaxTree=*/false,
-                                                  /*SyntacticOnly=*/false);
+  SKEditorConsumerOptions Opts;
+  Opts.EnableSyntaxMap = true;
+  Opts.EnableStructure = true;
+  auto EditC = std::make_shared<SKEditorConsumer>(Rec, Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorOpenSwiftSourceInterface(Name, HeaderName, Args, EditC);
 }
@@ -2112,33 +2110,27 @@
 static void
 editorOpenSwiftTypeInterface(StringRef TypeUsr, ArrayRef<const char *> Args,
                              ResponseReceiver Rec) {
-  auto EditC = std::make_shared<SKEditorConsumer>(Rec,
-                                                  /*EnableSyntaxMap=*/true,
-                                                  /*EnableStructure=*/true,
-                                                  /*EnableDiagnostics=*/false,
-                                                  /*EnableSyntaxTree=*/false,
-                                                  /*SyntacticOnly=*/false);
+  SKEditorConsumerOptions Opts;
+  Opts.EnableSyntaxMap = true;
+  Opts.EnableStructure = true;
+  auto EditC = std::make_shared<SKEditorConsumer>(Rec, Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorOpenTypeInterface(*EditC, Args, TypeUsr);
 }
 
 static sourcekitd_response_t editorExtractTextFromComment(StringRef Source) {
-  SKEditorConsumer EditC(/*EnableSyntaxMap=*/false,
-                         /*EnableStructure=*/false,
-                         /*EnableDiagnostics=*/false,
-                         /*EnableSyntaxTree=*/false,
-                         /*SyntacticOnly=*/true);
+  SKEditorConsumerOptions Opts;
+  Opts.SyntacticOnly = true;
+  SKEditorConsumer EditC(Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorExtractTextFromComment(Source, EditC);
   return EditC.createResponse();
 }
 
 static sourcekitd_response_t editorConvertMarkupToXML(StringRef Source) {
-  SKEditorConsumer EditC(/*EnableSyntaxMap=*/false,
-                         /*EnableStructure=*/false,
-                         /*EnableDiagnostics=*/false,
-                         /*EnableSyntaxTree=*/false,
-                         /*SyntacticOnly=*/true);
+  SKEditorConsumerOptions Opts;
+  Opts.SyntacticOnly = true;
+  SKEditorConsumer EditC(Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorConvertMarkupToXML(Source, EditC);
   return EditC.createResponse();
@@ -2150,11 +2142,10 @@
                           bool UsingSwiftArgs,
                           bool SynthesizedExtensions,
                           StringRef swiftVersion) {
-  SKEditorConsumer EditC(/*EnableSyntaxMap=*/true,
-                         /*EnableStructure=*/true,
-                         /*EnableDiagnostics=*/false,
-                         /*EnableSyntaxTree=*/false,
-                         /*SyntacticOnly=*/false);
+  SKEditorConsumerOptions Opts;
+  Opts.EnableSyntaxMap = true;
+  Opts.EnableStructure = true;
+  SKEditorConsumer EditC(Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorOpenHeaderInterface(EditC, Name, HeaderName, Args, UsingSwiftArgs,
                                  SynthesizedExtensions, swiftVersion);
@@ -2171,11 +2162,8 @@
 
 static sourcekitd_response_t
 editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf, unsigned Offset,
-                  unsigned Length, bool EnableSyntaxMap, bool EnableStructure,
-                  bool EnableDiagnostics, bool EnableSyntaxTree,
-                  bool SyntacticOnly) {
-  SKEditorConsumer EditC(EnableSyntaxMap, EnableStructure,
-                         EnableDiagnostics, EnableSyntaxTree, SyntacticOnly);
+                  unsigned Length, SKEditorConsumerOptions Opts) {
+  SKEditorConsumer EditC(Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorReplaceText(Name, Buf, Offset, Length, EditC);
   return EditC.createResponse();
@@ -2190,8 +2178,9 @@
 
 static sourcekitd_response_t
 editorFormatText(StringRef Name, unsigned Line, unsigned Length) {
-  SKEditorConsumer EditC(false, false, false, false,
-                         /*SyntacticOnly=*/true);
+  SKEditorConsumerOptions Opts;
+  Opts.SyntacticOnly = true;
+  SKEditorConsumer EditC(Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorFormatText(Name, Line, Length, EditC);
   return EditC.createResponse();
@@ -2199,8 +2188,9 @@
 
 static sourcekitd_response_t
 editorExpandPlaceholder(StringRef Name, unsigned Offset, unsigned Length) {
-  SKEditorConsumer EditC(false, false, false, false,
-                         /*SyntacticOnly=*/true);
+  SKEditorConsumerOptions Opts;
+  Opts.SyntacticOnly = true;
+  SKEditorConsumer EditC(Opts);
   LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
   Lang.editorExpandPlaceholder(Name, Offset, Length, EditC);
   return EditC.createResponse();
@@ -2210,7 +2200,7 @@
   if (Error)
     return Error;
 
-  if (EnableSyntaxMap) {
+  if (Opts.EnableSyntaxMap) {
     Dict.setCustomBuffer(KeySyntaxMap,
         CustomBufferKind::TokenAnnotationsArray,
         SyntaxMap.createBuffer());
@@ -2220,7 +2210,7 @@
         CustomBufferKind::TokenAnnotationsArray,
         SemanticAnnotations.createBuffer());
   }
-  if (EnableStructure) {
+  if (Opts.EnableStructure) {
     Dict.setCustomBuffer(KeySubStructure, CustomBufferKind::DocStructureArray,
                          DocStructure.createBuffer());
   }
@@ -2241,7 +2231,7 @@
 
 bool SKEditorConsumer::handleSyntaxMap(unsigned Offset, unsigned Length,
                                        UIdent Kind) {
-  if (!EnableSyntaxMap)
+  if (!Opts.EnableSyntaxMap)
     return true;
 
   SyntaxMap.add(Kind, Offset, Length, /*IsSystem=*/false);
@@ -2273,7 +2263,7 @@
                                             StringRef SelectorName,
                                             ArrayRef<StringRef> InheritedTypes,
                                             ArrayRef<std::tuple<UIdent, unsigned, unsigned>> Attrs) {
-  if (EnableStructure) {
+  if (Opts.EnableStructure) {
     DocStructure.beginSubStructure(
         Offset, Length, Kind, AccessLevel, SetterAccessLevel, NameOffset,
         NameLength, BodyOffset, BodyLength, DocOffset, DocLength, DisplayName,
@@ -2283,7 +2273,7 @@
 }
 
 bool SKEditorConsumer::endDocumentSubStructure() {
-  if (EnableStructure)
+  if (Opts.EnableStructure)
     DocStructure.endSubStructure();
   return true;
 }
@@ -2291,7 +2281,7 @@
 bool SKEditorConsumer::handleDocumentSubStructureElement(UIdent Kind,
                                                          unsigned Offset,
                                                          unsigned Length) {
-  if (EnableStructure)
+  if (Opts.EnableStructure)
     DocStructure.addElement(Kind, Offset, Length);
   return true;
 }
@@ -2387,7 +2377,7 @@
 
 bool SKEditorConsumer::handleDiagnostic(const DiagnosticEntryInfo &Info,
                                         UIdent DiagStage) {
-  if (!EnableDiagnostics)
+  if (!Opts.EnableDiagnostics)
     return true;
 
   ResponseBuilder::Array &Arr = Diags;
@@ -2405,12 +2395,8 @@
   return true;
 }
 
-bool SKEditorConsumer::syntaxTreeEnabled() {
-  return EnableSyntaxTree;
-}
-
 bool SKEditorConsumer::handleSerializedSyntaxTree(StringRef Text) {
-  if (EnableSyntaxTree)
+  if (syntaxTreeEnabled())
     Dict.set(KeySerializedSyntaxTree, Text);
   return true;
 }
diff --git a/tools/driver/modulewrap_main.cpp b/tools/driver/modulewrap_main.cpp
index 663799e..6c1a07d 100644
--- a/tools/driver/modulewrap_main.cpp
+++ b/tools/driver/modulewrap_main.cpp
@@ -171,6 +171,8 @@
   LangOpts.Target = Invocation.getTargetTriple();
   ASTContext &ASTCtx = *ASTContext::get(LangOpts, SearchPathOpts, SrcMgr,
                                         Instance.getDiags());
+  registerTypeCheckerRequestFunctions(ASTCtx.evaluator);
+  
   ClangImporterOptions ClangImporterOpts;
   ASTCtx.addModuleLoader(ClangImporter::create(ASTCtx, ClangImporterOpts, ""),
                          true);
diff --git a/unittests/AST/ArithmeticEvaluator.cpp b/unittests/AST/ArithmeticEvaluator.cpp
index 0d2f697..cfa6165 100644
--- a/unittests/AST/ArithmeticEvaluator.cpp
+++ b/unittests/AST/ArithmeticEvaluator.cpp
@@ -87,9 +87,8 @@
   : public SimpleRequest<Derived, Caching, double, ArithmeticExpr *>
 {
   using SimpleRequest<Derived, Caching, double, ArithmeticExpr *>::SimpleRequest;
-  using SimpleRequest<Derived, Caching, double, ArithmeticExpr *>::operator();
 
-  double operator()(Evaluator &evaluator, ArithmeticExpr *expr) const {
+  double evaluate(Evaluator &evaluator, ArithmeticExpr *expr) const {
     switch (expr->kind) {
     case ArithmeticExpr::Kind::Literal:
       return static_cast<Literal *>(expr)->value;
@@ -179,16 +178,25 @@
 
 // Define the arithmetic evaluator's zone.
 namespace swift {
-#define SWIFT_TYPEID_ZONE 255
+#define SWIFT_ARITHMETIC_EVALUATOR_ZONE 255
+#define SWIFT_TYPEID_ZONE SWIFT_ARITHMETIC_EVALUATOR_ZONE
 #define SWIFT_TYPEID_HEADER "ArithmeticEvaluatorTypeIDZone.def"
 #include "swift/Basic/DefineTypeIDZone.h"
 
-#define SWIFT_TYPEID_ZONE 255
+#define SWIFT_TYPEID_ZONE SWIFT_ARITHMETIC_EVALUATOR_ZONE
 #define SWIFT_TYPEID_HEADER "ArithmeticEvaluatorTypeIDZone.def"
 #include "swift/Basic/ImplementTypeIDZone.h"
 
 }
 
+/// All of the arithmetic request functions.
+static AbstractRequestFunction *arithmeticRequestFunctions[] = {
+#define SWIFT_TYPEID(Name)                                    \
+  reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
+#include "ArithmeticEvaluatorTypeIDZone.def"
+#undef SWIFT_TYPEID
+};
+
 TEST(ArithmeticEvaluator, Simple) {
   // (3.14159 + 2.71828) * 42
   ArithmeticExpr *pi = new Literal(3.14159);
@@ -201,6 +209,8 @@
   SourceManager sourceMgr;
   DiagnosticEngine diags(sourceMgr);
   Evaluator evaluator(diags, CycleDiagnosticKind::FullDiagnose);
+  evaluator.registerRequestFunctions(SWIFT_ARITHMETIC_EVALUATOR_ZONE,
+                                     arithmeticRequestFunctions);
 
   const double expectedResult = (3.14159 + 2.71828) * 42.0;
   EXPECT_EQ(evaluator(InternallyCachedEvaluationRule(product)),
@@ -321,6 +331,8 @@
   SourceManager sourceMgr;
   DiagnosticEngine diags(sourceMgr);
   Evaluator evaluator(diags, CycleDiagnosticKind::FullDiagnose);
+  evaluator.registerRequestFunctions(SWIFT_ARITHMETIC_EVALUATOR_ZONE,
+                                     arithmeticRequestFunctions);
 
   // Evaluate when there is a cycle.
   UncachedEvaluationRule::brokeCycle = false;
diff --git a/unittests/AST/TestContext.cpp b/unittests/AST/TestContext.cpp
index cd1366a..6890661 100644
--- a/unittests/AST/TestContext.cpp
+++ b/unittests/AST/TestContext.cpp
@@ -13,6 +13,7 @@
 #include "TestContext.h"
 #include "swift/AST/Module.h"
 #include "swift/Strings.h"
+#include "swift/Subsystems.h"
 
 using namespace swift;
 using namespace swift::unittest;
@@ -34,6 +35,7 @@
 
 TestContext::TestContext(ShouldDeclareOptionalTypes optionals)
     : Ctx(*ASTContext::get(LangOpts, SearchPathOpts, SourceMgr, Diags)) {
+  registerTypeCheckerRequestFunctions(Ctx.evaluator);
   auto stdlibID = Ctx.getIdentifier(STDLIB_NAME);
   auto *module = ModuleDecl::create(stdlibID, Ctx);
   Ctx.LoadedModules[stdlibID] = module;
diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
index 4b314a2..3477e8d 100644
--- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
+++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
@@ -136,8 +136,7 @@
     auto Args = CArgs.hasValue() ? makeArgs(DocName, *CArgs)
                                  : std::vector<const char *>{};
     auto Buf = MemoryBuffer::getMemBufferCopy(Text, DocName);
-    getLang().editorOpen(DocName, Buf.get(), /*EnableSyntaxMap=*/false,
-                         Consumer, Args);
+    getLang().editorOpen(DocName, Buf.get(), Consumer, Args);
   }
 
   void replaceText(StringRef DocName, unsigned Offset, unsigned Length,
diff --git a/unittests/SourceKit/SwiftLang/EditingTest.cpp b/unittests/SourceKit/SwiftLang/EditingTest.cpp
index 0c61b0f..bc7d217 100644
--- a/unittests/SourceKit/SwiftLang/EditingTest.cpp
+++ b/unittests/SourceKit/SwiftLang/EditingTest.cpp
@@ -157,8 +157,7 @@
             EditorConsumer &Consumer) {
     auto Args = makeArgs(DocName, CArgs);
     auto Buf = MemoryBuffer::getMemBufferCopy(Text, DocName);
-    getLang().editorOpen(DocName, Buf.get(), /*EnableSyntaxMap=*/false, Consumer,
-                         Args);
+    getLang().editorOpen(DocName, Buf.get(), Consumer, Args);
   }
 
   void close(const char *DocName) {
diff --git a/validation-test/IDE/crashers/032-swift-expr-propagatelvalueaccesskind.swift b/validation-test/IDE/crashers/032-swift-expr-propagatelvalueaccesskind.swift
deleted file mode 100644
index f7bf01e..0000000
--- a/validation-test/IDE/crashers/032-swift-expr-propagatelvalueaccesskind.swift
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
-// REQUIRES: asserts
-{()=(var a{#^A^#
diff --git a/validation-test/IDE/crashers_fixed/032-swift-expr-propagatelvalueaccesskind.swift b/validation-test/IDE/crashers_fixed/032-swift-expr-propagatelvalueaccesskind.swift
new file mode 100644
index 0000000..6eec7a0
--- /dev/null
+++ b/validation-test/IDE/crashers_fixed/032-swift-expr-propagatelvalueaccesskind.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+
+{()=(var a{#^A^#
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift b/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift
index 5525c1a..1eef996 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar19612086.swift
@@ -13,7 +13,10 @@
   var description : String {
     return "\(i)" + Stringly(format: "%.2f", x) +
            "\(i+1)" + Stringly(format: "%.2f", x) +
-           "\(i+2)" + Stringly(format: "%.2f", x)
+           "\(i+2)" + Stringly(format: "%.2f", x) +
+           "\(i+3)" + Stringly(format: "%.2f", x) +
+           "\(i+4)" + Stringly(format: "%.2f", x) +
+           "\(i+5)" + Stringly(format: "%.2f", x)
     // expected-error@-1 {{reasonable time}}
   }
 }
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift b/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
index 9e0f15d..a640a29 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
@@ -9,5 +9,9 @@
 
 [Int](0..<1).map {
   // expected-error@-1 {{reasonable time}}
-  print(Stringly(format: "%d: ", $0 * 2 * 42) + ["a", "b", "c", "d", "e", "f", "g"][$0 * 2] + "," + "," + ",")
+  print(Stringly(format: "%d: ",
+      $0 * 2 * 42 +
+      $0 * 2 * 42 +
+      $0 * 2 * 42
+    ) + ["a", "b", "c", "d", "e", "f", "g"][$0 * 2] + "," + "," + ",")
 }
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar22770433.swift b/validation-test/Sema/type_checker_perf/slow/rdar22770433.swift
index cd2d914..9ccd3b5 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar22770433.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar22770433.swift
@@ -3,7 +3,7 @@
 
 func test(n: Int) -> Int {
   return n == 0 ? 0 : (0..<n).reduce(0) {
-  // expected-error@-1 {{reasonable time}}
-    ($0 > 0 && $1 % 2 == 0) ? (($0 + $1) / ($1 - $0)) : $0
+    // expected-error@-1 {{reasonable time}}
+    ($0 > 0 && $1 % 2 == 0) ? ((($0 + $1) - ($0 + $1)) / ($1 - $0)) + (($0 + $1) / ($1 - $0)) : $0
   }
 }
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar22949523.swift b/validation-test/Sema/type_checker_perf/slow/rdar22949523.swift
index fc29dbd..1ee4dc3 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar22949523.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar22949523.swift
@@ -1,5 +1,5 @@
 // RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1
 // REQUIRES: tools-release,no_asserts
 
-_ = [0,1,2,3].lazy.map { String($0)+"hi" }.sorted(by: { $0 > $1 })
+_ = [0,1,2,3].lazy.map { String($0)+"hi" }.sorted(by: { $0 > $1 && $1 < $0 && ($1 + $0) < 1000 })
 // expected-error@-1 {{reasonable time}}
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar23429943.swift b/validation-test/Sema/type_checker_perf/slow/rdar23429943.swift
index 1410c5d..c75dff8 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar23429943.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar23429943.swift
@@ -3,5 +3,5 @@
 
 let _ = [0].reduce([Int]()) {
   // expected-error@-1 {{reasonable time}}
-  return $0.count == 0 && $1 == 0 ? [] : $0 + [$1]
+  return $0.count == 0 && ($1 == 0 || $1 == 2 || $1 == 3) ? [] : $0 + [$1]
 }
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar23861629.swift b/validation-test/Sema/type_checker_perf/slow/rdar23861629.swift
index 2cf28a1..4942edb 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar23861629.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar23861629.swift
@@ -6,6 +6,6 @@
 func rdar23861629(_ a: [S]) {
   _ = a.reduce("") {
     // expected-error@-1 {{reasonable time}}
-    ($0 == "") ? ($1.s ?? "") : $0 + "," + ($1.s ?? "")
+    ($0 == "") ? ($1.s ?? "") : ($0 + "," + ($1.s ?? "")) + ($1.s ?? "test") + ($1.s ?? "okay")
   }
 }
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar31742586.swift b/validation-test/Sema/type_checker_perf/slow/rdar31742586.swift
index a4819a6..4907dbb 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar31742586.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar31742586.swift
@@ -2,6 +2,6 @@
 // REQUIRES: tools-release,no_asserts
 
 func rdar31742586() -> Double {
-  return -(1 + 2) + -(3 + 4) + 5
+  return -(1 + 2) + -(3 + 4) + 5 - (-(1 + 2) + -(3 + 4) + 5)
   // expected-error@-1 {{reasonable time}}
 }
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar32998180.swift b/validation-test/Sema/type_checker_perf/slow/rdar32998180.swift
index da38c36..3e13c52 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar32998180.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar32998180.swift
@@ -2,7 +2,8 @@
 // REQUIRES: tools-release,no_asserts
 
 func rdar32998180(value: UInt16) -> UInt16 {
-  var result = (((value >> 1) ^ (value >> 1) ^ (value >> 1) ^ (value >> 1)) & 1) << 1
+  var result = ((((value >> 1) ^ (value >> 1) ^ (value >> 1) ^ (value >> 1)) & 1) << 1)
+  | (((((value >> 1) ^ (value >> 1) ^ (value >> 1) ^ (value >> 1)) & 1) << 1) << 1)
   // expected-error@-1 {{reasonable time}}
   return result
 }
diff --git a/validation-test/compiler_crashers_2_fixed/0165-sr5427.swift b/validation-test/compiler_crashers_2_fixed/0165-sr5427.swift
new file mode 100644
index 0000000..845d263
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0165-sr5427.swift
@@ -0,0 +1,7 @@
+// RUN: %target-typecheck-verify-swift
+
+// Used to crash with: apply expression is not marked as throwing or
+// non-throwing
+struct SR5427 : Error {}
+func sr5427(op: (() throws -> Void)?) rethrows { try op?() }
+try? sr5427(op: { throw SR5427() })
diff --git a/validation-test/compiler_crashers/28847-type-hasunboundgenerictype.swift b/validation-test/compiler_crashers_fixed/28847-type-hasunboundgenerictype.swift
similarity index 84%
rename from validation-test/compiler_crashers/28847-type-hasunboundgenerictype.swift
rename to validation-test/compiler_crashers_fixed/28847-type-hasunboundgenerictype.swift
index 1d8ad46..fb6f0bf 100644
--- a/validation-test/compiler_crashers/28847-type-hasunboundgenerictype.swift
+++ b/validation-test/compiler_crashers_fixed/28847-type-hasunboundgenerictype.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 extension a{protocol P{}}class a<a{var f=a a{}func a:P&
diff --git a/validation-test/stdlib/AnyHashable.swift.gyb b/validation-test/stdlib/AnyHashable.swift.gyb
index 05084ad..c6fa6cf 100644
--- a/validation-test/stdlib/AnyHashable.swift.gyb
+++ b/validation-test/stdlib/AnyHashable.swift.gyb
@@ -767,6 +767,132 @@
   expectEqual(MinimalHashableRCSwiftError.self, type(of: ah.base))
 }
 
+AnyHashableTests.test("AnyHashable(NumericTypes)/Hashable") {
+  // Numeric types holding mathematically equal values must compare equal and
+  // hash the same way when converted to AnyHashable.
+  let groups: [[AnyHashable]] = [
+    [
+      1 as Int,
+      1 as UInt,
+      1 as Int8,
+      1 as UInt8,
+      1 as Int16,
+      1 as UInt16,
+      1 as Int32,
+      1 as UInt32,
+      1 as Int64,
+      1 as UInt64,
+      1 as Float,
+      1 as Double,
+    ],
+    [
+      42 as Int,
+      42 as UInt,
+      42 as Int8,
+      42 as UInt8,
+      42 as Int16,
+      42 as UInt16,
+      42 as Int32,
+      42 as UInt32,
+      42 as Int64,
+      42 as UInt64,
+      42 as Float,
+      42 as Double,
+    ],
+    [
+      Int(Int32.max),
+      UInt(Int32.max),
+      Int32.max,
+      UInt32(Int32.max),
+      Int64(Int32.max),
+      UInt64(Int32.max),
+      Double(Int32.max),
+    ],
+    [
+      Float.infinity,
+      Double.infinity,
+    ],
+    [
+      0x1.aP1 as Float, // 3.25
+      0x1.aP1 as Double,
+    ],
+    [
+      0x1.a000000000001P1, // 3.25.nextUp, not representable by a Float
+    ]
+  ]
+  checkHashableGroups(groups)
+}
+
+#if !os(Windows) && (arch(i386) || arch(x86_64))
+AnyHashableTests.test("AnyHashable(Float80)/Hashable") {
+  let groups: [[AnyHashable]] = [
+    [
+      42 as Int,
+      42 as Float,
+      42 as Double,
+      42 as Float80,
+    ],
+    [
+      Float.infinity,
+      Double.infinity,
+      Float80.infinity,
+    ],
+    [
+      3.25 as Float,
+      3.25 as Double,
+      3.25 as Float80,
+    ],
+    [
+      0x1.a000000000001P1 as Double, // 3.25.nextUp
+      0x1.a000000000001P1 as Float80,
+    ],
+    [
+      0x1.a000000000000002p1 as Float80, // (3.25 as Float80).nextUp
+    ],
+  ]
+  checkHashableGroups(groups)
+}
+#endif
+
+#if _runtime(_ObjC)
+// A wrapper type around an Int that bridges to NSNumber.
+struct IntWrapper1 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+  let rawValue: Int
+}
+
+// A wrapper type around an Int that bridges to NSNumber.
+struct IntWrapper2 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+  let rawValue: Int
+}
+
+// A wrapper type around an Int that bridges to NSNumber.
+struct Int8Wrapper : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
+  let rawValue: Int8
+}
+
+AnyHashableTests.test("AnyHashable(IntWrappers)/Hashable") {
+  let groups: [[AnyHashable]] = [
+    [
+      IntWrapper1(rawValue: 42),
+      IntWrapper2(rawValue: 42),
+      Int8Wrapper(rawValue: 42),
+      42,
+      42 as Double,
+      42 as NSNumber,
+    ],
+    [
+      IntWrapper1(rawValue: -23),
+      IntWrapper2(rawValue: -23),
+      Int8Wrapper(rawValue: -23),
+      -23,
+      -23 as Double,
+      -23 as NSNumber,
+    ],
+  ]
+  checkHashableGroups(groups)
+}
+#endif
+
 #if _runtime(_ObjC)
 // A wrapper type around a String that bridges to NSString.
 struct StringWrapper1 : _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {
@@ -778,126 +904,101 @@
   let rawValue: String
 }
 
-AnyHashableTests.test("AnyHashable(Wrappers)/Hashable") {
-  let values: [AnyHashable] = [
-    StringWrapper1(rawValue: "hello"),
-    StringWrapper2(rawValue: "hello"),
-    "hello" as String,
-    "hello" as NSString,
-    StringWrapper1(rawValue: "world"),
-    StringWrapper2(rawValue: "world"),
-    "world" as String,
-    "world" as NSString,
+AnyHashableTests.test("AnyHashable(StringWrappers)/Hashable") {
+  let groups: [[AnyHashable]] = [
+    [
+      StringWrapper1(rawValue: "hello"),
+      StringWrapper2(rawValue: "hello"),
+      "hello" as String,
+      "hello" as NSString,
+    ],
+    [
+      StringWrapper1(rawValue: "world"),
+      StringWrapper2(rawValue: "world"),
+      "world" as String,
+      "world" as NSString,
+    ]
   ]
-
-  func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
-    // Elements in [0, 3] match 3.
-    if lhs == 3 { return rhs >= 0 && rhs <= 3 }
-    if rhs == 3 { return lhs >= 0 && lhs <= 3 }
-
-    // Elements in [4, 7] match 7.
-    if lhs == 7 { return rhs >= 4 && rhs <= 7 }
-    if rhs == 7 { return lhs >= 4 && lhs <= 7 }
-
-    return lhs == rhs
-  }
-
-  func hashEqualityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
-    // Elements in [0, 3] hash the same, as do elements in [4, 7].
-    return lhs / 4 == rhs / 4
-  }
-
-  checkHashable(
-    values,
-    equalityOracle: equalityOracle,
-    hashEqualityOracle: hashEqualityOracle,
-    allowBrokenTransitivity: true)
+  checkHashableGroups(groups)
 }
 
 AnyHashableTests.test("AnyHashable(Set)/Hashable") {
-  let values: [AnyHashable] = [
-    Set([1, 2, 3]),
-    NSSet(set: [1, 2, 3]),
-    Set([2, 3, 4]),
-    NSSet(set: [2, 3, 4]),
-    Set([Set([1, 2]), Set([3, 4])]),
-    NSSet(set: [NSSet(set: [1, 2]), NSSet(set: [3, 4])]),
-    Set([Set([1, 3]), Set([2, 4])]),
-    NSSet(set: [NSSet(set: [1, 3]), NSSet(set: [2, 4])]),
+  let groups: [[AnyHashable]] = [
+    [
+      Set([1, 2, 3]),
+      Set([1, 2, 3] as [Int8]),
+      Set([1, 2, 3] as [Float]),
+      NSSet(set: [1, 2, 3]),
+    ],
+    [
+      Set([2, 3, 4]),
+      NSSet(set: [2, 3, 4]),
+    ],
+    [
+      Set([Set([1, 2]), Set([3, 4])]),
+      NSSet(set: [NSSet(set: [1, 2]), NSSet(set: [3, 4])]),
+    ],
+    [
+      Set([Set([1, 3]), Set([2, 4])]),
+      NSSet(set: [NSSet(set: [1, 3]), NSSet(set: [2, 4])]),
+    ],
   ]
-
-  func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
-    switch (lhs, rhs) {
-    case (0...1, 0...1): return true
-    case (2...3, 2...3): return true
-    case (4...5, 4...5): return true
-    case (6...7, 6...7): return true
-    default: return false
-    }
-  }
-
-  checkHashable(
-    values,
-    equalityOracle: equalityOracle,
-    allowBrokenTransitivity: true)
+  checkHashableGroups(groups)
 }
 
 AnyHashableTests.test("AnyHashable(Array)/Hashable") {
-  let values: [AnyHashable] = [
-    [1, 2, 3],
-    NSArray(array: [1, 2, 3]),
-    [3, 2, 1],
-    NSArray(array: [3, 2, 1]),
-    [[1, 2], [3, 4]],
-    NSArray(array: [NSArray(array: [1, 2]), NSArray(array: [3, 4])]),
-    [[3, 4], [1, 2]],
-    NSArray(array: [NSArray(array: [3, 4]), NSArray(array: [1, 2])]),
+  let groups: [[AnyHashable]] = [
+    [
+      [1, 2, 3],
+      [1, 2, 3] as [Int8],
+      [1, 2, 3] as [Double],
+      NSArray(array: [1, 2, 3]),
+    ],
+    [
+      [3, 2, 1],
+      [3, 2, 1] as [AnyHashable],
+      NSArray(array: [3, 2, 1]),
+    ],
+    [
+      [[1, 2], [3, 4]],
+      NSArray(array: [NSArray(array: [1, 2]), NSArray(array: [3, 4])]),
+    ],
+    [
+      [[3, 4], [1, 2]],
+      NSArray(array: [NSArray(array: [3, 4]), NSArray(array: [1, 2])]),
+    ]
   ]
-
-  func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
-    switch (lhs, rhs) {
-    case (0...1, 0...1): return true
-    case (2...3, 2...3): return true
-    case (4...5, 4...5): return true
-    case (6...7, 6...7): return true
-    default: return false
-    }
-  }
-
-  checkHashable(values, equalityOracle: equalityOracle,
-                allowBrokenTransitivity: true)
+  checkHashableGroups(groups)
 }
 
 AnyHashableTests.test("AnyHashable(Dictionary)/Hashable") {
-  let values: [AnyHashable] = [
-    ["hello": 1, "world": 2],
-    NSDictionary(dictionary: ["hello": 1, "world": 2]),
-    ["hello": 2, "world": 1],
-    NSDictionary(dictionary: ["hello": 2, "world": 1]),
-    ["hello": ["foo": 1, "bar": 2],
-     "world": ["foo": 2, "bar": 1]],
-    NSDictionary(dictionary: [
-        "hello": ["foo": 1, "bar": 2],
-        "world": ["foo": 2, "bar": 1]]),
-    ["hello": ["foo": 2, "bar": 1],
-     "world": ["foo": 1, "bar": 2]],
-    NSDictionary(dictionary: [
-        "hello": ["foo": 2, "bar": 1],
-        "world": ["foo": 1, "bar": 2]]),
+  let groups: [[AnyHashable]] = [
+    [
+      ["hello": 1, "world": 2] as [String: Int],
+      ["hello": 1, "world": 2] as [String: Int16],
+      ["hello": 1, "world": 2] as [String: Float],
+      NSDictionary(dictionary: ["hello": 1, "world": 2]),
+    ],
+    [
+      ["hello": 2, "world": 1],
+      NSDictionary(dictionary: ["hello": 2, "world": 1]),
+    ],
+    [
+      ["hello": ["foo": 1, "bar": 2],
+        "world": ["foo": 2, "bar": 1]],
+      NSDictionary(dictionary: [
+          "hello": ["foo": 1, "bar": 2],
+          "world": ["foo": 2, "bar": 1]]),
+    ],
+    [
+      ["hello": ["foo": 2, "bar": 1],
+        "world": ["foo": 1, "bar": 2]],
+      NSDictionary(dictionary: [
+          "hello": ["foo": 2, "bar": 1],
+          "world": ["foo": 1, "bar": 2]]),
+    ],
   ]
-
-  func equalityOracle(_ lhs: Int, _ rhs: Int) -> Bool {
-    switch (lhs, rhs) {
-    case (0...1, 0...1): return true
-    case (2...3, 2...3): return true
-    case (4...5, 4...5): return true
-    case (6...7, 6...7): return true
-    default: return false
-    }
-  }
-
-  checkHashable(values, equalityOracle: equalityOracle,
-                allowBrokenTransitivity: true)
+  checkHashableGroups(groups)
 }
 
 AnyHashableTests.test("AnyHashable(_SwiftNativeNSError(MinimalHashablePODSwiftError))/Hashable") {
diff --git a/validation-test/stdlib/BoolDiagnostics_Dataflow.swift b/validation-test/stdlib/BoolDiagnostics_Dataflow.swift
index 29774a6..576b4d0 100644
--- a/validation-test/stdlib/BoolDiagnostics_Dataflow.swift
+++ b/validation-test/stdlib/BoolDiagnostics_Dataflow.swift
@@ -55,5 +55,5 @@
   }
 } // expected-error {{missing return in a function expected to return 'Int'}}
 
-// expected-warning@+1 {{'ExpressibleByStringInterpolation' is deprecated: it will be replaced or redesigned in Swift 4.0.  Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'}}
+// expected-warning@+1 {{'ExpressibleByStringInterpolation' is deprecated: it will be replaced or redesigned in Swift 5.0.  Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'}}
 typealias X = ExpressibleByStringInterpolation
diff --git a/validation-test/stdlib/CollectionCompatibility.swift b/validation-test/stdlib/CollectionCompatibility.swift
index 4040c41..4049393 100644
--- a/validation-test/stdlib/CollectionCompatibility.swift
+++ b/validation-test/stdlib/CollectionCompatibility.swift
@@ -24,7 +24,7 @@
 }
 
 //===--- MyBidiCollection -------------------------------------------------===//
-/// A simple collection that attempts to use an Int16 IndexDistance
+/// A simple collection that doesn't declare an IndexDistance
 struct MyBidiCollection<Element>: BidirectionalCollection {
   var _elements: [Element]
   
@@ -45,12 +45,12 @@
 
 CollectionDistance.test("Int16/distance") {
   let c = MyCollection<Int>(_elements: [1,2,3])
-  let d: Int16 = c.distance(from: c.startIndex, to: c.endIndex)
+  var d: Int16 = c.distance(from: c.startIndex, to: c.endIndex)
   expectEqual(3, d)
+  expectType(MyCollection<Int>.IndexDistance.self, &d)
   // without type context, you now get an Int
   var i = c.distance(from: c.startIndex, to: c.endIndex)
   expectType(Int.self, &i)
-  expectType(MyCollection<Int>.IndexDistance.self, &i)
 }
 
 CollectionDistance.test("Int16/advance") {
@@ -76,12 +76,10 @@
 
 CollectionDistance.test("Int64/distance") {
   let c = MyBidiCollection<Int>(_elements: [1,2,3])
-  let d: Int16 = c.distance(from: c.startIndex, to: c.endIndex)
+  var d = c.distance(from: c.startIndex, to: c.endIndex)
   expectEqual(3, d)
-  // without type context, you now get an Int
-  var i = c.distance(from: c.startIndex, to: c.endIndex)
-  expectType(Int.self, &i)
-  expectType(MyCollection<Int>.IndexDistance.self, &i)
+  expectType(Int.self, &d)
+  expectType(MyBidiCollection<Int>.IndexDistance.self, &d)
 }
 
 CollectionDistance.test("Int64/advance") {
@@ -106,4 +104,15 @@
   checkBidirectionalCollection(c, [1,2,3])
 }
 
+extension Collection where Index == Int, IndexDistance == Int {
+  var myCount: Int {
+    return distance(from: startIndex, to: endIndex)
+  }
+}
+
+CollectionDistance.test("IndexDistance/constraint") {
+  let n = [1,2,3].myCount
+  expectEqual(3, n)
+}
+
 runAllTests()
diff --git a/validation-test/stdlib/CollectionDiagnostics.swift b/validation-test/stdlib/CollectionDiagnostics.swift
index f1158bc..78cee40 100644
--- a/validation-test/stdlib/CollectionDiagnostics.swift
+++ b/validation-test/stdlib/CollectionDiagnostics.swift
@@ -48,7 +48,8 @@
   array.sorted { $0 < $1 } // expected-warning {{result of call to 'sorted(by:)' is unused}}
 }
 
-// expected-warning@+1 {{'Indexable' is deprecated: it will be removed in Swift 4.0.  Please use 'Collection' instead}}
+// expected-warning@+2 {{'Indexable' is deprecated: it will be removed in Swift 5.0.  Please use 'Collection' instead}}
+// expected-note@+1 {{use 'Collection' instead}}
 struct GoodIndexable : Indexable { 
   func index(after i: Int) -> Int { return i + 1 }
   var startIndex: Int { return 0 }
@@ -59,7 +60,8 @@
 }
 
 
-// expected-warning@+1 {{'Indexable' is deprecated: it will be removed in Swift 4.0.  Please use 'Collection' instead}}
+// expected-warning@+2 {{'Indexable' is deprecated: it will be removed in Swift 5.0.  Please use 'Collection' instead}}
+// expected-note@+1 {{use 'Collection' instead}}
 struct AnotherGoodIndexable1 : Indexable {
   func index(after i: Int) -> Int { return i + 1 }
   var startIndex: Int { return 0 }
@@ -68,8 +70,9 @@
   subscript(pos: Int) -> Int { return 0 }
 }
 
-// expected-warning@+2 {{'Indexable' is deprecated: it will be removed in Swift 4.0.  Please use 'Collection' instead}}
-// expected-error@+1 {{type 'BadIndexable2' does not conform to protocol 'Collection'}}
+// expected-warning@+3 {{'Indexable' is deprecated: it will be removed in Swift 5.0.  Please use 'Collection' instead}}
+// expected-error@+2 {{type 'BadIndexable2' does not conform to protocol 'Collection'}}
+// expected-note@+1 {{use 'Collection' instead}}
 struct BadIndexable2 : Indexable {
   var startIndex: Int { return 0 }
   var endIndex: Int { return 0 }
@@ -79,7 +82,8 @@
   // Missing index(after:) -> Int
 }
 
-// expected-warning@+1 {{'BidirectionalIndexable' is deprecated: it will be removed in Swift 4.0.  Please use 'BidirectionalCollection' instead}}
+// expected-warning@+2 {{'BidirectionalIndexable' is deprecated: it will be removed in Swift 5.0.  Please use 'BidirectionalCollection' instead}}
+// expected-note@+1 {{use 'BidirectionalCollection' instead}}
 struct GoodBidirectionalIndexable1 : BidirectionalIndexable {
   var startIndex: Int { return 0 }
   var endIndex: Int { return 0 }
@@ -92,7 +96,8 @@
 
 // We'd like to see: {{type 'BadBidirectionalIndexable' does not conform to protocol 'BidirectionalIndexable'}}
 // But the compiler doesn't generate that error.
-// expected-warning@+1 {{'BidirectionalIndexable' is deprecated: it will be removed in Swift 4.0.  Please use 'BidirectionalCollection' instead}}
+// expected-warning@+2 {{'BidirectionalIndexable' is deprecated: it will be removed in Swift 5.0.  Please use 'BidirectionalCollection' instead}}
+// expected-note@+1 {{use 'BidirectionalCollection' instead}}
 struct BadBidirectionalIndexable : BidirectionalIndexable {
   var startIndex: Int { return 0 }
   var endIndex: Int { return 0 }
diff --git a/validation-test/stdlib/DictionaryAnyHashableExtensions.swift b/validation-test/stdlib/DictionaryAnyHashableExtensions.swift
index 8cfaaa6..9d57794 100644
--- a/validation-test/stdlib/DictionaryAnyHashableExtensions.swift
+++ b/validation-test/stdlib/DictionaryAnyHashableExtensions.swift
@@ -6,26 +6,73 @@
 var DictionaryTests = TestSuite("Dictionary")
 
 DictionaryTests.test("index<Hashable>(forKey:)") {
-  let d: [AnyHashable : Int] = [
-    AnyHashable(10) : 1010,
-    AnyHashable(20) : 2020,
-    AnyHashable(30.0) : 3030,
+  let a = AnyHashable(10 as UInt16)
+  let b = AnyHashable(20)
+  let c = AnyHashable(30.0)
+  let d: [AnyHashable: Int] = [
+    a: 1010,
+    b: 2020,
+    c: 3030,
   ]
 
-  expectEqual(1010, d[d.index(forKey: 10)!].value)
-  expectEqual(2020, d[d.index(forKey: 20)!].value)
-  expectEqual(3030, d[d.index(forKey: 30.0)!].value)
+  for (key, k, value) in [(a, 10, 1010), (b, 20, 2020), (c, 30, 3030)] {
+    let index = d.index(forKey: key)!
+    expectEqual(value, d[index].value)
+    // We must be able to look up the same number in any representation.
+    expectEqual(index, d.index(forKey: UInt8(k)))
+    expectEqual(index, d.index(forKey: UInt16(k)))
+    expectEqual(index, d.index(forKey: UInt32(k)))
+    expectEqual(index, d.index(forKey: UInt64(k)))
+    expectEqual(index, d.index(forKey: UInt(k)))
+    expectEqual(index, d.index(forKey: Int8(k)))
+    expectEqual(index, d.index(forKey: Int16(k)))
+    expectEqual(index, d.index(forKey: Int32(k)))
+    expectEqual(index, d.index(forKey: Int64(k)))
+    expectEqual(index, d.index(forKey: Int(k)))
+    expectEqual(index, d.index(forKey: Float(k)))
+    expectEqual(index, d.index(forKey: Double(k)))
 
-  expectNil(d.index(forKey: 10.0))
-  expectNil(d.index(forKey: 20.0))
-  expectNil(d.index(forKey: 30))
+    expectNil(d.index(forKey: String(k)))
+  }
 }
 
 DictionaryTests.test("subscript<Hashable>(_:)") {
-  var d: [AnyHashable : Int] = [
-    AnyHashable(10) : 1010,
-    AnyHashable(20) : 2020,
-    AnyHashable(30.0) : 3030,
+  let a = AnyHashable(10 as UInt16)
+  let b = AnyHashable(20)
+  let c = AnyHashable(30.0)
+  let d: [AnyHashable: Int] = [
+    a: 1010,
+    b: 2020,
+    c: 3030,
+  ]
+
+  for (key, k, value) in [(a, 10, 1010), (b, 20, 2020), (c, 30, 3030)] {
+    let index = d.index(forKey: key)!
+    expectEqual(value, d[key])
+    // We must be able to look up the same number in any representation.
+    expectEqual(value, d[UInt8(k)])
+    expectEqual(value, d[UInt16(k)])
+    expectEqual(value, d[UInt32(k)])
+    expectEqual(value, d[UInt64(k)])
+    expectEqual(value, d[UInt(k)])
+    expectEqual(value, d[Int8(k)])
+    expectEqual(value, d[Int16(k)])
+    expectEqual(value, d[Int32(k)])
+    expectEqual(value, d[Int64(k)])
+    expectEqual(value, d[Int(k)])
+    expectEqual(value, d[Float(k)])
+    expectEqual(value, d[Double(k)])
+
+    expectNil(d[String(k)])
+  }
+}
+
+
+DictionaryTests.test("subscript<Hashable>(_:)/2") {
+  var d: [AnyHashable: Int] = [
+    AnyHashable(10): 1010,
+    AnyHashable(20): 2020,
+    AnyHashable(30.0): 3030,
   ]
 
   expectEqual(1010, d[10])
@@ -100,57 +147,61 @@
     expectEqual(expected, d)
   }
 
-  expectNil(d.updateValue(4040, forKey: 10.0))
+  expectEqual(101010, d.updateValue(4040, forKey: 10.0))
   do {
     let expected: [AnyHashable : Int] = [
-      AnyHashable(10) : 101010,
+      AnyHashable(10) : 4040,
       AnyHashable(20) : 202020,
       AnyHashable(30.0) : 303030,
-      AnyHashable(10.0) : 4040,
     ]
     expectEqual(expected, d)
   }
 
-  expectNil(d.updateValue(5050, forKey: 20.0))
+  expectEqual(202020, d.updateValue(5050, forKey: 20.0))
   do {
     let expected: [AnyHashable : Int] = [
-      AnyHashable(10) : 101010,
-      AnyHashable(20) : 202020,
+      AnyHashable(10) : 4040,
+      AnyHashable(20) : 5050,
       AnyHashable(30.0) : 303030,
-      AnyHashable(10.0) : 4040,
-      AnyHashable(20.0) : 5050,
     ]
     expectEqual(expected, d)
   }
 
-  expectNil(d.updateValue(6060, forKey: 30))
+  expectEqual(303030, d.updateValue(6060, forKey: 30))
   do {
     let expected: [AnyHashable : Int] = [
-      AnyHashable(10) : 101010,
-      AnyHashable(20) : 202020,
-      AnyHashable(30.0) : 303030,
-      AnyHashable(10.0) : 4040,
-      AnyHashable(20.0) : 5050,
-      AnyHashable(30) : 6060,
+      AnyHashable(10) : 4040,
+      AnyHashable(20) : 5050,
+      AnyHashable(30.0) : 6060,
     ]
     expectEqual(expected, d)
   }
 }
 
 DictionaryTests.test("removeValue<Hashable>(forKey:)") {
-  var d: [AnyHashable : Int] = [
-    AnyHashable(10) : 1010,
+  let d: [AnyHashable : Int] = [
+    AnyHashable(10 as UInt8) : 1010,
     AnyHashable(20) : 2020,
     AnyHashable(30.0) : 3030,
   ]
 
-  expectNil(d.removeValue(forKey: 10.0))
-  expectNil(d.removeValue(forKey: 20.0))
-  expectNil(d.removeValue(forKey: 30))
+  for (key, value) in [(10, 1010), (20, 2020), (30, 3030)] {
+    var dd = d
+    expectEqual(value, dd.removeValue(forKey: UInt8(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: UInt16(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: UInt32(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: UInt64(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: UInt(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: Int8(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: Int16(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: Int32(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: Int64(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: Int(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: Float(key)))
+    dd = d; expectEqual(value, dd.removeValue(forKey: Double(key)))
 
-  expectEqual(1010, d.removeValue(forKey: 10)!)
-  expectEqual(2020, d.removeValue(forKey: 20)!)
-  expectEqual(3030, d.removeValue(forKey: 30.0)!)
+    dd = d; expectNil(dd.removeValue(forKey: String(key)))
+  }
 }
 
 runAllTests()
diff --git a/validation-test/stdlib/FixedPoint.swift.gyb b/validation-test/stdlib/FixedPoint.swift.gyb
index 7ac2f9d..dd371bf 100644
--- a/validation-test/stdlib/FixedPoint.swift.gyb
+++ b/validation-test/stdlib/FixedPoint.swift.gyb
@@ -233,22 +233,26 @@
 % for self_ty in all_integer_types(word_bits):
 %   Self = self_ty.stdlib_name
 
-FixedPoint.test("${Self}.hashValue") {
+FixedPoint.test("${Self}.hash(into:)") {
 
 %   for bit_pattern in test_bit_patterns:
 
   do {
 %     input = prepare_bit_pattern(bit_pattern, self_ty.bits, self_ty.is_signed)
     let input = get${Self}(${input})
-    let output = getInt(input.hashValue)
+    var hasher = Hasher()
+    input.hash(into: &hasher)
+    let output = getInt(hasher.finalize())
 
-    var hasher = _SipHash13(_seed: Hasher._seed)
-%     if prepare_bit_pattern(input, word_bits, self_ty.is_signed) == input:
-    hasher._combine(UInt(truncatingIfNeeded: ${input} as ${"" if self_ty.is_signed else "U"}Int))
+%     reference = prepare_bit_pattern(bit_pattern, self_ty.bits, False)
+%     if self_ty.bits == 64:
+    let expected = Hasher._hash(seed: Hasher._seed, ${reference} as UInt64)
 %     else:
-    hasher._combine(UInt64(truncatingIfNeeded: input))
+    let expected = Hasher._hash(
+      seed: Hasher._seed,
+      bytes: ${reference},
+      count: ${self_ty.bits / 8})
 %     end
-    let expected = getInt(Int(truncatingIfNeeded: hasher.finalize()))
     expectEqual(expected, output, "input: \(input)")
   }
 
diff --git a/validation-test/stdlib/SetAnyHashableExtensions.swift b/validation-test/stdlib/SetAnyHashableExtensions.swift
index 3ab8cea..54ef1f7 100644
--- a/validation-test/stdlib/SetAnyHashableExtensions.swift
+++ b/validation-test/stdlib/SetAnyHashableExtensions.swift
@@ -28,28 +28,45 @@
 
 SetTests.test("contains<Hashable>(_:)") {
   let s: Set<AnyHashable> = [
-    AnyHashable(1010), AnyHashable(2020), AnyHashable(3030.0)
+    AnyHashable(1010 as UInt16), AnyHashable(2020), AnyHashable(3030.0)
   ]
-  expectTrue(s.contains(1010))
-  expectTrue(s.contains(2020))
-  expectTrue(s.contains(3030.0))
+  for i in [1010, 2020, 3030] {
+    // We must be able to look up the same number in any representation.
+    expectTrue(s.contains(UInt16(i)))
+    expectTrue(s.contains(UInt32(i)))
+    expectTrue(s.contains(UInt64(i)))
+    expectTrue(s.contains(UInt(i)))
+    expectTrue(s.contains(Int16(i)))
+    expectTrue(s.contains(Int32(i)))
+    expectTrue(s.contains(Int64(i)))
+    expectTrue(s.contains(Int(i)))
+    expectTrue(s.contains(Float(i)))
+    expectTrue(s.contains(Double(i)))
 
-  expectFalse(s.contains(1010.0))
-  expectFalse(s.contains(2020.0))
-  expectFalse(s.contains(3030))
+    expectFalse(s.contains(String(i)))
+  }
 }
 
 SetTests.test("index<Hashable>(of:)") {
-  let s: Set<AnyHashable> = [
-    AnyHashable(1010), AnyHashable(2020), AnyHashable(3030.0)
-  ]
-  expectEqual(AnyHashable(1010), s[s.firstIndex(of: 1010)!])
-  expectEqual(AnyHashable(2020), s[s.firstIndex(of: 2020)!])
-  expectEqual(AnyHashable(3030.0), s[s.firstIndex(of: 3030.0)!])
+  let a = AnyHashable(1010 as UInt16)
+  let b = AnyHashable(2020)
+  let c = AnyHashable(3030.0)
+  let s: Set<AnyHashable> = [a, b, c]
+  for (element, i) in [(a, 1010), (b, 2020), (c, 3030)] {
+    let index = s.firstIndex(of: element)!
 
-  expectNil(s.firstIndex(of: 1010.0))
-  expectNil(s.firstIndex(of: 2020.0))
-  expectNil(s.firstIndex(of: 3030))
+    // We must be able to look up the same number in any representation.
+    expectEqual(index, s.firstIndex(of: UInt16(i)))
+    expectEqual(index, s.firstIndex(of: UInt32(i)))
+    expectEqual(index, s.firstIndex(of: UInt64(i)))
+    expectEqual(index, s.firstIndex(of: UInt(i)))
+    expectEqual(index, s.firstIndex(of: Int16(i)))
+    expectEqual(index, s.firstIndex(of: Int32(i)))
+    expectEqual(index, s.firstIndex(of: Int64(i)))
+    expectEqual(index, s.firstIndex(of: Int(i)))
+    expectEqual(index, s.firstIndex(of: Float(i)))
+    expectEqual(index, s.firstIndex(of: Double(i)))
+  }
 }
 
 SetTests.test("insert<Hashable>(_:)") {
@@ -230,5 +247,28 @@
   s.remove(TestHashableDerivedB(2020, identity: 2))
 }
 
+SetTests.test("Hashable/Conversions") {
+  let input: [Set<AnyHashable>] = [
+    [10 as UInt8, 20 as UInt8, 30 as UInt8],
+    [10 as UInt16, 20 as UInt16, 30 as UInt16],
+    [10 as UInt32, 20 as UInt32, 30 as UInt32],
+    [10 as UInt64, 20 as UInt64, 30 as UInt64],
+    [10 as UInt, 20 as UInt, 30 as UInt],
+    [10 as Int8, 20 as Int8, 30 as Int8],
+    [10 as Int16, 20 as Int16, 30 as Int16],
+    [10 as Int32, 20 as Int32, 30 as Int32],
+    [10 as Int64, 20 as Int64, 30 as Int64],
+    [10 as Int, 20 as Int, 30 as Int],
+    [10 as Float, 20 as Float, 30 as Float],
+    [10 as Double, 20 as Double, 30 as Double],
+    [[1, 2, 3] as Set<Int>, [2, 3, 4] as Set<UInt8>, [3, 4, 5] as Set<Float>],
+    [[1, 2, 3] as Set<Int8>, [2, 3, 4] as Set<Double>, [3, 4, 5] as Set<Int32>],
+    [[1, 2, 3] as Set<UInt32>, [2, 3, 4] as Set<Int16>, [3, 4, 5] as Set<UInt>],
+  ]
+
+  checkHashable(input, equalityOracle: { ($0 < 12) == ($1 < 12) })
+}
+
+
 runAllTests()