aboutsummaryrefslogblamecommitdiff
path: root/compiler/src/dotty/tools/dotc/transform/Literalize.scala.disabled
blob: f33baa52b810bf64b4f0c5607e324c607a8f0078 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                               

                                        



                                                                               


                                                                                        
   
                                                              

                  
                                               


























                                                                                   






                                                                          












                                                                                                        

                                                                                                                     
                                                                                                                  

                  
 
                                                                   




                                                                              


                                                                                





                                                                                                                  
 
package dotty.tools.dotc
package transform

import TreeTransforms._
import core.DenotTransformers._
import core.Symbols._
import core.Contexts._
import core.Types._
import core.Flags._
import core.Decorators._
import core.StdNames.nme
import ast.Trees._
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Constants._

/** This phase rewrites idempotent expressions with constant types to Literals.
 *  The constant types are eliminated by erasure, so we need to keep
 *  the info about constantness in the trees.
 *
 *  The phase also makes sure that the constant of a literal is the same as the constant
 *  in the type of the literal.
 */
class Literalize extends MiniPhaseTransform { thisTransform =>
  import ast.tpd._

  override def phaseName: String = "literalize"

  /** Note: Demanding idempotency instead of purity is strictly speaking too loose.
   *  Example
   *
   *    object O { final val x = 42; println("43") }
   *    O.x
   *
   *  Strictly speaking we can't replace `O.x` with `42`.  But this would make
   *  most expressions non-constant. Maybe we can change the spec to accept this
   *  kind of eliding behavior. Or else enforce true purity in the compiler.
   *  The choice will be affected by what we will do with `inline` and with
   *  Singleton type bounds (see SIP 23). Presumably
   *
   *     object O1 { val x: Singleton = 42; println("43") }
   *     object O2 { inline val x = 42; println("43") }
   *
   *  should behave differently.
   *
   *     O1.x  should have the same effect as   { println("43"; 42 }
   *
   *  whereas
   *
   *     O2.x = 42
   *
   *  Revisit this issue once we have implemented `inline`. Then we can demand
   *  purity of the prefix unless the selection goes to an inline val.
   */
  def literalize(tree: Tree)(implicit ctx: Context): Tree = {
    def recur(tp: Type): Tree = tp match {
      case ConstantType(value) if isIdempotentExpr(tree) => Literal(value)
      case tp: TermRef if tp.symbol.isStable => recur(tp.info.widenExpr)
      case _ => tree
    }
    recur(tree.tpe)
  }

  override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree =
    literalize(tree)

  override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree =
    literalize(tree)

  override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
    literalize(tree)

  override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree =
    literalize(tree)

  override def transformLiteral(tree: Literal)(implicit ctx: Context, info: TransformerInfo): Tree = tree.tpe match {
    case ConstantType(const) if tree.const.value != const.value || (tree.const.tag != const.tag) => Literal(const)
    case _ => tree
  }

  /** Check that all literals have types match underlying constants
    */
  override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
    tree match {
      case Literal(c @ Constant(treeValue)) =>
        tree.tpe match {
          case ConstantType(c2 @ Constant(typeValue)) =>
            assert(treeValue == typeValue && c2.tag == c.tag,
              i"Type of Literal $tree is inconsistent with underlying constant")
          case tpe =>
            assert(c.tpe =:= tpe, i"Type of Literal $tree is inconsistent with underlying constant type ${c.tpe}")
        }
      case _ =>
    }
  }
}