Skip to content

Add documentation to debug missing position crash #6582

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions compiler/src/dotty/tools/dotc/ast/Positioned.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import core.Flags.{JavaDefined, Extension}
import core.StdNames.nme
import annotation.constructorOnly
import annotation.internal.sharable
import reporting.Reporter

import java.io.{ PrintWriter }

/** A base class for things that have positions (currently: modifiers and trees)
*/
Expand All @@ -24,13 +27,11 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Pro
def uniqueId: Int = myUniqueId

def uniqueId_=(id: Int): Unit = {
if (Positioned.debugId == id) {
def printTrace() = {
val stack = Thread.currentThread().getStackTrace().map("> " + _)
System.err.println(stack.mkString(s"> Debug tree (id=${Positioned.debugId}) creation \n> $this\n", "\n", "\n"))
}
printTrace()
def printTrace() = {
println(s"Debug tree (id=${Positioned.debugId}) creation \n$this\n")
Reporter.displayPrompt(Console.in, new PrintWriter(Console.err, true))
}
if (Positioned.debugId == id) printTrace()
myUniqueId = id
}

Expand Down
25 changes: 1 addition & 24 deletions compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ConsoleReporter(
val didPrint = m match {
case m: Error =>
printMessage(messageAndPos(m.contained(), m.pos, diagnosticLevel(m)))
if (ctx.settings.Xprompt.value) displayPrompt()
if (ctx.settings.Xprompt.value) Reporter.displayPrompt(reader, writer)
true
case m: ConditionalWarning if !m.enablingOption.value =>
false
Expand All @@ -40,28 +40,5 @@ class ConsoleReporter(
printMessage("\nlonger explanation available when compiling with `-explain`")
}

/** Show prompt if `-Xprompt` is passed as a flag to the compiler */
def displayPrompt(): Unit = {
writer.println()
writer.print("a)bort, s)tack, r)esume: ")
writer.flush()
if (reader != null) {
def loop(): Unit = reader.read match {
case 'a' | 'A' =>
new Throwable().printStackTrace(writer)
System.exit(1)
case 's' | 'S' =>
new Throwable().printStackTrace(writer)
writer.println()
writer.flush()
case 'r' | 'R' =>
()
case _ =>
loop()
}
loop()
}
}

override def flush()(implicit ctx: Context): Unit = { writer.flush() }
}
28 changes: 27 additions & 1 deletion compiler/src/dotty/tools/dotc/reporting/Reporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import core.Contexts._
import util.{SourcePosition, NoSourcePosition}
import core.Decorators.PhaseListDecorator
import collection.mutable
import java.lang.System.currentTimeMillis
import core.Mode
import dotty.tools.dotc.core.Symbols.{Symbol, NoSymbol}
import diagnostic.messages._
import diagnostic._
import ast.{tpd, Trees}
import Message._

import java.lang.System.currentTimeMillis
import java.io.{ BufferedReader, PrintWriter }


object Reporter {
/** Convert a SimpleReporter into a real Reporter */
def fromSimpleReporter(simple: interfaces.SimpleReporter): Reporter =
Expand All @@ -37,6 +40,29 @@ object Reporter {

private val defaultIncompleteHandler: ErrorHandler =
(mc, ctx) => ctx.reporter.report(mc)(ctx)

/** Show prompt if `-Xprompt` is passed as a flag to the compiler */
def displayPrompt(reader: BufferedReader, writer: PrintWriter): Unit = {
writer.println()
writer.print("a)bort, s)tack, r)esume: ")
writer.flush()
if (reader != null) {
def loop(): Unit = reader.read match {
case 'a' | 'A' =>
new Throwable().printStackTrace(writer)
System.exit(1)
case 's' | 'S' =>
new Throwable().printStackTrace(writer)
writer.println()
writer.flush()
case 'r' | 'R' =>
()
case _ =>
loop()
}
loop()
}
}
}

trait Reporting { this: Context =>
Expand Down
32 changes: 32 additions & 0 deletions docs/docs/internals/debug-macros.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
layout: doc-page
title: "Debug Macros"
---

Complex macros may break invariants of the compiler, which leads to compiler crashes.
Here we lists common compiler crashes and how to deal with them.

## position not set

For this problem, here is the log that is usually shown:

```
[error] assertion failed: position not set for org.scalactic.anyvals.PosZInt.+$extension3(SizeParam.this.minSize)(
[error] org.scalactic.anyvals.PosZInt.widenToInt(SizeParam.this.sizeRange)
[error] ) # 2326942 of class dotty.tools.dotc.ast.Trees$Apply in library/src-bootstrapped/scala/tasty/reflect/utils/TreeUtils.scala
```

To debug why the position is not set, note the tree id `2326942`, and enable
the following compiler option:

```
-Ydebug-tree-with-id 2326942
```

With the option above, the compiler will crash when the tree is created. From
the stack trace, we will be able to figure out where the tree is created.

If the position is in the compiler, then either report a compiler bug or
fix the problem with `.withSpan(tree.span)`. The following fix is an example:

- https://github.com/lampepfl/dotty/pull/6581
2 changes: 2 additions & 0 deletions docs/sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ sidebar:
url: docs/internals/type-system.html
- title: "Dotty Internals 1: Trees & Symbols (Meeting Notes)"
url: docs/internals/dotty-internals-1-notes.html
- title: Debug Macros
url: docs/internals/debug-macros.html
- title: Resources
subsection:
- title: Talks
Expand Down