Merge pull request #19601 from slavapestov/fewer-gsbs-2

Create fewer GenericSignatureBuilders, part 2
diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h
index 47b4198..db19336 100644
--- a/include/swift/AST/GenericSignature.h
+++ b/include/swift/AST/GenericSignature.h
@@ -190,9 +190,10 @@
   Optional<ProtocolConformanceRef>
   lookupConformance(CanType depTy, ProtocolDecl *proto) const;
 
-  /// Return a vector of all generic parameters that are not subject to
-  /// a concrete same-type constraint.
-  SmallVector<GenericTypeParamType *, 2> getSubstitutableParams() const;
+  /// Iterate over all generic parameters, passing a flag to the callback
+  /// indicating if the generic parameter is canonical or not.
+  void forEachParam(
+    llvm::function_ref<void(GenericTypeParamType *, bool)> callback) const;
 
   /// Check if the generic signature makes all generic parameters
   /// concrete.
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 22aabc2..dd28931 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -415,7 +415,6 @@
   {
     assert(!conformingType->hasArchetype() &&
            "ProtocolConformances should store interface types");
-    differenceAndStoreConditionalRequirements();
   }
 
   NormalProtocolConformance(Type conformingType,
@@ -428,7 +427,6 @@
   {
     assert(!conformingType->hasArchetype() &&
            "ProtocolConformances should store interface types");
-    differenceAndStoreConditionalRequirements();
   }
 
   void resolveLazyInfo() const;
diff --git a/include/swift/AST/Witness.h b/include/swift/AST/Witness.h
index 302ad86..0721398 100644
--- a/include/swift/AST/Witness.h
+++ b/include/swift/AST/Witness.h
@@ -117,6 +117,15 @@
     return Witness(requirement);
   }
 
+  /// Create a witness for the given requirement.
+  ///
+  /// Deserialized witnesses do not have a synthetic environment.
+  static Witness forDeserialized(ValueDecl *decl,
+                                 SubstitutionMap substitutions) {
+    // TODO: It's probably a good idea to have a separate 'deserialized' bit.
+    return Witness(decl, substitutions, nullptr, SubstitutionMap());
+  }
+
   /// Create a witness that requires substitutions.
   ///
   /// \param decl The declaration for the witness.
diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h
index d87b92a..0a02ba0 100644
--- a/include/swift/SIL/TypeSubstCloner.h
+++ b/include/swift/SIL/TypeSubstCloner.h
@@ -297,12 +297,15 @@
     if (SubsMap.empty())
       return false;
 
-    for (auto ParamType : Sig->getSubstitutableParams()) {
+    bool Result = false;
+    Sig->forEachParam([&](GenericTypeParamType *ParamType, bool Canonical) {
+      if (!Canonical)
+        return;
       if (!Type(ParamType).subst(SubsMap)->isEqual(ParamType))
-        return true;
-    }
+        Result = true;
+    });
 
-    return false;
+    return Result;
   }
 
   enum { ForInlining = true };
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 5fb65dd..9b69765 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
 /// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 449; // Last change: serialize @_implements names
+const uint16_t VERSION_MINOR = 450; // Last change: don't serialize requirement environment
 
 using DeclIDField = BCFixed<31>;
 
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 032db0f..b0e5469 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -4384,14 +4384,15 @@
   // Profile those replacement types that corresponding to canonical generic
   // parameters within the generic signature.
   id.AddInteger(replacementTypes.size());
-  auto genericParams = genericSig->getGenericParams();
-  for (unsigned i : indices(genericParams)) {
-    auto gp = genericParams[i];
-    if (genericSig->isCanonicalTypeInContext(gp->getCanonicalType()))
+
+  unsigned i = 0;
+  genericSig->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
+    if (canonical)
       id.AddPointer(replacementTypes[i].getPointer());
     else
       id.AddPointer(nullptr);
-  }
+    i++;
+  });
 
   // Conformances.
   id.AddInteger(conformances.size());
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index cd6b5b4..c1e71d0 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -97,45 +97,42 @@
   return params;
 }
 
