2

我正在开发一个 Scala 编译器插件,试图转换每个函数调用,比如

myfuncall(1)

进入

val newvalue = myfuncall(1)
newvalue

但是,当函数调用是另一个函数的返回值时,我会遇到麻烦。这是我要转换的代码

class A[C]
class B[C] extends A[C]

trait MyTrait[C] {
    def func1: A[C]
}

object MyObject extends MyTrait[Int] {
    def func1 = new B
}

在上面的示例中,编译器可以成功推断出 的结果new B应该转换为A[Int],因为func1in应该具有与inMyObject相同的返回类型。func1MyTrait[Int]

但是,当我使用编译器插件进行转换时会出现问题。

class A[C]
class B[C] extends A[C]

trait MyTrait[C] {
    def func1: A[C]
}

object MyObject extends MyTrait[Int] {
    def func1 = { 
        val newvalue = new B
        newvalue
    }
}

现在,newvalue不提供任何额外的类型信息,而是编译器必须推断它。结果类型newvalueB[Nothing],这是编译器可以推断的最具体的类型。

然后当我尝试newvalue作为func1. func1requires A[Int], whilenewvalue是 type B[Nothing],无法匹配。

如果我能提前知道所需的返回类型,问题就可以解决func1,因为我可以newvalue用这个返回类型指定,如下所示

class A[C]
class B[C] extends A[C]

trait MyTrait[C] {
    def func1: A[C]
}

object MyObject extends MyTrait[Int] {
    def func1 = { 
        val newvalue: A[Int] = new B
        newvalue
    }
}

上面的代码可以编译成功。

我的问题是,在编写 Scala 编译器插件时,我怎么知道func1in的返回类型,因为 的签名并没有告诉它的返回类型。MyObjectA[Int]func1

我认为找出编译器如何从in的签名中获取inA[Int]的返回类型也很有帮助。 func1MyObjectfunc1MyTrait[Int]

MyTraitMyObject被定义在两个不同的源文件中时,这个问题就变得更加困难了。

4

0 回答 0