Skip to content

Commit 01205ef

Browse files
committed
Change naming scheme for inline and protedcted accessors
Use inline$x inline$x_= protected$x protected$x_= instead of inline_get$x inline_set$x protected_get$x protected_set$x Advantage: more idiomatic, and it's possible to make this work on untyped trees as well. The old scheme would have required accessors for every operator assignment when extending it to untyped trees.
1 parent 6a8c490 commit 01205ef

File tree

7 files changed

+84
-67
lines changed

7 files changed

+84
-67
lines changed

compiler/src/dotty/tools/dotc/core/NameKinds.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,8 @@ object NameKinds {
354354

355355
val SuperAccessorName = new PrefixNameKind(SUPERACCESSOR, "super$")
356356
val InitializerName = new PrefixNameKind(INITIALIZER, "initial$")
357-
val ProtectedGetterName = new PrefixNameKind(PROTECTEDGETTER, "protected_get$")
358-
val ProtectedSetterName = new PrefixNameKind(PROTECTEDSETTER, "protected_set$")
359-
val InlineGetterName = new PrefixNameKind(INLINEGETTER, "inline_get$")
360-
val InlineSetterName = new PrefixNameKind(INLINESETTER, "inline_set$")
357+
val ProtectedAccessorName = new PrefixNameKind(PROTECTEDACCESSOR, "protected$")
358+
val InlineAccessorName = new PrefixNameKind(INLINEACCESSOR, "inline$")
361359

362360
val AvoidClashName = new SuffixNameKind(AVOIDCLASH, "$_avoid_name_clash_$")
363361
val DirectMethodName = new SuffixNameKind(DIRECT, "$direct") { override def definesNewName = true }

compiler/src/dotty/tools/dotc/core/NameTags.scala

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ object NameTags extends TastyFormat.NameTags {
1515
// outer accessor that will be filled in by ExplicitOuter.
1616
// <num> indicates the number of hops needed to select the outer field.
1717

18-
final val PROTECTEDGETTER = 24 // The name of a protected getter `protected_get$<name>` created by ProtectedAccessors.
19-
20-
final val PROTECTEDSETTER = 25 // The name of a protected setter `protected_set$<name>` created by ProtectedAccessors.
18+
final val PROTECTEDACCESSOR = 24 // The name of a protected accesor `protected$<name>` created by ProtectedAccessors.
2119

2220
final val INITIALIZER = 26 // A mixin initializer method
2321

@@ -51,10 +49,8 @@ object NameTags extends TastyFormat.NameTags {
5149
case OUTERSELECT => "OUTERSELECT"
5250

5351
case SUPERACCESSOR => "SUPERACCESSOR"
54-
case INLINEGETTER => "INLINEGETTER"
55-
case INLINESETTER => "INLINESETTER"
56-
case PROTECTEDGETTER => "PROTECTEDGETTER"
57-
case PROTECTEDSETTER => "PROTECTEDSETTER"
52+
case INLINEACCESSOR => "INLINEACCESSOR"
53+
case PROTECTEDACCESSOR => "PROTECTEDACCESSOR"
5854
case INITIALIZER => "INITIALIZER"
5955
case AVOIDCLASH => "AVOIDCLASH"
6056
case DIRECT => "DIRECT"

compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ Macro-format:
3939
VARIANT Length underlying_NameRef variance_Nat // 0: Contravariant, 1: Covariant
4040
4141
SUPERACCESSOR Length underlying_NameRef
42-
INLINEGETTER Length underlying_NameRef
43-
INLINESETTER Length underlying_NameRef
42+
INLINEACCESSOR Length underlying_NameRef
4443
OBJECTCLASS Length underlying_NameRef
4544
4645
SIGNED Length original_NameRef resultSig_NameRef paramSig_NameRef*
@@ -252,9 +251,7 @@ object TastyFormat {
252251

253252
final val SUPERACCESSOR = 20 // The name of a super accessor `super$name` created by SuperAccesors.
254253

255-
final val INLINEGETTER = 21 // The name of an inline getter `inline_get$name`
256-
257-
final val INLINESETTER = 22 // The name of an inline setter `inline_set$name`
254+
final val INLINEACCESSOR = 21 // The name of an inline accessor `inline$name`
258255

259256
final val OBJECTCLASS = 23 // The name of an object class (or: module class) `<name>$`.
260257

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

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Contexts.Context
66
import Symbols._
77
import Flags._
88
import Names._
9+
import NameOps._
910
import Decorators._
1011
import TypeUtils._
1112
import Annotations.Annotation
@@ -23,9 +24,6 @@ abstract class AccessProxies {
2324
import ast.tpd._
2425
import AccessProxies._
2526

26-
def getterName: ClassifiedNameKind
27-
def setterName: ClassifiedNameKind
28-
2927
/** accessor -> accessed */
3028
private val accessedBy = newMutableSymbolMap[Symbol]
3129

@@ -38,7 +36,7 @@ abstract class AccessProxies {
3836
polyDefDef(accessor.asTerm, tps => argss => {
3937
val accessRef = ref(TermRef(cls.thisType, accessed))
4038
val rhs =
41-
if (accessor.name.is(setterName) &&
39+
if (accessor.name.isSetterName &&
4240
argss.nonEmpty && argss.head.nonEmpty) // defensive conditions
4341
accessRef.becomes(argss.head.head)
4442
else
@@ -56,6 +54,7 @@ abstract class AccessProxies {
5654
trait Insert {
5755
import ast.tpd._
5856

57+
def accessorNameKind: ClassifiedNameKind
5958
def needsAccessor(sym: Symbol)(implicit ctx: Context): Boolean
6059

6160
/** A fresh accessor symbol */
@@ -65,18 +64,41 @@ abstract class AccessProxies {
6564
sym
6665
}
6766

67+
private def rewire(reference: RefTree, accessor: Symbol)(implicit ctx: Context): Tree = {
68+
reference match {
69+
case Select(qual, _) => qual.select(accessor)
70+
case Ident(name) => ref(accessor)
71+
}
72+
}.withPos(reference.pos)
73+
74+
private def isAccessor(sym: Symbol, accessed: Symbol) = accessedBy.get(sym) == Some(accessed)
75+
76+
def useSetter(getterRef: RefTree)(implicit ctx: Context): Tree = {
77+
val getter = getterRef.symbol
78+
val accessed = accessedBy(getter)
79+
val accessedName = accessed.name.asTermName
80+
val setterName = accessorNameKind(accessedName.setterName)
81+
val setter =
82+
getter.owner.info.decl(setterName).suchThat(isAccessor(_, accessed)).symbol.orElse {
83+
val setterInfo = MethodType(getter.info.widenExpr :: Nil, defn.UnitType)
84+
val setter = newAccessorSymbol(getter.owner, setterName, setterInfo, getter.pos)
85+
accessedBy(setter) = accessed
86+
setter
87+
}
88+
rewire(getterRef, setter)
89+
}
90+
6891
/** Create an accessor unless one exists already, and replace the original
6992
* access with a reference to the accessor.
7093
*
7194
* @param reference The original reference to the non-public symbol
7295
* @param onLHS The reference is on the left-hand side of an assignment
7396
*/
7497
def useAccessor(reference: RefTree, onLHS: Boolean)(implicit ctx: Context): Tree = {
98+
assert(!onLHS)
7599

76-
def nameKind = if (onLHS) setterName else getterName
77100
val accessed = reference.symbol.asTerm
78101

79-
def refersToAccessed(sym: Symbol) = accessedBy.get(sym) == Some(accessed)
80102

81103
var accessorClass = hostForAccessorOf(accessed: Symbol)
82104
if (!accessorClass.exists) {
@@ -87,26 +109,23 @@ abstract class AccessProxies {
87109
accessorClass = curCls
88110
}
89111

90-
val accessorRawInfo =
91-
if (onLHS) MethodType(accessed.info :: Nil, defn.UnitType)
92-
else accessed.info.ensureMethodic
93-
val accessorInfo =
94-
accessorRawInfo.asSeenFrom(accessorClass.thisType, accessed.owner)
95-
val accessorName = nameKind(accessed.name)
96-
97-
val accessorSymbol =
98-
accessorClass.info.decl(accessorName).suchThat(refersToAccessed).symbol
99-
.orElse {
100-
val acc = newAccessorSymbol(accessorClass, accessorName, accessorInfo, accessed.pos)
101-
accessedBy(acc) = accessed
102-
acc
103-
}
104-
105-
{ reference match {
106-
case Select(qual, _) => qual.select(accessorSymbol)
107-
case Ident(name) => ref(accessorSymbol)
112+
val accessorName = accessorNameKind(
113+
if (onLHS) accessed.name.setterName else accessed.name)
114+
115+
116+
val accessor =
117+
accessorClass.info.decl(accessorName).suchThat(isAccessor(_, accessed)).symbol.orElse {
118+
val accessorRawInfo =
119+
if (onLHS) MethodType(accessed.info :: Nil, defn.UnitType)
120+
else accessed.info.ensureMethodic
121+
val accessorInfo =
122+
accessorRawInfo.asSeenFrom(accessorClass.thisType, accessed.owner)
123+
124+
val acc = newAccessorSymbol(accessorClass, accessorName, accessorInfo, accessed.pos)
125+
accessedBy(acc) = accessed
126+
acc
108127
}
109-
}.withPos(reference.pos)
128+
rewire(reference, accessor)
110129
}
111130

112131
/** Replace tree with a reference to an accessor if needed */

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

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import core.Flags._
88
import core.Decorators._
99
import MegaPhase.MiniPhase
1010
import ast.Trees._
11-
import util.Property
1211

1312
/** Add accessors for all protected accesses. An accessor is needed if
1413
* according to the rules of the JVM a protected class member is not accesissible
@@ -18,8 +17,6 @@ import util.Property
1817
object ProtectedAccessors {
1918
val name = "protectedAccessors"
2019

21-
private val LHS = new Property.StickyKey[Unit]
22-
2320
/** Is the current context's owner inside the access boundary established by `sym`? */
2421
def insideBoundaryOf(sym: Symbol)(implicit ctx: Context): Boolean = {
2522
if (sym.is(JavaDefined)) {
@@ -56,32 +53,30 @@ class ProtectedAccessors extends MiniPhase {
5653
override def phaseName = ProtectedAccessors.name
5754

5855
object Accessors extends AccessProxies {
59-
def getterName = ProtectedGetterName
60-
def setterName = ProtectedSetterName
61-
6256
val insert = new Insert {
57+
def accessorNameKind = ProtectedAccessorName
6358
def needsAccessor(sym: Symbol)(implicit ctx: Context) = ProtectedAccessors.needsAccessor(sym)
6459
}
6560
}
6661

67-
override def prepareForAssign(tree: Assign)(implicit ctx: Context) = {
68-
tree.lhs match {
69-
case lhs: RefTree if needsAccessor(lhs.symbol) => lhs.putAttachment(LHS, ())
70-
case _ =>
71-
}
72-
ctx
73-
}
74-
75-
private def isLHS(tree: RefTree) = tree.removeAttachment(LHS).isDefined
76-
7762
override def transformIdent(tree: Ident)(implicit ctx: Context): Tree =
78-
if (isLHS(tree)) tree else Accessors.insert.accessorIfNeeded(tree)
63+
Accessors.insert.accessorIfNeeded(tree)
7964

8065
override def transformSelect(tree: Select)(implicit ctx: Context): Tree =
81-
if (isLHS(tree)) tree else Accessors.insert.accessorIfNeeded(tree)
66+
Accessors.insert.accessorIfNeeded(tree)
8267

8368
override def transformAssign(tree: Assign)(implicit ctx: Context): Tree =
84-
Accessors.insert.accessorIfNeeded(tree)
69+
tree.lhs match {
70+
case lhs: RefTree =>
71+
lhs.name match {
72+
case ProtectedAccessorName(name) =>
73+
cpy.Apply(tree)(Accessors.insert.useSetter(lhs), tree.rhs :: Nil)
74+
case _ =>
75+
tree
76+
}
77+
case _ =>
78+
tree
79+
}
8580

8681
override def transformTemplate(tree: Template)(implicit ctx: Context): Tree =
8782
cpy.Template(tree)(body = Accessors.addAccessorDefs(tree.symbol.owner, tree.body))

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ class SuperAccessors(thisPhase: DenotTransformer) {
155155
AccessProxies.hostForAccessorOf(sym).is(Trait)
156156
qual match {
157157
case _: This if needsSuperAccessor =>
158-
println(i"trans super $sel in $currentClass")
159158
/*
160159
* A trait which extends a class and accesses a protected member
161160
* of that class cannot implement the necessary accessor method
@@ -165,7 +164,6 @@ class SuperAccessors(thisPhase: DenotTransformer) {
165164
* by the implementing class. See SI-2296.
166165
*/
167166
superAccessorCall(sel)
168-
.reporting(res => i"trans super $sel in $currentClass = $res")
169167
case Super(_, mix) =>
170168
transformSuperSelect(sel)
171169
case _ =>

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import StdNames.nme
1515
import Contexts.Context
1616
import Names.{Name, TermName, EmptyTermName}
1717
import NameOps._
18-
import NameKinds.{ClassifiedNameKind, InlineGetterName, InlineSetterName}
18+
import NameKinds.{ClassifiedNameKind, InlineAccessorName}
1919
import ProtoTypes.selectionProto
2020
import SymDenotations.SymDenotation
2121
import Annotations._
@@ -32,13 +32,12 @@ object Inliner {
3232
import tpd._
3333

3434
class InlineAccessors extends AccessProxies {
35-
def getterName = InlineGetterName
36-
def setterName = InlineSetterName
3735

3836
/** A tree map which inserts accessors for all non-public term members accessed
3937
* from inlined code. Accessors are collected in the `accessors` buffer.
4038
*/
4139
class MakeInlineable(inlineSym: Symbol) extends TreeMap with Insert {
40+
def accessorNameKind = InlineAccessorName
4241

4342
/** A definition needs an accessor if it is private, protected, or qualified private
4443
* and it is not part of the tree that gets inlined. The latter test is implemented
@@ -54,8 +53,23 @@ object Inliner {
5453
// This is quite tricky, as such types can appear anywhere, including as parts
5554
// of types of other things. For the moment we do nothing and complain
5655
// at the implicit expansion site if there's a reference to an inaccessible type.
57-
override def transform(tree: Tree)(implicit ctx: Context): Tree =
58-
super.transform(accessorIfNeeded(tree))
56+
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
57+
case tree: Assign =>
58+
transform(tree.lhs) match {
59+
case lhs1: RefTree =>
60+
lhs1.name match {
61+
case InlineAccessorName(name) =>
62+
cpy.Apply(tree)(useSetter(lhs1), transform(tree.rhs) :: Nil)
63+
case _ =>
64+
super.transform(tree)
65+
}
66+
case _ =>
67+
super.transform(tree)
68+
}
69+
case _ =>
70+
super.transform(accessorIfNeeded(tree))
71+
}
72+
5973
}
6074

6175
/** Adds accessors for all non-public term members accessed

0 commit comments

Comments
 (0)