Skip to content

Commit 85e3c7b

Browse files
authored
Merge pull request swiftlang#36696 from hborla/wrapped-parameter-accessor-synthesis
[Property Wrappers] Fix accessor synthesis of wrapped parameters that infer the property wrapper attribute.
2 parents 70a13aa + 2a4cc91 commit 85e3c7b

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
@@ -8092,17 +8092,30 @@ namespace {
80928092

80938093
// Set the interface type of each property wrapper synthesized var
80948094
auto *backingVar = param->getPropertyWrapperBackingProperty();
8095-
backingVar->setInterfaceType(
8096-
solution.simplifyType(solution.getType(backingVar))->mapTypeOutOfContext());
8095+
auto backingType =
8096+
solution.simplifyType(solution.getType(backingVar))->mapTypeOutOfContext();
8097+
backingVar->setInterfaceType(backingType);
80978098

80988099
if (auto *projectionVar = param->getPropertyWrapperProjectionVar()) {
80998100
projectionVar->setInterfaceType(
81008101
solution.simplifyType(solution.getType(projectionVar)));
81018102
}
81028103

81038104
auto *wrappedValueVar = param->getPropertyWrapperWrappedValueVar();
8104-
wrappedValueVar->setInterfaceType(
8105-
solution.simplifyType(solution.getType(wrappedValueVar)));
8105+
auto wrappedValueType = solution.simplifyType(solution.getType(wrappedValueVar));
8106+
wrappedValueVar->setInterfaceType(wrappedValueType->getWithoutSpecifierType());
8107+
8108+
if (param->hasImplicitPropertyWrapper()) {
8109+
if (wrappedValueType->is<LValueType>())
8110+
wrappedValueVar->setImplInfo(StorageImplInfo::getMutableComputed());
8111+
8112+
// Add an explicit property wrapper attribute, which is needed for
8113+
// synthesizing the accessors.
8114+
auto &context = wrappedValueVar->getASTContext();
8115+
auto *typeExpr = TypeExpr::createImplicit(backingType, context);
8116+
auto *attr = CustomAttr::create(context, SourceLoc(), typeExpr, /*implicit=*/true);
8117+
wrappedValueVar->getAttrs().add(attr);
8118+
}
81068119
}
81078120

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

lib/Sema/CSSimplify.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8212,7 +8212,12 @@ ConstraintSystem::simplifyPropertyWrapperConstraint(
82128212
}
82138213

82148214
auto resolvedType = wrapperType->getTypeOfMember(DC->getParentModule(), typeInfo.valueVar);
8215-
addConstraint(ConstraintKind::Equal, wrappedValueType, resolvedType, locator);
8215+
if (typeInfo.valueVar->isSettable(nullptr) && typeInfo.valueVar->isSetterAccessibleFrom(DC) &&
8216+
!typeInfo.valueVar->isSetterMutating()) {
8217+
resolvedType = LValueType::get(resolvedType);
8218+
}
8219+
8220+
addConstraint(ConstraintKind::Bind, wrappedValueType, resolvedType, locator);
82168221

82178222
return SolutionKind::Solved;
82188223
}
@@ -8390,7 +8395,8 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
83908395

83918396
if (paramDecl->hasImplicitPropertyWrapper()) {
83928397
backingType = getContextualParamAt(i)->getPlainType();
8393-
wrappedValueType = createTypeVariable(getConstraintLocator(locator), TVO_CanBindToHole);
8398+
wrappedValueType = createTypeVariable(getConstraintLocator(locator),
8399+
TVO_CanBindToHole | TVO_CanBindToLValue);
83948400
} else {
83958401
auto *wrapperAttr = paramDecl->getAttachedPropertyWrappers().front();
83968402
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)