Skip to content

Commit dd65e1a

Browse files
committed
Show stacktrace for errors
1 parent 4f298c0 commit dd65e1a

File tree

2 files changed

+36
-28
lines changed

2 files changed

+36
-28
lines changed

compiler/src/dotty/tools/dotc/transform/init/Checker.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Checker extends MiniPhase {
6464
import semantic._
6565
val addr = Addr(cls, outer = Hot)
6666
heap(addr) = Objekt(cls, Map.empty, Map(cls -> Hot))
67-
val res = addr.call(cls.primaryConstructor, superType = NoType, tree)
67+
val res = addr.call(cls.primaryConstructor, superType = NoType, tree)(using ctx, Vector.empty)
6868
res.errors.foreach(_.issue)
6969
}
7070

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import StdNames._
1010

1111
import ast.tpd._
1212
import util.SourcePosition
13-
import config.Printers.{ init => printer }
14-
import reporting.trace
13+
import config.Printers.init as printer
14+
import reporting.trace as log
1515

1616
import Errors._
1717
import Util._
@@ -118,24 +118,32 @@ class Semantic {
118118

119119
def +(error: Error): Result = this.copy(errors = this.errors :+ error)
120120

121-
def ensureHot(msg: String, source: Tree): Result =
121+
def ensureHot(msg: String, source: Tree)(using Trace): Result =
122122
if value == Hot then this
123123
else
124124
// TODO: define a new error
125-
this + PromoteCold(source, Vector(source))
125+
this + PromoteCold(source, trace)
126126

127-
def select(f: Symbol, source: Tree)(using Context): Result =
127+
def select(f: Symbol, source: Tree)(using Context, Trace): Result =
128128
value.select(f, source) ++ errors
129129

130-
def call(meth: Symbol, superType: Type, source: Tree)(using Context): Result =
130+
def call(meth: Symbol, superType: Type, source: Tree)(using Context, Trace): Result =
131131
value.call(meth, superType, source) ++ errors
132132

133-
def instantiate(klass: ClassSymbol, ctor: Symbol, source: Tree)(using Context): Result =
133+
def instantiate(klass: ClassSymbol, ctor: Symbol, source: Tree)(using Context, Trace): Result =
134134
value.instantiate(klass, ctor, source) ++ errors
135135
}
136136

137+
// ----- Error Handling -----------------------------------
138+
type Trace = Vector[Tree]
139+
137140
val noErrors = Nil
138141

