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

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

There is a newer version: 3.6.4-RC1-bin-20241220-0bfa1af-NIGHTLY
Show newest version
package dotty.tools
package dotc
package transform

import dotty.tools.dotc.core.Contexts.*
import dotty.tools.dotc.core.Decorators.*
import dotty.tools.dotc.core.Symbols.*
import dotty.tools.dotc.core.Flags.*
import dotty.tools.dotc.core.Types.*
import dotty.tools.dotc.transform.MegaPhase.MiniPhase
import dotty.tools.dotc.inlines.Inlines

/** Check that `tree.rhs` can be right hand-side of an `inline` value definition. */
class InlineVals extends MiniPhase:
  import ast.tpd.*

  override def phaseName: String = InlineVals.name

  override def description: String = InlineVals.description

  override def checkPostCondition(tree: Tree)(using Context): Unit =
    if !ctx.erasedTypes then
      tree match
        case tree: ValDef => checkInlineConformant(tree)
        case _ =>

  override def transformValDef(tree: ValDef)(using Context): Tree =
    checkInlineConformant(tree)
    tree

  /** Check that `tree.rhs` can be right hand-side of an `inline` value definition. */
  private def checkInlineConformant(tree: ValDef)(using Context): Unit = {
    if tree.symbol.is(Inline, butNot = DeferredOrTermParamOrAccessor)
      && !Inlines.inInlineMethod
    then
      val rhs = tree.rhs
      val tpt = tree.tpt
      tpt.tpe.widenTermRefExpr.dealiasKeepOpaques.normalized match
        case tp: ConstantType =>
          if !isPureExpr(rhs) then
            def details = if enclosingInlineds.isEmpty then "" else i"but was: $rhs"
            report.error(em"inline value must be pure$details", rhs.srcPos)
        case tp =>
          if tp.typeSymbol.is(Opaque) then
            report.error(em"The type of an `inline val` cannot be an opaque type.\n\nTo inline, consider using `inline def` instead", rhs)
          else if tp.derivesFrom(defn.UnitClass) then
            report.error(em"`inline val` of type `Unit` is not supported.\n\nTo inline a `Unit` consider using `inline def`", rhs)
          else if tp.derivesFrom(defn.StringClass) || defn.ScalaValueClasses().exists(tp.derivesFrom(_)) then
            val pos = if tpt.span.isZeroExtent then rhs.srcPos else tpt.srcPos
            report.error(em"inline value must have a literal constant type", pos)
          else if tp.derivesFrom(defn.NullClass) then
            report.error(em"`inline val` with `null` is not supported.\n\nTo inline a `null` consider using `inline def`", rhs)
          else
            report.error(em"inline value must contain a literal constant value.\n\nTo inline more complex types consider using `inline def`", rhs)
  }

object InlineVals:
  val name: String = "inlineVals"
  val description: String = "check right hand-sides of an `inline val`s"




© 2015 - 2025 Weber Informatics LLC | Privacy Policy