Skip to content

Commit 4785cc4

Browse files
committed
Find trait local static forwarder
1 parent e3288d2 commit 4785cc4

File tree

4 files changed

+58
-13
lines changed

4 files changed

+58
-13
lines changed

modules/unpickler/src/main/scala/ch/epfl/scala/debugadapter/internal/stacktrace/Patterns.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ object Patterns:
3636
def unapply(method: binary.Method): Option[String] =
3737
"""(.*)\$lzyINIT\d+""".r.unapplySeq(NameTransformer.decode(method.name)).map(xs => xs(0).stripSuffix("$"))
3838

39+
object TraitLocalStaticForwarder:
40+
def unapply(method: binary.Method): Option[Seq[String]] =
41+
if method.isTraitStaticForwarder then method.extractFromDecodedNames("(.+)\\$\\d+\\$".r)(_(0))
42+
else None
43+
3944
object TraitStaticForwarder:
4045
def unapply(method: binary.Method): Option[Seq[String]] =
4146
if method.isTraitStaticForwarder then Some(method.unexpandedDecodedNames.map(_.stripSuffix("$")))

modules/unpickler/src/main/scala/ch/epfl/scala/debugadapter/internal/stacktrace/Scala3Unpickler.scala

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import tastyquery.SourceLanguage
2020
import tastyquery.Traversers.TreeTraverser
2121
import scala.collection.mutable.Buffer
2222
import ch.epfl.scala.debugadapter.internal.binary.Instruction
23+
import ch.epfl.scala.debugadapter.internal.stacktrace.Patterns.TraitStaticForwarder
2324

