Merge pull request #12075 from apple/revert-12062-make-fewer-gsbs

Revert "Create fewer generic signature builders"
diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h
index b5c9da2..5a75c21 100644
--- a/include/swift/AST/ASTContext.h
+++ b/include/swift/AST/ASTContext.h
@@ -846,16 +846,6 @@
   /// not necessarily loaded.
   void getVisibleTopLevelClangModules(SmallVectorImpl<clang::Module*> &Modules) const;
 
-private:
-  /// Register the given generic signature builder to be used as the canonical
-  /// generic signature builder for the given signature, if we don't already
-  /// have one.
-  void registerGenericSignatureBuilder(GenericSignature *sig,
-                                       ModuleDecl &module,
-                                       GenericSignatureBuilder &&builder);
-  friend class GenericSignatureBuilder;
-
-public:
   /// Retrieve or create the stored generic signature builder for the given
   /// canonical generic signature and module.
   GenericSignatureBuilder *getOrCreateGenericSignatureBuilder(CanGenericSignature sig,
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index f9a2668..1727e84 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -4591,7 +4591,7 @@
   /// Clone constructor, allocates a new ParamDecl identical to the first.
   /// Intentionally not defined as a typical copy constructor to avoid
   /// accidental copies.
-  ParamDecl(ParamDecl *PD, bool withTypes);
+  ParamDecl(ParamDecl *PD);
   
   /// Retrieve the argument (API) name for this function parameter.
   Identifier getArgumentName() const { return ArgumentName; }
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index dd8db75..ddf8ebe 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -215,14 +215,6 @@
     /// a superclass requirement.
     bool isConformanceSatisfiedBySuperclass(ProtocolDecl *proto) const;
 
-    /// Lookup a nested type with the given name within this equivalence
-    /// class.
-    ///
-    /// \param otherConcreteTypes If non-null, will be filled in the all of the
-    /// concrete types we found (other than the result) with the same name.
-    TypeDecl *lookupNestedType(Identifier name,
-                               SmallVectorImpl<TypeDecl *> *otherConcreteTypes);
-
     /// Dump a debugging representation of this equivalence class.
     void dump(llvm::raw_ostream &out) const;
 
@@ -240,17 +232,6 @@
       /// anchor was cached.
       unsigned numMembers;
     } archetypeAnchorCache;
-
-    /// Describes a cached nested type.
-    struct CachedNestedType {
-      unsigned numConformancesPresent;
-      CanType superclassPresent;
-      llvm::TinyPtrVector<TypeDecl *> types;
-    };
-
-    /// Cached nested-type information, which contains the best declaration
-    /// for a given name.
-    llvm::SmallDenseMap<Identifier, CachedNestedType> nestedTypeNameCache;
   };
 
   friend class RequirementSource;
@@ -541,6 +522,9 @@
   /// \brief Add all of a generic signature's parameters and requirements.
   void addGenericSignature(GenericSignature *sig);
 
+  /// \brief Build the generic signature.
+  GenericSignature *getGenericSignature();
+
   /// Infer requirements from the given type, recursively.
   ///
   /// This routine infers requirements from a type that occurs within the
@@ -574,14 +558,11 @@
   /// \brief Finalize the set of requirements and compute the generic
   /// signature.
   ///
-  /// After this point, one cannot introduce new requirements, and the
-  /// generic signature builder no longer has valid state.
+  /// After this point, one cannot introduce new requirements.
   GenericSignature *computeGenericSignature(
-                      ModuleDecl &module,
                       SourceLoc loc,
-                      bool allowConcreteGenericParams = false) &&;
+                      bool allowConcreteGenericParams = false);
 
-private:
   /// Finalize the set of requirements, performing any remaining checking
   /// required before generating archetypes.
   ///
@@ -591,7 +572,6 @@
                 ArrayRef<GenericTypeParamType *> genericParams,
                 bool allowConcreteGenericParams=false);
 
-public:
   /// Process any delayed requirements that can be handled now.
   void processDelayedRequirements();
 
@@ -1495,12 +1475,6 @@
     return pa->parentOrBuilder.get<GenericSignatureBuilder *>();
   }
 
-  // Replace the generic signature builder.
-  void replaceBuilder(GenericSignatureBuilder *builder) {
-    assert(parentOrBuilder.is<GenericSignatureBuilder *>());
-    parentOrBuilder = builder;
-  }
-
   friend class GenericSignatureBuilder;
   friend class GenericSignature;
 
@@ -1516,12 +1490,6 @@
     return parentOrBuilder.dyn_cast<PotentialArchetype *>();
   }
 
-  /// Retrieve the type declaration to which this nested type was resolved.
-  TypeDecl *getResolvedType() const {
-    assert(getParent() && "Not an associated type");
-    return identifier.assocTypeOrConcrete;
-  }
-
   /// Retrieve the associated type to which this potential archetype
   /// has been resolved.
   AssociatedTypeDecl *getResolvedAssociatedType() const {
@@ -1664,8 +1632,13 @@
                                     ArchetypeResolutionKind kind,
                                     GenericSignatureBuilder &builder);
 
-  /// \brief Retrieve (or create) a nested type with a known type.
-  PotentialArchetype *getNestedType(TypeDecl *type,
+  /// \brief Retrieve (or create) a nested type with a known associated type.
+  PotentialArchetype *getNestedType(AssociatedTypeDecl *assocType,
+                                    GenericSignatureBuilder &builder);
+
+  /// \brief Retrieve (or create) a nested type with a known concrete type
+  /// declaration.
+  PotentialArchetype *getNestedType(TypeDecl *concreteDecl,
                                     GenericSignatureBuilder &builder);
 
   /// \brief Retrieve (or create) a nested type that is the current best
@@ -1685,8 +1658,8 @@
   /// type or typealias of the given protocol, unless the \c kind implies that
   /// a potential archetype should not be created if it's missing.
   PotentialArchetype *updateNestedTypeForConformance(
-                        TypeDecl *type,
-                        ArchetypeResolutionKind kind);
+                      PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
+                      ArchetypeResolutionKind kind);
 
   /// Update the named nested type when we know this type conforms to the given
   /// protocol.
diff --git a/include/swift/AST/ParameterList.h b/include/swift/AST/ParameterList.h
index 09c275b..6238d1c 100644
--- a/include/swift/AST/ParameterList.h
+++ b/include/swift/AST/ParameterList.h
@@ -128,15 +128,9 @@
     Implicit = 0x01,
     /// The cloned pattern is for an inherited constructor; mark default
     /// arguments as inherited, and mark unnamed arguments as named.
-    Inherited = 0x02,
-    /// The cloned pattern will strip type information.
-    WithoutTypes = 0x04,
+    Inherited = 0x02
   };
-
-  friend OptionSet<CloneFlags> operator|(CloneFlags flag1, CloneFlags flag2) {
-    return OptionSet<CloneFlags>(flag1) | flag2;
-  }
-
+  
   /// Make a duplicate copy of this parameter list.  This allocates copies of
   /// the ParamDecls, so they can be reparented into a new DeclContext.
   ParameterList *clone(const ASTContext &C,
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index dd159c0..7917da8 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -43,7 +43,6 @@
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/Allocator.h"
@@ -53,12 +52,6 @@
 
 using namespace swift;
 
-#define DEBUG_TYPE "ASTContext"
-STATISTIC(NumRegisteredGenericSignatureBuilders,
-          "# of generic signature builders successfully registered");
-STATISTIC(NumRegisteredGenericSignatureBuildersAlready,
-          "# of generic signature builders already registered");
-
 /// Define this to 1 to enable expensive assertions of the
 /// GenericSignatureBuilder.
 #define SWIFT_GSB_EXPENSIVE_ASSERTIONS 0
@@ -1430,22 +1423,6 @@
     collectAllModules(Modules);
 }
 
-void ASTContext::registerGenericSignatureBuilder(
-                                       GenericSignature *sig,
-                                       ModuleDecl &module,
-                                       GenericSignatureBuilder &&builder) {
-  auto canSig = sig->getCanonicalSignature();
-  auto known = Impl.GenericSignatureBuilders.find({canSig, &module});
-  if (known != Impl.GenericSignatureBuilders.end()) {
-    ++NumRegisteredGenericSignatureBuildersAlready;
-    return;
-  }
-
-  ++NumRegisteredGenericSignatureBuilders;
-  Impl.GenericSignatureBuilders[{canSig, &module}] =
-    llvm::make_unique<GenericSignatureBuilder>(std::move(builder));
-}
-
 GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
                                                       CanGenericSignature sig,
                                                       ModuleDecl *mod) {
@@ -4614,7 +4591,7 @@
     GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
   builder.addRequirement(requirement, source, nullptr);
 
-  CanGenericSignature genericSig(std::move(builder).computeGenericSignature(*mod, SourceLoc()));
+  CanGenericSignature genericSig(builder.computeGenericSignature(SourceLoc()));
 
   auto result = Impl.ExistentialSignatures.insert(
     std::make_pair(existential, genericSig));
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index f55762c..a7c473a 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -491,9 +491,7 @@
         Builder.addGenericParameter(gp);
       }
 
-      auto GenericSig =
-        std::move(Builder).computeGenericSignature(*ctx.TheBuiltinModule,
-                                                   SourceLoc());
+      auto GenericSig = Builder.computeGenericSignature(SourceLoc());
       GenericEnv = GenericSig->createGenericEnvironment(*ctx.TheBuiltinModule);
     }
 
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 65d720a..7bd97a1 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3419,8 +3419,7 @@
          nullptr);
 
   // Compute and record the signature.
