Skip to content

Add trace.force back #11181

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 2 commits into from
Jan 22, 2021
Merged
Changes from 1 commit
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
29 changes: 21 additions & 8 deletions compiler/src/dotty/tools/dotc/reporting/trace.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,39 @@ import config.Config
import config.Printers
import core.Mode

object trace extends TraceSyntax:
inline def isForced: false = false
protected val doForceTrace = isForced

object force extends TraceSyntax:
inline def isForced: true = true
protected val doForceTrace = isForced
end trace

/** This module is carefully optimized to give zero overhead if Config.tracingEnabled
* is false. The `trace` operation is called in various hotspots, so every tiny bit
* of overhead is unacceptable: boxing, closures, additional method calls are all out.
*/
object trace:
trait TraceSyntax:

inline def isForced: Boolean
protected val doForceTrace: Boolean

inline def onDebug[TD](inline question: String)(inline op: TD)(using Context): TD =
conditionally(ctx.settings.YdebugTrace.value, question, false)(op)

inline def conditionally[TC](inline cond: Boolean, inline question: String, inline show: Boolean)(inline op: TC)(using Context): TC =
if Config.tracingEnabled then
inline if isForced || Config.tracingEnabled then
apply(question, if cond then Printers.default else Printers.noPrinter, show)(op)
else op

inline def apply[T](inline question: String, inline printer: Printers.Printer, inline showOp: Any => String)(inline op: T)(using Context): T =
if Config.tracingEnabled then
inline if isForced || Config.tracingEnabled then
doTrace[T](question, printer, showOp)(op)
else op

inline def apply[T](inline question: String, inline printer: Printers.Printer, inline show: Boolean)(inline op: T)(using Context): T =
if Config.tracingEnabled then
inline if isForced || Config.tracingEnabled then
doTrace[T](question, printer, if show then showShowable(_) else alwaysToString)(op)
else op

Expand All @@ -50,7 +62,7 @@ object trace:
printer: Printers.Printer = Printers.default,
showOp: Any => String = alwaysToString)
(op: => T)(using Context): T =
if ctx.mode.is(Mode.Printing) || (printer eq Printers.noPrinter) then op
if ctx.mode.is(Mode.Printing) || !doForceTrace && (printer eq Printers.noPrinter) then op
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am against having an override for printers. trace.force with default arguments gives you a printer anyway. If you want another printer, just enable it in Printers.scala. One way to do things.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that printers are orthogonal to what trace.force is trying to enable.

What I really want to be able to do is to tell students "to see information about GADT constraints, force this trace". And "if you need even more information, force this one as well". If the students were required to also enable the corresponding printers, that wouldn't give them any useful information - in fact, it'd just drown them in irrelevant information from the typer printer.

So what I'm trying to illustrate with that example is that I want something which allows forcing a specific trace to be printed out without doing anything else, and that something is trace.force.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I see the workflow better now. So the idea is that to enable a specific trace, you just replace the trace with trace.force. Makes sense.

else
// Avoid evaluating question multiple time, since each evaluation
// may cause some extra logging output.
Expand All @@ -61,18 +73,19 @@ object trace:
var logctx = ctx
while logctx.reporter.isInstanceOf[StoreReporter] do logctx = logctx.outer
def margin = ctx.base.indentTab * ctx.base.indent
def doLog(s: String) = if doForceTrace then println(s) else report.log(s)
def finalize(result: Any, note: String) =
if !finalized then
ctx.base.indent -= 1
report.log(s"$margin${trailing(result)}$note")
doLog(s"$margin${trailing(result)}$note")
finalized = true
try
report.log(s"$margin$leading")
doLog(s"$margin$leading")
ctx.base.indent += 1
val res = op
finalize(res, "")
res
catch case ex: Throwable =>
finalize("<missing>", s" (with exception $ex)")
throw ex
end trace
end TraceSyntax