scala / scala3

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

inline given results in malformed macro #15685

Open soronpo opened 2 years ago

soronpo commented 2 years ago

If we change the example from inline given to inline def no errors occur.

Compiler version

v3.2.0-RC2

Minimized code

https://scastie.scala-lang.org/QTG7yUwtRASOb0vRiGDxog

import scala.quoted.*
trait Foo
object Foo:
  inline given foo[T <: Foo]: T = ${ fooMacro[T] }
  def fooMacro[T <: Foo](using Quotes, Type[T]): Expr[T] =
    '{ ??? }

Output

Malformed macro parameter: Playground.Foo.foo[(Playground.Foo & quoted.Type[T])]

Parameters may only be:
 * Quoted parameters or fields
 * Literal values of primitive types
 * References to `inline val`s

Expectation

No error.

nicolasstucki commented 1 year ago

The issue is that when we type the top level splice we get the wrong implicit for Type[T].

inline given foo[T <: Foo]: T = ${ fooMacro[T] }

is typed as

inline given foo[T <: Foo]: T = ${ quotes ?=> fooMacro[T](using quotes, foo[Foo & Type[T]]) }

instead of

inline given foo[T <: Foo]: T = ${ quotes ?=> fooMacro[T](using quotes, Type.of[T]) }
nicolasstucki commented 1 year ago

Workaround

- inline given foo[T <: Foo]: T = ${ fooMacro[T] }
+ inline given foo[T <: Foo]: T = ${ quotes ?=> fooMacro[T](using quotes, Type.of[T]) }
nicolasstucki commented 1 year ago

It seems that in general inline given foo[T <: Foo]: T can be used to create any implicit.

trait Foo
object Foo:
  inline given foo[T <: Foo]: T = summon[Option[T]]
-- Warning: tests/pos-macros/i15685.scala:3:24 ---------------------------------
3 |  inline given foo[T ]: T = summon[Option[T]]
  |                        ^^^^^^^^^^^^^^^^^^^^^
  |                        Infinite loop in function body
  |                        summon[Option[T]](Foo.foo[Nothing]):T