From 621fe41b17d99e1917b4aeb24679aea1590e8b52 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Mar 2024 15:47:29 +0100 Subject: [PATCH] JVM: restore incorrect DFS logic in JavaModuleGraph for compatibility The problem is tracked in KT-66622. It should be fixed later, with a proper deprecation, because otherwise it can potentially break a lot of code. --- .../kotlin/cli/jvm/modules/JavaModuleGraph.kt | 3 +++ .../lib/foo/Foo.java | 3 +++ .../main.fir.txt | 1 + .../main.txt | 1 + .../main/module-info.java | 3 +++ .../main/usage.kt | 1 + .../lib/foo/Foo.java | 3 +++ .../main.fir.txt | 1 + .../main.txt | 1 + .../main/module-info.java | 5 ++++ .../main/usage.kt | 1 + .../unrelated/module-info.java | 3 +++ .../unrelated/unrelated/Unrelated.java | 3 +++ .../lib/foo/Foo.java | 3 +++ .../main.txt | 1 + .../main/module-info.java | 4 ++++ .../main/usage.kt | 1 + .../unrelated/unrelated/Unrelated.java | 3 +++ .../AbstractJavaModulesIntegrationTest.kt | 23 +++++++++++++++++++ 19 files changed, 64 insertions(+) create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/lib/foo/Foo.java create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main.fir.txt create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main.txt create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main/module-info.java create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main/usage.kt create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/lib/foo/Foo.java create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main.fir.txt create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main.txt create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main/module-info.java create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main/usage.kt create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/unrelated/module-info.java create mode 100644 compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/unrelated/unrelated/Unrelated.java create mode 100644 compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/lib/foo/Foo.java create mode 100644 compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main.txt create mode 100644 compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main/module-info.java create mode 100644 compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main/usage.kt create mode 100644 compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/unrelated/unrelated/Unrelated.java diff --git a/compiler/cli/cli-base/src/org/jetbrains/kotlin/cli/jvm/modules/JavaModuleGraph.kt b/compiler/cli/cli-base/src/org/jetbrains/kotlin/cli/jvm/modules/JavaModuleGraph.kt index d57baf54909..2759d7b60ff 100644 --- a/compiler/cli/cli-base/src/org/jetbrains/kotlin/cli/jvm/modules/JavaModuleGraph.kt +++ b/compiler/cli/cli-base/src/org/jetbrains/kotlin/cli/jvm/modules/JavaModuleGraph.kt @@ -78,6 +78,9 @@ class JavaModuleGraph(finder: JavaModuleFinder) { for ((dependencyModuleName, isTransitive) in module.moduleInfo.requires) { if (dependencyModuleName == dependencyName) return true if (isTransitive && dfs(dependencyModuleName)) return true + + // This is incorrect, but is left for compatibility, see KT-66622. + if (isTransitive && dfs(dependencyName)) return true } return false } diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/lib/foo/Foo.java b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/lib/foo/Foo.java new file mode 100644 index 00000000000..7f566bafd45 --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/lib/foo/Foo.java @@ -0,0 +1,3 @@ +package foo; + +public class Foo {} diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main.fir.txt b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main.fir.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main.fir.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main.txt b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main/module-info.java b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main/module-info.java new file mode 100644 index 00000000000..a51c95d5f18 --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main/module-info.java @@ -0,0 +1,3 @@ +module main { + requires transitive kotlin.stdlib; +} diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main/usage.kt b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main/usage.kt new file mode 100644 index 00000000000..894dd5e932c --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithTransitiveStdlib/main/usage.kt @@ -0,0 +1 @@ +val a = foo.Foo() diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/lib/foo/Foo.java b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/lib/foo/Foo.java new file mode 100644 index 00000000000..7f566bafd45 --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/lib/foo/Foo.java @@ -0,0 +1,3 @@ +package foo; + +public class Foo {} diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main.fir.txt b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main.fir.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main.fir.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main.txt b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main/module-info.java b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main/module-info.java new file mode 100644 index 00000000000..2a2cb7c2092 --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main/module-info.java @@ -0,0 +1,5 @@ +module main { + requires kotlin.stdlib; + + requires transitive unrelated; +} diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main/usage.kt b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main/usage.kt new file mode 100644 index 00000000000..894dd5e932c --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/main/usage.kt @@ -0,0 +1 @@ +val a = foo.Foo() diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/unrelated/module-info.java b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/unrelated/module-info.java new file mode 100644 index 00000000000..62d04881bcc --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/unrelated/module-info.java @@ -0,0 +1,3 @@ +module unrelated { + exports unrelated; +} diff --git a/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/unrelated/unrelated/Unrelated.java b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/unrelated/unrelated/Unrelated.java new file mode 100644 index 00000000000..52b1fd135bb --- /dev/null +++ b/compiler/testData/javaModules/namedDoesNotReadAutomaticWithUnrelatedNamed/unrelated/unrelated/Unrelated.java @@ -0,0 +1,3 @@ +package unrelated; + +public class Unrelated {} diff --git a/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/lib/foo/Foo.java b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/lib/foo/Foo.java new file mode 100644 index 00000000000..7f566bafd45 --- /dev/null +++ b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/lib/foo/Foo.java @@ -0,0 +1,3 @@ +package foo; + +public class Foo {} diff --git a/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main.txt b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main/module-info.java b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main/module-info.java new file mode 100644 index 00000000000..18d4d7f613c --- /dev/null +++ b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main/module-info.java @@ -0,0 +1,4 @@ +module main { + requires kotlin.stdlib; + requires unrelated; +} diff --git a/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main/usage.kt b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main/usage.kt new file mode 100644 index 00000000000..894dd5e932c --- /dev/null +++ b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/main/usage.kt @@ -0,0 +1 @@ +val a = foo.Foo() diff --git a/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/unrelated/unrelated/Unrelated.java b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/unrelated/unrelated/Unrelated.java new file mode 100644 index 00000000000..52b1fd135bb --- /dev/null +++ b/compiler/testData/javaModules/namedReadsAutomaticWithUnrelatedAutomatic/unrelated/unrelated/Unrelated.java @@ -0,0 +1,3 @@ +package unrelated; + +public class Unrelated {} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/modules/AbstractJavaModulesIntegrationTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/modules/AbstractJavaModulesIntegrationTest.kt index ab3e1c8700a..434e63bb9e4 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/modules/AbstractJavaModulesIntegrationTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/modules/AbstractJavaModulesIntegrationTest.kt @@ -387,4 +387,27 @@ abstract class AbstractJavaModulesIntegrationTest( val lib = module("lib", destination = File(tmpdir, name)) module("main", additionalKotlinArguments = listOf("-classpath", lib.path)) } + + fun testNamedDoesNotReadAutomaticWithUnrelatedNamed() { + // This test should result in an error because 'main' does not depend on 'lib' or any other automatic module. + // But currently it's OK for compatibility, see KT-66622. + val lib = module("lib") + val unrelated = module("unrelated") + module("main", listOf(lib, unrelated)) + } + + fun testNamedDoesNotReadAutomaticWithTransitiveStdlib() { + // This test should result in an error because 'main' does not depend on 'lib' or any other automatic module. + // But currently it's OK for compatibility, see KT-66622. + val lib = module("lib") + module("main", listOf(lib)) + } + + fun testNamedReadsAutomaticWithUnrelatedAutomatic() { + // Similarly to how it works in javac, if we depend on one automatic module, we depend on all of them. So even though 'main' does + // not have explicit "requires lib", in fact it depends on 'lib' because it has "requires unrelated". So "OK" is expected. + val lib = module("lib") + val unrelated = module("unrelated") + module("main", listOf(lib, unrelated)) + } }