Skip to content

Commit

Permalink
Improve trace for TASTy without valid line numbers
Browse files Browse the repository at this point in the history
Ref: #18882
  • Loading branch information
liufengyun committed Nov 15, 2023
1 parent 8cb4945 commit dde0a0c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 26 deletions.
30 changes: 14 additions & 16 deletions compiler/src/dotty/tools/dotc/transform/init/Objects.scala
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ object Objects:
case Some(theValue) =>
theValue
case _ =>
report.warning("[Internal error] Value not found " + x.show + "\nenv = " + data.show + ". Calling trace:\n" + Trace.show, Trace.position)
report.warning("[Internal error] Value not found " + x.show + "\nenv = " + data.show + ". " + Trace.show, Trace.position)
Bottom

def getVal(x: Symbol)(using data: Data, ctx: Context): Option[Value] = data.getVal(x)
Expand Down Expand Up @@ -619,7 +619,7 @@ object Objects:
def call(value: Value, meth: Symbol, args: List[ArgInfo], receiver: Type, superType: Type, needResolve: Boolean = true): Contextual[Value] = log("call " + meth.show + ", this = " + value.show + ", args = " + args.map(_.value.show), printer, (_: Value).show) {
value match
case Cold =>
report.warning("Using cold alias. Calling trace:\n" + Trace.show, Trace.position)
report.warning("Using cold alias. " + Trace.show, Trace.position)
Bottom

case Bottom =>
Expand Down Expand Up @@ -781,15 +781,15 @@ object Objects:
errorReadOtherStaticObject(State.currentObject, addr.owner)
Bottom
else if ref.isObjectRef && ref.klass.hasSource then
report.warning("Access uninitialized field " + field.show + ". Call trace: " + Trace.show, Trace.position)
report.warning("Access uninitialized field " + field.show + ". " + Trace.show, Trace.position)
Bottom
else
// initialization error, reported by the initialization checker
Bottom
else if ref.hasVal(target) then
ref.valValue(target)
else if ref.isObjectRef && ref.klass.hasSource then
report.warning("Access uninitialized field " + field.show + ". Call trace: " + Trace.show, Trace.position)
report.warning("Access uninitialized field " + field.show + ". " + Trace.show, Trace.position)
Bottom
else
// initialization error, reported by the initialization checker
Expand Down Expand Up @@ -836,7 +836,7 @@ object Objects:
report.warning("[Internal error] unexpected tree in assignment, array = " + arr.show + Trace.show, Trace.position)

case Cold =>
report.warning("Assigning to cold aliases is forbidden. Calling trace:\n" + Trace.show, Trace.position)
report.warning("Assigning to cold aliases is forbidden. " + Trace.show, Trace.position)

case Bottom =>

Expand All @@ -851,7 +851,7 @@ object Objects:
else
Heap.writeJoin(addr, rhs)
else
report.warning("Mutating a field before its initialization: " + field.show + ". Calling trace:\n" + Trace.show, Trace.position)
report.warning("Mutating a field before its initialization: " + field.show + ". " + Trace.show, Trace.position)
end match

Bottom
Expand Down Expand Up @@ -936,7 +936,7 @@ object Objects:
Bottom
end if
case _ =>
report.warning("[Internal error] Variable not found " + sym.show + "\nenv = " + env.show + ". Calling trace:\n" + Trace.show, Trace.position)
report.warning("[Internal error] Variable not found " + sym.show + "\nenv = " + env.show + ". " + Trace.show, Trace.position)
Bottom
else
given Env.Data = env
Expand All @@ -948,17 +948,17 @@ object Objects:
given Env.Data = fun.env
eval(fun.code, fun.thisV, fun.klass)
case Cold =>
report.warning("Calling cold by-name alias. Call trace: \n" + Trace.show, Trace.position)
report.warning("Calling cold by-name alias. " + Trace.show, Trace.position)
Bottom
case _: ValueSet | _: Ref | _: OfArray =>
report.warning("[Internal error] Unexpected by-name value " + value.show + ". Calling trace:\n" + Trace.show, Trace.position)
report.warning("[Internal error] Unexpected by-name value " + value.show + ". " + Trace.show, Trace.position)
Bottom
else
value

case _ =>
if isByNameParam(sym) then
report.warning("Calling cold by-name alias. Call trace: \n" + Trace.show, Trace.position)
report.warning("Calling cold by-name alias. " + Trace.show, Trace.position)
Bottom
else
Cold
Expand All @@ -983,10 +983,10 @@ object Objects:
else
Heap.writeJoin(addr, value)
case _ =>
report.warning("[Internal error] Variable not found " + sym.show + "\nenv = " + env.show + ". Calling trace:\n" + Trace.show, Trace.position)
report.warning("[Internal error] Variable not found " + sym.show + "\nenv = " + env.show + ". " + Trace.show, Trace.position)

case _ =>
report.warning("Assigning to variables in outer scope. Calling trace:\n" + Trace.show, Trace.position)
report.warning("Assigning to variables in outer scope. " + Trace.show, Trace.position)

Bottom
}
Expand Down Expand Up @@ -1715,15 +1715,13 @@ object Objects:
def errorMutateOtherStaticObject(currentObj: ClassSymbol, otherObj: ClassSymbol)(using Trace, Context) =
val msg =
s"Mutating ${otherObj.show} during initialization of ${currentObj.show}.\n" +
"Mutating other static objects during the initialization of one static object is forbidden. " +
"Calling trace:\n" + Trace.show
"Mutating other static objects during the initialization of one static object is forbidden. " + Trace.show

