Empty Arrays of Nothing

147 views
Skip to first unread message

Miles Sabin

unread,
Jan 20, 2013, 3:03:08 PM1/20/13
to scala-internals
This appears to be a change in behaviour between 2.10.x and 2.11.0-SNAPSHOT,

Welcome to Scala version 2.11.0-20130116-203322-1dc6a99edc (Java
HotSpot(TM) 64-Bit Server VM, Java 1.7.0_05).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.collection.generic.CanBuildFrom
import scala.collection.generic.CanBuildFrom

scala> implicitly[CanBuildFrom[Nothing, Nothing, Array[Nothing]]]
<console>:9: error: Cannot construct a collection of type
Array[Nothing] with elements of type Nothing based on a collection of
type Nothing.
implicitly[CanBuildFrom[Nothing, Nothing, Array[Nothing]]]

The issue here is the lack of consistency between Array and non-array
collection types,

scala> List[Nothing]()
res0: List[Nothing] = List()

scala> new Array[Nothing](0)
res1: Array[Nothing] = Array()

scala> val cbf1 = implicitly[CanBuildFrom[Nothing, Nothing, List[Nothing]]]
cbf1: scala.collection.generic.CanBuildFrom[Nothing,Nothing,List[Nothing]]
= scala.collection.generic.GenTraversableFactory$$anon$1@61bb1e36

scala> cbf1().result
res2: List[Nothing] = List()

scala> val cbf2 = implicitly[CanBuildFrom[Nothing, Nothing, Array[Nothing]]]
<console>:8: error: Cannot construct a collection of type
Array[Nothing] with elements of type Nothing based on a collection of
type Nothing.
val cbf2 = implicitly[CanBuildFrom[Nothing, Nothing, Array[Nothing]]]

Intentional change? Regression?

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
skype: milessabin
gtalk: mi...@milessabin.com
g+: http://www.milessabin.com
http://twitter.com/milessabin

Paul Phillips

unread,
Jan 20, 2013, 5:44:50 PM1/20/13
to scala-i...@googlegroups.com

On Sun, Jan 20, 2013 at 12:03 PM, Miles Sabin <mi...@milessabin.com> wrote:
Intentional change? Regression?

Don't know, but here's the guilty commit. This is - yet, yet, yet, yet, again - a consequence of using "Nothing" to mean both "undetermined type parameter" and to mean "Nothing". We should have fixed this years ago. I know it works to change it; I fixed a subset of the open Nothing-related bugs that way a while ago, but I never crossed the finish line.

% git show fe60284769
commit fe6028476931b031e712c37d3e570125b1d034ae
Author: Eugene Burmako <xen...@gmail.com>
Date:   3 weeks ago

    SI-5923 adapt macros when they are deferred
    
    Amazingly enough, the fix for the "macro not expanded" problem was super
    easy. (And I remember spending a day or two trying to find a quick fix
    somewhen around Scala Days 2012!)
    
    The problem was in the implementation of the macro expansion trigger,
    which was buried in a chain of if-elif-elif. This meant that macro
    expansion was mutually exclusive with a lot of important adaptations, e.g.
    with `instantiate`.
    
    More precisely, if an expandee contains an undetparam, its expansion
    should be delayed until all its undetparams are inferred and then retried
    later. Sometimes such inference can only happen upon a call to instantiate
    in one of the elif's coming after the macro expansion elif. However this
    elif would never be called for expandees, because control flow would always
    enter the macro expansion branch preceding the inference branch.
    
    Consequences of this fix are vast. First of all, we can get rid of the
    "type parameter must be specified" hack. Secondly and most importantly,
    we can now remove the `materializeImplicit` method from Implicits and
    rely on implicit macros to materialize tags for us. (This is a tricky
    change, and I'll do it later after we merge as much of my pending work
    as possible). Finally, we learn that the current scheme of interaction
    between macros, type inference and implicits is, in principle, sound!

Paolo G. Giarrusso

unread,
Jan 20, 2013, 5:49:21 PM1/20/13
to scala-i...@googlegroups.com
Il giorno domenica 20 gennaio 2013 23:44:50 UTC+1, Paul Phillips ha scritto:

On Sun, Jan 20, 2013 at 12:03 PM, Miles Sabin <mi...@milessabin.com> wrote:
Intentional change? Regression?

Don't know, but here's the guilty commit. This is - yet, yet, yet, yet, again - a consequence of using "Nothing" to mean both "undetermined type parameter" and to mean "Nothing". We should have fixed this years ago. I know it works to change it; I fixed a subset of the open Nothing-related bugs that way a while ago, but I never crossed the finish line.
Care to open an issue for it and attach your code? That might help anybody wanting to take it over.

