@@ -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
@@ -703,17 +730,33 @@ createDesignatedInitOverride(ClassDecl *classDecl,
703
730
return nullptr ;
704
731
}
705
732
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,
712
735
classDecl,
713
736
superclassTy,
714
737
superclassCtor);
715
738
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
+ }
717
760
718
761
// Create the initializer parameter patterns.
719
762
OptionSet<ParameterList::CloneFlags> options
@@ -733,7 +776,7 @@ createDesignatedInitOverride(ClassDecl *classDecl,
733
776
auto *bodyParam = bodyParams->get (idx);
734
777
735
778
auto paramTy = superclassParam->getInterfaceType ();
736
- auto substTy = paramTy.subst (subMap );
779
+ auto substTy = paramTy.subst (overrideInfo. OverrideSubMap );
737
780
738
781
bodyParam->setInterfaceType (substTy);
739
782
}
@@ -748,12 +791,13 @@ createDesignatedInitOverride(ClassDecl *classDecl,
748
791
/* Async=*/ false , /* AsyncLoc=*/ SourceLoc (),
749
792
/* Throws=*/ superclassCtor->hasThrows (),
750
793
/* ThrowsLoc=*/ SourceLoc (),
751
- bodyParams, genericParams, classDecl);
794
+ bodyParams, overrideInfo.GenericParams ,
795
+ classDecl);
752
796
753
797
ctor->setImplicit ();
754
798
755
799
// Set the interface type of the initializer.
756
- ctor->setGenericSignature (genericSig );
800
+ ctor->setGenericSignature (overrideInfo. GenericSig );
757
801
758
802
ctor->setImplicitlyUnwrappedOptional (
759
803
superclassCtor->isImplicitlyUnwrappedOptional ());
0 commit comments