From 80acc2d331cf8359c00d9a15c8cc10d537be503a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 12 Feb 2014 18:07:36 +0100 Subject: Some changes in the interest of speedups. --- src/dotty/tools/dotc/ast/tpd.scala | 4 +- src/dotty/tools/dotc/core/Denotations.scala | 1 + src/dotty/tools/dotc/core/TypeOps.scala | 22 ++++++ src/dotty/tools/dotc/core/Types.scala | 82 ++++++++++------------ .../tools/dotc/core/pickling/ClassfileParser.scala | 6 +- src/dotty/tools/dotc/printing/PlainPrinter.scala | 8 +-- src/dotty/tools/dotc/printing/RefinedPrinter.scala | 4 +- src/dotty/tools/dotc/typer/Applications.scala | 2 +- src/dotty/tools/dotc/typer/Typer.scala | 33 ++++----- 9 files changed, 89 insertions(+), 73 deletions(-) (limited to 'src/dotty/tools/dotc') diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 77983830c..a8da15bd7 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -108,12 +108,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def apply(tp: Type) = tp match { case tp: TermRef if toAvoid(tp) && variance > 0 => apply(tp.info) - case tp @ TypeRef(pre, _) if toAvoid(pre) => + case tp: TypeRef if toAvoid(tp.prefix) => tp.info match { case TypeAlias(ref) => apply(ref) case _ => mapOver(tp) } - case tp @ RefinedType(parent, _) => + case tp: RefinedType => val tp1 @ RefinedType(parent1, _) = mapOver(tp) if (tp1.refinedInfo existsPart toAvoid) { typr.println(s"dropping refinement from $tp1") 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 diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala index 71c255c17..84936fbac 100644 --- a/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -100,8 +100,8 @@ class PlainPrinter(_ctx: Context) extends Printer { toText(tp.underlying) ~ ".type" case tp: SingletonType => toText(tp.underlying) ~ "(" ~ toTextRef(tp) ~ ")" - case tp @ TypeRef(pre, name) => - toTextPrefix(pre) ~ selectionString(tp) + case tp: TypeRef => + toTextPrefix(tp.prefix) ~ selectionString(tp) case tp: RefinedType => // return tp.toString // !!! DEBUG val parent :: (refined: List[RefinedType]) = @@ -187,8 +187,8 @@ class PlainPrinter(_ctx: Context) extends Printer { /** The string representation of this type used as a prefix */ protected def toTextRef(tp: SingletonType): Text = controlled { tp match { - case tp @ TermRef(pre, name) => - toTextPrefix(pre) ~ selectionString(tp) + case tp: TermRef => + toTextPrefix(tp.prefix) ~ selectionString(tp) case ThisType(cls) => nameString(cls) + ".this" case SuperType(thistpe: SingletonType, _) => diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index df00280ac..87f9fc29e 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -57,7 +57,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { tp match { case ThisType(cls) => if (isOmittablePrefix(cls)) return "" - case tp @ TermRef(pre, name) => + case tp @ TermRef(pre, _) => val sym = tp.symbol if (sym.isPackageObject) return toTextPrefix(pre) if (isOmittablePrefix(sym)) return "" @@ -109,7 +109,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { } case tp: ViewProto => return toText(tp.argType) ~ " ?=>? " ~ toText(tp.resultType) - case tp @ TypeRef(pre, name) => + case tp: TypeRef => if (tp.symbol is TypeParam | TypeArgument) { return tp.info match { case TypeAlias(hi) => toText(hi) diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 63117e2ac..15dd0e9ad 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -223,7 +223,7 @@ trait Applications extends Compatibility { self: Typer => if (meth.isClassConstructor) { // default getters for class constructors are found in the companion object mpre.baseType(cls) match { - case TypeRef(clspre, _) => ref(clspre, cls.companionModule) + case tp: TypeRef => ref(tp.prefix, cls.companionModule) case _ => NoType } } else mpre diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 8c066cdd0..25721ad74 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -63,26 +63,23 @@ class Typer extends Namer with Applications with Implicits { */ private var importedFromRoot: Set[Symbol] = Set() - /** A denotation exists really if it exists and does not point to a stale symbol. - def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean = denot match { - case denot: SymDenotation => - denot.ensureCompleted - denot.exists && !denot.isAbsent - case _ => - true - }*/ - - /** A denotation exists really if it exists and does not point to a stale symbol. */ - def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean = - try - denot.exists && { + /** A denotation exists really if it exists and does not point to a stale symbol. */ + final def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean = try + denot match { + case denot: SymDenotation => + denot.exists && { + denot.ensureCompleted + !denot.isAbsent + } + case denot: SingleDenotation => val sym = denot.symbol - sym.ensureCompleted - (sym eq NoSymbol) || !sym.isAbsent - } - catch { - case ex: StaleSymbol => false + (sym eq NoSymbol) || reallyExists(sym.denot) + case _ => + true } + catch { + case ex: StaleSymbol => false + } /** The type of a selection with `name` of a tree with type `site`. */ -- cgit v1.2.3