簡體   English   中英

Scala 3 宏:來自 class 的泛型類型

[英]Scala 3 macro: generic type from class

我正在使用 Scala 3 宏編程編寫序列化庫。 我想動態生成序列化程序。 因為這是一個庫,所以我不知道編譯過程中序列化器是什么class。 所以我需要一個運行時編譯功能。

代碼:

object CodecMacro {
    import scala.quoted.staging.*
    given Compiler = Compiler.make(getClass.getClassLoader)
    
    // function 1: entry point: a Class object
    def buildSerializer(clazz: Class[_]): Serializer = {
        given staging.Compiler = staging.Compiler.make(getClass.getClassLoader)
        val fn = (qctx: Quotes) ?=> {
            given q: Quotes = qctx
            buildSerializerAdapter(clazz)
        }
        staging.run(fn)
    }
    
    // function 2: convert clazz to generic T
    // My main question is here
    private def buildSerializerAdapter(clazz: Class[_])(using quotes: Quotes): Expr[Serializer] = {
        import quotes.reflect.*
        val tpe: TypeRepr = TypeRepr.typeConstructorOf(clazz)
        val t = tpe.asType
        type T = t.Underlying
        buildSerializerImpl[T]  // error: Missing type parameters for T
    }
    
    // function 3: Using a generic T to generate a Serializer
    private def buildSerializerImpl[T: Type](using quotes: Quotes): Expr[Serializer] = {
        val t = summon[Type[T]]
        '{
            type T = t.Underlying
            new Serializer[T] {
            override def serialize(writer: Writer, value: T): Unit = {
            // Implemetation, not important
            writer.writeString("aaa")
        }
    }
}  

Function 1 是入口點,需要一個 Class object。 Function 3 是最終實現,需要一個泛型類型 T。

Function 2 是從 Class object 轉換為通用類型 T ,這是我的主要問題。

我的解決方案是

    Class ->  TypeRepr  use: TypeRepr.typeConstructorOf(clazz)
    TypeRepr -> Type    use: TypeRepr.asType
    Type -> type T      use: Type.Underlying

我以為Type下的type T會解決我的問題,但是編譯器給了我一個錯誤:“Missing type parameters for T”

在 Function 3 中: type T = t.Underlying value: T
泛型 T 工作正常。

有什么方法可以將 Class object 轉換為通用類型 T?

這是應該完成的方式:

        tpe.asType  match
            case '[t] =>
                buildSerializerImpl[t]

這個非常奇怪的調用直接來自asType 的文檔 這是必要的,因為asType返回一個Type[?] ,其中Type接受任何類型類型,但這里我們需要一個具體的類型類型。 如果類型是更高的類型,例如Type[List]List構造函數采用類型參數),則匹配將失敗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM