@@ -1461,14 +1461,31 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
1461
1461
Closures.push_back (ACE);
1462
1462
}
1463
1463
1464
+ static bool isEnclosingSelfReference (VarDecl *var,
1465
+ const AbstractClosureExpr *inClosure) {
1466
+ if (var->isSelfParameter ())
1467
+ return true ;
1468
+
1469
+ // Capture variables have a DC of the parent function.
1470
+ if (inClosure && var->isSelfParamCapture () &&
1471
+ var->getDeclContext () != inClosure->getParent ())
1472
+ return true ;
1473
+
1474
+ return false ;
1475
+ }
1476
+
1464
1477
// / Return true if this is an implicit reference to self which is required
1465
1478
// / to be explicit in an escaping closure. Metatype references and value
1466
1479
// / type references are excluded.
1467
- static bool isImplicitSelfParamUseLikelyToCauseCycle (Expr *E) {
1480
+ static bool isImplicitSelfParamUseLikelyToCauseCycle (Expr *E,
1481
+ const AbstractClosureExpr *inClosure) {
1468
1482
auto *DRE = dyn_cast<DeclRefExpr>(E);
1469
1483
1470
- if (!DRE || !DRE->isImplicit () || !isa<VarDecl>(DRE->getDecl ()) ||
1471
- !cast<VarDecl>(DRE->getDecl ())->isSelfParameter ())
1484
+ if (!DRE || !DRE->isImplicit ())
1485
+ return false ;
1486
+
1487
+ auto var = dyn_cast<VarDecl>(DRE->getDecl ());
1488
+ if (!var || !isEnclosingSelfReference (var, inClosure))
1472
1489
return false ;
1473
1490
1474
1491
// Defensive check for type. If the expression doesn't have type here, it
@@ -1544,7 +1561,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
1544
1561
1545
1562
SourceLoc memberLoc = SourceLoc ();
1546
1563
if (auto *MRE = dyn_cast<MemberRefExpr>(E))
1547
- if (isImplicitSelfParamUseLikelyToCauseCycle (MRE->getBase ())) {
1564
+ if (isImplicitSelfParamUseLikelyToCauseCycle (MRE->getBase (), ACE )) {
1548
1565
auto baseName = MRE->getMember ().getDecl ()->getBaseName ();
1549
1566
memberLoc = MRE->getLoc ();
1550
1567
Diags.diagnose (memberLoc,
@@ -1554,7 +1571,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
1554
1571
1555
1572
// Handle method calls with a specific diagnostic + fixit.
1556
1573
if (auto *DSCE = dyn_cast<DotSyntaxCallExpr>(E))
1557
- if (isImplicitSelfParamUseLikelyToCauseCycle (DSCE->getBase ()) &&
1574
+ if (isImplicitSelfParamUseLikelyToCauseCycle (DSCE->getBase (), ACE ) &&
1558
1575
isa<DeclRefExpr>(DSCE->getFn ())) {
1559
1576
auto MethodExpr = cast<DeclRefExpr>(DSCE->getFn ());
1560
1577
memberLoc = DSCE->getLoc ();
@@ -1569,7 +1586,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
1569
1586
}
1570
1587
1571
1588
// Catch any other implicit uses of self with a generic diagnostic.
1572
- if (isImplicitSelfParamUseLikelyToCauseCycle (E))
1589
+ if (isImplicitSelfParamUseLikelyToCauseCycle (E, ACE ))
1573
1590
Diags.diagnose (E->getLoc (), diag::implicit_use_of_self_in_closure);
1574
1591
1575
1592
return { true , E };
0 commit comments