@@ -408,11 +408,9 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
408
408
return e ? CS.getType (e) : Type ();
409
409
}
410
410
411
- // / This is the same as typeCheckChildIndependently, but works on an arbitrary
412
- // / subexpression of the current node because it handles ClosureExpr parents
413
- // / of the specified node.
414
- Expr *typeCheckArbitrarySubExprIndependently (Expr *subExpr,
415
- TCCOptions options = TCCOptions());
411
+ // / Find a nearest declaration context which could be used
412
+ // / to type-check this sub-expression.
413
+ DeclContext *findDeclContext (Expr *subExpr) const ;
416
414
417
415
// / Special magic to handle inout exprs and tuples in argument lists.
418
416
Expr *typeCheckArgumentChildIndependently (Expr *argExpr, Type argType,
@@ -1150,8 +1148,8 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){
1150
1148
// constraint.
1151
1149
if (CS.getContextualTypePurpose () != CTP_Unused)
1152
1150
options |= TCC_ForceRecheck;
1153
-
1154
- auto sub = typeCheckArbitrarySubExprIndependently (anchor, options);
1151
+
1152
+ auto sub = typeCheckChildIndependently (anchor, options);
1155
1153
if (!sub) return true ;
1156
1154
fromType = CS.getType (sub);
1157
1155
}
@@ -1624,10 +1622,14 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
1624
1622
if ((!convertType || options.contains (TCC_AllowUnresolvedTypeVariables)) &&
1625
1623
allowFreeTypeVariables)
1626
1624
TCEOptions |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
1627
-
1628
- auto resultTy = CS.TC .typeCheckExpression (
1629
- subExpr, CS.DC , TypeLoc::withoutLoc (convertType), convertTypePurpose,
1630
- TCEOptions, listener, &CS);
1625
+
1626
+ // When we're type checking a single-expression closure, we need to reset the
1627
+ // DeclContext to this closure for the recursive type checking. Otherwise,
1628
+ // if there is a closure in the subexpression, we can violate invariants.
1629
+ auto *DC = findDeclContext (subExpr);
1630
+ auto resultTy =
1631
+ CS.TC .typeCheckExpression (subExpr, DC, TypeLoc::withoutLoc (convertType),
1632
+ convertTypePurpose, TCEOptions, listener, &CS);
1631
1633
1632
1634
CS.cacheExprTypes (subExpr);
1633
1635
@@ -1663,49 +1665,53 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
1663
1665
return subExpr;
1664
1666
}
1665
1667
1666
- // / This is the same as typeCheckChildIndependently, but works on an arbitrary
1667
- // / subexpression of the current node because it handles ClosureExpr parents
1668
- // / of the specified node.
1669
- Expr *FailureDiagnosis::
1670
- typeCheckArbitrarySubExprIndependently (Expr *subExpr, TCCOptions options) {
1671
- if (subExpr == expr)
1672
- return typeCheckChildIndependently (subExpr, options);
1673
-
1674
- // Construct a parent map for the expr tree we're investigating.
1675
- auto parentMap = expr->getParentMap ();
1676
-
1677
- ClosureExpr *NearestClosure = nullptr ;
1678
-
1679
- // Walk the parents of the specified expression, handling any ClosureExprs.
1680
- for (Expr *node = parentMap[subExpr]; node; node = parentMap[node]) {
1681
- auto *CE = dyn_cast<ClosureExpr>(node);
1682
- if (!CE) continue ;
1683
-
1684
- // Keep track of the innermost closure we see that we're jumping into.
1685
- if (!NearestClosure)
1686
- NearestClosure = CE;
1687
-
1688
- // If we have a ClosureExpr parent of the specified node, check to make sure
1689
- // none of its arguments are type variables. If so, these type variables
1690
- // would be accessible to name lookup of the subexpression and may thus leak
1691
- // in. Reset them to UnresolvedTypes for safe measures.
1692
- for (auto *param : *CE->getParameters ()) {
1693
- if (param->hasValidSignature ()) {
1694
- auto type = param->getType ();
1695
- assert (!type->hasTypeVariable () && !type->hasError ());
1696
- (void )type;
1668
+ DeclContext *FailureDiagnosis::findDeclContext (Expr *subExpr) const {
1669
+ if (auto *closure =
1670
+ dyn_cast<ClosureExpr>(subExpr->getSemanticsProvidingExpr ()))
1671
+ return closure->getParent ();
1672
+
1673
+ struct DCFinder : public ASTWalker {
1674
+ DeclContext *DC, *CurrDC;
1675
+ Expr *SubExpr;
1676
+
1677
+ DCFinder (DeclContext *DC, Expr *expr) : DC(DC), CurrDC(DC), SubExpr(expr) {}
1678
+
1679
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
1680
+ if (E == SubExpr) {
1681
+ DC = CurrDC;
1682
+ return {false , nullptr };
1683
+ }
1684
+
1685
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
1686
+ CurrDC = closure;
1687
+ // If we have a ClosureExpr parent of the specified node, check to make
1688
+ // sure none of its arguments are type variables. If so, these type
1689
+ // variables would be accessible to name lookup of the subexpression and
1690
+ // may thus leak in. Reset them to UnresolvedTypes for safe measures.
1691
+ assert (llvm::all_of (*closure->getParameters (), [](const ParamDecl *PD) {
1692
+ if (PD->hasValidSignature ()) {
1693
+ auto paramTy = PD->getType ();
1694
+ return !(paramTy->hasTypeVariable () || paramTy->hasError ());
1695
+ }
1696
+ return true ;
1697
+ }));
1698
+ }
1699
+
1700
+ return {true , E};
1701
+ }
1702
+
1703
+ Expr *walkToExprPost (Expr *E) override {
1704
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
1705
+ assert (CurrDC == closure && " DeclContext imbalance" );
1706
+ CurrDC = closure->getParent ();
1697
1707
}
1708
+ return E;
1698
1709
}
1699
- }
1700
1710
1701
- // When we're type checking a single-expression closure, we need to reset the
1702
- // DeclContext to this closure for the recursive type checking. Otherwise,
1703
- // if there is a closure in the subexpression, we can violate invariants.
1704
- auto newDC = NearestClosure ? NearestClosure : CS.DC ;
1705
- llvm::SaveAndRestore<DeclContext *> SavedDC (CS.DC , newDC);
1711
+ } finder (CS.DC , subExpr);
1706
1712
1707
- // Otherwise, we're ok to type check the subexpr.
1708
- return typeCheckChildIndependently (subExpr, options) ;
1713
+ expr-> walk (finder);
1714
+ return finder. DC ;
1709
1715
}
1710
1716
1711
1717
// / For an expression being type checked with a CTP_CalleeResult contextual
@@ -6723,8 +6729,7 @@ bool FailureDiagnosis::diagnoseMemberFailures(
6723
6729
NameLoc = DeclNameLoc (memberRange.Start );
6724
6730
6725
6731
// Retypecheck the anchor type, which is the base of the member expression.
6726
- baseExpr =
6727
- typeCheckArbitrarySubExprIndependently (baseExpr, TCC_AllowLValue);
6732
+ baseExpr = typeCheckChildIndependently (baseExpr, TCC_AllowLValue);
6728
6733
if (!baseExpr)
6729
6734
return true ;
6730
6735
0 commit comments