Merge pull request #18060 from jrose-apple/and-you-get-a-class_getImageName

[runtime] Backwards-deployment support for class_getImageName

https://bugs.swift.org/browse/SR-1917
rdar://problem/41535552
diff --git a/docs/GenericsManifesto.md b/docs/GenericsManifesto.md
index 2413bee..b54fa9b 100644
--- a/docs/GenericsManifesto.md
+++ b/docs/GenericsManifesto.md
@@ -757,9 +757,9 @@
 One explicit way to allow such operations in a type-safe manner is to introduce an "open existential" operation of some sort, which extracts and gives a name to the dynamic type stored inside an existential. For example:
 
 ```Swift
-if let storedInE1 = e1 openas T {     // T is a the type of storedInE1, a copy of the value stored in e1
-  if let storedInE2 = e2 as? T {      // is e2 also a T?
-    if storedInE1 == storedInE2 { ... } // okay: storedInT1 and storedInE2 are both of type T, which we know is Equatable
+if let storedInE1 = e1 openas T { // T is the type of storedInE1, a copy of the value stored in e1
+  if let storedInE2 = e2 as? T {  // Does e2 have type T? If so, copy its value to storedInE2
+    if storedInE1 == storedInE2 { ... } // Okay: storedInT1 and storedInE2 are both of type T, which we know is Equatable
   }
 }
 ```
diff --git a/include/swift/AST/AnyRequest.h b/include/swift/AST/AnyRequest.h
index f742f95..6cb7d0f 100644
--- a/include/swift/AST/AnyRequest.h
+++ b/include/swift/AST/AnyRequest.h
@@ -136,9 +136,20 @@
 
 public:
   AnyRequest(const AnyRequest &other) = default;
-  AnyRequest(AnyRequest &&other) = default;
   AnyRequest &operator=(const AnyRequest &other) = default;
-  AnyRequest &operator=(AnyRequest &&other) = default;
+
+  AnyRequest(AnyRequest &&other)
+      : storageKind(other.storageKind), stored(std::move(other.stored)) {
+    other.storageKind = StorageKind::Empty;
+  }
+
+  AnyRequest &operator=(AnyRequest &&other) {
+    storageKind = other.storageKind;
+    stored = std::move(other.stored);
+    other.storageKind = StorageKind::Empty;
+    other.stored = nullptr;
+    return *this;
+  }
 
   AnyRequest(AnyRequest &other)
     : storageKind(other.storageKind), stored(other.stored) { }
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 057521b..ec62472 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -2242,8 +2242,20 @@
     /// Whether there are any "overridden" declarations. The actual overridden
     /// declarations are kept in a side table in the ASTContext.
     unsigned hasOverridden : 1;
+
+    /// Whether the "isDynamic" bit has been computed yet.
+    unsigned isDynamicComputed : 1;
+
+    /// Whether this declaration is 'dynamic', meaning that all uses of
+    /// the declaration will go through an extra level of indirection that
+    /// allows the entity to be replaced at runtime.
+    unsigned isDynamic : 1;
   } LazySemanticInfo;
 
+  friend class OverriddenDeclsRequest;
+  friend class IsObjCRequest;
+  friend class IsDynamicRequest;
+
 protected:
   ValueDecl(DeclKind K,
             llvm::PointerUnion<DeclContext *, ASTContext *> context,
@@ -2256,6 +2268,8 @@
     LazySemanticInfo.isObjC = false;
     LazySemanticInfo.hasOverriddenComputed = false;
     LazySemanticInfo.hasOverridden = false;
+    LazySemanticInfo.isDynamicComputed = false;
+    LazySemanticInfo.isDynamic = false;
   }
 
   // MemberLookupTable borrows a bit from this type
@@ -2468,18 +2482,15 @@
   ValueDecl *getOverriddenDecl() const;
 
   /// Retrieve the declarations that this declaration overrides, if any.
-  ArrayRef<ValueDecl *> getOverriddenDecls() const;
+  llvm::TinyPtrVector<ValueDecl *> getOverriddenDecls() const;
 
   /// Set the declaration that this declaration overrides.
   void setOverriddenDecl(ValueDecl *overridden) {
-    (void)setOverriddenDecls(overridden);
+    setOverriddenDecls(overridden);
   }
 
   /// Set the declarations that this declaration overrides.
-  ///
-  /// \returns the ASTContext-allocated version of the array of overridden
-  /// declarations.
-  ArrayRef<ValueDecl *> setOverriddenDecls(ArrayRef<ValueDecl *> overridden);
+  void setOverriddenDecls(ArrayRef<ValueDecl *> overridden);
 
   /// Whether the overridden declarations have already been computed.
   bool overriddenDeclsComputed() const;
@@ -2507,8 +2518,14 @@
   }
 
   /// Is this declaration marked with 'dynamic'?
-  bool isDynamic() const {
-    return getAttrs().hasAttribute<DynamicAttr>();
+  bool isDynamic() const;
+
+  /// Set whether this type is 'dynamic' or not.
+  void setIsDynamic(bool value);
+
+  /// Whether the 'dynamic' bit has been computed already.
+  bool isDynamicComputed() const {
+    return LazySemanticInfo.isDynamicComputed;
   }
 
   /// Returns true if this decl can be found by id-style dynamic lookup.
@@ -2884,11 +2901,7 @@
 
   /// Retrieve the set of associated types overridden by this associated
   /// type.
-  CastArrayRefView<ValueDecl *, AssociatedTypeDecl>
-  getOverriddenDecls() const {
-    return CastArrayRefView<ValueDecl *, AssociatedTypeDecl>(
-        AbstractTypeParamDecl::getOverriddenDecls());
-  }
+  llvm::TinyPtrVector<AssociatedTypeDecl *> getOverriddenDecls() const;
 
   SourceLoc getStartLoc() const { return KeywordLoc; }
   SourceRange getSourceRange() const;
diff --git a/include/swift/AST/LazyResolver.h b/include/swift/AST/LazyResolver.h
index 3620dc0..3f45cd5 100644
--- a/include/swift/AST/LazyResolver.h
+++ b/include/swift/AST/LazyResolver.h
@@ -60,12 +60,6 @@
   /// consistency and provides the value a type.
   virtual void resolveDeclSignature(ValueDecl *VD) = 0;
 
-  /// Resolve the "overridden" declaration of the given declaration.
-  virtual void resolveOverriddenDecl(ValueDecl *VD) = 0;
-
-  /// Resolve the "is Objective-C" bit for the given declaration.
-  virtual void resolveIsObjC(ValueDecl *VD) = 0;
-
   /// Resolve the trailing where clause of the given protocol in-place.
   virtual void resolveTrailingWhereClause(ProtocolDecl *proto) = 0;
 
diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h
index c551604..be4ea1a 100644
--- a/include/swift/AST/NameLookup.h
+++ b/include/swift/AST/NameLookup.h
@@ -287,12 +287,10 @@
 ///
 /// \param decls The set of declarations being considered.
 /// \param curModule The current module.
-/// \param typeResolver Used to resolve overload types.
 ///
 /// \returns true if any shadowed declarations were removed.
 bool removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
-                         const ModuleDecl *curModule,
-                         LazyResolver *typeResolver);
+                         const ModuleDecl *curModule);
 
 /// Finds decls visible in the given context and feeds them to the given
 /// VisibleDeclConsumer.  If the current DeclContext is nested in a function,
diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h
index 437414a..51f5eb3 100644
--- a/include/swift/AST/TypeCheckRequests.h
+++ b/include/swift/AST/TypeCheckRequests.h
@@ -21,6 +21,7 @@
 #include "swift/AST/SimpleRequest.h"
 #include "swift/Basic/Statistic.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/TinyPtrVector.h"
 
 namespace swift {
 
@@ -121,6 +122,89 @@
   void cacheResult(Type value) const;
 };
 
+/// Request to determine the set of declarations that were are overridden
+/// by the given declaration.
+class OverriddenDeclsRequest
+  : public SimpleRequest<OverriddenDeclsRequest,
+                         CacheKind::SeparatelyCached,
+                         llvm::TinyPtrVector<ValueDecl *>,
+                         ValueDecl *> {
+public:
+  using SimpleRequest::SimpleRequest;
+
+private:
+  friend class SimpleRequest;
+
+  // Evaluation.
+  llvm::TinyPtrVector<ValueDecl *> evaluate(Evaluator &evaluator,
+                                            ValueDecl *decl) const;
+
+public:
+  // Cycle handling
+  llvm::TinyPtrVector<ValueDecl *> breakCycle() const { return { }; }
+  void diagnoseCycle(DiagnosticEngine &diags) const;
+  void noteCycleStep(DiagnosticEngine &diags) const;
+
+  // Separate caching.
+  bool isCached() const { return true; }
+  Optional<llvm::TinyPtrVector<ValueDecl *>> getCachedResult() const;
+  void cacheResult(llvm::TinyPtrVector<ValueDecl *> value) const;
+};
+
+/// Determine whether the given declaration is exposed to Objective-C.
+class IsObjCRequest :
+    public SimpleRequest<IsObjCRequest,
+                         CacheKind::SeparatelyCached,
+                         bool,
+                         ValueDecl *> {
+public:
+  using SimpleRequest::SimpleRequest;
+
+private:
+  friend class SimpleRequest;
+
+  // Evaluation.
+  bool evaluate(Evaluator &evaluator, ValueDecl *decl) const;
+
+public:
+  // Cycle handling
+  bool breakCycle() const;
+  void diagnoseCycle(DiagnosticEngine &diags) const;
+  void noteCycleStep(DiagnosticEngine &diags) const;
+
+  // Separate caching.
+  bool isCached() const { return true; }
+  Optional<bool> getCachedResult() const;
+  void cacheResult(bool value) const;
+};
+
+/// Determine whether the given declaration is 'dynamic''.
+class IsDynamicRequest :
+    public SimpleRequest<IsDynamicRequest,
+                         CacheKind::SeparatelyCached,
+                         bool,
+                         ValueDecl *> {
+public:
+  using SimpleRequest::SimpleRequest;
+
+private:
+  friend class SimpleRequest;
+
+  // Evaluation.
+  bool evaluate(Evaluator &evaluator, ValueDecl *decl) const;
+
+public:
+  // Cycle handling
+  bool breakCycle() const;
+  void diagnoseCycle(DiagnosticEngine &diags) const;
+  void noteCycleStep(DiagnosticEngine &diags) const;
+
+  // Separate caching.
+  bool isCached() const { return true; }
+  Optional<bool> getCachedResult() const;
+  void cacheResult(bool value) const;
+};
+
 /// The zone number for the type checker.
 #define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10
 
diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def
index 44732e6..d754436 100644
--- a/include/swift/AST/TypeCheckerTypeIDZone.def
+++ b/include/swift/AST/TypeCheckerTypeIDZone.def
@@ -17,3 +17,6 @@
 SWIFT_TYPEID(InheritedTypeRequest)
 SWIFT_TYPEID(SuperclassTypeRequest)
 SWIFT_TYPEID(EnumRawTypeRequest)
+SWIFT_TYPEID(OverriddenDeclsRequest)
+SWIFT_TYPEID(IsObjCRequest)
+SWIFT_TYPEID(IsDynamicRequest)
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4bad14c..c63bb39 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -35,6 +35,7 @@
 #include "swift/AST/RawComment.h"
 #include "swift/AST/SubstitutionMap.h"
 #include "swift/AST/SILLayout.h"
+#include "swift/AST/TypeCheckRequests.h"
 #include "swift/AST/TypeCheckerDebugConsumer.h"
 #include "swift/Basic/Compiler.h"
 #include "swift/Basic/SourceManager.h"
@@ -1594,53 +1595,47 @@
   return env;
 }
 
