summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/ClassfileConstants.scala80
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala23
-rw-r--r--src/compiler/scala/reflect/internal/HasFlags.scala3
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala277
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala114
-rw-r--r--src/compiler/scala/reflect/internal/pickling/UnPickler.scala2
-rw-r--r--src/compiler/scala/reflect/runtime/JavaToScala.scala11
-rw-r--r--src/compiler/scala/reflect/runtime/TreeBuildUtil.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala44
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala70
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala16
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala35
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala40
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala29
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala37
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala21
-rw-r--r--src/library/scala/Function1.scala10
-rw-r--r--src/library/scala/PartialFunction.scala30
-rw-r--r--src/library/scala/collection/GenTraversableLike.scala23
-rw-r--r--src/library/scala/collection/TraversableLike.scala3
-rw-r--r--src/library/scala/collection/generic/GenericTraversableTemplate.scala14
-rw-r--r--src/library/scala/reflect/Manifest.scala2
-rwxr-xr-xsrc/library/scala/reflect/api/Symbols.scala4
-rw-r--r--src/partest/scala/tools/partest/nest/PathSettings.scala7
30 files changed, 583 insertions, 349 deletions
diff --git a/src/compiler/scala/reflect/internal/ClassfileConstants.scala b/src/compiler/scala/reflect/internal/ClassfileConstants.scala
index 136350ebbb..f1bf41ede9 100644
--- a/src/compiler/scala/reflect/internal/ClassfileConstants.scala
+++ b/src/compiler/scala/reflect/internal/ClassfileConstants.scala
@@ -6,6 +6,8 @@
package scala.reflect
package internal
+import annotation.switch
+
object ClassfileConstants {
final val JAVA_MAGIC = 0xCAFEBABE
@@ -326,28 +328,62 @@ object ClassfileConstants {
final val impdep1 = 0xfe
final val impdep2 = 0xff
- def toScalaFlags(flags: Int, isClass: Boolean = false, isField: Boolean = false): Long = {
+ abstract class FlagTranslation {
import Flags._
- var res = 0l
- if ((flags & JAVA_ACC_PRIVATE) != 0)
- res = res | PRIVATE
- else if ((flags & JAVA_ACC_PROTECTED) != 0)
- res = res | PROTECTED
- if ((flags & JAVA_ACC_ABSTRACT) != 0 && (flags & JAVA_ACC_ANNOTATION) == 0)
- res = res | DEFERRED
- if ((flags & JAVA_ACC_FINAL) != 0)
- res = res | FINAL
- if (((flags & JAVA_ACC_INTERFACE) != 0) &&
- ((flags & JAVA_ACC_ANNOTATION) == 0))
- res = res | TRAIT | INTERFACE | ABSTRACT
- if ((flags & JAVA_ACC_SYNTHETIC) != 0)
- res = res | SYNTHETIC
- if ((flags & JAVA_ACC_STATIC) != 0)
- res = res | STATIC
- if (isClass && ((res & DEFERRED) != 0L))
- res = res & ~DEFERRED | ABSTRACT
- if (isField && (res & FINAL) == 0L)
- res = res | MUTABLE
- res | JAVA
+
+ private var isAnnotation = false
+ private var isClass = false
+ private def initFields(flags: Int) = {
+ isAnnotation = (flags & JAVA_ACC_ANNOTATION) != 0
+ isClass = false
+ }
+ private def translateFlag(jflag: Int): Long = (jflag: @switch) match {
+ case JAVA_ACC_PRIVATE => PRIVATE
+ case JAVA_ACC_PROTECTED => PROTECTED
+ case JAVA_ACC_FINAL => FINAL
+ case JAVA_ACC_SYNTHETIC => SYNTHETIC
+ case JAVA_ACC_STATIC => STATIC
+ case JAVA_ACC_ABSTRACT => if (isAnnotation) 0L else if (isClass) ABSTRACT else DEFERRED
+ case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT
+ case _ => 0L
+ }
+ private def translateFlags(jflags: Int, baseFlags: Long): Long = {
+ var res: Long = JAVA | baseFlags
+ /** fast, elegant, maintainable, pick any two... */
+ res |= translateFlag(jflags & JAVA_ACC_PRIVATE)
+ res |= translateFlag(jflags & JAVA_ACC_PROTECTED)
+ res |= translateFlag(jflags & JAVA_ACC_FINAL)
+ res |= translateFlag(jflags & JAVA_ACC_SYNTHETIC)
+ res |= translateFlag(jflags & JAVA_ACC_STATIC)
+ res |= translateFlag(jflags & JAVA_ACC_ABSTRACT)
+ res |= translateFlag(jflags & JAVA_ACC_INTERFACE)
+ res
+ }
+
+ def classFlags(jflags: Int): Long = {
+ initFields(jflags)
+ isClass = true
+ translateFlags(jflags, 0)
+ }
+ def fieldFlags(jflags: Int): Long = {
+ initFields(jflags)
+ translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0)
+ }
+ def methodFlags(jflags: Int): Long = {
+ initFields(jflags)
+ translateFlags(jflags, 0)
+ }
}
+ object FlagTranslation extends FlagTranslation { }
+
+ def toScalaMethodFlags(flags: Int): Long = FlagTranslation methodFlags flags
+ def toScalaClassFlags(flags: Int): Long = FlagTranslation classFlags flags
+ def toScalaFieldFlags(flags: Int): Long = FlagTranslation fieldFlags flags
+
+ @deprecated("Use another method in this object", "2.10.0")
+ def toScalaFlags(flags: Int, isClass: Boolean = false, isField: Boolean = false): Long = (
+ if (isClass) toScalaClassFlags(flags)
+ else if (isField) toScalaFieldFlags(flags)
+ else toScalaMethodFlags(flags)
+ )
}
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index f4abb8cad3..d38b62cbb4 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -16,14 +16,12 @@ 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 setInfo ClassInfoType(parents, new Scope, clazz)
- owner.info.decls enter clazz
+ clazz setInfoAndEnter ClassInfoType(parents, new Scope, 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)
val params = msym.newSyntheticValueParams(formals)
- msym setInfo MethodType(params, restpe)
- owner.info.decls enter msym
+ msym setInfoAndEnter MethodType(params, restpe)
}
// the scala value classes
@@ -130,7 +128,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
// the source level, but _root_ is essentially a function () => <root>.
lazy val RootPackage: Symbol = {
val rp = (
- NoSymbol.newValue(nme.ROOTPKG, flags = FINAL | MODULE | PACKAGE | JAVA)
+ NoSymbol.newValue(nme.ROOTPKG, NoPosition, FINAL | MODULE | PACKAGE | JAVA)
setInfo NullaryMethodType(RootClass.tpe)
)
RootClass.sourceModule = rp
@@ -139,11 +137,11 @@ trait Definitions extends reflect.api.StandardDefinitions {
// This is the actual root of everything, including the package _root_.
lazy val RootClass: ModuleClassSymbol = (
- NoSymbol.newModuleClassSymbol(tpnme.ROOT, flags = FINAL | MODULE | PACKAGE | JAVA)
+ NoSymbol.newModuleClassSymbol(tpnme.ROOT, NoPosition, FINAL | MODULE | PACKAGE | JAVA)
setInfo rootLoader
)
// The empty package, which holds all top level types without given packages.
- lazy val EmptyPackage = RootClass.newPackage(nme.EMPTY_PACKAGE_NAME, flags = FINAL)
+ lazy val EmptyPackage = RootClass.newPackage(nme.EMPTY_PACKAGE_NAME, NoPosition, FINAL)
lazy val EmptyPackageClass = EmptyPackage.moduleClass
lazy val JavaLangPackage = getModule(sn.JavaLang)
@@ -208,8 +206,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
sealed abstract class BottomClassSymbol(name: TypeName, parent: Symbol) extends ClassSymbol(ScalaPackageClass, NoPosition, name) {
locally {
this initFlags ABSTRACT | TRAIT | FINAL
- this setInfo ClassInfoType(List(parent.tpe), new Scope, this)
- owner.info.decls enter this
+ this setInfoAndEnter ClassInfoType(List(parent.tpe), new Scope, this)
}
final override def isBottomClass = true
}
@@ -829,12 +826,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
ClassInfoType(List(AnyRefClass.tpe, p), new Scope, clazz)))
}
- private def newAlias(owner: Symbol, name: TypeName, alias: Type): Symbol = {
- val tpsym = owner.newAliasType(name)
- tpsym.setInfo(alias)
- owner.info.decls.enter(tpsym)
- tpsym
- }
+ private def newAlias(owner: Symbol, name: TypeName, alias: Type): Symbol =
+ owner.newAliasType(name) setInfoAndEnter alias
/** tcon receives the type parameter symbol as argument */
private def newPolyMethod(owner: Symbol, name: TermName, tcon: Symbol => Type): Symbol =
diff --git a/src/compiler/scala/reflect/internal/HasFlags.scala b/src/compiler/scala/reflect/internal/HasFlags.scala
index 46dca0940a..ec4e919bdc 100644
--- a/src/compiler/scala/reflect/internal/HasFlags.scala
+++ b/src/compiler/scala/reflect/internal/HasFlags.scala
@@ -136,6 +136,9 @@ trait HasFlags {
/** Whether this entity has NONE of the flags in the given mask.
*/
def hasNoFlags(mask: Long): Boolean = !hasFlag(mask)
+
+ protected def isSetting(f: Long, mask: Long) = !hasFlag(f) && ((mask & f) != 0L)
+ protected def isClearing(f: Long, mask: Long) = hasFlag(f) && ((mask & f) != 0L)
// Tests which come through cleanly: both Symbol and Modifiers use these
// identically, testing for a single flag.
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index d969cb43bb..1b9ff54141 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -42,6 +42,10 @@ 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 =
+ new FreeVar(name, value) initFlags newFlags setInfo tpe
/** The original owner of a class. Used by the backend to generate
* EnclosingMethod attributes.
@@ -49,9 +53,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
val originalOwner = perRunCaches.newMap[Symbol, Symbol]()
abstract class AbsSymbolImpl extends AbsSymbol { this: Symbol =>
- def newNestedSymbol(pos: Position, name: Name) = name match {
- case n: TermName => newTermSymbol(n, pos)
- case n: TypeName => newTypeSymbol(n, pos)
+ def newNestedSymbol(name: Name, pos: Position, newFlags: Long) = name match {
+ case n: TermName => newTermSymbol(n, pos, newFlags)
+ case n: TypeName => newTypeSymbol(n, pos, newFlags)
}
def typeSig: Type = info
def typeSigIn(site: Type): Type = site.memberInfo(this)
@@ -79,7 +83,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private var rawpos = initPos
val id = { ids += 1; ids } // identity displayed when -uniqid
- //assert(id != 3204, initName)
var validTo: Period = NoPeriod
@@ -96,24 +99,24 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ------ creators -------------------------------------------------------------------
- final def newValue(name: TermName, pos: Position = NoPosition, flags: Long = 0L): TermSymbol =
- newTermSymbol(name, pos, flags)
- final def newVariable(name: TermName, pos: Position = NoPosition, flags: Long = 0L): TermSymbol =
- newTermSymbol(name, pos, MUTABLE | flags)
- final def newValueParameter(name: TermName, pos: Position = NoPosition, flags: Long = 0L): TermSymbol =
- newTermSymbol(name, pos, PARAM | flags)
+ final def newValue(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
+ newTermSymbol(name, pos, newFlags)
+ final def newVariable(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
+ newTermSymbol(name, pos, MUTABLE | newFlags)
+ final def newValueParameter(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
+ newTermSymbol(name, pos, PARAM | newFlags)
/** Create local dummy for template (owner of local blocks) */
final def newLocalDummy(pos: Position) =
newTermSymbol(nme.localDummyName(this), pos) setInfo NoType
- final def newMethod(name: TermName, pos: Position = NoPosition, flags: Long = 0L): MethodSymbol =
- newMethodSymbol(name, pos, METHOD | flags)
+ final def newMethod(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol =
+ newMethodSymbol(name, pos, METHOD | newFlags)
final def newLabel(name: TermName, pos: Position = NoPosition): MethodSymbol =
newMethod(name, pos, LABEL)
/** Propagates ConstrFlags (JAVA, specifically) from owner to constructor. */
- final def newConstructor(pos: Position, flags: Long = 0L) =
- newMethod(nme.CONSTRUCTOR, pos, getFlag(ConstrFlags) | flags)
+ final def newConstructor(pos: Position, newFlags: Long = 0L) =
+ newMethod(nme.CONSTRUCTOR, pos, getFlag(ConstrFlags) | newFlags)
/** Static constructor with info set. */
def newStaticConstructor(pos: Position) =
@@ -128,48 +131,63 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (isPackage || !settings.overrideObjects.value) MODULE | FINAL
else MODULE
)
- def newLinkedModule(clazz: Symbol, flags: Long = 0L): ModuleSymbol = {
- val m = newModuleSymbol(clazz.name.toTermName, clazz.pos, ModuleFlags | flags)
+ def newLinkedModule(clazz: Symbol, newFlags: Long = 0L): ModuleSymbol = {
+ val m = newModuleSymbol(clazz.name.toTermName, clazz.pos, ModuleFlags | newFlags)
connectModuleToClass(m, clazz.asInstanceOf[ClassSymbol])
}
- final def newModule(name: TermName, pos: Position = NoPosition, flags: Long = 0L): ModuleSymbol = {
- val m = newModuleSymbol(name, pos, flags | ModuleFlags)
+ final def newModule(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = {
+ val m = newModuleSymbol(name, pos, newFlags | ModuleFlags)
val clazz = newModuleClassSymbol(name.toTypeName, pos, (m getFlag ModuleToClassFlags) | MODULE)
connectModuleToClass(m, clazz)
}
- final def newPackage(name: TermName, pos: Position = NoPosition, flags: Long = 0L): ModuleSymbol = {
+ final def newPackage(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = {
assert(name == nme.ROOT || isPackageClass, this)
- newModule(name, pos, JAVA | PACKAGE | flags)
+ newModule(name, pos, JAVA | PACKAGE | newFlags)
}
final def newThisSym(pos: Position) =
newTermSymbol(nme.this_, pos, SYNTHETIC)
final def newImport(pos: Position) =
newTermSymbol(nme.IMPORT, pos)
-
+
/** Direct symbol factories.
* For internal use; these are unlikely to be what you want.
*/
- def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: Long = 0L): TermSymbol =
- new TermSymbol(this, pos, name) initFlags flags
+ def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
+ new TermSymbol(this, pos, name) initFlags newFlags
- def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: Long = 0L): TypeSymbol =
- new TypeSymbol(this, pos, name) initFlags flags
+ def newAbstractTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol =
+ new AbstractTypeSymbol(this, pos, name) initFlags newFlags
+
+ def newAliasTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol =
+ new AliasTypeSymbol(this, pos, name) initFlags newFlags
- def newModuleSymbol(name: TermName, pos: Position = NoPosition, flags: Long = 0L): ModuleSymbol =
- new ModuleSymbol(this, pos, name) initFlags flags
+ def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol =
+ new ModuleSymbol(this, pos, name) initFlags newFlags
- def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: Long = 0L): MethodSymbol =
- new MethodSymbol(this, pos, name) initFlags flags
+ def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol =
+ new MethodSymbol(this, pos, name) initFlags newFlags
- def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: Long = 0L): ClassSymbol =
- new ClassSymbol(this, pos, name) initFlags flags
+ def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol =
+ new ClassSymbol(this, pos, name) initFlags newFlags
- def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, flags: Long = 0L): ModuleClassSymbol =
- new ModuleClassSymbol(this, pos, name) initFlags flags
+ def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol =
+ new ModuleClassSymbol(this, pos, name) initFlags newFlags
+
+ /** Derive whether it is an abstract type from the flags; after creation
+ * the DEFERRED flag will be ignored.
+ */
+ def newTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol =
+ if ((newFlags & DEFERRED) == 0L)
+ newAliasTypeSymbol(name, pos, newFlags)
+ else
+ newAbstractTypeSymbol(name, pos, newFlags)
- def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, flags: Long = 0L): TypeSkolem =
- new TypeSkolem(this, pos, name, origin) initFlags flags
+ def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem =
+ if ((newFlags & DEFERRED) == 0L)
+ new TypeSkolem(this, pos, name, origin) initFlags newFlags
+ else
+ new TypeSkolem(this, pos, name, origin) with AbstractTypeMixin initFlags newFlags
/** @param pre type relative to which alternatives are seen.
* for instance:
@@ -210,18 +228,18 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Symbol of a type definition type T = ...
*/
- final def newAliasType(name: TypeName, pos: Position = NoPosition, flags: Long = 0L): Symbol =
- newTypeSymbol(name, pos, flags)
+ final def newAliasType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol =
+ newAliasTypeSymbol(name, pos, newFlags)
/** Symbol of an abstract type type T >: ... <: ...
*/
- final def newAbstractType(name: TypeName, pos: Position = NoPosition, flags: Long = 0L): Symbol =
- newTypeSymbol(name, pos, DEFERRED | flags)
+ final def newAbstractType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol =
+ newAbstractTypeSymbol(name, pos, DEFERRED | newFlags)
/** Symbol of a type parameter
*/
- final def newTypeParameter(name: TypeName, pos: Position = NoPosition, flags: Long = 0L) =
- newAbstractType(name, pos, PARAM | flags)
+ final def newTypeParameter(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) =
+ newAbstractType(name, pos, PARAM | newFlags)
/** Synthetic value parameters when parameter symbols are not available
*/
@@ -231,11 +249,19 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
mmap(argtypess)(tp => newValueParameter(freshName(), focusPos(owner.pos), SYNTHETIC) setInfo tp)
}
- final def newExistential(name: TypeName, pos: Position = NoPosition, flags: Long = 0L): Symbol =
- newAbstractType(name, pos, EXISTENTIAL | flags)
+ /** Create a new existential type skolem with this symbol its owner,
+ * based on the given symbol and origin.
+ */
+ def newExistentialSkolem(basis: Symbol, origin: AnyRef): TypeSkolem = {
+ val skolem = newTypeSkolemSymbol(basis.name.toTypeName, origin, basis.pos, (basis.flags | EXISTENTIAL) & ~PARAM)
+ skolem setInfo (basis.info cloneInfo skolem)
+ }
+
+ final def newExistential(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol =
+ newAbstractType(name, pos, EXISTENTIAL | newFlags)
final def freshExistential(suffix: String): Symbol =
- newExistential(pos, freshExistentialName(suffix))
+ newExistential(freshExistentialName(suffix), pos)
/** Synthetic value parameters when parameter symbols are not available.
* Calling this method multiple times will re-use the same parameter names.
@@ -257,8 +283,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def newTypeSkolem: Symbol =
owner.newTypeSkolemSymbol(name.toTypeName, this, pos, flags)
- final def newClass(name: TypeName, pos: Position = NoPosition) =
- newClassSymbol(name, pos)
+ final def newClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) =
+ newClassSymbol(name, pos, newFlags)
final def newModuleClass(name: TypeName, pos: Position = NoPosition) =
newModuleClassSymbol(name, pos)
@@ -266,11 +292,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def newAnonymousClass(pos: Position) =
newClassSymbol(tpnme.ANON_CLASS_NAME, pos)
- final def newAnonymousFunctionClass(pos: Position, flags: Long = 0L) =
- newClassSymbol(tpnme.ANON_FUN_NAME, pos, FINAL | SYNTHETIC | flags)
+ final def newAnonymousFunctionClass(pos: Position, newFlags: Long = 0L) =
+ newClassSymbol(tpnme.ANON_FUN_NAME, pos, FINAL | SYNTHETIC | newFlags)
- final def newAnonymousFunctionValue(pos: Position, flags: Long = 0L) =
- newTermSymbol(nme.ANON_FUN_NAME, pos, SYNTHETIC | flags) setInfo NoType
+ final def newAnonymousFunctionValue(pos: Position, newFlags: Long = 0L) =
+ newTermSymbol(nme.ANON_FUN_NAME, pos, SYNTHETIC | newFlags) setInfo NoType
/** Refinement types P { val x: String; type T <: Number }
* also have symbols, they are refinementClasses
@@ -281,7 +307,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Create a new getter for current symbol (which must be a field)
*/
final def newGetter: Symbol = (
- owner.newMethod(nme.getterName(name.toTermName), flags = getterFlags(flags))
+ owner.newMethod(nme.getterName(name.toTermName), NoPosition, getterFlags(flags))
setPrivateWithin privateWithin
setInfo MethodType(Nil, tpe)
)
@@ -454,9 +480,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass
// A package object or its module class
- final def isPackageObjectOrClass = name == nme.PACKAGE || name == tpnme.PACKAGE
- final def isPackageObject = name == nme.PACKAGE && owner.isPackageClass
- final def isPackageObjectClass = name == tpnme.PACKAGE && owner.isPackageClass
+ final def isPackageObjectOrClass = (this ne NoSymbol) && owner.isPackageClass && (name == nme.PACKAGE || name == tpnme.PACKAGE)
+ final def isPackageObject = (this ne NoSymbol) && owner.isPackageClass && name == nme.PACKAGE
+ final def isPackageObjectClass = (this ne NoSymbol) && owner.isPackageClass && name == tpnme.PACKAGE
final def isDefinedInPackage = effectiveOwner.isPackageClass
final def isJavaInterface = isJavaDefined && isTrait
@@ -467,7 +493,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** The owner, skipping package objects.
*/
- def effectiveOwner = owner.skipPackageObject
+ def effectiveOwner = if (owner.isPackageObjectClass) owner.skipPackageObject else owner
/** If this is a package object or its implementing class, its owner: otherwise this.
*/
@@ -976,6 +1002,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Substitute second list of symbols for first in current info. */
def substInfo(syms0: List[Symbol], syms1: List[Symbol]) = modifyInfo(_.substSym(syms0, syms1))
def setInfoOwnerAdjusted(info: Type): this.type = setInfo(info atOwner this)
+
+ /** Set the info and enter this symbol into the owner's scope. */
+ def setInfoAndEnter(info: Type): this.type = {
+ setInfo(info)
+ owner.info.decls enter this
+ this
+ }
/** Set new info valid from start of this phase. */
final def updateInfo(info: Type): Symbol = {
@@ -1180,15 +1213,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* the bound of the type variable that stands for it
* pre: symbol is a term, a class, or an abstract type (no alias type allowed)
*/
- def existentialBound: Type =
- if (this.isClass)
- polyType(this.typeParams, TypeBounds.upper(this.classBound))
- else if (this.isAbstractType)
- this.info
- else if (this.isTerm)
- singletonBounds(this.tpe)
- else
- abort("unexpected alias type: "+this.ownerChain+ " " + hasFlagsToString(-1L))
+ def existentialBound: Type
/** Reset symbol to initial state
*/
@@ -1322,17 +1347,17 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** A clone of this symbol, but with given owner. */
final def cloneSymbol(owner: Symbol): Symbol = {
- val newSym = cloneSymbolImpl(owner)
+ val newSym = cloneSymbolImpl(owner, this.rawflags)
( newSym
- initFlags this.rawflags
setPrivateWithin privateWithin
setInfo (info cloneInfo newSym)
setAnnotations this.annotations
)
}
-
- /** Internal method to clone a symbol's implementation without flags or type. */
- def cloneSymbolImpl(owner: Symbol): Symbol
+
+ /** Internal method to clone a symbol's implementation with the given flags and no info. */
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol
+ def cloneSymbolImpl(owner: Symbol): Symbol = cloneSymbolImpl(owner, 0L)
// ------ access to related symbols --------------------------------------------------
@@ -2036,9 +2061,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
privateWithin = NoSymbol
var referenced: Symbol = NoSymbol
+
+ def existentialBound = singletonBounds(this.tpe)
- def cloneSymbolImpl(owner: Symbol): Symbol =
- owner.newTermSymbol(name, pos).copyAttrsFrom(this)
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
+ owner.newTermSymbol(name, pos, newFlags).copyAttrsFrom(this)
def copyAttrsFrom(original: TermSymbol): this.type = {
referenced = original.referenced
@@ -2134,8 +2161,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else rawname.toTermName
)
- override def cloneSymbolImpl(owner: Symbol): Symbol =
- owner.newModuleSymbol(name, pos).copyAttrsFrom(this)
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
+ owner.newModuleSymbol(name, pos, newFlags).copyAttrsFrom(this)
}
/** A class for method symbols */
@@ -2146,8 +2173,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private var mtpeResult: Type = _
private var mtpeInfo: Type = _
- override def cloneSymbolImpl(owner: Symbol): Symbol =
- owner.newMethodSymbol(name, pos).copyAttrsFrom(this)
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
+ owner.newMethodSymbol(name, pos, newFlags).copyAttrsFrom(this)
def typeAsMemberOf(pre: Type): Type = {
if (mtpePeriod == currentPeriod) {
@@ -2164,24 +2191,71 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
res
}
}
+
+ class AliasTypeSymbol(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 = {
+ if (isSetting(DEFERRED, mask)) {
+ println("Setting DEFERRED on alias at")
+ (new Throwable).printStackTrace
+ }
+ super.setFlag(mask)
+ }
+ final override def isAliasType = true
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): AliasTypeSymbol =
+ owner.newAliasTypeSymbol(name, pos, newFlags)
+ }
+
+ class AbstractTypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
+ extends TypeSymbol(initOwner, initPos, initName) with AbstractTypeMixin {
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): AbstractTypeSymbol =
+ owner.newAbstractTypeSymbol(name, pos, newFlags)
+ }
+
+ /** Might be mixed into TypeSymbol or TypeSkolem.
+ */
+ trait AbstractTypeMixin extends TypeSymbol {
+ override def resetFlag(mask: Long): this.type = {
+ // Temporary programmatic help tracking down who might do such a thing
+ if (settings.debug.value) {
+ if (isClearing(DEFERRED, mask)) {
+ println("Clearing DEFERRED on abstract type at")
+ (new Throwable).printStackTrace
+ }
+ }
+ super.resetFlag(mask)
+ }
+ final override def isAbstractType = true
+ override def existentialBound = this.info
+ }
/** A class of type symbols. Alias and abstract types are direct instances
* of this class. Classes are instances of a subclass.
*/
- class TypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
- extends Symbol(initOwner, initPos, initName) {
+ sealed abstract class TypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) extends Symbol(initOwner, initPos, initName) {
privateWithin = NoSymbol
private var tyconCache: Type = null
private var tyconRunId = NoRunId
private var tpeCache: Type = _
private var tpePeriod = NoPeriod
+ /** Overridden in subclasses for which it makes sense.
+ */
+ def existentialBound: Type = abort("unexpected type: "+this.getClass+ " "+this.fullLocationString+ " " + hasFlagsToString(-1L))
+
override def name: TypeName = super.name.asInstanceOf[TypeName]
final override def isType = true
override def isNonClassType = true
- override def isAbstractType = isDeferred
- override def isAliasType = !isDeferred
-
+ override def isAbstractType = {
+ if (settings.debug.value) {
+ if (isDeferred) {
+ println("TypeSymbol claims to be abstract type: " + this.getClass + " " + hasFlagsToString(-1L) + " at ")
+ (new Throwable).printStackTrace
+ }
+ }
+ isDeferred
+ }
private def newTypeRef(targs: List[Type]) = {
val pre = if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType
typeRef(pre, this, targs)
@@ -2278,7 +2352,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
}
- def cloneSymbolImpl(owner: Symbol): Symbol = owner.newTypeSymbol(name, pos)
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
+ owner.newTypeSymbol(name, pos, newFlags)
incCounter(typeSymbolCount)
}
@@ -2316,8 +2391,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
//@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo
override def typeParams = info.typeParams
- override def cloneSymbolImpl(owner: Symbol): Symbol =
- owner.newTypeSkolemSymbol(name, origin, pos)
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
+ owner.newTypeSkolemSymbol(name, origin, pos, newFlags)
override def nameString: String =
if (settings.debug.value) (super.nameString + "&" + level)
@@ -2335,6 +2410,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final override def isNonClassType = false
final override def isAbstractType = false
final override def isAliasType = false
+
+ override def existentialBound = polyType(this.typeParams, TypeBounds.upper(this.classBound))
override def sourceFile =
if (owner.isPackageClass) source
@@ -2397,8 +2474,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
thissym = newThisSym(pos).setInfo(tp)
}
- override def cloneSymbolImpl(owner: Symbol): Symbol = {
- val clone = owner.newClassSymbol(name, pos)
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = {
+ val clone = owner.newClassSymbol(name, pos, newFlags)
if (thisSym != this) {
clone.typeOfThis = typeOfThis
clone.thisSym.name = thisSym.name
@@ -2432,25 +2509,27 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if ((implicitMembersCacheKey1 ne tp) || (implicitMembersCacheKey2 ne tp.decls.elems)) {
implicitMembersCacheKey1 = tp
implicitMembersCacheKey2 = tp.decls.elems
- implicitMembersCacheValue = tp.implicitMembers
+ // When a package object which defines an implicit, it may turn up here in two
+ // forms which are not recognized as the same implicit definition, creating a
+ // spurious ambiguity (see pos/t3999). Since I haven't figured out package objects
+ // well enough to fix this at the root, I am filtering here by applying the
+ // property that a member's owner must be unique.
+ if (isPackageClass)
+ implicitMembersCacheValue = tp.implicitMembers filter (_.owner eq this)
+ else
+ implicitMembersCacheValue = tp.implicitMembers
}
implicitMembersCacheValue
}
override def sourceModule = module
override def sourceModule_=(module: Symbol) { this.module = module }
}
-
- def newFreeVar(name0: TermName, tpe: Type, value: Any, flags: Long = 0L) =
- new FreeVar(name0, tpe, value) initFlags flags
-
- class FreeVar(name0: TermName, tpe: Type, val value: Any) extends TermSymbol(definitions.RootClass, NoPosition, name0) {
- setInfo(tpe)
+ class FreeVar(name0: TermName, val value: Any) extends TermSymbol(NoSymbol, NoPosition, name0) {
override def hashCode = value.hashCode
-
override def equals(other: Any): Boolean = other match {
case that: FreeVar => this.value.asInstanceOf[AnyRef] eq that.value.asInstanceOf[AnyRef]
- case _ => false
+ case _ => false
}
}
@@ -2477,10 +2556,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def alternatives: List[Symbol] = List()
override def reset(completer: Type) {}
override def info: Type = NoType
+ override def existentialBound: Type = NoType
override def rawInfo: Type = NoType
protected def doCookJavaRawInfo() {}
override def accessBoundary(base: Symbol): Symbol = RootClass
- def cloneSymbolImpl(owner: Symbol): Symbol = abort()
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = abort()
override def originalEnclosingMethod = this
}
@@ -2552,13 +2632,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def mapParamss[T](sym: Symbol)(f: Symbol => T): List[List[T]] = mmap(sym.info.paramss)(f)
- /** Create a new existential type skolem with the given owner and origin.
- */
- def newExistentialSkolem(sym: Symbol, owner: Symbol, origin: AnyRef): TypeSkolem = {
- val skolem = owner.newTypeSkolemSymbol(sym.name.toTypeName, origin, sym.pos, (sym.flags | EXISTENTIAL) & ~PARAM)
- skolem setInfo (sym.info cloneInfo skolem)
- }
-
/** An exception for cyclic references of symbol definitions */
case class CyclicReference(sym: Symbol, info: Type)
extends TypeError("illegal cyclic reference involving " + sym) {
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index fa62d00c6a..dfe098e282 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -1814,13 +1814,18 @@ trait Types extends api.Types { self: SymbolTable =>
override def typeConstructor = this
// eta-expand, subtyping relies on eta-expansion of higher-kinded types
- // override protected def normalizeImpl: Type =
- // if (isHigherKinded) etaExpand else super.normalizeImpl
+
+ override protected def normalizeImpl: Type =
+ if (isHigherKinded) etaExpand else super.normalizeImpl
}
trait ClassTypeRef extends TypeRef {
// !!! There are scaladoc-created symbols arriving which violate this require.
// require(sym.isClass, sym)
+
+ override protected def normalizeImpl: Type =
+ if (sym.isRefinementClass) sym.info.normalize // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers
+ else super.normalizeImpl
override def baseType(clazz: Symbol): Type =
if (sym == clazz) this
@@ -1868,12 +1873,40 @@ trait Types extends api.Types { self: SymbolTable =>
override def isVolatile = normalize.isVolatile
override def narrow = normalize.narrow
override def thisInfo = normalize
- // override def prefix = normalize.prefix
- // override def termSymbol = if (this ne normalize) normalize.termSymbol else super.termSymbol
- // override def typeSymbol = if (this ne normalize) normalize.typeSymbol else sym
+ override def prefix = if (this ne normalize) normalize.prefix else pre
+ override def termSymbol = if (this ne normalize) normalize.termSymbol else super.termSymbol
+ override def typeSymbol = if (this ne normalize) normalize.typeSymbol else sym
+
// beta-reduce, but don't do partial application -- cycles have been checked in typeRef
- // override protected zzImpl =
- // if (typeParamsMatchArgs) betaReduce.normalize else ErrorType
+ override protected def normalizeImpl =
+ if (typeParamsMatchArgs) betaReduce.normalize
+ else if (isHigherKinded) super.normalizeImpl
+ else ErrorType
+
+ // isHKSubType0 introduces synthetic type params so that
+ // betaReduce can first apply sym.info to typeArgs before calling
+ // asSeenFrom. asSeenFrom then skips synthetic type params, which
+ // are used to reduce HO subtyping to first-order subtyping, but
+ // which can't be instantiated from the given prefix and class.
+ //
+ // this crashes pos/depmet_implicit_tpbetareduce.scala
+ // appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner)
+ def betaReduce = transform(sym.info.resultType)
+
+ // #3731: return sym1 for which holds: pre bound sym.name to sym and
+ // pre1 now binds sym.name to sym1, conceptually exactly the same
+ // symbol as sym. The selection of sym on pre must be updated to the
+ // selection of sym1 on pre1, since sym's info was probably updated
+ // by the TypeMap to yield a new symbol, sym1 with transformed info.
+ // @returns sym1
+ override def coevolveSym(pre1: Type): Symbol =
+ if (pre eq pre1) sym else (pre, pre1) match {
+ // don't look at parents -- it would be an error to override alias types anyway
+ case (RefinedType(_, _), RefinedType(_, decls1)) => decls1 lookup sym.name
+ // TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre?
+ case _ => sym
+ }
+
}
trait AbstractTypeRef extends NonClassTypeRef {
@@ -1920,7 +1953,7 @@ trait Types extends api.Types { self: SymbolTable =>
thisInfoCache
}
override def isStable = bounds.hi.typeSymbol isSubClass SingletonClass
- override def bounds = if (sym.isAbstractType) thisInfo.bounds else super.bounds
+ 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
}
@@ -1945,33 +1978,20 @@ trait Types extends api.Types { self: SymbolTable =>
// corresponding type parameters (unbound type variables)
def transform(tp: Type): Type
- private def normalize0: Type = (
- if (pre eq WildcardType) WildcardType // arises when argument-dependent types are approximated (see def depoly in implicits)
- else if (isHigherKinded) etaExpand // eta-expand, subtyping relies on eta-expansion of higher-kinded types
- else if (sym.isAliasType && typeParamsMatchArgs) betaReduce.normalize // beta-reduce, but don't do partial application -- cycles have been checked in typeRef
- else if (sym.isRefinementClass) sym.info.normalize // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers
- else if (sym.isAliasType) ErrorType //println("!!error: "+(pre, sym, sym.info, sym.info.typeParams, args))
- else super.normalize
- )
+ // eta-expand, subtyping relies on eta-expansion of higher-kinded types
+ protected def normalizeImpl: Type = if (isHigherKinded) etaExpand else super.normalize
- // TODO: test case that is compiled in a specific order and in different runs
- override def normalize: Type = {
- if (phase.erasedTypes) normalize0
+ // TODO: test case that is compiled in a specific order and in different runs
+ final override def normalize: Type = {
+ // arises when argument-dependent types are approximated (see def depoly in implicits)
+ if (pre eq WildcardType) WildcardType
+ else if (phase.erasedTypes) normalizeImpl
else {
if (normalized eq null)
- normalized = normalize0
+ normalized = normalizeImpl
normalized
}
}
- // isHKSubType0 introduces synthetic type params so that
- // betaReduce can first apply sym.info to typeArgs before calling
- // asSeenFrom. asSeenFrom then skips synthetic type params, which
- // are used to reduce HO subtyping to first-order subtyping, but
- // which can't be instantiated from the given prefix and class.
- //
- // this crashes pos/depmet_implicit_tpbetareduce.scala
- // appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner)
- def betaReduce = transform(sym.info.resultType)
def etaExpand: Type = {
// must initialise symbol, see test/files/pos/ticket0137.scala
@@ -1980,23 +2000,9 @@ trait Types extends api.Types { self: SymbolTable =>
else typeFunAnon(tpars, copyTypeRef(this, pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
}
- // #3731: return sym1 for which holds: pre bound sym.name to sym and
- // pre1 now binds sym.name to sym1, conceptually exactly the same
- // symbol as sym. The selection of sym on pre must be updated to the
- // selection of sym1 on pre1, since sym's info was probably updated
- // by the TypeMap to yield a new symbol, sym1 with transformed info.
- // @returns sym1
- //
// only need to rebind type aliases, as typeRef already handles abstract types
// (they are allowed to be rebound more liberally)
- def coevolveSym(pre1: Type): Symbol =
- if (!sym.isAliasType || (pre eq pre1)) sym
- else (pre, pre1) match {
- // don't look at parents -- it would be an error to override alias types anyway
- case (RefinedType(_, _), RefinedType(_, decls1)) => decls1 lookup sym.name
- // TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre?
- case _ => sym
- }
+ def coevolveSym(pre1: Type): Symbol = sym
//@M! use appliedType on the polytype that represents the bounds (or if aliastype, the rhs)
def transformInfo(tp: Type): Type = appliedType(asSeenFromOwner(tp), args)
@@ -2009,13 +2015,13 @@ trait Types extends api.Types { self: SymbolTable =>
override def baseClasses = thisInfo.baseClasses
override def baseTypeSeqDepth = baseTypeSeq.maxDepth
override def isStable = (sym eq NothingClass) || (sym eq SingletonClass)
- override def prefix = if (sym.isAliasType && (this ne normalize)) normalize.prefix else pre
+ override def prefix = pre
+ override def termSymbol = super.termSymbol
+ override def termSymbolDirect = super.termSymbol
override def typeArgs = args
override def typeOfThis = transform(sym.typeOfThis)
- override def termSymbol = if (sym.isAliasType && (this ne normalize)) normalize.termSymbol else super.termSymbol
- override def typeSymbol = if (sym.isAliasType && (this ne normalize)) normalize.typeSymbol else sym
+ override def typeSymbol = sym
override def typeSymbolDirect = sym
- override def termSymbolDirect = super.termSymbol
override lazy val isTrivial: Boolean =
!sym.isTypeParameter && pre.isTrivial && args.forall(_.isTrivial)
@@ -2332,7 +2338,7 @@ trait Types extends api.Types { self: SymbolTable =>
override def isHigherKinded = false
override def skolemizeExistential(owner: Symbol, origin: AnyRef) =
- deriveType(quantified, tparam => newExistentialSkolem(tparam, owner orElse tparam.owner, origin))(underlying)
+ deriveType(quantified, tparam => (owner orElse tparam.owner).newExistentialSkolem(tparam, origin))(underlying)
private def wildcardArgsString(available: Set[Symbol], args: List[Type]): List[String] = args match {
case TypeRef(_, sym, _) :: args1 if (available contains sym) =>
@@ -3359,7 +3365,9 @@ trait Types extends api.Types { self: SymbolTable =>
/** Guard these lists against AnyClass and NothingClass appearing,
* else loBounds.isEmpty will have different results for an empty
- * constraint and one with Nothing as a lower bound.
+ * constraint and one with Nothing as a lower bound. [Actually
+ * guarding addLoBound/addHiBound somehow broke raw types so it
+ * only guards against being created with them.]
*/
private var lobounds = lo0 filterNot (_.typeSymbolDirect eq NothingClass)
private var hibounds = hi0 filterNot (_.typeSymbolDirect eq AnyClass)
@@ -3378,8 +3386,7 @@ trait Types extends api.Types { self: SymbolTable =>
else if (!isNumericSubType(tp, numlo))
numlo = numericLoBound
}
- else if (tp.typeSymbolDirect ne NothingClass)
- lobounds ::= tp
+ else lobounds ::= tp
}
def checkWidening(tp: Type) {
@@ -3398,8 +3405,7 @@ trait Types extends api.Types { self: SymbolTable =>
else if (!isNumericSubType(numhi, tp))
numhi = numericHiBound
}
- else if (tp.typeSymbolDirect ne AnyClass)
- hibounds ::= tp
+ else hibounds ::= tp
}
def isWithinBounds(tp: Type): Boolean =
diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
index 3fddc990e4..b21b33e138 100644
--- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
@@ -282,7 +282,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
finishSym(tag match {
case TYPEsym => owner.newAbstractType(name.toTypeName)
- case ALIASsym => owner.newTypeSymbol(name.toTypeName)
+ case ALIASsym => owner.newAliasType(name.toTypeName)
case CLASSsym =>
val sym = (isClassRoot, isModuleFlag) match {
case (true, true) => moduleRoot.moduleClass
diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala
index fd3b9b9aa0..cd87d6331b 100644
--- a/src/compiler/scala/reflect/runtime/JavaToScala.scala
+++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala
@@ -154,7 +154,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
override def load(sym: Symbol) = {
debugInfo("completing from Java " + sym + "/" + clazz.fullName)//debug
assert(sym == clazz || (module != NoSymbol && (sym == module || sym == module.moduleClass)), sym)
- val flags = toScalaFlags(jclazz.getModifiers, isClass = true)
+ val flags = toScalaClassFlags(jclazz.getModifiers)
clazz setFlag (flags | JAVA)
if (module != NoSymbol) {
module setFlag (flags & PRIVATE | JAVA)
@@ -337,8 +337,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
if (pkg == NoSymbol) {
pkg = owner.newPackage(name)
pkg.moduleClass setInfo new LazyPackageType
- pkg setInfo pkg.moduleClass.tpe
- owner.info.decls enter pkg
+ pkg setInfoAndEnter pkg.moduleClass.tpe
info("made Scala "+pkg)
} else if (!pkg.isPackage)
throw new ReflectError(pkg+" is not a package")
@@ -469,7 +468,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
*/
private def jfieldAsScala(jfield: jField): Symbol = fieldCache.toScala(jfield) {
val field = sOwner(jfield).newValue(NoPosition, newTermName(jfield.getName))
- .setFlag(toScalaFlags(jfield.getModifiers, isField = true) | JAVA)
+ .setFlag(toScalaFieldFlags(jfield.getModifiers) | JAVA)
.setInfo(typeToScala(jfield.getGenericType))
fieldCache enter (jfield, field)
copyAnnotations(field, jfield)
@@ -489,7 +488,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
private def jmethodAsScala(jmeth: jMethod): Symbol = methodCache.toScala(jmeth) {
val clazz = sOwner(jmeth)
val meth = clazz.newMethod(NoPosition, newTermName(jmeth.getName))
- .setFlag(toScalaFlags(jmeth.getModifiers) | JAVA)
+ .setFlag(toScalaMethodFlags(jmeth.getModifiers) | JAVA)
methodCache enter (jmeth, meth)
val tparams = jmeth.getTypeParameters.toList map createTypeParameter
val paramtpes = jmeth.getGenericParameterTypes.toList map typeToScala
@@ -512,7 +511,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
// [Martin] Note: I know there's a lot of duplication wrt jmethodAsScala, but don't think it's worth it to factor this out.
val clazz = sOwner(jconstr)
val constr = clazz.newMethod(NoPosition, nme.CONSTRUCTOR)
- .setFlag(toScalaFlags(jconstr.getModifiers) | JAVA)
+ .setFlag(toScalaMethodFlags(jconstr.getModifiers) | JAVA)
constructorCache enter (jconstr, constr)
val tparams = jconstr.getTypeParameters.toList map createTypeParameter
val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala
diff --git a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala
index 9d66ca6c6e..fc4177e956 100644
--- a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala
+++ b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala
@@ -39,7 +39,7 @@ trait TreeBuildUtil extends Universe with api.TreeBuildUtil {
selectIn(owner.info, idx)
}
- def freeVar(name: String, info: Type, value: Any) = new FreeVar(newTermName(name), info, value)
+ def freeVar(name: String, info: Type, value: Any) = newFreeVar(newTermName(name), info, value)
def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers =
Modifiers(flags, privateWithin, annotations)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index 7388ecf163..46ade7d889 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -117,7 +117,7 @@ trait MarkupParsers {
* | `{` scalablock `}`
*/
def xAttributes = {
- val aMap = mutable.HashMap[String, Tree]()
+ val aMap = mutable.LinkedHashMap[String, Tree]()
while (isNameStart(ch)) {
val start = curOffset
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
index 937b0bdc3d..6421d6c8ef 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -619,6 +619,50 @@ abstract class TypeFlowAnalysis {
}
}
+ class MTFAGrowable extends MethodTFA {
+
+ import icodes._
+
+ /** discards what must be discarded, blanks what needs to be blanked out, and keeps the rest. */
+ def reinit(m: icodes.IMethod, staleOut: List[BasicBlock], inlined: collection.Set[BasicBlock], staleIn: collection.Set[BasicBlock]) {
+ if (this.method == null || this.method.symbol != m.symbol) {
+ init(m)
+ return
+ } else if(staleOut.isEmpty && inlined.isEmpty && staleIn.isEmpty) {
+ // this promotes invoking reinit if in doubt, no performance degradation will ensue!
+ return;
+ }
+
+ reinit {
+ // asserts conveying an idea what CFG shapes arrive here.
+ // staleIn foreach (p => assert( !in.isDefinedAt(p), p))
+ // staleIn foreach (p => assert(!out.isDefinedAt(p), p))
+ // inlined foreach (p => assert( !in.isDefinedAt(p), p))
+ // inlined foreach (p => assert(!out.isDefinedAt(p), p))
+ // inlined foreach (p => assert(!p.successors.isEmpty || p.lastInstruction.isInstanceOf[icodes.opcodes.THROW], p))
+ // staleOut foreach (p => assert( in.isDefinedAt(p), p))
+
+ // never rewrite in(m.startBlock)
+ staleOut foreach { b =>
+ if(!inlined.contains(b)) { worklist += b }
+ out(b) = typeFlowLattice.bottom
+ }
+ // nothing else is added to the worklist, bb's reachable via succs will be tfa'ed
+ blankOut(inlined)
+ blankOut(staleIn)
+ // no need to add startBlocks from m.exh
+ }
+ }
+
+ private def blankOut(blocks: collection.Set[BasicBlock]) {
+ blocks foreach { b =>
+ in(b) = typeFlowLattice.bottom
+ out(b) = typeFlowLattice.bottom
+ }
+ }
+
+ }
+
class Timer {
var millis = 0L
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 88bbb16e34..3e8ef3f611 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -102,11 +102,21 @@ abstract class Inliners extends SubComponent {
debuglog("Analyzing " + cls)
this.currentIClazz = cls
- cls.methods filterNot (_.symbol.isConstructor) foreach analyzeMethod
+ val ms = cls.methods filterNot { _.symbol.isConstructor }
+ ms foreach { im =>
+ if(hasInline(im.symbol)) {
+ log("Not inlining into " + im.symbol.originalName.decode + " because it is marked @inline.")
+ } else if(im.hasCode) {
+ analyzeMethod(im)
+ }
+ }
}
- val tfa = new analysis.MethodTFA()
+ val tfa = new analysis.MTFAGrowable()
tfa.stat = global.opt.printStats
+ val staleOut = new mutable.ListBuffer[BasicBlock]
+ val splicedBlocks = mutable.Set.empty[BasicBlock]
+ val staleIn = mutable.Set.empty[BasicBlock]
// how many times have we already inlined this method here?
private val inlinedMethodCount = perRunCaches.newMap[Symbol, Int]() withDefaultValue 0
@@ -208,34 +218,35 @@ abstract class Inliners extends SubComponent {
import scala.util.control.Breaks._
do {
retry = false
- if (caller.inline) {
- log("Not inlining into " + caller.sym.originalName.decode + " because it is marked @inline.")
- }
- else if (caller.m.hasCode) {
- log("Analyzing " + m + " count " + count + " with " + caller.length + " blocks")
- tfa init m
- tfa.run
- caller.m.linearizedBlocks() foreach { bb =>
- info = tfa in bb
-
- breakable {
- for (i <- bb) {
- i match {
- // Dynamic == normal invocations
- // Static(true) == calls to private members
- case CALL_METHOD(msym, Dynamic | Static(true)) if !msym.isConstructor =>
- if (analyzeInc(msym, i, bb))
- break
- case _ => ()
- }
- info = tfa.interpret(info, i)
+ log("Analyzing " + m + " count " + count + " with " + caller.length + " blocks")
+ tfa.reinit(m, staleOut.toList, splicedBlocks, staleIn)
+ tfa.run
+ staleOut.clear()
+ splicedBlocks.clear()
+ staleIn.clear()
+
+ caller.m.linearizedBlocks() foreach { bb =>
+ info = tfa in bb
+
+ breakable {
+ for (i <- bb) {
+ i match {
+ // Dynamic == normal invocations
+ // Static(true) == calls to private members
+ case CALL_METHOD(msym, Dynamic | Static(true)) if !msym.isConstructor =>
+ if (analyzeInc(msym, i, bb)) {
+ break
+ }
+ case _ => ()
}
+ info = tfa.interpret(info, i)
}
}
- if (tfa.stat)
- log(m.symbol.fullName + " iterations: " + tfa.iterations + " (size: " + caller.length + ")")
}
+
+ if (tfa.stat)
+ log(m.symbol.fullName + " iterations: " + tfa.iterations + " (size: " + caller.length + ")")
}
while (retry && count < MAX_INLINE_RETRY)
@@ -343,6 +354,9 @@ abstract class Inliners extends SubComponent {
* The instruction must be a CALL_METHOD.
*/
def doInline(block: BasicBlock, instr: Instruction) {
+
+ staleOut += block
+
val targetPos = instr.pos
log("Inlining " + inc.m + " in " + caller.m + " at pos: " + posToStr(targetPos))
@@ -478,7 +492,8 @@ abstract class Inliners extends SubComponent {
block.close
// duplicate the other blocks in the callee
- inc.m.linearizedBlocks() foreach { bb =>
+ val calleeLin = inc.m.linearizedBlocks()
+ calleeLin foreach { bb =>
var info = a in bb
def emitInlined(i: Instruction) = inlinedBlock(bb).emit(i, targetPos)
def emitDrops(toDrop: Int) = info.stack.types drop toDrop foreach (t => emitInlined(DROP(t)))
@@ -503,6 +518,9 @@ abstract class Inliners extends SubComponent {
afterBlock emit instrAfter
afterBlock.close
+ staleIn += afterBlock
+ splicedBlocks ++= (calleeLin map inlinedBlock)
+
// add exception handlers of the callee
caller addHandlers (inc.handlers map translateExh)
assert(pending.isEmpty, "Pending NEW elements: " + pending)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 61521ea250..b6eef8c0bb 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -465,11 +465,9 @@ abstract class ClassfileParser {
}
ss = name.subName(0, start)
owner.info.decls lookup ss orElse {
- sym = owner.newClass(NoPosition, ss.toTypeName) setInfo completer
- if (opt.verboseDebug)
- println("loaded "+sym+" from file "+file)
-
- owner.info.decls enter sym
+ sym = owner.newClass(NoPosition, ss.toTypeName) setInfoAndEnter completer
+ debuglog("loaded "+sym+" from file "+file)
+ sym
}
}
@@ -499,7 +497,7 @@ abstract class ClassfileParser {
def parseClass() {
val jflags = in.nextChar
val isAnnotation = hasAnnotation(jflags)
- var sflags = toScalaFlags(jflags, isClass = true)
+ var sflags = toScalaClassFlags(jflags)
var nameIdx = in.nextChar
externalName = pool.getClassName(nameIdx)
val c = if (externalName.toString.indexOf('$') < 0) pool.getClassSymbol(nameIdx) else clazz
@@ -604,7 +602,7 @@ abstract class ClassfileParser {
def parseField() {
val jflags = in.nextChar
- var sflags = toScalaFlags(jflags, isField = true)
+ var sflags = toScalaFieldFlags(jflags)
if ((sflags & PRIVATE) != 0L && !global.settings.XO.value) {
in.skip(4); skipAttributes()
} else {
@@ -635,7 +633,7 @@ abstract class ClassfileParser {
def parseMethod() {
val jflags = in.nextChar.toInt
- var sflags = toScalaFlags(jflags)
+ var sflags = toScalaMethodFlags(jflags)
if (isPrivate(jflags) && !global.settings.XO.value) {
val name = pool.getName(in.nextChar)
if (name == nme.CONSTRUCTOR)
@@ -1074,7 +1072,7 @@ abstract class ClassfileParser {
def enterClassAndModule(entry: InnerClassEntry, completer: global.loaders.SymbolLoader, jflags: Int) {
val name = entry.originalName
- var sflags = toScalaFlags(jflags, isClass = true)
+ var sflags = toScalaClassFlags(jflags)
val innerClass = getOwner(jflags).newClass(name.toTypeName).setInfo(completer).setFlag(sflags)
val innerModule = getOwner(jflags).newModule(name.toTermName).setInfo(completer).setFlag(sflags)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 288e19af06..3c97122c9c 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -60,8 +60,7 @@ abstract class ICodeReader extends ClassfileParser {
this.staticCode = new IClass(staticModule)
val jflags = in.nextChar
val isAttribute = (jflags & JAVA_ACC_ANNOTATION) != 0
- var sflags = toScalaFlags(jflags, true)
- if ((sflags & DEFERRED) != 0L) sflags = sflags & ~DEFERRED | ABSTRACT
+ val sflags = toScalaClassFlags(jflags) // what, this is never used??
val c = pool getClassSymbol in.nextChar
parseInnerClasses()
@@ -86,29 +85,24 @@ abstract class ICodeReader extends ClassfileParser {
val jflags = in.nextChar
val name = pool getName in.nextChar
val owner = getOwner(jflags)
- val dummySym = owner.newMethod(owner.pos, name) setFlag javaToScalaFlags(jflags)
+ val dummySym = owner.newMethod(name, owner.pos, toScalaMethodFlags(jflags))
try {
- val ch = in.nextChar
- var tpe = pool.getType(dummySym, ch)
+ val ch = in.nextChar
+ val tpe = pool.getType(dummySym, ch)
if ("<clinit>" == name.toString)
(jflags, NoSymbol)
else {
val owner = getOwner(jflags)
- var sym = owner.info.findMember(name, 0, 0, false).suchThat(old => sameType(old.tpe, tpe));
+ var sym = owner.info.findMember(name, 0, 0, false).suchThat(old => sameType(old.tpe, tpe))
if (sym == NoSymbol)
- sym = owner.info.findMember(newTermName(name + nme.LOCAL_SUFFIX_STRING), 0, 0, false).suchThat(old => old.tpe =:= tpe);
+ sym = owner.info.findMember(newTermName(name + nme.LOCAL_SUFFIX_STRING), 0, 0, false).suchThat(_.tpe =:= tpe)
if (sym == NoSymbol) {
log("Could not find symbol for " + name + ": " + tpe)
log(owner.info.member(name).tpe + " : " + tpe)
- if (name.toString == "toMap")
- tpe = pool.getType(dummySym, ch)
- if (field)
- sym = owner.newValue(owner.pos, name).setInfo(tpe).setFlag(MUTABLE | javaToScalaFlags(jflags))
- else
- sym = dummySym.setInfo(tpe)
- owner.info.decls.enter(sym)
+ sym = if (field) owner.newValue(name, owner.pos, toScalaFieldFlags(jflags)) else dummySym
+ sym setInfoAndEnter tpe
log("added " + sym + ": " + sym.tpe)
}
(jflags, sym)
@@ -119,19 +113,6 @@ abstract class ICodeReader extends ClassfileParser {
}
}
- private def javaToScalaFlags(flags: Int): Long = {
- import ch.epfl.lamp.fjbg.JAccessFlags._
-
- var res = 0L
- if ((flags & ACC_PRIVATE) != 0) res |= Flags.PRIVATE
- if ((flags & ACC_PROTECTED) != 0) res |= Flags.PROTECTED
- if ((flags & ACC_FINAL) != 0) res |= Flags.FINAL
- if ((flags & ACC_ABSTRACT) != 0) res |= Flags.DEFERRED
- if ((flags & ACC_SYNTHETIC) != 0) res |= Flags.SYNTHETIC
-
- res
- }
-
/** Checks if `tp1` is the same type as `tp2`, modulo implicit methods.
* We don't care about the distinction between implicit and explicit
* methods as this point, and we can't get back the information from
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index c59a819b02..8a8131c0f4 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -247,8 +247,8 @@ abstract class AddInterfaces extends InfoTransform {
addMixinConstructorDef(clazz, templ.body map implMemberDef))
.setSymbol(clazz.newLocalDummy(templ.pos))
}
- new ChangeOwnerTraverser(templ.symbol.owner, clazz)(
- new ChangeOwnerTraverser(templ.symbol, templ1.symbol)(templ1))
+ templ1.changeOwner(templ.symbol.owner -> clazz, templ.symbol -> templ1.symbol)
+ templ1
}
def implClassDefs(trees: List[Tree]): List[Tree] = {
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 4d4f4f4c27..2b3e5f311f 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -105,8 +105,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
// Move tree into constructor, take care of changing owner from `oldowner` to constructor symbol
def intoConstructor(oldowner: Symbol, tree: Tree) =
- intoConstructorTransformer.transform(
- new ChangeOwnerTraverser(oldowner, constr.symbol)(tree))
+ intoConstructorTransformer transform tree.changeOwner(oldowner -> constr.symbol)
// Should tree be moved in front of super constructor call?
def canBeMoved(tree: Tree) = tree match {
@@ -454,28 +453,24 @@ abstract class Constructors extends Transform with ast.TreeDSL {
def delayedInitClosure(stats: List[Tree]) =
localTyper.typed {
atPos(impl.pos) {
- val closureClass = clazz.newClass(impl.pos, nme.delayedInitArg.toTypeName)
- .setFlag(SYNTHETIC | FINAL)
+ val closureClass = clazz.newClass(nme.delayedInitArg.toTypeName, impl.pos, SYNTHETIC | FINAL)
val closureParents = List(AbstractFunctionClass(0).tpe, ScalaObjectClass.tpe)
- closureClass.setInfo(new ClassInfoType(closureParents, new Scope, closureClass))
-
- val outerField = closureClass.newValue(impl.pos, nme.OUTER)
- .setFlag(PrivateLocal | PARAMACCESSOR)
- .setInfo(clazz.tpe)
-
- val applyMethod = closureClass.newMethod(impl.pos, nme.apply)
- .setFlag(FINAL)
- .setInfo(MethodType(List(), ObjectClass.tpe))
-
- closureClass.info.decls enter outerField
- closureClass.info.decls enter applyMethod
-
- val outerFieldDef = ValDef(outerField)
-
- val changeOwner = new ChangeOwnerTraverser(impl.symbol, applyMethod)
+ closureClass setInfoAndEnter new ClassInfoType(closureParents, new Scope, closureClass)
+
+ val outerField = (
+ closureClass
+ newValue(nme.OUTER, impl.pos, PrivateLocal | PARAMACCESSOR)
+ setInfoAndEnter clazz.tpe
+ )
+ val applyMethod = (
+ closureClass
+ newMethod(nme.apply, impl.pos, FINAL)
+ setInfoAndEnter MethodType(Nil, ObjectClass.tpe)
+ )
+ val outerFieldDef = ValDef(outerField)
val closureClassTyper = localTyper.atOwner(closureClass)
- val applyMethodTyper = closureClassTyper.atOwner(applyMethod)
+ val applyMethodTyper = closureClassTyper.atOwner(applyMethod)
val constrStatTransformer = new Transformer {
override def transform(tree: Tree): Tree = tree match {
@@ -507,8 +502,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
}
else tree
case _ =>
- changeOwner.changeOwner(tree)
- tree
+ tree.changeOwner(impl.symbol -> applyMethod)
}
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index f3b1e77c8d..71696c24e6 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -768,10 +768,8 @@ abstract class Erasure extends AddInterfaces
}
);
if (bridgeNeeded) {
- val bridge = other.cloneSymbolImpl(owner)
- .setPos(owner.pos)
- .setFlag(member.flags | BRIDGE)
- .resetFlag(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
+ val newFlags = (member.flags | BRIDGE) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
+ val bridge = other.cloneSymbolImpl(owner, newFlags) setPos owner.pos
// the parameter symbols need to have the new owner
bridge.setInfo(otpe.cloneInfo(bridge))
bridgeTarget(bridge) = member
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index 2180fd4f3a..0f11161914 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -213,17 +213,14 @@ abstract class LambdaLift extends InfoTransform {
atPhase(phase.next) {
for ((owner, freeValues) <- free.toList) {
+ val newFlags = SYNTHETIC | ( if (owner.isClass) PARAMACCESSOR | PrivateLocal else PARAM )
debuglog("free var proxy: %s, %s".format(owner.fullLocationString, freeValues.toList.mkString(", ")))
-
- proxies(owner) =
- for (fv <- freeValues.toList) yield {
- val proxy = owner.newValue(owner.pos, fv.name)
- .setFlag(if (owner.isClass) PARAMACCESSOR | PrivateLocal else PARAM)
- .setFlag(SYNTHETIC)
- .setInfo(fv.info);
- if (owner.isClass) owner.info.decls enter proxy;
- proxy
- }
+ proxies(owner) =
+ for (fv <- freeValues.toList) yield {
+ val proxy = owner.newValue(fv.name, owner.pos, newFlags) setInfo fv.info
+ if (owner.isClass) owner.info.decls enter proxy
+ proxy
+ }
}
}
}
@@ -409,12 +406,12 @@ abstract class LambdaLift extends InfoTransform {
}
else tree1
case Block(stats, expr0) =>
- val (lzyVals, rest) = stats.partition {
- case stat@ValDef(_, _, _, _) if stat.symbol.isLazy => true
- case stat@ValDef(_, _, _, _) if stat.symbol.hasFlag(MODULEVAR) => true
- case _ => false
- }
- treeCopy.Block(tree, lzyVals:::rest, expr0)
+ val (lzyVals, rest) = stats partition {
+ case stat: ValDef => stat.symbol.isLazy || stat.symbol.isModuleVar
+ case _ => false
+ }
+ if (lzyVals.isEmpty) tree
+ else treeCopy.Block(tree, lzyVals ::: rest, expr0)
case _ =>
tree
}
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index bc7d1754d4..c5475fa0f2 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -71,6 +71,8 @@ abstract class LiftCode extends Transform with TypingTransformers {
case mod => mod.toString
}
+ // I fervently hope this is a test case or something, not anything being
+ // depended upon. Of more fragile code I cannot conceive.
for (line <- (tree.toString.split(Properties.lineSeparator) drop 2 dropRight 1)) {
var s = line.trim
s = s.replace("$mr.", "")
@@ -81,24 +83,23 @@ abstract class LiftCode extends Transform with TypingTransformers {
s = s.replace("immutable.this.Nil", "List()")
s = s.replace("modifiersFromInternalFlags", "Modifiers")
s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()")
- s = """Modifiers\((\d+)L, newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => {
- val buf = new StringBuffer()
+ s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => {
+ val buf = new StringBuilder
val flags = m.group(1).toLong
- var s_flags = Flags.modifiersOfFlags(flags) map copypasteModifier
- buf.append("Set(" + s_flags.mkString(", ") + ")")
+ val s_flags = Flags.modifiersOfFlags(flags) map copypasteModifier mkString ", "
+ if (s_flags != "")
+ buf.append("Set(" + s_flags + ")")
- var privateWithin = m.group(2)
- buf.append(", " + "newTypeName(\"" + privateWithin + "\")")
+ val privateWithin = "" + m.group(2)
+ if (privateWithin != "")
+ buf.append(", newTypeName(\"" + privateWithin + "\")")
- var annotations = m.group(3)
- buf.append(", " + "List(" + annotations + ")")
+ val annotations = m.group(3)
+ if (annotations.nonEmpty)
+ buf.append(", List(" + annotations + ")")
- var s = buf.toString
- if (s.endsWith(", List()")) s = s.substring(0, s.length - ", List()".length)
- if (s.endsWith(", newTypeName(\"\")")) s = s.substring(0, s.length - ", newTypeName(\"\")".length)
- if (s.endsWith("Set()")) s = s.substring(0, s.length - "Set()".length)
- "Modifiers(" + s + ")"
+ "Modifiers(" + buf.toString + ")"
})
s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => {
val flags = m.group(1).toLong
@@ -310,13 +311,13 @@ abstract class LiftCode extends Transform with TypingTransformers {
*/
private def reifySymbolDef(sym: Symbol): Tree = {
if (reifyDebug) println("reify sym def " + sym)
- var rsym: Tree =
+
+ ValDef(NoMods, localName(sym), TypeTree(),
Apply(
Select(reify(sym.owner), "newNestedSymbol"),
- List(reify(sym.pos), reify(sym.name)))
- if (sym.flags != 0L)
- rsym = Apply(Select(rsym, "setInternalFlags"), List(Literal(Constant(sym.flags))))
- ValDef(NoMods, localName(sym), TypeTree(), rsym)
+ List(reify(sym.name), reify(sym.pos), Literal(Constant(sym.flags)))
+ )
+ )
}
/**
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 4ae4042cc7..2e2ff23881 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -271,10 +271,14 @@ abstract class UnCurry extends InfoTransform
def missingCaseCall(scrutinee: Tree): Tree = Apply(Select(This(anonClass), nme.missingCase), List(scrutinee))
def applyMethodDef() = {
- val body =
+ val body = localTyper.typedPos(fun.pos) {
if (isPartial) gen.mkUncheckedMatch(gen.withDefaultCase(fun.body, missingCaseCall))
else fun.body
- DefDef(Modifiers(FINAL), nme.apply, Nil, List(fun.vparams), TypeTree(restpe), body) setSymbol applyMethod
+ }
+ // Have to repack the type to avoid mismatches when existentials
+ // appear in the result - see SI-4869.
+ val applyResultType = localTyper.packedType(body, applyMethod)
+ DefDef(Modifiers(FINAL), nme.apply, Nil, List(fun.vparams), TypeTree(applyResultType), body) setSymbol applyMethod
}
def isDefinedAtMethodDef() = {
val isDefinedAtName = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 71c0de10ff..354b8caaa3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1390,10 +1390,9 @@ trait Namers extends MethodSynthesis {
)
if (sym hasAnnotation NativeAttr)
sym resetFlag DEFERRED
- else if (!symbolAllowsDeferred && ownerRequiresConcrete) {
+ else if (!symbolAllowsDeferred && ownerRequiresConcrete)
fail("only classes can have declared but undefined members" + abstractVarMessage(sym))
- sym resetFlag DEFERRED
- }
+
checkWithDeferred(PRIVATE)
checkWithDeferred(FINAL)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 42a60666de..4c14031da3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -171,8 +171,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
def varargBridge(member: Symbol, bridgetpe: Type): Tree = {
log("Generating varargs bridge for " + member.fullLocationString + " of type " + bridgetpe)
- val bridge = member.cloneSymbolImpl(clazz)
- .setPos(clazz.pos).setFlag(member.flags | VBRIDGE)
+ val bridge = member.cloneSymbolImpl(clazz, member.flags | VBRIDGE) setPos clazz.pos
bridge.setInfo(bridgetpe.cloneInfo(bridge))
clazz.info.decls enter bridge
@@ -1167,12 +1166,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
def createStaticModuleAccessor() = atPhase(phase.next) {
val method = (
- sym.owner.newMethod(sym.pos, sym.name.toTermName)
- setFlag (sym.flags | STABLE)
- resetFlag MODULE
- setInfo NullaryMethodType(sym.moduleClass.tpe)
+ sym.owner.newMethod(sym.name.toTermName, sym.pos, (sym.flags | STABLE) & ~MODULE)
+ setInfoAndEnter NullaryMethodType(sym.moduleClass.tpe)
)
- sym.owner.info.decls enter method
localTyper.typedPos(tree.pos)(gen.mkModuleAccessDef(method, sym))
}
def createInnerModuleAccessor(vdef: Tree) = List(
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 6476244221..243d922732 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2542,7 +2542,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val pattp = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
// turn any unresolved type variables in freevars into existential skolems
- val skolems = freeVars map (fv => newExistentialSkolem(fv, unapplyContext.owner, fv))
+ val skolems = freeVars map (fv => unapplyContext.owner.newExistentialSkolem(fv, fv))
arg.tpe = pattp.substSym(freeVars, skolems)
argDummy setInfo arg.tpe
}
@@ -3804,7 +3804,24 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
pre = cx.enclClass.prefix
defEntry = cx.scope.lookupEntry(name)
if ((defEntry ne null) && qualifies(defEntry.sym)) {
- defSym = defEntry.sym
+ // Right here is where SI-1987, overloading in package objects, can be
+ // seen to go wrong. There is an overloaded symbol, but when referring
+ // to the unqualified identifier from elsewhere in the package, only
+ // the last definition is visible. So overloading mis-resolves and is
+ // definition-order dependent, bad things. See run/t1987.scala.
+ //
+ // I assume the actual problem involves how/where these symbols are entered
+ // into the scope. But since I didn't figure out how to fix it that way, I
+ // catch it here by looking up package-object-defined symbols in the prefix.
+ if (isInPackageObject(defEntry.sym, pre.typeSymbol)) {
+ defSym = pre.member(defEntry.sym.name)
+ if (defSym ne defEntry.sym) {
+ log("!!! Overloaded package object member resolved incorrectly.\n Discarded: " +
+ defEntry.sym.defString + "\n Using: " + defSym.defString)
+ }
+ }
+ else
+ defSym = defEntry.sym
}
else {
cx = cx.enclClass
diff --git a/src/library/scala/Function1.scala b/src/library/scala/Function1.scala
index dc8e67bbb0..7517e6604b 100644
--- a/src/library/scala/Function1.scala
+++ b/src/library/scala/Function1.scala
@@ -24,10 +24,18 @@ package scala
* assert(succ(0) == anonfun1(0))
* }
* }}}
+ *
+ * Note that `Function1` does not define a total function, as might
+ * be suggested by the existence of [[scala.PartialFunction]]. The only
+ * distinction between `Function1` and `PartialFunction` is that the
+ * latter can specify inputs which it will not handle.
+ *
*/
@annotation.implicitNotFound(msg = "No implicit view available from ${T1} => ${R}.")
trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends AnyRef { self =>
- /** Apply the body of this function to the argument.
+ /** Apply the body of this function to the argument. It may throw an
+ * exception.
+ *
* @return the result of function application.
*/
def apply(v1: T1): R
diff --git a/src/library/scala/PartialFunction.scala b/src/library/scala/PartialFunction.scala
index b2910c2278..70caff0221 100644
--- a/src/library/scala/PartialFunction.scala
+++ b/src/library/scala/PartialFunction.scala
@@ -13,6 +13,36 @@ package scala
* The function `isDefinedAt` allows to test dynamically if a value is in
* the domain of the function.
*
+ * Even if `isDefinedAt` returns true for an `a: A`, calling `apply(a)` may
+ * still throw an exception, so the following code is legal:
+ *
+ * {{{
+ * val f: PartialFunction[Int, Any] = { case _ => 1/0 }
+ * }}}
+ *
+ * The main distinction between `PartialFunction` and [[scala.Function1]] is
+ * that the user of a `PartialFunction` may choose to do something different
+ * with input that is declared to be outside its domain. For example:
+ *
+ * {{{
+ * val sample = 1 to 10
+ * val isEven: PartialFunction[Int, String] = {
+ * case x if x % 2 == 0 => x+" is even"
+ * }
+ *
+ * // the method collect can use isDefinedAt to select which members to collect
+ * val evenNumbers = sample collect isEven
+ *
+ * val isOdd: PartialFunction[Int, String] = {
+ * case x if x % 2 == 1 => x+" is odd"
+ * }
+ *
+ * // the method orElse allows chaining another partial function to handle
+ * // input outside the declared domain
+ * val numbers = sample map (isEven orElse isOdd)
+ * }}}
+ *
+ *
* @author Martin Odersky
* @version 1.0, 16/07/2003
*/
diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala
index 122eec2d90..c837775cf9 100644
--- a/src/library/scala/collection/GenTraversableLike.scala
+++ b/src/library/scala/collection/GenTraversableLike.scala
@@ -177,7 +177,28 @@ trait GenTraversableLike[+A, +Repr] extends GenTraversableOnce[A] with Paralleli
def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That
/** Builds a new collection by applying a function to all elements of this $coll
- * and concatenating the results.
+ * and using the elements of the resulting collections. For example:
+ *
+ * {{{
+ * def getWords(lines: Seq[String]): Seq[String] = lines flatMap (line => line split "\\W+")
+ * }}}
+ *
+ * The type of the resulting collection is guided by the static type of $coll. This might
+ * cause unexpected results sometimes. For example:
+ *
+ * {{{
+ * // lettersOf will return a Seq[Char] of likely repeated letters, instead of a Set
+ * def lettersOf(words: Seq[String]) = words flatMap (word => word.toSet)
+ *
+ * // lettersOf will return a Set[Char], not a Seq
+ * def lettersOf(words: Seq[String]) = words.toSet flatMap (word => word.toSeq)
+ *
+ * // xs will be a an Iterable[Int]
+ * val xs = Map("a" -> List(11,111), "b" -> List(22,222)).flatMap(_._2)
+ *
+ * // ys will be a Map[Int, Int]
+ * val ys = Map("a" -> List(1 -> 11,1 -> 111), "b" -> List(2 -> 22,2 -> 222)).flatMap(_._2)
+ * }}}
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index e2acc0b3e0..b4813e6341 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -709,6 +709,9 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
* outer $coll containing this `WithFilter` instance that satisfy
* predicate `p` and concatenating the results.
*
+ * The type of the resulting collection will be guided by the static type
+ * of the outer $coll.
+ *
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
* @tparam That $thatinfo
diff --git a/src/library/scala/collection/generic/GenericTraversableTemplate.scala b/src/library/scala/collection/generic/GenericTraversableTemplate.scala
index 12c1a75c7a..7333074778 100644
--- a/src/library/scala/collection/generic/GenericTraversableTemplate.scala
+++ b/src/library/scala/collection/generic/GenericTraversableTemplate.scala
@@ -116,7 +116,19 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew
}
/** Converts this $coll of traversable collections into
- * a $coll in which all element collections are concatenated.
+ * a $coll formed by the elements of these traversable
+ * collections.
+ *
+ * The resulting collection's type will be guided by the
+ * static type of $coll. For example:
+ *
+ * {{{
+ * val xs = List(Set(1, 2, 3), Set(1, 2, 3))
+ * // xs == List(1, 2, 3, 1, 2, 3)
+ *
+ * val ys = Set(List(1, 2, 3), List(3, 2, 1))
+ * // ys == Set(1, 2, 3)
+ * }}}
*
* @tparam B the type of the elements of each traversable collection.
* @param asTraversable an implicit conversion which asserts that the element
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index be08409636..8bd45c0e33 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -60,7 +60,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals {
override def hashCode = this.erasure.##
}
-sealed abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals {
+abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals {
override def <:<(that: ClassManifest[_]): Boolean =
(that eq this) || (that eq Manifest.Any) || (that eq Manifest.AnyVal)
override def canEqual(other: Any) = other match {
diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala
index 31bcdebe7e..8b4b170847 100755
--- a/src/library/scala/reflect/api/Symbols.scala
+++ b/src/library/scala/reflect/api/Symbols.scala
@@ -150,10 +150,10 @@ trait Symbols { self: Universe =>
*/
def asTypeIn(site: Type): Type
- /** A fresh symbol with given position `pos` and name `name` that has
+ /** A fresh symbol with given name `name`, position `pos` and flags `flags` that has
* the current symbol as its owner.
*/
- def newNestedSymbol(pos: Position, name: Name): Symbol // needed by LiftCode
+ def newNestedSymbol(name: Name, pos: Position, flags: Long): Symbol // needed by LiftCode
/** Low-level operation to set the symbol's flags
* @return the symbol itself
diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala
index f6353faa6f..04f36ffa11 100644
--- a/src/partest/scala/tools/partest/nest/PathSettings.scala
+++ b/src/partest/scala/tools/partest/nest/PathSettings.scala
@@ -16,6 +16,9 @@ object PathSettings {
private def cwd = Directory.Current getOrElse sys.error("user.dir property not set")
private def isPartestDir(d: Directory) = (d.name == "test") && (d / srcDirName isDirectory)
+ private def findJar(d: Directory, name: String): Option[File] = findJar(d.files, name)
+ private def findJar(files: Iterator[File], name: String): Option[File] =
+ files filter (_ hasExtension "jar") find { _.name startsWith name }
// Directory <root>/test
lazy val testRoot: Directory = testRootDir getOrElse {
@@ -33,7 +36,7 @@ object PathSettings {
// Directory <root>/test/files/speclib
lazy val srcSpecLibDir = Directory(srcDir / "speclib")
- lazy val srcSpecLib: File = srcSpecLibDir.files find (_.name startsWith "instrumented") getOrElse {
+ lazy val srcSpecLib: File = findJar(srcSpecLibDir, "instrumented") getOrElse {
sys.error("No instrumented.jar found in %s".format(srcSpecLibDir))
}
@@ -51,7 +54,7 @@ object PathSettings {
lazy val buildPackLibDir = Directory(buildDir / "pack" / "lib")
lazy val scalaCheck: File =
- buildPackLibDir.files ++ srcLibDir.files find (_.name startsWith "scalacheck") getOrElse {
+ findJar(buildPackLibDir.files ++ srcLibDir.files, "scalacheck") getOrElse {
sys.error("No scalacheck jar found in '%s' or '%s'".format(buildPackLibDir, srcLibDir))
}
}