-
-SmallVector<GenericTypeParamType *, 2>
-GenericSignature::getSubstitutableParams() const {
+void GenericSignature::forEachParam(
+    llvm::function_ref<void(GenericTypeParamType *, bool)> callback) const {
   // Figure out which generic parameters are concrete or same-typed to another
-  // generic parameter.
+  // type parameter.
   auto genericParams = getGenericParams();
-  auto genericParamsAreNotSubstitutable =
-    SmallVector<bool, 4>(genericParams.size(), false);
+  auto genericParamsAreCanonical =
+    SmallVector<bool, 4>(genericParams.size(), true);
+
   for (auto req : getRequirements()) {
     if (req.getKind() != RequirementKind::SameType) continue;
 
     GenericTypeParamType *gp;
     if (auto secondGP = req.getSecondType()->getAs<GenericTypeParamType>()) {
-      // If two generic parameters are same-typed, then the left-hand one
-      // is canonical.
+      // If two generic parameters are same-typed, then the right-hand one
+      // is non-canonical.
+      assert(req.getFirstType()->is<GenericTypeParamType>());
       gp = secondGP;
     } else {
-      // If an associated type is same-typed, it doesn't constrain the generic
-      // parameter itself.
-      if (req.getSecondType()->isTypeParameter()) continue;
-
-      // Otherwise, the generic parameter is concrete.
+      // Otherwise, the right-hand side is an associated type or concrete type,
+      // and the left-hand one is non-canonical.
       gp = req.getFirstType()->getAs<GenericTypeParamType>();
       if (!gp) continue;
+
+      // If an associated type is same-typed, it doesn't constrain the generic
+      // parameter itself. That is, if T == U.Foo, then T is canonical, whereas
+      // U.Foo is not.
+      if (req.getSecondType()->isTypeParameter()) continue;
     }
 
     unsigned index = GenericParamKey(gp).findIndexIn(genericParams);
-    genericParamsAreNotSubstitutable[index] = true;
+    genericParamsAreCanonical[index] = false;
   }
 
-  // Collect the generic parameters that are substitutable.
-  SmallVector<GenericTypeParamType *, 2> result;
-  for (auto index : indices(genericParams)) {
-    auto gp = genericParams[index];
-    if (!genericParamsAreNotSubstitutable[index])
-      result.push_back(gp);
-  }
-
-  return result;
+  // Call the callback with each parameter and the result of the above analysis.
+  for (auto index : indices(genericParams))
+    callback(genericParams[index], genericParamsAreCanonical[index]);
 }
 
 bool GenericSignature::areAllParamsConcrete() const {
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 507366a..f2f03c6 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -886,7 +886,6 @@
     GenericSubstitutions(substitutions)
 {
   assert(genericConformance->getKind() != ProtocolConformanceKind::Specialized);
-  computeConditionalRequirements();
 }
 
 void SpecializedProtocolConformance::computeConditionalRequirements() const {
diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp
index 41a6c17..c81100a 100644
--- a/lib/AST/SubstitutionMap.cpp
+++ b/lib/AST/SubstitutionMap.cpp
@@ -200,18 +200,19 @@
   // Form the replacement types.
   SmallVector<Type, 4> replacementTypes;
   replacementTypes.reserve(genericSig->getGenericParams().size());
-  for (auto gp : genericSig->getGenericParams()) {
+
+  genericSig->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
     // Don't eagerly form replacements for non-canonical generic parameters.
-    if (!genericSig->isCanonicalTypeInContext(gp->getCanonicalType())) {
+    if (!canonical) {
       replacementTypes.push_back(Type());
-      continue;
+      return;
     }
 
     // Record the replacement.
     Type replacement = Type(gp).subst(subs, lookupConformance,
                                       SubstFlags::UseErrorType);
     replacementTypes.push_back(replacement);
-  }
+  });
 
   // Form the stored conformances.
   SmallVector<ProtocolConformanceRef, 4> conformances;
@@ -318,6 +319,20 @@
   if (!type->isTypeParameter())
     return None;
 
+  auto genericSig = getGenericSignature();
+
+  // Fast path
+  unsigned index = 0;
+  for (auto reqt : genericSig->getRequirements()) {
+    if (reqt.getKind() == RequirementKind::Conformance) {
+      if (reqt.getFirstType()->isEqual(type) &&
+          reqt.getSecondType()->isEqual(proto->getDeclaredType()))
+        return getConformances()[index];
+
+      index++;
+    }
+  }
+
   // Retrieve the starting conformance from the conformance map.
   auto getInitialConformance =
     [&](Type type, ProtocolDecl *proto) -> Optional<ProtocolConformanceRef> {
@@ -338,8 +353,6 @@
       return None;
     };
 
-  auto genericSig = getGenericSignature();
-
   // If the type doesn't conform to this protocol, the result isn't formed
   // from these requirements.
   if (!genericSig->conformsToProtocol(type, proto)) {
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index c7d8caa..953d72f 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -313,15 +313,15 @@
       GenericSignature *sig = asImpl().getGenericSignature();
       assert(sig);
       auto canSig = sig->getCanonicalSignature();
-      
-      for (auto param : canSig->getGenericParams()) {
+
+      canSig->forEachParam([&](GenericTypeParamType *param, bool canonical) {
         // Currently, there are only type parameters. The parameter is a key
         // argument if it's canonical in its generic context.
         asImpl().addGenericParameter(GenericParamKind::Type,
-                 /*key argument*/ canSig->isCanonicalTypeInContext(param),
-                 /*extra argument*/ false);
-      }
-      
+                                     /*key argument*/ canonical,
+                                     /*extra argument*/ false);
+      });
+
       // Pad the structure up to four bytes for the following requirements.
       unsigned padding = (unsigned) -canSig->getGenericParams().size() & 3;
       for (unsigned i = 0; i < padding; ++i)
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 9a6883a..f35622a 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -238,9 +238,10 @@
   if (!signature) return;
 
   // Get all of the type metadata.
-  for (auto gp : signature->getSubstitutableParams()) {
-    callback({CanType(gp), nullptr});
-  }
+  signature->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
+    if (canonical)
+      callback({CanType(gp), nullptr});
+  });
 
   // Get the protocol conformances.
   for (auto &reqt : signature->getRequirements()) {
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index 6c69919..7a831fa 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -178,7 +178,12 @@
 
     // Build a SubstitutionMap.
     auto *genericSig = decl->getGenericSignature();
-    auto genericParams = genericSig->getSubstitutableParams();
+
+    SmallVector<GenericTypeParamType *, 4> genericParams;
+    genericSig->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
+      if (canonical)
+        genericParams.push_back(gp);
+    });
     if (genericParams.size() != args.size())
       return Type();
 
