summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/partest/scala/tools/partest/nest/RunnerManager.scala30
1 files changed, 27 insertions, 3 deletions
diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala
index 5a7684dc61..2a0d62eb9f 100644
--- a/src/partest/scala/tools/partest/nest/RunnerManager.scala
+++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala
@@ -323,10 +323,34 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP
val (scalaFiles, javaFiles) = g partition isScala
val allFiles = javaFiles ++ scalaFiles
+ /* The test can contain both java and scala files, each of which should be compiled with the corresponding
+ * compiler. Since the source files can reference each other both ways (java referencing scala classes and
+ * vice versa, the partest compilation routine attempts to reach a "bytecode fixpoint" between the two
+ * compilers -- that's when bytecode generated by each compiler implements the signatures expected by the other.
+ *
+ * In theory this property can't be guaranteed, as neither compiler can know what signatures the other
+ * compiler expects and how to implement them. (see SI-1240 for the full story)
+ *
+ * In practice, this happens in 3 steps:
+ * STEP1: feed all the files to scalac
+ * it will parse java files and obtain their expected signatures and generate bytecode for scala files
+ * STEP2: feed the java files to javac
+ * it will generate the bytecode for the java files and link to the scalac-generated bytecode for scala
+ * STEP3: only if there are both scala and java files, recompile the scala sources so they link to the correct
+ * java signatures, in case the signatures deduced by scalac from the source files were wrong. Since the
+ * bytecode for java is already in place, we only feed the scala files to scalac so it will take the
+ * java signatures from the existing javac-generated bytecode
+ */
List(1, 2, 3).foldLeft(CompileSuccess: CompilationOutcome) {
- case (CompileSuccess, 1) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile) // java + scala
- case (CompileSuccess, 2) if javaFiles.nonEmpty => javac(outDir, javaFiles, logFile) // java
- case (CompileSuccess, 3) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile) // scala
+ case (CompileSuccess, 1) if scalaFiles.nonEmpty =>
+ compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile)
+ case (CompileSuccess, 2) if javaFiles.nonEmpty =>
+ javac(outDir, javaFiles, logFile)
+ case (CompileSuccess, 3) if scalaFiles.nonEmpty && javaFiles.nonEmpty =>
+ // TODO: Do we actually need this? SI-1240 is known to require this, but we don't know if other tests
+ // require it: https://groups.google.com/forum/?fromgroups#!topic/scala-internals/rFDKAcOKciU
+ compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile)
+
case (outcome, _) => outcome
}
}