Open
Description
Compiler version
3.2.2,
3.3.1-RC1-bin-20230328-5c2efc5-NIGHTLY
Minimized code
Transparent Macro:
import scala.quoted.{Quotes,Type,Expr}
// Library part
trait View
// type class
trait ViewOf[M]:
type Out <: View
object ViewOf :
transparent inline def whiteMacro[M]: ViewOf[M] = ${whiteMacroImpl[M]}
def whiteMacroImpl[M:Type](using quotes:Quotes) : Expr[ViewOf[M]] =
val res = Type.of[View] match
case '[tpe] => '{
new ViewOf[M]:
type Out = tpe
}
println(res.show)
res
end whiteMacroImpl
end ViewOf
Usage:
whiteMacro[Nothing]
Output
{
final class $anon() extends refine.ViewOf[scala.Nothing] {
type Out = refine.View
}
(new $anon(): refine.ViewOf[scala.Nothing])
}
Expectation
The returned type is expected to be refined:
{
final class $anon() extends refine.ViewOf[scala.Nothing] {
type Out = refine.View
}
(new $anon(): refine.ViewOf[scala.Nothing] {
type Out >: refine.View <: refine.View
})
}
Observations:
(1) When the upper bound of Out
in trait ViewOf[M]
is removed, correct behavior is restored:
trait ViewOf[M]:
type Out
(2) When the type assigned in the anonymous class does not come from the type match, correct behavior is restored:
case '[tpe] => '{
new ViewOf[M]:
type Out = View
}
(3) When a type ascription is placed on the anonymous class, correct behavior is restored. (thank you, @smarter )
case '[tpe] => '{
(new ViewOf[M]:
type Out = tpe
) : ViewOf[M] { type Out = tpe }
}