From f77069a74c4df65c7f69a6476aeb6b52fa8acb48 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Fri, 10 Feb 2023 15:36:06 +0100 Subject: [PATCH] ClassfileParser: Avoid cycle when accessing companion in inner class lookup Previously, the call to `info` on the module val could lead to a cycle since the module val might be in the process of being completed. This commit fixes this by only using the module class which is all we need to lookup members. Fixes #15288. Fixes #14059. Co-Authored-By: Tom Grigg --- .../tools/dotc/core/classfile/ClassfileParser.scala | 8 ++++---- sbt-test/java-compat/i15288/QueryRequest.java | 9 +++++++++ sbt-test/java-compat/i15288/Test.scala | 2 ++ sbt-test/java-compat/i15288/build.sbt | 1 + sbt-test/java-compat/i15288/test | 5 +++++ 5 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 sbt-test/java-compat/i15288/QueryRequest.java create mode 100644 sbt-test/java-compat/i15288/Test.scala create mode 100644 sbt-test/java-compat/i15288/build.sbt create mode 100644 sbt-test/java-compat/i15288/test diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 7702e6a93446..eeeb3767bd34 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -1086,10 +1086,10 @@ class ClassfileParser( if (sym == classRoot.symbol) staticScope.lookup(name) else { - var module = sym.companionModule - if (!module.exists && sym.isAbsent()) - module = sym.scalacLinkedClass - module.info.member(name).symbol + var moduleClass = sym.registeredCompanion + if (!moduleClass.exists && sym.isAbsent()) + moduleClass = sym.scalacLinkedClass + moduleClass.info.member(name).symbol } else if (sym == classRoot.symbol) instanceScope.lookup(name) diff --git a/sbt-test/java-compat/i15288/QueryRequest.java b/sbt-test/java-compat/i15288/QueryRequest.java new file mode 100644 index 000000000000..e43487e09449 --- /dev/null +++ b/sbt-test/java-compat/i15288/QueryRequest.java @@ -0,0 +1,9 @@ +interface CopyableBuilder {} +interface ToCopyableBuilder {} + +public class QueryRequest implements ToCopyableBuilder { + public static Builder builder() { throw new UnsupportedOperationException(); } + public interface Builder extends CopyableBuilder { + void build(); + } +} diff --git a/sbt-test/java-compat/i15288/Test.scala b/sbt-test/java-compat/i15288/Test.scala new file mode 100644 index 000000000000..e03617ac4c33 --- /dev/null +++ b/sbt-test/java-compat/i15288/Test.scala @@ -0,0 +1,2 @@ +class Test: + def makeQuery = QueryRequest.builder().build() diff --git a/sbt-test/java-compat/i15288/build.sbt b/sbt-test/java-compat/i15288/build.sbt new file mode 100644 index 000000000000..63e314982c41 --- /dev/null +++ b/sbt-test/java-compat/i15288/build.sbt @@ -0,0 +1 @@ +scalaVersion := sys.props("plugin.scalaVersion") diff --git a/sbt-test/java-compat/i15288/test b/sbt-test/java-compat/i15288/test new file mode 100644 index 000000000000..ad1a8a5987ee --- /dev/null +++ b/sbt-test/java-compat/i15288/test @@ -0,0 +1,5 @@ +## This could just be a pos test checked by FromTastyTests, but +## ParallelTesting#compileTastyInDir does not support test with multiple files +## currently. +> compile +> doc