Skip to content

Commit 2a4cc91

Browse files
committed
[Property Wrappers] Fix accessor synthesis of wrapped parameters that infer
the property wrapper attribute.
1 parent b85bf55 commit 2a4cc91

File tree

3 files changed

+63
-8
lines changed

3 files changed

+63
-8
lines changed

lib/Sema/CSApply.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7983,17 +7983,30 @@ namespace {
79837983

79847984
// Set the interface type of each property wrapper synthesized var
79857985
auto *backingVar = param->getPropertyWrapperBackingProperty();
7986-
backingVar->setInterfaceType(
7987-
solution.simplifyType(solution.getType(backingVar))->mapTypeOutOfContext());
7986+
auto backingType =
7987+
solution.simplifyType(solution.getType(backingVar))->mapTypeOutOfContext();
7988+
backingVar->setInterfaceType(backingType);
79887989

79897990
if (auto *projectionVar = param->getPropertyWrapperProjectionVar()) {
79907991
projectionVar->setInterfaceType(
79917992
solution.simplifyType(solution.getType(projectionVar)));
79927993
}
79937994

79947995
auto *wrappedValueVar = param->getPropertyWrapperWrappedValueVar();
7995-
wrappedValueVar->setInterfaceType(
7996-
solution.simplifyType(solution.getType(wrappedValueVar)));
7996+
auto wrappedValueType = solution.simplifyType(solution.getType(wrappedValueVar));
7997+
wrappedValueVar->setInterfaceType(wrappedValueType->getWithoutSpecifierType());
7998+
7999+
if (param->hasImplicitPropertyWrapper()) {
8000+
if (wrappedValueType->is<LValueType>())
8001+
wrappedValueVar->setImplInfo(StorageImplInfo::getMutableComputed());
8002+
8003+
// Add an explicit property wrapper attribute, which is needed for
8004+
// synthesizing the accessors.
8005+
auto &context = wrappedValueVar->getASTContext();
8006+
auto *typeExpr = TypeExpr::createImplicit(backingType, context);
8007+
auto *attr = CustomAttr::create(context, SourceLoc(), typeExpr, /*implicit=*/true);
8008+
wrappedValueVar->getAttrs().add(attr);
8009+
}
79978010
}
79988011

79998012
TypeChecker::checkParameterList(closure->getParameters(), closure);

lib/Sema/CSSimplify.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8158,7 +8158,12 @@ ConstraintSystem::simplifyPropertyWrapperConstraint(
81588158
}
81598159

81608160
auto resolvedType = wrapperType->getTypeOfMember(DC->getParentModule(), typeInfo.valueVar);
8161-
addConstraint(ConstraintKind::Equal, wrappedValueType, resolvedType, locator);
8161+
if (typeInfo.valueVar->isSettable(nullptr) && typeInfo.valueVar->isSetterAccessibleFrom(DC) &&
8162+
!typeInfo.valueVar->isSetterMutating()) {
8163+
resolvedType = LValueType::get(resolvedType);
8164+
}
8165+
8166+
addConstraint(ConstraintKind::Bind, wrappedValueType, resolvedType, locator);
81628167

81638168
return SolutionKind::Solved;
81648169
}
@@ -8336,7 +8341,8 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
83368341

