From f0b4fc58e0c5e5372c23bd817954ed3aa82b2102 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 26 Nov 2013 17:08:58 +0100 Subject: More posishings of SymDenots/Denotations. In particular - closed a loophole where we did not go through parentDenot in ClassDenotation. - fused some of the predenotation ops used in computeMemberNames --- src/dotty/tools/dotc/config/Config.scala | 1 + src/dotty/tools/dotc/core/Denotations.scala | 47 ++++++++++++++------------ src/dotty/tools/dotc/core/SymDenotations.scala | 36 ++++++++------------ src/dotty/tools/dotc/core/Types.scala | 10 +++--- src/dotty/tools/dotc/typer/Namer.scala | 2 +- 5 files changed, 47 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala index af75aea89..4d93fae29 100644 --- a/src/dotty/tools/dotc/config/Config.scala +++ b/src/dotty/tools/dotc/config/Config.scala @@ -4,6 +4,7 @@ object Config { final val cacheMemberNames = true final val cacheAsSeenFrom = true + final val useFingerPrints = true /** When set, use new signature-based matching. * Advantantage of doing so: It's supposed to be faster diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 72c999f9b..8aafa5e64 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -540,19 +540,13 @@ object Denotations { if (p(this)) this else NoDenotation final def filterDisjoint(denots: PreDenotation)(implicit ctx: Context): SingleDenotation = if (denots.containsSig(signature)) NoDenotation else this - def disjointAsSeenFrom(denots: PreDenotation, pre: Type)(implicit ctx: Context): SingleDenotation = - if (isType) filterDisjoint(denots).asSeenFrom(pre) - else asSeenFrom(pre).filterDisjoint(denots) + def mapInherited(ownDenots: PreDenotation, prevDenots: PreDenotation, pre: Type)(implicit ctx: Context): SingleDenotation = + if (hasUniqueSym && prevDenots.containsSym(symbol)) NoDenotation + else if (overlaps(Private)) NoDenotation + else if (isType) filterDisjoint(ownDenots).asSeenFrom(pre) + else asSeenFrom(pre).filterDisjoint(ownDenots) final def filterExcluded(excluded: FlagSet)(implicit ctx: Context): SingleDenotation = - if (excluded.isEmpty) this - else this match { - case thisd: SymDenotation => - if (thisd is excluded) NoDenotation else this - case _ => - if (symbol is excluded) NoDenotation else this - } - final def dropUniqueRefsIn(denots: PreDenotation): SingleDenotation = - if (hasUniqueSym && denots.containsSym(symbol)) NoDenotation else this + if (excluded.isEmpty || !(this overlaps excluded)) this else NoDenotation type AsSeenFromResult = SingleDenotation protected def computeAsSeenFrom(pre: Type)(implicit ctx: Context): SingleDenotation = { @@ -563,6 +557,11 @@ object Denotations { if (!owner.membersNeedAsSeenFrom(pre)) this else derivedSingleDenotation(symbol, info.asSeenFrom(pre, owner)) } + + private def overlaps(fs: FlagSet)(implicit ctx: Context): Boolean = this match { + case sd: SymDenotation => sd is fs + case _ => symbol is fs + } } class UniqueRefDenotation( @@ -624,18 +623,23 @@ object Denotations { */ def filterDisjoint(denots: PreDenotation)(implicit ctx: Context): PreDenotation - def disjointAsSeenFrom(denots: PreDenotation, pre: Type)(implicit ctx: Context): PreDenotation + /** Keep only those inherited members M of this predenotation for which the following is true + * - M is not marked Private + * - If M has a unique symbol, it does not appear in `prevDenots`. + * - M's signature as seen from prefix `pre` does not appear in `ownDenots` + * Return the denotation as seen from `pre`. + * Called from SymDenotations.computeMember. There, `ownDenots` are the denotations found in + * the base class, which shadow any inherited denotations with the same signature. + * `prevDenots` are the denotations that are defined in the class or inherited from + * a base type which comes earlier in the linearization. + */ + def mapInherited(ownDenots: PreDenotation, prevDenots: PreDenotation, pre: Type)(implicit ctx: Context): PreDenotation /** Keep only those denotations in this group whose flags do not intersect * with `excluded`. */ def filterExcluded(excluded: FlagSet)(implicit ctx: Context): PreDenotation - /** Drop all denotations which refer to a unique symbol that is - * already referred uniquely in `denots`. - */ - def dropUniqueRefsIn(denots: PreDenotation): PreDenotation - private var cachedPrefix: Type = _ private var cachedAsSeenFrom: AsSeenFromResult = _ private var validAsSeenFrom: Period = Nowhere @@ -674,12 +678,11 @@ object Denotations { derivedUnion(denots1 filterWithPredicate p, denots2 filterWithPredicate p) def filterDisjoint(denots: PreDenotation)(implicit ctx: Context): PreDenotation = derivedUnion(denots1 filterDisjoint denots, denots2 filterDisjoint denots) - def disjointAsSeenFrom(denots: PreDenotation, pre: Type)(implicit ctx: Context): PreDenotation = - derivedUnion(denots1.disjointAsSeenFrom(denots, pre), denots2.disjointAsSeenFrom(denots, pre)) + def mapInherited(ownDenots: PreDenotation, prevDenots: PreDenotation, pre: Type)(implicit ctx: Context): PreDenotation = + derivedUnion(denots1.mapInherited(ownDenots, prevDenots, pre), denots2.mapInherited(ownDenots, prevDenots, pre)) def filterExcluded(excluded: FlagSet)(implicit ctx: Context): PreDenotation = derivedUnion(denots1.filterExcluded(excluded), denots2.filterExcluded(excluded)) - def dropUniqueRefsIn(denots: PreDenotation): PreDenotation = - derivedUnion(denots1.dropUniqueRefsIn(denots), denots2.dropUniqueRefsIn(denots)) + type AsSeenFromResult = PreDenotation protected def computeAsSeenFrom(pre: Type)(implicit ctx: Context): PreDenotation = derivedUnion(denots1.asSeenFrom(pre), denots2.asSeenFrom(pre)) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 2727095cf..fa7b71450 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -359,6 +359,8 @@ object SymDenotations { /** Is this a subclass of `base`, * and is the denoting symbol also different from `Null` or `Nothing`? + * @note erroneous classes are assumed to derive from all other classes + * and all classes derive from them. */ def derivesFrom(base: Symbol)(implicit ctx: Context) = false @@ -449,7 +451,7 @@ object SymDenotations { !( this.isTerm || this.isStaticOwner || ctx.erasedTypes && symbol != defn.ArrayClass - || (pre eq thisType) + || (pre eq NoPrefix) || (pre eq thisType) ) /** Is this symbol concrete, or that symbol deferred? */ @@ -737,24 +739,22 @@ object SymDenotations { /** The type parameters of this class */ override final def typeParams(implicit ctx: Context): List[TypeSymbol] = { + def computeTypeParams = decls.filter(sym => + (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]] if (myTypeParams == null) myTypeParams = computeTypeParams myTypeParams } - private def computeTypeParams(implicit ctx: Context): List[TypeSymbol] = - decls.filter(sym => - (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]] - /** A key to verify that all caches influenced by parent classes are valid */ private var parentDenots: List[Denotation] = null /** The denotations of all parents in this class. - * Note: Always use this method instead of `classInfo.classParents` + * Note: Always use this method instead of `classInfo.myClassParents` * because the latter does not ensure that the `parentDenots` key * is up-to-date, which might lead to invalid caches later on. */ def classParents(implicit ctx: Context) = { - val ps = classInfo.classParents + val ps = classInfo.myClassParents if (parentDenots == null) parentDenots = ps map (_.denot) ps } @@ -762,7 +762,7 @@ object SymDenotations { /** Are caches influenced by parent classes still valid? */ private def parentsAreValid(implicit ctx: Context): Boolean = parentDenots == null || - parentDenots.corresponds(classInfo.classParents)(_ eq _.denot) + parentDenots.corresponds(classInfo.myClassParents)(_ eq _.denot) /** If caches influenced by parent classes are still valid, the denotation * itself, otherwise a freshly initialized copy. @@ -785,11 +785,11 @@ object SymDenotations { else ThisType(classSymbol) */ - private[this] var myTypeConstructor: TypeRef = null + private[this] var myTypeRef: TypeRef = null override def typeRef(implicit ctx: Context): TypeRef = { - if (myTypeConstructor == null) myTypeConstructor = super.typeRef - myTypeConstructor + if (myTypeRef == null) myTypeRef = super.typeRef + myTypeRef } private[this] var myBaseClasses: List[ClassSymbol] = null @@ -941,7 +941,9 @@ object SymDenotations { } else computeMembersNamed(name) private def computeMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = - if (!classSymbol.hasChildren || (memberFingerPrint contains name)) { + if (!classSymbol.hasChildren || + !Config.useFingerPrints || + (memberFingerPrint contains name)) { val ownDenots = decls.denotsNamed(name) if (debugTrace) // DEBUG println(s"$this.member($name), ownDenots = $ownDenots") @@ -950,17 +952,9 @@ object SymDenotations { val denots1 = collect(denots, ps) p.symbol.denot match { case parentd: ClassDenotation => - if (debugTrace) { // DEBUG - val s1 = parentd.membersNamed(name) - val s2 = s1.filterExcluded(Private) - val s3 = s2.disjointAsSeenFrom(ownDenots, thisType) - println(s"$this.member($name) $s1 $s2 $s3") - } denots1 union parentd.membersNamed(name) - .dropUniqueRefsIn(denots1) - .filterExcluded(Private) - .disjointAsSeenFrom(ownDenots, thisType) + .mapInherited(ownDenots, denots1, thisType) case _ => denots1 } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 437839c4f..9c849bfdf 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1708,7 +1708,7 @@ object Types { abstract case class ClassInfo( prefix: Type, cls: ClassSymbol, - classParents: List[TypeRef], + myClassParents: List[TypeRef], // to be used only in ClassDenotation! decls: Scope, selfInfo: DotClass /* should be: Type | Symbol */) extends CachedGroundType with TypeType { @@ -1738,16 +1738,16 @@ object Types { override def parents(implicit ctx: Context): List[TypeRef] = { if (parentsCache == null) - parentsCache = classParents.mapConserve(rebase(_).asInstanceOf[TypeRef]) + parentsCache = cls.classParents.mapConserve(rebase(_).asInstanceOf[TypeRef]) parentsCache } def derivedClassInfo(prefix: Type)(implicit ctx: Context) = if (prefix eq this.prefix) this - else ClassInfo(prefix, cls, classParents, decls, selfInfo) + else ClassInfo(prefix, cls, myClassParents, decls, selfInfo) - def derivedClassInfo(prefix: Type, classParents: List[TypeRef], selfInfo: Type)(implicit ctx: Context) = - if ((prefix eq this.prefix) && (classParents eq this.classParents) && (selfInfo eq this.selfInfo)) this + def derivedClassInfo(prefix: Type = this.prefix, classParents: List[TypeRef] = myClassParents, selfInfo: DotClass = this.selfInfo)(implicit ctx: Context) = + if ((prefix eq this.prefix) && (classParents eq this.myClassParents) && (selfInfo eq this.selfInfo)) this else ClassInfo(prefix, cls, classParents, decls, selfInfo) override def computeHash = doHash(cls, prefix) diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index f8551d615..66d238614 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -338,7 +338,7 @@ class Namer { typer: Typer => case sig: TypeRef => sig case sig: ClassInfo => - sig.derivedClassInfo(sig.prefix, sig.classParents, sig.prefix select sourceModule) + sig.derivedClassInfo(selfInfo = sig.prefix select sourceModule) case _ => sig } -- cgit v1.2.3