这是scalac bug吗? X类[A](val值:A){ def未应用[B o.value} println(pf(字符串)+1) }

这是scalac bug吗? X类[A](val值:A){ def未应用[B o.value} println(pf(字符串)+1) },scala,pattern-matching,classcastexception,partialfunction,Scala,Pattern Matching,Classcastexception,Partialfunction,我认为这段代码应该抛出一个MatchError,而不是ClassCastException。或者scalac应该警告这段代码 Scala 2.11.5 编辑: Scala 2.9.3警告如下,但不是2.10和2.11 Main.scala:8: warning: non variable type-argument B in type pattern X[B] is unchecked since it is eliminated by erasure val pf: PartialFunc

我认为这段代码应该抛出一个
MatchError
,而不是
ClassCastException
。或者scalac应该警告这段代码

Scala 2.11.5

编辑:

Scala 2.9.3警告如下,但不是2.10和2.11

Main.scala:8: warning: non variable type-argument B in type pattern X[B] is unchecked since it is eliminated by erasure
  val pf: PartialFunction[Any, Int] = { case o @ int() => o.value }
                                                    ^
我从一开始就理解类型擦除

换句话说,
pf.isDefinedAt(string)
返回true,但
pf.apply(string)
抛出
ClassCastException

Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_67).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

class X[A](val value: A){
  def unapply[B <: A](x: X[B]) = true
}

val int = new X(1)
val string = new X("a")
val pf: PartialFunction[Any, Int] = { case o @ int() => o.value }

// Exiting paste mode, now interpreting.

defined class X
int: X[Int] = X@4f3cb3fc
string: X[String] = X@1a4c8e08
pf: PartialFunction[Any,Int] = <function1>

scala> pf.isDefinedAt(string)
res0: Boolean = true

scala> pf.apply(string)
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
  at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
  ... 33 elided
欢迎使用Scala 2.11.5版(Java HotSpot(TM)64位服务器虚拟机,Java 1.7.067)。
键入要计算的表达式。
键入:有关详细信息的帮助。
scala>:粘贴
//进入粘贴模式(按ctrl-D键完成)
X类[A](val值:A){
def未应用[B o.value}
//正在退出粘贴模式,现在正在解释。
定义类X
int:X[int]=X@4f3cb3fc
字符串:X[字符串]=X@1a4c8e08
pf:PartialFunction[Any,Int]=
scala>pf.isDefinedAt(字符串)
res0:Boolean=true
scala>pf.apply(字符串)
java.lang.ClassCastException:java.lang.String不能转换为java.lang.Integer
在scala.runtime.BoxesRunTime.unextoint(BoxesRunTime.java:105)中
…33删去

他们竭尽全力:

scala> import reflect._
import reflect._

scala> class X[A: ClassTag](val v: A) { def unapply[B <: A](x: X[B]) = x.v match {
     |   case _: A => true
     |   case _    => false } }
defined class X

scala> val int = new X(1)
int: X[Int] = X@2a5ca609

scala> val s = new X("a")
s: X[String] = X@4667ae56

scala> val pf: PartialFunction[Any, Int] = { case o @ int() => o.v }
pf: PartialFunction[Any,Int] = <function1>

scala> pf(s)
scala.MatchError: X@4667ae56 (of class X)
  at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:253)
  at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:251)
  at $anonfun$1.applyOrElse(<console>:12)
  at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
  ... 33 elided

scala> pf(int)
res1: Int = 1
scala>导入反射_
导入反映_
scala>classx[A:ClassTag](val v:A){def unapply[B true
|大小写{=>false}
定义类X
scala>val int=new X(1)
int:X[int]=X@2a5ca609
scala>val s=新X(“a”)
s:X[字符串]=X@4667ae56
scala>val-pf:PartialFunction[Any,Int]={case o@Int()=>o.v}
pf:PartialFunction[Any,Int]=
scala>pf(s)
scala.MatchError:X@4667ae56(属第X类)
在scala.PartialFunction$$anon$1.apply处(PartialFunction.scala:253)
在scala.PartialFunction$$anon$1.apply处(PartialFunction.scala:251)
在$anonfun$1.应用程序其他(:12)
在scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)中
…33删去
scala>pf(int)
res1:Int=1
但我想你的意思是,如果他们静态地抱怨这个问题,为什么他们不为我插入一个instanceof test?至少在他们可以的时候

scala> val pf: PartialFunction[X[_], Int] = { case o @ int() => o.v }
<console>:12: error: inferred type arguments [_$1] do not conform to method unapply's type parameter bounds [B <: Int]
       val pf: PartialFunction[X[_], Int] = { case o @ int() => o.v }
                                                       ^
<console>:12: error: type mismatch;
 found   : _1
 required: Int
       val pf: PartialFunction[X[_], Int] = { case o @ int() => o.v }
                                                                  ^
scala>val-pf:PartialFunction[X[\ux],Int]={case o@Int()=>o.v}
:12:错误:推断的类型参数[$1]不符合unapply方法的类型参数界限[BO.v}
^
:12:错误:类型不匹配;
找到:_1
必填项:Int
val-pf:PartialFunction[X[_],Int]={case o@Int()=>o.v}
^

使用
任何
都是代码中的一个大问题。当你扔掉你的类型信息时,你不能给编译器出毛病

首先,我将用
X[C]
替换
Any

def pf[C]: PartialFunction[X[C], Int] = { case o @ int() => o.value }
这会导致以下编译错误:

[error] Foo.scala:12: inferred type arguments [C] do not conform to method unapply's type parameter bounds [B <: Int]
[error]   def pf[C]: PartialFunction[X[C], Int] = { case o @ int() => o.value }
[error]                                                      ^
现在我们必须告诉编译器,如果匹配成功,
C
实际上是
Int

def pf[C]: PartialFunction[X[C], Int] = { case o @ int() => o.value.asInstanceOf[Int] }
println(pf(int) + 1)  
println(pf(string) + 1)
这似乎有效:

[info] Running Main 
2
[error] (run-main-7) scala.MatchError: X@1c34aaaa (of class X)
scala.MatchError: X@1c34aaaa (of class X)

看起来像是类型擦除问题,Scala无法区分
X[Int]
X[String]
,因此匹配为正,但函数返回类型为
Int
,而值为
String
def pf[C]: PartialFunction[X[C], Int] = { case o @ int() => o.value.asInstanceOf[Int] }
println(pf(int) + 1)  
println(pf(string) + 1)
[info] Running Main 
2
[error] (run-main-7) scala.MatchError: X@1c34aaaa (of class X)
scala.MatchError: X@1c34aaaa (of class X)