default values of variables of type Any and AnyVal

159 views
Skip to first unread message

Grzegorz Balcerek

unread,
Feb 11, 2013, 1:38:17 PM2/11/13
to scala-l...@googlegroups.com
Why does the following work? I would expect a compilation error here.
Is this a known bug?


scala> var x: Any = _
x: Any = null

scala> var x: AnyVal = _
x: AnyVal = null


Regards,
Grzegorz Balcerek

Paul Phillips

unread,
Feb 11, 2013, 10:59:47 PM2/11/13
to scala-l...@googlegroups.com
On Mon, Feb 11, 2013 at 10:38 AM, Grzegorz Balcerek <gbalc...@gmail.com> wrote:
Why does the following work? I would expect a compilation error here.
Is this a known bug?

scala> var x: Any = _
x: Any = null

You would expect a compilation error here? On what grounds? If that's a compilation error then I think they'll all have to be compilation errors.

scala> var x: AnyVal = _
x: AnyVal = null

This one, people expect a compilation error. https://issues.scala-lang.org/browse/SI-1470

Grzegorz Balcerek

unread,
Feb 12, 2013, 6:18:37 AM2/12/13
to scala-l...@googlegroups.com

scala> var x: Any = _
x: Any = null

You would expect a compilation error here? On what grounds? If that's a compilation error then I think they'll all have to be compilation errors.


Because I did not understand on what grounds the compiler assigned the value null here.
Ok, I verified in the spec and it is true that the specification says it should be null ("null for all other types T").
Still, it seems like an arbitrary choice to me. Why is that null and not 0 or false or () ? Is Any biased towards AnyRef somehow?
By the way, according to the specification an AnyVal variable should also get the value of null (because of the same "null for all other types T" statement).

Regards,
Grzegorz

Grzegorz Balcerek

unread,
Feb 12, 2013, 6:30:40 AM2/12/13
to scala-l...@googlegroups.com
How about this? Isn't that weird? 0 == null ?


scala> class A { type X <: Any; var x: X = _ }
defined class A

scala> val a = new A
a: A = A@167198e

scala> a.x
res0: a.X = null

scala> class B extends A { type X = Int }
defined class B

scala> val b = new B
b: B = B@988dd6

scala> val c: A = b
c: A = B@988dd6

scala> b.x
res1: b.X = 0

scala> c.x
res2: c.X = null

scala> b == c
res3: Boolean = true



Regards,
Grzegorz

Grzegorz Balcerek

unread,
Feb 12, 2013, 6:37:32 AM2/12/13
to scala-l...@googlegroups.com
Correction. The last expression is supposed to be:

scala> b.x == c.x
res4: Boolean = true

Grzegorz

Andrew Phillips

unread,
Feb 12, 2013, 10:10:51 AM2/12/13
to scala-l...@googlegroups.com
>  Isn't that weird? 0 == null ?

While trying to run this locally (2.10.0 REPL), I came across this variant:

scala> class A { type X <: Any; var x: X = _ }
defined class A

scala> class B extends A { type X = Int }
defined class B

scala> val a = new A
a: A = A@3d7c4374

scala> a.x
res0: a.X = null

scala> println(a.x)
null

scala> val b = new B
b: B = B@7bc2a4e8

scala> b.x
res2: b.X = 0

scala> println(b.x)
null

scala> val c: A = b
c: A = B@7bc2a4e8

scala> c.x
res4: c.X = null

scala> println(c.x)
null

Decompiling the bytecode [1] doesn't show any signs of any autoboxing or -unboxing that I originally thought might be responsible for the difference. Curious to find out what's going on!

ap

Paul Phillips

unread,
Feb 12, 2013, 10:44:18 AM2/12/13
to scala-l...@googlegroups.com

On Tue, Feb 12, 2013 at 3:18 AM, Grzegorz Balcerek <gbalc...@gmail.com> wrote:
Still, it seems like an arbitrary choice to me. Why is that null and not 0 or false or () ? Is Any biased towards AnyRef somehow?

Absolutely. As are we all, Any is biased toward its future self: Any erases to Object, as does AnyVal.

Paul Phillips

unread,
Feb 12, 2013, 10:48:24 AM2/12/13
to scala-l...@googlegroups.com

On Tue, Feb 12, 2013 at 7:10 AM, Andrew Phillips <share...@gmail.com> wrote:
scala> val b = new B
b: B = B@7bc2a4e8

scala> b.x
res2: b.X = 0

scala> println(b.x)
null

The field x, at the bytecode level, is an Object (it was declared in A and inherited.) B specialized its type to Int, but the same storage is used. That means "uninitialized Int" behavior (as opposed to "uninitialized reference" behavior) depends on the contents of the field being unboxed into an Int.

That happens when you call b.x, because x has type Int. That doesn't happen when you println(b.x), because println takes an Any argument, so the expected type of the expression is Any. Scala doesn't understand any need to translate representations, because the expression has been upcast to Any already. 

scala> println(b.x: Any)
null

scala> println(b.x: Int)
0

Andrew Phillips

unread,
Feb 12, 2013, 11:01:50 AM2/12/13
to scala-l...@googlegroups.com
Thanks for clarifying, Paul!

ap

Oliver Ruebenacker

unread,
Feb 12, 2013, 6:38:27 PM2/12/13
to scala-l...@googlegroups.com
Hello,

On Tue, Feb 12, 2013 at 10:44 AM, Paul Phillips <pa...@improving.org> wrote:
> Absolutely. As are we all, Any is biased toward its future self: Any erases
> to Object, as does AnyVal.

Isn't that a problem if AnyVal erases to Object, considering that
Object can be null, but AnyVal can not? Or is Scala's null different
from Java's null?

Take care
Oliver

--
IT Project Lead at PanGenX (http://www.pangenx.com)
The purpose is always improvement

Paul Phillips

unread,
Feb 12, 2013, 8:12:45 PM2/12/13
to scala-l...@googlegroups.com

On Tue, Feb 12, 2013 at 3:38 PM, Oliver Ruebenacker <cur...@gmail.com> wrote:
Isn't that a problem if AnyVal erases to Object, considering that
Object can be null, but AnyVal can not? Or is Scala's null different
from Java's null?

AnyVal can't be null within scala's type system. The thing we use to hold the AnyVal, it can be null. If you keep your hands and feet inside the vehicle, you'll be safe. If you stick your head out the window...

Reply all
Reply to author
Forward
0 new messages