All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dotty.tools.dotc.transform.ElimByName.scala Maven / Gradle / Ivy

The newest version!
package dotty.tools.dotc
package transform

import core._
import DenotTransformers.InfoTransformer
import Symbols._
import Contexts._
import Types._
import core.StdNames.nme
import ast.Trees._

/** This phase eliminates ExprTypes `=> T` as types of method parameter references, and replaces them b
 *  nullary function types.  More precisely:
 *
 *  For the types of parameter symbols:
 *
 *         => T       ==>    () => T
 *
 *  For cbn parameter values
 *
 *         x          ==>    x()
 *
 *  Note: This scheme to have inconsistent types between method types (whose formal types are still
 *  ExprTypes and parameter valdefs (which are now FunctionTypes) is not pretty. There are two
 *  other options which have been abandoned or not yet pursued.
 *
 *  Option 1: Transform => T to () => T also in method and function types. The problem with this is
 *  that is that it requires to look at every type, and this forces too much, causing
 *  Cyclic Reference errors. Abandoned for this reason.
 *
 *  Option 2: Merge ElimByName with erasure, or have it run immediately before. This has not been
 *  tried yet.
 */
class ElimByName extends TransformByNameApply with InfoTransformer {
  import ast.tpd._

  override def phaseName: String = ElimByName.name

  override def changesParents: Boolean = true // Only true for by-names

  /** Map `tree` to `tree.apply()` is `ftree` was of ExprType and becomes now a function */
  private def applyIfFunction(tree: Tree, ftree: Tree)(implicit ctx: Context) =
    if (isByNameRef(ftree)) {
      val tree0 = transformFollowing(tree)
      ctx.atPhase(next) { implicit ctx => tree0.select(defn.Function0_apply).appliedToNone }
    }
    else tree

  override def transformIdent(tree: Ident)(implicit ctx: Context): Tree =
    applyIfFunction(tree, tree)

  override def transformSelect(tree: Select)(implicit ctx: Context): Tree =
    applyIfFunction(tree, tree)

  override def transformTypeApply(tree: TypeApply)(implicit ctx: Context): Tree = tree match {
    case TypeApply(Select(_, nme.asInstanceOf_), arg :: Nil) =>
      // tree might be of form e.asInstanceOf[x.type] where x becomes a function.
      // See pos/t296.scala
      applyIfFunction(tree, arg)
    case _ => tree
  }

  override def transformValDef(tree: ValDef)(implicit ctx: Context): Tree =
    ctx.atPhase(next) { implicit ctx =>
      if (exprBecomesFunction(tree.symbol))
        cpy.ValDef(tree)(tpt = tree.tpt.withType(tree.symbol.info))
      else tree
    }

  def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp match {
    case ExprType(rt) => defn.FunctionOf(Nil, rt)
    case _ => tp
  }

  override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym.isTerm && exprBecomesFunction(sym)
}

object ElimByName {
  val name: String = "elimByName"
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy