diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 8ea78f935efe..8a3097521f02 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -397,5 +397,7 @@ private sealed trait YSettings: val YinstrumentDefs: Setting[Boolean] = BooleanSetting("-Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.") 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.") + + val YdebugMacros: Setting[Boolean] = BooleanSetting("-Ydebug-macros", "Show debug info when quote pattern match fails") end YSettings diff --git a/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala b/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala index 31678a9481e4..29d02be60c4a 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala @@ -102,12 +102,9 @@ import dotty.tools.dotc.util.optional * * ``` */ -object QuoteMatcher { +class QuoteMatcher(debug: Boolean) { import tpd.* - // TODO use flag from Context. Maybe -debug or add -debug-macros - private inline val debug = false - /** Sequence of matched expressions. * These expressions are part of the scrutinee and will be bound to the quote pattern term splices. */ @@ -134,7 +131,6 @@ object QuoteMatcher { given Env = Map.empty scrutinee =?= pat1 }.map { matchings => - import QuoteMatcher.MatchResult.* lazy val spliceScope = SpliceScope.getCurrent // After matching and doing all subtype checks, we have to approximate all the type bindings // that we have found, seal them in a quoted.Type and add them to the result @@ -234,7 +230,7 @@ object QuoteMatcher { case _ => None end TypeTreeTypeTest - val res = pattern match + def runMatch(): optional[MatchingExprs] = pattern match /* Term hole */ // Match a scala.internal.Quoted.patternHole typed as a repeated argument and return the scrutinee tree @@ -426,24 +422,32 @@ object QuoteMatcher { // No Match case _ => notMatched + end runMatch + + if debug then + try { + runMatch() + } catch { + case e: util.boundary.Break[?] => + val quotes = QuotesImpl() + println( + s""">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + |Scrutinee + | ${scrutinee.show} + |did not match pattern + | ${pattern.show} + | + |with environment: ${summon[Env]} + | + |Scrutinee: ${quotes.reflect.Printer.TreeStructure.show(scrutinee.asInstanceOf)} + |Pattern: ${quotes.reflect.Printer.TreeStructure.show(pattern.asInstanceOf)} + | + |""".stripMargin) + throw e + } + else + runMatch() - if (debug && res == notMatched) - val quotes = QuotesImpl() - println( - s""">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - |Scrutinee - | ${scrutinee.show} - |did not match pattern - | ${pattern.show} - | - |with environment: ${summon[Env]} - | - |Scrutinee: ${quotes.reflect.Printer.TreeStructure.show(scrutinee.asInstanceOf)} - |Pattern: ${quotes.reflect.Printer.TreeStructure.show(pattern.asInstanceOf)} - | - |""".stripMargin) - - res end =?= end extension diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 68fb646fe2bb..7648d38c84b2 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -39,13 +39,14 @@ object QuotesImpl { class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler, QuoteMatching: private val xCheckMacro: Boolean = ctx.settings.XcheckMacros.value + private val yDebugMacro: Boolean = ctx.settings.YdebugMacros.value extension [T](self: scala.quoted.Expr[T]) def show: String = reflect.Printer.TreeCode.show(reflect.asTerm(self)) def matches(that: scala.quoted.Expr[Any]): Boolean = - QuoteMatcher.treeMatch(reflect.asTerm(self), reflect.asTerm(that)).nonEmpty + QuoteMatcher(yDebugMacro).treeMatch(reflect.asTerm(self), reflect.asTerm(that)).nonEmpty def valueOrAbort(using fromExpr: FromExpr[T]): T = def reportError = @@ -3155,14 +3156,14 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def unapply[TypeBindings, Tup <: Tuple](scrutinee: scala.quoted.Expr[Any])(using pattern: scala.quoted.Expr[Any]): Option[Tup] = val scrutineeTree = reflect.asTerm(scrutinee) val patternTree = reflect.asTerm(pattern) - QuoteMatcher.treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]] + QuoteMatcher(yDebugMacro).treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]] end ExprMatch object TypeMatch extends TypeMatchModule: def unapply[TypeBindings, Tup <: Tuple](scrutinee: scala.quoted.Type[?])(using pattern: scala.quoted.Type[?]): Option[Tup] = val scrutineeTree = reflect.TypeTree.of(using scrutinee) val patternTree = reflect.TypeTree.of(using pattern) - QuoteMatcher.treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]] + QuoteMatcher(yDebugMacro).treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]] end TypeMatch end QuotesImpl