隐式转换为值的错误消息 类
error messages on implicit conversion to value classes
定义一个接受类型的方法:List[_ <: 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:在警告信息中,为什么编译器会忽略Predef.scala中定义的另外两个"generic to AnyVal"隐式转换?
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)
class returns 一个AnyRef类型的Tuple2。因此,更有用的错误消息可能是 found Tuple2 required AnyVal
?
先回答你的第二个问题。试试这个:
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
。它的真实身份无关紧要。
第一个问题:
以我的理解,隐式作为第一个搜索基础。所以一旦它找到两个并且有歧义,它就会停止抱怨。可能这就是为什么它不尝试使用 StringFormat
等。这可以通过重新排序隐式顺序
在 repl 上确认
implicit class OtherTemp2[T](a:T) extends Temp{
}
implicit class OtherTemp[T](a:T) extends Temp{
}
foo(List[Temp]("asdf"))
编译器抱怨 Arrow
和 OtherTemp2
冲突。如果您重新排序并再次 运行 repl,它会根据首先发现的隐式进行抱怨。
但我找不到证实这一点的官方消息来源。
定义一个接受类型的方法:List[_ <: 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:在警告信息中,为什么编译器会忽略Predef.scala中定义的另外两个"generic to AnyVal"隐式转换?
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)
class returns 一个AnyRef类型的Tuple2。因此,更有用的错误消息可能是 found Tuple2 required AnyVal
?
先回答你的第二个问题。试试这个:
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
。它的真实身份无关紧要。
第一个问题:
以我的理解,隐式作为第一个搜索基础。所以一旦它找到两个并且有歧义,它就会停止抱怨。可能这就是为什么它不尝试使用 StringFormat
等。这可以通过重新排序隐式顺序
implicit class OtherTemp2[T](a:T) extends Temp{
}
implicit class OtherTemp[T](a:T) extends Temp{
}
foo(List[Temp]("asdf"))
编译器抱怨 Arrow
和 OtherTemp2
冲突。如果您重新排序并再次 运行 repl,它会根据首先发现的隐式进行抱怨。
但我找不到证实这一点的官方消息来源。