-  auto requirementSig =
-    std::move(builder).computeGenericSignature(*module, SourceLoc());
+  auto requirementSig = builder.computeGenericSignature(SourceLoc());
   RequirementSignature = requirementSig->getRequirements().data();
   assert(RequirementSignature != nullptr);
   NumRequirementsInSignature = requirementSig->getRequirements().size();
@@ -4218,11 +4217,10 @@
 
 /// Clone constructor, allocates a new ParamDecl identical to the first.
 /// Intentionally not defined as a copy constructor to avoid accidental copies.
-ParamDecl::ParamDecl(ParamDecl *PD, bool withTypes)
+ParamDecl::ParamDecl(ParamDecl *PD)
   : VarDecl(DeclKind::Param, /*IsStatic*/false, PD->getSpecifier(),
             /*IsCaptureList*/false, PD->getNameLoc(), PD->getName(),
-            PD->hasType() && withTypes? PD->getType() : Type(),
-            PD->getDeclContext()),
+            PD->hasType() ? PD->getType() : Type(), PD->getDeclContext()),
     ArgumentName(PD->getArgumentName()),
     ArgumentNameLoc(PD->getArgumentNameLoc()),
     SpecifierLoc(PD->getSpecifierLoc()),
@@ -4230,10 +4228,7 @@
     IsTypeLocImplicit(PD->IsTypeLocImplicit),
     defaultArgumentKind(PD->defaultArgumentKind) {
   typeLoc = PD->getTypeLoc().clone(PD->getASTContext());
-  if (!withTypes && typeLoc.getTypeRepr())
-    typeLoc.setType(Type());
-
-  if (withTypes && PD->hasInterfaceType())
+  if (PD->hasInterfaceType())
     setInterfaceType(PD->getInterfaceType());
 }
 
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 3177d3d..f0b85ea 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -76,10 +76,6 @@
           "# of hits in the archetype anchor cache");
 STATISTIC(NumArchetypeAnchorCacheMisses,
           "# of misses in the archetype anchor cache");
-STATISTIC(NumNestedTypeCacheHits,
-         "# of hits in the equivalence class nested type cache");
-STATISTIC(NumNestedTypeCacheMisses,
-         "# of misses in the equivalence class nested type cache");
 STATISTIC(NumProcessDelayedRequirements,
           "# of times we process delayed requirements");
 STATISTIC(NumProcessDelayedRequirementsUnchanged,
@@ -118,12 +114,6 @@
   /// Whether we are currently processing delayed requirements.
   bool ProcessingDelayedRequirements = false;
 
-  /// Whether there were any errors.
-  bool HadAnyError = false;
-
-  /// FIXME: Hack to work around a small number of minimization bugs.
-  bool HadAnyRedundantConstraints = false;
-
 #ifndef NDEBUG
   /// Whether we've already finalized the builder.
   bool finalized = false;
@@ -1564,159 +1554,6 @@
   return false;
 }
 
-/// Compare two associated types.
-static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
-                                  AssociatedTypeDecl *assocType2) {
-  // - by name.
-  if (int result = assocType1->getName().str().compare(
-                                              assocType2->getName().str()))
-    return result;
-
-  // - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
-  auto proto1 = assocType1->getProtocol();
-  auto proto2 = assocType2->getProtocol();
-  if (int compareProtocols = ProtocolType::compareProtocols(&proto1, &proto2))
-    return compareProtocols;
-
-  // Error case: if we have two associated types with the same name in the
-  // same protocol, just tie-break based on address.
-  if (assocType1 != assocType2)
-    return assocType1 < assocType2 ? -1 : +1;
-
-  return 0;
-}
-
-TypeDecl *EquivalenceClass::lookupNestedType(
-                             Identifier name,
-                             SmallVectorImpl<TypeDecl *> *otherConcreteTypes) {
-  // Populates the result structures from the given cache entry.
-  auto populateResult = [&](const CachedNestedType &cache) -> TypeDecl * {
-    if (otherConcreteTypes)
-      otherConcreteTypes->clear();
-
-    // If there aren't any types in the cache, we're done.
-    if (cache.types.empty()) return nullptr;
-
-    // The first type in the cache is always the final result.
-    // Collect the rest in the concrete-declarations list, if needed.
-    if (otherConcreteTypes) {
-      for (auto type : ArrayRef<TypeDecl *>(cache.types).slice(1)) {
-        otherConcreteTypes->push_back(type);
-      }
-    }
-
-    return cache.types.front();
-  };
-
-  // If we have a cached value that is up-to-date, use that.
-  auto cached = nestedTypeNameCache.find(name);
-  if (cached != nestedTypeNameCache.end() &&
-      cached->second.numConformancesPresent == conformsTo.size() &&
-      (!superclass ||
-       cached->second.superclassPresent == superclass->getCanonicalType())) {
-    ++NumNestedTypeCacheHits;
-    return populateResult(cached->second);
-  }
-
-  // Cache miss; go compute the result.
-  ++NumNestedTypeCacheMisses;
-
-  // Look for types with the given name in protocols that we know about.
-  AssociatedTypeDecl *bestAssocType = nullptr;
-  SmallVector<TypeDecl *, 4> concreteDecls;
-  for (const auto &conforms : conformsTo) {
-    ProtocolDecl *proto = conforms.first;
-
-    // Look for an associated type and/or concrete type with this name.
-    for (auto member : proto->lookupDirect(name,
-                                           /*ignoreNewExtensions=*/true)) {
-      // If this is an associated type, record whether it is the best
-      // associated type we've seen thus far.
-      if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
-        if (!bestAssocType ||
-             compareAssociatedTypes(assocType, bestAssocType) < 0)
-          bestAssocType = assocType;
-
-        continue;
-      }
-
-      // If this is another type declaration, determine whether we should
-      // record it.
-      if (auto type = dyn_cast<TypeDecl>(member)) {
-        // FIXME: Filter out type declarations that aren't in the same
-        // module as the protocol itself. This is an unprincipled hack, but
-        // provides consistent lookup semantics for the generic signature
-        // builder in all contents.
-        if (type->getDeclContext()->getParentModule()
-              != proto->getParentModule())
-          continue;
-
-        // Resolve the signature of this type.
-        if (!type->hasInterfaceType()) {
-          type->getASTContext().getLazyResolver()->resolveDeclSignature(type);
-          if (!type->hasInterfaceType())
-            continue;
-        }
-
-        concreteDecls.push_back(type);
-        continue;
-      }
-    }
-  }
-
-  // If we haven't found anything yet but have a superclass, look for a type
-  // in the superclass.
-  // FIXME: Shouldn't we always look in the superclass?
-  if (!bestAssocType && concreteDecls.empty() && superclass) {
-    if (auto classDecl = superclass->getClassOrBoundGenericClass()) {
-      SmallVector<ValueDecl *, 2> superclassMembers;
-      classDecl->getParentModule()->lookupQualified(
-          superclass, name,
-          NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers, nullptr,
-          superclassMembers);
-      for (auto member : superclassMembers) {
-        if (auto type = dyn_cast<TypeDecl>(member)) {
-          // Resolve the signature of this type.
-          if (!type->hasInterfaceType()) {
-            type->getASTContext().getLazyResolver()->resolveDeclSignature(type);
-            if (!type->hasInterfaceType())
-              continue;
-          }
-
-          concreteDecls.push_back(type);
-        }
-      }
-    }
-  }
-
-  // Form the new cache entry.
-  CachedNestedType entry;
-  entry.numConformancesPresent = conformsTo.size();
-  entry.superclassPresent =
-    superclass ? superclass->getCanonicalType() : CanType();
-  if (bestAssocType) {
-    entry.types.push_back(bestAssocType);
-    entry.types.insert(entry.types.end(),
-                       concreteDecls.begin(), concreteDecls.end());
-  } else if (!concreteDecls.empty()) {
-    // Find the best concrete type.
-    auto bestConcreteTypeIter =
-      std::min_element(concreteDecls.begin(), concreteDecls.end(),
-                       [](TypeDecl *type1, TypeDecl *type2) {
-                         return TypeDecl::compare(type1, type2) < 0;
-                       });
-
-    // Put the best concrete type first; the rest will follow.
-    entry.types.push_back(*bestConcreteTypeIter);
-    entry.types.insert(entry.types.end(),
-                       concreteDecls.begin(), bestConcreteTypeIter);
-    entry.types.insert(entry.types.end(),
-                       bestConcreteTypeIter + 1, concreteDecls.end());
-  }
-
-  return populateResult((nestedTypeNameCache[name] = std::move(entry)));
-}
-
 void EquivalenceClass::dump(llvm::raw_ostream &out) const {
   out << "Equivalence class represented by "
     << members.front()->getRepresentative()->getDebugName() << ":\n";
@@ -1896,14 +1733,11 @@
                               ->castTo<ProtocolType>());
   if (!conformance) {
     if (!concrete->hasError() && concreteSource->getLoc().isValid()) {
-      Impl->HadAnyError = true;
-
       Diags.diagnose(concreteSource->getLoc(),
                      diag::requires_generic_param_same_type_does_not_conform,
                      concrete, proto->getName());
     }
 
-    Impl->HadAnyError = true;
     paEquivClass->invalidConcreteType = true;
     return nullptr;
   }
@@ -2127,6 +1961,28 @@
   return result;
 }
 
