-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix incorrect ctx chain in TreeUnpickler #4889
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
Conversation
In this example: object Test { def length(l: LIST): Boolean = l eq l sealed trait LIST } trait LIST used to have the context of method length as its outer context. After this PR TreeUnpickler follows the same pattern used in Namer.
The failing test is non deterministic and can only be reproduced in the REPL. Here is a minimization: class Inv
abstract class C {
val s = locally(1)
} @allanrenucci Any idea how to investigate that? |
Can be reproduced (it seems in a deterministic way) with: scala> 1
val res0: Int = 1
scala> locally
Exception in thread "main" java.lang.AssertionError: assertion failed: denotation module scala invalid in run 2. ValidFor: Period(1..68, run = 3)
at scala.Predef$.assert(Predef.scala:219) The REPL and the IDE create multiple runs of the compiler. However some symbols (such as the ones in Looking at your proposed fix, it seems that a symbol's completer is created in run 1 and then completed in run 2 with a context that derives from run 1. Hope this helps |
That's unfortunately a rather sweeping change, which will create severe memory leaks. For this reason, it was intentional that completers in TreeUnpicklers do not store their context. So the description of the problem is actually what is intended. Is there an issue where things go wrong with the status quo? |
Is this really intended? While unpickling, type assigner will see object Test {
def length(l: LIST): Boolean = {
l eq l
sealed trait LIST
}
} Instead of what's in the source (where This seems clearly wrong. It might be the case that typing In our case we use the chain outer context to know whether or not we are in a transparent context, the addition of method length in that chain changes things when length is itself transparent. |
Leaving out the context from the unpickler is necessary. It's true that it's fragile, but I don't see another way. We can't leave contexts (which have about a 4MB transitive footprint) hanging in completers because these completers might not be triggered until many runs later. So this would prevent the compiler from being resident at all, which would make the IDE impossible. |
Ok makes sense, we will try to find a workaround for our transparent methods. |
Instead of closing over contexts, could one complete symbols after unpickling "outside-in" following the pattern in Namer? |
Could you use the chain of owners instead? |
As a side-note, the fact that the unpickling completers have these weird contexts where you can't trust everything is a pretty big trap, maybe we could set a flag on them or something so that any attempt to read fields like |
test performance please |
performance test scheduled: 1 job(s) in queue, 0 running. |
performance test failed: Please check http://lamppc37.epfl.ch:8000/pull-4889-08-23-16.54.out for more information |
@OlivierBlanvillain You might want to restore this branch if you want to test its performance 😉 |
test performance please |
performance test scheduled: 1 job(s) in queue, 0 running. |
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/4889/ to see the changes. Benchmarks is based on merging with master (33afaa2) |
In this example:
trait LIST used to have the context of method length as its outer context. After this PR TreeUnpickler follows the same pattern used in Namer.