Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 奇怪的类型与宏不匹配:找到:singleton类型与基础类型a,必需:a_Scala_Scala Macros_Scala Reflect - Fatal编程技术网

Scala 奇怪的类型与宏不匹配:找到:singleton类型与基础类型a,必需:a

Scala 奇怪的类型与宏不匹配:找到:singleton类型与基础类型a,必需:a,scala,scala-macros,scala-reflect,Scala,Scala Macros,Scala Reflect,我有 其中,superCallwhitebox宏应该扩展到super.foo[B](x,y),这就是-Ymacro-debug-lite显示的内容。问题是它无法编译,出现以下错误: class Foo[A] { def foo[B](x: A, y: B) = y } class Bar[A] extends Foo[A] { override def foo[B](x: A, y: B) = superCall } 这对我来说毫无意义:y.type比B更窄,所以如果在需要B时找到它

我有

其中,
superCall
whitebox宏应该扩展到
super.foo[B](x,y)
,这就是
-Ymacro-debug-lite
显示的内容。问题是它无法编译,出现以下错误:

class Foo[A] {
  def foo[B](x: A, y: B) = y
}

class Bar[A] extends Foo[A] {
  override def foo[B](x: A, y: B) = superCall
}
这对我来说毫无意义:
y.type
B
更窄,所以如果在需要
B
时找到它,应该不会是错误。更奇怪的是,如果我用它的扩展名
super.foo[B](x,y)
替换
superCall
,错误就会消失

superCall
实现(通过删除不相关的条件稍微简化,您可以看到完整版本):

编辑:添加
-uniqid
显示

def superCall: Tree = {
  val method = c.internal.enclosingOwner.asMethod
  val args = method.paramLists.map(_.map(sym => c.Expr(q"$sym")))
  val typeParams = method.typeParams.map(_.asType.name)
  q"super.${method.name.toTermName}[..$typeParams](...$args)"
}
这解释了错误是如何可能的,但没有解释2
B
的不同之处。我尝试将
B
重命名为
C
,以防其中一个引用了
Foo.Foo
B
,但它仍然使用两个不同的ID显示
C
,即使程序中只有一个
C

编辑2:请参见。树型打字机在这里生成(使用
super.foo[B](x,y)
而不是
superCall
)是

class Foo#26818[A#26819]扩展了scala#22.AnyRef#2757{
def#26822():Foo#26818[A#26819]={
Foo#26818.super.#3104();
()
};
def foo 26823[B#26824](x#26827:A#26819,y#26828:B#26825):B#26824=y#26828
};
类栏"26820[A"26821]扩展了Foo"26818[A"26821]{
def#26831():Bar#26820[A#26821]={
Bar#26820.super.#26822();
()
};
覆盖def foo 26832[B#26833](x#26836:A#26821,y#26837:B#26834):B#26833=Bar#26820.super.foo#26823[B#26834](x#26836,y#26837)
};

因此,似乎
superCall
扩展为
Bar#26820.super.foo#26823[B#26833](x#26836,y#26837)
相反。

您试图通过类型参数的名称将您的类型信息传回,这让您的生活更加艰难。简单的名称是一种非常有损的交换媒介。但是,您为什么要提供类型参数呢?在没有相反证据的情况下,您应该编写
q“super.$methodName(…$args)”
,它们将被推断出来。

args
更改为
method.paramLists.map(u.map(u.asTerm.name))
应该可以工作,尽管我不确定目前我是否能很好地解释为什么。@TravisBrown它确实适用于这种情况!不幸的是,它破坏了一个不同的测试(当参数被隐藏时,我想使用原始参数)。嗯,在这种情况下,也许我应该抛出一个错误,或者至少是一个警告。请参阅未提供类型参数无法编译的示例。如何提供除名称以外的类型参数?如果我通过了
TypeSymbol
s,我会得到“无法取消引用列表[supermpl.this.c.universe.TypeSymbol]”。这是要点,哦,是的,我一毫秒都忘了在任何给定的努力下还有很多其他的bug。类型参数是类型,而不是符号。试试。asType.toType。那种可怕的.asType.toType让我想起这一切是多么疯狂。祝你好运我尝试过,但不幸的是,它导致了类型不匹配(不管我是按照Travis Brown的建议使用
asTerm.name
,还是像我最初在
args
中使用的那样使用
q“$sym”
)。
def superCall: Tree = {
  val method = c.internal.enclosingOwner.asMethod
  val args = method.paramLists.map(_.map(sym => c.Expr(q"$sym")))
  val typeParams = method.typeParams.map(_.asType.name)
  q"super.${method.name.toTermName}[..$typeParams](...$args)"
}
[error]  found   : y#26847.type (with underlying type B#26833)
[error]  required: B#26834
[error]             override def foo[B](x: A, y: B) = superCall
[error]                                               ^
[error] one error found
class Foo#26818[A#26819] extends scala#22.AnyRef#2757 {
  def <init>#26822(): Foo#26818[A#26819] = {
    Foo#26818.super.<init>#3104();
    ()
  };
  def foo#26823[B#26824](x#26827: A#26819, y#26828: B#26825): B#26824 = y#26828
};
class Bar#26820[A#26821] extends Foo#26818[A#26821] {
  def <init>#26831(): Bar#26820[A#26821] = {
    Bar#26820.super.<init>#26822();
    ()
  };
  override def foo#26832[B#26833](x#26836: A#26821, y#26837: B#26834): B#26833 = Bar#26820.super.foo#26823[B#26834](x#26836, y#26837)
};