From 5b4f154c9e4c2c6ff48ac68b8d984e306853328f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 21 Mar 2013 21:30:30 +0100 Subject: More fixes to classfile reading. Can now read all classes in scala.collection.generic. Some failures remain for their companion objects. --- src/dotty/tools/dotc/core/Contexts.scala | 2 +- src/dotty/tools/dotc/core/Denotations.scala | 22 ++++++++--- src/dotty/tools/dotc/core/Flags.scala | 4 +- src/dotty/tools/dotc/core/Printers.scala | 45 ++++++++++++---------- src/dotty/tools/dotc/core/SymDenotations.scala | 12 ++++++ src/dotty/tools/dotc/core/SymbolLoaders.scala | 11 +++++- src/dotty/tools/dotc/core/Types.scala | 12 +++++- src/dotty/tools/dotc/core/pickling/UnPickler.scala | 15 ++++++-- src/dotty/tools/dotc/util/Text.scala | 1 + 9 files changed, 89 insertions(+), 35 deletions(-) (limited to 'src/dotty/tools') diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 2759d1079..6dfd2050d 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -256,7 +256,7 @@ object Contexts { .withSetting(settings.debug, true) .withSetting(settings.Ylogcp, true) .withSetting(settings.printtypes, true) - .withSetting(settings.pageWidth, 120) + .withSetting(settings.pageWidth, 90) /** The symbol loaders */ val loaders = new SymbolLoaders diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 24008ab63..f8837fafe 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -463,15 +463,25 @@ object Denotations { final def first = this final def toDenot(implicit ctx: Context) = this final def containsSig(sig: Signature)(implicit ctx: Context) = - signature == sig + exists && signature == sig final def filterDisjoint(denots: PreDenotation)(implicit ctx: Context): SingleDenotation = if (denots.containsSig(signature)) NoDenotation else this final def filterExcluded(excluded: FlagSet)(implicit ctx: Context): SingleDenotation = - if (excluded != EmptyFlags && (asSymDenotation is excluded)) NoDenotation - else this - def asSeenFrom(pre: Type)(implicit ctx: Context): SingleDenotation = - if (!asSymDenotation.owner.membersNeedAsSeenFrom(pre)) this - else derivedSingleDenotation(symbol, info.asSeenFrom(pre, asSymDenotation.owner)) + if (excluded == EmptyFlags) this + else this match { + case thisd: SymDenotation => + if (thisd is excluded) NoDenotation else this + case _ => + if (symbol is excluded) NoDenotation else this + } + def asSeenFrom(pre: Type)(implicit ctx: Context): SingleDenotation = { + val owner = this match { + case thisd: SymDenotation => thisd.owner + case _ => if (symbol.exists) symbol.owner else NoSymbol + } + if (!owner.membersNeedAsSeenFrom(pre)) this + else derivedSingleDenotation(symbol, info.asSeenFrom(pre, owner)) + } } class UniqueRefDenotation( diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index ff0a2e0ee..43d5e5cd1 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -220,6 +220,8 @@ object Flags { /** Labeled with `sealed` modifier (sealed class) */ final val Sealed = typeFlag(11, "sealed") + final val AccessorOrSealed = Accessor.toCommonFlags + /** A mutable var */ final val Mutable = termFlag(12, "mutable") @@ -369,7 +371,7 @@ object Flags { /** Flags guaranteed to be set upon symbol creation */ final val FromStartFlags = AccessFlags | Module | Package | Deferred | Param | Scala2ExistentialCommon | Touched | - Static | CovariantCommon | ContravariantCommon | ExpandedName + Static | CovariantCommon | ContravariantCommon | ExpandedName | AccessorOrSealed assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags) // TODO: Should check that FromStartFlags do not changed in completion diff --git a/src/dotty/tools/dotc/core/Printers.scala b/src/dotty/tools/dotc/core/Printers.scala index e6b2288ab..d271658b2 100644 --- a/src/dotty/tools/dotc/core/Printers.scala +++ b/src/dotty/tools/dotc/core/Printers.scala @@ -96,6 +96,9 @@ object Printers { try { ctx.toTextRecursions += 1 op + } catch { + case ex: CyclicReference => + "" } finally { ctx.toTextRecursions -= 1 } @@ -165,11 +168,11 @@ object Printers { Text(refined.map(toTextRefinement), "; ").close ~ "}" case AndType(tp1, tp2) => (prec parenthesize AndPrec) { - toText(tp1, AndPrec) ~ "&" ~ toText(tp2, AndPrec) + toText(tp1, AndPrec) ~ " & " ~ toText(tp2, AndPrec) } case OrType(tp1, tp2) => (prec parenthesize OrPrec) { - toText(tp1, OrPrec) ~ "|" ~ toText(tp2, OrPrec) + toText(tp1, OrPrec) ~ " | " ~ toText(tp2, OrPrec) } case ErrorType => "" @@ -282,7 +285,7 @@ object Printers { else Text() val parentsText = Text(cparents.map(toText(_, WithPrec)), " with ") val declsText = if (decls.isEmpty) Text() else dclsText(decls.toList) - "extends " ~ parentsText ~ "{" ~ selfText ~ declsText ~ + " extends " ~ parentsText ~ "{" ~ selfText ~ declsText ~ "} at " ~ preText case _ => ": " ~ toTextGlobal(tp) @@ -291,22 +294,22 @@ object Printers { /** String representation of symbol's kind. */ def kindString(sym: Symbol): String = - if (sym is PackageClass) "package class" - else if (sym is PackageVal) "package" + if (sym isUnsafe PackageClass) "package class" + else if (sym isUnsafe PackageVal) "package" else if (sym.isPackageObject) if (sym.isClass) "package object class" else "package object" else if (sym.isAnonymousClass) "anonymous class" - else if (sym is ModuleClass) "module class" - else if (sym is ModuleVal) "module" - else if (sym is ImplClass) "implementation class" - else if (sym is Trait) "trait" + else if (sym isUnsafe ModuleClass) "module class" + else if (sym isUnsafe ModuleVal) "module" + else if (sym isUnsafe ImplClass) "implementation class" + else if (sym isUnsafe Trait) "trait" else if (sym.isClass) "class" else if (sym.isType) "type" else if (sym.isGetter) "getter" else if (sym.isSetter) "setter" - else if (sym is Lazy) "lazy value" - else if (sym is Mutable) "variable" + else if (sym isUnsafe Lazy) "lazy value" + else if (sym isUnsafe Mutable) "variable" else if (sym.isClassConstructor && sym.isPrimaryConstructor) "primary constructor" else if (sym.isClassConstructor) "constructor" else if (sym.isSourceMethod) "method" @@ -315,15 +318,15 @@ object Printers { /** String representation of symbol's definition key word */ protected def keyString(sym: Symbol): String = - if (sym is JavaInterface) "interface" - else if (sym is (Trait, butNot = ImplClass)) "trait" + if (sym isUnsafe JavaInterface) "interface" + else if ((sym isUnsafe Trait) && !(sym isUnsafe ImplClass)) "trait" else if (sym.isClass) "class" - else if (sym.isType && !(sym is ExpandedTypeParam)) "type" - else if (sym is Mutable) "var" - else if (sym is Package) "package" - else if (sym is Module) "object" + else if (sym.isType && !(sym isUnsafe ExpandedTypeParam)) "type" + else if (sym isUnsafe Mutable) "var" + else if (sym isUnsafe Package) "package" + else if (sym isUnsafe Module) "object" else if (sym.isSourceMethod) "def" - else if (sym.isTerm && (!(sym is Param))) "val" + else if (sym.isTerm && (!(sym isUnsafe Param))) "val" else "" /** String representation of symbol's flags */ @@ -476,10 +479,10 @@ object Printers { } override def kindString(sym: Symbol) = - if (sym is Package) "package" + if (sym isUnsafe Package) "package" else if (sym.isPackageObject) "package object" - else if (sym is Module) "object" - else if (sym is ImplClass) "class" + else if (sym isUnsafe Module) "object" + else if (sym isUnsafe ImplClass) "class" else if (sym.isClassConstructor) "constructor" else super.kindString(sym) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index d5ccfb74a..42583c5cd 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -81,6 +81,7 @@ object SymDenotations { (if (fs <= FromStartFlags) _flags else flags) is fs final def is(fs: FlagConjunction, butNot: FlagSet) = (if (fs <= FromStartFlags && butNot <= FromStartFlags) _flags else flags) is (fs, butNot) + final def isUnsafe(fs: FlagSet) = _flags is fs /** The type info. * The info is an instance of TypeType iff this is a type denotation @@ -107,6 +108,8 @@ object SymDenotations { /** The denotation is completed: all attributes are fully defined */ final def isCompleted: Boolean = ! _info.isInstanceOf[LazyType] + final def isCompleting: Boolean = (_flags is Touched) && !isCompleted + /** The completer of this denotation. @pre: Denotation is not yet completed */ final def completer: LazyType = _info.asInstanceOf[LazyType] @@ -803,10 +806,19 @@ object SymDenotations { private def computeMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = if (!classSymbol.hasChildren || (memberFingerPrint contains name)) { val ownDenots = info.decls.denotsNamed(name) +// if (name.toString == "GenericCanBuildFrom") // DEBUG +// println(s"$this.member(GenericCanBuildFrom), ownDenots = $ownDenots") def collect(denots: PreDenotation, parents: List[TypeRef]): PreDenotation = parents match { case p :: ps => val denots1 = p.symbol.denot match { case parentd: ClassDenotation => +// if (name.toString == "GenericCanBuildFrom") { // DEBUG +// val s1 = parentd.membersNamed(name) +// val s2 = s1.filterExcluded(Private) +// val s3 = s2.asSeenFrom(thisType) +// val s4 = s3.filterDisjoint(ownDenots) +// println(s"$this.member(GenericCanBuildFrom) $s1 $s2 $s3 $s4") +// } denots union parentd.membersNamed(name) .filterExcluded(Private) diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index b71b0c660..fa62d29e3 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -15,6 +15,13 @@ import StdNames._ import Decorators.StringDecorator import pickling.ClassfileParser +object SymbolLoaders { + /** A marker trait for a completer that replaces the original + * Symbol loader for an unpickled root. + */ + trait SecondCompleter +} + /** A base class for Symbol loaders with some overridable behavior */ class SymbolLoaders { @@ -225,7 +232,9 @@ trait SymbolLoader extends LazyType { throw ex } finally { def postProcess(denot: SymDenotation) = - if ((denot is Touched) && !denot.isCompleted) denot.markAbsent() + if (!denot.isCompleted && + !denot.completer.isInstanceOf[SymbolLoaders.SecondCompleter]) + denot.markAbsent() postProcess(root) if (!root.isRoot) postProcess(root.linkedClass.denot) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 252901b17..b061a1227 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -551,7 +551,13 @@ object Types { } def hkRefinement(tp: TypeRef): Type = { - val hkArgs = hkApp(tp.info).typeArgs + val hkArgs = + if (tp.symbol.isCompleting) + // This can happen if a higher-kinded type appears applied to arguments in its own bounds. + // TODO: Catch this case and mark as "proceed at own risk" later. + args map (_ => defn.InvariantBetweenClass.typeConstructor) + else + hkApp(tp.info).typeArgs ((tp: Type) /: hkArgs.zipWithIndex.zip(args)) { case (parent, ((hkArg, idx), arg)) => val vsym = hkArg.typeSymbol @@ -1627,6 +1633,10 @@ object Types { name.isTermName && (pre member name).hasAltWith(_ is Deferred) } + object takeAllFilter extends NameFilter { + def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = true + } + // ----- Exceptions ------------------------------------------------------------- class TypeError(msg: String) extends Exception(msg) diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 2f7bcc94d..4b3f17703 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -135,7 +135,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: import cctx.debug val moduleRoot = moduleClassRoot.sourceModule.denot - println(s"moduleRoot = $moduleRoot, ${moduleRoot.isTerm}") // !!! DEBUG + assert(moduleRoot.isTerm) checkVersion() @@ -494,7 +494,8 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: object localMemberUnpickler extends LocalUnpickler - class RootUnpickler(start: Coord, cls: Symbol) extends LocalClassUnpickler(cls) { + class RootUnpickler(start: Coord, cls: Symbol) + extends LocalClassUnpickler(cls) with SymbolLoaders.SecondCompleter { override def startCoord(denot: SymDenotation): Coord = start } @@ -581,7 +582,10 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: sym.asType) } else TypeRef(pre, sym.name.asTypeName) val args = until(end, readTypeRef) - if (args.nonEmpty) println(s"reading app type $tycon ${tycon.typeSymbol.debugString} $args, owner = ${tycon.typeSymbol.owner.debugString}") // !!! DEBUG + if (args.nonEmpty) { // DEBUG + println(s"reading app type $tycon") + println(s"${tycon.typeSymbol.debugString} $args") + } tycon.appliedTo(args) case TYPEBOUNDStpe => TypeBounds(readTypeRef(), readTypeRef()) @@ -606,7 +610,10 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: case METHODtpe | IMPLICITMETHODtpe => val restpe = readTypeRef() val params = until(end, readSymbolRef) - val maker = if (tag == METHODtpe) MethodType else ImplicitMethodType + def isImplicit = + tag == IMPLICITMETHODtpe || + params.nonEmpty && (params.head is Implicit) + val maker = if (isImplicit) ImplicitMethodType else MethodType maker.fromSymbols(params, restpe) case POLYtpe => val restpe = readTypeRef() diff --git a/src/dotty/tools/dotc/util/Text.scala b/src/dotty/tools/dotc/util/Text.scala index 251274371..a314e8ab4 100644 --- a/src/dotty/tools/dotc/util/Text.scala +++ b/src/dotty/tools/dotc/util/Text.scala @@ -45,6 +45,7 @@ object Texts { this match { case Str(s1) => Str(s1 + s2) case Fluid(Str(s1) :: prev) => Fluid(Str(s1 + s2) :: prev) + case Fluid(relems) => Fluid(that :: relems) } case Fluid(relems) => (this /: relems.reverse)(_ appendToLastLine _) -- cgit v1.2.3