@@ -3193,12 +3193,15 @@ namespace {
3193
3193
// / This is done in the case of a typecheck failure, after we re-typecheck
3194
3194
// / partially-typechecked subexpressions in a context-free manner.
3195
3195
// /
3196
- static void eraseOpenedExistentials (Expr *&expr) {
3196
+ static void eraseOpenedExistentials (Expr *&expr, ConstraintSystem &CS ) {
3197
3197
3198
3198
class ExistentialEraser : public ASTWalker {
3199
+ ConstraintSystem &CS;
3199
3200
llvm::SmallDenseMap<OpaqueValueExpr *, Expr *, 4 > OpenExistentials;
3200
3201
3201
3202
public:
3203
+ ExistentialEraser (ConstraintSystem &CS) : CS(CS) {}
3204
+
3202
3205
std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
3203
3206
if (auto OOE = dyn_cast<OpenExistentialExpr>(expr)) {
3204
3207
auto archetypeVal = OOE->getOpaqueValue ();
@@ -3236,8 +3239,11 @@ static void eraseOpenedExistentials(Expr *&expr) {
3236
3239
}
3237
3240
3238
3241
Expr *walkToExprPost (Expr *expr) override {
3239
- Type type = expr->getType ();
3240
- if (!type || !type->hasOpenedExistential ())
3242
+ if (!CS.hasType (expr))
3243
+ return expr;
3244
+
3245
+ Type type = CS.getType (expr);
3246
+ if (!type->hasOpenedExistential ())
3241
3247
return expr;
3242
3248
3243
3249
type = type.transform ([&](Type type) -> Type {
@@ -3247,7 +3253,7 @@ static void eraseOpenedExistentials(Expr *&expr) {
3247
3253
3248
3254
return type;
3249
3255
});
3250
- expr-> setType (type);
3256
+ CS. setType (expr, type);
3251
3257
3252
3258
return expr;
3253
3259
}
@@ -3259,7 +3265,7 @@ static void eraseOpenedExistentials(Expr *&expr) {
3259
3265
}
3260
3266
};
3261
3267
3262
- expr = expr->walk (ExistentialEraser ());
3268
+ expr = expr->walk (ExistentialEraser (CS ));
3263
3269
}
3264
3270
3265
3271
// / Unless we've already done this, retypecheck the specified subexpression on
@@ -3355,19 +3361,21 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
3355
3361
// anything that the type-checker doesn't expect to see. This can happen
3356
3362
// because of repeated type-checking; the removal below, while independently
3357
3363
// important, isn't itself sufficient because of AST mutation.
3358
- eraseOpenedExistentials (subExpr);
3364
+ eraseOpenedExistentials (subExpr, CS );
3359
3365
3360
3366
auto resultTy = CS.TC .typeCheckExpression (
3361
3367
subExpr, CS.DC , TypeLoc::withoutLoc (convertType), convertTypePurpose,
3362
3368
TCEOptions, listener, &CS);
3363
3369
3370
+ CS.cacheExprTypes (subExpr);
3371
+
3364
3372
// This is a terrible hack to get around the fact that typeCheckExpression()
3365
3373
// might change subExpr to point to a new OpenExistentialExpr. In that case,
3366
3374
// since the caller passed subExpr by value here, they would be left
3367
3375
// holding on to an expression containing open existential types but
3368
3376
// no OpenExistentialExpr, which breaks invariants enforced by the
3369
3377
// ASTChecker.
3370
- eraseOpenedExistentials (subExpr);
3378
+ eraseOpenedExistentials (subExpr, CS );
3371
3379
3372
3380
// If recursive type checking failed, then an error was emitted. Return
3373
3381
// null to indicate this to the caller.
@@ -3378,10 +3386,11 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
3378
3386
// just pretend as though nothing happened.
3379
3387
if (resultTy->is <ErrorType>()) {
3380
3388
subExpr = preCheckedExpr;
3389
+ if (subExpr->getType ())
3390
+ CS.cacheType (subExpr);
3381
3391
SavedTypeData.restore ();
3382
3392
}
3383
3393
3384
- CS.cacheExprTypes (subExpr);
3385
3394
CS.TC .addExprForDiagnosis (preCheckedExpr, std::make_pair (subExpr, &CS));
3386
3395
3387
3396
return subExpr;
0 commit comments