Closed scabug closed 13 years ago
Imported From: https://issues.scala-lang.org/browse/SI-2323?orig=1 Reporter: @gaydenko Attachments:
@gaydenko said: test ant project
@gaydenko said: reduced test case
@gaydenko said: myth8.zip is a reduced test case. Steps to reproduce are exactly the same.
@paulp said: I spent a while with this last night hoping it'd be easy since you'd reduced it so far. No such luck. Pickler is just too complicated - I don't even know who is ostensibly responsible for understanding it.
@gaydenko said: To be sure the problem is not ant-related (I remember 2320 :-)), I have reproduced the error after replacing ant script with tiny bash scripts (will attach myth9.zip). Steps are in fact the same:
@gaydenko said: ant script is replaced with tiny bash scripts
@paulp said: It wasn't in any danger of being seen as ant-related. It's definitely the [un]pickler. You don't need two files to demonstrate it either, just compile A.scala and reference A.a in the repl. But without better tools for examining the pickled data I can/will not debug this; I would have to write the tools first, as I have burned through my lifetime quota of pickler head scratching.
@lrytz said: Gilles, i think this one is for you, it has to do with refinement types.
when compiling the following
trait T
object C { val c = List(1).map(e => new T{}) }
object A { val a = C.c }
the type of C.c is the refinement Object with T
. The typeSymbol of the !RefinedType (the refinement class symbol) has as owner value $$anonfun
, which in turn
has owner value c
(debug case RefinedType
in the putType
method of the pickler).
Un-Pickling fails because in value c
no member called $$anonfun
can be found.
If you specify the type of c manually, i.e.
object C { val c: List[Object with T] = List(1).map(e => new T{}) }
the owner of the refinement symbol is object C
, and everything works fine.
So the question is: what should be the owner of the refinement-class-symbol in the first case?
@paulp said: Based on lukas's nice clear explanation of what is taking place, I just committed a simple (and replaceable pending gilles's investigation) fix in r18702, as I know at least a few people are blocked on using trunk because of this. It would be awesome if the pickler would refuse to pickle anything it knows it can't unpickle... but what I committed only addresses the specific case of refinement type creation, and continues up the owner chain if the owner is $$anonfun.
I'm leaving this ticket open though.
@odersky said: (In r19670) Fixed #2323; made Pickler do the right thing.
@odersky said: The fix was in Pickler: There we need to correct the owner of all local symbols which have a non-local owner.
@adriaanm said: In retrospect, I would argue we should not have those problematic owner chains at all.
SBT's incremental compilation scheme is foiled by the shape of owner chains depending on whether a symbol's info was pickled and then unpickled or if it was obtained directly by type checking source code. We can make SBT insensitive to these changes in the case of refinements, but as a general principle, it should hold that unpickle(pickle(typecheck) == typecheck
. See #6596.
@adriaanm said (edited on Nov 2, 2012 1:28:59 AM UTC): I'm going to revert r19670 (https://github.com/scala/scala/commit/6063bf3d78 and https://github.com/scala/scala/commit/44e60b3ae6) in master as I cannot reproduce the failure after having replaced localizedOwner by the identity. It seems this workaround is no longer needed.
There's no test in the suite for this, so I compiled the following:
trait T
trait U
object C { val c = List(1).map(e => (e, new T with U { def x: this.type = ???})) }
object A { val a = C.c }
and then accessed A.a
in the repl -- everything works fine.
I'll first try to find out how this works now exactly. After reverting, I see the same RefinedType being created in #6596 whether unpickling or typing directly.
Small ant test project to reproduce the error is attached. Steps:
SCALA_HOME environment var is supposed to be set
Inside a project dir:
ant clean compile
Edit src/B.scala - say, add empty line
Now compile only:
ant compile