Skip to content

Commit cfe61d7

Browse files
committed
Fix tests and error reporting improvements
1 parent 860dd17 commit cfe61d7

File tree

9 files changed

+95
-103
lines changed

9 files changed

+95
-103
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pri-sessions/
3838
stainless.out/
3939
repairs.dat
4040
tmp
41+
stainless-debug.txt
4142

4243
#eclipse
4344
.cache

core/src/main/scala/stainless/MainHelpers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ trait MainHelpers extends inox.MainHelpers { self =>
181181
} catch {
182182
case e: Throwable =>
183183
reporter.debug(e)(frontend.DebugSectionFrontend)
184-
reporter.error(e.getMessage)
184+
reporter.error("There was an error during the watch cycle")
185185
compiler = newCompiler()
186186
}
187187

core/src/main/scala/stainless/frontend/BatchedCallBack.scala

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,8 @@ class BatchedCallBack(components: Seq[Component])(implicit val context: inox.Con
9494

9595
val reports = runs map { run =>
9696
val ids = symbols.functions.keys.toSeq
97-
val analysis = Try(Await.result(run(ids, symbols, filterSymbols = true), Duration.Inf))
98-
99-
analysis match {
100-
case Success(analysis) =>
101-
RunReport(run)(analysis.toReport)
102-
103-
case Failure(err) =>
104-
val msg = s"Run has failed with error: $err\n\n" + err.getStackTrace.map(_.toString).mkString("\n")
105-
reporter.fatalError(msg)
106-
}
97+
val analysis = Await.result(run(ids, symbols, filterSymbols = true), Duration.Inf)
98+
RunReport(run)(analysis.toReport)
10799
}
108100

109101
report = Report(reports)

core/src/main/scala/stainless/frontend/SplitCallBack.scala

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,8 @@ class SplitCallBack(components: Seq[Component])(override implicit val context: i
176176
// Dispatch a task to the executor service instead of blocking this thread.
177177
val componentReports: Seq[Future[RunReport]] = {
178178
runs map { run =>
179-
Try(run(id, syms)) match {
180-
case Success(future) =>
181-
val runReport = future map { a =>
182-
RunReport(run)(a.toReport): RunReport
183-
}
184-
runReport
185-
186-
case Failure(err) =>
187-
val msg = s"Run has failed with error: $err\n\n" +
188-
err.getStackTrace.map(_.toString).mkString("\n")
189-
190-
reporter.fatalError(msg)
179+
run(id, syms) map { a =>
180+
RunReport(run)(a.toReport): RunReport
191181
}
192182
}
193183
}

core/src/main/scala/stainless/package.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ package object stainless {
108108
}
109109
}
110110

111-
def topLevelErrorHandler[T](e: Throwable)(implicit ctx: inox.Context): T = {
112-
ctx.reporter.error("Stainless terminated with an error.")
111+
def topLevelErrorHandler(e: Throwable)(implicit ctx: inox.Context): Nothing = {
112+
ctx.reporter.error(s"Stainless terminated with an error.")
113113

114114
val sw = new StringWriter
115115
e.printStackTrace(new PrintWriter(sw))
@@ -119,6 +119,8 @@ package object stainless {
119119

120120
if (ctx.options.findOptionOrDefault(frontend.optPrintStackTrace))
121121
ctx.reporter.error(sw.toString)
122+
else
123+
ctx.reporter.error("You may use the option --print-trace to have the stack trace displayed in the output.")
122124

123125
System.exit(2)
124126
??? // unreachable

core/src/main/scala/stainless/termination/MeasureInference.scala

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,20 @@ trait MeasureInference
99
extends extraction.CachingPhase
1010
with extraction.SimplyCachedSorts
1111
with extraction.IdentitySorts
12-
with extraction.SimpleFunctions
13-
with extraction.SimplyCachedFunctions { self =>
12+
with extraction.SimpleFunctions { self =>
1413

1514
val s: Trees
1615
val t: Trees
1716
import s._
1817

1918
import context.{options, timers, reporter}
2019

20+
// Measure inference depends on functions that are mutually recursive with `fd`,
21+
// so we include all dependencies in the key calculation
22+
override protected final val funCache = new ExtractionCache[s.FunDef, FunctionResult]((fd, context) =>
23+
getDependencyKey(fd.id)(context.symbols)
24+
)
25+
2126
val sizes: SizeFunctions { val trees: s.type } = new {
2227
val trees: s.type = self.s
2328
} with SizeFunctions
@@ -54,14 +59,26 @@ trait MeasureInference
5459
}
5560
}
5661

57-
def needsMeasure(fd: FunDef): Boolean = symbols.isRecursive(fd.id) &&
58-
fd.measure(symbols).isEmpty &&
59-
symbols.dependencies(fd.id).forall(id =>
60-
symbols.lookupFunction(id).forall(fd2 =>
61-
!symbols.dependencies(fd2.id).contains(fd.id) ||
62-
fd2.measure(symbols).isEmpty
63-
)
64-
)
62+
def needsMeasure(fd: FunDef): Boolean = {
63+
if (symbols.isRecursive(fd.id) && fd.measure(symbols).isEmpty) {
64+
symbols.dependencies(fd.id).find(id =>
65+
symbols.lookupFunction(id).exists(fd2 =>
66+
symbols.dependencies(fd2.id).contains(fd.id) &&
67+
!fd2.measure(symbols).isEmpty
68+
)
69+
) match {
70+
case None =>
71+
true
72+
case Some(id) =>
73+
reporter.fatalError(fd.getPos,
74+
s"""Function ${fd.id} has no measure annotated, but mutually recursive function ${id} has one.
75+
|Please annotated both with a measure, or none for measure inference.""".stripMargin
76+
)
77+
}
78+
} else {
79+
false
80+
}
81+
}
6582

6683
def inferMeasure(original: FunDef): FunDef = measureCache.get(original) match {
6784
case Some(measure) =>

0 commit comments

Comments
 (0)