aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-02-12 18:07:36 +0100
committerMartin Odersky <odersky@gmail.com>2014-02-12 18:07:36 +0100
commit80acc2d331cf8359c00d9a15c8cc10d537be503a (patch)
tree52665a28aed3fd663dccd26d2c8f89b89b5f5479 /src/dotty/tools/dotc/core
parenta6c50c1872cff7ffb20388c7ac2197d983085625 (diff)
downloaddotty-80acc2d331cf8359c00d9a15c8cc10d537be503a.tar.gz
dotty-80acc2d331cf8359c00d9a15c8cc10d537be503a.tar.bz2
dotty-80acc2d331cf8359c00d9a15c8cc10d537be503a.zip
Some changes in the interest of speedups.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala1
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala22
-rw-r--r--src/dotty/tools/dotc/core/Types.scala82
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala6
4 files changed, 65 insertions, 46 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 5ca53b04e..1e4d0f47a 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -769,6 +769,7 @@ object Denotations {
/** An exception for accessing symbols that are no longer valid in current run */
class StaleSymbol(msg: => String) extends Exception {
+ util.Stats.record("stale symbol")
override def getMessage() = msg
}
}
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index 1a782ac63..6e984e43c 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -47,6 +47,28 @@ trait TypeOps { this: Context =>
def apply(tp: Type) = asSeenFrom(tp, pre, cls, this)
}
+ /** Implementation of Types#simplified */
+ final def simplify(tp: Type, theMap: SimplifyMap): Type = tp match {
+ case tp: NamedType =>
+ tp.derivedSelect(simplify(tp.prefix, theMap))
+ case _: ThisType | NoPrefix =>
+ tp
+ case tp: RefinedType =>
+ tp.derivedRefinedType(simplify(tp.parent, theMap), tp.refinedName, simplify(tp.refinedInfo, theMap))
+ case AndType(l, r) =>
+ simplify(l, theMap) & simplify(r, theMap)
+ case OrType(l, r) =>
+ simplify(l, theMap) | simplify(r, theMap)
+ case tp: PolyParam =>
+ typerState.constraint.typeVarOfParam(tp) orElse tp
+ case _ =>
+ (if (theMap != null) theMap else new SimplifyMap).mapOver(tp)
+ }
+
+ class SimplifyMap extends TypeMap {
+ def apply(tp: Type) = simplify(tp, this)
+ }
+
final def isVolatile(tp: Type): Boolean = {
/** Pre-filter to avoid expensive DNF computation */
def needsChecking(tp: Type, isPart: Boolean): Boolean = tp match {
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 71218680a..b99162383 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -26,6 +26,7 @@ import Uniques._
import collection.{mutable, Seq, breakOut}
import config.Config
import config.Printers._
+import annotation.tailrec
import language.implicitConversions
object Types {
@@ -342,45 +343,52 @@ object Types {
* flags in `excluded` from consideration.
*/
final def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation = try {
- this match {
+ @tailrec def go(tp: Type): Denotation = tp match {
case tp: RefinedType =>
- val pdenot = tp.parent.findMember(name, pre, excluded)
- if (name eq tp.refinedName) {
- val rinfo = tp.refinedInfo.substThis(tp, pre)
- if (name.isTypeName) // simplified case that runs more efficiently
- pdenot.asSingleDenotation.derivedSingleDenotation(pdenot.symbol, rinfo)
- else
- pdenot & (new JointRefDenotation(NoSymbol, rinfo, Period.allInRun(ctx.runId)), pre)
- } else pdenot
+ if (name eq tp.refinedName) goRefined(tp) else go(tp.parent)
case tp: ThisType =>
- val d = tp.underlying.findMember(name, pre, excluded)
- if (d.exists) d
- else
- // There is a special case to handle:
- // trait Super { this: Sub => private class Inner {} println(this.Inner) }
- // class Sub extends Super
- // When resolving Super.this.Inner, the normal logic goes to the self type and
- // looks for Inner from there. But this fails because Inner is private.
- // We fix the problem by having the following fallback case, which links up the
- // member in Super instead of Sub.
- // As an example of this in the wild, see
- // loadClassWithPrivateInnerAndSubSelf in ShowClassTests
- tp.cls.typeRef.findMember(name, pre, excluded) orElse d
+ goThis(tp)
case tp: TypeRef =>
tp.denot.findMember(name, pre, excluded)
case tp: TypeProxy =>
- tp.underlying.findMember(name, pre, excluded)
+ go(tp.underlying)
case tp: ClassInfo =>
tp.cls.findMember(name, pre, excluded)
case AndType(l, r) =>
- l.findMember(name, pre, excluded) & (r.findMember(name, pre, excluded), pre)
+ goAnd(l, r)
case OrType(l, r) =>
- l.findMember(name, pre, excluded) | (r.findMember(name, pre, excluded), pre)
+ goOr(l, r)
case ErrorType =>
ctx.newErrorSymbol(pre.classSymbol orElse defn.RootClass, name)
case _ =>
NoDenotation
}
+ def goRefined(tp: RefinedType) = {
+ val pdenot = go(tp.parent)
+ val rinfo = tp.refinedInfo.substThis(tp, pre)
+ if (name.isTypeName) // simplified case that runs more efficiently
+ pdenot.asSingleDenotation.derivedSingleDenotation(pdenot.symbol, rinfo)
+ else
+ pdenot & (new JointRefDenotation(NoSymbol, rinfo, Period.allInRun(ctx.runId)), pre)
+ }
+ def goThis(tp: ThisType) = {
+ val d = go(tp.underlying)
+ if (d.exists) d
+ else
+ // There is a special case to handle:
+ // trait Super { this: Sub => private class Inner {} println(this.Inner) }
+ // class Sub extends Super
+ // When resolving Super.this.Inner, the normal logic goes to the self type and
+ // looks for Inner from there. But this fails because Inner is private.
+ // We fix the problem by having the following fallback case, which links up the
+ // member in Super instead of Sub.
+ // As an example of this in the wild, see
+ // loadClassWithPrivateInnerAndSubSelf in ShowClassTests
+ go(tp.cls.typeRef) orElse d
+ }
+ def goAnd(l: Type, r: Type) = go(l) & (go(r), pre)
+ def goOr(l: Type, r: Type) = go(l) | (go(r), pre)
+ go(this)
} catch {
case ex: MergeError =>
throw new MergeError(s"${ex.getMessage} as members of type ${pre.show}")
@@ -843,26 +851,12 @@ object Types {
/** A simplified version of this type which is equivalent wrt =:= to this type.
* This applies a typemap to the type which (as all typemaps) follows type
* variable instances and reduces typerefs over refined types. It also
- * re-evaluatesall occurrences of And/OrType with &/| because
+ * re-evaluates all occurrences of And/OrType with &/| because
* what was a union or intersection of type variables might be a simpler type
* after the type variables are instantiated. Finally, it
* maps poly params in the current constraint set back to their type vars.
*/
- def simplified(implicit ctx: Context) = {
- class Simplify extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case AndType(l, r) =>
- this(l) & this(r)
- case OrType(l, r) =>
- this(l) | this(r)
- case tp: PolyParam =>
- ctx.typerState.constraint.typeVarOfParam(tp) orElse tp
- case _ =>
- mapOver(tp)
- }
- }
- new Simplify().apply(this)
- }
+ def simplified(implicit ctx: Context) = ctx.simplify(this, null)
/** customized hash code of this type.
* NotCached for uncached types. Cached types
@@ -2096,7 +2090,8 @@ object Types {
tp.derivedSelect(this(tp.prefix))
case _: ThisType
- | _: BoundType => tp
+ | _: BoundType
+ | NoPrefix => tp
case tp: RefinedType =>
tp.derivedRefinedType(this(tp.parent), tp.refinedName, this(tp.refinedInfo))
@@ -2217,7 +2212,8 @@ object Types {
this(x, tp.prefix)
case _: ThisType
- | _: BoundType => x
+ | _: BoundType
+ | NoPrefix => x
case tp: RefinedType =>
this(this(x, tp.parent), tp.refinedInfo)
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index 0fc661842..1395b4f43 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -239,13 +239,13 @@ class ClassfileParser(
case BOOL_TAG => defn.BooleanType
case 'L' =>
def processInner(tp: Type): Type = tp match {
- case tp @ TypeRef(pre, name) if !(tp.symbol.owner is Flags.ModuleClass) =>
- TypeRef(processInner(pre.widen), name)
+ case tp: TypeRef if !(tp.symbol.owner is Flags.ModuleClass) =>
+ TypeRef(processInner(tp.prefix.widen), tp.name)
case _ =>
tp
}
def processClassType(tp: Type): Type = tp match {
- case tp @ TypeRef(pre, name) =>
+ case tp: TypeRef =>
if (sig(index) == '<') {
accept('<')
var tp1: Type = tp