-ArrayRef<ValueDecl *> ValueDecl::getOverriddenDecls() const {
-  // Check whether the overrides have already been computed.
-  if (LazySemanticInfo.hasOverriddenComputed) {
-    // If there are no overridden declarations (the common case), return.
-    if (!LazySemanticInfo.hasOverridden) return { };
+Optional<llvm::TinyPtrVector<ValueDecl *>>
+OverriddenDeclsRequest::getCachedResult() const {
+  auto decl = std::get<0>(getStorage());
+  if (!decl->LazySemanticInfo.hasOverriddenComputed)
+    return None;
 
-    // Look up the overridden declarations in the ASTContext.
-    auto known = getASTContext().getImpl().Overrides.find(this);
-    assert(known != getASTContext().getImpl().Overrides.end());
-    return known->second;
-  }
+  // If there are no overridden declarations (the common case), return.
+  llvm::TinyPtrVector<ValueDecl *> overridden;
+  if (!decl->LazySemanticInfo.hasOverridden) return overridden;
 
-  ASTContext &ctx = getASTContext();
-  if (auto resolver = ctx.getLazyResolver()) {
-    resolver->resolveOverriddenDecl(const_cast<ValueDecl *>(this));
-    assert(LazySemanticInfo.hasOverriddenComputed);
-    return getOverriddenDecls();
-  }
-
-  // FIXME: Shouldn't need this fallback.
-  return { };
+  // Retrieve the set of overrides from the ASTContext.
+  ASTContext &ctx = decl->getASTContext();
+  auto known = ctx.getImpl().Overrides.find(decl);
+  assert(known != ctx.getImpl().Overrides.end());
+  overridden.insert(overridden.end(),
+                    known->second.begin(), known->second.end());
+  return overridden;
 }
 
-ArrayRef<ValueDecl *> ValueDecl::setOverriddenDecls(
-                                            ArrayRef<ValueDecl *> overridden) {
-  LazySemanticInfo.hasOverriddenComputed = true;
+void OverriddenDeclsRequest::cacheResult(
+                                llvm::TinyPtrVector<ValueDecl *> value) const {
+  auto decl = std::get<0>(getStorage());
+  decl->LazySemanticInfo.hasOverriddenComputed = true;
+  decl->LazySemanticInfo.hasOverridden = !value.empty();
 
-  // If the set of overridden declarations is empty, note that.
-  if (overridden.empty()) {
-    LazySemanticInfo.hasOverridden = false;
-    return { };
-  }
+  if (value.empty())
+    return;
 
   // Sanity-check the declarations we were given.
-  for (auto decl : overridden) {
-    assert(decl->getKind() == this->getKind() &&
+  for (auto overriddenDecl : value) {
+    assert(overriddenDecl->getKind() == decl->getKind() &&
            "Overridden decl kind mismatch");
-    if (auto func = dyn_cast<AbstractFunctionDecl>(decl))
+    if (auto func = dyn_cast<AbstractFunctionDecl>(overriddenDecl))
       func->setIsOverridden();
   }
 
   // Record the overrides in the context.
-  auto &ctx = getASTContext();
-  LazySemanticInfo.hasOverridden = true;
-  auto overriddenCopy = ctx.AllocateCopy(overridden);
-  (void)ctx.getImpl().Overrides.insert({this, overriddenCopy});
-  return overriddenCopy;
+  auto &ctx = decl->getASTContext();
+  auto overriddenCopy =
+    ctx.AllocateCopy(value.operator ArrayRef<ValueDecl *>());
+  (void)ctx.getImpl().Overrides.insert({decl, overriddenCopy});
 }
 
 bool ASTContext::canImportModule(std::pair<Identifier, SourceLoc> ModulePath) {
@@ -2372,8 +2367,6 @@
 
 Optional<ForeignErrorConvention>
 AbstractFunctionDecl::getForeignErrorConvention() const {
-  if (!isObjC() && !getAttrs().hasAttribute<CDeclAttr>())
-    return None;
   if (!hasThrows())
     return None;
   auto &conventionsMap = getASTContext().getImpl().ForeignErrorConventions;
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 0c200d8..30879fc 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -181,6 +181,16 @@
   }
 };
 
+namespace {
+  /// Retrieve the "overridden" declaration of this declaration, but only if
+  // it's already been computed.
+  template<typename T>
+  T *getOverriddenDeclIfAvailable(T *decl) {
+    if (!decl->overriddenDeclsComputed()) return nullptr;
+
+    return cast_or_null<T>(decl->getOverriddenDecl());
+  }
+}
 class Verifier : public ASTWalker {
   PointerUnion<ModuleDecl *, SourceFile *> M;
   ASTContext &Ctx;
@@ -841,7 +851,7 @@
         }
       }
 
-      if (auto Overridden = D->getOverriddenDecl()) {
+      if (auto Overridden = getOverriddenDeclIfAvailable(D)) {
         if (D->getDeclContext() == Overridden->getDeclContext()) {
           PrettyStackTraceDecl debugStack("verifying overridden", D);
           Out << "cannot override a decl in the same DeclContext";
@@ -2232,42 +2242,6 @@
         }
       }
 
-      // Make sure we consistently set accessor overrides.
-      if (auto *baseASD = ASD->getOverriddenDecl()) {
-        if (ASD->getGetter() && baseASD->getGetter())
-          assert(ASD->getGetter()->getOverriddenDecl() ==
-                 baseASD->getGetter() &&
-                 "Storage overrides but getter does not");
-        if (ASD->getSetter() && baseASD->getSetter() &&
-            baseASD->isSetterAccessibleFrom(ASD->getDeclContext()))
-          assert(ASD->getSetter()->getOverriddenDecl() ==
-                 baseASD->getSetter() &&
-                 "Storage overrides but setter does not");
-        if (ASD->getMaterializeForSetFunc() &&
-            baseASD->getMaterializeForSetFunc() &&
-            baseASD->isSetterAccessibleFrom(ASD->getDeclContext())) {
-          if (baseASD->getMaterializeForSetFunc()->hasForcedStaticDispatch()) {
-            assert(ASD->getMaterializeForSetFunc()->getOverriddenDecl() == nullptr
-                   && "Forced static dispatch materializeForSet should not be "
-                   "overridden");
-          } else {
-            assert(ASD->getMaterializeForSetFunc()->getOverriddenDecl() ==
-                   baseASD->getMaterializeForSetFunc() &&
-                   "Storage override but materializeForSet does not");
-          }
-        }
-      } else {
-        if (ASD->getGetter())
-          assert(!ASD->getGetter()->getOverriddenDecl() &&
-                 "Storage does not override but getter does");
-        if (ASD->getSetter())
-          assert(!ASD->getSetter()->getOverriddenDecl() &&
-                 "Storage does not override but setter does");
-        if (ASD->getMaterializeForSetFunc())
-          assert(!ASD->getMaterializeForSetFunc()->getOverriddenDecl() &&
-                 "Storage does not override but materializeForSet does");
-      }
-
       verifyCheckedBase(ASD);
     }
 
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 1833cdb..3f86048 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2022,13 +2022,20 @@
   return CanType();
 }
 
-bool ValueDecl::isObjC() const {
-  if (LazySemanticInfo.isObjCComputed)
-    return LazySemanticInfo.isObjC;
+llvm::TinyPtrVector<ValueDecl *> ValueDecl::getOverriddenDecls() const {
+  ASTContext &ctx = getASTContext();
+  return ctx.evaluator(OverriddenDeclsRequest{const_cast<ValueDecl *>(this)});
+}
 
-  // Fallback: look for an @objc attribute.
-  // FIXME: This should become an error, eventually.
-  return getAttrs().hasAttribute<ObjCAttr>();
+void ValueDecl::setOverriddenDecls(ArrayRef<ValueDecl *> overridden) {
+  llvm::TinyPtrVector<ValueDecl *> overriddenVec(overridden);
+  OverriddenDeclsRequest request{const_cast<ValueDecl *>(this)};
+  request.cacheResult(overriddenVec);
+}
+
+bool ValueDecl::isObjC() const {
+  ASTContext &ctx = getASTContext();
+  return ctx.evaluator(IsObjCRequest{const_cast<ValueDecl *>(this)});
 }
 
 void ValueDecl::setIsObjC(bool value) {
@@ -2043,6 +2050,24 @@
   LazySemanticInfo.isObjC = value;
 }
 
+bool ValueDecl::isDynamic() const {
+  ASTContext &ctx = getASTContext();
+  return ctx.evaluator(IsDynamicRequest{const_cast<ValueDecl *>(this)});
+}
+
+void ValueDecl::setIsDynamic(bool value) {
+  assert(!LazySemanticInfo.isDynamicComputed ||
+         LazySemanticInfo.isDynamic == value);
+
+  if (LazySemanticInfo.isDynamicComputed) {
+    assert(LazySemanticInfo.isDynamic == value);
+    return;
+  }
+
+  LazySemanticInfo.isDynamicComputed = true;
+  LazySemanticInfo.isDynamic = value;
+}
+
 bool ValueDecl::canBeAccessedByDynamicLookup() const {
   if (!hasName())
     return false;
@@ -2866,6 +2891,24 @@
   return SourceRange(KeywordLoc, endLoc);
 }
 
+llvm::TinyPtrVector<AssociatedTypeDecl *>
+AssociatedTypeDecl::getOverriddenDecls() const {
+  // FIXME: Performance hack because we end up looking at the overridden
+  // declarations of an associated type a *lot*.
+  OverriddenDeclsRequest request{const_cast<AssociatedTypeDecl *>(this)};
+  llvm::TinyPtrVector<ValueDecl *> overridden;
+  if (auto cached = request.getCachedResult())
+    overridden = std::move(*cached);
+  else
+    overridden = AbstractTypeParamDecl::getOverriddenDecls();
+
+  llvm::TinyPtrVector<AssociatedTypeDecl *> assocTypes;
+  for (auto decl : overridden) {
+    assocTypes.push_back(cast<AssociatedTypeDecl>(decl));
+  }
+  return assocTypes;
+}
+
 AssociatedTypeDecl *AssociatedTypeDecl::getAssociatedTypeAnchor() const {
   auto overridden = getOverriddenDecls();
 
@@ -3042,7 +3085,9 @@
     if (CD->isGenericContext())
       genericAncestry = true;
 
-    if (CD->isObjC())
+    // FIXME: Checking isObjC() introduces cyclic dependencies here, but this
+    // doesn't account for ill-formed @objc.
+    if (CD->getAttrs().hasAttribute<ObjCAttr>())
       isObjC = true;
 
     if (!CD->hasSuperclass())
@@ -4869,6 +4914,10 @@
 
 ObjCSelector
 AbstractFunctionDecl::getObjCSelector(DeclName preferredName) const {
+  // FIXME: Forces computation of the Objective-C selector.
+  if (getASTContext().getLazyResolver())
+    (void)isObjC();
+
   // If there is an @objc attribute with a name, use that name.
   auto *objc = getAttrs().getAttribute<ObjCAttr>();
   if (auto name = getNameFromObjcAttribute(objc, preferredName)) {
@@ -5020,7 +5069,7 @@
 
   // Final members are always be called directly.
   // Dynamic methods are always accessed by objc_msgSend().
-  if (decl->isFinal() || decl->isDynamic())
+  if (decl->isFinal() || decl->isDynamic() || decl->hasClangNode())
     return false;
 
   if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
@@ -5046,7 +5095,7 @@
   }
 
   auto base = decl->getOverriddenDecl();
-  if (!base || base->hasClangNode())
+  if (!base || base->hasClangNode() || base->isDynamic())
     return true;
 
   // If the method overrides something, we only need a new entry if the
diff --git a/lib/AST/LookupVisibleDecls.cpp b/lib/AST/LookupVisibleDecls.cpp
index d77c23d..d69a4c6 100644
--- a/lib/AST/LookupVisibleDecls.cpp
+++ b/lib/AST/LookupVisibleDecls.cpp
@@ -215,7 +215,7 @@
   }
 
   // Handle shadowing.
-  removeShadowedDecls(FoundDecls, CurrDC->getParentModule(), TypeResolver);
+  removeShadowedDecls(FoundDecls, CurrDC->getParentModule());
 }
 
 /// \brief Enumerate immediate members of the type \c LookupType and its
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index 3093bd7..9a32213 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -157,8 +157,9 @@
 }
 
 bool swift::removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
-                                const ModuleDecl *curModule,
-                                LazyResolver *typeResolver) {
+                                const ModuleDecl *curModule) {
+  auto typeResolver = curModule->getASTContext().getLazyResolver();
+
   // Category declarations by their signatures.
   llvm::SmallDenseMap<std::pair<CanType, DeclBaseName>,
                       llvm::TinyPtrVector<ValueDecl *>>
@@ -478,6 +479,7 @@
 {
   ModuleDecl &M = *DC->getParentModule();
   ASTContext &Ctx = M.getASTContext();
+  if (!TypeResolver) TypeResolver = Ctx.getLazyResolver();
   const SourceManager &SM = Ctx.SourceMgr;
   DebuggerClient *DebugClient = M.getDebugClient();
 
@@ -1491,8 +1493,6 @@
     createObjCMethodLookup();
   }
 
-  assert(method->isObjC() && "Not an Objective-C method");
-
   // Record the method.
   bool isInstanceMethod = method->isObjCInstanceMethod();
   auto selector = method->getObjCSelector();
@@ -1614,6 +1614,9 @@
   using namespace namelookup;
   assert(decls.empty() && "additive lookup not supported");
 
+  if (!typeResolver)
+    typeResolver = getASTContext().getLazyResolver();
+  
   auto checkLookupCascading = [this, options]() -> Optional<bool> {
     switch (static_cast<unsigned>(options & NL_KnownDependencyMask)) {
     case 0:
@@ -1885,9 +1888,6 @@
         continue;
 
       // If the declaration is not @objc, it cannot be called dynamically.
-      if (typeResolver)
-        typeResolver->resolveIsObjC(decl);
-
       if (!decl->isObjC())
         continue;
 
@@ -1920,7 +1920,7 @@
   // If we're supposed to remove shadowed/hidden declarations, do so now.
   ModuleDecl *M = getParentModule();
   if (options & NL_RemoveNonVisible)
-    removeShadowedDecls(decls, M, typeResolver);
+    removeShadowedDecls(decls, M);
 
   if (auto *debugClient = M->getDebugClient())
     filterForDiscriminator(decls, debugClient);
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 0d7e18c..3eee9ef 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -673,6 +673,7 @@
 
   // Otherwise, resolve the type witness.
   PrettyStackTraceRequirement trace("resolving", this, assocType);
+  if (!resolver) resolver = assocType->getASTContext().getLazyResolver();
   assert(resolver && "Unable to resolve type witness");
 
   // Block recursive resolution of this type witness.
@@ -800,6 +801,7 @@
 
   auto known = Mapping.find(requirement);
   if (known == Mapping.end()) {
+    if (!resolver) resolver = requirement->getASTContext().getLazyResolver();
     assert(resolver && "Unable to resolve witness without resolver");
     resolver->resolveWitness(this, requirement);
     known = Mapping.find(requirement);
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 74e3e5f..c29348a 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1154,6 +1154,18 @@
   case TypeKind::GenericTypeParam: {
     GenericTypeParamType *gp = cast<GenericTypeParamType>(this);
     auto gpDecl = gp->getDecl();
+
+    // If we haven't set a depth for this generic parameter, try to do so.
+    // FIXME: This is a dreadful hack.
+    if (gpDecl->getDepth() == GenericTypeParamDecl::InvalidDepth) {
+      auto resolver = gpDecl->getASTContext().getLazyResolver();
+      assert(resolver && "Need to resolve generic parameter depth");
+      if (auto decl =
+            gpDecl->getDeclContext()->getInnermostDeclarationDeclContext())
+        if (auto valueDecl = dyn_cast<ValueDecl>(decl))
+          resolver->resolveDeclSignature(valueDecl);
+    }
+
     assert(gpDecl->getDepth() != GenericTypeParamDecl::InvalidDepth &&
            "parameter hasn't been validated");
     Result = GenericTypeParamType::get(gpDecl->getDepth(), gpDecl->getIndex(),
@@ -1866,10 +1878,6 @@
 
   // @objc classes.
   if (auto classDecl = type->getClassOrBoundGenericClass()) {
-    auto &ctx = classDecl->getASTContext();
-    if (auto resolver = ctx.getLazyResolver())
-      resolver->resolveIsObjC(classDecl);
-
     if (classDecl->isObjC())
       return ForeignRepresentableKind::Object;
   }
diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp
index 3937522..48894a0 100644
--- a/lib/AST/TypeCheckRequests.cpp
+++ b/lib/AST/TypeCheckRequests.cpp
@@ -146,3 +146,84 @@
   auto enumDecl = std::get<0>(getStorage());
   enumDecl->LazySemanticInfo.RawType.setPointerAndInt(value, true);
 }
+
+//----------------------------------------------------------------------------//
+// Overridden decls computation.
+//----------------------------------------------------------------------------//
+void OverriddenDeclsRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+  auto decl = std::get<0>(getStorage());
+  diags.diagnose(decl, diag::circular_reference);
+}
+
+void OverriddenDeclsRequest::noteCycleStep(DiagnosticEngine &diags) const {
+  auto decl = std::get<0>(getStorage());
+  diags.diagnose(decl, diag::circular_reference_through);
+}
+
+//----------------------------------------------------------------------------//
+// isObjC computation.
+//----------------------------------------------------------------------------//
+
+bool IsObjCRequest::breakCycle() const {
+  auto decl = std::get<0>(getStorage());
+  return decl->getAttrs().hasAttribute<ObjCAttr>();
+}
+
+void IsObjCRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+  // FIXME: Improve this diagnostic.
+  auto decl = std::get<0>(getStorage());
+  diags.diagnose(decl, diag::circular_reference);
+}
+
+void IsObjCRequest::noteCycleStep(DiagnosticEngine &diags) const {
+  auto decl = std::get<0>(getStorage());
+  // FIXME: Customize this further.
+  diags.diagnose(decl, diag::circular_reference_through);
+}
+
+Optional<bool> IsObjCRequest::getCachedResult() const {
+  auto decl = std::get<0>(getStorage());
+  if (decl->LazySemanticInfo.isObjCComputed)
+    return decl->LazySemanticInfo.isObjC;
+
+  return None;
+}
+
+void IsObjCRequest::cacheResult(bool value) const {
+  auto decl = std::get<0>(getStorage());
+  decl->setIsObjC(value);
+}
+
+//----------------------------------------------------------------------------//
+// isDynamic computation.
+//----------------------------------------------------------------------------//
+
+bool IsDynamicRequest::breakCycle() const {
+  auto decl = std::get<0>(getStorage());
+  return decl->getAttrs().hasAttribute<DynamicAttr>();
+}
+
+void IsDynamicRequest::diagnoseCycle(DiagnosticEngine &diags) const {
+  // FIXME: Improve this diagnostic.
+  auto decl = std::get<0>(getStorage());
+  diags.diagnose(decl, diag::circular_reference);
+}
+
+void IsDynamicRequest::noteCycleStep(DiagnosticEngine &diags) const {
+  auto decl = std::get<0>(getStorage());
+  // FIXME: Customize this further.
+  diags.diagnose(decl, diag::circular_reference_through);
+}
+
+Optional<bool> IsDynamicRequest::getCachedResult() const {
+  auto decl = std::get<0>(getStorage());
+  if (decl->LazySemanticInfo.isDynamicComputed)
+    return decl->LazySemanticInfo.isDynamic;
+
+  return None;
+}
+
+void IsDynamicRequest::cacheResult(bool value) const {
+  auto decl = std::get<0>(getStorage());
+  decl->setIsDynamic(value);
+}
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 7930e93..11b3717 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -3542,10 +3542,6 @@
     return EffectiveClangContext();
   }
 
-  // Resolve the type.
-  if (auto typeResolver = getTypeResolver())
-    typeResolver->resolveIsObjC(const_cast<NominalTypeDecl *>(nominal));
-
   // If it's an @objc entity, go look for it.
   if (nominal->isObjC()) {
     // Map the name. If we can't represent the Swift name in Clang.
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 8668b58..ffd40ec 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -531,6 +531,7 @@
                      /*GenericParams=*/nullptr, params,
                      TypeLoc::withoutLoc(rawTy), enumDecl);
   getterDecl->setImplicit();
+  getterDecl->setIsObjC(false);
 
   auto type = ParameterList::getFullInterfaceType(rawTy, params, C);
 
@@ -615,6 +616,7 @@
                      /*GenericParams=*/nullptr, params,
                      TypeLoc::withoutLoc(computedType), structDecl);
   getterDecl->setImplicit();
+  getterDecl->setIsObjC(false);
 
   auto type = ParameterList::getFullInterfaceType(computedType, params, C);
 
@@ -684,6 +686,7 @@
                      /*GenericParams=*/nullptr, params,
                      TypeLoc::withoutLoc(getterType), importedDecl, clangNode);
   getterDecl->setAccess(AccessLevel::Public);
+  getterDecl->setIsObjC(false);
 
   auto type = ParameterList::getFullInterfaceType(getterType, params, C);
   getterDecl->setInterfaceType(type);
@@ -725,6 +728,7 @@
                      /*ThrowsLoc=*/SourceLoc(),
                      /*GenericParams=*/nullptr, params,
                      TypeLoc::withoutLoc(voidTy), importedDecl, clangNode);
+  setterDecl->setIsObjC(false);
 
   auto type = ParameterList::getFullInterfaceType(voidTy, params, C);
   setterDecl->setInterfaceType(type);
@@ -1883,6 +1887,7 @@
                      TypeLoc::withoutLoc(stringTy), swiftDecl);
   getterDecl->setInterfaceType(toStringTy);
   getterDecl->setValidationToChecked();
+  getterDecl->setIsObjC(false);
 
   swiftDecl->addMember(errorDomainPropertyDecl);
   swiftDecl->addMember(getterDecl);
@@ -3445,6 +3450,7 @@
                        Impl.importSourceLoc(decl->getLocStart()),
                        name, dc->mapTypeIntoContext(type), dc);
       result->setInterfaceType(type);
+      result->setIsObjC(false);
       Impl.recordImplicitUnwrapForDecl(result,
                                        importedType.isImplicitlyUnwrapped());
 
@@ -3579,6 +3585,7 @@
 
       result->setInterfaceType(type);
       result->setValidationToChecked();
+      result->setIsObjC(false);
       Impl.recordImplicitUnwrapForDecl(result,
                                        importedType.isImplicitlyUnwrapped());
 
@@ -3672,6 +3679,7 @@
                               /*IsCaptureList*/false,
                               Impl.importSourceLoc(decl->getLocation()),
                               name, dc->mapTypeIntoContext(type), dc);
+      result->setIsObjC(false);
       result->setInterfaceType(type);
       Impl.recordImplicitUnwrapForDecl(result,
                                        importedType.isImplicitlyUnwrapped());
@@ -3757,6 +3765,7 @@
                        /*IsCaptureList*/false,
                        Impl.importSourceLoc(decl->getLocation()),
                        name, dc->mapTypeIntoContext(type), dc);
+      result->setIsObjC(false);
       result->setInterfaceType(type);
       Impl.recordImplicitUnwrapForDecl(result,
                                        importedType.isImplicitlyUnwrapped());
@@ -5675,6 +5684,8 @@
   result->setInterfaceType(allocType);
   Impl.recordImplicitUnwrapForDecl(result,
                                    importedType.isImplicitlyUnwrapped());
+  result->setOverriddenDecls({ });
+  result->setIsObjC(false);
 
   finishFuncDecl(decl, result);
   if (correctSwiftName)
@@ -5921,6 +5932,7 @@
       VarDecl::Specifier::Var, /*IsCaptureList*/false, SourceLoc(),
       propertyName, dc->mapTypeIntoContext(swiftPropertyType), dc);
   property->setInterfaceType(swiftPropertyType);
+  property->setIsObjC(false);
   Impl.recordImplicitUnwrapForDecl(property,
                                    importedType.isImplicitlyUnwrapped());
 
@@ -6389,13 +6401,10 @@
   // Make sure that we always set the overriden declarations.
   SWIFT_DEFER {
     if (!decl->overriddenDeclsComputed())
-      (void)decl->setOverriddenDecls({ });
+      decl->setOverriddenDecls({ });
   };
 
   // Figure out the class in which this method occurs.
-  if (!decl->getDeclContext()->isTypeContext())
-    return;
-
   auto classDecl = decl->getDeclContext()->getAsClassOrClassExtensionContext();
   if (!classDecl)
     return;
@@ -8323,6 +8332,7 @@
   }
 
   var->setInterfaceType(type);
+  var->setIsObjC(false);
 
   // Form the argument patterns.
   SmallVector<ParameterList*, 3> getterArgs;
@@ -8357,6 +8367,7 @@
   func->setAccess(getOverridableAccessLevel(dc));
   func->setValidationToChecked();
   func->setImplicit();
+  func->setIsObjC(false);
 
   // If we're not done type checking, build the getter body.
   if (!hasFinishedTypeChecking()) {
@@ -8433,6 +8444,7 @@
                                               VarDecl::Specifier::Var,
                                               /*IsCaptureList*/false,
                                               SourceLoc(), name, type, dc);
+  var->setIsObjC(false);
   var->setInterfaceType(type);
   markUnavailable(var, UnavailableMessage);
 
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 9f1c46a..c2be909 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -1431,7 +1431,7 @@
       // Builtin.swift3ImplicitObjCEntrypoint() to enable runtime logging of
       // the uses of such entrypoints.
       if (attr->isSwift3Inferred() &&
-          !decl->getAttrs().hasAttribute<DynamicAttr>() &&
+          !decl->isDynamic() &&
           !getASTContext().LangOpts.isSwiftVersion3()) {
         
         // Get the starting source location of the declaration so we can say
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 183e34d..4bb9c6d 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -449,9 +449,24 @@
                            /*resolver*/nullptr,
                            results);
     assert(!results.empty() && "couldn't find UIApplicationMain in UIKit");
-    assert(results.size() == 1 && "more than one UIApplicationMain?");
 
-    auto mainRef = SILDeclRef(results.front()).asForeign();
+    // We want the original UIApplicationMain() declaration from Objective-C,
+    // not any overlay overloads.
+    ValueDecl *UIApplicationMainDecl = nullptr;
+    for (auto *result : results) {
+      if (result->hasClangNode()) {
+        assert(!UIApplicationMainDecl
+               && "more than one UIApplicationMain defined in ObjC?!");
+        UIApplicationMainDecl = result;
+#ifndef NDEBUG
+        break;
+#endif
+      }
+    }
+    
+    assert(UIApplicationMainDecl && "no UIApplicationMain defined in ObjC?!");
+
+    auto mainRef = SILDeclRef(UIApplicationMainDecl).asForeign();
     auto UIApplicationMainFn = SGM.M.getOrCreateFunction(mainClass, mainRef,
                                                          NotForDefinition);
     auto fnTy = UIApplicationMainFn->getLoweredFunctionType();
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index c74645d..969e349 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -18,6 +18,7 @@
 
 #include "ConstraintSystem.h"
 #include "MiscDiagnostics.h"
+#include "TypeCheckProtocol.h"
 #include "swift/AST/ASTVisitor.h"
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/ExistentialLayout.h"
@@ -558,6 +559,7 @@
                        FunctionRefKind functionRefKind,
                        AccessSemantics semantics) {
       auto *decl = choice.getDecl();
+
       // Determine the declaration selected for this overloaded reference.
       auto &ctx = cs.getASTContext();
       
@@ -900,6 +902,7 @@
                          FunctionRefKind functionRefKind,
                          AccessSemantics semantics, bool isDynamic) {
       ValueDecl *member = choice.getDecl();
+
       auto &tc = cs.getTypeChecker();
       auto &context = tc.Context;
 
@@ -4610,8 +4613,7 @@
 
       // Mark any _ObjectiveCBridgeable conformances as 'used'.
       if (result) {
-        auto &tc = cs.getTypeChecker();
-        tc.useObjectiveCBridgeableConformances(cs.DC, cs.getType(result));
+        useObjectiveCBridgeableConformances(cs.DC, cs.getType(result));
       }
 
       assert(expr == ExprStack.back());
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index 954f05f..46eb6c9 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -67,11 +67,7 @@
     case SK_CollectionUpcastConversion:
       log << "collection upcast conversion";
       break;
-
-    case SK_BindOptionalToArchetype:
-      log << "bind optional to archetype";
-      break;
-
+        
     case SK_ValueToOptional:
       log << "value to optional";
       break;
@@ -638,28 +634,6 @@
           Type paramType1 = getAdjustedParamType(param1);
           Type paramType2 = getAdjustedParamType(param2);
 
-          // If we have:
-          //   param1Type = $T0?
-          //   param2Type = $T1
-          // the subtype constraint check will always return true
-          // since we'll attempt to bind $T1 as $T0?.
-          //
-          // What we're comparing here is foo<T>(_: T?) vs. foo<T>(_: T) and
-          // we don't want to consider the optional-taking function to be the
-          // the more specialized one since throughout the type system we
-          // consider T to be a subtype of T?.
-          SmallVector<Type, 2> optionals1;
-          paramType1->lookThroughAllOptionalTypes(optionals1);
-          auto numOptionals1 = optionals1.size();
-
-          SmallVector<Type, 2> optionals2;
-          Type objType2 = paramType2->lookThroughAllOptionalTypes(optionals2);
-          auto numOptionals2 = optionals2.size();
-
-          if (numOptionals1 > numOptionals2 &&
-              (objType2->is<TypeVariableType>() || objType2->isAny()))
-            return false;
-
           // Check whether the first parameter is a subtype of the second.
           cs.addConstraint(ConstraintKind::Subtype,
                            paramType1, paramType2, locator);
@@ -708,7 +682,10 @@
 
       if (!knownNonSubtype) {
         // Solve the system.
-        if (cs.solveSingle(FreeTypeVariableBinding::Allow))
+        auto solution = cs.solveSingle(FreeTypeVariableBinding::Allow);
+
+        // Ban value-to-optional conversions.
+        if (solution && solution->getFixedScore().Data[SK_ValueToOptional] == 0)
           return true;
       }
 
@@ -775,6 +752,9 @@
   auto foundRefinement1 = false;
   auto foundRefinement2 = false;
 
+  bool isStdlibOptionalMPlusOperator1 = false;
+  bool isStdlibOptionalMPlusOperator2 = false;
+
   auto getWeight = [&](ConstraintLocator *locator) -> unsigned {
     if (auto *anchor = locator->getAnchor()) {
       auto weight = weights.find(anchor);
@@ -980,6 +960,40 @@
         foundRefinement2 = decl2InSubprotocol;
       }
     }
+
+    // FIXME: Lousy hack for ?? to prefer the catamorphism (flattening)
+    // over the mplus (non-flattening) overload if all else is equal.
+    if (decl1->getBaseName() == "??") {
+      assert(decl2->getBaseName() == "??");
+
+      auto check = [](const ValueDecl *VD) -> bool {
+        if (!VD->getModuleContext()->isStdlibModule())
+          return false;
+        auto fnTy = VD->getInterfaceType()->castTo<AnyFunctionType>();
+        if (!fnTy->getResult()->getOptionalObjectType())
+          return false;
+
+        // Check that the standard library hasn't added another overload of
+        // the ?? operator.
+        auto params = fnTy->getParams();
+        assert(params.size() == 2);
+
+        auto param1 = params[0].getType();
+        auto param2 = params[1].getType()->castTo<AnyFunctionType>();
+
+        assert(param1->getOptionalObjectType());
+        assert(param2->isAutoClosure());
+        assert(param2->getResult()->getOptionalObjectType());
+
+        (void) param1;
+        (void) param2;
+
+        return true;
+      };
+
+      isStdlibOptionalMPlusOperator1 = check(decl1);
+      isStdlibOptionalMPlusOperator2 = check(decl2);
+    }
   }
 
   // Compare the type variable bindings.
@@ -1095,6 +1109,14 @@
     }
   }
 
