Skip to content

Commit 8d8ce45

Browse files
committed
Use a map instead of an annotation to keep track of accessors
Reverted: New annotation on inline accessors (reverted from commit 9cde3dd) Also: Fix accessor definition to work for accesses to members of superclasses.
1 parent 2b53d67 commit 8d8ce45

File tree

9 files changed

+59
-57
lines changed

9 files changed

+59
-57
lines changed

compiler/src/dotty/tools/dotc/CompilationUnit.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package dotty.tools
22
package dotc
33

4-
import dotty.tools.dotc.core.Types.Type // Do not remove me #3383
4+
import core.Types.Type // Do not remove me #3383
55
import util.SourceFile
66
import ast.{tpd, untpd}
7-
import dotty.tools.dotc.ast.tpd.{ Tree, TreeTraverser }
7+
import tpd.{ Tree, TreeTraverser }
8+
import typer.Inliner.InlineAccessors
89
import dotty.tools.dotc.core.Contexts.Context
910
import dotty.tools.dotc.core.SymDenotations.ClassDenotation
1011
import dotty.tools.dotc.core.Symbols._
@@ -27,6 +28,9 @@ class CompilationUnit(val source: SourceFile) {
2728
* is used in phase ReifyQuotes in order to avoid traversing a quote-less tree.
2829
*/
2930
var containsQuotesOrSplices: Boolean = false
31+
32+
/** A structure containing a temporary map for generating inline accessors */
33+
val inlineAccessors = new InlineAccessors
3034
}
3135

