Skip to content

Refine error messages for early promotion #15263

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 11 commits into from
May 25, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
48 changes: 21 additions & 27 deletions compiler/src/dotty/tools/dotc/transform/init/Errors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ import util.SourcePosition
import Decorators._, printing.SyntaxHighlighting
import Types._, Symbols._, Contexts._

object Errors {
type Errors = Seq[Error]
val empty: Errors = Nil

def show(errs: Errors)(using Context): String =
errs.map(_.show).mkString(", ")
import scala.collection.mutable

object Errors:
sealed trait Error {
def source: Tree
def trace: Seq[Tree]
Expand All @@ -24,11 +20,12 @@ object Errors {
def issue(using Context): Unit =
report.warning(show + stacktrace, source.srcPos)

def toErrors: Errors = this :: Nil
private def isTraceInformative: Boolean =
trace.size > 1 || trace.size == 1 && trace.head.ne(source)

def stacktrace(using Context): String = if (trace.isEmpty) "" else " Calling trace:\n" + {
var last: String = ""
val sb = new StringBuilder
def stacktrace(using Context): String = if !isTraceInformative then "" else " Calling trace:\n" + {
var lastLineNum = -1
var lines: mutable.ArrayBuffer[String] = new mutable.ArrayBuffer
trace.foreach { tree =>
val pos = tree.sourcePos
val prefix = "-> "
Expand All @@ -44,10 +41,16 @@ object Errors {
positionMarker(pos)
else ""

if (last != line) sb.append(prefix + line + "\n" + positionMarkerLine )
// always use the more precise trace location
if lastLineNum == pos.line then
lines.dropRightInPlace(1)

last = line
lines += (prefix + line + "\n" + positionMarkerLine)

lastLineNum = pos.line
}
val sb = new StringBuilder
for line <- lines do sb.append(line)
sb.toString
}

Expand All @@ -65,13 +68,6 @@ object Errors {
s"$padding$carets\n"
}

/** Flatten UnsafePromotion errors
*/
def flatten: Errors = this match {
case unsafe: UnsafePromotion => unsafe.errors.flatMap(_.flatten)
case _ => this :: Nil
}

override def toString() = this.getClass.getName.nn
}

Expand All @@ -85,9 +81,9 @@ object Errors {
report.warning(show + stacktrace, field.srcPos)
}

/** Promote `this` under initialization to fully-initialized */
/** Promote a value under initialization to fully-initialized */
case class PromoteError(msg: String, source: Tree, trace: Seq[Tree]) extends Error {
def show(using Context): String = "Cannot prove that the value is fully initialized. " + msg + "."
def show(using Context): String = msg
}

case class AccessCold(field: Symbol, source: Tree, trace: Seq[Tree]) extends Error {
Expand All @@ -107,16 +103,14 @@ object Errors {
}

/** Promote a value under initialization to fully-initialized */
case class UnsafePromotion(msg: String, source: Tree, trace: Seq[Tree], errors: Errors) extends Error {
assert(errors.nonEmpty)
case class UnsafePromotion(msg: String, source: Tree, trace: Seq[Tree], error: Error) extends Error {
override def issue(using Context): Unit =
report.warning(show, source.srcPos)

def show(using Context): String = {
var index = 0
"Cannot prove that the value is fully initialized. " + msg + ".\n" + stacktrace +
"\nThe unsafe promotion may cause the following problem:\n" +
errors.head.show + errors.head.stacktrace
msg + stacktrace + "\n" +
"Promoting the value to fully initialized failed due to the following problem:\n" +
error.show + error.stacktrace
}
}
}
Loading