@@ -2800,8 +2800,10 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
2800
2800
llvm::DenseMap<Expr *, Expr *> parentMap;
2801
2801
2802
2802
static bool isEffectAnchor (Expr *e) {
2803
- return isa<AbstractClosureExpr>(e) || isa<DiscardAssignmentExpr>(e) ||
2804
- isa<AssignExpr>(e);
2803
+ return isa<AbstractClosureExpr>(e) ||
2804
+ isa<DiscardAssignmentExpr>(e) ||
2805
+ isa<AssignExpr>(e) ||
2806
+ (isa<DeclRefExpr>(e) && e->isImplicit ());
2805
2807
}
2806
2808
2807
2809
static bool isAnchorTooEarly (Expr *e) {
@@ -3581,27 +3583,43 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
3581
3583
Ctx.Diags .diagnose (E->getAwaitLoc (), diag::no_async_in_await);
3582
3584
}
3583
3585
3584
- void diagnoseUncoveredAsyncSite (const Expr *anchor) const {
3585
- auto asyncPointIter = uncoveredAsync.find (anchor);
3586
- if (asyncPointIter == uncoveredAsync.end ())
3587
- return ;
3588
- const std::vector<DiagnosticInfo> &errors = asyncPointIter->getSecond ();
3586
+ std::pair<SourceLoc, std::string>
3587
+ getFixItForUncoveredAsyncSite (const Expr *anchor) const {
3589
3588
SourceLoc awaitInsertLoc = anchor->getStartLoc ();
3590
- if (const AnyTryExpr *tryExpr = dyn_cast<AnyTryExpr>(anchor))
3589
+ std::string insertion = " await " ;
3590
+ if (auto *tryExpr = dyn_cast<AnyTryExpr>(anchor))
3591
3591
awaitInsertLoc = tryExpr->getSubExpr ()->getStartLoc ();
3592
- else if (const AutoClosureExpr *autoClosure = dyn_cast<AutoClosureExpr>(anchor)) {
3593
- if (const AnyTryExpr *tryExpr = dyn_cast<AnyTryExpr>(autoClosure->getSingleExpressionBody ()))
3592
+ else if (auto *autoClosure = dyn_cast<AutoClosureExpr>(anchor)) {
3593
+ if (auto *tryExpr = dyn_cast<AnyTryExpr>
3594
+ (autoClosure->getSingleExpressionBody ()))
3594
3595
awaitInsertLoc = tryExpr->getSubExpr ()->getStartLoc ();
3596
+ // Supply a tailored fixIt including the identifier if we are
3597
+ // looking at a shorthand optional binding.
3598
+ } else if (anchor->isImplicit ()) {
3599
+ if (auto declRef = dyn_cast<DeclRefExpr>(anchor))
3600
+ if (auto var = dyn_cast_or_null<VarDecl>(declRef->getDecl ())) {
3601
+ insertion = " = await " + var->getNameStr ().str ();
3602
+ awaitInsertLoc = Lexer
3603
+ ::getLocForEndOfToken (Ctx.Diags.SourceMgr, anchor->getStartLoc ());
3604
+ }
3595
3605
}
3606
+ return std::make_pair(awaitInsertLoc, insertion);
3607
+ }
3596
3608
3609
+ void diagnoseUncoveredAsyncSite (const Expr *anchor) const {
3610
+ auto asyncPointIter = uncoveredAsync.find (anchor);
3611
+ if (asyncPointIter == uncoveredAsync.end ())
3612
+ return ;
3613
+ const std::vector<DiagnosticInfo> &errors = asyncPointIter->getSecond ();
3614
+ const auto fixIt = getFixItForUncoveredAsyncSite (anchor);
3597
3615
bool downgradeToWarning = llvm::all_of (errors,
3598
3616
[&](DiagnosticInfo diag) -> bool {
3599
3617
return diag.downgradeToWarning ;
3600
3618
});
3601
3619
3602
3620
Ctx.Diags .diagnose (anchor->getStartLoc (), diag::async_expr_without_await)
3603
3621
.warnUntilSwiftVersionIf (downgradeToWarning, 6 )
3604
- .fixItInsert (awaitInsertLoc, " await " )
3622
+ .fixItInsert (fixIt. first , fixIt. second )
3605
3623
.highlight (anchor->getSourceRange ());
3606
3624
3607
3625
for (const DiagnosticInfo &diag: errors) {
0 commit comments