Skip to content

Commit 0a700b7

Browse files
committed
[SILGen] Don't emit property wrapper generator functions for local property
wrappers with initializers. Instead, call the property wrapper initializer directly.
1 parent 2e1fca3 commit 0a700b7

File tree

3 files changed

+75
-21
lines changed

3 files changed

+75
-21
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,14 +1796,20 @@ class SolutionApplicationTarget {
17961796
}
17971797

17981798
/// Whether or not an opaque value placeholder should be injected into the
1799-
/// first \c wrappedValue argument of an apply expression.
1799+
/// first \c wrappedValue argument of an apply expression so the initializer
1800+
/// expression can be turned into a property wrapper generator function.
18001801
bool shouldInjectWrappedValuePlaceholder(ApplyExpr *apply) const {
18011802
if (kind != Kind::expression ||
18021803
expression.contextualPurpose != CTP_Initialization)
18031804
return false;
18041805

18051806
auto *wrappedVar = expression.propertyWrapper.wrappedVar;
1806-
if (!apply || !wrappedVar || wrappedVar->isStatic())
1807+
if (!apply || !wrappedVar)
1808+
return false;
1809+
1810+
// Don't create property wrapper generator functions for static variables and
1811+
// local variables with initializers.
1812+
if (wrappedVar->isStatic() || wrappedVar->getDeclContext()->isLocalContext())
18071813
return false;
18081814

18091815
return expression.propertyWrapper.innermostWrappedValueInit == apply;

lib/SILGen/SILGenDecl.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,14 +1190,16 @@ void SILGenFunction::emitPatternBinding(PatternBindingDecl *PBD,
11901190
if (var && var->getDeclContext()->isLocalContext()) {
11911191
if (auto *orig = var->getOriginalWrappedProperty()) {
11921192
auto wrapperInfo = orig->getPropertyWrapperBackingPropertyInfo();
1193-
Init = wrapperInfo.getWrappedValuePlaceholder()->getOriginalWrappedValue();
1194-
1195-
auto value = emitRValue(Init);
1196-
emitApplyOfPropertyWrapperBackingInitializer(SILLocation(PBD), orig,
1197-
getForwardingSubstitutionMap(),
1198-
std::move(value))
1199-
.forwardInto(*this, SILLocation(PBD), initialization.get());
1200-
return;
1193+
if (auto *placeholder = wrapperInfo.getWrappedValuePlaceholder()) {
1194+
Init = placeholder->getOriginalWrappedValue();
1195+
1196+
auto value = emitRValue(Init);
1197+
emitApplyOfPropertyWrapperBackingInitializer(SILLocation(PBD), orig,
1198+
getForwardingSubstitutionMap(),
1199+
std::move(value))
1200+
.forwardInto(*this, SILLocation(PBD), initialization.get());
1201+
return;
1202+
}
12011203
}
12021204
}
12031205

test/SILGen/property_wrapper_local.swift

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ struct Wrapper<T> {
55
var wrappedValue: T
66
var projectedValue: Wrapper { self }
77

8+
// CHECK-LABEl: sil hidden [ossa] @$s22property_wrapper_local7WrapperV12wrappedValueACyxGx_tcfC : $@convention(method) <T> (@in T, @thin Wrapper<T>.Type) -> @out Wrapper<T>
89
init(wrappedValue: T) {
910
self.wrappedValue = wrappedValue
1011
}
@@ -65,7 +66,7 @@ func testInitialValue() {
6566
// CHECK-LABEL: sil hidden [ossa] @$s22property_wrapper_local16testInitialValueyyF : $@convention(thin) () -> () {
6667

6768
@Wrapper var value: Int = 10
68-
// CHECK: function_ref @$s22property_wrapper_local16testInitialValueyyF5valueL_SivpfP : $@convention(thin) (Int) -> Wrapper<Int>
69+
// CHECK: function_ref @$s22property_wrapper_local7WrapperV12wrappedValueACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin Wrapper<τ_0_0>.Type) -> @out Wrapper<τ_0_0>
6970

7071
value = 15
7172
// CHECK: function_ref @$s22property_wrapper_local16testInitialValueyyF5valueL_Sivs : $@convention(thin) (Int, @guaranteed { var Wrapper<Int> }) -> ()
@@ -77,15 +78,14 @@ func testInitialValue() {
7778
// CHECK-NOT: assign_by_wrapper
7879

7980
// CHECK: return
80-
81-
// CHECK-LABEL: sil private [ossa] @$s22property_wrapper_local16testInitialValueyyF5valueL_SivpfP : $@convention(thin) (Int) -> Wrapper<Int> {
8281
}
8382

8483
@propertyWrapper
8584
enum Lazy<Value> {
8685
case uninitialized(() -> Value)
8786
case initialized(Value)
8887

88+
// CHECK-LABEL: sil hidden [ossa] @$s22property_wrapper_local4LazyO12wrappedValueACyxGxyXA_tcfC : $@convention(method) <Value> (@owned @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Value>, @thin Lazy<Value>.Type) -> @out Lazy<Value>
8989
init(wrappedValue initialValue: @autoclosure @escaping () -> Value) {
9090
self = .uninitialized(initialValue)
9191
}
@@ -111,19 +111,65 @@ func testLocalLazy() {
111111
// CHECK-LABEL: sil hidden [ossa] @$s22property_wrapper_local13testLocalLazyyyF : $@convention(thin) () -> () {
112112

113113
@Lazy var value = "hello!"
114-
// CHECK: [[C:%.*]] = function_ref @$s22property_wrapper_local13testLocalLazyyyFSSycfu_SSycfu0_ : $@convention(thin) () -> @owned String
115-
// CHECK: [[C2:%.*]] = thin_to_thick_function [[C]] : $@convention(thin) () -> @owned String to $@callee_guaranteed () -> @owned String
116-
// CHECK: [[I:%.*]] = function_ref @$s22property_wrapper_local13testLocalLazyyyF5valueL_SSvpfP : $@convention(thin) (@owned @callee_guaranteed () -> @owned String) -> @owned Lazy<String>
117-
//CHECK: apply [[I]]([[C2]])
114+
// CHECK: function_ref @$s22property_wrapper_local13testLocalLazyyyFSSycfu_ : $@convention(thin) () -> @owned String
115+
// CHECK: [[I:%.*]] = function_ref @$s22property_wrapper_local4LazyO12wrappedValueACyxGxyXA_tcfC : $@convention(method) <τ_0_0> (@owned @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <τ_0_0>, @thin Lazy<τ_0_0>.Type) -> @out Lazy<τ_0_0>
116+
//CHECK: apply [[I]]<String>
118117

119118
_ = value
120119
// CHECK: function_ref @$s22property_wrapper_local13testLocalLazyyyF5valueL_SSvg : $@convention(thin) (@guaranteed { var Lazy<String> }) -> @owned String
121120

122-
123-
// property wrapper backing initializer of value #1 in testLocalLazy()
124-
// CHECK-LABEL: sil private [ossa] @$s22property_wrapper_local13testLocalLazyyyF5valueL_SSvpfP : $@convention(thin) (@owned @callee_guaranteed () -> @owned String) -> @owned Lazy<String> {
125-
126121
// getter of value #1 in testLocalLazy()
127122
// CHECK-LABEL: sil private [ossa] @$s22property_wrapper_local13testLocalLazyyyF5valueL_SSvg : $@convention(thin) (@guaranteed { var Lazy<String> }) -> @owned String {
128123
// CHECK: function_ref @$s22property_wrapper_local4LazyO12wrappedValuexvg : $@convention(method) <τ_0_0> (@inout Lazy<τ_0_0>) -> @out τ_0_0
129124
}
125+
126+
@propertyWrapper
127+
struct BoundedNumber<T: Numeric & Comparable> {
128+
private let min:T
129+
private let max:T
130+
var value:T
131+
132+
var wrappedValue: T {
133+
get { value }
134+
set {
135+
if value < min {
136+
value = min
137+
} else if value > max {
138+
value = max
139+
}
140+
}
141+
}
142+
143+
// CHECK-LABEL: sil hidden [ossa] @$s22property_wrapper_local13BoundedNumberV12wrappedValue3min3maxACyxGx_xxtcfC : $@convention(method) <T where T : Comparable, T : Numeric> (@in T, @in T, @in T, @thin BoundedNumber<T>.Type) -> @out BoundedNumber<T>
144+
init(wrappedValue: T, min: T, max: T) {
145+
self.min = min
146+
self.max = max
147+
148+
if wrappedValue < min {
149+
self.value = min
150+
} else if wrappedValue > max {
151+
self.value = max
152+
} else {
153+
self.value = wrappedValue
154+
}
155+
}
156+
}
157+
158+
func testLocalReference(count: Int) {
159+
// CHECK-LABEL: sil hidden [ossa] @$s22property_wrapper_local18testLocalReference5countySi_tF : $@convention(thin) (Int) -> ()
160+
161+
@BoundedNumber(min: 0, max: count) var value = 10
162+
// CHECK: function_ref @$s22property_wrapper_local13BoundedNumberV12wrappedValue3min3maxACyxGx_xxtcfC : $@convention(method) <τ_0_0 where τ_0_0 : Comparable, τ_0_0 : Numeric> (@in τ_0_0, @in τ_0_0, @in τ_0_0, @thin BoundedNumber<τ_0_0>.Type) -> @out BoundedNumber<τ_0_0>
163+
164+
_ = value
165+
// CHECK: function_ref @$s22property_wrapper_local18testLocalReference5countySi_tF5valueL_Sivg : $@convention(thin) (@guaranteed { var BoundedNumber<Int> }) -> Int
166+
167+
value = count
168+
// CHECK: function_ref @$s22property_wrapper_local18testLocalReference5countySi_tF5valueL_Sivs : $@convention(thin) (Int, @guaranteed { var BoundedNumber<Int> }) -> ()
169+
170+
// getter of value #1 in testLocalReference(count:)
171+
// CHECK: sil private [ossa] @$s22property_wrapper_local18testLocalReference5countySi_tF5valueL_Sivg : $@convention(thin) (@guaranteed { var BoundedNumber<Int> }) -> Int
172+
173+
// setter of value #1 in testLocalReference(count:)
174+
// CHECK: sil private [ossa] @$s22property_wrapper_local18testLocalReference5countySi_tF5valueL_Sivs : $@convention(thin) (Int, @guaranteed { var BoundedNumber<Int> }) -> ()
175+
}

0 commit comments

Comments
 (0)