Scala中Null与T&Null(T<:AnyRef)的类型差异及简化疑问
Scala交集类型简化疑问与验证过程
问题背景
先看这段Scala方法代码:
def toOption[T <: AnyRef](value: T | Null): Option[T] = value match { case null => None case content: T => Some(content) }
检查模式变量content的类型时,IntelliJ显示为T | T & Null,推测这是被检查值value: T | Null与匹配模式content: T的类型交集结果。
由此产生疑问:当T <: AnyRef时,编译器是否应将T & Null简化为Null,使content类型变为T | Null?Null与T & Null类型的区别是什么?
交集类型的两种定义分析
- 若交集类型代表同时属于A、B的值集合:
- 若
T包含null,则交集仅含null;若T不含null,交集为空(即Nothing)。因此T & Null = Null | Nothing = Null。
- 若
- 若交集类型定义为符合
A & B的值需同时满足A、B的类型约束:- 若
null符合T,仅null能同时满足两者;若null不符合T,则没有值能同时满足两者。因此T & Null = Null | Nothing = Null。
- 若
那到底是我忽略了什么细节,还是编译器存在bug?
编辑补充1:IntelliJ显示问题验证
最初用IntelliJ检查类型,之后通过宏验证编译器给出的content实际类型为T,确认是IntelliJ的显示问题,错怪了编译器。宏代码如下:
inline def typeOf[A](a: A): String = ${typeOfMacro[A]('{a})} def typeOfMacro[A : Type](a: Expr[A])(using q: Quotes): Expr[String] = Expr(q.reflect.TypeRepr.of[A].show)
但Scala REPL并未将A & Null(A <: AnyRef)简化为Null,示例如下:
scala> val text: String & Null = null val text: String & Null = null
同时REPL也未将A & Nothing简化为Nothing,问题仍待解答。
编辑补充2:类型理论结论
根据类型理论,不存在类型X使得对任意A,A & X等同于X,因此之前预期的简化逻辑是错误的,REPL给出的类型是正确的,确实是我忽略了相关类型理论细节。
内容的提问来源于stack exchange,提问作者Readren
相关产品推荐
相关产品推荐

