隐式转换为值类的错误消息

时间:2016-09-23 06:53:21

标签: scala implicit-conversion

定义一个接受类型的方法:List [_&lt ;: AnyVal]

def foo(x : List[_ <: AnyVal]) = x 

尝试使用AnyRef:

foo(List(new Test))

error: type mismatch;
 found   : Test
 required: AnyVal
Note that implicit conversions are not applicable because they are ambiguous:
 both method ArrowAssoc in object Predef of type [A](self: A)ArrowAssoc[A]
 and method Ensuring in object Predef of type [A](self: A)Ensuring[A]
 are possible conversion functions from Test to AnyVal

问题1:在警告消息中,为什么编译器会忽略其他两个&#34;泛化为AnyVal&#34; Predef.scala中定义的隐式转换?

final implicit class StringFormat[A] extends AnyVal
final implicit class any2stringadd[A] extends AnyVal

删除先前的歧义并强制编译器使用ArrowAssoc隐式转换:

foo(List(new Test -> 1))

error: the result type of an implicit conversion must be more specific than AnyVal

问题2:此错误消息暗示什么?令人困惑。 ArrowAssoc类中的方法def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y)返回一个AnyRef类型的Tuple2。那么,更有用的错误消息可能是found Tuple2 required AnyVal

1 个答案:

答案 0 :(得分:2)

首先回答你的第二个问题。试试这个:

class Temp

implicit class Arrow[T](a:T) extends Temp{
  def -->[B](b:B) = (a,b)
}
def foo(x : List[_ <: Temp]) = x

scala>     foo(List(1 --> 2))
res0: List[Temp] = List(Arrow@2e17a321)

这可以按预期工作。它没有抱怨,因为它正在搜索Temp而不是Tuple2。 现在介绍歧义:

implicit class OtherTemp[T](a:T) extends Temp{}
foo(List(1 --> 2)) //compile error

它没有抱怨碰撞。所以回答你关于为什么它没有显示AnyRef的问题是因为:

记得ArrowAssoc正在调用以获得AnyVal代表。对于->,它有一个Tuple2并且正在尝试检索AnyVal。由于无法检索AnyVal,因此无法转换为AnyVal时将其标记为错误。它的真实身份是无关紧要的。

对于第一个问题: 根据我的理解,implicits作为第一搜索基础。因此,一旦发现两个并且存在歧义,它就会退出抱怨。可能这就是为什么它不会尝试使用StringFormat等。这可以通过重新排序隐式订单在repl上确认

implicit class OtherTemp2[T](a:T) extends Temp{
}
implicit class OtherTemp[T](a:T) extends Temp{
}

foo(List[Temp]("asdf"))

编译器以ArrowOtherTemp2作为冲突投诉。如果您重新订购并再次运行repl,它会根据首先发现的隐式进行投诉。 但我找不到一个证实这一点的官方消息来源。