Skip to content

Commit c01612a

Browse files
Refactor SymUtils.decorate* as an implicit class
1 parent f2fba0b commit c01612a

File tree

4 files changed

+135
-140
lines changed

4 files changed

+135
-140
lines changed

compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -828,8 +828,8 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
828828
def freshLocal(cunit: CompilationUnit, name: String, tpe: Type, pos: Position, flags: Flags): Symbol =
829829
ctx.newSymbol(sym, name.toTermName, FlagSet(flags), tpe, NoSymbol, pos.toCoord)
830830

831-
def getter(clz: Symbol): Symbol = decorateSymbol(sym).getter
832-
def setter(clz: Symbol): Symbol = decorateSymbol(sym).setter
831+
def getter(clz: Symbol): Symbol = new SymUtilsOps(sym).getter
832+
def setter(clz: Symbol): Symbol = new SymUtilsOps(sym).setter
833833

834834
def moduleSuffix: String = "" // todo: validate that names already have $ suffix
835835
def outputDirectory: AbstractFile = DottyBackendInterface.this.outputDirectory
@@ -842,7 +842,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
842842
* Redundant interfaces are removed unless there is a super call to them.
843843
*/
844844
def superInterfaces: List[Symbol] = {
845-
val directlyInheritedTraits = decorateSymbol(sym).directlyInheritedTraits
845+
val directlyInheritedTraits = new SymUtilsOps(sym).directlyInheritedTraits
846846
val directlyInheritedTraitsSet = directlyInheritedTraits.toSet
847847
val allBaseClasses = directlyInheritedTraits.iterator.flatMap(_.symbol.asClass.baseClasses.drop(1)).toSet
848848
val superCalls = superCallsMap.getOrElse(sym, Set.empty)

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,9 +575,9 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
575575

576576
if (denot.isConstructor) addConstructorTypeParams(denot)
577577
if (atEnd) {
578-
assert(!denot.isSuperAccessor, denot)
578+
assert(!denot.symbol.isSuperAccessor, denot)
579579
} else {
580-
assert(denot.is(ParamAccessor) || denot.isSuperAccessor, denot)
580+
assert(denot.is(ParamAccessor) || denot.symbol.isSuperAccessor, denot)
581581
def disambiguate(alt: Symbol) = { // !!! DEBUG
582582
trace.onDebug(s"disambiguating ${denot.info} =:= ${denot.owner.thisType.memberInfo(alt)} ${denot.owner}") {
583583
denot.info matches denot.owner.thisType.memberInfo(alt)

compiler/src/dotty/tools/dotc/transform/SymUtils.scala

Lines changed: 129 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -18,169 +18,164 @@ import language.implicitConversions
1818
import scala.annotation.tailrec
1919

2020
object SymUtils {
21-
implicit def decorateSymbol(sym: Symbol): SymUtils = new SymUtils(sym)
22-
implicit def decorateSymDenot(d: SymDenotation): SymUtils = new SymUtils(d.symbol)
23-
}
24-
25-
/** A decorator that provides methods on symbols
26-
* that are needed in the transformer pipeline.
27-
*/
28-
class SymUtils(val self: Symbol) extends AnyVal {
29-
import SymUtils._
30-
31-
/** All traits implemented by a class or trait except for those inherited through the superclass. */
32-
def directlyInheritedTraits(implicit ctx: Context) = {
33-
val superCls = self.asClass.superClass
34-
val baseClasses = self.asClass.baseClasses
35-
if (baseClasses.isEmpty) Nil
36-
else baseClasses.tail.takeWhile(_ ne superCls).reverse
37-
}
38-
39-
/** All traits implemented by a class, except for those inherited through the superclass.
40-
* The empty list if `self` is a trait.
21+
/** A decorator that provides methods on symbols
22+
* that are needed in the transformer pipeline.
4123
*/
42-
def mixins(implicit ctx: Context) = {
43-
if (self is Trait) Nil
44-
else directlyInheritedTraits
45-
}
24+
implicit class SymUtilsOps(val self: Symbol) extends AnyVal {
25+
/** All traits implemented by a class or trait except for those inherited through the superclass. */
26+
def directlyInheritedTraits(implicit ctx: Context) = {
27+
val superCls = self.asClass.superClass
28+
val baseClasses = self.asClass.baseClasses
29+
if (baseClasses.isEmpty) Nil
30+
else baseClasses.tail.takeWhile(_ ne superCls).reverse
31+
}
4632

47-
def isTypeTest(implicit ctx: Context): Boolean =
48-
self == defn.Any_isInstanceOf || self == defn.Any_typeTest
33+
/** All traits implemented by a class, except for those inherited through the superclass.
34+
* The empty list if `self` is a trait.
35+
*/
36+
def mixins(implicit ctx: Context) = {
37+
if (self is Trait) Nil
38+
else directlyInheritedTraits
39+
}
4940

50-
def isTypeTestOrCast(implicit ctx: Context): Boolean =
51-
self == defn.Any_asInstanceOf || isTypeTest
41+
def isTypeTest(implicit ctx: Context): Boolean =
42+
self == defn.Any_isInstanceOf || self == defn.Any_typeTest
5243

53-
def isVolatile(implicit ctx: Context) = self.hasAnnotation(defn.VolatileAnnot)
44+
def isTypeTestOrCast(implicit ctx: Context): Boolean =
45+
self == defn.Any_asInstanceOf || isTypeTest
5446

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

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

60-
/** A type or term parameter or a term parameter accessor */
61-
def isParamOrAccessor(implicit ctx: Context) =
62-
self.is(Param) || self.is(ParamAccessor)
52+
def isSuperAccessor(implicit ctx: Context) = self.name.is(SuperAccessorName)
6353

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

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

73-
/** The closest enclosing method or class of this symbol */
74-
@tailrec final def enclosingMethodOrClass(implicit ctx: Context): Symbol =
75-
if (self.is(Method, butNot = Label) || self.isClass) self
76-
else if (self.exists) self.owner.enclosingMethodOrClass
77-
else NoSymbol
78-
79-
/** Apply symbol/symbol substitution to this symbol */
80-
def subst(from: List[Symbol], to: List[Symbol]): Symbol = {
81-
@tailrec def loop(from: List[Symbol], to: List[Symbol]): Symbol =
82-
if (from.isEmpty) self
83-
else if (self eq from.head) to.head
84-
else loop(from.tail, to.tail)
85-
loop(from, to)
86-
}
62+
/** The closest properly enclosing method or class of this symbol. */
63+
final def enclosure(implicit ctx: Context) = {
64+
self.owner.enclosingMethodOrClass
65+
}
8766

88-
def accessorNamed(name: TermName)(implicit ctx: Context): Symbol =
89-
self.owner.info.decl(name).suchThat(_ is Accessor).symbol
67+
/** The closest enclosing method or class of this symbol */
68+
@tailrec final def enclosingMethodOrClass(implicit ctx: Context): Symbol =
69+
if (self.is(Method, butNot = Label) || self.isClass) self
70+
else if (self.exists) self.owner.enclosingMethodOrClass
71+
else NoSymbol
72+
73+
/** Apply symbol/symbol substitution to this symbol */
74+
def subst(from: List[Symbol], to: List[Symbol]): Symbol = {
75+
@tailrec def loop(from: List[Symbol], to: List[Symbol]): Symbol =
76+
if (from.isEmpty) self
77+
else if (self eq from.head) to.head
78+
else loop(from.tail, to.tail)
79+
loop(from, to)
80+
}
9081

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

94-
def caseAccessors(implicit ctx: Context): List[Symbol] =
95-
self.info.decls.filter(_ is CaseAccessor)
85+
def paramAccessors(implicit ctx: Context): List[Symbol] =
86+
self.info.decls.filter(_ is ParamAccessor)
9687

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

100-
def setter(implicit ctx: Context): Symbol =
101-
if (self.isSetter) self
102-
else accessorNamed(self.asTerm.name.setterName)
91+
def getter(implicit ctx: Context): Symbol =
92+
if (self.isGetter) self else accessorNamed(self.asTerm.name.getterName)
10393

104-
def field(implicit ctx: Context): Symbol = {
105-
val thisName = self.name.asTermName
106-
val fieldName =
107-
if (self.hasAnnotation(defn.ScalaStaticAnnot)) thisName.getterName
108-
else thisName.fieldName
109-
self.owner.info.decl(fieldName).suchThat(!_.is(Method)).symbol
110-
}
94+
def setter(implicit ctx: Context): Symbol =
95+
if (self.isSetter) self
96+
else accessorNamed(self.asTerm.name.setterName)
97+
98+
def field(implicit ctx: Context): Symbol = {
99+
val thisName = self.name.asTermName
100+
val fieldName =
101+
if (self.hasAnnotation(defn.ScalaStaticAnnot)) thisName.getterName
102+
else thisName.fieldName
103+
self.owner.info.decl(fieldName).suchThat(!_.is(Method)).symbol
104+
}
111105

112-
def isField(implicit ctx: Context): Boolean =
113-
self.isTerm && !self.is(Method)
106+
def isField(implicit ctx: Context): Boolean =
107+
self.isTerm && !self.is(Method)
114108

115-
def implClass(implicit ctx: Context): Symbol =
116-
self.owner.info.decl(self.name.implClassName).symbol
109+
def implClass(implicit ctx: Context): Symbol =
110+
self.owner.info.decl(self.name.implClassName).symbol
117111

118-
def traitOfImplClass(implicit ctx: Context): Symbol =
119-
self.owner.info.decl(self.name.traitOfImplClassName).symbol
112+
def traitOfImplClass(implicit ctx: Context): Symbol =
113+
self.owner.info.decl(self.name.traitOfImplClassName).symbol
120114

121-
def annotationsCarrying(meta: ClassSymbol)(implicit ctx: Context): List[Annotation] =
122-
self.annotations.filter(_.symbol.hasAnnotation(meta))
115+
def annotationsCarrying(meta: ClassSymbol)(implicit ctx: Context): List[Annotation] =
116+
self.annotations.filter(_.symbol.hasAnnotation(meta))
123117

124-
def withAnnotationsCarrying(from: Symbol, meta: ClassSymbol)(implicit ctx: Context): self.type = {
125-
self.addAnnotations(from.annotationsCarrying(meta))
126-
self
127-
}
118+
def withAnnotationsCarrying(from: Symbol, meta: ClassSymbol)(implicit ctx: Context): self.type = {
119+
self.addAnnotations(from.annotationsCarrying(meta))
120+
self
121+
}
128122

129-
def registerCompanionMethod(name: Name, target: Symbol)(implicit ctx: Context) = {
130-
if (!self.unforcedDecls.lookup(name).exists) {
131-
val companionMethod = ctx.synthesizeCompanionMethod(name, target, self)
132-
if (companionMethod.exists) {
133-
companionMethod.entered
123+
def registerCompanionMethod(name: Name, target: Symbol)(implicit ctx: Context) = {
124+
if (!self.unforcedDecls.lookup(name).exists) {
125+
val companionMethod = ctx.synthesizeCompanionMethod(name, target, self)
126+
if (companionMethod.exists) {
127+
companionMethod.entered
128+
}
134129
}
135130
}
136-
}
137131

138-
/** If this symbol is an enum value or a named class, register it as a child
139-
* in all direct parent classes which are sealed.
140-
* @param @late If true, register only inaccessible children (all others are already
141-
* entered at this point).
142-
*/
143-
def registerIfChild(late: Boolean = false)(implicit ctx: Context): Unit = {
144-
def register(child: Symbol, parent: Type) = {
145-
val cls = parent.classSymbol
146-
if (cls.is(Sealed) && (!late || child.isInaccessibleChildOf(cls)))
147-
cls.addAnnotation(Annotation.Child(child))
148-
}
149-
if (self.isClass && !self.isAnonymousClass)
150-
self.asClass.classParents.foreach { parent =>
151-
val child = if (self.is(Module)) self.sourceModule else self
152-
register(child, parent)
132+
/** If this symbol is an enum value or a named class, register it as a child
133+
* in all direct parent classes which are sealed.
134+
* @param @late If true, register only inaccessible children (all others are already
135+
* entered at this point).
136+
*/
137+
def registerIfChild(late: Boolean = false)(implicit ctx: Context): Unit = {
138+
def register(child: Symbol, parent: Type) = {
139+
val cls = parent.classSymbol
140+
if (cls.is(Sealed) && (!late || child.isInaccessibleChildOf(cls)))
141+
cls.addAnnotation(Annotation.Child(child))
153142
}
154-
else if (self.is(CaseVal, butNot = Method | Module))
155-
register(self, self.info)
156-
}
143+
if (self.isClass && !self.isAnonymousClass)
144+
self.asClass.classParents.foreach { parent =>
145+
val child = if (self.is(Module)) self.sourceModule else self
146+
register(child, parent)
147+
}
148+
else if (self.is(CaseVal, butNot = Method | Module))
149+
register(self, self.info)
150+
}
157151

158-
/** Is this symbol defined locally (i.e. at some level owned by a term) and
159-
* defined in a different toplevel class than its supposed parent class `cls`?
160-
* Such children are not pickled, and have to be reconstituted manually.
161-
*/
162-
def isInaccessibleChildOf(cls: Symbol)(implicit ctx: Context) =
163-
self.isLocal && !cls.topLevelClass.isLinkedWith(self.topLevelClass)
152+
/** Is this symbol defined locally (i.e. at some level owned by a term) and
153+
* defined in a different toplevel class than its supposed parent class `cls`?
154+
* Such children are not pickled, and have to be reconstituted manually.
155+
*/
156+
def isInaccessibleChildOf(cls: Symbol)(implicit ctx: Context) =
157+
self.isLocal && !cls.topLevelClass.isLinkedWith(self.topLevelClass)
158+
159+
/** If this is a sealed class, its known children */
160+
def children(implicit ctx: Context): List[Symbol] =
161+
self.annotations.collect {
162+
case Annotation.Child(child) => child
163+
}
164164

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

171-
/** Is symbol directly or indirectly owned by a term symbol? */
172-
@tailrec def isLocal(implicit ctx: Context): Boolean = {
173-
val owner = self.owner
174-
if (owner.isTerm) true
175-
else if (owner.is(Package)) false
176-
else owner.isLocal
177-
}
178-
179-
/** Is symbol a quote operation? */
180-
def isQuote(implicit ctx: Context): Boolean =
181-
self == defn.quoteMethod || self == defn.typeQuoteMethod
173+
/** Is symbol a quote operation? */
174+
def isQuote(implicit ctx: Context): Boolean =
175+
self == defn.quoteMethod || self == defn.typeQuoteMethod
182176

183-
/** Is symbol a splice operation? */
184-
def isSplice(implicit ctx: Context): Boolean =
185-
self == defn.QuotedExpr_~ || self == defn.QuotedType_~
177+
/** Is symbol a splice operation? */
178+
def isSplice(implicit ctx: Context): Boolean =
179+
self == defn.QuotedExpr_~ || self == defn.QuotedType_~
180+
}
186181
}

compiler/src/dotty/tools/dotc/transform/ValueClasses.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ object ValueClasses {
2525
d.isRealMethod &&
2626
isDerivedValueClass(d.owner) &&
2727
!d.isConstructor &&
28-
!d.isSuperAccessor &&
28+
!d.symbol.isSuperAccessor &&
2929
!d.is(Macro)
3030

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

0 commit comments

Comments
 (0)