@@ -418,30 +418,49 @@ synthesizeStubBody(AbstractFunctionDecl *fn, void *) {
418
418
/* isTypeChecked=*/ true };
419
419
}
420
420
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,
423
431
ClassDecl *classDecl,
424
432
Type superclassTy,
425
433
ConstructorDecl *superclassCtor) {
426
- auto *superclassDecl = superclassTy->getAnyNominal ();
427
-
428
434
auto *moduleDecl = classDecl->getParentModule ();
429
- auto subMap = superclassTy->getContextSubstitutionMap (
430
- moduleDecl, superclassDecl);
431
435
432
- GenericSignature genericSig;
433
- auto *genericParams = superclassCtor->getGenericParams ();
436
+ auto *superclassDecl = superclassTy->getAnyNominal ();
434
437
438
+ auto classSig = classDecl->getGenericSignature ();
435
439
auto superclassCtorSig = superclassCtor->getGenericSignature ();
436
440
auto superclassSig = superclassDecl->getGenericSignature ();
437
441
442
+ // These are our outputs.
443
+ GenericSignature genericSig = classSig;
444
+ auto *genericParams = superclassCtor->getGenericParams ();
445
+ auto subMap = superclassTy->getContextSubstitutionMap (
446
+ moduleDecl, superclassDecl);
447
+
438
448
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
+
439
456
SmallVector<GenericTypeParamDecl *, 4 > newParams;
440
457
SmallVector<GenericTypeParamType *, 1 > newParamTypes;
441
458
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.
443
462
if (genericParams) {
444
- // First, clone the superclass constructor 's generic parameter list,
463
+ // First, clone the base class initializer 's generic parameter list,
445
464
// but change the depth of the generic parameters to be one greater
446
465
// than the depth of the subclass.
447
466
unsigned depth = 0 ;
@@ -457,8 +476,8 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
457
476
newParams.push_back (newParam);
458
477
}
459
478
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 .
462
481
genericParams = GenericParamList::create (ctx,
463
482
SourceLoc (),
464
483
newParams,
@@ -473,7 +492,7 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
473
492
}
474
493
}
475
494
476
- // Build a generic signature for the derived class initializer .
495
+ // The depth at which the initializer's own generic parameters start, if any .
477
496
unsigned superclassDepth = 0 ;
478
497
if (superclassSig)
479
498
superclassDepth = superclassSig->getGenericParams ().back ()->getDepth () + 1 ;
@@ -482,44 +501,52 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
482
501
// initializer to form the requirements of the derived class initializer.
483
502
auto substFn = [&](SubstitutableType *type) -> Type {
484
503
auto *gp = cast<GenericTypeParamType>(type);
504
+ // Generic parameters of the base class itself are mapped via the
505
+ // substitution map of the superclass type.
485
506
if (gp->getDepth () < superclassDepth)
486
507
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.
487
511
return genericParams->getParams ()[gp->getIndex ()]
488
512
->getDeclaredInterfaceType ();
489
513
};
490
514
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
+ }
520
547
}
521
548
522
- return std::make_tuple ( genericSig, genericParams, subMap) ;
549
+ return DesignatedInitOverrideInfo{ genericSig, genericParams, subMap} ;
523
550
}
524
551
525
552
static void
@@ -702,17 +729,33 @@ createDesignatedInitOverride(ClassDecl *classDecl,
702
729
return nullptr ;
703
730
}
704
731
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,
711
734
classDecl,
712
735
superclassTy,
713
736
superclassCtor);
714
737
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
+ }
716
759
717
760
// Create the initializer parameter patterns.
718
761
OptionSet<ParameterList::CloneFlags> options
@@ -732,7 +775,7 @@ createDesignatedInitOverride(ClassDecl *classDecl,
732
775
auto *bodyParam = bodyParams->get (idx);
733
776
734
777
auto paramTy = superclassParam->getInterfaceType ();
735
- auto substTy = paramTy.subst (subMap );
778
+ auto substTy = paramTy.subst (overrideInfo. OverrideSubMap );
736
779
737
780
bodyParam->setInterfaceType (substTy);
738
781
}
@@ -747,12 +790,13 @@ createDesignatedInitOverride(ClassDecl *classDecl,
747
790
/* Async=*/ false , /* AsyncLoc=*/ SourceLoc (),
748
791
/* Throws=*/ superclassCtor->hasThrows (),
749
792
/* ThrowsLoc=*/ SourceLoc (),
750
- bodyParams, genericParams, classDecl);
793
+ bodyParams, overrideInfo.GenericParams ,
794
+ classDecl);
751
795
752
796
ctor->setImplicit ();
753
797
754
798
// Set the interface type of the initializer.
755
- ctor->setGenericSignature (genericSig );
799
+ ctor->setGenericSignature (overrideInfo. GenericSig );
756
800
757
801
ctor->setImplicitlyUnwrappedOptional (
758
802
superclassCtor->isImplicitlyUnwrappedOptional ());
0 commit comments