Skip to content

Commit d70c055

Browse files
committed
[Constraint system] Sink more init logic into SolutionApplicationTarget
More steps toward eliminating ExprTypeCheckListener.
1 parent 614f618 commit d70c055

File tree

3 files changed

+86
-67
lines changed

3 files changed

+86
-67
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3994,9 +3994,62 @@ SolutionApplicationTarget::SolutionApplicationTarget(
39943994
expression.dc = dc;
39953995
expression.contextualPurpose = contextualPurpose;
39963996
expression.convertType = convertType;
3997+
expression.pattern = nullptr;
3998+
expression.wrappedVar = nullptr;
39973999
expression.isDiscarded = isDiscarded;
39984000
}
39994001

4002+
void SolutionApplicationTarget::maybeApplyPropertyWrapper() {
4003+
assert(kind == Kind::expression);
4004+
assert(expression.contextualPurpose == CTP_Initialization);
4005+
auto singleVar = expression.pattern->getSingleVar();
4006+
if (!singleVar)
4007+
return;
4008+
4009+
auto wrapperAttrs = singleVar->getAttachedPropertyWrappers();
4010+
if (wrapperAttrs.empty())
4011+
return;
4012+
4013+
// If the outermost property wrapper is directly initialized, form the
4014+
// call.
4015+
auto &ctx = singleVar->getASTContext();
4016+
auto outermostWrapperAttr = wrapperAttrs.front();
4017+
Expr *backingInitializer;
4018+
if (Expr *initializer = expression.expression) {
4019+
// Form init(wrappedValue:) call(s).
4020+
Expr *wrappedInitializer =
4021+
buildPropertyWrapperInitialValueCall(
4022+
singleVar, Type(), initializer, /*ignoreAttributeArgs=*/false);
4023+
if (!wrappedInitializer)
4024+
return;
4025+
4026+
backingInitializer = wrappedInitializer;
4027+
} else if (auto outermostArg = outermostWrapperAttr->getArg()) {
4028+
Type outermostWrapperType =
4029+
singleVar->getAttachedPropertyWrapperType(0);
4030+
if (!outermostWrapperType)
4031+
return;
4032+
4033+
auto typeExpr = TypeExpr::createImplicitHack(
4034+
outermostWrapperAttr->getTypeLoc().getLoc(),
4035+
outermostWrapperType, ctx);
4036+
backingInitializer = CallExpr::create(
4037+
ctx, typeExpr, outermostArg,
4038+
outermostWrapperAttr->getArgumentLabels(),
4039+
outermostWrapperAttr->getArgumentLabelLocs(),
4040+
/*hasTrailingClosure=*/false,
4041+
/*implicit=*/false);
4042+
} else {
4043+
llvm_unreachable("No initializer anywhere?");
4044+
}
4045+
wrapperAttrs[0]->setSemanticInit(backingInitializer);
4046+
4047+
// Note that we have applied to property wrapper, so we can adjust
4048+
// the initializer type later.
4049+
expression.wrappedVar = singleVar;
4050+
expression.expression = backingInitializer;
4051+
}
4052+
40004053
SolutionApplicationTarget SolutionApplicationTarget::forInitialization(
40014054
Expr *initializer, DeclContext *dc, Type patternType, Pattern *pattern) {
40024055
// Determine the contextual type for the initialization.
@@ -4020,6 +4073,7 @@ SolutionApplicationTarget SolutionApplicationTarget::forInitialization(
40204073
initializer, dc, CTP_Initialization, contextualType,
40214074
/*isDiscarded=*/false);
40224075
target.expression.pattern = pattern;
4076+
target.maybeApplyPropertyWrapper();
40234077
return target;
40244078
}
40254079

lib/Sema/ConstraintSystem.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,10 +1161,14 @@ class SolutionApplicationTarget {
11611161

11621162
/// When initializing a pattern from the expression, this is the
11631163
/// pattern.
1164-
Pattern *pattern = nullptr;
1164+
Pattern *pattern;
1165+
1166+
/// The variable to which property wrappers have been applied, if
1167+
/// this is an initialization involving a property wrapper.
1168+
VarDecl *wrappedVar;
11651169

11661170
/// Whether the expression result will be discarded at the end.
1167-
bool isDiscarded = false;
1171+
bool isDiscarded;
11681172
} expression;
11691173

11701174
struct {
@@ -1173,6 +1177,11 @@ class SolutionApplicationTarget {
11731177
} function;
11741178
};
11751179

