Merge pull request #13939 from davezarzycki/declnode_declctxt_cleanup

diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index bfdd042..6747434 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -58,6 +58,7 @@
   class LiteralExpr;
   class BraceStmt;
   class DeclAttributes;
+  class GenericContext;
   class GenericSignature;
   class GenericTypeParamDecl;
   class GenericTypeParamType;
@@ -847,6 +848,9 @@
     return getClangNodeImpl().getAsMacro();
   }
 
+  /// \brief Return the GenericContext if the Decl has one.
+  const GenericContext *getAsGenericContext() const;
+
   bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const;
 
   /// Whether this declaration is weak-imported.
@@ -6200,6 +6204,9 @@
   Identifier getName() const { return name; }
   
   static bool classof(const Decl *D) {
+    // Workaround: http://llvm.org/PR35906
+    if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl)
+      return D->getKind() >= DeclKind::First_OperatorDecl;
     return D->getKind() >= DeclKind::First_OperatorDecl
         && D->getKind() <= DeclKind::Last_OperatorDecl;
   }
@@ -6480,6 +6487,41 @@
 inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d)
   : Depth(d->getDepth()), Index(d->getIndex()) { }
 
+inline const GenericContext *Decl::getAsGenericContext() const {
+  switch (getKind()) {
+  default: return nullptr;
+#define DECL(Id, Parent) // See previous line
+#define GENERIC_DECL(Id, Parent) \
+  case DeclKind::Id: \
+    return static_cast<const Id##Decl*>(this);
+#include "swift/AST/DeclNodes.def"
+  }
+}
+
+inline bool DeclContext::classof(const Decl *D) {
+  switch (D->getKind()) { //
+  default: return false;
+#define DECL(ID, PARENT) // See previous line
+#define CONTEXT_DECL(ID, PARENT) \
+  case DeclKind::ID: return true;
+#include "swift/AST/DeclNodes.def"
+  }
+}
+
+inline DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) {
+  // XXX -- ModuleDecl is not defined in Decl.h, but because DeclContexts
+  // preface decls in memory, any DeclContext type will due.
+  const DeclContext *DC = static_cast<const ExtensionDecl*>(D);
+  switch (D->getKind()) {
+  default: llvm_unreachable("Not a DeclContext");
+#define DECL(ID, PARENT) // See previous line
+#define CONTEXT_DECL(ID, PARENT) \
+  case DeclKind::ID:
+#include "swift/AST/DeclNodes.def"
+    return const_cast<DeclContext *>(DC);
+  }
+}
+
 } // end namespace swift
 
 #endif
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index 688bf93..9c2c3bd 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -208,6 +208,7 @@
   template<class A, class B, class C>
   friend struct ::llvm::cast_convert_val;
   
+  // See swift/AST/Decl.h
   static DeclContext *castDeclToDeclContext(const Decl *D);
 
   /// If this DeclContext is a GenericType declaration or an
@@ -235,6 +236,7 @@
     llvm_unreachable("Unhandled DeclContextKind");
   }
 
+public:
   Decl *getAsDeclOrDeclExtensionContext() {
     return ParentAndKind.getInt() == ASTHierarchy::Decl ?
       reinterpret_cast<Decl*>(this + 1) : nullptr;
@@ -243,7 +245,6 @@
     return const_cast<DeclContext*>(this)->getAsDeclOrDeclExtensionContext();
   }
 
-public:
   DeclContext(DeclContextKind Kind, DeclContext *Parent)
       : ParentAndKind(Parent, getASTHierarchyFromKind(Kind)) {
     if (Kind != DeclContextKind::Module)
@@ -554,7 +555,7 @@
   void *operator new(size_t Bytes, ASTContext &C,
                      unsigned Alignment = alignof(DeclContext));
   
-  // Some Decls are DeclContexts, but not all.
+  // Some Decls are DeclContexts, but not all. See swift/AST/Decl.h
   static bool classof(const Decl *D);
 };
 
diff --git a/include/swift/AST/DeclNodes.def b/include/swift/AST/DeclNodes.def
index a22de9b..6ebbc98 100644
--- a/include/swift/AST/DeclNodes.def
+++ b/include/swift/AST/DeclNodes.def
@@ -38,25 +38,68 @@
 #define CONTEXT_DECL(Id, Parent) DECL(Id, Parent)
 #endif
 
