From 0872740a0fa324a8e60e171dd7f8dcce87961d52 Mon Sep 17 00:00:00 2001 From: Hamza Remmal Date: Thu, 27 Nov 2025 22:51:56 +0100 Subject: [PATCH] fix: look at the underlying of a TermRef for a getter --- .../tools/dotc/transform/GenericSignatures.scala | 10 ++++++++++ tests/run/i24553.check | 11 +++++++++++ tests/run/i24553.scala | 8 ++++++++ 3 files changed, 29 insertions(+) create mode 100644 tests/run/i24553.check create mode 100644 tests/run/i24553.scala diff --git a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala index a882ed8f41c2..e7a852745e4c 100644 --- a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala +++ b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala @@ -246,6 +246,16 @@ object GenericSignatures { jsig(erasedUnderlying, toplevel = toplevel, unboxedVCs = unboxedVCs) else typeParamSig(ref.paramName.lastPart) + case ref: TermRef if ref.symbol.isGetter => + // If the type of a val is a TermRef to another val, generating the generic signature + // based on the underlying type will produce the type `scala.Function0` + // The reason behind this is that during the `getters` phase, the same symbol will now + // refer to the getter where the type will be now `=> `. + // Since the TermRef originally intended to capture the underlying type of a `val`, + // we recover that information by directly checking the resultType of the getter. + // See `tests/run/i24553.scala` for an example + jsig(ref.info.resultType, toplevel = toplevel, unboxedVCs = unboxedVCs) + case ref: SingletonType => // Singleton types like `x.type` need to be widened to their underlying type // For example, `def identity[A](x: A): x.type` should have signature diff --git a/tests/run/i24553.check b/tests/run/i24553.check new file mode 100644 index 000000000000..8b8b6648a406 --- /dev/null +++ b/tests/run/i24553.check @@ -0,0 +1,11 @@ +public boolean java.lang.Object.equals(java.lang.Object) +public final native java.lang.Class java.lang.Object.getClass() +public native int java.lang.Object.hashCode() +public int Foo.hello() +public final native void java.lang.Object.notify() +public final native void java.lang.Object.notifyAll() +public java.lang.String java.lang.Object.toString() +public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException +public final void java.lang.Object.wait() throws java.lang.InterruptedException +public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException +public int Foo.x() diff --git a/tests/run/i24553.scala b/tests/run/i24553.scala new file mode 100644 index 000000000000..910c287c5c7f --- /dev/null +++ b/tests/run/i24553.scala @@ -0,0 +1,8 @@ +// scalajs: --skip +class Foo: + val hello = 1337 + val x: hello.type = ??? + +@main def Test = + val mtds = classOf[Foo].getMethods().sortBy(_.getName()) + for mtd <- mtds do println(mtd.toGenericString())