Skip to content

Commit 5dbdcd9

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents cbc4ffd + 1542bb5 commit 5dbdcd9

File tree

5 files changed

+174
-15
lines changed

5 files changed

+174
-15
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ static unsigned getElementCountRec(TypeExpansionContext context,
9595
for (auto *VD : NTD->getStoredProperties())
9696
NumElements += getElementCountRec(
9797
context, Module, T.getFieldType(VD, Module, context), false);
98+
for (auto *P : NTD->getInitAccessorProperties()) {
99+
auto *init = P->getAccessor(AccessorKind::Init);
100+
if (init->getInitializedProperties().empty())
101+
++NumElements;
102+
}
98103
return NumElements;
99104
}
100105
}
@@ -451,6 +456,15 @@ DIMemoryObjectInfo::getPathStringToElement(unsigned Element,
451456
Element -= NumFieldElements;
452457
}
453458

459+
for (auto *property : NTD->getInitAccessorProperties()) {
460+
auto *init = property->getAccessor(AccessorKind::Init);
461+
if (init->getInitializedProperties().empty()) {
462+
if (Element == 0)
463+
return property;
464+
--Element;
465+
}
466+
}
467+
454468
// If we do not have any stored properties, we have nothing of interest.
455469
if (!HasStoredProperty)
456470
return nullptr;
@@ -497,6 +511,15 @@ bool DIMemoryObjectInfo::isElementLetProperty(unsigned Element) const {
497511
Element -= NumFieldElements;
498512
}
499513

