diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-04-13 18:52:12 +0200 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-04-14 11:50:27 +0200 |
commit | 3515ac4449c72992be411e1e0579d76189dc7bf1 (patch) | |
tree | dac0bcf20a2fd49d6cacefbb9c7014b02a2f6a56 | |
parent | d383f458aa5c53629727c5b6abb5134218471543 (diff) | |
download | scala-3515ac4449c72992be411e1e0579d76189dc7bf1.tar.gz scala-3515ac4449c72992be411e1e0579d76189dc7bf1.tar.bz2 scala-3515ac4449c72992be411e1e0579d76189dc7bf1.zip |
more prudent bridging to unapply[Seq]
since we can't statically know whether the unapply
we'll be bridging to is synthetic, drop this condition,
and do pessimistic bridging for all unapply[Seq]
(i.e., if we can't statically guarantee the type
that would be assumed to be safe to cast to by a synthetic
extractor, do the type test and return None if it fails)
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 9 | ||||
-rw-r--r-- | test/files/run/patmat_unapp_abstype.check | 2 | ||||
-rw-r--r-- | test/files/run/patmat_unapp_abstype.scala | 49 |
3 files changed, 50 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index bdf2f2883f..5e61359a25 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -480,11 +480,10 @@ abstract class Erasure extends AddInterfaces // TODO: should we do this for user-defined unapplies as well? // does the first argument list have exactly one argument -- for user-defined unapplies we can't be sure def maybeWrap(bridgingCall: Tree): Tree = { - val canReturnNone = afterErasure( - member.isSynthetic - && (member.name == nme.unapply || member.name == nme.unapplySeq) - && !(member.tpe <:< other.tpe) // no static guarantees (TODO: is the subtype test ever true?) - ) + val canReturnNone = ( // can't statically know which member is going to be selected, so don't let this depend on member.isSynthetic + (member.name == nme.unapply || member.name == nme.unapplySeq) + && !afterErasure((member.tpe <:< other.tpe))) // no static guarantees (TODO: is the subtype test ever true?) + if (canReturnNone) { import CODE._ val typeTest = gen.mkIsInstanceOf(REF(bridge.firstParam), member.tpe.params.head.tpe) diff --git a/test/files/run/patmat_unapp_abstype.check b/test/files/run/patmat_unapp_abstype.check index ac28ccdb95..72239d16cd 100644 --- a/test/files/run/patmat_unapp_abstype.check +++ b/test/files/run/patmat_unapp_abstype.check @@ -1,2 +1,4 @@ TypeRef none of the above +Bar +Foo diff --git a/test/files/run/patmat_unapp_abstype.scala b/test/files/run/patmat_unapp_abstype.scala index e5adec5c16..fb0b491d39 100644 --- a/test/files/run/patmat_unapp_abstype.scala +++ b/test/files/run/patmat_unapp_abstype.scala @@ -32,8 +32,47 @@ trait TypesImpl extends TypesAPI { //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 +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() +} |