2425
class Scala3Unpickler(
2526
classpaths: Array[Path],
@@ -113,16 +114,8 @@ class Scala3Unpickler(
113114
.orFind { case Patterns.ByNameArgProxy() => findByNameArgsProxy(binaryClass, method) }
114115
.orFind { case Patterns.SuperArg() => requiresBinaryClass(findSuperArgs(_, method)) }
115116
.orFind { case Patterns.LiftedTree() => findLiftedTry(binaryClass, method) }
116-
.orFind { case Patterns.LocalMethod(names) =>
117-
val localMethods = collectLocalMethods(binaryClass, method)(inlined => {
118-
case term if names.contains(term.nameStr) && matchSignature(method, term, checkTypeErasure = !inlined) =>
119-
BinaryMethod(binaryClass, term)
120-
})
121-
val anonTraitParamGetters =
122-
if names.contains("x") then requiresBinaryClass(findInstanceMethods(_, method))
123-
else Seq.empty
124-
localMethods ++ anonTraitParamGetters
125-
}
117+
.orFind { case Patterns.TraitLocalStaticForwarder(names) => findTraitLocalStaticForwarder(method) }
118+
.orFind { case Patterns.LocalMethod(names) => findLocalMethods(binaryClass, method, names) }
126119
.orFind { case Patterns.LazyInit(name) => requiresBinaryClass(findLazyInit(_, name)) }
127120
.orFind { case Patterns.Outer(_) => Seq(findOuter(binaryClass)) }
128121
.orFind { case Patterns.TraitInitializer() => requiresBinaryClass(findTraitInitializer(_, method)) }
@@ -426,6 +419,30 @@ class Scala3Unpickler(
426419
// figure out and split findMethodsFromTraits in 2
427420
fromClass.orIfEmpty(findBridgesAndMixinForwarders(binaryClass, method))
428421

422+
private def findTraitLocalStaticForwarder(method: binary.Method): Seq[BinaryMethodSymbol] =
423+
method.instructions
424+
.collect {
425+
case Instruction.Method(_, owner, name, descriptor, _) if method.declaringClass.name == owner =>
426+
method.declaringClass.method(name, descriptor)
427+
}
428+
.flatten
429+
.singleOpt
430+
.toSeq
431+
.map { binaryTarget =>
432+
val target = findMethod(binaryTarget)
433+
BinaryTraitStaticForwarder(target)
434+
}
435+
436+
private def findLocalMethods(
437+
binaryClass: BinaryClassSymbol,
438+
method: binary.Method,
439+
names: Seq[String]
440+
): Seq[BinaryMethodSymbol] =
441+
collectLocalMethods(binaryClass, method)(inlined => {
442+
case term if names.contains(term.nameStr) && matchSignature(method, term, checkTypeErasure = !inlined) =>
443+
BinaryMethod(binaryClass, term)
444+
})
445+
429446
private def findLazyInit(binaryClass: BinaryClass, name: String): Seq[BinaryMethodSymbol] =
430447
val matcher: PartialFunction[Symbol, TermSymbol] =
431448
case sym: TermSymbol if sym.isModuleOrLazyVal && sym.nameStr == name => sym

modules/unpickler/src/test/scala/ch/epfl/scala/debugadapter/internal/stacktrace/Scala3UnpicklerStats.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,22 @@ class Scala3UnpicklerStats extends munit.FunSuite:
5151

5252
for
5353
cls <- loadClasses(jars, "scala3-compiler_3-3.3.0", binaryClassLoader)
54-
// if cls.name == "dotty.tools.dotc.reporting.MissingImplicitArgument"
54+
// if cls.name == "dotty.tools.dotc.core.Types$TermLambda"
5555
clsSym <- cls match
5656
case Patterns.LocalClass(_, _, _) => unpickler.tryFind(cls, localClassCounter)
5757
case Patterns.AnonClass(_, _) => unpickler.tryFind(cls, anonClassCounter)
5858
case Patterns.InnerClass(_) => unpickler.tryFind(cls, innerClassCounter)
5959
case _ => unpickler.tryFind(cls, topLevelClassCounter)
6060
method <- cls.declaredMethods
61-
// if method.name == "dotty$tools$dotc$reporting$ShowMatchTrace$$super$msgPostscript"
61+
// if method.name == "dotty$tools$dotc$core$Types$TermLambda$$_$compute$1$"
6262
do
6363
method match
6464
case Patterns.AnonFun(_) => unpickler.tryFind(method, anonFunCounter)
6565
case Patterns.AdaptedAnonFun(_) => unpickler.tryFind(method, adaptedAnonFunCounter)
6666
case Patterns.LocalLazyInit(_) => unpickler.tryFind(method, localLazyInitCounter)
6767
case Patterns.LocalMethod(_) => unpickler.tryFind(method, localMethodCounter)
6868
case _ => unpickler.tryFind(method, methodCounter)
69+
localMethodCounter.printNotFound()
6970
methodCounter.printNotFound()
7071
localClassCounter.printReport()
7172
anonClassCounter.printReport()
@@ -84,7 +85,7 @@ class Scala3UnpicklerStats extends munit.FunSuite:
8485
checkCounter(anonFunCounter, 6649, expectedAmbiguous = 331, expectedNotFound = 5)
8586
checkCounter(adaptedAnonFunCounter, 288, expectedAmbiguous = 83)
8687
checkCounter(localLazyInitCounter, 108)
87-
checkCounter(methodCounter, 57743, expectedAmbiguous = 128, expectedNotFound = 1)
88+
checkCounter(methodCounter, 57744, expectedAmbiguous = 128)
8889

8990
def checkCounter(
9091
counter: Counter,

modules/unpickler/src/test/scala/ch/epfl/scala/debugadapter/internal/stacktrace/Scala3UnpicklerTests.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,6 +1680,28 @@ abstract class Scala3UnpicklerTests(val scalaVersion: ScalaVersion) extends FunS
16801680
)
16811681
}
16821682

1683+
test("trait local static forwarder") {
1684+
val source =
1685+
"""|package example
1686+
|
1687+
|trait A:
1688+
| val x: String
1689+
| private def m1 =
1690+
| class B:
1691+
| def m2 = m3
1692+
| def m3: String = x + x
1693+
| ()
1694+
|""".stripMargin
1695+
val debuggee = TestingDebuggee.mainClass(source, "example", scalaVersion)
1696+
debuggee.assertFormat(
1697+
"example.A",
1698+
"java.lang.String example$A$$_$m3$1$(example.A $this)",
1699+
"A.m1.m3.<static forwarder>: String",
1700+
skip = true,
1701+
loadExtraInfo = true
1702+
)
1703+
}
1704+
16831705
extension (debuggee: TestingDebuggee)
16841706
private def loader(loadExtraInfo: Boolean): JavaReflectLoader =
16851707
new JavaReflectLoader(debuggee.classLoader, loadExtraInfo = loadExtraInfo)

0 commit comments

Comments
 (0)