scala / scala3

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

Inconsistency in type inference from function parameters #20114

Open KuceraMartin opened 3 months ago

KuceraMartin commented 3 months ago

Compiler version

3.5.0-RC1-bin-20240405-85672a0-NIGHTLY

Minimized code

opaque type MyInt <: Int = Int
object MyInt:
  def apply(v: Int): MyInt = v

def f1[A, B](box: B => A)(unbox: A => B): B = ???
def f2[A, B](box: B => A): B = ???

@main
def main =
  val a = f1(MyInt.apply)(identity)
  val b = f1(MyInt(_))(identity)
  val c = f2(MyInt.apply)
  val d = f2(MyInt(_))

Output

The types of a, b, c, and d are inferred as MyInt, Int, Nothing, and Int, respectively.

Expectation

In the best possible world, I would like all four vals to be of type Int because box is of type Int => MyInt. Since MyInt <: Int, I can understand why MyInt might be inferred, but I would at least expect the types of a and b to be the same, and also the types of c and d to be the same.

EugeneFlesselle commented 3 months ago

Minimisation:

def foo(v: Int): Any = v
def bar[B](f: B => Any): B = ???

val infersInt = bar(x => foo(x))
val infersNothing = bar(foo)

In the first case, we have an explicit parameter which unifies the two constraints B <: x and x <: Int. Whereas in the second case, the parameter from the expansion (say v) gets a separate type variable (say C). We then have the constraints B <: C, C <: v and v <: Int, but B is instantiated later and hence from below.

EugeneFlesselle commented 3 months ago

18558 is likely related