@@ -8705,6 +8705,9 @@ namespace {
8705
8705
return Action::SkipChildren ();
8706
8706
}
8707
8707
8708
+ NullablePtr<Pattern>
8709
+ rewritePattern (Pattern *pattern, DeclContext *DC);
8710
+
8708
8711
// / Rewrite the target, producing a new target.
8709
8712
Optional<SyntacticElementTarget>
8710
8713
rewriteTarget (SyntacticElementTarget target);
@@ -8951,12 +8954,68 @@ static Expr *wrapAsyncLetInitializer(
8951
8954
return resultInit;
8952
8955
}
8953
8956
8957
+ static Pattern *rewriteExprPattern (const SyntacticElementTarget &matchTarget,
8958
+ Type patternTy,
8959
+ RewriteTargetFn rewriteTarget) {
8960
+ auto *EP = matchTarget.getExprPattern ();
8961
+
8962
+ // See if we can simplify to another kind of pattern.
8963
+ if (auto simplified = TypeChecker::trySimplifyExprPattern (EP, patternTy))
8964
+ return simplified.get ();
8965
+
8966
+ auto resultTarget = rewriteTarget (matchTarget);
8967
+ if (!resultTarget)
8968
+ return nullptr ;
8969
+
8970
+ EP->setMatchExpr (resultTarget->getAsExpr ());
8971
+ EP->getMatchVar ()->setInterfaceType (patternTy->mapTypeOutOfContext ());
8972
+ EP->setType (patternTy);
8973
+ return EP;
8974
+ }
8975
+
8976
+ // / Attempt to rewrite either an ExprPattern, or a pattern that was solved as
8977
+ // / an ExprPattern, e.g an EnumElementPattern that could not refer to an enum
8978
+ // / case.
8979
+ static Optional<Pattern *>
8980
+ tryRewriteExprPattern (Pattern *P, Solution &solution, Type patternTy,
8981
+ RewriteTargetFn rewriteTarget) {
8982
+ // See if we have a match expression target.
8983
+ auto matchTarget = solution.getTargetFor (P);
8984
+ if (!matchTarget)
8985
+ return None;
8986
+
8987
+ return rewriteExprPattern (*matchTarget, patternTy, rewriteTarget);
8988
+ }
8989
+
8990
+ NullablePtr<Pattern> ExprWalker::rewritePattern (Pattern *pattern,
8991
+ DeclContext *DC) {
8992
+ auto &solution = Rewriter.solution ;
8993
+
8994
+ // Figure out the pattern type.
8995
+ auto patternTy = solution.getResolvedType (pattern);
8996
+ patternTy = patternTy->reconstituteSugar (/* recursive=*/ false );
8997
+
8998
+ // Coerce the pattern to its appropriate type.
8999
+ TypeResolutionOptions patternOptions (TypeResolverContext::InExpression);
9000
+ patternOptions |= TypeResolutionFlags::OverrideType;
9001
+
9002
+ auto tryRewritePattern = [&](Pattern *EP, Type ty) {
9003
+ return ::tryRewriteExprPattern (
9004
+ EP, solution, ty, [&](auto target) { return rewriteTarget (target); });
9005
+ };
9006
+
9007
+ auto contextualPattern = ContextualPattern::forRawPattern (pattern, DC);
9008
+ return TypeChecker::coercePatternToType (contextualPattern, patternTy,
9009
+ patternOptions, tryRewritePattern);
9010
+ }
9011
+
8954
9012
// / Apply the given solution to the initialization target.
8955
9013
// /
8956
9014
// / \returns the resulting initialization expression.
8957
9015
static Optional<SyntacticElementTarget>
8958
9016
applySolutionToInitialization (Solution &solution, SyntacticElementTarget target,
8959
- Expr *initializer) {
9017
+ Expr *initializer,
9018
+ RewriteTargetFn rewriteTarget) {
8960
9019
auto wrappedVar = target.getInitializationWrappedVar ();
8961
9020
Type initType;
8962
9021
if (wrappedVar) {
@@ -9021,10 +9080,14 @@ applySolutionToInitialization(Solution &solution, SyntacticElementTarget target,
9021
9080
9022
9081
finalPatternType = finalPatternType->reconstituteSugar (/* recursive =*/ false );
9023
9082
9083
+ auto tryRewritePattern = [&](Pattern *EP, Type ty) {
9084
+ return ::tryRewriteExprPattern (EP, solution, ty, rewriteTarget);
9085
+ };
9086
+
9024
9087
// Apply the solution to the pattern as well.
9025
9088
auto contextualPattern = target.getContextualPattern ();
9026
9089
if (auto coercedPattern = TypeChecker::coercePatternToType (
9027
- contextualPattern, finalPatternType, options)) {
9090
+ contextualPattern, finalPatternType, options, tryRewritePattern )) {
9028
9091
resultTarget.setPattern (coercedPattern);
9029
9092
} else {
9030
9093
return None;
@@ -9171,10 +9234,15 @@ static Optional<SyntacticElementTarget> applySolutionToForEachStmt(
9171
9234
TypeResolutionOptions options (TypeResolverContext::ForEachStmt);
9172
9235
options |= TypeResolutionFlags::OverrideType;
9173
9236
9237
+ auto tryRewritePattern = [&](Pattern *EP, Type ty) {
9238
+ return ::tryRewriteExprPattern (EP, solution, ty, rewriteTarget);
9239
+ };
9240
+
9174
9241
// Apply the solution to the pattern as well.
9175
9242
auto contextualPattern = target.getContextualPattern ();
9176
9243
auto coercedPattern = TypeChecker::coercePatternToType (
9177
- contextualPattern, forEachStmtInfo.initType , options);
9244
+ contextualPattern, forEachStmtInfo.initType , options,
9245
+ tryRewritePattern);
9178
9246
if (!coercedPattern)
9179
9247
return None;
9180
9248
@@ -9262,7 +9330,8 @@ ExprWalker::rewriteTarget(SyntacticElementTarget target) {
9262
9330
switch (target.getExprContextualTypePurpose ()) {
9263
9331
case CTP_Initialization: {
9264
9332
auto initResultTarget = applySolutionToInitialization (
9265
- solution, target, rewrittenExpr);
9333
+ solution, target, rewrittenExpr,
9334
+ [&](auto target) { return rewriteTarget (target); });
9266
9335
if (!initResultTarget)
9267
9336
return None;
9268
9337
@@ -9353,47 +9422,11 @@ ExprWalker::rewriteTarget(SyntacticElementTarget target) {
9353
9422
ConstraintSystem &cs = solution.getConstraintSystem ();
9354
9423
auto info = *cs.getCaseLabelItemInfo (*caseLabelItem);
9355
9424
9356
- // Figure out the pattern type.
9357
- Type patternType = solution.simplifyType (solution.getType (info.pattern ));
9358
- patternType = patternType->reconstituteSugar (/* recursive=*/ false );
9359
-
9360
- // Check whether this enum element is resolved via ~= application.
9361
- if (auto *enumElement = dyn_cast<EnumElementPattern>(info.pattern )) {
9362
- if (auto target = cs.getTargetFor (enumElement)) {
9363
- auto *EP = target->getExprPattern ();
9364
- auto enumType = solution.getResolvedType (EP);
9365
-
9366
- auto *matchCall = target->getAsExpr ();
9367
-
9368
- auto *result = matchCall->walk (*this );
9369
- if (!result)
9370
- return None;
9371
-
9372
- {
9373
- auto *matchVar = EP->getMatchVar ();
9374
- matchVar->setInterfaceType (enumType->mapTypeOutOfContext ());
9375
- }
9376
-
9377
- EP->setMatchExpr (result);
9378
- EP->setType (enumType);
9379
-
9380
- (*caseLabelItem)->setPattern (EP, /* resolved=*/ true );
9381
- return target;
9382
- }
9383
- }
9384
-
9385
- // Coerce the pattern to its appropriate type.
9386
- TypeResolutionOptions patternOptions (TypeResolverContext::InExpression);
9387
- patternOptions |= TypeResolutionFlags::OverrideType;
9388
- auto contextualPattern =
9389
- ContextualPattern::forRawPattern (info.pattern ,
9390
- target.getDeclContext ());
9391
- if (auto coercedPattern = TypeChecker::coercePatternToType (
9392
- contextualPattern, patternType, patternOptions)) {
9393
- (*caseLabelItem)->setPattern (coercedPattern, /* resolved=*/ true );
9394
- } else {
9425
+ auto pattern = rewritePattern (info.pattern , target.getDeclContext ());
9426
+ if (!pattern)
9395
9427
return None;
9396
- }
9428
+
9429
+ (*caseLabelItem)->setPattern (pattern.get (), /* resolved=*/ true );
9397
9430
9398
9431
// If there is a guard expression, coerce that.
9399
9432
if (auto *guardExpr = info.guardExpr ) {
@@ -9461,8 +9494,13 @@ ExprWalker::rewriteTarget(SyntacticElementTarget target) {
9461
9494
options |= TypeResolutionFlags::OverrideType;
9462
9495
}
9463
9496
9497
+ auto tryRewritePattern = [&](Pattern *EP, Type ty) {
9498
+ return ::tryRewriteExprPattern (
9499
+ EP, solution, ty, [&](auto target) { return rewriteTarget (target); });
9500
+ };
9501
+
9464
9502
if (auto coercedPattern = TypeChecker::coercePatternToType (
9465
- contextualPattern, patternType, options)) {
9503
+ contextualPattern, patternType, options, tryRewritePattern )) {
9466
9504
auto resultTarget = target;
9467
9505
resultTarget.setPattern (coercedPattern);
9468
9506
return resultTarget;
0 commit comments