From 19143c67d77a71bd5ef18769e222beed291fa92b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Apr 2013 23:01:07 +0200 Subject: Changes to pre complete decls Dropped preCompleteDecls for a general refactoring that makes decls available after a class is loaded and before it is completed. Also some other fixes to classloading problems. --- src/dotty/tools/dotc/core/Definitions.scala | 2 +- src/dotty/tools/dotc/core/Denotations.scala | 8 +++++ src/dotty/tools/dotc/core/SymDenotations.scala | 23 +++++++------- src/dotty/tools/dotc/core/SymbolLoaders.scala | 7 ++-- src/dotty/tools/dotc/core/Symbols.scala | 4 +-- src/dotty/tools/dotc/core/TypedTrees.scala | 4 +-- src/dotty/tools/dotc/core/Types.scala | 37 ++++++++++++---------- .../tools/dotc/core/pickling/ClassfileParser.scala | 5 +-- src/dotty/tools/dotc/core/pickling/UnPickler.scala | 10 +++--- 9 files changed, 57 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index f7e8029aa..81e01a1e1 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -66,7 +66,7 @@ class Definitions(implicit ctx: Context) { lazy val AnyRefAlias: TypeSymbol = { val anyRef = ctx.newSymbol( ScalaPackageClass, tpnme.AnyRef, EmptyFlags, TypeAlias(ObjectClass.typeConstructor)) - ScalaPackageClass.enter(anyRef, ScalaPackageClass.preCompleteDecls) + ScalaPackageClass.enter(anyRef, ScalaPackageClass.decls) anyRef } lazy val AnyClass: ClassSymbol = ctx.newCompleteClassSymbol( diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 53e366bcc..2d6d107f3 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -163,6 +163,14 @@ object Denotations { /** Does this denotation have an alternative that satisfies the predicate `p`? */ def hasAltWith(p: Symbol => Boolean): Boolean + /** Find member of this denotation with given name and + * produce a denotation that contains the type of the member + * as seen from given prefix `pre`. Exclude all members that have + * flags in `excluded` from consideration. + */ + def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation = + info.findMember(name, pre, excluded) + /** If this denotation is overloaded, filter with given predicate. * If result is still overloaded throw a TypeError. * Note: disambiguate is slightly different from suchThat in that diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index c019d94e0..2a66c9b7e 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -156,14 +156,12 @@ object SymDenotations { case Nil => Nil } - /** The symbols defined in this class when the class is not yet completed. - * @pre: this is a class + /** The symbols defined in this class. */ - protected[core] final def preCompleteDecls: Scope = _info match { + final def decls(implicit ctx: Context): Scope = _info match { case cinfo: ClassCompleter => cinfo.decls - case cinfo: ClassInfo => cinfo.decls - case cinfo: LazyType => completeFrom(cinfo); preCompleteDecls - case cinfo => throw new AssertionError(s"unexpected class completer for $debugString: ${cinfo.getClass}") + case cinfo: LazyType => completeFrom(cinfo); decls // complete-once + case _ => info.decls } // ------ Names ---------------------------------------------- @@ -651,7 +649,7 @@ object SymDenotations { } private def computeTypeParams(implicit ctx: Context): List[TypeSymbol] = - preCompleteDecls.toList.filter(sym => + decls.filter(sym => (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]] // ------ class-specific operations ----------------------------------- @@ -824,7 +822,7 @@ object SymDenotations { private def computeMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = if (!classSymbol.hasChildren || (memberFingerPrint contains name)) { - val ownDenots = info.decls.denotsNamed(name) + val ownDenots = decls.denotsNamed(name) if (debugTrace) // DEBUG println(s"$this.member($name), ownDenots = $ownDenots") def collect(denots: PreDenotation, parents: List[TypeRef]): PreDenotation = parents match { @@ -851,6 +849,9 @@ object SymDenotations { collect(ownDenots, classInfo.classParents) } else NoDenotation + override final def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation = + membersNamed(name).filterExcluded(excluded).asSeenFrom(pre).toDenot + private[this] var baseTypeCache: java.util.HashMap[CachedType, Type] = null private[this] var baseTypeValid: RunId = NoRunId @@ -946,7 +947,7 @@ object SymDenotations { override def primaryConstructor(implicit ctx: Context): Symbol = { val cname = if (this is Trait | ImplClass) nme.TRAIT_CONSTRUCTOR else nme.CONSTRUCTOR - info.decls.denotsNamed(cname).first.symbol + decls.denotsNamed(cname).first.symbol } } @@ -985,8 +986,8 @@ object SymDenotations { def sourceModule: Symbol = NoSymbol } - class ModuleClassCompleter(module: Symbol, underlying: LazyType = NoCompleter) - extends ClassCompleter(newScope, underlying) { + class ModuleClassCompleter(module: Symbol, decls: Scope = newScope, underlying: LazyType = NoCompleter) + extends ClassCompleter(decls, underlying) { override def sourceModule = module } diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index ad3b63fe8..49a25be11 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -49,7 +49,7 @@ class SymbolLoaders { modFlags: FlagSet = EmptyFlags, clsFlags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(implicit ctx: CondensedContext): Symbol = { val module = ctx.newModuleSymbol( owner, name.toTermName, modFlags, clsFlags, - (modul, _) => new ModuleClassCompleter(modul, completer), + (modul, _) => new ModuleClassCompleter(modul, newScope, completer), assocFile = completer.sourceFileOrNull) enterNew(owner, module, completer, scope) } @@ -142,13 +142,13 @@ class SymbolLoaders { /** Load contents of a package */ class PackageLoader(override val sourceModule: TermSymbol, classpath: ClassPath)(implicit val cctx: CondensedContext) - extends ClassCompleter(newScope) with SymbolLoader { + extends ClassCompleter(newScope) with SymbolLoader { // !!! TODO: ClassCompleter needed? def description = "package loader " + classpath.name def doComplete(root: SymDenotation) { assert(root is PackageClass, root) val pre = root.owner.thisType - root.info = ClassInfo(pre, root.symbol.asClass, Nil, root.preCompleteDecls, TermRef(pre, sourceModule)) + root.info = ClassInfo(pre, root.symbol.asClass, Nil, root.decls, TermRef(pre, sourceModule)) if (!sourceModule.isCompleted) sourceModule.completer.complete(sourceModule) if (!root.isRoot) { @@ -192,6 +192,7 @@ class SymbolLoaders { dest.enter(member) } } + // !!! TODO info.decls -> decls // enter decls of parent classes for (p <- container.info.parents) { if (p.symbol != defn.ObjectClass) { diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 12c3c7beb..0e439cb5f 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -182,7 +182,7 @@ trait Symbols { this: Context => def stubCompleter = new StubInfo()(condensed) val normalizedOwner = if (owner is ModuleVal) owner.moduleClass else owner println(s"creating stub for ${name.show}, owner = ${normalizedOwner.denot.debugString}, file = $file") - println(s"decls = ${normalizedOwner.preCompleteDecls.toList.map(_.debugString).mkString("\n ")}") // !!! DEBUG + println(s"decls = ${normalizedOwner.decls.toList.map(_.debugString).mkString("\n ")}") // !!! DEBUG throw new Error() val stub = name match { case name: TermName => @@ -376,7 +376,7 @@ object Symbols { override def toString: String = if (lastDenot == null) s"Naked$prefixString#$id" - else lastDenot.toString + else lastDenot.toString +"#"+id // !!! DEBUG def toText(implicit ctx: Context): Text = ctx.toText(this) diff --git a/src/dotty/tools/dotc/core/TypedTrees.scala b/src/dotty/tools/dotc/core/TypedTrees.scala index bd8474355..32ccaeeac 100644 --- a/src/dotty/tools/dotc/core/TypedTrees.scala +++ b/src/dotty/tools/dotc/core/TypedTrees.scala @@ -489,8 +489,8 @@ object TypedTrees { case _ => true } def noLeaksInClass(sym: ClassSymbol): Boolean = - (sym.classInfo.parents forall noLeaksIn) && - (sym.classInfo.decls.toList forall (t => noLeaksIn(t.info))) + (sym.info.parents forall noLeaksIn) && + (sym.decls.toList forall (t => noLeaksIn(t.info))) check(noLeaksIn(tree.tpe)) case If(cond, thenp, elsep) => check(cond.isValue); check(thenp.isValue); check(elsep.isValue) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 3b45eb53e..1a99e487b 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -297,15 +297,18 @@ object Types { // As an example of this in the wild, see // loadClassWithPrivateInnerAndSubSelf in ShowClassTests tp.cls.symbolicRef.findMember(name, pre, excluded) orElse d + case tp: TypeRef => + tp.denot.findMember(name, pre, excluded) case tp: TypeProxy => tp.underlying.findMember(name, pre, excluded) case tp: ClassInfo => - val candidates = tp.cls.membersNamed(name) - candidates.filterExcluded(excluded).asSeenFrom(pre).toDenot + tp.cls.findMember(name, pre, excluded) case AndType(l, r) => l.findMember(name, pre, excluded) & r.findMember(name, pre, excluded) case OrType(l, r) => (l.findMember(name, pre, excluded) | r.findMember(name, pre, excluded))(pre) + case NoType => + NoDenotation } /* !!! DEBUG ensuring { denot => denot.alternatives forall (_.symbol.name == name) }*/ @@ -397,7 +400,7 @@ object Types { case _ => NoType } - final def & (that: Type)(implicit ctx: Context): Type = + def & (that: Type)(implicit ctx: Context): Type = ctx.glb(this, that) def | (that: Type)(implicit ctx: Context): Type = @@ -492,12 +495,12 @@ object Types { case _ => TypeAlias(this) } - /** The type parameter with given `name`. This tries first `preCompleteDecls` + /** The type parameter with given `name`. This tries first `decls` * in order not to provoke a cylce by forcing the info. If that yields * no symbol it tries `member` as an alternative. */ def typeParamNamed(name: TypeName)(implicit ctx: Context): Symbol = - typeSymbol.preCompleteDecls.lookup(name) orElse member(name).symbol + typeSymbol.decls.lookup(name) orElse member(name).symbol /** The disjunctive normal form of this type. * This collects a set of alternatives, each alternative consisting @@ -569,7 +572,7 @@ object Types { case arg :: args1 => if (tparams.isEmpty) { println(s"applied type mismatch: $this $args, typeParams = $typeParams, tsym = ${this.typeSymbol.debugString}") // !!! DEBUG - println(s"precomplete decls = ${typeSymbol.preCompleteDecls.toList.map(_.denot).mkString("\n ")}") + println(s"precomplete decls = ${typeSymbol.decls.toList.map(_.denot).mkString("\n ")}") } val tparam = tparams.head val tp1 = RefinedType(tp, tparam.name, arg.toRHS(tparam)) @@ -1002,12 +1005,8 @@ object Types { } final class TermRefBySym(prefix: Type, name: TermName, val fixedSym: TermSymbol) - extends TermRef(prefix, name) with HasFixedSym { - override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef = - if (prefix.baseType(fixedSym.owner).exists) TermRef(prefix, fixedSym) - else TermRef(prefix, name, fixedSym.signature) - } - + extends TermRef(prefix, name) with HasFixedSym + final class TermRefWithSignature(prefix: Type, name: TermName, val sig: Signature) extends TermRef(prefix, name) { override def signature(implicit ctx: Context) = sig override def loadDenot(implicit ctx: Context): Denotation = @@ -1026,11 +1025,7 @@ object Types { } final class TypeRefBySym(prefix: Type, name: TypeName, val fixedSym: TypeSymbol) - extends TypeRef(prefix, name) with HasFixedSym { - override def newLikeThis(prefix: Type)(implicit ctx: Context): TypeRef = - if (prefix.baseType(fixedSym.owner).exists) TypeRef(prefix, fixedSym) - else TypeRef(prefix, name) - } + extends TypeRef(prefix, name) with HasFixedSym final class CachedTermRef(prefix: Type, name: TermName) extends TermRef(prefix, name) final class CachedTypeRef(prefix: Type, name: TypeName) extends TypeRef(prefix, name) @@ -1485,6 +1480,14 @@ object Types { def |(that: TypeBounds)(implicit ctx: Context): TypeBounds = TypeBounds(this.lo & that.lo, this.hi | that.hi) + override def & (that: Type)(implicit ctx: Context) = that match { + case that: TypeBounds => this & that + } + + override def | (that: Type)(implicit ctx: Context) = that match { + case that: TypeBounds => this | that + } + def map(f: Type => Type)(implicit ctx: Context): TypeBounds = TypeBounds(f(lo), f(hi)) diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index e273634ef..7af76f4f0 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -36,6 +36,7 @@ class ClassfileParser( protected var classTParams = Map[Name,Symbol]() classRoot.info = new ClassCompleter(instanceScope) + moduleRoot.info = new ModuleClassCompleter(staticModule, staticScope) private def currentIsTopLevel = classRoot.owner is Flags.PackageClass @@ -341,7 +342,7 @@ class ClassfileParser( val s = cctx.newSymbol( owner, expname, Flags.TypeParamCreationFlags, typeParamCompleter(index), coord = indexCoord(index)) - if (owner.isClass) owner.asClass.enter(s, owner.preCompleteDecls) + if (owner.isClass) owner.asClass.enter(s, owner.decls) tparams = tparams + (tpname -> s) sig2typeBounds(tparams, skiptvs = true) newTParams += s @@ -377,7 +378,7 @@ class ClassfileParser( case ENUM_TAG => val t = pool.getType(index) val n = pool.getName(in.nextChar) - val s = t.typeSymbol.companionModule.info.decls.lookup(n) + val s = t.typeSymbol.companionModule.decls.lookup(n) assert(s != NoSymbol, t) if (skip) None else Some(Literal(Constant(s))) case ARRAY_TAG => diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index d320ec280..02fc079ef 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -342,7 +342,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: if (denot.exists && !denot1.exists) { // !!!DEBUG val alts = denot.alternatives map (d => d+":"+d.info+"/"+d.signature) System.err.println(s"!!! disambiguation failure: $alts") - val members = denot.alternatives.head.symbol.owner.info.decls.toList map (d => d+":"+d.info+"/"+d.signature) + val members = denot.alternatives.head.symbol.owner.decls.toList map (d => d+":"+d.info+"/"+d.signature) System.err.println(s"!!! all members: $members") } if (tag == EXTref) sym else sym.moduleClass @@ -461,8 +461,8 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: def completer(cls: Symbol) = new LocalClassUnpickler(cls) { override def sourceModule = if (flags is ModuleClass) - cls.owner.preCompleteDecls.lookup( - cls.name.stripModuleClassSuffix.toTermName).suchThat(_ is Module).symbol + cls.owner.decls.lookup(cls.name.stripModuleClassSuffix.toTermName) + .suchThat(_ is Module).symbol else NoSymbol } cctx.newClassSymbol(owner, name.asTypeName, flags, completer, coord = start) @@ -621,7 +621,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: // and also for the inner Transform class in all views. We fix it by // replacing the this with the appropriate super. if (sym.owner != cls) { - val overriding = cls.preCompleteDecls.lookup(sym.name) + val overriding = cls.decls.lookup(sym.name) if (overriding.exists && overriding != sym) { val base = pre.baseType(sym.owner) assert(base.exists) @@ -641,7 +641,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: } else TypeRef(pre, sym.name.asTypeName).withDenot(sym) val args = until(end, readTypeRef) // if (args.nonEmpty) { // DEBUG -// println(s"reading app type $tycon $args") +// println(s"reading app type $tycon $args") // } tycon.appliedTo(args) case TYPEBOUNDStpe => -- cgit v1.2.3