我正在开发一个 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]
,因为func1
in应该具有与inMyObject
相同的返回类型。func1
MyTrait[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
不提供任何额外的类型信息,而是编译器必须推断它。结果类型newvalue
是B[Nothing]
,这是编译器可以推断的最具体的类型。
然后当我尝试newvalue
作为func1
. func1
requires 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 编译器插件时,我怎么知道func1
in的返回类型,因为 的签名并没有告诉它的返回类型。MyObject
A[Int]
func1
我认为找出编译器如何从in的签名中获取inA[Int]
的返回类型也很有帮助。 func1
MyObject
func1
MyTrait[Int]
当MyTrait
和MyObject
被定义在两个不同的源文件中时,这个问题就变得更加困难了。