scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.88k stars 1.06k forks source link

Inconsistent type inference with literal types #19689

Open kpodsiad opened 9 months ago

kpodsiad commented 9 months ago

Compiler version

3.3.1

Minimized code

def foo[A](a: A): A          = a
def foo2[A](a: A): Option[A] = Option(a)

val x1 = foo[Int](2)
val x2 = foo[1 | 2 | 3](2)
val x3 = foo2[1 | 2 | 3](2)

val x4 = foo2[1 | 2 | 3](x2)

or

Welcome to Scala 3.3.1 (21.0.1, Java Java HotSpot(TM) 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> def foo[A](a: A): A = a
def foo[A](a: A): A

scala> def foo2[A](a: A): Option[A] = Option(a)
def foo2[A](a: A): Option[A]

scala> foo(2)
val res0: Int = 2

scala> foo[1 | 2 | 3](2)
val res1: Int = 2

scala> foo2[1 | 2 | 3](2)
val res2: Option[1 | 2 | 3] = Some(2)

scala> foo2[1 | 2 | 3](res1)
-- [E007] Type Mismatch Error: -------------------------------------------------
1 |foo2[1 | 2 | 3](res1)
  |                ^^^^
  |                Found:    (res1 : Int)
  |                Required: (1 : Int) | (2 : Int) | (3 : Int)
  |
  | longer explanation available when compiling with `-explain`
1 error found

Output

Found:    (x2 : Int)
Required: (1 : Int) | (2 : Int) | (3 : Int)

or the one from repl.

Expectation

Return type of foo(2) is Int and it's ok, but foo[1 | 2 | 3](2) should have 1 | 2 | 3. At least it is incosistent with foo2[1 | 2 | 3](2) having Option[1 | 2 | 3]

odersky commented 9 months ago

The result type of foo[1 | 2 | 3](2) is an inferred type and is therefore widened to Int. That's a very carefully calibrated behavior which is according to spec. Any change would open a big rabbit hole. Not saying someone should not try it, ever, but this is way to much to ask in an issue and is certainly not a bug.

kpodsiad commented 9 months ago

It's not a big deal as user can provide an explicit type and it'll work. I was just a bit surprised to see difference between foo and foo2, that in the second case it's not widened to Int. Thanks for explanation!