Skip to content

Commit 4ecf1ad

Browse files
committed
Provide for watching term references
We have the DerivedTypeTree abstraction to generate a TypeTree during desugaring that watches a symbol that does not yet exist. We now need to generalize this so that we can also create term references (i.e. term idents) that watch a symbol. The necessity comes from enums an enum like enum Color { case C1; ...; case Cn; ... } needs to be expanded to sealed abstract class Color { import Color.{C1, ..., Cn} ... } object Color { case class C1; ...; case class Cn } Otherwise the `...` in class `Color` could not refer to the cases. The problem is that we cannot simply write an untyped ident `Color` in the import clause, because a different `Color` might be defined or inherited in the `enum`, so we would get a wrong binding. We need to refer to the `Color` companion object as a symbol, but this one does not yet exist at the point where we expand. Hence the need for a new mechanism. An added complexity comes from the fact that these references go to the ValDef part of a synthesized companion objects. But these objects might be merged with user-defined ones later. We have to make sure that References attachments are correctly passed along in such merges.
1 parent c8623db commit 4ecf1ad

File tree

4 files changed

+22
-8
lines changed

4 files changed

+22
-8
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ object desugar {
3333
// ----- DerivedTypeTrees -----------------------------------
3434

3535
class SetterParamTree extends DerivedTypeTree {
36-
def derivedType(sym: Symbol)(implicit ctx: Context) = sym.info.resultType
36+
def derivedTree(sym: Symbol)(implicit ctx: Context) = tpd.TypeTree(sym.info.resultType)
3737
}
3838

3939
class TypeRefTree extends DerivedTypeTree {
40-
def derivedType(sym: Symbol)(implicit ctx: Context) = sym.typeRef
40+
def derivedTree(sym: Symbol)(implicit ctx: Context) = tpd.TypeTree(sym.typeRef)
41+
}
42+
43+
class TermRefTree extends DerivedTypeTree {
44+
def derivedTree(sym: Symbol)(implicit ctx: Context) = tpd.ref(sym)
4145
}
4246

4347
/** A type tree that computes its type from an existing parameter.
@@ -73,7 +77,7 @@ object desugar {
7377
*
7478
* parameter name == reference name ++ suffix
7579
*/
76-
def derivedType(sym: Symbol)(implicit ctx: Context) = {
80+
def derivedTree(sym: Symbol)(implicit ctx: Context) = {
7781
val relocate = new TypeMap {
7882
val originalOwner = sym.owner
7983
def apply(tp: Type) = tp match {
@@ -91,7 +95,7 @@ object desugar {
9195
mapOver(tp)
9296
}
9397
}
94-
relocate(sym.info)
98+
tpd.TypeTree(relocate(sym.info))
9599
}
96100
}
97101

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
228228
*/
229229
def ensureCompletions(implicit ctx: Context): Unit = ()
230230

231-
/** The method that computes the type of this tree */
232-
def derivedType(originalSym: Symbol)(implicit ctx: Context): Type
231+
/** The method that computes the tree with the derived type */
232+
def derivedTree(originalSym: Symbol)(implicit ctx: Context): tpd.Tree
233233
}
234234

235235
/** Property key containing TypeTrees whose type is computed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,13 @@ class Namer { typer: Typer =>
526526
mdef.putAttachment(ExpandedTree, Thicket(trees.filter(_ != tree)))
527527
}
528528

529+
/** Transfer all references to `from` to `to` */
530+
def transferReferences(from: ValDef, to: ValDef): Unit = {
531+
val fromRefs = from.removeAttachment(References).getOrElse(Nil)
532+
val toRefs = to.removeAttachment(References).getOrElse(Nil)
533+
to.putAttachment(References, fromRefs ++ toRefs)
534+
}
535+
529536
/** Merge the module class `modCls` in the expanded tree of `mdef` with the given stats */
530537
def mergeModuleClass(mdef: Tree, modCls: TypeDef, stats: List[Tree]): TypeDef = {
531538
var res: TypeDef = null
@@ -580,9 +587,12 @@ class Namer { typer: Typer =>
580587
case vdef @ ValDef(name, _, _) if valid(vdef) =>
581588
moduleValDef.get(name) match {
582589
case Some((stat1, vdef1)) =>
583-
if (vdef.mods.is(Synthetic) && !vdef1.mods.is(Synthetic))
590+
if (vdef.mods.is(Synthetic) && !vdef1.mods.is(Synthetic)) {
591+
transferReferences(vdef, vdef1)
584592
removeInExpanded(stat, vdef)
593+
}
585594
else if (!vdef.mods.is(Synthetic) && vdef1.mods.is(Synthetic)) {
595+
transferReferences(vdef1, vdef)
586596
removeInExpanded(stat1, vdef1)
587597
moduleValDef(name) = (stat, vdef)
588598
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ class Typer extends Namer
11521152
tree.ensureCompletions
11531153
tree.getAttachment(untpd.OriginalSymbol) match {
11541154
case Some(origSym) =>
1155-
TypeTree(tree.derivedType(origSym)).withPos(tree.pos)
1155+
tree.derivedTree(origSym).withPos(tree.pos)
11561156
// btw, no need to remove the attachment. The typed
11571157
// tree is different from the untyped one, so the
11581158
// untyped tree is no longer accessed after all

0 commit comments

Comments
 (0)