|
| 1 | +package dotty.tools.backend.jvm |
| 2 | + |
| 3 | +import dotty.tools.dotc.ast.Trees.Thicket |
| 4 | +import dotty.tools.dotc.ast.{Trees, tpd} |
| 5 | +import dotty.tools.dotc.core.Contexts.Context |
| 6 | +import dotty.tools.dotc.core.Types |
| 7 | +import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, MiniPhase, MiniPhaseTransform} |
| 8 | +import dotty.tools.dotc |
| 9 | +import dotty.tools.dotc.backend.jvm.DottyPrimitives |
| 10 | +import dotty.tools.dotc.core.Flags.FlagSet |
| 11 | +import dotty.tools.dotc.transform.Erasure |
| 12 | +import dotty.tools.dotc.transform.SymUtils._ |
| 13 | +import java.io.{File => JFile} |
| 14 | + |
| 15 | +import scala.collection.generic.Clearable |
| 16 | +import scala.collection.mutable |
| 17 | +import scala.collection.mutable.{ListBuffer, ArrayBuffer} |
| 18 | +import scala.reflect.ClassTag |
| 19 | +import scala.reflect.internal.util.WeakHashSet |
| 20 | +import scala.reflect.io.{Directory, PlainDirectory, AbstractFile} |
| 21 | +import scala.tools.asm.{ClassVisitor, FieldVisitor, MethodVisitor} |
| 22 | +import scala.tools.nsc.backend.jvm.{BCodeHelpers, BackendInterface} |
| 23 | +import dotty.tools.dotc.core._ |
| 24 | +import Periods._ |
| 25 | +import SymDenotations._ |
| 26 | +import Contexts._ |
| 27 | +import Types._ |
| 28 | +import Symbols._ |
| 29 | +import Denotations._ |
| 30 | +import Phases._ |
| 31 | +import java.lang.AssertionError |
| 32 | +import dotty.tools.dotc.util.Positions.Position |
| 33 | +import Decorators._ |
| 34 | +import tpd._ |
| 35 | +import Flags._ |
| 36 | +import StdNames.nme |
| 37 | + |
| 38 | +/** |
| 39 | + * Ensures that tree does not contain type subsumptions where subsumed type is bottom type |
| 40 | + * of our typesystem, but not the bottom type of JVM typesystem. |
| 41 | + */ |
| 42 | +class BottomTypes extends MiniPhaseTransform { |
| 43 | + def phaseName: String = "bottomTypes" |
| 44 | + |
| 45 | + |
| 46 | + def adaptBottom(treeOfBottomType: tpd.Tree, expectedType: Type)(implicit ctx: Context) = { |
| 47 | + if (Erasure.Boxing.isNonJVMBottomType(treeOfBottomType.tpe) && (treeOfBottomType.tpe ne expectedType)) |
| 48 | + Erasure.Boxing.adaptToType(treeOfBottomType, expectedType) |
| 49 | + else treeOfBottomType |
| 50 | + } |
| 51 | + |
| 52 | + override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { |
| 53 | + val returnTp = tree.symbol.info.dealias.finalResultType |
| 54 | + cpy.DefDef(tree)(rhs = adaptBottom(tree.rhs, returnTp)) |
| 55 | + } |
| 56 | + |
| 57 | + |
| 58 | + override def transformAssign(tree: tpd.Assign)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { |
| 59 | + val returnTp = tree.lhs.symbol.info.dealias |
| 60 | + cpy.Assign(tree)(tree.lhs, adaptBottom(tree.rhs, returnTp)) |
| 61 | + } |
| 62 | + |
| 63 | + |
| 64 | + override def transformTyped(tree: tpd.Typed)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { |
| 65 | + cpy.Typed(tree)(adaptBottom(tree.expr, tree.tpt.tpe), tree.tpt) |
| 66 | + } |
| 67 | + |
| 68 | + override def transformApply(tree: tpd.Apply)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { |
| 69 | + val fun = tree.fun |
| 70 | + val newArgs: List[tpd.Tree] = tree.args.zip(fun.tpe.dealias.firstParamTypes).map(x => adaptBottom(x._1, x._2)) |
| 71 | + val changeNeeded = tree.args == newArgs // cpy.Apply does not check if elements are the same, |
| 72 | + // it only does `eq` on lists as whole |
| 73 | + if (changeNeeded) cpy.Apply(tree)(fun = fun, args = newArgs) |
| 74 | + else tree |
| 75 | + } |
| 76 | + |
| 77 | + override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { |
| 78 | + val returnTp = tree.symbol.info.dealias |
| 79 | + cpy.ValDef(tree)(rhs = adaptBottom(tree.rhs, returnTp)) |
| 80 | + } |
| 81 | +} |
0 commit comments