Skip to content

Commit a40e8e8

Browse files
committed
[ConstraintSystem] Use affected range (if any) to diagnose 'too complex' failures
1 parent ef2f24b commit a40e8e8

File tree

6 files changed

+31
-13
lines changed

6 files changed

+31
-13
lines changed

include/swift/Sema/SolutionResult.h

+8-3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ class SolutionResult {
6464
/// \c numSolutions entries.
6565
Solution *solutions = nullptr;
6666

67+
/// A source range that was too complex to solve.
68+
Optional<SourceRange> TooComplexAt = None;
69+
6770
/// General constructor for the named constructors.
6871
SolutionResult(Kind kind) : kind(kind) {
6972
emittedDiagnostic = false;
@@ -95,9 +98,7 @@ class SolutionResult {
9598

9699
/// Produce a "too complex" failure, which was not yet been
97100
/// diagnosed.
98-
static SolutionResult forTooComplex() {
99-
return SolutionResult(TooComplex);
100-
}
101+
static SolutionResult forTooComplex(Optional<SourceRange> affected);
101102

102103
/// Produce a failure that has already been diagnosed.
103104
static SolutionResult forError() {
@@ -123,6 +124,10 @@ class SolutionResult {
123124
/// Take the set of solutions when there is an ambiguity.
124125
MutableArrayRef<Solution> takeAmbiguousSolutions() &&;
125126

127+
/// Retrieve a range of source that has been determined to be too
128+
/// complex to solve in a reasonable time.
129+
Optional<SourceRange> getTooComplexAt() const { return TooComplexAt; }
130+
126131
/// Whether this solution requires the client to produce a diagnostic.
127132
bool requiresDiagnostic() const {
128133
switch (kind) {

lib/Sema/CSApply.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -9106,6 +9106,12 @@ SolutionResult SolutionResult::forAmbiguous(
91069106
return result;
91079107
}
91089108

9109+
SolutionResult SolutionResult::forTooComplex(Optional<SourceRange> affected) {
9110+
SolutionResult result(Kind::TooComplex);
9111+
result.TooComplexAt = affected;
9112+
return result;
9113+
}
9114+
91099115
SolutionResult::~SolutionResult() {
91109116
assert((!requiresDiagnostic() || emittedDiagnostic) &&
91119117
"SolutionResult was destroyed without emitting a diagnostic");

lib/Sema/CSSolver.cpp

+14-5
Original file line numberDiff line numberDiff line change
@@ -1298,12 +1298,21 @@ Optional<std::vector<Solution>> ConstraintSystem::solve(
12981298
maybeProduceFallbackDiagnostic(target);
12991299
return None;
13001300

1301-
case SolutionResult::TooComplex:
1302-
getASTContext().Diags.diagnose(
1303-
target.getLoc(), diag::expression_too_complex)
1304-
.highlight(target.getSourceRange());
1301+
case SolutionResult::TooComplex: {
1302+
auto affectedRange = solution.getTooComplexAt();
1303+
1304+
// If affected range is unknown, let's use whole
1305+
// target.
1306+
if (!affectedRange)
1307+
affectedRange = target.getSourceRange();
1308+
1309+
getASTContext()
1310+
.Diags.diagnose(affectedRange->Start, diag::expression_too_complex)
1311+
.highlight(*affectedRange);
1312+
13051313
solution.markAsDiagnosed();
13061314
return None;
1315+
}
13071316

13081317
case SolutionResult::Ambiguous:
13091318
// If salvaging produced an ambiguous result, it has already been
@@ -1375,7 +1384,7 @@ ConstraintSystem::solveImpl(SolutionApplicationTarget &target,
13751384
solve(solutions, allowFreeTypeVariables);
13761385

13771386
if (isTooComplex(solutions))
1378-
return SolutionResult::forTooComplex();
1387+
return SolutionResult::forTooComplex(getTooComplexRange());
13791388

13801389
switch (solutions.size()) {
13811390
case 0:

lib/Sema/ConstraintSystem.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3784,7 +3784,7 @@ SolutionResult ConstraintSystem::salvage() {
37843784
}
37853785

37863786
if (isTooComplex(viable))
3787-
return SolutionResult::forTooComplex();
3787+
return SolutionResult::forTooComplex(getTooComplexRange());
37883788

37893789
// Could not produce a specific diagnostic; punt to the client.
37903790
return SolutionResult::forUndiagnosedError();

validation-test/Sema/type_checker_perf/slow/rdar19612086.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ struct rdar19612086 {
1111
let x = 1.0
1212

1313
var description : String {
14-
return "\(i)" + Stringly(format: "%.2f", x) +
14+
return "\(i)" + Stringly(format: "%.2f", x) + // expected-error {{reasonable time}}
1515
"\(i+1)" + Stringly(format: "%.2f", x) +
1616
"\(i+2)" + Stringly(format: "%.2f", x) +
1717
"\(i+3)" + Stringly(format: "%.2f", x) +
1818
"\(i+4)" + Stringly(format: "%.2f", x) +
1919
"\(i+5)" + Stringly(format: "%.2f", x)
20-
// expected-error@-1 {{reasonable time}}
2120
}
2221
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=1
22
// REQUIRES: tools-release,no_asan
33

4-
let _ = (0...1).lazy.flatMap {
4+
let _ = (0...1).lazy.flatMap { // expected-error {{reasonable time}}
55
a in (1...2).lazy.map { b in (a, b) }
66
}.filter {
7-
// expected-error@-1 {{reasonable time}}
87
1 < $0 && $0 < $1 && $0 + $1 < 3
98
}

0 commit comments

Comments
 (0)