@@ -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
@@ -702,17 +729,33 @@ createDesignatedInitOverride(ClassDecl *classDecl,
702729 return nullptr ;
703730 }
704731
705- GenericSignature genericSig;
706- GenericParamList *genericParams;
707- SubstitutionMap subMap;
708-
709- std::tie (genericSig, genericParams, subMap) =
710- configureGenericDesignatedInitOverride (ctx,
732+ auto overrideInfo =
733+ computeDesignatedInitOverrideSignature (ctx,
711734 classDecl,
712735 superclassTy,
713736 superclassCtor);
714737
715- // Determine the initializer parameters.
738+ if (auto superclassCtorSig = superclassCtor->getGenericSignature ()) {
739+ auto *genericEnv = (overrideInfo.GenericSig
740+ ? overrideInfo.GenericSig ->getGenericEnvironment ()
741+ : nullptr );
742+
743+ // If the base class initializer has a 'where' clause, it might impose
744+ // requirements on the base class's own generic parameters that are not
745+ // satisfied by the derived class. In this case, we don't want to inherit
746+ // this initializer; there's no way to call it on the derived class.
747+ auto checkResult = TypeChecker::checkGenericArguments (
748+ superclassCtor, SourceLoc (), SourceLoc (), Type (),
749+ superclassCtorSig->getGenericParams (),
750+ superclassCtorSig->getRequirements (),
751+ [&](Type type) -> Type {
752+ auto substType = type.subst (overrideInfo.OverrideSubMap );
753+ return GenericEnvironment::mapTypeIntoContext (
754+ genericEnv, substType);
755+ });
756+ if (checkResult != RequirementCheckResult::Success)
757+ return nullptr ;
758+ }
716759
717760 // Create the initializer parameter patterns.
718761 OptionSet<ParameterList::CloneFlags> options
@@ -732,7 +775,7 @@ createDesignatedInitOverride(ClassDecl *classDecl,
732775 auto *bodyParam = bodyParams->get (idx);
733776
734777 auto paramTy = superclassParam->getInterfaceType ();
735- auto substTy = paramTy.subst (subMap );
778+ auto substTy = paramTy.subst (overrideInfo. OverrideSubMap );
736779
737780 bodyParam->setInterfaceType (substTy);
738781 }
@@ -747,12 +790,13 @@ createDesignatedInitOverride(ClassDecl *classDecl,
747790 /* Async=*/ false , /* AsyncLoc=*/ SourceLoc (),
748791 /* Throws=*/ superclassCtor->hasThrows (),
749792 /* ThrowsLoc=*/ SourceLoc (),
750- bodyParams, genericParams, classDecl);
793+ bodyParams, overrideInfo.GenericParams ,
794+ classDecl);
751795
752796 ctor->setImplicit ();
753797
754798 // Set the interface type of the initializer.
755- ctor->setGenericSignature (genericSig );
799+ ctor->setGenericSignature (overrideInfo. GenericSig );
756800
757801 ctor->setImplicitlyUnwrappedOptional (
758802 superclassCtor->isImplicitlyUnwrappedOptional ());
0 commit comments