Skip to content

Commit 914356f

Browse files
authored
Merge pull request #6801 from xedin/keypath-crashers
[QoI] Cleanup AST after trying to shrink constraint system of invalid expression
2 parents 6ff95da + 488fc0f commit 914356f

12 files changed

+75
-63
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,53 +1449,77 @@ ConstraintSystem::solveSingle(FreeTypeVariableBinding allowFreeTypeVariables) {
14491449
}
14501450

14511451
bool ConstraintSystem::Candidate::solve() {
1452-
// Cleanup after constraint system generation/solving,
1453-
// because it would assign types to expressions, which
1454-
// might interfere with solving higher-level expressions.
1455-
ExprCleaner cleaner(E);
1452+
// For cleanup to work correctly e.g. `CleanupIllFormedExpressionRAII`
1453+
// `E` has to be 'reference to pointer' but, in this situation, it can't
1454+
// because we don't want to accidently modify AST while trying to reduce
1455+
// type domains of sub-expressions. Because constraint generation _might_
1456+
// produce completely different expression let's use a locally scoped
1457+
// 'reference to pointer' variable instead of `E` which enables both
1458+
// proper constraint generation/solving and cleanup.
1459+
auto *&expr = E;
1460+
{
1461+
// Cleanup after constraint system generation/solving,
1462+
// because it would assign types to expressions, which
1463+
// might interfere with solving higher-level expressions.
1464+
ExprCleaner cleaner(expr);
1465+
CleanupIllFormedExpressionRAII cleanup(TC.Context, expr);
1466+
1467+
// Allocate new constraint system for sub-expression.
1468+
ConstraintSystem cs(TC, DC, None);
1469+
1470+
// Generate constraints for the new system.
1471+
if (auto generatedExpr = cs.generateConstraints(expr)) {
1472+
expr = generatedExpr;
1473+
} else {
1474+
// Failure to generate constraint system for sub-expression
1475+
// means we can't continue solving sub-expressions.
1476+
return true;
1477+
}
14561478

1457-
// Allocate new constraint system for sub-expression.
1458-
ConstraintSystem cs(TC, DC, None);
1479+
// If there is contextual type present, add an explicit "conversion"
1480+
// constraint to the system.
1481+
if (!CT.isNull()) {
1482+
auto constraintKind = ConstraintKind::Conversion;
1483+
if (CTP == CTP_CallArgument)
1484+
constraintKind = ConstraintKind::ArgumentConversion;
14591485

1460-
// Generate constraints for the new system.
1461-
if (auto generatedExpr = cs.generateConstraints(E)) {
1462-
E = generatedExpr;
1463-
} else {
1464-
// Failure to generate constraint system for sub-expression means we can't
1465-
// continue solving sub-expressions.
1466-
return true;
1467-
}
1468-
1469-
// If there is contextual type present, add an explicit "conversion"
1470-
// constraint to the system.
1471-
if (!CT.isNull()) {
1472-
auto constraintKind = ConstraintKind::Conversion;
1473-
if (CTP == CTP_CallArgument)
1474-
constraintKind = ConstraintKind::ArgumentConversion;
1486+
cs.addConstraint(constraintKind, cs.getType(expr), CT,
1487+
cs.getConstraintLocator(expr), /*isFavored=*/true);
1488+
}
14751489

1476-
cs.addConstraint(constraintKind, cs.getType(E), CT,
1477-
cs.getConstraintLocator(E), /*isFavored=*/true);
1478-
}
1490+
// Try to solve the system and record all available solutions.
1491+
llvm::SmallVector<Solution, 2> solutions;
1492+
{
1493+
SolverState state(cs);
14791494

1480-
// Try to solve the system and record all available solutions.
1481-
llvm::SmallVector<Solution, 2> solutions;
1482-
{
1483-
SolverState state(cs);
1495+
// Use solveRec() instead of solve() in here, because solve()
1496+
// would try to deduce the best solution, which we don't
1497+
// really want. Instead, we want the reduced set of domain choices.
1498+
cs.solveRec(solutions, FreeTypeVariableBinding::Allow);
1499+
}
14841500

1485-
// Use solveRec() instead of solve() in here, because solve()
1486-
// would try to deduce the best solution, which we don't
1487-
// really want. Instead, we want the reduced set of domain choices.
1488-
cs.solveRec(solutions, FreeTypeVariableBinding::Allow);
1489-
}
1501+
// No solutions for the sub-expression means that either main expression
1502+
// needs salvaging or it's inconsistent (read: doesn't have solutions).
1503+
if (solutions.empty())
1504+
return true;
14901505

1491-
// No solutions for the sub-expression means that either main expression
1492-
// needs salvaging or it's inconsistent (read: doesn't have solutions).
1493-
if (solutions.empty())
1494-
return true;
1506+
// Record found solutions as suggestions.
1507+
this->applySolutions(solutions);
1508+
1509+
// Solution application is going to modify types of sub-expresssions,
1510+
// so we need to avoid clean-up afterwords, but let's double-check
1511+
// if we have any implicit expressions with type variables and
1512+
// nullify their types.
1513+
cleanup.disable();
1514+
expr->forEachChildExpr([&](Expr *childExpr) -> Expr * {
1515+
Type type = childExpr->getType();
1516+
if (childExpr->isImplicit() && type && type->hasTypeVariable())
1517+
childExpr->setType(Type());
1518+
return childExpr;
1519+
});
14951520

1496-
// Record found solutions as suggestions.
1497-
this->applySolutions(solutions);
1498-
return false;
1521+
return false;
1522+
}
14991523
}
15001524

