Skip to content

Commit c82a4b5

Browse files
committed
Merge pull request #223 from dotty-staging/fix/elimRepeatedTransformSym
Avoid forcing infos of some symbols in InfoTransforms
2 parents 4cb35ef + 35a54f1 commit c82a4b5

File tree

7 files changed

+39
-14
lines changed

7 files changed

+39
-14
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ language: scala
22
script:
33
- sbt -Ddotty.travis.build=yes update compile test
44
jdk:
5-
- oraclejdk7
5+
- oraclejdk8
66
notifications:
77
email:
88
- dotty-reports@googlegroups.com

src/dotty/tools/dotc/core/DenotTransformers.scala

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,23 @@ object DenotTransformers {
3838
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type
3939

4040
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = {
41-
val info1 = transformInfo(ref.info, ref.symbol)
42-
if (info1 eq ref.info) ref
43-
else ref match {
44-
case ref: SymDenotation => ref.copySymDenotation(info = info1)
45-
case _ => ref.derivedSingleDenotation(ref.symbol, info1)
41+
val sym = ref.symbol
42+
if (sym.exists && !mayChange(sym)) ref
43+
else {
44+
val info1 = transformInfo(ref.info, ref.symbol)
45+
if (info1 eq ref.info) ref
46+
else ref match {
47+
case ref: SymDenotation => ref.copySymDenotation(info = info1)
48+
case _ => ref.derivedSingleDenotation(ref.symbol, info1)
49+
}
4650
}
4751
}
52+
53+
/** Denotations with a symbol where `mayChange` is false are guaranteed to be
54+
* unaffected by this transform, so `transformInfo` need not be run. This
55+
* can save time, and more importantly, can help avoid forcing symbol completers.
56+
*/
57+
protected def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = true
4858
}
4959

5060
/** A transformer that only transforms SymDenotations */

src/dotty/tools/dotc/core/Types.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ object Types {
105105
false
106106
}
107107

108+
/** Is this type a (neither aliased nor applied) reference to class `sym`? */
109+
def isDirectRef(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar match {
110+
case this1: TypeRef =>
111+
this1.name == sym.name && // avoid forcing info if names differ
112+
(this1.symbol eq sym)
113+
case _ =>
114+
false
115+
}
116+
108117
/** Is this type an instance of a non-bottom subclass of the given class `cls`? */
109118
final def derivesFrom(cls: Symbol)(implicit ctx: Context): Boolean = this match {
110119
case tp: TypeRef =>
@@ -663,10 +672,6 @@ object Types {
663672
case _ => this
664673
}
665674

666-
/** Map references to Object to references to Any; needed for Java interop */
667-
final def objToAny(implicit ctx: Context) =
668-
if ((this isRef defn.ObjectClass) && !ctx.phase.erasedTypes) defn.AnyType else this
669-
670675
/** If this is a (possibly aliased, annotated, and/or parameterized) reference to
671676
* a class, the class type ref, otherwise NoType.
672677
*/

src/dotty/tools/dotc/core/pickling/ClassfileParser.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ class ClassfileParser(
214214
}
215215
}
216216

217+
/** Map direct references to Object to references to Any */
218+
final def objToAny(tp: Type)(implicit ctx: Context) =
219+
if (tp.isDirectRef(defn.ObjectClass) && !ctx.phase.erasedTypes) defn.AnyType else tp
220+
217221
private def sigToType(sig: TermName, owner: Symbol = null)(implicit ctx: Context): Type = {
218222
var index = 0
219223
val end = sig.length
@@ -258,12 +262,12 @@ class ClassfileParser(
258262
case variance @ ('+' | '-' | '*') =>
259263
index += 1
260264
val bounds = variance match {
261-
case '+' => TypeBounds.upper(sig2type(tparams, skiptvs).objToAny)
265+
case '+' => objToAny(TypeBounds.upper(sig2type(tparams, skiptvs)))
262266
case '-' =>
263267
val tp = sig2type(tparams, skiptvs)
264268
// sig2type seems to return AnyClass regardless of the situation:
265269
// we don't want Any as a LOWER bound.
266-
if (tp isRef defn.AnyClass) TypeBounds.empty
270+
if (tp.isDirectRef(defn.AnyClass)) TypeBounds.empty
267271
else TypeBounds.lower(tp)
268272
case '*' => TypeBounds.empty
269273
}
@@ -310,7 +314,7 @@ class ClassfileParser(
310314
var paramnames = new ListBuffer[TermName]()
311315
while (sig(index) != ')') {
312316
paramnames += nme.syntheticParamName(paramtypes.length)
313-
paramtypes += sig2type(tparams, skiptvs).objToAny
317+
paramtypes += objToAny(sig2type(tparams, skiptvs))
314318
}
315319
index += 1
316320
val restype = sig2type(tparams, skiptvs)
@@ -328,7 +332,7 @@ class ClassfileParser(
328332
while (sig(index) == ':') {
329333
index += 1
330334
if (sig(index) != ':') // guard against empty class bound
331-
ts += sig2type(tparams, skiptvs).objToAny
335+
ts += objToAny(sig2type(tparams, skiptvs))
332336
}
333337
TypeBounds.upper(((NoType: Type) /: ts)(_ & _) orElse defn.AnyType)
334338
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,6 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform
116116
case ExprType(rt) if exprBecomesFunction(sym) => defn.FunctionType(Nil, rt)
117117
case _ => tp
118118
}
119+
120+
override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym.isTerm
119121
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer { thisTransfo
2828
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
2929
elimRepeated(tp)
3030

31+
override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym is Method
32+
3133
private def elimRepeated(tp: Type)(implicit ctx: Context): Type = tp.stripTypeVar match {
3234
case tp @ MethodType(paramNames, paramTypes) =>
3335
val resultType1 = elimRepeated(tp.resultType)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf
5555
tp
5656
}
5757

58+
override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym.isClass
59+
5860
/** First, add outer accessors if a class does not have them yet and it references an outer this.
5961
* If the class has outer accessors, implement them.
6062
* Furthermore, if a parent trait might have an outer accessor,

0 commit comments

Comments
 (0)