Classes defined in REPL have no ScalaSig annotation

86 views
Skip to first unread message

rktoomey

unread,
May 11, 2011, 10:34:29 AM5/11/11
to scala-user
Hi,

I'm the developer behind Salat (https://github.com/novus/salat), a
Scala case class <-> Mongo DBObject serialization library that
requires pickled Scala signatures to work.

I can't get pickled Scala signatures on classes defined in the REPL no
matter what I try because those classes have neither a ScalaSig
annotation nor a .class file. (Experimentally the only time I have
identified a case when the ScalaSig annotation was present but there
wasn't a .class file was using Dalvik on Android.)

So my question is: why don't classes defined in the REPL have a
ScalaSig annotation? And should I expect them to? Shouldn't I expect
all Scala classes compiled using scalac to have the ScalaSig
annotation all the time?

Here's a simple case in 2.8.1 REPL showing the problem: the class
defined has no ScalaSig annotation:

Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit
Server VM, Java 1.6.0_24).

scala> case class Foo(x: String)
defined class Foo

scala> val clazz = classOf[Foo]
clazz: java.lang.Class[Foo] = class Foo

scala> clazz.getAnnotations
res1: Array[java.lang.annotation.Annotation] = Array()

Compare with this example, running sbt console in the Salat project
looking at one of the Salat test model classes, which has of course
a .class file but also a ScalaSig annotation:

scala> import com.novus.salat.test.model._
import com.novus.salat.test.model._

scala> val clazz = classOf[Hector]
x: java.lang.Class[com.novus.salat.test.model.Hector] = class
com.novus.salat.test.model.Hector

scala> clazz.getAnnotations
res2: Array[java.lang.annotation.Annotation] =
!A/Z:u s9 "A tC2,GN calaSignature(bytes= c C Q
GO
// etc etc etc

I am rather concerned because this doesn't work in the REPL for
2.9.0.RC4 either:

Welcome to Scala version 2.9.0.RC4 (Java HotSpot(TM) 64-Bit Server
VM, Java 1.6.0_24).

scala> case class Foo(x: String)
defined class Foo

scala> val clazz = classOf[Foo]
clazz: java.lang.Class[Foo] = class Foo

scala> clazz.getAnnotations
res0: Array[java.lang.annotation.Annotation] = Array()

Is there any definitive information under what circumstances I should
expect to find a pickled Scala signature?

Thanks,
Rose

Paul Phillips

unread,
May 11, 2011, 11:09:10 AM5/11/11
to rktoomey, scala-user
On 5/11/11 7:34 AM, rktoomey wrote:
> So my question is: why don't classes defined in the REPL have a
> ScalaSig annotation?

I don't know. I tried to fix it at some point but did not succeed. You
can consider it a bug: I'm aware of it but I don't think there's a
ticket, so opening one would be good.

iulian dragos

unread,
May 11, 2011, 11:16:12 AM5/11/11
to Paul Phillips, rktoomey, scala-user

AFAIK only top-level classes have a scala signature. The signature
contains all the type information, for all its members (including
inner classes). I doubt this can be changed without a major re-design
of the pickle format. Also, AFAIK there are no top-level classes in
the REPL, everything is wrapped in 'object' definitions.

iulian

--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais

Paul Phillips

unread,
May 11, 2011, 11:34:08 AM5/11/11
to iulian dragos, rktoomey, scala-user
On 5/11/11 8:16 AM, iulian dragos wrote:
> AFAIK only top-level classes have a scala signature. The signature
> contains all the type information, for all its members (including
> inner classes). I doubt this can be changed without a major re-design
> of the pickle format. Also, AFAIK there are no top-level classes in
> the REPL, everything is wrapped in 'object' definitions.

Ah, that pointed the way. Yes, the signature is there, just not where one might expect to find it. (The line which says "line elided for control chars: possibly a scala signature" is just that.)


sc[paulp@stem ~ (master)]$ scala29
Welcome to Scala version 2.10.0.r24909-b20110508001538 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class Foo
defined class Foo

scala> println(new Foo getClass)
class $line1.$read$$iw$$iw$Foo

scala> :javap -v $line1.$read
Compiled from "<console>"
public final class $line1.$read extends java.lang.Object
SourceFile: "<console>"
ScalaSig: length = 0x3
05 00 00
RuntimeVisibleAnnotations: length = 0xB
00 01 00 04 00 01 00 05 73 00 06
minor version: 0
major version: 49
Constant pool:
const #1 = Asciz SourceFile;
const #2 = Asciz <console>;
const #3 = Asciz ScalaSig;
const #4 = Asciz Lscala/reflect/ScalaSignature;;
const #5 = Asciz bytes;
const #6 = Asciz [line elided for control chars: possibly a scala signature]
const #7 = Asciz RuntimeVisibleAnnotations;
const #8 = Asciz $line1/$read;
const #9 = class #8; // $line1/$read
const #10 = Asciz java/lang/Object;
const #11 = class #10; // java/lang/Object

rktoomey

unread,
May 11, 2011, 11:40:24 AM5/11/11
to scala-user
Thanks, Paul - I created https://lampsvn.epfl.ch/trac/scala/ticket/4567.

Really finding the discussion here extremely useful - would
appreciate .

Best,
Rose

rktoomey

unread,
May 11, 2011, 11:53:20 AM5/11/11
to scala-user
Paul,

this is a Scala signature but alas for the containing object (?) not
for the class I wanted:

Welcome to Scala version 2.9.0.RC4 (Java HotSpot(TM) 64-Bit Server VM,
Java 1.6.0_24).
Type in expressions to have them evaluated.
Type :help for more information.

scala> case class Foo(x: String) {
| def distinctiveMethodName = "Hello"
| }
defined class Foo

scala> val clazz = classOf[Foo]
clazz: java.lang.Class[Foo] = class Foo

scala> println(clazz)
class $line1.$read$$iw$$iw$Foo

scala> val cfn = Class.forName("$line1.$read")
cfn: java.lang.Class[_] = class $line1.$read

scala> cfn.getDeclaredMethods.filter(_.getName ==
"distinctiveMethodName")
res1: Array[java.lang.reflect.Method] = Array()

// and that would be because there are no declared methods at all on
$line1.$read
scala> cfn.getDeclaredMethods
res3: Array[java.lang.reflect.Method] = Array()

// whereas this is the stuff I want
scala> Class.forName("$line1.$read$$iw$$iw$Foo").getDeclaredMethods
res8: Array[java.lang.reflect.Method] = Array(public boolean
Foo.equals(java.lang.Object), public java.lang.String Foo.toString(),
public int Foo.hashCode(), public Foo Foo.copy(java.lang.String),
public java.lang.String Foo.x(), private final boolean
Foo.gd1$1(java.lang.String), public java.lang.String
Foo.productPrefix(), public int Foo.productArity(), public
java.lang.Object Foo.productElement(int), public
scala.collection.Iterator Foo.productIterator(), public
scala.collection.Iterator Foo.productElements(), public boolean
Foo.canEqual(java.lang.Object), public java.lang.String Foo.copy
$default$1(), public java.lang.String Foo.distinctiveMethodName())

(Stupid question: I don't have :javap available from the REPL in
2.9.0.RC4 - what do I need to do to get it? Also, where is the best
place to find power mode documentation -
https://github.com/paulp/scala-full/blob/master/src/compiler/scala/tools/nsc/interpreter/Power.scala
?)

Thanks,
Rose

rktoomey

unread,
May 11, 2011, 12:24:50 PM5/11/11
to scala-user
Actually, that last was incorrect.

The ScalaSignature for $line1.$read actually does have the methods I
expect:
https://gist.github.com/966803

Paul Phillips

unread,
May 11, 2011, 12:42:48 PM5/11/11
to rktoomey, scala-user
On 5/11/11 8:53 AM, rktoomey wrote:
> (Stupid question: I don't have :javap available from the REPL in
> 2.9.0.RC4 - what do I need to do to get it?

You need tools.jar on your classpath.

> Also, where is the best
> place to find power mode documentation -
> https://github.com/paulp/scala-full/blob/master/src/compiler/scala/tools/nsc/interpreter/Power.scala

There's no secret documentation, you found the source. It's the subject
of my scala days talk though so it seems likely it will have a little
more documentation by then.

Reply all
Reply to author
Forward
0 new messages