Skip to content

Commit 5db4a88

Browse files
dan-zhengrxwei
authored andcommitted
[Sema] Always create memberwise init when deriving AdditiveArithmetic. (#25495)
Previously, during `AdditiveArithmetic` derived conformances, memberwise initializers were synthesized only when synthesizing `static var zero`. This led to a crash for types that specified `static var zero` but not other requirements. Resolves [TF-579](https://bugs.swift.org/browse/TF-579).
1 parent 3417a08 commit 5db4a88

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

lib/Sema/DerivedConformanceAdditiveArithmetic.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ static ValueDecl *getProtocolRequirement(ProtocolDecl *proto, Identifier name) {
6161
return lookup.front();
6262
}
6363

64+
// Get the effective memberwise initializer of the given nominal type, or create
65+
// it if it does not exist.
66+
static ConstructorDecl *getOrCreateEffectiveMemberwiseInitializer(
67+
TypeChecker &TC, NominalTypeDecl *nominal) {
68+
auto &C = nominal->getASTContext();
69+
if (auto *initDecl = nominal->getEffectiveMemberwiseInitializer())
70+
return initDecl;
71+
auto *initDecl = createImplicitConstructor(
72+
TC, nominal, ImplicitConstructorKind::Memberwise);
73+
nominal->addMember(initDecl);
74+
C.addSynthesizedDecl(initDecl);
75+
return initDecl;
76+
}
77+
6478
// Return true if given nominal type has a `let` stored with an initial value.
6579
static bool hasLetStoredPropertyWithInitialValue(NominalTypeDecl *nominal) {
6680
return llvm::any_of(nominal->getStoredProperties(), [&](VarDecl *v) {
@@ -302,16 +316,6 @@ static ValueDecl *deriveAdditiveArithmetic_zero(DerivedConformance &derived) {
302316
auto &TC = derived.TC;
303317
auto &C = TC.Context;
304318

305-
// The implicit memberwise constructor must be explicitly created so that it
306-
// can called when synthesizing the `zero` property getter. Normally, the
307-
// memberwise constructor is synthesized during SILGen, which is too late.
308-
if (!nominal->getEffectiveMemberwiseInitializer()) {
309-
auto *initDecl = createImplicitConstructor(
310-
TC, nominal, ImplicitConstructorKind::Memberwise);
311-
nominal->addMember(initDecl);
312-
C.addSynthesizedDecl(initDecl);
313-
}
314-
315319
auto returnInterfaceTy = nominal->getDeclaredInterfaceType();
316320
auto returnTy = parentDC->mapTypeIntoContext(returnInterfaceTy);
317321

@@ -338,6 +342,8 @@ DerivedConformance::deriveAdditiveArithmetic(ValueDecl *requirement) {
338342
// Diagnose conformances in disallowed contexts.
339343
if (checkAndDiagnoseDisallowedContext(requirement))
340344
return nullptr;
345+
// Create memberwise initializer for nominal type if it doesn't already exist.
346+
getOrCreateEffectiveMemberwiseInitializer(TC, Nominal);
341347
if (requirement->getBaseName() == TC.Context.getIdentifier("+"))
342348
return deriveMathOperator(*this, Add);
343349
if (requirement->getBaseName() == TC.Context.getIdentifier("-"))

test/Sema/struct_additive_arithmetic.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ struct NoMemberwiseInitializer<T : AdditiveArithmetic> : AdditiveArithmetic {
9191
var value: T
9292
init(randomLabel value: T) { self.value = value }
9393
}
94+
struct NoMemberwiseInitializerCustomZero: AdditiveArithmetic {
95+
var x: Float
96+
static var zero: Self { return NoMemberwiseInitializerCustomZero(0) }
97+
init(_ x: Float) {
98+
self.x = x
99+
}
100+
}
94101
struct NoMemberwiseInitializerExtended<T> {
95102
var value: T
96103
init(_ value: T) {

0 commit comments

Comments
 (0)