scala / scala3

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

Type refinement lost within nested inline methods #19554

Open soronpo opened 6 months ago

soronpo commented 6 months ago

Compiler version

v3.4.0-RC3

Minimized code

trait Foo{type Out}
transparent inline def foo: Foo = new Foo{type Out = 1}

abstract class ABox
class Box[T] extends ABox
transparent inline def box: ABox =
  val f = foo
  Box[f.Out]

final val x: Box[1] = box //error

Output

Found:    Box[?]
Required: Box[(1 : Int)]

Expectation

No error.

dwijnand commented 6 months ago

Dupe of #8739 (at a glance)

EugeneFlesselle commented 6 months ago

I believe this is the expected behaviour. inline definitions are not inlined within the body of other inline defs, so when typechecking the body of baz below we infer the type y to be Int:

transparent inline def foo(x: Int): Int = x
transparent inline def bar(x: Int): Int = foo(x)
transparent inline def baz(x: Int): Int =
  val y/*: Int*/ = foo(x)
  y

val x1 = bar(0): 0 // OK
val x2 = baz(0): 0 // Error
nicolasstucki commented 6 months ago

This is not exactly the same situation as in https://github.com/lampepfl/dotty/issues/8739.

soronpo commented 6 months ago

Dupe of #8739 (at a glance)

I actually replied with a similar minimization on that issue and completely forgot about it 😃. As I mentioned there, I'm constantly hitting this if it's the same issue. This is not a recursive call though.

nicolasstucki commented 6 months ago

It seems that this issue cobined the issue in https://github.com/lampepfl/dotty/issues/8739 and the minimization above and possibly also an extra hurdle with type avoidance.

Notice that { val f = foo; Box[f.Out] } is ascribed with { val f = foo; Box[f.Out]: Box[?] } to avoid the local reference to f.