@@ -58,33 +58,38 @@ abstract class AccessProxies {
5858 def needsAccessor (sym : Symbol )(implicit ctx : Context ): Boolean
5959
6060 /** 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 = {
6262 val sym = ctx.newSymbol(owner, name, Synthetic | Method , info, coord = pos).entered
6363 if (sym.allOverriddenSymbols.exists(! _.is(Deferred ))) sym.setFlag(Override )
6464 sym
6565 }
6666
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 */
6778 private def rewire (reference : RefTree , accessor : Symbol )(implicit ctx : Context ): Tree = {
6879 reference match {
6980 case Select (qual, _) => qual.select(accessor)
7081 case Ident (name) => ref(accessor)
7182 }
7283 }.withPos(reference.pos)
7384
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 */
7686 def useSetter (getterRef : RefTree )(implicit ctx : Context ): Tree = {
7787 val getter = getterRef.symbol
7888 val accessed = accessedBy(getter)
7989 val accessedName = accessed.name.asTermName
8090 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)
8893 rewire(getterRef, setter)
8994 }
9095
@@ -94,12 +99,8 @@ abstract class AccessProxies {
9499 * @param reference The original reference to the non-public symbol
95100 * @param onLHS The reference is on the left-hand side of an assignment
96101 */
97- def useAccessor (reference : RefTree , onLHS : Boolean )(implicit ctx : Context ): Tree = {
98- assert(! onLHS)
99-
102+ def useAccessor (reference : RefTree )(implicit ctx : Context ): Tree = {
100103 val accessed = reference.symbol.asTerm
101-
102-
103104 var accessorClass = hostForAccessorOf(accessed : Symbol )
104105 if (! accessorClass.exists) {
105106 val curCls = ctx.owner.enclosingClass
@@ -108,23 +109,10 @@ abstract class AccessProxies {
108109 reference.pos)
109110 accessorClass = curCls
110111 }
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)
128116 rewire(reference, accessor)
129117 }
130118
@@ -135,15 +123,16 @@ abstract class AccessProxies {
135123 ctx.error(" Implementation restriction: cannot use private constructors in inline methods" , tree.pos)
136124 tree // TODO: create a proper accessor for the private constructor
137125 }
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)
141127 case _ =>
142128 tree
143129 }
144130 }
145131}
146132object 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+ */
147136 def hostForAccessorOf (accessed : Symbol )(implicit ctx : Context ): Symbol =
148137 ctx.owner.ownersIterator.findSymbol(_.derivesFrom(accessed.owner))
149138}
0 commit comments