Skip to content

Commit 3dfbf15

Browse files
committed
Sema: Fix inherited designated init synthesis when there's a 'where' clause but no new generic parameters
SE-0267 allows where clauses on declarations without their own generic parameters, which means we can longer assume that if getGenericParams() returns nullptr on a constructor, then the constructor has the same generic signature as its parent class. Instead, explicitly compare the superclass constructor's generic signature with that of the superclass, and if they don't match, compute a new generic signature for the override. Fixes https://bugs.swift.org/browse/SR-14118 / rdar://73764827.
1 parent 1b2ef54 commit 3dfbf15

File tree

2 files changed

+63
-39
lines changed

2 files changed

+63
-39
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -424,51 +424,53 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
424424
moduleDecl, superclassDecl);
425425

426426
GenericSignature genericSig;
427-
428-
// Inheriting initializers that have their own generic parameters
429427
auto *genericParams = superclassCtor->getGenericParams();
430-
if (genericParams) {
431-
SmallVector<GenericTypeParamDecl *, 4> newParams;
432428

433-
// First, clone the superclass constructor's generic parameter list,
434-
// but change the depth of the generic parameters to be one greater
435-
// than the depth of the subclass.
436-
unsigned depth = 0;
437-
if (auto genericSig = classDecl->getGenericSignature())
438-
depth = genericSig->getGenericParams().back()->getDepth() + 1;
439-
440-
for (auto *param : genericParams->getParams()) {
441-
auto *newParam = new (ctx) GenericTypeParamDecl(classDecl,
442-
param->getName(),
443-
SourceLoc(),
444-
depth,
445-
param->getIndex());
446-
newParams.push_back(newParam);
447-
}
429+
auto superclassCtorSig = superclassCtor->getGenericSignature();
430+
auto superclassSig = superclassDecl->getGenericSignature();
448431

449-
// We don't have to clone the requirements, because they're not
450-
// used for anything.
451-
genericParams = GenericParamList::create(ctx,
452-
SourceLoc(),
453-
newParams,
454-
SourceLoc(),
455-
ArrayRef<RequirementRepr>(),
456-
SourceLoc());
432+
if (superclassCtorSig.getPointer() != superclassSig.getPointer()) {
433+
SmallVector<GenericTypeParamDecl *, 4> newParams;
434+
SmallVector<GenericTypeParamType *, 1> newParamTypes;
457435

458-
// Build a generic signature for the derived class initializer.
436+
// Inheriting initializers that have their own generic parameters
437+
if (genericParams) {
438+
// First, clone the superclass constructor's generic parameter list,
439+
// but change the depth of the generic parameters to be one greater
440+
// than the depth of the subclass.
441+
unsigned depth = 0;
442+
if (auto genericSig = classDecl->getGenericSignature())
443+
depth = genericSig->getGenericParams().back()->getDepth() + 1;
444+
445+
for (auto *param : genericParams->getParams()) {
446+
auto *newParam = new (ctx) GenericTypeParamDecl(classDecl,
447+
param->getName(),
448+
SourceLoc(),
449+
depth,
450+
param->getIndex());
451+
newParams.push_back(newParam);
452+
}
459453

460-
// Add the generic parameters.
461-
SmallVector<GenericTypeParamType *, 1> newParamTypes;
462-
for (auto *newParam : newParams) {
463-
newParamTypes.push_back(
464-
newParam->getDeclaredInterfaceType()->castTo<GenericTypeParamType>());
454+
// We don't have to clone the requirements, because they're not
455+
// used for anything.
456+
genericParams = GenericParamList::create(ctx,
457+
SourceLoc(),
458+
newParams,
459+
SourceLoc(),
460+
ArrayRef<RequirementRepr>(),
461+
SourceLoc());
462+
463+
// Add the generic parameter types.
464+
for (auto *newParam : newParams) {
465+
newParamTypes.push_back(
466+
newParam->getDeclaredInterfaceType()->castTo<GenericTypeParamType>());
467+
}
465468
}
466469

467-
auto superclassSig = superclassCtor->getGenericSignature();
468-
470+
// Build a generic signature for the derived class initializer.
469471
unsigned superclassDepth = 0;
470-
if (auto genericSig = superclassDecl->getGenericSignature())
471-
superclassDepth = genericSig->getGenericParams().back()->getDepth() + 1;
472+
if (superclassSig)
473+
superclassDepth = superclassSig->getGenericParams().back()->getDepth() + 1;
472474

473475
// We're going to be substituting the requirements of the base class
474476
// initializer to form the requirements of the derived class initializer.
@@ -490,13 +492,13 @@ configureGenericDesignatedInitOverride(ASTContext &ctx,
490492
};
491493

492494
SmallVector<Requirement, 2> requirements;
493-
for (auto reqt : superclassSig->getRequirements())
495+
for (auto reqt : superclassCtorSig->getRequirements())
494496
if (auto substReqt = reqt.subst(substFn, lookupConformanceFn))
495497
requirements.push_back(*substReqt);
496498

497499
// Now form the substitution map that will be used to remap parameter
498500
// types.
499-
subMap = SubstitutionMap::get(superclassSig,
501+
subMap = SubstitutionMap::get(superclassCtorSig,
500502
substFn, lookupConformanceFn);
501503

502504
genericSig = evaluateOrDefault(
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-emit-silgen -primary-file %s | %FileCheck %s
2+
3+
public protocol Ungulate {}
4+
public protocol Domesticated {}
5+
6+
public class Horse<U: Ungulate> {
7+
// CHECK-LABEL: sil [serialized] [exact_self_class] [ossa] @$s45designated_init_inheritance_with_where_clause5HorseCACyxGycfC : $@convention(method) <U where U : Ungulate> (@thick Horse<U>.Type) -> @owned Horse<U> {
8+
// CHECK-LABEL: sil [ossa] @$s45designated_init_inheritance_with_where_clause5HorseCACyxGycfc : $@convention(method) <U where U : Ungulate> (@owned Horse<U>) -> @owned Horse<U> {
9+
public init() { }
10+
11+
// CHECK-LABEL: sil [serialized] [exact_self_class] [ossa] @$s45designated_init_inheritance_with_where_clause5HorseCACyxGycAA12DomesticatedRzrlufC : $@convention(method) <U where U : Domesticated, U : Ungulate> (@thick Horse<U>.Type) -> @owned Horse<U> {
12+
// CHECK-LABEL: sil [ossa] @$s45designated_init_inheritance_with_where_clause5HorseCACyxGycAA12DomesticatedRzrlufc : $@convention(method) <U where U : Domesticated, U : Ungulate> (@owned Horse<U>) -> @owned Horse<U> {
13+
public init() where U: Domesticated { }
14+
}
15+
16+
public class Pony<U : Ungulate> : Horse<U> {
17+
// CHECK-LABEL: sil [serialized] [exact_self_class] [ossa] @$s45designated_init_inheritance_with_where_clause4PonyCACyxGycfC : $@convention(method) <U where U : Ungulate> (@thick Pony<U>.Type) -> @owned Pony<U> {
18+
// CHECK-LABEL: sil [ossa] @$s45designated_init_inheritance_with_where_clause4PonyCACyxGycfc : $@convention(method) <U where U : Ungulate> (@owned Pony<U>) -> @owned Pony<U> {
19+
20+
// CHECK-LABEL: sil [serialized] [exact_self_class] [ossa] @$s45designated_init_inheritance_with_where_clause4PonyCACyxGycAA12DomesticatedRzrlufC : $@convention(method) <U where U : Domesticated, U : Ungulate> (@thick Pony<U>.Type) -> @owned Pony<U> {
21+
// CHECK-LABEL: sil [ossa] @$s45designated_init_inheritance_with_where_clause4PonyCACyxGycAA12DomesticatedRzrlufc : $@convention(method) <U where U : Domesticated, U : Ungulate> (@owned Pony<U>) -> @owned Pony<U> {
22+
}

0 commit comments

Comments
 (0)