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

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

package dotty.tools
package dotc
package transform

import core.*
import dotty.tools.dotc.transform.MegaPhase.*
import Flags.*
import Types.*
import Contexts.*
import Symbols.*
import Denotations.{SingleDenotation, NonSymSingleDenotation}
import SymDenotations.SymDenotation
import DenotTransformers.*
import Names.*

object ElimOpaque {
  val name: String = "elimOpaque"
  val description: String = "turn opaque into normal aliases"
}

/** Rewrites opaque type aliases to normal alias types */
class ElimOpaque extends MiniPhase with DenotTransformer {
  thisPhase =>
  import ast.tpd.*

  override def phaseName: String = ElimOpaque.name

  override def description: String = ElimOpaque.description

  // Override checks need to take place before treating opaque types as aliases
  override def runsAfterGroupsOf: Set[String] = Set(typer.RefChecks.name)

  // base types of opaque aliases change
  override def changesBaseTypes = true

  def transform(ref: SingleDenotation)(using Context): SingleDenotation = {
    val sym = ref.symbol
    ref match {
      case ref: SymDenotation if sym.isOpaqueAlias =>
        ref.copySymDenotation(
          info = TypeAlias(ref.opaqueAlias),
          initFlags = ref.flags &~ (Opaque | Deferred))
      case ref: SymDenotation if sym.containsOpaques =>
        def stripOpaqueRefinements(tp: Type): Type = tp match {
          case RefinedType(parent, rname, TypeAlias(_))
          if ref.info.decl(rname).symbol.isOpaqueAlias => stripOpaqueRefinements(parent)
          case _ => tp
        }
        val cinfo = sym.asClass.classInfo
        val strippedSelfType = stripOpaqueRefinements(cinfo.selfType)
        ref.copySymDenotation(
          info = cinfo.derivedClassInfo(selfInfo = strippedSelfType),
          initFlags = ref.flags &~ Opaque)
      case ref: NonSymSingleDenotation if sym.isOpaqueAlias =>
        ref.derivedSingleDenotation(sym, TypeAlias(sym.opaqueAlias.asSeenFrom(ref.prefix, sym.owner)))
      case _ =>
        ref
    }
  }

  /** Resolve overloading of `==` and `!=` methods with the representation
   *  types in order to avoid boxing.
   */
  override def transformApply(tree: Apply)(using Context): Tree =
    val sym = tree.symbol
    if sym == defn.Any_== || sym == defn.Any_!= then
      tree match
        case Apply(Select(receiver, name: TermName), args)
        if atPhase(thisPhase)(receiver.tpe.widenDealias.typeSymbol.isOpaqueAlias) =>
          applyOverloaded(receiver, name, args, Nil, defn.BooleanType)
        case _ =>
          tree
    else
      tree
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy