How can I get the equivalent of foo.asInstanceOf[SomeType] in a Scala 3 macro?

35 Views Asked by At

I have this in my macro impl:

def renderJsonFn(rt: RType): Expr[(Any,StringBuilder) => StringBuilder] = 

  val reflectedClassFieldInfo = ???
  val typeMaker = reflectedClassFieldInfo.fieldType.toType // (quotes: Quotes) => TypeRepr
  val fieldType = typeMaker(quotes).asType // Type[? <: AnyKind]

  '{(a:Any, sb:StringBuilder) => 

     val typedA = ?? // <<— need equivalent of a.asInstanceOf[fieldType] here

     val typedFieldValue = ${ 
       Select.unique('{ typedA }.asTerm, someFieldName).asExpr 
     }
     // This fails if I use ‘a’ —> someFieldName is not a member of Any
     // Having a:T is highly impractical—and just moves the problem.  Still need a way to typecast in a macro 
  }
1

There are 1 best solutions below

2
Mateusz Kubuszok On

If you have expr: Expr[A] and AST would typecheck if the expr value was Expr[B] (because it is of this type, just Scala for some reason doesn't know this, e.g. you constructed this expr by hand or received from somewhere as Term) you can use .asExprOf

expr.asExprOf[B] // requires given Type[B]

However if you cannot prove it in the compile time (compiler then should throw exception in the macro, after all you can check expr.asTerm.tpe <:< TypeRepr.of[B]) and you want to create asInstanceOf[B] in the generated code to perform the cast in the runtime, you can just use quoting and unquoting for that

'{ ${ expr }.asInstanceOf[B] } // also requires given Type[B]