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
2.9.0+: Runtime exception with structural-type reflection cache and self-types #4560
Comments
Imported From: https://issues.scala-lang.org/browse/SI-4560?orig=1 |
@dragos said: |
@odersky said: |
@jrudolph said: trait A
trait B
trait C { self: A with B =>
} My brief tests with the Scala 2.10.0-SNAPSHOT from 17.5. shows that this case seems to be fixed with the last commit as well but maybe you want to add another test-case for this case anyways. |
@propensive said (edited on Jun 2, 2011 11:59:21 PM UTC): object C { implicit def y(s : String) = new { def x(implicit x : List[Int] = Nil) = "" } }
import C._
object A extends B { def main(args : Array[String]) : Unit = fail() }
trait B { this : A.type => def fail() = "".x } |
@paulp said:
|
@retronym said (edited on Jul 13, 2011 11:36:27 AM UTC): |
@odersky said: |
@jrudolph said: cb4fd65825f3c88908103e48d0d7e89d70d26c22 which "tentatively" replaces the |
@odersky said: |
@jrudolph said: https://scala-webapps.epfl.ch/jenkins/job/pr-scala-testsuite-linux-opt/645/consoleFull |
@jrudolph said: There seem to be three cases:
All of those classes again have self-types. So what we have here could mean: a) the original fix ("tentative fix for RC5 lift build problem.") actually fixed a related problem to this ticket but created a regression for the cases listed here |
@paulp said: Example error:
That method is defined in trait MarkupParserCommon, which MarkupParser extends. It may be relevant that MarkupParserCommon is private[scala]. The MarkupHandler target must be taken from MarkupParser's self type, which is
But MarkupHandler by itself does not define any xToken method. In the current working version, the generated call is
|
@paulp said: I think it's this one. |
@jrudolph said: |
@paulp said:
Appears to me likely to also depend on martin's recent elimination of redundant $outer fields. |
@paulp said:
What I see is: if a class appears in the self type (possibly there are more conditions) then it acts like everything is in that class. But if you have trait Foo extends Bar { ... Then a member might be in the implementation class of Foo, Bar, or anything inherited from Bar, or in Baz, Quux, or anything inherited through them, or the implementation classes of any of those. |
@jrudolph said: object Outer {
class Tester
private[Outer] trait B4 { _: Tester =>
protected val FREQ = 23
def fail() = {
println(FREQ)
}
}
object C4 extends Tester with B4
} Note the necessity of This is a case which still worked in 2.9.0.RC1. So there might be another possibility: The original issue was something else but the original fix then started to mask issues. |
@jrudolph said: object Outer2 {
abstract class A5
private[Outer2] trait C5 {
def impl() { println("SUCCESS") }
}
trait B5 extends C5 { self: A5 =>
def fail() { impl() }
}
object Test5 extends A5 with B5 with C5
} So again a class is the self-type and the implementing trait is private. |
@jrudolph said: we've got now 4 more or less different failure scenarios: the original three in this report (which are in the test file in the pull request) plus the one from the previous comment (I'm putting both previous ones into one category). Archaeological research showed the following:
My previous explanation that the tentative fix was the original commit introducing the regression is definitely wrong simply because it was already in the codebase long before the regression (actually I can't figure out any more from where I dug this commit out). It is a curious thing that the commit still is related otherwise reverting wouldn't have such an effect. I'm not so sure where to go from here: I wouldn't say the best solution is reverting a bunch of stuff if the outcome is at least one new previously unknown regression. In contrast, it isn't probably too hard to extend the current workaround to handle the last known remaining issue (self-type is singleton-type). The price is that we still have a workaround in the codebase for an issue for that no one seems to understand exactly where it comes from and which other variations may exist. Maybe I'll start a bisect between 2.9.0.RC1 and 2.9.0.RC2 to find out where it really showed up first. (In the meantime while scalac is compiling I read one of Alan Turing's articles, here's an excerpt about the "Learning Machine": bq.An important feature of a learning machine is that its teacher will often be very largely ignorant of quite what is going on inside, although he may still be able to some extent to predict his pupil's behavior. This should apply most strongly to the later education of a machine arising from a child machine of well-tried design (or programme). This is in clear contrast with normal procedure when using a machine to do computations one's object is then to have a clear mental picture of the state of the machine at each moment in the computation. This object can only be achieved with a struggle. The view that "the machine can only do what we know how to order it to do,"' appears strange in face of this. Most of the programmes which we can put into the machine will result in its doing something that we cannot make sense. Sometimes I worry we are getting more and more into the area of trying to educate the compiler what to do instead of having "a clear mental picture of the state of the machine at each moment" but maybe that's just my ignorance) |
@jrudolph said: I think the solution would then be to fix it properly at the place where the error was introduced ( |
@paulp said:
Since you've been so helpful in this ticket already, if there are more cases not well covered by that one test it would be awesome if you could save me dredging around for more. I think I have this nailed but I'd feel a lot better with more tests. |
@paulp said: object Outer {
class Tester
private[Outer] trait B4 { _: Tester =>
protected val FREQ = 23
def fail() = {
println(FREQ)
}
}
object C4 extends Tester with B4
}
object Outer2 {
abstract class A5
private[Outer2] trait C5 {
def impl() { println("SUCCESS") }
}
trait B5 extends C5 { self: A5 =>
def fail() { impl() }
}
object Test5 extends A5 with B5 with C5
}
object Test {
def main(args: Array[String]): Unit = {
Outer.C4.fail()
Outer2.Test5.fail()
}
} Which prints 23 and SUCCESS as expected. |
@paulp said: |
=== What steps will reproduce the problem? ===
=== What is the expected behavior? ===
5
=== What do you see instead? ===
A runtime error:
=== Additional information ===
This happens since 2.9.0.RC2 (RC1 was fine) and happens only with the self-type in place. The problem seems to be that the reflection cache inside of
B$$class
looks for the cache field inside of classB
:In another [http://groups.google.com/group/spray-user/msg/59eb57b6cb2ce512 case] for some reason the cache was looked for in a class declared as the self-type.
The text was updated successfully, but these errors were encountered: