what happened |
WARNING: redirect compiler's error output to a file, or your terminal might crash (mine did).
sean-mcdirmid:~/workspace/lampion/src mcdirmid$ time ../../scala/build/quick/bin/scalac -d ../bin -sourcepa\
th . lampion/matcher/BraceMatcherXXX.scala >& out
real 0m39.947s
user 0m39.130s
sys 0m0.749s
sean-mcdirmid:~/workspace/lampion/src mcdirmid$ ls -l out
-rw-r--r-- 1 mcdirmid mcdirmid 1728822 Nov 11 10:07 out
I'm not going to bother posting the compiler-generated error message here (it is just a 1.7 megabyte approximate\
d type string along the lines of the one that the bug tracking system chocked on).
Note also that the 40 second compile time will also show up in the presentation compiler IDE, effectively causin\
g a long very annoying pause. In a larger code context, it will be interpreted as a crash.
The problem will get significantly more worse in the context of more code. If I add type parameters back in, thi\
s will blow up to 2.5 minutes (though the approximated type doesn't seem to get much bigger). If I put this code\
in the context of the entire Lampion framework, it won't finish within any amount of time that I'm willing to w\
ait (much longer than 15 minutes), effectively locking up the IDE. This basically is why I initially thought thi\
s bug was a non-termination bug.
Note also that the overrides of toSelf and toMatch in OpenImpl and CloseImpl are useless but relevant wrt the pe\
rformance of the inference algorithm. Getting rid of the toMatch overrides reduces the compile time to 13 second\
s with a 500K approximated type. Getting rid of the toSelf methods reduces the compile time to around 4 seconds \
with an 88K approximated type. The latter case is similar to the code that I posted in #807. My guess is that th\
e inferencer gets exponentially worse as the number of overridden methods in OpenImpl and CloseImpl increases. C\
hecking my hypothesis: add a toSelf0 : BraceImpl => Self method to BraceImpl with corresponding overrides in Ope\
nImpl and CloseImpl, compile time is 2 minutes 14 seconds with no output, instead we get an OutOfMemory error (m\
eaning exhausted heap space, recursion isn't the problem!). Not sure how to adjust heap space for scalac, but in\
the IDE, I've set my heap space to around 1 GB (for dealing with NSC), so it is able to go a lot longer (causin\
g a lock up rather than a crash).
Also, if toSelf/toMatch are simplified to toSelf : Self and toMatch : Match, the problem becomes worse much more\
quickly.
Of course, a type annotation on yyy will fix the problem by avoiding having the inferencer run. But if someone f\
orgets, the compiler will probably lock up or crash if there is a lot of code around it.
Motivation: the type refinement used in brace expresses a standard male/female connector type, so this is not an\
esoteric example. The type is intuitively not that complicated: the brace has a self type and a match type whos\
e own match type is the brace's self type. As a result, we can express a two-way link between two different type\
s without downcasting:
val brace : Self = ...;
val found : Match = ...;
// trait BraceImpl { ... var matching : Match = _; }
brace.matching = found;
found.matching = brace;
|