scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

malformed Scala signature with test case #2323

Closed scabug closed 13 years ago

scabug commented 15 years ago

Small ant test project to reproduce the error is attached. Steps:

  1. SCALA_HOME environment var is supposed to be set

  2. Inside a project dir:

ant clean compile

  1. Edit src/B.scala - say, add empty line

  2. Now compile only:

ant compile

  1. java.lang.RuntimeException: malformed Scala signature of A at 639
scabug commented 15 years ago

Imported From: https://issues.scala-lang.org/browse/SI-2323?orig=1 Reporter: @gaydenko Attachments:

scabug commented 15 years ago

@gaydenko said: test ant project

scabug commented 15 years ago

@gaydenko said: reduced test case

scabug commented 15 years ago

@gaydenko said: myth8.zip is a reduced test case. Steps to reproduce are exactly the same.

scabug commented 15 years ago

@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.

scabug commented 15 years ago

@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:

  1. ./recompile
  2. add empty string to src/B.scala
  3. ./compileB
scabug commented 15 years ago

@gaydenko said: ant script is replaced with tiny bash scripts

scabug commented 15 years ago

@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.

scabug commented 15 years ago

@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?

scabug commented 15 years ago

@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.

scabug commented 14 years ago

@odersky said: (In r19670) Fixed #2323; made Pickler do the right thing.

scabug commented 14 years ago

@odersky said: The fix was in Pickler: There we need to correct the owner of all local symbols which have a non-local owner.

scabug commented 11 years ago

@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.

scabug commented 11 years ago

@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.