diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 4294e55da470..8e66ccd6fb0f 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -447,18 +447,20 @@ private class ExtractDependenciesCollector extends tpd.TreeTraverser { thisTreeT private abstract class TypeDependencyTraverser(using Context) extends TypeTraverser() { protected def addDependency(symbol: Symbol): Unit - val seen = new mutable.HashSet[Type] + // Avoid cycles by remembering both the types (testcase: + // tests/run/enum-values.scala) and the symbols of named types (testcase: + // tests/pos-java-interop/i13575) we've seen before. + val seen = new mutable.HashSet[Symbol | Type] def traverse(tp: Type): Unit = if (!seen.contains(tp)) { seen += tp tp match { case tp: NamedType => val sym = tp.symbol - if (!sym.is(Package)) { + if !seen.contains(sym) && !sym.is(Package) then + seen += sym addDependency(sym) - if (!sym.isClass) - traverse(tp.info) + if !sym.isClass then traverse(tp.info) traverse(tp.prefix) - } case tp: ThisType => traverse(tp.underlying) case tp: ConstantType => diff --git a/tests/pos-java-interop/i13575/Builder.java b/tests/pos-java-interop/i13575/Builder.java new file mode 100644 index 000000000000..a267a21ffd6a --- /dev/null +++ b/tests/pos-java-interop/i13575/Builder.java @@ -0,0 +1,16 @@ +package com.lamoroso.example; + +import java.util.Collections; +import java.util.List; + +public abstract class Builder, R> { + + private List pools; + + public Builder withPool(String... pools) { + Collections.addAll(this.pools, pools); + return this; + } + + public Builder build(){return null;} +} \ No newline at end of file diff --git a/tests/pos-java-interop/i13575/Client.java b/tests/pos-java-interop/i13575/Client.java new file mode 100644 index 000000000000..a5b19d39d1f0 --- /dev/null +++ b/tests/pos-java-interop/i13575/Client.java @@ -0,0 +1,9 @@ +package com.lamoroso.example; + +public class Client { + + public static Builder builder() { + return null; + } + +} diff --git a/tests/pos-java-interop/i13575/RestClient.java b/tests/pos-java-interop/i13575/RestClient.java new file mode 100644 index 000000000000..feba30c8ac35 --- /dev/null +++ b/tests/pos-java-interop/i13575/RestClient.java @@ -0,0 +1,15 @@ +package com.lamoroso.example; + +public class RestClient { + + private Object instance; + + public RestClient(Object instance) { + this.instance = instance; + } + + public static RestClientBuilder builder() { + return new RestClientBuilder(); + } + +} diff --git a/tests/pos-java-interop/i13575/RestClientBuilder.java b/tests/pos-java-interop/i13575/RestClientBuilder.java new file mode 100644 index 000000000000..65907b157be7 --- /dev/null +++ b/tests/pos-java-interop/i13575/RestClientBuilder.java @@ -0,0 +1,19 @@ +package com.lamoroso.example; + +public class RestClientBuilder, R> { + + private Builder wrappedBuilder; + + protected RestClientBuilder() { + this.wrappedBuilder = Client.builder(); + } + + public RestClientBuilder withPool(String... pools) { + this.wrappedBuilder.withPool(pools); + return this; + } + + public RestClient build() { + return new RestClient(wrappedBuilder.build()); + } +} \ No newline at end of file diff --git a/tests/pos-java-interop/i13575/ScalaApp.scala b/tests/pos-java-interop/i13575/ScalaApp.scala new file mode 100644 index 000000000000..230940384f97 --- /dev/null +++ b/tests/pos-java-interop/i13575/ScalaApp.scala @@ -0,0 +1,5 @@ +package com.lamoroso.example + +object ScalaApp extends App { + RestClient.builder().withPool("hello").build() +}