From 5cc3dad991cde9c55c49c451a93a496a16b3afe1 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 8 Nov 2011 11:36:30 +0000 Subject: smarter bridges to unapplies wraps the call to a bridged synthetic unapply(Seq) in a defensive if-test: if (x.isInstanceOf[expectedType]) real.unapply(x.asInstanceOf[expectedType]) else None NOTE: the test is WRONG, but it has to be due to #1697/#2337 -- once those are fixed, this one should generate the expected output --- test/files/run/patmat_unapp_abstype.check | 2 ++ test/files/run/patmat_unapp_abstype.scala | 39 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 test/files/run/patmat_unapp_abstype.check create mode 100644 test/files/run/patmat_unapp_abstype.scala (limited to 'test/files') diff --git a/test/files/run/patmat_unapp_abstype.check b/test/files/run/patmat_unapp_abstype.check new file mode 100644 index 0000000000..ac28ccdb95 --- /dev/null +++ b/test/files/run/patmat_unapp_abstype.check @@ -0,0 +1,2 @@ +TypeRef +none of the above diff --git a/test/files/run/patmat_unapp_abstype.scala b/test/files/run/patmat_unapp_abstype.scala new file mode 100644 index 0000000000..e5adec5c16 --- /dev/null +++ b/test/files/run/patmat_unapp_abstype.scala @@ -0,0 +1,39 @@ +// 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] +} + +object Test extends TypesImpl with TypesUser with App { + 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! +} \ No newline at end of file -- cgit v1.2.3