Skip to content

Commit

Permalink
Determistically enter classes from directory into package scope
Browse files Browse the repository at this point in the history
On Linux, the directory listing is not automatically sorted on Mac.
This leads to non-determistic ids of Symbols of the classes in a
directory, which in turn leads to instability of the ordering of
parents within inferred refinement types.

Notable, with this patch, we will stably infer:

```
scala> case class C(); case class D(); List(C(), D()).head
defined class C
defined class D
res0: Product with Serializable = C()
```

rather than sometimes getting `Serializable with Product` on
Linux. As such, I've removed the workarounds for this instability
in two test cases.
  • Loading branch information
retronym committed Aug 18, 2016
1 parent b8e4d1f commit c141254
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 10 deletions.
24 changes: 21 additions & 3 deletions src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ package scala.tools.nsc.classpath

import java.io.File
import java.net.URL
import java.util
import java.util.Comparator

import scala.reflect.io.{AbstractFile, PlainFile}
import scala.tools.nsc.util.{ClassPath, ClassRepresentation}
import FileUtils._
Expand Down Expand Up @@ -87,9 +90,24 @@ trait JFileDirectoryLookup[FileEntryType <: ClassRepresentation] extends Directo
if (packageDir.exists && packageDir.isDirectory) Some(packageDir)
else None
}
protected def listChildren(dir: File, filter: Option[File => Boolean]): Array[File] = filter match {
case Some(f) => dir.listFiles(mkFileFilter(f))
case None => dir.listFiles()
protected def listChildren(dir: File, filter: Option[File => Boolean]): Array[File] = {
val listing = filter match {
case Some(f) => dir.listFiles(mkFileFilter(f))
case None => dir.listFiles()
}

// Sort by file name for stable order of directory .class entries in package scope.
// This gives stable results ordering of base type sequences for unrelated classes
// with the same base type depth.
//
// Notably, this will stably infer`Product with Serializable`
// as the type of `ase class C(); case class D(); List(C(), D()).head`, rather than the opposite order.
// On Mac, the HFS performs this sorting transparently, but on Linux the order is unspecified.
//
// Note this behaviour can be enabled with in javac with `javac -XDsortfiles`, but that's only
// intended to improve determinism of the compiler for compiler hackers.
util.Arrays.sort(listing, (o1: File, o2: File) => o1.getName.compareTo(o2.getName))
listing
}
protected def getName(f: File): String = f.getName
protected def toAbstractFile(f: File): AbstractFile = new PlainFile(new scala.reflect.io.File(f))
Expand Down
5 changes: 1 addition & 4 deletions test/files/presentation/callcc-interpreter/Runner.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import scala.tools.nsc.interactive.tests._

object Test extends InteractiveTest {
// Normalize ordering of LUB
override def normalize(s: String) = s.replace("Serializable with Product", "Product with Serializable")
}
object Test extends InteractiveTest
4 changes: 1 addition & 3 deletions test/files/run/t7747-repl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ object Test extends ReplTest {

override def normalize(s: String) = {
// replace indylambda function names by <function0>
val s2 = """\$Lambda.*""".r.replaceAllIn(s, "<function0>")
// Normalize ordering of LUB
s2.replace("Serializable with Product", "Product with Serializable")
"""\$Lambda.*""".r.replaceAllIn(s, "<function0>")
}

def code = """
Expand Down

0 comments on commit c141254

Please sign in to comment.