Skip to content

Disallow Array[Nothing], Array[Null], ... to avoid ClassCastException in some cases #1730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
smarter opened this issue Nov 21, 2016 · 8 comments

Comments

@smarter
Copy link
Member

smarter commented Nov 21, 2016

See also https://issues.scala-lang.org/browse/SI-7453

In scalac:

scala> if (false) Array("qwe") else Array()
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

In dotty, thankfully:

scala> if (false) Array("qwe") else Array() 
res1: Array[String] | Array[Nothing] = [Ljava.lang.Object;@1dd92fe2

But still in dotty:

scala> val x = if (false) Array("qwe") else Array() 
x: Array[String] | Array[Nothing] = [Ljava.lang.Object;@5454d35e
scala> val y: Array[_ <: String] = x 
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

We either need to disallow Array[Nothing], Array[Null], etc or we need to erase Array[_ <: X] to Object instead of [X;.

It would also be much nicer if we could infer the empty array above to have type Array[String] instead of Array[Nothing], I don't know what prevents us from doing this currently.

@odersky
Copy link
Contributor

odersky commented Nov 21, 2016

Erasing Array[_ <: X] to Object is very expensive computationally, and it would be surprising for users. So I am much in favor of disallowing Array[Nothing] and Array[Null].

@smarter smarter changed the title Array[_ <: X] for all X should be erased to Object to avoid ClassCastException with Array[Nothing] and Array[Null] Disallow Array[Nothing], Array[Null], ... to avoid ClassCastException in some cases Nov 21, 2016
@odersky
Copy link
Contributor

odersky commented Feb 2, 2017

One quite radical idea would be to treat Nothing and Null not as classes but as abstract types. That means we could not generate a ClassTag for them and therefore it would be impossible to create instances of Array[Nothing] and Array[Null]`

@sjrd
Copy link
Member

sjrd commented Feb 2, 2017

If we disallow classTag[Null], then we should also disallow classOf[Null]. This is extreme, as now we have concrete types we cannot a classOf/classTag of anymore. "Treating them as abstract types" seems completely unjustified, other than as a workaround for this implementation limitation related to arrays. This seems wrong to me.

@odersky
Copy link
Contributor

odersky commented Feb 2, 2017

Is classOf[Null] used anywhere?

I have my doubts because in the end there is no class Null on the JVM. We fake one, but it's a hack.

@retronym
Copy link
Member

retronym commented Feb 2, 2017

Here are a few usages I found in projects I've checked out. Seems fairly rare.

⚡ ack --scala 'classOf\[Null\]'

json4s/scalabeans/src/main/scala/org/scalastuff/scalabeans/sig/ScalaTypeCompiler.scala
117:    else if (clazz == "scala.Null") Some(classOf[Null])

scalatra/scalatra/swagger/src/main/scala/org/scalatra/swagger/reflect/Reflector.scala
26:  private[this] val defaultExcluded = Set(classOf[Nothing], classOf[Null])

twitter/util/util-reflect/src/main/scala/com/twitter/util/reflect/Proxy.scala
89:    (rt eq classOf[Unit]) || (rt eq classOf[Null]) || (rt eq java.lang.Void.TYPE)

@nicolasstucki
Copy link
Contributor

Currently in Dotty we have

scala> if (false) Array("qwe") else Array() 
-- Error: <console>:5:36 -------------------------------------------------------
5 |if (false) Array("qwe") else Array()
  |                                    ^
  |attempt to take ClassTag of undetermined type for parameter evidence$2 of method apply in object Array

@odersky can this issue be closed? This was probably fixed in e34555f

@smarter
Copy link
Member Author

smarter commented May 17, 2017

@nicolasstucki No, as stated in the PR that this commit comes from: #1921 (comment)

@odersky
Copy link
Contributor

odersky commented Jan 26, 2018

The comment says that we might want to consider disallowing forming a ClassTag[Null] or ClassTag[Nothing] manually (they are not synthesized anymore). On the other hand, anyone who would do that in a sense does homegrown meta-programming, and it's not clear to what extent we want to give soundness guarantees for such code. So I think it's OK to close for now. If we feel like it, revisit the manual creation issue.

@odersky odersky closed this as completed Jan 26, 2018
smarter added a commit to dotty-staging/dotty that referenced this issue Dec 9, 2022
`typeSymbol` returns NoSymbol on an intersection type, so our previous check
wasn't good enough. See scala#1730 for background.
smarter added a commit to dotty-staging/dotty that referenced this issue Dec 9, 2022
`typeSymbol` returns NoSymbol on an intersection type, so our previous check
wasn't good enough. See scala#1730 for background.
odersky added a commit that referenced this issue Dec 12, 2022
…ference failure (#16492)

The first commit generalizes the fix for #1730, the second commit
improves inference in a common situation to generate a valid ClassTag
rather than emitting an error, fixing the example from
#16328 (comment).
little-inferno pushed a commit to little-inferno/dotty that referenced this issue Jan 25, 2023
`typeSymbol` returns NoSymbol on an intersection type, so our previous check
wasn't good enough. See scala#1730 for background.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants