@@ -3530,9 +3530,12 @@ namespace {
3530
3530
// Convert the subexpression.
3531
3531
Expr *sub = expr->getSubExpr ();
3532
3532
3533
- sub = solution.coerceToType (sub, toType, cs.getConstraintLocator (sub));
3534
- if (!sub)
3533
+ solution.setExprTypes (sub);
3534
+
3535
+ if (TypeChecker::convertToType (sub, toType, cs.DC ))
3535
3536
return nullptr ;
3537
+
3538
+ cs.cacheExprTypes (sub);
3536
3539
3537
3540
expr->setSubExpr (sub);
3538
3541
cs.setType (expr, toType);
@@ -3583,6 +3586,9 @@ namespace {
3583
3586
return nullptr ;
3584
3587
case CheckedCastKind::Coercion:
3585
3588
case CheckedCastKind::BridgingCoercion: {
3589
+ if (SuppressDiagnostics)
3590
+ return nullptr ;
3591
+
3586
3592
if (cs.getType (sub)->isEqual (toType)) {
3587
3593
ctx.Diags .diagnose (expr->getLoc (), diag::forced_downcast_noop, toType)
3588
3594
.fixItRemove (SourceRange (
@@ -3596,9 +3602,14 @@ namespace {
3596
3602
" as" );
3597
3603
}
3598
3604
3599
- expr->setCastKind (castKind);
3600
- cs.setType (expr, toType);
3601
- return expr;
3605
+ // Transmute the checked cast into a coercion expression.
3606
+ auto *result =
3607
+ new (ctx) CoerceExpr (sub, expr->getLoc (), expr->getCastTypeLoc ());
3608
+ cs.setType (result, toType);
3609
+ cs.setType (result->getCastTypeLoc (), toType);
3610
+ unsigned disjunctionChoice =
3611
+ (castKind == CheckedCastKind::Coercion ? 0 : 1 );
3612
+ return visitCoerceExpr (result, disjunctionChoice);
3602
3613
}
3603
3614
3604
3615
// Valid casts.
@@ -3651,18 +3662,37 @@ namespace {
3651
3662
fromType, toType, castContextKind, cs.DC , expr->getLoc (), sub,
3652
3663
expr->getCastTypeLoc ().getSourceRange ());
3653
3664
switch (castKind) {
3654
- // Invalid cast.
3665
+ / / / Invalid cast.
3655
3666
case CheckedCastKind::Unresolved:
3656
3667
expr->setCastKind (CheckedCastKind::ValueCast);
3657
3668
break ;
3658
3669
3659
3670
case CheckedCastKind::Coercion:
3660
3671
case CheckedCastKind::BridgingCoercion: {
3672
+ if (SuppressDiagnostics)
3673
+ return nullptr ;
3674
+
3661
3675
ctx.Diags .diagnose (expr->getLoc (), diag::conditional_downcast_coercion,
3662
3676
cs.getType (sub), toType);
3663
- expr->setCastKind (castKind);
3664
- cs.setType (expr, OptionalType::get (toType));
3665
- return expr;
3677
+
3678
+ // Transmute the checked cast into a coercion expression.
3679
+ auto *coerce =
3680
+ new (ctx) CoerceExpr (sub, expr->getLoc (), expr->getCastTypeLoc ());
3681
+ cs.setType (coerce, toType);
3682
+ cs.setType (coerce->getCastTypeLoc (), toType);
3683
+ unsigned disjunctionChoice =
3684
+ (castKind == CheckedCastKind::Coercion ? 0 : 1 );
3685
+ Expr *result = visitCoerceExpr (coerce, disjunctionChoice);
3686
+ if (!result)
3687
+ return nullptr ;
3688
+
3689
+ // Wrap the result in an optional. Mark the optional injection as
3690
+ // explicit, because the user did in fact write the '?' as part of
3691
+ // 'as?', even though it wasn't necessary.
3692
+ result =
3693
+ new (ctx) InjectIntoOptionalExpr (result, OptionalType::get (toType));
3694
+ result->setImplicit (false );
3695
+ return cs.cacheType (result);
3666
3696
}
3667
3697
3668
3698
// Valid casts.
0 commit comments