Paul Phillips

unread,
Jan 20, 2013, 5:59:04 PM1/20/13
to scala-i...@googlegroups.com

On Sun, Jan 20, 2013 at 2:49 PM, Paolo G. Giarrusso <p.gia...@gmail.com> wrote:
Care to open an issue for it and attach your code? That might help anybody wanting to take it over.

Here are some of the issues already open. It is unlikely someone else will get anywhere with it: vast are the number of places in the compiler code which make assumptions about Nothing. I'll see if there's something remotely publishable though.


Eugene Burmako

unread,
Apr 28, 2013, 7:49:54 AM4/28/13
to scala-i...@googlegroups.com
Luckily the problem had nothing to do with the inferencer treating Nothing in a special way. That was just a bug in my implementation, which is now fixed: https://github.com/scala/scala/pull/2464

Paul Phillips

unread,
Apr 28, 2013, 11:33:20 AM4/28/13
to scala-i...@googlegroups.com

On Sun, Apr 28, 2013 at 4:49 AM, Eugene Burmako <eugene....@epfl.ch> wrote:
Luckily the problem had nothing to do with the inferencer treating Nothing in a special way. That was just a bug in my implementation, which is now fixed: https://github.com/scala/scala/pull/2464

Here is the issue with Array lubs:

For a type CC[T] where T is invariant, the lub of CC[A] and CC[B] should be

  CC[T] forSome { type T >: glb(A, B) <: lub(A, B) }.

But if A=Nothing, that is simplified to

  CC[T] forSome { type T <: B }

You can usually get away with this. Take Set for instance. If you make a list with a Set[Nothing] and a Set[Int] in it, it will appear as a Set[_ <: Int]. Since you can't get any values out of a Set[Nothing], nor put any into it, erasure protects you from the lie being revealed. There is nothing but a "Set" there under the hood.

With Arrays, there is storage and the storage has a type which is stronger than "Array". That means if you discard any information when taking the lub, you risk failing at runtime. The lub of Array[Nothing] and Array[Int] has to be

  Array[T] forSome { type T <: Int with Nothing }

In other words it cannot simplify "Int with Nothing" to "Int" as it does at present. It is not safe to replace "A with B" with "A" in an existential bound, even when B is a subtype of A.

Paul Phillips

unread,
Apr 28, 2013, 12:23:59 PM4/28/13
to scala-i...@googlegroups.com
Before:

pre/post erasure lubs of            Array[Any] and Array[Any]            are            Array[Any] <and> Array[Any]
pre/post erasure lubs of            Array[Any] and Array[Array[Int]]     are              Array[_] <and> Array[Any]
pre/post erasure lubs of            Array[Any] and Array[Array[String]]  are              Array[_] <and> Array[Any]
pre/post erasure lubs of            Array[Any] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of            Array[Any] and Array[Nothing]        are              Array[_] <and> Array[Any]
pre/post erasure lubs of            Array[Any] and Array[Null]           are              Array[_] <and> Array[Any]
pre/post erasure lubs of            Array[Any] and Array[Object]         are              Array[_] <and> Array[Object]
pre/post erasure lubs of            Array[Any] and Array[String]         are              Array[_] <and> Array[Any]
pre/post erasure lubs of     Array[Array[Int]] and Array[Array[Int]]     are     Array[Array[Int]] <and> Array[Array[Int]]
pre/post erasure lubs of  Array[Array[String]] and Array[Array[Int]]     are              Array[_] <and> Array[Object]
pre/post erasure lubs of  Array[Array[String]] and Array[Array[String]]  are  Array[Array[String]] <and> Array[Array[String]]
pre/post erasure lubs of  Array[Array[String]] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[Object]         are              Array[_] <and> Array[Object]
pre/post erasure lubs of            Array[Int] and Array[Any]            are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Array[Int]]     are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Array[String]]  are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Int]            are            Array[Int] <and> Array[Int]
pre/post erasure lubs of            Array[Int] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Nothing]        are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Object]         are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[String]         are              Array[_] <and> Object
pre/post erasure lubs of           Array[Long] and Array[Array[Int]]     are              Array[_] <and> Object
pre/post erasure lubs of           Array[Long] and Array[Long]           are           Array[Long] <and> Array[Long]
pre/post erasure lubs of           Array[Long] and Array[Object]         are              Array[_] <and> Object
pre/post erasure lubs of        Array[Nothing] and Array[Array[Int]]     are              Array[_] <and> Array[Array[Int]]
pre/post erasure lubs of        Array[Nothing] and Array[Array[String]]  are              Array[_] <and> Array[Array[String]]
pre/post erasure lubs of        Array[Nothing] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of        Array[Nothing] and Array[Nothing]        are        Array[Nothing] <and> Array[Nothing]
pre/post erasure lubs of        Array[Nothing] and Array[Object]         are              Array[_] <and> Array[Object]
pre/post erasure lubs of           Array[Null] and Array[Array[Int]]     are              Array[_] <and> Array[Array[Int]]
pre/post erasure lubs of           Array[Null] and Array[Array[String]]  are              Array[_] <and> Array[Array[String]]
pre/post erasure lubs of           Array[Null] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of           Array[Null] and Array[Nothing]        are              Array[_] <and> Array[Null]
pre/post erasure lubs of           Array[Null] and Array[Null]           are           Array[Null] <and> Array[Null]
pre/post erasure lubs of           Array[Null] and Array[Object]         are              Array[_] <and> Array[Object]
pre/post erasure lubs of         Array[Object] and Array[Array[Int]]     are              Array[_] <and> Array[Object]
pre/post erasure lubs of         Array[Object] and Array[Object]         are         Array[Object] <and> Array[Object]
pre/post erasure lubs of         Array[String] and Array[Array[Int]]     are              Array[_] <and> Array[Object]
pre/post erasure lubs of         Array[String] and Array[Array[String]]  are              Array[_] <and> Array[Object]
pre/post erasure lubs of         Array[String] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of         Array[String] and Array[Nothing]        are              Array[_] <and> Array[String]
pre/post erasure lubs of         Array[String] and Array[Null]           are              Array[_] <and> Array[String]
pre/post erasure lubs of         Array[String] and Array[Object]         are              Array[_] <and> Array[Object]
pre/post erasure lubs of         Array[String] and Array[String]         are         Array[String] <and> Array[String]

