aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala2
-rw-r--r--src/dotty/tools/dotc/core/Scopes.scala168
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala4
-rw-r--r--src/dotty/tools/dotc/core/SymbolLoaders.scala4
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala6
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala6
8 files changed, 112 insertions, 82 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 4af1fefa4..878cec877 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -25,7 +25,7 @@ class Definitions(implicit ctx: Context) {
import ctx.{requiredClass, requiredModule, requiredPackage}
- private def newSyntheticTypeParam(cls: ClassSymbol, scope: Scope, suffix: String = "T0") = {
+ private def newSyntheticTypeParam(cls: ClassSymbol, scope: MutableScope, suffix: String = "T0") = {
val tname = suffix.toTypeName.expandedName(cls)
val tparam = ctx.newSymbol(cls, tname, TypeParamCreationFlags, TypeBounds.empty)
scope.enter(tparam)
diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala
index 51e5419e6..89bdeb94b 100644
--- a/src/dotty/tools/dotc/core/Scopes.scala
+++ b/src/dotty/tools/dotc/core/Scopes.scala
@@ -42,12 +42,81 @@ object Scopes {
override def toString: String = sym.toString
}
- /** Note: constructor is protected to force everyone to use the factory methods newScope or newNestedScope instead.
+ /** A scope contains a set of symbols. It can be an extension
+ * of some outer scope, from which it inherits all symbols.
+ * This class does not have any methods to add symbols to a scope
+ * or to delete them. These methods are provided by subclass
+ * MutableScope.
+ */
+ abstract class Scope extends Iterable[Symbol] {
+ private[dotc] def lastEntry: ScopeEntry
+
+ /** The number of symbols in this scope (including inherited ones
+ * from outer scopes).
+ */
+ def size: Int
+
+ /** The number of outer scopes from which symbols are inherited */
+ def nestingLevel: Int
+
+ /** The symbols in this scope in the order they were entered;
+ * inherited from outer ones first.
+ */
+ def toList: List[Symbol]
+
+ /** Return all symbols as an iterator in the order they were entered in this scope.
+ */
+ def iterator: Iterator[Symbol] = toList.iterator
+
+ /** Returns a new scope with the same content as this one. */
+ def cloneScope(implicit ctx: Context): Scope
+
+ /** Is the scope empty? */
+ override def isEmpty: Boolean = lastEntry eq null
+
+ /** Lookup a symbol entry matching given name. */
+ def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry
+
+ /** Lookup next entry with same name as this one */
+ def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry
+
+ /** Lookup a symbol */
+ final def lookup(name: Name)(implicit ctx: Context): Symbol = {
+ val e = lookupEntry(name)
+ if (e eq null) NoSymbol else e.sym
+ }
+
+ /** Returns an iterator yielding every symbol with given name in this scope.
+ */
+ final def lookupAll(name: Name)(implicit ctx: Context): Iterator[Symbol] = new Iterator[Symbol] {
+ var e = lookupEntry(name)
+ def hasNext: Boolean = e ne null
+ def next(): Symbol = { val r = e.sym; e = lookupNextEntry(e); r }
+ }
+
+ /** The denotation set of all the symbols with given name in this scope */
+ final def denotsNamed(name: Name)(implicit ctx: Context): PreDenotation = {
+ var syms: PreDenotation = NoDenotation
+ var e = lookupEntry(name)
+ while (e != null) {
+ syms = syms union e.sym.denot
+ e = lookupNextEntry(e)
+ }
+ syms
+ }
+
+ /** Cast this scope to a mutable scope */
+ final def openForMutations: MutableScope = this.asInstanceOf[MutableScope]
+ }
+
+ /** A subclass of Scope that defines methods for entering and
+ * unlinking entries.
+ * Note: constructor is protected to force everyone to use the factory methods newScope or newNestedScope instead.
* This is necessary because when run from reflection every scope needs to have a
* SynchronizedScope as mixin.
*/
- class Scope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int = 0)
- extends Iterable[Symbol] {
+ class MutableScope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int = 0)
+ extends Scope {
protected[Scopes] def this(base: Scope)(implicit ctx: Context) = {
this(base.lastEntry, base.size, base.nestingLevel + 1)
@@ -61,7 +130,7 @@ object Scopes {
/** The size of the scope */
private[this] var _size = initSize
- override def size = _size
+ override final def size = _size
private def size_= (x: Int) = _size = x
/** the hash table
@@ -72,11 +141,7 @@ object Scopes {
*/
private var elemsCache: List[Symbol] = null
- /** Returns a new scope with the same content as this one. */
- def cloneScope(implicit ctx: Context): Scope = newScopeWith(this.toList: _*)
-
- /** is the scope empty? */
- override def isEmpty: Boolean = lastEntry eq null
+ def cloneScope(implicit ctx: Context): MutableScope = newScopeWith(this.toList: _*)
/** create and enter a scope entry */
protected def newScopeEntry(sym: Symbol)(implicit ctx: Context): ScopeEntry = {
@@ -100,20 +165,14 @@ object Scopes {
hashTable(i) = e
}
- /** enter a symbol
- *
- * @param sym ...
- */
- def enter[T <: Symbol](sym: T)(implicit ctx: Context): T = {
+ /** enter a symbol in this scope. */
+ final def enter[T <: Symbol](sym: T)(implicit ctx: Context): T = {
newScopeEntry(sym)
sym
}
- /** enter a symbol, asserting that no symbol with same name exists in scope
- *
- * @param sym ...
- */
- def enterUnique(sym: Symbol)(implicit ctx: Context) {
+ /** enter a symbol, asserting that no symbol with same name exists in scope */
+ final def enterUnique(sym: Symbol)(implicit ctx: Context) {
assert(lookup(sym.name) == NoSymbol, (sym.showLocated, lookup(sym.name).showLocated))
enter(sym)
}
@@ -146,7 +205,7 @@ object Scopes {
}
/** remove entry from this scope. */
- def unlink(e: ScopeEntry)(implicit ctx: Context) {
+ final def unlink(e: ScopeEntry)(implicit ctx: Context) {
if (lastEntry == e) {
lastEntry = e.prev
} else {
@@ -169,7 +228,7 @@ object Scopes {
}
/** remove symbol from this scope */
- def unlink(sym: Symbol)(implicit ctx: Context) {
+ final def unlink(sym: Symbol)(implicit ctx: Context) {
var e = lookupEntry(sym.name)
while (e ne null) {
if (e.sym == sym) unlink(e);
@@ -177,41 +236,12 @@ object Scopes {
}
}
- /** lookup a symbol
- *
- * @param name ...
- * @return ...
- */
- def lookup(name: Name)(implicit ctx: Context): Symbol = {
- val e = lookupEntry(name)
- if (e eq null) NoSymbol else e.sym
- }
-
- /** Returns an iterator yielding every symbol with given name in this scope.
- */
- def lookupAll(name: Name)(implicit ctx: Context): Iterator[Symbol] = new Iterator[Symbol] {
- var e = lookupEntry(name)
- def hasNext: Boolean = e ne null
- def next(): Symbol = { val r = e.sym; e = lookupNextEntry(e); r }
- }
-
- /** The denotation set of all the symbols with given name in this scope */
- def denotsNamed(name: Name)(implicit ctx: Context): PreDenotation = {
- var syms: PreDenotation = NoDenotation
- var e = lookupEntry(name)
- while (e != null) {
- syms = syms union e.sym.denot
- e = lookupNextEntry(e)
- }
- syms
- }
-
/** lookup a symbol entry matching given name.
* @note from Martin: I believe this is a hotspot or will be one
* in future versions of the type system. I have reverted the previous
* change to use iterators as too costly.
*/
- def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = {
+ override final def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = {
var e: ScopeEntry = null
if (hashTable ne null) {
e = hashTable(name.start & (hashTable.length - 1))
@@ -228,7 +258,7 @@ object Scopes {
}
/** lookup next entry with same name as this one */
- def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = {
+ override final def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = {
var e = entry
if (hashTable ne null)
do { e = e.tail } while ((e ne null) && e.sym.name != entry.sym.name)
@@ -239,7 +269,7 @@ object Scopes {
/** Return all symbols as a list in the order they were entered in this scope.
*/
- override def toList: List[Symbol] = {
+ override final def toList: List[Symbol] = {
if (elemsCache eq null) {
elemsCache = Nil
var e = lastEntry
@@ -253,54 +283,54 @@ object Scopes {
/** Vanilla scope - symbols are stored in declaration order.
*/
- def sorted: List[Symbol] = toList
-
- /** Return all symbols as an iterator in the order they were entered in this scope.
- */
- def iterator: Iterator[Symbol] = toList.iterator
+ final def sorted: List[Symbol] = toList
override def foreach[U](p: Symbol => U): Unit = toList foreach p
- def filteredScope(p: Symbol => Boolean)(implicit ctx: Context): Scope = {
+ final def filteredScope(p: Symbol => Boolean)(implicit ctx: Context): MutableScope = {
val unfiltered = toList
val filtered = unfiltered filterConserve p
if (filtered eq unfiltered) this
else newScopeWith(filtered: _*)
}
- def show(implicit ctx: Context): String = ctx.show(this)
+ final def show(implicit ctx: Context): String = ctx.show(this)
}
/** Create a new scope */
- def newScope: Scope = new Scope()
+ def newScope: MutableScope = new MutableScope()
/** Create a new scope nested in another one with which it shares its elements */
- def newNestedScope(outer: Scope)(implicit ctx: Context): Scope = new Scope(outer)
+ def newNestedScope(outer: Scope)(implicit ctx: Context): MutableScope = new MutableScope(outer)
/** Create a new scope with given initial elements */
- def newScopeWith(elems: Symbol*)(implicit ctx: Context): Scope = {
+ def newScopeWith(elems: Symbol*)(implicit ctx: Context): MutableScope = {
val scope = newScope
elems foreach scope.enter
scope
}
/** Create new scope for the members of package `pkg` */
- def newPackageScope(pkgClass: Symbol): Scope = newScope
+ def newPackageScope(pkgClass: Symbol): MutableScope = newScope
/** Transform scope of members of `owner` using operation `op`
* This is overridden by the reflective compiler to avoid creating new scopes for packages
*/
- def scopeTransform(owner: Symbol)(op: => Scope): Scope = op
+ def scopeTransform(owner: Symbol)(op: => MutableScope): MutableScope = op
/** The empty scope (immutable).
*/
object EmptyScope extends Scope {
- override def newScopeEntry(sym: Symbol)(implicit ctx: Context): ScopeEntry = {
- throw new AssertionError("EmptyScope.newScopeEntry")
- }
+ override def lastEntry = null
+ override def size = 0
+ override def nestingLevel = 0
+ override def toList = Nil
+ override def cloneScope(implicit ctx: Context): Scope = this
+ override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = null
+ override def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = null
}
/** The error scope (mutable)
*/
- class ErrorScope(owner: Symbol) extends Scope
+ class ErrorScope(owner: Symbol) extends MutableScope
}
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 975c4d6f1..144432245 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -722,7 +722,7 @@ object SymDenotations {
*/
def enter(sym: Symbol)(implicit ctx: Context) = {
require(!(this is Frozen))
- info.decls enter sym
+ info.decls.openForMutations.enter(sym)
if (_definedFingerPrint != null)
includeName(_definedFingerPrint, sym.name)
if (_memberCache != null)
@@ -735,7 +735,7 @@ object SymDenotations {
*/
def delete(sym: Symbol)(implicit ctx: Context) = {
require(!(this is Frozen))
- info.decls unlink sym
+ info.decls.openForMutations.unlink(sym)
if (_definedFingerPrint != null)
computeDefinedFingerPrint
if (_memberCache != null)
diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala
index 59835beda..9559db68a 100644
--- a/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -20,7 +20,7 @@ class SymbolLoaders {
protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader)(implicit ctx: Context): Symbol = {
assert(owner.info.decls.lookup(member.name) == NoSymbol, owner.fullName + "." + member.name)
- owner.info.decls enter member
+ owner.asClass.enter(member)
member
}
@@ -57,7 +57,7 @@ class SymbolLoaders {
else if (ctx.settings.termConflict.value == "package") {
ctx.warning(
s"Resolving package/object name conflict in favor of package ${preExisting.fullName}. The object will be inaccessible.")
- owner.info.decls.unlink(preExisting)
+ owner.asClass.delete(preExisting)
} else {
ctx.warning(
s"Resolving package/object name conflict in favor of object ${preExisting.fullName}. The package will be inaccessible.")
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index 2491e2ff9..90b9837ca 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -318,7 +318,7 @@ object Symbols {
def superId: Int = -1
final def entered(implicit ctx: Context): this.type = {
- this.owner.info.decls.enter(this)
+ this.owner.asClass.enter(this)
this
}
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index a8c9af32d..6628aa824 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -197,7 +197,7 @@ trait TypeOps { this: Context =>
* to a list of typerefs, by converting all refinements to member
* definitions in scope `decls`. Can add members to `decls` as a side-effect.
*/
- def normalizeToRefs(parents: List[Type], cls: ClassSymbol, decls: Scope): List[TypeRef] = {
+ def normalizeToRefs(parents: List[Type], cls: ClassSymbol, decls: MutableScope): List[TypeRef] = {
var refinements = Map[TypeName, Type]()
var formals = Map[TypeName, Symbol]()
def normalizeToRef(tp: Type): TypeRef = tp match {
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index 685ece6cb..5fbafb431 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -26,8 +26,8 @@ class ClassfileParser(
protected val staticModule: Symbol = moduleRoot.sourceModule
- protected val instanceScope: Scope = newScope // the scope of all instance definitions
- protected val staticScope: Scope = newScope // the scope of all static definitions
+ protected val instanceScope: MutableScope = newScope // the scope of all instance definitions
+ protected val staticScope: MutableScope = newScope // the scope of all static definitions
protected var pool: ConstantPool = _ // the classfile's constant pool
protected var currentClassName: Name = _ // JVM name of the current class
@@ -707,7 +707,7 @@ class ClassfileParser(
protected def getOwner(flags: Int): Symbol =
if (isStatic(flags)) moduleRoot.symbol else classRoot.symbol
- protected def getScope(flags: Int): Scope =
+ protected def getScope(flags: Int): MutableScope =
if (isStatic(flags)) staticScope else instanceScope
private def setPrivateWithin(denot: SymDenotation, jflags: Int) {
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 9edc8cb84..55ed9b63d 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -24,7 +24,7 @@ object UnPickler {
case class TempPolyType(tparams: List[Symbol], tpe: Type) extends UncachedGroundType
/** Temporary type for classinfos, will be decomposed on completion of the class */
- case class TempClassInfoType(parentTypes: List[Type], decls: Scope, clazz: Symbol) extends UncachedGroundType
+ case class TempClassInfoType(parentTypes: List[Type], decls: MutableScope, clazz: Symbol) extends UncachedGroundType
def depoly(tp: Type)(implicit ctx: Context): Type = tp match {
case TempPolyType(tparams, restpe) => PolyType.fromSymbols(tparams, restpe)
@@ -356,7 +356,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleRoot: Clas
isUnpickleRoot(sym) ||
(sym is (ModuleClass | TypeParam | Scala2Existential)) ||
isRefinementClass(sym)))
- symScope(sym.owner) enter sym
+ symScope(sym.owner).openForMutations.enter(sym)
sym
}
@@ -519,7 +519,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleRoot: Clas
}
case CLASSINFOtpe =>
val clazz = readSymbolRef()
- TempClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)
+ TempClassInfoType(until(end, readTypeRef), symScope(clazz).openForMutations, clazz)
case METHODtpe | IMPLICITMETHODtpe =>
val restpe = readTypeRef()
val params = until(end, readSymbolRef)