diff --git a/lib/SILOptimizer/IPO/EagerSpecializer.cpp b/lib/SILOptimizer/IPO/EagerSpecializer.cpp
index ef533dd..0cdf70d 100644
--- a/lib/SILOptimizer/IPO/EagerSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/EagerSpecializer.cpp
@@ -347,7 +347,11 @@
   auto GenericSig =
     GenericFunc->getLoweredFunctionType()->getGenericSignature();
   auto SubMap = ReInfo.getClonerParamSubstitutionMap();
-  for (auto ParamTy : GenericSig->getSubstitutableParams()) {
+
+  GenericSig->forEachParam([&](GenericTypeParamType *ParamTy, bool Canonical) {
+    if (!Canonical)
+      return;
+
     auto Replacement = Type(ParamTy).subst(SubMap);
     assert(!Replacement->hasTypeParameter());
 
@@ -368,7 +372,8 @@
                                   Replacement, LayoutInfo);
       }
     }
-  }
+  });
+
   static_cast<void>(FailedTypeCheckBB);
 
   if (OldReturnBB == &EntryBB) {
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index a586a0a..8622424 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -434,7 +434,11 @@
   bool HasConcreteGenericParams = false;
   bool HasNonArchetypeGenericParams = false;
   HasUnboundGenericParams = false;
-  for (auto GP : CalleeGenericSig->getSubstitutableParams()) {
+
+  CalleeGenericSig->forEachParam([&](GenericTypeParamType *GP, bool Canonical) {
+    if (!Canonical)
+      return;
+
     // Check only the substitutions for the generic parameters.
     // Ignore any dependent types, etc.
     auto Replacement = Type(GP).subst(CalleeParamSubMap);
@@ -458,11 +462,10 @@
             HasNonArchetypeGenericParams = true;
         }
       }
-      continue;
+    } else {
+      HasConcreteGenericParams = true;
     }
-
-    HasConcreteGenericParams = true;
-  }
+  });
 
   if (HasUnboundGenericParams) {
     // Bail if we cannot specialize generic substitutions, but all substitutions
@@ -1561,14 +1564,16 @@
   // Simply create a set of same-type requirements based on concrete
   // substitutions.
   SmallVector<Requirement, 4> Requirements;
-  for (auto GP : CalleeGenericSig->getSubstitutableParams()) {
+  CalleeGenericSig->forEachParam([&](GenericTypeParamType *GP, bool Canonical) {
+    if (!Canonical)
+      return;
     auto Replacement = Type(GP).subst(CalleeInterfaceToCallerArchetypeMap);
     if (Replacement->hasArchetype())
-      continue;
+      return;
     // Replacement is concrete. Add a same type requirement.
     Requirement Req(RequirementKind::SameType, GP, Replacement);
     Requirements.push_back(Req);
-  }
+  });
 
   // Create a new generic signature by taking the existing one
   // and adding new requirements to it. No need to introduce
diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
index a8d9d99..80102db 100644
--- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
+++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
@@ -625,10 +625,15 @@
 static bool isCallerAndCalleeLayoutConstraintsCompatible(FullApplySite AI) {
   SILFunction *Callee = AI.getReferencedFunction();
   auto CalleeSig = Callee->getLoweredFunctionType()->getGenericSignature();
-  auto SubstParams = CalleeSig->getSubstitutableParams();
   auto AISubs = AI.getSubstitutionMap();
-  for (auto idx : indices(SubstParams)) {
-    auto Param = SubstParams[idx];
+
+  SmallVector<GenericTypeParamType *, 4> SubstParams;
+  CalleeSig->forEachParam([&](GenericTypeParamType *Param, bool Canonical) {
+    if (Canonical)
+      SubstParams.push_back(Param);
+  });
+
+  for (auto Param : SubstParams) {
     // Map the parameter into context
     auto ContextTy = Callee->mapTypeIntoContext(Param->getCanonicalType());
     auto Archetype = ContextTy->getAs<ArchetypeType>();
diff --git a/lib/SILOptimizer/Utils/SpecializationMangler.cpp b/lib/SILOptimizer/Utils/SpecializationMangler.cpp
index aea7e04..03f5746 100644
--- a/lib/SILOptimizer/Utils/SpecializationMangler.cpp
+++ b/lib/SILOptimizer/Utils/SpecializationMangler.cpp
@@ -83,10 +83,12 @@
   }
 
   bool First = true;
-  for (auto ParamType : Sig->getSubstitutableParams()) {
-    appendType(Type(ParamType).subst(SubMap)->getCanonicalType());
-    appendListSeparator(First);
-  }
+  Sig->forEachParam([&](GenericTypeParamType *ParamType, bool Canonical) {
+    if (Canonical) {
+      appendType(Type(ParamType).subst(SubMap)->getCanonicalType());
+      appendListSeparator(First);
+    }
+  });
   assert(!First && "no generic substitutions");
 
   if (isInlined)
diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp
index 1814e55..7ac46ba 100644
--- a/lib/Sema/CSBindings.cpp
+++ b/lib/Sema/CSBindings.cpp
@@ -333,7 +333,7 @@
   // should be allowed to escape. As a result we allow anything
   // passed in to escape.
   if (auto *fnTy = type->getAs<AnyFunctionType>())
-    if (typeVar->getImpl().getArchetype() && !shouldAttemptFixes())
+    if (typeVar->getImpl().getGenericParameter() && !shouldAttemptFixes())
       type = fnTy->withExtInfo(fnTy->getExtInfo().withNoEscape(false));
 
   // Check whether we can perform this binding.
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index e186492..912246d 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -472,15 +472,16 @@
   /// true.
   bool diagnoseAmbiguousMultiStatementClosure(ClosureExpr *closure);
 
-  /// Check the associated constraint system to see if it has any archetypes
-  /// not properly resolved or missing. If so, diagnose the problem with
-  /// an error and return true.
-  bool diagnoseArchetypeAmbiguity();
+  /// Check the associated constraint system to see if it has any opened generic
+  /// parameters that were not bound to a fixed type. If so, diagnose the
+  /// problem with an error and return true.
+  bool diagnoseAmbiguousGenericParameters();
 
-  /// Emit an error message about an unbound generic parameter existing, and
-  /// emit notes referring to the target of a diagnostic, e.g., the function
-  /// or parameter being used.
-  void diagnoseUnboundArchetype(ArchetypeType *archetype, Expr *anchor);
+  /// Emit an error message about an unbound generic parameter, and emit notes
+  /// referring to the target of a diagnostic, e.g., the function or parameter
+  /// being used.
+  void diagnoseAmbiguousGenericParameter(GenericTypeParamType *paramTy,
+                                         Expr *anchor);
 
   /// Produce a diagnostic for a general member-lookup failure (irrespective of
   /// the exact expression kind).
@@ -4687,9 +4688,12 @@
                          .getOldType()
                          ->getWithoutSpecifierType();
 
-      if (argType->is<ArchetypeType>()) {
-        diagnoseUnboundArchetype(archetype, fnExpr);
-        return true;
+      if (auto *archetype = argType->getAs<ArchetypeType>()) {
+        auto interfaceTy = archetype->getInterfaceType();
+        if (auto *paramTy = interfaceTy->getAs<GenericTypeParamType>()) {
+          diagnoseAmbiguousGenericParameter(paramTy, fnExpr);
+          return true;
+        }
       }
 
       if (isUnresolvedOrTypeVarType(argType) || argType->hasError())
@@ -7735,22 +7739,18 @@
   diagnosis.diagnoseAmbiguity(expr);
 }
 
-// FIXME: Instead of doing this, we should store the decl in the type
-// variable, or in the locator.
-static bool hasArchetype(const GenericTypeDecl *generic,
-                         ArchetypeType *archetype) {
-  assert(!archetype->getOpenedExistentialType() &&
-         !archetype->getParent());
-
-  auto genericEnv = generic->getGenericEnvironment();
-  if (!genericEnv)
+static bool hasGenericParameter(const GenericTypeDecl *generic,
+                                GenericTypeParamType *paramTy) {
+  auto *decl = paramTy->getDecl();
+  if (!decl)
     return false;
 
-  return archetype->getGenericEnvironment() == genericEnv;
+  return decl->getDeclContext() == generic;
 }
 
-static void noteArchetypeSource(const TypeLoc &loc, ArchetypeType *archetype,
-                                ConstraintSystem &cs) {
+static void noteGenericParameterSource(const TypeLoc &loc,
+                                       GenericTypeParamType *paramTy,
+                                       ConstraintSystem &cs) {
   const GenericTypeDecl *FoundDecl = nullptr;
   const ComponentIdentTypeRepr *FoundGenericTypeBase = nullptr;
 
@@ -7759,10 +7759,10 @@
     struct FindGenericTypeDecl : public ASTWalker {
       const GenericTypeDecl *FoundDecl = nullptr;
       const ComponentIdentTypeRepr *FoundGenericTypeBase = nullptr;
-      ArchetypeType *Archetype;
+      GenericTypeParamType *ParamTy;
 
-      FindGenericTypeDecl(ArchetypeType *Archetype)
-          : Archetype(Archetype) {}
+      FindGenericTypeDecl(GenericTypeParamType *ParamTy)
+          : ParamTy(ParamTy) {}
       
       bool walkToTypeReprPre(TypeRepr *T) override {
         // If we already emitted the note, we're done.
@@ -7771,7 +7771,7 @@
         if (auto ident = dyn_cast<ComponentIdentTypeRepr>(T)) {
           auto *generic =
               dyn_cast_or_null<GenericTypeDecl>(ident->getBoundDecl());
-          if (generic && hasArchetype(generic, Archetype)) {
+          if (generic && hasGenericParameter(generic, ParamTy)) {
             FoundDecl = generic;
             FoundGenericTypeBase = ident;
             return false;
@@ -7780,7 +7780,7 @@
         // Keep walking.
         return true;
       }
-    } findGenericTypeDecl(archetype);
+    } findGenericTypeDecl(paramTy);
 
     typerepr->walk(findGenericTypeDecl);
     FoundDecl = findGenericTypeDecl.FoundDecl;
@@ -7791,7 +7791,7 @@
   // type checked expression.
   if (!FoundDecl) {
     if (const GenericTypeDecl *generic = loc.getType()->getAnyGeneric())
-      if (hasArchetype(generic, archetype))
+      if (hasGenericParameter(generic, paramTy))
         FoundDecl = generic;
   }
 
@@ -7804,7 +7804,7 @@
       type = typeAlias->getUnboundGenericType();
     else
       type = FoundDecl->getDeclaredInterfaceType();
-    tc.diagnose(FoundDecl, diag::archetype_declared_in_type, archetype, type);
+    tc.diagnose(FoundDecl, diag::archetype_declared_in_type, paramTy, type);
   }
 
   if (FoundGenericTypeBase && !isa<GenericIdentTypeRepr>(FoundGenericTypeBase)){
@@ -8065,25 +8065,23 @@
 /// Check the associated constraint system to see if it has any archetypes
 /// not properly resolved or missing. If so, diagnose the problem with
 /// an error and return true.
-bool FailureDiagnosis::diagnoseArchetypeAmbiguity() {
-  using Archetype = std::tuple<ArchetypeType *, ConstraintLocator *, unsigned>;
+bool FailureDiagnosis::diagnoseAmbiguousGenericParameters() {
+  using GenericParameter = std::tuple<GenericTypeParamType *,
+                                      ConstraintLocator *,
+                                      unsigned>;
 
-  llvm::SmallVector<Archetype, 2> unboundParams;
-  // Check out all of the type variables lurking in the system.  If any are
-  // unbound archetypes, then the problem is that it couldn't be resolved.
+  llvm::SmallVector<GenericParameter, 2> unboundParams;
+  // Check out all of the type variables lurking in the system.  If any free
+  // type variables were created when opening generic parameters, diagnose
+  // that the generic parameter could not be inferred.
   for (auto tv : CS.getTypeVariables()) {
     auto &impl = tv->getImpl();
 
     if (impl.hasRepresentativeOrFixed())
       continue;
 
-    // If this is a conversion to a type variable used to form an archetype,
-    // Then diagnose this as a generic parameter that could not be resolved.
-    auto archetype = impl.getArchetype();
-
-    // Only diagnose archetypes that don't have a parent, i.e., ones
-    // that correspond to generic parameters.
-    if (!archetype || archetype->getParent())
+    auto *paramTy = impl.getGenericParameter();
+    if (!paramTy)
       continue;
 
     // Number of constraints related to particular unbound parameter
@@ -8117,22 +8115,22 @@
     }
 
     auto locator = impl.getLocator();
-    unboundParams.push_back(
-        std::make_tuple(archetype, locator, numConstraints));
+    unboundParams.emplace_back(paramTy, locator, numConstraints);
   }
 
   // We've found unbound generic parameters, let's diagnose
   // based on the number of constraints each one is related to.
   if (!unboundParams.empty()) {
-    // Let's prioritize archetypes that don't have any constraints associated.
+    // Let's prioritize generic parameters that don't have any constraints
+    // associated.
     std::stable_sort(unboundParams.begin(), unboundParams.end(),
-                     [](Archetype a, Archetype b) {
+                     [](GenericParameter a, GenericParameter b) {
                        return std::get<2>(a) < std::get<2>(b);
                      });
 
     auto param = unboundParams.front();
-    diagnoseUnboundArchetype(std::get<0>(param),
-                             std::get<1>(param)->getAnchor());
+    diagnoseAmbiguousGenericParameter(std::get<0>(param),
+                                      std::get<1>(param)->getAnchor());
     return true;
   }
 
@@ -8142,18 +8140,19 @@
 /// Emit an error message about an unbound generic parameter existing, and
 /// emit notes referring to the target of a diagnostic, e.g., the function
 /// or parameter being used.
-void FailureDiagnosis::diagnoseUnboundArchetype(ArchetypeType *archetype,
-                                                Expr *anchor) {
+void FailureDiagnosis::
+diagnoseAmbiguousGenericParameter(GenericTypeParamType *paramTy,
+                                  Expr *anchor) {
   auto &tc = CS.getTypeChecker();
 
-  // The archetype may come from the explicit type in a cast expression.
+  // The generic parameter may come from the explicit type in a cast expression.
   if (auto *ECE = dyn_cast_or_null<ExplicitCastExpr>(anchor)) {
     tc.diagnose(ECE->getLoc(), diag::unbound_generic_parameter_cast,
-                archetype, ECE->getCastTypeLoc().getType())
+                paramTy, ECE->getCastTypeLoc().getType())
       .highlight(ECE->getCastTypeLoc().getSourceRange());
 
     // Emit a note specifying where this came from, if we can find it.
-    noteArchetypeSource(ECE->getCastTypeLoc(), archetype, CS);
+    noteGenericParameterSource(ECE->getCastTypeLoc(), paramTy, CS);
     return;
   }
 
@@ -8173,17 +8172,17 @@
 
   
   // Otherwise, emit an error message on the expr we have, and emit a note
-  // about where the archetype came from.
-  tc.diagnose(expr->getLoc(), diag::unbound_generic_parameter, archetype);
+  // about where the generic parameter came from.
+  tc.diagnose(expr->getLoc(), diag::unbound_generic_parameter, paramTy);
   
   // If we have an anchor, drill into it to emit a
-  // "note: archetype declared here".
+  // "note: generic parameter declared here".
   if (!anchor) return;
 
 
   if (auto TE = dyn_cast<TypeExpr>(anchor)) {
     // Emit a note specifying where this came from, if we can find it.
-    noteArchetypeSource(TE->getTypeLoc(), archetype, CS);
+    noteGenericParameterSource(TE->getTypeLoc(), paramTy, CS);
     return;
   }
 
@@ -8232,8 +8231,8 @@
 /// Emit an ambiguity diagnostic about the specified expression.
 void FailureDiagnosis::diagnoseAmbiguity(Expr *E) {
   // First, let's try to diagnose any problems related to ambiguous
-  // archetypes (generic parameters) present in the constraint system.
-  if (diagnoseArchetypeAmbiguity())
+  // generic parameters present in the constraint system.
+  if (diagnoseAmbiguousGenericParameters())
     return;
 
   // Unresolved/Anonymous ClosureExprs are common enough that we should give
diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp
index c2c6664..08b73ed 100644
--- a/lib/Sema/CSDiagnostics.cpp
+++ b/lib/Sema/CSDiagnostics.cpp
@@ -271,12 +271,12 @@
     return false;
 
   auto &last = path.back();
-  if (last.getKind() != ConstraintLocator::Archetype)
+  if (last.getKind() != ConstraintLocator::GenericParameter)
     return false;
 
-  auto *archetype = last.getArchetype();
+  auto *paramTy = last.getGenericParameter();
   emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
-                 archetype);
+                 paramTy);
   return true;
 }
 
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index d75bb0a..2cfdb67 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1532,7 +1532,7 @@
   // represent an opened archetype. If we allowed this it would allow
   // the noescape function to potentially escape.
   if (auto *fnTy = type->getAs<FunctionType>()) {
-    if (fnTy->isNoEscape() && typeVar->getImpl().getArchetype()) {
+    if (fnTy->isNoEscape() && typeVar->getImpl().getGenericParameter()) {
       if (shouldAttemptFixes()) {
         auto *fix = MarkExplicitlyEscaping::create(
             *this, getConstraintLocator(locator));
diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp
index c107aec..6b84550 100644
--- a/lib/Sema/ConstraintLocator.cpp
+++ b/lib/Sema/ConstraintLocator.cpp
@@ -33,8 +33,8 @@
   for (auto elt : path) {
     id.AddInteger(elt.getKind());
     switch (elt.getKind()) {
-    case Archetype:
-      id.AddPointer(elt.getArchetype()->getCanonicalType().getPointer());
+    case GenericParameter:
+      id.AddPointer(elt.getGenericParameter());
       break;
 
     case Requirement:
@@ -109,8 +109,8 @@
   for (auto elt : getPath()) {
     out << " -> ";
     switch (elt.getKind()) {
-    case Archetype:
-      out << "archetype '" << elt.getArchetype()->getString() << "'";
+    case GenericParameter:
+      out << "generic parameter '" << elt.getGenericParameter()->getString() << "'";
       break;
 
     case ApplyArgument:
diff --git a/lib/Sema/ConstraintLocator.h b/lib/Sema/ConstraintLocator.h
index 0cb7d41..83e5de5 100644
--- a/lib/Sema/ConstraintLocator.h
+++ b/lib/Sema/ConstraintLocator.h
@@ -59,10 +59,10 @@
     ApplyFunction,
     /// Matching an argument to a parameter.
     ApplyArgToParam,
-    /// \brief An archetype being opened.
+    /// \brief A generic parameter being opened.
     ///
-    /// Also contains the archetype itself.
-    Archetype,
+    /// Also contains the generic parameter type itself.
+    GenericParameter,
     /// \brief The argument type of a function.
     FunctionArgument,
     /// \brief The result type of a function.
@@ -133,7 +133,7 @@
     switch (kind) {
     case ApplyArgument:
     case ApplyFunction:
-    case Archetype:
+    case GenericParameter:
     case FunctionArgument:
     case FunctionResult:
     case OptionalPayload:
@@ -205,7 +205,7 @@
     case RValueAdjustment:
     case SubscriptMember:
     case OpenedGeneric:
-    case Archetype:
+    case GenericParameter:
     case GenericArgument:
     case NamedTupleElement:
     case TupleElement:
@@ -233,7 +233,7 @@
   class PathElement {
     /// \brief Describes the kind of data stored here.
     enum StoredKind : unsigned char {
-      StoredArchetype,
+      StoredGenericParameter,
       StoredRequirement,
       StoredWitness,
       StoredKindAndValue
@@ -291,13 +291,13 @@
              "Path element requires value");
     }
 
-    PathElement(ArchetypeType *archetype)
-      : storage((reinterpret_cast<uintptr_t>(archetype) >> 2)),
-        storedKind(StoredArchetype)
+    PathElement(GenericTypeParamType *type)
+      : storage((reinterpret_cast<uintptr_t>(type) >> 2)),
+        storedKind(StoredGenericParameter)
     {
-      static_assert(alignof(ArchetypeType) >= 4,
+      static_assert(alignof(GenericTypeParamType) >= 4,
                     "archetypes insufficiently aligned");
-      assert(getArchetype() == archetype);
+      assert(getGenericParameter() == type);
     }
 
     PathElement(PathElementKind kind, ValueDecl *decl)
@@ -353,8 +353,8 @@
     /// \brief Retrieve the kind of path element.
     PathElementKind getKind() const {
       switch (static_cast<StoredKind>(storedKind)) {
-      case StoredArchetype:
-        return Archetype;
+      case StoredGenericParameter:
+        return GenericParameter;
 
       case StoredRequirement:
         return Requirement;
@@ -400,10 +400,12 @@
       return reinterpret_cast<ValueDecl *>(storage << 2);
     }
 
-    /// \brief Retrieve the actual archetype for an archetype path element.
-    ArchetypeType *getArchetype() const {
-      assert(getKind() == Archetype && "Not an archetype path element");
-      return reinterpret_cast<ArchetypeType *>(storage << 2);
+    /// \brief Retrieve the actual archetype for a generic parameter path
+    /// element.
+    GenericTypeParamType *getGenericParameter() const {
+      assert(getKind() == GenericParameter &&
+             "Not a generic parameter path element");
+      return reinterpret_cast<GenericTypeParamType *>(storage << 2);
     }
 
     /// Retrieve the declaration for a requirement path element.
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 3d457a7..926227f 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -801,7 +801,7 @@
   SmallVector<LocatorPathElt, 2> pathElts;
   Expr *anchor = locator.getLocatorParts(pathElts);
   if (!pathElts.empty() &&
-      pathElts.back().getKind() == ConstraintLocator::Archetype)
+      pathElts.back().getKind() == ConstraintLocator::GenericParameter)
     return;
 
   // If the locator is empty, ignore it.
@@ -1070,14 +1070,11 @@
     return;
 
   auto locatorPtr = getConstraintLocator(locator);
-  auto *genericEnv = innerDC->getGenericEnvironmentOfContext();
 
   // Create the type variables for the generic parameters.
   for (auto gp : sig->getGenericParams()) {
-    auto contextTy = GenericEnvironment::mapTypeIntoContext(genericEnv, gp);
-    if (auto *archetype = contextTy->getAs<ArchetypeType>())
-      locatorPtr = getConstraintLocator(
-          locator.withPathElement(LocatorPathElt(archetype)));
+    locatorPtr = getConstraintLocator(
+        locator.withPathElement(LocatorPathElt(gp)));
 
     auto typeVar = createTypeVariable(locatorPtr,
                                       TVO_PrefersSubtypeBinding);
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 0bbd0d5..48ba066 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -279,8 +279,8 @@
     return locator;
   }
 
-  /// \brief Retrieve the archetype opened by this type variable.
-  ArchetypeType *getArchetype() const;
+  /// \brief Retrieve the generic parameter opened by this type variable.
+  GenericTypeParamType *getGenericParameter() const;
 
   /// \brief Retrieve the representative of the equivalence class to which this
   /// type variable belongs.
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index ab3273c..eec2c2b 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -73,14 +73,16 @@
   typeVar->getImpl().ParentOrFixed = ParentOrFixed;
 }
 
-ArchetypeType *TypeVariableType::Implementation::getArchetype() const {
-  // Check whether we have a path that terminates at an archetype locator.
+GenericTypeParamType *
+TypeVariableType::Implementation::getGenericParameter() const {
+  // Check whether we have a path that terminates at a generic parameter
+  // locator.
   if (!locator || locator->getPath().empty() ||
-      locator->getPath().back().getKind() != ConstraintLocator::Archetype)
+      locator->getPath().back().getKind() != ConstraintLocator::GenericParameter)
     return nullptr;
 
   // Retrieve the archetype.
-  return locator->getPath().back().getArchetype();
+  return locator->getPath().back().getGenericParameter();
 }
 
 // Only allow allocation of resolved overload set list items using the
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index f9b0e10..31686eb 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -5305,15 +5305,6 @@
       conformance->setWitness(req, Witness::forOpaque(req));
     };
 
-    // Requirement -> synthetic map.
-    if (auto syntheticSig = getGenericSignature(*rawIDIter++)) {
-      // Create the synthetic environment.
-      syntheticEnv = syntheticSig->createGenericEnvironment();
-    }
-
-    // Requirement -> synthetic substitutions.
-    SubstitutionMap reqToSyntheticSubs = getSubstitutionMap(*rawIDIter++);
-
     // Witness substitutions.
     SubstitutionMap witnessSubstitutions = getSubstitutionMap(*rawIDIter++);
 
@@ -5324,8 +5315,7 @@
     }
 
     // Set the witness.
-    trySetWitness(Witness(witness, witnessSubstitutions,
-                          syntheticEnv, reqToSyntheticSubs));
+    trySetWitness(Witness::forDeserialized(witness, witnessSubstitutions));
   }
   assert(rawIDIter <= rawIDs.end() && "read too much");
   
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 66013ce..905619e 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1595,18 +1595,21 @@
       // If there is no witness, we're done.
       if (!witness.getDecl()) return;
 
-      if (auto *genericEnv = witness.getSyntheticEnvironment()) {
-        // Generic signature.
-        auto *genericSig = genericEnv->getGenericSignature();
-        data.push_back(addGenericSignatureRef(genericSig));
-      } else {
-        data.push_back(/*null generic signature*/0);
-      }
+      auto subs = witness.getSubstitutions();
 
-      data.push_back(
-        addSubstitutionMapRef(witness.getRequirementToSyntheticSubs()));
-      data.push_back(
-        addSubstitutionMapRef(witness.getSubstitutions()));
+      // Canonicalize away typealiases, since these substitutions aren't used
+      // for diagnostics and we reference fewer declarations that way.
+      subs = subs.getCanonical();
+
+      // Map archetypes to type parameters, since we always substitute them
+      // away. Note that in a merge-modules pass, we're serializing conformances
+      // that we deserialized, so they will already have their replacement types
+      // in terms of interface types; hence the hasArchetypes() check is
+      // necessary for correctness, not just as a fast path.
+      if (subs.hasArchetypes())
+        subs = subs.mapReplacementTypesOutOfContext();
+
+      data.push_back(addSubstitutionMapRef(subs));
   });
 
   unsigned numSignatureConformances =
diff --git a/test/Frontend/debug-generic-signatures.swift b/test/Frontend/debug-generic-signatures.swift
index cff7ce0..3ec6d50 100644
--- a/test/Frontend/debug-generic-signatures.swift
+++ b/test/Frontend/debug-generic-signatures.swift
@@ -118,8 +118,7 @@
 // CHECK-NEXT:              (normal_conformance type=Recur protocol=P2 (details printed above))))
 // CHECK-NEXT:         (conformance type=U
 // CHECK-NEXT:            (normal_conformance type=Recur protocol=P2 (details printed above))))
-// CHECK-NEXT:     conforms_to: NonRecur P2
-// CHECK-NEXT:     conforms_to: Recur P2
+// CHECK-NEXT:     (conditional requirements unable to be computed)
 // CHECK-NEXT:     (normal_conformance type=Super<T, U> protocol=P2
 // CHECK-NEXT:       (assoc_type req=A type=T)
 // CHECK-NEXT:       (assoc_type req=B type=T)
diff --git a/test/Serialization/Inputs/conformance-multi-file-other.swift b/test/Serialization/Inputs/conformance-multi-file-other.swift
index 73b1aa2..bac7587 100644
--- a/test/Serialization/Inputs/conformance-multi-file-other.swift
+++ b/test/Serialization/Inputs/conformance-multi-file-other.swift
@@ -9,3 +9,9 @@
 extension Base : BaseProto {
   public func method() {}
 }
+
+// Make sure we can serialize witness substitutions where replacement types
+// involve generic parameters.
+public class GenericWitness<T> : BaseProto {
+  public func method() {}
+}
diff --git a/test/decl/protocol/req/recursion.swift b/test/decl/protocol/req/recursion.swift
index 59c1217..9fb66a3 100644
--- a/test/decl/protocol/req/recursion.swift
+++ b/test/decl/protocol/req/recursion.swift
@@ -48,7 +48,7 @@
 // expected-error@-2 {{generic struct 'S' references itself}}
   func f(a: A.T) {
     g(a: id(t: a))
-    // expected-error@-1 {{generic parameter 'T' could not be inferred}}
+    // expected-error@-1 {{cannot convert value of type 'A.T' to expected argument type 'S<_>'}}
     _ = A.T.self
   }
 
diff --git a/validation-test/compiler_crashers_2_fixed/0158-rdar40165062.swift b/validation-test/compiler_crashers_2_fixed/0158-rdar40165062.swift
index 388f1b7..e5cf3b6 100644
--- a/validation-test/compiler_crashers_2_fixed/0158-rdar40165062.swift
+++ b/validation-test/compiler_crashers_2_fixed/0158-rdar40165062.swift
@@ -1,9 +1,11 @@
 // RUN: %target-typecheck-verify-swift
 
-struct Foo<T, U> {
+struct Foo<T, U> { // expected-note {{'U' declared as parameter to type 'Foo'}}
   var value: U
   func bar() -> Foo<T, U> {
-    return Foo(value) // expected-error {{generic parameter 'T' could not be inferred}}
+    return Foo(value)
+    // expected-error@-1 {{generic parameter 'U' could not be inferred}}
+    // expected-note@-2 {{explicitly specify the generic arguments to fix this issue}}
   }
 }