From e59b8822f53fa6fad057ac9642d31e4026800bf5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 21 Jan 2013 12:43:11 +0100 Subject: Big renaming to drop Reference(d) as a terminology and use Denotation instead. previous Denotations (which already were a subclass) are renamed to SymDenotations. --- src/dotty/tools/dotc/core/SymDenotations.scala | 440 +++++++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 src/dotty/tools/dotc/core/SymDenotations.scala (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala') diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala new file mode 100644 index 000000000..d92d6eb27 --- /dev/null +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -0,0 +1,440 @@ +package dotty.tools.dotc +package core + +import Periods._, Contexts._, Symbols._, Denotations._, Names._, Annotations._ +import Types._, Flags._, Decorators._, Transformers._ +import Scopes.Scope +import collection.mutable +import collection.immutable.BitSet + +object SymDenotations { + + /** A denotation represents the contents of a definition + * during a period. + */ + abstract class SymDenotation(initFlags: FlagSet) extends SingleDenotation { + + def owner: Symbol + + def name: Name + + def symbol: Symbol + + def info: Type + + private[this] var _flags: FlagSet = initFlags + + def flags: FlagSet = _flags + + def flags_=(flags: FlagSet): Unit = + _flags |= flags + + def setFlags(flags: FlagSet): Unit = + _flags |= flags + + def resetFlags(flags: FlagSet): Unit = + _flags &~= flags + + private[this] var _privateWithin: Symbol = NoSymbol + + def privateWithin: Symbol = _privateWithin + + def privateWithin_=(sym: Symbol): Unit = + _privateWithin = sym + + final def isLoaded = _privateWithin != null + + private[this] var _annotations: List[Annotation] = Nil + + def annotations: List[Annotation] = _annotations + + def annotations_=(annots: List[Annotation]): Unit = + _annotations = annots + + final def isCompleted = _annotations != null + + /** is this symbol a class? */ + def isClass: Boolean = false + + /** is this symbol a method? */ + def isMethod: Boolean = false + + /** is this symbol the result of an erroneous definition? */ + def isError: Boolean = false + + def withType(tp: Type): SymDenotation = ??? + + override protected def copy(s: Symbol, i: Type): SingleDenotation = new UniqueRefDenotation(s, i, validFor) + } + + class CompleteSymDenotation( + val symbol: Symbol, + val owner: Symbol, + val name: Name, + initFlags: FlagSet, + val info: Type + ) extends SymDenotation(initFlags) + + trait LazyCompletion extends SymDenotation { + privateWithin = null + annotations = null + + override final def flags = { + if (!isLoaded) tryLoad() + super.flags + } + + override final def privateWithin = { + if (!isLoaded) tryLoad() + super.privateWithin + } + + override final def annotations: List[Annotation] = { + val annots = super.annotations + if (annots != null) annots else { tryComplete(); annotations } + } + + protected def tryLoad(): Unit = try { + if (flags is Locked) throw new CyclicReference(symbol) + setFlags(Locked) + load() + } catch { + case ex: CyclicReference => handleCycle() + } finally { + flags &~= Locked + } + + protected def tryComplete() = try { + if (flags is Locked) throw new CyclicReference(symbol) + complete() + } catch { + case ex: CyclicReference => handleCycle() + } finally { + flags &~= Locked + } + + protected def handleCycle(): Unit + protected def load(): Unit + protected def complete(): Unit + } + + abstract class LazySymDenotation( + val symbol: Symbol, + val owner: Symbol, + val name: Name, + initFlags: FlagSet + ) extends SymDenotation(initFlags) with LazyCompletion { + + private var currentInfo: Type = null + + override def info = { + if (currentInfo == null) complete() + currentInfo + } + } + + abstract class ClassDenotation(initFlags: FlagSet)(implicit ctx: Context) + extends SymDenotation(initFlags) { + import NameFilter._ + import util.LRU8Cache + + val symbol: ClassSymbol + + def typeParams: List[TypeSymbol] + + def parents: List[Type] + + def decls: Scope + + val info = ClassInfo(owner.thisType, this) + + private var memberCacheVar: LRU8Cache[Name, DenotationSet] = null + + private def memberCache: LRU8Cache[Name, DenotationSet] = { + if (memberCacheVar == null) memberCacheVar = new LRU8Cache + memberCacheVar + } + + private var thisTypeCache: ThisType = null + + def thisType(implicit ctx: Context): Type = { + if (thisTypeCache == null) + thisTypeCache = ThisType(symbol) + thisTypeCache + } + + private var typeConstructorCache: Type = null + + def typeConstructor(implicit ctx: Context): Type = { + if (typeConstructorCache == null) + typeConstructorCache = NamedType(thisType, symbol.name) + typeConstructorCache + } + + private var typeTemplateCache: Type = null + + def typeTemplate(implicit ctx: Context): Type = { + if (typeTemplateCache == null) + AppliedType.make(typeConstructor, typeParams map (_.typeConstructor)) + typeTemplateCache + } + + private var baseClassesVar: List[ClassSymbol] = null + private var superClassBitsVar: BitSet = null + + private def computeSuperClassBits(implicit ctx: Context): Unit = { + val seen = new mutable.BitSet + val locked = new mutable.BitSet + def addBaseClasses(bcs: List[ClassSymbol], to: List[ClassSymbol]) + : List[ClassSymbol] = bcs match { + case bc :: bcs1 => + val id = bc.superId + if (seen contains id) to + else if (locked contains id) throw new CyclicReference(symbol) + else { + locked += id + val bcs1added = addBaseClasses(bcs1, to) + seen += id + if (bcs1added eq bcs1) bcs else bc :: bcs1added + } + case _ => + to + } + def addParentBaseClasses(ps: List[Type], to: List[ClassSymbol]): List[ClassSymbol] = ps match { + case p :: ps1 => + addBaseClasses(p.baseClasses, addParentBaseClasses(ps1, to)) + case _ => + to + } + baseClassesVar = symbol :: addParentBaseClasses(parents, Nil) + superClassBitsVar = ctx.root.uniqueBits.findEntryOrUpdate(seen.toImmutable) + } + + def superClassBits(implicit ctx: Context): BitSet = { + if (superClassBitsVar == null) computeSuperClassBits + superClassBitsVar + } + + def baseClasses(implicit ctx: Context): List[ClassSymbol] = { + if (baseClassesVar == null) computeSuperClassBits + baseClassesVar + } + + /** Is this class a subclass of `clazz`? */ + final def isSubClass(clazz: ClassSymbol)(implicit ctx: Context): Boolean = { + superClassBits contains clazz.superId + } + + private var definedFingerPrintCache: FingerPrint = null + + private def computeDefinedFingerPrint(implicit ctx: Context): FingerPrint = { + var bits = newNameFilter + var e = decls.lastEntry + while (e != null) { + includeName(bits, name) + e = e.prev + } + var ps = parents + while (ps.nonEmpty) { + val parent = ps.head.typeSymbol + parent.denot match { + case classd: ClassDenotation => + includeFingerPrint(bits, classd.definedFingerPrint) + parent.denot.setFlags(Frozen) + case _ => + } + ps = ps.tail + } + definedFingerPrintCache = bits + bits + } + + /** Enter a symbol in current scope. + * Note: We require that this does not happen after the first time + * someone does a findMember on a subclass. + */ + def enter(sym: Symbol)(implicit ctx: Context) = { + require(!(this is Frozen)) + decls enter sym + if (definedFingerPrintCache != null) + includeName(definedFingerPrintCache, sym.name) + if (memberCacheVar != null) + memberCache invalidate sym.name + } + + /** Delete symbol from current scope. + * Note: We require that this does not happen after the first time + * someone does a findMember on a subclass. + */ + def delete(sym: Symbol)(implicit ctx: Context) = { + require(!(this is Frozen)) + decls unlink sym + if (definedFingerPrintCache != null) + computeDefinedFingerPrint + if (memberCacheVar != null) + memberCache invalidate sym.name + } + + def definedFingerPrint(implicit ctx: Context): FingerPrint = { + val fp = definedFingerPrintCache + if (fp != null) fp else computeDefinedFingerPrint + } + + final def membersNamed(name: Name)(implicit ctx: Context): DenotationSet = { + var refs: DenotationSet = memberCache lookup name + if (refs == null) { + if (containsName(definedFingerPrint, name)) { + val ownDenots = decls.denotsNamed(name) + refs = ownDenots + var ps = parents + while (ps.nonEmpty) { + val parentSym = ps.head.typeSymbol + parentSym.denot match { + case parentd: ClassDenotation => + refs = refs union + parentd.membersNamed(name) + .filterExcluded(Flags.Private) + .asSeenFrom(thisType, parentSym) + .filterDisjoint(ownDenots) + case _ => + } + } + } else { + refs = NoDenotation + } + memberCache enter (name, refs) + } + refs + } + + private var baseTypeCache: java.util.HashMap[CachedType, Type] = null + private var baseTypeValid: RunId = NoRunId + + final def baseTypeOf(tp: Type)(implicit ctx: Context): Type = { + + def computeBaseTypeOf(tp: Type): Type = tp match { + case AppliedType(tycon, args) => + baseTypeOf(tycon).subst(tycon.typeParams, args) + case tp: TypeProxy => + baseTypeOf(tp.underlying) + case AndType(tp1, tp2) => + baseTypeOf(tp1) & baseTypeOf(tp2) + case OrType(tp1, tp2) => + baseTypeOf(tp1) | baseTypeOf(tp2) + case tp @ ClassInfo(pre, classd) => + def reduce(bt: Type, ps: List[Type]): Type = ps match { + case p :: ps1 => reduce(bt & baseTypeOf(p), ps1) + case _ => bt + } + if (classd.symbol == symbol) tp.typeTemplate + else reduce(NoType, classd.parents).substThis(classd.symbol, tp.prefix) + } + + if (symbol.isStaticMono) symbol.typeConstructor + else tp match { + case tp: CachedType => + if (baseTypeValid != ctx.runId) { + baseTypeCache = new java.util.HashMap[CachedType, Type] + baseTypeValid = ctx.runId + } + var basetp = baseTypeCache get tp + if (basetp == null) { + baseTypeCache.put(tp, NoType) + basetp = computeBaseTypeOf(tp) + baseTypeCache.put(tp, basetp) + } else if (basetp == NoType) { + throw new CyclicReference(symbol) + } + basetp + case _ => + computeBaseTypeOf(tp) + } + } + + private var memberNamesCache: Map[NameFilter, Set[Name]] = Map() + + def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = + memberNamesCache get keepOnly match { + case Some(names) => + names + case _ => + val inheritedNames = (parents flatMap (_.memberNames(thisType, keepOnly))).toSet + val ownNames = decls.iterator map (_.name) + val candidates = inheritedNames ++ ownNames + val names = candidates filter (keepOnly(thisType, _)) + memberNamesCache += (keepOnly -> names) + names + } + } + + class CompleteClassDenotation( + val symbol: ClassSymbol, + val owner: Symbol, + val name: Name, + initFlags: FlagSet, + val typeParams: List[TypeSymbol], + val parents: List[Type], + val decls: Scope + )(implicit ctx: Context) extends ClassDenotation(initFlags) + + abstract class LazyClassDenotation( + val symbol: ClassSymbol, + val owner: Symbol, + val name: Name, + initFlags: FlagSet + )(implicit ctx: Context) extends ClassDenotation(initFlags) with LazyCompletion { + + protected var _typeParams: List[TypeSymbol] = null + protected var _parents: List[Type] = null + protected var _decls: Scope = null + + final def typeParams: List[TypeSymbol] = { + val tparams = _typeParams + if (tparams != null) tparams else { tryLoad(); typeParams } + } + + final def parents: List[Type] = { + val ps = _parents + if (ps != null) ps else { tryComplete(); parents } + } + + final def decls: Scope = { + val ds = _decls + if (ds != null) ds else { tryComplete(); decls } + } + } + + object NoDenotation extends SymDenotation(Flags.Empty) { + override def symbol: Symbol = NoSymbol + override def owner: Symbol = throw new AssertionError("NoDenotation.owner") + override def name: Name = BootNameTable.newTermName("") + override def info: Type = NoType + } + + object NameFilter { + final val WordSizeLog = 6 + final val DefinedNamesWords = 16 + final val DefinedNamesSize = DefinedNamesWords << WordSizeLog + final val DefinedNamesMask = DefinedNamesSize - 1 + + type FingerPrint = Array[Long] + + def includeName(bits: FingerPrint, name: Name): Unit = { + val hash = name.start & DefinedNamesMask + bits(hash >> 6) |= (1 << hash) + } + + def includeFingerPrint(bits1: FingerPrint, bits2: FingerPrint): Unit = + for (i <- 0 until DefinedNamesWords) bits1(i) |= bits2(i) + + def containsName(bits: FingerPrint, name: Name): Boolean = { + val hash = name.start & DefinedNamesMask + (bits(hash >> 6) & (1 << hash)) != 0 + } + + def newNameFilter: FingerPrint = new Array[Long](DefinedNamesWords) + } + + implicit def toFlagSet(denot: SymDenotation): FlagSet = denot.flags + +} -- cgit v1.2.3 From 8621d34646e15b14ffd7ac2a7a8ca6eb587b1426 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 24 Jan 2013 15:20:28 +0100 Subject: Various additions to symbols, denotations, and elsewhere --- src/dotty/tools/dotc/core/Annotations.scala | 7 +- src/dotty/tools/dotc/core/Contexts.scala | 19 +- src/dotty/tools/dotc/core/Decorators.scala | 13 ++ src/dotty/tools/dotc/core/Denotations.scala | 33 +-- src/dotty/tools/dotc/core/Flags.scala | 5 +- src/dotty/tools/dotc/core/Printers.scala | 26 +++ src/dotty/tools/dotc/core/Scopes.scala | 7 +- src/dotty/tools/dotc/core/SubTypers.scala | 14 +- src/dotty/tools/dotc/core/SymDenotations.scala | 263 ++++++++++++++++++++-- src/dotty/tools/dotc/core/Symbols.scala | 289 +++++++++++++------------ src/dotty/tools/dotc/core/TypeOps.scala | 2 +- src/dotty/tools/dotc/core/Types.scala | 26 ++- 12 files changed, 493 insertions(+), 211 deletions(-) create mode 100644 src/dotty/tools/dotc/core/Printers.scala (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala') diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala index 756430fb3..ead92409e 100644 --- a/src/dotty/tools/dotc/core/Annotations.scala +++ b/src/dotty/tools/dotc/core/Annotations.scala @@ -1,8 +1,11 @@ package dotty.tools.dotc.core +import Symbols._ + object Annotations { - abstract class Annotation - abstract class AnnotationInfo + abstract class Annotation { + def matches(cls: Symbol) = ??? + } } \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 74b6e851f..645820792 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -7,7 +7,7 @@ import Names._ import Phases._ import Types._ import Symbols._ -import SubTypers._ +import TypeComparers._, Printers._ import collection.mutable import collection.immutable.BitSet @@ -21,27 +21,34 @@ object Contexts { val root: RootContext val period: Period def constraints: Constraints - def subTyper: SubTyper + def typeComparer: TypeComparer + def printer: Printer = ??? def names: NameTable + def enclClass: Context = ??? def phase: Phase = ??? + def owner: Symbol = ??? def erasedTypes: Boolean = ??? } + abstract class DiagnosticsContext(ctx: Context) extends SubContext(ctx) { + var diagnostics: () => String + } + abstract class SubContext(val underlying: Context) extends Context { val root: RootContext = underlying.root val period: Period = underlying.period val constraints = underlying.constraints def names: NameTable = root.names - lazy val subTyper = - if (constraints eq underlying.constraints) underlying.subTyper - else new SubTyper(this) + lazy val typeComparer = + if (constraints eq underlying.constraints) underlying.typeComparer + else new TypeComparer(this) } class RootContext extends Context with Transformers { val underlying: Context = throw new UnsupportedOperationException("RootContext.underlying") - def subTyper: SubTyper = ??? + def typeComparer: TypeComparer = ??? val root: RootContext = this val period = Nowhere diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index ba3123358..d0ce3efe0 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -1,6 +1,9 @@ package dotty.tools.dotc package core +import annotation.tailrec +import Symbols._ + import Contexts._, Names._ object Decorators { @@ -15,6 +18,16 @@ object Decorators { context.names.newTermName(s) } + implicit class SymbolIteratorDecorator(val it: Iterator[Symbol]) extends AnyVal { + final def findSymbol(p: Symbol => Boolean): Symbol = { + while (it.hasNext) { + val sym = it.next + if (p(sym)) return sym + } + NoSymbol + } + } + final val MaxRecursions = 1000 implicit class ListDecorator[T](val xs: List[T]) extends AnyVal { diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 6b19f4589..12b522427 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -8,6 +8,7 @@ import Names.TypeName import Symbols.NoSymbol import Symbols.Symbol import Types._, Periods._, Flags._, Transformers._ +import Decorators.SymbolIteratorDecorator /** Denotations represent the meaning of symbols and named types. @@ -20,10 +21,7 @@ import Types._, Periods._, Flags._, Transformers._ * Lines ending in a horizontal line mean subtying (right is a subtype of left). * * NamedType------NamedTypeWithSignature - * | | | - * | +-----------------------------------------+ - * | | | symbol - * | | v + * | | Symbol---------ClassSymbol * | | | | * | denot | denot | denot | denot @@ -134,7 +132,7 @@ object Denotations { def isType: Boolean = false /** Is this a reference to a term symbol? */ - def isTerm: Boolean = !isType + def isTerm: Boolean = false /** Is this denotation overloaded? */ def isOverloaded = isInstanceOf[MultiDenotation] @@ -150,6 +148,8 @@ object Denotations { def exists: Boolean = true + def filter(p: Symbol => Boolean)(implicit ctx: Context): Denotation + /** Form a denotation by conjoining with denotation `that` */ def & (that: Denotation)(implicit ctx: Context): Denotation = if (this eq that) this @@ -199,8 +199,8 @@ object Denotations { def lubSym(sym1: Symbol, sym2: Symbol): Symbol = { def qualifies(sym: Symbol) = - (sym isAccessibleFrom pre) && (sym2.owner isSubClass sym.owner) - sym1.allOverriddenSymbols find qualifies getOrElse NoSymbol + sym.isAccessibleFrom(pre) && sym2.owner.isSubClass(sym.owner) + sym1.allOverriddenSymbols findSymbol qualifies } def throwError = throw new MatchError(s"$this | $that") @@ -237,11 +237,15 @@ object Denotations { * @param variants The overloaded variants indexed by thheir signatures. */ case class MultiDenotation(denot1: Denotation, denot2: Denotation) extends Denotation { + final override def isType = false + final override def isTerm = true def derivedMultiDenotation(d1: Denotation, d2: Denotation) = if ((d1 eq denot1) && (d2 eq denot2)) this else MultiDenotation(d1, d2) def symbol = unsupported("symbol") def info = unsupported("info") def signature = unsupported("signature") + def filter(p: Symbol => Boolean)(implicit ctx: Context): Denotation = + (denot1 filter p) & (denot2 filter p) def atSignature(sig: Signature): SingleDenotation = denot1.atSignature(sig) orElse denot2.atSignature(sig) def validFor = denot1.validFor & denot2.validFor @@ -252,6 +256,7 @@ object Denotations { abstract class SingleDenotation extends Denotation with DenotationSet { override def isType = symbol.isType + override def isTerm = symbol.isTerm override def signature: Signature = { def sig(tp: Type): Signature = tp match { case tp: PolyType => @@ -272,6 +277,9 @@ object Denotations { def orElse(that: => SingleDenotation) = if (this.exists) this else that + def filter(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = + if (p(symbol)) this else NoDenotation + def atSignature(sig: Signature): SingleDenotation = if (sig == signature) this else NoDenotation @@ -346,19 +354,17 @@ object Denotations { current } - def asSymDenotation = asInstanceOf[SymDenotation] + //final def asSymDenotation = asInstanceOf[SymDenotation] // ------ DenotationSet ops ---------------------------------------------- def toDenot(implicit ctx: Context) = this def containsSig(sig: Signature)(implicit ctx: Context) = signature == sig - def filter(p: Symbol => Boolean)(implicit ctx: Context): DenotationSet = - if (p(symbol)) this else NoDenotation def filterDisjoint(denots: DenotationSet)(implicit ctx: Context): DenotationSet = if (denots.containsSig(signature)) NoDenotation else this def filterExcluded(flags: FlagSet)(implicit ctx: Context): DenotationSet = - if (symbol.hasFlag(flags)) NoDenotation else this + if (symbol is flags) NoDenotation else this def filterAccessibleFrom(pre: Type)(implicit ctx: Context): DenotationSet = if (symbol.isAccessibleFrom(pre)) this else NoDenotation def asSeenFrom(pre: Type, owner: Symbol)(implicit ctx: Context): DenotationSet = @@ -394,7 +400,6 @@ object Denotations { def exists: Boolean def toDenot(implicit ctx: Context): Denotation def containsSig(sig: Signature)(implicit ctx: Context): Boolean - def filter(p: Symbol => Boolean)(implicit ctx: Context): DenotationSet def filterDisjoint(denots: DenotationSet)(implicit ctx: Context): DenotationSet def filterExcluded(flags: FlagSet)(implicit ctx: Context): DenotationSet def filterAccessibleFrom(pre: Type)(implicit ctx: Context): DenotationSet @@ -416,8 +421,8 @@ object Denotations { def toDenot(implicit ctx: Context) = denots1.toDenot & denots2.toDenot def containsSig(sig: Signature)(implicit ctx: Context) = (denots1 containsSig sig) || (denots2 containsSig sig) - def filter(p: Symbol => Boolean)(implicit ctx: Context) = - derivedUnion(denots1 filter p, denots2 filter p) + //def filter(p: Symbol => Boolean)(implicit ctx: Context) = + // derivedUnion(denots1 filter p, denots2 filter p) def filterDisjoint(denots: DenotationSet)(implicit ctx: Context): DenotationSet = derivedUnion(denots1 filterDisjoint denots, denots2 filterDisjoint denots) def filterExcluded(flags: FlagSet)(implicit ctx: Context): DenotationSet = diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 7a3b8f0bc..0e995f756 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -238,7 +238,7 @@ object Flags { final val Local = commonFlag(20, "") /** Symbol is defined by a Java class */ - final val Java = commonFlag(21, "") + final val JavaDefined = commonFlag(21, "") /** A compiler-generated symbol. which is visible for type-checking * (compare with artifact) @@ -344,8 +344,9 @@ object Flags { final val PrivateOrLocal = oneOf(Private, Local) /** Java symbol which is `protected` and `static` */ - final val StaticProtected = allOf(Java, Protected, Static) + final val StaticProtected = allOf(JavaDefined, Protected, Static) /** Labeled `protected[this]` */ final val ProtectedLocal = allOf(Protected, Local) + } \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Printers.scala b/src/dotty/tools/dotc/core/Printers.scala new file mode 100644 index 000000000..67d4d3422 --- /dev/null +++ b/src/dotty/tools/dotc/core/Printers.scala @@ -0,0 +1,26 @@ +package dotty.tools.dotc +package core + +import Types._, Symbols._, Contexts._, Scopes._ + +object Printers { + + abstract class Printer { + def show(tp: Type)(implicit ctx: Context): String + def show(sym: Symbol)(implicit ctx: Context): String + def showLocated(sym: Symbol)(implicit ctx: Context): String + def showDef(sym: Symbol)(implicit ctx: Context): String + def show(sc: Scope)(implicit ctx: Context): String + } + + class StdPrinter extends Printer { + def show(tp: Type)(implicit ctx: Context): String = ??? + def show(sym: Symbol)(implicit ctx: Context): String = ??? + def showLocated(sym: Symbol)(implicit ctx: Context): String = ??? + def showDef(sym: Symbol)(implicit ctx: Context): String = ??? + def show(sc: Scope)(implicit ctx: Context): String = + sc.toList.map(_.showDef).mkString("Scope{\n ", ";\n ", "\n}") + } + + +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala index 98f0b6390..0eadb8cb9 100644 --- a/src/dotty/tools/dotc/core/Scopes.scala +++ b/src/dotty/tools/dotc/core/Scopes.scala @@ -114,7 +114,7 @@ object Scopes { * @param sym ... */ def enterUnique(sym: Symbol)(implicit ctx: Context) { - assert(lookup(sym.name) == NoSymbol, (sym.locatedFullString, lookup(sym.name).locatedFullString)) + assert(lookup(sym.name) == NoSymbol, (sym.showLocated, lookup(sym.name).showLocated)) enter(sym) } @@ -270,11 +270,6 @@ object Scopes { @deprecated("Use `toList.reverse` instead", "2.10.0") def reverse: List[Symbol] = toList.reverse - - override def mkString(start: String, sep: String, end: String) = - toList.map(_.defString).mkString(start, sep, end) - - override def toString(): String = mkString("Scope{\n ", ";\n ", "\n}") } /** Create a new scope */ diff --git a/src/dotty/tools/dotc/core/SubTypers.scala b/src/dotty/tools/dotc/core/SubTypers.scala index 29c7b7388..2dcceceba 100644 --- a/src/dotty/tools/dotc/core/SubTypers.scala +++ b/src/dotty/tools/dotc/core/SubTypers.scala @@ -1,18 +1,18 @@ package dotty.tools.dotc.core -import Types._, Contexts._, Symbols._ +import Types._, Contexts._, Symbols._, Flags._ import collection.mutable -object SubTypers { +object TypeComparers { type Constraints = Map[PolyParam, TypeBounds] - object SubTyper { + object TypeComparer { private final val LogPendingSubTypesThreshold = 50 } - class SubTyper(_ctx: Context) extends DotClass { - import SubTyper._ + class TypeComparer(_ctx: Context) extends DotClass { + import TypeComparer._ implicit val ctx = _ctx @@ -72,7 +72,7 @@ object SubTypers { val pre2 = tp2.prefix (sym1 == sym2 && ( ctx.erasedTypes || - sym1.owner.hasFlag(Flags.Package) || + (sym1.owner.isPackage) || isSubType(pre1, pre2)) || tp1.name == tp2.name && @@ -175,7 +175,7 @@ object SubTypers { case tp1: TypeRef => ((tp1 eq defn.NothingType) || - (tp1 eq defn.NullType) && tp2.typeSymbol.containsNull + (tp1 eq defn.NullType) && tp2.typeSymbol.isNonValueClass || (!tp1.symbol.isClass && isSubType(tp1.info.bounds.hi, tp2))) case RefinedType(parent, _) => diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index d92d6eb27..9df52470b 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -6,6 +6,9 @@ import Types._, Flags._, Decorators._, Transformers._ import Scopes.Scope import collection.mutable import collection.immutable.BitSet +import scala.reflect.io.AbstractFile +import Decorators.SymbolIteratorDecorator +import annotation.tailrec object SymDenotations { @@ -51,20 +54,231 @@ object SymDenotations { def annotations_=(annots: List[Annotation]): Unit = _annotations = annots + def hasAnnotation(cls: Symbol) = dropOtherAnnotations(annotations, cls).nonEmpty + + @tailrec + private def dropOtherAnnotations(anns: List[Annotation], cls: Symbol): List[Annotation] = anns match { + case ann :: rest => if (ann matches cls) anns else dropOtherAnnotations(rest, cls) + case Nil => Nil + } + final def isCompleted = _annotations != null - /** is this symbol a class? */ - def isClass: Boolean = false + /** is this denotation a class? */ + final def isClass: Boolean = symbol.isInstanceOf[ClassSymbol] + + /** Special case tests for flags that are known a-priori and do not need loading + * flags. + */ + final def isModule = _flags is Module + final def isModuleObj = _flags is ModuleObj + final def isModuleClass = _flags is ModuleClass + final def isPackage = _flags is Package + final def isPackageObj = _flags is PackageObj + final def isPackageClass = _flags is PackageClass + + /** is this denotation a method? */ + //def isMethod: Boolean = false - /** is this symbol a method? */ - def isMethod: Boolean = false + def isSubClass(cls: Symbol)(implicit ctx: Context) = false + + def isNonBottomSubClass(cls: Symbol)(implicit ctx: Context) = false + + final def isSubClassOrCompanion(base: Symbol)(implicit ctx: Context): Boolean = + isNonBottomSubClass(base) || + isModuleClass && linkedClass.isNonBottomSubClass(base) + + final def enclosingSubClass(implicit ctx: Context) = { + val thissym = symbol + ctx.owner.ownersIterator.findSymbol(_.isSubClass(thissym)) + } /** is this symbol the result of an erroneous definition? */ def isError: Boolean = false + final def ownersIterator(implicit ctx: Context) = new Iterator[Symbol] { + private var current = symbol + def hasNext = current.exists + def next: Symbol = { + val result = current + current = current.owner + result + } + } + + final def hasTransOwner(sym: Symbol)(implicit ctx: Context): Boolean = { + var o = symbol + while ((o ne sym) && (o ne NoSymbol)) o = o.owner + (o eq sym) + } + def withType(tp: Type): SymDenotation = ??? override protected def copy(s: Symbol, i: Type): SingleDenotation = new UniqueRefDenotation(s, i, validFor) + + def moduleClass(implicit ctx: Context): Symbol = + if (this.isModuleObj) info.typeSymbol else NoSymbol + + /** Desire to re-use the field in ClassSymbol which stores the source + * file to also store the classfile, but without changing the behavior + * of sourceFile (which is expected at least in the IDE only to + * return actual source code.) So sourceFile has classfiles filtered out. + */ + private def sourceFileOnly(file: AbstractFile): AbstractFile = + if ((file eq null) || (file.path endsWith ".class")) null else file + + private def binaryFileOnly(file: AbstractFile): AbstractFile = + if ((file eq null) || !(file.path endsWith ".class")) null else file + + final def topLevelClass(implicit ctx: Context): Symbol = + if (!(owner.isPackageClass)) owner.topLevelClass + else if (isClass) symbol + else moduleClass + + final def enclosingPackage(implicit ctx: Context): Symbol = + if (isPackageClass) symbol else owner.enclosingPackage + + def associatedFile(implicit ctx: Context): AbstractFile = topLevelClass.associatedFile + final def binaryFile(implicit ctx: Context): AbstractFile = binaryFileOnly(associatedFile) + final def sourceFile(implicit ctx: Context): AbstractFile = sourceFileOnly(associatedFile) + + /** Is this symbol a type or stable term? */ + final def isStable(implicit ctx: Context) = !( + isTerm && + this.is(UnstableValue, butNot = Stable) || + info.isVolatile && !hasAnnotation(defn.uncheckedStableClass) + ) + + final def matchingSymbol(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = { + var denot = inClass.info.nonPrivateDecl(name) + if (denot.isTerm) { + val targetType = site.memberInfo(this) + if (denot.isOverloaded) + denot = denot.atSignature(targetType.signature) + if (!(site.memberInfo(denot.asInstanceOf[SymDenotation]) matches targetType)) + denot = NoDenotation + } + denot.symbol + } + + final def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol = + if (owner isSubClass inClass) matchingSymbol(inClass, owner.thisType) + else NoSymbol + + final def allOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] = + info.baseClasses.tail.iterator map overriddenSymbol filter (_.exists) + + /** Is this symbol defined in the same scope and compilation unit as `that` symbol? */ + private def isCoDefinedWith(that: Symbol)(implicit ctx: Context) = + (this.owner == that.owner) && + ( !(this.owner.isPackageClass) + || (this.sourceFile == null) + || (that.sourceFile == null) + || (this.sourceFile.path == that.sourceFile.path) // Cheap possibly wrong check, then expensive normalization + || (this.sourceFile.canonicalPath == that.sourceFile.canonicalPath) + ) + + def companionModule(implicit ctx: Context): Symbol = + owner.info.decl(name.toTermName).filter(_.isModule).symbol + + def companionClass(implicit ctx: Context): Symbol = + owner.info.decl(name.toTypeName).filter(_.isClass).symbol + + def linkedClass(implicit ctx: Context): Symbol = + if (this.isModuleClass) companionClass + else if (this.isClass) companionModule.moduleClass + else NoSymbol + + final def accessBoundary(base: Symbol)(implicit ctx: Context): Symbol = { + val fs = flags + if (fs is PrivateOrLocal) owner + else if (fs is StaticProtected) defn.RootClass + else if (privateWithin.exists && !ctx.phase.erasedTypes) privateWithin + else if (fs is Protected) base + else defn.RootClass + } + + final def isContainedIn(boundary: Symbol)(implicit ctx: Context): Boolean = + if (symbol eq boundary) true + else if (!this.exists || + (this.isPackageClass) && !(boundary.isPackageClass)) false + else owner.isContainedIn(boundary) + + def isAsAccessibleAs(that: Symbol)(implicit ctx: Context): Boolean = + (that.accessBoundary(NoSymbol) isContainedIn this.accessBoundary(NoSymbol)) && + (this.isStable || !that.isStable) + + def isAccessibleFrom(pre: Type, superAccess: Boolean = false)(implicit ctx: Context): Boolean = { + + def accessWithinLinked(boundary: Symbol) = { + val linked = boundary.linkedClass + (linked ne NoSymbol) && accessWithin(linked) + } + + /** Are we inside definition of `boundary`? */ + def accessWithin(boundary: Symbol) = + owner.hasTransOwner(boundary) && + (!(this is JavaDefined) || + owner.enclosingPackage == boundary.enclosingPackage) + + def isCorrectThisType(pre: Type): Boolean = pre match { + case ThisType(pclazz) => + (pclazz eq owner) || + (this is Protected) && pclazz.isNonBottomSubClass(owner) + case _ => false + } + + /** Is protected access to target symbol permitted? */ + def isProtectedAccessOK = { + def fail(diagnostics: () => String): Boolean = { + ctx match { + case ctx: DiagnosticsContext => ctx.diagnostics = diagnostics + case _ => + } + false + } + val cls = owner.enclosingSubClass + if (!cls.exists) + fail(() => + s"""Access to protected $this not permitted because + |enclosing ${ctx.enclClass.owner.showLocated} is not a subclass of + |${owner.showLocated} where target is defined""".stripMargin) + else if (!(isType || // allow accesses to types from arbitrary subclasses fixes #4737 + pre.widen.typeSymbol.isSubClassOrCompanion(cls) || + cls.isModuleClass && + pre.widen.typeSymbol.isSubClassOrCompanion(cls.linkedClass))) + fail(() => + s"""Access to protected $show not permitted because + |prefix type ${pre.widen.show} does not conform to + |${cls.showLocated} where the access takes place""".stripMargin) + else true + } + + (pre == NoPrefix) || { + val boundary = accessBoundary(owner) + + ( (boundary.isTerm + || (boundary eq defn.RootClass)) + || (accessWithin(boundary) || accessWithinLinked(boundary)) && + ( !(this is Local) + || (owner is ImplClass) // allow private local accesses to impl class members + || isCorrectThisType(pre) + ) + || (this is Protected) && + ( superAccess + || pre.isInstanceOf[ThisType] + || ctx.phase.erasedTypes + || isProtectedAccessOK + ) + ) + } + } + + def isNonValueClass(implicit ctx: Context): Boolean = + isClass && !isSubClass(defn.AnyValClass) + + def show(implicit ctx: Context): String = ??? + def showLocated(implicit ctx: Context): String = ??? } class CompleteSymDenotation( @@ -133,7 +347,7 @@ object SymDenotations { } } - abstract class ClassDenotation(initFlags: FlagSet)(implicit ctx: Context) + abstract class ClassDenotation(initFlags: FlagSet, assocFile: AbstractFile)(implicit ctx: Context) extends SymDenotation(initFlags) { import NameFilter._ import util.LRU8Cache @@ -148,6 +362,8 @@ object SymDenotations { val info = ClassInfo(owner.thisType, this) + override def associatedFile(implicit ctx: Context): AbstractFile = assocFile + private var memberCacheVar: LRU8Cache[Name, DenotationSet] = null private def memberCache: LRU8Cache[Name, DenotationSet] = { @@ -220,10 +436,15 @@ object SymDenotations { baseClassesVar } - /** Is this class a subclass of `clazz`? */ - final def isSubClass(clazz: ClassSymbol)(implicit ctx: Context): Boolean = { - superClassBits contains clazz.superId - } + final override def isNonBottomSubClass(cls: Symbol)(implicit ctx: Context): Boolean = + (symbol eq cls) || + (superClassBits contains cls.superId) || + (this is Erroneous) || + (cls is Erroneous) && cls.isClass + + final override def isSubClass(cls: Symbol)(implicit ctx: Context) = + isNonBottomSubClass(cls) || + cls.isClass && ((symbol eq defn.NothingClass) || (symbol eq defn.NullClass)) private var definedFingerPrintCache: FingerPrint = null @@ -281,17 +502,17 @@ object SymDenotations { } final def membersNamed(name: Name)(implicit ctx: Context): DenotationSet = { - var refs: DenotationSet = memberCache lookup name - if (refs == null) { + var denots: DenotationSet = memberCache lookup name + if (denots == null) { if (containsName(definedFingerPrint, name)) { val ownDenots = decls.denotsNamed(name) - refs = ownDenots + denots = ownDenots var ps = parents while (ps.nonEmpty) { val parentSym = ps.head.typeSymbol parentSym.denot match { case parentd: ClassDenotation => - refs = refs union + denots = denots union parentd.membersNamed(name) .filterExcluded(Flags.Private) .asSeenFrom(thisType, parentSym) @@ -300,11 +521,11 @@ object SymDenotations { } } } else { - refs = NoDenotation + denots = NoDenotation } - memberCache enter (name, refs) + memberCache enter (name, denots) } - refs + denots } private var baseTypeCache: java.util.HashMap[CachedType, Type] = null @@ -374,15 +595,17 @@ object SymDenotations { initFlags: FlagSet, val typeParams: List[TypeSymbol], val parents: List[Type], - val decls: Scope - )(implicit ctx: Context) extends ClassDenotation(initFlags) + val decls: Scope, + assocFile: AbstractFile = null + )(implicit ctx: Context) extends ClassDenotation(initFlags, assocFile) abstract class LazyClassDenotation( val symbol: ClassSymbol, val owner: Symbol, val name: Name, - initFlags: FlagSet - )(implicit ctx: Context) extends ClassDenotation(initFlags) with LazyCompletion { + initFlags: FlagSet, + assocFile: AbstractFile = null + )(implicit ctx: Context) extends ClassDenotation(initFlags, assocFile) with LazyCompletion { protected var _typeParams: List[TypeSymbol] = null protected var _parents: List[Type] = null diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 9c8738527..decdb6c84 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -13,13 +13,14 @@ import SymDenotations._ import Types._, Annotations._ import Denotations.{Denotation, SingleDenotation, MultiDenotation} import collection.mutable +import reflect.io.AbstractFile object Symbols { /** A Symbol represents a Scala definition/declaration or a package. */ - abstract class Symbol { + abstract class Symbol(denotf: Symbol => SymDenotation) { /** Is symbol different from NoSymbol? */ def exists = true @@ -27,82 +28,156 @@ object Symbols { /** This symbol, if it exists, otherwise the result of evaluating `that` */ def orElse(that: => Symbol) = if (exists) this else that - /** Set the denotation of this symbol. - */ - def setDenotation(denot: SymDenotation) = - lastDenot = denot + def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol /** The last denotation of this symbol */ - protected[this] var lastDenot: SymDenotation = null + private[this] var lastDenot: SymDenotation = denotf(this) - /** Load denotation of this symbol */ - protected def loadDenot(implicit ctx: Context): SymDenotation + final def denot(implicit ctx: Context): SymDenotation = { + var denot = lastDenot + if (!(denot.validFor contains ctx.period)) denot = denot.current.asInstanceOf[SymDenotation] + denot + } - /** The denotation of this symbol + def isType: Boolean = false + def isTerm: Boolean = false + def isClass: Boolean = false + + /** Special case tests for flags that are known a-priori and do not need loading + * flags. */ - def denot(implicit ctx: Context): SymDenotation = { - val denot = lastDenot - if (denot == null) loadDenot - else { - val currentPeriod = ctx.period - val valid = denot.validFor - if (valid contains currentPeriod) denot - else if (valid.runId != currentPeriod.runId) reloadDenot - else denot.current.asSymDenotation - } - } + def isModule(implicit ctx: Context) = denot.isModule + def isModuleObj(implicit ctx: Context) = denot.isModuleObj + def isModuleClass(implicit ctx: Context) = denot.isModuleClass + def isPackage(implicit ctx: Context) = denot.isPackage + def isPackageObj(implicit ctx: Context) = denot.isPackageObj + def isPackageClass(implicit ctx: Context) = denot.isPackageClass + + /** A unique, densely packed integer tag for each class symbol, -1 + * for all other symbols. To save memory, this method + * should be called only if class is a super class of some other class. + */ + def superId: Int = -1 + +// --------- Forwarders for sym methods -------------------------- + + /** The current owner of this symbol */ + final def owner(implicit ctx: Context): Symbol = denot.owner - /** - * Get loaded denotation if lastDenot points to a denotation from - * a different run. !!! needed? + /** The current name of this symbol */ + final def name(implicit ctx: Context): Name = denot.name + + /** The current type info of this symbol */ + final def info(implicit ctx: Context): Type = denot.info + + /** The current flag set of this symbol */ + final def flags(implicit ctx: Context): FlagSet = denot.flags + + /** The current privateWithin boundary of this symbol, NoSymbol if no boundary is given. */ + final def privateWithin(implicit ctx: Context): Symbol = denot.privateWithin + + /** The current annotations of this symbol */ + final def annotations(implicit ctx: Context): List[Annotation] = denot.annotations + + /** Does this symbol have an annotation matching the given class symbol? */ + final def hasAnnotation(cls: Symbol)(implicit ctx: Context): Boolean = denot.hasAnnotation(cls) + + /** The chain of owners of this symbol, starting with the symbol itself */ + final def ownersIterator(implicit ctx: Context): Iterator[Symbol] = denot.ownersIterator + + /** Same as `ownersIterator contains sym` but more efficient. */ + final def hasTransOwner(sym: Symbol)(implicit ctx: Context): Boolean = denot.hasTransOwner(sym) + + /** The top-level class containing this symbol, except for a toplevel module + * its module class */ - private def reloadDenot(implicit ctx: Context): SymDenotation = { - val initDenot = lastDenot.initial.asSymDenotation - val newSym: Symbol = - ctx.atPhase(FirstPhaseId) { implicit ctx => - initDenot.owner.info.decl(initDenot.name) - .atSignature(denot.signature).symbol - } - if (newSym eq this) { // no change, change validity - var d = initDenot - do { - d.validFor = Period(ctx.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId) - d = d.nextInRun.asSymDenotation - } while (d ne initDenot) - } - newSym.denot - } + def topLevelClass(implicit ctx: Context): Symbol = denot.topLevelClass + + /** The package containing this symbol */ + def enclosingPackage(implicit ctx: Context): Symbol = denot.enclosingPackage + + final def associatedFile(implicit ctx: Context): AbstractFile = denot.associatedFile + final def binaryFile(implicit ctx: Context): AbstractFile = denot.binaryFile + final def sourceFile(implicit ctx: Context): AbstractFile = denot.sourceFile + + final def companionClass(implicit ctx: Context): Symbol = denot.companionClass + + final def companionModule(implicit ctx: Context): Symbol = denot.companionModule + + final def linkedClass(implicit ctx: Context): Symbol = denot.linkedClass + + /** Is this symbol a subclass of the given class? */ + final def isSubClass(cls: Symbol)(implicit ctx: Context): Boolean = denot.isSubClass(cls) + + /** Is this class symbol a subclass of `cls`, + * and is this class symbol also different from Null or Nothing? + */ + final def isNonBottomSubClass(cls: Symbol)(implicit ctx: Context): Boolean = denot.isNonBottomSubClass(cls) + + /** Is this symbol a subclass of `base` or a companion object of such a subclass? */ + final def isSubClassOrCompanion(base: Symbol)(implicit ctx: Context): Boolean = denot.isSubClassOrCompanion(base) + + /** The class that encloses the owner of the current context + * and that is a subclass of this class. + */ + final def enclosingSubClass(implicit ctx: Context) = denot.enclosingSubClass + + ///** Is this symbol a proper subclass of the given class? */ + //def isProperSubClass(cls: ClassSymbol)(implicit ctx: Context): Boolean = (this ne cls) && this.isSubClass(cls) + + /** The non-private symbol whose type matches the type of this symbol + * in in given class. + * + * @param inClass The class containing the symbol's definition + * @param site The base type from which member types are computed + */ + final def matchingSymbol(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = denot.matchingSymbol(inClass, site) + + /** The symbol, in class `inClass`, that is overridden by this symbol. */ + final def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol = denot.overriddenSymbol(inClass) - def isType: Boolean - def isTerm = !isType + /** All symbols overriden by this symbol. */ + final def allOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] = denot.allOverriddenSymbols + /** The class or term symbol up to which this symbol is accessible, + * or RootClass if it is public. As java protected statics are + * otherwise completely inaccessible in scala, they are treated + * as public. + * @param base + */ + final def accessBoundary(base: Symbol)(implicit ctx: Context): Symbol = denot.accessBoundary(base) + /** Is this symbol contained in `boundary`? */ + final def isContainedIn(boundary: Symbol)(implicit ctx: Context): Boolean = denot.isContainedIn(boundary) - // forwarders for sym methods - def owner(implicit ctx: Context): Symbol = denot.owner - def name(implicit ctx: Context): Name = denot.name - def flags(implicit ctx: Context): FlagSet = denot.flags - def info(implicit ctx: Context): Type = denot.info + /** Is this symbol accessible whenever `that` symbol is accessible? + * Does not take into account status of protected members. + */ + final def isAsAccessibleAs(that: Symbol)(implicit ctx: Context): Boolean = denot.isAsAccessibleAs(that) + + /** Is this symbol a non-value class? */ + final def isNonValueClass(implicit ctx: Context): Boolean = denot.isNonValueClass + + /** Is this symbol accessible as a member of tree with type `pre`? + * @param pre The type of the tree from which the selection is made + * @param superAccess Access is via super + */ + final def isAccessibleFrom(pre: Type, superAccess: Boolean = false)(implicit ctx: Context): Boolean = denot.isAccessibleFrom(pre, superAccess) + + def show(implicit ctx: Context): String = ctx.printer.show(this) + def showLocated(implicit ctx: Context): String = ctx.printer.showLocated(this) + def showDef(implicit ctx: Context): String = ctx.printer.showDef(this) - def prefix(implicit ctx: Context) = owner.thisType - def allOverriddenSymbols: Iterator[Symbol] = ??? - def isAsAccessibleAs(other: Symbol): Boolean = ??? - def isAccessibleFrom(pre: Type)(implicit ctx: Context): Boolean = ??? - def locationString: String = ??? - def locatedFullString: String = ??? - def defString: String = ??? def typeParams: List[TypeSymbol] = ??? def unsafeTypeParams: List[TypeSymbol] = ??? def thisType: Type = ??? def isStaticMono = isStatic && typeParams.isEmpty - def isPackageClass: Boolean = ??? def isRoot: Boolean = ??? def moduleClass: Symbol = ??? def cloneSymbol: Symbol = ??? def hasAnnotation(ann: Annotation): Boolean = ??? def hasAnnotation(ann: ClassSymbol): Boolean = ??? - def asTerm: TermSymbol = ??? def asType: TypeSymbol = ??? def asClass: ClassSymbol = ??? @@ -116,91 +191,24 @@ object Symbols { def isConcrete = !isDeferred def isJava: Boolean = ??? - def isSubClass(that: Symbol): Boolean = ??? - def isNonBottomSubClass(that: Symbol): Boolean = ??? - def isProperSubClass(that: Symbol): Boolean = - (this ne that) && (this isSubClass that) - - def privateWithin(implicit ctx: Context): Symbol = denot.privateWithin def isAbstractType: Boolean = ??? def newAbstractType(name: TypeName, info: TypeBounds): TypeSymbol = ??? def newAbstractTerm(name: TermName, tpe: Type): TypeSymbol = ??? - def isClass: Boolean = false - def isMethod(implicit ctx: Context): Boolean = denot.isMethod - def hasFlag(required: FlagSet)(implicit ctx: Context): Boolean = (flags & required) != Flags.Empty - def hasAllFlags(required: FlagSet)(implicit ctx: Context): Boolean = (flags & required) == flags - - /** The non-private symbol whose type matches the type of this symbol - * in in given class. - * - * @param ofClass The class containing the symbol's definition - * @param site The base type from which member types are computed - */ - final def matchingSymbol(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = { - var ref = inClass.info.nonPrivateDecl(name) - if (ref.isTerm) { - val targetType = site.memberInfo(this) - if (ref.isOverloaded) ref = ref.atSignature(targetType.signature) - val candidate = ref.symbol - if (site.memberInfo(candidate) matches targetType) candidate - else NoSymbol - } else ref.symbol - } - - def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol = - if (owner isSubClass inClass) matchingSymbol(inClass, owner.thisType) - else NoSymbol + //def isMethod(implicit ctx: Context): Boolean = denot.isMethod - def isStable(implicit ctx: Context): Boolean = false + def isStable(implicit ctx: Context): Boolean = denot.isStable - /** The class or term symbol up to which this symbol is accessible, - * or RootClass if it is public. As java protected statics are - * otherwise completely inaccessible in scala, they are treated - * as public. - * @param base - */ - def accessBoundary(base: Symbol)(implicit ctx: Context): Symbol = { - val denot = this.denot - val fs = denot.flags - if (fs is PrivateOrLocal) owner - else if (fs is StaticProtected) defn.RootClass - else if (denot.privateWithin.exists && !ctx.phase.erasedTypes) denot.privateWithin - else if (fs is Protected) base - else defn.RootClass - } - - /** Is this symbol contained in `boundary`? */ - def isContainedIn(boundary: Symbol)(implicit ctx: Context): Boolean = - if (this eq boundary) true - else if (!this.exists || - (this is PackageClass) && !(boundary is PackageClass)) false - else owner.isContainedIn(boundary) - - /** Is this symbol accessible whenever `that` symbol is accessible? - * Does not take into account status of protected members. - */ - def isAsAccessible(that: Symbol)(implicit ctx: Context): Boolean = - (that.accessBoundary(NoSymbol) isContainedIn this.accessBoundary(NoSymbol)) && - this.isStable || !that.isStable - - def containsNull(implicit ctx: Context): Boolean = - isClass && !(isSubClass(defn.AnyValClass)) } - abstract class TermSymbol extends Symbol { + abstract class TermSymbol(denotf: Symbol => SymDenotation) extends Symbol(denotf) { def name: TermName - def isType = true - - override def isStable(implicit ctx: Context) = !( - this.is(UnstableValue, butNot = Stable) || - info.isVolatile && !hasAnnotation(defn.uncheckedStableClass) - ) + override def isTerm = true } - abstract class TypeSymbol extends Symbol { + abstract class TypeSymbol(denotf: Symbol => SymDenotation) extends Symbol(denotf) { def name: TypeName - def isType = false + override def isType = true def variance: Int = ??? @@ -208,23 +216,20 @@ object Symbols { def typeTemplate(implicit ctx: Context): Type = ??? } - abstract class ClassSymbol extends TypeSymbol { + abstract class ClassSymbol(denotf: Symbol => ClassDenotation) extends TypeSymbol(denotf) { override def isClass = true private var superIdHint: Int = -1 - override def denot(implicit ctx: Context): ClassDenotation = - super.denot.asInstanceOf[ClassDenotation] + final def classDenot(implicit ctx: Context): ClassDenotation = + denot.asInstanceOf[ClassDenotation] def typeOfThis(implicit ctx: Context): Type = ??? - def baseClasses(implicit ctx: Context): List[ClassSymbol] = denot.baseClasses + def baseClasses(implicit ctx: Context): List[ClassSymbol] = classDenot.baseClasses - override def typeConstructor(implicit ctx: Context): Type = denot.typeConstructor - override def typeTemplate(implicit ctx: Context): Type = denot.typeTemplate + override def typeConstructor(implicit ctx: Context): Type = classDenot.typeConstructor + override def typeTemplate(implicit ctx: Context): Type = classDenot.typeTemplate - /** The unique, densely packed identifier of this class symbol. Should be called - * only if class is a super class of some other class. - */ def superId(implicit ctx: Context): Int = { val hint = superIdHint val rctx = ctx.root @@ -245,11 +250,13 @@ object Symbols { } } - object NoSymbol extends Symbol { - def loadDenot(implicit ctx: Context): SymDenotation = NoDenotation + class ErrorSymbol(underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(sym => underlying.denot) { + override def isType = underlying.isType + override def isTerm = underlying.isTerm + } + + object NoSymbol extends Symbol(sym => NoDenotation) { override def exists = false - def isType = false - override def isTerm = false } implicit def defn(implicit ctx: Context): Definitions = ctx.root.definitions diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 8b4952489..8fb3d69a0 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -31,7 +31,7 @@ trait TypeOps { this: Context => ErrorType // don't be overzealous with throwing exceptions, see #2641 else throw new Error( - s"something is wrong (wrong class file?): ${tparam.locationString} cannot be instantiated from ${pre.widen}") + s"something is wrong (wrong class file?): ${tparam.showLocated} cannot be instantiated from ${pre.widen.show}") def prefixMatches = pre.typeSymbol isNonBottomSubClass tparamOwner diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index dc8c7c9f1..624720d50 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -3,7 +3,7 @@ package core import util.HashSet import Symbols._ -import SubTypers._ +import TypeComparers._ import Flags._ import Names._ import Scopes._ @@ -314,13 +314,13 @@ object Types { /** Is this type a subtype of that type? */ final def <:<(that: Type)(implicit ctx: Context): Boolean = - ctx.subTyper.isSubType(this, that) + ctx.typeComparer.isSubType(this, that) /** Is this type the same as that type? * This is the case iff `this <:< that` and `that <:< this`. */ final def =:=(that: Type)(implicit ctx: Context): Boolean = - ctx.subTyper.isSameType(this, that) + ctx.typeComparer.isSameType(this, that) /** Is this type close enough to that type so that members * with the two type would override each other? @@ -335,15 +335,15 @@ object Types { * poly types. */ def matches(that: Type)(implicit ctx: Context): Boolean = - ctx.subTyper.matchesType(this, that, !ctx.phase.erasedTypes) + ctx.typeComparer.matchesType(this, that, !ctx.phase.erasedTypes) /** Does this type match that type * */ /** The info of `sym`, seen as a member of this type. */ - final def memberInfo(sym: Symbol)(implicit ctx: Context): Type = { - sym.info.asSeenFrom(this, sym.owner) + final def memberInfo(denot: SymDenotation)(implicit ctx: Context): Type = { + denot.info.asSeenFrom(this, denot.owner) } /** Widen from singleton type to its underlying non-singleton @@ -447,7 +447,9 @@ object Types { def |(that: Type)(implicit ctx: Context): Type = ctx.lub(this, that) - // hashing + def show(implicit ctx: Context): String = ctx.printer.show(this) + +// ----- hashing ------------------------------------------------------ /** customized hash code of this type. * NotCached for uncached types. Cached types @@ -978,15 +980,15 @@ object Types { // ----- AnnotatedTypes ----------------------------------------------------------- - case class AnnotatedType(annots: List[AnnotationInfo], tpe: Type) extends UncachedProxyType { + case class AnnotatedType(annots: List[Annotation], tpe: Type) extends UncachedProxyType { override def underlying(implicit ctx: Context): Type = tpe - def derivedAnnotatedType(annots1: List[AnnotationInfo], tpe1: Type) = + def derivedAnnotatedType(annots1: List[Annotation], tpe1: Type) = if ((annots1 eq annots) && (tpe1 eq tpe)) this else AnnotatedType.make(annots1, tpe1) } object AnnotatedType { - def make(annots: List[AnnotationInfo], underlying: Type) = + def make(annots: List[Annotation], underlying: Type) = if (annots.isEmpty) underlying else AnnotatedType(annots, underlying) } @@ -1060,7 +1062,7 @@ object Types { tp } - def mapOverAnnotations(annots: List[AnnotationInfo]): List[AnnotationInfo] = ??? + def mapOverAnnotations(annots: List[Annotation]): List[Annotation] = ??? } @@ -1090,7 +1092,7 @@ object Types { abstract class TypeAccumulator[T] extends ((T, Type) => T) { def apply(x: T, tp: Type): T - def apply(x: T, annot: AnnotationInfo): T = ??? + def apply(x: T, annot: Annotation): T = ??? def foldOver(x: T, tp: Type): T = tp match { case tp: NamedType => -- cgit v1.2.3 From c215dbb2870a748ad7d3f2285c561cf452848c92 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 27 Jan 2013 09:12:40 +0100 Subject: More eliminations of AppliedType --- src/dotty/tools/dotc/core/Substituters.scala | 199 +++++++++++++------------ src/dotty/tools/dotc/core/SymDenotations.scala | 8 +- src/dotty/tools/dotc/core/TypeOps.scala | 81 ++++------ src/dotty/tools/dotc/core/Types.scala | 178 +++++++++++++--------- 4 files changed, 241 insertions(+), 225 deletions(-) (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala') diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala index 471718f63..c6547f77d 100644 --- a/src/dotty/tools/dotc/core/Substituters.scala +++ b/src/dotty/tools/dotc/core/Substituters.scala @@ -7,46 +7,30 @@ import Types._, Symbols._, Contexts._ */ trait Substituters { this: Context => - final def subst(tp: Type, from: PolyType, to: PolyType, map: SubstPolyMap = null): Type = + final def subst(tp: Type, from: BindingType, to: BindingType, map: SubstBindingMap): Type = tp match { - case tp @ PolyParam(pt, n) => - if (pt eq from) PolyParam(to, n) else tp + case tp: BoundType => + if (tp.binder eq from) tp.copy(to.asInstanceOf[tp.BT]) else tp case tp: NamedType => if (tp.symbol.isStatic) tp else tp.derivedNamedType(subst(tp.prefix, from, to, map), tp.name) - case ThisType(_) - | MethodParam(_, _) - | NoPrefix => tp + case _: ThisType | NoPrefix => + tp + case tp: RefinedType1 => + tp.derivedRefinedType1( + subst(tp.parent, from, to, map), + tp.name1, + subst(tp.info1, from, to, map)) + case tp: RefinedType2 => + tp.derivedRefinedType2( + subst(tp.parent, from, to, map), + tp.name1, + subst(tp.info1, from, to, map), + tp.name2, + subst(tp.info2, from, to, map)) case _ => - val substMap = if (map != null) map else new SubstPolyMap(from, to) - tp match { - case tp: AppliedType => - tp.derivedAppliedType( - substMap(tp.tycon), tp.typeArgs mapConserve substMap) - case _ => - substMap mapOver tp - } - } - - final def subst(tp: Type, from: MethodType, to: MethodType, map: SubstMethodMap): Type = - tp match { - case tp @ MethodParam(mt, n) => - if (mt eq from) MethodParam(to, n) else tp - case tp: NamedType => - if (tp.symbol.isStatic) tp - else tp.derivedNamedType(subst(tp.prefix, from, to, map), tp.name) - case ThisType(_) - | PolyParam(_, _) - | NoPrefix => tp - case _ => - val substMap = if (map != null) map else new SubstMethodMap(from, to) - tp match { - case tp: AppliedType => - tp.derivedAppliedType( - substMap(tp.tycon), tp.typeArgs mapConserve substMap) - case _ => - substMap mapOver tp - } + (if (map != null) map else new SubstBindingMap(from, to)) + .mapOver(tp) } final def subst1(tp: Type, from: Symbol, to: Type, map: Subst1Map): Type = { @@ -59,19 +43,23 @@ trait Substituters { this: Context => } if (sym.isStatic) tp else tp.derivedNamedType(subst1(tp.prefix, from, to, map), tp.name) - case ThisType(_) - | MethodParam(_, _) - | PolyParam(_, _) - | NoPrefix => tp + case _: ThisType | _: BoundType | NoPrefix => + tp + case tp: RefinedType1 => + tp.derivedRefinedType1( + subst1(tp.parent, from, to, map), + tp.name1, + subst1(tp.info1, from, to, map)) + case tp: RefinedType2 => + tp.derivedRefinedType2( + subst1(tp.parent, from, to, map), + tp.name1, + subst1(tp.info1, from, to, map), + tp.name2, + subst1 (tp.info2, from, to, map)) case _ => - val substMap = if (map != null) map else new Subst1Map(from, to) - tp match { - case tp: AppliedType => - tp.derivedAppliedType( - substMap(tp.tycon), tp.typeArgs mapConserve substMap) - case _ => - substMap mapOver tp - } + (if (map != null) map else new Subst1Map(from, to)) + .mapOver(tp) } } @@ -87,19 +75,23 @@ trait Substituters { this: Context => } if (sym.isStatic) tp else tp.derivedNamedType(subst2(tp.prefix, from1, to1, from2, to2, map), tp.name) - case ThisType(_) - | MethodParam(_, _) - | PolyParam(_, _) - | NoPrefix => tp + case _: ThisType | _: BoundType | NoPrefix => + tp + case tp: RefinedType1 => + tp.derivedRefinedType1( + subst2(tp.parent, from1, to1, from2, to2, map), + tp.name1, + subst2(tp.info1, from1, to1, from2, to2, map)) + case tp: RefinedType2 => + tp.derivedRefinedType2( + subst2(tp.parent, from1, to1, from2, to2, map), + tp.name1, + subst2(tp.info1, from1, to1, from2, to2, map), + tp.name2, + subst2(tp.info2, from1, to1, from2, to2, map)) case _ => - val substMap = if (map != null) map else new Subst2Map(from1, to1, from2, to2) - tp match { - case tp: AppliedType => - tp.derivedAppliedType( - substMap(tp.tycon), tp.typeArgs mapConserve substMap) - case _ => - substMap mapOver tp - } + (if (map != null) map else new Subst2Map(from1, to1, from2, to2)) + .mapOver(tp) } } @@ -119,19 +111,23 @@ trait Substituters { this: Context => } if (sym.isStatic) tp else tp.derivedNamedType(subst(tp.prefix, from, to, map), tp.name) - case ThisType(_) - | MethodParam(_, _) - | PolyParam(_, _) - | NoPrefix => tp + case _: ThisType | _: BoundType | NoPrefix => + tp + case tp: RefinedType1 => + tp.derivedRefinedType1( + subst(tp.parent, from, to, map), + tp.name1, + subst(tp.info1, from, to, map)) + case tp: RefinedType2 => + tp.derivedRefinedType2( + subst(tp.parent, from, to, map), + tp.name1, + subst(tp.info1, from, to, map), + tp.name2, + subst(tp.info2, from, to, map)) case _ => - val substMap = if (map != null) map else new SubstMap(from, to) - tp match { - case tp: AppliedType => - tp.derivedAppliedType( - substMap(tp.tycon), tp.typeArgs mapConserve substMap) - case _ => - substMap mapOver tp - } + (if (map != null) map else new SubstMap(from, to)) + .mapOver(tp) } } @@ -142,18 +138,23 @@ trait Substituters { this: Context => case tp: NamedType => if (tp.symbol.isStatic) tp else tp.derivedNamedType(substThis(tp.prefix, from, to, map), tp.name) - case MethodParam(_, _) - | PolyParam(_, _) - | NoPrefix => tp + case _: BoundType | NoPrefix => + tp + case tp: RefinedType1 => + tp.derivedRefinedType1( + substThis(tp.parent, from, to, map), + tp.name1, + substThis(tp.info1, from, to, map)) + case tp: RefinedType2 => + tp.derivedRefinedType2( + substThis(tp.parent, from, to, map), + tp.name1, + substThis(tp.info1, from, to, map), + tp.name2, + substThis(tp.info2, from, to, map)) case _ => - val substMap = if (map != null) map else new SubstThisMap(from, to) - tp match { - case tp: AppliedType => - tp.derivedAppliedType( - substMap(tp.tycon), tp.typeArgs mapConserve substMap) - case _ => - substMap mapOver tp - } + (if (map != null) map else new SubstThisMap(from, to)) + .mapOver(tp) } final def substThis(tp: Type, from: RefinedType, to: Type, map: SubstRefinedThisMap): Type = @@ -163,26 +164,26 @@ trait Substituters { this: Context => case tp: NamedType => if (tp.symbol.isStatic) tp else tp.derivedNamedType(substThis(tp.prefix, from, to, map), tp.name) - case ThisType(_) - | MethodParam(_, _) - | PolyParam(_, _) - | NoPrefix => tp + case _: ThisType | _: BoundType | NoPrefix => + tp + case tp: RefinedType1 => + tp.derivedRefinedType1( + substThis(tp.parent, from, to, map), + tp.name1, + substThis(tp.info1, from, to, map)) + case tp: RefinedType2 => + tp.derivedRefinedType2( + substThis(tp.parent, from, to, map), + tp.name1, + substThis(tp.info1, from, to, map), + tp.name2, + substThis(tp.info2, from, to, map)) case _ => - val substMap = if (map != null) map else new SubstRefinedThisMap(from, to) - tp match { - case tp: AppliedType => - tp.derivedAppliedType( - substMap(tp.tycon), tp.typeArgs mapConserve substMap) - case _ => - substMap mapOver tp - } + (if (map != null) map else new SubstRefinedThisMap(from, to)) + .mapOver(tp) } - final class SubstPolyMap(from: PolyType, to: PolyType) extends TypeMap { - def apply(tp: Type) = subst(tp, from, to, this) - } - - final class SubstMethodMap(from: MethodType, to: MethodType) extends TypeMap { + final class SubstBindingMap(from: BindingType, to: BindingType) extends TypeMap { def apply(tp: Type) = subst(tp, from, to, this) } diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 9df52470b..a9da9806e 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -356,7 +356,7 @@ object SymDenotations { def typeParams: List[TypeSymbol] - def parents: List[Type] + def parents: List[TypeRef] def decls: Scope @@ -594,7 +594,7 @@ object SymDenotations { val name: Name, initFlags: FlagSet, val typeParams: List[TypeSymbol], - val parents: List[Type], + val parents: List[TypeRef], val decls: Scope, assocFile: AbstractFile = null )(implicit ctx: Context) extends ClassDenotation(initFlags, assocFile) @@ -608,7 +608,7 @@ object SymDenotations { )(implicit ctx: Context) extends ClassDenotation(initFlags, assocFile) with LazyCompletion { protected var _typeParams: List[TypeSymbol] = null - protected var _parents: List[Type] = null + protected var _parents: List[TypeRef] = null protected var _decls: Scope = null final def typeParams: List[TypeSymbol] = { @@ -616,7 +616,7 @@ object SymDenotations { if (tparams != null) tparams else { tryLoad(); typeParams } } - final def parents: List[Type] = { + final def parents: List[TypeRef] = { val ps = _parents if (ps != null) ps else { tryComplete(); parents } } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 558d34f52..08d7c0cd6 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -21,61 +21,44 @@ trait TypeOps { this: Context => else toPrefix(pre.baseType(clazz).normalizedPrefix, clazz.owner, thisclazz) - def toInstance(pre: Type, clazz: Symbol, tparam: Symbol): Type = { - if (skipPrefixOf(pre, clazz)) tp - else { - val tparamOwner = tparam.owner - - def throwError = - if (tparamOwner.info.parents exists (_.isErroneous)) - ErrorType // don't be overzealous with throwing exceptions, see #2641 - else - throw new Error( - s"something is wrong (wrong class file?): ${tparam.showLocated} cannot be instantiated from ${pre.widen.show}") - - def prefixMatches = pre.typeSymbol isNonBottomSubClass tparamOwner - - val basePre = pre.baseType(clazz) - - def instParamFrom(typeInst: Type): Type = typeInst match { - case ConstantType(_) => - // have to deconst because it may be a Class[T]. - instParamFrom(typeInst.deconst) - case AppliedType(tycon, baseArgs) => - instParam(tycon.typeParams, baseArgs) - case _ => - throwError - } - - def instParam(ps: List[Symbol], as: List[Type]): Type = - if (as.isEmpty) tp - else if (ps.isEmpty) throwError - else if (tparam eq ps.head) - if (as.head.exists) as.head else tp - else instParam(ps.tail, as.tail) - - if (tparamOwner == clazz && prefixMatches) instParamFrom(basePre) - else toInstance(basePre.normalizedPrefix, clazz.owner, tparam) - } - } - tp match { case tp: NamedType => val sym = tp.symbol - if (tp.symbol.isTypeParameter) toInstance(pre, clazz, sym) - else if (sym.isStatic) tp - else tp.derivedNamedType(asSeenFrom(tp.prefix, pre, clazz, theMap), tp.name) + if (sym.isStatic) tp + else { + val pre0 = tp.prefix + val pre1 = asSeenFrom(pre0, pre, clazz, theMap) + if (pre1 eq pre0) tp + else { + val tp1 = NamedType(pre1, tp.name) + if (sym.isTypeParameter) { + // short-circuit instantiated type parameters + // by replacing pre.tp with its alias, if it has one. + val tp2 = tp1.info + if (tp2.isAliasTypeBounds) return tp2.bounds.hi + } + tp1 + } + } case ThisType(thisclazz) => toPrefix(pre, clazz, thisclazz) + case _: BoundType | NoPrefix => + tp + case tp: RefinedType1 => + tp.derivedRefinedType1( + asSeenFrom(tp.parent, pre, clazz, theMap), + tp.name1, + asSeenFrom(tp.info1, pre, clazz, theMap)) + case tp: RefinedType2 => + tp.derivedRefinedType2( + asSeenFrom(tp.parent, pre, clazz, theMap), + tp.name1, + asSeenFrom(tp.info1, pre, clazz, theMap), + tp.name2, + asSeenFrom(tp.info2, pre, clazz, theMap)) case _ => - val asSeenFromMap = if (theMap != null) theMap else new AsSeenFromMap(pre, clazz) - tp match { - case tp: AppliedType => - tp.derivedAppliedType( - asSeenFromMap(tp.tycon), tp.targs mapConserve asSeenFromMap) - case _ => - asSeenFromMap mapOver tp - } + (if (theMap != null) theMap else new AsSeenFromMap(pre, clazz)) + .mapOver(tp) } } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index a45ea7596..b0d5695c7 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -44,7 +44,6 @@ object Types { * | +- ExprType * | +- AnnotatedType * +- GroundType -+- PolyParam - * +- AppliedType * +- RefinedType * +- AndType * +- OrType @@ -139,6 +138,14 @@ object Types { case _ => false } + /** Is this type a TypeBounds instance, with lower and upper bounds + * that are identical? + */ + final def isAliasTypeBounds: Boolean = this match { + case tp: TypeBounds => tp.lo eq tp.hi + case _ => false + } + /** This type seen as a TypeBounds */ final def bounds(implicit ctx: Context): TypeBounds = this match { case tp: TypeBounds => tp @@ -195,42 +202,41 @@ object Types { /** Substitute all types of the form `PolyParam(from, N)` by * `PolyParam(to, N)`. */ - final def subst(from: PolyType, to: PolyType)(implicit ctx: Context): Type = + final def subst(from: BindingType, to: BindingType)(implicit ctx: Context): Type = ctx.subst(this, from, to, null) - /** Substitute all types of the form `MethodParam(from, N)` by - * `MethodParam(to, N)`. - */ - final def subst(from: MethodType, to: MethodType)(implicit ctx: Context): Type = - if (from.isDependent) ctx.subst(this, from, to, null) - else this - /** Substitute all occurrences of `This(clazz)` by `tp` */ final def substThis(clazz: ClassSymbol, tp: Type)(implicit ctx: Context): Type = ctx.substThis(this, clazz, tp, null) - /** Substitute all occurrences of `RefinedThis(from)` by `tp` */ - final def substThis(from: RefinedType, tp: Type)(implicit ctx: Context): Type = - ctx.substThis(this, from, tp, null) + /** Substitute all occurrences of `RefinedThis(rt)` by `tp` */ + final def substThis(rt: RefinedType, tp: Type)(implicit ctx: Context): Type = + ctx.substThis(this, rt, tp, null) /** For a ClassInfo type, its parents, - * For an AndType, its operands, - * For an applied type, the instantiated parents of its base type. * Inherited by all type proxies. Empty for all other types. * Overwritten in ClassInfo, where parents is cached. */ - def parents(implicit ctx: Context): List[Type] = this match { - case tp: AppliedType => - val tycon = tp.tycon - tycon.parents.mapConserve(_.subst(tycon.typeParams, tp.targs)) + def parents(implicit ctx: Context): List[TypeRef] = this match { + case tp: TypeProxy => + tp.underlying.parents + case _ => List() + } + + /** The elements of an AndType or OrType */ + def factors(implicit ctx: Context): List[Type] = this match { case tp: AndType => def components(tp: Type): List[Type] = tp match { case AndType(tp1, tp2) => components(tp1) ++ components(tp2) case _ => List(tp) } components(tp) - case tp: TypeProxy => - tp.underlying.parents + case tp: OrType => + def components(tp: Type): List[Type] = tp match { + case OrType(tp1, tp2) => components(tp1) ++ components(tp2) + case _ => List(tp) + } + components(tp) case _ => List() } @@ -302,8 +308,11 @@ object Types { */ final def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation = this match { case tp: RefinedType => - tp.parent.findMember(name, pre, excluded | Flags.Private) & - tp.findDecl(name, pre) + val denot = tp.findDecl(name, pre) + if ((denot.symbol is TypeParam) && denot.info.isAliasTypeBounds) + denot + else + tp.parent.findMember(name, pre, excluded | Flags.Private) & denot case tp: TypeProxy => tp.underlying.findMember(name, pre, excluded) case tp: ClassInfo => @@ -762,14 +771,14 @@ object Types { // --- Refined Type --------------------------------------------------------- - abstract case class RefinedType(parent: Type) extends CachedProxyType { + abstract case class RefinedType(parent: Type) extends CachedProxyType with BindingType { override def underlying(implicit ctx: Context) = parent def derivedRefinedType(parent: Type, names: List[Name], infos: List[Type])(implicit ctx: Context): RefinedType = if ((parent eq this.parent) && (names eq this.names) && (infos eq this.infos)) this else - RefinedType(parent, names, infos map (info => (rt: RefinedType) => info.substThis(this, RefinedThis(rt)))) + RefinedType(parent, names, infos map (info => (rt: RefinedType) => info.subst(this, rt))) def names: List[Name] @@ -777,6 +786,9 @@ object Types { def info(name: Name): Type + // needed??? + //def refine(tp: Type)(implicit ctx: Context): Type + def findDecl(name: Name, pre: Type)(implicit ctx: Context): Denotation = { val tpe = info(name) if (tpe == NoType) NoDenotation @@ -814,6 +826,12 @@ object Types { def derivedRefinedType1(parent: Type, name1: Name, info1: Type)(implicit ctx: Context): RefinedType1 = if ((parent eq this.parent) && (name1 eq this.name1) && (info1 eq this.info1)) this else RefinedType(parent, name1, rt => info1.substThis(this, RefinedThis(rt))) + + /*def refine(parent: Type)(implicit ctx: Context) = + if (parent.nonPrivateMember(name1).exists) + derivedRefinedType1(parent, name1, info1) + else parent*/ + override def computeHash = doHash(name1, info1, parent) } @@ -826,14 +844,23 @@ object Types { if (name == name1) info1 else if (name == name2) info2 else NoType + def derivedRefinedType2(parent: Type, name1: Name, info1: Type, name2: Name, info2: Type)(implicit ctx: Context): RefinedType2 = if ((parent eq this.parent) && (name1 eq this.name1) && (info1 eq this.info1) && (name2 eq this.name2) && (info2 eq this.info2)) this else RefinedType(parent, name1, rt => info1.substThis(this, RefinedThis(rt)), name2, rt => info2.substThis(this, RefinedThis(rt))) + + /*def refine(parent: Type)(implicit ctx: Context) = + if (parent.nonPrivateMember(name1).exists || + parent.nonPrivateMember(name2).exists) + derivedRefinedType2(parent, name1, info1, name2, info2) + else parent*/ + override def computeHash = doHash(name1, name2, info1, info2, parent) } class RefinedTypeN(parent: Type, val names: List[Name], infofs: List[RefinedType => Type]) extends RefinedType(parent) { val infos = infofs map (_(this)) + def info(name: Name): Type = { var ns = names var is = infos @@ -844,6 +871,12 @@ object Types { } NoType } + + /*def refine(parent: Type)(implicit ctx: Context) = + if (names exists (parent.nonPrivateMember(_).exists)) + derivedRefinedType(parent, names, infos) + else parent*/ + override def computeHash = doHash(names, parent, infos) } @@ -884,11 +917,13 @@ object Types { // ----- Method types: MethodType/ExprType/PolyType/MethodParam/PolyParam --------------- + trait BindingType extends Type + // Note: method types are cached whereas poly types are not. // The reason is that most poly types are cyclic via poly params, // and therefore two different poly types would never be equal. - abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends CachedGroundType { + abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends CachedGroundType with BindingType { lazy val resultType = resultTypeExp(this) def isJava = false def isImplicit = false @@ -962,7 +997,8 @@ object Types { unique(new CachedExprType(resultType)) } - case class PolyType(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) extends UncachedGroundType { + case class PolyType(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) + extends UncachedGroundType with BindingType { lazy val paramBounds = paramBoundsExp(this) lazy val resultType = resultTypeExp(this) @@ -987,21 +1023,33 @@ object Types { } } - case class MethodParam(mt: MethodType, paramNum: Int) extends UncachedProxyType with SingletonType { - override def underlying(implicit ctx: Context) = mt.paramTypes(paramNum) - override def hashCode = doHash(System.identityHashCode(mt) + paramNum) + abstract class BoundType extends UncachedProxyType { + type BT <: BindingType + def binder: BT + def copy(bt: BT): Type } - case class RefinedThis(rt: RefinedType) extends UncachedProxyType with SingletonType { - override def underlying(implicit ctx: Context) = rt.parent - override def hashCode = doHash(System.identityHashCode(rt)) + case class MethodParam(binder: MethodType, paramNum: Int) extends BoundType with SingletonType { + type BT = MethodType + override def underlying(implicit ctx: Context) = binder.paramTypes(paramNum) + override def hashCode = doHash(System.identityHashCode(binder) + paramNum) + def copy(bt: BT) = MethodParam(bt, paramNum) } - case class PolyParam(pt: PolyType, paramNum: Int) extends UncachedProxyType { - override def underlying(implicit ctx: Context) = pt.paramBounds(paramNum).hi + case class PolyParam(binder: PolyType, paramNum: Int) extends BoundType { + type BT = PolyType + override def underlying(implicit ctx: Context) = binder.paramBounds(paramNum).hi + def copy(bt: BT) = PolyParam(bt, paramNum) // no hashCode needed because cycle is broken in PolyType } + case class RefinedThis(binder: RefinedType) extends BoundType with SingletonType { + type BT = RefinedType + override def underlying(implicit ctx: Context) = binder.parent + def copy(bt: BT) = RefinedThis(bt) + override def hashCode = doHash(System.identityHashCode(binder)) + } + // ------ ClassInfo, Type Bounds ------------------------------------------------------------ abstract case class ClassInfo(prefix: Type, classd: ClassDenotation) extends CachedGroundType { @@ -1013,11 +1061,11 @@ object Types { NamedType(prefix, classd.symbol.name) // cached because baseType needs parents - private var parentsCache: List[Type] = null + private var parentsCache: List[TypeRef] = null - override def parents(implicit ctx: Context): List[Type] = { + override def parents(implicit ctx: Context): List[TypeRef] = { if (parentsCache == null) - parentsCache = classd.parents.mapConserve(_.substThis(classd.symbol, prefix)) + parentsCache = classd.parents.mapConserve(_.substThis(classd.symbol, prefix).asInstanceOf[TypeRef]) parentsCache } @@ -1104,12 +1152,17 @@ object Types { case tp: NamedType => tp.derivedNamedType(this(tp.prefix), tp.name) - case ThisType(_) - | MethodParam(_, _) - | PolyParam(_, _) => tp + case _: ThisType + | _: BoundType => tp + + case tp: RefinedType1 => + tp.derivedRefinedType1(this(tp.parent), tp.name1, this(tp.info1)) + + case tp: RefinedType2 => + tp.derivedRefinedType2(this(tp.parent), tp.name1, this(tp.info1), tp.name2, this(tp.info2)) - case tp @ AppliedType(tycon, targs) => - tp.derivedAppliedType(this(tycon), targs mapConserve this) + case tp: RefinedTypeN => + tp.derivedRefinedType(this(tp.parent), tp.names, tp.infos mapConserve this) case tp @ PolyType(pnames) => tp.derivedPolyType( @@ -1132,15 +1185,6 @@ object Types { tp.derivedTypeBounds(this(lo), this(hi)) } - case tp: RefinedType1 => - tp.derivedRefinedType1(this(tp.parent), tp.name1, this(tp.info1)) - - case tp: RefinedType2 => - tp.derivedRefinedType2(this(tp.parent), tp.name1, this(tp.info1), tp.name2, this(tp.info2)) - - case tp: RefinedTypeN => - tp.derivedRefinedType(this(tp.parent), tp.names, tp.infos mapConserve this) - case tp @ AnnotatedType(annots, underlying) => tp.derivedAnnotatedType(mapOverAnnotations(annots), this(underlying)) @@ -1166,12 +1210,6 @@ object Types { } } - class InstRefinedMap(rt: RefinedType)(implicit ctx: Context) extends TypeMap { - def apply(tp: Type) = tp match { - case RefinedThis(`rt`) => rt.parent - case _ => mapOver(tp) - } - } // ----- TypeAccumulators ---------------------------------------------------- @@ -1184,14 +1222,17 @@ object Types { case tp: NamedType => this(x, tp.prefix) - case ThisType(_) - | MethodParam(_, _) - | PolyParam(_, _) - | ConstantType(_) - | NoPrefix => x + case _: ThisType + | _: BoundType => x - case AppliedType(tycon, targs) => - (this(x, tycon) /: targs)(this) + case tp: RefinedType1 => + this(this(x, tp.parent), tp.info1) + + case tp: RefinedType2 => + this(this(this(x, tp.parent), tp.info1), tp.info2) + + case tp: RefinedTypeN => + (this(x, tp.parent) /: tp.infos)(apply) case tp @ PolyType(pnames) => this((x /: tp.paramBounds)(this), tp.resultType) @@ -1208,15 +1249,6 @@ object Types { case TypeBounds(lo, hi) => this(this(x, lo), hi) - case tp: RefinedType1 => - this(this(x, tp.parent), tp.info1) - - case tp: RefinedType2 => - this(this(this(x, tp.parent), tp.info1), tp.info2) - - case tp: RefinedTypeN => - (this(x, tp.parent) /: tp.infos)(apply) - case AnnotatedType(annots, underlying) => this((x /: annots)(apply), underlying) -- cgit v1.2.3 From 26cc006105195892c723a26ff2ee4ea703ba971a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 27 Jan 2013 10:21:44 +0100 Subject: Completed elimination of AppliedType --- src/dotty/tools/dotc/core/SymDenotations.scala | 7 ++-- src/dotty/tools/dotc/core/Symbols.scala | 2 +- src/dotty/tools/dotc/core/TypeComparers.scala | 7 +--- src/dotty/tools/dotc/core/Types.scala | 45 ++------------------------ 4 files changed, 8 insertions(+), 53 deletions(-) (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala') diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index a9da9806e..8dbf43f00 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -387,6 +387,7 @@ object SymDenotations { typeConstructorCache } + /* private var typeTemplateCache: Type = null def typeTemplate(implicit ctx: Context): Type = { @@ -394,7 +395,7 @@ object SymDenotations { AppliedType.make(typeConstructor, typeParams map (_.typeConstructor)) typeTemplateCache } - +*/ private var baseClassesVar: List[ClassSymbol] = null private var superClassBitsVar: BitSet = null @@ -534,8 +535,6 @@ object SymDenotations { final def baseTypeOf(tp: Type)(implicit ctx: Context): Type = { def computeBaseTypeOf(tp: Type): Type = tp match { - case AppliedType(tycon, args) => - baseTypeOf(tycon).subst(tycon.typeParams, args) case tp: TypeProxy => baseTypeOf(tp.underlying) case AndType(tp1, tp2) => @@ -547,7 +546,7 @@ object SymDenotations { case p :: ps1 => reduce(bt & baseTypeOf(p), ps1) case _ => bt } - if (classd.symbol == symbol) tp.typeTemplate + if (classd.symbol == symbol) tp.typeConstructor // was: typeTemplate else reduce(NoType, classd.parents).substThis(classd.symbol, tp.prefix) } diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index decdb6c84..84ffc53a7 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -228,7 +228,7 @@ object Symbols { def baseClasses(implicit ctx: Context): List[ClassSymbol] = classDenot.baseClasses override def typeConstructor(implicit ctx: Context): Type = classDenot.typeConstructor - override def typeTemplate(implicit ctx: Context): Type = classDenot.typeTemplate +// override def typeTemplate(implicit ctx: Context): Type = classDenot.typeTemplate def superId(implicit ctx: Context): Int = { val hint = superIdHint diff --git a/src/dotty/tools/dotc/core/TypeComparers.scala b/src/dotty/tools/dotc/core/TypeComparers.scala index 304bd9938..22ba680ca 100644 --- a/src/dotty/tools/dotc/core/TypeComparers.scala +++ b/src/dotty/tools/dotc/core/TypeComparers.scala @@ -117,11 +117,6 @@ object TypeComparers { def thirdTry(tp1: Type, tp2: Type): Boolean = tp2 match { case tp2: TypeRef => thirdTryRef(tp1, tp2) - case AppliedType(tycon, targs) => - val clazz2 = tycon.typeSymbol - val base = tp1.baseType(clazz2) - base.exists && isSubArgs(base.typeArgs, tp2.typeArgs, clazz2.typeParams) || - fourthTry(tp1, tp2) case tp2: RefinedType1 => isSubType(tp1, tp2.parent) && isSubType(tp1.member(tp2.name1).info, tp2.info1) @@ -169,7 +164,7 @@ object TypeComparers { case TypeBounds(lo1, hi1) => isSubType(lo2, lo1) && isSubType(hi1, hi2) case tp1: ClassInfo => - val tt = tp1.typeTemplate + val tt = tp1.typeConstructor // was typeTemplate lo2 <:< tt && tt <:< hi2 case _ => false diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 09efd28c0..d55afcca6 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -420,31 +420,14 @@ object Types { /** The type parameters of this type are: * For a ClassInfo type, the type parameters of its denotation. - * For an applied type, the type parameters of its constructor - * that have not been instantiated yet. * Inherited by type proxies. * Empty list for all other types. */ final def typeParams(implicit ctx: Context): List[TypeSymbol] = this match { - case tp: AppliedType => - tp.tycon.typeParams drop tp.targs.length - case tp: TypeProxy => - tp.underlying.typeParams case tp: ClassInfo => tp.classd.typeParams - case _ => Nil - } - - /** The type arguments of this type are: - * For an Applied type, its type arguments. - * Inherited by type proxies. - * Empty list for all other types. - */ - final def typeArgs(implicit ctx: Context): List[Type] = this match { - case tp: AppliedType => - tp.targs case tp: TypeProxy => - tp.underlying.typeArgs + tp.underlying.typeParams case _ => Nil } @@ -735,28 +718,6 @@ object Types { unique(new CachedConstantType(value)) } - // --- AppliedType ----------------------------------------------------------------- - - abstract case class AppliedType(tycon: Type, targs: List[Type]) extends CachedProxyType { - - override def underlying(implicit ctx: Context) = tycon - - def derivedAppliedType(tycon: Type, targs: List[Type])(implicit ctx: Context): Type = - if ((tycon eq this.tycon) && (targs eq this.targs)) this - else AppliedType(tycon, targs) - - override def computeHash = doHash(tycon, targs) - } - - final class CachedAppliedType(tycon: Type, targs: List[Type]) extends AppliedType(tycon, targs) - - object AppliedType { - def apply(tycon: Type, targs: List[Type])(implicit ctx: Context) = - unique(new CachedAppliedType(tycon, targs)) - def make(tycon: Type, targs: List[Type])(implicit ctx: Context) = - if (targs.isEmpty) tycon else apply(tycon, targs) - } - // --- Refined Type --------------------------------------------------------- abstract case class RefinedType(parent: Type) extends CachedProxyType with BindingType { @@ -1042,9 +1003,9 @@ object Types { abstract case class ClassInfo(prefix: Type, classd: ClassDenotation) extends CachedGroundType { - def typeTemplate(implicit ctx: Context): Type = +/* def typeTemplate(implicit ctx: Context): Type = classd.typeTemplate asSeenFrom (prefix, classd.symbol) - +*/ def typeConstructor(implicit ctx: Context): Type = NamedType(prefix, classd.symbol.name) -- cgit v1.2.3