Skip to content

Commit 8a09fc1

Browse files
author
Adam Cmiel
committed
[Sema] Dig out other constructor if call is wrapped in a Dot-Call
Guessing this bug /feature is introduced in CSApply ExprRewriter::buildMemberRef but didn't dig deep enough to find there. If a derived class' designated initializer initializes all stored let properties before calling super.init(), we don't properly type-check the chained init call. This does not happen if the stored properties are var or default initialized. We can however dig the OtherConstructorDeclRefExpr out of the semanticFn of the DotSyntaxCallExpr and proceed as normal.
1 parent 97b249b commit 8a09fc1

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

lib/Sema/TypeCheckStmt.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -2163,11 +2163,15 @@ static Expr* constructCallToSuperInit(ConstructorDecl *ctor,
21632163
/// \returns true if an error occurred.
21642164
static bool checkSuperInit(ConstructorDecl *fromCtor,
21652165
ApplyExpr *apply, bool implicitlyGenerated) {
2166+
auto Callee = apply->getSemanticFn();
2167+
if (auto dotCall = dyn_cast<DotSyntaxCallExpr>(Callee))
2168+
Callee = dotCall->getSemanticFn();
2169+
21662170
// Make sure we are referring to a designated initializer.
2167-
auto otherCtorRef = dyn_cast<OtherConstructorDeclRefExpr>(
2168-
apply->getSemanticFn());
2169-
if (!otherCtorRef)
2171+
auto otherCtorRef = dyn_cast<OtherConstructorDeclRefExpr>(Callee);
2172+
if (!otherCtorRef) {
21702173
return false;
2174+
}
21712175

21722176
auto ctor = otherCtorRef->getDecl();
21732177
if (!ctor->isDesignatedInit()) {

test/decl/func/complete_object_init.swift

+33-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Declaration of complete object initializers and basic semantic checking
55
// ---------------------------------------------------------------------------
66
class A {
7-
convenience init(int i: Int) { // expected-note{{convenience initializer is declared here}}
7+
convenience init(int i: Int) { // expected-note 5 {{convenience initializer is declared here}}
88
self.init(double: Double(i))
99
}
1010

@@ -39,6 +39,38 @@ class DerivesA : A {
3939
}
4040
}
4141

42+
// Fixing https://github.com/swiftlang/swift/issues/80311
43+
class DerivesAWithLet : A {
44+
let str: String
45+
init(int i: Int) {
46+
str = "foo"
47+
super.init(int: i) // expected-error{{must call a designated initializer of the superclass 'A'}}
48+
}
49+
}
50+
51+
class DerivesAWithVar : A {
52+
var str: String
53+
init(int i: Int) {
54+
str = "foo"
55+
super.init(int: i) // expected-error{{must call a designated initializer of the superclass 'A'}}
56+
}
57+
}
58+
59+
class DerivesAWithDefaultLet : A {
60+
let str: String = "foo"
61+
init(int i: Int) {
62+
super.init(int: i) // expected-error{{must call a designated initializer of the superclass 'A'}}
63+
}
64+
}
65+
66+
class DerivesAWithDefaultVar : A {
67+
var str: String = "foo"
68+
init(int i: Int) {
69+
super.init(int: i) // expected-error{{must call a designated initializer of the superclass 'A'}}
70+
}
71+
}
72+
73+
4274
struct S {
4375
convenience init(int i: Int) { // expected-error{{initializers in structs are not marked with 'convenience'}}
4476
self.init(double: Double(i))

0 commit comments

Comments
 (0)