Merge pull request #17419 from slavapestov/generic-init-inherit-fix

Sema: Use a different strategy for computing derived initializer generic signature
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 2c81d96..7f017f6 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2048,36 +2048,6 @@
       newParams.push_back(newParam);
     }
 
-    // Substitution map that maps the generic parameters of the superclass
-    // to the generic parameters of the derived class, and the generic
-    // parameters of the superclass initializer to the generic parameters
-    // of the derived class initializer.
-    auto *superclassSig = superclassCtor->getGenericSignature();
-    if (superclassSig) {
-      unsigned superclassDepth = 0;
-      if (auto *genericSig = superclassDecl->getGenericSignature())
-        superclassDepth = genericSig->getGenericParams().back()->getDepth() + 1;
-
-      subMap = SubstitutionMap::get(
-        superclassSig,
-        [&](SubstitutableType *type) -> Type {
-          auto *gp = cast<GenericTypeParamType>(type);
-          if (gp->getDepth() < superclassDepth)
-            return Type(gp).subst(subMap);
-          return CanGenericTypeParamType::get(
-              gp->getDepth() - superclassDepth + depth,
-              gp->getIndex(),
-              ctx);
-        },
-        [&](CanType depTy, Type substTy, ProtocolDecl *proto)
-            -> Optional<ProtocolConformanceRef> {
-          if (auto conf = subMap.lookupConformance(depTy, proto))
-            return conf;
-
-          return ProtocolConformanceRef(proto);
-        });
-    }
-
     // We don't have to clone the requirements, because they're not
     // used for anything.
     genericParams = GenericParamList::create(ctx,
@@ -2088,18 +2058,52 @@
                                              SourceLoc());
     genericParams->setOuterParameters(classDecl->getGenericParamsOfContext());
 
+    // Build a generic signature for the derived class initializer.
     GenericSignatureBuilder builder(ctx);
     builder.addGenericSignature(classDecl->getGenericSignature());
 
+    // Add the generic parameters.
     for (auto *newParam : newParams)
       builder.addGenericParameter(newParam);
 
     auto source =
       GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
+    auto *superclassSig = superclassCtor->getGenericSignature();
+
+    unsigned superclassDepth = 0;
+    if (auto *genericSig = superclassDecl->getGenericSignature())
+      superclassDepth = genericSig->getGenericParams().back()->getDepth() + 1;
+
+    // We're going to be substituting the requirements of the base class
+    // initializer to form the requirements of the derived class initializer.
+    auto substFn = [&](SubstitutableType *type) -> Type {
+      auto *gp = cast<GenericTypeParamType>(type);
+      if (gp->getDepth() < superclassDepth)
+        return Type(gp).subst(subMap);
+      return CanGenericTypeParamType::get(
+        gp->getDepth() - superclassDepth + depth,
+          gp->getIndex(),
+          ctx);
+    };
+
+    auto lookupConformanceFn =
+      [&](CanType depTy, Type substTy, ProtocolDecl *proto)
+        -> Optional<ProtocolConformanceRef> {
+      if (auto conf = subMap.lookupConformance(depTy, proto))
+        return conf;
+
+      return ProtocolConformanceRef(proto);
+    };
+
     for (auto reqt : superclassSig->getRequirements())
-      if (auto substReqt = reqt.subst(subMap))
+      if (auto substReqt = reqt.subst(substFn, lookupConformanceFn))
         builder.addRequirement(*substReqt, source, nullptr);
 
+    // Now form the substitution map that will be used to remap parameter
+    // types.
+    subMap = SubstitutionMap::get(superclassSig,
+                                  substFn, lookupConformanceFn);
+
     genericSig = std::move(builder).computeGenericSignature(SourceLoc());
     genericEnv = genericSig->createGenericEnvironment();
   } else {
diff --git a/test/SILGen/inherit_initializers.swift b/test/SILGen/inherit_initializers.swift
index 731fd44..7daff76 100644
--- a/test/SILGen/inherit_initializers.swift
+++ b/test/SILGen/inherit_initializers.swift
@@ -122,4 +122,6 @@
   init<Z>(_: Z) where Z : Q, Z.A == X, Z.B == Y, X == Y {}
 }
 
-class Once<T> : Twice<T, T> {}
\ No newline at end of file
+class Pair<T, U> : Twice<T, U> {}
+
+class Once<T> : Twice<T, T> {}