Skip to content

Commit 84123cb

Browse files
committed
[Property Wrappers] Unify the initializer type checking code paths between
wrapped parameters and wrapped properties. This fixes a bug where @autoclosure was not propagated from the wrapper's init(wrappedValue:) to a wrapped argument.
1 parent a87f803 commit 84123cb

File tree

6 files changed

+58
-44
lines changed

6 files changed

+58
-44
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,10 @@ class SolutionApplicationTarget {
16951695
static SolutionApplicationTarget forUninitializedWrappedVar(
16961696
VarDecl *wrappedVar);
16971697

1698+
/// Form a target for a synthesized property wrapper initializer.
1699+
static SolutionApplicationTarget forPropertyWrapperInitializer(
1700+
VarDecl *wrappedVar, DeclContext *dc, Expr *initializer);
1701+
16981702
Expr *getAsExpr() const {
16991703
switch (kind) {
17001704
case Kind::expression:
@@ -1802,7 +1806,7 @@ class SolutionApplicationTarget {
18021806
bool isOptionalSomePatternInit() const {
18031807
return kind == Kind::expression &&
18041808
expression.contextualPurpose == CTP_Initialization &&
1805-
isa<OptionalSomePattern>(expression.pattern) &&
1809+
dyn_cast_or_null<OptionalSomePattern>(expression.pattern) &&
18061810
!expression.pattern->isImplicit();
18071811
}
18081812

@@ -1826,7 +1830,9 @@ class SolutionApplicationTarget {
18261830

18271831
// Don't create property wrapper generator functions for static variables and
18281832
// local variables with initializers.
1829-
if (wrappedVar->isStatic() || wrappedVar->getDeclContext()->isLocalContext())
1833+
bool hasInit = expression.propertyWrapper.hasInitialWrappedValue;
1834+
if (wrappedVar->isStatic() ||
1835+
(hasInit && wrappedVar->getDeclContext()->isLocalContext()))
18301836
return false;
18311837

18321838
return expression.propertyWrapper.innermostWrappedValueInit == apply;

lib/Sema/CSApply.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8432,13 +8432,18 @@ static Optional<SolutionApplicationTarget> applySolutionToInitialization(
84328432
// been subsumed by the backing property.
84338433
if (wrappedVar) {
84348434
ASTContext &ctx = cs.getASTContext();
8435-
wrappedVar->getParentPatternBinding()->setInitializerSubsumed(0);
84368435
ctx.setSideCachedPropertyWrapperBackingPropertyType(
84378436
wrappedVar, initType->mapTypeOutOfContext());
84388437

84398438
// Record the semantic initializer on the outermost property wrapper.
84408439
wrappedVar->getAttachedPropertyWrappers().front()
84418440
->setSemanticInit(initializer);
8441+
8442+
// If this is a wrapped parameter, we're done.
8443+
if (isa<ParamDecl>(wrappedVar))
8444+
return resultTarget;
8445+
8446+
wrappedVar->getParentPatternBinding()->setInitializerSubsumed(0);
84428447
}
84438448

84448449
// Coerce the pattern to the type of the initializer.

lib/Sema/ConstraintSystem.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5102,7 +5102,14 @@ SolutionApplicationTarget::SolutionApplicationTarget(
51025102
void SolutionApplicationTarget::maybeApplyPropertyWrapper() {
51035103
assert(kind == Kind::expression);
51045104
assert(expression.contextualPurpose == CTP_Initialization);
5105-
auto singleVar = expression.pattern->getSingleVar();
5105+
5106+
VarDecl *singleVar;
5107+
if (auto *pattern = expression.pattern) {
5108+
singleVar = pattern->getSingleVar();
5109+
} else {
5110+
singleVar = expression.propertyWrapper.wrappedVar;
5111+
}
5112+
51065113
if (!singleVar)
51075114
return;
51085115

@@ -5232,6 +5239,23 @@ SolutionApplicationTarget::forUninitializedWrappedVar(VarDecl *wrappedVar) {
52325239
return SolutionApplicationTarget(wrappedVar);
52335240
}
52345241

5242+
SolutionApplicationTarget
5243+
SolutionApplicationTarget::forPropertyWrapperInitializer(
5244+
VarDecl *wrappedVar, DeclContext *dc, Expr *initializer) {
5245+
SolutionApplicationTarget target(
5246+
initializer, dc, CTP_Initialization, wrappedVar->getType(),
5247+
/*isDiscarded=*/false);
5248+
target.expression.propertyWrapper.wrappedVar = wrappedVar;
5249+
if (auto *patternBinding = wrappedVar->getParentPatternBinding()) {
5250+
auto index = patternBinding->getPatternEntryIndexForVarDecl(wrappedVar);
5251+
target.expression.initialization.patternBinding = patternBinding;
5252+
target.expression.initialization.patternBindingIndex = index;
5253+
target.expression.pattern = patternBinding->getPattern(index);
5254+
}
5255+
target.maybeApplyPropertyWrapper();
5256+
return target;
5257+
}
5258+
52355259
ContextualPattern
52365260
SolutionApplicationTarget::getContextualPattern() const {
52375261
assert(kind == Kind::expression);

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,8 +2597,8 @@ void swift::checkEnumElementActorIsolation(
25972597
}
25982598

25992599
void swift::checkPropertyWrapperActorIsolation(
2600-
PatternBindingDecl *binding, Expr *expr) {
2601-
ActorIsolationChecker checker(binding->getDeclContext());
2600+
VarDecl *wrappedVar, Expr *expr) {
2601+
ActorIsolationChecker checker(wrappedVar->getDeclContext());
26022602
expr->walk(checker);
26032603
}
26042604

lib/Sema/TypeCheckConcurrency.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class ProtocolConformance;
4444
class TopLevelCodeDecl;
4545
class TypeBase;
4646
class ValueDecl;
47+
class VarDecl;
4748

4849
/// Add notes suggesting the addition of 'async' or '@asyncHandler', as
4950
/// appropriate, to a diagnostic for a function that isn't an async context.
@@ -54,8 +55,7 @@ void checkTopLevelActorIsolation(TopLevelCodeDecl *decl);
5455
void checkFunctionActorIsolation(AbstractFunctionDecl *decl);
5556
void checkInitializerActorIsolation(Initializer *init, Expr *expr);
5657
void checkEnumElementActorIsolation(EnumElementDecl *element, Expr *expr);
57-
void checkPropertyWrapperActorIsolation(
58-
PatternBindingDecl *binding, Expr *expr);
58+
void checkPropertyWrapperActorIsolation(VarDecl *wrappedVar, Expr *expr);
5959

6060
/// Determine the isolation of a particular closure.
6161
///

lib/Sema/TypeCheckStorage.cpp

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,31 +2571,24 @@ static VarDecl *synthesizePropertyWrapperProjectionVar(
25712571

25722572
static void typeCheckSynthesizedWrapperInitializer(VarDecl *wrappedVar,
25732573
Expr *&initializer) {
2574-
// Figure out the context in which the initializer was written.
2575-
auto *parentPBD = wrappedVar->getParentPatternBinding();
2576-
auto i = parentPBD->getPatternEntryIndexForVarDecl(wrappedVar);
2577-
DeclContext *originalDC = parentPBD->getDeclContext();
2578-
if (!originalDC->isLocalContext()) {
2579-
auto initContext =
2580-
cast_or_null<PatternBindingInitializer>(parentPBD->getInitContext(i));
2581-
if (initContext)
2582-
originalDC = initContext;
2583-
}
2574+
auto *dc = wrappedVar->getInnermostDeclContext();
2575+
auto &ctx = wrappedVar->getASTContext();
2576+
auto *initContext = new (ctx) PropertyWrapperInitializer(
2577+
dc, wrappedVar, PropertyWrapperInitializer::Kind::WrappedValue);
25842578

25852579
// Type-check the initialization.
2586-
auto *pattern = parentPBD->getPattern(i);
2587-
TypeChecker::typeCheckBinding(pattern, initializer, originalDC,
2588-
wrappedVar->getType(), parentPBD, i);
2580+
using namespace constraints;
2581+
auto target = SolutionApplicationTarget::forPropertyWrapperInitializer(
2582+
wrappedVar, initContext, initializer);
2583+
auto result = TypeChecker::typeCheckExpression(target);
2584+
if (!result)
2585+
return;
25892586

2590-
if (auto initializerContext =
2591-
dyn_cast_or_null<Initializer>(parentPBD->getInitContext(i))) {
2592-
TypeChecker::contextualizeInitializer(initializerContext, initializer);
2593-
}
2587+
initializer = result->getAsExpr();
25942588

2595-
auto *backingVar = wrappedVar->getPropertyWrapperBackingProperty();
2596-
auto *backingPBD = backingVar->getParentPatternBinding();
2597-
checkPropertyWrapperActorIsolation(backingPBD, initializer);
2598-
TypeChecker::checkPropertyWrapperEffects(backingPBD, initializer);
2589+
TypeChecker::contextualizeInitializer(initContext, initializer);
2590+
checkPropertyWrapperActorIsolation(wrappedVar, initializer);
2591+
TypeChecker::checkInitializerEffects(initContext, initializer);
25992592
}
26002593

26012594
static PropertyWrapperMutability::Value
@@ -2954,21 +2947,7 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
29542947
!var->getName().hasDollarPrefix()) {
29552948
wrappedValueInit = PropertyWrapperValuePlaceholderExpr::create(
29562949
ctx, var->getSourceRange(), var->getType(), /*wrappedValue=*/nullptr);
2957-
2958-
if (auto *param = dyn_cast<ParamDecl>(var)) {
2959-
wrappedValueInit = buildPropertyWrapperInitCall(
2960-
var, storageType, wrappedValueInit, PropertyWrapperInitKind::WrappedValue);
2961-
TypeChecker::typeCheckExpression(wrappedValueInit, dc);
2962-
2963-
// Check initializer effects.
2964-
auto *initContext = new (ctx) PropertyWrapperInitializer(
2965-
dc, param, PropertyWrapperInitializer::Kind::WrappedValue);
2966-
TypeChecker::contextualizeInitializer(initContext, wrappedValueInit);
2967-
checkInitializerActorIsolation(initContext, wrappedValueInit);
2968-
TypeChecker::checkInitializerEffects(initContext, wrappedValueInit);
2969-
} else {
2970-
typeCheckSynthesizedWrapperInitializer(var, wrappedValueInit);
2971-
}
2950+
typeCheckSynthesizedWrapperInitializer(var, wrappedValueInit);
29722951
}
29732952

29742953
return PropertyWrapperInitializerInfo(wrappedValueInit, projectedValueInit);

0 commit comments

Comments
 (0)