+/// Compare two associated types.
+static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
+                                  AssociatedTypeDecl *assocType2) {
+  // - by name.
+  if (int result = assocType1->getName().str().compare(
+                                              assocType2->getName().str()))
+    return result;
+
+  // - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
+  auto proto1 = assocType1->getProtocol();
+  auto proto2 = assocType2->getProtocol();
+  if (int compareProtocols = ProtocolType::compareProtocols(&proto1, &proto2))
+    return compareProtocols;
+
+  // Error case: if we have two associated types with the same name in the
+  // same protocol, just tie-break based on address.
+  if (assocType1 != assocType2)
+    return assocType1 < assocType2 ? -1 : +1;
+
+  return 0;
+}
+
 /// Whether there are any concrete type declarations in the potential archetype.
 static bool hasConcreteDecls(const PotentialArchetype *pa) {
   auto parent = pa->getParent();
@@ -2354,9 +2210,16 @@
 }
 
 PotentialArchetype *PotentialArchetype::getNestedType(
-                                            TypeDecl *type,
+                                            AssociatedTypeDecl *assocType,
                                             GenericSignatureBuilder &builder) {
-  return updateNestedTypeForConformance(type,
+  return updateNestedTypeForConformance(assocType,
+                                        ArchetypeResolutionKind::WellFormed);
+}
+
+PotentialArchetype *PotentialArchetype::getNestedType(
+                                            TypeDecl *getConcreteTypeDecl,
+                                            GenericSignatureBuilder &builder) {
+  return updateNestedTypeForConformance(getConcreteTypeDecl,
                                         ArchetypeResolutionKind::WellFormed);
 }
 
@@ -2364,21 +2227,94 @@
                                            Identifier name,
                                            GenericSignatureBuilder &builder,
                                            ArchetypeResolutionKind kind) {
+  // Look for the best associated type or concrete type within the protocols
+  // we know about.
+  AssociatedTypeDecl *bestAssocType = nullptr;
+  TypeDecl *bestConcreteDecl = nullptr;
   SmallVector<TypeDecl *, 4> concreteDecls;
-  auto bestType =
-    getOrCreateEquivalenceClass()->lookupNestedType(name, &concreteDecls);
+  auto rep = getRepresentative();
+  for (auto proto : rep->getConformsTo()) {
+    // Look for an associated type and/or concrete type with this name.
+    AssociatedTypeDecl *assocType = nullptr;
+    TypeDecl *concreteDecl = nullptr;
+    for (auto member : proto->lookupDirect(name,
+                                           /*ignoreNewExtensions=*/true)) {
+      if (!assocType)
+        assocType = dyn_cast<AssociatedTypeDecl>(member);
 
-  // We didn't find any type with this name.
-  if (!bestType) return nullptr;
+      // FIXME: Filter out type declarations that aren't in the protocol itself?
+      if (!concreteDecl && !isa<AssociatedTypeDecl>(member)) {
+        if (!member->hasInterfaceType())
+          builder.getLazyResolver()->resolveDeclSignature(member);
+        if (member->hasInterfaceType())
+          concreteDecl = dyn_cast<TypeDecl>(member);
+      }
+    }
 
-  // Resolve the nested type.
-  auto resultPA = updateNestedTypeForConformance(bestType, kind);
+    if (assocType &&
+        (!bestAssocType ||
+         compareAssociatedTypes(assocType, bestAssocType) < 0))
+      bestAssocType = assocType;
+
+    if (concreteDecl) {
+      // Record every concrete type.
+      concreteDecls.push_back(concreteDecl);
+
+      // Track the best concrete type.
+      if (!bestConcreteDecl ||
+          TypeDecl::compare(concreteDecl, bestConcreteDecl) < 0)
+        bestConcreteDecl = concreteDecl;
+    }
+  }
+
+  // If we found an associated type, use it.
+  PotentialArchetype *resultPA = nullptr;
+  if (bestAssocType) {
+    resultPA = updateNestedTypeForConformance(bestAssocType, kind);
+  }
+
+  // If we have an associated type, drop any concrete decls that aren't in
+  // the same module as the protocol.
+  // FIXME: This is an unprincipled hack for an unprincipled feature.
+  concreteDecls.erase(
+    std::remove_if(concreteDecls.begin(), concreteDecls.end(),
+                   [&](TypeDecl *concreteDecl) {
+      return concreteDecl->getDeclContext()->getParentModule() !=
+        concreteDecl->getDeclContext()
+          ->getAsNominalTypeOrNominalTypeExtensionContext()->getParentModule();
+    }),
+    concreteDecls.end());
+
+  // If we haven't found anything yet but have a superclass, look for a type
+  // in the superclass.
+  if (!resultPA && concreteDecls.empty()) {
+    if (auto superclass = getSuperclass()) {
+      if (auto classDecl = superclass->getClassOrBoundGenericClass()) {
+        SmallVector<ValueDecl *, 2> superclassMembers;
+        classDecl->getParentModule()->lookupQualified(superclass, name, NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers, nullptr,
+            superclassMembers);
+        for (auto member : superclassMembers) {
+          if (auto concreteDecl = dyn_cast<TypeDecl>(member)) {
+            // Track the best concrete type.
+            if (!bestConcreteDecl ||
+                TypeDecl::compare(concreteDecl, bestConcreteDecl) < 0)
+              bestConcreteDecl = concreteDecl;
+
+            concreteDecls.push_back(concreteDecl);
+          }
+        }
+      }
+    }
+  }
 
   // Update for all of the concrete decls with this name, which will introduce
   // various same-type constraints.
   for (auto concreteDecl : concreteDecls) {
-    (void)updateNestedTypeForConformance(concreteDecl,
-                                         ArchetypeResolutionKind::WellFormed);
+    auto concreteDeclPA = updateNestedTypeForConformance(
+                                      concreteDecl,
+                                      ArchetypeResolutionKind::WellFormed);
+    if (!resultPA && concreteDecl == bestConcreteDecl)
+      resultPA = concreteDeclPA;
   }
 
   return resultPA;
@@ -2389,22 +2325,43 @@
                                                  Identifier name,
                                                  ProtocolDecl *proto,
                                                  ArchetypeResolutionKind kind) {
-  // Lookup the best type for this name.
-  auto bestType =
-    getOrCreateEquivalenceClass()->lookupNestedType(name, nullptr);
-  if (!bestType) return nullptr;
+  /// Determine whether there is an associated type or concrete type with this
+  /// name in this protocol. If not, there's nothing to do.
+  AssociatedTypeDecl *assocType = nullptr;
+  TypeDecl *concreteDecl = nullptr;
+  for (auto member : proto->lookupDirect(name, /*ignoreNewExtensions=*/true)) {
+    if (!assocType)
+      assocType = dyn_cast<AssociatedTypeDecl>(member);
 
-  // Form the potential archetype.
-  return updateNestedTypeForConformance(bestType, kind);
+    // FIXME: Filter out concrete types that aren't in the protocol itself?
+    if (!concreteDecl && !isa<AssociatedTypeDecl>(member)) {
+      if (!member->hasInterfaceType())
+        proto->getASTContext().getLazyResolver()->resolveDeclSignature(member);
+      if (member->hasInterfaceType())
+        concreteDecl = dyn_cast<TypeDecl>(member);
+    }
+  }
+
+  // There is no associated type or concrete type with this name in this
+  // protocol
+  if (!assocType && !concreteDecl)
+    return nullptr;
+
+  // If we had both an associated type and a concrete type, ignore the latter.
+  // This is for ill-formed code.
+  if (assocType)
+    return updateNestedTypeForConformance(assocType, kind);
+
+  return updateNestedTypeForConformance(concreteDecl, kind);
 }
 
 PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
-                                              TypeDecl *type,
-                                              ArchetypeResolutionKind kind) {
-  if (!type) return nullptr;
-
-  AssociatedTypeDecl *assocType = dyn_cast<AssociatedTypeDecl>(type);
-  TypeDecl *concreteDecl = assocType ? nullptr : type;
+                      PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
+                      ArchetypeResolutionKind kind) {
+  auto *assocType = type.dyn_cast<AssociatedTypeDecl *>();
+  auto *concreteDecl = type.dyn_cast<TypeDecl *>();
+  if (!assocType && !concreteDecl)
+    return nullptr;
 
   // If we were asked for a complete, well-formed archetype, make sure we
   // process delayed requirements if anything changed.
@@ -2865,23 +2822,7 @@
     Context.Stats->getFrontendCounters().NumGenericSignatureBuilders++;
 }
 