3236
object CompilationUnit {

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

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -146,26 +146,11 @@ object Annotations {
146146
def deferredResolve(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation =
147147
deferred(atp.classSymbol, implicit ctx => resolveConstructor(atp, args))
148148

149-
class TermRefAnnotExtractor(annotFn: Context => Symbol) {
149+
def makeAlias(sym: TermSymbol)(implicit ctx: Context) =
150+
apply(defn.AliasAnnot, List(
151+
ref(TermRef(sym.owner.thisType, sym.name, sym))))
150152

151-
def apply(sym: TermSymbol)(implicit ctx: Context): Annotation =
152-
Annotation(annotFn(ctx).typeRef, List(ref(TermRef(sym.owner.thisType, sym.name, sym))))
153-
154-
def unapply(ann: Annotation)(implicit ctx: Context): Option[Symbol] =
155-
if (ann.symbol == annotFn(ctx)) {
156-
val ast.Trees.Apply(fn, arg :: Nil) = ann.tree
157-
Some(arg.symbol)
158-
}
159-
else None
160-
}
161-
162-
/** Extractor for "accessed" annotations */
163-
object Accessed extends TermRefAnnotExtractor(implicit ctx => defn.AccessedAnnot)
164-
165-
/** Extractor for "aliased" annotations */
166-
object Alias extends TermRefAnnotExtractor(implicit ctx => defn.AliasAnnot)
167-
168-
/** Extractor for "child" annotations */
153+
/** Extractor for child annotations */
169154
object Child {
170155

171156
/** A deferred annotation to the result of a given child computation */

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -692,8 +692,6 @@ class Definitions {
692692
// Annotation classes
693693
lazy val AliasAnnotType = ctx.requiredClassRef("scala.annotation.internal.Alias")
694694
def AliasAnnot(implicit ctx: Context) = AliasAnnotType.symbol.asClass
695-
lazy val AccessedAnnotType = ctx.requiredClassRef("scala.annotation.internal.Accessed")
696-
def AccessedAnnot(implicit ctx: Context) = AccessedAnnotType.symbol.asClass
697695
lazy val AnnotationDefaultAnnotType = ctx.requiredClassRef("scala.annotation.internal.AnnotationDefault")
698696
def AnnotationDefaultAnnot(implicit ctx: Context) = AnnotationDefaultAnnotType.symbol.asClass
699697
lazy val BodyAnnotType = ctx.requiredClassRef("scala.annotation.internal.Body")

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
578578
}
579579
}
580580
val alias = readDisambiguatedSymbolRef(disambiguate).asTerm
581-
denot.addAnnotation(Annotation.Alias(alias))
581+
denot.addAnnotation(Annotation.makeAlias(alias))
582582
}
583583
}
584584
// println(s"unpickled ${denot.debugString}, info = ${denot.info}") !!! DEBUG

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

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,36 @@ import ast.Trees._
1515
import util.Property
1616
import util.Positions.Position
1717

18+
/** A utility class for generating access proxies. Currently used for
19+
* inline accessors and protected accessors.
20+
*/
1821
abstract class AccessProxies {
1922
import ast.tpd._
2023

2124
def getterName: ClassifiedNameKind
2225
def setterName: ClassifiedNameKind
2326

27+
/** accessor -> accessed */
28+
private val accessedBy = newMutableSymbolMap[Symbol]
29+
2430
/** The accessor definitions that need to be added to class `cls`
25-
* As a side-effect, this method removes the `Accessed` annotations from
26-
* the accessor symbols. So a second call of the same method will yield the empty list.
31+
* As a side-effect, this method removes entries from the `accessedBy` map.
32+
* So a second call of the same method will yield the empty list.
2733
*/
28-
private def accessorDefs(cls: Symbol)(implicit ctx: Context): List[DefDef] =
29-
for {
30-
accessor <- cls.info.decls.filter(sym => sym.name.is(getterName) || sym.name.is(setterName))
31-
Annotation.Accessed(accessed) <- accessor.getAnnotation(defn.AccessedAnnot)
32-
}
33-
yield polyDefDef(accessor.asTerm, tps => argss => {
34-
accessor.removeAnnotation(defn.AccessedAnnot)
35-
val rhs =
36-
if (accessor.name.is(setterName) &&
37-
argss.nonEmpty && argss.head.nonEmpty) // defensive conditions
38-
ref(accessed).becomes(argss.head.head)
39-
else
40-
ref(accessed).appliedToTypes(tps).appliedToArgss(argss)
41-
rhs.withPos(accessed.pos)
42-
})
34+
private def accessorDefs(cls: Symbol)(implicit ctx: Context): Iterator[DefDef] =
35+
for (accessor <- cls.info.decls.iterator; accessed <- accessedBy.remove(accessor)) yield
36+
polyDefDef(accessor.asTerm, tps => argss => {
37+
val accessRef = ref(TermRef(cls.thisType, accessed))
38+
val rhs =
39+
if (accessor.name.is(setterName) &&
40+
argss.nonEmpty && argss.head.nonEmpty) // defensive conditions
41+
accessRef.becomes(argss.head.head)
42+
else
43+
accessRef.appliedToTypes(tps).appliedToArgss(argss)
44+
rhs.withPos(accessed.pos)
45+
})
4346

47+
/** Add all needed accessors to the `body` of class `cls` */
4448
def addAccessorDefs(cls: Symbol, body: List[Tree])(implicit ctx: Context): List[Tree] = {
4549
val accDefs = accessorDefs(cls)
4650
if (accDefs.isEmpty) body else body ++ accDefs
@@ -67,10 +71,7 @@ abstract class AccessProxies {
6771
def nameKind = if (onLHS) setterName else getterName
6872
val accessed = reference.symbol.asTerm
6973

70-
def refersToAccessed(sym: Symbol) = sym.getAnnotation(defn.AccessedAnnot) match {
71-
case Some(Annotation.Accessed(sym)) => sym `eq` accessed
72-
case _ => false
73-
}
74+
def refersToAccessed(sym: Symbol) = accessedBy.get(sym) == Some(accessed)
7475

7576
val accessorInfo =
7677
if (onLHS) MethodType(accessed.info :: Nil, defn.UnitType)
@@ -80,7 +81,7 @@ abstract class AccessProxies {
8081
accessed.owner.info.decl(accessorName).suchThat(refersToAccessed).symbol
8182
.orElse {
8283
val acc = newAccessorSymbol(accessed, accessorName, accessorInfo)
83-
acc.addAnnotation(Annotation.Accessed(accessed))
84+
accessedBy(acc) = accessed
8485
acc
8586
}
8687

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import util.Positions.Position
3131
object Inliner {
3232
import tpd._
3333

34-
object InlineAccessors extends AccessProxies {
34+
class InlineAccessors extends AccessProxies {
3535
def getterName = InlineGetterName
3636
def setterName = InlineSetterName
3737

@@ -95,7 +95,7 @@ object Inliner {
9595
sym.updateAnnotation(LazyBodyAnnotation { _ =>
9696
implicit val ctx = inlineCtx
9797
val body = treeExpr(ctx)
98-
if (ctx.reporter.hasErrors) body else InlineAccessors.makeInlineable(body)
98+
if (ctx.reporter.hasErrors) body else ctx.compilationUnit.inlineAccessors.makeInlineable(body)
9999
})
100100
}
101101
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1562,7 +1562,7 @@ class Typer extends Namer
15621562
}
15631563

15641564
protected def addAccessorDefs(cls: Symbol, body: List[Tree])(implicit ctx: Context): List[Tree] =
1565-
Inliner.InlineAccessors.addAccessorDefs(cls, body)
1565+
ctx.compilationUnit.inlineAccessors.addAccessorDefs(cls, body)
15661566

15671567
/** Ensure that the first type in a list of parent types Ps points to a non-trait class.
15681568
* If that's not already the case, add one. The added class type CT is determined as follows.

library/src/scala/annotation/internal/Accessed.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/run/inlineProtected.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package P {
2+
class C {
3+
protected def f(): Int = 22
4+
}
5+
}
6+
7+
package Q {
8+
class D extends P.C {
9+
class Inner {
10+
inline def g() = f()
11+
}
12+
}
13+
}
14+
15+
object Test extends App {
16+
import Q._
17+
18+
val d = new D
19+
val i = new d.Inner
20+
val x = i.g()
21+
assert(x == 22)
22+
}

0 commit comments

Comments
 (0)