diff options
Diffstat (limited to 'src/compiler/scala/reflect/internal/TreeGen.scala')
-rw-r--r-- | src/compiler/scala/reflect/internal/TreeGen.scala | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala index 1c93a904c0..e537c6b83f 100644 --- a/src/compiler/scala/reflect/internal/TreeGen.scala +++ b/src/compiler/scala/reflect/internal/TreeGen.scala @@ -154,9 +154,13 @@ abstract class TreeGen { debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase) assert(!tree.tpe.isInstanceOf[MethodType], tree) assert(!pt.typeSymbol.isPackageClass && !pt.typeSymbol.isPackageObjectClass, pt) - // @MAT only called during erasure, which already takes care of that - // @PP: "only called during erasure" is not very true these days. - // In addition, at least, are: typer, uncurry, explicitouter, cleanup. + // 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)) } @@ -262,6 +266,25 @@ 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()) |