dotty.tools.dotc.transform.ExplicitSelf.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala3-compiler_3 Show documentation
Show all versions of scala3-compiler_3 Show documentation
scala3-compiler-bootstrapped
package dotty.tools.dotc
package transform
import core.*
import Contexts.*, Types.*, MegaPhase.*, ast.Trees.*, Symbols.*, Decorators.*, Flags.*
/** Transform references of the form
*
* C.this.m
*
* where `C` is a class with explicit self type and `C` is not a
* subclass of the owner of `m` to
*
* C.this.asInstanceOf[S & C.this.type].m
*
* where `S` is the self type of `C`.
* See run/i789.scala for a test case why this is needed.
*
* Also replaces idents referring to the self type with ThisTypes.
*/
class ExplicitSelf extends MiniPhase {
import ast.tpd.*
override def phaseName: String = ExplicitSelf.name
override def description: String = ExplicitSelf.description
private def needsCast(tree: RefTree, cls: ClassSymbol)(using Context) =
!cls.is(Package)
&& cls.givenSelfType.exists
&& tree.symbol.exists
&& !cls.derivesFrom(tree.symbol.owner)
private def castQualifier(tree: RefTree, cls: ClassSymbol, thiz: Tree)(using Context) =
val selfType = cls.classInfo.selfType
if selfType.classSymbols.exists(_.isValueClass) && !cls.isUniversalTrait then
report.error(em"self type $selfType of $cls may not be a value class", thiz.srcPos)
cpy.Select(tree)(thiz.cast(AndType(selfType, thiz.tpe)), tree.name)
override def transformIdent(tree: Ident)(using Context): Tree = tree.tpe match {
case tp: ThisType =>
report.debuglog(s"owner = ${ctx.owner}, context = ${ctx}")
This(tp.cls).withSpan(tree.span)
case TermRef(thisTp: ThisType, _) =>
val cls = thisTp.cls
if needsCast(tree, cls) then castQualifier(tree, cls, This(cls))
else tree
case _ =>
tree
}
override def transformSelect(tree: Select)(using Context): Tree = tree match {
case Select(thiz: This, name) if name.isTermName =>
val cls = thiz.symbol.asClass
if needsCast(tree, cls) then castQualifier(tree, cls, thiz)
else tree
case _ => tree
}
}
object ExplicitSelf:
val name: String = "explicitSelf"
val description: String = "make references to non-trivial self types explicit as casts"
© 2015 - 2025 Weber Informatics LLC | Privacy Policy