Skip to content
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

Compiler and runtime inconsistent as to whether Null <: AnyVal #1470

Open
scabug opened this issue Oct 31, 2008 · 10 comments
Open

Compiler and runtime inconsistent as to whether Null <: AnyVal #1470

scabug opened this issue Oct 31, 2008 · 10 comments
Milestone

Comments

@scabug
Copy link

scabug commented Oct 31, 2008

Neither or both of the following should work, but having one working and not the other is inconsistent:

scala> new Array[AnyVal](2)   
res0: Array[AnyVal] = Array(null, null)

scala> res0(0)
res1: AnyVal = null
scala> val x : AnyVal = null 
<console>:4: error: type mismatch;
 found   : Null(null)
 required: AnyVal
       val x : AnyVal = null
@scabug
Copy link
Author

scabug commented Oct 31, 2008

Imported From: https://issues.scala-lang.org/browse/SI-1470?orig=1
Reporter: @DRMacIver

@scabug
Copy link
Author

scabug commented Nov 4, 2008

@lrytz said:
Postponed until we know more about non-nullable types. The problem also appears in other situations, e.g.

var x: AnyVal = _

@scabug
Copy link
Author

scabug commented Sep 3, 2016

@SethTisue said (edited on Sep 3, 2016 12:18:51 AM UTC):
huge 2016 thread on this at https://groups.google.com/d/msg/scala-user/VRmZ-XrFr0U/zFWJKUovBgAJ . most of the thread is about shenanigans involving asInstanceOf, but you don't actually need asInstanceOf to get into trouble.

one of the "other situations" Lukas mentions is with generic types:

scala> class Sloppy[A] { var value: A = _ }
defined class Sloppy

scala> new Sloppy[Double].value
res14: Double = 0.0

scala> new Sloppy[Double].value: Any
res15: Any = null

scala> new Sloppy[Double].value: AnyVal
res16: AnyVal = null

scala> println(new Sloppy[Double].value)
null

@scabug
Copy link
Author

scabug commented Sep 3, 2016

@SethTisue said:
maybe we should just deprecate this = _ thing. the only time it means something you can really count on is for AnyRef types, in which case you might as well write = null, rather than sneak a null into your program without actually writing "null" into the source. and if someone wants the Any/AnyVal behavior they can always write = null.asInstanceOf[T], raising explicit two red flags right there in the source — again, less sneaking.

@scabug
Copy link
Author

scabug commented Sep 3, 2016

@soc said:
I'd rather wait a bit until we know what we can expect from Java 10 in the future. Maybe it will make things easier, maybe not.

@scabug
Copy link
Author

scabug commented Sep 7, 2016

Oliver Ruebenacker (curoli) said:
Specialization changes the behavior:

object GenInitApp extends App {

class Unspecialized[T] { var x: T = _ }
class Specialized[@specialized(Float) T] { var x: T = _ }

println("Unspecialized x is " + (new Unspecialized[Float]).x)
println("Specialized x is " + (new Specialized[Float]).x)

}

Output is:

Unspecialized x is null
Specialized x is 0.0

@scabug
Copy link
Author

scabug commented Sep 10, 2016

@som-snytt said (edited on Sep 10, 2016 6:33:35 AM UTC):
Without default value syntax, you can't distinguish default value from "reset".

var x: String = if (x == null) null else x  // don't munge early setting

I was just looking at a field that was side-effected from early definition, so the explicit definition would have to be early, too, and not just earlier in the template body.

The comment on the warning:

bq. val bar: X = bar, which come up more frequently than you might think.

@gaelrenoux
Copy link

Adding two cents here: deprecating the val x = _ notation won't be enough, because the problem is also triggered when calling Java parametric classes from Scala. Take this Java class:

public class Producer<A> {
    A get() {
        return null;
    }
}

And call it from Scala:

  val p = new Producer[Boolean]
  val bool = p.get()
  println(bool) // prints "false"
  println(bool.getClass) // prints "boolean"
  println(p.get()) // prints "null"
  println(p.get().getClass) // prints "boolean"

@neonxray
Copy link

@gaelrenoux Starting Scala 3 Dotty, it will actually be a non issue. A variable cannot be assigned to null unless the type is a union type with Null. So in your example, returning null as A is illegal in Scala. As for Java interface, all values from Java library output is implicitly a union type with Null.

@som-snytt
Copy link

Expected type of Any says no unboxing of null:

scala> class C[A] { def get: A = null.asInstanceOf[A] }
defined class C

scala> new C[Boolean].get
res0: Boolean = false

scala> new C[Boolean].get: Any
res1: Any = null

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

4 participants