scala/scala3

`transparent` modifier doesn't work in splices

Closed this issue · 1 comments

Compiler version

3.6.3

Minimized code

import scala.quoted.*

def foo(using Quotes): Expr[Int] =
  '{ assert(false) }
//   ^^^^^^^^^^^^^
// Found:    Unit
// Required: Int

transparent inline def transp: Any = (1: Int)

def bar(using Quotes): Expr[Int] =
  '{ transp }
//   ^^^^^^
// Found:    Any
// Required: Int

Output

[error] -- [E007] Type Mismatch Error: main.scala:9:11 
[error] 9 |  '{ assert(false) }
[error]   |     ^^^^^^^^^^^^^
[error]   |     Found:    Unit
[error]   |     Required: Int
[error]   |
[error] -- [E007] Type Mismatch Error: main.scala:17:5 
[error] 17 |  '{ transp }
[error]    |     ^^^^^^
[error]    |     Found:    Any
[error]    |     Required: Int

Expectation

This should compile

Hi @t9dupuy,
This is expected behavior. The inline method calls inserted into quoted code (the one with '{...}) are inlined only after that quoted code itself is inlined (so after the macro expansion). In general, inline methods cannot be inlined into another inline method until after that method itself is inlined.
E.g.:

def call(num: Int) = ???
transparent inline def a(): Any = 0
transparent inline def b(): Any = call(a()) // if the `transparent inline` is removed, it works

will show a similar error:

-- [E007] Type Mismatch Error: test.scala:3:28 ----------------------------------
3 |inline def b(): Any = call(a()) // if the `inline` is removed, it works
  |                           ^^^
  |                           Found:    Any
  |                           Required: Int
  |
  | longer explanation available when compiling with `-explain`

For the transparent keyword to be taken into account by the type checker, the method has to be inlined first.