diff options
author | Paul Phillips <paulp@improving.org> | 2012-01-25 10:16:17 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-01-25 10:16:17 -0800 |
commit | cbad2ec3b1a564efa7312c45cd40733bf292294b (patch) | |
tree | e5d01aa8e0ce17b26e91aa465d524a12788dd950 /src | |
parent | c9a2d079eabd1d6d143ef43d95d2cb93d1996bfc (diff) | |
parent | 3a09b7845c3b16906c9bea9b9deccc545b7a4cb7 (diff) | |
download | scala-cbad2ec3b1a564efa7312c45cd40733bf292294b.tar.gz scala-cbad2ec3b1a564efa7312c45cd40733bf292294b.tar.bz2 scala-cbad2ec3b1a564efa7312c45cd40733bf292294b.zip |
Merge remote-tracking branch 'odersky/topic/reflect' into develop
Conflicts:
src/compiler/scala/reflect/internal/Symbols.scala
src/compiler/scala/reflect/internal/Types.scala
src/compiler/scala/tools/nsc/typechecker/Typers.scala
src/library/scala/reflect/api/Trees.scala
Diffstat (limited to 'src')
45 files changed, 924 insertions, 459 deletions
diff --git a/src/compiler/scala/reflect/internal/AnnotationCheckers.scala b/src/compiler/scala/reflect/internal/AnnotationCheckers.scala index 666c1d74cb..449b0ca0bc 100644 --- a/src/compiler/scala/reflect/internal/AnnotationCheckers.scala +++ b/src/compiler/scala/reflect/internal/AnnotationCheckers.scala @@ -49,6 +49,7 @@ trait AnnotationCheckers { def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = tree } + // Syncnote: Annotation checkers inaccessible to reflection, so no sync in var necessary. /** The list of annotation checkers that have been registered */ private var annotationCheckers: List[AnnotationChecker] = Nil diff --git a/src/compiler/scala/reflect/internal/AnnotationInfos.scala b/src/compiler/scala/reflect/internal/AnnotationInfos.scala index 255e69c3c6..c3dde3e6d1 100644 --- a/src/compiler/scala/reflect/internal/AnnotationInfos.scala +++ b/src/compiler/scala/reflect/internal/AnnotationInfos.scala @@ -178,7 +178,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => private var rawpos: Position = NoPosition def pos = rawpos - def setPos(pos: Position): this.type = { + def setPos(pos: Position): this.type = { // Syncnote: Setpos inaccessible to reflection, so no sync in rawpos necessary. rawpos = pos this } diff --git a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala b/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala index 38277b5a09..9e5c93753f 100644 --- a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala @@ -29,7 +29,14 @@ 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) + + /** Note: constructor is protected to force everyone to use the factory method newBaseTypeSeq instead. + * This is necessary because when run from reflection every base type sequence needs to have a + * SynchronizedBaseTypeSeq as mixin. + */ + class BaseTypeSeq protected[BaseTypeSeqs] (private[BaseTypeSeqs] val parents: List[Type], private[BaseTypeSeqs] val elems: Array[Type]) { self => incCounter(baseTypeSeqCount) incCounter(baseTypeSeqLenTotal, elems.length) @@ -41,7 +48,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 +96,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 +120,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 +173,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 +240,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 02d6737bdb..1490d80d7a 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) @@ -211,7 +211,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 } @@ -357,7 +357,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") @@ -615,7 +615,7 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val ValueTypeClass: Symbol = getClass(sn.ValueType) // System.MulticastDelegate lazy val DelegateClass: Symbol = getClass(sn.Delegate) - var Delegate_scalaCallers: List[Symbol] = List() + var Delegate_scalaCallers: List[Symbol] = List() // Syncnote: No protection necessary yet as only for .NET where reflection is not supported. // Symbol -> (Symbol, Type): scalaCaller -> (scalaMethodSym, DelegateType) // var Delegate_scalaCallerInfos: HashMap[Symbol, (Symbol, Type)] = _ lazy val Delegate_scalaCallerTargets: mutable.HashMap[Symbol, Symbol] = mutable.HashMap() @@ -635,31 +635,47 @@ trait Definitions extends reflect.api.StandardDefinitions { case _ => false }) } - + // members of class scala.Any - var Any_== : Symbol = _ - var Any_!= : Symbol = _ - var Any_equals : Symbol = _ - var Any_hashCode : Symbol = _ - var Any_toString : Symbol = _ - var Any_getClass : Symbol = _ - var Any_isInstanceOf: Symbol = _ - var Any_asInstanceOf: Symbol = _ - var Any_## : Symbol = _ - - // members of class java.lang.{Object, String} - var Object_eq : Symbol = _ - var Object_ne : Symbol = _ - var Object_== : Symbol = _ - var Object_!= : Symbol = _ - var Object_## : Symbol = _ - var Object_synchronized: Symbol = _ + lazy val Any_== = newMethod(AnyClass, nme.EQ, anyparam, booltype, FINAL) + lazy val Any_!= = newMethod(AnyClass, nme.NE, anyparam, booltype, FINAL) + lazy val Any_equals = newMethod(AnyClass, nme.equals_, anyparam, booltype) + lazy val Any_hashCode = newMethod(AnyClass, nme.hashCode_, Nil, inttype) + lazy val Any_toString = newMethod(AnyClass, nme.toString_, Nil, stringtype) + lazy val Any_## = newMethod(AnyClass, nme.HASHHASH, Nil, inttype, FINAL) + + // Any_getClass requires special handling. The return type is determined on + // a per-call-site basis as if the function being called were actually: + // + // // Assuming `target.getClass()` + // def getClass[T](target: T): Class[_ <: T] + // + // Since getClass is not actually a polymorphic method, this requires compiler + // participation. At the "Any" level, the return type is Class[_] as it is in + // java.lang.Object. Java also special cases the return type. + lazy val Any_getClass = + newMethod(AnyClass, nme.getClass_, Nil, getMember(ObjectClass, nme.getClass_).tpe.resultType, DEFERRED) + lazy val Any_isInstanceOf = newPolyMethod( + AnyClass, nme.isInstanceOf_, tparam => NullaryMethodType(booltype)) setFlag FINAL + lazy val Any_asInstanceOf = newPolyMethod( + AnyClass, nme.asInstanceOf_, tparam => NullaryMethodType(tparam.typeConstructor)) setFlag FINAL + + // members of class java.lang.{ Object, String } + lazy val Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL) + lazy val Object_== = newMethod(ObjectClass, nme.EQ, anyrefparam, booltype, FINAL) + lazy val Object_!= = newMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL) + lazy val Object_eq = newMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL) + lazy val Object_ne = newMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL) + lazy val Object_synchronized = newPolyMethodCon( + ObjectClass, nme.synchronized_, + tparam => msym => MethodType(msym.newSyntheticValueParams(List(tparam.typeConstructor)), tparam.typeConstructor)) setFlag FINAL lazy val Object_isInstanceOf = newPolyMethod( ObjectClass, newTermName("$isInstanceOf"), tparam => MethodType(List(), booltype)) setFlag (FINAL | SYNTHETIC) lazy val Object_asInstanceOf = newPolyMethod( ObjectClass, newTermName("$asInstanceOf"), tparam => MethodType(List(), tparam.typeConstructor)) setFlag (FINAL | SYNTHETIC) + lazy val String_+ = newMethod(StringClass, nme.raw.PLUS, anyparam, stringtype, FINAL) def Object_getClass = getMember(ObjectClass, nme.getClass_) def Object_clone = getMember(ObjectClass, nme.clone_) @@ -670,7 +686,6 @@ trait Definitions extends reflect.api.StandardDefinitions { def Object_hashCode = getMember(ObjectClass, nme.hashCode_) def Object_toString = getMember(ObjectClass, nme.toString_) - var String_+ : Symbol = _ // boxed classes lazy val ObjectRefClass = getRequiredClass("scala.runtime.ObjectRef") @@ -829,7 +844,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 = @@ -946,43 +961,7 @@ trait Definitions extends reflect.api.StandardDefinitions { RootClass.info.decls enter EmptyPackage RootClass.info.decls enter RootPackage - - // members of class scala.Any - Any_== = newMethod(AnyClass, nme.EQ, anyparam, booltype, FINAL) - Any_!= = newMethod(AnyClass, nme.NE, anyparam, booltype, FINAL) - Any_equals = newMethod(AnyClass, nme.equals_, anyparam, booltype) - Any_hashCode = newMethod(AnyClass, nme.hashCode_, Nil, inttype) - Any_toString = newMethod(AnyClass, nme.toString_, Nil, stringtype) - Any_## = newMethod(AnyClass, nme.HASHHASH, Nil, inttype, FINAL) - - // Any_getClass requires special handling. The return type is determined on - // a per-call-site basis as if the function being called were actually: - // - // // Assuming `target.getClass()` - // def getClass[T](target: T): Class[_ <: T] - // - // Since getClass is not actually a polymorphic method, this requires compiler - // participation. At the "Any" level, the return type is Class[_] as it is in - // java.lang.Object. Java also special cases the return type. - Any_getClass = - newMethod(AnyClass, nme.getClass_, Nil, getMember(ObjectClass, nme.getClass_).tpe.resultType, DEFERRED) - Any_isInstanceOf = newPolyMethod( - AnyClass, nme.isInstanceOf_, tparam => NullaryMethodType(booltype)) setFlag FINAL - Any_asInstanceOf = newPolyMethod( - AnyClass, nme.asInstanceOf_, tparam => NullaryMethodType(tparam.typeConstructor)) setFlag FINAL - - // members of class java.lang.{ Object, String } - Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL) - Object_== = newMethod(ObjectClass, nme.EQ, anyrefparam, booltype, FINAL) - Object_!= = newMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL) - Object_eq = newMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL) - Object_ne = newMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL) - Object_synchronized = newPolyMethodCon( - ObjectClass, nme.synchronized_, - tparam => msym => MethodType(msym.newSyntheticValueParams(List(tparam.typeConstructor)), tparam.typeConstructor)) setFlag FINAL - - String_+ = newMethod(StringClass, nme.raw.PLUS, anyparam, stringtype, FINAL) - + val forced = List( // force initialization of every symbol that is entered as a side effect AnnotationDefaultAttr, // #2264 RepeatedParamClass, @@ -995,8 +974,24 @@ trait Definitions extends reflect.api.StandardDefinitions { NothingClass, SingletonClass, EqualsPatternClass, + Any_==, + Any_!=, + Any_equals, + Any_hashCode, + Any_toString, + Any_getClass, + Any_isInstanceOf, + Any_asInstanceOf, + Any_##, + Object_eq, + Object_ne, + Object_==, + Object_!=, + Object_##, + Object_synchronized, Object_isInstanceOf, - Object_asInstanceOf + Object_asInstanceOf, + String_+ ) /** Removing the anyref parent they acquire from having a source file. 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/InfoTransformers.scala b/src/compiler/scala/reflect/internal/InfoTransformers.scala index 9c54b1b4cd..96d9d8f076 100644 --- a/src/compiler/scala/reflect/internal/InfoTransformers.scala +++ b/src/compiler/scala/reflect/internal/InfoTransformers.scala @@ -9,6 +9,8 @@ package internal trait InfoTransformers { self: SymbolTable => + /* Syncnote: This should not need to be protected, as reflection does not run in multiple phases. + */ abstract class InfoTransformer { var prev: InfoTransformer = this var next: InfoTransformer = this diff --git a/src/compiler/scala/reflect/internal/Scopes.scala b/src/compiler/scala/reflect/internal/Scopes.scala index fb3012adff..54d3de09cd 100644 --- a/src/compiler/scala/reflect/internal/Scopes.scala +++ b/src/compiler/scala/reflect/internal/Scopes.scala @@ -37,9 +37,18 @@ trait Scopes extends api.Scopes { self: SymbolTable => def unapplySeq(decls: Scope): Some[Seq[Symbol]] = Some(decls.toList) } - class Scope(initElems: ScopeEntry) extends Iterable[Symbol] { + /** 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 = null) extends Iterable[Symbol] { + + protected[Scopes] 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 +74,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 +308,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 +318,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 +349,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 6b4080c6ad..9f8476a6fe 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 = @@ -68,7 +72,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** The class for all symbols */ - abstract class Symbol(initOwner: Symbol, initPos: Position, initName: Name) + abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name) extends AbsSymbolImpl with HasFlags with Annotatable[Symbol] { @@ -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): Boolean = { + private[scala] def lock(handler: => Unit): Boolean = { if ((rawflags & LOCKED) != 0L) { if (settings.Yrecursion.value != 0) { recursionTable get this match { @@ -371,11 +385,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => } // 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 } @@ -740,7 +754,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). @@ -748,8 +762,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 @@ -782,7 +796,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 @@ -791,7 +805,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => ifs = ifs.prev } } - rawname = name + _rawname = name } } @@ -859,20 +873,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 @@ -958,7 +972,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => throw CyclicReference(this, tp) } } else { - rawflags |= LOCKED + _rawflags |= LOCKED // activeLocks += 1 // lockedSyms += this } @@ -987,7 +1001,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. */ @@ -1006,11 +1020,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 } @@ -1048,11 +1062,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 @@ -1063,7 +1077,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 { @@ -1072,7 +1087,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 = ( @@ -1088,6 +1103,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } } + } /** Initialize the symbol */ final def initialize: this.type = { @@ -1097,6 +1113,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 @@ -1104,6 +1121,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 @@ -1215,7 +1233,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def reset(completer: Type) { resetFlags() infos = null - validTo = NoPeriod + _validTo = NoPeriod //limit = NoPhase.id setInfo(completer) } @@ -1242,7 +1260,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("(", ", ", ")") @@ -2052,15 +2070,18 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** A class for term symbols */ - class TermSymbol(initOwner: Symbol, initPos: Position, initName: TermName) + class TermSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) extends Symbol(initOwner, initPos, initName) { final override def isTerm = true 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 = @@ -2142,7 +2163,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** A class for module symbols */ - class ModuleSymbol(initOwner: Symbol, initPos: Position, initName: TermName) + class ModuleSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) extends TermSymbol(initOwner, initPos, initName) { private var flatname: TermName = null @@ -2165,7 +2186,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** A class for method symbols */ - class MethodSymbol(initOwner: Symbol, initPos: Position, initName: TermName) + class MethodSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName) extends TermSymbol(initOwner, initPos, initName) { private var mtpePeriod = NoPeriod private var mtpePre: Type = _ @@ -2191,7 +2212,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } - class AliasTypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) + class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { // Temporary programmatic help tracking down who might do such a thing override def setFlag(mask: Long): this.type = { @@ -2232,7 +2253,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 protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends Symbol(initOwner, initPos, initName) { privateWithin = NoSymbol private var tyconCache: Type = null private var tyconRunId = NoRunId @@ -2370,7 +2391,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * * origin.isInstanceOf[Symbol] == !hasFlag(EXISTENTIAL) */ - class TypeSkolem(initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef) + class TypeSkolem protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef) extends TypeSymbol(initOwner, initPos, initName) { /** The skolemization level in place when the skolem was constructed */ @@ -2399,11 +2420,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** A class for class symbols */ - class ClassSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) + class ClassSymbol protected[Symbols] (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 @@ -2465,7 +2486,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } typeOfThisCache } - else thissym.tpe + else thisSym.tpe } /** Sets the self type of the class */ @@ -2485,7 +2506,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 } @@ -2496,7 +2517,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * Note: Not all module classes are of this type; when unpickled, we get * plain class symbols! */ - class ModuleClassSymbol(owner: Symbol, pos: Position, name: TypeName) + class ModuleClassSymbol protected[Symbols] (owner: Symbol, pos: Position, name: TypeName) extends ClassSymbol(owner, pos, name) { private var module: Symbol = null private var implicitMembersCacheValue: List[Symbol] = List() @@ -2529,10 +2550,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 protected[Symbols]() 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 @@ -2563,6 +2586,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)") } + 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 8ca00dd5c5..35d26493f8 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,36 @@ 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) + if (baseTypeSeqCache eq undetBaseTypeSeq) + throw new RecoverableCyclicReference(typeSymbol) + + baseTypeSeqCache } - if (baseTypeSeqCache eq undetBaseTypeSeq) - throw new RecoverableCyclicReference(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) + if (baseClassesCache eq null) + throw new RecoverableCyclicReference(typeSymbol) + + baseClassesCache } - if (baseClassesCache eq null) - throw new RecoverableCyclicReference(typeSymbol) - baseClassesCache } /** The slightly less idiomatic use of Options is due to @@ -1475,6 +1415,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 +1614,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 +1628,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 +1787,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 +1872,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 +1892,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 +1960,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 +1988,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 +2006,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 +2017,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 +2081,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 +2098,19 @@ 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) + if (baseTypeSeqCache == undetBaseTypeSeq) + throw new RecoverableCyclicReference(sym) + + baseTypeSeqCache } - if (baseTypeSeqCache == undetBaseTypeSeq) - throw new RecoverableCyclicReference(sym) - baseTypeSeqCache } private def preString = ( @@ -2151,6 +2196,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 +2648,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 +3124,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 @@ -3352,7 +3428,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) @@ -3376,6 +3452,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 @@ -3648,7 +3730,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 */ @@ -3713,6 +3795,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 = _ @@ -3767,7 +3854,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 { @@ -4381,15 +4468,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. @@ -4406,12 +4498,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 @@ -5848,7 +5943,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 @@ -5999,7 +6094,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 @@ -6298,7 +6393,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) @@ -6343,4 +6438,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/ConversionUtil.scala b/src/compiler/scala/reflect/runtime/ConversionUtil.scala index bd40200310..e75fd78590 100644 --- a/src/compiler/scala/reflect/runtime/ConversionUtil.scala +++ b/src/compiler/scala/reflect/runtime/ConversionUtil.scala @@ -17,36 +17,42 @@ trait ConversionUtil { self: SymbolTable => private val toScalaMap = new HashMap[J, S] private val toJavaMap = new HashMap[S, J] - def enter(j: J, s: S) = { + def enter(j: J, s: S) = synchronized { debugInfo("cached: "+j+"/"+s) toScalaMap(j) = s toJavaMap(s) = j } - def toScala(key: J)(body: => S): S = toScalaMap get key match { - case Some(v) => - v - case none => - val result = body - enter(key, result) - result + def toScala(key: J)(body: => S): S = synchronized { + toScalaMap get key match { + case Some(v) => + v + case none => + val result = body + enter(key, result) + result + } } - def toJava(key: S)(body: => J): J = toJavaMap get key match { - case Some(v) => - v - case none => - val result = body - enter(result, key) - result + def toJava(key: S)(body: => J): J = synchronized { + toJavaMap get key match { + case Some(v) => + v + case none => + val result = body + enter(result, key) + result + } } - def toJavaOption(key: S)(body: => Option[J]): Option[J] = toJavaMap get key match { - case None => - val result = body - for (value <- result) enter(value, key) - result - case some => some + def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized { + toJavaMap get key match { + case None => + val result = body + for (value <- result) enter(value, key) + result + case some => some + } } } diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala index bc5d616ae3..b4bcc52a23 100644 --- a/src/compiler/scala/reflect/runtime/JavaToScala.scala +++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala @@ -175,7 +175,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => load(sym) completeRest() } - def completeRest(): Unit = { + def completeRest(): Unit = self.synchronized { val tparams = clazz.rawInfo.typeParams val parents = try { diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala index 7aca052fa9..4b35a5b37e 100644 --- a/src/compiler/scala/reflect/runtime/Loaders.scala +++ b/src/compiler/scala/reflect/runtime/Loaders.scala @@ -97,9 +97,9 @@ 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]() + private val negatives = mutable.Set[Name]() // Syncnote: Performance only, so need not be protected. override def lookupEntry(name: Name): ScopeEntry = { val e = super.lookupEntry(name) if (e != null) diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala index 09a4bbe198..4808326902 100644 --- a/src/compiler/scala/reflect/runtime/Mirror.scala +++ b/src/compiler/scala/reflect/runtime/Mirror.scala @@ -51,7 +51,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..72adbd4004 --- /dev/null +++ b/src/compiler/scala/reflect/runtime/SynchronizedOps.scala @@ -0,0 +1,51 @@ +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 + + 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 e805b4e75e..426700f3b2 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 b818927ceb..811bb6ee05 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 17d63ea439..1c41e68532 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -139,7 +139,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 bdd6a73b79..ab4a2141a9 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 d828b019f9..a1ade61dad 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -253,7 +253,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 6cb1d562ce..eaf1b1ffbc 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 701c69a4bb..0ff2b418f4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -89,7 +89,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 @@ -838,7 +838,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 dc5e248631..73a43bf4a1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala @@ -1457,7 +1457,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 0405163ef3..1a54b26307 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 da7e54af5c..889c04a59b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1404,7 +1404,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { assert(clazz != NoSymbol) reenterTypeParams(cdef.tparams) val tparams1 = cdef.tparams mapConserve (typedTypeDef) - val impl1 = typerReportAnyContextErrors(context.make(cdef.impl, clazz, new Scope)){ + val impl1 = typerReportAnyContextErrors(context.make(cdef.impl, clazz, newScope)) { _.typedTemplate(cdef.impl, parentTypes(cdef.impl)) } val impl2 = finishMethodSynthesis(impl1, clazz, context) @@ -1439,7 +1439,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val clazz = mdef.symbol.moduleClass val typedMods = removeAnnotations(mdef.mods) assert(clazz != NoSymbol, mdef) - val impl1 = typerReportAnyContextErrors(context.make(mdef.impl, clazz, new Scope)){ + val impl1 = typerReportAnyContextErrors(context.make(mdef.impl, clazz, newScope)) { _.typedTemplate(mdef.impl, { parentTypes(mdef.impl) ++ ( if (linkedClass == NoSymbol || !linkedClass.isSerializable || clazz.isSerializable) Nil @@ -1448,7 +1448,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { List(TypeTree(SerializableClass.tpe) setPos clazz.pos.focus) } ) - })} + }) + } val impl2 = finishMethodSynthesis(impl1, clazz, context) treeCopy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType @@ -4043,7 +4044,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val parents1 = templ.parents mapConserve (typedType(_, mode)) if (parents1 exists (_.isErrorTyped)) 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/Names.scala b/src/library/scala/reflect/api/Names.scala index e226d2265a..9498f0af36 100755 --- a/src/library/scala/reflect/api/Names.scala +++ b/src/library/scala/reflect/api/Names.scala @@ -1,32 +1,59 @@ package scala.reflect package api +/** A trait that manages names. + * A name is a string in one of two name universes: terms and types. + * The same string can be a name in both universes. + * Two names are equal if they represent the same string and they are + * members of the same universe. + * + * Names are interned. That is, for two names `name11 and `name2`, + * `name1 == name2` implies `name1 eq name2`. + */ trait Names { - + + /** The abstract type of names */ type Name >: Null <: AbsName + + /** The abstract type of names representing terms */ type TypeName <: Name + + /** The abstract type of names representing types */ type TermName <: Name abstract class AbsName { + /** Is this name a term name? */ def isTermName: Boolean + + /** Is this name a type name? */ def isTypeName: Boolean + + /** Returns a term name that represents the same string as this name */ def toTermName: TermName + + /** Returns a type name that represents the same string as this name */ def toTypeName: TypeName - /** Replace all occurrences of $op_names in this name by corresponding operator symbols. + /** Replaces all occurrences of $op_names in this name by corresponding operator symbols. * Example: `foo_+=` becomes `foo_$plus$eq`. */ def decode: String - /** Replace all occurrences of operator symbols in this name by corresponding $op_names. + /** Replaces all occurrences of operator symbols in this name by corresponding $op_names. * Example: `foo_$plus$eq` becomes `foo_+=` */ def encode: Name } + /** Create a new term name. + */ def newTermName(s: String): TermName + + /** Creates a new type name. + */ def newTypeName(s: String): TypeName def EmptyTermName: TermName = newTermName("") + def EmptyTypeName: TypeName = EmptyTermName.toTypeName } 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/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala index 8b4b170847..01c1a0f2ae 100755 --- a/src/library/scala/reflect/api/Symbols.scala +++ b/src/library/scala/reflect/api/Symbols.scala @@ -15,7 +15,14 @@ trait Symbols { self: Universe => */ def hasModifier(mod: Modifier.Value): Boolean - /** The owner of this symbol. + /** The owner of this symbol. This is the symbol + * that directly contains the current symbol's definition. + * The `NoSymbol` symbol does not have an owner, and calling this method + * on one causes an internal error. + * The owner of the Scala root class [[scala.reflect.api.mirror.RootClass]] + * and the Scala root object [[scala.reflect.api.mirror.RootPackage]] is `NoSymbol`. + * Every other symbol has a chain of owners that ends in + * [[scala.reflect.api.mirror.RootClass]]. */ def owner: Symbol @@ -74,23 +81,6 @@ trait Symbols { self: Universe => */ def annotations: List[self.AnnotationInfo] - /** The type of the symbol - */ - def tpe: Type - - /** The info of the symbol. This is like tpe, except for class symbols where the `info` - * describes the contents of the class whereas the `tpe` is a reference to the class. - */ - def info: Type - - /** If this symbol is a class or trait, its self type, otherwise the type of the symbol itself - */ - def typeOfThis: Type - - /** The type `C.this`, where `C` is the current class. - */ - def thisType: Type - /** For a class: the module or case class factory with the same name in the same package. * For all others: NoSymbol */ @@ -114,20 +104,43 @@ trait Symbols { self: Universe => /** The top-level class containing this symbol. */ def toplevelClass: Symbol - /** The next enclosing class */ + /** The next enclosing class, or `NoSymbol` if none exists */ def enclClass : Symbol - /** The next enclosing method */ + /** The next enclosing method, or `NoSymbol` if none exists */ def enclMethod : Symbol + /** Does this symbol represent the definition of term? + * Note that every symbol is either a term or a type. + * So for every symbol `sym`, either `sym.isTerm` is true + * or `sym.isType` is true. + */ def isTerm : Boolean + + /** Does this symbol represent the definition of type? + * Note that every symbol is either a term or a type. + * So for every symbol `sym`, either `sym.isTerm` is true + * or `sym.isType` is true. + */ def isType : Boolean + + /** Does this symbol represent the definition of class? + * If yes, `isType` is also guaranteed to be true. + */ def isClass : Boolean + + /** Does this symbol represent the definition of a type alias? + * If yes, `isType` is also guaranteed to be true. + */ def isAliasType : Boolean + + /** Does this symbol represent the definition of an abstract type? + * If yes, `isType` is also guaranteed to be true. + */ def isAbstractType : Boolean /** The type signature of this symbol. - * Note if symbol is a member of a class, one almost always is interested + * Note if the symbol is a member of a class, one almost always is interested * in `typeSigIn` with a site type instead. */ def typeSig: Type @@ -136,22 +149,44 @@ trait Symbols { self: Universe => */ def typeSigIn(site: Type): Type - /** The type constructor corresponding to this type symbol. - */ - def asTypeConstructor: Type // needed by LiftCode - - /** A type reference that refers to this type symbol + /** A type reference that refers to this type symbol * Note if symbol is a member of a class, one almost always is interested * in `asTypeIn` with a site type instead. + * + * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol + * `C`. Then `C.asType` is the type `C[T]`. + * + * By contrast, `C.typeSig` would be a type signature of form + * `PolyType(ClassInfoType(...))` that describes type parameters, value + * parameters, parent types, and members of `C`. */ def asType: Type - /** A type reference that refers to this type symbol seen as a member of given type `site`. + /** A type reference that refers to this type symbol seen + * as a member of given type `site`. */ def asTypeIn(site: Type): Type + /** The type constructor corresponding to this type symbol. + * This is different from `asType` in that type parameters + * are part of results of `asType`, but not of `asTypeConstructor`. + * + * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol + * `C`. Then `C.asType` is the type `C[T]`, but `C.asTypeCponstructor` is `C`. + */ + def asTypeConstructor: Type // needed by LiftCode + + /** If this symbol is a class or trait, its self type, otherwise the type + * of the symbol itself. + */ + def typeOfThis: Type + + /** If this symbol is a class, the type `C.this`, otherwise `NoPrefix`. + */ + def thisType: Type + /** A fresh symbol with given name `name`, position `pos` and flags `flags` that has - * the current symbol as its owner. + * the current symbol as its owner. */ def newNestedSymbol(name: Name, pos: Position, flags: Long): Symbol // needed by LiftCode diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 27f2ab1d08..03b043c188 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -8,7 +8,8 @@ package api import scala.collection.mutable.ListBuffer -trait Trees /*extends reflect.generic.Trees*/ { self: Universe => +// Syncnote: Trees are currently not thread-safe. +trait Trees { self: Universe => private[scala] var nodeCount = 0 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. |