Different result of inlining if an inline parameter is a Unit #20082
-
I'm running into a behaviour I can't understand when using inlining and unit-typed inline parameters. inline def pipe[T, U](inline t: T, inline f: T => U): U = f(t)
def x(n: Int): Int = 10
def y(n: Unit): Int = 10 I've got a import scala.quoted.*
inline def printTree[T](inline x: T): Unit = ${ printTreeImpl('x) }
def printTreeImpl[T: Type](x: Expr[T])(using qctx: Quotes): Expr[Unit] =
import qctx.reflect.*
println(x.asTerm.show)
'{ () } Now, if I
However, if I do
So in the second case, the parameter is indeed inlined - as I would expect. But in the first one, it's first assigned to a val. Where does the difference come from? ContextYou might wonder - why would this matter? I arrived at the problem when the inline def forever(inline f: Unit): Nothing =
while true do f
throw new RuntimeException("can't get here")
extension [T](inline t: T)
inline def pipe[U](inline f: T => U): U =
f(t) And then, |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 10 replies
-
This has to do with the implementation of the beta-reduction optimization. inline def pipe[T, U](inline t: T, inline f: T => U): U = f(t)
def test1 = pipe((), (u: Unit) => u)
def test2 = pipe(10, (x: Int) => x) These technically get inlined as
but when inlining we also do a best-effort beta-reduction optimization. Semantically, these reduce to
But then we also attempt to elide redundant bindings for constants. This removes the In general, there is no guarantee that the bindings of the beta-reduction will be elided or not. |
Beta Was this translation helpful? Give feedback.
This has to do with the implementation of the beta-reduction optimization.
These technically get inlined as
but when inlining we also do a best-effort beta-reduction optimization. Semantically, these reduce to
But then we also attempt to elide redundant bindings for constants. This removes the
val x
intest2
. TheUnit
value is not exactly pure in bytecode terms as is ends up being a r…