After:

pre/post erasure lubs of            Array[Any] and Array[Any]            are            Array[Any] <and> Array[Any]
pre/post erasure lubs of            Array[Any] and Array[Array[Int]]     are              Array[_] <and> Object
pre/post erasure lubs of            Array[Any] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of            Array[Any] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of     Array[Array[Int]] and Array[Array[Int]]     are     Array[Array[Int]] <and> Array[Array[Int]]
pre/post erasure lubs of     Array[Array[Int]] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of     Array[Array[Int]] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[Any]            are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[Array[Int]]     are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[Array[String]]  are  Array[Array[String]] <and> Array[Array[String]]
pre/post erasure lubs of  Array[Array[String]] and Array[Int]            are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[Nothing]        are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[Object]         are              Array[_] <and> Object
pre/post erasure lubs of  Array[Array[String]] and Array[String]         are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Any]            are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Array[Int]]     are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Int]            are            Array[Int] <and> Array[Int]
pre/post erasure lubs of            Array[Int] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Nothing]        are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[Object]         are              Array[_] <and> Object
pre/post erasure lubs of            Array[Int] and Array[String]         are              Array[_] <and> Object
pre/post erasure lubs of           Array[Long] and Array[Long]           are           Array[Long] <and> Array[Long]
pre/post erasure lubs of           Array[Long] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of        Array[Nothing] and Array[Any]            are              Array[_] <and> Object
pre/post erasure lubs of        Array[Nothing] and Array[Array[Int]]     are              Array[_] <and> Object
pre/post erasure lubs of        Array[Nothing] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of        Array[Nothing] and Array[Nothing]        are        Array[Nothing] <and> Array[Nothing]
pre/post erasure lubs of        Array[Nothing] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of           Array[Null] and Array[Null]           are           Array[Null] <and> Array[Null]
pre/post erasure lubs of         Array[Object] and Array[Any]            are              Array[_] <and> Object
pre/post erasure lubs of         Array[Object] and Array[Array[Int]]     are              Array[_] <and> Object
pre/post erasure lubs of         Array[Object] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of         Array[Object] and Array[Nothing]        are              Array[_] <and> Object
pre/post erasure lubs of         Array[Object] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of         Array[Object] and Array[Object]         are         Array[Object] <and> Array[Object]
pre/post erasure lubs of         Array[String] and Array[Any]            are              Array[_] <and> Object
pre/post erasure lubs of         Array[String] and Array[Array[Int]]     are              Array[_] <and> Object
pre/post erasure lubs of         Array[String] and Array[Long]           are              Array[_] <and> Object
pre/post erasure lubs of         Array[String] and Array[Nothing]        are              Array[_] <and> Object
pre/post erasure lubs of         Array[String] and Array[Null]           are              Array[_] <and> Object
pre/post erasure lubs of         Array[String] and Array[Object]         are              Array[_] <and> Object
pre/post erasure lubs of         Array[String] and Array[String]         are         Array[String] <and> Array[String]
Reply all
Reply to author
Forward
0 new messages