Skip to content

Commit 2bfbb43

Browse files
committed
[CodeSynthesis] Teach AreAllStoredPropertiesDefaultInitableRequest about init accessors
If stored property is covered by one or more init accessor property, it's default initializable when at least one of the init accessor properties has default value.
1 parent fd2a7d5 commit 2bfbb43

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

lib/Sema/CodeSynthesis.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,10 @@ bool AreAllStoredPropertiesDefaultInitableRequest::evaluate(
845845
Evaluator &evaluator, NominalTypeDecl *decl) const {
846846
assert(!hasClangImplementation(decl));
847847

848+
std::multimap<VarDecl *, VarDecl *> initializedViaInitAccessor;
849+
decl->collectPropertiesInitializableByInitAccessors(
850+
initializedViaInitAccessor);
851+
848852
for (auto member : decl->getImplementationContext()->getMembers()) {
849853
// If a stored property lacks an initial value and if there is no way to
850854
// synthesize an initial value (e.g. for an optional) then we suppress
@@ -859,12 +863,24 @@ bool AreAllStoredPropertiesDefaultInitableRequest::evaluate(
859863
bool HasStorage = false;
860864
bool CheckDefaultInitializer = true;
861865
pbd->getPattern(idx)->forEachVariable(
862-
[&HasStorage, &CheckDefaultInitializer](VarDecl *VD) {
866+
[&HasStorage, &CheckDefaultInitializer,
867+
&initializedViaInitAccessor](VarDecl *VD) {
863868
// If one of the bound variables is @NSManaged, go ahead no matter
864869
// what.
865870
if (VD->getAttrs().hasAttribute<NSManagedAttr>())
866871
CheckDefaultInitializer = false;
867872

873+
// If this property is covered by one or more init accessor(s)
874+
// check whether at least one of them is initializable.
875+
auto initAccessorProperties =
876+
llvm::make_range(initializedViaInitAccessor.equal_range(VD));
877+
if (llvm::any_of(initAccessorProperties, [&](const auto &entry) {
878+
auto *property =
879+
entry.second->getParentPatternBinding();
880+
return property->isInitialized(0);
881+
}))
882+
return;
883+
868884
if (VD->hasStorageOrWrapsStorage())
869885
HasStorage = true;
870886
});

test/Interpreter/init_accessors.swift

+22
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,27 @@ func test_properties_with_inits() {
678678
}
679679

680680
_ = TestAssign(x1: S(x: 0), x2: S(x: -3), y: 2)
681+
682+
class TestDefault : CustomStringConvertible {
683+
var _a: Int
684+
685+
var a: Int = 42 {
686+
@storageRestrictions(initializes: _a)
687+
init {
688+
_a = newValue
689+
}
690+
691+
get { _a }
692+
}
693+
694+
var b: String = "<<default>>"
695+
696+
var description: String {
697+
"TestDefault(a: \(a), b: \(b))"
698+
}
699+
}
700+
701+
print("test-init-expr-3: \(TestDefault())")
681702
}
682703

683704
test_properties_with_inits()
@@ -687,3 +708,4 @@ test_properties_with_inits()
687708
// CHECK-NEXT: TestAssign in x.init: self.x = S(x: 42)
688709
// CHECK-NEXT: TestAssign in x.init: self.x = S(x: 0)
689710
// CHECK-NEXT: TestAssign: self.x = S(x: -3)
711+
// CHECK-NEXT: test-init-expr-3: TestDefault(a: 42, b: <<default>>)

test/SILOptimizer/init_accessor_raw_sil_lowering.swift

+30
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,34 @@ func test_default_inits() {
233233
// CHECK: function_ref variable initialization expression of y in Test3 #1 in test_default_inits()
234234
// CHECK-NOT: function_ref variable initialization expression of _y in Test3 #1 in test_default_inits()
235235
}
236+
237+
class Test4 {
238+
var _x: Int
239+
240+
var x: Int = 42 {
241+
@storageRestrictions(initializes: _x)
242+
init {
243+
_x = newValue
244+
}
245+
get { _x }
246+
}
247+
248+
var _y: String
249+
250+
var y: String = "" {
251+
@storageRestrictions(initializes: _y)
252+
init {
253+
_y = newValue
254+
}
255+
get { _y }
256+
}
257+
258+
// CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_CADycfc : $@convention(method) (@owned Test4) -> @owned Test4
259+
// CHECK: [[X_DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_C1xSivpfi : $@convention(thin) () -> Int
260+
// CHECK-NEXT: [[X_VALUE:%.*]] = apply [[X_DEFAULT]]() : $@convention(thin) () -> Int
261+
// CHECK: assign_or_init [init] self %0 : $Test4, value [[X_VALUE]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set undef : $@convention(thin) (Int) -> @out Int
262+
// CHECK: [[Y_DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_C1ySSvpfi : $@convention(thin) () -> @owned String
263+
// CHECK-NEXT: [[Y_VALUE:%.*]] = apply [[Y_DEFAULT]]() : $@convention(thin) () -> @owned String
264+
// CHECK: assign_or_init [init] self %0 : $Test4, value [[Y_VALUE]] : $String, init {{.*}} : $@convention(thin) (@owned String) -> @out String, set undef : $@convention(thin) (@owned String) -> @out String
265+
}
236266
}

0 commit comments

Comments
 (0)