15011525
void ConstraintSystem::Candidate::applySolutions(

validation-test/compiler_crashers/28593-unreachable-executed-at-swift-lib-ast-type-cpp-3771.swift renamed to validation-test/compiler_crashers_fixed/28593-unreachable-executed-at-swift-lib-ast-type-cpp-3771.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
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: deterministic-behavior
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
[{_=#keyPath(t>w
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
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: deterministic-behavior
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
f#keyPath(n&_==a>c{{{{{{{{{{{{{{{{{_=b:{{{{c{{{{{{d

validation-test/compiler_crashers/28631-unreachable-executed-at-swift-lib-ast-type-cpp-1130.swift renamed to validation-test/compiler_crashers_fixed/28631-unreachable-executed-at-swift-lib-ast-type-cpp-1130.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
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: deterministic-behavior
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
[{{{{{{{{{{{{{{0=#keyPath(n&_=d

validation-test/compiler_crashers/28632-unreachable-executed-at-swift-lib-ast-type-cpp-1130.swift renamed to validation-test/compiler_crashers_fixed/28632-unreachable-executed-at-swift-lib-ast-type-cpp-1130.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
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: deterministic-behavior
98
// REQUIRES: asserts
10-
// RUN: not --crash %target-swift-frontend %s -emit-ir
9+
// RUN: not %target-swift-frontend %s -emit-ir
1110

1211
{func a>
1312
print(a==#keyPath(a{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,5 @@
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: deterministic-behavior
9-
// REQUIRES: deterministic-behavior
10-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
119
func a|Set(#keyPath(t>a>a{

validation-test/compiler_crashers/28639-unreachable-executed-at-swift-lib-ast-type-cpp-1337.swift renamed to validation-test/compiler_crashers_fixed/28639-unreachable-executed-at-swift-lib-ast-type-cpp-1337.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
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: deterministic-behavior
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
print([{#keyPath(a}(t>A
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
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: deterministic-behavior
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
protocol a func a|Set(#keyPath(t>a{

validation-test/compiler_crashers/28641-result-case-not-implemented.swift renamed to validation-test/compiler_crashers_fixed/28641-result-case-not-implemented.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +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: deterministic-behavior
98
// REQUIRES: asserts
10-
// RUN: not --crash %target-swift-frontend %s -emit-ir
9+
// RUN: not %target-swift-frontend %s -emit-ir
1110
{let β=b&[{{{#keyPath(n&[{{{{{{{{{{{{{{{{{{{{{{{{{{a{{{{s

validation-test/compiler_crashers/28642-swift-optionaltype-get-swift-type.swift renamed to validation-test/compiler_crashers_fixed/28642-swift-optionaltype-get-swift-type.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
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: deterministic-behavior
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
Array(_==#keyPath(t>Void!
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
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: deterministic-behavior
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
(.n).h.n&[(#keyPath(t>A

validation-test/compiler_crashers/28646-swift-lvaluetype-get-swift-type.swift renamed to validation-test/compiler_crashers_fixed/28646-swift-lvaluetype-get-swift-type.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
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: deterministic-behavior
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
109
#keyPath(a
1110
print(Int
1211
print(_=#keyPath(a

0 commit comments

Comments
 (0)