Description
Skunk's sql
interpolator has a bug in which I am unable to abstract over interpolated Encoder[A]
s because the type arguments are crushed to Nothing
. I have minimized it in the following dumb but small macros.
Compiler version
3.0.0-RC3
Minimized code
Here is a pair of transparent macros. One takes any expression, and if it's a Set
it returns it, annotated with its own type. The other does the same, but with List
.
package test
import scala.quoted._
object Test {
// Invariant (Set)
def inv(arg: Expr[Any])(using Quotes): Expr[Any] =
arg match {
case '{ $h : Set[h] } => '{ $h : Set[h] }
}
transparent inline def inv(inline arg: Any): Any =
${ inv('arg) }
// Covariant (List)
def cov(arg: Expr[Any])(using Quotes): Expr[Any] =
arg match {
case '{ $h : List[h] } => '{ $h : List[h] }
}
transparent inline def cov(inline arg: Any): Any =
${ cov('arg) }
}
Here are some examples. In both cases calling the macros with concrete types works correctly; the passed expression is inlined with the correct type annotation. But in the case where the type argument is a type variable the covariant case works (the type is List[A]
) but in the invariant case the type is Set[Nothing]
rather than Set[A]
.
package test
val inv1: Set[Boolean] = Test.inv(Set(true))
def inv2[A](a: Set[A]): Set[A] = Test.inv(a) // doesn't compile; Set[Nothing] is inferred
val cov1: List[Boolean] = Test.cov(List(true))
def cov2[A](a: List[A]): List[A] = Test.cov(a)
Expectation
My expectation is that this mechanism shouldn't be sensitive to variance.
Notes
The annotated type is important in the code I generate. If I simplify the returned expressions above to simply h
then the examples work, but I can't do this in the actual macro because it causes inference failures downstream.