From 646e62ec8102090b4d946f994a3f7669e4bc644b Mon Sep 17 00:00:00 2001 From: i10416 Date: Sat, 24 Feb 2024 15:13:58 +0900 Subject: [PATCH] fix: cannot find Scala companion module from Java To find Scala companion mudule from Java, we should strip module suffix `$`. This provides workaround for #17255, but it requires some refinment to fully fix it because not-fully-qualified type like the following example still fails to compile due to missing symbol. ```java package example; public class Bar { private static final Foo$ MOD = Foo$.MODULE; } ``` This is because `pre` in `javaFindMember` for `Foo` in the case above is ``, not `example` and therefore `pre.findMember` looks for `.Foo` instead of `example.Foo`. I'm not sure whether the qualifier is intentionally dropped. --- .../dotty/tools/dotc/core/ContextOps.scala | 22 +++++++++++++------ .../test/dotc/pos-test-pickling.blacklist | 1 + tests/pos/i17255/Bar.java | 6 +++++ tests/pos/i17255/Foo.scala | 5 +++++ 4 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 tests/pos/i17255/Bar.java create mode 100644 tests/pos/i17255/Foo.scala diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index 55fb31fd1916..0511271a5d65 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -55,11 +55,18 @@ object ContextOps: final def javaFindMember(name: Name, pre: Type, lookInCompanion: Boolean, required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags): Denotation = assert(ctx.isJava) inContext(ctx) { - + import dotty.tools.dotc.core.NameOps.* val preSym = pre.typeSymbol // 1. Try to search in current type and parents. - val directSearch = pre.findMember(name, pre, required, excluded) + val directSearch = + if name.isTypeName && name.endsWith(StdNames.str.MODULE_SUFFIX) then + pre.findMember(name.stripModuleClassSuffix, pre, required, excluded) match + case NoDenotation => NoDenotation + case k: SymDenotation => + k.companionModule.denot + else + pre.findMember(name, pre, required, excluded) // 2. Try to search in companion class if current is an object. def searchCompanionClass = if lookInCompanion && preSym.is(Flags.Module) then @@ -81,11 +88,12 @@ object ContextOps: val pre1 = bc.companionModule.namedType pre1.findMember(name, pre1, required, excluded) }.find(_.exists).getOrElse(NoDenotation) - - if preSym.isClass then - directSearch orElse searchCompanionClass orElse searchSuperCompanionObjects - else - directSearch + val result = + if preSym.isClass then + directSearch orElse searchCompanionClass orElse searchSuperCompanionObjects + else + directSearch + result } /** A fresh local context with given tree and owner. diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index b0da78f0a1eb..32f8cdef1386 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -29,6 +29,7 @@ i16649-irrefutable.scala strict-pattern-bindings-3.0-migration.scala i17186b.scala i11982a.scala +i17255 # Tree is huge and blows stack for printing Text i7034.scala diff --git a/tests/pos/i17255/Bar.java b/tests/pos/i17255/Bar.java new file mode 100644 index 000000000000..35269af2179f --- /dev/null +++ b/tests/pos/i17255/Bar.java @@ -0,0 +1,6 @@ +package example; + + +public class Bar { + private static final example.Foo$ MOD = example.Foo$.MODULE$; +} \ No newline at end of file diff --git a/tests/pos/i17255/Foo.scala b/tests/pos/i17255/Foo.scala new file mode 100644 index 000000000000..9608b43b430f --- /dev/null +++ b/tests/pos/i17255/Foo.scala @@ -0,0 +1,5 @@ +package example + +case class Foo(i: Int) + +object Foo \ No newline at end of file