@@ -8688,6 +8688,9 @@ namespace {
8688
8688
return Action::SkipChildren ();
8689
8689
}
8690
8690
8691
+ NullablePtr<Pattern>
8692
+ rewritePattern (Pattern *pattern, DeclContext *DC);
8693
+
8691
8694
// / Rewrite the target, producing a new target.
8692
8695
Optional<SyntacticElementTarget>
8693
8696
rewriteTarget (SyntacticElementTarget target);
@@ -8934,12 +8937,68 @@ static Expr *wrapAsyncLetInitializer(
8934
8937
return resultInit;
8935
8938
}
8936
8939
8940
+ static Pattern *rewriteExprPattern (const SyntacticElementTarget &matchTarget,
8941
+ Type patternTy,
8942
+ RewriteTargetFn rewriteTarget) {
8943
+ auto *EP = matchTarget.getExprPattern ();
8944
+
8945
+ // See if we can simplify to another kind of pattern.
8946
+ if (auto simplified = TypeChecker::trySimplifyExprPattern (EP, patternTy))
8947
+ return simplified.get ();
8948
+
8949
+ auto resultTarget = rewriteTarget (matchTarget);
8950
+ if (!resultTarget)
8951
+ return nullptr ;
8952
+
8953
+ EP->setMatchExpr (resultTarget->getAsExpr ());
8954
+ EP->getMatchVar ()->setInterfaceType (patternTy->mapTypeOutOfContext ());
8955
+ EP->setType (patternTy);
8956
+ return EP;
8957
+ }
8958
+
8959
+ // / Attempt to rewrite either an ExprPattern, or a pattern that was solved as
8960
+ // / an ExprPattern, e.g an EnumElementPattern that could not refer to an enum
8961
+ // / case.
8962
+ static Optional<Pattern *>
8963
+ tryRewriteExprPattern (Pattern *P, Solution &solution, Type patternTy,
8964
+ RewriteTargetFn rewriteTarget) {
8965
+ // See if we have a match expression target.
8966
+ auto matchTarget = solution.getTargetFor (P);
8967
+ if (!matchTarget)
8968
+ return None;
8969
+
8970
+ return rewriteExprPattern (*matchTarget, patternTy, rewriteTarget);
8971
+ }
8972
+
8973
+ NullablePtr<Pattern> ExprWalker::rewritePattern (Pattern *pattern,
8974
+ DeclContext *DC) {
8975
+ auto &solution = Rewriter.solution ;
8976
+
8977
+ // Figure out the pattern type.
8978
+ auto patternTy = solution.getResolvedType (pattern);
8979
+ patternTy = patternTy->reconstituteSugar (/* recursive=*/ false );
8980
+
8981
+ // Coerce the pattern to its appropriate type.
8982
+ TypeResolutionOptions patternOptions (TypeResolverContext::InExpression);
8983
+ patternOptions |= TypeResolutionFlags::OverrideType;
8984
+
8985
+ auto tryRewritePattern = [&](Pattern *EP, Type ty) {
8986
+ return ::tryRewriteExprPattern (
8987
+ EP, solution, ty, [&](auto target) { return rewriteTarget (target); });
8988
+ };
8989
+
8990
+ auto contextualPattern = ContextualPattern::forRawPattern (pattern, DC);
8991
+ return TypeChecker::coercePatternToType (contextualPattern, patternTy,
8992
+ patternOptions, tryRewritePattern);
8993
+ }
8994
+
8937
8995
// / Apply the given solution to the initialization target.
8938
8996
// /
8939
8997
// / \returns the resulting initialization expression.
8940
8998
static Optional<SyntacticElementTarget>
8941
8999
applySolutionToInitialization (Solution &solution, SyntacticElementTarget target,
8942
- Expr *initializer) {
9000
+ Expr *initializer,
9001
+ RewriteTargetFn rewriteTarget) {
8943
9002
auto wrappedVar = target.getInitializationWrappedVar ();
8944
9003
Type initType;
8945
9004
if (wrappedVar) {
@@ -9004,10 +9063,14 @@ applySolutionToInitialization(Solution &solution, SyntacticElementTarget target,
9004
9063
9005
9064
finalPatternType = finalPatternType->reconstituteSugar (/* recursive =*/ false );
9006
9065
9066
+ auto tryRewritePattern = [&](Pattern *EP, Type ty) {
9067
+ return ::tryRewriteExprPattern (EP, solution, ty, rewriteTarget);
9068
+ };
9069
+
9007
9070
// Apply the solution to the pattern as well.
9008
9071
auto contextualPattern = target.getContextualPattern ();
9009
9072
if (auto coercedPattern = TypeChecker::coercePatternToType (
9010
- contextualPattern, finalPatternType, options)) {
9073
+ contextualPattern, finalPatternType, options, tryRewritePattern )) {
9011
9074
resultTarget.setPattern (coercedPattern);
9012
9075
} else {
9013
9076
return None;
@@ -9154,10 +9217,15 @@ static Optional<SyntacticElementTarget> applySolutionToForEachStmt(
9154
9217
TypeResolutionOptions options (TypeResolverContext::ForEachStmt);
9155
9218
options |= TypeResolutionFlags::OverrideType;
9156
9219
9220
+ auto tryRewritePattern = [&](Pattern *EP, Type ty) {
9221
+ return ::tryRewriteExprPattern (EP, solution, ty, rewriteTarget);
9222
+ };
9223
+
9157
9224
// Apply the solution to the pattern as well.
9158
9225
auto contextualPattern = target.getContextualPattern ();
9159
9226
auto coercedPattern = TypeChecker::coercePatternToType (
9160
- contextualPattern, forEachStmtInfo.initType , options);
9227
+ contextualPattern, forEachStmtInfo.initType , options,
9228
+ tryRewritePattern);
9161
9229
if (!coercedPattern)
9162
9230
return None;
9163
9231
@@ -9245,7 +9313,8 @@ ExprWalker::rewriteTarget(SyntacticElementTarget target) {
9245
9313
switch (target.getExprContextualTypePurpose ()) {
9246
9314
case CTP_Initialization: {
9247
9315
auto initResultTarget = applySolutionToInitialization (
9248
- solution, target, rewrittenExpr);
9316
+ solution, target, rewrittenExpr,
9317
+ [&](auto target) { return rewriteTarget (target); });
9249
9318
if (!initResultTarget)
9250
9319
return None;
9251
9320
@@ -9336,47 +9405,11 @@ ExprWalker::rewriteTarget(SyntacticElementTarget target) {
9336
9405
ConstraintSystem &cs = solution.getConstraintSystem ();
9337
9406
auto info = *cs.getCaseLabelItemInfo (*caseLabelItem);
9338
9407
9339
- // Figure out the pattern type.
9340
- Type patternType = solution.simplifyType (solution.getType (info.pattern ));
9341
- patternType = patternType->reconstituteSugar (/* recursive=*/ false );
9342
-
9343
- // Check whether this enum element is resolved via ~= application.
9344
- if (auto *enumElement = dyn_cast<EnumElementPattern>(info.pattern )) {
9345
- if (auto target = cs.getTargetFor (enumElement)) {
9346
- auto *EP = target->getExprPattern ();
9347
- auto enumType = solution.getResolvedType (EP);
9348
-
9349
- auto *matchCall = target->getAsExpr ();
9350
-
9351
- auto *result = matchCall->walk (*this );
9352
- if (!result)
9353
- return None;
9354
-
9355
- {
9356
- auto *matchVar = EP->getMatchVar ();
9357
- matchVar->setInterfaceType (enumType->mapTypeOutOfContext ());
9358
- }
9359
-
9360
- EP->setMatchExpr (result);
9361
- EP->setType (enumType);
9362
-
9363
- (*caseLabelItem)->setPattern (EP, /* resolved=*/ true );
9364
- return target;
9365
- }
9366
- }
9367
-
9368
- // Coerce the pattern to its appropriate type.
9369
- TypeResolutionOptions patternOptions (TypeResolverContext::InExpression);
9370
- patternOptions |= TypeResolutionFlags::OverrideType;
9371
- auto contextualPattern =
9372
- ContextualPattern::forRawPattern (info.pattern ,
9373
- target.getDeclContext ());
9374
- if (auto coercedPattern = TypeChecker::coercePatternToType (
9375
- contextualPattern, patternType, patternOptions)) {
9376
- (*caseLabelItem)->setPattern (coercedPattern, /* resolved=*/ true );
9377
- } else {
9408
+ auto pattern = rewritePattern (info.pattern , target.getDeclContext ());
9409
+ if (!pattern)
9378
9410
return None;
9379
- }
9411
+
9412
+ (*caseLabelItem)->setPattern (pattern.get (), /* resolved=*/ true );
9380
9413
9381
9414
// If there is a guard expression, coerce that.
9382
9415
if (auto *guardExpr = info.guardExpr ) {
@@ -9444,8 +9477,13 @@ ExprWalker::rewriteTarget(SyntacticElementTarget target) {
9444
9477
options |= TypeResolutionFlags::OverrideType;
9445
9478
}
9446
9479
9480
+ auto tryRewritePattern = [&](Pattern *EP, Type ty) {
9481
+ return ::tryRewriteExprPattern (
9482
+ EP, solution, ty, [&](auto target) { return rewriteTarget (target); });
9483
+ };
9484
+
9447
9485
if (auto coercedPattern = TypeChecker::coercePatternToType (
9448
- contextualPattern, patternType, options)) {
9486
+ contextualPattern, patternType, options, tryRewritePattern )) {
9449
9487
auto resultTarget = target;
9450
9488
resultTarget.setPattern (coercedPattern);
9451
9489
return resultTarget;
0 commit comments