Skip to content

Commit 916ce89

Browse files
committed
[Constraint system] Update type map code for recursion through salvage().
When we track which expressions we're already in the middle of type checking, we need to ensure that we also track the constraint system which has the types for that expression, and then transfer those types into our current constraint system so that we do not fail to look them up.
1 parent 856429c commit 916ce89

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3282,14 +3282,23 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
32823282
// expression (which may lead to infinite recursion). If the client is
32833283
// telling us that it knows what it is doing, then believe it.
32843284
if (!options.contains(TCC_ForceRecheck)) {
3285-
if (Expr *res = CS->TC.isExprBeingDiagnosed(subExpr)) {
3285+
if (CS->TC.isExprBeingDiagnosed(subExpr)) {
3286+
auto exprAndCS = CS->TC.getExprBeingDiagnosed(subExpr);
3287+
auto *savedExpr = exprAndCS.first;
3288+
if (subExpr == savedExpr)
3289+
return subExpr;
3290+
3291+
auto *oldCS = exprAndCS.second;
3292+
32863293
// The types on the result might have already been cached into
32873294
// another CS, but likely not this one.
3288-
CS->cacheExprTypes(res);
3289-
return res;
3295+
if (oldCS != CS)
3296+
CS->transferExprTypes(oldCS, savedExpr);
3297+
3298+
return savedExpr;
32903299
}
32913300

3292-
CS->TC.addExprForDiagnosis(subExpr, subExpr);
3301+
CS->TC.addExprForDiagnosis(subExpr, std::make_pair(subExpr, CS));
32933302
}
32943303

32953304
// Validate contextual type before trying to use it.
@@ -3377,8 +3386,8 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
33773386
SavedTypeData.restore();
33783387
}
33793388

3380-
CS->TC.addExprForDiagnosis(preCheckedExpr, subExpr);
33813389
CS->cacheExprTypes(subExpr);
3390+
CS->TC.addExprForDiagnosis(preCheckedExpr, std::make_pair(subExpr, CS));
33823391

33833392
return subExpr;
33843393
}

lib/Sema/ConstraintSystem.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,30 @@ class ConstraintSystem {
12871287
bool walkToDeclPre(Decl *decl) override { return false; }
12881288
};
12891289

1290+
class TransferExprTypes : public ASTWalker {
1291+
ConstraintSystem &toCS;
1292+
ConstraintSystem &fromCS;
1293+
1294+
public:
1295+
TransferExprTypes(ConstraintSystem &toCS, ConstraintSystem &fromCS)
1296+
: toCS(toCS), fromCS(fromCS) {}
1297+
1298+
Expr *walkToExprPost(Expr *expr) override {
1299+
if (fromCS.hasType(expr))
1300+
toCS.setType(expr, fromCS.getType(expr));
1301+
1302+
return expr;
1303+
}
1304+
1305+
/// \brief Ignore statements.
1306+
std::pair<bool, Stmt *> walkToStmtPre(Stmt *stmt) override {
1307+
return { false, stmt };
1308+
}
1309+
1310+
/// \brief Ignore declarations.
1311+
bool walkToDeclPre(Decl *decl) override { return false; }
1312+
};
1313+
12901314
public:
12911315

12921316
void setExprTypes(Expr *expr) {
@@ -1312,6 +1336,10 @@ class ConstraintSystem {
13121336
expr->walk(CacheExprTypes(expr, *this, excludeRoot));
13131337
}
13141338

1339+
void transferExprTypes(ConstraintSystem *oldCS, Expr *expr) {
1340+
expr->walk(TransferExprTypes(*this, *oldCS));
1341+
}
1342+
13151343
/// \brief The current solver state.
13161344
///
13171345
/// This will be non-null when we're actively solving the constraint

lib/Sema/TypeChecker.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ namespace constraints {
5555
typedef llvm::DenseMap<SubstitutableType *,
5656
SmallVector<ProtocolConformance *, 2>> ConformanceMap;
5757

58+
/// \brief Used for recursive lookups into an expr that is already
59+
/// being type-checked and the constraint system in which its type is
60+
/// stored.
61+
typedef std::pair<Expr *,
62+
constraints::ConstraintSystem *> ExprAndConstraintSystem;
63+
5864
/// Special-case type checking semantics for certain declarations.
5965
enum class DeclTypeCheckingSemantics {
6066
/// A normal declaration.
@@ -816,7 +822,7 @@ class TypeChecker final : public LazyResolver {
816822
llvm::DenseSet<CanType> CIntegerTypes;
817823

818824
/// The set of expressions currently being analyzed for failures.
819-
llvm::DenseMap<Expr*, Expr*> DiagnosedExprs;
825+
llvm::DenseMap<Expr*, ExprAndConstraintSystem> DiagnosedExprs;
820826

821827
ModuleDecl *StdlibModule = nullptr;
822828

@@ -2307,10 +2313,13 @@ class TypeChecker final : public LazyResolver {
23072313
void checkInitializerErrorHandling(Initializer *I, Expr *E);
23082314
void checkEnumElementErrorHandling(EnumElementDecl *D);
23092315

2310-
void addExprForDiagnosis(Expr *E1, Expr *Result) {
2316+
void addExprForDiagnosis(Expr *E1, ExprAndConstraintSystem Result) {
23112317
DiagnosedExprs[E1] = Result;
23122318
}
2313-
Expr *isExprBeingDiagnosed(Expr *E) {
2319+
bool isExprBeingDiagnosed(Expr *E) {
2320+
return DiagnosedExprs.count(E);
2321+
}
2322+
ExprAndConstraintSystem getExprBeingDiagnosed(Expr *E) {
23142323
return DiagnosedExprs[E];
23152324
}
23162325

0 commit comments

Comments
 (0)