Skip to content

Commit 0842b42

Browse files
committed
[SILGen] Only use assign_by_wrapper for wrapped instance properties inside an
initializer, and for wrapped local variables.
1 parent b33dbed commit 0842b42

File tree

4 files changed

+45
-16
lines changed

4 files changed

+45
-16
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,11 @@ namespace {
13141314
IsOnSelfParameter &&
13151315
isa<ConstructorDecl>(SGF.FunctionDC->getAsDecl());
13161316

1317+
// Assignment to a wrapped property can only be re-written to initialization for
1318+
// members of `self` in an initializer, and for local variables.
1319+
if (!(isAssignmentToSelfParamInInit || VD->getDeclContext()->isLocalContext()))
1320+
return false;
1321+
13171322
// If we have a nonmutating setter on a value type, the call
13181323
// captures all of 'self' and we cannot rewrite an assignment
13191324
// into an initialization.

test/SILGen/objc_properties.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,19 +285,28 @@ public struct SomeWrapper {
285285

286286
class SomeWrapperTests {
287287
@objc @SomeWrapper dynamic var someWrapper: Int = 0
288-
// CHECK-LABEL: sil hidden [ossa] @$s15objc_properties16SomeWrapperTestsC14testAssignmentyyF
288+
@W @objc dynamic var s: String? = nil
289+
290+
// CHECK-LABEL: sil hidden [ossa] @$s15objc_properties16SomeWrapperTestsCyACSScfc : $@convention(method) (@owned String, @owned SomeWrapperTests) -> @owned SomeWrapperTests {
289291
// CHECK: [[M:%.*]] = function_ref @$s15objc_properties16SomeWrapperTestsC04someD0SivsTD
290292
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[M]]({{.*}})
291293
// CHECK: assign_by_wrapper {{%.*}}: $Int to {{%.*}} : $*SomeWrapper, init {{.*}} : $@callee_guaranteed (Int) -> SomeWrapper, set [[C]] : $@callee_guaranteed (Int) -> ()
294+
// CHECK: [[M:%.*]] = function_ref @$s15objc_properties16SomeWrapperTestsC1sSSSgvsTD
295+
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[M]](
296+
// CHECK: assign_by_wrapper {{.*}} : $Optional<String> to {{.*}} : $*W<Optional<String>>, init {{.*}} : $@callee_guaranteed (@owned Optional<String>) -> @owned W<Optional<String>>, set [[C]] : $@callee_guaranteed (@owned Optional<String>) -> ()
297+
init(_ s: String) {
298+
someWrapper = 1000
299+
self.s = s
300+
}
301+
302+
// CHECK-LABEL: sil hidden [ossa] @$s15objc_properties16SomeWrapperTestsC14testAssignmentyyF
303+
// CHECK: objc_method %0 : $SomeWrapperTests, #SomeWrapperTests.someWrapper!setter.foreign : (SomeWrapperTests) -> (Int) -> (), $@convention(objc_method) (Int, SomeWrapperTests) -> ()
292304
func testAssignment() {
293305
someWrapper = 1000
294306
}
295307

296-
@W @objc dynamic var s: String? = nil
297308
// CHECK-LABEL: sil hidden [ossa] @$s15objc_properties16SomeWrapperTestsC16testBridgedValueyySSF
298-
// CHECK: [[M:%.*]] = function_ref @$s15objc_properties16SomeWrapperTestsC1sSSSgvsTD
299-
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[M]](
300-
// CHECK: assign_by_wrapper {{.*}} : $Optional<String> to {{.*}} : $*W<Optional<String>>, init {{.*}} : $@callee_guaranteed (@owned Optional<String>) -> @owned W<Optional<String>>, set [[C]] : $@callee_guaranteed (@owned Optional<String>) -> ()
309+
// CHECK: objc_method %1 : $SomeWrapperTests, #SomeWrapperTests.s!setter.foreign : (SomeWrapperTests) -> (String?) -> (), $@convention(objc_method) (Optional<NSString>, SomeWrapperTests) -> ()
301310
// Let's not crash.
302311
func testBridgedValue(_ s: String) {
303312
self.s = s

test/SILGen/property_wrappers.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,8 @@ struct WithTuples {
680680
class TestResilientDI {
681681
@MyPublished var data: Int? = nil
682682

683-
// CHECK: assign_by_wrapper {{%.*}} : $Optional<Int> to {{%.*}} : $*MyPublished<Optional<Int>>, init {{%.*}} : $@callee_guaranteed (Optional<Int>) -> @out MyPublished<Optional<Int>>, set {{%.*}} : $@callee_guaranteed (Optional<Int>) -> ()
683+
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers15TestResilientDIC11doSomethingyyF : $@convention(method) (@guaranteed TestResilientDI) -> () {
684+
// CHECK: class_method %0 : $TestResilientDI, #TestResilientDI.data!setter : (TestResilientDI) -> (Int?) -> (), $@convention(method) (Optional<Int>, @guaranteed TestResilientDI) -> ()
684685

685686
func doSomething() {
686687
self.data = Int()

test/SILGen/resilient_assign_by_wrapper.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,27 @@ public enum AddressOnlyEnum {
2424
public class AddressOnlySetter {
2525
@WrapGod var value: AddressOnlyEnum = .value(nil)
2626

27+
init() {
28+
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17AddressOnlySetterCACycfc
29+
// CHECK: [[E1:%.*]] = alloc_stack $AddressOnlyEnum
30+
// CHECK: [[W:%.*]] = alloc_stack $WrapGod<AddressOnlyEnum>
31+
// CHECK: [[I:%.*]] = function_ref @$s27resilient_assign_by_wrapper17AddressOnlySetterC5valueAA0eF4EnumOvpfP : $@convention(thin) (@in AddressOnlyEnum) -> @out WrapGod<AddressOnlyEnum>
32+
// CHECK: apply [[I]]([[W]], [[E1]])
33+
34+
// CHECK: [[E2:%.*]] = alloc_stack $AddressOnlyEnum
35+
// CHECK-NEXT: inject_enum_addr [[E2]] : $*AddressOnlyEnum, #AddressOnlyEnum.some!enumelt
36+
// CHECK: [[S:%.*]] = partial_apply [callee_guaranteed] {{%.*}}({{%.*}}) : $@convention(method) (@in AddressOnlyEnum, @guaranteed AddressOnlySetter) -> ()
37+
// CHECK: assign_by_wrapper [[E2]] : $*AddressOnlyEnum
38+
// CHECK-SAME: set [[S]] : $@callee_guaranteed (@in AddressOnlyEnum) -> ()
39+
self.value = .some
40+
}
41+
2742
func testAssignment() {
2843
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17AddressOnlySetterC14testAssignmentyyF
2944
// CHECK: [[E:%.*]] = alloc_stack $AddressOnlyEnum
3045
// CHECK: inject_enum_addr [[E]] : $*AddressOnlyEnum, #AddressOnlyEnum.some!enumelt
31-
// CHECK: [[S:%.*]] = partial_apply [callee_guaranteed] {{%.*}}({{%.*}}) : $@convention(method) (@in AddressOnlyEnum, @guaranteed AddressOnlySetter) -> ()
32-
// CHECK: assign_by_wrapper [[E]] : $*AddressOnlyEnum
33-
// CHECK-SAME: set [[S]] : $@callee_guaranteed (@in AddressOnlyEnum) -> ()
46+
// CHECK: [[S:%.*]] = class_method %0 : $AddressOnlySetter, #AddressOnlySetter.value!setter : (AddressOnlySetter) -> (AddressOnlyEnum) -> (), $@convention(method) (@in AddressOnlyEnum, @guaranteed AddressOnlySetter) -> ()
47+
// CHECK: apply [[S]]([[E]], %0) : $@convention(method) (@in AddressOnlyEnum, @guaranteed AddressOnlySetter) -> ()
3448
self.value = .some
3549
}
3650
}
@@ -40,8 +54,8 @@ public struct SubstitutedSetter<T> {
4054
}
4155

4256
extension SubstitutedSetter where T == Bool {
43-
mutating func testAssignment() {
44-
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17SubstitutedSetterVAASbRszlE14testAssignmentyyF
57+
init() {
58+
// CHECK-LABEL: hidden [ossa] @$s27resilient_assign_by_wrapper17SubstitutedSetterVAASbRszlEACySbGycfC
4559
// CHECK: [[W:%.*]] = struct_element_addr {{%.*}} : $*SubstitutedSetter<Bool>, #SubstitutedSetter._value
4660
// CHECK: [[B:%.*]] = alloc_stack $Bool
4761
// CHECK: assign_by_wrapper [[B]] : $*Bool to [[W]] : $*WrapGod<Bool>
@@ -56,9 +70,9 @@ public struct ReabstractedSetter<T> {
5670
}
5771

5872
extension ReabstractedSetter where T == Int {
59-
mutating func testAssignment() {
60-
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper18ReabstractedSetterVAASiRszlE14testAssignmentyyF
61-
// CHECK: [[F:%.*]] = function_ref @$s27resilient_assign_by_wrapper18ReabstractedSetterVAASiRszlE14testAssignmentyyFySicfU_ : $@convention(thin) (Int) -> ()
73+
init() {
74+
// CHECK-LABEL: hidden [ossa] @$s27resilient_assign_by_wrapper18ReabstractedSetterVAASiRszlEACySiGycfC
75+
// CHECK: [[F:%.*]] = function_ref @$s27resilient_assign_by_wrapper18ReabstractedSetterVAASiRszlEACySiGycfcySicfU_ : $@convention(thin) (Int) -> ()
6276
// CHECK: [[TH_F:%.*]] = thin_to_thick_function [[F]] : $@convention(thin) (Int) -> () to $@callee_guaranteed (Int) -> ()
6377
// CHECK: [[THUNK_REF:%.*]] = function_ref @$sSiIegy_SiIegn_TR : $@convention(thin) (@in_guaranteed Int, @guaranteed @callee_guaranteed (Int) -> ()) -> ()
6478
// CHECK: [[CF:%.*]] = partial_apply [callee_guaranteed] [[THUNK_REF]]([[TH_F]]) : $@convention(thin) (@in_guaranteed Int, @guaranteed @callee_guaranteed (Int) -> ()) -> ()
@@ -76,8 +90,8 @@ public struct ObjectifiedSetter<T: AnyObject> {
7690
public class SomeObject {}
7791

7892
extension ObjectifiedSetter where T == SomeObject {
79-
mutating func testAssignment() {
80-
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17ObjectifiedSetterVA2A10SomeObjectCRszrlE14testAssignmentyyF : $@convention(method) (@inout ObjectifiedSetter<SomeObject>) -> () {
93+
init() {
94+
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17ObjectifiedSetterV5valuexvs : $@convention(method) <T where T : AnyObject> (@owned T, @inout ObjectifiedSetter<T>) -> () {
8195
// CHECK: [[OBJ:%.*]] = apply {{%.*}}({{%.*}}) : $@convention(method) (@thick SomeObject.Type) -> @owned SomeObject
8296
// CHECK: [[STORAGE:%.*]] = struct_element_addr {{%.*}} : $*ObjectifiedSetter<SomeObject>, #ObjectifiedSetter._value
8397
// CHECK: assign_by_wrapper [[OBJ]] : $SomeObject to [[STORAGE]] : $*WrapGod<SomeObject>

0 commit comments

Comments
 (0)