1180+
// If the pattern contains a single variable that has an attached
1181+
// property wrapper, set up the initializer expression to initialize
1182+
// the backing storage.
1183+
void maybeApplyPropertyWrapper();
1184+
11761185
public:
11771186
SolutionApplicationTarget(Expr *expr, DeclContext *dc,
11781187
ContextualTypePurpose contextualPurpose,
@@ -1281,6 +1290,14 @@ class SolutionApplicationTarget {
12811290
isa<OptionalSomePattern>(expression.pattern);
12821291
}
12831292

1293+
/// Retrieve the wrapped variable when initializing a pattern with a
1294+
/// property wrapper.
1295+
VarDecl *getInitializationWrappedVar() const {
1296+
assert(kind == Kind::expression);
1297+
assert(expression.contextualPurpose == CTP_Initialization);
1298+
return expression.wrappedVar;
1299+
}
1300+
12841301
/// Whether this context infers an opaque return type.
12851302
bool infersOpaqueReturnType() const;
12861303

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 13 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2474,8 +2474,8 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
24742474
/// Type checking listener for pattern binding initializers.
24752475
class BindingListener : public ExprTypeCheckListener {
24762476
ASTContext &context;
2477-
Pattern *&pattern;
2478-
Expr *&initializer;
2477+
2478+
SolutionApplicationTarget target;
24792479

24802480
/// The locator we're using.
24812481
ConstraintLocator *Locator;
@@ -2487,11 +2487,9 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
24872487
VarDecl *wrappedVar = nullptr;
24882488

24892489
public:
2490-
explicit BindingListener(ASTContext &ctx, Pattern *&pattern,
2491-
Expr *&initializer)
2492-
: context(ctx), pattern(pattern), initializer(initializer),
2493-
Locator(nullptr) {
2494-
maybeApplyPropertyWrapper();
2490+
explicit BindingListener(ASTContext &ctx, SolutionApplicationTarget target)
2491+
: context(ctx), target(target), Locator(nullptr) {
2492+
wrappedVar = target.getInitializationWrappedVar();
24952493
}
24962494

24972495
/// Retrieve the type to which the pattern should be coerced.
@@ -2505,7 +2503,7 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
25052503
if (cs) {
25062504
Type valueType = LValueType::get(initType);
25072505
auto dc = wrappedVar->getInnermostDeclContext();
2508-
auto *loc = cs->getConstraintLocator(initializer);
2506+
auto *loc = cs->getConstraintLocator(target.getAsExpr());
25092507

25102508
for (unsigned i : indices(wrappedVar->getAttachedPropertyWrappers())) {
25112509
auto wrapperInfo = wrappedVar->getAttachedPropertyWrapperTypeInfo(i);
@@ -2538,7 +2536,8 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
25382536
Locator = cs.getConstraintLocator(expr, LocatorPathElt::ContextualType());
25392537

25402538
// Collect constraints from the pattern.
2541-
Type patternType = cs.generateConstraints(pattern, Locator);
2539+
Type patternType =
2540+
cs.generateConstraints(target.getInitializationPattern(), Locator);
25422541
if (!patternType)
25432542
return true;
25442543

@@ -2563,7 +2562,6 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
25632562
}
25642563

25652564
// The expression has been pre-checked; save it in case we fail later.
2566-
initializer = expr;
25672565
return false;
25682566
}
25692567

@@ -2593,70 +2591,20 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
25932591
->setSemanticInit(expr);
25942592
}
25952593

2596-
initializer = expr;
25972594
return expr;
25982595
}
2599-
2600-
private:
2601-
// If the pattern contains a single variable that has an attached
2602-
// property wrapper, set up the initializer expression to initialize
2603-
// the backing storage.
2604-
void maybeApplyPropertyWrapper() {
2605-
auto singleVar = pattern->getSingleVar();
2606-
if (!singleVar)
2607-
return;
2608-
2609-
auto wrapperAttrs = singleVar->getAttachedPropertyWrappers();
2610-
if (wrapperAttrs.empty())
2611-
return;
2612-
2613-
// If the outermost property wrapper is directly initialized, form the
2614-
// call.
2615-
auto &ctx = singleVar->getASTContext();
2616-
auto outermostWrapperAttr = wrapperAttrs.front();
2617-
if (initializer) {
2618-
// Form init(wrappedValue:) call(s).
2619-
Expr *wrappedInitializer =
2620-
buildPropertyWrapperInitialValueCall(
2621-
singleVar, Type(), initializer, /*ignoreAttributeArgs=*/false);
2622-
if (!wrappedInitializer)
2623-
return;
2624-
2625-
initializer = wrappedInitializer;
2626-
} else if (auto outermostArg = outermostWrapperAttr->getArg()) {
2627-
Type outermostWrapperType =
2628-
singleVar->getAttachedPropertyWrapperType(0);
2629-
if (!outermostWrapperType)
2630-
return;
2631-
2632-
auto typeExpr = TypeExpr::createImplicitHack(
2633-
outermostWrapperAttr->getTypeLoc().getLoc(),
2634-
outermostWrapperType, ctx);
2635-
initializer = CallExpr::create(
2636-
ctx, typeExpr, outermostArg,
2637-
outermostWrapperAttr->getArgumentLabels(),
2638-
outermostWrapperAttr->getArgumentLabelLocs(),
2639-
/*hasTrailingClosure=*/false,
2640-
/*implicit=*/false);
2641-
} else {
2642-
llvm_unreachable("No initializer anywhere?");
2643-
}
2644-
wrapperAttrs[0]->setSemanticInit(initializer);
2645-
2646-
// Note that we have applied to property wrapper, so we can adjust
2647-
// the initializer type later.
2648-
wrappedVar = singleVar;
2649-
}
26502596
};
26512597

26522598
auto &Context = DC->getASTContext();
2653-
BindingListener listener(Context, pattern, initializer);
2599+
auto target = SolutionApplicationTarget::forInitialization(
2600+
initializer, DC, patternType, pattern);
2601+
initializer = target.getAsExpr();
2602+
2603+
BindingListener listener(Context, target);
26542604
if (!initializer)
26552605
return true;
26562606

26572607
// Type-check the initializer.
2658-
auto target = SolutionApplicationTarget::forInitialization(
2659-
initializer, DC, patternType, pattern);
26602608
bool unresolvedTypeExprs = false;
26612609
auto resultTarget = typeCheckExpression(target, unresolvedTypeExprs,
26622610
None, &listener);

0 commit comments

Comments
 (0)