Skip to content

Commit 40cf56b

Browse files
committed
wip
1 parent 6f5bb34 commit 40cf56b

File tree

6 files changed

+78
-6
lines changed

6 files changed

+78
-6
lines changed

compiler/src/dotty/tools/dotc/core/ContextOps.scala

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,45 @@ import Contexts._, Symbols._, Types._, Flags._
55
import Denotations._, SymDenotations._
66
import Names.Name, StdNames.nme
77
import ast.untpd
8+
import scala.util.control.NonFatal
89

910
/** Extension methods for contexts where we want to keep the ctx.<methodName> syntax */
1011
object ContextOps:
11-
12+
case class Implosion(ex: Throwable) extends Exception(ex)
1213
extension (ctx: Context)
14+
/** Crash somewhat gracefully, reporting useful info.*/
15+
def implode(message: => Any, ex: Throwable): Nothing = {
16+
ex match
17+
case NonFatal(Implosion(_)) => throw ex // avoid implosions all the way down, ideally we should avoid catching Implosions in the first place
18+
case NonFatal(ex) =>
19+
given Context = ctx
20+
report.error(
21+
s"""|An unhandled exception was thrown in the compiler. Please file a crash
22+
|report here: https://github.com/lampepfl/dotty/issues/new/choose
23+
|
24+
|Exception: ${ex.getClass}
25+
| message: ${ex.getMessage()}
26+
| cause: ${ex.getCause()}
27+
| (truncated) stack trace:
28+
| ${ex.getStackTrace().take(10).mkString("\n ")}
29+
|Sources:
30+
| ${ctx.base.sources.keysIterator.mkString("\n ")}
31+
|Files:
32+
| ${ctx.base.files.keysIterator.mkString("\n ")}
33+
|Context:
34+
| phase: ${ctx.phase}
35+
| owner: ${ctx.owner}
36+
| unit: ${ctx.compilationUnit}
37+
| mode: ${ctx.mode}
38+
| source: ${ctx.source}:${ctx.tree.sourcePos.line + 1}:${ctx.tree.sourcePos.column + 1}
39+
| ${ctx.tree}
40+
|
41+
|""".stripMargin,
42+
ctx.tree.sourcePos)
43+
44+
throw Implosion(ex)
45+
case _ => throw ex
46+
}
1347

1448
/** Enter symbol into current class, if current class is owner of current context,
1549
* or into current scope, if not. Should always be called instead of scope.enter

compiler/src/dotty/tools/dotc/core/Phases.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import typer.ImportInfo.withRootImports
2121
import ast.{tpd, untpd}
2222
import scala.annotation.internal.sharable
2323
import scala.util.control.NonFatal
24+
import dotty.tools.dotc.core.ContextOps.*
25+
2426

2527
object Phases {
2628

@@ -323,7 +325,7 @@ object Phases {
323325
val unitCtx = ctx.fresh.setPhase(this.start).setCompilationUnit(unit).withRootImports
324326
try run(using unitCtx)
325327
catch case ex: Throwable =>
326-
println(s"$ex while running $phaseName on $unit")
328+
unitCtx.implode(i"$ex while running $phaseName on $unit", ex)
327329
throw ex
328330
unitCtx.compilationUnit
329331
}

compiler/src/dotty/tools/dotc/report.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ object report:
7373
error(msg.toMessage, pos)
7474

7575
def error(msg: => String)(using Context): Unit =
76-
error(msg, NoSourcePosition)
76+
error(msg, NoSourcePosition) //why default to NoSourcePosition? Surely the caller should be encouraged to at least think about the position and specify NoSourcePosition if no sane position exists
7777

7878
def error(ex: TypeError, pos: SrcPos)(using Context): Unit =
7979
val fullPos = addInlineds(pos)

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import ContextFunctionResults._
3434
import ExplicitOuter._
3535
import core.Mode
3636
import util.Property
37+
import util.Assert.assert
3738
import reporting._
3839

3940
class Erasure extends Phase with DenotTransformer {

compiler/src/dotty/tools/dotc/typer/ReTyper.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package typer
33

44
import core._
55
import Contexts._
6+
import ContextOps._
67
import Types._
78
import Symbols._
89
import StdNames._
@@ -126,9 +127,11 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking
126127
try super.typedUnadapted(tree, pt, locked)
127128
catch {
128129
case NonFatal(ex) =>
129-
if ctx.phase != Phases.typerPhase && ctx.phase != Phases.inliningPhase then
130-
println(i"exception while typing $tree of class ${tree.getClass} # ${tree.uniqueId}")
131-
throw ex
130+
131+
val message = if ctx.phase != Phases.typerPhase && ctx.phase != Phases.inliningPhase then
132+
i"exception while typing $tree of class ${tree.getClass} # ${tree.uniqueId}"
133+
else ""
134+
ctx.implode(message, ex)
132135
}
133136

134137
override def inlineExpansion(mdef: DefDef)(using Context): List[Tree] = mdef :: Nil
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package dotty.tools.dotc.util
2+
3+
import scala.quoted.*
4+
import dotty.tools.dotc.core.Contexts.*
5+
import dotty.tools.dotc.core.ContextOps.implode
6+
7+
object Assert{
8+
9+
inline def assert(inline expr: Boolean, inline message: => Any = "")(using inline ctx: Context): Unit =
10+
${ Assert.assertImpl('expr, 'message, 'ctx) }
11+
12+
def assertImpl(expr: Expr[Boolean], message: Expr[Any], ctx: Expr[Context])(using qctx: Quotes):Expr[Unit] = {
13+
import qctx.reflect.*
14+
val pos = Position.ofMacroExpansion
15+
val position = s"${pos.sourceFile.path}:${pos.startLine + 1}:${pos.startColumn +1}"
16+
'{
17+
if !$expr then {
18+
val expression = ${Expr(expr.asTerm.show(using Printer.TreeAnsiCode))}
19+
val pos = ${Expr(position)}
20+
val err = AssertionError(
21+
s"""failed assertion at $pos
22+
|predicate
23+
| $expression
24+
|was false
25+
|${$message}"
26+
""".stripMargin
27+
)
28+
${ctx}.implode(${message}, err)
29+
}
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)