-/// VALUE_DECL(Id, Parent)
-///   Used for subclasses of ValueDecl.  The default behavior is to do
-///   the same as for Decl.
-#ifndef VALUE_DECL
-#define VALUE_DECL(Id, Parent) DECL(Id, Parent)
+/// ITERABLE_NONGENERIC_DECL(Id, Parent)
+///   Used for Decls that are also IterableDeclContexts and DeclContexts. The
+///   default behavior is to do the same as for CONTEXT_DECL. This combination
+///   does not exist at the moment.
+#ifndef ITERABLE_NONGENERIC_DECL
+#ifdef ITERABLE_DECL
+#define ITERABLE_NONGENERIC_DECL(Id, Parent) ITERABLE_DECL(Id, Parent)
+#else
+#define ITERABLE_NONGENERIC_DECL(Id, Parent) CONTEXT_DECL(Id, Parent)
+#endif
+#endif
+
+/// GENERIC_DECL(Id, Parent)
+///   Used for Decls that are also GenericContexts. The default behavior is to
+///   do the same as for CONTEXT_DECL.
+#ifndef GENERIC_DECL
+#define GENERIC_DECL(Id, Parent) CONTEXT_DECL(Id, Parent)
+#endif
+
+/// ITERABLE_GENERIC_DECL(Id, Parent)
+///   Used for Decls that are also IterableDeclContexts and GenericContexts. The
+///   default behavior is to do the same as for GENERIC_DECL.
+#ifndef ITERABLE_GENERIC_DECL
+#ifdef ITERABLE_DECL
+#define ITERABLE_GENERIC_DECL(Id, Parent) ITERABLE_DECL(Id, Parent)
+#else
+#define ITERABLE_GENERIC_DECL(Id, Parent) GENERIC_DECL(Id, Parent)
+#endif
 #endif
 
 /// CONTEXT_VALUE_DECL(Id, Parent)
 ///   Used for subclasses of ValueDecl that are also DeclContexts. The default
-///   behavior is to do the same as for ValueDecl.
+///   behavior is to do the same as for CONTEXT_DECL.
 #ifndef CONTEXT_VALUE_DECL
+#ifdef VALUE_DECL
 #define CONTEXT_VALUE_DECL(Id, Parent) VALUE_DECL(Id, Parent)
+#else
+#define CONTEXT_VALUE_DECL(Id, Parent) CONTEXT_DECL(Id, Parent)
+#endif
 #endif
 
-/// FUNCTION_DECL(Id, Parent)
-///   Used for subclasses of AbstractFunctionDecl. The default behavior is to do
-///   the same as for CONTEXT_VALUE_DECL.
-#ifndef FUNCTION_DECL
-#define FUNCTION_DECL(Id, Parent) CONTEXT_VALUE_DECL(Id, Parent)
+/// GENERIC_VALUE_DECL(Id, Parent)
+///   Used for subclasses of ValueDecl that are also GenericContexts. The
+///   default behavior is to do the same as for GENERIC_DECL.
+#ifndef GENERIC_VALUE_DECL
+#ifdef VALUE_DECL
+#define GENERIC_VALUE_DECL(Id, Parent) VALUE_DECL(Id, Parent)
+#else
+#define GENERIC_VALUE_DECL(Id, Parent) GENERIC_DECL(Id, Parent)
+#endif
+#endif
+
+/// ITERABLE_GENERIC_VALUE_DECL(Id, Parent)
+///   Used for subclasses of ValueDecl that are also IterableDeclContexts and
+///   GenericContexts. The default behavior is to do the same as for
+///   ITERABLE_GENERIC_DECL.
+#ifndef ITERABLE_GENERIC_VALUE_DECL
+#ifdef VALUE_DECL
+#define ITERABLE_GENERIC_VALUE_DECL(Id, Parent) VALUE_DECL(Id, Parent)
+#else
+#define ITERABLE_GENERIC_VALUE_DECL(Id, Parent) ITERABLE_GENERIC_DECL(Id,Parent)
+#endif
 #endif
 
 /// OPERATOR_DECL(Id, Parent)
@@ -68,16 +111,16 @@
 
 /// NOMINAL_TYPE_DECL(Id, Parent)
 ///   Used for subclasses of NominalTypeDecl.  The default behavior is
-///   to do the same as for CONTEXT_VALUE_DECL.
+///   to do the same as for ITERABLE_GENERIC_VALUE_DECL.
 #ifndef NOMINAL_TYPE_DECL
-#define NOMINAL_TYPE_DECL(Id, Parent) CONTEXT_VALUE_DECL(Id, Parent)
+#define NOMINAL_TYPE_DECL(Id, Parent) ITERABLE_GENERIC_VALUE_DECL(Id, Parent)
 #endif
 
-/// EXTENSION_DECL(Id, Parent)
-///   Used for subclasses of ExtensionDecl.  The default behavior is
-///   to do the same as for CONTEXT_DECL.
-#ifndef EXTENSION_DECL
-#define EXTENSION_DECL(Id, Parent) CONTEXT_DECL(Id, Parent)
+/// VALUE_DECL(Id, Parent)
+///   Used for subclasses of ValueDecl.  The default behavior is to do
+///   the same as for Decl.
+#ifndef VALUE_DECL
+#define VALUE_DECL(Id, Parent) DECL(Id, Parent)
 #endif
 
 /// A convenience for determining the range of declarations.  These will always
