From 25421111a730681504c73b978e454dfa7a6ff447 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 26 Jul 2016 10:20:34 +0200 Subject: fix #1354: improve type test and typecast of union types --- .../tools/dotc/transform/TypeTestsCasts.scala | 31 ++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index c57d6fd1a..6de2bf44c 100644 --- a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -1,16 +1,12 @@ package dotty.tools.dotc package transform -import TreeTransforms._ -import core.Denotations._ -import core.SymDenotations._ import core.Contexts._ import core.Symbols._ import core.Types._ import core.Constants._ import core.StdNames._ import core.TypeErasure.isUnboundedGeneric -import typer.ErrorReporting._ import ast.Trees._ import Erasure.Boxing._ import core.TypeErasure._ @@ -92,14 +88,33 @@ trait TypeTestsCasts { unbox(qual.ensureConforms(defn.ObjectType), argType) else if (isDerivedValueClass(argCls)) { qual // adaptToType in Erasure will do the necessary type adaptation - } else + } + else derivedTree(qual, defn.Any_asInstanceOf, argType) } - def erasedArg = erasure(tree.args.head.tpe) + + /** Transform isInstanceOf OrType + * + * expr.isInstanceOf[A | B] ~~> expr.isInstanceOf[A] | expr.isInstanceOf[B] + * + * The transform happens before erasure of `argType`, thus cannot be merged + * with `transformIsInstanceOf`, which depends on erased type of `argType`. + */ + def transformOrTypeTest(qual: Tree, argType: Type): Tree = argType match { + case OrType(tp1, tp2) => + evalOnce(qual) { fun => + transformOrTypeTest(fun, tp1) + .select(nme.OR) + .appliedTo(transformOrTypeTest(fun, tp2)) + } + case _ => + transformIsInstanceOf(qual, erasure(argType)) + } + if (sym eq defn.Any_isInstanceOf) - transformIsInstanceOf(qual, erasedArg) + transformOrTypeTest(qual, tree.args.head.tpe) else if (sym eq defn.Any_asInstanceOf) - transformAsInstanceOf(erasedArg) + transformAsInstanceOf(erasure(tree.args.head.tpe)) else tree case _ => -- cgit v1.2.3