org.scalaide.core.compiler.NamePrinterTest failes from time to time with no apparent reason. See https://jenkins.scala-ide.org:8496/jenkins/job/pr-validator-master-luna-2.11.x/390/ for an example.
Leave a comment
This bug is best reproduced by modifying NamePrinterTest so that it is repeated many times; I've done exactly this here: Running the test repeatedly from within Eclipse reliably yields
after several runs. @sschaef, do you have any ideas?
!ENTRY org.scala-ide.sdt.core 4 0 2015-01-17 20:06:00.402
!MESSAGE Throwable during asyncExec
!STACK 0
scala.tools.nsc.interactive.FreshRunReq
2015-01-17 20:06:00,404 ERROR [main] - org.scala-ide.sdt.core - org.scala-ide.sdt.core - org.scala-ide.sdt.core - 0 - Throwable during asyncExec
scala.tools.nsc.interactive.FreshRunReq
after several runs. @sschaef, do you have any ideas?
Here is the same with "-Dscala.control.noTraceSuppression":
2015-01-18 09:31:46,325 ERROR [main] - NamePrinter - Error loading qualfied name
scala.tools.nsc.interactive.FreshRunReq
at scala.tools.nsc.interactive.FreshRunReq.scala$util$control$NoStackTrace$$super$fillInStackTrace(CompilerControl.scala:435)
at scala.util.control.NoStackTrace$class.fillInStackTrace(NoStackTrace.scala:22)
at scala.tools.nsc.interactive.FreshRunReq.fillInStackTrace(CompilerControl.scala:435)
at java.lang.Throwable.<init>(Throwable.java:250)
at scala.tools.nsc.interactive.FreshRunReq.<init>(CompilerControl.scala:435)
at scala.tools.nsc.interactive.Global.demandNewCompilerRun(Global.scala:307)
at scala.tools.nsc.interactive.Global.checkForMoreWork(Global.scala:519)
at scala.tools.nsc.interactive.Global.signalDone(Global.scala:359)
at scala.tools.nsc.typechecker.Typers$Typer.runTyper$1(Typers.scala:5395)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedInternal(Typers.scala:5400)
at scala.tools.nsc.typechecker.Typers$Typer.body$2(Typers.scala:5347)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5351)
at scala.tools.nsc.typechecker.Typers$Typer.typedType(Typers.scala:5494)
at scala.tools.nsc.typechecker.Typers$Typer.typedType(Typers.scala:5497)
at scala.tools.nsc.typechecker.Typers$Typer.typedValDefImpl(Typers.scala:1949)
at scala.tools.nsc.typechecker.Typers$Typer.typedValDef(Typers.scala:1940)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$35$$anonfun$apply$21.apply(Typers.scala:2163)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$35$$anonfun$apply$21.apply(Typers.scala:2163)
at scala.collection.immutable.List.loop$1(List.scala:173)
at scala.collection.immutable.List.mapConserve(List.scala:189)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$35.apply(Typers.scala:2163)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$35.apply(Typers.scala:2163)
at scala.collection.immutable.List.loop$1(List.scala:173)
at scala.collection.immutable.List.mapConserve(List.scala:189)
at scala.tools.nsc.typechecker.Typers$Typer.typedDefDef(Typers.scala:2163)
at scala.tools.nsc.typechecker.Typers$Typer.typedMemberDef$1(Typers.scala:5285)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5336)
at scala.tools.nsc.typechecker.Typers$Typer.runTyper$1(Typers.scala:5373)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedInternal(Typers.scala:5400)
at scala.tools.nsc.typechecker.Typers$Typer.body$2(Typers.scala:5347)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5351)
at scala.tools.nsc.typechecker.Typers$Typer.typedByValueExpr(Typers.scala:5429)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedStat$1(Typers.scala:3028)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$62.apply(Typers.scala:3132)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$62.apply(Typers.scala:3132)
at scala.collection.immutable.List.loop$1(List.scala:173)
at scala.collection.immutable.List.mapConserve(List.scala:189)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:3132)
at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1903)
at scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1744)
at scala.tools.nsc.typechecker.Typers$Typer.typedMemberDef$1(Typers.scala:5286)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5336)
at scala.tools.nsc.typechecker.Typers$Typer.runTyper$1(Typers.scala:5373)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedInternal(Typers.scala:5400)
at scala.tools.nsc.typechecker.Typers$Typer.body$2(Typers.scala:5347)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5351)
at scala.tools.nsc.typechecker.Typers$Typer.typedByValueExpr(Typers.scala:5429)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedStat$1(Typers.scala:3028)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$62.apply(Typers.scala:3132)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$62.apply(Typers.scala:3132)
at scala.collection.immutable.List.loop$1(List.scala:173)
at scala.collection.immutable.List.mapConserve(List.scala:189)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:3132)
at scala.tools.nsc.typechecker.Typers$Typer.typedPackageDef$1(Typers.scala:4989)
at scala.tools.nsc.typechecker.Typers$Typer.typedMemberDef$1(Typers.scala:5289)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5336)
at scala.tools.nsc.typechecker.Typers$Typer.runTyper$1(Typers.scala:5373)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedInternal(Typers.scala:5400)
at scala.tools.nsc.typechecker.Typers$Typer.body$2(Typers.scala:5347)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5351)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5425)
at scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3.apply(Analyzer.scala:102)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply$mcV$sp(Global.scala:441)
at scala.tools.nsc.Global$GlobalPhase.withCurrentUnit(Global.scala:432)
at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:441)
at scala.tools.nsc.interactive.Global$TyperRun$$anonfun$applyPhase$1.apply(Global.scala:1226)
at scala.tools.nsc.interactive.Global$TyperRun$$anonfun$applyPhase$1.apply(Global.scala:1226)
at scala.reflect.internal.SymbolTable.enteringPhase(SymbolTable.scala:235)
at scala.tools.nsc.interactive.Global$TyperRun.applyPhase(Global.scala:1226)
at scala.tools.nsc.interactive.Global$TyperRun.typeCheck(Global.scala:1219)
at scala.tools.nsc.interactive.Global.scala$tools$nsc$interactive$Global$$typeCheck(Global.scala:668)
at scala.tools.nsc.interactive.Global.typedTreeAt(Global.scala:817)
at scala.tools.nsc.interactive.Global.typedTreeAt(Global.scala:798)
at scala.tools.nsc.interactive.Global$$anonfun$getTypedTreeAt$1.apply(Global.scala:840)
at scala.tools.nsc.interactive.Global$$anonfun$getTypedTreeAt$1.apply(Global.scala:840)
at scala.tools.nsc.interactive.Global$$anonfun$respond$1.apply(Global.scala:699)
at scala.tools.nsc.interactive.Global$$anonfun$respond$1.apply(Global.scala:699)
at scala.tools.nsc.interactive.Global.respondGradually(Global.scala:706)
at scala.tools.nsc.interactive.Global.respond(Global.scala:699)
at scala.tools.nsc.interactive.Global.getTypedTreeAt(Global.scala:840)
at scala.tools.nsc.interactive.CompilerControl$AskTypeAtItem.apply$mcV$sp(CompilerControl.scala:326)
at scala.tools.nsc.interactive.Global$$anonfun$pollForWork$1.apply$mcV$sp(Global.scala:504)
at scala.util.control.Breaks.breakable(Breaks.scala:38)
at scala.tools.nsc.interactive.Global.pollForWork(Global.scala:429)
at scala.tools.nsc.interactive.PresentationCompilerThread.run(PresentationCompilerThread.scala:22)
2015-01-18 09:31:46,330 DEBUG [main] - ScalaPlugin - package framgent added or removedtestpackage2495910979265
on 2015-02-05 09:35 *
By Iulian Dragos
I have a hunch as to why this happens.
This is the way the presentation compiler cancels a current type-checking round and unwinds the stack, in order to star afresh. This happens as a result of certain services, and is normal to some extent, for example an `askTypeAt` would demand a new type-checking round after it's done. The reason is that type-at is targeted type-checking (skips everything outside the region of interest), so the tree needs to be re-type-checked for consistent error messages, for example.
Compiler calls should, as much as possible, avoid nesting. By that I mean that during a call to `asyncExec`, avoid calling any other compiler service, like `askTypeAt` or `askLoadedType`. This will most likely cancel the outermost call. This might actually work in some cases, but fail in others, and I think that's what's happening now.
I think the problem is that `NamePrinter` calls `asyncExec` at a very high level, and in the implementation calls `askLoadedType`. This is exactly the kind of nesting we should avoid. I think this code needs to be more careful, and call `asyncExec` only on the parts that really require it. I also think there is no need for `askLoadedType` at that point. If the typed tree is needed, it should be computed only once, before starting computing the qualified name, instead of recomputing the full typed tree for each enclosing definition. So, the solution might be to simply pull up the `askLoadedType` at the top-level, and use `locateIn` as many times as needed, potentially enclosing some of the calls in `asyncExec`
As a side-note, we should look if the code can be implemented (like all the other `enclosing*` methods) inside `CompilerApiExtensions`, and using the parse tree, not the type-checked tree.
FreshRunRequest
This is the way the presentation compiler cancels a current type-checking round and unwinds the stack, in order to star afresh. This happens as a result of certain services, and is normal to some extent, for example an `askTypeAt` would demand a new type-checking round after it's done. The reason is that type-at is targeted type-checking (skips everything outside the region of interest), so the tree needs to be re-type-checked for consistent error messages, for example.
Nesting
Compiler calls should, as much as possible, avoid nesting. By that I mean that during a call to `asyncExec`, avoid calling any other compiler service, like `askTypeAt` or `askLoadedType`. This will most likely cancel the outermost call. This might actually work in some cases, but fail in others, and I think that's what's happening now.
NamePrinter
I think the problem is that `NamePrinter` calls `asyncExec` at a very high level, and in the implementation calls `askLoadedType`. This is exactly the kind of nesting we should avoid. I think this code needs to be more careful, and call `asyncExec` only on the parts that really require it. I also think there is no need for `askLoadedType` at that point. If the typed tree is needed, it should be computed only once, before starting computing the qualified name, instead of recomputing the full typed tree for each enclosing definition. So, the solution might be to simply pull up the `askLoadedType` at the top-level, and use `locateIn` as many times as needed, potentially enclosing some of the calls in `asyncExec`
As a side-note, we should look if the code can be implemented (like all the other `enclosing*` methods) inside `CompilerApiExtensions`, and using the parse tree, not the type-checked tree.
on 2015-02-05 10:03 *
By Simon Schäfer
Thanks for the clarification Iulian, I had no idea of any of these things. Another reason why I should take a weekend off and debug the whole presentation compiler to learn more of its control flow (even though that will be quite exhausting). If Matthias doesn't find the time to work on this, I'll have a look by myself - but not before the next week.
No file chosen
You have an empty file field. Please select or remove it.
Name | Size |
---|