Skip to content

Commit 416bbae

Browse files
committed
[TypeChecker] InitAccessors: Fix handling of defaultable init accessor properties during default init synthesis
Default initializable init properties shouldn't prevent default init synthesis and such properties without anything to initialize should be considered by it.
1 parent 2149a46 commit 416bbae

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,12 +877,19 @@ bool AreAllStoredPropertiesDefaultInitableRequest::evaluate(
877877
if (llvm::any_of(initAccessorProperties, [&](const auto &entry) {
878878
auto *property =
879879
entry.second->getParentPatternBinding();
880-
return property->isInitialized(0);
880+
return property->isInitialized(0) ||
881+
property->isDefaultInitializable();
881882
}))
882883
return;
883884

884885
if (VD->hasStorageOrWrapsStorage())
885886
HasStorage = true;
887+
888+
// Treat an init accessor property that doesn't initialize other
889+
// properties as stored for initialization purposes.
890+
if (auto *initAccessor = VD->getAccessor(AccessorKind::Init)) {
891+
HasStorage |= initAccessor->getInitializedProperties().empty();
892+
}
886893
});
887894

888895
if (!HasStorage) continue;

test/Interpreter/init_accessors.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,3 +801,49 @@ do {
801801
}
802802
// CHECK: Person(name: P)
803803
// CHECK-NEXT: Person(name: O)
804+
805+
do {
806+
struct TestDefaultInitializable : CustomStringConvertible {
807+
var description: String {
808+
"TestDefaultInitializable(a: \(a))"
809+
}
810+
811+
var _a: Int?
812+
var a: Int? {
813+
@storageRestrictions(initializes: _a)
814+
init { _a = newValue }
815+
get { _a }
816+
}
817+
}
818+
819+
print(TestDefaultInitializable())
820+
print(TestDefaultInitializable(a: 42))
821+
822+
struct TestMixedDefaultInitalizable : CustomStringConvertible {
823+
var description: String {
824+
"TestMixedDefaultInitalizable(a: \(a), b: \(b))"
825+
}
826+
827+
var a: Int? {
828+
init {}
829+
get { nil }
830+
}
831+
832+
var _b: String
833+
var b: String? {
834+
@storageRestrictions(initializes: _b)
835+
init { self._b = (newValue ?? "") }
836+
get { _b }
837+
set { _b = newValue ?? "" }
838+
}
839+
}
840+
841+
print(TestMixedDefaultInitalizable())
842+
print(TestMixedDefaultInitalizable(b: "Hello"))
843+
print(TestMixedDefaultInitalizable(a: 42))
844+
}
845+
// CHECK: TestDefaultInitializable(a: nil)
846+
// CHECK-NEXT: TestDefaultInitializable(a: Optional(42))
847+
// CHECK-NEXT: TestMixedDefaultInitalizable(a: nil, b: Optional(""))
848+
// CHECK-NEXT: TestMixedDefaultInitalizable(a: nil, b: Optional("Hello"))
849+
// CHECK-NEXT: TestMixedDefaultInitalizable(a: nil, b: Optional(""))

test/decl/var/init_accessors.swift

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ extension TestStructPropWithoutSetter {
530530
}
531531

532532
do {
533-
class TestClassPropWithoutSetter {
533+
class TestClassPropWithoutSetter { // expected-error {{class 'TestClassPropWithoutSetter' has no initializers}}
534534
var x: Int {
535535
init {
536536
}
@@ -539,6 +539,44 @@ do {
539539
}
540540
}
541541

542+
// This should generate only memberwise initializer because `a` doesn't have a default
543+
struct TestStructWithoutSetter { // expected-note {{'init(a:)' declared here}}
544+
var a: Int {
545+
init {
546+
}
547+
get { 0 }
548+
}
549+
}
550+
551+
_ = TestStructWithoutSetter() // expected-error {{missing argument for parameter 'a' in call}}
552+
_ = TestStructWithoutSetter(a: 42) // Ok
553+
554+
struct TestDefaultInitializable {
555+
var a: Int? {
556+
init {}
557+
get { nil }
558+
}
559+
}
560+
561+
_ = TestDefaultInitializable() // Ok (`a` is initialized to `nil`)
562+
563+
struct TestMixedDefaultInitializable {
564+
var a: Int? {
565+
init {}
566+
get { nil }
567+
}
568+
569+
var _b: String
570+
var b: String? {
571+
@storageRestrictions(initializes: _b)
572+
init { _b = newValue ?? "" }
573+
get { _b }
574+
set { _b = newValue ?? "" }
575+
}
576+
}
577+
578+
_ = TestMixedDefaultInitializable() // Ok (both `a` and `b` are initialized to `nil`)
579+
542580
class SubTestPropWithoutSetter : TestClassPropWithoutSetter {
543581
init(otherV: Int) {
544582
x = otherV // Ok

0 commit comments

Comments
 (0)