E219: Cannot Instantiate Quoted Type Variable — quoted 패턴의 타입 변수는 new로 만들 수 없어요

E219: Cannot Instantiate Quoted Type Variable — quoted 패턴의 타입 변수는 new로 만들 수 없어요

quoted 패턴 안에서 타입 변수를 new 뒤에 사용하면 이 에러가 발생해요. 매크로에 쓰이는 quoted 패턴에서는 소문자 타입 이름이 "아무 타입이나 맞는" 타입 변수로 취급되는데, 이 타입 변수는 컴파일 타임에 어떤 생성자를 호출해야 할지 알 수 없어서 new로 인스턴스화할 수 없어요.

실제 클래스를 가리키려던 거라면 이름을 백틱으로 감싸서 이스케이프하면 되고, 패턴 매칭에서 인스턴스를 직접 만들어야 한다면 더 저수준인 quotes.reflect API를 사용하는 걸 고려해 보세요.

출처: Scala 3 Reference

본문

Example

import scala.quoted.*

def inspectMacro(x: Expr[Any])(using Quotes): Expr[String] =
  x match
    case '{ new t($arg) } => '{ "found new with arg" }
    case _ => '{ "other" }

Error

-- [E219] Staging Issue Error: example.scala:5:16 ------------------------------
5 |    case '{ new t($arg) } => '{ "found new with arg" }
  |                ^
  |Quoted pattern type variable `t` cannot be instantiated.
  |If you meant to refer to a class named `t`, wrap it in backticks.
  |If you meant to introduce a binding, this is not allowed after `new`. You might
  |want to use the lower-level `quotes.reflect` API instead.
  |Read more about type variables in quoted pattern in the Scala documentation:
  |https://docs.scala-lang.org/scala3/guides/macros/quotes.html#type-variables-in-quoted-patterns
  |

Solution

특정 클래스를 매칭하고 싶다면 백틱으로 이름을 이스케이프하면 됩니다.

import scala.quoted.*

class myClass(val value: Int)

def inspectMacro(x: Expr[Any])(using Quotes): Expr[String] =
  x match
    case '{ new `myClass`($arg) } => '{ "found myClass" }
    case _ => '{ "other" }

new가 얽힌 더 복잡한 패턴 매칭은 quotes.reflect API를 사용해 보세요.

import scala.quoted.*

def inspectMacro(x: Expr[Any])(using Quotes): Expr[String] =
  import quotes.reflect.*
  x.asTerm match
    case Apply(Select(New(tpt), _), args) => '{ "found new expression" }
    case _ => '{ "other" }