+  // FIXME: All other things being equal, prefer the catamorphism (flattening)
+  // overload of ?? over the mplus (non-flattening) overload.
+  if (score1 == score2) {
+    // This is correct: we want to /disprefer/ the mplus.
+    score2 += isStdlibOptionalMPlusOperator1;
+    score1 += isStdlibOptionalMPlusOperator2;
+  }
+
   // FIXME: There are type variables and overloads not common to both solutions
   // that haven't been considered. They make the systems different, but don't
   // affect ranking. We need to handle this.
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 33173e0..1c872de 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -683,9 +683,6 @@
       }
     }
 
-    if (!argType->isAny())
-      cs.increaseScore(ScoreKind::SK_EmptyExistentialConversion);
-
     return cs.getTypeMatchSuccess();
   }
 
@@ -1660,16 +1657,6 @@
       auto *typeVar = typeVar1 ? typeVar1 : typeVar2;
       auto type = typeVar1 ? type2 : type1;
 
-      if (type->getOptionalObjectType()) {
-        if (auto *typeVarLocator = typeVar->getImpl().getLocator()) {
-          auto path = typeVarLocator->getPath();
-          if (!path.empty() &&
-              path.back().getKind() == ConstraintLocator::Archetype) {
-            increaseScore(SK_BindOptionalToArchetype);
-          }
-        }
-      }
-
       return matchTypesBindTypeVar(typeVar, type, kind, flags, locator,
                                    formUnsolvedResult);
     }
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index abbd032..6d2a99a 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -218,10 +218,6 @@
   if (storage->isStatic())
     getter->setStatic();
 
-  if (auto *overridden = storage->getOverriddenDecl())
-    if (auto *overriddenAccessor = overridden->getGetter())
-      getter->setOverriddenDecl(overriddenAccessor);
-
   // Always add the getter to the context immediately after the storage.
   addMemberToContextIfNeeded(getter, storage->getDeclContext(), storage);
 
@@ -274,14 +270,6 @@
   if (isStatic)
     setter->setStatic();
 
-  if (auto *overridden = storage->getOverriddenDecl()) {
-    auto *overriddenAccessor = overridden->getSetter();
-    if (overriddenAccessor &&
-        overridden->isSetterAccessibleFrom(storage->getDeclContext())) {
-      setter->setOverriddenDecl(overriddenAccessor);
-    }
-  }
-
   // Always add the setter to the context immediately after the getter.
   if (!getter) getter = storage->getGetter();
   assert(getter && "always synthesize setter prototype after getter");
@@ -428,14 +416,6 @@
   if (storage->isFinal())
     makeFinal(ctx, materializeForSet);
 
-  if (auto *overridden = storage->getOverriddenDecl()) {
-    auto *overriddenAccessor = overridden->getMaterializeForSetFunc();
-    if (overriddenAccessor && !overriddenAccessor->hasForcedStaticDispatch() &&
-        overridden->isSetterAccessibleFrom(storage->getDeclContext())) {
-      materializeForSet->setOverriddenDecl(overriddenAccessor);
-    }
-  }
-
   // If the storage is dynamic or ObjC-native, we can't add a dynamically-
   // dispatched method entry for materializeForSet, so force it to be
   // statically dispatched. ("final" would be inappropriate because the
@@ -2414,25 +2394,16 @@
   ctor->getAttrs().add(new (ctx) OverrideAttr(/*IsImplicit=*/true));
   ctor->setOverriddenDecl(superclassCtor);
 
-  if (superclassCtor->isObjC()) {
-    // Inherit the @objc name from the superclass initializer, if it
-    // has one.
-    if (auto objcAttr = superclassCtor->getAttrs().getAttribute<ObjCAttr>()) {
-      if (objcAttr->hasName()) {
-        auto *clonedAttr = objcAttr->clone(ctx);
-        clonedAttr->setImplicit(true);
-        ctor->getAttrs().add(clonedAttr);
-      }
-    }
-
-    auto errorConvention = superclassCtor->getForeignErrorConvention();
-    markAsObjC(tc, ctor, ObjCReason(ObjCReason::ImplicitlyObjC),
-               errorConvention);
-  }
   if (superclassCtor->isRequired())
     ctor->getAttrs().add(new (ctx) RequiredAttr(/*IsImplicit=*/true));
-  if (superclassCtor->isDynamic())
-    ctor->getAttrs().add(new (ctx) DynamicAttr(/*IsImplicit*/true));
+
+  // If the superclass constructor is @objc but the subclass constructor is
+  // not representable in Objective-C, add @nonobjc implicitly.
+  Optional<ForeignErrorConvention> errorConvention;
+  if (superclassCtor->isObjC() &&
+      !isRepresentableInObjC(ctor, ObjCReason::MemberOfObjCSubclass,
+                             errorConvention))
+    ctor->getAttrs().add(new (ctx) NonObjCAttr(/*isImplicit=*/true));
 }
 
 ConstructorDecl *
diff --git a/lib/Sema/CodeSynthesis.h b/lib/Sema/CodeSynthesis.h
index ec9dba5..5d38391 100644
--- a/lib/Sema/CodeSynthesis.h
+++ b/lib/Sema/CodeSynthesis.h
@@ -95,10 +95,9 @@
 
 // These are implemented in TypeCheckDecl.cpp.
 void makeFinal(ASTContext &ctx, ValueDecl *D);
-void makeDynamic(ASTContext &ctx, ValueDecl *D);
 
 // Implemented in TypeCheckerOverride.cpp
-bool checkOverrides(TypeChecker &TC, ValueDecl *decl);
+bool checkOverrides(ValueDecl *decl);
 
 // These are implemented in CodeSynthesis.cpp.
 void maybeAddMaterializeForSet(AbstractStorageDecl *storage,
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index f7605a7..a2a2434 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -456,8 +456,6 @@
   SK_CollectionUpcastConversion,
   /// A value-to-optional conversion.
   SK_ValueToOptional,
-  /// Instantiating a function with archetype T as an Optional value.
-  SK_BindOptionalToArchetype,
   /// A conversion to an empty existential type ('Any' or '{}').
   SK_EmptyExistentialConversion,
   /// A key path application subscript.
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index f21c4e6..687378d 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -355,11 +355,6 @@
 }
 
 void AttributeEarlyChecker::visitDynamicAttr(DynamicAttr *attr) {
-  // Only instance members of classes can be dynamic.
-  auto classDecl = D->getDeclContext()->getAsClassOrClassExtensionContext();
-  if (!classDecl)
-    diagnoseAndRemoveAttr(attr, diag::dynamic_not_in_class);
-    
   // Members cannot be both dynamic and final.
   if (D->getAttrs().hasAttribute<FinalAttr>())
     diagnoseAndRemoveAttr(attr, diag::dynamic_with_final);
@@ -1964,7 +1959,10 @@
   // Symbols of dynamically-dispatched declarations are never referenced
   // directly, so marking them as @usableFromInline does not make sense.
   if (VD->isDynamic()) {
-    diagnoseAndRemoveAttr(attr, diag::usable_from_inline_dynamic_not_supported);
+    if (attr->isImplicit())
+      attr->setInvalid();
+    else
+      diagnoseAndRemoveAttr(attr, diag::usable_from_inline_dynamic_not_supported);
     return;
   }
 
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index bf5c5b2..ee993b9 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -1117,12 +1117,6 @@
   }
 }
 
-void swift::makeDynamic(ASTContext &ctx, ValueDecl *D) {
-  if (D && !D->isDynamic()) {
-    D->getAttrs().add(new (ctx) DynamicAttr(/*IsImplicit=*/true));
-  }
-}
-
 namespace {
 // The raw values of this enum must be kept in sync with
 // diag::implicitly_final_cannot_be_open.
@@ -1222,61 +1216,108 @@
   }
 }
 
-/// If we need to infer 'dynamic', do so now.
+/// Try to make the given declaration 'dynamic', checking any semantic
+/// constraints before doing so.
 ///
-/// This occurs when
-/// - it is implied by an attribute like @NSManaged
-/// - when we have an override of an imported method
-/// - we need to dynamically dispatch to a method in an extension
-///
-/// FIXME: The latter reason is a hack. We should figure out how to safely
-/// put extension methods into the class vtable.
-static void inferDynamic(ASTContext &ctx, ValueDecl *D) {
+/// \returns true if it can be made dynamic, false otherwise.
+static bool makeDynamic(ValueDecl *decl) {
+  // Only  members of classes can be dynamic.
+  auto classDecl = decl->getDeclContext()->getAsClassOrClassExtensionContext();
+  if (!classDecl) {
+    auto attr = decl->getAttrs().getAttribute<DynamicAttr>();
+    decl->diagnose(diag::dynamic_not_in_class)
+      .fixItRemove(attr ? SourceRange(attr->getLocation()) : SourceRange());
+    return false;
+  }
+
+  // 'dynamic' is only supported through the Objective-C runtime.
+  if (!decl->isObjC()) {
+    decl->diagnose(diag::dynamic_requires_objc,
+                   decl->getDescriptiveKind(), decl->getFullName())
+      .fixItInsert(decl->getAttributeInsertionLoc(/*forModifier=*/false),
+                   "@objc ");
+    return false;
+  }
+
+  // If there isn't already a 'dynamic' attribute, add an inferred one.
+  if (!decl->getAttrs().hasAttribute<DynamicAttr>()) {
+    auto attr = new (decl->getASTContext()) DynamicAttr(/*implicit=*/true);
+    decl->getAttrs().add(attr);
+  }
+
+  return true;
+}
+
+bool IsDynamicRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
   // If we can't infer dynamic here, don't.
-  if (!DeclAttribute::canAttributeAppearOnDecl(DAK_Dynamic, D))
-    return;
+  if (!DeclAttribute::canAttributeAppearOnDecl(DAK_Dynamic, decl))
+    return false;
 
-  // The presence of 'dynamic' blocks the inference of 'dynamic'.
-  if (D->isDynamic())
-    return;
+  // If 'dynamic' was explicitly specified, check it.
+  if (auto dynamicAttr = decl->getAttrs().getAttribute<DynamicAttr>()) {
+    return makeDynamic(decl);
+  }
 
-  // Only 'objc' declarations use 'dynamic'.
-  if (!D->isObjC() || D->hasClangNode())
-    return;
+  // Runtime-replacable accessors are dynamic when their storage declaration
+  // is dynamic. Other accessors are never dynamic.
+  if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
+    switch (accessor->getAccessorKind()) {
+    case AccessorKind::Get:
+    case AccessorKind::Set:
+      if (evaluator(IsDynamicRequest{accessor->getStorage()}))
+        return makeDynamic(decl);
 
-  bool overridesImportedMethod =
-    (D->getOverriddenDecl() &&
-     D->getOverriddenDecl()->hasClangNode());
+      return false;
 
-  bool overridesDyanmic =
-    (D->getOverriddenDecl() &&
-     D->getOverriddenDecl()->isDynamic());
+    case AccessorKind::Address:
+    case AccessorKind::DidSet:
+    case AccessorKind::MaterializeForSet:
+    case AccessorKind::MutableAddress:
+    case AccessorKind::WillSet:
+      return false;
+    }
+  }
 
-  bool isNSManaged = D->getAttrs().hasAttribute<NSManagedAttr>();
-
-  bool isExtension = isa<ExtensionDecl>(D->getDeclContext());
-
-  // We only infer 'dynamic' in these three cases.
-  if (!isExtension && !isNSManaged && !overridesImportedMethod &&
-      !overridesDyanmic)
-    return;
+  // The 'NSManaged' attribute implies 'dynamic'.
+  // FIXME: Use a semantic check for NSManaged rather than looking for the
+  // attribute (which could be ill-formed).
+  if (decl->getAttrs().hasAttribute<NSManagedAttr>()) {
+    return makeDynamic(decl);
+  }
 
   // The presence of 'final' blocks the inference of 'dynamic'.
-  if (D->isFinal() && !isNSManaged)
-    return;
+  if (decl->isFinal())
+    return false;
 
-  // Accessors should not infer 'dynamic' on their own; they can get it from
-  // their storage decls.
-  if (isa<AccessorDecl>(D))
-    return;
+  // Types are never 'dynamic'.
+  if (isa<TypeDecl>(decl))
+    return false;
 
-  // Only classes can use 'dynamic'.
-  auto classDecl = D->getDeclContext()->getAsClassOrClassExtensionContext();
-  if (!classDecl)
-    return;
+  // A non-@objc entity is never 'dynamic'.
+  if (!decl->isObjC())
+    return false;
 
-  // Add the 'dynamic' attribute.
-  D->getAttrs().add(new (ctx) DynamicAttr(/*IsImplicit=*/true));
+  // @objc declarations in class extensions are implicitly dynamic.
+  // This is intended to enable overriding the declarations.
+  auto dc = decl->getDeclContext();
+  if (isa<ExtensionDecl>(dc) && dc->getAsClassOrClassExtensionContext()) {
+    return makeDynamic(decl);
+  }
+
+  // If any of the declarations overridden by this declaration are dynamic
+  // or were imported from Objective-C, this declaration is dynamic.
+  // Don't do this if the declaration is not exposed to Objective-C; that's
+  // currently the (only) manner in which one can make an override of a
+  // dynamic declaration non-dynamic.
+  for (auto overridden : evaluator(OverriddenDeclsRequest{decl})) {
+    if (overridden->isDynamic())
+      return makeDynamic(decl);
+
+    if (overridden->hasClangNode())
+      return makeDynamic(decl);
+  }
+
+  return false;
 }
 
 namespace {
@@ -2227,16 +2268,6 @@
   // 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.
-  if (storage->isObjC()) {
-    if (auto *getter = storage->getGetter())
-      TC.validateDecl(getter);
-    if (auto *setter = storage->getSetter())
-      TC.validateDecl(setter);
-  }
-
   // Everything else about the accessors can wait until finalization.
   // This will validate all the accessors.
   TC.DeclsToFinalize.insert(storage);
@@ -2267,7 +2298,10 @@
 
     if (auto VD = dyn_cast<ValueDecl>(decl)) {
       checkRedeclaration(TC, VD);
-      
+
+      (void)VD->isObjC();
+      (void)VD->isDynamic();
+
       // If this is a member of a nominal type, don't allow it to have a name of
       // "Type" or "Protocol" since we reserve the X.Type and X.Protocol
       // expressions to mean something builtin to the language.  We *do* allow
@@ -2382,7 +2416,7 @@
       }
     }
 
