Description
Compiler version
3.0.0-RC3
Minimized example
I am attempting to extract name of the selected field from lambda expression (to create lens-like functionality). I am attempting to remove layers of inlined because of the passing of the lambda as an inline parameter multiple times
//macros definition
import scala.quoted.{given, *}
import deriving.*, compiletime.*
object MacroUtils:
transparent inline def extracNameFromSelector[To, T](inline code: To => T) = ${extractNameFromSelectorImpl('code)}
def extractNameFromSelectorImpl[To: Type, T: Type](code: Expr[To => T])(using Quotes): Expr[String] =
import quotes.reflect.*
val extractors = new Extractors
code.asTerm match
case extractors.InlinedLambda(_, Select(_, name)) => Expr(name)
case t => report.throwError(s"Illegal argument to extractor: ${code.show}, in tasty: $t")
class Extractors(using val quotes: Quotes):
//attempt to strip away consecutive inlines in AST and extract only final lambda
import quotes.reflect.*
object InlinedLambda:
def unapply(arg: Term): Option[(List[ValDef], Term)] =
arg match
case Inlined(_, _, Lambda(vals, term)) => Some((vals, term))
case Inlined(_, _, nested) => InlinedLambda.unapply(nested)
case t => None
end InlinedLambda
end Extractors
end MacroUtils
object Usage:
case class Bar(x: Int, y: String, z: (Double, Double))
MacroUtils.extractNameFromSelector[Bar, String](_.y + "abc")
end Usage
Full example can be found here:
Output
When attempting to compile Usage
I get the following compilation exception:
- "java.lang.ClassCastException: dotty.tools.dotc.ast.Trees$Apply cannot be cast to dotty.tools.dotc.ast.Trees$Select"
When macro is invoked with correct lambda body (for example: _.y
), the following error is reported in the macro instead (but name extraction works fine):
- (at line case extractors.InlinedLambda(, Select(, name)): "the type test for extractors.quotes.reflect.Term cannot be checked at runtime"
I am suspecting that I messed-up imports and I am using wrong extractors (via importing quotes.reflect multiple times or something like that)
Expectation
I am trying to provide nice error message in case passed lambda expression is incorrect (which should be matched correctly given my understanding of quotes.reflect extractors) and also avoid this warning, which hints that for some reason some unsound pattern matching is taking place in macro implementation.