From 3a5c70c0634a5d10cff5c52014661a22278b4245 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 22 Feb 2012 09:55:41 +0100 Subject: Moved mkCast and derived method from reflect.internal.TreeGen to tools.nsc.ast.TreeGen. Made mkCast generate the "right" version of casts according to current phase. --- src/compiler/scala/reflect/internal/TreeGen.scala | 35 --------------------- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 37 +++++++++++++++++++++-- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala index def1350187..3b3c7f6298 100644 --- a/src/compiler/scala/reflect/internal/TreeGen.scala +++ b/src/compiler/scala/reflect/internal/TreeGen.scala @@ -148,22 +148,6 @@ abstract class TreeGen { None } - /** Cast `tree` to type `pt` */ - def mkCast(tree: Tree, pt: Type): Tree = { - debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase) - assert(!tree.tpe.isInstanceOf[MethodType], tree) - assert(!pt.typeSymbol.isPackageClass && !pt.typeSymbol.isPackageObjectClass, pt) - // called during (at least): typer, uncurry, explicitouter, cleanup. - // TODO: figure out the truth table for any/wrapInApply - // - the `any` flag seems to relate to erasure's adaptMember: "x.asInstanceOf[T] becomes x.$asInstanceOf[T]", - // where asInstanceOf is Any_asInstanceOf and $asInstanceOf is Object_asInstanceOf - // erasure will only unbox the value in a tree made by mkCast if `any && wrapInApply` - // - the `wrapInApply` flag need not be true if the tree will be adapted to have the empty argument list added before it gets to erasure - // in fact, I think it should be false for trees that will be type checked during typer - assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) - atPos(tree.pos)(mkAsInstanceOf(tree, pt, any = false, wrapInApply = true)) - } - /** Builds a reference with stable type to given symbol */ def mkAttributedStableRef(pre: Type, sym: Symbol): Tree = stabilize(mkAttributedRef(pre, sym)) @@ -265,25 +249,6 @@ abstract class TreeGen { tree setType tp } - def mkZeroContravariantAfterTyper(tp: Type): Tree = { - // contravariant -- for replacing an argument in a method call - // must use subtyping, as otherwise we miss types like `Any with Int` - val tree = - if (NullClass.tpe <:< tp) Literal(Constant(null)) - else if (UnitClass.tpe <:< tp) Literal(Constant()) - else if (BooleanClass.tpe <:< tp) Literal(Constant(false)) - else if (FloatClass.tpe <:< tp) Literal(Constant(0.0f)) - else if (DoubleClass.tpe <:< tp) Literal(Constant(0.0d)) - else if (ByteClass.tpe <:< tp) Literal(Constant(0.toByte)) - else if (ShortClass.tpe <:< tp) Literal(Constant(0.toShort)) - else if (IntClass.tpe <:< tp) Literal(Constant(0)) - else if (LongClass.tpe <:< tp) Literal(Constant(0L)) - else if (CharClass.tpe <:< tp) Literal(Constant(0.toChar)) - else mkCast(Literal(Constant(null)), tp) - - tree - } - /** Builds a tuple */ def mkTuple(elems: List[Tree]): Tree = if (elems.isEmpty) Literal(Constant()) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 265d017653..4e2c906cde 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -30,7 +30,7 @@ abstract class TreeGen extends reflect.internal.TreeGen { else tree } - + /** Builds a fully attributed wildcard import node. */ def mkWildcardImport(pkg: Symbol): Import = { @@ -98,7 +98,7 @@ abstract class TreeGen extends reflect.internal.TreeGen { def mkModuleVarDef(accessor: Symbol) = { val inClass = accessor.owner.isClass val extraFlags = if (inClass) PrivateLocal | SYNTHETIC else 0 - + val mval = ( accessor.owner.newVariable(nme.moduleVarName(accessor.name), accessor.pos.focus, MODULEVAR | extraFlags) setInfo accessor.tpe.finalResultType @@ -188,6 +188,20 @@ abstract class TreeGen extends reflect.internal.TreeGen { ) } + /** Cast `tree` to type `pt` by creating + * one of the calls of the form + * + * x.asInstanceOf[`pt`] up to phase uncurry + * x.asInstanceOf[`pt`]() if after uncurry but before erasure + * x.$asInstanceOf[`pt`]() if at or after erasure + */ + def mkCast(tree: Tree, pt: Type): Tree = { + debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase) + assert(!tree.tpe.isInstanceOf[MethodType], tree) + assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) + atPos(tree.pos)(mkAsInstanceOf(tree, pt, any = !phase.next.erasedTypes, wrapInApply = phase.id > currentRun.uncurryPhase.id)) + } + /** Generate a cast for tree Tree representing Array with * elem type elemtp to expected type pt. */ @@ -197,6 +211,25 @@ abstract class TreeGen extends reflect.internal.TreeGen { else mkCast(tree, pt) + def mkZeroContravariantAfterTyper(tp: Type): Tree = { + // contravariant -- for replacing an argument in a method call + // must use subtyping, as otherwise we miss types like `Any with Int` + val tree = + if (NullClass.tpe <:< tp) Literal(Constant(null)) + else if (UnitClass.tpe <:< tp) Literal(Constant()) + else if (BooleanClass.tpe <:< tp) Literal(Constant(false)) + else if (FloatClass.tpe <:< tp) Literal(Constant(0.0f)) + else if (DoubleClass.tpe <:< tp) Literal(Constant(0.0d)) + else if (ByteClass.tpe <:< tp) Literal(Constant(0.toByte)) + else if (ShortClass.tpe <:< tp) Literal(Constant(0.toShort)) + else if (IntClass.tpe <:< tp) Literal(Constant(0)) + else if (LongClass.tpe <:< tp) Literal(Constant(0L)) + else if (CharClass.tpe <:< tp) Literal(Constant(0.toChar)) + else mkCast(Literal(Constant(null)), tp) + + tree + } + /** Translate names in Select/Ident nodes to type names. */ def convertToTypeName(tree: Tree): Option[RefTree] = tree match { -- cgit v1.2.3