-    if (!checkOverrides(TC, VD)) {
+    if (!checkOverrides(VD)) {
       // If a property has an override attribute but does not override
       // anything, complain.
       auto overridden = VD->getOverriddenDecl();
@@ -2398,6 +2432,24 @@
     TC.checkDeclAttributes(VD);
 
     triggerAccessorSynthesis(TC, VD);
+
+    // Under the Swift 3 inference rules, if we have @IBInspectable or
+    // @GKInspectable but did not infer @objc, warn that the attribute is
+    if (!VD->isObjC() && TC.Context.LangOpts.EnableSwift3ObjCInference) {
+      if (auto attr = VD->getAttrs().getAttribute<IBInspectableAttr>()) {
+        TC.diagnose(attr->getLocation(),
+                    diag::attribute_meaningless_when_nonobjc,
+                    attr->getAttrName())
+          .fixItRemove(attr->getRange());
+      }
+
+      if (auto attr = VD->getAttrs().getAttribute<GKInspectableAttr>()) {
+        TC.diagnose(attr->getLocation(),
+                    diag::attribute_meaningless_when_nonobjc,
+                    attr->getAttrName())
+          .fixItRemove(attr->getRange());
+      }
+    }
   }
 
 
@@ -2540,7 +2592,7 @@
     AccessControlChecker::checkAccessControl(TC, SD);
     UsableFromInlineChecker::checkUsableFromInline(TC, SD);
 
-    if (!checkOverrides(TC, SD)) {
+    if (!checkOverrides(SD)) {
       // If a subscript has an override attribute but does not override
       // anything, complain.
       if (auto *OA = SD->getAttrs().getAttribute<OverrideAttr>()) {
@@ -3042,7 +3094,7 @@
     AccessControlChecker::checkAccessControl(TC, FD);
     UsableFromInlineChecker::checkUsableFromInline(TC, FD);
 
-    if (!checkOverrides(TC, FD)) {
+    if (!checkOverrides(FD)) {
       // If a method has an 'override' keyword but does not
       // override anything, complain.
       if (auto *OA = FD->getAttrs().getAttribute<OverrideAttr>()) {
@@ -3183,7 +3235,7 @@
 
     // Check whether this initializer overrides an initializer in its
     // superclass.
-    if (!checkOverrides(TC, CD)) {
+    if (!checkOverrides(CD)) {
       // If an initializer has an override attribute but does not override
       // anything or overrides something that doesn't need an 'override'
       // keyword (e.g., a convenience initializer), complain.
@@ -3801,10 +3853,6 @@
     validateAttributes(*this, D);
 
     if (auto CD = dyn_cast<ClassDecl>(nominal)) {
-      // Mark a class as @objc. This must happen before checking its members.
-      Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, CD);
-      markAsObjC(*this, CD, isObjC);
-
       // Determine whether we require in-class initializers.
       if (CD->getAttrs().hasAttribute<RequiresStoredPropertyInitsAttr>() ||
           (CD->hasSuperclass() &&
@@ -3824,7 +3872,6 @@
     if (auto *ED = dyn_cast<EnumDecl>(nominal)) {
       // @objc enums use their raw values as the value representation, so we
       // need to force the values to be checked.
-      resolveIsObjC(ED);
       if (ED->isObjC())
         checkEnumRawValues(*this, ED);
     }
@@ -3880,25 +3927,6 @@
 
     validateAttributes(*this, D);
 
-    // If the protocol is @objc, it may only refine other @objc protocols.
-    // FIXME: Revisit this restriction.
-    if (proto->getAttrs().hasAttribute<ObjCAttr>()) {
-      Optional<ObjCReason> isObjC = ObjCReason(ObjCReason::ImplicitlyObjC);
-
-      for (auto inherited : proto->getInheritedProtocols()) {
-        if (!inherited->isObjC()) {
-          diagnose(proto->getLoc(),
-                   diag::objc_protocol_inherits_non_objc_protocol,
-                   proto->getDeclaredType(), inherited->getDeclaredType());
-          diagnose(inherited->getLoc(), diag::kind_identifier_declared_here,
-                   DescriptiveDeclKind::Protocol, inherited->getName());
-          isObjC = None;
-        }
-      }
-
-      markAsObjC(*this, proto, isObjC);
-    }
-
     // FIXME: IRGen likes to emit @objc protocol descriptors even if the
     // protocol comes from a different module or translation unit.
     //
@@ -3975,33 +4003,6 @@
     // Properties need some special validation logic.
     if (auto *nominalDecl = VD->getDeclContext()
             ->getAsNominalTypeOrNominalTypeExtensionContext()) {
-      // If this is a property, check if it needs to be exposed to
-      // Objective-C.
-      Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, VD);
-
-      if (isObjC && !swift::isRepresentableInObjC(VD, *isObjC))
-        isObjC = None;
-
-      markAsObjC(*this, VD, isObjC);
-
-      // Under the Swift 3 inference rules, if we have @IBInspectable or
-      // @GKInspectable but did not infer @objc, warn that the attribute is
-      if (!isObjC && Context.LangOpts.EnableSwift3ObjCInference) {
-        if (auto attr = VD->getAttrs().getAttribute<IBInspectableAttr>()) {
-          diagnose(attr->getLocation(),
-                   diag::attribute_meaningless_when_nonobjc,
-                   attr->getAttrName())
-            .fixItRemove(attr->getRange());
-        }
-
-        if (auto attr = VD->getAttrs().getAttribute<GKInspectableAttr>()) {
-          diagnose(attr->getLocation(),
-                   diag::attribute_meaningless_when_nonobjc,
-                   attr->getAttrName())
-            .fixItRemove(attr->getRange());
-        }
-      }
-
       // If this variable is a class member, mark it final if the
       // class is final, or if it was declared with 'let'.
       auto staticSpelling =
@@ -4021,9 +4022,6 @@
           fixItAccess(inFlightDiag, D, AccessLevel::Public);
         }
       }
-
-      // Infer 'dynamic' after 'final' but before touching accessors.
-      inferDynamic(Context, VD);
     }
 
     // Perform accessor-related validation.
@@ -4206,16 +4204,8 @@
       if (FD->isOperator())
         checkMemberOperator(*this, FD);
 
-      Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, FD);
       auto accessor = dyn_cast<AccessorDecl>(FD);
 
-      auto *protocolContext = dyn_cast<ProtocolDecl>(
-          FD->getDeclContext());
-      if (protocolContext && accessor) {
-        if (isObjC)
-          isObjC = ObjCReason::Accessor;
-      }
-
       if (accessor && accessor->isGetterOrSetter()) {
         // If the property decl is an instance property, its accessors will
         // be instance methods and the above condition will mark them ObjC.
@@ -4224,48 +4214,12 @@
 
         AbstractStorageDecl *storage = accessor->getStorage();
 
-        if (storage->getAttrs().hasAttribute<NonObjCAttr>())
-          isObjC = None;
-        else if (storage->isObjC()) {
-          if (!isObjC) {
-            // Make this accessor @objc because its property is @objc.
-            isObjC = ObjCReason::Accessor;
-          } else if (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.
-            ;
-            if (storageObjCAttr && storageObjCAttr->isSwift3Inferred() &&
-                shouldDiagnoseObjCReason(*isObjC, Context)) {
-              diagnose(storage, diag::accessor_swift3_objc_inference,
-                       storage->getDescriptiveKind(), storage->getFullName(),
-                       isa<SubscriptDecl>(storage), accessor->isSetter())
-                .fixItInsert(storage->getAttributeInsertionLoc(
-                                                      /*forModifier=*/false),
-                             "@objc ");
-            }
-          }
-        }
-
-        // If the storage is dynamic or final, propagate to this accessor.
-        if (isObjC &&
-            storage->isDynamic())
-          makeDynamic(Context, FD);
-
+        // If the storage is final, propagate to this accessor.
         if (storage->isFinal())
           makeFinal(Context, FD);
       }
 
-      Optional<ForeignErrorConvention> errorConvention;
-      if (isObjC &&
-          (FD->isInvalid() || !isRepresentableInObjC(FD, *isObjC,
-                                                     errorConvention)))
-        isObjC = None;
-      markAsObjC(*this, FD, isObjC, errorConvention);
-
       inferFinalAndDiagnoseIfNeeded(*this, FD, FD->getStaticSpelling());
-      inferDynamic(Context, FD);
     }
 
     // If the function is exported to C, it must be representable in (Obj-)C.
@@ -4354,22 +4308,6 @@
 
     validateAttributes(*this, CD);
 
-    // An initializer is ObjC-compatible if it's explicitly @objc or a member
-    // of an ObjC-compatible class.
-    if (CD->getDeclContext()->isTypeContext()) {
-      Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, CD,
-          /*allowImplicit=*/true);
-
-      Optional<ForeignErrorConvention> errorConvention;
-      if (isObjC &&
-          (CD->isInvalid() ||
-           !isRepresentableInObjC(CD, *isObjC, errorConvention)))
-        isObjC = None;
-      markAsObjC(*this, CD, isObjC, errorConvention);
-    }
-
-    inferDynamic(Context, CD);
-
     if (CD->getFailability() == OTK_ImplicitlyUnwrappedOptional) {
       auto &C = CD->getASTContext();
       CD->getAttrs().add(
@@ -4405,16 +4343,7 @@
 
     DD->setSignatureIsValidated();
 
-    // Do this before markAsObjC() to diagnose @nonobjc better
     validateAttributes(*this, DD);
-
-    // Destructors are always @objc, because their Objective-C entry point is
-    // -dealloc.
-    if (Context.LangOpts.EnableObjCInterop)
-      markAsObjC(*this, DD, ObjCReason(ObjCReason::ImplicitlyObjC));
-    else
-      DD->setIsObjC(false);
-
     break;
   }
 
@@ -4443,17 +4372,6 @@
     if (SD->getDeclContext()->isTypeContext()) {
       // If this is a class member, mark it final if the class is final.
       inferFinalAndDiagnoseIfNeeded(*this, SD, StaticSpellingKind::None);
-
-      // A subscript is ObjC-compatible if it's explicitly @objc, or a
-      // member of an ObjC-compatible class or protocol.
-      Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, SD);
-
-      if (isObjC && !swift::isRepresentableInObjC(SD, *isObjC))
-        isObjC = None;
-      markAsObjC(*this, SD, isObjC);
-
-      // Infer 'dynamic' before touching accessors.
-      inferDynamic(Context, SD);
     }
 
     // Perform accessor-related validation.
@@ -4673,6 +4591,28 @@
     requestNominalLayout(classDecl);
   if (auto *protocolDecl = dyn_cast<ProtocolDecl>(dc))
     requestNominalLayout(protocolDecl);
+
+  // Compute overrides.
+  (void)member->getOverriddenDecls();
+
+  // Check whether the member is @objc or dynamic.
+  (void)member->isObjC();
+  (void)member->isDynamic();
+
+  // If this represents (abstract) storage, form the appropriate accessors.
+  if (auto storage = dyn_cast<AbstractStorageDecl>(member)) {
+    validateAbstractStorageDecl(*this, storage);
+
+    // Request layout of the accessors for an @objc declaration.
+    // 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.
+    if (storage->isObjC()) {
+      for (auto accessor : storage->getAllAccessors()) {
+        requestMemberLayout(accessor);
+      }
+    }
+  }
 }
 
 void TypeChecker::requestNominalLayout(NominalTypeDecl *nominalDecl) {
@@ -4708,6 +4648,8 @@
 
     TC.validateDecl(VD);
 
+    TC.requestMemberLayout(VD);
+
     // The only thing left to do is synthesize storage for lazy variables.
     auto *prop = dyn_cast<VarDecl>(D);
     if (!prop)
diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp
index c8b6b6a..3b545a8 100644
--- a/lib/Sema/TypeCheckDeclObjC.cpp
+++ b/lib/Sema/TypeCheckDeclObjC.cpp
@@ -16,11 +16,13 @@
 //===----------------------------------------------------------------------===//
 #include "TypeCheckObjC.h"
 #include "TypeChecker.h"
+#include "TypeCheckProtocol.h"
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/Decl.h"
 #include "swift/AST/ExistentialLayout.h"
 #include "swift/AST/ForeignErrorConvention.h"
 #include "swift/AST/ParameterList.h"
+#include "swift/AST/TypeCheckRequests.h"
 #include "swift/Basic/StringExtras.h"
 using namespace swift;
 
@@ -232,6 +234,11 @@
   ASTContext &ctx = AFD->getASTContext();
   auto &diags = ctx.Diags;
 
+  if (!AFD->hasInterfaceType()) {
+    ctx.getLazyResolver()->resolveDeclSignature(
+                                      const_cast<AbstractFunctionDecl *>(AFD));
+  }
+
   bool Diagnose = shouldDiagnoseObjCReason(Reason, ctx);
   bool IsObjC = true;
   unsigned NumParams = PL->size();
@@ -262,6 +269,9 @@
       return false;
     }
 
+    if (param->getType()->hasError())
+      return false;
+    
     if (param->getType()->isRepresentableIn(
           ForeignLanguage::ObjectiveC,
           const_cast<AbstractFunctionDecl *>(AFD)))
@@ -434,7 +444,8 @@
     // Global computed properties may however @_cdecl their accessors.
     auto storage = accessor->getStorage();
     if (!storage->isObjC() && Reason != ObjCReason::ExplicitlyCDecl &&
-        Reason != ObjCReason::WitnessToObjC) {
+        Reason != ObjCReason::WitnessToObjC &&
+        Reason != ObjCReason::MemberOfObjCProtocol) {
       if (Diagnose) {
         auto error = accessor->isGetter()
                   ? (isa<VarDecl>(storage)
@@ -498,10 +509,7 @@
       !isParamListRepresentableInObjC(AFD,
                                       AFD->getParameterLists().back(),
                                       Reason)) {
-    if (!Diagnose) {
-      // Return as soon as possible if we are not producing diagnostics.
-      return false;
-    }
+    return false;
   }
 
   if (auto FD = dyn_cast<FuncDecl>(AFD)) {
@@ -742,6 +750,11 @@
   if (VD->isInvalid())
     return false;
 
+  if (!VD->hasInterfaceType()) {
+    VD->getASTContext().getLazyResolver()->resolveDeclSignature(
+                                              const_cast<VarDecl *>(VD));
+  }
+
   Type T = VD->getDeclContext()->mapTypeIntoContext(VD->getInterfaceType());
   if (auto *RST = T->getAs<ReferenceStorageType>()) {
     // In-memory layout of @weak and @unowned does not correspond to anything
@@ -787,6 +800,11 @@
   if (checkObjCInForeignClassContext(SD, Reason))
     return false;
 
+  if (!SD->hasInterfaceType()) {
+    SD->getASTContext().getLazyResolver()->resolveDeclSignature(
+                                              const_cast<SubscriptDecl *>(SD));
+  }
+
   // Figure out the type of the indices.
   Type IndicesType = SD->getIndicesInterfaceType()->getWithoutImmediateLabel();
 
@@ -1010,13 +1028,19 @@
 }
 
 /// Figure out if a declaration should be exported to Objective-C.
-Optional<ObjCReason> swift::shouldMarkAsObjC(TypeChecker &TC,
-                                             const ValueDecl *VD,
-                                             bool allowImplicit) {
+Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
+  // If Objective-C interoperability is disabled, nothing gets marked as @objc.
+  if (!VD->getASTContext().LangOpts.EnableObjCInterop)
+    return None;
+
   if (auto classDecl = dyn_cast<ClassDecl>(VD)) {
     return shouldMarkClassAsObjC(classDecl);
   }
 
+  // Destructors are always @objc, with -dealloc as their entry point.
+  if (auto deinit = dyn_cast<DestructorDecl>(VD))
+    return ObjCReason(ObjCReason::ImplicitlyObjC);
+
   ProtocolDecl *protocolContext =
       dyn_cast<ProtocolDecl>(VD->getDeclContext());
   bool isMemberOfObjCProtocol =
@@ -1042,6 +1066,16 @@
   // explicitly declared @objc.
   if (VD->getAttrs().hasAttribute<ObjCAttr>())
     return ObjCReason(ObjCReason::ExplicitlyObjC);
+  // Getter or setter for an @objc property or subscript.
+  if (auto accessor = dyn_cast<AccessorDecl>(VD)) {
+    if (accessor->getAccessorKind() == AccessorKind::Get ||
+        accessor->getAccessorKind() == AccessorKind::Set) {
+      if (accessor->getStorage()->isObjC())
+        return ObjCReason(ObjCReason::Accessor);
+
+      return None;
+    }
+  }
   // @IBOutlet, @IBAction, @NSManaged, and @GKInspectable imply @objc.
   //
   // @IBInspectable and @GKInspectable imply @objc quietly in Swift 3
@@ -1076,23 +1110,18 @@
   // A witness to an @objc protocol requirement is implicitly @objc.
   if (VD->getDeclContext()->getAsClassOrClassExtensionContext()) {
     auto requirements =
-      TC.findWitnessedObjCRequirements(VD, /*anySingleRequirement=*/true);
+      findWitnessedObjCRequirements(VD, /*anySingleRequirement=*/true);
     if (!requirements.empty())
       return ObjCReason::witnessToObjC(requirements.front());
   }
 
   ASTContext &ctx = VD->getASTContext();
 
-  // Infer '@objc' for 'dynamic' members.
+  // Under Swift 3's @objc inference rules, 'dynamic' infers '@objc'.
   if (auto attr = VD->getAttrs().getAttribute<DynamicAttr>()) {
-    // For implicit 'dynamic', just infer '@objc' implicitly.
-    if (attr->isImplicit())
-      return ObjCReason(ObjCReason::ImplicitlyObjC);
-
     bool isGetterOrSetter =
       isa<AccessorDecl>(VD) && cast<AccessorDecl>(VD)->isGetterOrSetter();
 
-    // Under Swift 3's @objc inference rules, 'dynamic' infers '@objc'.
     if (ctx.LangOpts.EnableSwift3ObjCInference) {
       // If we've been asked to warn about deprecated @objc inference, do so
       // now.
@@ -1112,10 +1141,8 @@
     // anyway for better recovery.
     VD->diagnose(diag::dynamic_requires_objc,
                  VD->getDescriptiveKind(), VD->getFullName())
-      .highlight(attr->getRange())
       .fixItInsert(VD->getAttributeInsertionLoc(/*forModifier=*/false),
-                   "@objc ");
-
+                 "@objc ");
     return ObjCReason(ObjCReason::ImplicitlyObjC);
   }
 
@@ -1140,8 +1167,7 @@
       return None;
 
     if (classDecl->checkObjCAncestry() != ObjCClassKind::NonObjC) {
-      return VD->isImplicit() ? ObjCReason(ObjCReason::ImplicitlyObjC)
-                              : ObjCReason(ObjCReason::MemberOfObjCSubclass);
+      return ObjCReason(ObjCReason::MemberOfObjCSubclass);
     }
   }
 
@@ -1223,47 +1249,118 @@
   return true;
 }
 
-void TypeChecker::resolveIsObjC(ValueDecl *VD) {
+/// Record that a declaration is @objc.
+static void markAsObjC(ValueDecl *D, ObjCReason reason,
+                       Optional<ForeignErrorConvention> errorConvention);
+
+
+bool IsObjCRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const {
   auto dc = VD->getDeclContext();
-  if (dc->getAsClassOrClassExtensionContext()) {
+  Optional<ObjCReason> isObjC;
+  if (dc->getAsClassOrClassExtensionContext() && !isa<TypeDecl>(VD)) {
     // Members of classes can be @objc.
+    isObjC = shouldMarkAsObjC(VD, isa<ConstructorDecl>(VD));
   }
   else if (isa<ClassDecl>(VD)) {
     // Classes can be @objc.
 
     // Protocols and enums can also be @objc, but this is covered by the
-    // isObjC() check at the beginning.
+    // isObjC() check a the beginning.;
+    isObjC = shouldMarkAsObjC(VD, /*allowImplicit=*/false);
   } else if (auto enumDecl = dyn_cast<EnumDecl>(VD)) {
     // Enums can be @objc so long as they have a raw type that is representable
     // as an arithmetic type in C.
-    auto isObjC = isEnumObjC(enumDecl);
-    VD->setIsObjC(isObjC);
-    if (!isObjC) {
-      if (auto objcAttr = enumDecl->getAttrs().getAttribute<ObjCAttr>()) {
-        objcAttr->setInvalid();
+    if (isEnumObjC(enumDecl))
+      isObjC = ObjCReason(ObjCReason::ExplicitlyObjC);
+  } else if (auto proto = dyn_cast<ProtocolDecl>(VD)) {
+    if (proto->getAttrs().hasAttribute<ObjCAttr>()) {
+      isObjC = ObjCReason(ObjCReason::ExplicitlyObjC);
+
+      // If the protocol is @objc, it may only refine other @objc protocols.
+      // FIXME: Revisit this restriction.
+      for (auto inherited : proto->getInheritedProtocols()) {
+        if (!inherited->isObjC()) {
+          proto->diagnose(diag::objc_protocol_inherits_non_objc_protocol,
+                          proto->getDeclaredType(),
+                          inherited->getDeclaredType());
+          inherited->diagnose(diag::kind_identifier_declared_here,
+                              DescriptiveDeclKind::Protocol,
+                              inherited->getName());
+          isObjC = None;
+        }
       }
     }
   } else if (isa<ProtocolDecl>(dc) && cast<ProtocolDecl>(dc)->isObjC()) {
     // Members of @objc protocols are @objc.
+    isObjC = shouldMarkAsObjC(VD, isa<ConstructorDecl>(VD));
   } else {
-    // Cannot be @objc; do nothing.
-    return;
+    // Cannot be @objc.
   }
 
-  // Short-circuit this operation if we already know that the entity is @objc.
-  if (VD->isObjC()) return;
+  // Perform some icky stateful hackery to mark this declaration as
+  // not being @objc.
+  auto makeNotObjC = [&] {
+    if (auto objcAttr = VD->getAttrs().getAttribute<ObjCAttr>()) {
+      objcAttr->setInvalid();
+    }
+  };
 
+  // If this declaration should not be exposed to Objective-C, we're done.
+  if (!isObjC) {
+    makeNotObjC();
+    return false;
+  }
 
-  // FIXME: Narrow this computation to just the @objc bits.
-  validateDeclForNameLookup(VD);
+  if (auto accessor = dyn_cast<AccessorDecl>(VD)) {
+    auto storage = accessor->getStorage();
+    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.
+      ASTContext &ctx = dc->getASTContext();
+      if (storageObjCAttr && storageObjCAttr->isSwift3Inferred() &&
+          shouldDiagnoseObjCReason(*isObjC, ctx)) {
+        storage->diagnose(diag::accessor_swift3_objc_inference,
+                 storage->getDescriptiveKind(), storage->getFullName(),
+                 isa<SubscriptDecl>(storage), accessor->isSetter())
+          .fixItInsert(storage->getAttributeInsertionLoc(/*forModifier=*/false),
+                       "@objc ");
+      }
+    }
+  }
+
+  // If needed, check whether this declaration is representable in Objective-C.
+  Optional<ForeignErrorConvention> errorConvention;
+  if (auto var = dyn_cast<VarDecl>(VD)) {
+    if (!isRepresentableInObjC(var, *isObjC)) {
+      makeNotObjC();
+      return false;
+    }
+  } else if (auto subscript = dyn_cast<SubscriptDecl>(VD)) {
+    if (!isRepresentableInObjC(subscript, *isObjC)) {
+      makeNotObjC();
+      return false;
+    }
+  } else if (isa<DestructorDecl>(VD)) {
+    // Destructors need no additional checking.
+  } else if (auto func = dyn_cast<AbstractFunctionDecl>(VD)) {
+    if (!isRepresentableInObjC(func, *isObjC, errorConvention)) {
+      makeNotObjC();
+      return false;
+    }
+  }
+
+  // Note that this declaration is exposed to Objective-C.
+  markAsObjC(VD, *isObjC, errorConvention);
+
+  return true;
 }
 
 /// Infer the Objective-C name for a given declaration.
-static void inferObjCName(TypeChecker &tc, ValueDecl *decl) {
+static void inferObjCName(ValueDecl *decl) {
   if (isa<DestructorDecl>(decl))
     return;
 
-  assert(decl->isObjC() && "Must be known to be @objc");
   auto attr = decl->getAttrs().getAttribute<ObjCAttr>();
 
   /// Set the @objc name.
@@ -1356,7 +1453,7 @@
   // requirements for which this declaration is a witness.
   Optional<ObjCSelector> requirementObjCName;
   ValueDecl *firstReq = nullptr;
-  for (auto req : tc.findWitnessedObjCRequirements(decl)) {
+  for (auto req : findWitnessedObjCRequirements(decl)) {
     // If this is the first requirement, take its name.
     if (!requirementObjCName) {
       requirementObjCName = req->getObjCRuntimeName();
@@ -1402,35 +1499,31 @@
 ///
 /// If the declaration has a @nonobjc attribute, diagnose an error
 /// using the given Reason, if present.
-void swift::markAsObjC(TypeChecker &TC, ValueDecl *D,
-                       Optional<ObjCReason> isObjC,
-                       Optional<ForeignErrorConvention> errorConvention) {
-  D->setIsObjC(isObjC.hasValue());
-
-  if (!isObjC) {
-    // FIXME: For now, only @objc declarations can be dynamic.
-    if (auto attr = D->getAttrs().getAttribute<DynamicAttr>())
-      attr->setInvalid();
-    return;
-  }
-
+void markAsObjC(ValueDecl *D, ObjCReason reason,
+                Optional<ForeignErrorConvention> errorConvention) {
   ASTContext &ctx = D->getASTContext();
 
   // By now, the caller will have handled the case where an implicit @objc
   // could be overridden by @nonobjc. If we see a @nonobjc and we are trying
   // to add an @objc for whatever reason, diagnose an error.
   if (auto *attr = D->getAttrs().getAttribute<NonObjCAttr>()) {
-    if (!shouldDiagnoseObjCReason(*isObjC, ctx))
-      isObjC = ObjCReason::ImplicitlyObjC;
+    if (!shouldDiagnoseObjCReason(reason, ctx))
+      reason = ObjCReason::ImplicitlyObjC;
 
     D->diagnose(diag::nonobjc_not_allowed,
-                getObjCDiagnosticAttrKind(*isObjC));
+                getObjCDiagnosticAttrKind(reason));
 
     attr->setInvalid();
   }
 
-  TC.useObjectiveCBridgeableConformances(D->getInnermostDeclContext(),
-                                         D->getInterfaceType());
+  if (!D->hasInterfaceType()) {
+    ctx.getLazyResolver()->resolveDeclSignature(D);
+  }
+
+  if (!isa<AccessorDecl>(D)) {
+    useObjectiveCBridgeableConformances(D->getInnermostDeclContext(),
+                                        D->getInterfaceType());
+  }
 
   // Record the name of this Objective-C method in its class.
   if (auto classDecl
@@ -1458,7 +1551,7 @@
       }
 
       // Infer the Objective-C name for this method.
-      inferObjCName(TC, method);
+      inferObjCName(method);
 
       // ... then record it.
       classDecl->recordObjCMethod(method);
@@ -1500,7 +1593,7 @@
       }
     } else if (isa<VarDecl>(D)) {
       // Infer the Objective-C name for this property.
-      inferObjCName(TC, D);
+      inferObjCName(D);
     }
   } else if (auto method = dyn_cast<AbstractFunctionDecl>(D)) {
     if (method->hasThrows()) {
@@ -1520,7 +1613,7 @@
 
   // Special handling for Swift 3 @objc inference rules that are no longer
   // present in later versions of Swift.
-  if (*isObjC == ObjCReason::MemberOfObjCSubclass) {
+  if (reason == ObjCReason::MemberOfObjCSubclass) {
     // If we've been asked to unconditionally warn about these deprecated
     // @objc inference rules, do so now. However, we don't warn about
     // accessors---just the main storage declarations.
diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp
index 3bede61..ac1ed80 100644
--- a/lib/Sema/TypeCheckDeclOverride.cpp
+++ b/lib/Sema/TypeCheckDeclOverride.cpp
@@ -21,6 +21,7 @@
 #include "swift/AST/Availability.h"
 #include "swift/AST/Decl.h"
 #include "swift/AST/ParameterList.h"
+#include "swift/AST/TypeCheckRequests.h"
 using namespace swift;
 
 static void adjustFunctionTypeForOverride(Type &type) {
@@ -356,8 +357,7 @@
 /// \c overridden declaration.
 ///
 /// \returns true if an error occurred.
-static bool recordOverride(TypeChecker &TC, ValueDecl *override,
-                           ValueDecl *base, bool isKnownObjC = false);
+static bool checkSingleOverride(ValueDecl *override, ValueDecl *base);
 
 /// If the difference between the types of \p decl and \p base is something
 /// we feel confident about fixing (even partially), emit a note with fix-its
@@ -536,7 +536,6 @@
   /// Class that handles the checking of a particular declaration against
   /// superclass entities that it could override.
   class OverrideMatcher {
-    TypeChecker &tc;
     ASTContext &ctx;
     ValueDecl *decl;
 
@@ -553,7 +552,7 @@
     Type cachedDeclType;
 
   public:
-    OverrideMatcher(TypeChecker &tc, ValueDecl *decl);
+    OverrideMatcher(ValueDecl *decl);
 
     /// Returns true when it's possible to perform any override matching.
     explicit operator bool() const {
@@ -582,8 +581,8 @@
   };
 }
 
-OverrideMatcher::OverrideMatcher(TypeChecker &tc, ValueDecl *decl)
-    : tc(tc), ctx(decl->getASTContext()), decl(decl) {
+OverrideMatcher::OverrideMatcher(ValueDecl *decl)
+    : ctx(decl->getASTContext()), decl(decl) {
   // The final step for this constructor is to set up the superclass type,
   // without which we will not perform an matching. Early exits therefore imply
   // that there is no way we can match this declaration.
@@ -644,7 +643,8 @@
     lookupOptions -= NameLookupFlags::PerformConformanceCheck;
 
     membersName = name;
-    members = tc.lookupMember(dc, superclass, membersName, lookupOptions);
+    members = TypeChecker::lookupMember(dc, superclass, membersName,
+                                        lookupOptions);
   }
 
   // Check each member we found.
@@ -783,6 +783,8 @@
     diags.diagnose(baseDecl, diag::overridden_here);
   }
 
+  bool isAccessor = isa<AccessorDecl>(decl);
+
   // Check that the override has the required access level.
   // Overrides have to be at least as accessible as what they
   // override, except:
@@ -793,7 +795,8 @@
   // never really "overridden" in the intended sense here, because of
   // course derived classes will change how the class is initialized.
   AccessLevel matchAccess = baseDecl->getFormalAccess(dc);
-  if (matchAccess < AccessLevel::Open &&
+  if (!isAccessor &&
+      matchAccess < AccessLevel::Open &&
       baseDecl->getModuleContext() != decl->getModuleContext() &&
       !isa<ConstructorDecl>(decl)) {
     diags.diagnose(decl, diag::override_of_non_open,
@@ -955,21 +958,35 @@
     }
   }
 
+  if (emittedMatchError)
+    return true;
+
   // Catch-all to make sure we don't silently accept something we shouldn't.
-  if (attempt != OverrideCheckingAttempt::PerfectMatch &&
-      !emittedMatchError) {
+  if (attempt != OverrideCheckingAttempt::PerfectMatch) {
     OverrideMatch match{decl, /*isExact=*/false, declTy};
     diagnoseGeneralOverrideFailure(decl, match, attempt);
   }
 
-  return recordOverride(tc, decl, baseDecl);
+  return checkSingleOverride(decl, baseDecl);
+}
+
+// Invalidate an existing "override" attribute or add a new invalid "override"
+// attribute, which will suppress additional checking.
+static void invalidateOverrideAttribute(ValueDecl *decl) {
+  auto overrideAttr = decl->getAttrs().getAttribute<OverrideAttr>(true);
+  if (!overrideAttr) {
+    overrideAttr = new (decl->getASTContext()) OverrideAttr(true);
+    decl->getAttrs().add(overrideAttr);
+  }
+
+  overrideAttr->setInvalid();
 }
 
 /// Determine which method or subscript this method or subscript overrides
 /// (if any).
 ///
 /// \returns true if an error occurred.
-bool swift::checkOverrides(TypeChecker &TC, ValueDecl *decl) {
+bool swift::checkOverrides(ValueDecl *decl) {
   // If we already computed overridden declarations and either succeeded
   // or invalidated the attribute, there's nothing more to do.
   if (decl->overriddenDeclsComputed()) {
@@ -986,16 +1003,16 @@
     // Otherwise, we have more checking to do.
   }
 
-  // Set up matching, but bail out if there's nothing to match.
-  OverrideMatcher matcher(TC, decl);
-  if (!matcher) return false;
-
-  // Ignore accessor methods (e.g. getters and setters), they will be handled
-  // when their storage decl is processed.
-  // FIXME: We should pull information from the storage declaration, but
-  // that will be handled at a different point.
-  if (isa<AccessorDecl>(decl))
+  // Accessor methods get overrides through their storage declaration, and
+  // all checking can be performed via that mechanism.
+  if (isa<AccessorDecl>(decl)) {
+    (void)decl->getOverriddenDecls();
     return false;
+  }
+
+  // Set up matching, but bail out if there's nothing to match.
+  OverrideMatcher matcher(decl);
+  if (!matcher) return false;
 
   // Look for members with the same name and matching types as this
   // one.
@@ -1042,11 +1059,24 @@
   // If we override more than one declaration, complain.
   if (matches.size() > 1) {
     diagnoseGeneralOverrideFailure(decl, matches, attempt);
+    invalidateOverrideAttribute(decl);
     return true;
   }
 
-  // If we have a single match (exact or not), take it.
-  return matcher.checkOverride(matches.front().Decl, attempt);
+  // Check the single match. If it's ill-formed, invalidate the override
+  // attribute so we don't try again.
+  if (matcher.checkOverride(matches.front().Decl, attempt)) {
+    invalidateOverrideAttribute(decl);
+    return true;
+  }
+
+  // FIXME: Check for missing 'override' keyword here?
+
+  // We performed override checking, so record the override.
+  // FIXME: It's weird to be pushing state here, but how do we say that
+  // this check subsumes the normal 'override' check?
+  decl->setOverriddenDecl(matches.front().Decl);
+  return false;
 }
 
 namespace  {
@@ -1078,6 +1108,7 @@
     UNINTERESTING_ATTR(Alignment)
     UNINTERESTING_ATTR(CDecl)
     UNINTERESTING_ATTR(Consuming)
+    UNINTERESTING_ATTR(Dynamic)
     UNINTERESTING_ATTR(DynamicMemberLookup)
     UNINTERESTING_ATTR(SILGenName)
     UNINTERESTING_ATTR(Exported)
@@ -1092,6 +1123,7 @@
     UNINTERESTING_ATTR(Optimize)
     UNINTERESTING_ATTR(Inlinable)
     UNINTERESTING_ATTR(Effects)
+    UNINTERESTING_ATTR(Final)
     UNINTERESTING_ATTR(FixedLayout)
     UNINTERESTING_ATTR(Lazy)
     UNINTERESTING_ATTR(LLDBDebuggerFunction)
@@ -1162,46 +1194,6 @@
       }
     }
 
-    void visitFinalAttr(FinalAttr *attr) {
-      // If this is an accessor, don't complain if we would have
-      // complained about the storage declaration.
-      if (auto accessor = dyn_cast<AccessorDecl>(Override)) {
-        if (auto storageDecl = accessor->getStorage()) {
-          if (storageDecl->getOverriddenDecl() &&
-              storageDecl->getOverriddenDecl()->isFinal())
-            return;
-        }
-      }
-
-      // FIXME: Customize message to the kind of thing.
-      auto baseKind = Base->getDescriptiveKind();
-      switch (baseKind) {
-      case DescriptiveDeclKind::StaticLet:
-      case DescriptiveDeclKind::StaticVar:
-      case DescriptiveDeclKind::StaticMethod:
-        Diags.diagnose(Override, diag::override_static, baseKind);
-        break;
-      default:
-        Diags.diagnose(Override, diag::override_final,
-                       Override->getDescriptiveKind(), baseKind);
-        break;
-      }
-
-      Diags.diagnose(Base, diag::overridden_here);
-    }
-
-    void visitDynamicAttr(DynamicAttr *attr) {
-      // Final overrides are not dynamic.
-      if (Override->isFinal())
-        return;
-
-      // Must be @objc to be 'dynamic'.
-      if (!Override->isObjC())
-        return;
-
-      makeDynamic(Override->getASTContext(), Override);
-    }
-
     void visitObjCAttr(ObjCAttr *attr) {
       // Checking for overrides of declarations that are implicitly @objc
       // and occur in class extensions, because overriding will no longer be
@@ -1246,6 +1238,9 @@
     return ctor->isDesignatedInit() && !ctor->isRequired();
   }
 
+  if (isa<AccessorDecl>(overridden))
+    return false;
+
   return true;
 }
 
@@ -1343,9 +1338,10 @@
   return true;
 }
 
-static bool recordOverride(TypeChecker &TC, ValueDecl *override,
-                           ValueDecl *base, bool isKnownObjC) {
+static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) {
   // This can happen with circular inheritance.
+  // FIXME: This shouldn't be possible once name lookup goes through the
+  // request-evaluator.
   if (override == base)
     return true;
 
@@ -1357,7 +1353,8 @@
     auto *overrideASD = cast<AbstractStorageDecl>(override);
 
     // Make sure that the overriding property doesn't have storage.
-    if (overrideASD->hasStorage() &&
+    if ((overrideASD->hasStorage() ||
+         overrideASD->getAttrs().hasAttribute<LazyAttr>()) &&
         !(overrideASD->getWillSetFunc() || overrideASD->getDidSetFunc())) {
       bool downgradeToWarning = false;
       if (!ctx.isSwiftVersionAtLeast(5) &&
@@ -1417,11 +1414,17 @@
     }
   }
 
+  // Various properties are only checked for the storage declarations
+  // and not for the individual accessors. Otherwise, we end up with
+  // duplicated diagnostics.
+  bool isAccessor = isa<AccessorDecl>(override);
+
   // Non-Objective-C declarations in extensions cannot override or
   // be overridden.
-  if ((base->getDeclContext()->isExtensionContext() ||
+  if (!isAccessor &&
+      (base->getDeclContext()->isExtensionContext() ||
        override->getDeclContext()->isExtensionContext()) &&
-      !base->isObjC() && !isKnownObjC) {
+      !base->isObjC()) {
     bool baseCanBeObjC = canBeRepresentedInObjC(base);
     diags.diagnose(override, diag::override_decl_extension, baseCanBeObjC,
                    !base->getDeclContext()->isExtensionContext());
@@ -1450,7 +1453,6 @@
     else
       diags.diagnose(override, diag::missing_override);
     diags.diagnose(base, diag::overridden_here);
-    override->getAttrs().add(new (ctx) OverrideAttr(SourceLoc()));
   }
 
   // If the overridden method is declared in a Swift Class Declaration,
@@ -1460,8 +1462,9 @@
   // FIXME: Only warn if the extension is in another module, and if
   // it is in the same module, update the vtable.
   if (auto *baseDecl = dyn_cast<ClassDecl>(base->getDeclContext())) {
-    if (baseDecl->hasKnownSwiftImplementation() &&
-        !base->isDynamic() && !isKnownObjC &&
+    if (!isAccessor &&
+        baseDecl->hasKnownSwiftImplementation() &&
+        !base->isDynamic() &&
         override->getDeclContext()->isExtensionContext()) {
       // For compatibility, only generate a warning in Swift 3
       diags.diagnose(override, (ctx.isSwiftVersion3()
@@ -1488,6 +1491,27 @@
     }
   }
 
+  // The overridden declaration cannot be 'final'.
+  if (base->isFinal() && !isAccessor) {
+    // FIXME: Customize message to the kind of thing.
+    auto baseKind = base->getDescriptiveKind();
+    switch (baseKind) {
+    case DescriptiveDeclKind::StaticLet:
+    case DescriptiveDeclKind::StaticVar:
+    case DescriptiveDeclKind::StaticMethod:
+      override->diagnose(diag::override_static, baseKind);
+      break;
+    default:
+      override->diagnose(diag::override_final,
+                         override->getDescriptiveKind(), baseKind);
+      break;
+    }
+
+    base->diagnose(diag::overridden_here);
+
+    return true;
+  }
+
   // FIXME: Possibly should extend to more availability checking.
   if (auto *attr = base->getAttrs().getUnavailable(ctx)) {
     diagnoseUnavailableOverride(override, base, attr);
@@ -1497,17 +1521,6 @@
     diagnoseOverrideForAvailability(override, base);
   }
 
-  if (auto overridingFunc = dyn_cast<FuncDecl>(override)) {
-    overridingFunc->setOverriddenDecl(cast<FuncDecl>(base));
-  } else if (auto overridingCtor = dyn_cast<ConstructorDecl>(override)) {
-    overridingCtor->setOverriddenDecl(cast<ConstructorDecl>(base));
-  } else if (auto overridingASD = dyn_cast<AbstractStorageDecl>(override)) {
-    auto *baseASD = cast<AbstractStorageDecl>(base);
-    overridingASD->setOverriddenDecl(baseASD);
-  } else {
-    llvm_unreachable("Unexpected decl");
-  }
-
   /// Check attributes associated with the base; some may need to merged with
   /// or checked against attributes in the overriding declaration.
   AttributeOverrideChecker attrChecker(base, override);
@@ -1515,55 +1528,13 @@
     attrChecker.visit(attr);
   }
 
-  if (auto overridingASD = dyn_cast<AbstractStorageDecl>(override)) {
-    // Make sure we get consistent overrides for the accessors as well.
-    auto *baseASD = cast<AbstractStorageDecl>(base);
-    assert(baseASD->getGetter());
-
-    auto recordAccessorOverride = [&](AccessorKind kind) {
-      // We need the same accessor on both.
-      auto baseAccessor = baseASD->getAccessor(kind);
-      if (!baseAccessor) return;
-      auto overridingAccessor = overridingASD->getAccessor(kind);
-      if (!overridingAccessor) return;
-
-      // For setter accessors, we need the base's setter to be
-      // accessible from the overriding context, or it's not an override.
-      if ((kind == AccessorKind::Set ||
-           kind == AccessorKind::MaterializeForSet) &&
-          !baseASD->isSetterAccessibleFrom(overridingASD->getDeclContext()))
-        return;
-
-      // A materializeForSet for an override of storage with a
-      // forced static dispatch materializeForSet is not itself an
-      // override.
-      if (kind == AccessorKind::MaterializeForSet &&
-          baseAccessor->hasForcedStaticDispatch())
-        return;
-
-      // FIXME: Egregious hack to set an 'override' attribute.
-      if (!overridingAccessor->getAttrs().hasAttribute<OverrideAttr>()) {
-        auto loc = overridingASD->getOverrideLoc();
-        overridingAccessor->getAttrs().add(
-            new (ctx) OverrideAttr(loc));
-      }
-
-      recordOverride(TC, overridingAccessor, baseAccessor, baseASD->isObjC());
-    };
-
-    // FIXME: Another list of accessors, yay!
-    recordAccessorOverride(AccessorKind::Get);
-    recordAccessorOverride(AccessorKind::Set);
-    recordAccessorOverride(AccessorKind::MaterializeForSet);
-  }
-
   return false;
 }
 
 /// Minimize the set of overridden associated types, eliminating any
 /// associated types that are overridden by other associated types.
 static void minimizeOverriddenAssociatedTypes(
-                           SmallVectorImpl<ValueDecl *> &assocTypes) {
+                           llvm::TinyPtrVector<ValueDecl *> &assocTypes) {
   // Mark associated types that are "worse" than some other associated type,
   // because they come from an inherited protocol.
   bool anyWorse = false;
@@ -1591,9 +1562,10 @@
   // Copy in the associated types that aren't worse than any other associated
   // type.
   unsigned nextIndex = 0;
-  for (unsigned i : indices(assocTypes)) {
+  MutableArrayRef<ValueDecl *> buffer = assocTypes;
+  for (unsigned i : indices(buffer)) {
     if (worseThanAny[i]) continue;
-    assocTypes[nextIndex++] = assocTypes[i];
+    buffer[nextIndex++] = buffer[i];
   }
 
   assocTypes.erase(assocTypes.begin() + nextIndex, assocTypes.end());
@@ -1609,11 +1581,11 @@
 
 /// Compute the set of associated types that are overridden by the given
 /// associated type.
-static SmallVector<ValueDecl *, 4>
+static llvm::TinyPtrVector<ValueDecl *>
 computeOverriddenAssociatedTypes(AssociatedTypeDecl *assocType) {
   // Find associated types with the given name in all of the inherited
   // protocols.
-  SmallVector<ValueDecl *, 4> overriddenAssocTypes;
+  llvm::TinyPtrVector<ValueDecl *> overriddenAssocTypes;
   auto proto = assocType->getProtocol();
   proto->walkInheritedProtocols([&](ProtocolDecl *inheritedProto) {
     if (proto == inheritedProto) return TypeWalker::Action::Continue;
@@ -1648,78 +1620,109 @@
   return overriddenAssocTypes;
 }
 
-void TypeChecker::resolveOverriddenDecl(ValueDecl *VD) {
-  // If this function or something it calls didn't set any overridden
-  // declarations, it means that there are no overridden declarations. Set
-  // the empty list.
-  // Note: the request-evaluator would do this for free, but this function
-  // is still fundamentally stateful.
-  SWIFT_DEFER {
-    if (!VD->overriddenDeclsComputed())
-      (void)VD->setOverriddenDecls({ });
-  };
-
+llvm::TinyPtrVector<ValueDecl *>
+OverriddenDeclsRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
   // For an associated type, compute the (minimized) set of overridden
   // declarations.
-  if (auto assocType = dyn_cast<AssociatedTypeDecl>(VD)) {
-    // Assume there are no overridden declarations for the purposes of this
-    // computation.
-    // FIXME: The request-evaluator will eventually handle this for us.
-    (void)assocType->setOverriddenDecls({ });
-
-    auto overriddenAssocTypes = computeOverriddenAssociatedTypes(assocType);
-    (void)assocType->setOverriddenDecls(overriddenAssocTypes);
-    return;
+  if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
+    return computeOverriddenAssociatedTypes(assocType);
   }
 
   // Only members of classes can override other declarations.
-  if (!VD->getDeclContext()->getAsClassOrClassExtensionContext())
-    return;
+  if (!decl->getDeclContext()->getAsClassOrClassExtensionContext())
+    return { };
 
   // Types that aren't associated types cannot be overridden.
-  if (isa<TypeDecl>(VD))
-    return;
+  if (isa<TypeDecl>(decl))
+    return { };
+
+  // Accessors determine their overrides based on their abstract storage
+  // declarations.
+  if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
+    auto overridingASD = accessor->getStorage();
+
+    // Find the overidden storage declaration. If there isn't one, we're done.
+    auto baseASD = overridingASD->getOverriddenDecl();
+    if (!baseASD) return { };
+
+    auto kind = accessor->getAccessorKind();
+
+    // Find the base accessor; if there isn't one, we're done.
+    auto baseAccessor = baseASD->getAccessor(kind);
+    if (!baseAccessor) return { };
+
+    switch (kind) {
+      case AccessorKind::Get:
+        break;
+
+      case AccessorKind::MaterializeForSet:
+        // A materializeForSet for an override of storage with a
+        // forced static dispatch materializeForSet is not itself an
+        // override.
+        if (baseAccessor->hasForcedStaticDispatch())
+          return { };
+
+        LLVM_FALLTHROUGH;
+
+      case AccessorKind::Set:
+        // For setter accessors, we need the base's setter to be
+        // accessible from the overriding context, or it's not an override.
+        if (!baseASD->isSetterAccessibleFrom(overridingASD->getDeclContext()))
+          return { };
+        break;
+
+      case AccessorKind::Address:
+      case AccessorKind::DidSet:
+      case AccessorKind::MutableAddress:
+      case AccessorKind::WillSet:
+        return { };
+    }
+
+    // We are overriding the base accessor.
+
+    // Check the correctness of the override.
+    OverrideMatcher matcher(accessor);
+    if (matcher.checkOverride(baseAccessor,
+                              OverrideCheckingAttempt::PerfectMatch)) {
+      invalidateOverrideAttribute(decl);
+      return { };
+    }
+
+    return llvm::TinyPtrVector<ValueDecl *>{baseAccessor};
+  }
 
   // Only initializers and declarations marked with the 'override' declaration
   // modifier can override declarations.
-  if (!isa<ConstructorDecl>(VD) && !VD->getAttrs().hasAttribute<OverrideAttr>())
-    return;
-
-  // Invalidate an existing "override" attribute or add a new invalid "override"
-  // attribute, which will suppress additional checking.
-  auto invalidateOverrideAttribute = [VD]() {
-    auto overrideAttr = VD->getAttrs().getAttribute<OverrideAttr>(true);
-    if (!overrideAttr) {
-      overrideAttr = new (VD->getASTContext()) OverrideAttr(true);
-      VD->getAttrs().add(overrideAttr);
-    }
-
-    overrideAttr->setInvalid();
-  };
+  if (!isa<ConstructorDecl>(decl) &&
+      !decl->getAttrs().hasAttribute<OverrideAttr>())
+    return { };
 
   // Try to match potential overridden declarations.
-  OverrideMatcher matcher(*this, VD);
+  OverrideMatcher matcher(decl);
   if (!matcher) {
-    return;
+    return { };
   }
 
   auto matches = matcher.match(OverrideCheckingAttempt::PerfectMatch);
   if (matches.empty()) {
-    return;
+    return { };
   }
 
   // If we have more than one potential match, diagnose the ambiguity and
   // fail.
   if (matches.size() > 1) {
-    diagnoseGeneralOverrideFailure(VD, matches,
+    diagnoseGeneralOverrideFailure(decl, matches,
                                    OverrideCheckingAttempt::PerfectMatch);
-    invalidateOverrideAttribute();
-    return;
+    invalidateOverrideAttribute(decl);
+    return { };
   }
 
   // Check the correctness of the override.
-  // FIXME: This also records the override.
   if (matcher.checkOverride(matches.front().Decl,
-                            OverrideCheckingAttempt::PerfectMatch))
-    invalidateOverrideAttribute();
+                            OverrideCheckingAttempt::PerfectMatch)) {
+    invalidateOverrideAttribute(decl);
+    return { };
+  }
+
+  return llvm::TinyPtrVector<ValueDecl *>{matches.front().Decl};
 }
diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp
index 0e65a4a..9f0f0be 100644
--- a/lib/Sema/TypeCheckNameLookup.cpp
+++ b/lib/Sema/TypeCheckNameLookup.cpp
@@ -71,7 +71,6 @@
   /// Builder that helps construct a lookup result from the raw lookup
   /// data.
   class LookupResultBuilder {
-    TypeChecker &TC;
     LookupResult &Result;
     DeclContext *DC;
     NameLookupOptions Options;
@@ -86,12 +85,12 @@
     llvm::SmallDenseMap<std::pair<ValueDecl *, DeclContext *>, bool, 4> Known;
 
   public:
-    LookupResultBuilder(TypeChecker &tc, LookupResult &result, DeclContext *dc,
+    LookupResultBuilder(LookupResult &result, DeclContext *dc,
                         NameLookupOptions options,
                         bool isMemberLookup)
-      : TC(tc), Result(result), DC(dc), Options(options),
+      : Result(result), DC(dc), Options(options),
         IsMemberLookup(isMemberLookup) {
-      if (!TC.Context.LangOpts.EnableAccessControl)
+      if (!dc->getASTContext().LangOpts.EnableAccessControl)
         Options |= NameLookupFlags::IgnoreAccessControl;
     }
 
@@ -132,8 +131,8 @@
       removeOverriddenDecls(FoundOuterDecls);
 
       // Remove any shadowed declarations from the found-declarations set.
-      removeShadowedDecls(FoundDecls, DC->getParentModule(), &TC);
-      removeShadowedDecls(FoundOuterDecls, DC->getParentModule(), &TC);
+      removeShadowedDecls(FoundDecls, DC->getParentModule());
+      removeShadowedDecls(FoundOuterDecls, DC->getParentModule());
 
       // Filter out those results that have been removed from the
       // found-declarations set.
@@ -232,7 +231,10 @@
 
       // Dig out the protocol conformance.
       auto *foundProto = cast<ProtocolDecl>(foundDC);
-      auto conformance = TC.conformsToProtocol(conformingType, foundProto, DC,
+      auto resolver = DC->getASTContext().getLazyResolver();
+      assert(resolver && "Need an active resolver");
+      auto &tc = *static_cast<TypeChecker *>(resolver);
+      auto conformance = tc.conformsToProtocol(conformingType, foundProto, DC,
                                                conformanceOptions);
       if (!conformance) {
         // If there's no conformance, we have an existential
@@ -254,10 +256,10 @@
       ValueDecl *witness = nullptr;
       auto concrete = conformance->getConcrete();
       if (auto assocType = dyn_cast<AssociatedTypeDecl>(found)) {
-        witness = concrete->getTypeWitnessAndDecl(assocType, &TC)
+        witness = concrete->getTypeWitnessAndDecl(assocType, nullptr)
           .second;
       } else if (found->isProtocolRequirement()) {
-        witness = concrete->getWitnessDecl(found, &TC);
+        witness = concrete->getWitnessDecl(found, nullptr);
 
         // It is possible that a requirement is visible to us, but
         // not the witness. In this case, just return the requirement;
@@ -300,12 +302,11 @@
 LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclName name,
                                             SourceLoc loc,
                                             NameLookupOptions options) {
-  UnqualifiedLookup lookup(name, dc, this, loc,
+  UnqualifiedLookup lookup(name, dc, nullptr, loc,
                            convertToUnqualifiedLookupOptions(options));
 
   LookupResult result;
-  LookupResultBuilder builder(*this, result, dc, options,
-                              /*memberLookup*/false);
+  LookupResultBuilder builder(result, dc, options, /*memberLookup*/false);
   for (auto idx : indices(lookup.Results)) {
     const auto &found = lookup.Results[idx];
     // Determine which type we looked through to find this result.
@@ -336,7 +337,7 @@
   {
     // Try lookup without ProtocolMembers first.
     UnqualifiedLookup lookup(
-        name, dc, this, loc,
+        name, dc, nullptr, loc,
         ulOptions - UnqualifiedLookup::Flags::AllowProtocolMembers);
 
     if (!lookup.Results.empty() ||
@@ -352,7 +353,7 @@
     // is called too early, we start resolving extensions -- even those
     // which do provide not conformances.
     UnqualifiedLookup lookup(
-        name, dc, this, loc,
+        name, dc, nullptr, loc,
         ulOptions | UnqualifiedLookup::Flags::AllowProtocolMembers);
 
     return LookupResult(lookup.Results, lookup.IndexOfFirstOuterResult);
@@ -380,10 +381,10 @@
   subOptions &= ~NL_RemoveOverridden;
   subOptions &= ~NL_RemoveNonVisible;
 
-  LookupResultBuilder builder(*this, result, dc, options,
+  LookupResultBuilder builder(result, dc, options,
                               /*memberLookup*/true);
   SmallVector<ValueDecl *, 4> lookupResults;
-  dc->lookupQualified(type, name, subOptions, this, lookupResults);
+  dc->lookupQualified(type, name, subOptions, nullptr, lookupResults);
 
   for (auto found : lookupResults)
     builder.add(found, nullptr, type, /*isOuter=*/false);
diff --git a/lib/Sema/TypeCheckObjC.h b/lib/Sema/TypeCheckObjC.h
index 58f5630..117369c 100644
--- a/lib/Sema/TypeCheckObjC.h
+++ b/lib/Sema/TypeCheckObjC.h
@@ -112,16 +112,6 @@
 /// complain about the correct attribute during @objc inference.
 unsigned getObjCDiagnosticAttrKind(ObjCReason reason);
 
-/// Figure out if a declaration should be exported to Objective-C.
-Optional<ObjCReason> shouldMarkAsObjC(TypeChecker &TC,
-                                      const ValueDecl *VD,
-                                      bool allowImplicit = false);
-
-/// Record whether the given declaration is @objc, and why.
-void markAsObjC(TypeChecker &TC, ValueDecl *D,
-                Optional<ObjCReason> isObjC,
-                Optional<ForeignErrorConvention> errorConvention = llvm::None);
-
 /// Determine whether the given function can be represented in Objective-C,
 /// and figure out its foreign error convention (if any).
 bool isRepresentableInObjC(const AbstractFunctionDecl *AFD,
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index aa534e3..0b894e2 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2270,14 +2270,15 @@
 
   // Record type witnesses for any "overridden" associated types.
   llvm::SetVector<AssociatedTypeDecl *> overriddenAssocTypes;
-  overriddenAssocTypes.insert(assocType->getOverriddenDecls().begin(),
-                              assocType->getOverriddenDecls().end());
+  auto assocOverriddenDecls = assocType->getOverriddenDecls();
+  overriddenAssocTypes.insert(assocOverriddenDecls.begin(),
+                              assocOverriddenDecls.end());
   for (unsigned idx = 0; idx < overriddenAssocTypes.size(); ++idx) {
     auto overridden = overriddenAssocTypes[idx];
 
     // Note all of the newly-discovered overridden associated types.
-    overriddenAssocTypes.insert(overridden->getOverriddenDecls().begin(),
-                                overridden->getOverriddenDecls().end());
+    auto overriddenDecls = overridden->getOverriddenDecls();
+    overriddenAssocTypes.insert(overriddenDecls.begin(), overriddenDecls.end());
 
     // Find the conformance for this overridden protocol.
     auto overriddenConformance =
@@ -3966,16 +3967,15 @@
 /// These conformances might not appear in any substitution lists produced
 /// by Sema, since bridging is done at the SILGen level, so we have to
 /// force them here to ensure SILGen can find them.
-void TypeChecker::useObjectiveCBridgeableConformances(DeclContext *dc,
-                                                      Type type) {
+void swift::useObjectiveCBridgeableConformances(DeclContext *dc, Type type) {
   class Walker : public TypeWalker {
-    TypeChecker &TC;
+    ASTContext &Ctx;
     DeclContext *DC;
     ProtocolDecl *Proto;
 
   public:
-    Walker(TypeChecker &tc, DeclContext *dc, ProtocolDecl *proto)
-      : TC(tc), DC(dc), Proto(proto) { }
+    Walker(DeclContext *dc, ProtocolDecl *proto)
+      : Ctx(dc->getASTContext()), DC(dc), Proto(proto) { }
 
     Action walkToTypePre(Type ty) override {
       ConformanceCheckOptions options =
@@ -3989,23 +3989,27 @@
         if (isa<ClassDecl>(nominalDecl) || isa<ProtocolDecl>(nominalDecl))
           return Action::Continue;
 
-        (void)TC.conformsToProtocol(ty, Proto, DC, options,
+        auto lazyResolver = Ctx.getLazyResolver();
+        assert(lazyResolver &&
+               "Cannot do conforms-to-protocol check without a type checker");
+        TypeChecker &tc = *static_cast<TypeChecker *>(lazyResolver);
+        (void)tc.conformsToProtocol(ty, Proto, DC, options,
                                     /*ComplainLoc=*/SourceLoc());
 
         // Set and Dictionary bridging also requires the conformance
         // of the key type to Hashable.
-        if (nominalDecl == TC.Context.getSetDecl() ||
-            nominalDecl == TC.Context.getDictionaryDecl()) {
+        if (nominalDecl == Ctx.getSetDecl() ||
+            nominalDecl == Ctx.getDictionaryDecl()) {
           if (auto boundGeneric = ty->getAs<BoundGenericType>()) {
             auto args = boundGeneric->getGenericArgs();
             if (!args.empty()) {
               auto keyType = args[0];
               auto *hashableProto =
-                TC.Context.getProtocol(KnownProtocolKind::Hashable);
+                Ctx.getProtocol(KnownProtocolKind::Hashable);
               if (!hashableProto)
                 return Action::Stop;
 
-              auto result = TC.conformsToProtocol(
+              auto result = tc.conformsToProtocol(
                   keyType, hashableProto, DC, options,
                   /*ComplainLoc=*/SourceLoc());
             }
@@ -4017,18 +4021,18 @@
     }
   };
 
-  auto proto = getProtocol(SourceLoc(),
-                           KnownProtocolKind::ObjectiveCBridgeable);
+  auto proto =
+    dc->getASTContext().getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
   if (!proto) return;
 
-  Walker walker(*this, dc, proto);
+  Walker walker(dc, proto);
   type.walk(walker);
 }
 
-void TypeChecker::useObjectiveCBridgeableConformancesOfArgs(
+void swift::useObjectiveCBridgeableConformancesOfArgs(
        DeclContext *dc, BoundGenericType *bound) {
-  auto proto = getProtocol(SourceLoc(),
-                           KnownProtocolKind::ObjectiveCBridgeable);
+  ASTContext &ctx = dc->getASTContext();
+  auto proto = ctx.getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
   if (!proto) return;
 
   // Check whether the bound generic type itself is bridged to
@@ -4036,7 +4040,10 @@
   ConformanceCheckOptions options =
     (ConformanceCheckFlags::InExpression |
      ConformanceCheckFlags::SuppressDependencyTracking);
-  (void)conformsToProtocol(
+  auto lazyResolver = ctx.getLazyResolver();
+  assert(lazyResolver && "Need a type checker to check conforms-to-protocol");
+  auto &tc = *static_cast<TypeChecker *>(lazyResolver);
+  (void)tc.conformsToProtocol(
       bound->getDecl()->getDeclaredType(), proto, dc,
       options, /*ComplainLoc=*/SourceLoc());
 }
@@ -4877,8 +4884,8 @@
 }
 
 llvm::TinyPtrVector<ValueDecl *>
-TypeChecker::findWitnessedObjCRequirements(const ValueDecl *witness,
-                                           bool anySingleRequirement) {
+swift::findWitnessedObjCRequirements(const ValueDecl *witness,
+                                     bool anySingleRequirement) {
   llvm::TinyPtrVector<ValueDecl *> result;
 
   // Types don't infer @objc this way.
@@ -4910,6 +4917,7 @@
     }
   }
 
+  ASTContext &ctx = nominal->getASTContext();
   for (auto proto : nominal->getAllProtocols()) {
     // We only care about Objective-C protocols.
     if (!proto->isObjC()) continue;
@@ -4923,7 +4931,7 @@
       if (isa<TypeDecl>(req)) continue;
 
       // Skip unavailable requirements.
-      if (req->getAttrs().isUnavailable(Context)) continue;
+      if (req->getAttrs().isUnavailable(ctx)) continue;
 
       // Dig out the conformance.
       if (!conformance.hasValue()) {
@@ -4937,7 +4945,7 @@
       }
       if (!*conformance) continue;
 
-      const Decl *found = (*conformance)->getWitnessDecl(req, this);
+      const Decl *found = (*conformance)->getWitnessDecl(req, nullptr);
 
       if (!found) {
         // If we have an optional requirement in an inherited conformance,
@@ -4961,7 +4969,10 @@
         if (accessorKind)
           witnessToMatch = cast<AccessorDecl>(witness)->getStorage();
 
-        if (matchWitness(*this, proto, *conformance,
+        auto lazyResolver = ctx.getLazyResolver();
+        assert(lazyResolver && "Need a type checker to match witnesses");
+        auto &tc = *static_cast<TypeChecker *>(lazyResolver);
+        if (matchWitness(tc, proto, *conformance,
                          witnessToMatch->getDeclContext(), req,
                          const_cast<ValueDecl *>(witnessToMatch))
               .Kind == MatchKind::ExactMatch) {
diff --git a/lib/Sema/TypeCheckProtocol.h b/lib/Sema/TypeCheckProtocol.h
index 3a25dc0..c11ddb4 100644
--- a/lib/Sema/TypeCheckProtocol.h
+++ b/lib/Sema/TypeCheckProtocol.h
@@ -858,6 +858,28 @@
 /// the noescape-to-escaping adjustment.
 Type adjustInferredAssociatedType(Type type, bool &noescapeToEscaping);
 
+/// Find the @objc requirement that are witnessed by the given
+/// declaration.
+///
+/// \param anySingleRequirement If true, returns at most a single requirement,
+/// which might be any of the requirements that match.
+///
+/// \returns the set of requirements to which the given witness is a
+/// witness.
+llvm::TinyPtrVector<ValueDecl *> findWitnessedObjCRequirements(
+                                     const ValueDecl *witness,
+                                     bool anySingleRequirement = false);
+
+/// Mark any _ObjectiveCBridgeable conformances in the given type as "used".
+void useObjectiveCBridgeableConformances(
+                      DeclContext *dc, Type type);
+
+/// If this bound-generic type is bridged, mark any
+/// _ObjectiveCBridgeable conformances in the generic arguments of
+/// the given type as "used".
+void useObjectiveCBridgeableConformancesOfArgs(
+                      DeclContext *dc, BoundGenericType *bound);
+
 }
 
 #endif // SWIFT_SEMA_PROTOCOL_H
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 793e978..6293ae6 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -18,6 +18,7 @@
 #include "TypeChecker.h"
 #include "GenericTypeResolver.h"
 #include "TypeCheckAvailability.h"
+#include "TypeCheckProtocol.h"
 
 #include "swift/Strings.h"
 #include "swift/AST/ASTVisitor.h"
@@ -2623,7 +2624,7 @@
 
   if (!options.contains(TypeResolutionFlags::ResolveStructure)) {
     // Check for _ObjectiveCBridgeable conformances in the element type.
-    TC.useObjectiveCBridgeableConformances(DC, baseTy);
+    useObjectiveCBridgeableConformances(DC, baseTy);
   }
 
   return sliceTy;
@@ -2658,8 +2659,8 @@
 
       // Check for _ObjectiveCBridgeable conformances in the key and value
       // types.
-      TC.useObjectiveCBridgeableConformances(DC, keyTy);
-      TC.useObjectiveCBridgeableConformances(DC, valueTy);
+      useObjectiveCBridgeableConformances(DC, keyTy);
+      useObjectiveCBridgeableConformances(DC, valueTy);
     }
 
     return dictTy;
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 470aacb..c3557c5 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1234,12 +1234,6 @@
     validateDeclForNameLookup(VD);
   }
 
-  /// Resolve the "overridden" declaration of the given declaration.
-  virtual void resolveOverriddenDecl(ValueDecl *VD) override;
-
-  /// Resolve the "is Objective-C" bit for the given declaration.
-  virtual void resolveIsObjC(ValueDecl *VD) override;
-
   virtual void bindExtension(ExtensionDecl *ext) override;
 
   virtual void resolveExtension(ExtensionDecl *ext) override {
@@ -1925,28 +1919,6 @@
   /// Return true if there was an error.
   bool checkConformanceToNSCopying(VarDecl *var);
 
-  /// Find the @objc requirement that are witnessed by the given
-  /// declaration.
-  ///
-  /// \param anySingleRequirement If true, returns at most a single requirement,
-  /// which might be any of the requirements that match.
-  ///
-  /// \returns the set of requirements to which the given witness is a
-  /// witness.
-  llvm::TinyPtrVector<ValueDecl *> findWitnessedObjCRequirements(
-                                     const ValueDecl *witness,
-                                     bool anySingleRequirement = false);
-
-  /// Mark any _ObjectiveCBridgeable conformances in the given type as "used".
-  void useObjectiveCBridgeableConformances(
-                        DeclContext *dc, Type type);
-
-  /// If this bound-generic type is bridged, mark any
-  /// _ObjectiveCBridgeable conformances in the generic arguments of
-  /// the given type as "used".
-  void useObjectiveCBridgeableConformancesOfArgs(
-                        DeclContext *dc, BoundGenericType *bound);
-
   /// Mark any _BridgedNSError/_BridgedStoredNSError/related
   /// conformances in the given type as "used".
   void useBridgedNSErrorConformances(DeclContext *dc, Type type);
@@ -1989,9 +1961,10 @@
   /// \param name The name of the entity to look for.
   /// \param loc The source location at which name lookup occurs.
   /// \param options Options that control name lookup.
-  LookupResult lookupUnqualified(DeclContext *dc, DeclName name, SourceLoc loc,
-                                 NameLookupOptions options
-                                   = defaultUnqualifiedLookupOptions);
+  static LookupResult lookupUnqualified(DeclContext *dc, DeclName name,
+                                        SourceLoc loc,
+                                        NameLookupOptions options
+                                          = defaultUnqualifiedLookupOptions);
 
   /// Perform unqualified type lookup at the given source location
   /// within a particular declaration context.
@@ -2001,9 +1974,9 @@
   /// \param loc The source location at which name lookup occurs.
   /// \param options Options that control name lookup.
   LookupResult
-  lookupUnqualifiedType(DeclContext *dc, DeclName name, SourceLoc loc,
-                        NameLookupOptions options
-                          = defaultUnqualifiedLookupOptions);
+  static lookupUnqualifiedType(DeclContext *dc, DeclName name, SourceLoc loc,
+                               NameLookupOptions options
+                                 = defaultUnqualifiedLookupOptions);
 
   /// \brief Lookup a member in the given type.
   ///
@@ -2013,9 +1986,9 @@
   /// \param options Options that control name lookup.
   ///
   /// \returns The result of name lookup.
-  LookupResult lookupMember(DeclContext *dc, Type type, DeclName name,
-                            NameLookupOptions options
-                              = defaultMemberLookupOptions);
+  static LookupResult lookupMember(DeclContext *dc, Type type, DeclName name,
+                                   NameLookupOptions options
+                                     = defaultMemberLookupOptions);
 
   /// \brief Check whether the given declaration can be written as a
   /// member of the given base type.
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 0f5ad9f..865a087 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2709,7 +2709,7 @@
         overriddenAssocTypes.push_back(overriddenAssocType);
       }
     }
-    (void)assocType->setOverriddenDecls(overriddenAssocTypes);
+    assocType->setOverriddenDecls(overriddenAssocTypes);
 
     break;
   }
diff --git a/stdlib/public/SDK/Foundation/NSDictionary.swift b/stdlib/public/SDK/Foundation/NSDictionary.swift
index eeb3de3..387defc 100644
--- a/stdlib/public/SDK/Foundation/NSDictionary.swift
+++ b/stdlib/public/SDK/Foundation/NSDictionary.swift
@@ -192,7 +192,8 @@
 
 extension NSMutableDictionary {
   // Bridging subscript.
-  override public subscript(key: Any) -> Any? {
+  @objc override public subscript(key: Any) -> Any? {
+    @objc(_swift_objectForKeyedSubscript:)
     get {
       return self.object(forKey: key)
     }
diff --git a/test/ClangImporter/objc_override.swift b/test/ClangImporter/objc_override.swift
index f27995f..bf8bdd7 100644
--- a/test/ClangImporter/objc_override.swift
+++ b/test/ClangImporter/objc_override.swift
@@ -19,8 +19,7 @@
   @objc func initWithString(_ string: String) { }
 
   var isEnabled: Bool { // expected-error{{overriding declaration requires an 'override' keyword}}
-    // FIXE: The error that follows is a bit strange.
-    get { return super.isEnabled } // expected-error{{'@objc' getter for non-'@objc' property}}
+    get { return super.isEnabled }
   }
 
   @objc(enabled)
diff --git a/test/Constraints/diag_ambiguities.swift b/test/Constraints/diag_ambiguities.swift
index e9e266c..3e399f8 100644
--- a/test/Constraints/diag_ambiguities.swift
+++ b/test/Constraints/diag_ambiguities.swift
@@ -29,19 +29,11 @@
 func h<T>(_ x: T) -> () {}
 C(h) // expected-error{{ambiguous use of 'init'}}
 
-func rdar29691909_callee(_ o: AnyObject?) -> Any? { return o }
-func rdar29691909_callee(_ o: AnyObject) -> Any { return o }
+func rdar29691909_callee(_ o: AnyObject?) -> Any? { return o } // expected-note {{found this candidate}}
+func rdar29691909_callee(_ o: AnyObject) -> Any { return o } // expected-note {{found this candidate}}
 
 func rdar29691909(o: AnyObject) -> Any? {
-  return rdar29691909_callee(o)
-}
-
-func rdar29691909_callee_alt(_ o: AnyObject?) -> Int? { fatalError() }
-func rdar29691909_callee_alt(_ o: AnyObject) -> Int { fatalError() }
-
-func rdar29691909_1(o: AnyObject) -> Int {
-  let r = rdar29691909_callee_alt(o)
-  return r
+  return rdar29691909_callee(o) // expected-error{{ambiguous use of 'rdar29691909_callee'}}
 }
 
 func rdar29907555(_ value: Any!) -> String {
diff --git a/test/Constraints/overload.swift b/test/Constraints/overload.swift
index fb03975..8e5e666 100644
--- a/test/Constraints/overload.swift
+++ b/test/Constraints/overload.swift
@@ -236,53 +236,3 @@
 func test_autoclosure1(ia: [Int]) {
   autoclosure1(ia, X()) // okay: resolves to the second function
 }
-
-// Ensure that we select the (T?, T) -> T overload of '??' in coalesce() below.
-func apply<T>(_ fn: () -> T) -> T { return fn() }
-func opt(x: String) -> String { return x }
-func opt() -> String? { return "hi" }
-
-func coalesce() {
-  let _ = apply{
-    _ = opt()
-    return opt()
-  } ?? ""
-}
-
-// Ensure that we do not select the (T?, T) -> T version of ??, which
-// would result in a warning about RHS never being selected.
-func rdar19748710_0(_ value: Int?) -> Int? {
-  return value ?? value
-}
-
-// Again, ensure we do not select (T?, T) -> T, despite forcing the result.
-func rdar19748710_1(_ value: Int?) -> Int? {
-  return (value ?? value)!
-}
-
-// FIXME: We choose to inject the LHS, which really doesn't seem like
-// the reasonable choice here. It seems more predictable and safe to
-// either inject the result of ??, or treat this as an error since the
-// current behavior will result in .some(nil) being force-unwrapped
-// rather than the RHS value. The diagnostic is problematic, too,
-// since it claims 'Int?' is a non-optional type.
-func rdar19748710_2(_ value: Int?) -> Int? {
-  return (value ?? value)!! // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'Int?', so the right side is never used}}
-}
-
-// Ensure that we select the more closely matching function between
-// the two _g overloads.
-func giveAny() -> Any { fatalError() }
-func giveAnyOptional() -> Any? { fatalError() }
-func takeAny(_ a: Any?) -> Any? { fatalError() }
-func takeAny(_ a: Any) -> Any { fatalError() }
-
-func testAnyOptional() {
-  let r = takeAny(giveAnyOptional())
-  let _ = r!
-}
-
-func testAny() {
-  let r = takeAny(giveAny())
-  let _ = r! // expected-error {{cannot force unwrap value of non-optional type 'Any'}}
-}
diff --git a/test/Constraints/overload_silgen.swift b/test/Constraints/overload_silgen.swift
deleted file mode 100644
index ae0e1ed..0000000
--- a/test/Constraints/overload_silgen.swift
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %target-swift-emit-silgen %s | %FileCheck %s
-
-// CHECK: sil hidden @$S15overload_silgen8anyToIntySiypF
-// CHECK: end sil function '$S15overload_silgen8anyToIntySiypF'
-func anyToInt(_: Any) -> Int { fatalError() }
-
-// CHECK: sil hidden @$S15overload_silgen8anyToIntySiSgypSgF
-// CHECK: function_ref @$S15overload_silgen8anyToIntySiypF
-// CHECK: end sil function '$S15overload_silgen8anyToIntySiSgypSgF'
-func anyToInt(_ value: Any?) -> Int? { return anyToInt(value!) }
diff --git a/test/Driver/Dependencies/only-skip-once.swift b/test/Driver/Dependencies/only-skip-once.swift
index c98052f..b2647a4 100644
--- a/test/Driver/Dependencies/only-skip-once.swift
+++ b/test/Driver/Dependencies/only-skip-once.swift
@@ -4,8 +4,6 @@
 
 // RUN: cd %t && %target-swiftc_driver -driver-show-job-lifecycle -output-file-map %t/output-file-map.json -incremental main.swift file1.swift file2.swift -j1 2>&1 | %FileCheck -check-prefix=CHECK-INITIAL %s
 
-// CHECK-INITIAL-NOT: warning
-// CHECK-INITIAL: Queuing (initial):
 // CHECK-INITIAL: Job finished: {compile: main.o <= main.swift}
 // CHECK-INITIAL: Job finished: {compile: file1.o <= file1.swift}
 // CHECK-INITIAL: Job finished: {compile: file2.o <= file2.swift}
@@ -15,7 +13,6 @@
 // RUN: cd %t && %target-swiftc_driver -driver-show-job-lifecycle -output-file-map %t/output-file-map.json -incremental main.swift file1.swift file2.swift -j1 2>&1 | %FileCheck -check-prefix=CHECK-REBUILD %s
 
 // We should skip the main and file1 rebuilds here, but we should only note skipping them _once_
-// CHECK-REBUILD: Queuing (initial):
 // CHECK-REBUILD: Job finished: {compile: file2.o <= file2.swift}
 // CHECK-REBUILD: Job skipped: {compile: main.o <= main.swift}
 // CHECK-REBUILD: Job skipped: {compile: file1.o <= file1.swift}
diff --git a/test/IDE/complete_stdlib_optional.swift b/test/IDE/complete_stdlib_optional.swift
index 12252d8..c57c957 100644
--- a/test/IDE/complete_stdlib_optional.swift
+++ b/test/IDE/complete_stdlib_optional.swift
@@ -16,38 +16,14 @@
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_1 > %t.opt.txt
 // RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_FOOSTRUCT < %t.opt.txt
 
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_2 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_FOOSTRUCT_RETURN < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_3 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_INT < %t.opt.txt
-
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_DOT_1 > %t.opt.txt
 // RUN: %FileCheck %s -check-prefix=UN_OPT_DOT_FOOSTRUCT < %t.opt.txt
 
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_DOT_2 > %t.opt.txt
 // RUN: %FileCheck %s -check-prefix=UN_OPT_DOT_FOOSTRUCT_RETURN < %t.opt.txt
 
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_DOT_3 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=UN_OPT_DOT_INT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_NO_DOT_1 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_NO_DOT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_NO_DOT_2 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_NO_DOT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_DOT_1 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_DOT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_DOT_2 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_DOT < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_FORCE_RETURN_OPTIONAL_1 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OPT_NO_DOT_OBJCCLASS < %t.opt.txt
-
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_CAST_AS_RESULT_1 > %t.opt.txt
-// RUN: %FileCheck %s -check-prefix=OPT_NO_DOT_OBJCCLASS < %t.opt.txt
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_2 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_FOOSTRUCT_RETURN < %t.opt.txt
 
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_TUPLE_1 | %FileCheck %s -check-prefix=OPT_TUPLE_1
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_TUPLE_2 | %FileCheck %s -check-prefix=OPT_TUPLE_2
@@ -76,12 +52,6 @@
   return FooStruct()
 }
 
-@objc
-class ObjcClass {
-  @objc var instanceVar: Int = 0
-  @objc func instanceFunc() -> ObjcClass { return self }
-}
-
 // OPT_NO_DOT_FOOSTRUCT: Begin completions
 // OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceVar]/CurrNominal:    ?.instanceVar[#Int#]{{; name=.+$}}
 // OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#Void#]{{; name=.+$}}
@@ -97,16 +67,6 @@
 // OPT_DOT_FOOSTRUCT_SPACES-DAG: Decl[InstanceMethod]/CurrNominal/Erase[3]: ?.instanceFunc()[#Void#]{{; name=.+$}}
 // OPT_DOT_FOOSTRUCT_SPACES: End completions
 
-// UN_OPT_NO_DOT_FOOSTRUCT: Begin completions
-// UN_OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceVar]/CurrNominal:    .instanceVar[#Int#]{{; name=.+$}}
-// UN_OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: .instanceFunc()[#Void#]{{; name=.+$}}
-// UN_OPT_NO_DOT_FOOSTRUCT: End completions
-
-// UN_OPT_NO_DOT_FOOSTRUCT_RETURN: Begin completions
-// UN_OPT_NO_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceVar]/CurrNominal:    ?.instanceVar[#Int#]{{; name=.+$}}
-// UN_OPT_NO_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#Void#]{{; name=.+$}}
-// UN_OPT_NO_DOT_FOOSTRUCT_RETURN: End completions
-
 // UN_OPT_DOT_FOOSTRUCT: Begin completions
 // UN_OPT_DOT_FOOSTRUCT-DAG: Decl[InstanceVar]/CurrNominal:    instanceVar[#Int#]{{; name=.+$}}
 // UN_OPT_DOT_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: instanceFunc()[#Void#]{{; name=.+$}}
@@ -117,32 +77,6 @@
 // UN_OPT_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceMethod]/CurrNominal/Erase[1]: ?.instanceFunc()[#Void#]{{; name=.+$}}
 // UN_OPT_DOT_FOOSTRUCT_RETURN: End completions
 
-// UN_OPT_NO_DOT_INT: Begin completions
-// UN_OPT_NO_DOT_INT-DAG: Decl[InstanceVar]/CurrNominal: ?.nonzeroBitCount[#Int#]{{; name=.+$}}
-// UN_OPT_NO_DOT_INT: End completions
-
-// UN_OPT_DOT_INT: Begin completions
-// UN_OPT_DOT_INT-DAG: Decl[InstanceVar]/CurrNominal/Erase[1]: ?.nonzeroBitCount[#Int#]{{; name=.+$}}
-// UN_OPT_DOT_INT: End completions
-
-// OPT_NO_DOT_OBJCCLASS: Begin completions
-// OPT_NO_DOT_OBJCCLASS-DAG: Decl[InstanceVar]/CurrNominal:    ?.instanceVar[#Int#]{{; name=.+$}}
-// OPT_NO_DOT_OBJCCLASS-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#ObjcClass#]{{; name=.+$}}
-// OPT_NO_DOT_OBJCCLASS: End completions
-
-// OBJCCLASS_MEMBERS_NO_DOT: Begin completions
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal:    .instanceVar[#Int#]
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc()[#ObjcClass#]
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: === {#AnyObject?#}[#Bool#]
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: !== {#AnyObject?#}[#Bool#]
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Keyword[self]/CurrNominal: .self[#ObjcClass#]; name=self
-// OBJCCLASS_MEMBERS_NO_DOT-NEXT: End completions
-
-// OBJCCLASS_MEMBERS_DOT: Begin completions
-// OBJCCLASS_MEMBERS_DOT-NEXT: Keyword[self]/CurrNominal: self[#ObjcClass#]; name=self
-// OBJCCLASS_MEMBERS_DOT-NEXT: Decl[InstanceVar]/CurrNominal:    instanceVar[#Int#]
-// OBJCCLASS_MEMBERS_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc()[#ObjcClass#]
-// OBJCCLASS_MEMBERS_DOT-NEXT: End completions
 
 //===---
 //===--- Tests.
@@ -184,38 +118,6 @@
   returnsImplicitlyUnwrappedOptional().#^UN_OPT_DOT_2^#
 }
 
-func testAnyObject1(a: AnyObject) {
-  a.instanceVar#^UN_OPT_NO_DOT_3^#
-}
-
-func testAnyObject2(a: AnyObject) {
-  a.instanceVar.#^UN_OPT_DOT_3^#
-}
-
-func testAnyObject3(a: AnyObject) {
-  a.instanceFunc!()#^OPT_DL_NO_DOT_1^#
-}
-
-func testAnyObject4(a: AnyObject) {
-  a.instanceFunc?()#^OPT_DL_NO_DOT_2^#
-}
-
-func testAnyObject5(a: AnyObject) {
-  a.instanceFunc!().#^OPT_DL_DOT_1^#
-}
-
-func testAnyObject6(a: AnyObject) {
-  a.instanceFunc?().#^OPT_DL_DOT_2^#
-}
-
-func testAnyObject7(a: AnyObject) {
-  (a.instanceFunc?())#^OPT_DL_FORCE_RETURN_OPTIONAL_1^#
-}
-
-func testAnyObject8(a: AnyObject) {
-  (a as? ObjcClass)#^OPT_CAST_AS_RESULT_1^#
-}
-
 func testOptionalTuple1(a: (Int, String)?) {
   a#^OPT_TUPLE_1^#
 }
@@ -245,3 +147,13 @@
 }
 // OPT_TUPLE_5: Pattern/CurrNominal/Erase[1]:       ?.x[#Int#]
 // OPT_TUPLE_5: Pattern/CurrNominal/Erase[1]:       ?.y[#String#]
+
+// UN_OPT_NO_DOT_FOOSTRUCT: Begin completions
+// UN_OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceVar]/CurrNominal:    .instanceVar[#Int#]{{; name=.+$}}
+// UN_OPT_NO_DOT_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: .instanceFunc()[#Void#]{{; name=.+$}}
+// UN_OPT_NO_DOT_FOOSTRUCT: End completions
+
+// UN_OPT_NO_DOT_FOOSTRUCT_RETURN: Begin completions
+// UN_OPT_NO_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceVar]/CurrNominal:    ?.instanceVar[#Int#]{{; name=.+$}}
+// UN_OPT_NO_DOT_FOOSTRUCT_RETURN-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#Void#]{{; name=.+$}}
+// UN_OPT_NO_DOT_FOOSTRUCT_RETURN: End completions
diff --git a/test/IDE/complete_stdlib_optional_objc.swift b/test/IDE/complete_stdlib_optional_objc.swift
new file mode 100644
index 0000000..46c5692
--- /dev/null
+++ b/test/IDE/complete_stdlib_optional_objc.swift
@@ -0,0 +1,90 @@
+// REQUIRES: objc_interop
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_NO_DOT_3 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=UN_OPT_NO_DOT_INT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=UN_OPT_DOT_3 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=UN_OPT_DOT_INT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_NO_DOT_1 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_NO_DOT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_NO_DOT_2 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_NO_DOT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_DOT_1 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_DOT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_DOT_2 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OBJCCLASS_MEMBERS_DOT < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_DL_FORCE_RETURN_OPTIONAL_1 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OPT_NO_DOT_OBJCCLASS < %t.opt.txt
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -disable-objc-attr-requires-foundation-module -code-completion-token=OPT_CAST_AS_RESULT_1 > %t.opt.txt
+// RUN: %FileCheck %s -check-prefix=OPT_NO_DOT_OBJCCLASS < %t.opt.txt
+
+@objc
+class ObjcClass {
+  @objc var instanceVar: Int = 0
+  @objc func instanceFunc() -> ObjcClass { return self }
+}
+
+func testAnyObject1(a: AnyObject) {
+  a.instanceVar#^UN_OPT_NO_DOT_3^#
+}
+
+func testAnyObject2(a: AnyObject) {
+  a.instanceVar.#^UN_OPT_DOT_3^#
+}
+
+func testAnyObject3(a: AnyObject) {
+  a.instanceFunc!()#^OPT_DL_NO_DOT_1^#
+}
+
+func testAnyObject4(a: AnyObject) {
+  a.instanceFunc?()#^OPT_DL_NO_DOT_2^#
+}
+
+func testAnyObject5(a: AnyObject) {
+  a.instanceFunc!().#^OPT_DL_DOT_1^#
+}
+
+func testAnyObject6(a: AnyObject) {
+  a.instanceFunc?().#^OPT_DL_DOT_2^#
+}
+
+func testAnyObject7(a: AnyObject) {
+  (a.instanceFunc?())#^OPT_DL_FORCE_RETURN_OPTIONAL_1^#
+}
+
+func testAnyObject8(a: AnyObject) {
+  (a as? ObjcClass)#^OPT_CAST_AS_RESULT_1^#
+}
+
+// UN_OPT_NO_DOT_INT: Begin completions
+// UN_OPT_NO_DOT_INT-DAG: Decl[InstanceVar]/CurrNominal: ?.nonzeroBitCount[#Int#]{{; name=.+$}}
+// UN_OPT_NO_DOT_INT: End completions
+
+// UN_OPT_DOT_INT: Begin completions
+// UN_OPT_DOT_INT-DAG: Decl[InstanceVar]/CurrNominal/Erase[1]: ?.nonzeroBitCount[#Int#]{{; name=.+$}}
+// UN_OPT_DOT_INT: End completions
+
+// OBJCCLASS_MEMBERS_NO_DOT: Begin completions
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal:    .instanceVar[#Int#]
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc()[#ObjcClass#]
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: === {#AnyObject?#}[#Bool#]
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: !== {#AnyObject?#}[#Bool#]
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: Keyword[self]/CurrNominal: .self[#ObjcClass#]; name=self
+// OBJCCLASS_MEMBERS_NO_DOT-NEXT: End completions
+
+// OBJCCLASS_MEMBERS_DOT: Begin completions
+// OBJCCLASS_MEMBERS_DOT-NEXT: Keyword[self]/CurrNominal: self[#ObjcClass#]; name=self
+// OBJCCLASS_MEMBERS_DOT-NEXT: Decl[InstanceVar]/CurrNominal:    instanceVar[#Int#]
+// OBJCCLASS_MEMBERS_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc()[#ObjcClass#]
+// OBJCCLASS_MEMBERS_DOT-NEXT: End completions
+
+// OPT_NO_DOT_OBJCCLASS: Begin completions
+// OPT_NO_DOT_OBJCCLASS-DAG: Decl[InstanceVar]/CurrNominal:    ?.instanceVar[#Int#]{{; name=.+$}}
+// OPT_NO_DOT_OBJCCLASS-DAG: Decl[InstanceMethod]/CurrNominal: ?.instanceFunc()[#ObjcClass#]{{; name=.+$}}
+// OPT_NO_DOT_OBJCCLASS: End completions
diff --git a/test/IRGen/objc_attr_NSManaged.sil b/test/IRGen/objc_attr_NSManaged.sil
index 288388d..a87587f 100644
--- a/test/IRGen/objc_attr_NSManaged.sil
+++ b/test/IRGen/objc_attr_NSManaged.sil
@@ -25,9 +25,7 @@
 // CHECK: @_PROPERTIES__TtC19objc_attr_NSManaged10SwiftGizmo = private constant { {{.*}}i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* [[X]], i64 0, i64 0),
 
 // The getter/setter should not show up in the Swift metadata.
-/* FIXME: sil_vtable parser picks the wrong 'init' overload. Both vtable entries
-   ought to be nonnull here. rdar://problem/19572342 */
-// CHECK: @"$S19objc_attr_NSManaged10SwiftGizmoCMf" = internal global <{ {{.*}} }> <{ void (%T19objc_attr_NSManaged10SwiftGizmoC*)* @"$S19objc_attr_NSManaged10SwiftGizmoCfD", i8** @"$SBOWV", i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC19objc_attr_NSManaged10SwiftGizmo" to i64), %objc_class* @"OBJC_CLASS_$_Gizmo", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [2 x { i8*, i8*, i8* }] }*, i8*, i8*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC19objc_attr_NSManaged10SwiftGizmo to i64), i64 {{1|2}}), i32 {{1|0}}, i32 0, i32 8, i16 7, i16 0, i32 112, i32 16, {{.*}}* @"$S19objc_attr_NSManaged10SwiftGizmoCMn", i8* null, %T19objc_attr_NSManaged10SwiftGizmoC* (i64, %T19objc_attr_NSManaged10SwiftGizmoC*)* @"$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnACSi_tcfc", i8* bitcast (void ()* @swift_deletedMethodError to i8*) }>
+// CHECK: @"$S19objc_attr_NSManaged10SwiftGizmoCMf" = internal global <{ {{.*}} }> <{ void (%T19objc_attr_NSManaged10SwiftGizmoC*)* @"$S19objc_attr_NSManaged10SwiftGizmoCfD", i8** @"$SBOWV", i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC19objc_attr_NSManaged10SwiftGizmo" to i64), %objc_class* @"OBJC_CLASS_$_Gizmo", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [2 x { i8*, i8*, i8* }] }*, i8*, i8*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC19objc_attr_NSManaged10SwiftGizmo to i64), i64 {{1|2}}), i32 {{1|0}}, i32 0, i32 8, i16 7, i16 0, i32 96, i32 16, {{.*}}* @"$S19objc_attr_NSManaged10SwiftGizmoCMn", i8* null }>
 
 @objc class SwiftGizmo : Gizmo {
   @objc @NSManaged var x: X
@@ -62,8 +60,5 @@
 
 sil @$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnSQyACGSi_tcfc : $@convention(method) (Int, @owned SwiftGizmo) -> Int
 
-/* FIXME: sil_vtable parser picks the wrong 'init' overload. rdar://problem/19572342 */
 sil_vtable SwiftGizmo {
-  // #SwiftGizmo.init!initializer.1: $S19objc_attr_NSManaged10SwiftGizmoCACycfc
-  #SwiftGizmo.init!initializer.1: @$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnACSi_tcfc
 }
diff --git a/test/IRGen/objc_super.swift b/test/IRGen/objc_super.swift
index c8b86cb..dc9bfb5 100644
--- a/test/IRGen/objc_super.swift
+++ b/test/IRGen/objc_super.swift
@@ -97,7 +97,7 @@
 // CHECK:   [[CLASS:%.*]] = and i64 [[ISA]], [[ISAMASK]]
 // CHECK:   [[TY:%.*]] = inttoptr i64 [[CLASS]] to %swift.type*
 // CHECK:   [[CAST:%.*]] = bitcast %swift.type* [[TY]] to i64*
-// CHECK:   [[OFFSETADDR:%.*]] = getelementptr inbounds i64, i64* [[CAST]], i64 19
+// CHECK:   [[OFFSETADDR:%.*]] = getelementptr inbounds i64, i64* [[CAST]], i64 17
 // CHECK:   [[FIELDOFFSET:%.*]] = load i64, i64* [[OFFSETADDR]]
 // CHECK:   [[BYTEADDR:%.*]] = bitcast %T10objc_super13GenericRuncerC* %0 to i8*
 // CHECK:   [[FIELDADDR:%.*]] = getelementptr inbounds i8, i8* [[BYTEADDR]], i64 [[FIELDOFFSET]]
diff --git a/test/Index/kinds.swift b/test/Index/kinds.swift
index 36ecf46..f37d67c 100644
--- a/test/Index/kinds.swift
+++ b/test/Index/kinds.swift
@@ -225,18 +225,6 @@
   // CHECK: [[@LINE-1]]:8 | instance-method/Swift | testMeNot() |
 }
 
-@objc class TargetForIBAction {}
-// CHECK: [[@LINE-1]]:13 | class/Swift | TargetForIBAction | [[TargetForIBAction_USR:.*]] | Def |
-class AttrAnnots {
-  @IBOutlet var iboutletString: AnyObject?
-  // CHECK: [[@LINE-1]]:17 | instance-property(IB)/Swift | iboutletString |
-  @IBAction func someibaction(o: TargetForIBAction) {}
-  // CHECK: [[@LINE-1]]:18 | instance-method(IB)/Swift | someibaction(o:) | {{.*}} | Def,Dyn,RelChild,RelIBType | rel: 2
-  // CHECK-NEXT: RelIBType | class/Swift | TargetForIBAction | [[TargetForIBAction_USR]]
-  @GKInspectable var gkString = "gk"
-  // CHECK: [[@LINE-1]]:22 | instance-property(GKI)/Swift | gkString |
-}
-
 // CHECK: [[@LINE+1]]:7 | class/Swift | C1 | [[C1_USR:.*]] | Def | rel: 0
 class C1 {}
 // CHECK: [[@LINE+1]]:11 | type-alias/Swift | C1Alias | [[C1Alias_USR:.*]] | Def | rel: 0
diff --git a/test/Index/kinds_objc.swift b/test/Index/kinds_objc.swift
new file mode 100644
index 0000000..1abc2a3
--- /dev/null
+++ b/test/Index/kinds_objc.swift
@@ -0,0 +1,15 @@
+// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+@objc class TargetForIBAction {}
+// CHECK: [[@LINE-1]]:13 | class/Swift | TargetForIBAction | [[TargetForIBAction_USR:.*]] | Def |
+class AttrAnnots {
+  @IBOutlet var iboutletString: AnyObject?
+  // CHECK: [[@LINE-1]]:17 | instance-property(IB)/Swift | iboutletString |
+  @IBAction func someibaction(o: TargetForIBAction) {}
+  // CHECK: [[@LINE-1]]:18 | instance-method(IB)/Swift | someibaction(o:) | {{.*}} | Def,Dyn,RelChild,RelIBType | rel: 2
+  // CHECK-NEXT: RelIBType | class/Swift | TargetForIBAction | [[TargetForIBAction_USR]]
+  @GKInspectable var gkString = "gk"
+  // CHECK: [[@LINE-1]]:22 | instance-property(GKI)/Swift | gkString |
+}
+
diff --git a/test/SILGen/Inputs/UIKit.swift b/test/SILGen/Inputs/UIKit.swift
index 1079d7e..6c89222 100644
--- a/test/SILGen/Inputs/UIKit.swift
+++ b/test/SILGen/Inputs/UIKit.swift
@@ -1,3 +1,4 @@
 import Foundation
 @_exported import UIKit
 
+public func UIApplicationMain() {}
diff --git a/test/SILGen/Inputs/usr/include/UIKit.h b/test/SILGen/Inputs/usr/include/UIKit.h
index 67df73c..bba1a98 100644
--- a/test/SILGen/Inputs/usr/include/UIKit.h
+++ b/test/SILGen/Inputs/usr/include/UIKit.h
@@ -3,6 +3,12 @@
 @protocol UIApplicationDelegate
 @end
 
+#ifdef SILGEN_TEST_UIAPPLICATIONMAIN_NULLABILITY
+int UIApplicationMain(int argc, char *_Nullable *_Nonnull argv,
+                      NSString *_Nullable principalClassName, 
+                      NSString *_Nullable delegateClassName);
+#else
 int UIApplicationMain(int argc, char **argv,
                       NSString *principalClassName, 
                       NSString *delegateClassName);
+#endif
diff --git a/test/SILGen/UIApplicationMain.swift b/test/SILGen/UIApplicationMain.swift
index 3a2f0ad..a5ac911 100644
--- a/test/SILGen/UIApplicationMain.swift
+++ b/test/SILGen/UIApplicationMain.swift
@@ -1,9 +1,13 @@
 // RUN: %empty-directory(%t)
 // RUN: %build-silgen-test-overlays
+// RUN: %build-silgen-test-overlays-ios
 
 // RUN: %target-swift-emit-silgen(mock-sdk: -sdk %S/Inputs -I %t) -parse-as-library %s | %FileCheck %s
 // RUN: %target-swift-emit-ir(mock-sdk: -sdk %S/Inputs -I %t) -parse-as-library %s | %FileCheck %s -check-prefix=IR
 
+// RUN: %target-swift-emit-silgen(mock-sdk: -Xcc -DSILGEN_TEST_UIAPPLICATIONMAIN_NULLABILITY -sdk %S/Inputs -I %t) -parse-as-library %s | %FileCheck %s
+// RUN: %target-swift-emit-ir(mock-sdk: -Xcc -DSILGEN_TEST_UIAPPLICATIONMAIN_NULLABILITY -sdk %S/Inputs -I %t) -parse-as-library %s | %FileCheck %s -check-prefix=IR
+
 // RUN: %target-swift-emit-silgen(mock-sdk: -sdk %S/Inputs -I %t) -parse-as-library %s -D REFERENCE | %FileCheck %s
 // RUN: %target-swift-emit-ir(mock-sdk: -sdk %S/Inputs -I %t) -parse-as-library %s -D REFERENCE | %FileCheck %s -check-prefix=IR
 
diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift
index 0c8b3ae..b25842c 100644
--- a/test/SILGen/dynamic.swift
+++ b/test/SILGen/dynamic.swift
@@ -545,7 +545,6 @@
 
 // No vtable entry for override of @objc extension property
 // CHECK-LABEL: sil_vtable [serialized] SubExt {
-// CHECK-NEXT: #BaseExt.init!initializer.1: (BaseExt.Type) -> () -> BaseExt : @$S7dynamic6SubExtCACycfc [override] // dynamic.SubExt.init() -> dynamic.SubExt
 // CHECK-NEXT: #SubExt.deinit!deallocator: @$S7dynamic6SubExtCfD // dynamic.SubExt.__deallocating_deinit
 // CHECK-NEXT: }
 
diff --git a/test/SILGen/lit.local.cfg b/test/SILGen/lit.local.cfg
index f946218..a8e15f8 100644
--- a/test/SILGen/lit.local.cfg
+++ b/test/SILGen/lit.local.cfg
@@ -5,3 +5,6 @@
                                 '%target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -enable-objc-interop -o %t %S/Inputs/ObjectiveC.swift && '
                                 '%target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -enable-objc-interop -o %t %S/Inputs/Dispatch.swift && '
                                 '%target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -enable-objc-interop -o %t %S/Inputs/Foundation.swift'))
+
+config.substitutions.insert(0, ('%build-silgen-test-overlays-ios',
+                                '%target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -enable-objc-interop -o %t %S/Inputs/UIKit.swift'))
diff --git a/test/SILGen/objc_attr_NSManaged.swift b/test/SILGen/objc_attr_NSManaged.swift
index e1c7556..dbb4f7c 100644
--- a/test/SILGen/objc_attr_NSManaged.swift
+++ b/test/SILGen/objc_attr_NSManaged.swift
@@ -119,16 +119,12 @@
 // CHECK-LABEL: sil_vtable SwiftGizmo {
 // CHECK-NEXT:   #SwiftGizmo.modifyX!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7modifyXyyF
 // CHECK-NEXT:   #SwiftGizmo.testFunc!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC8testFuncyyF
-// CHECK-NEXT:   #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoCACSgycfc
-// CHECK-NEXT:   #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnACSgSi_tcfc
 // CHECK-NEXT:   #SwiftGizmo.deinit!deallocator: @$S19objc_attr_NSManaged10SwiftGizmoCfD
 // CHECK-NEXT: }
 
 // CHECK-LABEL: sil_vtable FinalGizmo {
 // CHECK-NEXT:   #SwiftGizmo.modifyX!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7modifyX{{[_0-9a-zA-Z]*}}F
 // CHECK-NEXT:   #SwiftGizmo.testFunc!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC8testFunc{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT:   #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10FinalGizmoC{{[_0-9a-zA-Z]*}}fc
-// CHECK-NEXT:   #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10FinalGizmoC{{[_0-9a-zA-Z]*}}fc
 // CHECK-NEXT:   #FinalGizmo.deinit!deallocator: @$S19objc_attr_NSManaged10FinalGizmoCfD
 // CHECK-NEXT: }
 
diff --git a/test/SILGen/objc_implicitly_unwrapped_optional.swift b/test/SILGen/objc_implicitly_unwrapped_optional.swift
deleted file mode 100644
index 3e2eba1..0000000
--- a/test/SILGen/objc_implicitly_unwrapped_optional.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %target-swift-emit-sil(mock-sdk: %clang-importer-sdk) -enable-sil-ownership -assert-config Release %s | %FileCheck %s
-
-// REQUIRES: objc_interop
-
-import Foundation
-
-class C : Hive {}
-
-// CHECK-LABEL: sil private @$S34objc_implicitly_unwrapped_optional1DC5coderACSo7NSCoderC_tcfcAA1CCAdHSgAFSg_tcfcTV
-// CHECK: bb0(%0 : $Optional<NSCoder>, %1 : $D):
-// CHECK:   [[THUNK:%.*]] = function_ref @$S34objc_implicitly_unwrapped_optional1DC5coderACSo7NSCoderC_tcfc
-// CHECK:   [[REF:%.*]] = apply [[THUNK]]
-// CHECK:   [[RESULT:%.*]] = enum $Optional<D>, #Optional.some!enumelt.1, [[REF]] : $D
-// CHECK:   return [[RESULT]] : $Optional<D>
-class D : C {
-  override init(coder aCoder: NSCoder) {
-    super.init(coder: aCoder)
-  }
-}
diff --git a/test/SILGen/vtables_objc.swift b/test/SILGen/vtables_objc.swift
index ecc1f20..726b4d3 100644
--- a/test/SILGen/vtables_objc.swift
+++ b/test/SILGen/vtables_objc.swift
@@ -59,16 +59,12 @@
 // CHECK: sil_vtable Hoozit {
 // CHECK-NEXT:   #Hoozit.anse!1: {{.*}} : @$S12vtables_objc6HoozitC4anse{{[_0-9a-zA-Z]*}}F
 // CHECK-NEXT:   #Hoozit.incorrige!1: {{.*}} : @$S12vtables_objc6HoozitC9incorrige{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT:   #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit? : @$S12vtables_objc6HoozitCACSgycfc
-// CHECK-NEXT:   #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit? : @$S12vtables_objc6HoozitC7bellsOnACSgSi_tcfc
 // CHECK-NEXT:   #Hoozit.deinit!deallocator: @$S12vtables_objc6HoozitCfD
 // CHECK-NEXT: }
 
 // CHECK: sil_vtable Wotsit {
 // CHECK-NEXT:   #Hoozit.anse!1: {{.*}} : @$S12vtables_objc6HoozitC4anse{{[_0-9a-zA-Z]*}}F
 // CHECK-NEXT:   #Hoozit.incorrige!1: {{.*}} : @$S12vtables_objc6WotsitC9incorrige{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT:   #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit? : @$S12vtables_objc6WotsitCACSgycfc
-// CHECK-NEXT:   #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit? : @$S12vtables_objc6WotsitC7bellsOnACSgSi_tcfc
 // CHECK-NEXT:   #Wotsit.deinit!deallocator: @$S12vtables_objc6WotsitCfD
 // CHECK-NEXT: }
 
diff --git a/test/Sema/implicit_initializer_multi.swift b/test/Sema/implicit_initializer_multi.swift
index 6786111..b60ca5b 100644
--- a/test/Sema/implicit_initializer_multi.swift
+++ b/test/Sema/implicit_initializer_multi.swift
@@ -1,4 +1,5 @@
 // RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/implicit_initializer_multi_other.swift -verify
+// REQUIRES: objc_interop
 
 func test() {
   _ = DefaultInitializable()
diff --git a/test/attr/attr_dynamic.swift b/test/attr/attr_dynamic.swift
index a04a66e..963e784 100644
--- a/test/attr/attr_dynamic.swift
+++ b/test/attr/attr_dynamic.swift
@@ -12,20 +12,24 @@
 class Foo {
   @objc dynamic init() {}
   @objc dynamic init(x: NotObjCAble) {} // expected-error{{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}}
-
+  // expected-error@-1{{'dynamic' initializer 'init(x:)' must also be '@objc}}
+  
   @objc dynamic var x: Int
-
+  
   @objc dynamic var nonObjcVar: NotObjCAble // expected-error{{property cannot be marked @objc because its type cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}}
+  // expected-error@-1{{'dynamic' var 'nonObjcVar' must also be '@objc'}}
 
   @objc dynamic func foo(x: Int) {}
   @objc dynamic func bar(x: Int) {}
 
   @objc dynamic func nonObjcFunc(x: NotObjCAble) {} // expected-error{{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}}
-
+  // expected-error@-1{{'dynamic' instance method 'nonObjcFunc(x:)' must also be '@objc'}}
+  
   @objc dynamic subscript(x: Int) -> ObjCClass { get {} }
 
   @objc dynamic subscript(x: Int) -> NotObjCAble { get {} } // expected-error{{subscript cannot be marked @objc because its type cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}}
-
+  // expected-error@-1{{'dynamic' subscript 'subscript' must also be '@objc'}}
+  
   dynamic deinit {} // expected-error{{'dynamic' modifier cannot be applied to this declaration}} {{3-11=}}
 
   func notDynamic() {}
@@ -53,3 +57,9 @@
   // CHECK: {{^}} override func notDynamic()
   override func notDynamic() {}
 }
+
+// SR-5317
+@objcMembers
+class ObjCMemberCheck {
+  dynamic var s = NotObjCAble(c: Foo()) // expected-error{{'dynamic' var 's' must also be '@objc'}}
+}
diff --git a/test/attr/attr_dynamic_infer.swift b/test/attr/attr_dynamic_infer.swift
index 3264184..23cce63 100644
--- a/test/attr/attr_dynamic_infer.swift
+++ b/test/attr/attr_dynamic_infer.swift
@@ -1,4 +1,5 @@
 // RUN: %target-swift-ide-test -print-ast-typechecked -source-filename=%s -print-implicit-attrs -disable-objc-attr-requires-foundation-module | %FileCheck %s
+// REQUIRES: objc_interop
 
 @objc class Super {
   @objc dynamic func baseFoo() {}
@@ -36,17 +37,17 @@
 
   // CHECK: @objc override dynamic var prop: Super
   override var prop: Super {
-    // CHECK: @objc override dynamic get
+    // CHECK: @objc dynamic get
     get { return Super() }
-    // CHECK: @objc override dynamic set
+    // CHECK: @objc dynamic set
     set { }
   }
 
   // CHECK: @objc override dynamic subscript(sup: Super) -> Super
   override subscript(sup: Super) -> Super {
-    // CHECK: @objc override dynamic get
+    // CHECK: @objc dynamic get
     get { return sup }
-    // CHECK: @objc override dynamic set
+    // CHECK: @objc dynamic set
     set { }
   }
 
@@ -64,17 +65,17 @@
 
   // CHECK: @objc final var prop: Super
   @objc final var prop: Super {
-    // CHECK: @objc final get
+    // CHECK: final get
     get { return Super() }
-    // CHECK: @objc final set
+    // CHECK: final set
     set { }
   }
 
   // CHECK: @objc final subscript(sup: Super) -> Super
   @objc final subscript(sup: Super) -> Super {
-    // CHECK: @objc final get
+    // CHECK: final get
     get { return sup }
-    // CHECK: @objc final set
+    // CHECK: final set
     set { }
   }
 
diff --git a/test/attr/attr_ibaction.swift b/test/attr/attr_ibaction.swift
index 206f2df..b0d1651 100644
--- a/test/attr/attr_ibaction.swift
+++ b/test/attr/attr_ibaction.swift
@@ -75,21 +75,13 @@
 
   // Protocol types
   @IBAction func action7(_: P1) {} // expected-error{{argument to @IBAction method cannot have non-object type 'P1'}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
-  // expected-note@-2{{protocol-constrained type containing protocol 'P1' cannot be represented in Objective-C}}
   @IBAction func action8(_: CP1) {} // expected-error{{argument to @IBAction method cannot have non-object type 'CP1'}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
-  // expected-note@-2{{protocol-constrained type containing protocol 'CP1' cannot be represented in Objective-C}}
   @IBAction func action9(_: OP1) {}
   @IBAction func action10(_: P1?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action11(_: CP1?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action12(_: OP1?) {}
   @IBAction func action13(_: P1!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action14(_: CP1!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action15(_: OP1!) {}
 
   // Class metatype
@@ -104,27 +96,17 @@
 
   // Protocol types
   @IBAction func action21(_: P1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action22(_: CP1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action23(_: OP1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
   @IBAction func action24(_: P1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action25(_: CP1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action26(_: OP1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
   @IBAction func action27(_: P1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  //expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action28(_: CP1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  //expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
   @IBAction func action29(_: OP1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
 
   // Other bad cases
   @IBAction func action30(_: S) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
-  // expected-note@-2{{Swift structs cannot be represented in Objective-C}}
   @IBAction func action31(_: E) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
-  // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
-  // expected-note@-2{{non-'@objc' enums cannot be represented in Objective-C}}
   init() { }
 }
diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift
index 25c6ef2..5949bb0 100644
--- a/test/attr/attr_objc.swift
+++ b/test/attr/attr_objc.swift
@@ -1676,7 +1676,6 @@
 
   @IBAction func badAction(_ sender: PlainStruct?) { }
   // expected-error@-1{{argument to @IBAction method cannot have non-object type 'PlainStruct?'}}
-  // expected-error@-2{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
 }
 
 //===---
@@ -1716,6 +1715,7 @@
   var badManaged: PlainStruct
   // expected-error@-1 {{property cannot be marked @NSManaged because its type cannot be represented in Objective-C}}
   // expected-note@-2 {{Swift structs cannot be represented in Objective-C}}
+  // expected-error@-3{{'dynamic' var 'badManaged' must also be '@objc'}}
   // CHECK-LABEL: {{^}}  @NSManaged var badManaged: PlainStruct
 }
 
diff --git a/test/decl/class/circular_inheritance.swift b/test/decl/class/circular_inheritance.swift
index 8c6c9d3..8eca1c4 100644
--- a/test/decl/class/circular_inheritance.swift
+++ b/test/decl/class/circular_inheritance.swift
@@ -48,14 +48,10 @@
 
 // CHECK: ===CYCLE DETECTED===
 // CHECK-NEXT: `--{{.*}}SuperclassTypeRequest({{.*Left}}
-// CHECK-NEXT:      `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Left@
-// CHECK-NEXT:          `--{{.*}}AccessLevelRequest
-// CHECK-NEXT:          `--{{.*}}AccessLevelRequest
-// CHECK-NEXT:          `--{{.*}}SuperclassTypeRequest
-// CHECK-NEXT:              `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Right@
-// CHECK-NEXT:                  `--{{.*}}AccessLevelRequest{{.*}}
-// CHECK-NEXT:                  `--{{.*}}AccessLevelRequest{{.*}}
-// CHECK-NEXT:                  `--{{.*}}SuperclassTypeRequest{{.*(cyclic dependency)}}
+// CHECK:      `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Left@
+// CHECK:          `--{{.*}}SuperclassTypeRequest
+// CHECK:              `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Right@
+// CHECK:                  `--{{.*}}SuperclassTypeRequest{{.*(cyclic dependency)}}
 
 // CHECK-DOT: digraph Dependencies
 // CHECK-DOT: label="InheritedTypeRequest
diff --git a/test/decl/objc_override_multi.swift b/test/decl/objc_override_multi.swift
index b0eb7e1..deab0cd 100644
--- a/test/decl/objc_override_multi.swift
+++ b/test/decl/objc_override_multi.swift
@@ -4,5 +4,11 @@
 
 class SubSub1 : Sub1 {
   @objc func a() { } // expected-error{{method 'a()' with Objective-C selector 'a' conflicts with method 'f()' from superclass 'Super1' with the same Objective-C selector}}
+
+  func test() {
+    // Needed to force enough checking of Super1.f() to record its
+    // Objective-C selector.
+    f()
+  }
 }
 
diff --git a/test/decl/var/NSManaged_properties.swift b/test/decl/var/NSManaged_properties.swift
index 82961ba..553a027 100644
--- a/test/decl/var/NSManaged_properties.swift
+++ b/test/decl/var/NSManaged_properties.swift
@@ -38,6 +38,7 @@
 
   // expected-error@+1{{property cannot be marked @NSManaged because its type cannot be represented in Objective-C}}
   @NSManaged var nonobjc_var: SwiftProto?
+  // expected-error@-1{{'dynamic' var 'nonobjc_var' must also be '@objc'}}
 
   // expected-error@+4 {{@NSManaged only allowed on an instance property or method}}
   // expected-error@+3 {{@NSManaged property cannot have an initial value}}
diff --git a/validation-test/Sema/OverridesAndOverloads.swift b/validation-test/Sema/OverridesAndOverloads.swift
index bb32680..d615864 100644
--- a/validation-test/Sema/OverridesAndOverloads.swift
+++ b/validation-test/Sema/OverridesAndOverloads.swift
@@ -328,8 +328,7 @@
   }
 
   Base().foo(C1());     expectEqual("foo(C1)", which)
-  Base().foo(Token1()); expectEqual("foo(T)", which)
-  Base().foo(Token1() as Any); expectEqual("foo(Any)", which)
+  Base().foo(Token1()); expectEqual("foo(Any)", which)
 
   Base().bar(C1());     expectEqual("bar(C1)", which)
   Base().bar(Token1()); expectEqual("bar(T)", which)
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar33688063.swift b/validation-test/Sema/type_checker_perf/slow/rdar33688063.swift
index f4003c6..2c13ac1 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar33688063.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar33688063.swift
@@ -1,5 +1,5 @@
 // RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1 -swift-version 4
 // REQUIRES: tools-release,no_asserts
 
-let _ = 1 | UInt32(0) << 0 | UInt32(1) << 1 | UInt32(2) << 2
+let _ = 1 | UInt32(0) << 0 | UInt32(1) << 1 | UInt32(2) << 2 | UInt32(3) << 3 | UInt32(4) << 4
 // expected-error@-1 {{reasonable time}}
diff --git a/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift b/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift
index 0723703..fe2ed7e 100644
--- a/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift
+++ b/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift
@@ -9,7 +9,7 @@
 }
 extension Box where Representation == Repr, T == Representation.RawEnum {
     init(rawEnumValue: Representation.RawEnum) {
-        let _: Int.Type = T.self // expected-error {{cannot convert value of type '().Type' to specified type 'Int.Type'}}
+        let _: ().Type = T.self
         fatalError()
     }
 }