当
T
及其所有组件的类型都是特定类型时(与抽象类型参数相反),以下方法可以正常工作。
import scala.compiletime.*
private inline def loop[T <: Tuple, S <: Matchable](s: S, inline count: Int): Int = {
inline erasedValue[T] match {
case _: EmptyTuple.type => throw new MatchError(s)
case _: (head *: tail) => s match {
case _: head => count
case _ => loop[tail, S](s, count + 1) // compiler warning points to the underscore here
}
}
}
/** Does the same that [[scala.deriving.Mirror.Sum.ordinal]] would if `T` was [[scala.deriving.Mirror.SumOf[A].MirroredElemTypes]]. */
inline def indexOfFirstComponentTypeOfTupleToWhichTheArgumentConformsTo[T <: scala.Tuple, A <: Matchable](a: A): Int = {
loop[T, A](a, 0)
}
编译器会发出警告:除了 null 之外无法访问的情况(如果这是故意的,请考虑改为写 case null =>) at
case _ => loop[tail, S](s, count + 1)
我认为这是误导性的,因为只有当调用站点
T
的某个组件的实际类型是抽象类型参数时,该消息才是正确的。
相反,如果 T
的所有组件的类型都是特定的,那么当扩展 inline
方法时,head
表示的类型将是特定的,因此,在这种情况下警告为 false。
我的意思是,编译器总是在
inline
方法的实现中显示警告,假设最坏的情况:调用站点中组成 T
的某些类型是抽象类型参数(不是特定的)。
事实上,内联方法扩展所产生的代码的正确性可能取决于调用位置。至少当内联方法有其他内联子句时。那么,如果在调用站点显示警告以避免在适当情况下正常工作的代码出现错误警告/错误,不是更好吗?
值得注意的是,编译器会显示第二个警告,告诉您“A
的类型测试无法在运行时检查”,但是第二个警告仅在其他地方添加以下调用后出现:传递
T
使得组件的类型是抽象类型参数。 例如添加以下代码后:
def func[A <: C, B <: C, C <: Matchable](c: C): Int = {
indexOfFirstComponentTypeOfTupleToWhichTheArgumentConformsTo[(A, B), C](c)
}
这支持这样的观点:由内联代码引发并且依赖于调用站点的编译器消息应该显示在调用站点上,以便允许正确的代码,否则将被标记为警告/错误。
或者,至少,此类错误/警告应该与常规错误/警告不同,以便可以对其进行抑制,而不必担心重要的错误/警告被压制。问题是,这是编译器的预期行为,还是应该报告为错误?
编译器版本3.4.1
当该方法似乎不适用于
T
及其所有组件的类型都是特定类型时(与抽象类型参数相反),以下方法可以正常工作。
T = (Int, String, Boolean)
和
S = Int
或
Boolean
https://scastie.scala-lang.org/DmytroMitin/zxENZdYnSQW0gcvH5Xmqhw
https://scastie.scala-lang.org/DmytroMitin/zxENZdYnSQW0gcvH5Xmqhw/1
indexOfFirstComponentTypeOfTupleToWhichTheArgumentConformsTo[(Int, String, Boolean), Int](1)
//compile-time error: cannot test if value of type Int is a reference of class String
indexOfFirstComponentTypeOfTupleToWhichTheArgumentConformsTo[(Int, String, Boolean), String]("a")
// compile-time warning: Unreachable case except for null (if this is intentional, consider writing case null => instead).
// runtime: 1
indexOfFirstComponentTypeOfTupleToWhichTheArgumentConformsTo[(Int, String, Boolean), Boolean](true)
//compile-time error: cannot test if value of type Boolean is a reference of class String
模式匹配似乎不安全。无论如何,如果您确定仅在一切正常时才应用您的方法,您可以使用
@unchecked
case _: (head *: tail) => (s: @unchecked) match {
...