report.warning(msg, Trace.position)

def errorReadOtherStaticObject(currentObj: ClassSymbol, otherObj: ClassSymbol)(using Trace, Context) =
val msg =
"Reading mutable state of " + otherObj.show + " during initialization of " + currentObj.show + ".\n" +
"Reading mutable state of other static objects is forbidden as it breaks initialization-time irrelevance. " +
"Calling trace: " + Trace.show
"Reading mutable state of other static objects is forbidden as it breaks initialization-time irrelevance. " + Trace.show

report.warning(msg, Trace.position)
28 changes: 18 additions & 10 deletions compiler/src/dotty/tools/dotc/transform/init/Trace.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@ object Trace:

val empty: Trace = Vector.empty

val EMPTY_PADDING = " "
val CONNECTING_INDENT = "\u2502 " // "| "
val CHILD = "\u251c\u2500\u2500 " // "|-- "
val LAST_CHILD = "\u2514\u2500\u2500 " // "\-- "

extension (trace: Trace)
def add(node: Tree): Trace = trace :+ node
def toVector: Vector[Tree] = trace
def ++(trace2: Trace): Trace = trace ++ trace2

def show(using trace: Trace, ctx: Context): String = buildStacktrace(trace, "\n")
def show(using trace: Trace, ctx: Context): String = buildStacktrace(trace, "Calling trace:" + System.lineSeparator())

def position(using trace: Trace): Tree = trace.last

Expand All @@ -41,8 +46,8 @@ object Trace:
var lastLineNum = -1
var lines: mutable.ArrayBuffer[String] = new mutable.ArrayBuffer
trace.foreach { tree =>
val isLastTraceItem = tree `eq` trace.last
val pos = tree.sourcePos
val prefix = "-> "
val line =
if pos.source.exists then
val loc = "[ " + pos.source.file.name + ":" + (pos.line + 1) + " ]"
Expand All @@ -52,19 +57,22 @@ object Trace:
tree match
case defDef: DefTree =>
// The definition can be huge, avoid printing the whole definition.
defDef.symbol.show
defDef.symbol.showFullName
case _ =>
tree.show
tree.show.split(System.lineSeparator(), 2).nn.head.nn

val positionMarkerLine =
if pos.exists && pos.source.exists then
positionMarker(pos)
else ""
(if isLastTraceItem then EMPTY_PADDING else CONNECTING_INDENT)+ positionMarker(pos)
else
""

// always use the more precise trace location
if lastLineNum == pos.line then
if lastLineNum >= 0 && lastLineNum == pos.line then
lines.dropRightInPlace(1)

lines += (prefix + line + "\n" + positionMarkerLine)
val prefix = if isLastTraceItem then LAST_CHILD else CHILD
lines += (prefix + line + System.lineSeparator() + positionMarkerLine)

lastLineNum = pos.line
}
Expand All @@ -78,10 +86,10 @@ object Trace:
*/
private def positionMarker(pos: SourcePosition): String =
val trimmed = pos.source.lineContent(pos.start).takeWhile(c => c.isWhitespace).length
val padding = pos.startColumnPadding.substring(trimmed).nn + " "
val padding = pos.startColumnPadding.substring(trimmed).nn
val carets =
if (pos.startLine == pos.endLine)
"^" * math.max(1, pos.endColumn - pos.startColumn)
else "^"

s"$padding$carets\n"
s"$padding$carets" + System.lineSeparator()

0 comments on commit dde0a0c

Please sign in to comment.