aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/typer/Typer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-02-17 16:38:06 +0100
committerMartin Odersky <odersky@gmail.com>2017-02-17 16:38:06 +0100
commit80511914713237de894f896da7397965e52134a7 (patch)
tree0413b633ef8baafe30eb86188c59b78a31fca2ba /compiler/src/dotty/tools/dotc/typer/Typer.scala
parent6df672c7e7be65d7be1cd6524c610aed4f35178c (diff)
downloaddotty-80511914713237de894f896da7397965e52134a7.tar.gz
dotty-80511914713237de894f896da7397965e52134a7.tar.bz2
dotty-80511914713237de894f896da7397965e52134a7.zip
Fix #1991: Use classtag where available in unapply
Diffstat (limited to 'compiler/src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala33
1 files changed, 20 insertions, 13 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index 2b57cf778..820044b8e 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -523,18 +523,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
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 && !ctx.isAfterTyper =>
- 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 _ =>
- if (!ctx.isAfterTyper) tpt1.tpe.<:<(pt)(ctx.addMode(Mode.GADTflexible))
- }
- ascription(tpt1, isWildcard = true)
+ if (!ctx.isAfterTyper) tpt1.tpe.<:<(pt)(ctx.addMode(Mode.GADTflexible))
+ tryWithClassTag(ascription(tpt1, isWildcard = true), pt)
}
cases(
ifPat = handlePattern,
@@ -543,6 +533,23 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}
+ /** For a typed tree `e: T`, if `T` is an abstract type for which an implicit class tag `ctag`
+ * exists, rewrite to `ctag(e)`.
+ * @pre We are in pattern-matching mode (Mode.Pattern)
+ */
+ def tryWithClassTag(tree: Typed, pt: Type)(implicit ctx: Context) = tree.tpt.tpe.dealias match {
+ case tref: TypeRef if !tref.symbol.isClass && !ctx.isAfterTyper =>
+ require(ctx.mode.is(Mode.Pattern))
+ inferImplicit(defn.ClassTagType.appliedTo(tref),
+ EmptyTree, tree.tpt.pos)(ctx.retractMode(Mode.Pattern)) match {
+ case SearchSuccess(clsTag, _, _, _) =>
+ typed(untpd.Apply(untpd.TypedSplice(clsTag), untpd.TypedSplice(tree.expr)), pt)
+ case _ =>
+ tree
+ }
+ case _ => tree
+ }
+
def typedNamedArg(tree: untpd.NamedArg, pt: Type)(implicit ctx: Context) = track("typedNamedArg") {
val arg1 = typed(tree.arg, pt)
assignType(cpy.NamedArg(tree)(tree.name, arg1), arg1)
@@ -1123,7 +1130,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val body1 = typed(tree.body, pt1)
typr.println(i"typed bind $tree pt = $pt1 bodytpe = ${body1.tpe}")
body1 match {
- case UnApply(fn, Nil, arg :: Nil) if tree.body.isInstanceOf[untpd.Typed] =>
+ case UnApply(fn, Nil, arg :: Nil) if tree.body.isInstanceOf[untpd.Typed] && !body1.tpe.isError =>
// A typed pattern `x @ (_: T)` with an implicit `ctag: ClassTag[T]`
// was rewritten to `x @ ctag(_)`.
// Rewrite further to `ctag(x @ _)`