diff options
46 files changed, 1659 insertions, 1003 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 715a68cf55..f8342444c8 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -14,15 +14,25 @@ import PartialFunction._ trait Definitions extends reflect.api.StandardDefinitions { self: SymbolTable => - private def newClass(owner: Symbol, name: TypeName, parents: List[Type], flags: Long = 0L): Symbol = { + /** Since both the value parameter types and the result type may + * require access to the type parameter symbols, we model polymorphic + * creation as a function from those symbols to (formal types, result type). + * The Option is to distinguish between nullary methods and empty-param-list + * methods. + */ + private type PolyMethodCreator = List[Symbol] => (Option[List[Type]], Type) + + private def enterNewClass(owner: Symbol, name: TypeName, parents: List[Type], flags: Long = 0L): Symbol = { val clazz = owner.newClassSymbol(name, NoPosition, flags) clazz setInfoAndEnter ClassInfoType(parents, newScope, clazz) } private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): Symbol = { val msym = owner.newMethod(name.encode, NoPosition, flags) val params = msym.newSyntheticValueParams(formals) - msym setInfoAndEnter MethodType(params, restpe) + msym setInfo MethodType(params, restpe) } + private def enterNewMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): Symbol = + owner.info.decls enter newMethod(owner, name, formals, restpe, flags) // the scala value classes trait ValueClassDefinitions { @@ -156,7 +166,7 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val RuntimePackage = getRequiredModule("scala.runtime") lazy val RuntimePackageClass = RuntimePackage.moduleClass - + lazy val JavaLangEnumClass = getRequiredClass("java.lang.Enum") // convenient one-argument parameter lists @@ -168,10 +178,10 @@ trait Definitions extends reflect.api.StandardDefinitions { private def booltype = BooleanClass.typeConstructor private def inttype = IntClass.typeConstructor private def stringtype = StringClass.typeConstructor - + // Java types def javaTypeName(jclazz: Class[_]): TypeName = newTypeName(jclazz.getName) - + def javaTypeToValueClass(jtype: Class[_]): Symbol = jtype match { case java.lang.Void.TYPE => UnitClass case java.lang.Byte.TYPE => ByteClass @@ -198,7 +208,7 @@ trait Definitions extends reflect.api.StandardDefinitions { } // top types - lazy val AnyClass = newClass(ScalaPackageClass, tpnme.Any, Nil, ABSTRACT) + lazy val AnyClass = enterNewClass(ScalaPackageClass, tpnme.Any, Nil, ABSTRACT) lazy val AnyRefClass = newAlias(ScalaPackageClass, tpnme.AnyRef, ObjectClass.typeConstructor) lazy val ObjectClass = getClass(sn.Object) lazy val AnyCompanionClass = getRequiredClass("scala.AnyCompanion") initFlags (SEALED | ABSTRACT | TRAIT) @@ -264,7 +274,7 @@ trait Definitions extends reflect.api.StandardDefinitions { def Predef_identity = getMember(PredefModule, nme.identity) def Predef_conforms = getMember(PredefModule, nme.conforms) def Predef_wrapRefArray = getMember(PredefModule, nme.wrapRefArray) - + /** Is `sym` a member of Predef with the given name? * Note: DON't replace this by sym == Predef_conforms/etc, as Predef_conforms is a `def` * which does a member lookup (it can't be a lazy val because we might reload Predef @@ -303,7 +313,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // .setInfo(UnitClass.tpe) lazy val TypeConstraintClass = getRequiredClass("scala.annotation.TypeConstraint") - lazy val SingletonClass = newClass(ScalaPackageClass, tpnme.Singleton, anyparam, ABSTRACT | TRAIT | FINAL) + lazy val SingletonClass = enterNewClass(ScalaPackageClass, tpnme.Singleton, anyparam, ABSTRACT | TRAIT | FINAL) lazy val SerializableClass = getRequiredClass("scala.Serializable") lazy val JavaSerializableClass = getClass(sn.JavaSerializable) lazy val ComparableClass = getRequiredClass("java.lang.Comparable") @@ -311,17 +321,10 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val RemoteInterfaceClass = getRequiredClass("java.rmi.Remote") lazy val RemoteExceptionClass = getRequiredClass("java.rmi.RemoteException") - lazy val RepeatedParamClass = newCovariantPolyClass( - ScalaPackageClass, - tpnme.REPEATED_PARAM_CLASS_NAME, - tparam => seqType(tparam.typeConstructor) - ) - - lazy val JavaRepeatedParamClass = newCovariantPolyClass( - ScalaPackageClass, - tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, - tparam => arrayType(tparam.typeConstructor) - ) + lazy val ByNameParamClass = specialPolyClass(tpnme.BYNAME_PARAM_CLASS_NAME, COVARIANT)(_ => AnyClass.typeConstructor) + lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN_NAME, 0L)(_ => AnyClass.typeConstructor) + lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.typeConstructor)) + lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.typeConstructor)) def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass @@ -350,15 +353,6 @@ trait Definitions extends reflect.api.StandardDefinitions { case _ => false } - lazy val ByNameParamClass = newCovariantPolyClass( - ScalaPackageClass, - tpnme.BYNAME_PARAM_CLASS_NAME, - tparam => AnyClass.typeConstructor - ) - lazy val EqualsPatternClass = { - val clazz = newClass(ScalaPackageClass, tpnme.EQUALS_PATTERN_NAME, Nil) - clazz setInfo GenPolyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, newScope, clazz)) - } lazy val MatchingStrategyClass = getRequiredClass("scala.MatchingStrategy") // collections classes @@ -429,24 +423,27 @@ trait Definitions extends reflect.api.StandardDefinitions { * information into the toString method. */ def manifestToType(m: OptManifest[_]): Type = m match { - case x: AnyValManifest[_] => - getClassIfDefined("scala." + x).tpe case m: ClassManifest[_] => - val name = m.erasure.getName - if (name endsWith nme.MODULE_SUFFIX_STRING) - getModuleIfDefined(name stripSuffix nme.MODULE_SUFFIX_STRING).tpe - else { - val sym = getClassIfDefined(name) - val args = m.typeArguments - - if (sym eq NoSymbol) NoType - else if (args.isEmpty) sym.tpe - else appliedType(sym.typeConstructor, args map manifestToType) - } + val sym = manifestToSymbol(m) + val args = m.typeArguments + + if ((sym eq NoSymbol) || args.isEmpty) sym.tpe + else appliedType(sym.typeConstructor, args map manifestToType) case _ => NoType } + def manifestToSymbol(m: ClassManifest[_]): Symbol = m match { + case x: scala.reflect.AnyValManifest[_] => + getMember(ScalaPackageClass, newTypeName("" + x)) + case _ => + val name = m.erasure.getName + if (name endsWith nme.MODULE_SUFFIX_STRING) + getModuleIfDefined(name stripSuffix nme.MODULE_SUFFIX_STRING) + else + getClassIfDefined(name) + } + // The given symbol represents either String.+ or StringAdd.+ def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+ def isArrowAssoc(sym: Symbol) = ArrowAssocClass.tpe.decls.toList contains sym @@ -499,7 +496,7 @@ trait Definitions extends reflect.api.StandardDefinitions { case DoubleClass => nme.wrapDoubleArray case BooleanClass => nme.wrapBooleanArray case UnitClass => nme.wrapUnitArray - case _ => + case _ => if ((elemtp <:< AnyRefClass.tpe) && !isPhantomClass(elemtp.typeSymbol)) nme.wrapRefArray else nme.genericWrapArray } @@ -594,6 +591,14 @@ trait Definitions extends reflect.api.StandardDefinitions { case _ => NoType } + /** To avoid unchecked warnings on polymorphic classes, translate + * a Foo[T] into a Foo[_] for use in the pattern matcher. + */ + def typeCaseType(clazz: Symbol) = clazz.tpe.normalize match { + case TypeRef(_, sym, args) if args.nonEmpty => newExistentialType(sym.typeParams, clazz.tpe) + case tp => tp + } + def seqType(arg: Type) = appliedType(SeqClass.typeConstructor, List(arg)) def arrayType(arg: Type) = appliedType(ArrayClass.typeConstructor, List(arg)) def byNameType(arg: Type) = appliedType(ByNameParamClass.typeConstructor, List(arg)) @@ -635,14 +640,14 @@ trait Definitions extends reflect.api.StandardDefinitions { case _ => false }) } - + // members of class scala.Any - lazy val Any_== = newMethod(AnyClass, nme.EQ, anyparam, booltype, FINAL) - lazy val Any_!= = newMethod(AnyClass, nme.NE, anyparam, booltype, FINAL) - lazy val Any_equals = newMethod(AnyClass, nme.equals_, anyparam, booltype) - lazy val Any_hashCode = newMethod(AnyClass, nme.hashCode_, Nil, inttype) - lazy val Any_toString = newMethod(AnyClass, nme.toString_, Nil, stringtype) - lazy val Any_## = newMethod(AnyClass, nme.HASHHASH, Nil, inttype, FINAL) + lazy val Any_== = enterNewMethod(AnyClass, nme.EQ, anyparam, booltype, FINAL) + lazy val Any_!= = enterNewMethod(AnyClass, nme.NE, anyparam, booltype, FINAL) + lazy val Any_equals = enterNewMethod(AnyClass, nme.equals_, anyparam, booltype) + lazy val Any_hashCode = enterNewMethod(AnyClass, nme.hashCode_, Nil, inttype) + lazy val Any_toString = enterNewMethod(AnyClass, nme.toString_, Nil, stringtype) + lazy val Any_## = enterNewMethod(AnyClass, nme.HASHHASH, Nil, inttype, FINAL) // Any_getClass requires special handling. The return type is determined on // a per-call-site basis as if the function being called were actually: @@ -653,38 +658,60 @@ trait Definitions extends reflect.api.StandardDefinitions { // Since getClass is not actually a polymorphic method, this requires compiler // participation. At the "Any" level, the return type is Class[_] as it is in // java.lang.Object. Java also special cases the return type. - lazy val Any_getClass = - newMethod(AnyClass, nme.getClass_, Nil, getMember(ObjectClass, nme.getClass_).tpe.resultType, DEFERRED) - lazy val Any_isInstanceOf = newPolyMethod( - AnyClass, nme.isInstanceOf_, tparam => NullaryMethodType(booltype)) setFlag FINAL - lazy val Any_asInstanceOf = newPolyMethod( - AnyClass, nme.asInstanceOf_, tparam => NullaryMethodType(tparam.typeConstructor)) setFlag FINAL - + lazy val Any_getClass = enterNewMethod(AnyClass, nme.getClass_, Nil, getMember(ObjectClass, nme.getClass_).tpe.resultType, DEFERRED) + lazy val Any_isInstanceOf = newT1NullaryMethod(AnyClass, nme.isInstanceOf_, FINAL)(_ => booltype) + lazy val Any_asInstanceOf = newT1NullaryMethod(AnyClass, nme.asInstanceOf_, FINAL)(_.typeConstructor) + // AnyVal_getClass is defined here. Once we have a new strap, it could also be // defined directly in the AnyVal trait. Right now this does not work, because // strap complains about overriding a final getClass method in Any. - lazy val AnyVal_getClass = { - val m = AnyValClass.newMethod(nme.getClass_) - val tparam = m.newExistential(newTypeName("T")) setInfo TypeBounds(NothingClass.tpe, AnyValClass.tpe) - m setInfoAndEnter MethodType(List(), ExistentialType(List(tparam), appliedType(ClassClass.typeConstructor, List(tparam.tpe)))) + lazy val AnyVal_getClass = newMethod(AnyValClass, nme.getClass_, Nil, getClassReturnType(AnyValClass.tpe)) + + // A type function from T => Class[U], used to determine the return + // type of getClass calls. The returned type is: + // + // 1. If T is a value type, Class[T]. + // 2. If T is a phantom type (Any or AnyVal), Class[_]. + // 3. If T is a local class, Class[_ <: |T|]. + // 4. Otherwise, Class[_ <: T]. + // + // Note: AnyVal cannot be Class[_ <: AnyVal] because if the static type of the + // receiver is AnyVal, it implies the receiver is boxed, so the correct + // class object is that of java.lang.Integer, not Int. + // + // TODO: If T is final, return type could be Class[T]. Should it? + def getClassReturnType(tp: Type): Type = { + val sym = tp.typeSymbol + + if (phase.erasedTypes) ClassClass.tpe + else if (isValueClass(sym)) ClassType(tp.widen) + else { + val eparams = typeParamsToExistentials(ClassClass, ClassClass.typeParams) + val upperBound = ( + if (isPhantomClass(sym)) AnyClass.tpe + else if (sym.isLocalClass) erasure.intersectionDominator(tp.parents) + else tp.widen + ) + + existentialAbstraction( + eparams, + ClassType(eparams.head setInfo TypeBounds.upper(upperBound) tpe) + ) + } } // members of class java.lang.{ Object, String } - lazy val Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL) - lazy val Object_== = newMethod(ObjectClass, nme.EQ, anyrefparam, booltype, FINAL) - lazy val Object_!= = newMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL) - lazy val Object_eq = newMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL) - lazy val Object_ne = newMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL) - lazy val Object_synchronized = newPolyMethodCon( - ObjectClass, nme.synchronized_, - tparam => msym => MethodType(msym.newSyntheticValueParams(List(tparam.typeConstructor)), tparam.typeConstructor)) setFlag FINAL - lazy val Object_isInstanceOf = newPolyMethod( - ObjectClass, newTermName("$isInstanceOf"), - tparam => MethodType(List(), booltype)) setFlag (FINAL | SYNTHETIC) - lazy val Object_asInstanceOf = newPolyMethod( - ObjectClass, newTermName("$asInstanceOf"), - tparam => MethodType(List(), tparam.typeConstructor)) setFlag (FINAL | SYNTHETIC) - lazy val String_+ = newMethod(StringClass, nme.raw.PLUS, anyparam, stringtype, FINAL) + lazy val Object_## = enterNewMethod(ObjectClass, nme.HASHHASH, Nil, inttype, FINAL) + lazy val Object_== = enterNewMethod(ObjectClass, nme.EQ, anyrefparam, booltype, FINAL) + lazy val Object_!= = enterNewMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL) + lazy val Object_eq = enterNewMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL) + lazy val Object_ne = enterNewMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL) + lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC)(_ => booltype) + lazy val Object_asInstanceOf = newT1NoParamsMethod(ObjectClass, nme.asInstanceOf_Ob, FINAL | SYNTHETIC)(_.typeConstructor) + lazy val Object_synchronized = newPolyMethod(1, ObjectClass, nme.synchronized_, FINAL)(tps => + (Some(List(tps.head.typeConstructor)), tps.head.typeConstructor) + ) + lazy val String_+ = enterNewMethod(StringClass, nme.raw.PLUS, anyparam, stringtype, FINAL) def Object_getClass = getMember(ObjectClass, nme.getClass_) def Object_clone = getMember(ObjectClass, nme.clone_) @@ -695,7 +722,6 @@ trait Definitions extends reflect.api.StandardDefinitions { def Object_hashCode = getMember(ObjectClass, nme.hashCode_) def Object_toString = getMember(ObjectClass, nme.toString_) - // boxed classes lazy val ObjectRefClass = getRequiredClass("scala.runtime.ObjectRef") lazy val VolatileObjectRefClass = getRequiredClass("scala.runtime.VolatileObjectRef") @@ -770,7 +796,7 @@ trait Definitions extends reflect.api.StandardDefinitions { ) lazy val AnnotationDefaultAttr: Symbol = { - val attr = newClass(RuntimePackageClass, tpnme.AnnotationDefaultATTR, List(AnnotationClass.typeConstructor)) + val attr = enterNewClass(RuntimePackageClass, tpnme.AnnotationDefaultATTR, List(AnnotationClass.typeConstructor)) // This attribute needs a constructor so that modifiers in parsed Java code make sense attr.info.decls enter attr.newClassConstructor(NoPosition) attr @@ -790,10 +816,10 @@ trait Definitions extends reflect.api.StandardDefinitions { while (result.isAliasType) result = result.info.typeSymbol result } - + def getRequiredModule(fullname: String): Symbol = getModule(newTermNameCached(fullname)) - def getRequiredClass(fullname: String): Symbol = + def getRequiredClass(fullname: String): Symbol = getClass(newTypeNameCached(fullname)) def getClassIfDefined(fullname: String): Symbol = @@ -840,39 +866,36 @@ trait Definitions extends reflect.api.StandardDefinitions { */ private def getModuleOrClass(path: Name): Symbol = getModuleOrClass(path, path.length) - private def newCovariantPolyClass(owner: Symbol, name: TypeName, parent: Symbol => Type): Symbol = { - val clazz = newClass(owner, name, List()) - val tparam = newTypeParam(clazz, 0) setFlag COVARIANT - val p = parent(tparam) -/* p.typeSymbol.initialize - println(p.typeSymbol + " flags: " + Flags.flagsToString(p.typeSymbol.flags)) - val parents = /*if (p.typeSymbol.isTrait) - List(definitions.AnyRefClass.tpe, p) - else*/ List(p) - println("creating " + name + " with parents " + parents) */ - clazz.setInfo( - GenPolyType( - List(tparam), - ClassInfoType(List(AnyRefClass.tpe, p), newScope, clazz))) - } - 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 = - newPolyMethodCon(owner, name, tparam => msym => tcon(tparam)) - - /** tcon receives the type parameter symbol and the method symbol as arguments */ - private def newPolyMethodCon(owner: Symbol, name: TermName, tcon: Symbol => Symbol => Type): Symbol = { - val msym = owner.info.decls enter owner.newMethod(name.encode) - val tparam = newTypeParam(msym, 0) - - msym setInfo PolyType(List(tparam), tcon(tparam)(msym)) + + private def specialPolyClass(name: TypeName, flags: Long)(parentFn: Symbol => Type): Symbol = { + val clazz = enterNewClass(ScalaPackageClass, name, Nil) + val tparam = clazz.newSyntheticTypeParam("T0", flags) + val parents = List(AnyRefClass.tpe, parentFn(tparam)) + + clazz setInfo GenPolyType(List(tparam), ClassInfoType(parents, newScope, clazz)) } + + def newPolyMethod(typeParamCount: Int, owner: Symbol, name: TermName, flags: Long)(createFn: PolyMethodCreator): Symbol = { + val msym = owner.newMethod(name.encode, NoPosition, flags) + val tparams = msym.newSyntheticTypeParams(typeParamCount) + val mtpe = createFn(tparams) match { + case (Some(formals), restpe) => MethodType(msym.newSyntheticValueParams(formals), restpe) + case (_, restpe) => NullaryMethodType(restpe) + } - private def newTypeParam(owner: Symbol, index: Int): Symbol = - owner.newTypeParameter(newTypeName("T" + index)) setInfo TypeBounds.empty + msym setInfoAndEnter polyType(tparams, mtpe) + } + + /** T1 means one type parameter. + */ + def newT1NullaryMethod(owner: Symbol, name: TermName, flags: Long)(createFn: Symbol => Type): Symbol = { + newPolyMethod(1, owner, name, flags)(tparams => (None, createFn(tparams.head))) + } + def newT1NoParamsMethod(owner: Symbol, name: TermName, flags: Long)(createFn: Symbol => Type): Symbol = { + newPolyMethod(1, owner, name, flags)(tparams => (Some(Nil), createFn(tparams.head))) + } lazy val boxedClassValues = boxedClass.values.toSet lazy val isUnbox = unboxMethod.values.toSet @@ -970,7 +993,7 @@ trait Definitions extends reflect.api.StandardDefinitions { RootClass.info.decls enter EmptyPackage RootClass.info.decls enter RootPackage - + val forced = List( // force initialization of every symbol that is entered as a side effect AnnotationDefaultAttr, // #2264 RepeatedParamClass, @@ -1023,7 +1046,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // tparam => resultType, which is the resultType of PolyType, i.e. the result type after applying the // type parameter =-> a MethodType in this case // TODO: set type bounds manually (-> MulticastDelegate), see newTypeParam - val newCaller = newMethod(DelegateClass, name, paramTypes, delegateType, FINAL | STATIC) + val newCaller = enterNewMethod(DelegateClass, name, paramTypes, delegateType, FINAL | STATIC) // val newCaller = newPolyMethod(DelegateClass, name, // tparam => MethodType(paramTypes, tparam.typeConstructor)) setFlag (FINAL | STATIC) Delegate_scalaCallers = Delegate_scalaCallers ::: List(newCaller) diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index aba00088f9..b3069adfb4 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -291,6 +291,7 @@ trait StdNames extends NameManglers { self: SymbolTable => val array_update : NameType = "array_update" val arraycopy: NameType = "arraycopy" val asInstanceOf_ : NameType = "asInstanceOf" + val asInstanceOf_Ob : NameType = "$asInstanceOf" val asTypeConstructor: NameType = "asTypeConstructor" val assert_ : NameType = "assert" val assume_ : NameType = "assume" @@ -336,6 +337,7 @@ trait StdNames extends NameManglers { self: SymbolTable => val isDefinedAt: NameType = "isDefinedAt" val isEmpty: NameType = "isEmpty" val isInstanceOf_ : NameType = "isInstanceOf" + val isInstanceOf_Ob : NameType = "$isInstanceOf" val java: NameType = "java" val lang: NameType = "lang" val length: NameType = "length" diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 009120af00..e504cea8cf 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -17,7 +17,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => import definitions._ protected var ids = 0 - + val emptySymbolArray = new Array[Symbol](0) def symbolCount = ids // statistics @@ -38,14 +38,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => nextexid += 1 newTypeName("_" + nextexid + suffix) } - + // Set the fields which point companions at one another. Returns the module. def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol = { moduleClass.sourceModule = m 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 = @@ -84,19 +84,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api private[this] var _rawname = initName private[this] var _rawflags = 0L - + def rawowner = _rawowner def rawname = _rawname def rawflags = _rawflags - + protected def rawflags_=(x: FlagsType) { _rawflags = x } - + private var rawpos = initPos - + val id = nextId() // identity displayed when -uniqid private[this] var _validTo: Period = NoPeriod - + def validTo = _validTo def validTo_=(x: Period) { _validTo = x} @@ -169,10 +169,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol = new TermSymbol(this, pos, name) initFlags newFlags - + 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 @@ -184,10 +184,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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, 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. */ @@ -196,7 +196,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => newAliasTypeSymbol(name, pos, newFlags) else newAbstractTypeSymbol(name, pos, newFlags) - + 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 @@ -233,7 +233,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ 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, newFlags: Long = 0L): Symbol = @@ -251,6 +251,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => def freshName() = { cnt += 1; nme.syntheticParamName(cnt) } mmap(argtypess)(tp => newValueParameter(freshName(), focusPos(owner.pos), SYNTHETIC) setInfo tp) } + + def newSyntheticTypeParam(): Symbol = newSyntheticTypeParam("T0", 0L) + def newSyntheticTypeParam(name: String, newFlags: Long): Symbol = newTypeParameter(newTypeName(name), NoPosition, newFlags) setInfo TypeBounds.empty + def newSyntheticTypeParams(num: Int): List[Symbol] = (0 until num).toList map (n => newSyntheticTypeParam("T" + n, 0L)) /** Create a new existential type skolem with this symbol its owner, * based on the given symbol and origin. @@ -288,7 +292,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) = newClassSymbol(name, pos, newFlags) - + /** A new class with its info set to a ClassInfoType with given scope and parents. */ def newClassWithInfo(name: TypeName, parents: List[Type], scope: Scope, pos: Position = NoPosition, newFlags: Long = 0L) = { val clazz = newClass(name, pos, newFlags) @@ -340,9 +344,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => def newAliasType(pos: Position, name: TypeName): Symbol = newAliasType(name, pos) @deprecated("Use the other signature", "2.10.0") def newAbstractType(pos: Position, name: TypeName): Symbol = newAbstractType(name, pos) - @deprecated("Use the other signature", "2.10.0") + @deprecated("Use the other signature", "2.10.0") def newExistential(pos: Position, name: TypeName): Symbol = newExistential(name, pos) - @deprecated("Use the other signature", "2.10.0") + @deprecated("Use the other signature", "2.10.0") def newMethod(pos: Position, name: TermName): MethodSymbol = newMethod(name, pos) // ----- locking and unlocking ------------------------------------------------------ @@ -826,7 +830,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def addModuleSuffix(n: Name): Name = if (needsModuleSuffix) n append nme.MODULE_SUFFIX_STRING else n - + def moduleSuffix: String = ( if (needsModuleSuffix) nme.MODULE_SUFFIX_STRING else "" @@ -834,7 +838,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Whether this symbol needs nme.MODULE_SUFFIX_STRING (aka $) appended on the java platform. */ def needsModuleSuffix = ( - hasModuleFlag + hasModuleFlag && !isMethod && !isImplClass && !isJavaDefined @@ -861,7 +865,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (owner.isEffectiveRoot) name else effectiveOwner.enclClass.fullNameAsName(separator) append separator append name ) - + def fullNameAsName(separator: Char): Name = nme.dropLocalSuffix(fullNameInternal(separator)) /** The encoded full path name of this symbol, where outer names and inner names @@ -1013,7 +1017,7 @@ 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) @@ -1315,7 +1319,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ final def isNestedIn(that: Symbol): Boolean = owner == that || owner != NoSymbol && (owner isNestedIn that) - + /** Is this class symbol a subclass of that symbol, * and is this class symbol also different from Null or Nothing? */ def isNonBottomSubClass(that: Symbol): Boolean = false @@ -1830,6 +1834,18 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } + /** Remove any access boundary and clear flags PROTECTED | PRIVATE. + */ + def makePublic = this setPrivateWithin NoSymbol resetFlag AccessFlags + + /** The first parameter to the first argument list of this method, + * or NoSymbol if inapplicable. + */ + def firstParam = info.params match { + case p :: _ => p + case _ => NoSymbol + } + /** change name by appending $$<fully-qualified-name-of-class `base`> * Do the same for any accessed symbols or setters/getters */ @@ -1900,36 +1916,43 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (isTerm && (!isParameter || isParamAccessor)) "val" else "" + private case class SymbolKind(accurate: String, sanitized: String, abbreviation: String) + private def symbolKind: SymbolKind = { + val kind = + if (isInstanceOf[FreeVar]) ("free variable", "free variable", "FV") + else if (isPackage) ("package", "package", "PK") + else if (isPackageClass) ("package class", "package", "PKC") + else if (isPackageObject) ("package object", "package", "PKO") + else if (isPackageObjectClass) ("package object class", "package", "PKOC") + else if (isAnonymousClass) ("anonymous class", "anonymous class", "AC") + else if (isRefinementClass) ("refinement class", "", "RC") + else if (isModule) ("module", "object", "MOD") + else if (isModuleClass) ("module class", "object", "MODC") + else if (isGetter) ("getter", if (isSourceMethod) "method" else "value", "GET") + else if (isSetter) ("setter", if (isSourceMethod) "method" else "value", "SET") + else if (isTerm && isLazy) ("lazy value", "lazy value", "LAZ") + else if (isVariable) ("field", "variable", "VAR") + else if (isTrait) ("trait", "trait", "TRT") + else if (isClass) ("class", "class", "CLS") + else if (isType) ("type", "type", "TPE") + else if (isClassConstructor) ("constructor", "constructor", "CTOR") + else if (isSourceMethod) ("method", "method", "METH") + else if (isTerm) ("value", "value", "VAL") + else ("", "", "???") + SymbolKind(kind._1, kind._2, kind._3) + } + /** Accurate string representation of symbols' kind, suitable for developers. */ final def accurateKindString: String = - if (isPackage) "package" - else if (isPackageClass) "package class" - else if (isPackageObject) "package object" - else if (isPackageObjectClass) "package object class" - else if (isRefinementClass) "refinement class" - else if (isModule) "module" - else if (isModuleClass) "module class" - else if (isGetter) "getter" - else if (isSetter) "setter" - else if (isVariable) "field" - else sanitizedKindString + symbolKind.accurate /** String representation of symbol's kind, suitable for the masses. */ private def sanitizedKindString: String = - if (isPackage || isPackageClass) "package" - else if (isModule || isModuleClass) "object" - else if (isAnonymousClass) "anonymous class" - else if (isRefinementClass) "" - else if (isTrait) "trait" - else if (isClass) "class" - else if (isType) "type" - else if (isInstanceOf[FreeVar]) "free variable" - else if (isTerm && isLazy) "lazy value" - else if (isVariable) "variable" - else if (isClassConstructor) "constructor" - else if (isSourceMethod) "method" - else if (isTerm) "value" - else "" + symbolKind.sanitized + + /** String representation of symbol's kind, suitable for the masses. */ + protected[scala] def abbreviatedKindString: String = + symbolKind.abbreviation final def kindString: String = if (settings.debug.value) accurateKindString @@ -1952,12 +1975,25 @@ trait Symbols extends api.Symbols { self: SymbolTable => * If !settings.debug translates expansions of operators back to operator symbol. * E.g. $eq => =. * If settings.uniqid, adds id. + * If settings.Yshowsymkinds, adds abbreviated symbol kind. */ def nameString: String = ( - if (settings.uniqid.value) decodedName + "#" + id - else "" + decodedName + if (!settings.uniqid.value && !settings.Yshowsymkinds.value) "" + decodedName + else if (settings.uniqid.value && !settings.Yshowsymkinds.value) decodedName + "#" + id + else if (!settings.uniqid.value && settings.Yshowsymkinds.value) decodedName + "#" + abbreviatedKindString + else decodedName + "#" + id + "#" + abbreviatedKindString ) + def fullNameString: String = { + def recur(sym: Symbol): String = { + if (sym.isRoot || sym.isRootPackage || sym == NoSymbol) sym.nameString + else if (sym.owner.isEffectiveRoot) sym.nameString + else recur(sym.effectiveOwner.enclClass) + "." + sym.nameString + } + + recur(this) + } + /** If settings.uniqid is set, the symbol's id, else "" */ final def idString = if (settings.uniqid.value) "#"+id else "" @@ -2083,7 +2119,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def referenced: Symbol = _referenced def referenced_=(x: Symbol) { _referenced = x } - + def existentialBound = singletonBounds(this.tpe) def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = @@ -2177,7 +2213,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (!isMethod && needsFlatClasses) { if (flatname eq null) flatname = nme.flattenedName(rawowner.name, rawname) - + flatname } else rawname.toTermName @@ -2213,7 +2249,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => res } } - + class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { // Temporary programmatic help tracking down who might do such a thing @@ -2228,13 +2264,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => 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 { @@ -2432,7 +2468,7 @@ 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 = GenPolyType(this.typeParams, TypeBounds.upper(this.classBound)) override def sourceFile = @@ -2460,19 +2496,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => } thisTypeCache } - + override def owner: Symbol = if (needsFlatClasses) rawowner.owner else rawowner override def name: TypeName = ( if (needsFlatClasses) { if (flatname eq null) flatname = nme.flattenedName(rawowner.name, rawname).toTypeName - + flatname } else rawname.toTypeName ) - + /** A symbol carrying the self type of the class as its type */ override def thisSym: Symbol = thissym @@ -2655,7 +2691,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => val syms1 = cloneSymbolsAtOwner(syms, owner) creator(syms1, tpe.substSym(syms, syms1)) } - + /** A deep map on a symbol's paramss. */ def mapParamss[T](sym: Symbol)(f: Symbol => T): List[List[T]] = mmap(sym.info.paramss)(f) diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index 00c20535ba..e7ba0c793d 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/scala/reflect/internal/TreePrinters.scala @@ -27,10 +27,20 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => /** Turns a path into a String, introducing backquotes * as necessary. */ - def backquotedPath(t: Tree): String = t match { - case Select(qual, name) => "%s.%s".format(backquotedPath(qual), quotedName(name)) - case Ident(name) => quotedName(name) - case _ => t.toString + def backquotedPath(t: Tree): String = { + def suffix(t: Tree) = { + var suffix = "" + if (t.hasSymbol && settings.uniqid.value) suffix += ("#" + t.symbol.id) + if (t.hasSymbol && settings.Yshowsymkinds.value) suffix += ("#" + t.symbol.abbreviatedKindString) + suffix + } + + t match { + case Select(qual, name) if name.isTermName => "%s.%s".format(backquotedPath(qual), quotedName(name)) + suffix(t) + case Select(qual, name) if name.isTypeName => "%s#%s".format(backquotedPath(qual), quotedName(name)) + suffix(t) + case Ident(name) => quotedName(name) + suffix(t) + case _ => t.toString + } } class TreePrinter(out: PrintWriter) extends super.TreePrinter { @@ -239,17 +249,17 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => print("AnyVal") } else { - printRow(parents, " with ") - if (!body.isEmpty) { - if (self.name != nme.WILDCARD) { - print(" { ", self.name); printOpt(": ", self.tpt); print(" => ") - } else if (!self.tpt.isEmpty) { - print(" { _ : ", self.tpt, " => ") - } else { - print(" {") - } - printColumn(body, "", ";", "}") + printRow(parents, " with ") + if (!body.isEmpty) { + if (self.name != nme.WILDCARD) { + print(" { ", self.name); printOpt(": ", self.tpt); print(" => ") + } else if (!self.tpt.isEmpty) { + print(" { _ : ", self.tpt, " => ") + } else { + print(" {") } + printColumn(body, "", ";", "}") + } } currentOwner = currentOwner1 diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 50929ecc32..3c339ad8e2 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -10,7 +10,7 @@ import Flags._ import api.Modifier trait Trees extends api.Trees { self: SymbolTable => - + // Belongs in TreeInfo but then I can't reach it from TreePrinters. def isReferenceToScalaMember(t: Tree, Id: Name) = t match { case Ident(Id) => true @@ -133,7 +133,7 @@ trait Trees extends api.Trees { self: SymbolTable => new ChangeOwnerTraverser(oldOwner, newOwner) apply t } } - + def substTreeSyms(pairs: (Symbol, Symbol)*): Tree = substTreeSyms(pairs.map(_._1).toList, pairs.map(_._2).toList) diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index e6d4599417..49ac205409 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -110,13 +110,13 @@ trait Types extends api.Types { self: SymbolTable => * to undo constraints in the case of isSubType/isSameType failure. */ lazy val undoLog = newUndoLog - + protected def newUndoLog = new UndoLog - + class UndoLog { private type UndoPairs = List[(TypeVar, TypeConstraint)] private var log: UndoPairs = List() - + // register with the auto-clearing cache manager perRunCaches.recordCache(this) @@ -136,7 +136,7 @@ trait Types extends api.Types { self: SymbolTable => private[reflect] def record(tv: TypeVar) = { log ::= ((tv, tv.constr.cloneInternal)) } - + private[scala] def clear() { if (settings.debug.value) self.log("Clearing " + log.size + " entries from the undoLog.") @@ -427,7 +427,7 @@ trait Types extends api.Types { self: SymbolTable => /** For a typeref, its arguments. The empty list for all other types */ def typeArgs: List[Type] = List() - + /** A list of placeholder types derived from the type parameters. * Used by RefinedType and TypeRef. */ @@ -524,7 +524,7 @@ trait Types extends api.Types { self: SymbolTable => * Alternatives of overloaded symbol appear in the order they are declared. */ def decl(name: Name): Symbol = findDecl(name, 0) - + /** A list of all non-private members defined or declared in this type. */ def nonPrivateDecls: List[Symbol] = decls filter (x => !x.isPrivate) toList @@ -565,7 +565,7 @@ trait Types extends api.Types { self: SymbolTable => */ def nonPrivateMember(name: Name): Symbol = memberBasedOnName(name, BridgeAndPrivateFlags) - + /** All members with the given flags, excluding bridges. */ def membersWithFlags(requiredFlags: Long): List[Symbol] = @@ -590,7 +590,7 @@ trait Types extends api.Types { self: SymbolTable => * an OverloadedSymbol if several exist, NoSymbol if none exist */ def nonLocalMember(name: Name): Symbol = memberBasedOnName(name, BridgeFlags | LOCAL) - + /** Members excluding and requiring the given flags. * Note: unfortunately it doesn't work to exclude DEFERRED this way. */ @@ -1205,7 +1205,7 @@ trait Types extends api.Types { self: SymbolTable => if (settings.debug.value) sym.nameString + ".this." else if (sym.isAnonOrRefinementClass) "this." else if (sym.isOmittablePrefix) "" - else if (sym.isModuleClass) sym.fullName + "." + else if (sym.isModuleClass) sym.fullNameString + "." else sym.nameString + ".this." override def safeToString: String = if (sym.isRoot) "<root>" @@ -1236,7 +1236,7 @@ trait Types extends api.Types { self: SymbolTable => private[reflect] var underlyingPeriod = NoPeriod override def underlying: Type = { val cache = underlyingCache - if (underlyingPeriod == currentPeriod && cache != null) cache + if (underlyingPeriod == currentPeriod && cache != null) cache else { defineUnderlyingOfSingleType(this) underlyingCache @@ -1279,7 +1279,7 @@ trait Types extends api.Types { self: SymbolTable => unique(new UniqueSingleType(pre, sym)) } } - + protected def defineUnderlyingOfSingleType(tpe: SingleType) = { val period = tpe.underlyingPeriod if (period != currentPeriod) { @@ -1349,13 +1349,13 @@ trait Types extends api.Types { self: SymbolTable => override def baseTypeSeq: BaseTypeSeq = { val cached = baseTypeSeqCache - if (baseTypeSeqPeriod == currentPeriod && cached != null && cached != undetBaseTypeSeq) + if (baseTypeSeqPeriod == currentPeriod && cached != null && cached != undetBaseTypeSeq) cached else { defineBaseTypeSeqOfCompoundType(this) if (baseTypeSeqCache eq undetBaseTypeSeq) throw new RecoverableCyclicReference(typeSymbol) - + baseTypeSeqCache } } @@ -1369,7 +1369,7 @@ trait Types extends api.Types { self: SymbolTable => defineBaseClassesOfCompoundType(this) if (baseClassesCache eq null) throw new RecoverableCyclicReference(typeSymbol) - + baseClassesCache } } @@ -1415,7 +1415,7 @@ trait Types extends api.Types { self: SymbolTable => (if (settings.debug.value || parents.isEmpty || (decls.elems ne null)) decls.mkString("{", "; ", "}") else "") } - + protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = { val period = tpe.baseTypeSeqPeriod if (period != currentPeriod) { @@ -1468,7 +1468,7 @@ trait Types extends api.Types { self: SymbolTable => if (tpe.baseTypeSeqCache eq undetBaseTypeSeq) throw new TypeError("illegal cyclic inheritance involving " + tpe.typeSymbol) } - + protected def defineBaseClassesOfCompoundType(tpe: CompoundType) = { def computeBaseClasses: List[Symbol] = if (tpe.parents.isEmpty) List(tpe.typeSymbol) @@ -1787,13 +1787,13 @@ trait Types extends api.Types { self: SymbolTable => } } - /* Syncnote: The `volatile` var and `pendingVolatiles` mutable set need not be protected + /* Syncnote: The `volatile` var and `pendingVolatiles` mutable set need not be protected * with synchronized, because they are accessed only from isVolatile, which is called only from * Typer. */ private var volatileRecursions: Int = 0 private val pendingVolatiles = new mutable.HashSet[Symbol] - + class ArgsTypeRef(pre0: Type, sym0: Symbol, args0: List[Type]) extends TypeRef(pre0, sym0, args0) with UniqueType { require(args0.nonEmpty, this) @@ -1811,7 +1811,7 @@ trait Types extends api.Types { self: SymbolTable => asSeenFromOwner(tp).instantiateTypeParams(sym.typeParams, args) } - + // note: does not go through typeRef. There's no need to because // neither `pre` nor `sym` changes. And there's a performance // advantage to call TypeRef directly. @@ -1826,7 +1826,7 @@ trait Types extends api.Types { self: SymbolTable => override def isHigherKinded = typeParams.nonEmpty override def typeParams = if (isDefinitionsInitialized) sym.typeParams else sym.unsafeTypeParams private def isRaw = !phase.erasedTypes && isRawIfWithoutArgs(sym) - + override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type = if (isHigherKinded) { if (sameLength(formals intersect typeParams, typeParams)) @@ -1846,9 +1846,9 @@ trait Types extends api.Types { self: SymbolTable => res } - override def transformInfo(tp: Type): Type = + override def transformInfo(tp: Type): Type = appliedType(asSeenFromOwner(tp), dummyArgs) - + override def narrow = if (sym.isModuleClass) singleType(pre, sym.sourceModule) else super.narrow @@ -1856,14 +1856,14 @@ 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 = + 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 @@ -1872,7 +1872,7 @@ trait Types extends api.Types { self: SymbolTable => if (sym == clazz) this else transform(sym.info.baseType(clazz)) } - + trait NonClassTypeRef extends TypeRef { require(sym.isNonClassType, sym) @@ -1891,11 +1891,11 @@ trait Types extends api.Types { self: SymbolTable => } relativeInfoCache } - + override def baseType(clazz: Symbol): Type = if (sym == clazz) this else baseTypeOfNonClassTypeRef(this, clazz) } - + protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) = try { basetypeRecursions += 1 if (basetypeRecursions < LogPendingBaseTypesThreshold) @@ -1912,7 +1912,7 @@ trait Types extends api.Types { self: SymbolTable => } finally { basetypeRecursions -= 1 } - + trait AliasTypeRef extends NonClassTypeRef { require(sym.isAliasType, sym) @@ -1930,7 +1930,7 @@ trait Types extends api.Types { self: SymbolTable => 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 @@ -1940,7 +1940,7 @@ trait Types extends api.Types { self: SymbolTable => // 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 @@ -1954,12 +1954,12 @@ trait Types extends api.Types { self: SymbolTable => // TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre? case _ => sym } - + } trait AbstractTypeRef extends NonClassTypeRef { require(sym.isAbstractType, sym) - + /** Syncnote: Pure performance caches; no need to synchronize in multi-threaded environment */ private var symInfoCache: Type = _ @@ -1988,7 +1988,7 @@ trait Types extends api.Types { self: SymbolTable => volatileRecursions -= 1 } } - + override def thisInfo = { val symInfo = sym.info if (thisInfoCache == null || (symInfo ne symInfoCache)) { @@ -2021,7 +2021,7 @@ trait Types extends api.Types { self: SymbolTable => private[reflect] var parentsPeriod = NoPeriod private[reflect] var baseTypeSeqCache: BaseTypeSeq = _ private[reflect] var baseTypeSeqPeriod = NoPeriod - private var normalized: Type = _ + private var normalized: Type = _ // @M: propagate actual type params (args) to `tp`, by replacing // formal type parameters with actual ones. If tp is higher kinded, @@ -2043,7 +2043,7 @@ trait Types extends api.Types { self: SymbolTable => normalized } } - + def etaExpand: Type = { // must initialise symbol, see test/files/pos/ticket0137.scala val tpars = initializedTypeParams @@ -2097,12 +2097,12 @@ trait Types extends api.Types { self: SymbolTable => } thisInfo.decls } - + protected[Types] def baseTypeSeqImpl: BaseTypeSeq = sym.info.baseTypeSeq map transform override def baseTypeSeq: BaseTypeSeq = { val cache = baseTypeSeqCache - if (baseTypeSeqPeriod == currentPeriod && cache != null && cache != undetBaseTypeSeq) + if (baseTypeSeqPeriod == currentPeriod && cache != null && cache != undetBaseTypeSeq) cache else { defineBaseTypeSeqOfTypeRef(this) @@ -2196,7 +2196,7 @@ trait Types extends api.Types { self: SymbolTable => } }) } - + protected def defineParentsOfTypeRef(tpe: TypeRef) = { val period = tpe.parentsPeriod if (period != currentPeriod) { @@ -2208,7 +2208,7 @@ trait Types extends api.Types { self: SymbolTable => } } } - + protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) = { val period = tpe.baseTypeSeqPeriod if (period != currentPeriod) { @@ -2368,7 +2368,7 @@ trait Types extends api.Types { self: SymbolTable => } object PolyType extends PolyTypeExtractor - + /** A creator for existential types which flattens nested existentials. */ def newExistentialType(quantified: List[Symbol], underlying: Type): Type = @@ -2571,7 +2571,7 @@ trait Types extends api.Types { self: SymbolTable => else if (args.isEmpty) new HKTypeVar(origin, constr, params) else throw new Error("Invalid TypeVar construction: " + ((origin, constr, args, params))) ) - + trace("create", "In " + tv.originLocation)(tv) } } @@ -2612,7 +2612,7 @@ trait Types extends api.Types { self: SymbolTable => override def isHigherKinded = true override protected def typeVarString = params.map(_.name).mkString("[", ", ", "]=>" + originName) } - + /** Precondition: zipped params/args nonEmpty. (Size equivalence enforced structurally.) */ class AppliedTypeVar( @@ -2620,17 +2620,17 @@ trait Types extends api.Types { self: SymbolTable => _constr: TypeConstraint, zippedArgs: List[(Symbol, Type)] ) extends TypeVar(_origin, _constr) { - + require(zippedArgs.nonEmpty, this) override def params: List[Symbol] = zippedArgs map (_._1) override def typeArgs: List[Type] = zippedArgs map (_._2) - + override protected def typeVarString = ( zippedArgs map { case (p, a) => p.name + "=" + a } mkString (origin + "[", ", ", "]") ) } - + /** A class representing a type variable: not used after phase `typer`. * * A higher-kinded TypeVar has params (Symbols) and typeArgs (Types). @@ -2648,7 +2648,7 @@ trait Types extends api.Types { self: SymbolTable => override def typeArgs: List[Type] = Nil override def isHigherKinded = false - /** The constraint associated with the variable + /** The constraint associated with the variable * Syncnote: Type variables are assumed to be used from only one * thread. They are not exposed in api.Types and are used only locally * in operations that are exposed from types. Hence, no syncing of `constr` @@ -2659,7 +2659,7 @@ trait Types extends api.Types { self: SymbolTable => /** The variable's skolemization level */ val level = skolemizationLevel - + /** Two occurrences of a higher-kinded typevar, e.g. `?CC[Int]` and `?CC[String]`, correspond to * ''two instances'' of `TypeVar` that share the ''same'' `TypeConstraint`. * @@ -2690,7 +2690,7 @@ trait Types extends api.Types { self: SymbolTable => // inference may generate several TypeVar's for a single type parameter that must be inferred, // only one of them is in the set of tvars that need to be solved, but // they share the same TypeConstraint instance - + // When comparing to types containing skolems, remember the highest level // of skolemization. If that highest level is higher than our initial // skolemizationLevel, we can't re-use those skolems as the solution of this @@ -2914,7 +2914,7 @@ trait Types extends api.Types { self: SymbolTable => def originLocation = { val sym = origin.typeSymbolDirect val encl = sym.owner.logicallyEnclosingMember - + // This should display somewhere between one and three // things which enclose the origin: at most, a class, a // a method, and a term. At least, a class. @@ -3258,8 +3258,8 @@ trait Types extends api.Types { self: SymbolTable => */ object GenPolyType { def apply(tparams: List[Symbol], tpe: Type): Type = - if (tparams nonEmpty) typeFun(tparams, tpe) - else tpe // it's okay to be forgiving here + if (tparams nonEmpty) typeFun(tparams, tpe) + else tpe // it's okay to be forgiving here def unapply(tpe: Type): Option[(List[Symbol], Type)] = tpe match { case PolyType(tparams, restpe) => Some(tparams, restpe) case _ => Some(List(), tpe) @@ -3351,7 +3351,7 @@ trait Types extends api.Types { self: SymbolTable => mapOver(tp) } } - + /** Type with all top-level occurrences of abstract types replaced by their bounds */ def abstractTypesToBounds(tp: Type): Type = tp match { // @M don't normalize here (compiler loops on pos/bug1090.scala ) case TypeRef(_, sym, _) if sym.isAbstractType => @@ -3461,7 +3461,7 @@ trait Types extends api.Types { self: SymbolTable => def this(lo0: List[Type], hi0: List[Type]) = this(lo0, hi0, NoType, NoType) def this(bounds: TypeBounds) = this(List(bounds.lo), List(bounds.hi)) def this() = this(List(), List()) - + /* Syncnote: Type constraints are assumed to be used from only one * thread. They are not exposed in api.Types and are used only locally * in operations that are exposed from types. Hence, no syncing of any @@ -3561,7 +3561,7 @@ trait Types extends api.Types { self: SymbolTable => override def variance = _variance def variance_=(x: Int) = _variance = x - + override protected def noChangeToSymbols(origSyms: List[Symbol]) = { origSyms forall { sym => val v = variance @@ -3727,7 +3727,7 @@ trait Types extends api.Types { self: SymbolTable => protected def mapOverArgs(args: List[Type], tparams: List[Symbol]): List[Type] = args mapConserve this - + /** Called by mapOver to determine whether the original symbols can * be returned, or whether they must be cloned. Overridden in VariantTypeMap. */ @@ -3741,7 +3741,7 @@ trait Types extends api.Types { self: SymbolTable => if (elems1 eq elems) scope else newScopeWith(elems1: _*) } - + /** Map this function over given list of symbols */ def mapOver(origSyms: List[Symbol]): List[Symbol] = { // fast path in case nothing changes due to map @@ -3804,7 +3804,7 @@ trait Types extends api.Types { self: SymbolTable => def traverse(tp: Type): Unit def apply(tp: Type): Type = { traverse(tp); tp } } - + abstract class TypeTraverserWithResult[T] extends TypeTraverser { def result: T def clear(): Unit @@ -3824,13 +3824,13 @@ trait Types extends api.Types { self: SymbolTable => */ // class ContainsVariantExistentialCollector(v: Int) extends TypeCollector(false) with VariantTypeMap { // variance = v - // + // // def traverse(tp: Type) = tp match { // case ExistentialType(_, _) if (variance == v) => result = true // case _ => mapOver(tp) // } // } - // + // // val containsCovariantExistentialCollector = new ContainsVariantExistentialCollector(1) // val containsContravariantExistentialCollector = new ContainsVariantExistentialCollector(-1) @@ -3884,7 +3884,7 @@ trait Types extends api.Types { self: SymbolTable => mapOver(tp) } } - + /** Used by existentialAbstraction. */ class ExistentialExtrapolation(tparams: List[Symbol]) extends VariantTypeMap { @@ -3902,10 +3902,10 @@ trait Types extends api.Types { self: SymbolTable => countOccs(tpe) for (tparam <- tparams) countOccs(tparam.info) - + apply(tpe) } - + def apply(tp: Type): Type = { val tp1 = mapOver(tp) if (variance == 0) tp1 @@ -4484,12 +4484,12 @@ trait Types extends api.Types { self: SymbolTable => result } } - + protected def commonOwnerMap: CommonOwnerMap = commonOwnerMapObj - + protected class CommonOwnerMap extends TypeTraverserWithResult[Symbol] { var result: Symbol = _ - + def clear() { result = null } private def register(sym: Symbol) { @@ -4507,7 +4507,7 @@ trait Types extends api.Types { self: SymbolTable => case _ => mapOver(tp) } } - + private lazy val commonOwnerMapObj = new CommonOwnerMap class MissingAliasControl extends ControlThrowable @@ -4515,7 +4515,7 @@ trait Types extends api.Types { self: SymbolTable => class MissingTypeControl extends ControlThrowable object adaptToNewRunMap extends TypeMap { - + private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = { if (phase.flatClasses) { sym @@ -4682,7 +4682,7 @@ trait Types extends api.Types { self: SymbolTable => case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => assert(sym1 == sym2) pre1 =:= pre2 && - forall3(args1, args2, sym1.typeParams) { (arg1, arg2, tparam) => + forall3(args1, args2, sym1.typeParams) { (arg1, arg2, tparam) => //if (tparam.variance == 0 && !(arg1 =:= arg2)) Console.println("inconsistent: "+arg1+"!="+arg2)//DEBUG if (tparam.variance == 0) arg1 =:= arg2 else if (arg1.isInstanceOf[TypeVar]) @@ -5692,8 +5692,8 @@ trait Types extends api.Types { self: SymbolTable => val formatted = tableDef.table(transposed) println("** Depth is " + depth + "\n" + formatted) } - - /** From a list of types, find any which take type parameters + + /** From a list of types, find any which take type parameters * where the type parameter bounds contain references to other * any types in the list (including itself.) * @@ -6212,13 +6212,13 @@ trait Types extends api.Types { self: SymbolTable => if (ts exists (_.isNotNull)) res.notNull else res } - + /** A list of the typevars in a type. */ def typeVarsInType(tp: Type): List[TypeVar] = { var tvs: List[TypeVar] = Nil tp foreach { case t: TypeVar => tvs ::= t - case _ => + case _ => } tvs.reverse } @@ -6230,7 +6230,7 @@ trait Types extends api.Types { self: SymbolTable => // !!! Is it somehow guaranteed that this will not break under nesting? // In general one has to save and restore the contents of the field... tvs foreach (_.suspended = true) - tvs + tvs } /** Compute lub (if `variance == 1`) or glb (if `variance == -1`) of given list @@ -6460,5 +6460,5 @@ trait Types extends api.Types { self: SymbolTable => } finally { tostringRecursions -= 1 } - + } diff --git a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala index 6980d28bfb..0092f73fe3 100644 --- a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala @@ -38,6 +38,7 @@ abstract class MutableSettings extends AbsSettings { def explaintypes: BooleanSetting def verbose: BooleanSetting def uniqid: BooleanSetting + def Yshowsymkinds: BooleanSetting def Xprintpos: BooleanSetting def Yrecursion: IntSetting def maxClassfileName: IntSetting diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala index 3b805804a0..813c66e1f0 100644 --- a/src/compiler/scala/reflect/runtime/JavaToScala.scala +++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala @@ -354,7 +354,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => def classToScala(jclazz: jClass[_]): Symbol = classCache.toScala(jclazz) { val jname = javaTypeName(jclazz) def lookup = sOwner(jclazz).info.decl(newTypeName(jclazz.getSimpleName)) - + if (jclazz.isMemberClass && !nme.isImplClassName(jname)) { val sym = lookup assert(sym.isType, sym+"/"+jclazz+"/"+sOwner(jclazz)+"/"+jclazz.getSimpleName) diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/compiler/scala/reflect/runtime/Settings.scala index 2a6cdea519..b4f0123114 100644 --- a/src/compiler/scala/reflect/runtime/Settings.scala +++ b/src/compiler/scala/reflect/runtime/Settings.scala @@ -28,6 +28,7 @@ class Settings extends internal.settings.MutableSettings { val explaintypes = new BooleanSetting(false) val verbose = new BooleanSetting(false) val uniqid = new BooleanSetting(false) + val Yshowsymkinds = new BooleanSetting(false) val Xprintpos = new BooleanSetting(false) val printtypes = new BooleanSetting(false) val Yrecursion = new IntSetting(0) diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index 9ab12c6a86..46d890c5d1 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -123,15 +123,21 @@ trait ToolBoxes extends { self: Universe => applyMeth.invoke(result) } } - - def showAttributed(tree: Tree): String = { - val saved = settings.printtypes.value + + def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = { + val saved1 = settings.printtypes.value + val saved2 = settings.uniqid.value + val saved3 = settings.Yshowsymkinds.value try { - settings.printtypes.value = true - //settings.uniqid.value = true + settings.printtypes.value = printTypes + settings.uniqid.value = printIds + settings.uniqid.value = printKinds tree.toString - } finally - compiler.settings.printtypes.value = saved + } finally { + settings.printtypes.value = saved1 + settings.uniqid.value = saved2 + settings.Yshowsymkinds.value = saved3 + } } } diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 8026e92a21..c63070b18f 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -152,7 +152,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** Register top level class (called on entering the class) */ def registerTopLevelSym(sym: Symbol) {} - + // ------------------ Reporting ------------------------------------- // not deprecated yet, but a method called "error" imported into @@ -709,18 +709,18 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb private lazy val unitTimings = mutable.HashMap[CompilationUnit, Long]() withDefaultValue 0L // tracking time spent per unit private def unitTimingsFormatted(): String = { def toMillis(nanos: Long) = "%.3f" format nanos / 1000000d - + val formatter = new util.TableDef[(String, String)] { >> ("ms" -> (_._1)) >+ " " << ("path" -> (_._2)) } "" + ( - new formatter.Table(unitTimings.toList sortBy (-_._2) map { + new formatter.Table(unitTimings.toList sortBy (-_._2) map { case (unit, nanos) => (toMillis(nanos), unit.source.path) }) ) } - + protected def addToPhasesSet(sub: SubComponent, descr: String) { phasesSet += sub phasesDescMap(sub) = descr @@ -867,7 +867,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** Counts for certain classes of warnings during this run. */ var deprecationWarnings: List[(Position, String)] = Nil var uncheckedWarnings: List[(Position, String)] = Nil - + /** A flag whether macro expansions failed */ var macroExpansionFailed = false @@ -1014,7 +1014,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb } def cancel() { reporter.cancelled = true } - + private def currentProgress = (phasec * size) + unitc private def totalProgress = (phaseDescriptors.size - 1) * size // -1: drops terminal phase private def refreshProgress() = if (size > 0) progress(currentProgress, totalProgress) @@ -1181,12 +1181,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb */ def compileUnits(units: List[CompilationUnit], fromPhase: Phase) { try compileUnitsInternal(units, fromPhase) - catch { case ex => + catch { case ex => globalError(supplementErrorMessage("uncaught exception during compilation: " + ex.getClass.getName)) throw ex } } - + private def compileUnitsInternal(units: List[CompilationUnit], fromPhase: Phase) { units foreach addUnit if (opt.profileAll) { diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index c3e156104f..eb7c5a6699 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -292,8 +292,8 @@ self => } private lazy val primitiveNames: Set[Name] = tpnme.ScalaValueNames.toSet - private def inScalaRootPackage = inScalaPackage && currentPackage == "scala" - private def isScalaArray(name: Name) = inScalaRootPackage && name == tpnme.Array + private def inScalaRootPackage = inScalaPackage && currentPackage == "scala" + private def isScalaArray(name: Name) = inScalaRootPackage && name == tpnme.Array private def isPrimitiveType(name: Name) = inScalaRootPackage && primitiveNames(name) def parseStartRule: () => Tree diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 8cdd2334ab..567d6c2f78 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -1125,6 +1125,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val termname = newTypeName(name) findName(termname) getOrElse getModuleIfDefined(termname) } + def types[T: ClassManifest] : Symbol = types(classManifest[T].erasure.getName) + def terms[T: ClassManifest] : Symbol = terms(classManifest[T].erasure.getName) + def apply[T: ClassManifest] : Symbol = apply(classManifest[T].erasure.getName) /** the previous requests this interpreter has processed */ private lazy val prevRequests = mutable.ListBuffer[Request]() diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala index b4a9b9b0e3..2ec41506ab 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -20,7 +20,7 @@ import io.{ Path } class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: ReplValsImpl) { import intp.{ beQuietDuring, typeOfExpression, interpret, parse } import intp.global._ - import definitions.{ manifestToType, getClassIfDefined, getModuleIfDefined } + import definitions.{ manifestToType, manifestToSymbol, getClassIfDefined, getModuleIfDefined } abstract class SymSlurper { def isKeep(sym: Symbol): Boolean @@ -65,10 +65,7 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl } } - class PackageSlurper(pkgName: String) extends SymSlurper { - val pkgSymbol = getModuleIfDefined(pkgName) - val modClass = pkgSymbol.moduleClass - + class PackageSlurper(packageClass: Symbol) extends SymSlurper { /** Looking for dwindling returns */ def droppedEnough() = unseenHistory.size >= 4 && { unseenHistory takeRight 4 sliding 2 forall { it => @@ -79,9 +76,16 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl def isRecur(sym: Symbol) = true def isIgnore(sym: Symbol) = sym.isAnonOrRefinementClass || (sym.name.toString contains "$mc") - def isKeep(sym: Symbol) = sym.hasTransOwner(modClass) + def isKeep(sym: Symbol) = sym.hasTransOwner(packageClass) def isFinished() = droppedEnough() - def slurp() = apply(modClass) + def slurp() = { + if (packageClass.isPackageClass) + apply(packageClass) + else { + repldbg("Not a package class! " + packageClass) + Set() + } + } } private def customBanner = replProps.powerBanner.option flatMap (f => io.File(f).safeSlurp()) @@ -124,7 +128,7 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl def to_str(m: Symbol) = "%12s %s".format( m.decodedName, "" + elimRefinement(m.accessedOrSelf.tpe) stripPrefix "scala.tools.nsc.") - ( rutil.info[ReplValsImpl].declares + ( rutil.info[ReplValsImpl].membersDeclared filter (m => m.isPublic && !m.hasModuleFlag && !m.isConstructor) sortBy (_.decodedName) map to_str @@ -136,59 +140,78 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl implicit def apply[T: Manifest] : InternalInfo[T] = new InternalInfo[T](None) } object InternalInfo extends LowPriorityInternalInfo { } + + /** Now dealing with the problem of acidentally calling a method on Type + * when you're holding a Symbol and seeing the Symbol converted to the + * type of Symbol rather than the type of the thing represented by the + * symbol, by only implicitly installing one method, "?", and the rest + * of the conveniences exist on that wrapper. + */ + trait LowPriorityInternalInfoWrapper { + implicit def apply[T: Manifest] : InternalInfoWrapper[T] = new InternalInfoWrapper[T](None) + } + object InternalInfoWrapper extends LowPriorityInternalInfoWrapper { + + } + class InternalInfoWrapper[T: Manifest](value: Option[T] = None) { + def ? : InternalInfo[T] = new InternalInfo[T](value) + } /** Todos... * translate manifest type arguments into applied types * customizable symbol filter (had to hardcode no-spec to reduce noise) */ class InternalInfo[T: Manifest](value: Option[T] = None) { - // Decided it was unwise to have implicit conversions via commonly - // used type/symbol methods, because it's too easy to e.g. call - // "x.tpe" where x is a Type, and rather than failing you get the - // Type representing Types#Type (or Manifest, or whatever.) - private def tpe = tpe_ - private def symbol = symbol_ - private def name = name_ - - def symbol_ : Symbol = getClassIfDefined(erasure.getName) - def tpe_ : Type = manifestToType(man) - def name_ : Name = symbol.name - def companion = symbol.companionSymbol - def info = symbol.info - def module = symbol.moduleClass - def owner = symbol.owner - def owners = symbol.ownerChain drop 1 - def defn = symbol.defString - def decls = symbol.info.decls - - def declares = decls.toList - def inherits = members filterNot (declares contains _) - def types = members filter (_.name.isTypeName) - def methods = members filter (_.isMethod) - def overrides = declares filter (_.isOverride) - def inPackage = owners find (x => x.isPackageClass || x.isPackage) getOrElse definitions.RootPackage - - def man = manifest[T] - def erasure = man.erasure - def members = tpe.members filterNot (_.name.toString contains "$mc") - def allMembers = tpe.members - def bts = info.baseTypeSeq.toList - def btsmap = bts map (x => (x, x.decls.toList)) toMap - def pkgName = Option(erasure.getPackage) map (_.getName) - def pkg = pkgName map getModuleIfDefined getOrElse NoSymbol - def pkgmates = pkg.tpe.members - def pkgslurp = pkgName match { - case Some(name) => new PackageSlurper(name) slurp() - case _ => Set() - } - def ? = this - - def whoHas(name: String) = bts filter (_.decls exists (_.name.toString == name)) - def <:<[U: Manifest](other: U) = tpe <:< InternalInfo[U].tpe - def lub[U: Manifest](other: U) = intp.global.lub(List(tpe, InternalInfo[U].tpe)) - def glb[U: Manifest](other: U) = intp.global.glb(List(tpe, InternalInfo[U].tpe)) + private def newInfo[U: Manifest](value: U): InternalInfo[U] = new InternalInfo[U](Some(value)) + private def isSpecialized(s: Symbol) = s.name.toString contains "$mc" + private def isImplClass(s: Symbol) = s.name.toString endsWith "$class" + + /** Standard noise reduction filter. */ + def excludeMember(s: Symbol) = ( + isSpecialized(s) + || isImplClass(s) + || s.isAnonOrRefinementClass + || s.isAnonymousFunction + ) + def symbol = manifestToSymbol(fullManifest) + def tpe = manifestToType(fullManifest) + def name = symbol.name + def companion = symbol.companionSymbol + def info = symbol.info + def moduleClass = symbol.moduleClass + def owner = symbol.owner + def owners = symbol.ownerChain drop 1 + def signature = symbol.defString + + def decls = info.decls + def declsOverride = membersDeclared filter (_.isOverride) + def declsOriginal = membersDeclared filterNot (_.isOverride) + + def members = membersUnabridged filterNot excludeMember + def membersUnabridged = tpe.members + def membersDeclared = members filterNot excludeMember + def membersInherited = members filterNot (membersDeclared contains _) + def memberTypes = members filter (_.name.isTypeName) + def memberMethods = members filter (_.isMethod) + + def pkg = symbol.enclosingPackage + def pkgName = pkg.fullName + def pkgClass = symbol.enclosingPackageClass + def pkgMembers = pkg.info.members filterNot excludeMember + def pkgClasses = pkgMembers filter (s => s.isClass && s.isDefinedInPackage) + def pkgSymbols = new PackageSlurper(pkgClass).slurp() filterNot excludeMember + + def fullManifest = manifest[T] + def erasure = fullManifest.erasure + def shortClass = erasure.getName split "[$.]" last + def baseTypeSeq = tpe.baseTypeSeq.toList + def baseTypeSeqMap = baseTypeSeq map (x => (x, x.decls.toList)) toMap + + def baseTypeWhichDefines(name: String) = baseTypeSeq filter (_.decls exists (_.name.toString == name)) + def <:<[U: Manifest](other: U) = tpe <:< newInfo(other).tpe + def lub[U: Manifest](other: U) = intp.global.lub(List(tpe, newInfo(other).tpe)) + def glb[U: Manifest](other: U) = intp.global.glb(List(tpe, newInfo(other).tpe)) - def shortClass = erasure.getName split "[$.]" last override def toString = value match { case Some(x) => "%s (%s)".format(x, shortClass) case _ => erasure.getName @@ -288,11 +311,17 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl def slurp(): String = io.Streamable.slurp(url) def pp() { intp prettyPrint slurp() } } - + class RichSymbolList(syms: List[Symbol]) { + def sigs = syms map (_.defString) + def infos = syms map (_.info) + } + trait Implicits1 { // fallback implicit def replPrinting[T](x: T)(implicit pretty: Prettifier[T] = Prettifier.default[T]) = new SinglePrettifierClass[T](x) + + implicit def liftToTypeName(s: String): TypeName = newTypeName(s) } trait Implicits2 extends Implicits1 { class RichSymbol(sym: Symbol) { @@ -309,7 +338,7 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl implicit lazy val powerSymbolOrdering: Ordering[Symbol] = Ordering[Name] on (_.name) implicit lazy val powerTypeOrdering: Ordering[Type] = Ordering[Symbol] on (_.typeSymbol) - implicit def replInternalInfo[T: Manifest](x: T): InternalInfo[T] = new InternalInfo[T](Some(x)) + implicit def replInternalInfo[T: Manifest](x: T): InternalInfoWrapper[T] = new InternalInfoWrapper[T](Some(x)) implicit def replEnhancedStrings(s: String): RichReplString = new RichReplString(s) implicit def replMultiPrinting[T: Prettifier](xs: TraversableOnce[T]): MultiPrettifierClass[T] = new MultiPrettifierClass[T](xs.toSeq) @@ -318,6 +347,9 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl implicit def replInputStream(in: InputStream)(implicit codec: Codec) = new RichInputStream(in) implicit def replEnhancedURLs(url: URL)(implicit codec: Codec): RichReplURL = new RichReplURL(url)(codec) + + implicit def liftToTermName(s: String): TermName = newTermName(s) + implicit def replListOfSymbols(xs: List[Symbol]) = new RichSymbolList(xs) } trait ReplUtilities { diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 6806ca03ba..107ffc35c6 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -140,6 +140,7 @@ trait ScalaSettings extends AbsScalaSettings val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.") val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs.") val Yshowsyms = BooleanSetting ("-Yshow-syms", "Print the AST symbol hierarchy after each phase.") + val Yshowsymkinds = BooleanSetting ("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.") val skip = PhasesSetting ("-Yskip", "Skip") val Ygenjavap = StringSetting ("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "") val Ydumpclasses = StringSetting ("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 7aa3e77471..a0826c19c3 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -368,7 +368,7 @@ abstract class ClassfileParser { case arr: Type => Constant(arr) } } - + private def getSubArray(bytes: Array[Byte]): Array[Byte] = { val decodedLength = ByteCodecs.decode(bytes) val arr = new Array[Byte](decodedLength) @@ -719,7 +719,7 @@ abstract class ClassfileParser { index += 1 val bounds = variance match { case '+' => TypeBounds.upper(objToAny(sig2type(tparams, skiptvs))) - case '-' => + case '-' => val tp = sig2type(tparams, skiptvs) // sig2type seems to return AnyClass regardless of the situation: // we don't want Any as a LOWER bound. diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 5b1555bfb7..30bfdbaf5b 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -31,39 +31,6 @@ abstract class Erasure extends AddInterfaces // -------- erasure on types -------------------------------------------------------- - // A type function from T => Class[U], used to determine the return - // type of getClass calls. The returned type is: - // - // 1. If T is a value type, Class[T]. - // 2. If T is a phantom type (Any or AnyVal), Class[_]. - // 3. If T is a local class, Class[_ <: |T|]. - // 4. Otherwise, Class[_ <: T]. - // - // Note: AnyVal cannot be Class[_ <: AnyVal] because if the static type of the - // receiver is AnyVal, it implies the receiver is boxed, so the correct - // class object is that of java.lang.Integer, not Int. - // - // TODO: If T is final, return type could be Class[T]. Should it? - def getClassReturnType(tp: Type): Type = { - val sym = tp.typeSymbol - - if (phase.erasedTypes) ClassClass.tpe - else if (isValueClass(sym)) ClassType(tp.widen) - else { - val eparams = typeParamsToExistentials(ClassClass, ClassClass.typeParams) - val upperBound = ( - if (isPhantomClass(sym)) AnyClass.tpe - else if (sym.isLocalClass) intersectionDominator(tp.parents) - else tp.widen - ) - - existentialAbstraction( - eparams, - ClassType(eparams.head setInfo TypeBounds.upper(upperBound) tpe) - ) - } - } - // convert a numeric with a toXXX method def numericConversion(tree: Tree, numericSym: Symbol): Tree = { val mname = newTermName("to" + numericSym.name) @@ -797,7 +764,7 @@ abstract class Erasure extends AddInterfaces // && (bridge.paramss.nonEmpty && bridge.paramss.head.nonEmpty && bridge.paramss.head.tail.isEmpty) // does the first argument list has exactly one argument -- for user-defined unapplies we can't be sure && !(atPhase(phase.next)(member.tpe <:< other.tpe))) { // no static guarantees (TODO: is the subtype test ever true?) import CODE._ - val typeTest = gen.mkIsInstanceOf(REF(bridge.paramss.head.head), member.tpe.params.head.tpe, any = true, wrapInApply = true) // any = true since we're before erasure (?), wrapInapply is true since we're after uncurry + val typeTest = gen.mkIsInstanceOf(REF(bridge.firstParam), member.tpe.params.head.tpe, any = true, wrapInApply = true) // any = true since we're before erasure (?), wrapInapply is true since we're after uncurry // println("unapp type test: "+ typeTest) IF (typeTest) THEN bridgingCall ELSE REF(NoneModule) } else bridgingCall @@ -989,8 +956,8 @@ abstract class Erasure extends AddInterfaces } else if (fn.symbol.owner.isInlineClass && extensionMethods.hasExtension(fn.symbol)) { Apply(gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args) } else { - tree - } + tree + } case Select(qual, name) => val owner = tree.symbol.owner diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index 35edf19a41..712298bd89 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -18,7 +18,7 @@ abstract class LambdaLift extends InfoTransform { /** the following two members override abstract members in Transform */ val phaseName: String = "lambdalift" - + /** Converts types of captured variables to *Ref types. */ def boxIfCaptured(sym: Symbol, tpe: Type, erasedTypes: Boolean) = @@ -72,10 +72,10 @@ abstract class LambdaLift extends InfoTransform { /** Buffers for lifted out classes and methods */ private val liftedDefs = new LinkedHashMap[Symbol, List[Tree]] - + /** True if we are transforming under a ReferenceToBoxed node */ private var isBoxedRef = false - + private type SymSet = TreeSet[Symbol] private def newSymSet = new TreeSet[Symbol](_ isLess _) @@ -213,7 +213,7 @@ abstract class LambdaLift extends InfoTransform { for (caller <- called.keys ; callee <- called(caller) ; fvs <- free get callee ; fv <- fvs) markFree(fv, caller) } while (changedFreeVars) - + def renameSym(sym: Symbol) { val originalName = sym.name val base = sym.name + nme.NAME_JOIN_STRING + ( @@ -404,10 +404,10 @@ abstract class LambdaLift extends InfoTransform { def refConstr(expr: Tree): Tree = expr match { case Try(block, catches, finalizer) => Try(refConstr(block), catches map refConstrCase, finalizer) - case _ => + case _ => Apply(Select(New(TypeTree(sym.tpe)), nme.CONSTRUCTOR), List(expr)) } - def refConstrCase(cdef: CaseDef): CaseDef = + def refConstrCase(cdef: CaseDef): CaseDef = CaseDef(cdef.pat, cdef.guard, refConstr(cdef.body)) treeCopy.ValDef(tree, mods, name, tpt1, typer.typedPos(rhs.pos) { refConstr(constructorArg) @@ -452,7 +452,7 @@ abstract class LambdaLift extends InfoTransform { tree } } - + private def preTransform(tree: Tree) = super.transform(tree) setType lifted(tree.tpe) override def transform(tree: Tree): Tree = tree match { @@ -461,7 +461,7 @@ abstract class LambdaLift extends InfoTransform { case _ => postTransform(preTransform(tree)) } - + /** Transform statements and add lifted definitions to them. */ override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { def addLifted(stat: Tree): Tree = stat match { diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index bd29336703..b3b7596f9a 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -1053,7 +1053,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { else accessedRef match { case Literal(_) => accessedRef case _ => - val init = Assign(accessedRef, Ident(sym.paramss.head.head)) + val init = Assign(accessedRef, Ident(sym.firstParam)) val getter = sym.getter(clazz) if (!needsInitFlag(getter)) init diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 422b1b7b7d..7d49c98dfb 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -74,7 +74,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { AnyRefClass, ObjectClass, Predef_AnyRef, uncheckedVarianceClass } - + /** TODO - this is a lot of maps. */ @@ -494,7 +494,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long) = member.cloneSymbol(sClass, flagFn(member.flags | SPECIALIZED)) - + sClass.sourceFile = clazz.sourceFile currentRun.symSource(sClass) = clazz.sourceFile // needed later on by mixin @@ -1197,7 +1197,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } else NoSymbol def illegalSpecializedInheritance(clazz: Symbol): Boolean = ( - hasSpecializedFlag(clazz) + hasSpecializedFlag(clazz) && originalClass(clazz).parentSymbols.exists(p => hasSpecializedParams(p) && !p.isTrait) ) @@ -1261,7 +1261,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val specMember = specCandidates suchThat { s => doesConform(symbol, tree.tpe, qual.tpe.memberType(s), env) } - + log("[specSym] found: " + specCandidates.tpe + ", instantiated as: " + tree.tpe) log("[specSym] found specMember: " + specMember) if (specMember ne NoSymbol) @@ -1378,7 +1378,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { (new CollectMethodBodies)(tree) val parents1 = map2(currentOwner.info.parents, parents)((tpe, parent) => TypeTree(tpe) setPos parent.pos) - + treeCopy.Template(tree, parents1 /*currentOwner.info.parents.map(tpe => TypeTree(tpe) setPos parents.head.pos)*/ , self, diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 685dce213c..68bc80ffc4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -31,14 +31,14 @@ trait ContextErrors { case class NormalTypeError(underlyingTree: Tree, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError { - + def errPos:Position = underlyingTree.pos override def toString() = "[Type error at:" + underlyingTree.pos + "] " + errMsg } case class SymbolTypeError(underlyingSym: Symbol, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError { - + def errPos = underlyingSym.pos } @@ -76,7 +76,7 @@ trait ContextErrors { } def issueTypeError(err: AbsTypeError)(implicit context: Context) { context.issue(err) } - + def typeErrorMsg(found: Type, req: Type, possiblyMissingArgs: Boolean) = { def missingArgsMsg = if (possiblyMissingArgs) "\n possible cause: missing arguments for method or constructor" else "" "type mismatch" + foundReqMsg(found, req) + missingArgsMsg @@ -177,13 +177,13 @@ trait ContextErrors { val calcSimilar = ( name.length > 2 && ( startingIdentCx.reportErrors - || startingIdentCx.enclClassOrMethod.reportErrors + || startingIdentCx.enclClassOrMethod.reportErrors ) ) - // avoid calculating if we're in "silent" mode. - // name length check to limit unhelpful suggestions for e.g. "x" and "b1" + // avoid calculating if we're in "silent" mode. + // name length check to limit unhelpful suggestions for e.g. "x" and "b1" val similar = { - if (!calcSimilar) "" + if (!calcSimilar) "" else { val allowed = ( startingIdentCx.enclosingContextChain @@ -636,8 +636,8 @@ trait ContextErrors { def CyclicReferenceError(errPos: Position, lockedSym: Symbol) = issueTypeError(PosAndMsgTypeError(errPos, "illegal cyclic reference involving " + lockedSym)) - - def MacroExpandError(tree: Tree, t: Any) = { + + def MacroExpandError(tree: Tree, t: Any) = { issueNormalTypeError(tree, "macros must return a compiler-specific tree; returned class is: " + t.getClass) setError(tree) } @@ -667,7 +667,7 @@ trait ContextErrors { type ErrorType = Value val WrongNumber, NoParams, ArgsDoNotConform = Value } - + private def ambiguousErrorMsgPos(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String) = if (sym1.hasDefaultFlag && sym2.hasDefaultFlag && sym1.enclClass == sym2.enclClass) { val methodName = nme.defaultGetterToMethod(sym1.name) @@ -830,14 +830,14 @@ trait ContextErrors { object NamerErrorGen { implicit val context0 = context - + object SymValidateErrors extends Enumeration { val ImplicitConstr, ImplicitNotTerm, ImplicitTopObject, OverrideClass, SealedNonClass, AbstractNonClass, OverrideConstr, AbstractOverride, LazyAndEarlyInit, ByNameParameter, AbstractVar = Value } - + object DuplicatesErrorKinds extends Enumeration { val RenamedTwice, AppearsTwice = Value } @@ -845,7 +845,7 @@ trait ContextErrors { import SymValidateErrors._ import DuplicatesErrorKinds._ import symtab.Flags - + def TypeSigError(tree: Tree, ex: TypeError) = { ex match { case CyclicReference(sym, info: TypeCompleter) => @@ -854,7 +854,7 @@ trait ContextErrors { context0.issue(TypeErrorWithUnderlyingTree(tree, ex)) } } - + def GetterDefinedTwiceError(getter: Symbol) = issueSymbolTypeError(getter, getter+" is defined twice") @@ -897,37 +897,37 @@ trait ContextErrors { val msg = errKind match { case ImplicitConstr => "`implicit' modifier not allowed for constructors" - + case ImplicitNotTerm => "`implicit' modifier can be used only for values, variables and methods" - + case ImplicitTopObject => "`implicit' modifier cannot be used for top-level objects" - + case OverrideClass => "`override' modifier not allowed for classes" - + case SealedNonClass => "`sealed' modifier can be used only for classes" - + case AbstractNonClass => "`abstract' modifier can be used only for classes; it should be omitted for abstract members" - + case OverrideConstr => "`override' modifier not allowed for constructors" - + case AbstractOverride => "`abstract override' modifier only allowed for members of traits" - + case LazyAndEarlyInit => "`lazy' definitions may not be initialized early" - + case ByNameParameter => "pass-by-name arguments not allowed for case class parameters" - + case AbstractVar => "only classes can have declared but undefined members" + abstractVarMessage(sym) - + } issueSymbolTypeError(sym, msg) } diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index c6ca9870c3..0c32ff32c0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -17,6 +17,139 @@ trait MethodSynthesis { import global._ import definitions._ + import CODE._ + + object synthesisUtil { + type M[T] = Manifest[T] + type CM[T] = ClassManifest[T] + + def ValOrDefDef(sym: Symbol, body: Tree) = + if (sym.isLazy) ValDef(sym, body) + else DefDef(sym, body) + + def applyTypeInternal(manifests: List[M[_]]): Type = { + val symbols = manifests map manifestToSymbol + val container :: args = symbols + val tparams = container.typeConstructor.typeParams + + // Conservative at present - if manifests were more usable this could do a lot more. + require(symbols forall (_ ne NoSymbol), "Must find all manifests: " + symbols) + require(container.owner.isPackageClass, "Container must be a top-level class in a package: " + container) + require(tparams.size == args.size, "Arguments must match type constructor arity: " + tparams + ", " + args) + + typeRef(container.typeConstructor.prefix, container, args map (_.tpe)) + } + + def companionType[T](implicit m: M[T]) = + getRequiredModule(m.erasure.getName).tpe + + // Use these like `applyType[List, Int]` or `applyType[Map, Int, String]` + def applyType[CC](implicit m1: M[CC]): Type = + applyTypeInternal(List(m1)) + + def applyType[CC[X1], X1](implicit m1: M[CC[_]], m2: M[X1]): Type = + applyTypeInternal(List(m1, m2)) + + def applyType[CC[X1, X2], X1, X2](implicit m1: M[CC[_,_]], m2: M[X1], m3: M[X2]): Type = + applyTypeInternal(List(m1, m2, m3)) + + def applyType[CC[X1, X2, X3], X1, X2, X3](implicit m1: M[CC[_,_,_]], m2: M[X1], m3: M[X2], m4: M[X3]): Type = + applyTypeInternal(List(m1, m2, m3, m4)) + + def newMethodType[F](owner: Symbol)(implicit m: Manifest[F]): Type = { + val fnSymbol = manifestToSymbol(m) + assert(fnSymbol isSubClass FunctionClass(m.typeArguments.size - 1), (owner, m)) + val symbols = m.typeArguments map (m => manifestToSymbol(m)) + val formals = symbols.init map (_.typeConstructor) + val params = owner newSyntheticValueParams formals + + MethodType(params, symbols.last.typeConstructor) + } + } + import synthesisUtil._ + + class ClassMethodSynthesis(val clazz: Symbol, localTyper: Typer) { + private def isOverride(name: TermName) = + clazzMember(name).alternatives exists (sym => !sym.isDeferred && (sym.owner != clazz)) + + def newMethodFlags(name: TermName) = { + val overrideFlag = if (isOverride(name)) OVERRIDE else 0L + overrideFlag | SYNTHETIC + } + def newMethodFlags(method: Symbol) = { + val overrideFlag = if (isOverride(method.name)) OVERRIDE else 0L + (method.flags | overrideFlag | SYNTHETIC) & ~DEFERRED + } + + private def finishMethod(method: Symbol, f: Symbol => Tree): Tree = + logResult("finishMethod")(localTyper typed ValOrDefDef(method, f(method))) + + private def createInternal(name: Name, f: Symbol => Tree, info: Type): Tree = { + val m = clazz.newMethod(name.toTermName, clazz.pos.focus, newMethodFlags(name)) + finishMethod(m setInfoAndEnter info, f) + } + private def createInternal(name: Name, f: Symbol => Tree, infoFn: Symbol => Type): Tree = { + val m = clazz.newMethod(name.toTermName, clazz.pos.focus, newMethodFlags(name)) + finishMethod(m setInfoAndEnter infoFn(m), f) + } + private def cloneInternal(original: Symbol, f: Symbol => Tree, name: Name): Tree = { + val m = original.cloneSymbol(clazz, newMethodFlags(original)) setPos clazz.pos.focus + m.name = name + finishMethod(clazz.info.decls enter m, f) + } + + private def cloneInternal(original: Symbol, f: Symbol => Tree): Tree = + cloneInternal(original, f, original.name) + + def clazzMember(name: Name) = clazz.info nonPrivateMember name + def typeInClazz(sym: Symbol) = clazz.thisType memberType sym + + /** Function argument takes the newly created method symbol of + * the same type as `name` in clazz, and returns the tree to be + * added to the template. + */ + def overrideMethod(name: Name)(f: Symbol => Tree): Tree = + overrideMethod(clazzMember(name))(f) + + def overrideMethod(original: Symbol)(f: Symbol => Tree): Tree = + cloneInternal(original, sym => f(sym setFlag OVERRIDE)) + + def deriveMethod(original: Symbol, nameFn: Name => Name)(f: Symbol => Tree): Tree = + cloneInternal(original, f, nameFn(original.name)) + + def createMethod(name: Name, paramTypes: List[Type], returnType: Type)(f: Symbol => Tree): Tree = + createInternal(name, f, (m: Symbol) => MethodType(m newSyntheticValueParams paramTypes, returnType)) + + def createMethod(name: Name, returnType: Type)(f: Symbol => Tree): Tree = + createInternal(name, f, NullaryMethodType(returnType)) + + def createMethod(original: Symbol)(f: Symbol => Tree): Tree = + createInternal(original.name, f, original.info) + + def forwardMethod(original: Symbol, newMethod: Symbol)(transformArgs: List[Tree] => List[Tree]): Tree = + createMethod(original)(m => gen.mkMethodCall(newMethod, transformArgs(m.paramss.head map Ident))) + + def createSwitchMethod(name: Name, range: Seq[Int], returnType: Type)(f: Int => Tree) = { + createMethod(name, List(IntClass.tpe), returnType) { m => + val arg0 = Ident(m.firstParam) + val default = DEFAULT ==> THROW(IndexOutOfBoundsExceptionClass, arg0) + val cases = range.map(num => CASE(LIT(num)) ==> f(num)).toList :+ default + + Match(arg0, cases) + } + } + + // def foo() = constant + def constantMethod(name: Name, value: Any): Tree = { + val constant = Constant(value) + createMethod(name, Nil, constant.tpe)(_ => Literal(constant)) + } + // def foo = constant + def constantNullary(name: Name, value: Any): Tree = { + val constant = Constant(value) + createMethod(name, constant.tpe)(_ => Literal(constant)) + } + } /** There are two key methods in here. * diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 1c40675508..b9f3adec75 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -113,7 +113,7 @@ trait Namers extends MethodSynthesis { private def contextFile = context.unit.source.file private def typeErrorHandler[T](tree: Tree, alt: T): PartialFunction[Throwable, T] = { case ex: TypeError => - // H@ need to ensure that we handle only cyclic references + // H@ need to ensure that we handle only cyclic references TypeSigError(tree, ex) alt } @@ -296,7 +296,7 @@ trait Namers extends MethodSynthesis { val pos = tree.pos val isParameter = tree.mods.isParameter val flags = tree.mods.flags & mask - + tree match { case TypeDef(_, _, _, _) if isParameter => owner.newTypeParameter(name.toTypeName, pos, flags) case TypeDef(_, _, _, _) => owner.newTypeSymbol(name.toTypeName, pos, flags) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index d492ba3662..4449116fd1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -686,13 +686,13 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R } else if (clazz.isTrait) { // prevent abstract methods in interfaces that override final members in Object; see #4431 if (!(clazz isSubClass AnyValClass)) { - for (decl <- clazz.info.decls.iterator) { - val overridden = decl.overriddenSymbol(ObjectClass) - if (overridden.isFinal) - unit.error(decl.pos, "trait cannot redefine final method from class AnyRef") - } + for (decl <- clazz.info.decls.iterator) { + val overridden = decl.overriddenSymbol(ObjectClass) + if (overridden.isFinal) + unit.error(decl.pos, "trait cannot redefine final method from class AnyRef") } } + } /** Returns whether there is a symbol declared in class `inclazz` * (which must be different from `clazz`) whose name and type diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 4e986dc5aa..4ea21b1c44 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -36,158 +36,13 @@ trait SyntheticMethods extends ast.TreeDSL { import definitions._ import CODE._ - private object util { - private type CM[T] = ClassManifest[T] - - def ValOrDefDef(sym: Symbol, body: Tree) = - if (sym.isLazy) ValDef(sym, body) - else DefDef(sym, body) - - /** To avoid unchecked warnings on polymorphic classes. - */ - def clazzTypeToTest(clazz: Symbol) = clazz.tpe.normalize match { - case TypeRef(_, sym, args) if args.nonEmpty => newExistentialType(sym.typeParams, clazz.tpe) - case tp => tp - } - - def makeMethodPublic(method: Symbol): Symbol = ( - method setPrivateWithin NoSymbol resetFlag AccessFlags - ) - - def methodArg(method: Symbol, idx: Int): Tree = Ident(method.paramss.head(idx)) - - private def applyTypeInternal(manifests: List[CM[_]]): Type = { - val symbols = manifests map manifestToSymbol - val container :: args = symbols - val tparams = container.typeConstructor.typeParams - - // Overly conservative at present - if manifests were more usable - // this could do a lot more. - require(symbols forall (_ ne NoSymbol), "Must find all manifests: " + symbols) - require(container.owner.isPackageClass, "Container must be a top-level class in a package: " + container) - require(tparams.size == args.size, "Arguments must match type constructor arity: " + tparams + ", " + args) - require(args forall (_.typeConstructor.typeParams.isEmpty), "Arguments must be unparameterized: " + args) - - typeRef(container.typeConstructor.prefix, container, args map (_.tpe)) - } - - def manifestToSymbol(m: CM[_]): Symbol = m match { - case x: scala.reflect.AnyValManifest[_] => getMember(ScalaPackageClass, newTermName("" + x)) - case _ => getClassIfDefined(m.erasure.getName) - } - def companionType[T](implicit m: CM[T]) = - getRequiredModule(m.erasure.getName).tpe - - // Use these like `applyType[List, Int]` or `applyType[Map, Int, String]` - def applyType[M](implicit m1: CM[M]): Type = - applyTypeInternal(List(m1)) - - def applyType[M[X1], X1](implicit m1: CM[M[_]], m2: CM[X1]): Type = - applyTypeInternal(List(m1, m2)) - - def applyType[M[X1, X2], X1, X2](implicit m1: CM[M[_,_]], m2: CM[X1], m3: CM[X2]): Type = - applyTypeInternal(List(m1, m2, m3)) - - def applyType[M[X1, X2, X3], X1, X2, X3](implicit m1: CM[M[_,_,_]], m2: CM[X1], m3: CM[X2], m4: CM[X3]): Type = - applyTypeInternal(List(m1, m2, m3, m4)) - } - import util._ - - class MethodSynthesis(val clazz: Symbol, localTyper: Typer) { - private def isOverride(method: Symbol) = - clazzMember(method.name).alternatives exists (sym => (sym != method) && !sym.isDeferred) - - private def setMethodFlags(method: Symbol): Symbol = { - val overrideFlag = if (isOverride(method)) OVERRIDE else 0L - - method setFlag (overrideFlag | SYNTHETIC) resetFlag DEFERRED - } - - private def finishMethod(method: Symbol, f: Symbol => Tree): Tree = { - setMethodFlags(method) - clazz.info.decls enter method - logResult("finishMethod")(localTyper typed ValOrDefDef(method, f(method))) - } - - private def createInternal(name: Name, f: Symbol => Tree, info: Type): Tree = { - val m = clazz.newMethod(name.toTermName, clazz.pos.focus) - m setInfo info - finishMethod(m, f) - } - private def createInternal(name: Name, f: Symbol => Tree, infoFn: Symbol => Type): Tree = { - val m = clazz.newMethod(name.toTermName, clazz.pos.focus) - m setInfo infoFn(m) - finishMethod(m, f) - } - private def cloneInternal(original: Symbol, f: Symbol => Tree, name: Name): Tree = { - val m = original.cloneSymbol(clazz) setPos clazz.pos.focus - m.name = name - finishMethod(m, f) - } - - private def cloneInternal(original: Symbol, f: Symbol => Tree): Tree = - cloneInternal(original, f, original.name) - - def clazzMember(name: Name) = clazz.info nonPrivateMember name match { - case NoSymbol => log("In " + clazz + ", " + name + " not found: " + clazz.info) ; NoSymbol - case sym => sym - } - def typeInClazz(sym: Symbol) = clazz.thisType memberType sym - - /** Function argument takes the newly created method symbol of - * the same type as `name` in clazz, and returns the tree to be - * added to the template. - */ - def overrideMethod(name: Name)(f: Symbol => Tree): Tree = - overrideMethod(clazzMember(name))(f) - - def overrideMethod(original: Symbol)(f: Symbol => Tree): Tree = - cloneInternal(original, sym => f(sym setFlag OVERRIDE)) - - def deriveMethod(original: Symbol, nameFn: Name => Name)(f: Symbol => Tree): Tree = - cloneInternal(original, f, nameFn(original.name)) - - def createMethod(name: Name, paramTypes: List[Type], returnType: Type)(f: Symbol => Tree): Tree = - createInternal(name, f, (m: Symbol) => MethodType(m newSyntheticValueParams paramTypes, returnType)) - - def createMethod(name: Name, returnType: Type)(f: Symbol => Tree): Tree = - createInternal(name, f, NullaryMethodType(returnType)) - - def createMethod(original: Symbol)(f: Symbol => Tree): Tree = - createInternal(original.name, f, original.info) - - def forwardMethod(original: Symbol, newMethod: Symbol)(transformArgs: List[Tree] => List[Tree]): Tree = - createMethod(original)(m => gen.mkMethodCall(newMethod, transformArgs(m.paramss.head map Ident))) - - def createSwitchMethod(name: Name, range: Seq[Int], returnType: Type)(f: Int => Tree) = { - createMethod(name, List(IntClass.tpe), returnType) { m => - val arg0 = methodArg(m, 0) - val default = DEFAULT ==> THROW(IndexOutOfBoundsExceptionClass, arg0) - val cases = range.map(num => CASE(LIT(num)) ==> f(num)).toList :+ default - - Match(arg0, cases) - } - } - - // def foo() = constant - def constantMethod(name: Name, value: Any): Tree = { - val constant = Constant(value) - createMethod(name, Nil, constant.tpe)(_ => Literal(constant)) - } - // def foo = constant - def constantNullary(name: Name, value: Any): Tree = { - val constant = Constant(value) - createMethod(name, constant.tpe)(_ => Literal(constant)) - } - } - /** Add the synthetic methods to case classes. */ def addSyntheticMethods(templ: Template, clazz0: Symbol, context: Context): Template = { if (phase.erasedTypes) return templ - val synthesizer = new MethodSynthesis( + val synthesizer = new ClassMethodSynthesis( clazz0, newTyper( if (reporter.hasErrors) context makeSilent false else context ) ) @@ -212,11 +67,12 @@ trait SyntheticMethods extends ast.TreeDSL { // like Manifests and Arrays which are not robust and infer things // which they shouldn't. val accessorLub = ( - if (opt.experimental) + if (opt.experimental) { global.weakLub(accessors map (_.tpe.finalResultType))._1 match { case RefinedType(parents, decls) if !decls.isEmpty => intersectionType(parents) case tp => tp } + } else AnyClass.tpe ) @@ -258,11 +114,10 @@ trait SyntheticMethods extends ast.TreeDSL { /** The canEqual method for case classes. * def canEqual(that: Any) = that.isInstanceOf[This] */ - def canEqualMethod: Tree = { - createMethod(nme.canEqual_, List(AnyClass.tpe), BooleanClass.tpe)(m => - methodArg(m, 0) IS_OBJ clazzTypeToTest(clazz) - ) - } + def canEqualMethod: Tree = ( + createMethod(nme.canEqual_, List(AnyClass.tpe), BooleanClass.tpe)(m => + Ident(m.firstParam) IS_OBJ typeCaseType(clazz)) + ) /** The equality method for case classes. * 0 args: @@ -276,8 +131,8 @@ trait SyntheticMethods extends ast.TreeDSL { * } */ def equalsClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => - val arg0 = methodArg(m, 0) - val thatTest = gen.mkIsInstanceOf(arg0, clazzTypeToTest(clazz), true, false) + val arg0 = Ident(m.firstParam) + val thatTest = gen.mkIsInstanceOf(arg0, typeCaseType(clazz), true, false) val thatCast = gen.mkCast(arg0, clazz.tpe) def argsBody: Tree = { @@ -331,7 +186,7 @@ trait SyntheticMethods extends ast.TreeDSL { Object_hashCode -> (() => constantMethod(nme.hashCode_, clazz.name.decode.hashCode)), Object_toString -> (() => constantMethod(nme.toString_, clazz.name.decode)) // Not needed, as reference equality is the default. - // Object_equals -> (() => createMethod(Object_equals)(m => This(clazz) ANY_EQ methodArg(m, 0))) + // Object_equals -> (() => createMethod(Object_equals)(m => This(clazz) ANY_EQ Ident(m.firstParam))) ) /** If you serialize a singleton and then deserialize it twice, @@ -381,7 +236,7 @@ trait SyntheticMethods extends ast.TreeDSL { for (ddef @ DefDef(_, _, _, _, _, _) <- templ.body ; if isRewrite(ddef.symbol)) { val original = ddef.symbol val newAcc = deriveMethod(ddef.symbol, name => context.unit.freshTermName(name + "$")) { newAcc => - makeMethodPublic(newAcc) + newAcc.makePublic newAcc resetFlag (ACCESSOR | PARAMACCESSOR) ddef.rhs.duplicate } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index b427e19820..b6f555e42a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -154,7 +154,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { case ErrorType => fun } - + def inferView(tree: Tree, from: Type, to: Type, reportAmbiguous: Boolean): Tree = inferView(tree, from, to, reportAmbiguous, true) @@ -274,7 +274,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } tp match { case TypeRef(pre, sym, args) => - checkNotLocked(sym) && + checkNotLocked(sym) && ((!sym.isNonClassType) || checkNonCyclic(pos, appliedType(pre.memberInfo(sym), args), sym)) // @M! info for a type ref to a type parameter now returns a polytype // @M was: checkNonCyclic(pos, pre.memberInfo(sym).subst(sym.typeParams, args), sym) @@ -793,7 +793,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val tree0 = etaExpand(context.unit, tree) // println("eta "+tree+" ---> "+tree0+":"+tree0.tpe+" undet: "+context.undetparams+ " mode: "+Integer.toHexString(mode)) - if (meth.typeParams.nonEmpty) { + if (context.undetparams.nonEmpty) { // #2624: need to infer type arguments for eta expansion of a polymorphic method // context.undetparams contains clones of meth.typeParams (fresh ones were generated in etaExpand) // need to run typer on tree0, since etaExpansion sets the tpe's of its subtrees to null @@ -939,7 +939,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { adaptType() else if (inExprModeButNot(mode, FUNmode) && tree.symbol != null && tree.symbol.isMacro && !tree.isDef) { val tree1 = expandMacro(tree) - if (tree1.isErroneous) tree1 else typed(tree1, mode, pt) + if (tree1.isErroneous) tree1 else typed(tree1, mode, pt) } else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) adaptConstrPattern() else if (inAllModes(mode, EXPRmode | FUNmode) && @@ -1084,7 +1084,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // Note: implicit arguments are still inferred (this kind of "chaining" is allowed) ) } - + def adaptToMember(qual: Tree, searchTemplate: Type): Tree = adaptToMember(qual, searchTemplate, true, true) def adaptToMember(qual: Tree, searchTemplate: Type, reportAmbiguous: Boolean): Tree = @@ -1099,12 +1099,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } inferView(qual, qual.tpe, searchTemplate, reportAmbiguous, saveErrors) match { case EmptyTree => qual - case coercion => + case coercion => if (settings.logImplicitConv.value) unit.echo(qual.pos, "applied implicit conversion from %s to %s = %s".format( qual.tpe, searchTemplate, coercion.symbol.defString)) - + typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual)))) } } @@ -2889,10 +2889,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def packSymbols(hidden: List[Symbol], tp: Type): Type = if (hidden.isEmpty) tp else existentialTransform(hidden, tp)(existentialAbstraction) - + def isReferencedFrom(ctx: Context, sym: Symbol): Boolean = - ctx.owner.isTerm && - (ctx.scope.exists { dcl => dcl.isInitialized && (dcl.info contains sym) }) || + ctx.owner.isTerm && + (ctx.scope.exists { dcl => dcl.isInitialized && (dcl.info contains sym) }) || { var ctx1 = ctx.outer while ((ctx1 != NoContext) && (ctx1.scope eq ctx.scope)) ctx1 = ctx1.outer @@ -3823,7 +3823,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { && qual.tpe.typeSymbol.isPublic ) if (isRefinableGetClass) - selection setType MethodType(Nil, erasure.getClassReturnType(qual.tpe)) + selection setType MethodType(Nil, getClassReturnType(qual.tpe)) else selection } @@ -3879,7 +3879,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { reallyExists(sym) && ((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod || sym.hasFlag(ACCESSOR)) } - + if (defSym == NoSymbol) { var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope @@ -4370,7 +4370,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { case ReferenceToBoxed(idt @ Ident(_)) => val id1 = typed1(idt, mode, pt) match { case id: Ident => id } - treeCopy.ReferenceToBoxed(tree, id1) setType AnyRefClass.tpe + treeCopy.ReferenceToBoxed(tree, id1) setType AnyRefClass.tpe case Literal(value) => tree setType ( diff --git a/src/library/scala/Byte.scala b/src/library/scala/Byte.scala index beff5ce208..f9c5f6003e 100644 --- a/src/library/scala/Byte.scala +++ b/src/library/scala/Byte.scala @@ -30,7 +30,7 @@ final class Byte extends AnyVal { * @return the bitwise negation of this value * @example {{{ * ~5 == -6 - * // in binary: ~00000101 == + * // in binary: ~00000101 == * // 11111010 * }}} */ @@ -60,22 +60,22 @@ final class Byte extends AnyVal { def <<(x: Long): Int = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ def >>>(x: Int): Int = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ @@ -85,8 +85,8 @@ final class Byte extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -96,8 +96,8 @@ final class Byte extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -281,9 +281,9 @@ final class Byte extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -292,9 +292,9 @@ final class Byte extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -303,9 +303,9 @@ final class Byte extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -314,9 +314,9 @@ final class Byte extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -325,9 +325,9 @@ final class Byte extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -337,9 +337,9 @@ final class Byte extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -348,9 +348,9 @@ final class Byte extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -359,9 +359,9 @@ final class Byte extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -370,9 +370,9 @@ final class Byte extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -381,9 +381,9 @@ final class Byte extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -393,9 +393,9 @@ final class Byte extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -404,9 +404,9 @@ final class Byte extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -415,9 +415,9 @@ final class Byte extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -426,9 +426,9 @@ final class Byte extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -437,9 +437,9 @@ final class Byte extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ diff --git a/src/library/scala/Char.scala b/src/library/scala/Char.scala index dade572396..3d459782cd 100644 --- a/src/library/scala/Char.scala +++ b/src/library/scala/Char.scala @@ -30,7 +30,7 @@ final class Char extends AnyVal { * @return the bitwise negation of this value * @example {{{ * ~5 == -6 - * // in binary: ~00000101 == + * // in binary: ~00000101 == * // 11111010 * }}} */ @@ -60,22 +60,22 @@ final class Char extends AnyVal { def <<(x: Long): Int = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ def >>>(x: Int): Int = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ @@ -85,8 +85,8 @@ final class Char extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -96,8 +96,8 @@ final class Char extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -281,9 +281,9 @@ final class Char extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -292,9 +292,9 @@ final class Char extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -303,9 +303,9 @@ final class Char extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -314,9 +314,9 @@ final class Char extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -325,9 +325,9 @@ final class Char extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -337,9 +337,9 @@ final class Char extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -348,9 +348,9 @@ final class Char extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -359,9 +359,9 @@ final class Char extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -370,9 +370,9 @@ final class Char extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -381,9 +381,9 @@ final class Char extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -393,9 +393,9 @@ final class Char extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -404,9 +404,9 @@ final class Char extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -415,9 +415,9 @@ final class Char extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -426,9 +426,9 @@ final class Char extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -437,9 +437,9 @@ final class Char extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ diff --git a/src/library/scala/Int.scala b/src/library/scala/Int.scala index 6b7debf2df..316bbced2d 100644 --- a/src/library/scala/Int.scala +++ b/src/library/scala/Int.scala @@ -30,7 +30,7 @@ final class Int extends AnyVal { * @return the bitwise negation of this value * @example {{{ * ~5 == -6 - * // in binary: ~00000101 == + * // in binary: ~00000101 == * // 11111010 * }}} */ @@ -60,22 +60,22 @@ final class Int extends AnyVal { def <<(x: Long): Int = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ def >>>(x: Int): Int = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ @@ -85,8 +85,8 @@ final class Int extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -96,8 +96,8 @@ final class Int extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -281,9 +281,9 @@ final class Int extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -292,9 +292,9 @@ final class Int extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -303,9 +303,9 @@ final class Int extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -314,9 +314,9 @@ final class Int extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -325,9 +325,9 @@ final class Int extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -337,9 +337,9 @@ final class Int extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -348,9 +348,9 @@ final class Int extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -359,9 +359,9 @@ final class Int extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -370,9 +370,9 @@ final class Int extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -381,9 +381,9 @@ final class Int extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -393,9 +393,9 @@ final class Int extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -404,9 +404,9 @@ final class Int extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -415,9 +415,9 @@ final class Int extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -426,9 +426,9 @@ final class Int extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -437,9 +437,9 @@ final class Int extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ diff --git a/src/library/scala/Long.scala b/src/library/scala/Long.scala index e734c92112..ce8618c22a 100644 --- a/src/library/scala/Long.scala +++ b/src/library/scala/Long.scala @@ -30,7 +30,7 @@ final class Long extends AnyVal { * @return the bitwise negation of this value * @example {{{ * ~5 == -6 - * // in binary: ~00000101 == + * // in binary: ~00000101 == * // 11111010 * }}} */ @@ -60,22 +60,22 @@ final class Long extends AnyVal { def <<(x: Long): Long = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ def >>>(x: Int): Long = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ @@ -85,8 +85,8 @@ final class Long extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -96,8 +96,8 @@ final class Long extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -281,9 +281,9 @@ final class Long extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -292,9 +292,9 @@ final class Long extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -303,9 +303,9 @@ final class Long extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -314,9 +314,9 @@ final class Long extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -325,9 +325,9 @@ final class Long extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -337,9 +337,9 @@ final class Long extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -348,9 +348,9 @@ final class Long extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -359,9 +359,9 @@ final class Long extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -370,9 +370,9 @@ final class Long extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -381,9 +381,9 @@ final class Long extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -393,9 +393,9 @@ final class Long extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -404,9 +404,9 @@ final class Long extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -415,9 +415,9 @@ final class Long extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -426,9 +426,9 @@ final class Long extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -437,9 +437,9 @@ final class Long extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ diff --git a/src/library/scala/Short.scala b/src/library/scala/Short.scala index 98e227d992..5664c3b44c 100644 --- a/src/library/scala/Short.scala +++ b/src/library/scala/Short.scala @@ -30,7 +30,7 @@ final class Short extends AnyVal { * @return the bitwise negation of this value * @example {{{ * ~5 == -6 - * // in binary: ~00000101 == + * // in binary: ~00000101 == * // 11111010 * }}} */ @@ -60,22 +60,22 @@ final class Short extends AnyVal { def <<(x: Long): Int = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ def >>>(x: Int): Int = sys.error("stub") /** * @return this value bit-shifted right by the specified number of bits, - * filling the new left bits with zeroes. + * filling the new left bits with zeroes. * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}} * @example {{{ - * -21 >>> 3 == 536870909 - * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == + * -21 >>> 3 == 536870909 + * // in binary: 11111111 11111111 11111111 11101011 >>> 3 == * // 00011111 11111111 11111111 11111101 * }}} */ @@ -85,8 +85,8 @@ final class Short extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -96,8 +96,8 @@ final class Short extends AnyVal { * filling in the right bits with the same value as the left-most bit of this. * The effect of this is to retain the sign of the value. * @example {{{ - * -21 >> 3 == -3 - * // in binary: 11111111 11111111 11111111 11101011 >> 3 == + * -21 >> 3 == -3 + * // in binary: 11111111 11111111 11111111 11101011 >> 3 == * // 11111111 11111111 11111111 11111101 * }}} */ @@ -281,9 +281,9 @@ final class Short extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -292,9 +292,9 @@ final class Short extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -303,9 +303,9 @@ final class Short extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -314,9 +314,9 @@ final class Short extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -325,9 +325,9 @@ final class Short extends AnyVal { * @return the bitwise OR of this value and x * @example {{{ * (0xf0 | 0xaa) == 0xfa - * // in binary: 11110000 - * // | 10101010 - * // -------- + * // in binary: 11110000 + * // | 10101010 + * // -------- * // 11111010 * }}} */ @@ -337,9 +337,9 @@ final class Short extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -348,9 +348,9 @@ final class Short extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -359,9 +359,9 @@ final class Short extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -370,9 +370,9 @@ final class Short extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -381,9 +381,9 @@ final class Short extends AnyVal { * @return the bitwise AND of this value and x * @example {{{ * (0xf0 & 0xaa) == 0xa0 - * // in binary: 11110000 - * // & 10101010 - * // -------- + * // in binary: 11110000 + * // & 10101010 + * // -------- * // 10100000 * }}} */ @@ -393,9 +393,9 @@ final class Short extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -404,9 +404,9 @@ final class Short extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -415,9 +415,9 @@ final class Short extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -426,9 +426,9 @@ final class Short extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ @@ -437,9 +437,9 @@ final class Short extends AnyVal { * @return the bitwise XOR of this value and x * @example {{{ * (0xf0 ^ 0xaa) == 0x5a - * // in binary: 11110000 - * // ^ 10101010 - * // -------- + * // in binary: 11110000 + * // ^ 10101010 + * // -------- * // 01011010 * }}} */ diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index f789de9fac..5f3f9b717f 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -620,7 +620,7 @@ object List extends SeqFactory[List] { } /** Only used for list serialization */ -@SerialVersionUID(0L - 8476791151975527571L) +@SerialVersionUID(0L - 8287891243975527522L) private[scala] case object ListSerializeStart /** Only used for list serialization */ diff --git a/src/library/scala/collection/mutable/AVLTree.scala b/src/library/scala/collection/mutable/AVLTree.scala index 0cf6cb06e5..ba2af8f120 100644 --- a/src/library/scala/collection/mutable/AVLTree.scala +++ b/src/library/scala/collection/mutable/AVLTree.scala @@ -9,7 +9,6 @@ package scala.collection package mutable -import annotation.tailrec /** * An immutable AVL Tree implementation used by mutable.TreeSet @@ -22,185 +21,221 @@ private[mutable] sealed trait AVLTree[+A] extends Serializable { def depth: Int -} + def iterator[B >: A]: Iterator[B] = Iterator.empty -private case class Node[A](val data: A, val left: AVLTree[A], val right: AVLTree[A]) extends AVLTree[A] { - override val balance: Int = right.depth - left.depth + def contains[B >: A](value: B, ordering: Ordering[B]): Boolean = false - override val depth: Int = math.max(left.depth, right.depth) + 1 + /** + * Returns a new tree containing the given element. + * Thows an IllegalArgumentException if element is already present. + * + */ + def insert[B >: A](value: B, ordering: Ordering[B]): AVLTree[B] = Node(value, Leaf, Leaf) + /** + * Return a new tree which not contains given element. + * + */ + def remove[B >: A](value: B, ordering: Ordering[B]): AVLTree[A] = + throw new NoSuchElementException(String.valueOf(value)) + + /** + * Return a tuple containing the smallest element of the provided tree + * and a new tree from which this element has been extracted. + * + */ + def removeMin[B >: A]: (B, AVLTree[B]) = sys.error("Should not happen.") + + /** + * Return a tuple containing the biggest element of the provided tree + * and a new tree from which this element has been extracted. + * + */ + def removeMax[B >: A]: (B, AVLTree[B]) = sys.error("Should not happen.") + + def rebalance[B >: A]: AVLTree[B] = this + + def leftRotation[B >: A]: Node[B] = sys.error("Should not happen.") + + def rightRotation[B >: A]: Node[B] = sys.error("Should not happen.") + + def doubleLeftRotation[B >: A]: Node[B] = sys.error("Should not happen.") + + def doubleRightRotation[B >: A]: Node[B] = sys.error("Should not happen.") } private case object Leaf extends AVLTree[Nothing] { override val balance: Int = 0 override val depth: Int = -1 - } -private[mutable] object AVLTree { +private case class Node[A](val data: A, val left: AVLTree[A], val right: AVLTree[A]) extends AVLTree[A] { + override val balance: Int = right.depth - left.depth + + override val depth: Int = math.max(left.depth, right.depth) + 1 + + override def iterator[B >: A]: Iterator[B] = new AVLIterator(this) + + override def contains[B >: A](value: B, ordering: Ordering[B]) = { + val ord = ordering.compare(value, data) + if (0 == ord) + true + else if (ord < 0) + left.contains(value, ordering) + else + right.contains(value, ordering) + } /** * Returns a new tree containing the given element. * Thows an IllegalArgumentException if element is already present. * */ - def insert[A](value: A, tree: AVLTree[A], ordering: Ordering[A]): AVLTree[A] = { - @tailrec - def insertTC(value: A, tree: AVLTree[A], reassemble: AVLTree[A] => AVLTree[A]): AVLTree[A] = tree match { - case Leaf => reassemble(Node(value, Leaf, Leaf)) - - case Node(a, left, right) => if (0 == ordering.compare(value, a)) { - throw new IllegalArgumentException() - } else if (-1 == ordering.compare(value, a)) { - insertTC(value, left, x => reassemble(rebalance(Node(a, x, right)))) - } else { - insertTC(value, right, x => reassemble(rebalance(Node(a, left, x)))) - } - } - - insertTC(value, tree, x => rebalance(x)) - } - - def contains[A](value: A, tree: AVLTree[A], ordering: Ordering[A]): Boolean = tree match { - case Leaf => false - - case Node(a, left, right) => if (0 == ordering.compare(value, a)) { - true - } else if (-1 == ordering.compare(value, a)) { - contains(value, left, ordering) - } else { - contains(value, right, ordering) - } + override def insert[B >: A](value: B, ordering: Ordering[B]) = { + val ord = ordering.compare(value, data) + if (0 == ord) + throw new IllegalArgumentException() + else if (ord < 0) + Node(data, left.insert(value, ordering), right).rebalance + else + Node(data, left, right.insert(value, ordering)).rebalance } /** * Return a new tree which not contains given element. * */ - def remove[A](value: A, tree: AVLTree[A], ordering: Ordering[A]): AVLTree[A] = tree match { - case Leaf => throw new NoSuchElementException() - - case Node(a, Leaf, Leaf) => if (0 == ordering.compare(value, a)) { - Leaf - } else { - throw new NoSuchElementException() - } - - case Node(a, left, right@Node(_, _, _)) => if (0 == ordering.compare(value, a)) { - val (min, newRight) = removeMin(right) - rebalance(Node(min, left, newRight)) - } else if (-1 == ordering.compare(value, a)) { - rebalance(Node(a, remove(value, left, ordering), right)) - } else { - rebalance(Node(a, left, remove(value, right, ordering))) - } - - case Node(a, left@Node(_, _, _), right) => if (0 == ordering.compare(value, a)) { - val (max, newLeft) = removeMax(left) - rebalance(Node(max, newLeft, right)) - } else if (-1 == ordering.compare(value, a)) { - rebalance(Node(a, remove(value, left, ordering), right)) + override def remove[B >: A](value: B, ordering: Ordering[B]): AVLTree[A] = { + val ord = ordering.compare(value, data) + if(ord == 0) { + if (Leaf == left) { + if (Leaf == right) { + Leaf + } else { + val (min, newRight) = right.removeMin + Node(min, left, newRight).rebalance + } + } else { + val (max, newLeft) = left.removeMax + Node(max, newLeft, right).rebalance + } + } else if (ord < 0) { + Node(data, left.remove(value, ordering), right).rebalance } else { - rebalance(Node(a, left, remove(value, right, ordering))) + Node(data, left, right.remove(value, ordering)).rebalance } } /** - * Return a tuple containing the biggest element of the provided tree + * Return a tuple containing the smallest element of the provided tree * and a new tree from which this element has been extracted. * */ - def removeMax[A](tree: Node[A]): (A, AVLTree[A]) = { - @tailrec - def removeMaxTC(tree: AVLTree[A], assemble: (A, AVLTree[A]) => (A, AVLTree[A])): (A, AVLTree[A]) = tree match { - case Node(a, Leaf, Leaf) => assemble(a, Leaf) - case Node(a, left, Leaf) => assemble(a, left) - case Node(a, left, right) => removeMaxTC(right, - (max: A, avl: AVLTree[A]) => assemble(max, rebalance(Node(a, left, avl)))) - case Leaf => sys.error("Should not happen.") + override def removeMin[B >: A]: (B, AVLTree[B]) = { + if (Leaf == left) + (data, right) + else { + val (min, newLeft) = left.removeMin + (min, Node(data, newLeft, right).rebalance) } - - removeMaxTC(tree, (a, b) => (a, b)) } /** - * Return a tuple containing the smallest element of the provided tree + * Return a tuple containing the biggest element of the provided tree * and a new tree from which this element has been extracted. * */ - def removeMin[A](tree: Node[A]): (A, AVLTree[A]) = { - @tailrec - def removeMinTC(tree: AVLTree[A], assemble: (A, AVLTree[A]) => (A, AVLTree[A])): (A, AVLTree[A]) = tree match { - case Node(a, Leaf, Leaf) => assemble(a, Leaf) - case Node(a, Leaf, right) => assemble(a, right) - case Node(a, left, right) => removeMinTC(left, - (min: A, avl: AVLTree[A]) => assemble(min, rebalance(Node(a, avl, right)))) - case Leaf => sys.error("Should not happen.") + override def removeMax[B >: A]: (B, AVLTree[B]) = { + if (Leaf == right) + (data, left) + else { + val (max, newRight) = right.removeMax + (max, Node(data, left, newRight).rebalance) } - - removeMinTC(tree, (a, b) => (a, b)) } - - /** - * Returns a bounded stream of elements in the tree. - * - */ - def toStream[A](tree: AVLTree[A], isLeftAcceptable: A => Boolean, isRightAcceptable: A => Boolean): Stream[A] = tree match { - case Leaf => Stream.empty - - case Node(a, left, right) => if (isLeftAcceptable(a)) { - if (isRightAcceptable(a)) { - toStream(left, isLeftAcceptable, isRightAcceptable) ++ Stream(a) ++ toStream(right, isLeftAcceptable, isRightAcceptable) - } else { - toStream(left, isLeftAcceptable, isRightAcceptable) - } - } else if (isRightAcceptable(a)) { - toStream(right, isLeftAcceptable, isRightAcceptable) + + override def rebalance[B >: A] = { + if (-2 == balance) { + if (1 == left.balance) + doubleRightRotation + else + rightRotation + } else if (2 == balance) { + if (-1 == right.balance) + doubleLeftRotation + else + leftRotation } else { - Stream.empty + this } } - /** - * Returns a bounded iterator of elements in the tree. - * - */ - def iterator[A](tree: AVLTree[A], isLeftAcceptable: A => Boolean, isRightAcceptable: A => Boolean): Iterator[A] = - toStream(tree, isLeftAcceptable, isRightAcceptable).iterator - - def rebalance[A](tree: AVLTree[A]): AVLTree[A] = (tree, tree.balance) match { - case (node@Node(_, left, _), -2) => left.balance match { - case 1 => doubleRightRotation(node) - case _ => rightRotation(node) - } - - case (node@Node(_, _, right), 2) => right.balance match { - case -1 => doubleLeftRotation(node) - case _ => leftRotation(node) - } + override def leftRotation[B >: A] = { + if (Leaf != right) { + val r: Node[A] = right.asInstanceOf[Node[A]] + Node(r.data, Node(data, left, r.left), r.right) + } else sys.error("Should not happen.") + } - case _ => tree + override def rightRotation[B >: A] = { + if (Leaf != left) { + val l: Node[A] = left.asInstanceOf[Node[A]] + Node(l.data, l.left, Node(data, l.right, right)) + } else sys.error("Should not happen.") } - def leftRotation[A](tree: Node[A]): AVLTree[A] = tree.right match { - case Node(b, left, right) => Node(b, Node(tree.data, tree.left, left), right) - case _ => sys.error("Should not happen.") + override def doubleLeftRotation[B >: A] = { + if (Leaf != right) { + val r: Node[A] = right.asInstanceOf[Node[A]] + // Let's save an instanceOf by 'inlining' the left rotation + val rightRotated = r.rightRotation + Node(rightRotated.data, Node(data, left, rightRotated.left), rightRotated.right) + } else sys.error("Should not happen.") } - def rightRotation[A](tree: Node[A]): AVLTree[A] = tree.left match { - case Node(b, left, right) => Node(b, left, Node(tree.data, right, tree.right)) - case _ => sys.error("Should not happen.") + override def doubleRightRotation[B >: A] = { + if (Leaf != left) { + val l: Node[A] = left.asInstanceOf[Node[A]] + // Let's save an instanceOf by 'inlining' the right rotation + val leftRotated = l.leftRotation + Node(leftRotated.data, leftRotated.left, Node(data, leftRotated.right, right)) + } else sys.error("Should not happen.") } +} + +private class AVLIterator[A](root: Node[A]) extends Iterator[A] { + val stack = mutable.ArrayStack[Node[A]](root) + diveLeft() - def doubleLeftRotation[A](tree: Node[A]): AVLTree[A] = tree.right match { - case right@Node(b, l, r) => leftRotation(Node(tree.data, tree.left, rightRotation(right))) - case _ => sys.error("Should not happen.") + private def diveLeft(): Unit = { + if (Leaf != stack.head.left) { + val left: Node[A] = stack.head.left.asInstanceOf[Node[A]] + stack.push(left) + diveLeft() + } } - def doubleRightRotation[A](tree: Node[A]): AVLTree[A] = tree.left match { - case left@Node(b, l, r) => rightRotation(Node(tree.data, leftRotation(left), tree.right)) - case _ => sys.error("Should not happen.") + private def engageRight(): Unit = { + if (Leaf != stack.head.right) { + val right: Node[A] = stack.head.right.asInstanceOf[Node[A]] + stack.pop + stack.push(right) + diveLeft() + } else + stack.pop } + override def hasNext: Boolean = !stack.isEmpty + + override def next(): A = { + if (stack.isEmpty) + throw new NoSuchElementException() + else { + val result = stack.head.data + // Let's maintain stack for the next invocation + engageRight() + result + } + } } diff --git a/src/library/scala/collection/mutable/TreeSet.scala b/src/library/scala/collection/mutable/TreeSet.scala index 38fa0c953f..e0f1c3adfe 100644 --- a/src/library/scala/collection/mutable/TreeSet.scala +++ b/src/library/scala/collection/mutable/TreeSet.scala @@ -79,7 +79,7 @@ class TreeSet[A](implicit val ordering: Ordering[A]) extends SortedSet[A] with S override def -=(elem: A): this.type = { try { - resolve.avl = AVLTree.remove(elem, resolve.avl, ordering) + resolve.avl = resolve.avl.remove(elem, ordering) resolve.cardinality = resolve.cardinality - 1 } catch { case e: NoSuchElementException => () @@ -89,7 +89,7 @@ class TreeSet[A](implicit val ordering: Ordering[A]) extends SortedSet[A] with S override def +=(elem: A): this.type = { try { - resolve.avl = AVLTree.insert(elem, resolve.avl, ordering) + resolve.avl = resolve.avl.insert(elem, ordering) resolve.cardinality = resolve.cardinality + 1 } catch { case e: IllegalArgumentException => () @@ -98,7 +98,7 @@ class TreeSet[A](implicit val ordering: Ordering[A]) extends SortedSet[A] with S } /** - * Thanks to the nature immutable of the + * Thanks to the immutable nature of the * underlying AVL Tree, we can share it with * the clone. So clone complexity in time is O(1). * @@ -113,11 +113,11 @@ class TreeSet[A](implicit val ordering: Ordering[A]) extends SortedSet[A] with S override def contains(elem: A): Boolean = { isLeftAcceptable(from, ordering)(elem) && isRightAcceptable(until, ordering)(elem) && - AVLTree.contains(elem, resolve.avl, ordering) + resolve.avl.contains(elem, ordering) } - override def iterator: Iterator[A] = - AVLTree.iterator(resolve.avl, - isLeftAcceptable(from, ordering), - isRightAcceptable(until, ordering)) + override def iterator: Iterator[A] = resolve.avl.iterator + .dropWhile(e => !isLeftAcceptable(from, ordering)(e)) + .takeWhile(e => isRightAcceptable(until, ordering)(e)) + } diff --git a/test/benchmarking/TreeSetInsert.scala b/test/benchmarking/TreeSetInsert.scala new file mode 100644 index 0000000000..9ede8aedc5 --- /dev/null +++ b/test/benchmarking/TreeSetInsert.scala @@ -0,0 +1,68 @@ + +object TreeSetInsert { + + def main(args: Array[String]): Unit = { + val n = 500000 + JavaUtilTS.main(args) + MutableTS.main(args) + ImmutableTS.main(args) + } +} + +class Dummy(val a: Int) extends math.Ordered[Dummy] { + def compare(other: Dummy) = this.a - other.a + + override def toString = a.toString + } + + +object JavaUtilTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: java.util.TreeSet[Dummy] = null + + def run = { + t = new java.util.TreeSet[Dummy]() + + var i = 0 + while (i < length) { + val elem = data(i) + t add elem + i += 1 + } + } +} + +object MutableTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: collection.mutable.TreeSet[Dummy] = null + + def run = { + t = collection.mutable.TreeSet[Dummy]() + + var i = 0 + while (i < length) { + val elem = data(i) + t += elem + i += 1 + } + } +} + +object ImmutableTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: collection.immutable.TreeSet[Dummy] = null + + def run = { + t = collection.immutable.TreeSet[Dummy]() + + var i = 0 + while (i < length) { + val elem = data(i) + t += elem + i += 1 + } + } +} diff --git a/test/benchmarking/TreeSetInsertRandom.scala b/test/benchmarking/TreeSetInsertRandom.scala new file mode 100644 index 0000000000..7f182548b7 --- /dev/null +++ b/test/benchmarking/TreeSetInsertRandom.scala @@ -0,0 +1,65 @@ + +object TreeSetInsertRandom { + + def main(args: Array[String]): Unit = { + val n = 500000 + new JavaUtilTS(n).main(args) + new MutableTS(n).main(args) + new ImmutableTS(n).main(args) + } +} + +class Dummy(val a: Int) extends math.Ordered[Dummy] { + def compare(other: Dummy) = this.a - other.a + + override def toString = a.toString + } + + +class JavaUtilTS(val length: Int) extends testing.Benchmark { + var data: Array[Dummy] = util.Random.shuffle((0 until length) map { a => new Dummy(a) }) toArray + var t: java.util.TreeSet[Dummy] = null + + def run = { + t = new java.util.TreeSet[Dummy]() + + var i = 0 + while (i < length) { + val elem = data(i) + t add elem + i += 1 + } + } +} + +class MutableTS(val length: Int) extends testing.Benchmark { + var data: Array[Dummy] = util.Random.shuffle((0 until length) map { a => new Dummy(a) }) toArray + var t: collection.mutable.TreeSet[Dummy] = null + + def run = { + t = collection.mutable.TreeSet[Dummy]() + + var i = 0 + while (i < length) { + val elem = data(i) + t += elem + i += 1 + } + } +} + +class ImmutableTS(val length: Int) extends testing.Benchmark { + var data: Array[Dummy] = util.Random.shuffle((0 until length) map { a => new Dummy(a) }) toArray + var t: collection.immutable.TreeSet[Dummy] = null + + def run = { + t = collection.immutable.TreeSet[Dummy]() + + var i = 0 + while (i < length) { + val elem = data(i) + t += elem + i += 1 + } + } +} diff --git a/test/benchmarking/TreeSetIterator.scala b/test/benchmarking/TreeSetIterator.scala new file mode 100644 index 0000000000..08c20e8b0c --- /dev/null +++ b/test/benchmarking/TreeSetIterator.scala @@ -0,0 +1,69 @@ + +object TreeSetIterator { + + def main(args: Array[String]): Unit = { + val n = 500000 + JavaUtilTS.main(args) + MutableTS.main(args) + ImmutableTS.main(args) + } +} + +class Dummy(val a: Int) extends math.Ordered[Dummy] { + def compare(other: Dummy) = this.a - other.a + + override def toString = a.toString + } + + +object JavaUtilTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: java.util.TreeSet[Dummy] = null + + def run = { + t = new java.util.TreeSet[Dummy]() + data foreach { a => t add a } + + var i: Dummy = null + var it = t.iterator + while (it.hasNext) { + i = it.next + } + i + } +} + +object MutableTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: collection.mutable.TreeSet[Dummy] = null + + def run = { + t = collection.mutable.TreeSet[Dummy](data: _*) + + var i: Dummy = null + var it = t.iterator + while (it.hasNext) { + i = it.next + } + i + } +} + +object ImmutableTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: collection.immutable.TreeSet[Dummy] = null + + def run = { + t = collection.immutable.TreeSet[Dummy](data: _*) + + var i: Dummy = null + var it = t.iterator + while (it.hasNext) { + i = it.next + } + i + } +} diff --git a/test/benchmarking/TreeSetRemove.scala b/test/benchmarking/TreeSetRemove.scala new file mode 100644 index 0000000000..f84066f336 --- /dev/null +++ b/test/benchmarking/TreeSetRemove.scala @@ -0,0 +1,69 @@ + +object TreeSetRemove { + + def main(args: Array[String]): Unit = { + val n = 500000 + JavaUtilTS.main(args) + MutableTS.main(args) + ImmutableTS.main(args) + } +} + +class Dummy(val a: Int) extends math.Ordered[Dummy] { + def compare(other: Dummy) = this.a - other.a + + override def toString = a.toString + } + + +object JavaUtilTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: java.util.TreeSet[Dummy] = null + + def run = { + t = new java.util.TreeSet[Dummy]() + data foreach { a => t add a } + + var i = 0 + while (i < length) { + val elem = data(i) + t remove elem + i += 1 + } + } +} + +object MutableTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: collection.mutable.TreeSet[Dummy] = null + + def run = { + t = collection.mutable.TreeSet[Dummy](data: _*) + + var i = 0 + while (i < length) { + val elem = data(i) + t -= elem + i += 1 + } + } +} + +object ImmutableTS extends testing.Benchmark { + val length = sys.props("length").toInt + var data: Array[Dummy] = (0 until length) map { a => new Dummy(a) } toArray + var t: collection.immutable.TreeSet[Dummy] = null + + def run = { + t = collection.immutable.TreeSet[Dummy](data: _*) + + var i = 0 + while (i < length) { + val elem = data(i) + t -= elem + i += 1 + } + } +} diff --git a/test/benchmarking/TreeSetRemoveRandom.scala b/test/benchmarking/TreeSetRemoveRandom.scala new file mode 100644 index 0000000000..4d311679e3 --- /dev/null +++ b/test/benchmarking/TreeSetRemoveRandom.scala @@ -0,0 +1,66 @@ + +object TreeSetRemoveRandom { + + def main(args: Array[String]): Unit = { + val n = 500000 + new JavaUtilTS(n).main(args) + new MutableTS(n).main(args) + new ImmutableTS(n).main(args) + } +} + +class Dummy(val a: Int) extends math.Ordered[Dummy] { + def compare(other: Dummy) = this.a - other.a + + override def toString = a.toString + } + + +class JavaUtilTS(val length: Int) extends testing.Benchmark { + var data: Array[Dummy] = util.Random.shuffle((0 until length) map { a => new Dummy(a) }) toArray + var t: java.util.TreeSet[Dummy] = null + + def run = { + t = new java.util.TreeSet[Dummy]() + data foreach { a => t add a } + + var i = 0 + while (i < length) { + val elem = data(i) + t remove elem + i += 1 + } + } +} + +class MutableTS(val length: Int) extends testing.Benchmark { + var data: Array[Dummy] = util.Random.shuffle((0 until length) map { a => new Dummy(a) }) toArray + var t: collection.mutable.TreeSet[Dummy] = null + + def run = { + t = collection.mutable.TreeSet[Dummy](data: _*) + + var i = 0 + while (i < length) { + val elem = data(i) + t -= elem + i += 1 + } + } +} + +class ImmutableTS(val length: Int) extends testing.Benchmark { + var data: Array[Dummy] = util.Random.shuffle((0 until length) map { a => new Dummy(a) }) toArray + var t: collection.immutable.TreeSet[Dummy] = null + + def run = { + t = collection.immutable.TreeSet[Dummy](data: _*) + + var i = 0 + while (i < length) { + val elem = data(i) + t -= elem + i += 1 + } + } +} diff --git a/test/files/neg/t4515.check b/test/files/neg/t4515.check new file mode 100644 index 0000000000..ce5350b35f --- /dev/null +++ b/test/files/neg/t4515.check @@ -0,0 +1,6 @@ +t4515.scala:37: error: type mismatch; + found : _0(in value $anonfun) where type _0(in value $anonfun) + required: (some other)_0(in value $anonfun) where type +(some other)_0(in value $anonfun) + handler.onEvent(target, ctx.getEvent, node, ctx) + ^ +one error found diff --git a/test/files/neg/t4515.scala b/test/files/neg/t4515.scala new file mode 100644 index 0000000000..63049f201d --- /dev/null +++ b/test/files/neg/t4515.scala @@ -0,0 +1,41 @@ +import scala.collection.mutable.HashMap + +object Main { + trait Target { } + + trait PushEventContext[EventType] { + def getEvent: EventType + } + trait PushNode[EventType] { } + trait DerivedPushNode[EventType] extends PushNode[EventType] { } + + trait HandlerBase[EventType] { + def onEvent(target: Target, + event: EventType, + node: PushNode[EventType], + ctx: PushEventContext[EventType]): Unit + } + val handlers = new HashMap[DerivedPushNode[_], HandlerBase[_]] + + object TimerPushService { + private val INSTANCE: TimerPushService = new TimerPushService + def get: TimerPushService = INSTANCE + } + + class TimerPushService { + def add[EventType](node: DerivedPushNode[EventType], + context: PushEventContext[EventType]): Unit = {} + + def pollEvents[EventType](node: DerivedPushNode[EventType]): List[PushEventContext[EventType]] = + Nil + } + + def onTimer(target: Target) { + val pushService = TimerPushService.get + for ((node, handler) <- handlers) { + for (ctx <- pushService.pollEvents(node)) { + handler.onEvent(target, ctx.getEvent, node, ctx) + } + } + } +}
\ No newline at end of file diff --git a/test/files/pos/t3999b.scala b/test/files/pos/t3999b.scala new file mode 100644 index 0000000000..d3fe108479 --- /dev/null +++ b/test/files/pos/t3999b.scala @@ -0,0 +1,20 @@ +object `package` { + trait Score { def toString : String } + trait Test[+T <: Score] { def apply(s : String) : T } + + case class FT(f : Float) extends Score + implicit object FT extends Test[FT] { def apply(s : String) : FT = new FT(s.toFloat) } + + case class IT(i : Int) extends Score + implicit object IT extends Test[IT] { def apply(s : String) : IT = new IT(s.toInt) } +} + +class TT[+T <: Score](implicit val tb : Test[T]) { + def read(s : String) : T = tb(s) +} + +object Tester { + val tt = new TT[FT] + val r = tt.read("1.0") + r.toString +}
\ No newline at end of file diff --git a/test/files/pos/t4336.scala b/test/files/pos/t4336.scala new file mode 100644 index 0000000000..e10d001585 --- /dev/null +++ b/test/files/pos/t4336.scala @@ -0,0 +1,19 @@ +object Main { + class NonGeneric {} + class Generic[T] {} + + class Composite { + def contains(setup : Composite => Unit) : Composite = this + } + + def generic[T](parent: Composite): Generic[T] = new Generic[T] + def nonGeneric(parent: Composite): NonGeneric = new NonGeneric + + new Composite().contains( + nonGeneric // should have type Composite => NonGeneric + ) + + new Composite().contains( + generic[Int] // should have type Composite => Generic[Int] + ) +} diff --git a/test/files/scalacheck/avl.scala b/test/files/scalacheck/avl.scala new file mode 100644 index 0000000000..51fb1fe8c3 --- /dev/null +++ b/test/files/scalacheck/avl.scala @@ -0,0 +1,114 @@ +import org.scalacheck.Gen +import org.scalacheck.Prop.forAll +import org.scalacheck.Properties + +import util.logging.ConsoleLogger + +package scala.collection.mutable { + + /** + * Property of an AVL Tree : Any node of the tree has a balance value beetween in [-1; 1] + */ + abstract class AVLTreeTest(name: String) extends Properties(name) with ConsoleLogger { + + def `2^`(n: Int) = (1 to n).fold(1)((a, b) => b*2) + + def capacityMax(depth: Int): Int = `2^`(depth+1) - 1 + + def minDepthForCapacity(x: Int): Int = { + var depth = 0 + while(capacityMax(depth) < x) + depth += 1 + depth + } + + def numberOfElementsInLeftSubTree(n: Int): collection.immutable.IndexedSeq[Int] = { + val mid = n/2 + n%2 + ((1 until mid) + .filter { i => math.abs(minDepthForCapacity(i) - minDepthForCapacity(n-i)) < 2 } + .flatMap { i => Seq(i, n-(i+1)) }).toIndexedSeq.distinct + } + + def makeAllBalancedTree[A](elements: List[A]): List[AVLTree[A]] = elements match { + case Nil => Leaf::Nil + case first::Nil => Node(first, Leaf, Leaf)::Nil + case first::second::Nil => Node(second, Node(first, Leaf, Leaf), Leaf)::Node(first, Leaf, Node(second, Leaf, Leaf))::Nil + case first::second::third::Nil => Node(second, Node(first, Leaf, Leaf), Node(third, Leaf, Leaf))::Nil + case _ => { + val combinations = for { + left <- numberOfElementsInLeftSubTree(elements.size) + root = elements(left) + right = elements.size - (left + 1) + } yield (root, left, right) + (combinations.flatMap(triple => for { + l <- makeAllBalancedTree(elements.take(triple._2)) + r <- makeAllBalancedTree(elements.takeRight(triple._3)) + } yield Node(triple._1, l, r))).toList + } + } + + def genInput: Gen[(Int, List[AVLTree[Int]])] = for { + size <- Gen.choose(20, 25) + elements <- Gen.listOfN(size, Gen.choose(0, 1000)) + selected <- Gen.choose(0, 1000) + } yield { + // selected mustn't be in elements already + val list = makeAllBalancedTree(elements.sorted.distinct.map(_*2)) + (selected*2+1, list) + } + + def genInputDelete: Gen[(Int, List[AVLTree[Int]])] = for { + size <- Gen.choose(20, 25) + elements <- Gen.listOfN(size, Gen.choose(0, 1000)) + e = elements.sorted.distinct + selected <- Gen.choose(0, e.size-1) + } yield { + // selected must be in elements already + val list = makeAllBalancedTree(e) + (e(selected), list) + } + } + + trait AVLInvariants { + self: AVLTreeTest => + + def isBalanced[A](t: AVLTree[A]): Boolean = t match { + case node: Node[A] => math.abs(node.balance) < 2 && (List(node.left, node.right) forall isBalanced) + case Leaf => true + } + + def setup(invariant: AVLTree[Int] => Boolean) = forAll(genInput) { + case (selected: Int, trees: List[AVLTree[Int]]) => + trees.map(tree => invariant(tree)).fold(true)((a, b) => a && b) + } + + property("Every tree is initially balanced.") = setup(isBalanced) + } + + object TestInsert extends AVLTreeTest("Insert") with AVLInvariants { + import math.Ordering.Int + property("`insert` creates a new tree containing the given element. The tree remains balanced.") = forAll(genInput) { + case (selected: Int, trees: List[AVLTree[Int]]) => + trees.map(tree => { + val modifiedTree = tree.insert(selected, Int) + modifiedTree.contains(selected, Int) && isBalanced(modifiedTree) + }).fold(true)((a, b) => a && b) + } + } + + object TestRemove extends AVLTreeTest("Remove") with AVLInvariants { + import math.Ordering.Int + property("`remove` creates a new tree without the given element. The tree remains balanced.") = forAll(genInputDelete) { + case (selected: Int, trees: List[AVLTree[Int]]) => + trees.map(tree => { + val modifiedTree = tree.remove(selected, Int) + tree.contains(selected, Int) && !modifiedTree.contains(selected, Int) && isBalanced(modifiedTree) + }).fold(true)((a, b) => a && b) + } + } +} + +object Test extends Properties("AVL") { + include(scala.collection.mutable.TestInsert) + include(scala.collection.mutable.TestRemove) +}
\ No newline at end of file diff --git a/test/pending/run/t5418.check b/test/pending/run/t5418.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/pending/run/t5418.check diff --git a/test/pending/run/t5418.scala b/test/pending/run/t5418.scala new file mode 100644 index 0000000000..065710f15e --- /dev/null +++ b/test/pending/run/t5418.scala @@ -0,0 +1,14 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + new Object().getClass + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +}
\ No newline at end of file |