@@ -90,14 +133,48 @@
 #define LAST_DECL(Id)
 #endif
 
-DECL(Import, Decl)
-EXTENSION_DECL(Extension, Decl)
-DECL(PatternBinding, Decl)
-DECL(EnumCase, Decl)
+// NOTE: For performance, maximize the numer of [important] abstract Decls
+// where "First_XYZDecl" == 0 to improve isa/dyn_cast code gen.
+
+ABSTRACT_DECL(Value, Decl)
+  ABSTRACT_DECL(Type, ValueDecl)
+    ABSTRACT_DECL(GenericType, TypeDecl)
+      ABSTRACT_DECL(NominalType, GenericTypeDecl)
+        NOMINAL_TYPE_DECL(Enum, NominalTypeDecl)
+        NOMINAL_TYPE_DECL(Struct, NominalTypeDecl)
+        NOMINAL_TYPE_DECL(Class, NominalTypeDecl)
+        NOMINAL_TYPE_DECL(Protocol, NominalTypeDecl)
+        DECL_RANGE(NominalType, Enum, Protocol)
+      GENERIC_VALUE_DECL(TypeAlias, GenericTypeDecl)
+      DECL_RANGE(GenericType, Enum, TypeAlias)
+    ABSTRACT_DECL(AbstractTypeParam, TypeDecl)
+      VALUE_DECL(GenericTypeParam, AbstractTypeParamDecl)
+      VALUE_DECL(AssociatedType, AbstractTypeParamDecl)
+      DECL_RANGE(AbstractTypeParam, GenericTypeParam, AssociatedType)
+    CONTEXT_VALUE_DECL(Module, TypeDecl)
+    DECL_RANGE(Type, Enum, Module)
+  ABSTRACT_DECL(AbstractStorage, ValueDecl)
+    VALUE_DECL(Var, AbstractStorageDecl)
+      VALUE_DECL(Param, VarDecl)
+    GENERIC_VALUE_DECL(Subscript, AbstractStorageDecl)
+    DECL_RANGE(AbstractStorage, Var, Subscript)
+  ABSTRACT_DECL(AbstractFunction, ValueDecl)
+    GENERIC_VALUE_DECL(Constructor, AbstractFunctionDecl)
+    GENERIC_VALUE_DECL(Destructor, AbstractFunctionDecl)
+    GENERIC_VALUE_DECL(Func, AbstractFunctionDecl)
+      GENERIC_VALUE_DECL(Accessor, FuncDecl)
+    DECL_RANGE(AbstractFunction, Constructor, Accessor)
+  VALUE_DECL(EnumElement, ValueDecl)
+  DECL_RANGE(Value, Enum, EnumElement)
+
+ITERABLE_GENERIC_DECL(Extension, Decl)
 CONTEXT_DECL(TopLevelCode, Decl)
+DECL(Import, Decl)
 DECL(IfConfig, Decl)
 DECL(PrecedenceGroup, Decl)
 DECL(MissingMember, Decl)
+DECL(PatternBinding, Decl)
+DECL(EnumCase, Decl)
 
 ABSTRACT_DECL(Operator, Decl)
   OPERATOR_DECL(InfixOperator, OperatorDecl)
@@ -105,45 +182,19 @@
   OPERATOR_DECL(PostfixOperator, OperatorDecl)
   DECL_RANGE(Operator, InfixOperator, PostfixOperator)
 
