aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-12-22 18:13:35 +0100
committerMartin Odersky <odersky@gmail.com>2012-12-22 18:13:35 +0100
commit39ab8822039706b88373954a7e39919938d79f6f (patch)
tree2d23e004ccae345357135474303290c7a56c66c8 /src/dotty
parent78f0d5a0e0ea477087385277d217d9300c018aa0 (diff)
downloaddotty-39ab8822039706b88373954a7e39919938d79f6f.tar.gz
dotty-39ab8822039706b88373954a7e39919938d79f6f.tar.bz2
dotty-39ab8822039706b88373954a7e39919938d79f6f.zip
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.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala227
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala27
-rw-r--r--src/dotty/tools/dotc/core/Types.scala589
3 files changed, 403 insertions, 440 deletions
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("<none>")
@@ -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