@@ -58,33 +58,38 @@ abstract class AccessProxies {
58
58
def needsAccessor (sym : Symbol )(implicit ctx : Context ): Boolean
59
59
60
60
/** A fresh accessor symbol */
61
- def newAccessorSymbol (owner : Symbol , name : TermName , info : Type , pos : Position )(implicit ctx : Context ): TermSymbol = {
61
+ private def newAccessorSymbol (owner : Symbol , name : TermName , info : Type , pos : Position )(implicit ctx : Context ): TermSymbol = {
62
62
val sym = ctx.newSymbol(owner, name, Synthetic | Method , info, coord = pos).entered
63
63
if (sym.allOverriddenSymbols.exists(! _.is(Deferred ))) sym.setFlag(Override )
64
64
sym
65
65
}
66
66
67
+ /** An accessor symbol, create a fresh one unless one exists already */
68
+ private def accessorSymbol (owner : Symbol , accessorName : TermName , accessorInfo : Type , accessed : Symbol )(implicit ctx : Context ) = {
69
+ def refersToAccessed (sym : Symbol ) = accessedBy.get(sym) == Some (accessed)
70
+ owner.info.decl(accessorName).suchThat(refersToAccessed).symbol.orElse {
71
+ val acc = newAccessorSymbol(owner, accessorName, accessorInfo, accessed.pos)
72
+ accessedBy(acc) = accessed
73
+ acc
74
+ }
75
+ }
76
+
77
+ /** Rewire reference to refer to `accessor` symbol */
67
78
private def rewire (reference : RefTree , accessor : Symbol )(implicit ctx : Context ): Tree = {
68
79
reference match {
69
80
case Select (qual, _) => qual.select(accessor)
70
81
case Ident (name) => ref(accessor)
71
82
}
72
83
}.withPos(reference.pos)
73
84
74
- private def isAccessor (sym : Symbol , accessed : Symbol ) = accessedBy.get(sym) == Some (accessed)
75
-
85
+ /** Given a reference to a getter accessor, the corresponding setter reference */
76
86
def useSetter (getterRef : RefTree )(implicit ctx : Context ): Tree = {
77
87
val getter = getterRef.symbol
78
88
val accessed = accessedBy(getter)
79
89
val accessedName = accessed.name.asTermName
80
90
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
- }
91
+ val setterInfo = MethodType (getter.info.widenExpr :: Nil , defn.UnitType )
92
+ val setter = accessorSymbol(getter.owner, setterName, setterInfo, accessed)
88
93
rewire(getterRef, setter)
89
94
}
90
95
@@ -94,12 +99,8 @@ abstract class AccessProxies {
94
99
* @param reference The original reference to the non-public symbol
95
100
* @param onLHS The reference is on the left-hand side of an assignment
96
101
*/
97
- def useAccessor (reference : RefTree , onLHS : Boolean )(implicit ctx : Context ): Tree = {
98
- assert(! onLHS)
99
-
102
+ def useAccessor (reference : RefTree )(implicit ctx : Context ): Tree = {
100
103
val accessed = reference.symbol.asTerm
101
-
102
-
103
104
var accessorClass = hostForAccessorOf(accessed : Symbol )
104
105
if (! accessorClass.exists) {
105
106
val curCls = ctx.owner.enclosingClass
@@ -108,23 +109,10 @@ abstract class AccessProxies {
108
109
reference.pos)
109
110
accessorClass = curCls
110
111
}
111
-
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
127
- }
112
+ val accessorName = accessorNameKind(accessed.name)
113
+ val accessorInfo =
114
+ accessed.info.ensureMethodic.asSeenFrom(accessorClass.thisType, accessed.owner)
115
+ val accessor = accessorSymbol(accessorClass, accessorName, accessorInfo, accessed)
128
116
rewire(reference, accessor)
129
117
}
130
118
@@ -135,15 +123,16 @@ abstract class AccessProxies {
135
123
ctx.error(" Implementation restriction: cannot use private constructors in inline methods" , tree.pos)
136
124
tree // TODO: create a proper accessor for the private constructor
137
125
}
138
- else useAccessor(tree, onLHS = false )
139
- case Assign (lhs : RefTree , rhs) if needsAccessor(lhs.symbol) =>
140
- cpy.Apply (tree)(useAccessor(lhs, onLHS = true ), List (rhs))
126
+ else useAccessor(tree)
141
127
case _ =>
142
128
tree
143
129
}
144
130
}
145
131
}
146
132
object AccessProxies {
133
+ /** Where an accessor for the `accessed` symbol should be placed.
134
+ * This is the closest enclosing class that has `accessed` as a member.
135
+ */
147
136
def hostForAccessorOf (accessed : Symbol )(implicit ctx : Context ): Symbol =
148
137
ctx.owner.ownersIterator.findSymbol(_.derivesFrom(accessed.owner))
149
138
}
0 commit comments