@@ -418,30 +418,49 @@ synthesizeStubBody(AbstractFunctionDecl *fn, void *) {
418418 /* isTypeChecked=*/ true };
419419}
420420
421- static std::tuple<GenericSignature, GenericParamList *, SubstitutionMap>
422- configureGenericDesignatedInitOverride (ASTContext &ctx,
421+ namespace {
422+ struct DesignatedInitOverrideInfo {
423+ GenericSignature GenericSig;
424+ GenericParamList *GenericParams;
425+ SubstitutionMap OverrideSubMap;
426+ };
427+ }
428+
429+ static DesignatedInitOverrideInfo
430+ computeDesignatedInitOverrideSignature (ASTContext &ctx,
423431 ClassDecl *classDecl,
424432 Type superclassTy,
425433 ConstructorDecl *superclassCtor) {
426- auto *superclassDecl = superclassTy->getAnyNominal ();
427-
428434 auto *moduleDecl = classDecl->getParentModule ();
429- auto subMap = superclassTy->getContextSubstitutionMap (
430- moduleDecl, superclassDecl);
431435
432- GenericSignature genericSig;
433- auto *genericParams = superclassCtor->getGenericParams ();
436+ auto *superclassDecl = superclassTy->getAnyNominal ();
434437
438+ auto classSig = classDecl->getGenericSignature ();
435439 auto superclassCtorSig = superclassCtor->getGenericSignature ();
436440 auto superclassSig = superclassDecl->getGenericSignature ();
437441
442+ // These are our outputs.
443+ GenericSignature genericSig = classSig;
444+ auto *genericParams = superclassCtor->getGenericParams ();
445+ auto subMap = superclassTy->getContextSubstitutionMap (
446+ moduleDecl, superclassDecl);
447+
438448 if (superclassCtorSig.getPointer () != superclassSig.getPointer ()) {
449+ // If the base initiliazer's generic signature is different
450+ // from that of the base class, the base class initializer either
451+ // has generic parameters or a 'where' clause.
452+ //
453+ // We need to "rebase" the requirements on top of the derived class's
454+ // generic signature.
455+
439456 SmallVector<GenericTypeParamDecl *, 4 > newParams;
440457 SmallVector<GenericTypeParamType *, 1 > newParamTypes;
441458
442- // Inheriting initializers that have their own generic parameters
459+ // If genericParams is non-null, the base class initializer has its own
460+ // generic parameters. Otherwise, it is non-generic with a contextual
461+ // 'where' clause.
443462 if (genericParams) {
444- // First, clone the superclass constructor 's generic parameter list,
463+ // First, clone the base class initializer 's generic parameter list,
445464 // but change the depth of the generic parameters to be one greater
446465 // than the depth of the subclass.
447466 unsigned depth = 0 ;
@@ -457,8 +476,8 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
457476 newParams.push_back (newParam);
458477 }
459478
460- // We don't have to clone the requirements , because they're not
461- // used for anything.
479+ // We don't have to clone the RequirementReprs , because they're not
480+ // used for anything other than SIL mode .
462481 genericParams = GenericParamList::create (ctx,
463482 SourceLoc (),
464483 newParams,
@@ -473,7 +492,7 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
473492 }
474493 }
475494
476- // Build a generic signature for the derived class initializer .
495+ // The depth at which the initializer's own generic parameters start, if any .
477496 unsigned superclassDepth = 0 ;
478497 if (superclassSig)
479498 superclassDepth = superclassSig->getGenericParams ().back ()->getDepth () + 1 ;
@@ -482,44 +501,52 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
482501 // initializer to form the requirements of the derived class initializer.
483502 auto substFn = [&](SubstitutableType *type) -> Type {
484503 auto *gp = cast<GenericTypeParamType>(type);
504+ // Generic parameters of the base class itself are mapped via the
505+ // substitution map of the superclass type.
485506 if (gp->getDepth () < superclassDepth)
486507 return Type (gp).subst (subMap);
508+
509+ // Generic parameters added by the base class initializer map to the new
510+ // generic parameters of the derived initializer.
487511 return genericParams->getParams ()[gp->getIndex ()]
488512 ->getDeclaredInterfaceType ();
489513 };
490514
491- auto lookupConformanceFn =
492- [&](CanType depTy, Type substTy,
493- ProtocolDecl *proto) -> ProtocolConformanceRef {
494- if (auto conf = subMap.lookupConformance (depTy, proto))
495- return conf;
496-
497- return ProtocolConformanceRef (proto);
498- };
499-
500- SmallVector<Requirement, 2 > requirements;
501- for (auto reqt : superclassCtorSig->getRequirements ())
502- if (auto substReqt = reqt.subst (substFn, lookupConformanceFn))
503- requirements.push_back (*substReqt);
504-
505- // Now form the substitution map that will be used to remap parameter
506- // types.
507- subMap = SubstitutionMap::get (superclassCtorSig,
508- substFn, lookupConformanceFn);
509-
510- genericSig = evaluateOrDefault (
511- ctx.evaluator ,
512- AbstractGenericSignatureRequest{
513- classDecl->getGenericSignature ().getPointer (),
514- std::move (newParamTypes),
515- std::move (requirements)
516- },
517- GenericSignature ());
518- } else {
519- genericSig = classDecl->getGenericSignature ();
515+ // If we don't have any new generic parameters and the derived class is
516+ // not generic, the base class initializer's 'where' clause should already
517+ // be fully satisfied, and we can just drop it.
518+ if (genericParams != nullptr || classSig) {
519+ auto lookupConformanceFn =
520+ [&](CanType depTy, Type substTy,
521+ ProtocolDecl *proto) -> ProtocolConformanceRef {
522+ if (auto conf = subMap.lookupConformance (depTy, proto))
523+ return conf;
524+
525+ return ProtocolConformanceRef (proto);
526+ };
527+
528+ SmallVector<Requirement, 2 > requirements;
529+ for (auto reqt : superclassCtorSig->getRequirements ())
530+ if (auto substReqt = reqt.subst (substFn, lookupConformanceFn))
531+ requirements.push_back (*substReqt);
532+
533+ // Now form the substitution map that will be used to remap parameter
534+ // types.
535+ subMap = SubstitutionMap::get (superclassCtorSig,
536+ substFn, lookupConformanceFn);
537+
538+ genericSig = evaluateOrDefault (
539+ ctx.evaluator ,
540+ AbstractGenericSignatureRequest{
541+ classSig.getPointer (),
542+ std::move (newParamTypes),
543+ std::move (requirements)
544+ },
545+ GenericSignature ());
546+ }
520547 }
521548
522- return std::make_tuple ( genericSig, genericParams, subMap) ;
549+ return DesignatedInitOverrideInfo{ genericSig, genericParams, subMap} ;
523550}
524551
525552static void
@@ -703,17 +730,33 @@ createDesignatedInitOverride(ClassDecl *classDecl,
703730 return nullptr ;
704731 }
705732
706- GenericSignature genericSig;
707- GenericParamList *genericParams;
708- SubstitutionMap subMap;
709-
710- std::tie (genericSig, genericParams, subMap) =
711- configureGenericDesignatedInitOverride (ctx,
733+ auto overrideInfo =
734+ computeDesignatedInitOverrideSignature (ctx,
712735 classDecl,
713736 superclassTy,
714737 superclassCtor);
715738
716- // Determine the initializer parameters.
739+ if (auto superclassCtorSig = superclassCtor->getGenericSignature ()) {
740+ auto *genericEnv = (overrideInfo.GenericSig
741+ ? overrideInfo.GenericSig ->getGenericEnvironment ()
742+ : nullptr );
743+
744+ // If the base class initializer has a 'where' clause, it might impose
745+ // requirements on the base class's own generic parameters that are not
746+ // satisfied by the derived class. In this case, we don't want to inherit
747+ // this initializer; there's no way to call it on the derived class.
748+ auto checkResult = TypeChecker::checkGenericArguments (
749+ superclassCtor, SourceLoc (), SourceLoc (), Type (),
750+ superclassCtorSig->getGenericParams (),
751+ superclassCtorSig->getRequirements (),
752+ [&](Type type) -> Type {
753+ auto substType = type.subst (overrideInfo.OverrideSubMap );
754+ return GenericEnvironment::mapTypeIntoContext (
755+ genericEnv, substType);
756+ });
757+ if (checkResult != RequirementCheckResult::Success)
758+ return nullptr ;
759+ }
717760
718761 // Create the initializer parameter patterns.
719762 OptionSet<ParameterList::CloneFlags> options
@@ -733,7 +776,7 @@ createDesignatedInitOverride(ClassDecl *classDecl,
733776 auto *bodyParam = bodyParams->get (idx);
734777
735778 auto paramTy = superclassParam->getInterfaceType ();
736- auto substTy = paramTy.subst (subMap );
779+ auto substTy = paramTy.subst (overrideInfo. OverrideSubMap );
737780
738781 bodyParam->setInterfaceType (substTy);
739782 }
@@ -748,12 +791,13 @@ createDesignatedInitOverride(ClassDecl *classDecl,
748791 /* Async=*/ false , /* AsyncLoc=*/ SourceLoc (),
749792 /* Throws=*/ superclassCtor->hasThrows (),
750793 /* ThrowsLoc=*/ SourceLoc (),
751- bodyParams, genericParams, classDecl);
794+ bodyParams, overrideInfo.GenericParams ,
795+ classDecl);
752796
753797 ctor->setImplicit ();
754798
755799 // Set the interface type of the initializer.
756- ctor->setGenericSignature (genericSig );
800+ ctor->setGenericSignature (overrideInfo. GenericSig );
757801
758802 ctor->setImplicitlyUnwrappedOptional (
759803 superclassCtor->isImplicitlyUnwrappedOptional ());
0 commit comments