New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"diverging implicit expansion" error: sensitive to lexicographic file ordering, breaks incremental compilation #10222
Comments
Imported From: https://issues.scala-lang.org/browse/SI-10222?orig=1 |
Yes, this is basically the same as #8541. This implicit is to blame.
I wasn't able to find a way out of the design errors in that implicit in a backwards compatible way. It is worth a fresh investigation. The sensitivity to order of compilation units is likely due to an implementation detail of implicit search: implicit candidates are explored based on the frequency that they have been chosen previously. This is a supposed performance optimization, but the cost of non-determinism seems too high to me. |
This performance optimization leads to compilation order dependent variations in whether an implicit search will diverge or will find a successful result. Let's try turning off this sorting and measuring the impact on compilation speed. Refererences: scala/bug#10222, scala/bug#8541, scala/bug#10080
thanks for the context @retronym I just hit this again (I think) with a very basic use of A.scala: object A { shapeless.Generic[T] } B.scala: sealed trait T
case object O extends T
could not find implicit value for parameter gen: shapeless.Generic[cubic.T]
[error] shapeless.Generic[T]
[error] ^ After After undoing the move ( So it clean-compiles iff the implicit-summon happens in a lexicographically-greater filename. It additionally incremental-compiles if it was previously compiled as above, before the files' lex-order was reversed. copied from shapeless gitter |
@ryan-williams I think the problem you're seeing there is #7046 rather than the issue being reported here. |
Interesting, yea I see now that my shapeless-based example above compiles fine from 2.11.9, while the original repro (more direct link than in the OP) still fails in 2.11.11 and 2.12.3. Thanks for catching/noting! |
This performance optimization leads to compilation order dependent variations in whether an implicit search will diverge or will find a successful result. Let's try turning off this sorting and measuring the impact on compilation speed. Refererences: scala/bug#10222, scala/bug#8541, scala/bug#10080
This performance optimization leads to compilation order dependent variations in whether an implicit search will diverge or will find a successful result. Let's try turning off this sorting and measuring the impact on compilation speed. Refererences: scala/bug#10222, scala/bug#8541, scala/bug#10080
tl;dr: if the compiler implicitly constructs an
Ordering[T]
from aComparable[T]
at some point, then later implicit construction of anOrdering[(T, U)]
from anOrdered[T]
(in unrelated code) will throw a "divergent implicit expansion" error.This behavior is sensitive to the order in which (otherwise unrelated) files are compiled, and also reliably puts zinc in an inconsistent state where a
clean
changes whether compilation succeeds or fails.A minimal repro can be found at ryan-williams/scalac-bug, and is reproduced below:
B.scala
C.scala
Repro steps
Compiling
B.scala
andC.scala
: fails:Compiling
C.scala
andB.scala
: succeedssbt compile
a working branch causes broken branch to requiresbt clean
Discussion
This looks similar to #8541 and #10080, but I've filed it separately as there are two things on display here that I didn't see explicitly discussed in them:
sbt clean
changes whether compilation succeeds or fails.I ran in to this in a very large codebase and had a very confusing time narrowing down the interactions that were causing it, since they turned out to involve a specific lexicographic ordering of two seemingly-unrelated parts of the codebase as well as one kind of compilation corrupting the compiler's state and causing another compilation to succeed or fail depending on whether an
sbt clean
was run.The text was updated successfully, but these errors were encountered: