Skip to content

Commit 5b687fb

Browse files
oderskygzm0
authored andcommitted
Generalize derived type tree scheme.
To get truly hygienic desugared trees, we need a derived type tree scheme that's more flexible than just the previous two choices of info-of-symbol and typeref-of-symbol. The new scheme based on DerivedTypeTrees allows arbitrary methods to derive the type tree's type.
1 parent 3ba0931 commit 5b687fb

File tree

3 files changed

+25
-34
lines changed

3 files changed

+25
-34
lines changed

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

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,6 @@ object desugar {
2424

2525
// ----- TypeTrees that refer to other tree's symbols -------------------
2626

27-
/** A marker tree used as the original for TypeTrees that get their type by taking
28-
* the typeRef of some other tree's symbol. (currently unused)
29-
*/
30-
val TypeRefOfSym = new TypeTree(EmptyTree)
31-
32-
/** A marker tree used as the original for TypeTrees that get their type by taking
33-
* the result type of the info of some other tree's symbol.
34-
*/
35-
val InfoOfSym = new TypeTree(EmptyTree)
36-
3727
/** Attachment key containing TypeTrees whose type is computed
3828
* from the symbol in this type. These type trees have marker trees
3929
* TypeRefOfSym or InfoOfSym as their originals.
@@ -46,15 +36,19 @@ object desugar {
4636
*/
4737
val OriginalSymbol = new Attachment.Key[Symbol]
4838

49-
/** A type tree that is marked to get its type by taking
50-
* the typeRef of some other tree's symbol. Enters the type tree
51-
* in the References attachment of the `original` tree as a side effect.
39+
/** A type tree that gets its type from some other tree's symbol. Enters the
40+
* type tree in the References attachment of the `from` tree as a side effect.
5241
*/
53-
def refTypeTree(original: Tree, marker: TypeTree): TypeTree = {
54-
val result = TypeTree(marker)
55-
val existing = original.attachmentOrElse(References, Nil)
56-
original.putAttachment(References, result :: existing)
57-
result
42+
abstract class DerivedTypeTree(from: Tree) extends TypeTree(EmptyTree) {
43+
val existing = from.attachmentOrElse(References, Nil)
44+
from.putAttachment(References, this :: existing)
45+
46+
/** The method that computes the type of this tree */
47+
def derivedType(originalSym: Symbol)(implicit ctx: Context): Type
48+
}
49+
50+
class SetterParam(vdef: ValDef) extends DerivedTypeTree(vdef) {
51+
def derivedType(vsym: Symbol)(implicit ctx: Context) = vsym.info.resultType
5852
}
5953

6054
// ----- Desugar methods -------------------------------------------------
@@ -73,7 +67,7 @@ object desugar {
7367
// val getter = ValDef(mods, name, tpt, rhs) withPos vdef.pos ?
7468
// right now vdef maps via expandedTree to a thicket which concerns itself.
7569
// I don't see a problem with that but if there is one we can avoid it by making a copy here.
76-
val setterParam = makeSyntheticParameter(tpt = refTypeTree(vdef, InfoOfSym))
70+
val setterParam = makeSyntheticParameter(tpt = new SetterParam(vdef))
7771
val setterRhs = if (vdef.rhs.isEmpty) EmptyTree else unitLiteral
7872
val setter = cpy.DefDef(vdef,
7973
mods | Accessor, name.setterName, Nil, (setterParam :: Nil) :: Nil,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,8 @@ class Namer { typer: Typer =>
458458
index(constr)
459459
index(rest)(inClassContext(selfInfo))
460460
denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo)
461+
// make sure constr parameters are all entered because we refer to them in desugarings:
462+
symbolOfTree(constr).ensureCompleted()
461463
}
462464
}
463465

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

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -635,23 +635,18 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
635635
}
636636

637637
def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = track("typedTypeTree") {
638-
if (tree.original.isEmpty) {
639-
def symbol = tree.attachment(desugar.OriginalSymbol)
640-
// btw, no need to remove the attachment. The typed
641-
// tree is different from the untyped one, so the
642-
// untyped tree is no longer accessed after all
643-
// accesses with typedTypeTree are done.
644-
val ownType = tree.original match {
645-
case untpd.EmptyTree =>
638+
if (tree.original.isEmpty)
639+
tree match {
640+
case tree: desugar.DerivedTypeTree =>
641+
TypeTree(tree.derivedType(tree.attachment(desugar.OriginalSymbol))) withPos tree.pos
642+
// btw, no need to remove the attachment. The typed
643+
// tree is different from the untyped one, so the
644+
// untyped tree is no longer accessed after all
645+
// accesses with typedTypeTree are done.
646+
case _ =>
646647
assert(isFullyDefined(pt, ForceDegree.none))
647-
pt
648-
case desugar.TypeRefOfSym =>
649-
symbol.typeRef
650-
case desugar.InfoOfSym =>
651-
symbol.info.resultType
648+
tree.withType(pt)
652649
}
653-
cpy.TypeTree(tree, untpd.EmptyTree).withType(ownType)
654-
}
655650
else {
656651
val original1 = typed(tree.original)
657652
cpy.TypeTree(tree, original1).withType(original1.tpe)

0 commit comments

Comments
 (0)