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

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

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

import core._
import MegaPhase._
import Contexts.Context
import Flags._
import SymUtils._
import Symbols._
import Types._
import Decorators._
import DenotTransformers._
import Annotations._
import StdNames._
import NameOps._
import NameKinds.{ExpandedName, TraitSetterName}
import ast.Trees._

object AugmentScala2Traits {
  val name: String = "augmentScala2Traits"
}

/** This phase augments Scala2 traits with additional members needed for mixin composition.
 *
 *  These symbols would have been added between Unpickling and Mixin in the Scala2 pipeline.
 *
 *  Specifically, we:
 *   - Add trait setters for vals defined in traits.
 *   - Expand the names of all private getters and setters as well as super accessors in the trait and make
 *     not-private.
 */
class AugmentScala2Traits extends MiniPhase with IdentityDenotTransformer { thisPhase =>
  import ast.tpd._

  override def changesMembers: Boolean = true

  override def phaseName: String = AugmentScala2Traits.name

  override def transformTemplate(impl: Template)(implicit ctx: Context): Template = {
    val cls = impl.symbol.owner.asClass
    for (mixin <- cls.mixins) {
      val erasedMixin = TypeErasure.normalizeClass(mixin)
      if (erasedMixin.is(Scala2x) && !erasedMixin.is(Scala2xPartiallyAugmented))
        augmentScala2Trait(erasedMixin)
    }
    impl
  }

  private def augmentScala2Trait(mixin: ClassSymbol)(implicit ctx: Context): Unit = {
    def traitSetter(getter: TermSymbol) =
      getter.copy(
        name = getter.ensureNotPrivate.name
          .expandedName(getter.owner, TraitSetterName)
          .asTermName.setterName,
        flags = Method | Accessor,
        info = MethodType(getter.info.resultType :: Nil, defn.UnitType))

    for (sym <- mixin.info.decls) {
      if (sym.isGetter && !sym.isOneOf(DeferredOrLazy) && !sym.setter.exists &&
          !sym.info.resultType.isInstanceOf[ConstantType])
        traitSetter(sym.asTerm).enteredAfter(thisPhase)
      if ((sym.isAllOf(PrivateAccessor) && !sym.name.is(ExpandedName) &&
        (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set.
        || sym.isSuperAccessor) // scala2 superaccessors are pickled as private, but are compiled as public expanded
        sym.ensureNotPrivate.installAfter(thisPhase)
    }
    mixin.setFlag(Scala2xPartiallyAugmented)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy