Skip to content

Remove PreName add (almost) all other implicit conversions #4077

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -828,8 +828,8 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
def freshLocal(cunit: CompilationUnit, name: String, tpe: Type, pos: Position, flags: Flags): Symbol =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SymUtils is not used much, to this commit looks smallish. But we should use it more often because it gives us a way to add methods without overloading SymDenotation. In that case I think it is essential that it works for Symbol and SymDenotation in the same way. So my vote is to leave this as is.

ctx.newSymbol(sym, name.toTermName, FlagSet(flags), tpe, NoSymbol, pos.toCoord)

def getter(clz: Symbol): Symbol = decorateSymbol(sym).getter
def setter(clz: Symbol): Symbol = decorateSymbol(sym).setter
def getter(clz: Symbol): Symbol = new SymUtilsOps(sym).getter
def setter(clz: Symbol): Symbol = new SymUtilsOps(sym).setter

def moduleSuffix: String = "" // todo: validate that names already have $ suffix
def outputDirectory: AbstractFile = DottyBackendInterface.this.outputDirectory
Expand All @@ -842,7 +842,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
* Redundant interfaces are removed unless there is a super call to them.
*/
def superInterfaces: List[Symbol] = {
val directlyInheritedTraits = decorateSymbol(sym).directlyInheritedTraits
val directlyInheritedTraits = new SymUtilsOps(sym).directlyInheritedTraits
val directlyInheritedTraitsSet = directlyInheritedTraits.toSet
val allBaseClasses = directlyInheritedTraits.iterator.flatMap(_.symbol.asClass.baseClasses.drop(1)).toSet
val superCalls = superCallsMap.getOrElse(sym, Set.empty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -575,9 +575,9 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas

if (denot.isConstructor) addConstructorTypeParams(denot)
if (atEnd) {
assert(!denot.isSuperAccessor, denot)
assert(!denot.symbol.isSuperAccessor, denot)
} else {
assert(denot.is(ParamAccessor) || denot.isSuperAccessor, denot)
assert(denot.is(ParamAccessor) || denot.symbol.isSuperAccessor, denot)
def disambiguate(alt: Symbol) = { // !!! DEBUG
trace.onDebug(s"disambiguating ${denot.info} =:= ${denot.owner.thisType.memberInfo(alt)} ${denot.owner}") {
denot.info matches denot.owner.thisType.memberInfo(alt)
Expand Down
263 changes: 129 additions & 134 deletions compiler/src/dotty/tools/dotc/transform/SymUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,169 +18,164 @@ import language.implicitConversions
import scala.annotation.tailrec

object SymUtils {
implicit def decorateSymbol(sym: Symbol): SymUtils = new SymUtils(sym)
implicit def decorateSymDenot(d: SymDenotation): SymUtils = new SymUtils(d.symbol)
}

/** A decorator that provides methods on symbols
* that are needed in the transformer pipeline.
*/
class SymUtils(val self: Symbol) extends AnyVal {
import SymUtils._

/** All traits implemented by a class or trait except for those inherited through the superclass. */
def directlyInheritedTraits(implicit ctx: Context) = {
val superCls = self.asClass.superClass
val baseClasses = self.asClass.baseClasses
if (baseClasses.isEmpty) Nil
else baseClasses.tail.takeWhile(_ ne superCls).reverse
}

/** All traits implemented by a class, except for those inherited through the superclass.
* The empty list if `self` is a trait.
/** A decorator that provides methods on symbols
* that are needed in the transformer pipeline.
*/
def mixins(implicit ctx: Context) = {
if (self is Trait) Nil
else directlyInheritedTraits
}
implicit class SymUtilsOps(val self: Symbol) extends AnyVal {
/** All traits implemented by a class or trait except for those inherited through the superclass. */
def directlyInheritedTraits(implicit ctx: Context) = {
val superCls = self.asClass.superClass
val baseClasses = self.asClass.baseClasses
if (baseClasses.isEmpty) Nil
else baseClasses.tail.takeWhile(_ ne superCls).reverse
}

def isTypeTest(implicit ctx: Context): Boolean =
self == defn.Any_isInstanceOf || self == defn.Any_typeTest
/** All traits implemented by a class, except for those inherited through the superclass.
* The empty list if `self` is a trait.
*/
def mixins(implicit ctx: Context) = {
if (self is Trait) Nil
else directlyInheritedTraits
}

def isTypeTestOrCast(implicit ctx: Context): Boolean =
self == defn.Any_asInstanceOf || isTypeTest
def isTypeTest(implicit ctx: Context): Boolean =
self == defn.Any_isInstanceOf || self == defn.Any_typeTest

def isVolatile(implicit ctx: Context) = self.hasAnnotation(defn.VolatileAnnot)
def isTypeTestOrCast(implicit ctx: Context): Boolean =
self == defn.Any_asInstanceOf || isTypeTest

def isAnyOverride(implicit ctx: Context) = self.is(Override) || self.is(AbsOverride)
// careful: AbsOverride is a term only flag. combining with Override would catch only terms.
def isVolatile(implicit ctx: Context) = self.hasAnnotation(defn.VolatileAnnot)

def isSuperAccessor(implicit ctx: Context) = self.name.is(SuperAccessorName)
def isAnyOverride(implicit ctx: Context) = self.is(Override) || self.is(AbsOverride)
// careful: AbsOverride is a term only flag. combining with Override would catch only terms.

/** A type or term parameter or a term parameter accessor */
def isParamOrAccessor(implicit ctx: Context) =
self.is(Param) || self.is(ParamAccessor)
def isSuperAccessor(implicit ctx: Context) = self.name.is(SuperAccessorName)

/** If this is a constructor, its owner: otherwise this. */
final def skipConstructor(implicit ctx: Context): Symbol =
if (self.isConstructor) self.owner else self
/** A type or term parameter or a term parameter accessor */
def isParamOrAccessor(implicit ctx: Context) =
self.is(Param) || self.is(ParamAccessor)

/** The closest properly enclosing method or class of this symbol. */
final def enclosure(implicit ctx: Context) = {
self.owner.enclosingMethodOrClass
}
/** If this is a constructor, its owner: otherwise this. */
final def skipConstructor(implicit ctx: Context): Symbol =
if (self.isConstructor) self.owner else self

/** The closest enclosing method or class of this symbol */
@tailrec final def enclosingMethodOrClass(implicit ctx: Context): Symbol =
if (self.is(Method, butNot = Label) || self.isClass) self
else if (self.exists) self.owner.enclosingMethodOrClass
else NoSymbol

/** Apply symbol/symbol substitution to this symbol */
def subst(from: List[Symbol], to: List[Symbol]): Symbol = {
@tailrec def loop(from: List[Symbol], to: List[Symbol]): Symbol =
if (from.isEmpty) self
else if (self eq from.head) to.head
else loop(from.tail, to.tail)
loop(from, to)
}
/** The closest properly enclosing method or class of this symbol. */
final def enclosure(implicit ctx: Context) = {
self.owner.enclosingMethodOrClass
}

def accessorNamed(name: TermName)(implicit ctx: Context): Symbol =
self.owner.info.decl(name).suchThat(_ is Accessor).symbol
/** The closest enclosing method or class of this symbol */
@tailrec final def enclosingMethodOrClass(implicit ctx: Context): Symbol =
if (self.is(Method, butNot = Label) || self.isClass) self
else if (self.exists) self.owner.enclosingMethodOrClass
else NoSymbol

/** Apply symbol/symbol substitution to this symbol */
def subst(from: List[Symbol], to: List[Symbol]): Symbol = {
@tailrec def loop(from: List[Symbol], to: List[Symbol]): Symbol =
if (from.isEmpty) self
else if (self eq from.head) to.head
else loop(from.tail, to.tail)
loop(from, to)
}

def paramAccessors(implicit ctx: Context): List[Symbol] =
self.info.decls.filter(_ is ParamAccessor)
def accessorNamed(name: TermName)(implicit ctx: Context): Symbol =
self.owner.info.decl(name).suchThat(_ is Accessor).symbol

def caseAccessors(implicit ctx: Context): List[Symbol] =
self.info.decls.filter(_ is CaseAccessor)
def paramAccessors(implicit ctx: Context): List[Symbol] =
self.info.decls.filter(_ is ParamAccessor)

def getter(implicit ctx: Context): Symbol =
if (self.isGetter) self else accessorNamed(self.asTerm.name.getterName)
def caseAccessors(implicit ctx: Context): List[Symbol] =
self.info.decls.filter(_ is CaseAccessor)

def setter(implicit ctx: Context): Symbol =
if (self.isSetter) self
else accessorNamed(self.asTerm.name.setterName)
def getter(implicit ctx: Context): Symbol =
if (self.isGetter) self else accessorNamed(self.asTerm.name.getterName)

def field(implicit ctx: Context): Symbol = {
val thisName = self.name.asTermName
val fieldName =
if (self.hasAnnotation(defn.ScalaStaticAnnot)) thisName.getterName
else thisName.fieldName
self.owner.info.decl(fieldName).suchThat(!_.is(Method)).symbol
}
def setter(implicit ctx: Context): Symbol =
if (self.isSetter) self
else accessorNamed(self.asTerm.name.setterName)

def field(implicit ctx: Context): Symbol = {
val thisName = self.name.asTermName
val fieldName =
if (self.hasAnnotation(defn.ScalaStaticAnnot)) thisName.getterName
else thisName.fieldName
self.owner.info.decl(fieldName).suchThat(!_.is(Method)).symbol
}

def isField(implicit ctx: Context): Boolean =
self.isTerm && !self.is(Method)
def isField(implicit ctx: Context): Boolean =
self.isTerm && !self.is(Method)

def implClass(implicit ctx: Context): Symbol =
self.owner.info.decl(self.name.implClassName).symbol
def implClass(implicit ctx: Context): Symbol =
self.owner.info.decl(self.name.implClassName).symbol

def traitOfImplClass(implicit ctx: Context): Symbol =
self.owner.info.decl(self.name.traitOfImplClassName).symbol
def traitOfImplClass(implicit ctx: Context): Symbol =
self.owner.info.decl(self.name.traitOfImplClassName).symbol

def annotationsCarrying(meta: ClassSymbol)(implicit ctx: Context): List[Annotation] =
self.annotations.filter(_.symbol.hasAnnotation(meta))
def annotationsCarrying(meta: ClassSymbol)(implicit ctx: Context): List[Annotation] =
self.annotations.filter(_.symbol.hasAnnotation(meta))

def withAnnotationsCarrying(from: Symbol, meta: ClassSymbol)(implicit ctx: Context): self.type = {
self.addAnnotations(from.annotationsCarrying(meta))
self
}
def withAnnotationsCarrying(from: Symbol, meta: ClassSymbol)(implicit ctx: Context): self.type = {
self.addAnnotations(from.annotationsCarrying(meta))
self
}

def registerCompanionMethod(name: Name, target: Symbol)(implicit ctx: Context) = {
if (!self.unforcedDecls.lookup(name).exists) {
val companionMethod = ctx.synthesizeCompanionMethod(name, target, self)
if (companionMethod.exists) {
companionMethod.entered
def registerCompanionMethod(name: Name, target: Symbol)(implicit ctx: Context) = {
if (!self.unforcedDecls.lookup(name).exists) {
val companionMethod = ctx.synthesizeCompanionMethod(name, target, self)
if (companionMethod.exists) {
companionMethod.entered
}
}
}
}

/** If this symbol is an enum value or a named class, register it as a child
* in all direct parent classes which are sealed.
* @param @late If true, register only inaccessible children (all others are already
* entered at this point).
*/
def registerIfChild(late: Boolean = false)(implicit ctx: Context): Unit = {
def register(child: Symbol, parent: Type) = {
val cls = parent.classSymbol
if (cls.is(Sealed) && (!late || child.isInaccessibleChildOf(cls)))
cls.addAnnotation(Annotation.Child(child))
}
if (self.isClass && !self.isAnonymousClass)
self.asClass.classParents.foreach { parent =>
val child = if (self.is(Module)) self.sourceModule else self
register(child, parent)
/** If this symbol is an enum value or a named class, register it as a child
* in all direct parent classes which are sealed.
* @param @late If true, register only inaccessible children (all others are already
* entered at this point).
*/
def registerIfChild(late: Boolean = false)(implicit ctx: Context): Unit = {
def register(child: Symbol, parent: Type) = {
val cls = parent.classSymbol
if (cls.is(Sealed) && (!late || child.isInaccessibleChildOf(cls)))
cls.addAnnotation(Annotation.Child(child))
}
else if (self.is(CaseVal, butNot = Method | Module))
register(self, self.info)
}
if (self.isClass && !self.isAnonymousClass)
self.asClass.classParents.foreach { parent =>
val child = if (self.is(Module)) self.sourceModule else self
register(child, parent)
}
else if (self.is(CaseVal, butNot = Method | Module))
register(self, self.info)
}

/** Is this symbol defined locally (i.e. at some level owned by a term) and
* defined in a different toplevel class than its supposed parent class `cls`?
* Such children are not pickled, and have to be reconstituted manually.
*/
def isInaccessibleChildOf(cls: Symbol)(implicit ctx: Context) =
self.isLocal && !cls.topLevelClass.isLinkedWith(self.topLevelClass)
/** Is this symbol defined locally (i.e. at some level owned by a term) and
* defined in a different toplevel class than its supposed parent class `cls`?
* Such children are not pickled, and have to be reconstituted manually.
*/
def isInaccessibleChildOf(cls: Symbol)(implicit ctx: Context) =
self.isLocal && !cls.topLevelClass.isLinkedWith(self.topLevelClass)

/** If this is a sealed class, its known children */
def children(implicit ctx: Context): List[Symbol] =
self.annotations.collect {
case Annotation.Child(child) => child
}

/** If this is a sealed class, its known children */
def children(implicit ctx: Context): List[Symbol] =
self.annotations.collect {
case Annotation.Child(child) => child
/** Is symbol directly or indirectly owned by a term symbol? */
@tailrec def isLocal(implicit ctx: Context): Boolean = {
val owner = self.owner
if (owner.isTerm) true
else if (owner.is(Package)) false
else owner.isLocal
}

/** Is symbol directly or indirectly owned by a term symbol? */
@tailrec def isLocal(implicit ctx: Context): Boolean = {
val owner = self.owner
if (owner.isTerm) true
else if (owner.is(Package)) false
else owner.isLocal
}

/** Is symbol a quote operation? */
def isQuote(implicit ctx: Context): Boolean =
self == defn.quoteMethod || self == defn.typeQuoteMethod
/** Is symbol a quote operation? */
def isQuote(implicit ctx: Context): Boolean =
self == defn.quoteMethod || self == defn.typeQuoteMethod

/** Is symbol a splice operation? */
def isSplice(implicit ctx: Context): Boolean =
self == defn.QuotedExpr_~ || self == defn.QuotedType_~
/** Is symbol a splice operation? */
def isSplice(implicit ctx: Context): Boolean =
self == defn.QuotedExpr_~ || self == defn.QuotedType_~
}
}
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/ValueClasses.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ object ValueClasses {
d.isRealMethod &&
isDerivedValueClass(d.owner) &&
!d.isConstructor &&
!d.isSuperAccessor &&
!d.symbol.isSuperAccessor &&
!d.is(Macro)

/** The member of a derived value class that unboxes it. */
Expand Down