abeln / dotty

Scala with explicit nulls
https://github.com/abeln/dotty/wiki/scala-with-explicit-nulls
Other
23 stars 2 forks source link

Don't widen `T|JavaNull` #3

Closed abeln closed 6 years ago

abeln commented 6 years ago

Right now

val l: java.util.ArrayList<String> = new java.util.ArrayList<String>()
val e = l.get(0)

infers Object as the type of e. This probably has to do with https://github.com/lampepfl/dotty/issues/4867

liufengyun commented 6 years ago

It seems to be a bug in Dotty -- no widening should happen here.

It seems to be a different issue from https://github.com/lampepfl/dotty/issues/4867, as the widening happens in assigning types to a ValDef.

class Test {
  val l: java.util.ArrayList[String | Int] = new java.util.ArrayList[String | Int]
  val e1: String | Int = l.get(0) // ok
  val e2 = l.get(0) // widening if the type is inferred
  e2 : String | Int // error
}

The widening logic is in the Namer:

https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/Namer.scala#L1083-L1087

abeln commented 6 years ago

After asking on Gitter, it looks like this is a deliberate decision. Guillaume says:

@abeln Yeah, basically we never infer union types (at the top level) This was changed and debated in lampepfl/dotty#2330 I don't think it's been revisited since then

In #2330, Martin says

This is an attempt at simplifying the way we handle type unions. The central idea is that type unions should be treated analogous to singleton types: We should eliminate them in inferred types unless they are explicitly given.

Guillaume suggested type Nullable[T] = T | Null as a workaround for now, since I guess NonNullable is an "explicitly given" type.

liufengyun commented 6 years ago

Yes, it is good that there is a walkaround.

abeln commented 6 years ago

Fixed by https://github.com/abeln/dotty/commit/afbf2f091e2766aa64aca57e26704537ad143a9f