Scala 奇怪的“匹配可能不详尽”警告
在Scala 2.10.2中 密封抽象A类 海豹{ 密封抽象类B扩展了 最后的C类扩展到B类 最后的D类扩展了B类 最后一类E扩展了A } 对象Main扩展了Foo{ def bar=新C:匹配{ 案例uuC=>C 案例uud=>D 案例u:E=>E } } 编译说 [warn] A.scala:12: match may not be exhaustive. [warn] It would fail on the following inputs: C(), D(), E() [warn] def bar = (new C(): A) match{ 但主键成功并返回c 我做错什么了吗?还是这是scalac bugScala 奇怪的“匹配可能不详尽”警告,scala,pattern-matching,inner-classes,Scala,Pattern Matching,Inner Classes,在Scala 2.10.2中 密封抽象A类 海豹{ 密封抽象类B扩展了 最后的C类扩展到B类 最后的D类扩展了B类 最后一类E扩展了A } 对象Main扩展了Foo{ def bar=新C:匹配{ 案例uuC=>C 案例uud=>D 案例u:E=>E } } 编译说 [warn] A.scala:12: match may not be exhaustive. [warn] It would fail on the following inputs: C(), D(), E() [warn]
不同foo的路径依赖Cs是不同的 这可能就是它抱怨的原因。警告中存在已知的错误。比如 这更好地代表了您的能力,并使警告静音:
def bar(a: A) = a match {
case _: Foo#C => "c" // instanceof Foo$C etc
case _: Foo#D => "d"
case _: Foo#E => "e"
}
更新:还有更多要说的,也就是说,在查看一个不相关的堆栈溢出时。一个真实的,而不是问答网站
简言之,它试图优化嵌套类到其封闭实例的外部指针,如果发生这种情况,则不能再将外部实例包含在匹配中。通常,它会测试instanceof和它的外层是否正确
将条移动到trait中并删除final将禁用优化并修复匹配
public static java.lang.String bar(badseal.Foo, badseal.A);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=4, args_size=2
0: aload_1
1: astore_2
2: aload_2
3: instanceof #9 // class badseal/Foo$D
6: ifeq 26
9: aload_2
10: checkcast #9 // class badseal/Foo$D
13: invokevirtual #13 // Method badseal/Foo$D.badseal$Foo$D$$$outer:()Lbadseal/Foo;
16: aload_0
17: if_acmpne 26
20: ldc #15 // String d
如果内部类是final,scalac至少会抱怨:
badseal.scala:17: warning: The outer reference in this type test cannot be checked at run time.
case _: C => "c"
^
但是,如果匹配在对象中,则此消息的启发式似乎会中断,因此您不再看到它
sealed abstract class A
trait Foo {
sealed abstract class B extends A
class C extends B
class D extends B
class E extends A
def bar(a: A) = a match {
case _: C => "c"
case _: D => "d"
case _: E => "e"
}
}
object X extends Foo
然后
正确警告和正确抛出
apm@mara:~/tmp$ skalac -unchecked badseal.scala ; skala badseal.Test
badseal.scala:11: warning: match may not be exhaustive.
It would fail on the following inputs: C(), D(), E()
def bar(a: A) = a match {
^
one warning found
scala.MatchError: badseal.Foo$C@756bc09d (of class badseal.Foo$C)
不同foo的路径依赖Cs是不同的 这可能就是它抱怨的原因。警告中存在已知的错误。比如 这更好地代表了您的能力,并使警告静音:
def bar(a: A) = a match {
case _: Foo#C => "c" // instanceof Foo$C etc
case _: Foo#D => "d"
case _: Foo#E => "e"
}
更新:还有更多要说的,也就是说,在查看一个不相关的堆栈溢出时。一个真实的,而不是问答网站
简言之,它试图优化嵌套类到其封闭实例的外部指针,如果发生这种情况,则不能再将外部实例包含在匹配中。通常,它会测试instanceof和它的外层是否正确
将条移动到trait中并删除final将禁用优化并修复匹配
public static java.lang.String bar(badseal.Foo, badseal.A);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=4, args_size=2
0: aload_1
1: astore_2
2: aload_2
3: instanceof #9 // class badseal/Foo$D
6: ifeq 26
9: aload_2
10: checkcast #9 // class badseal/Foo$D
13: invokevirtual #13 // Method badseal/Foo$D.badseal$Foo$D$$$outer:()Lbadseal/Foo;
16: aload_0
17: if_acmpne 26
20: ldc #15 // String d
如果内部类是final,scalac至少会抱怨:
badseal.scala:17: warning: The outer reference in this type test cannot be checked at run time.
case _: C => "c"
^
但是,如果匹配在对象中,则此消息的启发式似乎会中断,因此您不再看到它
sealed abstract class A
trait Foo {
sealed abstract class B extends A
class C extends B
class D extends B
class E extends A
def bar(a: A) = a match {
case _: C => "c"
case _: D => "d"
case _: E => "e"
}
}
object X extends Foo
然后
正确警告和正确抛出
apm@mara:~/tmp$ skalac -unchecked badseal.scala ; skala badseal.Test
badseal.scala:11: warning: match may not be exhaustive.
It would fail on the following inputs: C(), D(), E()
def bar(a: A) = a match {
^
one warning found
scala.MatchError: badseal.Foo$C@756bc09d (of class badseal.Foo$C)