加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 与宏的奇怪类型不匹配:找到:具有基础类型A的单例类型

发布时间:2020-12-16 19:23:29 所属栏目:安全 来源:网络整理
导读:我有 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} 其中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
}

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

[error] /home/aromanov/IdeaProjects/scala-dry/src/test/scala/com/github/alexeyr/scaladry/SuperTests.scala:80: type mismatch;
[error]  found   : y.type (with underlying type B)
[error]  required: B
[error]             override def foo[B](x: A,y: B) = superCall
[error]                                               ^

这对我来说没有意义:y.type比B更窄,所以如果在需要B时找到它,那么它应该不是错误.更奇怪的是,如果我用它的扩展super.foo [x](x,y)替换superCall,那么错误就会消失!

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

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)"
}

编辑:添加-uniqid显示

[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

这解释了错误是如何可能的,但没有解释2 B是如何不同的.我尝试将B重命名为C,以防其中一个引用Foo.foo的B,但它仍然显示C有2个不同的ID,即使程序中只有一个C.

编辑2:见Scala typer stage says two uses of type parameter are different.树形成器在这里产生(用super.foo [B](x,y)而不是superCall)是

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)
};

所以似乎superCall扩展到Bar#26820.super.foo#26823 [B#26833](x#26836,y#26837).

解决方法

你试图通过类型参数的名称来回输你的类型信息,从而使你的生活更加艰难 – 简单的名称是一种非常有损的交换媒介 – 但你为什么要提供类型参数呢?如果没有相反的证据,你应该写q“super.$methodName(… $args)”并推断出它们.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读