diff options
Diffstat (limited to 'src')
25 files changed, 455 insertions, 321 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/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/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/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)) } } |