diff options
Diffstat (limited to 'src')
37 files changed, 718 insertions, 337 deletions
diff --git a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala b/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala index 38277b5a09..53e89b3d1e 100644 --- a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala @@ -29,7 +29,10 @@ trait BaseTypeSeqs { this: SymbolTable => import definitions._ - class BaseTypeSeq(parents: List[Type], elems: Array[Type]) { + protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) = + new BaseTypeSeq(parents, elems) + + class BaseTypeSeq(private[BaseTypeSeqs] val parents: List[Type], private[BaseTypeSeqs] val elems: Array[Type]) { self => incCounter(baseTypeSeqCount) incCounter(baseTypeSeqLenTotal, elems.length) @@ -41,7 +44,7 @@ trait BaseTypeSeqs { // (while NoType is in there to indicate a cycle in this BTS, during the execution of // the mergePrefixAndArgs below, the elems get copied without the pending map, // so that NoType's are seen instead of the original type --> spurious compile error) - val pending = new mutable.BitSet(length) + private val pending = new mutable.BitSet(length) /** The type at i'th position in this sequence; lazy types are returned evaluated. */ def apply(i: Int): Type = @@ -89,11 +92,11 @@ trait BaseTypeSeqs { /** Return all evaluated types in this sequence as a list */ def toList: List[Type] = elems.toList - protected def copy(head: Type, offset: Int): BaseTypeSeq = { + def copy(head: Type, offset: Int): BaseTypeSeq = { val arr = new Array[Type](elems.length + offset) compat.Platform.arraycopy(elems, 0, arr, offset, elems.length) arr(0) = head - new BaseTypeSeq(parents, arr) + newBaseTypeSeq(parents, arr) } /** Compute new base type sequence with `tp` prepended to this sequence */ @@ -113,21 +116,10 @@ trait BaseTypeSeqs { arr(i) = f(elems(i)) i += 1 } - new BaseTypeSeq(parents, arr) + newBaseTypeSeq(parents, arr) } - def lateMap(f: Type => Type): BaseTypeSeq = new BaseTypeSeq(parents map f, elems) { - override def apply(i: Int) = f(self.apply(i)) - override def rawElem(i: Int) = f(self.rawElem(i)) - override def typeSymbol(i: Int) = self.typeSymbol(i) - override def toList = self.toList map f - override protected def copy(head: Type, offset: Int) = (self map f).copy(head, offset) - override def map(g: Type => Type) = lateMap(g) - override def lateMap(g: Type => Type) = self.lateMap(x => g(f(x))) - override def exists(p: Type => Boolean) = elems exists (x => p(f(x))) - override protected def maxDepthOfElems: Int = elems map (x => maxDpth(f(x))) max - override def toString = elems.mkString("MBTS(", ",", ")") - } + def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f) def exists(p: Type => Boolean): Boolean = elems exists p @@ -177,10 +169,10 @@ trait BaseTypeSeqs { /** A merker object for a base type sequence that's no yet computed. * used to catch inheritance cycles */ - val undetBaseTypeSeq: BaseTypeSeq = new BaseTypeSeq(List(), Array()) + val undetBaseTypeSeq: BaseTypeSeq = newBaseTypeSeq(List(), Array()) /** Create a base type sequence consisting of a single type */ - def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = new BaseTypeSeq(List(), Array(tp)) + def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = newBaseTypeSeq(List(), Array(tp)) /** Create the base type sequence of a compound type wuth given tp.parents */ def compoundBaseTypeSeq(tp: Type): BaseTypeSeq = { @@ -244,8 +236,21 @@ trait BaseTypeSeqs { val elems = new Array[Type](btsSize) buf.copyToArray(elems, 0) // Console.println("computed baseTypeSeq of " + tsym.tpe + " " + parents + ": "+elems.toString)//DEBUG - new BaseTypeSeq(parents, elems) + newBaseTypeSeq(parents, elems) } - + + class MappedBaseTypeSeq(orig: BaseTypeSeq, f: Type => Type) extends BaseTypeSeq(orig.parents map f, orig.elems) { + override def apply(i: Int) = f(orig.apply(i)) + override def rawElem(i: Int) = f(orig.rawElem(i)) + override def typeSymbol(i: Int) = orig.typeSymbol(i) + override def toList = orig.toList map f + override def copy(head: Type, offset: Int) = (orig map f).copy(head, offset) + override def map(g: Type => Type) = lateMap(g) + override def lateMap(g: Type => Type) = orig.lateMap(x => g(f(x))) + override def exists(p: Type => Boolean) = elems exists (x => p(f(x))) + override protected def maxDepthOfElems: Int = elems map (x => maxDpth(f(x))) max + override def toString = elems.mkString("MBTS(", ",", ")") + } + val CyclicInheritance = new Throwable } diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index d38b62cbb4..a733f0d1ee 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -16,7 +16,7 @@ trait Definitions extends reflect.api.StandardDefinitions { private def newClass(owner: Symbol, name: TypeName, parents: List[Type], flags: Long = 0L): Symbol = { val clazz = owner.newClassSymbol(name, NoPosition, flags) - clazz setInfoAndEnter ClassInfoType(parents, new Scope, clazz) + clazz setInfoAndEnter ClassInfoType(parents, newScope, clazz) } private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): Symbol = { val msym = owner.newMethod(name.encode, NoPosition, flags) @@ -206,7 +206,7 @@ trait Definitions extends reflect.api.StandardDefinitions { sealed abstract class BottomClassSymbol(name: TypeName, parent: Symbol) extends ClassSymbol(ScalaPackageClass, NoPosition, name) { locally { this initFlags ABSTRACT | TRAIT | FINAL - this setInfoAndEnter ClassInfoType(List(parent.tpe), new Scope, this) + this setInfoAndEnter ClassInfoType(List(parent.tpe), newScope, this) } final override def isBottomClass = true } @@ -352,7 +352,7 @@ trait Definitions extends reflect.api.StandardDefinitions { ) lazy val EqualsPatternClass = { val clazz = newClass(ScalaPackageClass, tpnme.EQUALS_PATTERN_NAME, Nil) - clazz setInfo polyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, new Scope, clazz)) + clazz setInfo polyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, newScope, clazz)) } lazy val MatchingStrategyClass = getRequiredClass("scala.MatchingStrategy") @@ -823,7 +823,7 @@ trait Definitions extends reflect.api.StandardDefinitions { clazz.setInfo( polyType( List(tparam), - ClassInfoType(List(AnyRefClass.tpe, p), new Scope, clazz))) + ClassInfoType(List(AnyRefClass.tpe, p), newScope, clazz))) } private def newAlias(owner: Symbol, name: TypeName, alias: Type): Symbol = diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 53380952c0..23b443919a 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -210,9 +210,9 @@ trait Importers { self: SymbolTable => result } - // !!! todo: override to vcater for PackageScopes + // !!! todo: override to cater for PackageScopes def importScope(decls: from.Scope): Scope = - new Scope(decls.toList map importSymbol) + newScopeWith(decls.toList map importSymbol: _*) def importName(name: from.Name): Name = if (name.isTypeName) newTypeName(name.toString) else newTermName(name.toString) diff --git a/src/compiler/scala/reflect/internal/Scopes.scala b/src/compiler/scala/reflect/internal/Scopes.scala index fb3012adff..8861386bc8 100644 --- a/src/compiler/scala/reflect/internal/Scopes.scala +++ b/src/compiler/scala/reflect/internal/Scopes.scala @@ -37,9 +37,14 @@ trait Scopes extends api.Scopes { self: SymbolTable => def unapplySeq(decls: Scope): Some[Seq[Symbol]] = Some(decls.toList) } - class Scope(initElems: ScopeEntry) extends Iterable[Symbol] { + class Scope(initElems: ScopeEntry = null) extends Iterable[Symbol] { + + def this(base: Scope) = { + this(base.elems) + nestinglevel = base.nestinglevel + 1 + } - var elems: ScopeEntry = initElems + private[scala] var elems: ScopeEntry = initElems /** The number of times this scope is nested in another */ @@ -65,20 +70,8 @@ trait Scopes extends api.Scopes { self: SymbolTable => if (size >= MIN_HASH) createHash() - def this() = this(null: ScopeEntry) - - def this(base: Scope) = { - this(base.elems) - nestinglevel = base.nestinglevel + 1 - } - - def this(decls: List[Symbol]) = { - this() - decls foreach enter - } - /** Returns a new scope with the same content as this one. */ - def cloneScope: Scope = new Scope(this.toList) + def cloneScope: Scope = newScopeWith(this.toList: _*) /** is the scope empty? */ override def isEmpty: Boolean = elems eq null @@ -311,7 +304,7 @@ trait Scopes extends api.Scopes { self: SymbolTable => override def foreach[U](p: Symbol => U): Unit = toList foreach p override def filter(p: Symbol => Boolean): Scope = - if (!(toList forall p)) new Scope(toList filter p) else this + if (!(toList forall p)) newScopeWith(toList filter p: _*) else this override def mkString(start: String, sep: String, end: String) = toList.map(_.defString).mkString(start, sep, end) @@ -321,21 +314,26 @@ trait Scopes extends api.Scopes { self: SymbolTable => } /** Create a new scope */ - def newScope: Scope = new Scope + def newScope: Scope = new Scope() + + /** Create a new scope nested in another one with which it shares its elements */ + def newNestedScope(outer: Scope): Scope = new Scope(outer) + + /** Create a new scope with given initial elements */ + def newScopeWith(elems: Symbol*): Scope = { + val scope = newScope + elems foreach scope.enter + scope + } /** Create new scope for the members of package `pkg` */ - def newPackageScope(pkgClass: Symbol): Scope = new Scope + def newPackageScope(pkgClass: Symbol): Scope = 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 newScopeWith(elems: Symbol*): Scope = { - val scope = newScope - elems foreach scope.enter - scope - } /** The empty scope (immutable). */ @@ -347,7 +345,7 @@ trait Scopes extends api.Scopes { self: SymbolTable => /** The error scope. */ - class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry) + class ErrorScope(owner: Symbol) extends Scope private final val maxRecursions = 1000 diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala index ace4d55b90..717693fa1f 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/compiler/scala/reflect/internal/SymbolTable.scala @@ -271,4 +271,9 @@ abstract class SymbolTable extends api.Universe /** The phase which has given index as identifier. */ val phaseWithId: Array[Phase] + + /** Is this symbol table part of reflexive mirror? In this case + * operations need to be made thread safe. + */ + def inReflexiveMirror = false } diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index b4d2b1531f..ecd2de6f56 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -16,10 +16,13 @@ import api.Modifier trait Symbols extends api.Symbols { self: SymbolTable => import definitions._ - private var ids = 0 + protected var ids = 0 + + val emptySymbolArray = new Array[Symbol](0) + def symbolCount = ids // statistics - val emptySymbolArray = new Array[Symbol](0) + protected def nextId() = { ids += 1; ids } /** Used for deciding in the IDE whether we can interrupt the compiler */ //protected var activeLocks = 0 @@ -31,7 +34,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => private var recursionTable = immutable.Map.empty[Symbol, Int] private var nextexid = 0 - private def freshExistentialName(suffix: String) = { + protected def freshExistentialName(suffix: String) = { nextexid += 1 newTypeName("_" + nextexid + suffix) } @@ -42,6 +45,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => m setModuleClass moduleClass m } + /** Create a new free variable. Its owner is NoSymbol. */ def newFreeVar(name: TermName, tpe: Type, value: Any, newFlags: Long = 0L): FreeVar = @@ -77,14 +81,24 @@ trait Symbols extends api.Symbols { self: SymbolTable => type AccessBoundaryType = Symbol type AnnotationType = AnnotationInfo - var rawowner = initOwner - var rawname = initName - var rawflags = 0L - + private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api + private[this] var _rawname = initName + private[this] var _rawflags = 0L + + def rawowner = _rawowner + def rawname = _rawname + def rawflags = _rawflags + + protected def rawflags_=(x: FlagsType) { _rawflags = x } + private var rawpos = initPos - val id = { ids += 1; ids } // identity displayed when -uniqid + + val id = nextId() // identity displayed when -uniqid - var validTo: Period = NoPeriod + private[this] var _validTo: Period = NoPeriod + + def validTo = _validTo + def validTo_=(x: Period) { _validTo = x} def pos = rawpos def setPos(pos: Position): this.type = { this.rawpos = pos; this } @@ -336,7 +350,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => // True if the symbol is unlocked. // True if the symbol is locked but still below the allowed recursion depth. // False otherwise - def lockOK: Boolean = { + private[scala] def lockOK: Boolean = { ((rawflags & LOCKED) == 0L) || ((settings.Yrecursion.value != 0) && (recursionTable get this match { @@ -345,7 +359,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } // Lock a symbol, using the handler if the recursion depth becomes too great. - def lock(handler: => Unit) = { + private[scala] def lock(handler: => Unit) = { if ((rawflags & LOCKED) != 0L) { if (settings.Yrecursion.value != 0) { recursionTable get this match { @@ -360,18 +374,18 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } else { handler } } else { - rawflags |= LOCKED + _rawflags |= LOCKED // activeLocks += 1 // lockedSyms += this } } // Unlock a symbol - def unlock() = { + private[scala] def unlock() = { if ((rawflags & LOCKED) != 0L) { // activeLocks -= 1 // lockedSyms -= this - rawflags = rawflags & ~LOCKED + _rawflags = rawflags & ~LOCKED if (settings.Yrecursion.value != 0) recursionTable -= this } @@ -736,7 +750,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ------ owner attribute -------------------------------------------------------------- def owner: Symbol = rawowner - final def owner_=(owner: Symbol) { + def owner_=(owner: Symbol) { // don't keep the original owner in presentation compiler runs // (the map will grow indefinitely, and the only use case is the // backend). @@ -744,8 +758,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (originalOwner contains this) () else originalOwner(this) = rawowner } - - rawowner = owner + assert(!inReflexiveMirror, "owner_= is not thread-safe; cannot be run in reflexive code") + _rawowner = owner } def ownerChain: List[Symbol] = this :: owner.ownerChain @@ -778,7 +792,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def name: Name = rawname - final def name_=(name: Name) { + def name_=(name: Name) { if (name != rawname) { if (owner.isClass) { var ifs = owner.infos @@ -787,7 +801,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => ifs = ifs.prev } } - rawname = name + _rawname = name } } @@ -855,20 +869,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => val fs = rawflags & phase.flagMask (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift) } - final def flags_=(fs: Long) = rawflags = fs + def flags_=(fs: Long) = _rawflags = fs /** Set the symbol's flags to the given value, asserting * that the previous value was 0. */ def initFlags(mask: Long): this.type = { assert(rawflags == 0L, this) - rawflags = mask + _rawflags = mask this } - def setFlag(mask: Long): this.type = { rawflags = rawflags | mask ; this } - def resetFlag(mask: Long): this.type = { rawflags = rawflags & ~mask ; this } + def setFlag(mask: Long): this.type = { _rawflags = rawflags | mask ; this } + def resetFlag(mask: Long): this.type = { _rawflags = rawflags & ~mask ; this } final def getFlag(mask: Long): Long = flags & mask - final def resetFlags() { rawflags = rawflags & TopLevelCreationFlags } + final def resetFlags() { _rawflags = rawflags & TopLevelCreationFlags } /** Does symbol have ANY flag in `mask` set? */ final def hasFlag(mask: Long): Boolean = (flags & mask) != 0L @@ -954,7 +968,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => throw CyclicReference(this, tp) } } else { - rawflags |= LOCKED + _rawflags |= LOCKED // activeLocks += 1 // lockedSyms += this } @@ -984,7 +998,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => assert(info ne null) infos = TypeHistory(currentPeriod, info, null) unlock() - validTo = if (info.isComplete) currentPeriod else NoPeriod + _validTo = if (info.isComplete) currentPeriod else NoPeriod } /** Set initial info. */ @@ -1003,11 +1017,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** Set new info valid from start of this phase. */ - final def updateInfo(info: Type): Symbol = { + def updateInfo(info: Type): Symbol = { assert(phaseId(infos.validFrom) <= phase.id) if (phaseId(infos.validFrom) == phase.id) infos = infos.prev infos = TypeHistory(currentPeriod, info, infos) - validTo = if (info.isComplete) currentPeriod else NoPeriod + _validTo = if (info.isComplete) currentPeriod else NoPeriod this } @@ -1045,11 +1059,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => infos = TypeHistory(currentPeriod + 1, info1, infos) this.infos = infos } - validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform + _validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform itr = itr.next } - validTo = if (itr.pid == NoPhase.id) curPeriod - else period(currentRunId, itr.pid) + _validTo = if (itr.pid == NoPhase.id) curPeriod + else period(currentRunId, itr.pid) } } finally { phase = current @@ -1060,7 +1074,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => } // adapt to new run in fsc. - private def adaptInfos(infos: TypeHistory): TypeHistory = + private def adaptInfos(infos: TypeHistory): TypeHistory = { + assert(!inReflexiveMirror) if (infos == null || runId(infos.validFrom) == currentRunId) { infos } else { @@ -1069,7 +1084,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else { val pid = phaseId(infos.validFrom) - validTo = period(currentRunId, pid) + _validTo = period(currentRunId, pid) phase = phaseWithId(pid) val info1 = ( @@ -1085,6 +1100,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } } + } /** Initialize the symbol */ final def initialize: this.type = { @@ -1094,6 +1110,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Was symbol's type updated during given phase? */ final def isUpdatedAt(pid: Phase#Id): Boolean = { + assert(!inReflexiveMirror) var infos = this.infos while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev infos ne null @@ -1101,6 +1118,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Was symbol's type updated during given phase? */ final def hasTypeAt(pid: Phase#Id): Boolean = { + assert(!inReflexiveMirror) var infos = this.infos while ((infos ne null) && phaseId(infos.validFrom) > pid) infos = infos.prev infos ne null @@ -1212,7 +1230,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def reset(completer: Type) { resetFlags() infos = null - validTo = NoPeriod + _validTo = NoPeriod //limit = NoPhase.id setInfo(completer) } @@ -1239,7 +1257,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ----- annotations ------------------------------------------------------------ // null is a marker that they still need to be obtained. - private var _annotations: List[AnnotationInfo] = Nil + private[this] var _annotations: List[AnnotationInfo] = Nil def annotationsString = if (annotations.isEmpty) "" else annotations.mkString("(", ", ", ")") @@ -2053,8 +2071,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def name: TermName = rawname.toTermName privateWithin = NoSymbol - var referenced: Symbol = NoSymbol - + private[this] var _referenced: Symbol = NoSymbol + + def referenced: Symbol = _referenced + def referenced_=(x: Symbol) { _referenced = x } + def existentialBound = singletonBounds(this.tpe) def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = @@ -2226,7 +2247,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A class of type symbols. Alias and abstract types are direct instances * of this class. Classes are instances of a subclass. */ - sealed abstract class TypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) extends Symbol(initOwner, initPos, initName) { + abstract class TypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) extends Symbol(initOwner, initPos, initName) { privateWithin = NoSymbol private var tyconCache: Type = null private var tyconRunId = NoRunId @@ -2395,9 +2416,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A class for class symbols */ class ClassSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { - private var flatname: TypeName = null - private var source: AbstractFileType = null - private var thissym: Symbol = this + private[this] var flatname: TypeName = null + private[this] var source: AbstractFileType = null + private[this] var thissym: Symbol = this final override def isClass = true final override def isNonClassType = false @@ -2459,7 +2480,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } typeOfThisCache } - else thissym.tpe + else thisSym.tpe } /** Sets the self type of the class */ @@ -2479,7 +2500,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def sourceModule = if (isModuleClass) companionModule else NoSymbol - private var childSet: Set[Symbol] = Set() + private[this] var childSet: Set[Symbol] = Set() override def children = childSet override def addChild(sym: Symbol) { childSet = childSet + sym } @@ -2523,10 +2544,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** An object representing a missing symbol */ - object NoSymbol extends Symbol(null, NoPosition, nme.NO_NAME) { - setInfo(NoType) - privateWithin = this - override def info_=(info: Type) { + class NoSymbol extends Symbol(null, NoPosition, nme.NO_NAME) { + synchronized { + setInfo(NoType) + privateWithin = this + } + override def info_=(info: Type) = { infos = TypeHistory(1, NoType, null) unlock() validTo = currentPeriod @@ -2553,6 +2576,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def originalEnclosingMethod = this } + protected def makeNoSymbol = new NoSymbol + + lazy val NoSymbol = makeNoSymbol + /** Derives a new list of symbols from the given list by mapping the given * list across the given function. Then fixes the info of all the new symbols * by substituting the new symbols for the original symbols. diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 73f1f3db84..4f4715498e 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -109,15 +109,19 @@ trait Types extends api.Types { self: SymbolTable => /** A log of type variable with their original constraints. Used in order * to undo constraints in the case of isSubType/isSameType failure. */ - object undoLog { - private type UndoLog = List[(TypeVar, TypeConstraint)] - private[scala] var log: UndoLog = List() - + lazy val undoLog = newUndoLog + + protected def newUndoLog = new UndoLog + + class UndoLog { + private type UndoPairs = List[(TypeVar, TypeConstraint)] + private var log: UndoPairs = List() + // register with the auto-clearing cache manager perRunCaches.recordCache(this) /** Undo all changes to constraints to type variables upto `limit`. */ - private def undoTo(limit: UndoLog) { + private def undoTo(limit: UndoPairs) { while ((log ne limit) && log.nonEmpty) { val (tv, constr) = log.head tv.constr = constr @@ -125,9 +129,14 @@ trait Types extends api.Types { self: SymbolTable => } } - private[Types] def record(tv: TypeVar) = { + /** No sync necessary, because record should only + * be called from within a undo or undoUnless block, + * which is already synchronized. + */ + private[reflect] def record(tv: TypeVar) = { log ::= ((tv, tv.constr.cloneInternal)) } + private[scala] def clear() { if (settings.debug.value) self.log("Clearing " + log.size + " entries from the undoLog.") @@ -249,8 +258,7 @@ trait Types extends api.Types { self: SymbolTable => abstract class AbsTypeImpl extends AbsType { this: Type => def declaration(name: Name): Symbol = decl(name) def nonPrivateDeclaration(name: Name): Symbol = nonPrivateDecl(name) - def allDeclarations = decls - def allMembers = members + def declarations = decls def typeArguments = typeArgs def erasedType = transformedType(this) } @@ -873,16 +881,7 @@ trait Types extends api.Types { self: SymbolTable => * after `maxTostringRecursions` recursion levels. Uses `safeToString` * to produce a string on each level. */ - override def toString: String = - if (tostringRecursions >= maxTostringRecursions) - "..." - else - try { - tostringRecursions += 1 - safeToString - } finally { - tostringRecursions -= 1 - } + override def toString: String = typeToString(this) /** Method to be implemented in subclasses. * Converts this type to a string in calling toString for its parts. @@ -992,7 +991,9 @@ trait Types extends api.Types { self: SymbolTable => if (membertpe eq null) membertpe = self.memberType(member) (membertpe matches self.memberType(sym)) })) { - members = new Scope(List(member, sym)) + members = newScope + members enter member + members enter sym } } else { var prevEntry = members.lookupEntry(sym.name) @@ -1105,7 +1106,7 @@ trait Types extends api.Types { self: SymbolTable => /** A base class for types that represent a single value * (single-types and this-types). */ - abstract class SingletonType extends SubType with SimpleTypeProxy with AbsSingletonType { + abstract class SingletonType extends SubType with SimpleTypeProxy { def supertype = underlying override def isTrivial = false override def isStable = true @@ -1231,18 +1232,15 @@ trait Types extends api.Types { self: SymbolTable => override val isTrivial: Boolean = pre.isTrivial // override def isNullable = underlying.isNullable override def isNotNull = underlying.isNotNull - private var underlyingCache: Type = NoType - private var underlyingPeriod = NoPeriod + private[reflect] var underlyingCache: Type = NoType + private[reflect] var underlyingPeriod = NoPeriod override def underlying: Type = { - val period = underlyingPeriod - if (period != currentPeriod) { - underlyingPeriod = currentPeriod - if (!isValid(period)) { - underlyingCache = pre.memberType(sym).resultType; - assert(underlyingCache ne this, this) - } + val cache = underlyingCache + if (underlyingPeriod == currentPeriod && cache != null) cache + else { + defineUnderlyingOfSingleType(this) + underlyingCache } - underlyingCache } // more precise conceptually, but causes cyclic errors: (paramss exists (_ contains sym)) @@ -1281,6 +1279,17 @@ trait Types extends api.Types { self: SymbolTable => unique(new UniqueSingleType(pre, sym)) } } + + protected def defineUnderlyingOfSingleType(tpe: SingleType) = { + val period = tpe.underlyingPeriod + if (period != currentPeriod) { + tpe.underlyingPeriod = currentPeriod + if (!isValid(period)) { + tpe.underlyingCache = tpe.pre.memberType(tpe.sym).resultType; + assert(tpe.underlyingCache ne tpe, tpe) + } + } + } abstract case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType { override val isTrivial: Boolean = thistpe.isTrivial && supertpe.isTrivial @@ -1333,105 +1342,30 @@ trait Types extends api.Types { self: SymbolTable => */ abstract class CompoundType extends Type { - var baseTypeSeqCache: BaseTypeSeq = _ - private var baseTypeSeqPeriod = NoPeriod - private var baseClassesCache: List[Symbol] = _ - private var baseClassesPeriod = NoPeriod + private[reflect] var baseTypeSeqCache: BaseTypeSeq = _ + private[reflect] var baseTypeSeqPeriod = NoPeriod + private[reflect] var baseClassesCache: List[Symbol] = _ + private[reflect] var baseClassesPeriod = NoPeriod override def baseTypeSeq: BaseTypeSeq = { - val period = baseTypeSeqPeriod; - if (period != currentPeriod) { // no caching in IDE - baseTypeSeqPeriod = currentPeriod - if (!isValidForBaseClasses(period)) { - if (parents.exists(_.exists(_.isInstanceOf[TypeVar]))) { - // rename type vars to fresh type params, take base type sequence of - // resulting type, and rename back all the entries in that sequence - var tvs = Set[TypeVar]() - for (p <- parents) - for (t <- p) t match { - case tv: TypeVar => tvs += tv - case _ => - } - val varToParamMap: Map[Type, Symbol] = tvs map (tv => tv -> tv.origin.typeSymbol.cloneSymbol) toMap - val paramToVarMap = varToParamMap map (_.swap) - val varToParam = new TypeMap { - def apply(tp: Type) = varToParamMap get tp match { - case Some(sym) => sym.tpe - case _ => mapOver(tp) - } - } - val paramToVar = new TypeMap { - def apply(tp: Type) = tp match { - case TypeRef(_, tsym, _) if paramToVarMap.isDefinedAt(tsym) => paramToVarMap(tsym) - case _ => mapOver(tp) - } - } - val bts = copyRefinedType(this.asInstanceOf[RefinedType], parents map varToParam, varToParam mapOver decls).baseTypeSeq - baseTypeSeqCache = bts lateMap paramToVar - } else { - incCounter(compoundBaseTypeSeqCount) - baseTypeSeqCache = undetBaseTypeSeq - baseTypeSeqCache = if (typeSymbol.isRefinementClass) - memo(compoundBaseTypeSeq(this))(_.baseTypeSeq updateHead typeSymbol.tpe) - else - compoundBaseTypeSeq(this) - // [Martin] suppressing memo-ization solves the problem with "same type after erasure" errors - // when compiling with - // scalac scala.collection.IterableViewLike.scala scala.collection.IterableLike.scala - // I have not yet figured out precisely why this is the case. - // My current assumption is that taking memos forces baseTypeSeqs to be computed - // at stale types (i.e. the underlying typeSymbol has already another type). - // I do not yet see precisely why this would cause a problem, but it looks - // fishy in any case. - } - } - //Console.println("baseTypeSeq(" + typeSymbol + ") = " + baseTypeSeqCache.toList);//DEBUG + val cached = baseTypeSeqCache + if (baseTypeSeqPeriod == currentPeriod && cached != null && cached != undetBaseTypeSeq) + cached + else { + defineBaseTypeSeqOfCompoundType(this) + baseTypeSeqCache } - if (baseTypeSeqCache eq undetBaseTypeSeq) - throw new TypeError("illegal cyclic inheritance involving " + typeSymbol) - baseTypeSeqCache } override def baseTypeSeqDepth: Int = baseTypeSeq.maxDepth override def baseClasses: List[Symbol] = { - def computeBaseClasses: List[Symbol] = - if (parents.isEmpty) List(typeSymbol) - else { - //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG - // optimized, since this seems to be performance critical - val superclazz = parents.head - var mixins = parents.tail - val sbcs = superclazz.baseClasses - var bcs = sbcs - def isNew(clazz: Symbol): Boolean = ( - superclazz.baseTypeIndex(clazz) < 0 && - { var p = bcs; - while ((p ne sbcs) && (p.head != clazz)) p = p.tail; - p eq sbcs - } - ); - while (!mixins.isEmpty) { - def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] = - if (mbcs.isEmpty) bcs - else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail) - else addMixinBaseClasses(mbcs.tail); - bcs = addMixinBaseClasses(mixins.head.baseClasses) - mixins = mixins.tail - } - typeSymbol :: bcs - } - val period = baseClassesPeriod - if (period != currentPeriod) { - baseClassesPeriod = currentPeriod - if (!isValidForBaseClasses(period)) { - baseClassesCache = null - baseClassesCache = memo(computeBaseClasses)(typeSymbol :: _.baseClasses.tail) - } + val cached = baseClassesCache + if (baseClassesPeriod == currentPeriod && cached != null) cached + else { + defineBaseClassesOfCompoundType(this) + baseClassesCache } - if (baseClassesCache eq null) - throw new TypeError("illegal cyclic reference involving " + typeSymbol) - baseClassesCache } /** The slightly less idiomatic use of Options is due to @@ -1475,6 +1409,97 @@ trait Types extends api.Types { self: SymbolTable => (if (settings.debug.value || parents.isEmpty || (decls.elems ne null)) decls.mkString("{", "; ", "}") else "") } + + protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = { + val period = tpe.baseTypeSeqPeriod; + if (period != currentPeriod) { + tpe.baseTypeSeqPeriod = currentPeriod + if (!isValidForBaseClasses(period)) { + if (tpe.parents.exists(_.exists(_.isInstanceOf[TypeVar]))) { + // rename type vars to fresh type params, take base type sequence of + // resulting type, and rename back all the entries in that sequence + var tvs = Set[TypeVar]() + for (p <- tpe.parents) + for (t <- p) t match { + case tv: TypeVar => tvs += tv + case _ => + } + val varToParamMap: Map[Type, Symbol] = tvs map (tv => tv -> tv.origin.typeSymbol.cloneSymbol) toMap + val paramToVarMap = varToParamMap map (_.swap) + val varToParam = new TypeMap { + def apply(tp: Type) = varToParamMap get tp match { + case Some(sym) => sym.tpe + case _ => mapOver(tp) + } + } + val paramToVar = new TypeMap { + def apply(tp: Type) = tp match { + case TypeRef(_, tsym, _) if paramToVarMap.isDefinedAt(tsym) => paramToVarMap(tsym) + case _ => mapOver(tp) + } + } + val bts = copyRefinedType(tpe.asInstanceOf[RefinedType], tpe.parents map varToParam, varToParam mapOver tpe.decls).baseTypeSeq + tpe.baseTypeSeqCache = bts lateMap paramToVar + } else { + incCounter(compoundBaseTypeSeqCount) + tpe.baseTypeSeqCache = undetBaseTypeSeq + tpe.baseTypeSeqCache = if (tpe.typeSymbol.isRefinementClass) + tpe.memo(compoundBaseTypeSeq(tpe))(_.baseTypeSeq updateHead tpe.typeSymbol.tpe) + else + compoundBaseTypeSeq(tpe) + // [Martin] suppressing memo-ization solves the problem with "same type after erasure" errors + // when compiling with + // scalac scala.collection.IterableViewLike.scala scala.collection.IterableLike.scala + // I have not yet figured out precisely why this is the case. + // My current assumption is that taking memos forces baseTypeSeqs to be computed + // at stale types (i.e. the underlying typeSymbol has already another type). + // I do not yet see precisely why this would cause a problem, but it looks + // fishy in any case. + } + } + } + //Console.println("baseTypeSeq(" + typeSymbol + ") = " + baseTypeSeqCache.toList);//DEBUG + if (tpe.baseTypeSeqCache eq undetBaseTypeSeq) + throw new TypeError("illegal cyclic inheritance involving " + tpe.typeSymbol) + } + + protected def defineBaseClassesOfCompoundType(tpe: CompoundType) = { + def computeBaseClasses: List[Symbol] = + if (tpe.parents.isEmpty) List(tpe.typeSymbol) + else { + //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG + // optimized, since this seems to be performance critical + val superclazz = tpe.parents.head + var mixins = tpe.parents.tail + val sbcs = superclazz.baseClasses + var bcs = sbcs + def isNew(clazz: Symbol): Boolean = + superclazz.baseTypeIndex(clazz) < 0 && + { var p = bcs; + while ((p ne sbcs) && (p.head != clazz)) p = p.tail; + p eq sbcs + } + while (!mixins.isEmpty) { + def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] = + if (mbcs.isEmpty) bcs + else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail) + else addMixinBaseClasses(mbcs.tail) + bcs = addMixinBaseClasses(mixins.head.baseClasses) + mixins = mixins.tail + } + tpe.typeSymbol :: bcs + } + val period = tpe.baseClassesPeriod + if (period != currentPeriod) { + tpe.baseClassesPeriod = currentPeriod + if (!isValidForBaseClasses(period)) { + tpe.baseClassesCache = null + tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail) + } + } + if (tpe.baseClassesCache eq null) + throw new TypeError("illegal cyclic reference involving " + tpe.typeSymbol) + } /** A class representing intersection types with refinements of the form * `<parents_0> with ... with <parents_n> { decls }` @@ -1583,7 +1608,7 @@ trait Types extends api.Types { self: SymbolTable => * by a path which contains at least one expansive reference. * @See Kennedy, Pierce: On Decidability of Nominal Subtyping with Variance */ - def expansiveRefs(tparam: Symbol) = { + private[scala] def expansiveRefs(tparam: Symbol) = { if (state == UnInitialized) { computeRefs() while (state != Initialized) propagate() @@ -1597,10 +1622,16 @@ trait Types extends api.Types { self: SymbolTable => /** The type parameters which are referenced type parameters of this class. * Two entries: refs(0): Non-expansive references * refs(1): Expansive references + * Syncnote: This var need not be protected with synchronized, because + * it is accessed only from expansiveRefs, which is called only from + * Typer. */ private var refs: Array[RefMap] = _ /** The initialization state of the class: UnInialized --> Initializing --> Initialized + * Syncnote: This var need not be protected with synchronized, because + * it is accessed only from expansiveRefs, which is called only from + * Typer. */ private var state = UnInitialized @@ -1750,6 +1781,10 @@ trait Types extends api.Types { self: SymbolTable => } } + /* Syncnote: The `volatile` var and `pendingVolatiles` mutable set need not be protected + * with synchronized, because they are accessed only from isVolatile, which is called only from + * Typer. + */ private var volatileRecursions: Int = 0 private val pendingVolatiles = new mutable.HashSet[Symbol] @@ -1831,13 +1866,18 @@ trait Types extends api.Types { self: SymbolTable => if (sym == clazz) this else transform(sym.info.baseType(clazz)) } + trait NonClassTypeRef extends TypeRef { require(sym.isNonClassType, sym) + /* Syncnote: These are pure caches for performance; no problem to evaluate these + * several times. Hence, no need to protected with synchronzied in a mutli-threaded + * usage scenario. + */ private var relativeInfoCache: Type = _ private var memberInfoCache: Type = _ - private def relativeInfo = { + private[Types] def relativeInfo = { val memberInfo = pre.memberInfo(sym) if (relativeInfoCache == null || (memberInfo ne memberInfoCache)) { memberInfoCache = memberInfo @@ -1846,25 +1886,27 @@ trait Types extends api.Types { self: SymbolTable => relativeInfoCache } - override def baseType(clazz: Symbol): Type = ( - if (sym == clazz) this else try { - basetypeRecursions += 1 - if (basetypeRecursions < LogPendingBaseTypesThreshold) - relativeInfo.baseType(clazz) - else if (pendingBaseTypes contains this) - if (clazz == AnyClass) clazz.tpe else NoType - else - try { - pendingBaseTypes += this - relativeInfo.baseType(clazz) - } finally { - pendingBaseTypes -= this - } + override def baseType(clazz: Symbol): Type = + if (sym == clazz) this else baseTypeOfNonClassTypeRef(this, clazz) + } + + protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) = try { + basetypeRecursions += 1 + if (basetypeRecursions < LogPendingBaseTypesThreshold) + tpe.relativeInfo.baseType(clazz) + else if (pendingBaseTypes contains tpe) + if (clazz == AnyClass) clazz.tpe else NoType + else + try { + pendingBaseTypes += tpe + tpe.relativeInfo.baseType(clazz) } finally { - basetypeRecursions -= 1 + pendingBaseTypes -= tpe } - ) + } finally { + basetypeRecursions -= 1 } + trait AliasTypeRef extends NonClassTypeRef { require(sym.isAliasType, sym) @@ -1912,6 +1954,8 @@ trait Types extends api.Types { self: SymbolTable => trait AbstractTypeRef extends NonClassTypeRef { require(sym.isAbstractType, sym) + /** Syncnote: Pure performance caches; no need to synchronize in multi-threaded environment + */ private var symInfoCache: Type = _ private var thisInfoCache: Type = _ @@ -1938,6 +1982,7 @@ trait Types extends api.Types { self: SymbolTable => volatileRecursions -= 1 } } + override def thisInfo = { val symInfo = sym.info if (thisInfoCache == null || (symInfo ne symInfoCache)) { @@ -1955,7 +2000,7 @@ trait Types extends api.Types { self: SymbolTable => override def isStable = bounds.hi.typeSymbol isSubClass SingletonClass override def bounds = thisInfo.bounds // def transformInfo(tp: Type): Type = appliedType(tp.asSeenFrom(pre, sym.owner), typeArgsOrDummies) - override protected def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this + override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this } /** A class for named types of the form @@ -1966,11 +2011,11 @@ trait Types extends api.Types { self: SymbolTable => * @M: a higher-kinded type is represented as a TypeRef with sym.typeParams.nonEmpty, but args.isEmpty */ abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type { - private var parentsCache: List[Type] = _ - private var parentsPeriod = NoPeriod - private var baseTypeSeqCache: BaseTypeSeq = _ - private var baseTypeSeqPeriod = NoPeriod - private var normalized: Type = _ + private[reflect] var parentsCache: List[Type] = _ + private[reflect] var parentsPeriod = NoPeriod + private[reflect] var baseTypeSeqCache: BaseTypeSeq = _ + private[reflect] var baseTypeSeqPeriod = NoPeriod + private var normalized: Type = _ // @M: propagate actual type params (args) to `tp`, by replacing // formal type parameters with actual ones. If tp is higher kinded, @@ -2030,16 +2075,12 @@ trait Types extends api.Types { self: SymbolTable => sym.isModuleClass || sym == NothingClass || isValueClass(sym) || super.isNotNull override def parents: List[Type] = { - val period = parentsPeriod - if (period != currentPeriod) { - parentsPeriod = currentPeriod - if (!isValidForBaseClasses(period)) { - parentsCache = thisInfo.parents map transform - } else if (parentsCache == null) { // seems this can happen if things are corrupted enough, see #2641 - parentsCache = List(AnyClass.tpe) - } + val cache = parentsCache + if (parentsPeriod == currentPeriod && cache != null) cache + else { + defineParentsOfTypeRef(this) + parentsCache } - parentsCache } override def decls: Scope = { @@ -2051,21 +2092,16 @@ trait Types extends api.Types { self: SymbolTable => thisInfo.decls } - protected def baseTypeSeqImpl: BaseTypeSeq = sym.info.baseTypeSeq map transform + protected[Types] def baseTypeSeqImpl: BaseTypeSeq = sym.info.baseTypeSeq map transform override def baseTypeSeq: BaseTypeSeq = { - val period = baseTypeSeqPeriod - if (period != currentPeriod) { - baseTypeSeqPeriod = currentPeriod - if (!isValidForBaseClasses(period)) { - incCounter(typerefBaseTypeSeqCount) - baseTypeSeqCache = undetBaseTypeSeq - baseTypeSeqCache = baseTypeSeqImpl - } + val cache = baseTypeSeqCache + if (baseTypeSeqPeriod == currentPeriod && cache != null && cache != undetBaseTypeSeq) + cache + else { + defineBaseTypeSeqOfTypeRef(this) + baseTypeSeqCache } - if (baseTypeSeqCache == undetBaseTypeSeq) - throw new TypeError("illegal cyclic inheritance involving " + sym) - baseTypeSeqCache } private def preString = ( @@ -2151,6 +2187,32 @@ trait Types extends api.Types { self: SymbolTable => } }) } + + protected def defineParentsOfTypeRef(tpe: TypeRef) = { + val period = tpe.parentsPeriod + if (period != currentPeriod) { + tpe.parentsPeriod = currentPeriod + if (!isValidForBaseClasses(period)) { + tpe.parentsCache = tpe.thisInfo.parents map tpe.transform + } else if (tpe.parentsCache == null) { // seems this can happen if things are corrupted enough, see #2641 + tpe.parentsCache = List(AnyClass.tpe) + } + } + } + + protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) = { + val period = tpe.baseTypeSeqPeriod + if (period != currentPeriod) { + tpe.baseTypeSeqPeriod = currentPeriod + if (!isValidForBaseClasses(period)) { + incCounter(typerefBaseTypeSeqCount) + tpe.baseTypeSeqCache = undetBaseTypeSeq + tpe.baseTypeSeqCache = tpe.baseTypeSeqImpl + } + } + if (tpe.baseTypeSeqCache == undetBaseTypeSeq) + throw new TypeError("illegal cyclic inheritance involving " + tpe.sym) + } /** A class representing a method type with parameters. * Note that a parameterless method is represented by a NullaryMethodType: @@ -2577,7 +2639,12 @@ trait Types extends api.Types { self: SymbolTable => override def typeArgs: List[Type] = Nil override def isHigherKinded = false - /** The constraint associated with the variable */ + /** The constraint associated with the variable + * Syncnote: Type variables are assumed to be used from only one + * thread. They are not exposed in api.Types and are used only locally + * in operations that are exposed from types. Hence, no syncing of `constr` + * or `encounteredHigherLevel` or `suspended` accesses should be necessary. + */ var constr = constr0 def instValid = constr.instValid @@ -3048,7 +3115,7 @@ trait Types extends api.Types { self: SymbolTable => * @return ... */ def refinedType(parents: List[Type], owner: Symbol): Type = - refinedType(parents, owner, new Scope, owner.pos) + refinedType(parents, owner, newScope, owner.pos) def copyRefinedType(original: RefinedType, parents: List[Type], decls: Scope) = if ((parents eq original.parents) && (decls eq original.decls)) original @@ -3338,7 +3405,7 @@ trait Types extends api.Types { self: SymbolTable => private var uniques: util.HashSet[Type] = _ private var uniqueRunId = NoRunId - private def unique[T <: Type](tp: T): T = { + protected def unique[T <: Type](tp: T): T = { incCounter(rawTypeCount) if (uniqueRunId != currentRunId) { uniques = util.HashSet[Type]("uniques", initialUniquesCapacity) @@ -3362,6 +3429,12 @@ trait Types extends api.Types { self: SymbolTable => def this(lo0: List[Type], hi0: List[Type]) = this(lo0, hi0, NoType, NoType) def this(bounds: TypeBounds) = this(List(bounds.lo), List(bounds.hi)) def this() = this(List(), List()) + + /* Syncnote: Type constraints are assumed to be used from only one + * thread. They are not exposed in api.Types and are used only locally + * in operations that are exposed from types. Hence, no syncing of any + * variables should be ncessesary. + */ /** Guard these lists against AnyClass and NothingClass appearing, * else loBounds.isEmpty will have different results for an empty @@ -3634,7 +3707,7 @@ trait Types extends api.Types { self: SymbolTable => val elems = scope.toList val elems1 = mapOver(elems) if (elems1 eq elems) scope - else new Scope(elems1) + else newScopeWith(elems1: _*) } /** Map this function over given list of symbols */ @@ -3699,6 +3772,11 @@ trait Types extends api.Types { self: SymbolTable => def traverse(tp: Type): Unit def apply(tp: Type): Type = { traverse(tp); tp } } + + abstract class TypeTraverserWithResult[T] extends TypeTraverser { + def result: T + def clear(): Unit + } abstract class TypeCollector[T](initial: T) extends TypeTraverser { var result: T = _ @@ -3753,7 +3831,7 @@ trait Types extends api.Types { self: SymbolTable => * the conversion of raw types to existential types might not have taken place * in ClassFileparser.sigToType (where it is usually done). */ - object rawToExistential extends TypeMap { + def rawToExistential = new TypeMap { private var expanded = immutable.Set[Symbol]() private var generated = immutable.Set[Type]() def apply(tp: Type): Type = tp match { @@ -4365,15 +4443,20 @@ trait Types extends api.Types { self: SymbolTable => private def commonOwner(tps: List[Type]): Symbol = { if (tps.isEmpty) NoSymbol else { - commonOwnerMap.result = null + commonOwnerMap.clear() tps foreach (commonOwnerMap traverse _) val result = if (commonOwnerMap.result ne null) commonOwnerMap.result else NoSymbol debuglog(tps.mkString("commonOwner(", ", ", ") == " + result)) result } } - private object commonOwnerMap extends TypeTraverser { + + protected def commonOwnerMap: CommonOwnerMap = commonOwnerMapObj + + protected class CommonOwnerMap extends TypeTraverserWithResult[Symbol] { var result: Symbol = _ + + def clear() { result = null } private def register(sym: Symbol) { // First considered type is the trivial result. @@ -4390,12 +4473,15 @@ trait Types extends api.Types { self: SymbolTable => case _ => mapOver(tp) } } + + private lazy val commonOwnerMapObj = new CommonOwnerMap class MissingAliasControl extends ControlThrowable val missingAliasException = new MissingAliasControl class MissingTypeControl extends ControlThrowable object adaptToNewRunMap extends TypeMap { + private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = { if (phase.flatClasses) { sym @@ -5832,7 +5918,7 @@ trait Types extends api.Types { self: SymbolTable => } /** The least upper bound wrt <:< of a list of types */ - def lub(ts: List[Type], depth: Int): Type = { + private def lub(ts: List[Type], depth: Int): Type = { def lub0(ts0: List[Type]): Type = elimSub(ts0, depth) match { case List() => NothingClass.tpe case List(t) => t @@ -5983,7 +6069,7 @@ trait Types extends api.Types { self: SymbolTable => /** The greatest lower bound wrt <:< of a list of types, which have been normalized * wrt elimSuper */ - private def glbNorm(ts: List[Type], depth: Int): Type = { + protected def glbNorm(ts: List[Type], depth: Int): Type = { def glb0(ts0: List[Type]): Type = ts0 match { case List() => AnyClass.tpe case List(t) => t @@ -6279,7 +6365,7 @@ trait Types extends api.Types { self: SymbolTable => private var indent: String = "" /** Perform operation `p` on arguments `tp1`, `arg2` and print trace of computation. */ - private def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = { + protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = { Console.println(indent + tp1 + " " + op + " " + arg2 + "?" /* + "("+tp1.getClass+","+arg2.getClass+")"*/) indent = indent + " " val result = p(tp1, arg2) @@ -6324,4 +6410,16 @@ trait Types extends api.Types { self: SymbolTable => final val maxTostringRecursions = 50 private var tostringRecursions = 0 + + protected def typeToString(tpe: Type): String = + if (tostringRecursions >= maxTostringRecursions) + "..." + else + try { + tostringRecursions += 1 + tpe.safeToString + } finally { + tostringRecursions -= 1 + } + } diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala index 7aca052fa9..0a5a21de1e 100644 --- a/src/compiler/scala/reflect/runtime/Loaders.scala +++ b/src/compiler/scala/reflect/runtime/Loaders.scala @@ -97,7 +97,7 @@ trait Loaders { self: SymbolTable => 0 < dp && dp < (name.length - 1) } - class PackageScope(pkgClass: Symbol) extends Scope { + class PackageScope(pkgClass: Symbol) extends Scope() with SynchronizedScope { assert(pkgClass.isType) private var negatives = mutable.Set[Name]() override def lookupEntry(name: Name): ScopeEntry = { diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala index 9490dc4ad7..47fc9f2dcf 100644 --- a/src/compiler/scala/reflect/runtime/Mirror.scala +++ b/src/compiler/scala/reflect/runtime/Mirror.scala @@ -40,7 +40,8 @@ class Mirror extends Universe with RuntimeTypes with TreeBuildUtil with ToolBoxe override def typeToClass(tpe: Type): java.lang.Class[_] = typeToJavaClass(tpe) override def symbolToClass(sym: Symbol): java.lang.Class[_] = classToJava(sym) - + + override def inReflexiveMirror = true } object Mirror extends Mirror diff --git a/src/compiler/scala/reflect/runtime/SymbolTable.scala b/src/compiler/scala/reflect/runtime/SymbolTable.scala index d1a806bcef..5331f0a53e 100644 --- a/src/compiler/scala/reflect/runtime/SymbolTable.scala +++ b/src/compiler/scala/reflect/runtime/SymbolTable.scala @@ -6,7 +6,7 @@ package runtime * It can be used either from the reflexive mirror itself (class Universe), or else from * a runtime compiler that uses reflection to get a class information (class scala.tools.nsc.ReflectGlobal) */ -trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with Loaders { +trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with Loaders with SynchronizedOps { /** If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package * <owner>.<name>, otherwise return NoSymbol. diff --git a/src/compiler/scala/reflect/runtime/SynchronizedOps.scala b/src/compiler/scala/reflect/runtime/SynchronizedOps.scala new file mode 100644 index 0000000000..98694c2ddf --- /dev/null +++ b/src/compiler/scala/reflect/runtime/SynchronizedOps.scala @@ -0,0 +1,52 @@ +package scala.reflect +package runtime + +trait SynchronizedOps extends internal.SymbolTable + with SynchronizedSymbols + with SynchronizedTypes { self: SymbolTable => + +// Names + + private lazy val nameLock = new Object + + override def newTermName(s: String): TermName = nameLock.synchronized { super.newTermName(s) } + override def newTypeName(s: String): TypeName = nameLock.synchronized { super.newTypeName(s) } + +// BaseTypeSeqs + + override protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) = + new BaseTypeSeq(parents, elems) with SynchronizedBaseTypeSeq + + trait SynchronizedBaseTypeSeq extends BaseTypeSeq { + override def apply(i: Int): Type = synchronized { super.apply(i) } + override def rawElem(i: Int) = synchronized { super.rawElem(i) } + override def typeSymbol(i: Int): Symbol = synchronized { super.typeSymbol(i) } + override def toList: List[Type] = synchronized { super.toList } + override def copy(head: Type, offset: Int): BaseTypeSeq = synchronized { super.copy(head, offset) } + override def map(f: Type => Type): BaseTypeSeq = synchronized { super.map(f) } + override def exists(p: Type => Boolean): Boolean = synchronized { super.exists(p) } + override lazy val maxDepth = synchronized { maxDepthOfElems } + override def toString = synchronized { super.toString } + + override def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f) with SynchronizedBaseTypeSeq + } + +// Scopes + + override def newScope = new Scope() with SynchronizedScope + override def newNestedScope(outer: Scope): Scope = new Scope(outer) with SynchronizedScope +// override def newScopeWith(elems: ScopeEntry): Scope = new Scope(elems) with SynchronizedScope + + trait SynchronizedScope extends Scope { + override def isEmpty: Boolean = synchronized { super.isEmpty } + override def size: Int = synchronized { super.size } + override def enter(sym: Symbol) = synchronized { super.enter(sym) } + override def rehash(sym: Symbol, newname: Name) = synchronized { super.rehash(sym, newname) } + override def unlink(e: ScopeEntry) = synchronized { super.unlink(e) } + override def unlink(sym: Symbol) = synchronized { super.unlink(sym) } + override def lookupAll(name: Name) = synchronized { super.lookupAll(name) } + override def lookupEntry(name: Name) = synchronized { super.lookupEntry(name) } + override def lookupNextEntry(entry: ScopeEntry) = synchronized { super.lookupNextEntry(entry) } + override def toList: List[Symbol] = synchronized { super.toList } + } +} diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala new file mode 100644 index 0000000000..9baf94f71d --- /dev/null +++ b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala @@ -0,0 +1,119 @@ +package scala.reflect +package runtime + +import internal.Flags.DEFERRED + +trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => + + override protected def nextId() = synchronized { super.nextId() } + + override protected def freshExistentialName(suffix: String) = + synchronized { super.freshExistentialName(suffix) } + + // Set the fields which point companions at one another. Returns the module. + override def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol = + synchronized { super.connectModuleToClass(m, moduleClass) } + + override def newFreeVar(name: TermName, tpe: Type, value: Any, newFlags: Long = 0L): FreeVar = + new FreeVar(name, value) with SynchronizedTermSymbol initFlags newFlags setInfo tpe + + override protected def makeNoSymbol = new NoSymbol with SynchronizedSymbol + + trait SynchronizedSymbol extends Symbol { + + override def rawowner = synchronized { super.rawowner } + override def rawname = synchronized { super.rawname } + override def rawflags = synchronized { super.rawflags } + + override def rawflags_=(x: FlagsType) = synchronized { super.rawflags_=(x) } + override def name_=(x: Name) = synchronized { super.name_=(x) } + override def owner_=(owner: Symbol) = synchronized { super.owner_=(owner) } + + override def validTo = synchronized { super.validTo } + override def validTo_=(x: Period) = synchronized { super.validTo_=(x) } + + override def pos = synchronized { super.pos } + override def setPos(pos: Position): this.type = { synchronized { super.setPos(pos) }; this } + + override def privateWithin = synchronized { super.privateWithin } + override def privateWithin_=(sym: Symbol) = synchronized { super.privateWithin_=(sym) } + + override def info = synchronized { super.info } + override def info_=(info: Type) = synchronized { super.info_=(info) } + override def updateInfo(info: Type): Symbol = synchronized { super.updateInfo(info) } + override def rawInfo: Type = synchronized { super.rawInfo } + + override def typeParams: List[Symbol] = synchronized { super.typeParams } + + override def reset(completer: Type) = synchronized { super.reset(completer) } + + override def infosString: String = synchronized { super.infosString } + + override def annotations: List[AnnotationInfo] = synchronized { super.annotations } + override def setAnnotations(annots: List[AnnotationInfo]): this.type = { synchronized { super.setAnnotations(annots) }; this } + + +// ------ creators ------------------------------------------------------------------- + + override def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol = + new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + + override def newAbstractTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol = + new AbstractTypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags + + override def newAliasTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol = + new AliasTypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags + + override def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = + new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + + override def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol = + new MethodSymbol(this, pos, name) with SynchronizedMethodSymbol initFlags newFlags + + override def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = + new ClassSymbol(this, pos, name) with SynchronizedClassSymbol initFlags newFlags + + override def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol = + new ModuleClassSymbol(this, pos, name) with SynchronizedModuleClassSymbol initFlags newFlags + + override def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem = + if ((newFlags & DEFERRED) == 0L) + new TypeSkolem(this, pos, name, origin) with SynchronizedTypeSymbol initFlags newFlags + else + new TypeSkolem(this, pos, name, origin) with AbstractTypeMixin with SynchronizedTypeSymbol initFlags newFlags + } + +// ------- subclasses --------------------------------------------------------------------- + + trait SynchronizedTermSymbol extends TermSymbol with SynchronizedSymbol { + override def referenced: Symbol = synchronized { super.referenced } + override def referenced_=(x: Symbol) = synchronized { super.referenced_=(x) } + } + + trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol { + override def typeAsMemberOf(pre: Type): Type = synchronized { super.typeAsMemberOf(pre) } + } + + trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol { + override def typeConstructor: Type = synchronized { super.typeConstructor } + override def tpe: Type = synchronized { super.tpe } + } + + trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol { + override def sourceFile = synchronized { super.sourceFile } + override def sourceFile_=(f: AbstractFileType) = synchronized { super.sourceFile_=(f) } + override def thisSym: Symbol = synchronized { super.thisSym } + override def thisType: Type = synchronized { super.thisType } + override def typeOfThis: Type = synchronized { super.typeOfThis } + override def typeOfThis_=(tp: Type) = synchronized { super.typeOfThis_=(tp) } + override def children = synchronized { super.children } + override def addChild(sym: Symbol) = synchronized { super.addChild(sym) } + } + + trait SynchronizedModuleClassSymbol extends ModuleClassSymbol with SynchronizedClassSymbol { + override def sourceModule = synchronized { super.sourceModule } + override def sourceModule_=(module: Symbol) = synchronized { super.sourceModule_=(module: Symbol) } + override def implicitMembers: List[Symbol] = synchronized { super.implicitMembers } + } +} + diff --git a/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala b/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala new file mode 100644 index 0000000000..c842d3dd01 --- /dev/null +++ b/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala @@ -0,0 +1,87 @@ +package scala.reflect +package runtime + +/** This trait overrides methods in reflect.internal, bracketing + * them in synchronized { ... } to make them thread-safe + */ +trait SynchronizedTypes extends internal.Types { self: SymbolTable => + + // No sharing of map objects: + override protected def commonOwnerMap = new CommonOwnerMap + + private val uniqueLock = new Object + override def unique[T <: Type](tp: T): T = uniqueLock.synchronized { super.unique(tp) } + + class SynchronizedUndoLog extends UndoLog { + + override def clear() = + synchronized { super.clear() } + + override def undo[T](block: => T): T = + synchronized { super.undo(block) } + + override def undoUnless(block: => Boolean): Boolean = + synchronized { super.undoUnless(block) } + } + + override protected def newUndoLog = new SynchronizedUndoLog + + override protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) = + synchronized { super.baseTypeOfNonClassTypeRef(tpe, clazz) } + + private val subsametypeLock = new Object + + override def isSameType(tp1: Type, tp2: Type): Boolean = + subsametypeLock.synchronized { super.isSameType(tp1, tp2) } + + override def isDifferentType(tp1: Type, tp2: Type): Boolean = + subsametypeLock.synchronized { super.isDifferentType(tp1, tp2) } + + override def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean = + subsametypeLock.synchronized { super.isSubType(tp1, tp2, depth) } + + private val lubglbLock = new Object + + override def glb(ts: List[Type]): Type = + lubglbLock.synchronized { super.glb(ts) } + + override def lub(ts: List[Type]): Type = + lubglbLock.synchronized { super.lub(ts) } + + private val indentLock = new Object + + override protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = { + indentLock.synchronized { super.explain(op, p, tp1, arg2) } + } + + private val toStringLock = new Object + + override protected def typeToString(tpe: Type): String = + toStringLock.synchronized(super.typeToString(tpe)) + + /* The idea of caches is as follows. + * When in reflexive mode, a cache is either null, or one sentinal + * value representing undefined or the final defined + * value. Hence, we can ask in non-synchronized ode whether the cache field + * is non null and different from the sentinel (if a sentinel exists). + * If that's true, the cache value is current. + * Otherwise we arrive in one of the defined... methods listed below + * which go through all steps in synchronized mode. + */ + + override protected def defineUnderlyingOfSingleType(tpe: SingleType) = + tpe.synchronized { super.defineUnderlyingOfSingleType(tpe) } + + override protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = + tpe.synchronized { super.defineBaseTypeSeqOfCompoundType(tpe) } + + override protected def defineBaseClassesOfCompoundType(tpe: CompoundType) = + tpe.synchronized { super.defineBaseClassesOfCompoundType(tpe) } + + override protected def defineParentsOfTypeRef(tpe: TypeRef) = + tpe.synchronized { super.defineParentsOfTypeRef(tpe) } + + override protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) = + tpe.synchronized { super.defineBaseTypeSeqOfTypeRef(tpe) } + +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index 8afd6d2231..9ab12c6a86 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -57,7 +57,7 @@ trait ToolBoxes extends { self: Universe => def wrapInObject(expr: Tree, fvs: List[Symbol]): ModuleDef = { val obj = EmptyPackageClass.newModule(nextWrapperModuleName()) - val minfo = ClassInfoType(List(ObjectClass.tpe, ScalaObjectClass.tpe), new Scope, obj.moduleClass) + val minfo = ClassInfoType(List(ObjectClass.tpe, ScalaObjectClass.tpe), newScope, obj.moduleClass) obj.moduleClass setInfo minfo obj setInfo obj.moduleClass.tpe val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName)) diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index c8db996de2..9ec1256ca8 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -615,7 +615,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb object icodeChecker extends icodeCheckers.ICodeChecker() object typer extends analyzer.Typer( - analyzer.NoContext.make(EmptyTree, Global.this.definitions.RootClass, new Scope) + analyzer.NoContext.make(EmptyTree, Global.this.definitions.RootClass, newScope) ) /** Add the internal compiler phases to the phases set. diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index e5748b7c23..18409cfffe 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -37,7 +37,7 @@ trait Patterns extends ast.TreeDSL { // } private lazy val dummyMethod = - new TermSymbol(NoSymbol, NoPosition, newTermName("matching$dummy")) + NoSymbol.newTermSymbol(newTermName("matching$dummy")) // Fresh patterns def emptyPatterns(i: Int): List[Pattern] = List.fill(i)(NoPattern) diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 4205c2ff36..942ec1fa86 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -207,7 +207,7 @@ abstract class SymbolLoaders { protected def doComplete(root: Symbol) { assert(root.isPackageClass, root) - root.setInfo(new PackageClassInfoType(new Scope(), root)) + root.setInfo(new PackageClassInfoType(newScope, root)) val sourcepaths = classpath.sourcepaths for (classRep <- classpath.classes if platform.doLoad(classRep)) { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 099145d3ae..a61c323824 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -536,8 +536,8 @@ abstract class ClassfileParser { addEnclosingTParams(clazz) parseInnerClasses() // also sets the isScala / isScalaRaw / hasMeta flags, see r15956 // get the class file parser to reuse scopes. - instanceDefs = new Scope - staticDefs = new Scope + instanceDefs = newScope + staticDefs = newScope val classInfo = ClassInfoType(parseParents, instanceDefs, clazz) val staticInfo = ClassInfoType(List(), staticDefs, statics) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala index ead431c8d7..eb8e7a14a5 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala @@ -108,7 +108,7 @@ abstract class MetaParser{ } protected def parseClass() { - locals = new Scope + locals = newScope def parse(): Type = { nextToken() if (token == "[") { @@ -130,7 +130,7 @@ abstract class MetaParser{ protected def parseMethod() { val globals = locals - locals = if (locals eq null) new Scope else new Scope(locals) + locals = if (locals eq null) newScope else newNestedScope(locals) def parse(): Type = { nextToken(); if (token == "[") PolyType(parseTypeParams(), parse()) diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala index 6c238f52cc..e11a5a4ad9 100644 --- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala @@ -165,7 +165,7 @@ abstract class TypeParser { clrTypes.sym2type(typMgdPtr) = clazzMgdPtr /* clazzMgdPtr but not clazzBoxed is mapped by clrTypes.types into an msil.Type instance, because there's no metadata-level representation for a "boxed valuetype" */ - val instanceDefsMgdPtr = new Scope + val instanceDefsMgdPtr = newScope val classInfoMgdPtr = ClassInfoType(definitions.anyvalparam, instanceDefsMgdPtr, clazzMgdPtr) clazzMgdPtr.setFlag(flags) clazzMgdPtr.setInfo(classInfoMgdPtr) @@ -196,8 +196,8 @@ abstract class TypeParser { } } /* END CLR generics (snippet 2) */ - instanceDefs = new Scope - staticDefs = new Scope + instanceDefs = newScope + staticDefs = newScope val classInfoAsInMetadata = { val ifaces: Array[MSILType] = typ.getInterfaces() @@ -212,7 +212,7 @@ abstract class TypeParser { } // methods, properties, events, fields are entered in a moment if (canBeTakenAddressOf) { - val instanceDefsBoxed = new Scope + val instanceDefsBoxed = newScope ClassInfoType(parents.toList, instanceDefsBoxed, clazzBoxed) } else ClassInfoType(parents.toList, instanceDefs, clazz) diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 8f5d308b8f..05b2b7a437 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -119,7 +119,7 @@ abstract class AddInterfaces extends InfoTransform { * given the decls ifaceDecls of its interface. */ private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = { - val decls = new Scope + val decls = newScope if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol) decls enter ( implClass.newMethod(nme.MIXIN_CONSTRUCTOR, implClass.pos) diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 23817545e2..d1c71faf1e 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -447,7 +447,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { val closureClass = clazz.newClass(nme.delayedInitArg.toTypeName, impl.pos, SYNTHETIC | FINAL) val closureParents = List(AbstractFunctionClass(0).tpe, ScalaObjectClass.tpe) - closureClass setInfoAndEnter new ClassInfoType(closureParents, new Scope, closureClass) + closureClass setInfoAndEnter new ClassInfoType(closureParents, newScope, closureClass) val outerField = ( closureClass diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 71696c24e6..b342b95742 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -742,7 +742,7 @@ abstract class Erasure extends AddInterfaces //println("computing bridges for " + owner)//DEBUG assert(phase == currentRun.erasurePhase) val site = owner.thisType - val bridgesScope = new Scope + val bridgesScope = newScope val bridgeTarget = new mutable.HashMap[Symbol, Symbol] var bridges: List[Tree] = List() val opc = atPhase(currentRun.explicitouterPhase) { diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index b17fd7b9b0..4fa5b52de3 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -65,7 +65,7 @@ abstract class Flatten extends InfoTransform { case ClassInfoType(parents, decls, clazz) => var parents1 = parents val decls1 = scopeTransform(clazz) { - val decls1 = new Scope() + val decls1 = newScope if (clazz.isPackageClass) { atPhase(phase.next)(decls foreach (decls1 enter _)) } else { diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index bf19cf10e9..bd29336703 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -403,12 +403,12 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { assert(clazz.sourceModule != NoSymbol || clazz.isAnonymousClass, clazz + " has no sourceModule: sym = " + sym + " sym.tpe = " + sym.tpe) parents1 = List() - decls1 = new Scope(decls.toList filter isImplementedStatically) + decls1 = newScopeWith(decls.toList filter isImplementedStatically: _*) } else if (!parents.isEmpty) { parents1 = parents.head :: (parents.tail map toInterface) } } - //decls1 = atPhase(phase.next)(new Scope(decls1.toList))//debug + //decls1 = atPhase(phase.next)(newScopeWith(decls1.toList: _*))//debug if ((parents1 eq parents) && (decls1 eq decls)) tp else ClassInfoType(parents1, decls1, clazz) @@ -480,7 +480,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { /** The rootContext used for typing */ private val rootContext = - erasure.NoContext.make(EmptyTree, RootClass, new Scope) + erasure.NoContext.make(EmptyTree, RootClass, newScope) /** The typer */ private var localTyper: erasure.Typer = _ diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala index 70f8d37585..1200e973c5 100644 --- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala +++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala @@ -74,7 +74,7 @@ abstract class OverridingPairs { } /** The symbols that can take part in an overriding pair */ - private val decls = new Scope + private val decls = newScope // fill `decls` with overriding shadowing overridden */ { def fillDecls(bcs: List[Symbol], deferredflag: Int) { diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index fd826fb6d8..4a104857db 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -502,7 +502,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { typeEnv(sClass) = env this.specializedClass((clazz, env0)) = sClass - val decls1 = new Scope // declarations of the newly specialized class 'sClass' + val decls1 = newScope // declarations of the newly specialized class 'sClass' var oldClassTParams: List[Symbol] = Nil // original unspecialized type parameters var newClassTParams: List[Symbol] = Nil // unspecialized type parameters of 'specializedClass' (cloned) @@ -1089,7 +1089,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (tparams.nonEmpty) " (poly)" else "", clazz, parents1, phase) ) - val newScope = new Scope(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz)) + val newScope = newScopeWith(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz): _*) // If tparams.isEmpty, this is just the ClassInfoType. polyType(tparams, ClassInfoType(parents1, newScope, clazz)) case _ => diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 56d9658377..bf41ddab9b 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -259,7 +259,7 @@ abstract class UnCurry extends InfoTransform else if (isPartial) List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe) else List(ObjectClass.tpe, fun.tpe, SerializableClass.tpe) - anonClass setInfo ClassInfoType(parents, new Scope, anonClass) + anonClass setInfo ClassInfoType(parents, newScope, anonClass) val applyMethod = anonClass.newMethod(nme.apply, fun.pos, FINAL) applyMethod setInfoAndEnter MethodType(applyMethod newSyntheticValueParams formals, restpe) anonClass addAnnotation serialVersionUIDAnnotation diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index faff4ccab2..c2647c709a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -218,7 +218,7 @@ trait Contexts { self: Analyzer => make(unit, tree, owner, scope, imports) def makeNewScope(tree: Tree, owner: Symbol): Context = - make(tree, owner, new Scope(scope)) + make(tree, owner, newNestedScope(scope)) // IDE stuff: distinguish between scopes created for typing and scopes created for naming. def make(tree: Tree, owner: Symbol): Context = diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 53e88b33c8..d0492c2f63 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -213,7 +213,7 @@ trait Implicits { /** An extractor for types of the form ? { name: (? >: argtpe <: Any*)restp } */ object HasMethodMatching { - val dummyMethod = new TermSymbol(NoSymbol, NoPosition, newTermName("typer$dummy")) + val dummyMethod = NoSymbol.newTermSymbol(newTermName("typer$dummy")) def templateArgType(argtpe: Type) = new BoundedWildcardType(TypeBounds.lower(argtpe)) def apply(name: Name, argtpes: List[Type], restpe: Type): Type = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 354b8caaa3..b19a471214 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -87,7 +87,7 @@ trait Namers extends MethodSynthesis { newNamer(context.makeNewScope(tree, sym)) } def createInnerNamer() = { - newNamer(context.make(context.tree, owner, new Scope)) + newNamer(context.make(context.tree, owner, newScope)) } def createPrimaryConstructorParameterNamer: Namer = { //todo: can we merge this with SCCmode? val classContext = context.enclClass @@ -832,7 +832,7 @@ trait Namers extends MethodSynthesis { val parents = typer.parentTypes(templ) map checkParent enterSelf(templ.self) - val decls = new Scope + val decls = newScope val templateNamer = newNamer(context.make(templ, clazz, decls)) templateNamer enterSyms templ.body diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala index 4104803194..b28a717049 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala @@ -1471,7 +1471,7 @@ defined class Foo */ def freshSym(pos: Position, tp: Type = NoType, prefix: String = "x") = {ctr += 1; // assert(owner ne null) // assert(owner ne NoSymbol) - new TermSymbol(NoSymbol, pos, vpmName.counted(prefix, ctr)) setInfo repackExistential(tp) + NoSymbol.newTermSymbol(vpmName.counted(prefix, ctr), pos) setInfo repackExistential(tp) } def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match { diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 112aa47114..ee2e292bba 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -955,7 +955,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R // Forward reference checking --------------------------------------------------- class LevelInfo(val outer: LevelInfo) { - val scope: Scope = if (outer eq null) new Scope else new Scope(outer.scope) + val scope: Scope = if (outer eq null) newScope else newNestedScope(outer.scope) var maxindex: Int = Int.MinValue var refpos: Position = _ var refsym: Symbol = _ diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index b4221365be..d6248891a2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1360,7 +1360,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { assert(clazz != NoSymbol) reenterTypeParams(cdef.tparams) val tparams1 = cdef.tparams mapConserve (typedTypeDef) - val impl1 = newTyper(context.make(cdef.impl, clazz, new Scope)) + val impl1 = newTyper(context.make(cdef.impl, clazz, newScope)) .typedTemplate(cdef.impl, parentTypes(cdef.impl)) val impl2 = finishMethodSynthesis(impl1, clazz, context) if ((clazz != ClassfileAnnotationClass) && @@ -1395,7 +1395,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val typedMods = removeAnnotations(mdef.mods) assert(clazz != NoSymbol, mdef) - val typer0 = newTyper(context.make(mdef.impl, clazz, new Scope)) + val typer0 = newTyper(context.make(mdef.impl, clazz, newScope)) val impl1 = typer0.typedTemplate(mdef.impl, { parentTypes(mdef.impl) ++ ( if (linkedClass == NoSymbol || !linkedClass.isSerializable || clazz.isSerializable) Nil @@ -3983,7 +3983,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val parents1 = templ.parents mapConserve (typedType(_, mode)) if (parents1 exists (_.tpe.isError)) tree setType ErrorType else { - val decls = new Scope + val decls = newScope //Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id) val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos) newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ.body) diff --git a/src/detach/plugin/scala/tools/detach/Detach.scala b/src/detach/plugin/scala/tools/detach/Detach.scala index e9cd474b82..fee2c5a273 100644 --- a/src/detach/plugin/scala/tools/detach/Detach.scala +++ b/src/detach/plugin/scala/tools/detach/Detach.scala @@ -735,7 +735,7 @@ abstract class Detach extends PluginComponent iface.sourceFile = clazz.sourceFile iface setFlag (ABSTRACT | TRAIT | INTERFACE) // Java interface val iparents = List(ObjectClass.tpe, RemoteClass.tpe, ScalaObjectClass.tpe) - iface setInfo ClassInfoType(iparents, new Scope, iface) + iface setInfo ClassInfoType(iparents, newScope, iface) // methods must throw RemoteException iface addAnnotation remoteAnnotationInfo @@ -749,7 +749,7 @@ abstract class Detach extends PluginComponent // Variant 2: un-/exportObject //val cparents = List(ObjectClass.tpe, iface.tpe, // UnreferencedClass.tpe, ScalaObjectClass.tpe) - iclaz setInfo ClassInfoType(cparents, new Scope, iclaz) + iclaz setInfo ClassInfoType(cparents, newScope, iclaz) val proxy = (iface, iclaz, new mutable.HashMap[Symbol, Symbol]) proxies(clazz) = proxy proxy diff --git a/src/library/scala/reflect/api/StandardDefinitions.scala b/src/library/scala/reflect/api/StandardDefinitions.scala index 6b480ab83d..08071660a2 100755 --- a/src/library/scala/reflect/api/StandardDefinitions.scala +++ b/src/library/scala/reflect/api/StandardDefinitions.scala @@ -12,9 +12,7 @@ trait StandardDefinitions { self: Universe => abstract class AbsDefinitions { // outer packages and their classes - // Under consideration - // def RootPackage: Symbol - + def RootPackage: Symbol def RootClass: Symbol def EmptyPackage: Symbol def EmptyPackageClass: Symbol diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala index 4b959649fd..6185a788ae 100755 --- a/src/library/scala/reflect/api/Types.scala +++ b/src/library/scala/reflect/api/Types.scala @@ -20,7 +20,7 @@ trait Types { self: Universe => /** The collection of declarations in this type */ - def allDeclarations: Iterable[Symbol] + def declarations: Iterable[Symbol] /** The member with given name, either directly declared or inherited, * an OverloadedSymbol if several exist, NoSymbol if none exist. @@ -36,7 +36,7 @@ trait Types { self: Universe => * Members appear in the linearization order of their owners. * Members with the same owner appear in reverse order of their declarations. */ - def allMembers: Iterable[Symbol] + def members: Iterable[Symbol] /** An iterable containing all non-private members of this type (directly declared or inherited) * Members appear in the linearization order of their owners. @@ -125,19 +125,23 @@ trait Types { self: Universe => /** Does this type contain a reference to given symbol? */ def contains(sym: Symbol): Boolean - } - /** This class declares methods that are visible in a `SingleType`. - */ - trait AbsSingletonType extends AbsType { + /** If this is a compound type, the list of its parent types; + * otherwise the empty list + */ + def parents: List[Type] - /** The type underlying a singleton type */ + /** If this is a singleton type, returns the type underlying it; + * otherwise returns this type itself. + */ def underlying: Type - /** Widen from singleton type to its underlying non-singleton - * base type by applying one or more `underlying` dereferences, - * identity for all other types. + /** If this is a singleton type, widen it to its nearest underlying non-singleton + * base type by applying one or more `underlying` dereferences. + * If this is not a singlecon type, returns this type itself. * + * Example: + * * class Outer { class C ; val x: C } * val o: Outer * <o.x.type>.widen = o.C @@ -145,19 +149,6 @@ trait Types { self: Universe => def widen: Type } - /** This class declares methods that are visible in a `CompoundType` (i.e. - * a class/trait/object template or refined type of the form - * {{{ - * P_1 with ... with P_m { D_1; ...; D_n } - * }}} - * P_n - */ - trait AbsCompoundType extends AbsType { - - /** The list of parent types of this compound type */ - def parents: List[Type] - } - /** The type of Scala types, and also Scala type signatures. * (No difference is internally made between the two). */ @@ -293,7 +284,7 @@ trait Types { self: Universe => /** A subtype of Type representing refined types as well as `ClassInfo` signatures. */ - type CompoundType <: /*AbsCompoundType with*/ Type + type CompoundType <: Type /** The `RefinedType` type defines types of any of the forms on the left, * with their RefinedType representations to the right. |