Compiler heisenbug involving "cyclic references"


#1

Have I found a bug in the Scala compiler, IntelliJ, or something else? I have a Github project that compiles on some machines, but not on others. In particular, the project compiles fine on my Mac running IntelliJ 2016.2.2 with Scala SDK 2.12.1 and JDK 1.8.0_71, but not on a Windows 10 computer running IntelliJ 2016.2 with Scala SDK 2.12.2 and JDK 1.8.0_92. When the compiler crashes, it gives me errors of the form “illegal cyclic reference involving class Point”.

For context, I have a trait Geometry that has a bunch of type members like this:

trait Geometry {
  type Point <: BasePoint

  trait BasePoint {
    this: Point => // Every BasePoint must also be a Point

  }
}

Elsewhere I have particular Geometry objects, such as one for planar geometries:

object PlanarGeometry extends Geometry {
  override type Point = planar.Point
}

In the planar package I implement the abstract type members above with classes like Point:

class Point extends PlanarGeometry.BasePoint {
  ...
}

This bug is difficult to reproduce. Indeed, I was unable to produce a smaller example that leads to the same behavior. I will also add that even though the project compiles fine on one machine, rearranging packages and class names can reliably break compilation. As far back as this commit, I observed that the compiler would crash with the same error if and only if the names of several classes occurred in a certain lexicographic order.

What’s the best way to fix this problem?


#2

One thing I would suggest trying is to clean and compile when you get errors. The inceremental compiler does misbehave.

regards,
Siddhartha


#3

Hello,

I also see on rare occasions that IntelliJ ignores recent changes to
source files and then continues to see errors even though they have been
removed or does not notice new errors that have been introduced. Sometimes
you can even run the project and the run will be based on outdated compiled
code.

I think this mostly happens when an error involves multiple files and the
files involved in the error are being modified.

In these cases, I either wait for IntelliJ to catch up, or run SBT
directly in a terminal to check which errors actually exist.

 Best, Oliver

#4

A long overdue update: previously, I wasn’t using SBT for this project, but I am now. It’s on Github. Sadly, even after trying the suggestions above and updating to the latest versions, I am still running into the same issues, as you can see below.

I’m no longer able to replicate the previous odd behavior where changing filenames or rearranging the directory structure fixes the problem, and indeed I now get consistent errors applying to the same classes. I suppose it’s a good thing that the behavior is consistent now, but I still cannot identify the source of the problem.

Any new ideas? Others are welcome to try to replicate the behavior by cloning the project and running sbt.

This is the output I get:

$ sbt clean compile
[info] Loading project definition from /Users/William/IdeaProjects/CirclePuzzlesSBT/project
[info] Set current project to CirclePuzzles (in build file:/Users/William/IdeaProjects/CirclePuzzlesSBT/)
[success] Total time: 0 s, completed Dec 14, 2017 3:53:51 AM
[info] Updating {file:/Users/William/IdeaProjects/CirclePuzzlesSBT/}circlepuzzlessbt...
[info] Resolving jline#jline;2.14.5 ...
[info] Done updating.
[info] Compiling 25 Scala sources to /Users/William/IdeaProjects/CirclePuzzlesSBT/target/scala-2.12/classes...
[error] /Users/William/IdeaProjects/CirclePuzzlesSBT/src/main/scala/circlepuzzles/geometry/planar/Circle.scala:13: illegal cyclic reference involving class Circle
[error] case class Circle(override val center: Point, radius: FixedPoint) extends PlanarGeometry.BaseCircle
[error]                  ^
[error] /Users/William/IdeaProjects/CirclePuzzlesSBT/src/main/scala/circlepuzzles/geometry/planar/Point.scala:11: illegal cyclic reference involving class Point
[error] case class Point(x: FixedPoint, y: FixedPoint) extends PlanarGeometry.BasePoint {
[error]                 ^
[error] /Users/William/IdeaProjects/CirclePuzzlesSBT/src/main/scala/circlepuzzles/geometry/spherical/Point.scala:12: illegal cyclic reference involving class Point
[error] case class Point(x: FixedPoint, y: FixedPoint, z: FixedPoint) extends SphericalGeometry.BasePoint {
[error]                 ^
[error] three errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 4 s, completed Dec 14, 2017 3:53:55 AM

I suppose it’s a little suspect that “compileIncremental” appears in the error message, but I don’t know what to make of this.


#5

Update: I’ve found something of a fix, which is now visible in the Github link above. Essentially, my Geometry trait had an inner trait Rotatable[T <: Rotatable[T]], and so I’d have something like trait BasePoint extends Rotatable[Point]. It seems this is what made SBT think there was a cyclic reference; getting rid of the Rotatable trait fixed the problem. I still think that my previous solution should have worked, but at least there’s a workaround.