Skip to content

Commit 3e84316

Browse files
committed
Use positioned types when generating types
1 parent af14aa5 commit 3e84316

File tree

5 files changed

+127
-56
lines changed

5 files changed

+127
-56
lines changed

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

Lines changed: 65 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ import Contexts._, Types._, Symbols._, TypeApplications._, Decorators._
66
import util.Positions._
77
import ast._
88
import Trees._, Names._, StdNames._
9+
import collection.mutable
10+
import Annotations.Annotation
911

1012
object TypePositions {
1113
import tpd._
1214

1315
/** Encapsulates a type and the position of a corresponding tree */
14-
case class Positioned(tp: Type, pos: Position) extends UncachedGroundType
16+
case class PosAnnot(pos: Position) extends Annotation {
17+
def tree(implicit ctx: Context) = EmptyTree
18+
}
1519

1620
/** An object to handle the point positions of definitions */
1721
private object PointPos {
@@ -20,10 +24,10 @@ object TypePositions {
2024
* the position.
2125
*/
2226
def add(tree: Tree, tpe: Type) = tpe match {
23-
case Positioned(tpe1, pos) if !tree.pos.isSynthetic =>
27+
case AnnotatedType(tpe1, PosAnnot(pos)) if !tree.pos.isSynthetic && false =>
2428
val pointDelta = pos.start - tree.pos.point
25-
assert(pointDelta > 0)
26-
Positioned(tpe1, pos.withPoint(pos.start + pointDelta))
29+
assert(pointDelta >= 0, s"$pos / ${tree.pos} / $tpe")
30+
AnnotatedType(tpe1, PosAnnot(pos.withPoint(pos.start + pointDelta)))
2731
case _ => tpe
2832
}
2933

@@ -43,35 +47,37 @@ object TypePositions {
4347
def unapply[T](xs: List[T]) =
4448
if (xs.isEmpty) None else Some((xs.init, xs.last))
4549
}
46-
50+
51+
private def stripPos(tpe: Type) = tpe match {
52+
case AnnotatedType(tpe1, _: PosAnnot) => tpe1
53+
case _ => tpe
54+
}
55+
4756
/** Given a type tree, produce the corresponding type with positions added */
4857
def toType(tree: Tree)(implicit ctx: Context): Type = {
4958

50-
def stripPos(tpe: Type) = tpe match {
51-
case Positioned(tpe1, _) => tpe1
52-
case _ => tpe
53-
}
54-
5559
def convertList(trees: List[Tree], tpes: List[Type]): List[Type] =
5660
tpes.zipWithConserve(trees)((tpe, tree) => convert(tree, tpe))
5761

5862
def convert(tree: Tree, tpe: Type): Type = {
59-
val tpe1 = (tree, tpe) match {
63+
val tpe1: Type = (tree, tpe.stripTypeVar) match {
6064
case (Select(qual, name), tpe: NamedType) if tpe.name == name =>
6165
tpe.derivedSelect(convert(qual, tpe.prefix))
62-
case (SingletonTypeTree(ref), _) =>
66+
case (SingletonTypeTree(ref), tpe) =>
6367
convert(ref, tpe)
6468
case (AndTypeTree(ltree, rtree), tpe @ AndType(ltpe, rtpe)) =>
6569
tpe.derivedAndType(convert(ltree, ltpe), convert(rtree, rtpe))
6670
case (OrTypeTree(ltree, rtree), tpe @ OrType(ltpe, rtpe)) =>
6771
tpe.derivedOrType(convert(ltree, ltpe), convert(rtree, rtpe))
72+
case (rtree: RefinedTypeTree, tpe: RecType) =>
73+
tpe.derivedRecType(convert(rtree, tpe.parent))
6874
case (RefinedTypeTree(ptree, Append(refinements, refinement: MemberDef)),
6975
tpe @ RefinedType(ptpe, rname, rinfo)) if rname == refinement.name =>
7076
val parent =
7177
if (refinements.isEmpty) ptree
7278
else cpy.RefinedTypeTree(tree)(ptree, refinements).withPos(NoPosition)
7379
tpe.derivedRefinedType(convert(parent, ptpe), rname, convert(refinement, rinfo))
74-
case (AppliedTypeTree(ftree, argtrees), AppliedType(ftpe, argtpes)) =>
80+
case (AppliedTypeTree(ftree, argtrees), AppliedType(ftpe, argtpes)) if argtrees.length == argtpes.length =>
7581
val ftpe1 = convert(ftree, ftpe)
7682
val argtpes1 = convertList(argtrees, argtpes)
7783
if ((ftpe1 eq ftpe) && (argtpes1 eq argtpes)) tpe
@@ -89,11 +95,15 @@ object TypePositions {
8995
tpe.paramNames,
9096
convertList(tparams, tpe.paramBounds).map(t => stripPos(t).bounds),
9197
convert(body, tpe.resultType))
92-
case (TypeDef(name, rhs), _) =>
98+
case (TypeDef(name, rhs), tpe @ TypeAlias(alias)) =>
99+
PointPos.add(tree, tpe.derivedTypeAlias(convert(rhs, alias)))
100+
case (TypeDef(name, rhs), tpe) =>
93101
PointPos.add(tree, convert(rhs, tpe))
94-
case (ValDef(name, tpt, _), _) =>
102+
case (ValDef(name, tpt, _), tpe) =>
95103
PointPos.add(tree, convert(tpt, tpe))
96-
case (DefDef(name, Nil, Nil, tpt, _), _) =>
104+
case (DefDef(name, Nil, Nil, tpt, _), tpe @ ExprType(rtpe)) =>
105+
PointPos.add(tree, tpe.derivedExprType(convert(tpt, rtpe)))
106+
case (DefDef(name, Nil, Nil, tpt, _), tpe) =>
97107
PointPos.add(tree, convert(tpt, tpe))
98108
case (tree @ DefDef(name, Nil, vparams :: vparamss1, tpt, _), tpe: MethodType) =>
99109
PointPos.add(tree,
@@ -107,12 +117,12 @@ object TypePositions {
107117
tpe.paramNames,
108118
convertList(tparams, tpe.paramBounds).map(t => stripPos(t).bounds),
109119
convert(cpy.DefDef(tree)(tparams = Nil).withPos(NoPosition), tpe.resultType)))
110-
case _ =>
120+
case (_, tpe) =>
111121
tpe
112122
}
113123
tpe1 match {
114-
case tpe1: Positioned => tpe1
115-
case _ => if (tree.pos.exists) Positioned(tpe1, tree.pos) else tpe1
124+
case AnnotatedType(_, _: PosAnnot) => tpe1
125+
case _ => if (!tree.pos.isSynthetic) AnnotatedType(tpe1, PosAnnot(tree.pos)) else tpe1
116126
}
117127
}
118128
convert(tree, tree.tpe)
@@ -124,18 +134,18 @@ object TypePositions {
124134
def typeTree = toTree(tpe)
125135
def untpdDef(tpe: Type): untpd.MemberDef = {
126136
import untpd._
127-
tpe match {
137+
stripPos(tpe) match {
128138
case tpe: PolyType =>
129139
def tparamTrees = (tpe.paramNames, tpe.paramBounds).zipped.map(toDef).asInstanceOf[List[TypeDef]]
130-
untpdDef(tpe.resultType) match {
140+
toDef(name, tpe.resultType) match {
131141
case mdef1: DefDef =>
132142
cpy.DefDef(mdef1)(tparams = tparamTrees)
133143
case mdef1: ValDef =>
134144
DefDef(mdef1.name, tparamTrees, Nil, mdef1.tpt, EmptyTree)
135145
}
136146
case tpe: MethodType =>
137147
def vparamTrees = (tpe.paramNames, tpe.paramTypes).zipped.map(toDef).asInstanceOf[List[ValDef]]
138-
untpdDef(tpe.resultType) match {
148+
toDef(name, tpe.resultType) match {
139149
case mdef1: DefDef =>
140150
cpy.DefDef(mdef1)(vparamss = vparamTrees :: mdef1.vparamss)
141151
case mdef1: ValDef =>
@@ -148,9 +158,9 @@ object TypePositions {
148158
}
149159
}
150160
}
151-
val tpdDef = untpdDef(tpe).withType(defn.AnyType)
161+
val tpdDef = untpdDef(tpe).withType(NoPrefix)
152162
tpe match {
153-
case Positioned(tpe1, pos) => tpdDef.withPos(PointPos.defPos(pos))
163+
case AnnotatedType(tpe1, PosAnnot(pos)) => tpdDef.withPos(PointPos.defPos(pos))
154164
case _ => tpdDef
155165
}
156166
}
@@ -173,8 +183,13 @@ object TypePositions {
173183
* In each case, the tree's type is `tpe`.
174184
*/
175185
def toTree(tpe: Type, hasPos: Boolean = false)(implicit ctx: Context): Tree = tpe match {
176-
case Positioned(tpe1, pos) =>
177-
toTree(tpe1, hasPos = true).withPos(pos.toSynthetic)
186+
case AnnotatedType(tpe1, PosAnnot(pos)) =>
187+
val tree = toTree(tpe1, hasPos = true) match {
188+
case t @ Select(qual, name) if name.length == pos.end - pos.start =>
189+
untpd.Ident(name).withType(t.tpe)
190+
case t => t
191+
}
192+
tree.withPos(pos.toSynthetic)
178193
case tpe =>
179194
val utree: untpd.Tree = {
180195
import untpd._
@@ -200,6 +215,8 @@ object TypePositions {
200215
This(tpnme.EMPTY)
201216
case tpe: ParamType if hasPos =>
202217
Ident(tpe.paramName)
218+
case tpe: RecType =>
219+
toTree(tpe.parent, hasPos)
203220
case AppliedType(tycon, args) =>
204221
mkTree(tycon) { AppliedTypeTree(_, args.map(toTree(_))) }
205222
case RefinedType(parent, rname, rinfo) =>
@@ -210,10 +227,20 @@ object TypePositions {
210227
case tpt =>
211228
RefinedTypeTree(tpt, toRefinement(rname, rinfo) :: Nil)
212229
}
213-
case tpe: RecType =>
214-
toTree(tpe.parent, hasPos)
215230
case TypeBounds(lo, hi) =>
216-
mkTree(lo) { TypeBoundsTree(_, toTree(hi)) }
231+
def toTreeOrEmpty(tpe: Type, cls: Symbol): Tree = {
232+
val tree = toTree(tpe)
233+
tpe match {
234+
case AnnotatedType(_, PosAnnot(pos)) if pos.start == pos.end && tree.tpe.isRef(cls) =>
235+
EmptyTree.withPos(pos)
236+
case _ =>
237+
tree
238+
}
239+
}
240+
toTreeOrEmpty(lo, defn.NothingClass) match {
241+
case tpt: TypeTree => tpt
242+
case lotree => TypeBoundsTree(lotree, toTreeOrEmpty(hi, defn.AnyClass))
243+
}
217244
case tpe: ExprType =>
218245
mkTree(tpe.resType) { ByNameTypeTree(_) }
219246
case tpe: PolyType =>
@@ -235,4 +262,13 @@ object TypePositions {
235262
}
236263
utree.withType(tpe)
237264
}
265+
266+
def refPositions(tree: Tree)(implicit ctx: Context): List[(Name, Position)] = {
267+
val b = new mutable.ListBuffer[(Name, Position)]
268+
tree foreachSubTree {
269+
case t: RefTree => b += ((t.name, t.pos.toSynthetic))
270+
case _ =>
271+
}
272+
b.toList
273+
}
238274
}

src/dotty/tools/dotc/core/tasty/TreeBuffer.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import util.Util.{bestFit, dble}
77
import TastyBuffer.{Addr, AddrWidth}
88
import config.Printers.pickling
99
import ast.untpd.Tree
10+
import ast.TypePositions.PosAnnot
11+
import Types.Type
1012

1113
class TreeBuffer extends TastyBuffer(50000) {
1214

@@ -18,13 +20,15 @@ class TreeBuffer extends TastyBuffer(50000) {
1820
private var numOffsets = 0
1921

2022
private type TreeAddrs = Any // really: Addr | List[Addr]
21-
23+
24+
private type Addressed = Any // really: Tree | Positioned
25+
2226
/** A map from trees to the address(es) at which a tree is pickled. There may be several
2327
* such addresses if the tree is shared. To keep the map compact, the value type is a
2428
* disjunction of a single address (which is the common case) and a list of addresses.
2529
*/
26-
private val treeAddrs = new java.util.IdentityHashMap[Tree, TreeAddrs]
27-
30+
private val treeAddrs = new java.util.IdentityHashMap[Addressed, TreeAddrs]
31+
2832
def registerTreeAddr(tree: Tree) =
2933
treeAddrs.put(tree,
3034
treeAddrs.get(tree) match {
@@ -39,6 +43,8 @@ class TreeBuffer extends TastyBuffer(50000) {
3943
case addrs: List[Addr] => addrs
4044
}
4145

46+
val posTypeOfTree = new java.util.IdentityHashMap[Tree, Type]
47+
4248
private def offset(i: Int): Addr = Addr(offsets(i))
4349

4450
private def keepOffset(relative: Boolean): Unit = {

src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ package core
44
package tasty
55

66
import ast.Trees._
7-
import ast.untpd
7+
import ast.{untpd, TypePositions}
8+
import TypePositions.PosAnnot
89
import TastyFormat._
910
import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annotations._, StdNames.tpnme, NameOps._
1011
import collection.mutable
@@ -52,7 +53,7 @@ class TreePickler(pickler: TastyPickler) {
5253

5354
def rhs(tdef: TypeDef)(implicit ctx: Context) =
5455
if (tdef.symbol.isClass) tdef.rhs
55-
else TypeTree(tdef.symbol.info).withPos(tdef.rhs.pos)
56+
else tdef.rhs.withType(tdef.symbol.info)
5657

5758
private def pickleName(name: Name): Unit = writeNat(nameIndex(name).index)
5859
private def pickleName(name: TastyName): Unit = writeNat(nameIndex(name).index)
@@ -140,21 +141,26 @@ class TreePickler(pickler: TastyPickler) {
140141
pickleType(c.symbolValue.termRef)
141142
}
142143

143-
def pickleType(tpe0: Type, richTypes: Boolean = false)(implicit ctx: Context): Unit = try {
144-
val tpe = tpe0.stripTypeVar
145-
val prev = pickledTypes.get(tpe)
146-
if (prev == null) {
147-
pickledTypes.put(tpe, currentAddr)
148-
pickleNewType(tpe, richTypes)
149-
}
150-
else {
151-
writeByte(SHARED)
152-
writeRef(prev.asInstanceOf[Addr])
153-
}
154-
} catch {
155-
case ex: AssertionError =>
156-
println(i"error when pickling type $tpe0")
157-
throw ex
144+
def pickleType(tpe0: Type, richTypes: Boolean = false)(implicit ctx: Context): Unit = tpe0 match {
145+
case AnnotatedType(tpe1, PosAnnot(pos)) =>
146+
pickleType(tpe1, richTypes)
147+
case _ =>
148+
try {
149+
val tpe = tpe0.stripTypeVar
150+
val prev = pickledTypes.get(tpe)
151+
if (prev == null) {
152+
pickledTypes.put(tpe, currentAddr)
153+
pickleNewType(tpe, richTypes)
154+
} else {
155+
writeByte(SHARED)
156+
writeRef(prev.asInstanceOf[Addr])
157+
}
158+
}
159+
catch {
160+
case ex: AssertionError =>
161+
println(i"error when pickling type $tpe0")
162+
throw ex
163+
}
158164
}
159165

160166
def pickleTypeWithPos(tpe: Type, tree: Tree)(implicit ctx: Context): Unit = {
@@ -308,9 +314,36 @@ class TreePickler(pickler: TastyPickler) {
308314
}
309315
pickled
310316
}
317+
318+
def pickleTpt(tpt: Tree)(implicit ctx: Context): Unit = tpt match {
319+
case _: TypeTree => pickleTypeWithPos(tpt.tpe, tpt)
320+
case _ =>
321+
val posType = TypePositions.toType(tpt)
322+
323+
def checkTypePositions() = {
324+
val tree = TypePositions.toTree(posType)
325+
val origRefs = TypePositions.refPositions(tpt)
326+
val newRefs = TypePositions.refPositions(tree)
327+
assert(TypePositions.refPositions(tpt).toSet subsetOf TypePositions.refPositions(tree).toSet,
328+
i"""$tpt
329+
|-->
330+
|$posType
331+
|-->
332+
|$tree
333+
|/
334+
|${posType.toString}
335+
|/
336+
|${tree.toString}""")
311337

312-
def pickleTpt(tpt: Tree)(implicit ctx: Context): Unit =
313-
pickleTypeWithPos(tpt.tpe, tpt) // TODO correlate with original when generating positions
338+
}
339+
if (false) checkTypePositions
340+
341+
posType match {
342+
case pd @ AnnotatedType(_, _: PosAnnot) => posTypeOfTree.put(tpt, pd)
343+
case _ =>
344+
}
345+
pickleTypeWithPos(posType, tpt)
346+
}
314347

315348
def pickleTreeUnlessEmpty(tree: Tree)(implicit ctx: Context): Unit =
316349
if (!tree.isEmpty) pickleTree(tree)

src/dotty/tools/dotc/transform/ExtensionMethods.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
/* NSC -- new Scala compiler
2-
* Copyright 2005-2013 LAMP/EPFL
3-
* @author Martin Odersky
4-
*/
51
package dotty.tools.dotc
62
package transform
73

src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
122122
case _ =>
123123
val tree1 = super.transform(tree)
124124
constToLiteral(tree1) match {
125-
case _: Literal => tree1
125+
case _: Literal => tree1 // keep tree, no need to transform super accessor
126126
case _ => superAcc.transformSelect(tree1, targs)
127127
}
128128
}

0 commit comments

Comments
 (0)