Skip to content

Commit 8c17b92

Browse files
committed
[ConstraintSystem] Add TypeLoc caching to constraint system
This is useful for explicit casts and type expressions, where type loc and expression types might be different, and allows constraint solver to avoid setting opened types to expressions which resolves multiple crashes.
1 parent c0f5711 commit 8c17b92

8 files changed

+43
-24
lines changed

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,10 +2458,9 @@ namespace {
24582458
}
24592459

24602460
Expr *visitTypeExpr(TypeExpr *expr) {
2461-
auto toType = simplifyType(expr->getTypeLoc().getType());
2461+
auto toType = simplifyType(cs.getType(expr->getTypeLoc()));
24622462
expr->getTypeLoc().setType(toType, /*validated=*/true);
24632463
cs.setType(expr, MetatypeType::get(toType));
2464-
24652464
return expr;
24662465
}
24672466

@@ -3121,7 +3120,7 @@ namespace {
31213120
Expr *visitIsExpr(IsExpr *expr) {
31223121
// Turn the subexpression into an rvalue.
31233122
auto &tc = cs.getTypeChecker();
3124-
auto toType = simplifyType(expr->getCastTypeLoc().getType());
3123+
auto toType = simplifyType(cs.getType(expr->getCastTypeLoc()));
31253124
auto sub = cs.coerceToRValue(expr->getSubExpr());
31263125

31273126
checkForImportedUsedConformances(toType);
@@ -3193,6 +3192,7 @@ namespace {
31933192
sub, expr->getLoc(), SourceLoc(),
31943193
TypeLoc::withoutLoc(toType));
31953194
cs.setType(cast, toOptType);
3195+
cs.setType(cast->getCastTypeLoc(), toType);
31963196
if (expr->isImplicit())
31973197
cast->setImplicit();
31983198

@@ -3470,7 +3470,7 @@ namespace {
34703470

34713471
Expr *visitCoerceExpr(CoerceExpr *expr, Optional<unsigned> choice) {
34723472
// Simplify the type we're casting to.
3473-
auto toType = simplifyType(expr->getCastTypeLoc().getType());
3473+
auto toType = simplifyType(cs.getType(expr->getCastTypeLoc()));
34743474
expr->getCastTypeLoc().setType(toType, /*validated=*/true);
34753475
checkForImportedUsedConformances(toType);
34763476

@@ -3556,7 +3556,7 @@ namespace {
35563556
// Most of the logic for dealing with ForcedCheckedCastExpr.
35573557
Expr *handleForcedCheckedCastExpr(ForcedCheckedCastExpr *expr) {
35583558
// Simplify the type we're casting to.
3559-
auto toType = simplifyType(expr->getCastTypeLoc().getType());
3559+
auto toType = simplifyType(cs.getType(expr->getCastTypeLoc()));
35603560
expr->getCastTypeLoc().setType(toType, /*validated=*/true);
35613561
checkForImportedUsedConformances(toType);
35623562

@@ -3599,6 +3599,7 @@ namespace {
35993599
auto *result = new (tc.Context) CoerceExpr(sub, expr->getLoc(),
36003600
expr->getCastTypeLoc());
36013601
cs.setType(result, toType);
3602+
cs.setType(result->getCastTypeLoc(), toType);
36023603
unsigned disjunctionChoice =
36033604
(castKind == CheckedCastKind::Coercion ? 0 : 1);
36043605
return visitCoerceExpr(result, disjunctionChoice);
@@ -3636,7 +3637,7 @@ namespace {
36363637
Expr *handleConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr,
36373638
bool isInsideIsExpr = false) {
36383639
// Simplify the type we're casting to.
3639-
auto toType = simplifyType(expr->getCastTypeLoc().getType());
3640+
auto toType = simplifyType(cs.getType(expr->getCastTypeLoc()));
36403641
checkForImportedUsedConformances(toType);
36413642
expr->getCastTypeLoc().setType(toType, /*validated=*/true);
36423643

@@ -3674,6 +3675,7 @@ namespace {
36743675
auto *coerce = new (tc.Context) CoerceExpr(sub, expr->getLoc(),
36753676
expr->getCastTypeLoc());
36763677
cs.setType(coerce, toType);
3678+
cs.setType(coerce->getCastTypeLoc(), toType);
36773679
unsigned disjunctionChoice =
36783680
(castKind == CheckedCastKind::Coercion ? 0 : 1);
36793681
Expr *result = visitCoerceExpr(coerce, disjunctionChoice);

lib/Sema/CSDiag.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6077,7 +6077,7 @@ bool FailureDiagnosis::visitInOutExpr(InOutExpr *IOE) {
60776077
bool FailureDiagnosis::visitCoerceExpr(CoerceExpr *CE) {
60786078
// Coerce the input to whatever type is specified by the CoerceExpr.
60796079
auto expr = typeCheckChildIndependently(CE->getSubExpr(),
6080-
CE->getCastTypeLoc().getType(),
6080+
CS.getType(CE->getCastTypeLoc()),
60816081
CTP_CoerceOperand);
60826082
if (!expr)
60836083
return true;
@@ -7922,12 +7922,13 @@ static void noteArchetypeSource(const TypeLoc &loc, ArchetypeType *archetype,
79227922
// `Pair<Any, Any>`.
79237923
// Right now we only handle this when the type that's at fault is the
79247924
// top-level type passed to this function.
7925-
if (loc.getType().isNull()) {
7926-
return;
7927-
}
7928-
7925+
auto type = loc.getType();
7926+
if (!type)
7927+
type = cs.getType(loc);
7928+
79297929
ArrayRef<Type> genericArgs;
7930-
if (auto *boundGenericTy = loc.getType()->getAs<BoundGenericType>()) {
7930+
7931+
if (auto *boundGenericTy = type->getAs<BoundGenericType>()) {
79317932
if (boundGenericTy->getDecl() == FoundDecl)
79327933
genericArgs = boundGenericTy->getGenericArgs();
79337934
}

lib/Sema/CSGen.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,7 @@ namespace {
13491349

13501350
auto locator = CS.getConstraintLocator(E);
13511351
type = CS.openUnboundGenericType(type, locator);
1352-
E->getTypeLoc().setType(type, /*validated=*/true);
1352+
CS.setType(E->getTypeLoc(), type);
13531353
return MetatypeType::get(type);
13541354
}
13551355

@@ -2521,7 +2521,7 @@ namespace {
25212521
// Open the type we're casting to.
25222522
auto toType = CS.openUnboundGenericType(expr->getCastTypeLoc().getType(),
25232523
CS.getConstraintLocator(expr));
2524-
expr->getCastTypeLoc().setType(toType, /*validated=*/true);
2524+
CS.setType(expr->getCastTypeLoc(), toType);
25252525

25262526
auto fromType = CS.getType(fromExpr);
25272527
auto locator = CS.getConstraintLocator(expr);
@@ -2550,7 +2550,7 @@ namespace {
25502550
// Open the type we're casting to.
25512551
auto toType = CS.openUnboundGenericType(expr->getCastTypeLoc().getType(),
25522552
CS.getConstraintLocator(expr));
2553-
expr->getCastTypeLoc().setType(toType, /*validated=*/true);
2553+
CS.setType(expr->getCastTypeLoc(), toType);
25542554

25552555
auto fromType = CS.getType(expr->getSubExpr());
25562556
auto locator = CS.getConstraintLocator(expr);
@@ -2584,7 +2584,7 @@ namespace {
25842584
// Open the type we're casting to.
25852585
auto toType = CS.openUnboundGenericType(expr->getCastTypeLoc().getType(),
25862586
CS.getConstraintLocator(expr));
2587-
expr->getCastTypeLoc().setType(toType, /*validated=*/true);
2587+
CS.setType(expr->getCastTypeLoc(), toType);
25882588

25892589
auto fromType = CS.getType(fromExpr);
25902590
auto locator = CS.getConstraintLocator(expr);
@@ -2613,7 +2613,7 @@ namespace {
26132613
// FIXME: Locator for the cast type?
26142614
auto toType = CS.openUnboundGenericType(expr->getCastTypeLoc().getType(),
26152615
CS.getConstraintLocator(expr));
2616-
expr->getCastTypeLoc().setType(toType, /*validated=*/true);
2616+
CS.setType(expr->getCastTypeLoc(), toType);
26172617

26182618
// Add a checked cast constraint.
26192619
auto fromType = CS.getType(expr->getSubExpr());
@@ -3203,6 +3203,7 @@ namespace {
32033203

32043204
auto *TE = TypeExpr::createImplicit(joinTy, CS.getASTContext());
32053205
CS.cacheType(TE);
3206+
CS.setType(TE->getTypeLoc(), joinTy);
32063207

32073208
auto *DSE = new (CS.getASTContext())
32083209
DotSelfExpr(TE, SourceLoc(), SourceLoc(), CS.getType(TE));

lib/Sema/ConstraintSystem.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,7 @@ class ConstraintSystem {
969969
/// run through various diagnostics passes without actually mutating
970970
/// the types on the expression nodes.
971971
llvm::DenseMap<const Expr *, TypeBase *> ExprTypes;
972+
llvm::DenseMap<const TypeLoc *, TypeBase *> TypeLocTypes;
972973

973974
/// Maps closure parameters to type variables.
974975
llvm::DenseMap<const ParamDecl *, TypeVariableType *>
@@ -1595,12 +1596,21 @@ class ConstraintSystem {
15951596
ExprTypes[E] = T.getPointer();
15961597
}
15971598

1599+
void setType(TypeLoc &L, Type T) {
1600+
assert(T && "Expected non-null type!");
1601+
TypeLocTypes[&L] = T.getPointer();
1602+
}
1603+
15981604
/// Check to see if we have a type for an expression.
15991605
bool hasType(const Expr *E) const {
16001606
assert(E != nullptr && "Expected non-null expression!");
16011607
return ExprTypes.find(E) != ExprTypes.end();
16021608
}
16031609

1610+
bool hasType(const TypeLoc &L) const {
1611+
return TypeLocTypes.find(&L) != TypeLocTypes.end();
1612+
}
1613+
16041614
/// Get the type for an expression.
16051615
Type getType(const Expr *E) const {
16061616
assert(hasType(E) && "Expected type to have been set!");
@@ -1611,6 +1621,11 @@ class ConstraintSystem {
16111621
return ExprTypes.find(E)->second;
16121622
}
16131623

1624+
Type getType(const TypeLoc &L) const {
1625+
assert(hasType(L) && "Expected type to have been set!");
1626+
return TypeLocTypes.find(&L)->second;
1627+
}
1628+
16141629
/// Cache the type of the expression argument and return that same
16151630
/// argument.
16161631
template <typename T>

test/Constraints/generics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func r22459135() {
188188

189189
// <rdar://problem/19710848> QoI: Friendlier error message for "[] as Set"
190190
// <rdar://problem/22326930> QoI: "argument for generic parameter 'Element' could not be inferred" lacks context
191-
_ = [] as Set // expected-error {{generic parameter 'Element' could not be inferred in cast to 'Set<_>}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{14-14=<<#Element: Hashable#>>}}
191+
_ = [] as Set // expected-error {{generic parameter 'Element' could not be inferred in cast to 'Set'}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{14-14=<<#Element: Hashable#>>}}
192192

193193

194194
//<rdar://problem/22509125> QoI: Error when unable to infer generic archetype lacks greatness

validation-test/compiler_crashers/28823-impl-getgraphindex-typevariables-size-out-of-bounds-index.swift renamed to validation-test/compiler_crashers_fixed/28823-impl-getgraphindex-typevariables-size-out-of-bounds-index.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// REQUIRES: asserts
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
9+
// RUN: not %target-swift-frontend %s -emit-ir
1010
{{}as ManagedBuffer}{
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// REQUIRES: asserts
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
9+
// RUN: not %target-swift-frontend %s -emit-ir
1010
{[Int?as?ManagedBuffer}{

validation-test/compiler_crashers/28868-known-typebindings-end.swift renamed to validation-test/compiler_crashers_fixed/28868-known-typebindings-end.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// REQUIRES: asserts
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
9+
// RUN: not %target-swift-frontend %s -emit-ir
1010
struct B{func a{a(Int?as?ManagedBuffer{

0 commit comments

Comments
 (0)