142+
extension (trace: Trace)
143+
def add(node: Tree): Trace = trace :+ node
144+
145+
def trace(using t: Trace): Trace = t
146+
139147
// ----- Operations on domains -----------------------------
140148
extension (a: Value)
141149
def join(b: Value): Value =
@@ -157,21 +165,21 @@ class Semantic {
157165
def join: Value = values.reduce { (v1, v2) => v1.join(v2) }
158166

159167
extension (value: Value)
160-
def select(f: Symbol, source: Tree)(using Context): Result =
168+
def select(f: Symbol, source: Tree)(using Context, Trace): Result =
161169
value match {
162170
case Hot =>
163171
Result(Hot, noErrors)
164172

165173
case Cold =>
166-
val error = AccessCold(f, source, Vector(source))
174+
val error = AccessCold(f, source, trace)
167175
Result(Hot, error :: Nil)
168176

169177
case addr: Addr =>
170178
val obj = heap(addr)
171179
if obj.fields.contains(f) then
172180
Result(obj.fields(f), Nil)
173181
else
174-
val error = AccessNonInit(f, Vector(source))
182+
val error = AccessNonInit(f, trace.add(source))
175183
Result(Hot, error :: Nil)
176184

177185
case _: Fun =>
@@ -184,13 +192,13 @@ class Semantic {
184192
Result(value2, errors)
185193
}
186194

187-
def call(meth: Symbol, superType: Type, source: Tree)(using Context): Result =
195+
def call(meth: Symbol, superType: Type, source: Tree)(using Context, Trace): Result =
188196
value match {
189197
case Hot =>
190198
Result(Hot, noErrors)
191199

192200
case Cold =>
193-
val error = CallCold(meth, source, Vector(source))
201+
val error = CallCold(meth, source, trace)
194202
Result(Hot, error :: Nil)
195203

196204
case addr: Addr =>
@@ -208,13 +216,13 @@ class Semantic {
208216
val rhs = target.defTree.asInstanceOf[DefDef].rhs
209217
eval(rhs, addr, target.owner.asClass)
210218
else
211-
val error = CallUnknown(target, source, Vector(source))
219+
val error = CallUnknown(target, source, trace)
212220
Result(Hot, error :: Nil)
213221
else
214222
if obj.fields.contains(target) then
215223
Result(obj.fields(target), Nil)
216224
else
217-
val error = AccessNonInit(target, Vector(source))
225+
val error = AccessNonInit(target, trace.add(source))
218226
Result(Hot, error :: Nil)
219227

220228
case Fun(body, thisV, klass) =>
@@ -229,13 +237,13 @@ class Semantic {
229237
Result(value2, errors)
230238
}
231239

232-
def instantiate(klass: ClassSymbol, ctor: Symbol, source: Tree)(using Context): Result =
240+
def instantiate(klass: ClassSymbol, ctor: Symbol, source: Tree)(using Context, Trace): Result =
233241
value match {
234242
case Hot =>
235243
Result(Hot, noErrors)
236244

237245
case Cold =>
238-
val error = CallCold(ctor, source, Vector(source))
246+
val error = CallCold(ctor, source, trace)
239247
Result(Hot, error :: Nil)
240248

241249
case addr: Addr =>
@@ -276,7 +284,7 @@ class Semantic {
276284
*
277285
* This method only handles cache logic and delegates the work to `cases`.
278286
*/
279-
def eval(expr: Tree, thisV: Value, klass: ClassSymbol)(using Context): Result = trace("evaluating " + expr.show, printer, res => res.asInstanceOf[Result].show) {
287+
def eval(expr: Tree, thisV: Value, klass: ClassSymbol)(using Context, Trace): Result = log("evaluating " + expr.show, printer, res => res.asInstanceOf[Result].show) {
280288
val cfg = Config(thisV, expr.sourcePos)
281289
if (cache.contains(cfg)) Result(cache(cfg), noErrors)
282290
else {
@@ -292,14 +300,14 @@ class Semantic {
292300
}
293301

294302
/** Evaluate a list of expressions */
295-
def eval(exprs: List[Tree], thisV: Value, klass: ClassSymbol)(using Context): List[Result] =
303+
def eval(exprs: List[Tree], thisV: Value, klass: ClassSymbol)(using Context, Trace): List[Result] =
296304
exprs.map { expr => eval(expr, thisV, klass) }
297305

298306
/** Handles the evaluation of different expressions
299307
*
300308
* Note: Recursive call should go to `eval` instead of `cases`.
301309
*/
302-
def cases(expr: Tree, thisV: Value, klass: ClassSymbol)(using Context): Result =
310+
def cases(expr: Tree, thisV: Value, klass: ClassSymbol)(using Context, Trace): Result =
303311
expr match {
304312
case Ident(nme.WILDCARD) =>
305313
// TODO: disallow `var x: T = _`
@@ -333,11 +341,11 @@ class Semantic {
333341
case Select(supert: Super, _) =>
334342
val SuperType(thisTp, superTp) = supert.tpe
335343
val thisValue2 = resolveThis(thisTp.classSymbol.asClass, thisV, klass)
336-
Result(thisValue2, errors).call(ref.symbol, superTp, expr)
344+
Result(thisValue2, errors).call(ref.symbol, superTp, expr)(using ctx, trace.add(expr))
337345

338346
case Select(qual, _) =>
339347
val res = eval(qual, thisV, klass) ++ errors
340-
res.call(ref.symbol, superType = NoType, source = expr)
348+
res.call(ref.symbol, superType = NoType, source = expr)(using ctx, trace.add(expr))
341349

342350
case id: Ident =>
343351
id.tpe match
@@ -349,10 +357,10 @@ class Semantic {
349357
case Hot => Result(Hot, errors)
350358
case _ =>
351359
val rhs = id.symbol.defTree.asInstanceOf[DefDef].rhs
352-
eval(rhs, thisValue2, enclosingClass)
360+
eval(rhs, thisValue2, enclosingClass)(using ctx, trace.add(expr))
353361
case TermRef(prefix, _) =>
354362
val res = cases(prefix, thisV, klass, id) ++ errors
355-
res.call(id.symbol, superType = NoType, source = expr)
363+
res.call(id.symbol, superType = NoType, source = expr)(using ctx, trace.add(expr))
356364

357365
case Select(qualifier, name) =>
358366
eval(qualifier, thisV, klass).select(expr.symbol, expr)
@@ -463,7 +471,7 @@ class Semantic {
463471
}
464472

465473
/** Handle semantics of leaf nodes */
466-
def cases(tp: Type, thisV: Value, klass: ClassSymbol, source: Tree)(using Context): Result = trace("evaluating " + tp.show, printer, res => res.asInstanceOf[Result].show) {
474+
def cases(tp: Type, thisV: Value, klass: ClassSymbol, source: Tree)(using Context, Trace): Result = log("evaluating " + tp.show, printer, res => res.asInstanceOf[Result].show) {
467475
tp match {
468476
case _: ConstantType =>
469477
Result(Hot, noErrors)
@@ -495,7 +503,7 @@ class Semantic {
495503
}
496504

497505
/** Resolve C.this that appear in `klass` */
498-
def resolveThis(target: ClassSymbol, thisV: Value, klass: ClassSymbol)(using Context): Value = trace("resolving " + target.show + ", this = " + thisV.show + " in " + klass.show, printer, res => res.asInstanceOf[Value].show) {
506+
def resolveThis(target: ClassSymbol, thisV: Value, klass: ClassSymbol)(using Context, Trace): Value = log("resolving " + target.show + ", this = " + thisV.show + " in " + klass.show, printer, res => res.asInstanceOf[Value].show) {
499507
if target == klass then thisV
500508
else
501509
thisV match
@@ -508,7 +516,7 @@ class Semantic {
508516
}
509517

510518
/** Compute the outer value that correspond to `tref.prefix` */
511-
def outerValue(tref: TypeRef, thisV: Value, klass: ClassSymbol, source: Tree)(using Context): Result =
519+
def outerValue(tref: TypeRef, thisV: Value, klass: ClassSymbol, source: Tree)(using Context, Trace): Result =
512520
val cls = tref.classSymbol.asClass
513521
if (tref.prefix == NoPrefix) then
514522
val enclosing = cls.owner.lexicallyEnclosingClass.asClass
@@ -518,7 +526,7 @@ class Semantic {
518526
cases(tref.prefix, thisV, klass, source)
519527

520528
/** Initialize part of an abstract object in `klass` of the inheritance chain */
521-
def init(klass: ClassSymbol, thisV: Addr)(using Context): Result = trace("init " + klass.show, printer, res => res.asInstanceOf[Result].show) {
529+
def init(klass: ClassSymbol, thisV: Addr)(using Context, Trace): Result = log("init " + klass.show, printer, res => res.asInstanceOf[Result].show) {
522530
val errorBuffer = new mutable.ArrayBuffer[Error]
523531

524532
val tpl = klass.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]

0 commit comments

Comments
 (0)