Skip to content

Commit 5c2d8bf

Browse files
committed
[Sema] Prevent the initializer being double contextualize by its backing storage.
1 parent e9f7e8d commit 5c2d8bf

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

lib/Sema/TypeCheckStorage.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,7 +2689,8 @@ static VarDecl *synthesizePropertyWrapperProjectionVar(
26892689
}
26902690

26912691
static void typeCheckSynthesizedWrapperInitializer(VarDecl *wrappedVar,
2692-
Expr *&initializer) {
2692+
Expr *&initializer,
2693+
bool contextualize = false) {
26932694
auto *dc = wrappedVar->getInnermostDeclContext();
26942695
auto &ctx = wrappedVar->getASTContext();
26952696
auto *initContext = new (ctx) PropertyWrapperInitializer(
@@ -2705,6 +2706,11 @@ static void typeCheckSynthesizedWrapperInitializer(VarDecl *wrappedVar,
27052706

27062707
initializer = result->getAsExpr();
27072708

2709+
// Contextualize the initializer which is a local variable with defaultInit or
2710+
// gets an independent initializer. The rest of initializer contextualizing
2711+
// will be done in visitPatternBindingDecl.
2712+
if (!contextualize)
2713+
return;
27082714
TypeChecker::contextualizeInitializer(initContext, initializer);
27092715
checkPropertyWrapperActorIsolation(wrappedVar, initializer);
27102716
TypeChecker::checkInitializerEffects(initContext, initializer);
@@ -2997,7 +3003,7 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
29973003
// FIXME: Record this expression somewhere so that DI can perform the
29983004
// initialization itself.
29993005
Expr *defaultInit = nullptr;
3000-
typeCheckSynthesizedWrapperInitializer(var, defaultInit);
3006+
typeCheckSynthesizedWrapperInitializer(var, defaultInit, dc->isLocalContext());
30013007
pbd->setInit(0, defaultInit);
30023008
pbd->setInitializerChecked(0);
30033009

@@ -3067,7 +3073,7 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
30673073
!var->getName().hasDollarPrefix()) {
30683074
wrappedValueInit = PropertyWrapperValuePlaceholderExpr::create(
30693075
ctx, var->getSourceRange(), var->getType(), /*wrappedValue=*/nullptr);
3070-
typeCheckSynthesizedWrapperInitializer(var, wrappedValueInit);
3076+
typeCheckSynthesizedWrapperInitializer(var, wrappedValueInit, true);
30713077
}
30723078

30733079
return PropertyWrapperInitializerInfo(wrappedValueInit, projectedValueInit);

test/Sema/property_wrappers.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,37 @@ struct TestInitSubscript {
4747
@Wrapper(wrappedValue: Color.allCases[0])
4848
var color: Color
4949
}
50+
51+
@propertyWrapper
52+
public class SR_15940Bar<Value> {
53+
private var _value: Value
54+
55+
public var wrappedValue: Value {
56+
get { _value }
57+
set {
58+
_value = newValue
59+
}
60+
}
61+
62+
public init(wrappedValue value: @autoclosure @escaping () -> Value) {
63+
self._value = value()
64+
}
65+
}
66+
67+
// CHECK-LABEL: struct_decl{{.*}}SR_15940_A
68+
struct SR_15940_A {
69+
// CHECK: argument_list implicit labels=wrappedValue:
70+
// CHECK-NEXT: argument label=wrappedValue
71+
// CHECK-NEXT: autoclosure_expr implicit type='() -> Bool?' discriminator=0 captures=(<opaque_value> ) escaping
72+
// CHECK: autoclosure_expr implicit type='() -> Bool?' discriminator=1 escaping
73+
@SR_15940Bar var a: Bool?
74+
}
75+
76+
// CHECK-LABEL: struct_decl{{.*}}SR_15940_B
77+
struct SR_15940_B {
78+
// CHECK: argument_list implicit labels=wrappedValue:
79+
// CHECK-NEXT: argument label=wrappedValue
80+
// CHECK-NEXT: autoclosure_expr implicit type='() -> Bool' location={{.*}}.swift:[[@LINE+2]]:30 range=[{{.+}}] discriminator=0 captures=(<opaque_value> ) escaping
81+
// CHECK: autoclosure_expr implicit type='() -> Bool' location={{.*}}.swift:[[@LINE+1]]:30 range=[{{.+}}] discriminator=1 escaping
82+
@SR_15940Bar var b: Bool = false
83+
}

0 commit comments

Comments
 (0)