Skip to content

Commit 81f5180

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 28caecb commit 81f5180

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
@@ -1706,6 +1706,10 @@ class SolutionApplicationTarget {
17061706
static SolutionApplicationTarget forUninitializedWrappedVar(
17071707
VarDecl *wrappedVar);
17081708

1709+
/// Form a target for a synthesized property wrapper initializer.
1710+
static SolutionApplicationTarget forPropertyWrapperInitializer(
1711+
VarDecl *wrappedVar, DeclContext *dc, Expr *initializer);
1712+
17091713
Expr *getAsExpr() const {
17101714
switch (kind) {
17111715
case Kind::expression:
@@ -1813,7 +1817,7 @@ class SolutionApplicationTarget {
18131817
bool isOptionalSomePatternInit() const {
18141818
return kind == Kind::expression &&
18151819
expression.contextualPurpose == CTP_Initialization &&
1816-
isa<OptionalSomePattern>(expression.pattern) &&
1820+
dyn_cast_or_null<OptionalSomePattern>(expression.pattern) &&
18171821
!expression.pattern->isImplicit();
18181822
}
18191823

@@ -1837,7 +1841,9 @@ class SolutionApplicationTarget {
18371841

18381842
// Don't create property wrapper generator functions for static variables and
18391843
// local variables with initializers.
1840-
if (wrappedVar->isStatic() || wrappedVar->getDeclContext()->isLocalContext())
1844+
bool hasInit = expression.propertyWrapper.hasInitialWrappedValue;
1845+
if (wrappedVar->isStatic() ||
1846+
(hasInit && wrappedVar->getDeclContext()->isLocalContext()))
18411847
return false;
18421848

18431849
return expression.propertyWrapper.innermostWrappedValueInit == apply;

lib/Sema/CSApply.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8420,13 +8420,18 @@ static Optional<SolutionApplicationTarget> applySolutionToInitialization(
84208420
// been subsumed by the backing property.
84218421
if (wrappedVar) {
84228422
ASTContext &ctx = cs.getASTContext();
8423-
wrappedVar->getParentPatternBinding()->setInitializerSubsumed(0);
84248423
ctx.setSideCachedPropertyWrapperBackingPropertyType(
84258424
wrappedVar, initType->mapTypeOutOfContext());
84268425

84278426
// Record the semantic initializer on the outermost property wrapper.
84288427
wrappedVar->getAttachedPropertyWrappers().front()
84298428
->setSemanticInit(initializer);
8429+
8430+
// If this is a wrapped parameter, we're done.
8431+
if (isa<ParamDecl>(wrappedVar))
8432+
return resultTarget;
8433+
8434+
wrappedVar->getParentPatternBinding()->setInitializerSubsumed(0);
84308435
}
84318436

84328437
// 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
@@ -5230,7 +5230,14 @@ SolutionApplicationTarget::SolutionApplicationTarget(
52305230
void SolutionApplicationTarget::maybeApplyPropertyWrapper() {
52315231
assert(kind == Kind::expression);
52325232
assert(expression.contextualPurpose == CTP_Initialization);
5233-
auto singleVar = expression.pattern->getSingleVar();
5233+
5234+
VarDecl *singleVar;
5235+
if (auto *pattern = expression.pattern) {
5236+
singleVar = pattern->getSingleVar();
5237+
} else {
5238+
singleVar = expression.propertyWrapper.wrappedVar;
5239+
}
5240+
52345241
if (!singleVar)
52355242
return;
52365243

@@ -5360,6 +5367,23 @@ SolutionApplicationTarget::forUninitializedWrappedVar(VarDecl *wrappedVar) {
53605367
return SolutionApplicationTarget(wrappedVar);
53615368
}
53625369

5370+
SolutionApplicationTarget
5371+
SolutionApplicationTarget::forPropertyWrapperInitializer(
5372+
VarDecl *wrappedVar, DeclContext *dc, Expr *initializer) {
5373+
SolutionApplicationTarget target(
5374+
initializer, dc, CTP_Initialization, wrappedVar->getType(),
5375+
/*isDiscarded=*/false);
5376+
target.expression.propertyWrapper.wrappedVar = wrappedVar;
5377+
if (auto *patternBinding = wrappedVar->getParentPatternBinding()) {
5378+
auto index = patternBinding->getPatternEntryIndexForVarDecl(wrappedVar);
5379+
target.expression.initialization.patternBinding = patternBinding;
5380+
target.expression.initialization.patternBindingIndex = index;
5381+
target.expression.pattern = patternBinding->getPattern(index);
5382+
}
5383+
target.maybeApplyPropertyWrapper();
5384+
return target;
5385+
}
5386+
53635387
ContextualPattern
53645388
SolutionApplicationTarget::getContextualPattern() const {
53655389
assert(kind == Kind::expression);

lib/Sema/TypeCheckConcurrency.cpp

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

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

lib/Sema/TypeCheckConcurrency.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class ProtocolConformance;
4545
class TopLevelCodeDecl;
4646
class TypeBase;
4747
class ValueDecl;
48+
class VarDecl;
4849

4950
/// Add notes suggesting the addition of 'async', as appropriate,
5051
/// to a diagnostic for a function that isn't an async context.
@@ -57,8 +58,7 @@ void checkActorConstructor(ClassDecl *decl, ConstructorDecl *ctor);
5758
void checkActorConstructorBody(ClassDecl *decl, ConstructorDecl *ctor, BraceStmt *body);
5859
void checkInitializerActorIsolation(Initializer *init, Expr *expr);
5960
void checkEnumElementActorIsolation(EnumElementDecl *element, Expr *expr);
60-
void checkPropertyWrapperActorIsolation(
61-
PatternBindingDecl *binding, Expr *expr);
61+
void checkPropertyWrapperActorIsolation(VarDecl *wrappedVar, Expr *expr);
6262

6363
/// Determine the isolation of a particular closure.
6464
///

lib/Sema/TypeCheckStorage.cpp

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

25872587
static void typeCheckSynthesizedWrapperInitializer(VarDecl *wrappedVar,
25882588
Expr *&initializer) {
2589-
// Figure out the context in which the initializer was written.
2590-
auto *parentPBD = wrappedVar->getParentPatternBinding();
2591-
auto i = parentPBD->getPatternEntryIndexForVarDecl(wrappedVar);
2592-
DeclContext *originalDC = parentPBD->getDeclContext();
2593-
if (!originalDC->isLocalContext()) {
2594-
auto initContext =
2595-
cast_or_null<PatternBindingInitializer>(parentPBD->getInitContext(i));
2596-
if (initContext)
2597-
originalDC = initContext;
2598-
}
2589+
auto *dc = wrappedVar->getInnermostDeclContext();
2590+
auto &ctx = wrappedVar->getASTContext();
2591+
auto *initContext = new (ctx) PropertyWrapperInitializer(
2592+
dc, wrappedVar, PropertyWrapperInitializer::Kind::WrappedValue);
25992593

26002594
// Type-check the initialization.
2601-
auto *pattern = parentPBD->getPattern(i);
2602-
TypeChecker::typeCheckBinding(pattern, initializer, originalDC,
2603-
wrappedVar->getType(), parentPBD, i);
2595+
using namespace constraints;
2596+
auto target = SolutionApplicationTarget::forPropertyWrapperInitializer(
2597+
wrappedVar, initContext, initializer);
2598+
auto result = TypeChecker::typeCheckExpression(target);
2599+
if (!result)
2600+
return;
26042601

2605-
if (auto initializerContext =
2606-
dyn_cast_or_null<Initializer>(parentPBD->getInitContext(i))) {
2607-
TypeChecker::contextualizeInitializer(initializerContext, initializer);
2608-
}
2602+
initializer = result->getAsExpr();
26092603

2610-
auto *backingVar = wrappedVar->getPropertyWrapperBackingProperty();
2611-
auto *backingPBD = backingVar->getParentPatternBinding();
2612-
checkPropertyWrapperActorIsolation(backingPBD, initializer);
2613-
TypeChecker::checkPropertyWrapperEffects(backingPBD, initializer);
2604+
TypeChecker::contextualizeInitializer(initContext, initializer);
2605+
checkPropertyWrapperActorIsolation(wrappedVar, initializer);
2606+
TypeChecker::checkInitializerEffects(initContext, initializer);
26142607
}
26152608

26162609
static PropertyWrapperMutability::Value
@@ -2969,21 +2962,7 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
29692962
!var->getName().hasDollarPrefix()) {
29702963
wrappedValueInit = PropertyWrapperValuePlaceholderExpr::create(
29712964
ctx, var->getSourceRange(), var->getType(), /*wrappedValue=*/nullptr);
2972-
2973-
if (auto *param = dyn_cast<ParamDecl>(var)) {
2974-
wrappedValueInit = buildPropertyWrapperInitCall(
2975-
var, storageType, wrappedValueInit, PropertyWrapperInitKind::WrappedValue);
2976-
TypeChecker::typeCheckExpression(wrappedValueInit, dc);
2977-
2978-
// Check initializer effects.
2979-
auto *initContext = new (ctx) PropertyWrapperInitializer(
2980-
dc, param, PropertyWrapperInitializer::Kind::WrappedValue);
2981-
TypeChecker::contextualizeInitializer(initContext, wrappedValueInit);
2982-
checkInitializerActorIsolation(initContext, wrappedValueInit);
2983-
TypeChecker::checkInitializerEffects(initContext, wrappedValueInit);
2984-
} else {
2985-
typeCheckSynthesizedWrapperInitializer(var, wrappedValueInit);
2986-
}
2965+
typeCheckSynthesizedWrapperInitializer(var, wrappedValueInit);
29872966
}
29882967

29892968
return PropertyWrapperInitializerInfo(wrappedValueInit, projectedValueInit);

0 commit comments

Comments
 (0)