514+
for (auto *property : NTD->getInitAccessorProperties()) {
515+
auto *init = property->getAccessor(AccessorKind::Init);
516+
if (init->getInitializedProperties().empty()) {
517+
if (Element == 0)
518+
return !property->getAccessor(AccessorKind::Set);
519+
--Element;
520+
}
521+
}
522+
500523
// Otherwise, we miscounted elements?
501524
assert(Element == 0 && "Element count problem");
502525
return false;
@@ -1221,10 +1244,22 @@ ElementUseCollector::collectAssignOrInitUses(AssignOrInitInst *Inst,
12211244

12221245
auto initializedElts = Inst->getInitializedProperties();
12231246
if (initializedElts.empty()) {
1224-
// Add a placeholder use that doesn't touch elements to make sure that
1225-
// the `assign_or_init` instruction gets the kind set when `initializes`
1226-
// list is empty.
1227-
trackUse(DIMemoryUse(Inst, DIUseKind::InitOrAssign, BaseEltNo, 0));
1247+
auto initAccessorProperties = typeDC->getInitAccessorProperties();
1248+
auto initFieldAt = typeDC->getStoredProperties().size();
1249+
1250+
for (auto *property : initAccessorProperties) {
1251+
auto initAccessor = property->getAccessor(AccessorKind::Init);
1252+
if (!initAccessor->getInitializedProperties().empty())
1253+
continue;
1254+
1255+
if (property == Inst->getProperty()) {
1256+
trackUse(DIMemoryUse(Inst, DIUseKind::InitOrAssign, initFieldAt,
1257+
/*NumElements=*/1));
1258+
break;
1259+
}
1260+
1261+
++initFieldAt;
1262+
}
12281263
} else {
12291264
for (auto *property : initializedElts)
12301265
addUse(property, DIUseKind::InitOrAssign);

test/Interpreter/init_accessors.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,3 +750,54 @@ func test_inheritance() {
750750
test_inheritance()
751751
// CHECK: test-inheritance-1: Person(firstName: <<unknown>>, age: 0)
752752
// CHECK-NEXT: test-inheritance-2: Person(firstName: Q, age: 42)
753+
754+
do {
755+
class BackingData<T> {
756+
var data: [PartialKeyPath<T>: Any] = [:]
757+
758+
func get<V>(_ key: KeyPath<T, V>) -> V { data[key] as! V }
759+
func set<V>(_ key: KeyPath<T, V>, _ value: V) {
760+
data[key] = value
761+
}
762+
}
763+
764+
class Person : CustomStringConvertible {
765+
var description: String {
766+
"Person(name: \(name))"
767+
}
768+
769+
private var backingData: BackingData<Person> = BackingData()
770+
771+
private var _name: Int
772+
773+
var name: String {
774+
@storageRestrictions(accesses: backingData, initializes: _name)
775+
init(newValue) {
776+
self.backingData.set(\.name, newValue)
777+
self._name = 0
778+
}
779+
780+
get { self.backingData.get(\.name) }
781+
set { self.backingData.set(\.name, newValue) }
782+
}
783+
784+
init(name: String) {
785+
self.name = name
786+
}
787+
788+
init(backingData: BackingData<Person>) {
789+
self.backingData = backingData
790+
self._name = 0
791+
}
792+
}
793+
794+
let person = Person(name: "P")
795+
print(person)
796+
797+
let localData = BackingData<Person>()
798+
localData.set(\.name, "O")
799+
800+
print(Person(backingData: localData))
801+
}
802+
// CHECK: Person(name: P)
803+
// CHECK-NEXT: Person(name: O)

test/SILOptimizer/init_accessor_definite_init_diagnostics.swift

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,73 @@ do {
268268
}
269269
}
270270
}
271+
272+
// Test that init accessor without "initializes" is required
273+
do {
274+
struct Test {
275+
var a: Int {
276+
init {}
277+
get { 42 }
278+
set {}
279+
}
280+
var b: Int { // expected-note 2 {{'self' not initialized}}
281+
init {}
282+
get { 0 }
283+
set { }
284+
}
285+
286+
init(a: Int) {
287+
self.a = a
288+
} // expected-error {{return from initializer without initializing all stored properties}}
289+
290+
init(a: Int, b: Int) {
291+
if a == 0 {
292+
self.a = a
293+
self.b = b
294+
} else {
295+
self.a = 0
296+
}
297+
} // expected-error {{return from initializer without initializing all stored properties}}
298+
299+
init() { // Ok
300+
self.a = 0
301+
self.b = 0
302+
}
303+
}
304+
305+
struct TestWithStored {
306+
var _value: Int = 0
307+
308+
var a: Int {
309+
@storageRestrictions(accesses: _value)
310+
init {}
311+
get { _value }
312+
set { _value = newValue }
313+
}
314+
}
315+
316+
_ = TestWithStored(a: 42) // Ok
317+
_ = TestWithStored(_value: 1, a: 42) // Ok
318+
319+
class TestWithStoredExplicit {
320+
var _value: Int = 0
321+
var _other: String = ""
322+
323+
var a: Int { // expected-note 2 {{'self' not initialized}}
324+
@storageRestrictions(accesses: _value)
325+
init {}
326+
get { _value }
327+
set { _value = newValue }
328+
}
329+
330+
init(data: Int) {
331+
self._value = data
332+
} // expected-error {{return from initializer without initializing all stored properties}}
333+
334+
init() {} // expected-error {{return from initializer without initializing all stored properties}}
335+
336+
init(a: Int) {
337+
self.a = a // Ok
338+
}
339+
}
340+
}

test/SILOptimizer/init_accessor_raw_sil_lowering.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ final class TestIndirectionThroughStorage {
4646
// CHECK: [[STORAGE_INIT:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC8_storage33_DE106275C2F16FB3D05881E72FBD87C8LLAA0H0_pAC1TAaFPRts_XPvpfi : $@convention(thin) () -> @out any Storage<TestIndirectionThroughStorage>
4747
// CHECK-NEXT: {{.*}} = apply [[STORAGE_INIT]]([[STORAGE_REF]]) : $@convention(thin) () -> @out any Storage<TestIndirectionThroughStorage>
4848
// Initialization:
49-
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.name, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
50-
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> (
49+
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.name, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
50+
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.age, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
5151
// Explicit set:
5252
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.name, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
53-
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> (
53+
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
5454
init(name: String, age: Int) {
5555
self.name = name
5656
self.age = age
@@ -61,8 +61,8 @@ final class TestIndirectionThroughStorage {
6161
// CHECK: [[STORAGE_INIT:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC8_storage33_DE106275C2F16FB3D05881E72FBD87C8LLAA0H0_pAC1TAaFPRts_XPvpfi : $@convention(thin) () -> @out any Storage<TestIndirectionThroughStorage>
6262
// CHECK-NEXT: {{.*}} = apply [[STORAGE_INIT]]([[STORAGE_REF]]) : $@convention(thin) () -> @out any Storage<TestIndirectionThroughStorage>
6363
// Initialization:
64-
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.name, self %1 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
65-
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self %1 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
64+
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.name, self %1 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
65+
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.age, self %1 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
6666
// Explicit set:
6767
// CHECK: [[STORAGE_SETTER:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC7storageAA0H0_pAC1TAaEPRts_XPvs : $@convention(method) (@in any Storage<TestIndirectionThroughStorage>, @guaranteed TestIndirectionThroughStorage) -> ()
6868
// CHECK-NEXT: {{.*}} = apply [[STORAGE_SETTER]]({{.*}}, %1) : $@convention(method) (@in any Storage<TestIndirectionThroughStorage>, @guaranteed TestIndirectionThroughStorage) -> ()
@@ -102,8 +102,8 @@ struct TestAccessOfOnePatternVars {
102102
// CHECK-NEXT: {{.*}} = apply [[Y_INIT]]() : $@convention(thin) () -> @owned String
103103
// CHECK-NOT: [[X_REF:%.*]] = struct_element_addr %3 : $*TestAccessOfOnePatternVars, #TestAccessOfOnePatternVars.x
104104
// CHECK-NOT: [[Y_REF:%.*]] = struct_element_addr {{.*}} : $*TestAccessOfOnePatternVars, #TestAccessOfOnePatternVars.y
105-
// CHECK: assign_or_init [set] #TestAccessOfOnePatternVars.data, self {{.*}} : $*TestAccessOfOnePatternVars, value {{.*}} : $(Int, String), init {{.*}} : $@convention(thin) (Int, @owned String, @inout Int, @inout String) -> (), set {{.*}} : $@callee_guaranteed (Int, @owned String) -> ()
106-
// CHECK: assign_or_init [set] #TestAccessOfOnePatternVars.other, self {{.*}} : $*TestAccessOfOnePatternVars, value {{.*}} : $Bool, init {{.*}} : $@convention(thin) (Bool, @inout Int) -> (), set {{.*}} : $@callee_guaranteed (Bool) -> ()
105+
// CHECK: assign_or_init [init] #TestAccessOfOnePatternVars.data, self {{.*}} : $*TestAccessOfOnePatternVars, value {{.*}} : $(Int, String), init {{.*}} : $@convention(thin) (Int, @owned String, @inout Int, @inout String) -> (), set {{.*}} : $@callee_guaranteed (Int, @owned String) -> ()
106+
// CHECK: assign_or_init [init] #TestAccessOfOnePatternVars.other, self {{.*}} : $*TestAccessOfOnePatternVars, value {{.*}} : $Bool, init {{.*}} : $@convention(thin) (Bool, @inout Int) -> (), set {{.*}} : $@callee_guaranteed (Bool) -> ()
107107
init(x: Int, y: String) {
108108
self.x = x
109109
self.y = y
@@ -196,7 +196,7 @@ struct Test {
196196
// CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering4TestV1vACSi_tcfC : $@convention(method) (Int, @thin Test.Type) -> Test
197197
init(v: Int) {
198198
// CHECK: [[INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering4TestV4testSivi : $@convention(thin) (Int) -> ()
199-
// CHECK: assign_or_init [set] #Test.test, self {{.*}}, value %0 : $Int, init [[INIT_REF]] : $@convention(thin) (Int) -> (), set {{.*}} : $@callee_guaranteed (Int) -> ()
199+
// CHECK: assign_or_init [init] #Test.test, self {{.*}}, value %0 : $Int, init [[INIT_REF]] : $@convention(thin) (Int) -> (), set {{.*}} : $@callee_guaranteed (Int) -> ()
200200
self.test = v
201201
}
202202
}

test/SILOptimizer/init_accessors.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,12 @@ struct TestSetter {
7373
}
7474

7575
// CHECK-LABEL: sil hidden [ossa] @$s14init_accessors10TestSetterV1x1yACSi_SitcfC : $@convention(method) (Int, Int, @thin TestSetter.Type) -> TestSetter
76-
// CHECK: [[SETTER_REF:%.*]] = function_ref @$s14init_accessors10TestSetterV5pointSi_Sitvs : $@convention(method) (Int, Int, @inout TestSetter) -> ()
77-
// CHECK-NEXT: [[SETTER_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]([[SELF_VALUE:%.*]]) : $@convention(method) (Int, Int, @inout TestSetter) -> ()
78-
// CHECK: {{.*}} = apply [[SETTER_CLOSURE]]({{.*}}) : $@callee_guaranteed (Int, Int) -> ()
76+
// CHECK: [[INIT_ACCESSOR:%.*]] = function_ref @$s14init_accessors10TestSetterV5pointSi_Sitvi : $@convention(thin) (Int, Int, @inout Int, @inout Int) -> ()
77+
// CHECK: [[SELF:%.*]] = begin_access [modify] [dynamic] %14 : $*TestSetter
78+
// CHECK-NEXT: ([[X:%.*]], [[Y:%.*]]) = destructure_tuple {{.*}} : $(Int, Int)
79+
// CHECK-NEXT: [[X_REF:%.*]] = struct_element_addr [[SELF]] : $*TestSetter, #TestSetter.x
80+
// CHECK-NEXT: [[Y_REF:%.*]] = struct_element_addr [[SELF]] : $*TestSetter, #TestSetter.y
81+
// CHECK-NEXT: {{.*}} = apply [[INIT_ACCESSOR]]([[X]], [[Y]], [[X_REF]], [[Y_REF]]) : $@convention(thin) (Int, Int, @inout Int, @inout Int) -> ()
7982
init(x: Int, y: Int) {
8083
self.x = x
8184
self.y = y

0 commit comments

Comments
 (0)