在我的项目中,我有一个类型A
,用于一些地方的参数,在这些地方我想将一堆类型自动转换为该类型。我已经在A
的伴随对象中使用一些隐式类实现了这一点。我已删除了触发问题所需的所有内容:
trait A
object A {
implicit class SeqA[T](v: Seq[T])(implicit x: T => A) extends A
implicit class IntA(v: Int) extends A
implicit class TupleA(v: (Int, Int)) extends SeqA(Seq(v._1, v._2))
}
但是scalac
由于非法循环引用而拒绝此代码:
$ scalac -version
Scala compiler version 2.12.8 -- Copyright 2002-2018, LAMP/EPFL and Lightbend, Inc.
$ scalac A.scala
A.scala:5: error: illegal cyclic reference involving class TupleA
implicit class TupleA(v: (Int, Int)) extends SeqA(Seq(v._1, v._2))
^
one error found
这里到底是什么问题?涉及非法小区的编译器打算做什么/推断/解决?
奖励指向实现这些隐式类的有效方法。
答案 0 :(得分:4)
您遇到SI-9553,这是一个三年半的编译器错误。
未修复该错误的原因可能部分是由于存在一种非常简单的解决方法-只需在要扩展的泛型类上放置一个显式类型参数即可:
trait A
object A {
implicit class SeqA[T](v: Seq[T])(implicit x: T => A) extends A
implicit class IntA(v: Int) extends A
implicit class TupleA(v: (Int, Int)) extends SeqA[Int](Seq(v._1, v._2))
}
无论如何,这可能是一个好主意,因为只要您在涉及隐式定义的地方让类型参数被推断出,便会遇到麻烦。
作为旁注,您可以使用-Xprint:typer
之类的编译器选项来调查此类问题。在这种情况下,它在REPL中显示以下内容:
// ...
implicit class TupleA extends $line6.$read.$iw.$iw.A.SeqA[Int] {
<paramaccessor> private[this] val v: (Int, Int) = _;
def <init>(v: (Int, Int)): $line6.$read.$iw.$iw.A.TupleA = {
TupleA.super.<init>(scala.collection.Seq.apply[Int](v._1, v._2))({
((v: Int) => A.this.IntA(v))
});
()
}
};
implicit <synthetic> def <TupleA: error>(v: (Int, Int)): <error> = new TupleA(v)
在这种情况下,这并不是十分有用,但是至少表明问题出在TupleA
隐式类的合成转换方法的定义中,而不是在此之前的某个时刻。 / p>