blob: fb0b491d391edd545167d66dff3e5590ae2964a4 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
// abstract types and extractors, oh my!
trait TypesAPI {
trait Type
// an alternative fix (implemented in the virtual pattern matcher, is to replace the isInstanceOf by a manifest-based run-time test)
// that's what typeRefMani is for
type TypeRef <: Type //; implicit def typeRefMani: Manifest[TypeRef]
val TypeRef: TypeRefExtractor; trait TypeRefExtractor {
def apply(x: Int): TypeRef
def unapply(x: TypeRef): Option[(Int)]
}
// just for illustration, should follow the same pattern as TypeRef
case class MethodType(n: Int) extends Type
}
// user should not be exposed to the implementation
trait TypesUser extends TypesAPI {
def shouldNotCrash(tp: Type): Unit = {
tp match {
case TypeRef(x) => println("TypeRef")
case MethodType(x) => println("MethodType")
case _ => println("none of the above")
}
}
}
trait TypesImpl extends TypesAPI {
object TypeRef extends TypeRefExtractor // this will have a bridged unapply(x: Type) = unapply(x.asInstanceOf[TypeRef])
case class TypeRef(n: Int) extends Type // this has a bridge from TypesAPI#Type to TypesImpl#TypeRef
// --> the cast in the bridge will fail because the pattern matcher can't type test against the abstract types in TypesUser
//lazy val typeRefMani = manifest[TypeRef]
}
trait Foos {
trait Bar
type Foo <: Bar
trait FooExtractor {
def unapply(foo: Foo): Option[Int]
}
val Foo: FooExtractor
}
trait RealFoos extends Foos {
class Foo(val x: Int) extends Bar
object Foo extends FooExtractor {
def unapply(foo: Foo): Option[Int] = Some(foo.x)
}
}
trait Intermed extends Foos {
def crash(bar: Bar): Unit =
bar match {
case Foo(x) => println("Foo")
case _ => println("Bar")
}
}
object TestUnappStaticallyKnownSynthetic extends TypesImpl with TypesUser {
def test() = {
shouldNotCrash(TypeRef(10)) // should and does print "TypeRef"
// once #1697/#2337 are fixed, this should generate the correct output
shouldNotCrash(MethodType(10)) // should print "MethodType" but prints "none of the above" -- good one, pattern matcher!
}
}
object TestUnappDynamicSynth extends RealFoos with Intermed {
case class FooToo(n: Int) extends Bar
def test() = {
crash(FooToo(10))
crash(new Foo(5))
}
}
object Test extends App {
TestUnappStaticallyKnownSynthetic.test()
TestUnappDynamicSynth.test()
}
|