Skip to content

Commit 4e38a03

Browse files
Fix debug print of QuoteMatcher to work on match failure (#18023)
The current logic of debug print in `QuoteMatcher` is intended to show debug information when a pattern match fails. However, it does not work because `notMatched` invokes a global escape that skips debug-print logic. This PR proposes to catch global escape when `debug=1` and show debug information.
2 parents 18f355d + be0c98a commit 4e38a03

File tree

3 files changed

+33
-26
lines changed

3 files changed

+33
-26
lines changed

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,6 @@ private sealed trait YSettings:
400400
val YinstrumentDefs: Setting[Boolean] = BooleanSetting("-Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.")
401401

402402
val YforceInlineWhileTyping: Setting[Boolean] = BooleanSetting("-Yforce-inline-while-typing", "Make non-transparent inline methods inline when typing. Emulates the old inlining behavior of 3.0.0-M3.")
403+
404+
val YdebugMacros: Setting[Boolean] = BooleanSetting("-Ydebug-macros", "Show debug info when quote pattern match fails")
403405
end YSettings

compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,9 @@ import dotty.tools.dotc.util.optional
102102
*
103103
* ```
104104
*/
105-
object QuoteMatcher {
105+
class QuoteMatcher(debug: Boolean) {
106106
import tpd.*
107107

108-
// TODO use flag from Context. Maybe -debug or add -debug-macros
109-
private inline val debug = false
110-
111108
/** Sequence of matched expressions.
112109
* These expressions are part of the scrutinee and will be bound to the quote pattern term splices.
113110
*/
@@ -134,7 +131,6 @@ object QuoteMatcher {
134131
given Env = Map.empty
135132
scrutinee =?= pat1
136133
}.map { matchings =>
137-
import QuoteMatcher.MatchResult.*
138134
lazy val spliceScope = SpliceScope.getCurrent
139135
// After matching and doing all subtype checks, we have to approximate all the type bindings
140136
// that we have found, seal them in a quoted.Type and add them to the result
@@ -234,7 +230,7 @@ object QuoteMatcher {
234230
case _ => None
235231
end TypeTreeTypeTest
236232

237-
val res = pattern match
233+
def runMatch(): optional[MatchingExprs] = pattern match
238234

239235
/* Term hole */
240236
// Match a scala.internal.Quoted.patternHole typed as a repeated argument and return the scrutinee tree
@@ -463,24 +459,32 @@ object QuoteMatcher {
463459
// No Match
464460
case _ =>
465461
notMatched
462+
end runMatch
463+
464+
if debug then
465+
try {
466+
runMatch()
467+
} catch {
468+
case e: util.boundary.Break[?] =>
469+
val quotes = QuotesImpl()
470+
println(
471+
s""">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
472+
|Scrutinee
473+
| ${scrutinee.show}
474+
|did not match pattern
475+
| ${pattern.show}
476+
|
477+
|with environment: ${summon[Env]}
478+
|
479+
|Scrutinee: ${quotes.reflect.Printer.TreeStructure.show(scrutinee.asInstanceOf)}
480+
|Pattern: ${quotes.reflect.Printer.TreeStructure.show(pattern.asInstanceOf)}
481+
|
482+
|""".stripMargin)
483+
throw e
484+
}
485+
else
486+
runMatch()
466487

467-
if (debug && res == notMatched)
468-
val quotes = QuotesImpl()
469-
println(
470-
s""">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
471-
|Scrutinee
472-
| ${scrutinee.show}
473-
|did not match pattern
474-
| ${pattern.show}
475-
|
476-
|with environment: ${summon[Env]}
477-
|
478-
|Scrutinee: ${quotes.reflect.Printer.TreeStructure.show(scrutinee.asInstanceOf)}
479-
|Pattern: ${quotes.reflect.Printer.TreeStructure.show(pattern.asInstanceOf)}
480-
|
481-
|""".stripMargin)
482-
483-
res
484488
end =?=
485489

486490
end extension

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
4141
import tpd.*
4242

4343
private val xCheckMacro: Boolean = ctx.settings.XcheckMacros.value
44+
private val yDebugMacro: Boolean = ctx.settings.YdebugMacros.value
4445

4546
extension [T](self: scala.quoted.Expr[T])
4647
def show: String =
4748
reflect.Printer.TreeCode.show(reflect.asTerm(self))
4849

4950
def matches(that: scala.quoted.Expr[Any]): Boolean =
50-
QuoteMatcher.treeMatch(reflect.asTerm(self), reflect.asTerm(that)).nonEmpty
51+
QuoteMatcher(yDebugMacro).treeMatch(reflect.asTerm(self), reflect.asTerm(that)).nonEmpty
5152

5253
def valueOrAbort(using fromExpr: FromExpr[T]): T =
5354
def reportError =
@@ -3168,14 +3169,14 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
31683169
def unapply[TypeBindings, Tup <: Tuple](scrutinee: scala.quoted.Expr[Any])(using pattern: scala.quoted.Expr[Any]): Option[Tup] =
31693170
val scrutineeTree = reflect.asTerm(scrutinee)
31703171
val patternTree = reflect.asTerm(pattern)
3171-
QuoteMatcher.treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
3172+
QuoteMatcher(yDebugMacro).treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
31723173
end ExprMatch
31733174

31743175
object TypeMatch extends TypeMatchModule:
31753176
def unapply[TypeBindings, Tup <: Tuple](scrutinee: scala.quoted.Type[?])(using pattern: scala.quoted.Type[?]): Option[Tup] =
31763177
val scrutineeTree = reflect.TypeTree.of(using scrutinee)
31773178
val patternTree = reflect.TypeTree.of(using pattern)
3178-
QuoteMatcher.treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
3179+
QuoteMatcher(yDebugMacro).treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
31793180
end TypeMatch
31803181

31813182
end QuotesImpl

0 commit comments

Comments
 (0)