diff options
author | Martin Odersky <odersky@gmail.com> | 2017-02-17 16:38:06 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2017-02-17 16:38:06 +0100 |
commit | 80511914713237de894f896da7397965e52134a7 (patch) | |
tree | 0413b633ef8baafe30eb86188c59b78a31fca2ba /compiler/src/dotty/tools/dotc/typer/Typer.scala | |
parent | 6df672c7e7be65d7be1cd6524c610aed4f35178c (diff) | |
download | dotty-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.scala | 33 |
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 @ _)` |