From 39ab8822039706b88373954a7e39919938d79f6f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 22 Dec 2012 18:13:35 +0100 Subject: Refactored ClassInfoType content back to Denotation. Created separate ClassInfo type, which combines a prefix with a ClassInfo denotation. That leads to better regularity elsewhere, because now taking the info of a TypeRef will not lose information: If the info is a TypeBounds, the prefix is already taken account in it, and for ClassInfo we now record it explicitly. --- src/dotty/tools/dotc/core/Denotations.scala | 227 ++++++++++- src/dotty/tools/dotc/core/Symbols.scala | 27 +- src/dotty/tools/dotc/core/Types.scala | 589 ++++++++-------------------- 3 files changed, 403 insertions(+), 440 deletions(-) (limited to 'src/dotty') diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 8126ad117..a1ad814ba 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -5,9 +5,12 @@ import Periods._, Contexts._, Symbols._, References._, Names._ import Types._, Flags._, Decorators._ import Scopes.Scope import collection.mutable +import collection.immutable.BitSet trait Denotations { self: Context => + /** A set for hash consing superclass bitsets */ + private val uniqueBits = new util.HashSet[BitSet]("superbits", 1024) } @@ -100,6 +103,228 @@ object Denotations { def newNameFilter: FingerPrint = new Array[Long](DefinedNamesWords) } + class ClassDenotation(val parents: List[Type], val decls: Scope, val clazz: ClassSymbol) extends Denotation { + import NameFilter._ + import util.LRU8Cache + + def typeParams: List[TypeSymbol] = ??? + + private var memberCacheVar: LRU8Cache[Name, RefSet] = null + + private def memberCache: LRU8Cache[Name, RefSet] = { + if (memberCacheVar == null) memberCacheVar = new LRU8Cache + memberCacheVar + } + + private var thisTypeCache: ThisType = null + + def thisType(implicit ctx: Context): Type = { + if (thisTypeCache == null) + thisTypeCache = ThisType(clazz) + thisTypeCache + } + + private var typeConstructorCache: Type = null + + def typeConstructor(implicit ctx: Context): Type = { + if (typeConstructorCache == null) + typeConstructorCache = NamedType(thisType, clazz.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(clazz) + 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 = clazz :: 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, clazz.name) + e = e.prev + } + var ps = parents + while (ps.nonEmpty) { + val parent = ps.head.typeSymbol + parent.deref match { + case classd: ClassDenotation => + includeFingerPrint(bits, classd.definedFingerPrint) + parent.deref setFlag 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((clazz.flags & Frozen) == Flags.Empty) + 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((clazz.flags & Frozen) == Flags.Empty) + 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 memberRefsNamed(name: Name)(implicit ctx: Context): RefSet = { + var refs: RefSet = memberCache lookup name + if (refs == null) { + if (containsName(definedFingerPrint, name)) { + val ownRefs = decls.refsNamed(name) + refs = ownRefs + var ps = parents + while (ps.nonEmpty) { + val parentSym = ps.head.typeSymbol + parentSym.deref match { + case parentd: ClassDenotation => + refs = refs union + parentd.memberRefsNamed(name) + .filterExcluded(Flags.Private) + .asSeenFrom(thisType, parentSym) + .filterDisjoint(ownRefs) + case _ => + } + } + } else { + refs = NoRef + } + memberCache enter (name, refs) + } + refs + } + + private var baseTypeCache: java.util.HashMap[UniqueType, Type] = null + + 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.clazz == clazz) tp.typeTemplate + else reduce(NoType, classd.parents).substThis(classd.clazz, tp.prefix) + } + + if (clazz.isStatic && clazz.typeParams.isEmpty) clazz.typeConstructor + else tp match { + case tp: UniqueType => + if (baseTypeCache == null) + baseTypeCache = new java.util.HashMap[UniqueType, Type] + 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(clazz) + } + basetp + case _ => + computeBaseTypeOf(tp) + } + } + + private var memberNamesCache: Map[NameFilter, Set[Name]] = Map() + + def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context): Set[Name] = + memberNamesCache get filter match { + case Some(names) => + names + case _ => + val inheritedNames = (parents flatMap (_.memberNames(thisType, filter))).toSet + val ownNames = decls.iterator map (_.name) + val candidates = inheritedNames ++ ownNames + val names = candidates filter (filter(thisType, _)) + memberNamesCache += (filter -> names) + names + } + } + object NoDenotation extends Denotation { override def owner: Symbol = throw new AssertionError("NoDenotation.owner") override def name: Name = BootNameTable.newTermName("") @@ -107,6 +332,4 @@ object Denotations { override def tpe: Type = NoType override def info: Type = NoType } - - } \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 3c8180e15..c76fc2cb9 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -152,13 +152,8 @@ object Symbols { val initDenot = lastDenot.initial val newSym: Symbol = ctx.atPhase(FirstPhaseId) { implicit ctx => - def relink(ref: Reference): Symbol = ref match { - case ref: SymRef => - if (ref.signature == thisRef.signature) ref.symbol else NoSymbol - case ref @ OverloadedRef(ref1, ref2) => - relink(ref1) orElse relink(ref2) - } - relink(initDenot.owner.info.decl(initDenot.name)) + initDenot.owner.info.decl(initDenot.name) + .atSignature(thisRef.signature).symbol } if (newSym eq this) { // no change, change validity var d = initDenot @@ -180,7 +175,6 @@ object Symbols { def name(implicit ctx: Context): Name = deref.name def flags(implicit ctx: Context): FlagSet = deref.flags def info(implicit ctx: Context): Type = deref.info - def tpe(implicit ctx: Context): Type = info def prefix(implicit ctx: Context) = owner.thisType def allOverriddenSymbols: Iterator[Symbol] = ??? @@ -223,6 +217,10 @@ object Symbols { def isMethod(implicit ctx: Context): Boolean = deref.isMethod def hasFlag(required: FlagSet)(implicit ctx: Context): Boolean = (flags & required) != Flags.Empty def hasAllFlags(required: FlagSet)(implicit ctx: Context): Boolean = (flags & required) == flags + + def containsNull(implicit ctx: Context): Boolean = + isClass && !(isSubClass(defn.AnyValClass)) + } abstract class TermSymbol extends Symbol { @@ -241,14 +239,25 @@ object Symbols { abstract class TypeSymbol extends Symbol { def name: TypeName def isType = false + + def variance: Int = ??? + + def typeConstructor(implicit ctx: Context): Type = ??? + def typeTemplate(implicit ctx: Context): Type = ??? } abstract class ClassSymbol extends TypeSymbol { override def isClass = true private var superIdHint: Int = -1 + override def deref(implicit ctx: Context): ClassDenotation = + super.deref.asInstanceOf[ClassDenotation] + def typeOfThis(implicit ctx: Context): Type = ??? + override def typeConstructor(implicit ctx: Context): Type = deref.typeConstructor + override def typeTemplate(implicit ctx: Context): Type = deref.typeTemplate + /** The unique, densely packed identifier of this class symbol. Should be called * only if class is a super class of some other class. */ @@ -277,4 +286,6 @@ object Symbols { override def exists = false def isType = false } + + implicit def defn(implicit ctx: Context): Definitions = ctx.root.definitions } \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 9c1ba9660..74b8ef959 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -14,10 +14,6 @@ import References._ import Periods._ import References.{Reference, RefSet, RefUnion, ErrorRef} import scala.util.hashing.{MurmurHash3 => hashing} -import collection.immutable.BitSet -import collection.mutable - -import collection.mutable trait Types { self: Context => @@ -28,9 +24,6 @@ trait Types { self: Context => private[Types] val uniques = new util.HashSet[Type]("uniques", initialUniquesCapacity) { override def hash(x: Type): Int = x.hash } - - /** A set for hash consing superclass bitsets */ - private[Types] val uniqueBits = new util.HashSet[BitSet]("superbits", 1024) } object Types { @@ -49,6 +42,8 @@ object Types { def <:< (that: Type): Boolean = ??? + def =:= (that: Type): Boolean = ??? + def hash = NotCached /** The type symbol associated with the type @@ -62,6 +57,27 @@ object Types { /** Does this type denote a stable reference (i.e. singleton type)? */ def isStable(implicit ctx: Context): Boolean = false + /** A type T is a legal prefix in a type selection T#A if + * T is stable or T contains no uninstantiated type variables. + */ + def isLegalPrefix(implicit ctx: Context): Boolean = + isStable || abstractTypeNames(this).isEmpty + + /** The set of names of members of this type that pass the given name filter when seen as members of + * `pre`. More precisely, these are all names of members `name` such that + * `filter(pre, name)` is `true`. + */ + def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context): Set[Name] = Set() + + def abstractTypeNames(pre: Type)(implicit ctx: Context): Set[Name] = + memberNames(pre, abstractTypeNameFilter) + + def abstractTermNames(pre: Type)(implicit ctx: Context): Set[Name] = + memberNames(pre, abstractTermNameFilter) + + def isRealTypeBounds: Boolean = false + + /** Is this type dangerous (i.e. it might contain conflicting * type information when empty, so that it can be constructed * so that type unsoundness results.) A dangerous type has an underlying @@ -106,15 +122,6 @@ object Types { def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Reference = unsupported("findMember") - protected def findMemberAmong(candidates: RefSet, pre: Type, owner: ClassSymbol, excluded: FlagSet)(implicit ctx: Context): Reference = { - val resultSyms = candidates - .filterAccessibleFrom(pre) - .filterExcluded(excluded) - .asSeenFrom(pre, owner) - if (resultSyms.exists) resultSyms.toRef - else ErrorRef // todo: refine - } - def memberType(sym: Symbol): Type = ??? def memberInfo(sym: Symbol): Type = ??? @@ -128,7 +135,8 @@ object Types { def resultType: Type = ??? - def baseClasses: List[ClassSymbol] = ??? + def baseClasses(implicit ctx: Context): List[ClassSymbol] = + unsupported("baseClasses") def typeArgs: List[Type] = ??? @@ -145,8 +153,8 @@ object Types { def substThis(clazz: ClassSymbol, tp: Type): Type = ??? def substThis(from: RefinedType, tp: Type): Type = ??? - def baseType(base: Symbol)(implicit ctx: Context): Type = base.info match { - case cinfo: ClassInfoType => cinfo.baseTypeOf(this) + def baseType(base: Symbol)(implicit ctx: Context): Type = base.deref match { + case classd: ClassDenotation => classd.baseTypeOf(this) case _ => NoType } @@ -306,6 +314,9 @@ object Types { underlying.findMember(name, pre, excluded) override def parents(implicit ctx: Context) = underlying.parents override def decls(implicit ctx: Context) = underlying.decls + override def baseClasses(implicit ctx: Context) = underlying.baseClasses + override def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context) = + underlying.memberNames(pre, filter) } trait TransformingProxy extends TypeProxy { @@ -316,7 +327,9 @@ object Types { } - trait SingletonType extends SubType + trait SingletonType extends SubType { + override def isStable(implicit ctx: Context) = true + } // --- NamedTypes ------------------------------------------------------------------ @@ -329,14 +342,14 @@ object Types { private[this] var referencedVar: Reference = null protected[this] var validPeriods = Nowhere - private def needsStablePrefix(sym: Symbol) = - sym.isAbstractType || sym.isClass && !sym.isJava + private def checkPrefix(sym: Symbol) = + sym.isAbstractType || sym.isClass def referenced(implicit ctx: Context): Reference = { if (!containsPeriod(validPeriods, ctx.period)) { referencedVar = prefix.member(name) validPeriods = ctx.stableInterval - if (needsStablePrefix(referencedVar.symbol) && !prefix.isStable) + if (checkPrefix(referencedVar.symbol) && !prefix.isLegalPrefix) throw new MalformedType(prefix, referencedVar.symbol) } referencedVar @@ -350,12 +363,6 @@ object Types { def underlying(implicit ctx: Context): Type = info - override def parents(implicit ctx: Context) = { - val ps = info.parents - val sym = symbol - if (sym.isClass) ps.mapConserve(_.substThis(sym.asClass, prefix)) else ps - } - def derivedNamedType(pre: Type, name: Name)(implicit ctx: Context): Type = if (pre eq prefix) this else NamedType(pre, name) @@ -384,6 +391,12 @@ object Types { validPeriods = allPeriods(ctx.runId) } + final class TermRefWithSignature(prefix: Type, name: TermName, val signature: Signature) extends TermRef(prefix, name) { + override def computeHash = doHash((name, signature), prefix) + override def referenced(implicit ctx: Context): Reference = + super.referenced.atSignature(signature) + } + final class TypeRefNoPrefix(val fixedSym: TypeSymbol)(implicit ctx: Context) extends TypeRef(NoPrefix, fixedSym.name) with NamedNoPrefix { validPeriods = allPeriods(ctx.runId) @@ -403,6 +416,8 @@ object Types { unique(new UniqueTermRef(prefix, name)) def apply(sym: TermSymbol)(implicit ctx: Context) = unique(new TermRefNoPrefix(sym)) + def apply(prefix: Type, name: TermName, signature: Signature)(implicit ctx: Context) = + unique(new TermRefWithSignature(prefix, name, signature)) } object TypeRef { @@ -416,7 +431,6 @@ object Types { abstract case class ThisType(clazz: ClassSymbol) extends SingletonType { def underlying(implicit ctx: Context) = clazz.typeOfThis - override def isStable(implicit ctx: Context) = true override def computeHash = doHash(clazz) } @@ -429,11 +443,10 @@ object Types { abstract case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType { def underlying(implicit ctx: Context) = supertpe - override def isStable(implicit ctx: Context) = true - override def computeHash = doHash(thistpe, supertpe) def derivedSuperType(thistp: Type, supertp: Type)(implicit ctx: Context) = if ((thistp eq thistpe) && (supertp eq supertpe)) this else SuperType(thistp, supertp) + override def computeHash = doHash(thistpe, supertpe) } final class UniqueSuperType(thistpe: Type, supertpe: Type) extends SuperType(thistpe, supertpe) @@ -457,21 +470,28 @@ object Types { // --- AppliedType ----------------------------------------------------------------- - abstract case class AppliedType(tycon: Type, override val typeArgs: List[Type]) extends UniqueType { + abstract case class AppliedType(tycon: Type, override val typeArgs: List[Type]) extends UniqueType with TypeProxy { assert(tycon.typeParams.length == typeArgs.length) - def derivedAppliedType(tc: Type, args: List[Type])(implicit ctx: Context): Type = + def underlying(implicit ctx: Context) = tycon + + def derivedAppliedType(tc: Type, args: List[Type])(implicit ctx: Context): Type = if ((tc eq tycon) && (args eq typeArgs)) this else AppliedType(tc, args) override def computeHash = doHash(tycon, typeArgs) - } + override def parents(implicit ctx: Context) = + tycon.parents.mapConserve(_.subst(tycon.typeParams, typeArgs)) + + } final class UniqueAppliedType(tycon: Type, typeArgs: List[Type]) extends AppliedType(tycon, typeArgs) object AppliedType { def apply(tycon: Type, typeArgs: List[Type])(implicit ctx: Context) = unique(new UniqueAppliedType(tycon, typeArgs)) + def make(tycon: Type, typeArgs: List[Type])(implicit ctx: Context) = + if (typeArgs.isEmpty) tycon else apply(tycon, typeArgs) } // --- Refined Type --------------------------------------------------------- @@ -507,207 +527,12 @@ object Types { parent.findMember(name, pre, excluded | Flags.Private) & findDecl(name, pre) + override def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context): Set[Name] = + parent.memberNames(pre, filter) ++ (names filter (filter(pre, _))).toSet + def computeHash = doHash(names, parent, infos) } -// --- ClassInfo Type --------------------------------------------------------- - - case class ClassInfoType(_parents: List[Type], _decls: Scope, clazz: ClassSymbol) extends UniqueType { - import NameFilter._ - import util.LRU8Cache - - override def parents(implicit ctx: Context) = _parents - override def decls(implicit ctx: Context) = _decls - - private var memberCacheVar: LRU8Cache[Name, RefSet] = null - - private def memberCache: LRU8Cache[Name, RefSet] = { - if (memberCacheVar == null) memberCacheVar = new LRU8Cache - memberCacheVar - } - - def thisType: Type = ??? - - 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(clazz) - 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 = clazz :: 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, clazz.name) - e = e.prev - } - var ps = parents - while (ps.nonEmpty) { - val parent = ps.head.typeSymbol - parent.info match { - case cinfo: ClassInfoType => - includeFingerPrint(bits, cinfo.definedFingerPrint) - parent.deref setFlag 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((clazz.flags & Frozen) == Flags.Empty) - 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((clazz.flags & Frozen) == Flags.Empty) - 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 memberRefsNamed(name: Name)(implicit ctx: Context): RefSet = { - var refs: RefSet = memberCache lookup name - if (refs == null) { - if (containsName(definedFingerPrint, name)) { - val ownRefs = decls.refsNamed(name) - refs = ownRefs - var ps = parents - while (ps.nonEmpty) { - val parentSym = ps.head.typeSymbol - parentSym.info match { - case pinfo: ClassInfoType => - refs = refs union - pinfo.memberRefsNamed(name) - .filterExcluded(Flags.Private) - .asSeenFrom(thisType, parentSym) - .filterDisjoint(ownRefs) - case _ => - } - } - } else { - refs = NoRef - } - memberCache enter (name, refs) - } - refs - } - - private var baseTypeCache: java.util.HashMap[UniqueType, Type] = null - - final def baseTypeOf(tp: Type)(implicit ctx: Context): Type = { - - def computeBaseTypeOf(tp: Type): Type = tp match { - case tp: NamedType => - val sym = tp.symbol - val bt = baseTypeOf(tp.info) - if (sym.isClass) bt.substThis(sym.asClass, tp.prefix) - else bt - case AppliedType(tycon, args) => - baseTypeOf(tycon).subst(tycon.typeParams, args) - case AndType(tp1, tp2) => - baseTypeOf(tp1) & baseTypeOf(tp2) - case OrType(tp1, tp2) => - baseTypeOf(tp1) | baseTypeOf(tp2) - case ClassInfoType(parents, _, _) => - def reduce(bt: Type, ps: List[Type]): Type = ps match { - case p :: ps1 => reduce(bt & baseTypeOf(p), ps1) - case _ => bt - } - reduce(NoType, parents) - case tp: TypeProxy => - baseTypeOf(tp.underlying) - } - - if (clazz.isStatic && clazz.typeParams.isEmpty) clazz.tpe - else tp match { - case tp: UniqueType => - if (baseTypeCache == null) - baseTypeCache = new java.util.HashMap[UniqueType, Type] - 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(clazz) - } - basetp - case _ => - computeBaseTypeOf(tp) - } - } - override def typeSymbol(implicit ctx: Context) = clazz - - override def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Reference = - findMemberAmong(memberRefsNamed(name), pre, clazz, excluded) - - def computeHash = clazz.hashCode - - } // --- AndType/OrType --------------------------------------------------------------- @@ -720,7 +545,10 @@ object Types { else AndType(t1, t2) override def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Reference = - (tp1 findMember (name, pre, excluded)) & (tp2 findMember (name, pre, excluded)) + tp1.findMember(name, pre, excluded) & tp2.findMember(name, pre, excluded) + + override def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context): Set[Name] = + tp1.memberNames(pre, filter) & tp2.memberNames(pre, filter) override def computeHash = doHash(tp1, tp2) } @@ -741,6 +569,9 @@ object Types { (tp1.findMember(name, pre, excluded) | tp2.findMember(name, pre, excluded))(pre) } + override def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context): Set[Name] = + tp1.memberNames(pre, filter) | tp2.memberNames(pre, filter) + override def computeHash = doHash(tp1, tp2) } @@ -755,6 +586,8 @@ object Types { abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends UniqueType { override lazy val resultType = resultTypeExp(this) + def isJava = false + def isImplicit = false lazy val isDependent = resultType exists { case MethodParam(mt, _) => mt eq this case _ => false @@ -773,12 +606,28 @@ object Types { override def computeHash = doHash(paramNames, resultType, paramTypes) } - final class UniqueMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends MethodType(paramNames, paramTypes)(resultTypeExp) + final class UniqueMethodType(paramNames: List[TermName], paramTypes: List[Type]) + (resultTypeExp: MethodType => Type) + extends MethodType(paramNames, paramTypes)(resultTypeExp) + final class JavaMethodType(paramNames: List[TermName], paramTypes: List[Type]) + (resultTypeExp: MethodType => Type) + extends MethodType(paramNames, paramTypes)(resultTypeExp) { + override def isJava = true + } + final class ImplicitMethodType(paramNames: List[TermName], paramTypes: List[Type]) + (resultTypeExp: MethodType => Type) + extends MethodType(paramNames, paramTypes)(resultTypeExp) { + override def isImplicit = true + } object MethodType { - def apply(paramNames: List[TermName], paramTypes: List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context) = + def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) = unique(new UniqueMethodType(paramNames, paramTypes)(resultTypeExp)) } + def JavaMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) = + unique(new JavaMethodType(paramNames, paramTypes)(resultTypeExp)) + def ImplicitMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) = + unique(new ImplicitMethodType(paramNames, paramTypes)(resultTypeExp)) abstract case class ExprType(override val resultType: Type) extends UniqueType { def derivedExprType(rt: Type)(implicit ctx: Context) = @@ -821,7 +670,55 @@ object Types { def underlying(implicit ctx: Context) = pt.paramBounds(paramNum).hi } -// ------ Type Bounds ------------------------------------------------------------ +// ------ ClassInfo, Type Bounds ------------------------------------------------------------ + + abstract case class ClassInfo(override val prefix: Type, classd: ClassDenotation) extends UniqueType { + override def typeSymbol(implicit ctx: Context) = classd.clazz + + override def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Reference = + findMemberAmong(classd.memberRefsNamed(name), pre, classd.clazz, excluded) + + private def findMemberAmong(candidates: RefSet, pre: Type, owner: ClassSymbol, excluded: FlagSet) + (implicit ctx: Context): Reference = { + val resultSyms = candidates + .filterAccessibleFrom(pre) + .filterExcluded(excluded) + .asSeenFrom(pre, owner) + if (resultSyms.exists) resultSyms.toRef + else ErrorRef // todo: refine + } + + override def baseClasses(implicit ctx: Context): List[ClassSymbol] = + classd.baseClasses + + override def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context): Set[Name] = + classd.memberNames(pre, filter) + + private var parentsCache: List[Type] = null + + override def decls(implicit ctx: Context) = classd.decls + + override def parents(implicit ctx: Context) = { + if (parentsCache == null) + parentsCache = classd.parents.mapConserve(_.substThis(classd.clazz, prefix)) + parentsCache + } + + def typeTemplate(implicit ctx: Context): Type = + classd.typeTemplate asSeenFrom (prefix, classd.clazz) + + def typeConstructor(implicit ctx: Context): Type = + NamedType(prefix, classd.clazz.name) + + override def computeHash = doHash(classd.clazz, prefix) + } + + final class UniqueClassInfo(pre: Type, classd: ClassDenotation) extends ClassInfo(pre, classd) + + object ClassInfo { + def apply(pre: Type, classd: ClassDenotation)(implicit ctx: Context) = + unique(new UniqueClassInfo(pre, classd)) + } abstract case class TypeBounds(lo: Type, hi: Type) extends UniqueType with TypeProxy { def underlying(implicit ctx: Context): Type = hi @@ -829,6 +726,8 @@ object Types { if ((lo1 eq lo) && (hi1 eq hi)) this else TypeBounds(lo, hi) + override def isRealTypeBounds = lo ne hi + def & (that: TypeBounds)(implicit ctx: Context): TypeBounds = TypeBounds(this.lo | that.lo, this.hi & that.hi) def | (that: TypeBounds)(implicit ctx: Context): TypeBounds = @@ -912,7 +811,7 @@ object Types { val restpe = tp.resultType val restpe1 = this(restpe) if ((ptypes1 eq ptypes) && (restpe1 eq restpe)) tp - else MethodType(pnames, ptypes1, x => restpe1.subst(tp, x)) + else MethodType(pnames, ptypes1)(x => restpe1.subst(tp, x)) case tp @ ExprType(restpe) => tp.derivedExprType(this(restpe)) @@ -986,7 +885,7 @@ object Types { val tparamOwner = tparam.owner def throwError = - if (tparamOwner.tpe.parents exists (_.isErroneous)) + if (tparamOwner.info.parents exists (_.isErroneous)) ErrorType // don't be overzealous with throwing exceptions, see #2641 else throw new Error( @@ -1073,203 +972,25 @@ object Types { this((x /: annots) (apply), underlying) case _ => x - } - } class ExistsAccumulator(p: Type => Boolean) extends TypeAccumulator[Boolean] { def apply(x: Boolean, tp: Type) = x || p(tp) || foldOver(x, tp) } -// ----- Subtyping ----------------------------------------------------------- - - type Constraints = Map[PolyParam, TypeBounds] - - class SubTyper(val constraints: Constraints = Map(), explain: Boolean = false) { - - /** - * isSubRefinement(T1, T2) = - * val clazz = T1.clazz - * - * - */ - def isSubRefinement(tp1: Type, tp2: Type)(implicit ctx: Context): Boolean = { - val clazz = tp1.typeSymbol - assert(clazz eq tp2.typeSymbol) - if (tp1.prefix != tp2.prefix) return false - tp1 match { - case AppliedType(tycon2, args2) => - isSubArgs(clazz.typeParams, tp1.typeArgs, args2) && - isSubRefinement(tp1, tycon2) - case RefinedType(tycon2, names) => - ??? - - } - } - - def isSubArgs(tparams: List[TypeSymbol], subargs: List[Type], superargs: List[Type]): Boolean = ??? - - /** - * NoType is not a sub or superType of Anything - * - * T <: ? - * ? <: T - * T <: Error - * Error <: T - * - * T1 <: T2[U2s] :- - * T1 <: T2 /\ - * val T[U1s] = T1 baseType T2.typeSymbol - * and for all i: - * if !(Ui contravariant in T) U1i <: U2i - * if !(Ui covariant in T) U2i <: U1i - * - * T1[U1s] <: T2 if - * T1 <: T2 - * - * P#A <: P#A if A is no a class, or both types have same symbol - * - * T1 <: T2 if class C = T2.typeSymbol - * /\ T1' = t1 baseType C - * /\ T1' isSubRefinement T2 - * - * T1 <: T2 { Ds } - * if T1 <: T2 and forall i, T1 specializesSym Di - * - * - */ - def isSubType(tp1: Type, tp2: Type)(implicit ctx: Context): Boolean = { -??? -/* - if (tp1 == NoType || tp2 == NoType) return false - if (tp1 eq tp2) return true - - tp2 match { - case tp2 @ NamedType(pre2, name2) => - val ref2 = tp2.referenced - if (name2.isTerm && ref2.isStable) return isSubType(tp1, ref2.info) - } - - tp1 match { - case tp1 @ NamedType(pre1, name1) => - val ref1 = tp1.referenced - val sym1 = ref1.symbol - if (sym1 != NoSymbol) { - tp2 match { - case tp2 @ NamedType(pre2, name2) => - val ref2 = tp2.referenced - val sym2 = ref2.symbol - if (sym1 eq sym2) return true - - - - - - if (sym1.isTerm) { - val expanded2 = if (ref2.info.isStable) return ref2.info else tp2 - return isSubType(ref1.info, expanded2) - } - - } - } - } - - (tp1, tp2) match { - case (tp1 @ NamedType(pre1, name1), tp2 @ NamedType(pre2, name2)) => - if (!(pre1 =:= pre2)) return false - val ref1 = tp1.referenced - val ref2 = tp2.referenced - val sym1 = ref1.symbol - val sym2 = ref2.symbol - if (sym1 != NoSymbol && sym2 != NoSymbol) { - if (sym1 eq sym2) return true - if (sym2.isTerm && ref2.isStable) return isSubType(tp1, ref2.info) - if (sym1.isTerm) return isSubType(ref1.info, tp2) - if (sym1.isClass) { - if (sym1 == NothingClass) return true - if (sym2.isClass) return sym1.isNonBottomSubClass(sym2) || sym1 == NullClass - } else if (isSubType(ref1.upperBound, tp2)) return true - // !sym1.isClass || !sym2.isClass - if (name1 == name2) return true - val lo = ref2.info.lowerBound - return lo.typeSymbol != NothingClass && isSubType(tp1, lo) - - - - - } - if (sym1 == NothingClass) return true - if () - if (sym1.isClass) - if (sym1 == NothingClass) true - if (sym2.isClass) sym1 isSubClass sym2 - else if (name1 eq name2) true - else if - } - - if (name1 == name2) - - } - - (!(tp1.symbol.isClass && tp2.symbol.isClass) || tp1.symbol == tp2.symbol) - - - - } - - } - - /** First try, on the right: - * - unwrap Annotated types, BoundedWildcardTypes, - * - bind TypeVars on the right, if lhs is not Annotated nor BoundedWildcard - * - handle common cases for first-kind TypeRefs on both sides as a fast path. - */ - def firstTry(tp1: Type, tp2: Type)(implicit ctx: Context): Boolean = tp2 match { - case tp2: NamedType => - firstTry(tp1, tp2.underlying) - case tp2: TypeRef => - - case tr2: TypeRef => - tp1 match { - case tr1: TypeRef => - val sym1 = tr1.sym - val sym2 = tr2.sym - val pre1 = tr1.pre - val pre2 = tr2.pre - (((if (sym1 == sym2) phase.erasedTypes || sym1.owner.hasPackageFlag || isSubType(pre1, pre2, depth) - else (sym1.name == sym2.name && !sym1.isModuleClass && !sym2.isModuleClass && - (isUnifiable(pre1, pre2) || - isSameSpecializedSkolem(sym1, sym2, pre1, pre2) || - sym2.isAbstractType && isSubPre(pre1, pre2, sym2)))) && - isSubArgs(tr1.args, tr2.args, sym1.typeParams, depth)) - || - sym2.isClass && { - val base = tr1 baseType sym2 - (base ne tr1) && isSubType(base, tr2, depth) - } - || - thirdTryRef(tr1, tr2)) - case _ => - secondTry - } - case AnnotatedType(_, _, _) => - isSubType(tp1.withoutAnnotations, tp2.withoutAnnotations, depth) && - annotationsConform(tp1, tp2) - case BoundedWildcardType(bounds) => - isSubType(tp1, bounds.hi, depth) - case tv2 @ TypeVar(_, constr2) => - tp1 match { - case AnnotatedType(_, _, _) | BoundedWildcardType(_) => - secondTry - case _ => - tv2.registerBound(tp1, true) - } - case _ => - secondTry*/ - } + abstract class NameFilter { + def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean + } + object abstractTypeNameFilter extends NameFilter { + def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = + name.isTypeName && (pre member name).info.isRealTypeBounds + } + object abstractTermNameFilter extends NameFilter { + def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = + name.isTermName && (pre member name).symbol.isDeferred } // ----- Exceptions ------------------------------------------------------------- @@ -1293,7 +1014,15 @@ object Types { else x1 :: xs1 } - def NothingType(implicit ctx: Context) = ctx.root.definitions.NothingType - def AnyType(implicit ctx: Context) = ctx.root.definitions.AnyType - lazy val SingletonType: Type = ??? + /** True if two lists have the same length. Since calling length on linear sequences + * is O(n), it is an inadvisable way to test length equality. + */ + final def sameLength[T](xs: List[T], ys: List[T]): Boolean = xs match { + case _ :: xs1 => + ys match { + case _ :: ys1 => sameLength(xs1, ys1) + case _ => false + } + case _ => ys.isEmpty + } } \ No newline at end of file -- cgit v1.2.3