-ABSTRACT_DECL(Value, Decl)
-  ABSTRACT_DECL(Type, ValueDecl)
-    ABSTRACT_DECL(AbstractTypeParam, TypeDecl)
-      VALUE_DECL(GenericTypeParam, AbstractTypeParamDecl)
-      VALUE_DECL(AssociatedType, AbstractTypeParamDecl)
-      DECL_RANGE(AbstractTypeParam, GenericTypeParam, AssociatedType)
-    ABSTRACT_DECL(GenericType, TypeDecl)
-      CONTEXT_VALUE_DECL(TypeAlias, GenericTypeDecl)
-      ABSTRACT_DECL(NominalType, GenericTypeDecl)
-        NOMINAL_TYPE_DECL(Enum, NominalTypeDecl)
-        NOMINAL_TYPE_DECL(Struct, NominalTypeDecl)
-        NOMINAL_TYPE_DECL(Class, NominalTypeDecl)
-        NOMINAL_TYPE_DECL(Protocol, NominalTypeDecl)
-        DECL_RANGE(NominalType, Enum, Protocol)
-      DECL_RANGE(GenericType, TypeAlias, Protocol)
-    CONTEXT_VALUE_DECL(Module, TypeDecl)
-    DECL_RANGE(Type, GenericTypeParam, Module)
-  ABSTRACT_DECL(AbstractStorage, ValueDecl)
-    VALUE_DECL(Var, AbstractStorageDecl)
-      VALUE_DECL(Param, VarDecl)
-    CONTEXT_VALUE_DECL(Subscript, AbstractStorageDecl)
-    DECL_RANGE(AbstractStorage, Var, Subscript)
-  ABSTRACT_DECL(AbstractFunction, ValueDecl)
-    FUNCTION_DECL(Constructor, AbstractFunctionDecl)
-    FUNCTION_DECL(Destructor, AbstractFunctionDecl)
-    FUNCTION_DECL(Func, AbstractFunctionDecl)
-      FUNCTION_DECL(Accessor, FuncDecl)
-    DECL_RANGE(AbstractFunction, Constructor, Accessor)
-  VALUE_DECL(EnumElement, ValueDecl)
-  DECL_RANGE(Value, GenericTypeParam, EnumElement)
-LAST_DECL(EnumElement)
+LAST_DECL(PostfixOperator)
 
 #undef NOMINAL_TYPE_DECL
+#undef CONTEXT_DECL
+#undef ITERABLE_NONGENERIC_DECL
+#undef GENERIC_DECL
+#undef ITERABLE_GENERIC_DECL
+#undef ITERABLE_DECL
+#undef CONTEXT_VALUE_DECL
+#undef GENERIC_VALUE_DECL
+#undef ITERABLE_GENERIC_VALUE_DECL
 #undef VALUE_DECL
 #undef DECL_RANGE
 #undef ABSTRACT_DECL
-#undef FUNCTION_DECL
-#undef CONTEXT_DECL
-#undef CONTEXT_VALUE_DECL
-#undef EXTENSION_DECL
 #undef DECL
 #undef LAST_DECL
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index f6bb709..6fa679e 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -1506,6 +1506,7 @@
   }
 
   static bool classof(const TypeBase *T) {
+    // Workaround: http://llvm.org/PR35906
     if (TypeKind::Last_Type == TypeKind::Last_SugarType)
       return T->getKind() >= TypeKind::First_SugarType;
     return T->getKind() >= TypeKind::First_SugarType &&
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index b1b6b58..dd6cca7 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -309,13 +309,6 @@
   return getDeclContext();
 }
 