-GenericSignatureBuilder::GenericSignatureBuilder(
-                                         GenericSignatureBuilder &&other)
-  : Context(other.Context), Diags(other.Diags), Impl(std::move(other.Impl))
-{
-  other.Impl.reset();
-
-  if (Impl) {
-    // Update the generic parameters to their canonical types.
-    for (auto &gp : Impl->GenericParams) {
-      gp = gp->getCanonicalType()->castTo<GenericTypeParamType>();
-    }
-
-    // Point each root potential archetype at this generic signature builder.
-    for (auto pa : Impl->PotentialArchetypes)
-      pa->replaceBuilder(this);
-  }
-}
+GenericSignatureBuilder::GenericSignatureBuilder(GenericSignatureBuilder &&) = default;
 
 GenericSignatureBuilder::~GenericSignatureBuilder() {
   if (!Impl)
@@ -3431,8 +3372,6 @@
     // If a layout requirement was explicitly written on a concrete type,
     // complain.
     if (source.isExplicit() && source.getLoc().isValid()) {
-      Impl->HadAnyError = true;
-
       Diags.diagnose(source.getLoc(), diag::requires_not_suitable_archetype,
                      TypeLoc::withoutLoc(resolvedSubject->getType()));
       return ConstraintResult::Concrete;
@@ -3576,7 +3515,6 @@
         subjectType = subject.get<PotentialArchetype *>()
                         ->getDependentType(Impl->GenericParams);
 
-      Impl->HadAnyError = true;
       Diags.diagnose(source.getLoc(), diag::requires_conformance_nonprotocol,
                      TypeLoc::withoutLoc(subjectType),
                      TypeLoc::withoutLoc(constraintType));
@@ -3605,7 +3543,6 @@
     // One cannot explicitly write a constraint on a concrete type.
     if (source.isExplicit()) {
       if (source.getLoc().isValid()) {
-        Impl->HadAnyError = true;
         Diags.diagnose(source.getLoc(), diag::requires_not_suitable_archetype,
                        TypeLoc::withoutLoc(resolvedSubject->getType()));
       }
@@ -3696,8 +3633,13 @@
   auto parentRepPA = parentPA->getRepresentative();
   if (parentPA == parentRepPA) return;
 
-  PotentialArchetype *existingPA =
-    parentRepPA->getNestedType(nestedPA->getResolvedType(), *this);
+  PotentialArchetype *existingPA;
+  if (auto assocType = nestedPA->getResolvedAssociatedType()) {
+    existingPA = parentRepPA->getNestedType(assocType, *this);
+  } else {
+    existingPA = parentRepPA->getNestedType(nestedPA->getConcreteTypeDecl(),
+                                            *this);
+  }
 
   auto sameNamedSource =
     FloatingRequirementSource::forNestedTypeNameMatch(
@@ -3951,11 +3893,8 @@
                                  UnresolvedHandlingKind unresolvedHandling) {
   return addSameTypeRequirement(paOrT1, paOrT2, source, unresolvedHandling,
                                 [&](Type type1, Type type2) {
-      Impl->HadAnyError = true;
-      if (source.getLoc().isValid()) {
-        Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
-                       type1, type2);
-      }
+      Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
+                     type1, type2);
     });
 }
 
@@ -4132,8 +4071,6 @@
         !Req->getSecondType()->hasTypeParameter()) {
       if (!Req->getFirstType()->hasError() &&
           !Req->getSecondType()->hasError()) {
-        Impl->HadAnyError = true;
-
         Diags.diagnose(Req->getEqualLoc(),
                        diag::requires_no_same_type_archetype)
           .highlight(Req->getFirstTypeLoc().getSourceRange())
@@ -4233,11 +4170,9 @@
         firstType, secondType, source,
         UnresolvedHandlingKind::GenerateConstraints,
         [&](Type type1, Type type2) {
-          Impl->HadAnyError = true;
-          if (source.getLoc().isValid()) {
+          if (source.getLoc().isValid())
             Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
                            type1, type2);
-          }
         });
   }
   }
