scala / scala3

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

Inconsistency of in inlined implicits in scope #16372

Open nicolasstucki opened 1 year ago

nicolasstucki commented 1 year ago

Compiler version

3.2.1, a1729b03ee7e446ebbd3e5c2bd758669a9da566a

Minimized code

inline def f()(using Int): Int =
  compiletime.summonInline[Int]
inline def g(): Int = {
  given Int = 10
  compiletime.summonInline[Int]
}
def test =
  f()
  g()

Output

-- Error: tests/pos/i16372.scala:9:5 -----------------------------------
9 |  f()
  |     ^
  |     No given instance of type Int was found for parameter x$1 of method f

Expectation

Both examples should find the implicit Int. I expect the binding for the argument of f to be implicitly available.

Larger example ```scala inline def f()(using Int): Int = compiletime.summonInline[Int] inline def g(): Int = { given Int = 10 compiletime.summonInline[Int] } inline def a(): Int = compiletime.summonInline[Int] inline def h(): Int = { given Int = 10 a() } inline def i(using Int): Int = a() def test = f() g() h() i() ```
nicolasstucki commented 1 year ago

There is also the question if the following should work (in #16160):

object O:
  given Int = 0
inline def f(): Int =
  import O._
  compiletime.summonInline[Int]
def test = f()
jchyb commented 1 year ago

I may be mistaken, but I believe it is not that the summonInline from an inlined f() is not able to to find the given Int (supplied here via using Int), but that the using Int in f() (even before inlining) could not find a given to begin with.

With that said, I played with the example a little bit and I would perhaps expect this one to compile:

inline def f(): Int =
  compiletime.summonInline[Int]
inline def g(): Int = {
  given Int = 10
  compiletime.summonInline[Int]
}
def test =
  g()
  f()

as if it was inlined to

def test = 
  given Int = 10
  compiletime.summonInline[Int]
  compiletime.summonInline[Int]

Though maybe it is good that it does not. Is this what you meant?

nicolasstucki commented 1 year ago

This last example would be expanded to

def test = 
  {
    given Int = 10
    compiletime.summonInline[Int]
  }
  compiletime.summonInline[Int]

and that is why the given of g is not in scope for f.