Skip to content

Commit 99e0666

Browse files
committed
[ConstraintSystem] Inject implicit applied property wrapper expressions
around arguments to property wrapper parameters.
1 parent 9cdecf4 commit 99e0666

File tree

5 files changed

+58
-41
lines changed

5 files changed

+58
-41
lines changed

include/swift/AST/PropertyWrappers.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ enum class PropertyWrapperInitKind {
4242
Default
4343
};
4444

45+
/// Information about an applied property wrapper, including the backing wrapper type
46+
/// and the initialization kind.
47+
struct AppliedPropertyWrapper {
48+
Type wrapperType;
49+
PropertyWrapperInitKind initKind;
50+
};
51+
4552
/// Describes a property wrapper type.
4653
struct PropertyWrapperTypeInfo {
4754
/// The property through which access that uses this wrapper type is

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ class Solution {
11871187
resultBuilderTransformed;
11881188

11891189
/// A map from argument expressions to their applied property wrapper expressions.
1190-
llvm::MapVector<ASTNode, SmallVector<Expr *, 2>> appliedPropertyWrappers;
1190+
llvm::MapVector<ASTNode, SmallVector<AppliedPropertyWrapper, 2>> appliedPropertyWrappers;
11911191

11921192
/// Simplify the given type by substituting all occurrences of
11931193
/// type variables for their fixed types.
@@ -2238,7 +2238,7 @@ class ConstraintSystem {
22382238

22392239
public:
22402240
/// A map from argument expressions to their applied property wrapper expressions.
2241-
llvm::SmallMapVector<ASTNode,SmallVector<Expr *, 2>, 4> appliedPropertyWrappers;
2241+
llvm::SmallMapVector<ASTNode, SmallVector<AppliedPropertyWrapper, 2>, 4> appliedPropertyWrappers;
22422242

22432243
/// The locators of \c Defaultable constraints whose defaults were used.
22442244
std::vector<ConstraintLocator *> DefaultedConstraints;

lib/Sema/CSApply.cpp

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ namespace {
979979

980980
AutoClosureExpr *buildPropertyWrapperFnThunk(
981981
Expr *fnRef, FunctionType *fnType, AnyFunctionRef fnDecl,
982-
ArrayRef<Expr *> appliedPropertyWrappers) {
982+
ArrayRef<AppliedPropertyWrapper> appliedPropertyWrappers) {
983983
auto &context = cs.getASTContext();
984984
auto paramInfo = fnType->getParams();
985985

@@ -1010,17 +1010,17 @@ namespace {
10101010
if (auto wrapperInfo = innerParam->getPropertyWrapperBackingPropertyInfo()) {
10111011
// Rewrite the parameter ref to the backing wrapper initialization
10121012
// expression.
1013-
Expr *init = appliedPropertyWrappers[appliedWrapperIndex++];
1014-
auto *placeholder = findWrappedValuePlaceholder(init);
1015-
placeholder->setOriginalWrappedValue(paramRef);
1016-
1017-
auto target = SolutionApplicationTarget(init, cs.DC, CTP_Unused, Type(),
1018-
/*isDiscarded=*/false);
1019-
auto result = cs.applySolution(solution, target);
1020-
if (!result)
1021-
return nullptr;
1013+
auto appliedWrapper = appliedPropertyWrappers[appliedWrapperIndex++];
1014+
auto wrapperType = appliedWrapper.wrapperType;
1015+
auto initKind = appliedWrapper.initKind;
1016+
1017+
using ValueKind = AppliedPropertyWrapperExpr::ValueKind;
1018+
ValueKind valueKind = (initKind == PropertyWrapperInitKind::ProjectedValue ?
1019+
ValueKind::ProjectedValue : ValueKind::WrappedValue);
10221020

1023-
paramRef = result->getAsExpr();
1021+
paramRef = AppliedPropertyWrapperExpr::create(context, innerParam,
1022+
innerParam->getStartLoc(),
1023+
wrapperType, paramRef, valueKind);
10241024
cs.cacheExprTypes(paramRef);
10251025

10261026
// SILGen knows how to emit property-wrapped parameters, but the
@@ -1836,7 +1836,7 @@ namespace {
18361836
ConcreteDeclRef callee, ApplyExpr *apply,
18371837
ArrayRef<Identifier> argLabels,
18381838
ConstraintLocatorBuilder locator,
1839-
ArrayRef<Expr *> appliedPropertyWrappers);
1839+
ArrayRef<AppliedPropertyWrapper> appliedPropertyWrappers);
18401840

18411841
/// Coerce the given 'self' argument (e.g., for the base of a
18421842
/// member expression) to the given type.
@@ -5599,7 +5599,7 @@ Expr *ExprRewriter::coerceCallArguments(
55995599
ApplyExpr *apply,
56005600
ArrayRef<Identifier> argLabels,
56015601
ConstraintLocatorBuilder locator,
5602-
ArrayRef<Expr *> appliedPropertyWrappers) {
5602+
ArrayRef<AppliedPropertyWrapper> appliedPropertyWrappers) {
56035603
auto &ctx = getConstraintSystem().getASTContext();
56045604
auto params = funcType->getParams();
56055605
unsigned appliedWrapperIndex = 0;
@@ -5832,19 +5832,17 @@ Expr *ExprRewriter::coerceCallArguments(
58325832
return true;
58335833
};
58345834

5835-
if (paramInfo.getPropertyWrapperParam(paramIdx)) {
5836-
Expr *init = appliedPropertyWrappers[appliedWrapperIndex++];
5837-
auto *placeholder = findWrappedValuePlaceholder(init);
5838-
placeholder->setOriginalWrappedValue(arg);
5835+
if (auto *param = paramInfo.getPropertyWrapperParam(paramIdx)) {
5836+
auto appliedWrapper = appliedPropertyWrappers[appliedWrapperIndex++];
5837+
auto wrapperType = solution.simplifyType(appliedWrapper.wrapperType);
5838+
auto initKind = appliedWrapper.initKind;
58395839

5840-
// Apply the solution to the property wrapper initializer.
5841-
auto target = SolutionApplicationTarget(init, cs.DC, CTP_Unused, Type(),
5842-
/*isDiscarded=*/false);
5843-
auto result = cs.applySolution(solution, target);
5844-
if (!result)
5845-
return nullptr;
5840+
using ValueKind = AppliedPropertyWrapperExpr::ValueKind;
5841+
ValueKind valueKind = (initKind == PropertyWrapperInitKind::ProjectedValue ?
5842+
ValueKind::ProjectedValue : ValueKind::WrappedValue);
58465843

5847-
arg = result->getAsExpr();
5844+
arg = AppliedPropertyWrapperExpr::create(ctx, param, arg->getStartLoc(),
5845+
wrapperType, arg, valueKind);
58485846
cs.cacheExprTypes(arg);
58495847
}
58505848

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4097,16 +4097,7 @@ ConstraintSystem::applyPropertyWrapperParameter(
40974097
initKind = PropertyWrapperInitKind::WrappedValue;
40984098
}
40994099

4100-
// Build the wrapper initializer expression and generate constraints.
4101-
auto *placeholder = PropertyWrapperValuePlaceholderExpr::create(
4102-
getASTContext(), anchor->getSourceRange(), Type(), /*wrappedValue*/nullptr);
4103-
setType(placeholder, paramType);
4104-
4105-
auto *init = buildPropertyWrapperInitCall(param, wrapperType, placeholder, initKind);
4106-
setType(init, wrapperType);
4107-
generateConstraints(init, DC);
4108-
4109-
appliedPropertyWrappers[anchor].push_back({ init });
4100+
appliedPropertyWrappers[anchor].push_back({ wrapperType, initKind });
41104101
return getTypeMatchSuccess();
41114102
}
41124103

test/SILGen/property_wrapper_parameter.swift

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ public func testSimpleWrapperParameter(@Wrapper value: Int) {
2929
_ = _value
3030
_ = $value
3131

32+
// property wrapper backing initializer of value #1 in testSimpleWrapperParameter(value:)
33+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter26testSimpleWrapperParameter5valueyAA0F0VySiG_tFACL_SivpfP : $@convention(thin) (Int) -> Wrapper<Int>
34+
35+
// property wrapper init from projected value of value #1 in testSimpleWrapperParameter(value:)
36+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter26testSimpleWrapperParameter5valueyAA0F0VySiG_tFACL_SivpfW : $@convention(thin) (Projection<Int>) -> Wrapper<Int>
37+
3238
// getter of $value #1 in testSimpleWrapperParameter(value:)
3339
// CHECK: sil private [ossa] @$s26property_wrapper_parameter26testSimpleWrapperParameter5valueyAA0F0VySiG_tF6$valueL_AA10ProjectionVySiGvg : $@convention(thin) (Wrapper<Int>) -> Projection<Int>
3440

@@ -39,15 +45,15 @@ public func testSimpleWrapperParameter(@Wrapper value: Int) {
3945
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_parameter28simpleWrapperParameterCaller10projectionyAA10ProjectionVySiG_tF : $@convention(thin) (Projection<Int>) -> ()
4046
func simpleWrapperParameterCaller(projection: Projection<Int>) {
4147
testSimpleWrapperParameter(value: projection.wrappedValue)
42-
// CHECK: function_ref @$s26property_wrapper_parameter7WrapperV12wrappedValueACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin Wrapper<τ_0_0>.Type) -> @out Wrapper<τ_0_0>
48+
// CHECK: function_ref @$s26property_wrapper_parameter26testSimpleWrapperParameter5valueyAA0F0VySiG_tFACL_SivpfP : $@convention(thin) (Int) -> Wrapper<Int>
4349

4450
testSimpleWrapperParameter($value: projection)
45-
// CHECK: function_ref @$s26property_wrapper_parameter7WrapperV14projectedValueACyxGAA10ProjectionVyxG_tcfC : $@convention(method) <τ_0_0> (@in Projection<τ_0_0>, @thin Wrapper<τ_0_0>.Type) -> @out Wrapper<τ_0_0>
51+
// CHECK: function_ref @$s26property_wrapper_parameter26testSimpleWrapperParameter5valueyAA0F0VySiG_tFACL_SivpfW : $@convention(thin) (Projection<Int>) -> Wrapper<Int>
4652
}
4753

4854
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_parameter33testSimpleClosureWrapperParameteryyF : $@convention(thin) () -> ()
4955
func testSimpleClosureWrapperParameter() {
50-
let closure: (Int) -> Void = { (@Wrapper value) in
56+
let closure: (Int) -> Void = { (@Wrapper value: Int) in
5157
_ = value
5258
_ = _value
5359
_ = $value
@@ -61,6 +67,9 @@ func testSimpleClosureWrapperParameter() {
6167
// closure #1 in implicit closure #1 in testSimpleClosureWrapperParameter()
6268
// CHECK: sil private [ossa] @$s26property_wrapper_parameter33testSimpleClosureWrapperParameteryyFySicfu_yAA0G0VySiGcfU_ : $@convention(thin) (Wrapper<Int>) -> ()
6369

70+
// property wrapper backing initializer of value #1 in closure #1 in implicit closure #1 in testSimpleClosureWrapperParameter()
71+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter33testSimpleClosureWrapperParameteryyFySicfu_yAA0G0VySiGcfU_5valueL_SivpfP : $@convention(thin) (Int) -> Wrapper<Int>
72+
6473
// getter of $value #1 in closure #1 in implicit closure #1 in testSimpleClosureWrapperParameter()
6574
// CHECK: sil private [ossa] @$s26property_wrapper_parameter33testSimpleClosureWrapperParameteryyFySicfu_yAA0G0VySiGcfU_6$valueL_AA10ProjectionVySiGvg : $@convention(thin) (Wrapper<Int>) -> Projection<Int>
6675

@@ -96,6 +105,12 @@ func testNonMutatingSetter(@NonMutatingSetterWrapper value1: String, @ClassWrapp
96105
_ = value1
97106
value1 = "hello!"
98107

108+
// property wrapper backing initializer of value1 #1 in testNonMutatingSetter(value1:value2:)
109+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter21testNonMutatingSetter6value16value2yAA0efG7WrapperVySSG_AA05ClassJ0CySiGtFACL_SSvpfP : $@convention(thin) (@owned String) -> @owned NonMutatingSetterWrapper<String>
110+
111+
// property wrapper backing initializer of value2 #1 in testNonMutatingSetter(value1:value2:)
112+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter21testNonMutatingSetter6value16value2yAA0efG7WrapperVySSG_AA05ClassJ0CySiGtFADL_SivpfP : $@convention(thin) (Int) -> @owned ClassWrapper<Int>
113+
99114
// getter of value1 #1 in testNonMutatingSetter(value1:value2:)
100115
// CHECK: sil private [ossa] @$s26property_wrapper_parameter21testNonMutatingSetter6value16value2yAA0efG7WrapperVySSG_AA05ClassJ0CySiGtFACL_SSvg : $@convention(thin) (@guaranteed NonMutatingSetterWrapper<String>) -> @owned String
101116

@@ -127,7 +142,7 @@ struct ProjectionWrapper<Value> {
127142

128143
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tF : $@convention(thin) (ProjectionWrapper<Int>) -> ()
129144
func testImplicitPropertyWrapper(projection: ProjectionWrapper<Int>) {
130-
let multiStatement: (ProjectionWrapper<Int>) -> Void = { $value in
145+
let multiStatement: (ProjectionWrapper<Int>) -> Void = { ($value: ProjectionWrapper<Int>) in
131146
_ = value
132147
_ = _value
133148
_ = $value
@@ -141,13 +156,16 @@ func testImplicitPropertyWrapper(projection: ProjectionWrapper<Int>) {
141156
// closure #1 in implicit closure #1 in testImplicitPropertyWrapper(projection:)
142157
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFyAFcfu_yAFcfU_ : $@convention(thin) (ProjectionWrapper<Int>) -> ()
143158

159+
// property wrapper init from projected value of $value #1 in closure #1 in implicit closure #1 in testImplicitPropertyWrapper(projection:)
160+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFyAFcfu_yAFcfU_6$valueL_AFvpfW : $@convention(thin) (ProjectionWrapper<Int>) -> ProjectionWrapper<Int>
161+
144162
// getter of $value #1 in closure #1 in implicit closure #1 in testImplicitPropertyWrapper(projection:)
145163
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFyAFcfu_yAFcfU_6$valueL_AFvg : $@convention(thin) (ProjectionWrapper<Int>) -> ProjectionWrapper<Int>
146164

147165
// getter of value #1 in closure #1 in implicit closure #1 in testImplicitPropertyWrapper(projection:)
148166
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFyAFcfu_yAFcfU_5valueL_Sivg : $@convention(thin) () -> Int
149167

150-
let _: (ProjectionWrapper<Int>) -> (Int, ProjectionWrapper<Int>) = { $value in
168+
let _: (ProjectionWrapper<Int>) -> (Int, ProjectionWrapper<Int>) = { ($value: ProjectionWrapper<Int>) in
151169
(value, $value)
152170
}
153171

@@ -157,6 +175,9 @@ func testImplicitPropertyWrapper(projection: ProjectionWrapper<Int>) {
157175
// closure #2 in implicit closure #2 in testImplicitPropertyWrapper(projection:)
158176
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFSi_AFtAFcfu0_Si_AFtAFcfU0_ : $@convention(thin) (ProjectionWrapper<Int>) -> (Int, ProjectionWrapper<Int>)
159177

178+
// property wrapper init from projected value of $value #1 in closure #2 in implicit closure #2 in testImplicitPropertyWrapper(projection:)
179+
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFSi_AFtAFcfu0_Si_AFtAFcfU0_6$valueL_AFvpfW : $@convention(thin) (ProjectionWrapper<Int>) -> ProjectionWrapper<Int>
180+
160181
// getter of $value #1 in closure #2 in implicit closure #2 in testImplicitPropertyWrapper(projection:)
161182
// CHECK: sil private [ossa] @$s26property_wrapper_parameter27testImplicitPropertyWrapper10projectionyAA010ProjectionG0VySiG_tFSi_AFtAFcfu0_Si_AFtAFcfU0_6$valueL_AFvg : $@convention(thin) (ProjectionWrapper<Int>) -> ProjectionWrapper<Int>
162183

0 commit comments

Comments
 (0)