From 050c9af51432e3a752715af78b0de577d5af7f87 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 19 Feb 2016 16:33:43 +0100 Subject: Special case for pattern matching tagged abstract types. Add special case when pattern matching against an abstract type that comes with a class tag --- src/dotty/tools/dotc/typer/Typer.scala | 21 ++++++++++++++++++--- tests/run/i1099.scala | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 tests/run/i1099.scala diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index fabee83b7..64c118288 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -427,10 +427,25 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit ifExpr = seqToRepeated(typedExpr(tree.expr, defn.SeqType)), wildName = nme.WILDCARD_STAR) else { - def tpt1 = checkSimpleKinded(typedType(tree.tpt)) + def typedTpt = checkSimpleKinded(typedType(tree.tpt)) + def handlePattern: Tree = { + val tpt1 = typedTpt + // special case for an abstract type that comes with a class tag + tpt1.tpe.dealias match { + case tref: TypeRef if !tref.symbol.isClass => + inferImplicit(defn.ClassTagType.appliedTo(tref), + EmptyTree, tpt1.pos)(ctx.retractMode(Mode.Pattern)) match { + case SearchSuccess(arg, _, _) => + return typed(untpd.Apply(untpd.TypedSplice(arg), tree.expr), pt) + case _ => + } + case _ => + } + ascription(tpt1, isWildcard = true) + } cases( - ifPat = ascription(tpt1, isWildcard = true), - ifExpr = ascription(tpt1, isWildcard = false), + ifPat = handlePattern, + ifExpr = ascription(typedTpt, isWildcard = false), wildName = nme.WILDCARD) } } diff --git a/tests/run/i1099.scala b/tests/run/i1099.scala new file mode 100644 index 000000000..15a428cc3 --- /dev/null +++ b/tests/run/i1099.scala @@ -0,0 +1,25 @@ +import scala.reflect.ClassTag +object Test { + def foo[T: ClassTag](x: Any) = + x match { + case t: T => true + case _ => false + } + // This is what `foo` expands to + def foo2[T](x: Any)(implicit ev: ClassTag[T]) = + x match { + case t @ ev(_) => true + case _ => false + } + def main(args: Array[String]): Unit = { + assert(foo[String]("a")) + assert(!foo[String](new Integer(1))) + assert(foo[Int](1)) + assert(!foo[Int](true)) + + assert(foo2[String]("a")) + assert(!foo2[String](new Integer(1))) + assert(foo2[Int](1)) + assert(!foo2[Int](true)) + } +} -- cgit v1.2.3