@@ -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
}
@@ -1559,10 +1557,14 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
1559
1557
if ((!convertType || options.contains (TCC_AllowUnresolvedTypeVariables)) &&
1560
1558
allowFreeTypeVariables)
1561
1559
TCEOptions |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
1562
-
1563
- auto resultTy = CS.TC .typeCheckExpression (
1564
- subExpr, CS.DC , TypeLoc::withoutLoc (convertType), convertTypePurpose,
1565
- TCEOptions, listener, &CS);
1560
+
1561
+ // When we're type checking a single-expression closure, we need to reset the
1562
+ // DeclContext to this closure for the recursive type checking. Otherwise,
1563
+ // if there is a closure in the subexpression, we can violate invariants.
1564
+ auto *DC = findDeclContext (subExpr);
1565
+ auto resultTy =
1566
+ CS.TC .typeCheckExpression (subExpr, DC, TypeLoc::withoutLoc (convertType),
1567
+ convertTypePurpose, TCEOptions, listener, &CS);
1566
1568
1567
1569
CS.cacheExprTypes (subExpr);
1568
1570
@@ -1598,49 +1600,53 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
1598
1600
return subExpr;
1599
1601
}
1600
1602
1601
- // / This is the same as typeCheckChildIndependently, but works on an arbitrary
1602
- // / subexpression of the current node because it handles ClosureExpr parents
1603
- // / of the specified node.
1604
- Expr *FailureDiagnosis::
1605
- typeCheckArbitrarySubExprIndependently (Expr *subExpr, TCCOptions options) {
1606
- if (subExpr == expr)
1607
- return typeCheckChildIndependently (subExpr, options);
1608
-
1609
- // Construct a parent map for the expr tree we're investigating.
1610
- auto parentMap = expr->getParentMap ();
1611
-
1612
- ClosureExpr *NearestClosure = nullptr ;
1613
-
1614
- // Walk the parents of the specified expression, handling any ClosureExprs.
1615
- for (Expr *node = parentMap[subExpr]; node; node = parentMap[node]) {
1616
- auto *CE = dyn_cast<ClosureExpr>(node);
1617
- if (!CE) continue ;
1618
-
1619
- // Keep track of the innermost closure we see that we're jumping into.
1620
- if (!NearestClosure)
1621
- NearestClosure = CE;
1622
-
1623
- // If we have a ClosureExpr parent of the specified node, check to make sure
1624
- // none of its arguments are type variables. If so, these type variables
1625
- // would be accessible to name lookup of the subexpression and may thus leak
1626
- // in. Reset them to UnresolvedTypes for safe measures.
1627
- for (auto *param : *CE->getParameters ()) {
1628
- if (param->hasValidSignature ()) {
1629
- auto type = param->getType ();
1630
- assert (!type->hasTypeVariable () && !type->hasError ());
1631
- (void )type;
1603
+ DeclContext *FailureDiagnosis::findDeclContext (Expr *subExpr) const {
1604
+ if (auto *closure =
1605
+ dyn_cast<ClosureExpr>(subExpr->getSemanticsProvidingExpr ()))
1606
+ return closure->getParent ();
1607
+
1608
+ struct DCFinder : public ASTWalker {
1609
+ DeclContext *DC, *CurrDC;
1610
+ Expr *SubExpr;
1611
+
1612
+ DCFinder (DeclContext *DC, Expr *expr) : DC(DC), CurrDC(DC), SubExpr(expr) {}
1613
+
1614
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
1615
+ if (E == SubExpr) {
1616
+ DC = CurrDC;
1617
+ return {false , nullptr };
1618
+ }
1619
+
1620
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
1621
+ CurrDC = closure;
1622
+ // If we have a ClosureExpr parent of the specified node, check to make
1623
+ // sure none of its arguments are type variables. If so, these type
1624
+ // variables would be accessible to name lookup of the subexpression and
1625
+ // may thus leak in. Reset them to UnresolvedTypes for safe measures.
1626
+ assert (llvm::all_of (*closure->getParameters (), [](const ParamDecl *PD) {
1627
+ if (PD->hasValidSignature ()) {
1628
+ auto paramTy = PD->getType ();
1629
+ return !(paramTy->hasTypeVariable () || paramTy->hasError ());
1630
+ }
1631
+ return true ;
1632
+ }));
1633
+ }
1634
+
1635
+ return {true , E};
1636
+ }
1637
+
1638
+ Expr *walkToExprPost (Expr *E) override {
1639
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
1640
+ assert (CurrDC == closure && " DeclContext imbalance" );
1641
+ CurrDC = closure->getParent ();
1632
1642
}
1643
+ return E;
1633
1644
}
1634
- }
1635
1645
1636
- // When we're type checking a single-expression closure, we need to reset the
1637
- // DeclContext to this closure for the recursive type checking. Otherwise,
1638
- // if there is a closure in the subexpression, we can violate invariants.
1639
- auto newDC = NearestClosure ? NearestClosure : CS.DC ;
1640
- llvm::SaveAndRestore<DeclContext *> SavedDC (CS.DC , newDC);
1646
+ } finder (CS.DC , subExpr);
1641
1647
1642
- // Otherwise, we're ok to type check the subexpr.
1643
- return typeCheckChildIndependently (subExpr, options) ;
1648
+ expr-> walk (finder);
1649
+ return finder. DC ;
1644
1650
}
1645
1651
1646
1652
// / For an expression being type checked with a CTP_CalleeResult contextual
@@ -6685,8 +6691,7 @@ bool FailureDiagnosis::diagnoseMemberFailures(
6685
6691
NameLoc = DeclNameLoc (memberRange.Start );
6686
6692
6687
6693
// Retypecheck the anchor type, which is the base of the member expression.
6688
- baseExpr =
6689
- typeCheckArbitrarySubExprIndependently (baseExpr, TCC_AllowLValue);
6694
+ baseExpr = typeCheckChildIndependently (baseExpr, TCC_AllowLValue);
6690
6695
if (!baseExpr)
6691
6696
return true ;
6692
6697
0 commit comments