diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index 110659bba3ee..046b649941b1 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -16,6 +16,7 @@ import core.Decorators._ import config.{SourceVersion, Feature} import StdNames.nme import scala.annotation.internal.sharable +import scala.util.control.NoStackTrace import transform.MacroAnnotations class CompilationUnit protected (val source: SourceFile) { @@ -105,7 +106,7 @@ class CompilationUnit protected (val source: SourceFile) { object CompilationUnit { - class SuspendException extends Exception + class SuspendException extends Exception with NoStackTrace /** Make a compilation unit for top class `clsd` with the contents of the `unpickled` tree */ def apply(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(using Context): CompilationUnit = diff --git a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala index f46bb779bf55..24a207da6836 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala @@ -12,10 +12,22 @@ import Denotations._ import Decorators._ import reporting._ import ast.untpd -import config.Printers.cyclicErrors +import config.Printers.{cyclicErrors, noPrinter} + +import scala.annotation.constructorOnly abstract class TypeError(using creationContext: Context) extends Exception(""): + /** Will the stack trace of this exception be filled in? + * This is expensive and only useful for debugging purposes. + */ + def computeStackTrace: Boolean = + ctx.debug || (cyclicErrors != noPrinter && this.isInstanceOf[CyclicReference] && !(ctx.mode is Mode.CheckCyclic)) + + override def fillInStackTrace(): Throwable = + if computeStackTrace then super.fillInStackTrace().nn + else this + /** Convert to message. This takes an additional Context, so that we * use the context when the message is first produced, i.e. when the TypeError * is handled. This makes a difference for CyclicErrors since we need to know @@ -164,7 +176,7 @@ class CyclicReference private (val denot: SymDenotation)(using Context) extends object CyclicReference: def apply(denot: SymDenotation)(using Context): CyclicReference = val ex = new CyclicReference(denot) - if !(ctx.mode is Mode.CheckCyclic) || ctx.settings.Ydebug.value then + if ex.computeStackTrace then cyclicErrors.println(s"Cyclic reference involving! $denot") val sts = ex.getStackTrace.asInstanceOf[Array[StackTraceElement]] for (elem <- sts take 200)