83378342
if (paramDecl->hasImplicitPropertyWrapper()) {
83388343
backingType = getContextualParamAt(i)->getPlainType();
8339-
wrappedValueType = createTypeVariable(getConstraintLocator(locator), TVO_CanBindToHole);
8344+
wrappedValueType = createTypeVariable(getConstraintLocator(locator),
8345+
TVO_CanBindToHole | TVO_CanBindToLValue);
83408346
} else {
83418347
auto *wrapperAttr = paramDecl->getAttachedPropertyWrappers().front();
83428348
auto wrapperType = paramDecl->getAttachedPropertyWrapperType(0);

test/SILGen/property_wrapper_parameter.swift

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ func testImplicitPropertyWrapper(projection: ProjectionWrapper<Int>) {
183183
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFyAFcfu_yAFcfU_6$valueL_AFvg : $@convention(thin) (ProjectionWrapper<Int>) -> ProjectionWrapper<Int>
184184

185185
// getter of value #1 in closure #1 in implicit closure #1 in testImplicitPropertyWrapper(projection:)
186-
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFyAFcfu_yAFcfU_5valueL_Sivg : $@convention(thin) () -> Int
186+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFyAFcfu_yAFcfU_5valueL_Sivg : $@convention(thin) (ProjectionWrapper<Int>) -> Int
187187

188188
let _: (ProjectionWrapper<Int>) -> (Int, ProjectionWrapper<Int>) = { $value in
189189
(value, $value)
@@ -202,7 +202,7 @@ func testImplicitPropertyWrapper(projection: ProjectionWrapper<Int>) {
202202
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFSi_AFtAFcfu0_Si_AFtAFcfU0_6$valueL_AFvg : $@convention(thin) (ProjectionWrapper<Int>) -> ProjectionWrapper<Int>
203203

204204
// getter of value #1 in closure #2 in implicit closure #2 in testImplicitPropertyWrapper(projection:)
205-
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFSi_AFtAFcfu0_Si_AFtAFcfU0_5valueL_Sivg : $@convention(thin) () -> Int
205+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFSi_AFtAFcfu0_Si_AFtAFcfU0_5valueL_Sivg : $@convention(thin) (ProjectionWrapper<Int>) -> Int
206206
}
207207

208208
@propertyWrapper
@@ -247,3 +247,39 @@ public func publicFunc(@PublicWrapper value: String) {
247247
// CHECK: function_ref @$s26property_wrapper_parameter10publicFunc5valueyAA13PublicWrapperVySSG_tFACL_SSvpfP : $@convention(thin) (@owned String) -> @owned PublicWrapper<String>
248248
// CHECK: function_ref @$s26property_wrapper_parameter10publicFunc5valueyAA13PublicWrapperVySSG_tF : $@convention(thin) (@guaranteed PublicWrapper<String>) -> ()
249249
}
250+
251+
@propertyWrapper
252+
struct NonmutatingSetter<Value> {
253+
var wrappedValue: Value {
254+
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_parameter17NonmutatingSetterV12wrappedValuexvg : $@convention(method) <Value> (NonmutatingSetter<Value>) -> @out Value
255+
get { fatalError() }
256+
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_parameter17NonmutatingSetterV12wrappedValuexvs : $@convention(method) <Value> (@in Value, NonmutatingSetter<Value>) -> ()
257+
nonmutating set {}
258+
}
259+
var projectedValue: Self { self }
260+
init(wrappedValue: Value) {}
261+
init(projectedValue: Self) {}
262+
}
263+
264+
func genericClosure<T>(arg: T, _ closure: (T) -> Int) {}
265+
266+
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_parameter30testNonmutatingSetterSynthesis5valueyAA0eF0VySiG_tF : $@convention(thin) (NonmutatingSetter<Int>) -> ()
267+
func testNonmutatingSetterSynthesis(@NonmutatingSetter value: Int) {
268+
genericClosure(arg: $value) { $value in
269+
(value = 10, value).1
270+
}
271+
272+
// closure #1 in implicit closure #1 in testNonmutatingSetterSynthesis(value:)
273+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter30testNonmutatingSetterSynthesis5valueyAA0eF0VySiG_tFSiAFcfu_SiAFcfU_ : $@convention(thin) (NonmutatingSetter<Int>) -> Int
274+
// CHECK: function_ref @$s26property_wrapper_parameter30testNonmutatingSetterSynthesis5valueyAA0eF0VySiG_tFSiAFcfu_SiAFcfU_ACL_Sivs : $@convention(thin) (Int, NonmutatingSetter<Int>) -> ()
275+
// CHECK: function_ref @$s26property_wrapper_parameter30testNonmutatingSetterSynthesis5valueyAA0eF0VySiG_tFSiAFcfu_SiAFcfU_ACL_Sivg : $@convention(thin) (NonmutatingSetter<Int>) -> Int
276+
// CHECK: return
277+
278+
// getter of value #1 in closure #1 in implicit closure #1 in testNonmutatingSetterSynthesis(value:)
279+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter30testNonmutatingSetterSynthesis5valueyAA0eF0VySiG_tFSiAFcfu_SiAFcfU_ACL_Sivg : $@convention(thin) (NonmutatingSetter<Int>) -> Int
280+
// CHECK: function_ref @$s26property_wrapper_parameter17NonmutatingSetterV12wrappedValuexvg : $@convention(method) <τ_0_0> (NonmutatingSetter<τ_0_0>) -> @out τ_0_0
281+
282+
// setter of value #1 in closure #1 in implicit closure #1 in testNonmutatingSetterSynthesis(value:)
283+
// CHECK-LABEL: sil private [ossa] @$s26property_wrapper_parameter30testNonmutatingSetterSynthesis5valueyAA0eF0VySiG_tFSiAFcfu_SiAFcfU_ACL_Sivs : $@convention(thin) (Int, NonmutatingSetter<Int>) -> ()
284+
// CHECK: function_ref @$s26property_wrapper_parameter17NonmutatingSetterV12wrappedValuexvs : $@convention(method) <τ_0_0> (@in τ_0_0, NonmutatingSetter<τ_0_0>) -> ()
285+
}

0 commit comments

Comments
 (0)