diff --git a/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala b/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala index 06a064860ac4..654fa94693c6 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala @@ -245,11 +245,12 @@ object QuoteMatcher { ref match case Select(qual1, _) => qual1 =?= qual2 case ref: Ident => - ref.tpe match - case TermRef(qual: TermRef, _) => tpd.ref(qual) =?= qual2 - case TermRef(qual: ThisType, _) if qual.classSymbol.is(Module, butNot = Package) => - tpd.ref(qual.classSymbol.companionModule) =?= qual2 - case _ => matched + if qual2.existsSubTree(_.symbol == defn.QuotedRuntimePatterns_patternHole) then + // Prefix has a hole, so we need to match the prefix to extract the value of the hole + tpd.desugarIdentPrefix(ref) =?= qual2 + else + matched + /* Match reference */ case _: Ident if symbolMatch(scrutinee, pattern) => matched /* Match type */ diff --git a/tests/run-custom-args/tasty-inspector/i14788.scala b/tests/run-custom-args/tasty-inspector/i14788.scala new file mode 100644 index 000000000000..29af31386499 --- /dev/null +++ b/tests/run-custom-args/tasty-inspector/i14788.scala @@ -0,0 +1,55 @@ + +import scala.quoted.* +import scala.tasty.inspector.Inspector +import scala.tasty.inspector.Tasty +import scala.tasty.inspector.TastyInspector +import scala.reflect.ClassTag + +import scala.quoted.* +import scala.tasty.inspector.* + +@main def Test: Unit = { + // Artefact of the current test infrastructure + // TODO improve infrastructure to avoid needing this code on each test + val classpath = dotty.tools.dotc.util.ClasspathFromClassloader(this.getClass.getClassLoader).split(java.io.File.pathSeparator).find(_.contains("runWithCompiler")).get + val allTastyFiles = dotty.tools.io.Path(classpath).walkFilter(_.extension == "tasty").map(_.toString).toList + val tastyFiles = allTastyFiles.filter(_.contains("MySeq")) + + TastyInspector.inspectTastyFiles(tastyFiles)(new MyInspector) +} + +class MySeq(override val length: Int) extends collection.Seq[String] { + def foo: Int = length // error + + def apply(v1: Int): String = ??? + def iterator: Iterator[String] = ??? +} + +class MyInspector extends Inspector { + def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit = { + import quotes.reflect.* + val traverser = new TreeTraverser { + override def traverseTree(tree: Tree)(owner: Symbol): Unit = { + if (tree.isExpr) { + try { + tree.asExpr match { + case '{ ($x: collection.Seq[t]).length } => + super.traverseTree(tree)(owner) + case _ => + super.traverseTree(tree)(owner) + } + } catch { + case e => + report.error(s"unexpected error ${e}", tree.pos) + throw e + } + } else { + super.traverseTree(tree)(owner) + } + } + } + tastys.foreach{ tasty => + traverser.traverseTree(tasty.ast)(tasty.ast.symbol) + } + } +}