@@ -4582,8 +4517,6 @@
       if (isRecursiveConcreteType(archetype, /*isSuperclass=*/false)) {
         if (auto constraint =
               equivClass->findAnyConcreteConstraintAsWritten()) {
-          Impl->HadAnyError = true;
-
           Diags.diagnose(constraint->source->getLoc(),
                          diag::recursive_same_type_constraint,
                          archetype->getDependentType(genericParams),
@@ -4600,8 +4533,6 @@
     if (equivClass->superclass) {
       if (isRecursiveConcreteType(archetype, /*isSuperclass=*/true)) {
         if (auto source = equivClass->findAnySuperclassConstraintAsWritten()) {
-          Impl->HadAnyError = true;
-
           Diags.diagnose(source->source->getLoc(),
                          diag::recursive_superclass_constraint,
                          source->archetype->getDependentType(genericParams),
@@ -4663,13 +4594,10 @@
       // because then we don't actually have a parameter.
       auto equivClass = rep->getOrCreateEquivalenceClass();
       if (equivClass->concreteType) {
-        if (auto constraint = equivClass->findAnyConcreteConstraintAsWritten()){
-          Impl->HadAnyError = true;
-
+        if (auto constraint = equivClass->findAnyConcreteConstraintAsWritten())
           Diags.diagnose(constraint->source->getLoc(),
                          diag::requires_generic_param_made_equal_to_concrete,
                          rep->getDependentType(genericParams));
-        }
         continue;
       }
 
@@ -4699,8 +4627,6 @@
         }
 
         if (repConstraint && repConstraint->source->getLoc().isValid()) {
-          Impl->HadAnyError = true;
-
           Diags.diagnose(repConstraint->source->getLoc(),
                          diag::requires_generic_params_made_equal,
                          pa->getDependentType(genericParams),
@@ -4980,8 +4906,6 @@
       // The requirement conflicts. If this constraint has a location, complain
       // about it.
       if (constraint.source->getLoc().isValid()) {
-        Impl->HadAnyError = true;
-
         auto subject = getSubjectType(constraint.archetype);
         Diags.diagnose(constraint.source->getLoc(), *conflictingDiag,
                        subject.first, subject.second,
@@ -4996,8 +4920,6 @@
       // do so now.
       if (!diagnosedConflictingRepresentative &&
           representativeConstraint->source->getLoc().isValid()) {
-        Impl->HadAnyError = true;
-
         auto subject = getSubjectType(representativeConstraint->archetype);
         Diags.diagnose(representativeConstraint->source->getLoc(),
                        *conflictingDiag,
@@ -5014,7 +4936,6 @@
     case ConstraintRelation::Redundant:
       // If this requirement is not derived or inferred (but has a useful
       // location) complain that it is redundant.
-      Impl->HadAnyRedundantConstraints = true;
       if (!constraint.source->isDerivedRequirement() &&
           !constraint.source->isInferredRequirement(
             /*includeQuietInferred=*/true) &&
@@ -5982,8 +5903,6 @@
     if (!equivClass->superclass->isExactSuperclassOf(equivClass->concreteType)) {
       if (auto existing = equivClass->findAnyConcreteConstraintAsWritten(
                             representativeConstraint.archetype)) {
-        Impl->HadAnyError = true;
-
         Diags.diagnose(existing->source->getLoc(), diag::type_does_not_inherit,
                        existing->archetype->getDependentType(
                                                    genericParams),
@@ -5991,8 +5910,6 @@
 
         // FIXME: Note the representative constraint.
       } else if (representativeConstraint.source->getLoc().isValid()) {
-        Impl->HadAnyError = true;
-
         Diags.diagnose(representativeConstraint.source->getLoc(),
                        diag::type_does_not_inherit,
                        representativeConstraint.archetype->getDependentType(
@@ -6376,53 +6293,21 @@
   });
 }
 
-GenericSignature *GenericSignatureBuilder::computeGenericSignature(
-                                          ModuleDecl &module,
-                                          SourceLoc loc,
-                                          bool allowConcreteGenericParams) && {
-  // Finalize the builder, producing any necessary diagnostics.
-  finalize(loc, Impl->GenericParams, allowConcreteGenericParams);
+GenericSignature *GenericSignatureBuilder::getGenericSignature() {
+  assert(Impl->finalized && "Must finalize builder first");
 
   // Collect the requirements placed on the generic parameter types.
   SmallVector<Requirement, 4> requirements;
   collectRequirements(*this, Impl->GenericParams, requirements);
 
-  // Form the generic signature.
   auto sig = GenericSignature::get(Impl->GenericParams, requirements);
-
-  // Was this a requirement signature?
-  bool isRequirementSignature = false;
-  if (auto firstEquivClass =
-        Impl->PotentialArchetypes.front()->getEquivalenceClassIfPresent()) {
-    if (!firstEquivClass->conformsTo.empty() &&
-        firstEquivClass->conformsTo.front().second.front().source->getRoot()
-          ->kind == RequirementSource::RequirementSignatureSelf)
-      isRequirementSignature = true;
-  }
-
-  // When we can, move this generic signature builder to make it the canonical
-  // builder, rather than constructing a new generic signature builder that
-  // will produce the same thing.
-  //
-  // We cannot do this for requirement signatures (because they aren't
-  // fully-formed generic signatures) or when there were errors.
-  // FIXME: hadAnyError() is a big over-approximation here.
-  // FIXME: The HadAnyRedundantConstraints bit is a hack because we are
-  // over-minimizing.
-  if (!isRequirementSignature && !Impl->HadAnyError &&
-      !Impl->HadAnyRedundantConstraints) {
-    // Set the conformance lookup function to something that works canonically.
-    Impl->LookupConformance = LookUpConformanceInModule(&module);
-
-    // Register this generic signature builer as the canonical builder for the
-    // given signature.
-    Context.registerGenericSignatureBuilder(sig, module, std::move(*this));
-  }
-
-  // Wipe out the internal state, ensuring that nobody uses this builder for
-  // anything more.
-  Impl.reset();
-
   return sig;
 }
 
+GenericSignature *GenericSignatureBuilder::computeGenericSignature(
+                                          SourceLoc loc,
+                                          bool allowConcreteGenericParams) {
+  finalize(loc, Impl->GenericParams, allowConcreteGenericParams);
+  return getGenericSignature();
+}
+
diff --git a/lib/AST/Parameter.cpp b/lib/AST/Parameter.cpp
index 4c15b4c..e86697f 100644
--- a/lib/AST/Parameter.cpp
+++ b/lib/AST/Parameter.cpp
@@ -88,12 +88,11 @@
   SmallVector<ParamDecl*, 8> params(begin(), end());
 
   // Remap the ParamDecls inside of the ParameterList.
-  bool withTypes = !options.contains(ParameterList::WithoutTypes);
   for (auto &decl : params) {
     bool hadDefaultArgument =
         decl->getDefaultArgumentKind() == DefaultArgumentKind::Normal;
 
-    decl = new (C) ParamDecl(decl, withTypes);
+    decl = new (C) ParamDecl(decl);
     if (options & Implicit)
       decl->setImplicit();
 
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index c74ed44..ca99376 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -7653,8 +7653,7 @@
     (void) result;
   }
 
-  return std::move(builder).computeGenericSignature(*dc->getParentModule(),
-                                                    SourceLoc());
+  return builder.computeGenericSignature(SourceLoc());
 }
 
 // Calculate the generic environment from an imported generic param list.
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 14b1769..829c219 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -2695,7 +2695,7 @@
   builder.addRequirement(newRequirement, source, nullptr);
 
   GenericSignature *genericSig =
-    std::move(builder).computeGenericSignature(*mod, SourceLoc(),
+    builder.computeGenericSignature(SourceLoc(),
                                     /*allowConcreteGenericParams=*/true);
   genericEnv = genericSig->createGenericEnvironment(*mod);
 
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index da1a9f1..1bf8554 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -800,8 +800,7 @@
   }
 
   auto NewGenSig =
-    std::move(Builder).computeGenericSignature(*M.getSwiftModule(),
-                                   SourceLoc(),
+    Builder.computeGenericSignature(SourceLoc(),
                                    /*allowConcreteGenericParams=*/true);
   auto NewGenEnv = NewGenSig->createGenericEnvironment(*M.getSwiftModule());
   return { NewGenEnv, NewGenSig };
@@ -1491,8 +1490,7 @@
 
   // Finalize the archetype builder.
   auto GenSig =
-      std::move(Builder).computeGenericSignature(*M.getSwiftModule(),
-                                      SourceLoc(),
+      Builder.computeGenericSignature(SourceLoc(),
                                       /*allowConcreteGenericParams=*/true);
   auto GenEnv = GenSig->createGenericEnvironment(*M.getSwiftModule());
   return { GenEnv, GenSig };
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 727f365..692dfde 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -104,8 +104,7 @@
 
   // Clone the parameter list over for a new decl, so we get new ParamDecls.
   auto indices = subscript->getIndices()->clone(context,
-                                                ParameterList::Implicit|
-                                                ParameterList::WithoutTypes);
+                                                ParameterList::Implicit);
   if (prefix.empty())
     return indices;
   
diff --git a/lib/Sema/GenericTypeResolver.h b/lib/Sema/GenericTypeResolver.h
index b7a9763..02b63fc 100644
--- a/lib/Sema/GenericTypeResolver.h
+++ b/lib/Sema/GenericTypeResolver.h
@@ -130,14 +130,14 @@
 /// to check the signature of a generic declaration and resolve (for example)
 /// all dependent member refers to archetype members.
 class CompleteGenericTypeResolver : public GenericTypeResolver {
-  TypeChecker &tc;
-  GenericSignature *genericSig;
-  ModuleDecl &module;
-  GenericSignatureBuilder &builder;
+  TypeChecker &TC;
+  GenericSignatureBuilder &Builder;
+  ArrayRef<GenericTypeParamType *> GenericParams;
 
 public:
-  CompleteGenericTypeResolver(TypeChecker &tc, GenericSignature *genericSig,
-                              ModuleDecl &module);
+  CompleteGenericTypeResolver(TypeChecker &tc, GenericSignatureBuilder &builder,
+                              ArrayRef<GenericTypeParamType *> genericParams)
+    : TC(tc), Builder(builder), GenericParams(genericParams) { }
 
   virtual Type mapTypeIntoContext(Type type);
 
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index f3438d3..63d7375 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -1851,9 +1851,7 @@
     Builder.addRequirement(&req, DC->getParentModule());
 
   // Check the result.
-  (void)std::move(Builder).computeGenericSignature(
-                                        *DC->getParentModule(),
-                                        attr->getLocation(),
+  (void)Builder.computeGenericSignature(attr->getLocation(),
                                         /*allowConcreteGenericParams=*/true);
 }
 
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index a9db914..fcfc379 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -827,8 +827,7 @@
     prepareGenericParamList(genericParams, DC);
 
     parentEnv = checkGenericEnvironment(genericParams, DC, parentSig,
-                                        /*allowConcreteGenericParams=*/true,
-                                        /*ext=*/nullptr);
+                                        /*allowConcreteGenericParams=*/true);
     parentSig = parentEnv->getGenericSignature();
 
     // Compute the final set of archetypes.
@@ -5234,18 +5233,10 @@
       // Revert the types within the signature so it can be type-checked with
       // archetypes below.
       TC.revertGenericFuncSignature(FD);
-    } else if (auto genericSig =
-                 FD->getDeclContext()->getGenericSignatureOfContext()) {
-      if (!FD->getAccessorStorageDecl()) {
-        (void)TC.validateGenericFuncSignature(FD);
-
-        // Revert all of the types within the signature of the function.
-        TC.revertGenericFuncSignature(FD);
-      } else {
-        // We've inherited all of the type information already.
-        TC.configureInterfaceType(FD, genericSig);
-      }
-
+    } else if (FD->getDeclContext()->getGenericSignatureOfContext()) {
+      (void)TC.validateGenericFuncSignature(FD);
+      // Revert all of the types within the signature of the function.
+      TC.revertGenericFuncSignature(FD);
       FD->setGenericEnvironment(
           FD->getDeclContext()->getGenericEnvironmentOfContext());
     }
@@ -8048,7 +8039,7 @@
   auto *env = tc.checkGenericEnvironment(genericParams,
                                          ext->getDeclContext(), nullptr,
                                          /*allowConcreteGenericParams=*/true,
-                                         ext, inferExtendedTypeReqs);
+                                         inferExtendedTypeReqs);
 
   // Validate the generic parameters for the last time, to splat down
   // actual archetypes.
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 8ca70e1..a7c6d01 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -116,17 +116,6 @@
       "recording a param type of a protocol requirement doesn't make sense");
 }
 
-CompleteGenericTypeResolver::CompleteGenericTypeResolver(
-                                              TypeChecker &tc,
-                                              GenericSignature *genericSig,
-                                              ModuleDecl &module)
-  : tc(tc), genericSig(genericSig), module(module),
-    builder(*tc.Context.getOrCreateGenericSignatureBuilder(
-                               genericSig->getCanonicalSignature(),
-                               &module))
-{
-}
-
 Type CompleteGenericTypeResolver::mapTypeIntoContext(Type type) {
   return type;
 }
@@ -138,7 +127,7 @@
                                     ComponentIdentTypeRepr *ref) {
   // Resolve the base to a potential archetype.
   auto basePA =
-    builder.resolveArchetype(baseTy,
+    Builder.resolveArchetype(baseTy,
                              ArchetypeResolutionKind::CompleteWellFormed);
   assert(basePA && "Missing potential archetype for base");
 
@@ -146,17 +135,17 @@
   auto nestedPA =
     basePA->getNestedType(ref->getIdentifier(),
                           ArchetypeResolutionKind::CompleteWellFormed,
-                          builder);
+                          Builder);
 
   // If there was no such nested type, produce an error.
   if (!nestedPA) {
     // Perform typo correction.
     LookupResult corrections;
-    tc.performTypoCorrection(DC, DeclRefKind::Ordinary,
+    TC.performTypoCorrection(DC, DeclRefKind::Ordinary,
                              MetatypeType::get(baseTy),
                              ref->getIdentifier(), ref->getIdLoc(),
                              NameLookupFlags::ProtocolMembers,
-                             corrections, &builder);
+                             corrections, &Builder);
 
     // Filter out non-types.
     corrections.filter([](const LookupResultEntry &result) {
@@ -170,17 +159,17 @@
     if (!singleType) {
       Identifier name = ref->getIdentifier();
       SourceLoc nameLoc = ref->getIdLoc();
-      tc.diagnose(nameLoc, diag::invalid_member_type, name, baseTy)
+      TC.diagnose(nameLoc, diag::invalid_member_type, name, baseTy)
         .highlight(baseRange);
       for (const auto &suggestion : corrections)
-        tc.noteTypoCorrection(name, DeclNameLoc(nameLoc),
+        TC.noteTypoCorrection(name, DeclNameLoc(nameLoc),
                               suggestion.getValueDecl());
 
-      return ErrorType::get(tc.Context);
+      return ErrorType::get(TC.Context);
     }
 
     // We have a single type result. Suggest it.
-    tc.diagnose(ref->getIdLoc(), diag::invalid_member_type_suggest,
+    TC.diagnose(ref->getIdLoc(), diag::invalid_member_type_suggest,
                 baseTy, ref->getIdentifier(),
                 singleType->getBaseName().getIdentifier())
       .fixItReplace(ref->getIdLoc(),
@@ -204,14 +193,14 @@
   // Otherwise, the nested type comes from a concrete type. Substitute the
   // base type into it.
   auto concrete = ref->getBoundDecl();
-  tc.validateDeclForNameLookup(concrete);
+  TC.validateDeclForNameLookup(concrete);
   if (!concrete->hasInterfaceType())
-    return ErrorType::get(tc.Context);
+    return ErrorType::get(TC.Context);
   if (baseTy->isTypeParameter()) {
     if (auto proto =
           concrete->getDeclContext()
             ->getAsProtocolOrProtocolExtensionContext()) {
-      tc.validateDecl(proto);
+      TC.validateDecl(proto);
       auto subMap = SubstitutionMap::getProtocolSubstitutions(
                       proto, baseTy, ProtocolConformanceRef(proto));
       return concrete->getDeclaredInterfaceType().subst(subMap);
@@ -226,12 +215,25 @@
     llvm_unreachable("shouldn't have a concrete decl here");
   }
 
-  return tc.substMemberTypeWithBase(DC->getParentModule(), concrete, baseTy);
+  return TC.substMemberTypeWithBase(DC->getParentModule(), concrete, baseTy);
 }
 
 bool CompleteGenericTypeResolver::areSameType(Type type1, Type type2) {
-  return genericSig->getCanonicalTypeInContext(type1, module)
-           == genericSig->getCanonicalTypeInContext(type2, module);
+  if (!type1->hasTypeParameter() && !type2->hasTypeParameter())
+    return type1->isEqual(type2);
+
+  auto equivClass1 =
+    Builder.resolveEquivalenceClass(
+                             type1,
+                             ArchetypeResolutionKind::CompleteWellFormed);
+  auto equivClass2 =
+    Builder.resolveEquivalenceClass(
+                             type2,
+                             ArchetypeResolutionKind::CompleteWellFormed);
+  if (equivClass1 && equivClass2)
+    return equivClass1 == equivClass2;
+
+  return type1->isEqual(type2);
 }
 
 void
@@ -748,55 +750,61 @@
 TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) {
   bool invalid = false;
 
-  GenericSignature *sig;
-  if (auto gp = func->getGenericParams()) {
+  auto *gp = func->getGenericParams();
+  if (gp)
     prepareGenericParamList(gp, func);
 
-    // Create the generic signature builder.
-    GenericSignatureBuilder builder(Context, LookUpConformance(*this, func));
+  // Collect the generic parameters.
+  SmallVector<GenericTypeParamType *, 4> allGenericParams;
+  if (auto parentSig = func->getDeclContext()->getGenericSignatureOfContext())
+    allGenericParams.append(parentSig->getGenericParams().begin(),
+                            parentSig->getGenericParams().end());
+  addGenericParamTypes(gp, allGenericParams);
 
-    // Type check the function declaration, treating all generic type
-    // parameters as dependent, unresolved.
-    DependentGenericTypeResolver dependentResolver;
-    if (checkGenericFuncSignature(*this, &builder, func, dependentResolver))
-      invalid = true;
+  // Create the generic signature builder.
+  GenericSignatureBuilder builder(Context, LookUpConformance(*this, func));
 
-    // The generic function signature is complete and well-formed. Determine
-    // the type of the generic function.
-    sig = std::move(builder).computeGenericSignature(*func->getParentModule(),
-                                                     func->getLoc());
+  // Type check the function declaration, treating all generic type
+  // parameters as dependent, unresolved.
+  DependentGenericTypeResolver dependentResolver;
+  if (checkGenericFuncSignature(*this, &builder, func, dependentResolver))
+    invalid = true;
 
-    // The generic signature builder now has all of the requirements, although
-    // there might still be errors that have not yet been diagnosed. Revert the
-    // generic function signature and type-check it again, completely.
-    revertGenericFuncSignature(func);
-    if (gp)
-      revertGenericParamList(gp);
+  // Finalize the generic requirements.
+  (void)builder.finalize(func->getLoc(), allGenericParams);
 
-    // Debugging of the generic signature.
-    if (Context.LangOpts.DebugGenericSignatures) {
-      func->dumpRef(llvm::errs());
-      llvm::errs() << "\n";
-      llvm::errs() << "Generic signature: ";
-      sig->print(llvm::errs());
-      llvm::errs() << "\n";
-      llvm::errs() << "Canonical generic signature: ";
-      sig->getCanonicalSignature()->print(llvm::errs());
-      llvm::errs() << "\n";
-    }
-  } else {
-    // Inherit the signature of our environment.
-    sig = func->getDeclContext()->getGenericSignatureOfContext();
-  }
+  // The generic signature builder now has all of the requirements, although
+  // there might still be errors that have not yet been diagnosed. Revert the
+  // generic function signature and type-check it again, completely.
+  revertGenericFuncSignature(func);
+  if (gp)
+    revertGenericParamList(gp);
 
-  CompleteGenericTypeResolver completeResolver(*this, sig,
-                                               *func->getModuleContext());
+  CompleteGenericTypeResolver completeResolver(*this, builder,
+                                               allGenericParams);
   if (checkGenericFuncSignature(*this, nullptr, func, completeResolver))
     invalid = true;
 
+  // The generic function signature is complete and well-formed. Determine
+  // the type of the generic function.
+  auto sig = builder.getGenericSignature();
+
   if (!invalid)
     invalid = checkProtocolSelfRequirements(sig, func, *this);
 
+  // Debugging of the generic signature builder and generic signature generation.
+  if (Context.LangOpts.DebugGenericSignatures) {
+    func->dumpRef(llvm::errs());
+    llvm::errs() << "\n";
+    builder.dump(llvm::errs());
+    llvm::errs() << "Generic signature: ";
+    sig->print(llvm::errs());
+    llvm::errs() << "\n";
+    llvm::errs() << "Canonical generic signature: ";
+    sig->getCanonicalSignature()->print(llvm::errs());
+    llvm::errs() << "\n";
+  }
+
   if (invalid) {
     func->setInterfaceType(ErrorType::get(Context));
     func->setInvalid();
@@ -972,57 +980,62 @@
 TypeChecker::validateGenericSubscriptSignature(SubscriptDecl *subscript) {
   bool invalid = false;
 
-  GenericSignature *sig;
-  if (auto *gp = subscript->getGenericParams()) {
+  auto *gp = subscript->getGenericParams();
+  if (gp)
     prepareGenericParamList(gp, subscript);
 
-    // Create the generic signature builder.
-    GenericSignatureBuilder builder(Context,
-                                    LookUpConformance(*this, subscript));
+  // Collect the generic parameters.
+  SmallVector<GenericTypeParamType *, 4> allGenericParams;
+  if (auto parentSig = subscript->getDeclContext()->getGenericSignatureOfContext())
+    allGenericParams.append(parentSig->getGenericParams().begin(),
+                            parentSig->getGenericParams().end());
+  addGenericParamTypes(gp, allGenericParams);
 
-    // Type check the function declaration, treating all generic type
-    // parameters as dependent, unresolved.
-    DependentGenericTypeResolver dependentResolver;
-    if (checkGenericSubscriptSignature(*this, &builder, subscript,
-                                       dependentResolver))
-      invalid = true;
+  // Create the generic signature builder.
+  GenericSignatureBuilder builder(Context, LookUpConformance(*this, subscript));
 
-    // The generic subscript signature is complete and well-formed. Determine
-    // the type of the generic subscript.
-    sig =
-      std::move(builder).computeGenericSignature(*subscript->getParentModule(),
-                                                 subscript->getLoc());
+  // Type check the function declaration, treating all generic type
+  // parameters as dependent, unresolved.
+  DependentGenericTypeResolver dependentResolver;
+  if (checkGenericSubscriptSignature(*this, &builder, subscript,
+                                     dependentResolver))
+    invalid = true;
 
-    // The generic signature builder now has all of the requirements, although
-    // there might still be errors that have not yet been diagnosed. Revert the
-    // generic function signature and type-check it again, completely.
-    revertGenericSubscriptSignature(subscript);
+  // Finalize the generic requirements.
+  (void)builder.finalize(subscript->getLoc(), allGenericParams);
+
+  // The generic signature builder now has all of the requirements, although
+  // there might still be errors that have not yet been diagnosed. Revert the
+  // generic function signature and type-check it again, completely.
+  revertGenericSubscriptSignature(subscript);
+  if (gp)
     revertGenericParamList(gp);
 
-    // Debugging of generic signature generation.
-    if (Context.LangOpts.DebugGenericSignatures) {
-      subscript->dumpRef(llvm::errs());
-      llvm::errs() << "\n";
-      llvm::errs() << "Generic signature: ";
-      sig->print(llvm::errs());
-      llvm::errs() << "\n";
-      llvm::errs() << "Canonical generic signature: ";
-      sig->getCanonicalSignature()->print(llvm::errs());
-      llvm::errs() << "\n";
-    }
-  } else {
-    // Inherit the signature of our environment.
-    sig = subscript->getDeclContext()->getGenericSignatureOfContext();
-  }
-
-  CompleteGenericTypeResolver completeResolver(*this, sig,
-                                               *subscript->getModuleContext());
+  CompleteGenericTypeResolver completeResolver(*this, builder,
+                                               allGenericParams);
   if (checkGenericSubscriptSignature(*this, nullptr, subscript, completeResolver))
     invalid = true;
 
+  // The generic subscript signature is complete and well-formed. Determine
+  // the type of the generic subscript.
+  auto sig = builder.getGenericSignature();
+
   if (!invalid)
     invalid = checkProtocolSelfRequirements(sig, subscript, *this);
 
+  // Debugging of the generic signature builder and generic signature generation.
+  if (Context.LangOpts.DebugGenericSignatures) {
+    subscript->dumpRef(llvm::errs());
+    llvm::errs() << "\n";
+    builder.dump(llvm::errs());
+    llvm::errs() << "Generic signature: ";
+    sig->print(llvm::errs());
+    llvm::errs() << "\n";
+    llvm::errs() << "Canonical generic signature: ";
+    sig->getCanonicalSignature()->print(llvm::errs());
+    llvm::errs() << "\n";
+  }
+
   if (invalid) {
     subscript->setInterfaceType(ErrorType::get(Context));
     subscript->setInvalid();
@@ -1067,105 +1080,72 @@
   visitor(genericParams);
 }
 
-/// Retrieve the generic parameter depth of the extended type.
-static unsigned getExtendedTypeGenericDepth(ExtensionDecl *ext) {
-  auto nominal = ext->getAsNominalTypeOrNominalTypeExtensionContext();
-  if (!nominal) return static_cast<unsigned>(-1);
-
-  auto sig = nominal->getGenericSignatureOfContext();
-  if (!sig) return static_cast<unsigned>(-1);
-
-  return sig->getGenericParams().back()->getDepth();
-}
-
 GenericEnvironment *TypeChecker::checkGenericEnvironment(
                       GenericParamList *genericParams,
                       DeclContext *dc,
                       GenericSignature *parentSig,
                       bool allowConcreteGenericParams,
-                      ExtensionDecl *ext,
                       llvm::function_ref<void(GenericSignatureBuilder &)>
                         inferRequirements) {
   assert(genericParams && "Missing generic parameters?");
   bool recursivelyVisitGenericParams =
     genericParams->getOuterParameters() && !parentSig;
 
-  GenericSignature *sig;
-  if (!ext || ext->getTrailingWhereClause() ||
-      getExtendedTypeGenericDepth(ext) != genericParams->getDepth()) {
-    // Collect the generic parameters.
-    SmallVector<GenericTypeParamType *, 4> allGenericParams;
-    if (recursivelyVisitGenericParams) {
-      visitOuterToInner(genericParams,
-                        [&](GenericParamList *gpList) {
-        addGenericParamTypes(gpList, allGenericParams);
-      });
-    } else {
-      if (parentSig) {
-        allGenericParams.append(parentSig->getGenericParams().begin(),
-                                parentSig->getGenericParams().end());
-      }
-
-      addGenericParamTypes(genericParams, allGenericParams);
-    }
-
-    // Create the generic signature builder.
-    GenericSignatureBuilder builder(Context, LookUpConformance(*this, dc));
-
-    // Type check the generic parameters, treating all generic type
-    // parameters as dependent, unresolved.
-    DependentGenericTypeResolver dependentResolver;
-    if (recursivelyVisitGenericParams) {
-      visitOuterToInner(genericParams,
-                        [&](GenericParamList *gpList) {
-        checkGenericParamList(&builder, gpList, nullptr, &dependentResolver);
-      });
-    } else {
-      checkGenericParamList(&builder, genericParams, parentSig,
-                            &dependentResolver);
-    }
-
-    /// Perform any necessary requirement inference.
-    inferRequirements(builder);
-
-    // Record the generic type parameter types and the requirements.
-    sig = std::move(builder).computeGenericSignature(
-                                         *dc->getParentModule(),
-                                         genericParams->getSourceRange().Start,
-                                         allowConcreteGenericParams);
-
-    // The generic signature builder now has all of the requirements, although
-    // there might still be errors that have not yet been diagnosed. Revert the
-    // signature and type-check it again, completely.
-    if (recursivelyVisitGenericParams) {
-      visitOuterToInner(genericParams,
-                        [&](GenericParamList *gpList) {
-        revertGenericParamList(gpList);
-      });
-    } else {
-      revertGenericParamList(genericParams);
-    }
-
-    // Debugging of the generic signature builder and generic signature
-    // generation.
-    if (Context.LangOpts.DebugGenericSignatures) {
-      dc->printContext(llvm::errs());
-      llvm::errs() << "\n";
-      llvm::errs() << "Generic signature: ";
-      sig->print(llvm::errs());
-      llvm::errs() << "\n";
-      llvm::errs() << "Canonical generic signature: ";
-      sig->getCanonicalSignature()->print(llvm::errs());
-      llvm::errs() << "\n";
-    }
+  // Collect the generic parameters.
+  SmallVector<GenericTypeParamType *, 4> allGenericParams;
+  if (recursivelyVisitGenericParams) {
+    visitOuterToInner(genericParams,
+                      [&](GenericParamList *gpList) {
+      addGenericParamTypes(gpList, allGenericParams);
+    });
   } else {
-    // Re-use the signature of the type being extended.
-    sig = ext->getAsNominalTypeOrNominalTypeExtensionContext()
-            ->getGenericSignatureOfContext();
+    if (parentSig) {
+      allGenericParams.append(parentSig->getGenericParams().begin(),
+                              parentSig->getGenericParams().end());
+    }
+
+    addGenericParamTypes(genericParams, allGenericParams);
   }
 
-  CompleteGenericTypeResolver completeResolver(*this, sig,
-                                               *dc->getParentModule());
+  // Create the generic signature builder.
+  ModuleDecl *module = dc->getParentModule();
+  GenericSignatureBuilder builder(Context, LookUpConformance(*this, dc));
+
+  // Type check the generic parameters, treating all generic type
+  // parameters as dependent, unresolved.
+  DependentGenericTypeResolver dependentResolver;
+  if (recursivelyVisitGenericParams) {
+    visitOuterToInner(genericParams,
+                      [&](GenericParamList *gpList) {
+      checkGenericParamList(&builder, gpList, nullptr, &dependentResolver);
+    });
+  } else {
+    checkGenericParamList(&builder, genericParams, parentSig,
+                          &dependentResolver);
+  }
+
+  /// Perform any necessary requirement inference.
+  inferRequirements(builder);
+
+  // Finalize the generic requirements.
+  (void)builder.finalize(genericParams->getSourceRange().Start,
+                         allGenericParams,
+                         allowConcreteGenericParams);
+
+  // The generic signature builder now has all of the requirements, although
+  // there might still be errors that have not yet been diagnosed. Revert the
+  // signature and type-check it again, completely.
+  if (recursivelyVisitGenericParams) {
+    visitOuterToInner(genericParams,
+                      [&](GenericParamList *gpList) {
+      revertGenericParamList(gpList);
+    });
+  } else {
+    revertGenericParamList(genericParams);
+  }
+
+  CompleteGenericTypeResolver completeResolver(*this, builder,
+                                               allGenericParams);
   if (recursivelyVisitGenericParams) {
     visitOuterToInner(genericParams,
                       [&](GenericParamList *gpList) {
@@ -1176,8 +1156,23 @@
                           &completeResolver);
   }
 
+  // Record the generic type parameter types and the requirements.
+  auto sig = builder.getGenericSignature();
+
+  // Debugging of the generic signature builder and generic signature generation.
+  if (Context.LangOpts.DebugGenericSignatures) {
+    dc->printContext(llvm::errs());
+    llvm::errs() << "\n";
+    builder.dump(llvm::errs());
+    llvm::errs() << "Generic signature: ";
+    sig->print(llvm::errs());
+    llvm::errs() << "\n";
+    llvm::errs() << "Canonical generic signature: ";
+    sig->getCanonicalSignature()->print(llvm::errs());
+    llvm::errs() << "\n";
+  }
+
   // Form the generic environment.
-  ModuleDecl *module = dc->getParentModule();
   return sig->createGenericEnvironment(*module);
 }
 
@@ -1202,10 +1197,8 @@
       proto->computeRequirementSignature();
   }
 
-  auto *env = checkGenericEnvironment(gp, dc,
-                                      dc->getGenericSignatureOfContext(),
-                                      /*allowConcreteGenericParams=*/false,
-                                      /*ext=*/nullptr);
+  auto *env = checkGenericEnvironment(gp, dc, dc->getGenericSignatureOfContext(),
+                                      /*allowConcreteGenericParams=*/false);
   typeDecl->setGenericEnvironment(env);
 }
 
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 1bc58f0..d730a4a 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1156,10 +1156,7 @@
   // Produce the generic signature and environment.
   // FIXME: Pass in a source location for the conformance, perhaps? It seems
   // like this could fail.
-  syntheticSignature =
-    std::move(builder).computeGenericSignature(
-                                           *conformanceDC->getParentModule(),
-                                           SourceLoc());
+  syntheticSignature = builder.computeGenericSignature(SourceLoc());
   syntheticEnvironment = syntheticSignature->createGenericEnvironment(
                                              *conformanceDC->getParentModule());
 }
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 0c3e4d8..4a7a0d9 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1367,9 +1367,6 @@
   /// context, if not available as part of the \c dc argument (used
   /// for SIL parsing).
   ///
-  /// \param ext The extension for which we're checking the generic
-  /// environment, or null if we're not checking an extension.
-  ///
   /// \param inferRequirements When non-empty, callback that will be invoked
   /// to perform any additional requirement inference that contributes to the
   /// generic environment..
@@ -1380,7 +1377,6 @@
                         DeclContext *dc,
                         GenericSignature *outerSignature,
                         bool allowConcreteGenericParams,
-                        ExtensionDecl *ext,
                         llvm::function_ref<void(GenericSignatureBuilder &)>
                           inferRequirements);
 
@@ -1398,10 +1394,9 @@
                         GenericParamList *genericParams,
                         DeclContext *dc,
                         GenericSignature *outerSignature,
-                        bool allowConcreteGenericParams,
-                        ExtensionDecl *ext) {
+                        bool allowConcreteGenericParams) {
     return checkGenericEnvironment(genericParams, dc, outerSignature,
-                                   allowConcreteGenericParams, ext,
+                                   allowConcreteGenericParams,
                                    [&](GenericSignatureBuilder &) { });
   }
 
diff --git a/test/Generics/associated_type_typo.swift b/test/Generics/associated_type_typo.swift
index 4ac5b86..f023418 100644
--- a/test/Generics/associated_type_typo.swift
+++ b/test/Generics/associated_type_typo.swift
@@ -34,6 +34,13 @@
 // expected-error@+1{{'T' does not have a member type named 'Assocp2'; did you mean 'AssocP2'?}}{{39-46=AssocP2}}
 func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
 
+
+// CHECK-GENERIC-LABEL: .typoAssoc4@
+// CHECK-GENERIC-NEXT: Requirements:
+// CHECK-GENERIC-NEXT:   τ_0_0 : P2 [τ_0_0: Explicit @ {{.*}}:21]
+// CHECK-GENERIC-NEXT:   τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (via Self.AssocP2 in P2)
+// CHECK-GENERIC-NEXT: Potential archetypes
+
 // <rdar://problem/19620340>
 
 func typoFunc1<T : P1>(x: TypoType) { // expected-error{{use of undeclared type 'TypoType'}}
diff --git a/test/Generics/protocol_type_aliases.swift b/test/Generics/protocol_type_aliases.swift
index 9c083d4..afb2661 100644
--- a/test/Generics/protocol_type_aliases.swift
+++ b/test/Generics/protocol_type_aliases.swift
@@ -14,6 +14,10 @@
 }
 
 // CHECK-LABEL: .requirementOnNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : Q [τ_0_0: Explicit @ 22:51]
+// CHECK-NEXT:   τ_0_0[.Q].B : P [τ_0_0: Explicit @ 22:51 -> Protocol requirement (via Self.B in Q)
+// CHECK-NEXT:   τ_0_0[.Q].B[.P].A == Int [τ_0_0[.Q].B[.P].X: Explicit @ 22:62]
 // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q, τ_0_0.B.A == Int>
 func requirementOnNestedTypeAlias<T>(_: T) where T: Q, T.B.X == Int {}
 
@@ -29,10 +33,20 @@
 }
 
 // CHECK-LABEL: .requirementOnConcreteNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : Q2 [τ_0_0: Explicit @ 42:59]
+// CHECK-NEXT:   τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 42:59 -> Protocol requirement (via Self.B in Q2)
+// CHECK-NEXT:   τ_0_0[.Q2].C == S<T.B.A> [τ_0_0[.Q2].C: Explicit]
+// CHECK-NEXT:   τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Concrete type binding]
 // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == S<τ_0_0.B.A>>
 func requirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, T.C == T.B.X {}
 
 // CHECK-LABEL: .concreteRequirementOnConcreteNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : Q2 [τ_0_0: Explicit @ 51:67]
+// CHECK-NEXT:   τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 51:67 -> Protocol requirement (via Self.B in Q2)
+// CHECK-NEXT:   τ_0_0[.Q2].C == τ_0_0[.Q2].B[.P2].A [τ_0_0[.Q2].C: Explicit]
+// CHECK-NEXT:   τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Concrete type binding]
 // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == τ_0_0.B.A>
 func concreteRequirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, S<T.C> == T.B.X {}
 
diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift
index 391c9b4..755d24d 100644
--- a/test/Generics/requirement_inference.swift
+++ b/test/Generics/requirement_inference.swift
@@ -54,9 +54,11 @@
   func p1() {}
 }
 
-class Box<T : Fox, U> {
+class Box<T : Fox> {
+// CHECK-LABEL: .unpack@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : Fox [τ_0_0: Explicit]
   func unpack(_ x: X1<T>) {}
-  func unpackFail(_ X: X1<U>) { } // expected-error{{type 'U' does not conform to protocol 'P1'}}
 }
 
 // ----------------------------------------------------------------------------
@@ -72,14 +74,16 @@
 struct V<T : Canidae> {}
 
 // CHECK-LABEL: .inferSuperclassRequirement1@
-// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Canidae>
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : Canidae
 func inferSuperclassRequirement1<T : Carnivora>(
 	_ v: V<T>) {}
 // expected-warning@-2{{redundant superclass constraint 'T' : 'Carnivora'}}
 // expected-note@-2{{superclass constraint 'T' : 'Canidae' inferred from type here}}
 
 // CHECK-LABEL: .inferSuperclassRequirement2@
-// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Canidae>
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : Canidae
 func inferSuperclassRequirement2<T : Canidae>(_ v: U<T>) {}
 
 // ----------------------------------------------------------------------------
@@ -108,17 +112,33 @@
 
 struct Model_P3_P4_Eq<T : P3, U : P4> where T.P3Assoc == U.P4Assoc {}
 
-func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) {
-  let u: U.P4Assoc? = nil
-  let _: T.P3Assoc? = u!
-}
+// CHECK-LABEL: .inferSameType1@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : P3 [τ_0_0: Inferred @ {{.*}}:32]
+// CHECK-NEXT:   τ_0_1 : P4 [τ_0_1: Inferred @ {{.*}}:32]
+// CHECK-NEXT:   τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P4Assoc in P4)
+// CHECK-NEXT:   τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P3Assoc in P3)
+// FIXME: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0: Inferred]
+func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
 
+// CHECK-LABEL: .inferSameType2@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:25]
+// CHECK-NEXT:   τ_0_1 : P4 [τ_0_1: Explicit @ {{.*}}:33]
+// CHECK-NEXT:   τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Explicit @ {{.*}}:33 -> Protocol requirement (via Self.P4Assoc in P4)
+// CHECK-NEXT:   τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (via Self.P3Assoc in P3)
+// CHECK-NEXT:   τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0[.P3].P3Assoc: Explicit]
 func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
 // expected-warning@-1{{redundant conformance constraint 'T.P3Assoc': 'P2'}}
 // expected-note@-2{{conformance constraint 'T.P3Assoc': 'P2' implied here}}
 
-func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {
-}
+// CHECK-LABEL: .inferSameType3@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT:   τ_0_0 : PCommonAssoc1 [τ_0_0: Explicit @ {{.*}}:25]
+// CHECK-NEXT:   τ_0_0 : PCommonAssoc2 [τ_0_0: Explicit @ {{.*}}:74]
+// CHECK-NEXT:   τ_0_0[.PCommonAssoc1].CommonAssoc : P1 [τ_0_0[.PCommonAssoc1].CommonAssoc: Explicit @ {{.*}}:66]
+// CHECK-NEXT: Potential archetypes
+func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {}
 
 protocol P5 {
   associatedtype Element
@@ -132,7 +152,7 @@
   associatedtype AssocP7: P6
 }
 
-// CHECK-LABEL: P7@
+// CHECK-LABEL: P7.nestedSameType1()@
 // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P7, τ_0_0.AssocP6.Element : P6, τ_0_0.AssocP6.Element == τ_0_0.AssocP7.AssocP6.Element>
 extension P7 where AssocP6.Element : P6, // expected-note{{conformance constraint 'Self.AssocP6.Element': 'P6' written here}}
         AssocP7.AssocP6.Element : P6, // expected-warning{{redundant conformance constraint 'Self.AssocP6.Element': 'P6'}}
@@ -167,7 +187,7 @@
 
 // Note: a standard-library-based stress test to make sure we don't inject
 // any additional requirements.
-// CHECK-LABEL: RangeReplaceableCollection
+// CHECK-LABEL: RangeReplaceableCollection.f()@
 // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : MutableCollection, τ_0_0 : RangeReplaceableCollection, τ_0_0.SubSequence == MutableRangeReplaceableSlice<τ_0_0>>
 extension RangeReplaceableCollection where
   Self: MutableCollection,
diff --git a/test/Generics/superclass_constraint.swift b/test/Generics/superclass_constraint.swift
index b27d7af..16ed23b 100644
--- a/test/Generics/superclass_constraint.swift
+++ b/test/Generics/superclass_constraint.swift
@@ -66,7 +66,18 @@
   typealias T = C
 }
 
+extension P2 where Self.T : C {
+  // CHECK: superclass_constraint.(file).P2.concreteTypeWitnessViaSuperclass1
+  // CHECK: Generic signature: <Self where Self : P2, Self.T : C>
+  // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P2, τ_0_0.T : C>
+  func concreteTypeWitnessViaSuperclass1(x: Self.T.T) {}
+}
+
 // CHECK: superclassConformance1
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:11]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:11 -> Derived]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:11 -> Superclass (C: P3)]
 // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
 func superclassConformance1<T>(t: T)
   where T : C, // expected-note{{conformance constraint 'T': 'P3' implied here}}
@@ -75,6 +86,10 @@
 
 
 // CHECK: superclassConformance2
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:11]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:11 -> Derived]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:11 -> Superclass (C: P3)]
 // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
 func superclassConformance2<T>(t: T)
   where T : C, // expected-note{{conformance constraint 'T': 'P3' implied here}}
@@ -85,6 +100,10 @@
 class C2 : C, P4 { }
 
 // CHECK: superclassConformance3
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C2 [τ_0_0: Explicit @ {{.*}}:61]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:46 -> Derived]
+// CHECK-NEXT: τ_0_0 : P4 [τ_0_0: Explicit @ {{.*}}:61 -> Superclass (C2: P4)]
 // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C2>
 func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {}
 // expected-warning@-1{{redundant superclass constraint 'T' : 'C'}}
diff --git a/test/Sema/availability_versions.swift b/test/Sema/availability_versions.swift
index e96f91a..5f1da36 100644
--- a/test/Sema/availability_versions.swift
+++ b/test/Sema/availability_versions.swift
@@ -1345,7 +1345,7 @@
 // Protocol Conformances
 
 protocol ProtocolWithRequirementMentioningUnavailable {
-      // expected-note@-1 4{{add @available attribute to enclosing protocol}}
+      // expected-note@-1 6{{add @available attribute to enclosing protocol}}
   func hasUnavailableParameter(_ p: ClassAvailableOn10_51) // expected-error * {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
       // expected-note@-1 * {{add @available attribute to enclosing instance method}}
       
diff --git a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift b/validation-test/compiler_crashers/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
similarity index 88%
rename from validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
rename to validation-test/compiler_crashers/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
index 1900ef7..bcd5e1c 100644
--- a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
+++ b/validation-test/compiler_crashers/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
@@ -6,7 +6,7 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // REQUIRES: asserts
-// RUN: not %target-swift-frontend %s -emit-ir
+// RUN: not --crash %target-swift-frontend %s -emit-ir
 class a:A
 protocol A:a{
 protocol A{struct a{var f:A