Skip to content

Avoid forcing infos of some symbols in InfoTransforms #223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 15, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ language: scala
script:
- sbt -Ddotty.travis.build=yes update compile test
jdk:
- oraclejdk7
- oraclejdk8
notifications:
email:
- dotty-reports@googlegroups.com
Expand Down
20 changes: 15 additions & 5 deletions src/dotty/tools/dotc/core/DenotTransformers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,23 @@ object DenotTransformers {
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type

def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = {
val info1 = transformInfo(ref.info, ref.symbol)
if (info1 eq ref.info) ref
else ref match {
case ref: SymDenotation => ref.copySymDenotation(info = info1)
case _ => ref.derivedSingleDenotation(ref.symbol, info1)
val sym = ref.symbol
if (sym.exists && !mayChange(sym)) ref
else {
val info1 = transformInfo(ref.info, ref.symbol)
if (info1 eq ref.info) ref
else ref match {
case ref: SymDenotation => ref.copySymDenotation(info = info1)
case _ => ref.derivedSingleDenotation(ref.symbol, info1)
}
}
}

/** Denotations with a symbol where `mayChange` is false are guaranteed to be
* unaffected by this transform, so `transformInfo` need not be run. This
* can save time, and more importantly, can help avoid forcing symbol completers.
*/
protected def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = true
}

/** A transformer that only transforms SymDenotations */
Expand Down
13 changes: 9 additions & 4 deletions src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ object Types {
false
}

/** Is this type a (neither aliased nor applied) reference to class `sym`? */
def isDirectRef(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar match {
case this1: TypeRef =>
this1.name == sym.name && // avoid forcing info if names differ
(this1.symbol eq sym)
case _ =>
false
}

/** Is this type an instance of a non-bottom subclass of the given class `cls`? */
final def derivesFrom(cls: Symbol)(implicit ctx: Context): Boolean = this match {
case tp: TypeRef =>
Expand Down Expand Up @@ -663,10 +672,6 @@ object Types {
case _ => this
}

/** Map references to Object to references to Any; needed for Java interop */
final def objToAny(implicit ctx: Context) =
if ((this isRef defn.ObjectClass) && !ctx.phase.erasedTypes) defn.AnyType else this

/** If this is a (possibly aliased, annotated, and/or parameterized) reference to
* a class, the class type ref, otherwise NoType.
*/
Expand Down
12 changes: 8 additions & 4 deletions src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ class ClassfileParser(
}
}

/** Map direct references to Object to references to Any */
final def objToAny(tp: Type)(implicit ctx: Context) =
if (tp.isDirectRef(defn.ObjectClass) && !ctx.phase.erasedTypes) defn.AnyType else tp

private def sigToType(sig: TermName, owner: Symbol = null)(implicit ctx: Context): Type = {
var index = 0
val end = sig.length
Expand Down Expand Up @@ -258,12 +262,12 @@ class ClassfileParser(
case variance @ ('+' | '-' | '*') =>
index += 1
val bounds = variance match {
case '+' => TypeBounds.upper(sig2type(tparams, skiptvs).objToAny)
case '+' => objToAny(TypeBounds.upper(sig2type(tparams, skiptvs)))
case '-' =>
val tp = sig2type(tparams, skiptvs)
// sig2type seems to return AnyClass regardless of the situation:
// we don't want Any as a LOWER bound.
if (tp isRef defn.AnyClass) TypeBounds.empty
if (tp.isDirectRef(defn.AnyClass)) TypeBounds.empty
else TypeBounds.lower(tp)
case '*' => TypeBounds.empty
}
Expand Down Expand Up @@ -310,7 +314,7 @@ class ClassfileParser(
var paramnames = new ListBuffer[TermName]()
while (sig(index) != ')') {
paramnames += nme.syntheticParamName(paramtypes.length)
paramtypes += sig2type(tparams, skiptvs).objToAny
paramtypes += objToAny(sig2type(tparams, skiptvs))
}
index += 1
val restype = sig2type(tparams, skiptvs)
Expand All @@ -328,7 +332,7 @@ class ClassfileParser(
while (sig(index) == ':') {
index += 1
if (sig(index) != ':') // guard against empty class bound
ts += sig2type(tparams, skiptvs).objToAny
ts += objToAny(sig2type(tparams, skiptvs))
}
TypeBounds.upper(((NoType: Type) /: ts)(_ & _) orElse defn.AnyType)
}
Expand Down
2 changes: 2 additions & 0 deletions src/dotty/tools/dotc/transform/ElimByName.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,6 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform
case ExprType(rt) if exprBecomesFunction(sym) => defn.FunctionType(Nil, rt)
case _ => tp
}

override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym.isTerm
}
2 changes: 2 additions & 0 deletions src/dotty/tools/dotc/transform/ElimRepeated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer { thisTransfo
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
elimRepeated(tp)

override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym is Method

private def elimRepeated(tp: Type)(implicit ctx: Context): Type = tp.stripTypeVar match {
case tp @ MethodType(paramNames, paramTypes) =>
val resultType1 = elimRepeated(tp.resultType)
Expand Down
2 changes: 2 additions & 0 deletions src/dotty/tools/dotc/transform/ExplicitOuter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf
tp
}

override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym.isClass

/** First, add outer accessors if a class does not have them yet and it references an outer this.
* If the class has outer accessors, implement them.
* Furthermore, if a parent trait might have an outer accessor,
Expand Down