Scala 3.4.1内联方法展开引发误导性不可达警告是否为Bug?
Scala 3 内联方法的误导性编译器警告问题
当泛型参数T及其所有组件均为具体类型(而非抽象类型参数)时,以下Scala方法可正常运行:
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) // 编译器警告指向此处的下划线 } } } /** 功能等同于当`T`为[[scala.deriving.Mirror.SumOf[A].MirroredElemTypes]]时,[[scala.deriving.Mirror.Sum.ordinal]]的行为 */ inline def indexOfFirstComponentTypeOfTupleToWhichTheArgumentConformsTo[T <: scala.Tuple, A <: Matchable](a: A): Int = { loop[T, A](a, 0) }
问题1:实现处的误导性不可达分支警告
编译器会在case _ => loop[tail, S](s, count + 1)的下划线位置触发警告:
Unreachable case except for null (if this is intentional, consider writing case null => instead)
该警告存在误导性:只有当调用站点的T包含抽象类型参数时,该分支才可能不可达;若T的所有组件均为具体类型,内联方法展开后head会被替换为具体类型,此时这个分支是完全可达的。
但编译器在方法实现阶段就会始终显示该警告,默认假设调用站点的T可能包含抽象类型参数。由于内联方法的展开逻辑正确性依赖调用站点上下文,更合理的处理方式应该是在调用站点触发该警告,避免对合法代码产生误报。
问题2:调用站点的类型检查警告
当添加如下调用代码(此时T的组件为抽象类型参数)时,编译器会触发第二个警告:
the type test for A cannot be checked at runtime
def func[A <: C, B <: C, C <: Matchable](c: C): Int = { indexOfFirstComponentTypeOfTupleToWhichTheArgumentConformsTo[(A, B), C](c) }
这一现象进一步说明:由内联代码引发、且依赖调用站点上下文的警告,应该在调用站点显示,或者与常规警告区分开,以便开发者安全抑制误报。
疑问
上述编译器行为是Scala 3的预期设计,还是应该作为Bug上报?(使用的编译器版本为3.4.1)
内容的提问来源于stack exchange,提问作者Readren
相关产品推荐
相关产品推荐