-DeclContext *Decl::getDeclContextForModule() const {
-  if (auto module = dyn_cast<ModuleDecl>(this))
-    return const_cast<ModuleDecl *>(module);
-
-  return nullptr;
-}
-
 void Decl::setDeclContext(DeclContext *DC) { 
   Context = DC;
 }
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index 6f3b54e..703cc30 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -153,135 +153,52 @@
 }
 
 GenericParamList *DeclContext::getGenericParamsOfContext() const {
-  for (const DeclContext *dc = this; ; dc = dc->getParent()) {
-    switch (dc->getContextKind()) {
-    case DeclContextKind::Module:
-    case DeclContextKind::FileUnit:
-    case DeclContextKind::TopLevelCodeDecl:
-      return nullptr;
-
-    case DeclContextKind::SerializedLocal:
-    case DeclContextKind::Initializer:
-    case DeclContextKind::AbstractClosureExpr:
-      // Closures and initializers can't themselves be generic, but they
-      // can occur in generic contexts.
-      continue;
-
-    case DeclContextKind::SubscriptDecl:
-      if (auto GP = cast<SubscriptDecl>(dc)->getGenericParams())
-        return GP;
-      continue;
-
-    case DeclContextKind::AbstractFunctionDecl:
-      if (auto GP = cast<AbstractFunctionDecl>(dc)->getGenericParams())
-        return GP;
-      continue;
-
-    case DeclContextKind::GenericTypeDecl:
-      if (auto GP = cast<GenericTypeDecl>(dc)->getGenericParams())
-        return GP;
-      continue;
-
-    case DeclContextKind::ExtensionDecl:
-      // Extensions do not capture outer generic parameters.
-      return cast<ExtensionDecl>(dc)->getGenericParams();
+  auto dc = this;
+  do {
+    if (auto decl = dc->getAsDeclOrDeclExtensionContext()) {
+      if (auto GC = decl->getAsGenericContext()) {
+        auto GP = GC->getGenericParams();
+        // Extensions do not capture outer generic parameters.
+        if (GP != nullptr || isa<ExtensionDecl>(decl))
+          return GP;
+      }
     }
-    llvm_unreachable("bad DeclContextKind");
-  }
-  llvm_unreachable("unknown parent");
+  } while ((dc = dc->getParent()));
+
+  return nullptr;
 }
 
 GenericSignature *DeclContext::getGenericSignatureOfContext() const {
-  for (const DeclContext *dc = this; ; dc = dc->getParent()) {
-    switch (dc->getContextKind()) {
-    case DeclContextKind::Module:
-    case DeclContextKind::FileUnit:
-    case DeclContextKind::TopLevelCodeDecl:
-      return nullptr;
+  auto dc = this;
+  do {
+    if (auto decl = dc->getAsDeclOrDeclExtensionContext())
+      if (auto GC = decl->getAsGenericContext())
+        return GC->getGenericSignature();
+  } while ((dc = dc->getParent()));
 
-    case DeclContextKind::Initializer:
-    case DeclContextKind::SerializedLocal:
-    case DeclContextKind::AbstractClosureExpr:
-      // Closures and initializers can't themselves be generic, but they
-      // can occur in generic contexts.
-      continue;
-
-    case DeclContextKind::SubscriptDecl:
-      return cast<SubscriptDecl>(dc)->getGenericSignature();
-
-    case DeclContextKind::AbstractFunctionDecl:
-      return cast<AbstractFunctionDecl>(dc)->getGenericSignature();
-
-    case DeclContextKind::GenericTypeDecl:
-      return cast<GenericTypeDecl>(dc)->getGenericSignature();
-
-    case DeclContextKind::ExtensionDecl:
-      return cast<ExtensionDecl>(dc)->getGenericSignature();
-    }
-    llvm_unreachable("bad DeclContextKind");
-  }
+  return nullptr;
 }
 
 GenericEnvironment *DeclContext::getGenericEnvironmentOfContext() const {
-  for (const DeclContext *dc = this; ; dc = dc->getParent()) {
-    switch (dc->getContextKind()) {
-    case DeclContextKind::Module:
-    case DeclContextKind::FileUnit:
-    case DeclContextKind::TopLevelCodeDecl:
-      return nullptr;
+  auto dc = this;
+  do {
+    if (auto decl = dc->getAsDeclOrDeclExtensionContext())
+      if (auto GC = decl->getAsGenericContext())
+        return GC->getGenericEnvironment();
+  } while ((dc = dc->getParent()));
 
-    case DeclContextKind::Initializer:
-    case DeclContextKind::SerializedLocal:
-    case DeclContextKind::AbstractClosureExpr:
-      // Closures and initializers can't themselves be generic, but they
-      // can occur in generic contexts.
-      continue;
-
-    case DeclContextKind::SubscriptDecl:
-      return cast<SubscriptDecl>(dc)->getGenericEnvironment();
-
-    case DeclContextKind::AbstractFunctionDecl:
-      return cast<AbstractFunctionDecl>(dc)->getGenericEnvironment();
-
-    case DeclContextKind::GenericTypeDecl:
-      return cast<GenericTypeDecl>(dc)->getGenericEnvironment();
-
-    case DeclContextKind::ExtensionDecl:
-      return cast<ExtensionDecl>(dc)->getGenericEnvironment();
-    }
-    llvm_unreachable("bad DeclContextKind");
-  }
+  return nullptr;
 }
 
 bool DeclContext::contextHasLazyGenericEnvironment() const {
-  for (const DeclContext *dc = this; ; dc = dc->getParent()) {
-    switch (dc->getContextKind()) {
-    case DeclContextKind::Module:
-    case DeclContextKind::FileUnit:
-    case DeclContextKind::TopLevelCodeDecl:
-      return false;
+  auto dc = this;
+  do {
+    if (auto decl = dc->getAsDeclOrDeclExtensionContext())
+      if (auto GC = decl->getAsGenericContext())
+        return GC->hasLazyGenericEnvironment();
+  } while ((dc = dc->getParent()));
 
-    case DeclContextKind::Initializer:
-    case DeclContextKind::SerializedLocal:
-    case DeclContextKind::AbstractClosureExpr:
-      // Closures and initializers can't themselves be generic, but they
-      // can occur in generic contexts.
-      continue;
-
-    case DeclContextKind::SubscriptDecl:
-      return cast<SubscriptDecl>(dc)->hasLazyGenericEnvironment();
-
-    case DeclContextKind::AbstractFunctionDecl:
-      return cast<AbstractFunctionDecl>(dc)->hasLazyGenericEnvironment();
-
-    case DeclContextKind::GenericTypeDecl:
-      return cast<GenericTypeDecl>(dc)->hasLazyGenericEnvironment();
-
-    case DeclContextKind::ExtensionDecl:
-      return cast<ExtensionDecl>(dc)->hasLazyGenericEnvironment();
-    }
-    llvm_unreachable("bad DeclContextKind");
-  }
+  return false;
 }
 
 Type DeclContext::mapTypeIntoContext(Type type) const {
@@ -298,76 +215,40 @@
 }
 
 AbstractFunctionDecl *DeclContext::getInnermostMethodContext() {
-  DeclContext *result = this;
-  while (true) {
-    switch (result->getContextKind()) {
-    case DeclContextKind::AbstractClosureExpr:
-    case DeclContextKind::Initializer:
-    case DeclContextKind::SerializedLocal:
-      // Look through closures, initial values.
-      result = result->getParent();
-      continue;
-
-    case DeclContextKind::AbstractFunctionDecl: {
-      // If this function is a method, we found our result.
-      auto func = dyn_cast<AbstractFunctionDecl>(result);
+  auto dc = this;
+  do {
+    if (auto decl = dc->getAsDeclOrDeclExtensionContext()) {
+      auto func = dyn_cast<AbstractFunctionDecl>(decl);
+      // If we found a non-func decl, we're done.
+      if (func == nullptr)
+        return nullptr;
       if (func->getDeclContext()->isTypeContext())
         return func;
-
-      // This function isn't a method; look through it.
-      result = func->getDeclContext();
-      continue;
     }
+  } while ((dc = dc->getParent()));
 
-    case DeclContextKind::ExtensionDecl:
-    case DeclContextKind::FileUnit:
-    case DeclContextKind::Module:
-    case DeclContextKind::GenericTypeDecl:
-    case DeclContextKind::TopLevelCodeDecl:
-    case DeclContextKind::SubscriptDecl:
-      // Not in a method context.
-      return nullptr;
-    }
-  }
+  return nullptr;
 }
 
 bool DeclContext::isTypeContext() const {
-  return isa<NominalTypeDecl>(this) ||
-         getContextKind() == DeclContextKind::ExtensionDecl;
+  if (auto decl = getAsDeclOrDeclExtensionContext())
+    return isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl);
+  return false;
 }
 
 DeclContext *DeclContext::getInnermostTypeContext() {
-  DeclContext *Result = this;
-  while (true) {
-    switch (Result->getContextKind()) {
-    case DeclContextKind::AbstractClosureExpr:
-    case DeclContextKind::Initializer:
-    case DeclContextKind::TopLevelCodeDecl:
-    case DeclContextKind::AbstractFunctionDecl:
-    case DeclContextKind::SubscriptDecl:
-    case DeclContextKind::SerializedLocal:
-      Result = Result->getParent();
-      continue;
+  auto dc = this;
+  do {
+    if (auto decl = dc->getAsDeclOrDeclExtensionContext())
+      if (isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl))
+        return dc;
+  } while ((dc = dc->getParent()));
 
-    case DeclContextKind::Module:
-    case DeclContextKind::FileUnit:
-      return nullptr;
-
-    case DeclContextKind::GenericTypeDecl:
-      if (isa<TypeAliasDecl>(Result)) {
-        Result = Result->getParent();
-        continue;
-      }
-      return Result;
-
-    case DeclContextKind::ExtensionDecl:
-      return Result;
-    }
-  }
+  return nullptr;
 }
 
 Decl *DeclContext::getInnermostDeclarationDeclContext() {
-  DeclContext *DC = this;
+  auto DC = this;
   do {
     if (auto decl = DC->getAsDeclOrDeclExtensionContext())
       return isa<ModuleDecl>(decl) ? nullptr : decl;
@@ -674,32 +555,6 @@
   return ctx.SourceMgr.getLineAndColumn(loc).first;
 }
 
-bool DeclContext::classof(const Decl *D) {
-  switch (D->getKind()) { //
-#define DECL(ID, PARENT)               case DeclKind::ID: return false;
-#define CONTEXT_DECL(ID, PARENT)       case DeclKind::ID: return true;
-#define CONTEXT_VALUE_DECL(ID, PARENT) case DeclKind::ID: return true;
-#include "swift/AST/DeclNodes.def"
-  }
-
-  llvm_unreachable("Unhandled DeclKind in switch.");
-}
-
-DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) {
-  switch (D->getKind()) {
-#define DECL(ID, PARENT) \
-  case DeclKind::ID: llvm_unreachable("not a decl context");
-#define CONTEXT_DECL(ID, PARENT) \
-  case DeclKind::ID: \
-    return const_cast<DeclContext *>( \
-        static_cast<const DeclContext*>(cast<ID##Decl>(D)));
-#define CONTEXT_VALUE_DECL(ID, PARENT) CONTEXT_DECL(ID, PARENT)
-#include "swift/AST/DeclNodes.def"
-  }
-
-  llvm_unreachable("Unhandled DeclKind in switch.");
-}
-
 unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
   unsigned Depth = 0;
   if (auto *P = getParent())
@@ -957,32 +812,25 @@
 
 bool IterableDeclContext::classof(const Decl *D) {
   switch (D->getKind()) {
-#define DECL(ID, PARENT)              case DeclKind::ID: return false;
-#define NOMINAL_TYPE_DECL(ID, PARENT) case DeclKind::ID: return true;
-#define EXTENSION_DECL(ID, PARENT)    case DeclKind::ID: return true;
+  default: return false;
+#define DECL(ID, PARENT) // See previous line
+#define ITERABLE_DECL(ID, PARENT) \
+  case DeclKind::ID: return true;
 #include "swift/AST/DeclNodes.def"
   }
-
-  llvm_unreachable("Unhandled DeclKind in switch.");
 }
 
 IterableDeclContext *
 IterableDeclContext::castDeclToIterableDeclContext(const Decl *D) {
   switch (D->getKind()) {
-#define DECL(ID, PARENT) \
-  case DeclKind::ID: llvm_unreachable("not a decl context");
-#define NOMINAL_TYPE_DECL(ID, PARENT) \
-  case DeclKind::ID: \
-    return const_cast<IterableDeclContext *>( \
-        static_cast<const IterableDeclContext*>(cast<ID##Decl>(D)));
-#define EXTENSION_DECL(ID, PARENT) \
+  default: llvm_unreachable("Decl is not a IterableDeclContext.");
+#define DECL(ID, PARENT) // See previous line
+#define ITERABLE_DECL(ID, PARENT) \
   case DeclKind::ID: \
     return const_cast<IterableDeclContext *>( \
         static_cast<const IterableDeclContext*>(cast<ID##Decl>(D)));
 #include "swift/AST/DeclNodes.def"
   }
-
-  llvm_unreachable("Unhandled DeclKind in switch.");
 }
 
 /// Return the DeclContext to compare when checking private access in
@@ -1076,6 +924,13 @@
   return false;
 }
 
+DeclContext *Decl::getDeclContextForModule() const {
+  if (auto module = dyn_cast<ModuleDecl>(this))
+    return const_cast<ModuleDecl *>(module);
+
+  return nullptr;
+}
+
 DeclContextKind DeclContext::getContextKind() const {
   switch (ParentAndKind.getInt()) {
   case ASTHierarchy::Expr:
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index bd943a8..dc1f80e 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -406,31 +406,11 @@
   size_t oldSize = results.size();
   bool alreadyInPrivateContext = false;
 
-  switch (container->getContextKind()) {
-  case DeclContextKind::SerializedLocal:
-  case DeclContextKind::AbstractClosureExpr:
-  case DeclContextKind::Initializer:
-  case DeclContextKind::TopLevelCodeDecl:
-  case DeclContextKind::AbstractFunctionDecl:
-  case DeclContextKind::SubscriptDecl:
-    llvm_unreachable("This context does not support lookup.");
+  auto containerDecl = container->getAsDeclOrDeclExtensionContext();
+  // If FileUnit, then use FileUnit::lookupValue instead.
+  assert(containerDecl != nullptr && "This context does not support lookup.");
 
-  case DeclContextKind::FileUnit:
-    llvm_unreachable("Use FileUnit::lookupValue instead.");
-
-  case DeclContextKind::ExtensionDecl:
-    llvm_unreachable("Use ExtensionDecl::lookupDirect instead.");
-
-  case DeclContextKind::Module: {
-    assert(container == this);
-    this->lookupValue({}, name, NLKind::QualifiedLookup, results);
-    break;
-  }
-
-  case DeclContextKind::GenericTypeDecl: {
-    auto nominal = dyn_cast<NominalTypeDecl>(container);
-    if (!nominal) break;
-
+  if (auto nominal = dyn_cast<NominalTypeDecl>(containerDecl)) {
     auto lookupResults = nominal->lookupDirect(name);
 
     // Filter out declarations from other modules.
@@ -443,9 +423,12 @@
     auto AS = nominal->getFormalAccessScope();
     if (AS.isPrivate() || AS.isFileScope())
       alreadyInPrivateContext = true;
-
-    break;
-  }
+  } else if (isa<ModuleDecl>(containerDecl)) {
+    assert(container == this);
+    this->lookupValue({}, name, NLKind::QualifiedLookup, results);
+  } else if (!isa<GenericTypeDecl>(containerDecl)) {
+    // If ExtensionDecl, then use ExtensionDecl::lookupDirect instead.
+    llvm_unreachable("This context does not support lookup.");
   }
 
   // Filter by private-discriminator, or filter out private decls if there isn't
diff --git a/test/IDE/Inputs/foo_swift_module.printed.comments.txt b/test/IDE/Inputs/foo_swift_module.printed.comments.txt
index c5013e9..57da84b 100644
--- a/test/IDE/Inputs/foo_swift_module.printed.comments.txt
+++ b/test/IDE/Inputs/foo_swift_module.printed.comments.txt
@@ -1,16 +1,5 @@
 import SwiftOnoneSupport
 
-precedencegroup High {
-  associativity: left
-  higherThan: BitwiseShiftPrecedence
-}
-
-infix operator %%% : High
-
-postfix operator =->
-
-postfix operator =>
-
 func %%% (lhs: Int, rhs: Int) -> Int
 
 postfix func =-> (lhs: Int) -> Int
@@ -64,3 +53,14 @@
 
 func visibleImport()
 
+precedencegroup High {
+  associativity: left
+  higherThan: BitwiseShiftPrecedence
+}
+
+infix operator %%% : High
+
+postfix operator =->
+
+postfix operator =>
+
diff --git a/test/Serialization/Recovery/typedefs.swift b/test/Serialization/Recovery/typedefs.swift
index 42e4d36..3e03146 100644
--- a/test/Serialization/Recovery/typedefs.swift
+++ b/test/Serialization/Recovery/typedefs.swift
@@ -91,29 +91,6 @@
 
 prefix operator ***
 
-// CHECK-LABEL: extension WrappedInt : WrappedProto {
-// CHECK-NEXT: func wrappedMethod()
-// CHECK-NEXT: prefix static func *** (x: WrappedInt)
-// CHECK-NEXT: }
-// CHECK-RECOVERY-NEGATIVE-NOT: extension WrappedInt
-extension WrappedInt: WrappedProto {
-  public func wrappedMethod() {}
-  public static prefix func ***(x: WrappedInt) {}
-}
-// CHECK-LABEL: extension Int32 : UnwrappedProto {
-// CHECK-NEXT: func unwrappedMethod()
-// CHECK-NEXT: prefix static func *** (x: UnwrappedInt)
-// CHECK-NEXT: }
-// CHECK-RECOVERY-LABEL: extension Int32 : UnwrappedProto {
-// CHECK-RECOVERY-NEXT: func unwrappedMethod()
-// CHECK-RECOVERY-NEXT: prefix static func *** (x: Int32)
-// CHECK-RECOVERY-NEXT: }
-// CHECK-RECOVERY-NEGATIVE-NOT: extension UnwrappedInt
-extension UnwrappedInt: UnwrappedProto {
-  public func unwrappedMethod() {}
-  public static prefix func ***(x: UnwrappedInt) {}
-}
-
 // CHECK-LABEL: class User {
 // CHECK-RECOVERY-LABEL: class User {
 open class User {
@@ -397,4 +374,28 @@
 public typealias ConstrainedWrapped<T: HasAssoc> = T where T.Assoc == WrappedInt
 public typealias ConstrainedUnwrapped<T: HasAssoc> = T where T.Assoc == UnwrappedInt
 
+// CHECK-LABEL: extension Int32 : UnwrappedProto {
+// CHECK-NEXT: func unwrappedMethod()
+// CHECK-NEXT: prefix static func *** (x: UnwrappedInt)
+// CHECK-NEXT: }
+// CHECK-RECOVERY-LABEL: extension Int32 : UnwrappedProto {
+// CHECK-RECOVERY-NEXT: func unwrappedMethod()
+// CHECK-RECOVERY-NEXT: prefix static func *** (x: Int32)
+// CHECK-RECOVERY-NEXT: }
+// CHECK-RECOVERY-NEGATIVE-NOT: extension UnwrappedInt
+extension UnwrappedInt: UnwrappedProto {
+  public func unwrappedMethod() {}
+  public static prefix func ***(x: UnwrappedInt) {}
+}
+
+// CHECK-LABEL: extension WrappedInt : WrappedProto {
+// CHECK-NEXT: func wrappedMethod()
+// CHECK-NEXT: prefix static func *** (x: WrappedInt)
+// CHECK-NEXT: }
+// CHECK-RECOVERY-NEGATIVE-NOT: extension WrappedInt
+extension WrappedInt: WrappedProto {
+  public func wrappedMethod() {}
+  public static prefix func ***(x: WrappedInt) {}
+}
+
 #endif // TEST
diff --git a/test/Serialization/extension-of-typealias.swift b/test/Serialization/extension-of-typealias.swift
index 2b49bf0..265e87a 100644
--- a/test/Serialization/extension-of-typealias.swift
+++ b/test/Serialization/extension-of-typealias.swift
@@ -10,6 +10,9 @@
 
 public typealias Zahl = Int
 
+// CHECK: typealias List
+// CHECK: typealias Zahl
+
 // CHECK-LABEL: extension Int {
 extension Zahl {
   // CHECK-NEXT: addedMember()
@@ -30,9 +33,6 @@
   public func addedMemberInt() {}
 } // CHECK-NEXT: {{^}$}}
 
-// CHECK: typealias List
-// CHECK: typealias Zahl
-
 #else
 
 import Library