@@ -347,11 +347,9 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
347
347
return e ? CS.getType (e) : Type ();
348
348
}
349
349
350
- // / This is the same as typeCheckChildIndependently, but works on an arbitrary
351
- // / subexpression of the current node because it handles ClosureExpr parents
352
- // / of the specified node.
353
- Expr *typeCheckArbitrarySubExprIndependently (Expr *subExpr,
354
- TCCOptions options = TCCOptions());
350
+ // / Find a nearest declaration context which could be used
351
+ // / to type-check this sub-expression.
352
+ DeclContext *findDeclContext (Expr *subExpr) const ;
355
353
356
354
// / Special magic to handle inout exprs and tuples in argument lists.
357
355
Expr *typeCheckArgumentChildIndependently (Expr *argExpr, Type argType,
@@ -1085,8 +1083,8 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){
1085
1083
// constraint.
1086
1084
if (CS.getContextualTypePurpose () != CTP_Unused)
1087
1085
options |= TCC_ForceRecheck;
1088
-
1089
- auto sub = typeCheckArbitrarySubExprIndependently (anchor, options);
1086
+
1087
+ auto sub = typeCheckChildIndependently (anchor, options);
1090
1088
if (!sub) return true ;
1091
1089
fromType = CS.getType (sub);
1092
1090
}
@@ -1542,10 +1540,14 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
1542
1540
if ((!convertType || options.contains (TCC_AllowUnresolvedTypeVariables)) &&
1543
1541
allowFreeTypeVariables)
1544
1542
TCEOptions |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
1545
-
1546
- auto resultTy = CS.TC .typeCheckExpression (
1547
- subExpr, CS.DC , TypeLoc::withoutLoc (convertType), convertTypePurpose,
1548
- TCEOptions, listener, &CS);
1543
+
1544
+ // When we're type checking a single-expression closure, we need to reset the
1545
+ // DeclContext to this closure for the recursive type checking. Otherwise,
1546
+ // if there is a closure in the subexpression, we can violate invariants.
1547
+ auto *DC = findDeclContext (subExpr);
1548
+ auto resultTy =
1549
+ CS.TC .typeCheckExpression (subExpr, DC, TypeLoc::withoutLoc (convertType),
1550
+ convertTypePurpose, TCEOptions, listener, &CS);
1549
1551
1550
1552
CS.cacheExprTypes (subExpr);
1551
1553
@@ -1581,49 +1583,53 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
1581
1583
return subExpr;
1582
1584
}
1583
1585
1584
- // / This is the same as typeCheckChildIndependently, but works on an arbitrary
1585
- // / subexpression of the current node because it handles ClosureExpr parents
1586
- // / of the specified node.
1587
- Expr *FailureDiagnosis::
1588
- typeCheckArbitrarySubExprIndependently (Expr *subExpr, TCCOptions options) {
1589
- if (subExpr == expr)
1590
- return typeCheckChildIndependently (subExpr, options);
1591
-
1592
- // Construct a parent map for the expr tree we're investigating.
1593
- auto parentMap = expr->getParentMap ();
1594
-
1595
- ClosureExpr *NearestClosure = nullptr ;
1596
-
1597
- // Walk the parents of the specified expression, handling any ClosureExprs.
1598
- for (Expr *node = parentMap[subExpr]; node; node = parentMap[node]) {
1599
- auto *CE = dyn_cast<ClosureExpr>(node);
1600
- if (!CE) continue ;
1601
-
1602
- // Keep track of the innermost closure we see that we're jumping into.
1603
- if (!NearestClosure)
1604
- NearestClosure = CE;
1605
-
1606
- // If we have a ClosureExpr parent of the specified node, check to make sure
1607
- // none of its arguments are type variables. If so, these type variables
1608
- // would be accessible to name lookup of the subexpression and may thus leak
1609
- // in. Reset them to UnresolvedTypes for safe measures.
1610
- for (auto *param : *CE->getParameters ()) {
1611
- if (param->hasValidSignature ()) {
1612
- auto type = param->getType ();
1613
- assert (!type->hasTypeVariable () && !type->hasError ());
1614
- (void )type;
1586
+ DeclContext *FailureDiagnosis::findDeclContext (Expr *subExpr) const {
1587
+ if (auto *closure =
1588
+ dyn_cast<ClosureExpr>(subExpr->getSemanticsProvidingExpr ()))
1589
+ return closure->getParent ();
1590
+
1591
+ struct DCFinder : public ASTWalker {
1592
+ DeclContext *DC, *CurrDC;
1593
+ Expr *SubExpr;
1594
+
1595
+ DCFinder (DeclContext *DC, Expr *expr) : DC(DC), CurrDC(DC), SubExpr(expr) {}
1596
+
1597
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
1598
+ if (E == SubExpr) {
1599
+ DC = CurrDC;
1600
+ return {false , nullptr };
1601
+ }
1602
+
1603
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
1604
+ CurrDC = closure;
1605
+ // If we have a ClosureExpr parent of the specified node, check to make
1606
+ // sure none of its arguments are type variables. If so, these type
1607
+ // variables would be accessible to name lookup of the subexpression and
1608
+ // may thus leak in. Reset them to UnresolvedTypes for safe measures.
1609
+ assert (llvm::all_of (*closure->getParameters (), [](const ParamDecl *PD) {
1610
+ if (PD->hasValidSignature ()) {
1611
+ auto paramTy = PD->getType ();
1612
+ return !(paramTy->hasTypeVariable () || paramTy->hasError ());
1613
+ }
1614
+ return true ;
1615
+ }));
1616
+ }
1617
+
1618
+ return {true , E};
1619
+ }
1620
+
1621
+ Expr *walkToExprPost (Expr *E) override {
1622
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
1623
+ assert (CurrDC == closure && " DeclContext imbalance" );
1624
+ CurrDC = closure->getParent ();
1615
1625
}
1626
+ return E;
1616
1627
}
1617
- }
1618
1628
1619
- // When we're type checking a single-expression closure, we need to reset the
1620
- // DeclContext to this closure for the recursive type checking. Otherwise,
1621
- // if there is a closure in the subexpression, we can violate invariants.
1622
- auto newDC = NearestClosure ? NearestClosure : CS.DC ;
1623
- llvm::SaveAndRestore<DeclContext *> SavedDC (CS.DC , newDC);
1629
+ } finder (CS.DC , subExpr);
1624
1630
1625
- // Otherwise, we're ok to type check the subexpr.
1626
- return typeCheckChildIndependently (subExpr, options) ;
1631
+ expr-> walk (finder);
1632
+ return finder. DC ;
1627
1633
}
1628
1634
1629
1635
// / For an expression being type checked with a CTP_CalleeResult contextual
@@ -6668,8 +6674,7 @@ bool FailureDiagnosis::diagnoseMemberFailures(
6668
6674
NameLoc = DeclNameLoc (memberRange.Start );
6669
6675
6670
6676
// Retypecheck the anchor type, which is the base of the member expression.
6671
- baseExpr =
6672
- typeCheckArbitrarySubExprIndependently (baseExpr, TCC_AllowLValue);
6677
+ baseExpr = typeCheckChildIndependently (baseExpr, TCC_AllowLValue);
6673
6678
if (!baseExpr)
6674
6679
return true ;
6675
6680
0 commit comments