diff options
author | Aleksandar Prokopec <axel22@gmail.com> | 2012-03-21 15:21:00 +0100 |
---|---|---|
committer | Aleksandar Prokopec <axel22@gmail.com> | 2012-03-21 15:21:00 +0100 |
commit | 0321df7292018d1e7408ef9ad193c8fc7bf4765d (patch) | |
tree | 6152d94c2b614bb823f75d864c2a729e8221248a /src | |
parent | 13a325b126ac6f2f5d2e7d1fc2c008d012367430 (diff) | |
parent | f6c050e8cfa5bd1ee4bbb3434086d2ae2d35e5f7 (diff) | |
download | scala-0321df7292018d1e7408ef9ad193c8fc7bf4765d.tar.gz scala-0321df7292018d1e7408ef9ad193c8fc7bf4765d.tar.bz2 scala-0321df7292018d1e7408ef9ad193c8fc7bf4765d.zip |
Merge branch 'master' into feature/pc-execution-contexts
Diffstat (limited to 'src')
187 files changed, 2792 insertions, 1080 deletions
diff --git a/src/android-library/scala/ScalaObject.scala b/src/android-library/scala/ScalaObject.scala deleted file mode 100644 index f44116d1ce..0000000000 --- a/src/android-library/scala/ScalaObject.scala +++ /dev/null @@ -1,13 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala - -trait ScalaObject extends AnyRef diff --git a/src/build/genprod.scala b/src/build/genprod.scala index cce00321df..6016f6fb92 100644 --- a/src/build/genprod.scala +++ b/src/build/genprod.scala @@ -608,7 +608,7 @@ object {className} {{ /** {className} is a cartesian product of {i} component{s}. * @since 2.3 */ -trait {className}{covariantArgs} extends Product {{ +trait {className}{covariantArgs} extends Any with Product {{ /** The arity of this product. * @return {i} */ diff --git a/src/build/maven/maven-deploy.xml b/src/build/maven/maven-deploy.xml index 2e490163e0..e0f31a5db2 100644 --- a/src/build/maven/maven-deploy.xml +++ b/src/build/maven/maven-deploy.xml @@ -16,10 +16,15 @@ <property name="local.release.repository" value="${user.home}/.m2/repository" /> <property name="repository.credentials.id" value="sonatype-nexus" /> <property name="settings.file" value="${user.home}/.m2/settings.xml" /> - + <condition property="version.is.snapshot"> + <contains string="${maven.version.number}" substring="-SNAPSHOT"/> + </condition> + <echo>Using server[${repository.credentials.id}] for maven repository credentials. Please make sure that your ~/.m2/settings.xml has the needed username/password for this server id </echo> + + </target> <target name="init.maven" depends="init.properties"> @@ -241,28 +246,31 @@ </target> <!-- Local Targets --> - <target name="deploy.snapshot.local" depends="deploy.local.init" description="Deploys the bundled snapshot of the Scala Lanaguage to a local maven repository"> - <deploy-local-all version="${maven.snapshot.version.number}" repository="${local.snapshot.repository}" /> + <target name="deploy.snapshot.local" depends="deploy.local.init" if="version.is.snapshot" description="Deploys the bundled snapshot of the Scala Lanaguage to a local maven repository"> + <deploy-local-all version="${maven.version.number}" repository="${local.snapshot.repository}" /> </target> - <target name="deploy.release.local" depends="deploy.local.init" description="Deploys the bundled files as a release into the local Maven repository"> - <deploy-local-all version="${version.number}" repository="${local.release.repository}" /> + <target name="deploy.release.local" depends="deploy.local.init" unless="version.is.snapshot" description="Deploys the bundled files as a release into the local Maven repository"> + <deploy-local-all version="${maven.version.number}" repository="${local.release.repository}" /> </target> + <target name="deploy.local" depends="deploy.snapshot.local, deploy.release.local" description="Deploys the bundle files to the local maven repo."/> - <!-- Remote Targets --> - <target name="deploy.signed.snapshot" depends="deploy.remote.init" description="Deploys the bundled files as a snapshot into the desired remote Maven repository"> - <deploy-remote-signed-all version="${maven.snapshot.version.number}" repository="${remote.snapshot.repository}" /> + <!-- Remote Signed Targets --> + <target name="deploy.signed.snapshot" depends="deploy.remote.init" if="version.is.snapshot" description="Deploys the bundled files as a snapshot into the desired remote Maven repository"> + <deploy-remote-signed-all version="${maven.version.number}" repository="${remote.snapshot.repository}" /> </target> - <target name="deploy.signed.release" depends="deploy.remote.init" description="Deploys the bundled files as a release into the desired remote Maven repository"> - <deploy-remote-signed-all version="${version.number}" repository="${remote.release.repository}" /> + <target name="deploy.signed.release" depends="deploy.remote.init" unless="version.is.snapshot" description="Deploys the bundled files as a release into the desired remote Maven repository"> + <deploy-remote-signed-all version="${maven.version.number}" repository="${remote.release.repository}" /> </target> - - <target name="deploy.snapshot" depends="deploy.remote.init" description="Deploys the bundled files as a snapshot into the desired remote Maven repository"> - <deploy-remote-all version="${maven.snapshot.version.number}" repository="${remote.snapshot.repository}" /> + <target name="deploy.signed" depends="deploy.signed.release, deploy.signed.snapshot" description="Deploys signed bundles to remote repo"/> + <!-- Remote unsigned targets --> + <target name="deploy.snapshot" depends="deploy.remote.init" if="version.is.snapshot" description="Deploys the bundled files as a snapshot into the desired remote Maven repository"> + <deploy-remote-all version="${maven.version.number}" repository="${remote.snapshot.repository}" /> </target> - <target name="deploy.release" depends="deploy.remote.init" description="Deploys the bundled files as a release into the desired remote Maven repository"> - <deploy-remote-all version="${version.number}" repository="${remote.release.repository}" /> + <target name="deploy.release" depends="deploy.remote.init" unless="version.is.snapshot" description="Deploys the bundled files as a release into the desired remote Maven repository"> + <deploy-remote-all version="${maven.version.number}" repository="${remote.release.repository}" /> </target> + <target name="deploy" depends="deploy.snapshot, deploy.release" description="Deploys unsigned artifacts to the maven repo."/> </project> diff --git a/src/build/pack.xml b/src/build/pack.xml index 90aec8e25b..e79895e3a8 100644 --- a/src/build/pack.xml +++ b/src/build/pack.xml @@ -299,7 +299,7 @@ MAIN DISTRIBUTION SBAZ <target name="pack-maven.latest.unix" depends="pack-maven.docs" unless="os.win"> <symlink link="${dists.dir}/maven/latest" - resource="${dists.dir}/maven/${version.number}" + resource="${version.number}" overwrite="yes"/> </target> @@ -315,8 +315,6 @@ MAIN DISTRIBUTION SBAZ <copy tofile="${dists.dir}/maven/${version.number}/build.xml" file="${src.dir}/build/maven/maven-deploy.xml"/> <!-- export properties for use when deploying --> - <property name="maven.snapshot.version.number" - value="${version.major}.${version.minor}.${version.patch}-SNAPSHOT"/> <echoproperties destfile="${dists.dir}/maven/${version.number}/build.properties"/> </target> diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index ec171c5f2c..bd823c3128 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -22,15 +22,17 @@ trait Definitions extends reflect.api.StandardDefinitions { */ private type PolyMethodCreator = List[Symbol] => (Option[List[Type]], Type) - private def newClass(owner: Symbol, name: TypeName, parents: List[Type], flags: Long = 0L): Symbol = { + 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 { @@ -101,7 +103,6 @@ trait Definitions extends reflect.api.StandardDefinitions { def isGetClass(sym: Symbol) = (sym.name == nme.getClass_) && (sym.paramss.isEmpty || sym.paramss.head.isEmpty) - lazy val AnyValClass = valueCache(tpnme.AnyVal) lazy val UnitClass = valueCache(tpnme.Unit) lazy val ByteClass = valueCache(tpnme.Byte) lazy val ShortClass = valueCache(tpnme.Short) @@ -205,8 +206,20 @@ trait Definitions extends reflect.api.StandardDefinitions { case _ => null } + private def fixupAsAnyTrait(tpe: Type): Type = tpe match { + case ClassInfoType(parents, decls, clazz) => + if (parents.head.typeSymbol == AnyClass) tpe + else { + assert(parents.head.typeSymbol == ObjectClass, parents) + ClassInfoType(AnyClass.tpe :: parents.tail, decls, clazz) + } + case PolyType(tparams, restpe) => + PolyType(tparams, fixupAsAnyTrait(restpe)) +// case _ => tpe + } + // 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) @@ -216,6 +229,14 @@ trait Definitions extends reflect.api.StandardDefinitions { @deprecated("Use AnyRefModule", "2.10.0") def Predef_AnyRef = AnyRefModule + lazy val AnyValClass = ScalaPackageClass.info member tpnme.AnyVal orElse { + val anyval = enterNewClass(ScalaPackageClass, tpnme.AnyVal, List(AnyClass.tpe, NotNullClass.tpe), ABSTRACT) + val av_constr = anyval.newClassConstructor(NoPosition) + anyval.info.decls enter av_constr + anyval + } + lazy val AnyVal_getClass = enterNewMethod(AnyValClass, nme.getClass_, Nil, getClassReturnType(AnyValClass.tpe)) + // bottom types lazy val RuntimeNothingClass = getClass(fulltpnme.RuntimeNothing) lazy val RuntimeNullClass = getClass(fulltpnme.RuntimeNull) @@ -248,7 +269,6 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val UninitializedErrorClass = getRequiredClass("scala.UninitializedFieldError") // fundamental reference classes - lazy val ScalaObjectClass = getMember(ScalaPackageClass, tpnme.ScalaObject) lazy val PartialFunctionClass = getRequiredClass("scala.PartialFunction") lazy val AbstractPartialFunctionClass = getRequiredClass("scala.runtime.AbstractPartialFunction") lazy val SymbolClass = getRequiredClass("scala.Symbol") @@ -319,10 +339,10 @@ 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") + lazy val JavaSerializableClass = getClass(sn.JavaSerializable) modifyInfo fixupAsAnyTrait + lazy val ComparableClass = getRequiredClass("java.lang.Comparable") modifyInfo fixupAsAnyTrait lazy val JavaCloneableClass = getRequiredClass("java.lang.Cloneable") lazy val RemoteInterfaceClass = getRequiredClass("java.rmi.Remote") lazy val RemoteExceptionClass = getRequiredClass("java.rmi.RemoteException") @@ -351,7 +371,7 @@ trait Definitions extends reflect.api.StandardDefinitions { } def isPrimitiveArray(tp: Type) = tp match { - case TypeRef(_, ArrayClass, arg :: Nil) => isValueClass(arg.typeSymbol) + case TypeRef(_, ArrayClass, arg :: Nil) => isPrimitiveValueClass(arg.typeSymbol) case _ => false } def isArrayOfSymbol(tp: Type, elem: Symbol) = tp match { @@ -660,12 +680,12 @@ trait Definitions extends reflect.api.StandardDefinitions { } // 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: @@ -676,22 +696,89 @@ 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_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) + // 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 (isPrimitiveValueClass(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) + ) + } + } + + /** Remove references to class Object (other than the head) in a list of parents */ + def removeLaterObjects(tps: List[Type]): List[Type] = tps match { + case Nil => Nil + case x :: xs => x :: xs.filterNot(_.typeSymbol == ObjectClass) + } + /** Remove all but one reference to class Object from a list of parents. */ + def removeRedundantObjects(tps: List[Type]): List[Type] = tps match { + case Nil => Nil + case x :: xs => + if (x.typeSymbol == ObjectClass) + x :: xs.filterNot(_.typeSymbol == ObjectClass) + else + x :: removeRedundantObjects(xs) + } + /** Order a list of types with non-trait classes before others. */ + def classesFirst(tps: List[Type]): List[Type] = { + val (classes, others) = tps partition (t => t.typeSymbol.isClass && !t.typeSymbol.isTrait) + if (classes.isEmpty || others.isEmpty || (tps startsWith classes)) tps + else classes ::: others + } + /** The following transformations applied to a list of parents. + * If any parent is a class/trait, all parents which normalize to + * Object are discarded. Otherwise, all parents which normalize + * to Object except the first one found are discarded. + */ + def normalizedParents(parents: List[Type]): List[Type] = { + if (parents exists (t => (t.typeSymbol ne ObjectClass) && t.typeSymbol.isClass)) + parents filterNot (_.typeSymbol eq ObjectClass) + else + removeRedundantObjects(parents) + } + def parentsString(parents: List[Type]) = + normalizedParents(parents) mkString " with " + // 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_## = 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_+ = newMethod(StringClass, nme.raw.PLUS, anyparam, stringtype, FINAL) + 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_) @@ -776,7 +863,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 @@ -817,6 +904,20 @@ trait Definitions extends reflect.api.StandardDefinitions { def termMember(owner: Symbol, name: String): Symbol = owner.info.member(newTermName(name)) def typeMember(owner: Symbol, name: String): Symbol = owner.info.member(newTypeName(name)) + def findMemberFromRoot(fullName: Name): Symbol = { + val segs = nme.segments(fullName.toString, fullName.isTermName) + if (segs.isEmpty) NoSymbol + else findNamedMember(segs.tail, definitions.RootClass.info member segs.head) + } + def findNamedMember(fullName: Name, root: Symbol): Symbol = { + val segs = nme.segments(fullName.toString, fullName.isTermName) + if (segs.isEmpty || segs.head != root.simpleName) NoSymbol + else findNamedMember(segs.tail, root) + } + def findNamedMember(segs: List[Name], root: Symbol): Symbol = + if (segs.isEmpty) root + else findNamedMember(segs.tail, root.info member segs.head) + def getMember(owner: Symbol, name: Name): Symbol = { if (owner == NoSymbol) NoSymbol else owner.info.nonPrivateMember(name) match { @@ -824,6 +925,7 @@ trait Definitions extends reflect.api.StandardDefinitions { case result => result } } + def packageExists(packageName: String): Boolean = getModuleIfDefined(packageName).isPackage @@ -853,11 +955,11 @@ trait Definitions extends reflect.api.StandardDefinitions { owner.newAliasType(name) setInfoAndEnter alias private def specialPolyClass(name: TypeName, flags: Long)(parentFn: Symbol => Type): Symbol = { - val clazz = newClass(ScalaPackageClass, name, Nil) + val clazz = enterNewClass(ScalaPackageClass, name, Nil) val tparam = clazz.newSyntheticTypeParam("T0", flags) val parents = List(AnyRefClass.tpe, parentFn(tparam)) - clazz setInfo polyType(List(tparam), ClassInfoType(parents, newScope, clazz)) + clazz setInfo GenPolyType(List(tparam), ClassInfoType(parents, newScope, clazz)) } def newPolyMethod(typeParamCount: Int, owner: Symbol, name: TermName, flags: Long)(createFn: PolyMethodCreator): Symbol = { @@ -890,14 +992,14 @@ trait Definitions extends reflect.api.StandardDefinitions { /** Is the symbol that of a parent which is added during parsing? */ lazy val isPossibleSyntheticParent = ProductClass.toSet[Symbol] + ProductRootClass + SerializableClass - private lazy val scalaValueClassesSet = ScalaValueClasses.toSet + lazy val scalaValueClassesSet = ScalaValueClasses.toSet private lazy val boxedValueClassesSet = boxedClass.values.toSet + BoxedUnitClass /** Is symbol a value class? */ - def isValueClass(sym: Symbol) = scalaValueClassesSet(sym) - def isNonUnitValueClass(sym: Symbol) = isValueClass(sym) && (sym != UnitClass) - def isSpecializableClass(sym: Symbol) = isValueClass(sym) || (sym == AnyRefClass) - def isScalaValueType(tp: Type) = scalaValueClassesSet(tp.typeSymbol) + def isPrimitiveValueClass(sym: Symbol) = scalaValueClassesSet(sym) + def isNonUnitValueClass(sym: Symbol) = isPrimitiveValueClass(sym) && (sym != UnitClass) + def isSpecializableClass(sym: Symbol) = isPrimitiveValueClass(sym) || (sym == AnyRefClass) + def isScalaValueType(tp: Type) = scalaValueClassesSet(tp.typeSymbol) /** Is symbol a boxed value class, e.g. java.lang.Integer? */ def isBoxedValueClass(sym: Symbol) = boxedValueClassesSet(sym) @@ -906,7 +1008,7 @@ trait Definitions extends reflect.api.StandardDefinitions { * value class. Otherwise, NoSymbol. */ def unboxedValueClass(sym: Symbol): Symbol = - if (isValueClass(sym)) sym + if (isPrimitiveValueClass(sym)) sym else if (sym == BoxedUnitClass) UnitClass else boxedClass.map(_.swap).getOrElse(sym, NoSymbol) @@ -929,7 +1031,7 @@ trait Definitions extends reflect.api.StandardDefinitions { else flatNameString(sym.owner, separator) + nme.NAME_JOIN_STRING + sym.simpleName def signature1(etp: Type): String = { if (etp.typeSymbol == ArrayClass) "[" + signature1(erasure(etp.normalize.typeArgs.head)) - else if (isValueClass(etp.typeSymbol)) abbrvTag(etp.typeSymbol).toString() + else if (isPrimitiveValueClass(etp.typeSymbol)) abbrvTag(etp.typeSymbol).toString() else "L" + flatNameString(etp.typeSymbol, '/') + ";" } val etp = erasure(tp) @@ -1007,16 +1109,11 @@ trait Definitions extends reflect.api.StandardDefinitions { Object_synchronized, Object_isInstanceOf, Object_asInstanceOf, - String_+ + String_+, + ComparableClass, + JavaSerializableClass ) - /** Removing the anyref parent they acquire from having a source file. - */ - setParents(AnyValClass, anyparam) - ScalaValueClasses foreach { sym => - setParents(sym, anyvalparam) - } - isInitialized = true } //init @@ -1029,7 +1126,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/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala index 270491d078..8aae80eed4 100644 --- a/src/compiler/scala/reflect/internal/Flags.scala +++ b/src/compiler/scala/reflect/internal/Flags.scala @@ -468,33 +468,34 @@ class Flags extends ModifierFlags { protected final val rawFlagPickledOrder: Array[Long] = pickledListOrder.toArray def flagOfModifier(mod: Modifier): Long = mod match { - case Modifier.`protected` => PROTECTED - case Modifier.`private` => PRIVATE - case Modifier.`override` => OVERRIDE - case Modifier.`abstract` => ABSTRACT - case Modifier.`final`=> FINAL - case Modifier.`sealed`=> SEALED - case Modifier.`implicit`=> IMPLICIT - case Modifier.`lazy`=> LAZY - case Modifier.`case`=> CASE - case Modifier.`trait`=> TRAIT - case Modifier.deferred => DEFERRED - case Modifier.interface => INTERFACE - case Modifier.mutable => MUTABLE - case Modifier.parameter => PARAM - case Modifier.`macro` => MACRO - case Modifier.covariant => COVARIANT - case Modifier.contravariant => CONTRAVARIANT - case Modifier.preSuper => PRESUPER + case Modifier.`protected` => PROTECTED + case Modifier.`private` => PRIVATE + case Modifier.`override` => OVERRIDE + case Modifier.`abstract` => ABSTRACT + case Modifier.`final` => FINAL + case Modifier.`sealed` => SEALED + case Modifier.`implicit` => IMPLICIT + case Modifier.`lazy` => LAZY + case Modifier.`case` => CASE + case Modifier.`trait` => TRAIT + case Modifier.deferred => DEFERRED + case Modifier.interface => INTERFACE + case Modifier.mutable => MUTABLE + case Modifier.parameter => PARAM + case Modifier.`macro` => MACRO + case Modifier.covariant => COVARIANT + case Modifier.contravariant => CONTRAVARIANT + case Modifier.preSuper => PRESUPER case Modifier.abstractOverride => ABSOVERRIDE - case Modifier.local => LOCAL - case Modifier.java => JAVA - case Modifier.static => STATIC - case Modifier.caseAccessor => CASEACCESSOR + case Modifier.local => LOCAL + case Modifier.java => JAVA + case Modifier.static => STATIC + case Modifier.caseAccessor => CASEACCESSOR case Modifier.defaultParameter => DEFAULTPARAM - case Modifier.defaultInit => DEFAULTINIT - case Modifier.paramAccessor => PARAMACCESSOR - case Modifier.bynameParameter => BYNAMEPARAM + case Modifier.defaultInit => DEFAULTINIT + case Modifier.paramAccessor => PARAMACCESSOR + case Modifier.bynameParameter => BYNAMEPARAM + case _ => 0 } def flagsOfModifiers(mods: List[Modifier]): Long = diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 1ae4f755ed..1003fa804f 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -88,7 +88,7 @@ trait Importers { self: SymbolTable => case from.PolyType(_, res) => res case result => result } - s setInfo polyType(mytypeParams, importType(result)) + s setInfo GenPolyType(mytypeParams, importType(result)) s setAnnotations (sym.annotations map importAnnotationInfo) } } @@ -200,7 +200,7 @@ trait Importers { self: SymbolTable => val myclazz = importSymbol(clazz) val myscope = if (myclazz.isPackageClass) newPackageScope(myclazz) else newScope val myclazzTpe = ClassInfoType(parents map importType, myscope, myclazz) - myclazz setInfo polyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope + myclazz setInfo GenPolyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope decls foreach importSymbol // will enter itself into myclazz myclazzTpe case from.RefinedType(parents, decls) => diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala index 12f56976c9..48f21721da 100644 --- a/src/compiler/scala/reflect/internal/NameManglers.scala +++ b/src/compiler/scala/reflect/internal/NameManglers.scala @@ -80,9 +80,9 @@ trait NameManglers { val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$" val SETTER_SUFFIX: TermName = encode("_=") - @deprecated("2.10.0", "Use SPECIALIZED_SUFFIX") + @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0") def SPECIALIZED_SUFFIX_STRING = SPECIALIZED_SUFFIX.toString - @deprecated("2.10.0", "Use SPECIALIZED_SUFFIX") + @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0") def SPECIALIZED_SUFFIX_NAME: TermName = SPECIALIZED_SUFFIX.toTermName def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index ef2114b608..84007425ed 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -145,7 +145,6 @@ trait StdNames extends NameManglers { self: SymbolTable => final val Object: NameType = "Object" final val PartialFunction: NameType = "PartialFunction" final val Product: NameType = "Product" - final val ScalaObject: NameType = "ScalaObject" final val Serializable: NameType = "Serializable" final val Singleton: NameType = "Singleton" final val String: NameType = "String" diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala index ce54c32273..b58a0ef7d5 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/compiler/scala/reflect/internal/SymbolTable.scala @@ -37,7 +37,7 @@ abstract class SymbolTable extends api.Universe def log(msg: => AnyRef): Unit def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg)) - @deprecated("2.10.0", "Give us a reason") + @deprecated("Give us a reason", "2.10.0") def abort(): Nothing = abort("unknown error") /** Override with final implementation for inlining. */ @@ -128,6 +128,10 @@ abstract class SymbolTable extends api.Universe final def period(rid: RunId, pid: Phase#Id): Period = (rid << 8) + pid + /** Are we later than given phase in compilation? */ + final def isAtPhaseAfter(p: Phase) = + p != NoPhase && phase.id > p.id + /** Perform given operation at given phase. */ @inline final def atPhase[T](ph: Phase)(op: => T): T = { val saved = pushPhase(ph) @@ -145,7 +149,7 @@ abstract class SymbolTable extends api.Universe @inline final def beforePrevPhase[T](op: => T): T = atPhase(phase.prev)(op) @inline final def atPhaseNotLaterThan[T](target: Phase)(op: => T): T = - if (target != NoPhase && phase.id > target.id) atPhase(target)(op) else op + if (isAtPhaseAfter(target)) atPhase(target)(op) else op final def isValid(period: Period): Boolean = period != 0 && runId(period) == currentRunId && { @@ -184,7 +188,7 @@ abstract class SymbolTable extends api.Universe } // enter decls of parent classes for (p <- container.parentSymbols) { - if (p != definitions.ObjectClass && p != definitions.ScalaObjectClass) { + if (p != definitions.ObjectClass) { openPackageModule(p, dest) } } diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index de490074b0..9678d2b8cd 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -441,7 +441,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isRefinementClass = isClass && name == tpnme.REFINE_CLASS_NAME final def isSourceMethod = isMethod && !hasFlag(STABLE) // exclude all accessors!!! final def isTypeParameter = isType && isParameter && !isSkolem - final def isValueClass = definitions.isValueClass(this) + final def isPrimitiveValueClass = definitions.isPrimitiveValueClass(this) final def isVarargsMethod = isMethod && hasFlag(VARARGS) /** Package tests */ @@ -499,6 +499,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR) + final def isDerivedValueClass = + isClass && info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass + + final def isMethodWithExtension = + isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) + final def isAnonymousClass = isClass && (name containsName tpnme.ANON_CLASS_NAME) final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME) final def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass @@ -1598,7 +1604,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else owner.logicallyEnclosingMember /** Kept for source compatibility with 2.9. Scala IDE for Eclipse relies on this. */ - @deprecated("Use enclosingTopLevelClass") + @deprecated("Use enclosingTopLevelClass", "2.10.0") def toplevelClass: Symbol = enclosingTopLevelClass /** The top-level class containing this symbol. */ @@ -1835,7 +1841,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => base.info.decl(sname) filter (_.hasAccessorFlag) } - /** The case module corresponding to this case class + /** Return the accessor method of the first parameter of this class. + * or NoSymbol if it does not exist. + */ + def firstParamAccessor: Symbol = NoSymbol + + /** The case module corresponding to this case class * @pre case class is a member of some other class or package */ final def caseModule: Symbol = { @@ -2510,7 +2521,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final override def isAbstractType = false final override def isAliasType = false - override def existentialBound = polyType(this.typeParams, TypeBounds.upper(this.classBound)) + override def existentialBound = GenPolyType(this.typeParams, TypeBounds.upper(this.classBound)) override def sourceFile = if (owner.isPackageClass) source @@ -2585,6 +2596,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def sourceModule = if (isModuleClass) companionModule else NoSymbol + override def firstParamAccessor = + info.decls.find(m => (m hasFlag PARAMACCESSOR) && m.isMethod) getOrElse NoSymbol + + private[this] var childSet: Set[Symbol] = Set() override def children = childSet override def addChild(sym: Symbol) { childSet = childSet + sym } @@ -2742,7 +2757,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** An exception for cyclic references of symbol definitions */ case class CyclicReference(sym: Symbol, info: Type) extends TypeError("illegal cyclic reference involving " + sym) { - // printStackTrace() // debug + if (settings.debug.value) printStackTrace() } case class InvalidCompanions(sym1: Symbol, sym2: Symbol) extends Throwable( diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala index 8c2a067d4d..141ff12f8a 100644 --- a/src/compiler/scala/reflect/internal/TreeGen.scala +++ b/src/compiler/scala/reflect/internal/TreeGen.scala @@ -10,11 +10,10 @@ abstract class TreeGen { def rootId(name: Name) = Select(Ident(nme.ROOTPKG), name) def rootScalaDot(name: Name) = Select(rootId(nme.scala_) setSymbol ScalaPackage, name) def scalaDot(name: Name) = Select(Ident(nme.scala_) setSymbol ScalaPackage, name) - def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) - def scalaUnitConstr = scalaDot(tpnme.Unit) - def scalaScalaObjectConstr = scalaDot(tpnme.ScalaObject) - def productConstr = scalaDot(tpnme.Product) - def serializableConstr = scalaDot(tpnme.Serializable) + def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) setSymbol AnyRefClass + def scalaUnitConstr = scalaDot(tpnme.Unit) setSymbol UnitClass + def productConstr = scalaDot(tpnme.Product) setSymbol ProductRootClass + def serializableConstr = scalaDot(tpnme.Serializable) setSymbol SerializableClass def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree, abstractFun: Boolean = false): Tree = { val cls = if (abstractFun) @@ -149,22 +148,6 @@ abstract class TreeGen { None } - /** Cast `tree` to type `pt` */ - def mkCast(tree: Tree, pt: Type): Tree = { - debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase) - assert(!tree.tpe.isInstanceOf[MethodType], tree) - assert(!pt.typeSymbol.isPackageClass && !pt.typeSymbol.isPackageObjectClass, pt) - // called during (at least): typer, uncurry, explicitouter, cleanup. - // TODO: figure out the truth table for any/wrapInApply - // - the `any` flag seems to relate to erasure's adaptMember: "x.asInstanceOf[T] becomes x.$asInstanceOf[T]", - // where asInstanceOf is Any_asInstanceOf and $asInstanceOf is Object_asInstanceOf - // erasure will only unbox the value in a tree made by mkCast if `any && wrapInApply` - // - the `wrapInApply` flag need not be true if the tree will be adapted to have the empty argument list added before it gets to erasure - // in fact, I think it should be false for trees that will be type checked during typer - assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) - atPos(tree.pos)(mkAsInstanceOf(tree, pt, any = false, wrapInApply = true)) - } - /** Builds a reference with stable type to given symbol */ def mkAttributedStableRef(pre: Type, sym: Symbol): Tree = stabilize(mkAttributedRef(pre, sym)) @@ -268,25 +251,6 @@ abstract class TreeGen { case _ => Constant(null) } - def mkZeroContravariantAfterTyper(tp: Type): Tree = { - // contravariant -- for replacing an argument in a method call - // must use subtyping, as otherwise we miss types like `Any with Int` - val tree = - if (NullClass.tpe <:< tp) Literal(Constant(null)) - else if (UnitClass.tpe <:< tp) Literal(Constant()) - else if (BooleanClass.tpe <:< tp) Literal(Constant(false)) - else if (FloatClass.tpe <:< tp) Literal(Constant(0.0f)) - else if (DoubleClass.tpe <:< tp) Literal(Constant(0.0d)) - else if (ByteClass.tpe <:< tp) Literal(Constant(0.toByte)) - else if (ShortClass.tpe <:< tp) Literal(Constant(0.toShort)) - else if (IntClass.tpe <:< tp) Literal(Constant(0)) - else if (LongClass.tpe <:< tp) Literal(Constant(0L)) - else if (CharClass.tpe <:< tp) Literal(Constant(0.toChar)) - else mkCast(Literal(Constant(null)), tp) - - tree - } - /** Builds a tuple */ def mkTuple(elems: List[Tree]): Tree = if (elems.isEmpty) Literal(Constant()) diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala index 3252b970d1..769d7a9ed1 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/compiler/scala/reflect/internal/TreeInfo.scala @@ -440,15 +440,6 @@ abstract class TreeInfo { EmptyTree } - /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? - */ - def isPredefExpr(t: Tree) = t match { - case Ident(nme.Predef) => true - case Select(Ident(nme.scala_), nme.Predef) => true - case Select(Select(Ident(nme.ROOTPKG), nme.scala_), nme.Predef) => true - case _ => false - } - /** Does list of trees start with a definition of * a class of module with given name (ignoring imports) */ @@ -468,7 +459,7 @@ abstract class TreeInfo { // Top-level definition whose leading imports include Predef. def containsLeadingPredefImport(defs: List[Tree]): Boolean = defs match { case PackageDef(_, defs1) :: _ => containsLeadingPredefImport(defs1) - case Import(expr, _) :: rest => isPredefExpr(expr) || containsLeadingPredefImport(rest) + case Import(expr, _) :: rest => isReferenceToPredef(expr) || containsLeadingPredefImport(rest) case _ => false } @@ -479,7 +470,6 @@ abstract class TreeInfo { } ( isUnitInScala(body, nme.Predef) - || isUnitInScala(body, tpnme.ScalaObject) || containsLeadingPredefImport(List(body))) } diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index 2b1d833c73..f823110440 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/scala/reflect/internal/TreePrinters.scala @@ -242,6 +242,10 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => case Template(parents, self, body) => val currentOwner1 = currentOwner if (tree.symbol != NoSymbol) currentOwner = tree.symbol.owner +// if (parents exists isReferenceToAnyVal) { +// print("AnyVal") +// } +// else { printRow(parents, " with ") if (!body.isEmpty) { if (self.name != nme.WILDCARD) { @@ -253,6 +257,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => } printColumn(body, "", ";", "}") } +// } currentOwner = currentOwner1 case Block(stats, expr) => diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 54cc53aaac..9b1712b790 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -11,6 +11,18 @@ 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 + case Select(Ident(nme.scala_), Id) => true + case Select(Select(Ident(nme.ROOTPKG), nme.scala_), Id) => true + case _ => false + } + /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? + */ + def isReferenceToPredef(t: Tree) = isReferenceToScalaMember(t, nme.Predef) + def isReferenceToAnyVal(t: Tree) = isReferenceToScalaMember(t, tpnme.AnyVal) + // --- modifiers implementation --------------------------------------- /** @param privateWithin the qualifier for a private (a type name) @@ -122,11 +134,14 @@ trait Trees extends api.Trees { self: SymbolTable => } } - def substTreeSyms(pairs: (Symbol, Symbol)*): Tree = { - val list = pairs.toList - val subst = new TreeSymSubstituter(list map (_._1), list map (_._2)) - subst(tree) - } + def substTreeSyms(pairs: (Symbol, Symbol)*): Tree = + substTreeSyms(pairs.map(_._1).toList, pairs.map(_._2).toList) + + def substTreeSyms(from: List[Symbol], to: List[Symbol]): Tree = + new TreeSymSubstituter(from, to)(tree) + + def substTreeThis(clazz: Symbol, to: Tree): Tree = new ThisSubstituter(clazz, to) transform tree + def shallowDuplicate: Tree = new ShallowDuplicator(tree) transform tree def shortClass: String = tree.getClass.getName split "[.$]" last @@ -268,10 +283,16 @@ trait Trees extends api.Trees { self: SymbolTable => } } - private object posAssigner extends Traverser { + trait PosAssigner extends Traverser { + var pos: Position + } + protected[this] lazy val posAssigner: PosAssigner = new DefaultPosAssigner + + protected class DefaultPosAssigner extends PosAssigner { var pos: Position = _ override def traverse(t: Tree) { - if (t != EmptyTree && t.pos == NoPosition) { + if (t eq EmptyTree) () + else if (t.pos == NoPosition) { t.setPos(pos) super.traverse(t) // TODO: bug? shouldn't the traverse be outside of the if? // @PP: it's pruning whenever it encounters a node with a @@ -303,10 +324,14 @@ trait Trees extends api.Trees { self: SymbolTable => } class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser { - def changeOwner(tree: Tree) = { - if ((tree.isDef || tree.isInstanceOf[Function]) && - tree.symbol != NoSymbol && tree.symbol.owner == oldowner) - tree.symbol.owner = newowner + def changeOwner(tree: Tree) = tree match { + case Return(expr) => + if (tree.symbol == oldowner) + tree.symbol = newowner + case _: DefTree | _: Function => + if (tree.symbol != NoSymbol && tree.symbol.owner == oldowner) + tree.symbol.owner = newowner + case _ => } override def traverse(tree: Tree) { changeOwner(tree) @@ -342,6 +367,19 @@ trait Trees extends api.Trees { self: SymbolTable => override def toString = substituterString("Symbol", "Tree", from, to) } + /** Substitute clazz.this with `to`. `to` must be an attributed tree. + */ + class ThisSubstituter(clazz: Symbol, to: => Tree) extends Transformer { + val newtpe = to.tpe + override def transform(tree: Tree) = { + if (tree.tpe ne null) tree.tpe = tree.tpe.substThis(clazz, newtpe) + tree match { + case This(_) if tree.symbol == clazz => to + case _ => super.transform(tree) + } + } + } + class TypeMapTreeSubstituter(val typeMap: TypeMap) extends Traverser { override def traverse(tree: Tree) { if (tree.tpe ne null) diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index b7b7ca5840..2382413a9a 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -65,6 +65,8 @@ import util.Statistics._ // inst is the instantiation and constr is a list of bounds. case DeBruijnIndex(level, index) // for dependent method types: a type referring to a method parameter. + case ErasedValueType(tp) + // only used during erasure of derived value classes. */ trait Types extends api.Types { self: SymbolTable => @@ -410,6 +412,11 @@ trait Types extends api.Types { self: SymbolTable => * The empty list for all other types */ def parents: List[Type] = List() + /** For a class with nonEmpty parents, the first parent. + * Otherwise some specific fixed top type. + */ + def firstParent = if (parents.nonEmpty) parents.head else ObjectClass.tpe + /** For a typeref or single-type, the prefix of the normalized type (@see normalize). * NoType for all other types. */ def prefix: Type = NoType @@ -1418,14 +1425,14 @@ trait Types extends api.Types { self: SymbolTable => // override def isNullable: Boolean = // parents forall (p => p.isNullable && !p.typeSymbol.isAbstractType); - override def safeToString: String = - parents.mkString(" with ") + + override def safeToString: String = parentsString(parents) + ( (if (settings.debug.value || parents.isEmpty || (decls.elems ne null)) decls.mkString("{", "; ", "}") else "") + ) } protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = { - val period = tpe.baseTypeSeqPeriod; + val period = tpe.baseTypeSeqPeriod if (period != currentPeriod) { tpe.baseTypeSeqPeriod = currentPeriod if (!isValidForBaseClasses(period)) { @@ -1483,7 +1490,7 @@ trait Types extends api.Types { self: SymbolTable => else { //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG // optimized, since this seems to be performance critical - val superclazz = tpe.parents.head + val superclazz = tpe.firstParent var mixins = tpe.parents.tail val sbcs = superclazz.baseClasses var bcs = sbcs @@ -1530,7 +1537,7 @@ trait Types extends api.Types { self: SymbolTable => ) override def typeParams = - if (isHigherKinded) parents.head.typeParams + if (isHigherKinded) firstParent.typeParams else super.typeParams //@M may result in an invalid type (references to higher-order args become dangling ) @@ -2099,7 +2106,7 @@ trait Types extends api.Types { self: SymbolTable => !sym.isTypeParameter && pre.isTrivial && args.forall(_.isTrivial) override def isNotNull = - sym.isModuleClass || sym == NothingClass || isValueClass(sym) || super.isNotNull + sym.isModuleClass || sym == NothingClass || (sym isNonBottomSubClass NotNullClass) || super.isNotNull override def parents: List[Type] = { val cache = parentsCache @@ -2148,12 +2155,12 @@ trait Types extends api.Types { self: SymbolTable => ) else "" ) + private def finishPrefix(rest: String) = ( if (sym.isPackageClass) packagePrefix + rest else if (sym.isModuleClass) objectPrefix + rest else if (!sym.isInitialized) rest - else if (sym.isAnonymousClass && !phase.erasedTypes) - thisInfo.parents.mkString("", " with ", refinementString) + else if (sym.isAnonymousClass && !phase.erasedTypes) parentsString(thisInfo.parents) + refinementString else if (sym.isRefinementClass) "" + thisInfo else rest ) @@ -3088,6 +3095,17 @@ trait Types extends api.Types { self: SymbolTable => } } + abstract case class ErasedValueType(sym: Symbol) extends Type { + override def safeToString = sym.name+"$unboxed" + } + + final class UniqueErasedValueType(sym: Symbol) extends ErasedValueType(sym) with UniqueType + + object ErasedValueType { + def apply(sym: Symbol): Type = + unique(new UniqueErasedValueType(sym)) + } + /** A class representing an as-yet unevaluated type. */ abstract class LazyType extends Type { @@ -3234,11 +3252,21 @@ trait Types extends api.Types { self: SymbolTable => * comment or in the code? */ def intersectionType(tps: List[Type], owner: Symbol): Type = tps match { - case List(tp) => - tp - case _ => - refinedType(tps, owner) -/* + case tp :: Nil => tp + case _ => refinedType(tps, owner) + } + /** A creator for intersection type where intersections of a single type are + * replaced by the type itself. + */ + def intersectionType(tps: List[Type]): Type = tps match { + case tp :: Nil => tp + case _ => refinedType(tps, commonOwner(tps)) + } + +/**** This implementation to merge parents was checked in in commented-out + form and has languished unaltered for five years. I think we should + use it or lose it. + def merge(tps: List[Type]): List[Type] = tps match { case tp :: tps1 => val tps1a = tps1 filter (_.typeSymbol.==(tp.typeSymbol)) @@ -3253,14 +3281,6 @@ trait Types extends api.Types { self: SymbolTable => } refinedType(merge(tps), owner) */ - } - - /** A creator for intersection type where intersections of a single type are - * replaced by the type itself. */ - def intersectionType(tps: List[Type]): Type = tps match { - case List(tp) => tp - case _ => refinedType(tps, commonOwner(tps)) - } /** A creator for type applications */ def appliedType(tycon: Type, args: List[Type]): Type = @@ -3299,7 +3319,7 @@ trait Types extends api.Types { self: SymbolTable => } } - /** A creator for type parameterizations that strips empty type parameter lists. + /** A creator and extractor for type parameterizations that strips empty type parameter lists. * Use this factory method to indicate the type has kind * (it's a polymorphic value) * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty). * @@ -3308,9 +3328,18 @@ trait Types extends api.Types { self: SymbolTable => * can we instead say this is the canonical creator for polyTypes which * may or may not be poly? (It filched the standard "canonical creator" name.) */ - def polyType(tparams: List[Symbol], tpe: Type): Type = + 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 + def unapply(tpe: Type): Option[(List[Symbol], Type)] = tpe match { + case PolyType(tparams, restpe) => Some(tparams, restpe) + case _ => Some(List(), tpe) + } + } + + @deprecated("use GenPolyType(...) instead") + def polyType(params: List[Symbol], tpe: Type): Type = GenPolyType(params, tpe) /** A creator for anonymous type functions, where the symbol for the type function still needs to be created. * @@ -3762,6 +3791,7 @@ trait Types extends api.Types { self: SymbolTable => case WildcardType => tp case NoType => tp case NoPrefix => tp + case ErasedSingleType(sym) => tp */ case _ => tp @@ -4519,9 +4549,7 @@ trait Types extends api.Types { self: SymbolTable => else { commonOwnerMap.clear() tps foreach (commonOwnerMap traverse _) - val result = if (commonOwnerMap.result ne null) commonOwnerMap.result else NoSymbol - debuglog(tps.mkString("commonOwner(", ", ", ") == " + result)) - result + if (commonOwnerMap.result ne null) commonOwnerMap.result else NoSymbol } } @@ -5419,8 +5447,7 @@ trait Types extends api.Types { self: SymbolTable => case NullClass => tp2 match { case TypeRef(_, sym2, _) => - sym2.isClass && (sym2 isNonBottomSubClass ObjectClass) && - !(tp2.normalize.typeSymbol isNonBottomSubClass NotNullClass) + containsNull(sym2) case _ => isSingleType(tp2) && tp1 <:< tp2.widen } @@ -5451,6 +5478,11 @@ trait Types extends api.Types { self: SymbolTable => firstTry } + private def containsNull(sym: Symbol): Boolean = + sym.isClass && sym != NothingClass && + !(sym isNonBottomSubClass AnyValClass) && + !(sym isNonBottomSubClass NotNullClass) + /** Are `tps1` and `tps2` lists of equal length such that all elements * of `tps1` conform to corresponding elements of `tps2`? */ @@ -5462,7 +5494,7 @@ trait Types extends api.Types { self: SymbolTable => */ def specializesSym(tp: Type, sym: Symbol): Boolean = tp.typeSymbol == NothingClass || - tp.typeSymbol == NullClass && (sym.owner isSubClass ObjectClass) || + tp.typeSymbol == NullClass && containsNull(sym.owner) || (tp.nonPrivateMember(sym.name).alternatives exists (alt => sym == alt || specializesSym(tp.narrow, alt, sym.owner.thisType, sym))) @@ -5853,14 +5885,6 @@ trait Types extends api.Types { self: SymbolTable => loop(initialBTSes) } - // @AM the following problem is solved by elimHOTparams in lublist - // @PP lubLists gone bad: lubList(List( - // List(scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq], ScalaObject, java.lang.Object, Any) - // List(scala.collection.generic.GenericCompanion[scala.collection.mutable.Seq], ScalaObject, java.lang.Object, Any) - // )) == ( - // List(scala.collection.generic.GenericCompanion[Seq**[Any]**], ScalaObject, java.lang.Object, Any) - // ) - /** The minimal symbol (wrt Symbol.isLess) of a list of types */ private def minSym(tps: List[Type]): Symbol = (tps.head.typeSymbol /: tps.tail) { @@ -6310,7 +6334,7 @@ trait Types extends api.Types { self: SymbolTable => } else { val args = argss map (_.head) if (args.tail forall (_ =:= args.head)) Some(typeRef(pre, sym, List(args.head))) - else if (args exists (arg => isValueClass(arg.typeSymbol))) Some(ObjectClass.tpe) + else if (args exists (arg => isPrimitiveValueClass(arg.typeSymbol))) Some(ObjectClass.tpe) else Some(typeRef(pre, sym, List(lub(args)))) } } @@ -6441,7 +6465,9 @@ trait Types extends api.Types { self: SymbolTable => // but that would be a big change. Left for further refactoring. /** An exception for cyclic references from which we can recover */ case class RecoverableCyclicReference(sym: Symbol) - extends TypeError("illegal cyclic reference involving " + sym) + extends TypeError("illegal cyclic reference involving " + sym) { + if (settings.debug.value) printStackTrace() + } class NoCommonType(tps: List[Type]) extends Throwable( "lub/glb of incompatible types: " + tps.mkString("", " and ", "")) with ControlThrowable diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index 34163d54f8..f1ec64bda9 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala @@ -229,6 +229,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { // (3) Try as a nested object symbol. nestedObjectSymbol orElse { // (4) Otherwise, fail. + //System.err.println("missing "+name+" in "+owner+"/"+owner.id+" "+owner.info.decls) adjust(errorMissingRequirement(name, owner)) } } diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index d59fc6d564..e87de8db80 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -2,6 +2,8 @@ package scala.reflect package internal package transform +import Flags.PARAMACCESSOR + trait Erasure { val global: SymbolTable @@ -63,49 +65,62 @@ trait Erasure { if (cls.owner.isClass) cls.owner.tpe else pre // why not cls.isNestedClass? } + def underlyingOfValueClass(clazz: Symbol): Type = + clazz.firstParamAccessor.tpe.resultType + abstract class ErasureMap extends TypeMap { def mergeParents(parents: List[Type]): Type - def apply(tp: Type): Type = { - tp match { - case ConstantType(_) => - tp - case st: SubType => - apply(st.supertype) - case TypeRef(pre, sym, args) => - if (sym == ArrayClass) - if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe - else if (args.head.typeSymbol.isBottomClass) ObjectArray - else typeRef(apply(pre), sym, args map this) - else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) erasedTypeRef(ObjectClass) - else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) - else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) - else if (sym.isClass) typeRef(apply(rebindInnerClass(pre, sym)), sym, List()) // #2585 - else apply(sym.info) // alias type or abstract type - case PolyType(tparams, restpe) => - apply(restpe) - case ExistentialType(tparams, restpe) => - apply(restpe) - case mt @ MethodType(params, restpe) => - MethodType( - cloneSymbolsAndModify(params, ErasureMap.this), - if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) - // this replaces each typeref that refers to an argument - // by the type `p.tpe` of the actual argument p (p in params) - else apply(mt.resultType(params map (_.tpe)))) - case RefinedType(parents, decls) => - apply(mergeParents(parents)) - case AnnotatedType(_, atp, _) => - apply(atp) - case ClassInfoType(parents, decls, clazz) => - ClassInfoType( - if (clazz == ObjectClass || isValueClass(clazz)) Nil - else if (clazz == ArrayClass) List(erasedTypeRef(ObjectClass)) - else removeDoubleObject(parents map this), - decls, clazz) - case _ => - mapOver(tp) - } + def eraseNormalClassRef(pre: Type, clazz: Symbol): Type = + typeRef(apply(rebindInnerClass(pre, clazz)), clazz, List()) // #2585 + + protected def eraseDerivedValueClassRef(clazz: Symbol): Type = + scalaErasure(underlyingOfValueClass(clazz)) + + def apply(tp: Type): Type = tp match { + case ConstantType(_) => + tp + case st: SubType => + apply(st.supertype) + case TypeRef(pre, sym, args) => + if (sym == ArrayClass) + if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe + else if (args.head.typeSymbol.isBottomClass) ObjectArray + else typeRef(apply(pre), sym, args map applyInArray) + else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) erasedTypeRef(ObjectClass) + else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) + else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) + else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(sym) + else if (sym.isClass) eraseNormalClassRef(pre, sym) + else apply(sym.info) // alias type or abstract type + case PolyType(tparams, restpe) => + apply(restpe) + case ExistentialType(tparams, restpe) => + apply(restpe) + case mt @ MethodType(params, restpe) => + MethodType( + cloneSymbolsAndModify(params, ErasureMap.this), + if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) + // this replaces each typeref that refers to an argument + // by the type `p.tpe` of the actual argument p (p in params) + else apply(mt.resultType(params map (_.tpe)))) + case RefinedType(parents, decls) => + apply(mergeParents(parents)) + case AnnotatedType(_, atp, _) => + apply(atp) + case ClassInfoType(parents, decls, clazz) => + ClassInfoType( + if (clazz == ObjectClass || isPrimitiveValueClass(clazz)) Nil + else if (clazz == ArrayClass) List(erasedTypeRef(ObjectClass)) + else removeLaterObjects(parents map this), + decls, clazz) + case _ => + mapOver(tp) + } + + def applyInArray(tp: Type): Type = tp match { + case TypeRef(pre, sym, args) if (sym.isDerivedValueClass) => eraseNormalClassRef(pre, sym) + case _ => apply(tp) } } @@ -138,17 +153,41 @@ trait Erasure { * parents |Ps|, but with duplicate references of Object removed. * - for all other types, the type itself (with any sub-components erased) */ - def erasure(sym: Symbol, tp: Type): Type = { - if (sym != NoSymbol && sym.enclClass.isJavaDefined) { - val res = javaErasure(tp) - if (verifyJavaErasure && sym.isMethod) { - val old = scalaErasure(tp) - if (!(res =:= old)) - log("Identified divergence between java/scala erasure:\n scala: " + old + "\n java: " + res) - } - res + def erasure(sym: Symbol): ErasureMap = + if (sym == NoSymbol || !sym.enclClass.isJavaDefined) scalaErasure + else if (verifyJavaErasure && sym.isMethod) verifiedJavaErasure + else javaErasure + + /** This is used as the Scala erasure during the erasure phase itself + * It differs from normal erasure in that value classes are erased to ErasedValueTypes which + * are then later converted to the underlying parameter type in phase posterasure. + */ + def specialErasure(sym: Symbol)(tp: Type): Type = + if (sym != NoSymbol && sym.enclClass.isJavaDefined) + erasure(sym)(tp) + else if (sym.isTerm && sym.owner.isDerivedValueClass) + specialErasureAvoiding(sym.owner, tp) + else if (sym.isValue && sym.owner.isMethodWithExtension) + specialErasureAvoiding(sym.owner.owner, tp) + else + specialScalaErasure(tp) + + def specialErasureAvoiding(clazz: Symbol, tpe: Type): Type = { + tpe match { + case PolyType(tparams, restpe) => + specialErasureAvoiding(clazz, restpe) + case ExistentialType(tparams, restpe) => + specialErasureAvoiding(clazz, restpe) + case mt @ MethodType(params, restpe) => + MethodType( + cloneSymbolsAndModify(params, specialErasureAvoiding(clazz, _)), + if (restpe.typeSymbol == UnitClass) erasedTypeRef(UnitClass) + else specialErasureAvoiding(clazz, (mt.resultType(params map (_.tpe))))) + case TypeRef(pre, `clazz`, args) => + typeRef(pre, clazz, List()) + case _ => + specialScalaErasure(tpe) } - else scalaErasure(tp) } /** Scala's more precise erasure than java's is problematic as follows: @@ -163,7 +202,7 @@ trait Erasure { * For this reason and others (such as distinguishing constructors from other methods) * erasure is now (Symbol, Type) => Type rather than Type => Type. */ - object scalaErasure extends ErasureMap { + class ScalaErasureMap extends ErasureMap { /** In scala, calculate a useful parent. * An intersection such as `Object with Trait` erases to Trait. */ @@ -171,6 +210,37 @@ trait Erasure { intersectionDominator(parents) } + class JavaErasureMap extends ErasureMap { + /** In java, always take the first parent. + * An intersection such as `Object with Trait` erases to Object. + */ + def mergeParents(parents: List[Type]): Type = + if (parents.isEmpty) ObjectClass.tpe + else parents.head + } + + object scalaErasure extends ScalaErasureMap + + /** This is used as the Scala erasure during the erasure phase itself + * It differs from normal erasure in that value classes are erased to ErasedValueTypes which + * are then later converted to the underlying parameter type in phase posterasure. + */ + object specialScalaErasure extends ScalaErasureMap { + override def eraseDerivedValueClassRef(clazz: Symbol): Type = ErasedValueType(clazz) + } + + object javaErasure extends JavaErasureMap + + object verifiedJavaErasure extends JavaErasureMap { + override def apply(tp: Type): Type = { + val res = javaErasure(tp) + val old = scalaErasure(tp) + if (!(res =:= old)) + log("Identified divergence between java/scala erasure:\n scala: " + old + "\n java: " + res) + res + } + } + /** The intersection dominator (SLS 3.7) of a list of types is computed as follows. * * - If the list contains one or more occurrences of scala.Array with @@ -206,26 +276,9 @@ trait Erasure { } } - object javaErasure extends ErasureMap { - /** In java, always take the first parent. - * An intersection such as `Object with Trait` erases to Object. - */ - def mergeParents(parents: List[Type]): Type = - if (parents.isEmpty) ObjectClass.tpe - else parents.head - } - /** Type reference after erasure */ def erasedTypeRef(sym: Symbol): Type = - typeRef(erasure(sym, sym.owner.tpe), sym, List()) - - /** Remove duplicate references to class Object in a list of parent classes */ - private def removeDoubleObject(tps: List[Type]): List[Type] = tps match { - case List() => List() - case tp :: tps1 => - if (tp.typeSymbol == ObjectClass) tp :: tps1.filter(_.typeSymbol != ObjectClass) - else tp :: removeDoubleObject(tps1) - } + typeRef(erasure(sym)(sym.owner.tpe), sym, Nil) /** The symbol's erased info. This is the type's erasure, except for the following symbols: * @@ -239,25 +292,25 @@ trait Erasure { if (sym == Object_asInstanceOf) sym.info else if (sym == Object_isInstanceOf || sym == ArrayClass) - PolyType(sym.info.typeParams, erasure(sym, sym.info.resultType)) + PolyType(sym.info.typeParams, specialErasure(sym)(sym.info.resultType)) else if (sym.isAbstractType) TypeBounds(WildcardType, WildcardType) else if (sym.isTerm && sym.owner == ArrayClass) { if (sym.isClassConstructor) tp match { case MethodType(params, TypeRef(pre, sym1, args)) => - MethodType(cloneSymbolsAndModify(params, erasure(sym, _)), - typeRef(erasure(sym, pre), sym1, args)) + MethodType(cloneSymbolsAndModify(params, specialErasure(sym)), + typeRef(specialErasure(sym)(pre), sym1, args)) } else if (sym.name == nme.apply) tp else if (sym.name == nme.update) (tp: @unchecked) match { case MethodType(List(index, tvar), restpe) => - MethodType(List(index.cloneSymbol.setInfo(erasure(sym, index.tpe)), tvar), + MethodType(List(index.cloneSymbol.setInfo(specialErasure(sym)(index.tpe)), tvar), erasedTypeRef(UnitClass)) } - else erasure(sym, tp) + else specialErasure(sym)(tp) } else if ( sym.owner != NoSymbol && sym.owner.owner == ArrayClass && @@ -267,7 +320,7 @@ trait Erasure { // symbol here tp } else { - erasure(sym, tp) + specialErasure(sym)(tp) } } } diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala index 4c49c0221f..89fd6bab64 100644 --- a/src/compiler/scala/reflect/runtime/JavaToScala.scala +++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala @@ -186,7 +186,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => } finally { parentsLevel -= 1 } - clazz setInfo polyType(tparams, new ClassInfoType(parents, newScope, clazz)) + clazz setInfo GenPolyType(tparams, new ClassInfoType(parents, newScope, clazz)) if (module != NoSymbol) { module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass) } @@ -534,7 +534,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => } private def setMethType(meth: Symbol, tparams: List[Symbol], paramtpes: List[Type], restpe: Type) = { - meth setInfo polyType(tparams, MethodType(meth.owner.newSyntheticValueParams(paramtpes map objToAny), restpe)) + meth setInfo GenPolyType(tparams, MethodType(meth.owner.newSyntheticValueParams(paramtpes map objToAny), restpe)) } /** @@ -572,7 +572,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => val tparams = jconstr.getTypeParameters.toList map createTypeParameter val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala setMethType(constr, tparams, paramtpes, clazz.tpe) - constr setInfo polyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe)) + constr setInfo GenPolyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe)) copyAnnotations(constr, jconstr) constr } diff --git a/src/compiler/scala/reflect/runtime/ScalaToJava.scala b/src/compiler/scala/reflect/runtime/ScalaToJava.scala index 405a00de8d..87cdd11652 100644 --- a/src/compiler/scala/reflect/runtime/ScalaToJava.scala +++ b/src/compiler/scala/reflect/runtime/ScalaToJava.scala @@ -28,7 +28,7 @@ trait ScalaToJava extends ConversionUtil { self: SymbolTable => def classToJava(clazz: Symbol): jClass[_] = classCache.toJava(clazz) { def noClass = throw new ClassNotFoundException("no Java class corresponding to "+clazz+" found") //println("classToJava "+clazz+" "+clazz.owner+" "+clazz.owner.isPackageClass)//debug - if (clazz.isValueClass) + if (clazz.isPrimitiveValueClass) valueClassToJavaType(clazz) else if (clazz == ArrayClass) noClass diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index f52662ce6f..8cc4d5f788 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -59,7 +59,7 @@ trait ToolBoxes extends { self: Universe => def wrapInObject(expr: Tree, fvs: List[Symbol]): ModuleDef = { val obj = EmptyPackageClass.newModule(nextWrapperModuleName()) - val minfo = ClassInfoType(List(ObjectClass.tpe, ScalaObjectClass.tpe), newScope, obj.moduleClass) + val minfo = ClassInfoType(List(ObjectClass.tpe), newScope, obj.moduleClass) obj.moduleClass setInfo minfo obj setInfo obj.moduleClass.tpe val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName)) diff --git a/src/compiler/scala/reflect/runtime/Universe.scala b/src/compiler/scala/reflect/runtime/Universe.scala index 700f819226..324fee87ab 100644 --- a/src/compiler/scala/reflect/runtime/Universe.scala +++ b/src/compiler/scala/reflect/runtime/Universe.scala @@ -37,6 +37,12 @@ class Universe extends SymbolTable { type Position = String // source file? val NoPosition = "" + definitions.AnyValClass // force it. + // establish root association to avoid cyclic dependency errors later classToScala(classOf[java.lang.Object]).initialize + +// println("initializing definitions") + definitions.init() + } diff --git a/src/compiler/scala/tools/cmd/gen/AnyVals.scala b/src/compiler/scala/tools/cmd/gen/AnyVals.scala index 7c9599dc45..0869350dd3 100644 --- a/src/compiler/scala/tools/cmd/gen/AnyVals.scala +++ b/src/compiler/scala/tools/cmd/gen/AnyVals.scala @@ -182,7 +182,7 @@ trait AnyValReps { def classLines: List[String] def objectLines: List[String] def commonClassLines = List( - "def getClass(): Class[@name@]" + "override def getClass(): Class[@name@]" ) def lcname = name.toLowerCase @@ -429,7 +429,7 @@ def &(x: Boolean): Boolean = sys.error("stub") */ def ^(x: Boolean): Boolean = sys.error("stub") -def getClass(): Class[Boolean] = sys.error("stub") +override def getClass(): Class[Boolean] = sys.error("stub") """.trim.lines.toList def objectLines = interpolate(allCompanions).lines.toList @@ -443,7 +443,7 @@ def getClass(): Class[Boolean] = sys.error("stub") */ """ def classLines = List( - """def getClass(): Class[Unit] = sys.error("stub")""" + """override def getClass(): Class[Unit] = sys.error("stub")""" ) def objectLines = interpolate(allCompanions).lines.toList diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 552479bc0b..9ccd0c28db 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -44,6 +44,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb with symtab.Positions { override def settings = currentSettings + + import definitions.{ findNamedMember, findMemberFromRoot } // alternate constructors ------------------------------------------ @@ -456,141 +458,155 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb // phaseName = "superaccessors" object superAccessors extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("typer") + val runsAfter = List("typer") val runsRightAfter = None } with SuperAccessors + // phaseName = "extmethods" + object extensionMethods extends { + val global: Global.this.type = Global.this + val runsAfter = List("superaccessors") + val runsRightAfter = None + } with ExtensionMethods + // phaseName = "pickler" object pickler extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("superaccessors") + val runsAfter = List("extmethods") val runsRightAfter = None } with Pickler // phaseName = "refchecks" override object refChecks extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("pickler") + val runsAfter = List("pickler") val runsRightAfter = None } with RefChecks // phaseName = "uncurry" override object uncurry extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("refchecks") + val runsAfter = List("refchecks") val runsRightAfter = None } with UnCurry // phaseName = "tailcalls" object tailCalls extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("uncurry") + val runsAfter = List("uncurry") val runsRightAfter = None } with TailCalls // phaseName = "explicitouter" object explicitOuter extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("tailcalls") + val runsAfter = List("tailcalls") val runsRightAfter = None } with ExplicitOuter // phaseName = "specialize" object specializeTypes extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("") + val runsAfter = List("") val runsRightAfter = Some("tailcalls") } with SpecializeTypes // phaseName = "erasure" override object erasure extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("explicitouter") + val runsAfter = List("explicitouter") val runsRightAfter = Some("explicitouter") } with Erasure + // phaseName = "posterasure" + object postErasure extends { + val global: Global.this.type = Global.this + val runsAfter = List("erasure") + val runsRightAfter = Some("erasure") + } with PostErasure + // phaseName = "lazyvals" object lazyVals extends { final val FLAGS_PER_WORD = 32 val global: Global.this.type = Global.this - val runsAfter = List[String]("erasure") + val runsAfter = List("erasure") val runsRightAfter = None } with LazyVals // phaseName = "lambdalift" object lambdaLift extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("lazyvals") + val runsAfter = List("lazyvals") val runsRightAfter = None } with LambdaLift // phaseName = "constructors" object constructors extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("lambdalift") + val runsAfter = List("lambdalift") val runsRightAfter = None } with Constructors // phaseName = "flatten" object flatten extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("constructors") + val runsAfter = List("constructors") val runsRightAfter = None } with Flatten // phaseName = "mixin" object mixer extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("flatten", "constructors") + val runsAfter = List("flatten", "constructors") val runsRightAfter = None } with Mixin // phaseName = "cleanup" object cleanup extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("mixin") + val runsAfter = List("mixin") val runsRightAfter = None } with CleanUp // phaseName = "icode" object genicode extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("cleanup") + val runsAfter = List("cleanup") val runsRightAfter = None } with GenICode // phaseName = "inliner" object inliner extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("icode") + val runsAfter = List("icode") val runsRightAfter = None } with Inliners // phaseName = "inlineExceptionHandlers" object inlineExceptionHandlers extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("inliner") + val runsAfter = List("inliner") val runsRightAfter = None } with InlineExceptionHandlers // phaseName = "closelim" object closureElimination extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("inlineExceptionHandlers") + val runsAfter = List("inlineExceptionHandlers") val runsRightAfter = None } with ClosureElimination // phaseName = "dce" object deadCode extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("closelim") + val runsAfter = List("closelim") val runsRightAfter = None } with DeadCodeElimination // phaseName = "jvm" object genJVM extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("dce") + val runsAfter = List("dce") val runsRightAfter = None } with GenJVM @@ -606,7 +622,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb object terminal extends { val global: Global.this.type = Global.this val phaseName = "terminal" - val runsAfter = List[String]("jvm", "msil") + val runsAfter = List("jvm", "msil") val runsRightAfter = None } with SubComponent { private var cache: Option[GlobalPhase] = None @@ -660,6 +676,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb analyzer.packageObjects -> "load package objects", analyzer.typerFactory -> "the meat and potatoes: type the trees", superAccessors -> "add super accessors in traits and nested classes", + extensionMethods -> "add extension methods for inline classes", pickler -> "serialize symbol tables", refChecks -> "reference/override checking, translate nested objects", uncurry -> "uncurry, translate function values to anonymous classes", @@ -667,6 +684,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb specializeTypes -> "@specialized-driven class and method specialization", explicitOuter -> "this refs to outer pointers, translate patterns", erasure -> "erase types, add interfaces for traits", + postErasure -> "clean up erased inline classes", lazyVals -> "allocate bitmaps, translate lazy vals into lazified defs", lambdaLift -> "move nested functions to top level", constructors -> "move field definitions into constructors", @@ -1102,6 +1120,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb val namerPhase = phaseNamed("namer") // val packageobjectsPhase = phaseNamed("packageobjects") val typerPhase = phaseNamed("typer") + val inlineclassesPhase = phaseNamed("inlineclasses") // val superaccessorsPhase = phaseNamed("superaccessors") val picklerPhase = phaseNamed("pickler") val refchecksPhase = phaseNamed("refchecks") @@ -1433,7 +1452,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** * Re-orders the source files to - * 1. ScalaObject + * 1. This Space Intentionally Left Blank * 2. LowPriorityImplicits / EmbeddedControls (i.e. parents of Predef) * 3. the rest * @@ -1461,7 +1480,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb def rank(f: SourceFile) = { if (f.file.container.name != "scala") goLast else f.file.name match { - case "ScalaObject.scala" => 1 case "LowPriorityImplicits.scala" => 2 case "StandardEmbeddings.scala" => 2 case "EmbeddedControls.scala" => 2 @@ -1478,21 +1496,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb afterPhase(phase) { currentRun.units foreach (treePrinter.print(_)) } } - private def findMemberFromRoot(fullName: Name): Symbol = { - val segs = nme.segments(fullName.toString, fullName.isTermName) - if (segs.isEmpty) NoSymbol - else findNamedMember(segs.tail, definitions.RootClass.info member segs.head) - } - - private def findNamedMember(fullName: Name, root: Symbol): Symbol = { - val segs = nme.segments(fullName.toString, fullName.isTermName) - if (segs.isEmpty || segs.head != root.simpleName) NoSymbol - else findNamedMember(segs.tail, root) - } - private def findNamedMember(segs: List[Name], root: Symbol): Symbol = - if (segs.isEmpty) root - else findNamedMember(segs.tail, root.info member segs.head) - /** We resolve the class/object ambiguity by passing a type/term name. */ def showDef(fullName: Name, declsOnly: Boolean, ph: Phase) = { diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index 6a6379cca2..678f7b3028 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -19,6 +19,8 @@ import scala.collection.mutable */ trait DocComments { self: Global => + var cookedDocComments = Map[Symbol, String]() + def reporter: Reporter /** The raw doc comment map */ @@ -50,21 +52,29 @@ trait DocComments { self: Global => else sym.owner.ancestors map (sym overriddenSymbol _) filter (_ != NoSymbol) } - /** The raw doc comment of symbol `sym`, minus @usecase and @define sections, augmented by + /** The raw doc comment of symbol `sym`, minus usecase and define sections, augmented by * missing sections of an inherited doc comment. * If a symbol does not have a doc comment but some overridden version of it does, * the doc comment of the overridden version is copied instead. */ - def cookedDocComment(sym: Symbol, docStr: String = ""): String = { - val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse "" - else DocComment(docStr).template - superComment(sym) match { - case None => - ownComment - case Some(sc) => - if (ownComment == "") sc - else merge(sc, ownComment, sym) - } + def cookedDocComment(sym: Symbol, docStr: String = ""): String = cookedDocComments.get(sym) match { + case Some(comment) => + comment + case None => + val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse "" + else DocComment(docStr).template + val comment = superComment(sym) match { + case None => + if (ownComment.indexOf("@inheritdoc") != -1) + reporter.warning(sym.pos, "The comment for " + sym + + " contains @inheritdoc, but no parent comment is available to inherit from.") + ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>") + case Some(sc) => + if (ownComment == "") sc + else expandInheritdoc(sc, merge(sc, ownComment, sym), sym) + } + cookedDocComments += (sym -> comment) + comment } /** The cooked doc comment of symbol `sym` after variable expansion, or "" if missing. @@ -99,10 +109,18 @@ trait DocComments { self: Global => */ def useCases(sym: Symbol, site: Symbol): List[(Symbol, String, Position)] = { def getUseCases(dc: DocComment) = { - for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield - (defn, - expandVariables(merge(cookedDocComment(sym), uc.comment.raw, defn), sym, site), - uc.pos) + val fullSigComment = cookedDocComment(sym) + for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield { + // use cases comments go through a series of transformations: + // 1 - filling in missing sections from the full signature + // 2 - expanding explicit inheritance @inheritdoc tags + // 3 - expanding variables like $COLL + val useCaseCommentRaw = uc.comment.raw + val useCaseCommentMerged = merge(fullSigComment, useCaseCommentRaw, defn) + val useCaseCommentInheritdoc = expandInheritdoc(fullSigComment, useCaseCommentMerged, sym) + val useCaseCommentVariables = expandVariables(useCaseCommentInheritdoc, sym, site) + (defn, useCaseCommentVariables, uc.pos) + } } getDocComment(sym) map getUseCases getOrElse List() } @@ -201,6 +219,80 @@ trait DocComments { self: Global => } } + /** + * Expand inheritdoc tags + * - for the main comment we transform the inheritdoc into the super variable, + * and the variable expansion can expand it further + * - for the param, tparam and throws sections we must replace comments on the spot + * + * This is done separately, for two reasons: + * 1. It takes longer to run compared to merge + * 2. The inheritdoc annotation should not be used very often, as building the comment from pieces severely + * impacts performance + */ + def expandInheritdoc(src: String, dst: String, sym: Symbol): String = + if (dst.indexOf("@inheritdoc") == -1) + dst + else { + val srcSections = tagIndex(src) + val dstSections = tagIndex(dst) + val srcTagMap = sectionTagMap(src, srcSections) + val srcNamedParams = Map() + + ("@param" -> paramDocs(src, "@param", srcSections)) + + ("@tparam" -> paramDocs(src, "@tparam", srcSections)) + + ("@throws" -> paramDocs(src, "@throws", srcSections)) + + val out = new StringBuilder + + def replaceInheritdoc(src: String, dst: String) = + if (dst.indexOf("@inheritdoc") == -1) + dst + else + dst.replaceAllLiterally("@inheritdoc", src) + + def getSourceSection(section: (Int, Int)): String = { + + def getSectionHeader = extractSectionTag(dst, section) match { + case param@("@param"|"@tparam"|"@throws") => param + " " + extractSectionParam(dst, section) + case other => other + } + + def sectionString(param: String, paramMap: Map[String, (Int, Int)]): String = + paramMap.get(param) match { + case Some(section) => + // Cleanup the section tag and parameter + val sectionTextBounds = extractSectionText(src, section) + cleanupSectionText(src.substring(sectionTextBounds._1, sectionTextBounds._2)) + case None => + reporter.info(sym.pos, "The \"" + getSectionHeader + "\" annotation of the " + sym + + " comment contains @inheritdoc, but the corresponding section in the parent is not defined.", true) + "<invalid inheritdoc annotation>" + } + + dst.substring(section._1, section._1 + 7) match { + case param@("@param "|"@tparam"|"@throws") => sectionString(extractSectionParam(dst, section), srcNamedParams(param.trim)) + case _ => sectionString(extractSectionTag(dst, section), srcTagMap) + } + } + + def mainComment(str: String, sections: List[(Int, Int)]): String = + if (str.trim.length > 3) + str.trim.substring(3, startTag(str, sections)) + else + "" + + // Append main comment + out.append("/**") + out.append(replaceInheritdoc(mainComment(src, srcSections), mainComment(dst, dstSections))) + + // Append sections + for (section <- dstSections) + out.append(replaceInheritdoc(getSourceSection(section), dst.substring(section._1, section._2))) + + out.append("*/") + out.toString + } + /** Maps symbols to the variable -> replacement maps that are defined * in their doc comments */ diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index d7159c5fa8..6d95b6ffdd 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -263,6 +263,22 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { ) } + /** Cast `tree` to type `pt` by creating + * one of the calls of the form + * + * x.asInstanceOf[`pt`] up to phase uncurry + * x.asInstanceOf[`pt`]() if after uncurry but before erasure + * x.$asInstanceOf[`pt`]() if at or after erasure + */ + def mkCast(tree: Tree, pt: Type): Tree = { + debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase) + assert(!tree.tpe.isInstanceOf[MethodType], tree) + assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) + atPos(tree.pos) { + mkAsInstanceOf(tree, pt, any = !phase.next.erasedTypes, wrapInApply = isAtPhaseAfter(currentRun.uncurryPhase)) + } + } + /** Generate a cast for tree Tree representing Array with * elem type elemtp to expected type pt. */ @@ -272,6 +288,25 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { else mkCast(tree, pt) + def mkZeroContravariantAfterTyper(tp: Type): Tree = { + // contravariant -- for replacing an argument in a method call + // must use subtyping, as otherwise we miss types like `Any with Int` + val tree = + if (NullClass.tpe <:< tp) Literal(Constant(null)) + else if (UnitClass.tpe <:< tp) Literal(Constant()) + else if (BooleanClass.tpe <:< tp) Literal(Constant(false)) + else if (FloatClass.tpe <:< tp) Literal(Constant(0.0f)) + else if (DoubleClass.tpe <:< tp) Literal(Constant(0.0d)) + else if (ByteClass.tpe <:< tp) Literal(Constant(0.toByte)) + else if (ShortClass.tpe <:< tp) Literal(Constant(0.toShort)) + else if (IntClass.tpe <:< tp) Literal(Constant(0)) + else if (LongClass.tpe <:< tp) Literal(Constant(0L)) + else if (CharClass.tpe <:< tp) Literal(Constant(0.toChar)) + else mkCast(Literal(Constant(null)), tp) + + tree + } + /** Translate names in Select/Ident nodes to type names. */ def convertToTypeName(tree: Tree): Option[RefTree] = tree match { diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index b16b3c89a0..9f361e5bcc 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -6,6 +6,7 @@ package scala.tools.nsc package ast +import reflect.internal.HasFlags import reflect.internal.Flags._ import symtab._ @@ -41,4 +42,14 @@ abstract class TreeInfo extends reflect.internal.TreeInfo { case ClassDef(_, `name`, _, _) :: Nil => true case _ => super.firstDefinesClassOrObject(trees, name) } + + def isInterface(mods: HasFlags, body: List[Tree]) = + mods.hasTraitFlag && (body forall isInterfaceMember) + + def isAllowedInUniversalTrait(stat: Tree): Boolean = stat match { + case _: ValDef => false + case Import(_, _) | EmptyTree => true + case _: DefTree => true + case _ => false + } } diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index ad87889145..43c231cf2d 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -16,6 +16,47 @@ import scala.reflect.internal.Flags.TRAIT trait Trees extends reflect.internal.Trees { self: Global => + def treeLine(t: Tree): String = + if (t.pos.isDefined && t.pos.isRange) t.pos.lineContent.drop(t.pos.column - 1).take(t.pos.end - t.pos.start + 1) + else t.summaryString + + def treeStatus(t: Tree, enclosingTree: Tree = null) = { + val parent = if (enclosingTree eq null) " " else " P#%5s".format(enclosingTree.id) + + "[L%4s%8s] #%-6s %-15s %-10s // %s".format(t.pos.safeLine, parent, t.id, t.pos.show, t.shortClass, treeLine(t)) + } + def treeSymStatus(t: Tree) = { + val line = if (t.pos.isDefined) "line %-4s".format(t.pos.safeLine) else " " + "#%-5s %s %-10s // %s".format(t.id, line, t.shortClass, + if (t.symbol ne NoSymbol) "(" + t.symbol.fullLocationString + ")" + else treeLine(t) + ) + } + + class ValidatingPosAssigner extends PosAssigner { + var pos: Position = _ + override def traverse(t: Tree) { + if (t eq EmptyTree) () + else if (t.pos == NoPosition) super.traverse(t setPos pos) + else if (globalPhase.id <= currentRun.picklerPhase.id) { + // When we prune due to encountering a position, traverse the + // pruned children so we can warn about those lacking positions. + t.children foreach { c => + if ((c eq EmptyTree) || (c eq emptyValDef)) () + else if (c.pos == NoPosition) { + reporter.warning(t.pos, " Positioned tree has unpositioned child in phase " + globalPhase) + inform("parent: " + treeSymStatus(t)) + inform(" child: " + treeSymStatus(c) + "\n") + } + } + } + } + } + + override protected[this] lazy val posAssigner: PosAssigner = + if (settings.Yrangepos.value && settings.debug.value || settings.Yposdebug.value) new ValidatingPosAssigner + else new DefaultPosAssigner + // --- additional cases -------------------------------------------------------- /** Only used during parsing */ case class Parens(args: List[Tree]) extends Tree @@ -34,6 +75,12 @@ trait Trees extends reflect.internal.Trees { self: Global => case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type) extends TermTree with RefTree + /** Derived value class injection (equivalent to: new C(arg) after easure); only used during erasure + * The class C is stored as the symbol of the tree node. + */ + case class InjectDerivedValue(arg: Tree) + extends SymTree + /** emitted by typer, eliminated by refchecks */ case class TypeTreeWithDeferredRefCheck()(val check: () => TypeTree) extends TypTree @@ -149,6 +196,8 @@ trait Trees extends reflect.internal.Trees { self: Global => traverser.traverse(definition) case SelectFromArray(qualifier, selector, erasure) => traverser.traverse(qualifier) + case InjectDerivedValue(arg) => + traverser.traverse(arg) case ReferenceToBoxed(idt) => traverser.traverse(idt) case TypeTreeWithDeferredRefCheck() => @@ -159,6 +208,7 @@ trait Trees extends reflect.internal.Trees { self: Global => trait TreeCopier extends super.TreeCopierOps { def DocDef(tree: Tree, comment: DocComment, definition: Tree): DocDef def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type): SelectFromArray + def InjectDerivedValue(tree: Tree, arg: Tree): InjectDerivedValue def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed def TypeTreeWithDeferredRefCheck(tree: Tree): TypeTreeWithDeferredRefCheck } @@ -171,6 +221,8 @@ trait Trees extends reflect.internal.Trees { self: Global => new DocDef(comment, definition).copyAttrs(tree) def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) = new SelectFromArray(qualifier, selector, erasure).copyAttrs(tree) + def InjectDerivedValue(tree: Tree, arg: Tree) = + new InjectDerivedValue(arg) def ReferenceToBoxed(tree: Tree, idt: Ident) = new ReferenceToBoxed(idt).copyAttrs(tree) def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match { @@ -189,6 +241,11 @@ trait Trees extends reflect.internal.Trees { self: Global => if (qualifier0 == qualifier) && (selector0 == selector) => t case _ => this.treeCopy.SelectFromArray(tree, qualifier, selector, erasure) } + def InjectDerivedValue(tree: Tree, arg: Tree) = tree match { + case t @ InjectDerivedValue(arg0) + if (arg0 == arg) => t + case _ => this.treeCopy.InjectDerivedValue(tree, arg) + } def ReferenceToBoxed(tree: Tree, idt: Ident) = tree match { case t @ ReferenceToBoxed(idt0) if (idt0 == idt) => t @@ -217,6 +274,9 @@ trait Trees extends reflect.internal.Trees { self: Global => case SelectFromArray(qualifier, selector, erasure) => transformer.treeCopy.SelectFromArray( tree, transformer.transform(qualifier), selector, erasure) + case InjectDerivedValue(arg) => + transformer.treeCopy.InjectDerivedValue( + tree, transformer.transform(arg)) case ReferenceToBoxed(idt) => transformer.treeCopy.ReferenceToBoxed( tree, transformer.transform(idt) match { case idt1: Ident => idt1 }) @@ -333,6 +393,7 @@ trait Trees extends reflect.internal.Trees { self: Global => case DocDef(comment, defn) => (eliminated by typer) case TypeTreeWithDeferredRefCheck() => (created and eliminated by typer) case SelectFromArray(_, _, _) => (created and eliminated by erasure) + case InjectDerivedValue(_) => (created and eliminated by erasure) */ diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala index 46ade7d889..93fa9a60f6 100644..100755 --- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala @@ -267,7 +267,7 @@ trait MarkupParsers { val (qname, attrMap) = xTag(()) if (ch == '/') { // empty element xToken("/>") - handle.element(r2p(start, start, curOffset), qname, attrMap, new ListBuffer[Tree]) + handle.element(r2p(start, start, curOffset), qname, attrMap, true, new ListBuffer[Tree]) } else { // handle content xToken('>') @@ -281,7 +281,7 @@ trait MarkupParsers { val pos = r2p(start, start, curOffset) qname match { case "xml:group" => handle.group(pos, ts) - case _ => handle.element(pos, qname, attrMap, ts) + case _ => handle.element(pos, qname, attrMap, false, ts) } } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 077f0f9c0e..ccebcfa54d 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -249,6 +249,8 @@ self => final val InBlock = 1 final val InTemplate = 2 + lazy val ScalaValueClassNames: Set[Name] = definitions.scalaValueClassesSet map (_.name) + import nme.raw abstract class Parser extends ParserCommon { @@ -290,11 +292,11 @@ self => inScalaPackage = false currentPackage = "" } - private lazy val anyValNames: Set[Name] = tpnme.ScalaValueNames.toSet + tpnme.AnyVal + 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 isAnyValType(name: Name) = inScalaRootPackage && anyValNames(name) + private def isPrimitiveType(name: Name) = inScalaRootPackage && primitiveNames(name) def parseStartRule: () => Tree @@ -392,7 +394,7 @@ self => // object Main def moduleName = newTermName(ScriptRunner scriptMain settings) - def moduleBody = Template(List(scalaScalaObjectConstr), emptyValDef, List(emptyInit, mainDef)) + def moduleBody = Template(List(atPos(o2p(in.offset))(scalaAnyRefConstr)), emptyValDef, List(emptyInit, mainDef)) def moduleDef = ModuleDef(NoMods, moduleName, moduleBody) // package <empty> { ... } @@ -2722,23 +2724,6 @@ self => * }}} */ def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]], tstart: Int): Template = { - /** Extra parents for case classes. */ - def caseParents() = ( - if (mods.isCase) { - val arity = if (vparamss.isEmpty || vparamss.head.isEmpty) 0 else vparamss.head.size - productConstr :: serializableConstr :: { - Nil - // if (arity == 0 || settings.YnoProductN.value) Nil - // else List( - // AppliedTypeTree( - // productConstrN(arity), - // vparamss.head map (vd => vd.tpt.duplicate setPos vd.tpt.pos.focus) - // ) - // ) - } - } - else Nil - ) val (parents0, argss, self, body) = ( if (in.token == EXTENDS || in.token == SUBTYPE && mods.hasTraitFlag) { in.nextToken() @@ -2750,21 +2735,27 @@ self => (List(), List(List()), self, body) } ) - + def anyrefParents() = { + val caseParents = if (mods.isCase) List(productConstr, serializableConstr) else Nil + parents0 ::: caseParents match { + case Nil => List(atPos(o2p(in.offset))(scalaAnyRefConstr)) + case ps => ps + } + } + def anyvalConstructor() = ( + // Not a well-formed constructor, has to be finished later - see note + // regarding AnyVal constructor in AddInterfaces. + DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(), Block(Nil, Literal(Constant()))) + ) val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart + atPos(tstart0) { - if (isAnyValType(name)) { - val parent = if (name == tpnme.AnyVal) tpnme.Any else tpnme.AnyVal - Template(List(scalaDot(parent)), self, body) - } - else { - val parents = ( - if (!isInterface(mods, body) && !isScalaArray(name)) parents0 :+ scalaScalaObjectConstr - else if (parents0.isEmpty) List(scalaAnyRefConstr) - else parents0 - ) ++ caseParents() - Template(parents, self, constrMods, vparamss, argss, body, o2p(tstart)) - } + // [Martin to Paul: This needs to be refined. We should only include the 9 primitive classes, + // not any other value classes that happen to be defined in the Scala package. + if (inScalaRootPackage && (name == tpnme.AnyVal || (ScalaValueClassNames contains name))) + Template(parents0, self, anyvalConstructor :: body) + else + Template(anyrefParents, self, constrMods, vparamss, argss, body, o2p(tstart)) } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index ffe65aec63..849437e4ff 100644..100755 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -101,7 +101,8 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { pre: Tree, label: Tree, attrs: Tree, - scope:Tree, + scope: Tree, + empty: Boolean, children: Seq[Tree]): Tree = { def starArgs = @@ -109,7 +110,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { else List(Typed(makeXMLseq(pos, children), wildStar)) def pat = Apply(_scala_xml__Elem, List(pre, label, wild, wild) ::: convertToTextPat(children)) - def nonpat = New(_scala_xml_Elem, List(List(pre, label, attrs, scope) ::: starArgs)) + def nonpat = New(_scala_xml_Elem, List(List(pre, label, attrs, scope, if (empty) Literal(Constant(true)) else Literal(Constant(false))) ::: starArgs)) atPos(pos) { if (isPattern) pat else nonpat } } @@ -140,7 +141,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { case (Some(pre), rest) => (const(pre), const(rest)) case _ => (wild, const(n)) } - mkXML(pos, true, prepat, labpat, null, null, args) + mkXML(pos, true, prepat, labpat, null, null, false, args) } protected def convertToTextPat(t: Tree): Tree = t match { @@ -188,7 +189,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { def unparsed(pos: Position, str: String): Tree = atPos(pos)( New(_scala_xml_Unparsed, LL(const(str))) ) - def element(pos: Position, qname: String, attrMap: mutable.Map[String, Tree], args: Seq[Tree]): Tree = { + def element(pos: Position, qname: String, attrMap: mutable.Map[String, Tree], empty: Boolean, args: Seq[Tree]): Tree = { def handleNamespaceBinding(pre: String, z: String): Tree = { def mkAssign(t: Tree): Tree = Assign( Ident(_tmpscope), @@ -259,6 +260,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { const(newlabel), makeSymbolicAttrs, Ident(_scope), + empty, args ) diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index ad93b4753f..0d2fbc5372 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -29,12 +29,13 @@ abstract class TreeBuilder { def rootId(name: Name) = gen.rootId(name) def rootScalaDot(name: Name) = gen.rootScalaDot(name) def scalaDot(name: Name) = gen.scalaDot(name) - def scalaAnyRefConstr = gen.scalaAnyRefConstr - def scalaUnitConstr = gen.scalaUnitConstr - def scalaScalaObjectConstr = gen.scalaScalaObjectConstr - def productConstr = gen.productConstr + def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) + def scalaAnyValConstr = scalaDot(tpnme.AnyVal) + def scalaAnyConstr = scalaDot(tpnme.Any) + def scalaUnitConstr = scalaDot(tpnme.Unit) + def productConstr = scalaDot(tpnme.Product) def productConstrN(n: Int) = scalaDot(newTypeName("Product" + n)) - def serializableConstr = gen.serializableConstr + def serializableConstr = scalaDot(tpnme.Serializable) def convertToTypeName(t: Tree) = gen.convertToTypeName(t) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index c609f126d3..4c77cb7082 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -746,7 +746,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if ((settings.check.value contains "genjvm")) { val normalizedTpe = beforeErasure(erasure.prepareSigMap(memberTpe)) val bytecodeTpe = owner.thisType.memberInfo(sym) - if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym, normalizedTpe) =:= bytecodeTpe)) { + if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) { clasz.cunit.warning(sym.pos, """|compiler bug: created generic signature for %s in %s that does not conform to its erasure |signature: %s diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala index 5e5320ca9a..e35286b281 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala @@ -438,7 +438,9 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { if(!comment.throws.isEmpty) { <dt>Exceptions thrown</dt> <dd>{ - val exceptionsXml: Iterable[scala.xml.NodeSeq] = (for(exception <- comment.throws ) yield <span class="cmt">{Text(exception._1) ++ bodyToHtml(exception._2)}</span> ) + val exceptionsXml: Iterable[scala.xml.NodeSeq] = + for(exception <- comment.throws.toList.sortBy(_._1) ) yield + <span class="cmt">{Text(exception._1) ++ bodyToHtml(exception._2)}</span> exceptionsXml.reduceLeft(_ ++ Text("") ++ _) }</dd> } else NodeSeq.Empty diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 127faf8ed9..496d004fd8 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -20,7 +20,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory: ModelFactory with CommentFactory with TreeFactory => import global._ - import definitions.{ ObjectClass, ScalaObjectClass, RootPackage, EmptyPackage, NothingClass, AnyClass, AnyValClass, AnyRefClass } + import definitions.{ ObjectClass, RootPackage, EmptyPackage, NothingClass, AnyClass, AnyValClass, AnyRefClass } private var droppedPackages = 0 def templatesCount = templatesCache.size - droppedPackages @@ -42,7 +42,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { memberSym.isOmittablePrefix || (closestPackage(memberSym) == closestPackage(templateSym)) } - private lazy val noSubclassCache = Set(AnyClass, AnyRefClass, ObjectClass, ScalaObjectClass) + private lazy val noSubclassCache = Set(AnyClass, AnyRefClass, ObjectClass) /** */ def makeModel: Option[Universe] = { @@ -217,13 +217,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } def parentType = { if (sym.isPackage || sym == AnyClass) None else { - val tps = - (sym.tpe.parents filter (_ != ScalaObjectClass.tpe)) map { _.asSeenFrom(sym.thisType, sym) } + val tps = sym.tpe.parents map { _.asSeenFrom(sym.thisType, sym) } Some(makeType(RefinedType(tps, EmptyScope), inTpl)) } } val linearization: List[(TemplateEntity, TypeEntity)] = { - sym.ancestors filter (_ != ScalaObjectClass) map { ancestor => + sym.ancestors map { ancestor => val typeEntity = makeType(sym.info.baseType(ancestor), this) val tmplEntity = makeTemplate(ancestor) match { case tmpl: DocTemplateImpl => tmpl registerSubClass this ; tmpl @@ -316,7 +315,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def normalizeTemplate(aSym: Symbol): Symbol = aSym match { case null | EmptyPackage | NoSymbol => normalizeTemplate(RootPackage) - case ScalaObjectClass | ObjectClass => + case ObjectClass => normalizeTemplate(AnyRefClass) case _ if aSym.isPackageObject => aSym diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala index efa524503c..b088c643cb 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala @@ -38,7 +38,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory => val key = (sym, inTpl) if (commentCache isDefinedAt key) Some(commentCache(key)) - else { // not reached for use-case comments + else { val c = defineComment(sym, inTpl) if (c isDefined) commentCache += (sym, inTpl) -> c.get c diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala index d1f738a435..d08a363a9d 100644 --- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala @@ -168,7 +168,7 @@ self: scala.tools.nsc.Global => /** Position a tree. * This means: Set position of a node and position all its unpositioned children. */ - override def atPos[T <: Tree](pos: Position)(tree: T): T = + override def atPos[T <: Tree](pos: Position)(tree: T): T = { if (pos.isOpaqueRange) { if (!tree.isEmpty && tree.pos == NoPosition) { tree.setPos(pos) @@ -182,6 +182,7 @@ self: scala.tools.nsc.Global => } else { super.atPos(pos)(tree) } + } // ---------------- Validating positions ---------------------------------- @@ -190,26 +191,33 @@ self: scala.tools.nsc.Global => val source = if (tree.pos.isDefined) tree.pos.source else "" inform("== "+prefix+" tree ["+tree.id+"] of type "+tree.productPrefix+" at "+tree.pos.show+source) inform("") - inform(tree.toString) + inform(treeStatus(tree)) inform("") } def positionError(msg: String)(body : => Unit) { - inform("======= Bad positions: "+msg) - inform("") + inform("======= Position error\n" + msg) body - inform("=== While validating") - inform("") - inform(tree.toString) - inform("") + inform("\nWhile validating #" + tree.id) + inform(treeStatus(tree)) + inform("\nChildren:") + tree.children map (t => " " + treeStatus(t, tree)) foreach inform inform("=======") throw new ValidateException(msg) } def validate(tree: Tree, encltree: Tree): Unit = { + if (!tree.isEmpty) { + if (settings.Yposdebug.value && (settings.verbose.value || settings.Yrangepos.value)) + println("[%10s] %s".format("validate", treeStatus(tree, encltree))) + if (!tree.pos.isDefined) - positionError("Unpositioned tree ["+tree.id+"]") { reportTree("Unpositioned", tree) } + positionError("Unpositioned tree #"+tree.id) { + inform("%15s %s".format("unpositioned", treeStatus(tree, encltree))) + inform("%15s %s".format("enclosing", treeStatus(encltree))) + encltree.children foreach (t => inform("%15s %s".format("sibling", treeStatus(t, encltree)))) + } if (tree.pos.isRange) { if (!encltree.pos.isRange) positionError("Synthetic tree ["+encltree.id+"] contains nonsynthetic tree ["+tree.id+"]") { diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index 7e032753f2..68bfeafbc6 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -183,7 +183,7 @@ trait MemberHandlers { // TODO: Need to track these specially to honor Predef masking attempts, // because they must be the leading imports in the code generated for each // line. We can use the same machinery as Contexts now, anyway. - def isPredefImport = treeInfo.isPredefExpr(expr) + def isPredefImport = isReferenceToPredef(expr) // wildcard imports, e.g. import foo._ private def selectorWild = selectors filter (_.name == nme.USCOREkw) diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala index e72a0007a0..ef17367ce0 100644 --- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala +++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala @@ -20,7 +20,7 @@ trait MatrixAdditions extends ast.TreeDSL { import CODE._ import Debug._ import treeInfo._ - import definitions.{ isValueClass } + import definitions.{ isPrimitiveValueClass } /** The Squeezer, responsible for all the squeezing. */ @@ -141,7 +141,7 @@ trait MatrixAdditions extends ast.TreeDSL { (sym.isMutable) && // indicates that have not yet checked exhaustivity !(sym hasFlag NO_EXHAUSTIVE) && // indicates @unchecked (sym.tpe.typeSymbol.isSealed) && - !isValueClass(sym.tpe.typeSymbol) // make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte + !isPrimitiveValueClass(sym.tpe.typeSymbol) // make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte } private lazy val inexhaustives: List[List[Combo]] = { @@ -155,7 +155,7 @@ trait MatrixAdditions extends ast.TreeDSL { pv.tpe.typeSymbol.sealedDescendants.toList sortBy (_.sealedSortName) // symbols which are both sealed and abstract need not be covered themselves, because // all of their children must be and they cannot otherwise be created. - filterNot (x => x.isSealed && x.isAbstractClass && !isValueClass(x)) + filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x)) // have to filter out children which cannot match: see ticket #3683 for an example filter (_.tpe matchesPattern pv.tpe) ) diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index e949cb3eb2..5f3c7ec32c 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -162,6 +162,7 @@ trait ScalaSettings extends AbsScalaSettings val Ybuildmanagerdebug = BooleanSetting ("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.") val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignments.") + val Yposdebug = BooleanSetting ("-Ypos-debug", "Trace position validation.") val Yinferdebug = BooleanSetting ("-Yinfer-debug", "Trace type inference and implicit search.") val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.") val Yreifycopypaste = diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 07d132f7dd..1cd4ab21ea 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -843,7 +843,7 @@ abstract class ClassfileParser { } ClassInfoType(parents.toList, instanceDefs, sym) } - polyType(ownTypeParams, tpe) + GenPolyType(ownTypeParams, tpe) } // sigToType class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType { diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 1abaf1c1d6..39e2cbe694 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -11,7 +11,7 @@ import Flags._ import scala.collection.{ mutable, immutable } import collection.mutable.ListBuffer -abstract class AddInterfaces extends InfoTransform { +abstract class AddInterfaces extends InfoTransform { self: Erasure => import global._ // the global environment import definitions._ // standard classes and methods @@ -21,14 +21,6 @@ abstract class AddInterfaces extends InfoTransform { */ override def phaseNewFlags: Long = lateDEFERRED | lateINTERFACE - /** Type reference after erasure; defined in Erasure. - */ - def erasedTypeRef(sym: Symbol): Type - - /** Erasure calculation; defined in Erasure. - */ - def erasure(sym: Symbol, tpe: Type): Type - /** A lazily constructed map that associates every non-interface trait with * its implementation class. */ @@ -176,14 +168,14 @@ abstract class AddInterfaces extends InfoTransform { /** If `tp` refers to a non-interface trait, return a * reference to its implementation class. Otherwise return `tp`. */ - def mixinToImplClass(tp: Type): Type = erasure(sym, + def mixinToImplClass(tp: Type): Type = erasure(sym) { tp match { //@MATN: no normalize needed (comes after erasure) case TypeRef(pre, sym, _) if sym.needsImplClass => typeRef(pre, implClass(sym), Nil) case _ => tp } - ) + } def implType(tp: Type): Type = tp match { case ClassInfoType(parents, decls, _) => assert(phase == implClassPhase, tp) @@ -272,11 +264,10 @@ abstract class AddInterfaces extends InfoTransform { else DefDef(clazz.primaryConstructor, Block(List(), Literal(Constant()))) :: stats private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos) { - val templ1 = atPos(templ.pos) { - Template(templ.parents, emptyValDef, - addMixinConstructorDef(clazz, templ.body map implMemberDef)) - .setSymbol(clazz.newLocalDummy(templ.pos)) - } + val templ1 = ( + Template(templ.parents, emptyValDef, addMixinConstructorDef(clazz, templ.body map implMemberDef)) + setSymbol clazz.newLocalDummy(templ.pos) + ) templ1.changeOwner(templ.symbol.owner -> clazz, templ.symbol -> templ1.symbol) templ1 } @@ -299,14 +290,22 @@ abstract class AddInterfaces extends InfoTransform { } val mixinConstructorCalls: List[Tree] = { for (mc <- clazz.mixinClasses.reverse - if mc.hasFlag(lateINTERFACE) && mc != ScalaObjectClass) + if mc.hasFlag(lateINTERFACE)) yield mixinConstructorCall(implClass(mc)) } - (tree: @unchecked) match { + tree match { + case Block(Nil, expr) => + // AnyVal constructor - have to provide a real body so the + // jvm doesn't throw a VerifyError. But we can't add the + // body until now, because the typer knows that Any has no + // constructor and won't accept a call to super.init. + assert((clazz isSubClass AnyValClass) || clazz.info.parents.isEmpty, clazz) + val superCall = Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), Nil) + Block(List(superCall), expr) + case Block(stats, expr) => // needs `hasSymbol` check because `supercall` could be a block (named / default args) val (presuper, supercall :: rest) = stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER)) - // assert(supercall.symbol.isClassConstructor, supercall) treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr) } } diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index d04c6115ca..b21fa4bc83 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -94,7 +94,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { localTyper.typedPos(pos)(tree) /** A value class is defined to be only Java-compatible values: unit is - * not part of it, as opposed to isValueClass in definitions. scala.Int is + * not part of it, as opposed to isPrimitiveValueClass in definitions. scala.Int is * a value class, java.lang.Integer is not. */ def isJavaValueClass(sym: Symbol) = boxedClass contains sym def isJavaValueType(tp: Type) = isJavaValueClass(tp.typeSymbol) @@ -165,24 +165,19 @@ abstract class CleanUp extends Transform with ast.TreeDSL { varSym } - def addStaticMethodToClass(forName: String, forArgsTypes: List[Type], forResultType: Type) - (forBody: Pair[Symbol, List[Symbol]] => Tree): Symbol = { + def addStaticMethodToClass(forBody: (Symbol, Symbol) => Tree): Symbol = { + val methSym = currentClass.newMethod(mkTerm(nme.reflMethodName), ad.pos, STATIC | SYNTHETIC) + val params = methSym.newSyntheticValueParams(List(ClassClass.tpe)) + methSym setInfoAndEnter MethodType(params, MethodClass.tpe) - val methSym = currentClass.newMethod(mkTerm(forName), ad.pos, STATIC | SYNTHETIC) - val params = methSym.newSyntheticValueParams(forArgsTypes) - methSym setInfoAndEnter MethodType(params, forResultType) - - val methDef = typedPos( DefDef(methSym, forBody(methSym -> params)) ) + val methDef = typedPos(DefDef(methSym, forBody(methSym, params.head))) newStaticMembers append transform(methDef) - methSym } def fromTypesToClassArrayLiteral(paramTypes: List[Type]): Tree = ArrayValue(TypeTree(ClassClass.tpe), paramTypes map LIT) - def theTypeClassArray = arrayType(ClassClass.tpe) - /* ... */ def reflectiveMethodCache(method: String, paramTypes: List[Type]): Symbol = dispatchType match { case NO_CACHE => @@ -197,12 +192,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, arrayType(ClassClass.tpe), fromTypesToClassArrayLiteral(paramTypes), true) - addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { - case Pair(reflMethodSym, List(forReceiverSym)) => - (REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym)) - } + addStaticMethodToClass((_, forReceiverSym) => + gen.mkMethodCall(REF(forReceiverSym), Class_getMethod, Nil, List(LIT(method), safeREF(reflParamsCacheSym))) + ) case MONO_CACHE => @@ -226,7 +220,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, arrayType(ClassClass.tpe), fromTypesToClassArrayLiteral(paramTypes), true) val reflMethodCacheSym: Symbol = addStaticVariableToClass(nme.reflMethodCacheName, MethodClass.tpe, NULL, false) @@ -237,17 +231,16 @@ abstract class CleanUp extends Transform with ast.TreeDSL { def isCacheEmpty(receiver: Symbol): Tree = reflClassCacheSym.IS_NULL() OR (reflClassCacheSym.GET() OBJ_NE REF(receiver)) - addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { - case Pair(reflMethodSym, List(forReceiverSym)) => - BLOCK( - IF (isCacheEmpty(forReceiverSym)) THEN BLOCK( - safeREF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) , - safeREF(reflClassCacheSym) === gen.mkSoftRef(REF(forReceiverSym)), - UNIT - ) ENDIF, - safeREF(reflMethodCacheSym) - ) - } + addStaticMethodToClass((_, forReceiverSym) => + BLOCK( + IF (isCacheEmpty(forReceiverSym)) THEN BLOCK( + safeREF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) , + safeREF(reflClassCacheSym) === gen.mkSoftRef(REF(forReceiverSym)), + UNIT + ) ENDIF, + safeREF(reflMethodCacheSym) + ) + ) case POLY_CACHE => @@ -273,7 +266,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, arrayType(ClassClass.tpe), fromTypesToClassArrayLiteral(paramTypes), true) def mkNewPolyCache = gen.mkSoftRef(NEW(TypeTree(EmptyMethodCacheClass.tpe))) val reflPolyCacheSym: Symbol = ( @@ -281,26 +274,25 @@ abstract class CleanUp extends Transform with ast.TreeDSL { ) def getPolyCache = gen.mkCast(fn(safeREF(reflPolyCacheSym), nme.get), MethodCacheClass.tpe) - addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) - { case Pair(reflMethodSym, List(forReceiverSym)) => - val methodSym = reflMethodSym.newVariable(mkTerm("method"), ad.pos) setInfo MethodClass.tpe - - BLOCK( - IF (getPolyCache OBJ_EQ NULL) THEN (safeREF(reflPolyCacheSym) === mkNewPolyCache) ENDIF, - VAL(methodSym) === ((getPolyCache DOT methodCache_find)(REF(forReceiverSym))) , - IF (REF(methodSym) OBJ_!= NULL) . - THEN (Return(REF(methodSym))) - ELSE { - def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) - def cacheRHS = ((getPolyCache DOT methodCache_add)(REF(forReceiverSym), REF(methodSym))) - BLOCK( - REF(methodSym) === (REF(ensureAccessibleMethod) APPLY (methodSymRHS)), - safeREF(reflPolyCacheSym) === gen.mkSoftRef(cacheRHS), - Return(REF(methodSym)) - ) - } - ) - } + addStaticMethodToClass((reflMethodSym, forReceiverSym) => { + val methodSym = reflMethodSym.newVariable(mkTerm("method"), ad.pos) setInfo MethodClass.tpe + + BLOCK( + IF (getPolyCache OBJ_EQ NULL) THEN (safeREF(reflPolyCacheSym) === mkNewPolyCache) ENDIF, + VAL(methodSym) === ((getPolyCache DOT methodCache_find)(REF(forReceiverSym))) , + IF (REF(methodSym) OBJ_!= NULL) . + THEN (Return(REF(methodSym))) + ELSE { + def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) + def cacheRHS = ((getPolyCache DOT methodCache_add)(REF(forReceiverSym), REF(methodSym))) + BLOCK( + REF(methodSym) === (REF(ensureAccessibleMethod) APPLY (methodSymRHS)), + safeREF(reflPolyCacheSym) === gen.mkSoftRef(cacheRHS), + Return(REF(methodSym)) + ) + } + ) + }) } /* ### HANDLING METHODS NORMALLY COMPILED TO OPERATORS ### */ @@ -551,7 +543,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { case Literal(c) if (c.tag == ClassTag) && !forMSIL=> val tpe = c.typeValue typedWithPos(tree.pos) { - if (isValueClass(tpe.typeSymbol)) { + if (isPrimitiveValueClass(tpe.typeSymbol)) { if (tpe.typeSymbol == UnitClass) REF(BoxedUnit_TYPE) else diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index d8f19f85c0..4f833c82d3 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -44,11 +44,14 @@ abstract class Constructors extends Transform with ast.TreeDSL { ) // decompose primary constructor into the three entities above. val constrInfo: ConstrInfo = { - val primary = stats find (_.symbol.isPrimaryConstructor) - assert(primary.isDefined, "no constructor in template: impl = " + impl) - - val ddef @ DefDef(_, _, _, List(vparams), _, rhs @ Block(_, _)) = primary.get + stats find (_.symbol.isPrimaryConstructor) match { + case Some(ddef @ DefDef(_, _, _, List(vparams), _, rhs @ Block(_, _))) => ConstrInfo(ddef, vparams map (_.symbol), rhs) + case x => + // AnyVal constructor is OK + assert(clazz eq AnyValClass, "no constructor in template: impl = " + impl) + return impl + } } import constrInfo._ @@ -443,7 +446,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { localTyper.typed { atPos(impl.pos) { val closureClass = clazz.newClass(nme.delayedInitArg.toTypeName, impl.pos, SYNTHETIC | FINAL) - val closureParents = List(AbstractFunctionClass(0).tpe, ScalaObjectClass.tpe) + val closureParents = List(AbstractFunctionClass(0).tpe) closureClass setInfoAndEnter new ClassInfoType(closureParents, newScope, closureClass) @@ -565,7 +568,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { override def transform(tree: Tree): Tree = tree match { - case ClassDef(_,_,_,_) if !tree.symbol.isInterface && !isValueClass(tree.symbol) => + case ClassDef(_,_,_,_) if !tree.symbol.isInterface && !isPrimitiveValueClass(tree.symbol) => deriveClassDef(tree)(transformClassTemplate) case _ => super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index d54ce78e18..a98cd5c6b1 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -31,33 +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(tpe: Type): Type = { - if (phase.erasedTypes) ClassClass.tpe else { - val tp = tpe.widen.normalize - val sym = tp.typeSymbol - - if (isValueClass(sym)) ClassType(tp) - else boundedClassType( - if (isPhantomClass(sym)) ObjectClass.tpe - else if (sym.isLocalClass) intersectionDominator(tp.parents) - else tp - ) - } - } - // convert a numeric with a toXXX method def numericConversion(tree: Tree, numericSym: Symbol): Tree = { val mname = newTermName("to" + numericSym.name) @@ -257,7 +230,7 @@ abstract class Erasure extends AddInterfaces // Anything which could conceivably be a module (i.e. isn't known to be // a type parameter or similar) must go through here or the signature is // likely to end up with Foo<T>.Empty where it needs Foo<T>.Empty$. - def fullNameInSig(sym: Symbol) = "L" + beforeIcode(sym.javaBinaryName.toString) + def fullNameInSig(sym: Symbol) = "L" + beforeIcode(sym.javaBinaryName) def jsig(tp0: Type, existentiallyBound: List[Symbol] = Nil, toplevel: Boolean = false, primitiveOK: Boolean = true): String = { val tp = tp0.dealias @@ -294,7 +267,7 @@ abstract class Erasure extends AddInterfaces jsig(RuntimeNothingClass.tpe) else if (sym == NullClass) jsig(RuntimeNullClass.tpe) - else if (isValueClass(sym)) { + else if (isPrimitiveValueClass(sym)) { if (!primitiveOK) jsig(ObjectClass.tpe) else if (sym == UnitClass) jsig(BoxedUnitClass.tpe) else abbrvTag(sym).toString @@ -317,7 +290,7 @@ abstract class Erasure extends AddInterfaces ) ) } - else jsig(erasure(sym0, tp), existentiallyBound, toplevel, primitiveOK) + else jsig(erasure(sym0)(tp), existentiallyBound, toplevel, primitiveOK) case PolyType(tparams, restpe) => assert(tparams.nonEmpty) val poly = if (toplevel) polyParamSig(tparams) else "" @@ -337,7 +310,7 @@ abstract class Erasure extends AddInterfaces println("something's wrong: "+sym0+":"+sym0.tpe+" has a bounded wildcard type") jsig(bounds.hi, existentiallyBound, toplevel, primitiveOK) case _ => - val etp = erasure(sym0, tp) + val etp = erasure(sym0)(tp) if (etp eq tp) throw new UnknownSig else jsig(etp) } @@ -396,36 +369,79 @@ abstract class Erasure extends AddInterfaces override def newTyper(context: Context) = new Eraser(context) - /** An extractor object for boxed expressions + private def safeToRemoveUnbox(cls: Symbol): Boolean = + (cls == definitions.NullClass) || isBoxedValueClass(cls) + + /** An extractor object for unboxed expressions (maybe subsumed by posterasure?) */ + object Unboxed { + def unapply(tree: Tree): Option[Tree] = tree match { + case Apply(fn, List(arg)) if isUnbox(fn.symbol) && safeToRemoveUnbox(arg.tpe.typeSymbol) => + Some(arg) + case Apply( + TypeApply( + cast @ Select( + Apply( + sel @ Select(arg, acc), + List()), + asinstanceof), + List(tpt)), + List()) + if cast.symbol == Object_asInstanceOf && + tpt.tpe.typeSymbol.isDerivedValueClass && + sel.symbol == tpt.tpe.typeSymbol.firstParamAccessor => + Some(arg) + case _ => + None + } + } + + /** An extractor object for boxed expressions (maybe subsumed by posterasure?) */ object Boxed { def unapply(tree: Tree): Option[Tree] = tree match { + case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isDerivedValueClass) => + Some(arg) case LabelDef(name, params, Boxed(rhs)) => Some(treeCopy.LabelDef(tree, name, params, rhs) setType rhs.tpe) - case Select(_, _) if tree.symbol == BoxedUnit_UNIT => - Some(Literal(Constant()) setPos tree.pos setType UnitClass.tpe) - case Block(List(unboxed), ret @ Select(_, _)) if ret.symbol == BoxedUnit_UNIT => - Some(if (unboxed.tpe.typeSymbol == UnitClass) tree - else Block(List(unboxed), Literal(Constant()) setPos tree.pos setType UnitClass.tpe)) - case Apply(fn, List(unboxed)) if isBox(fn.symbol) => - Some(unboxed) case _ => None } } - */ /** The modifier typer which retypes with erased types. */ class Eraser(_context: Context) extends Typer(_context) { - private def safeToRemoveUnbox(cls: Symbol): Boolean = - (cls == definitions.NullClass) || isBoxedValueClass(cls) + + private def isPrimitiveValueType(tpe: Type) = isPrimitiveValueClass(tpe.typeSymbol) + + private def isErasedValueType(tpe: Type) = tpe.isInstanceOf[ErasedValueType] + + private def isDifferentErasedValueType(tpe: Type, other: Type) = + isErasedValueType(tpe) && (tpe ne other) + + private def isPrimitiveValueMember(sym: Symbol) = + sym != NoSymbol && isPrimitiveValueClass(sym.owner) + + private def box(tree: Tree, target: => String): Tree = { + val result = box1(tree) + log("boxing "+tree+":"+tree.tpe+" to "+target+" = "+result+":"+result.tpe) + result + } /** Box `tree` of unboxed type */ - private def box(tree: Tree): Tree = tree match { + private def box1(tree: Tree): Tree = tree match { case LabelDef(_, _, _) => - val ldef = deriveLabelDef(tree)(box) + val ldef = deriveLabelDef(tree)(box1) ldef setType ldef.rhs.tpe case _ => - typedPos(tree.pos)(tree.tpe.typeSymbol match { + val tree1 = tree.tpe match { + case ErasedValueType(clazz) => + tree match { + case Unboxed(arg) if arg.tpe.typeSymbol == clazz => + log("shortcircuiting unbox -> box "+arg); arg + case _ => + New(clazz, cast(tree, underlyingOfValueClass(clazz))) + } + case _ => + tree.tpe.typeSymbol match { case UnitClass => if (treeInfo isExprSafeToInline tree) REF(BoxedUnit_UNIT) else BLOCK(tree, REF(BoxedUnit_UNIT)) @@ -445,7 +461,15 @@ abstract class Erasure extends AddInterfaces case _ => (REF(boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectClass.tpe } - }) + } + } + typedPos(tree.pos)(tree1) + } + + private def unbox(tree: Tree, pt: Type): Tree = { + val result = unbox1(tree, pt) + log("unboxing "+tree+":"+tree.tpe+" to "+pt+" = "+result+":"+result.tpe) + result } /** Unbox `tree` of boxed type to expected type `pt`. @@ -454,7 +478,7 @@ abstract class Erasure extends AddInterfaces * @param pt the expected type. * @return the unboxed tree */ - private def unbox(tree: Tree, pt: Type): Tree = tree match { + private def unbox1(tree: Tree, pt: Type): Tree = tree match { /* case Boxed(unboxed) => println("unbox shorten: "+tree) // this never seems to kick in during build and test; therefore disabled. @@ -464,7 +488,19 @@ abstract class Erasure extends AddInterfaces val ldef = deriveLabelDef(tree)(unbox(_, pt)) ldef setType ldef.rhs.tpe case _ => - typedPos(tree.pos)(pt.typeSymbol match { + val tree1 = pt match { + case ErasedValueType(clazz) => + tree match { + case Boxed(arg) if arg.tpe.isInstanceOf[ErasedValueType] => + log("shortcircuiting box -> unbox "+arg) + arg + case _ => + log("not boxed: "+tree) + val tree0 = adaptToType(tree, clazz.tpe) + cast(Apply(Select(tree0, clazz.firstParamAccessor), List()), pt) + } + case _ => + pt.typeSymbol match { case UnitClass => if (treeInfo isExprSafeToInline tree) UNIT else BLOCK(tree, UNIT) @@ -472,7 +508,9 @@ abstract class Erasure extends AddInterfaces assert(x != ArrayClass) // don't `setType pt` the Apply tree, as the Apply's fun won't be typechecked if the Apply tree already has a type Apply(unboxMethod(pt.typeSymbol), tree) - }) + } + } + typedPos(tree.pos)(tree1) } /** Generate a synthetic cast operation from tree.tpe to pt. @@ -487,9 +525,6 @@ abstract class Erasure extends AddInterfaces else gen.mkAttributedCast(tree, pt) } - private def isUnboxedValueMember(sym: Symbol) = - sym != NoSymbol && isValueClass(sym.owner) - /** Adapt `tree` to expected type `pt`. * * @param tree the given tree @@ -501,29 +536,30 @@ abstract class Erasure extends AddInterfaces log("adapting " + tree + ":" + tree.tpe + " : " + tree.tpe.parents + " to " + pt)//debug if (tree.tpe <:< pt) tree - else if (isValueClass(tree.tpe.typeSymbol) && !isValueClass(pt.typeSymbol)) - adaptToType(box(tree), pt) - else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.params.isEmpty) { + else if (isDifferentErasedValueType(tree.tpe, pt)) + adaptToType(box(tree, pt.toString), pt) + else if (isDifferentErasedValueType(pt, tree.tpe)) + adaptToType(unbox(tree, pt), pt) + else if (isPrimitiveValueType(tree.tpe) && !isPrimitiveValueType(pt)) { + adaptToType(box(tree, pt.toString), pt) + } else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.params.isEmpty) { assert(tree.symbol.isStable, "adapt "+tree+":"+tree.tpe+" to "+pt) adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt) - } else if (pt <:< tree.tpe) - cast(tree, pt) - else if (isValueClass(pt.typeSymbol) && !isValueClass(tree.tpe.typeSymbol)) +// } else if (pt <:< tree.tpe) +// cast(tree, pt) + } else if (isPrimitiveValueType(pt) && !isPrimitiveValueType(tree.tpe)) adaptToType(unbox(tree, pt), pt) else cast(tree, pt) } - // @PP 1/25/2011: This is less inaccurate than it was (I removed - // BoxedAnyArray, asInstanceOf$erased, and other long ago eliminated symbols) - // but I do not think it yet describes the code beneath it. - /** Replace member references as follows: * * - `x == y` for == in class Any becomes `x equals y` with equals in class Object. * - `x != y` for != in class Any becomes `!(x equals y)` with equals in class Object. * - x.asInstanceOf[T] becomes x.$asInstanceOf[T] * - x.isInstanceOf[T] becomes x.$isInstanceOf[T] + * - x.isInstanceOf[ErasedValueType(clazz)] becomes x.isInstanceOf[clazz.tpe] * - x.m where m is some other member of Any becomes x.m where m is a member of class Object. * - x.m where x has unboxed value type T and m is not a directly translated member of T becomes T.box(x).m * - x.m where x is a reference type and m is a directly translated member of value type T becomes x.TValue().m @@ -533,22 +569,34 @@ abstract class Erasure extends AddInterfaces private def adaptMember(tree: Tree): Tree = { //Console.println("adaptMember: " + tree); tree match { - case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_asInstanceOf => + case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) + if tree.symbol == Any_asInstanceOf => val qual1 = typedQualifier(qual, NOmode, ObjectClass.tpe) // need to have an expected type, see #3037 val qualClass = qual1.tpe.typeSymbol - val targClass = targ.tpe.typeSymbol /* + val targClass = targ.tpe.typeSymbol + if (isNumericValueClass(qualClass) && isNumericValueClass(targClass)) // convert numeric type casts atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List())) else */ - if (isValueClass(targClass)) unbox(qual1, targ.tpe) + if (isPrimitiveValueType(targ.tpe) || isErasedValueType(targ.tpe)) unbox(qual1, targ.tpe) else tree - case Select(qual, name) if (name != nme.CONSTRUCTOR) => - if (tree.symbol == NoSymbol) + case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) + if tree.symbol == Any_isInstanceOf => + targ.tpe match { + case ErasedValueType(clazz) => targ.setType(clazz.tpe) + case _ => + } tree - else if (tree.symbol == Any_asInstanceOf) + case Select(qual, name) => + if (tree.symbol == NoSymbol) { + tree + } else if (name == nme.CONSTRUCTOR) { + if (tree.symbol.owner == AnyValClass) tree.symbol = ObjectClass.primaryConstructor + tree + } else if (tree.symbol == Any_asInstanceOf) adaptMember(atPos(tree.pos)(Select(qual, Object_asInstanceOf))) else if (tree.symbol == Any_isInstanceOf) adaptMember(atPos(tree.pos)(Select(qual, Object_isInstanceOf))) @@ -556,12 +604,13 @@ abstract class Erasure extends AddInterfaces adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name)))) else { var qual1 = typedQualifier(qual) - if ((isValueClass(qual1.tpe.typeSymbol) && !isUnboxedValueMember(tree.symbol))) - qual1 = box(qual1) - else if (!isValueClass(qual1.tpe.typeSymbol) && isUnboxedValueMember(tree.symbol)) + if ((isPrimitiveValueType(qual1.tpe) && !isPrimitiveValueMember(tree.symbol)) || + isErasedValueType(qual1.tpe)) + qual1 = box(qual1, "owner "+tree.symbol.owner) + else if (!isPrimitiveValueType(qual1.tpe) && isPrimitiveValueMember(tree.symbol)) qual1 = unbox(qual1, tree.symbol.owner.tpe) - if (isValueClass(tree.symbol.owner) && !isValueClass(qual1.tpe.typeSymbol)) + if (isPrimitiveValueMember(tree.symbol) && !isPrimitiveValueType(qual1.tpe)) tree.symbol = NoSymbol else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.params.isEmpty) { assert(qual1.symbol.isStable, qual1.symbol); @@ -590,13 +639,22 @@ abstract class Erasure extends AddInterfaces */ override protected def typed1(tree: Tree, mode: Int, pt: Type): Tree = { val tree1 = try { + tree match { + case InjectDerivedValue(arg) => + val clazz = tree.symbol + val result = typed1(arg, mode, underlyingOfValueClass(clazz)) setType ErasedValueType(clazz) + log("transforming inject "+arg+":"+underlyingOfValueClass(clazz)+"/"+ErasedValueType(clazz)+" = "+result) + return result + + case _ => super.typed1(adaptMember(tree), mode, pt) + } } catch { case er: TypeError => Console.println("exception when typing " + tree) Console.println(er.msg + " in file " + context.owner.sourceFile) er.printStackTrace - abort() + abort("unrecoverable error") case ex: Exception => //if (settings.debug.value) try Console.println("exception when typing " + tree) @@ -646,6 +704,7 @@ abstract class Erasure extends AddInterfaces * but their erased types are the same. */ private def checkNoDoubleDefs(root: Symbol) { + def afterErasure[T](op: => T): T = atPhase(phase.next.next)(op) def doubleDefError(sym1: Symbol, sym2: Symbol) { // the .toString must also be computed at the earlier phase val tpe1 = afterRefchecks(root.thisType.memberType(sym1)) @@ -740,7 +799,7 @@ abstract class Erasure extends AddInterfaces var bridges: List[Tree] = List() val opc = beforeExplicitOuter { new overridingPairs.Cursor(owner) { - override def parents: List[Type] = List(owner.info.parents.head) + override def parents: List[Type] = List(owner.info.firstParent) override def exclude(sym: Symbol): Boolean = !sym.isMethod || sym.isPrivate || super.exclude(sym) } @@ -750,7 +809,7 @@ abstract class Erasure extends AddInterfaces val other = opc.overridden //println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString)//DEBUG if (beforeExplicitOuter(!member.isDeferred)) { - val otpe = erasure(owner, other.tpe) + val otpe = erasure(owner)(other.tpe) val bridgeNeeded = afterErasure ( !(other.tpe =:= member.tpe) && !(deconstMap(other.tpe) =:= deconstMap(member.tpe)) && @@ -795,7 +854,7 @@ abstract class Erasure extends AddInterfaces IF (typeTest) THEN bridgingCall ELSE REF(NoneModule) } else bridgingCall }); - debuglog("generating bridge from " + other + "(" + Flags.flagsToString(bridge.flags) + ")" + ":" + otpe + other.locationString + " to " + member + ":" + erasure(owner, member.tpe) + member.locationString + " =\n " + bridgeDef); + debuglog("generating bridge from " + other + "(" + Flags.flagsToString(bridge.flags) + ")" + ":" + otpe + other.locationString + " to " + member + ":" + erasure(owner)(member.tpe) + member.locationString + " =\n " + bridgeDef); bridgeDef } } :: bridges @@ -841,6 +900,7 @@ abstract class Erasure extends AddInterfaces * - Given a selection q.s, where the owner of `s` is not accessible but the * type symbol of q's type qT is accessible, insert a cast (q.asInstanceOf[qT]).s * This prevents illegal access errors (see #4283). + * - Remove all instance creations new C(arg) where C is an inlined class. * - Reset all other type attributes to null, thus enforcing a retyping. */ private val preTransformer = new TypingTransformer(unit) { @@ -866,7 +926,7 @@ abstract class Erasure extends AddInterfaces gen.mkMethodCall( qual1(), fun.symbol, - List(erasure(fun.symbol, arg.tpe)), + List(specialErasure(fun.symbol)(arg.tpe)), Nil ), isArrayTest(qual1()) @@ -899,7 +959,7 @@ abstract class Erasure extends AddInterfaces // need to do the cast in adaptMember treeCopy.Apply( tree, - SelectFromArray(qual, name, erasure(tree.symbol, qual.tpe)).copyAttrs(fn), + SelectFromArray(qual, name, erasure(tree.symbol)(qual.tpe)).copyAttrs(fn), args) } case Apply(fn @ Select(qual, _), Nil) if interceptedMethods(fn.symbol) => @@ -918,12 +978,18 @@ abstract class Erasure extends AddInterfaces } } // Rewrite 5.getClass to ScalaRunTime.anyValClass(5) - else if (isValueClass(qual.tpe.typeSymbol)) + else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) global.typer.typed(gen.mkRuntimeCall(nme.anyValClass, List(qual))) else tree + case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isDerivedValueClass) => + InjectDerivedValue(arg) setSymbol tpt.tpe.typeSymbol case Apply(fn, args) => + def qualifier = fn match { + case Select(qual, _) => qual + case TypeApply(Select(qual, _), _) => qual + } if (fn.symbol == Any_asInstanceOf) (fn: @unchecked) match { case TypeApply(Select(qual, _), List(targ)) => @@ -938,7 +1004,7 @@ abstract class Erasure extends AddInterfaces else if (fn.symbol == Any_isInstanceOf) { fn match { case TypeApply(sel @ Select(qual, name), List(targ)) => - if (qual.tpe != null && isValueClass(qual.tpe.typeSymbol) && targ.tpe != null && targ.tpe <:< AnyRefClass.tpe) + if (qual.tpe != null && isPrimitiveValueClass(qual.tpe.typeSymbol) && targ.tpe != null && targ.tpe <:< AnyRefClass.tpe) unit.error(sel.pos, "isInstanceOf cannot test if value types are references.") def mkIsInstanceOf(q: () => Tree)(tp: Type): Tree = @@ -973,20 +1039,13 @@ abstract class Erasure extends AddInterfaces } case _ => tree } - } - else { - def doDynamic(fn: Tree, qual: Tree): Tree = { - if (fn.symbol.owner.isRefinementClass && !fn.symbol.isOverridingSymbol) - ApplyDynamic(qual, args) setSymbol fn.symbol setPos tree.pos - else tree - } - fn match { - case Select(qual, _) => doDynamic(fn, qual) - case TypeApply(fni@Select(qual, _), _) => doDynamic(fni, qual)// type parameters are irrelevant in case of dynamic call - case _ => + } else if (fn.symbol.owner.isRefinementClass && !fn.symbol.isOverridingSymbol) { + ApplyDynamic(qualifier, args) setSymbol fn.symbol setPos tree.pos + } else if (fn.symbol.isMethodWithExtension) { + Apply(gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args) + } else { tree } - } case Select(qual, name) => val owner = tree.symbol.owner @@ -1019,7 +1078,11 @@ abstract class Erasure extends AddInterfaces case Literal(ct) if ct.tag == ClassTag && ct.typeValue.typeSymbol != definitions.UnitClass => - treeCopy.Literal(tree, Constant(erasure(NoSymbol, ct.typeValue))) + val erased = ct.typeValue match { + case TypeRef(pre, clazz, args) if clazz.isDerivedValueClass => scalaErasure.eraseNormalClassRef(pre, clazz) + case tpe => specialScalaErasure(tpe) + } + treeCopy.Literal(tree, Constant(erased)) case _ => tree @@ -1037,10 +1100,13 @@ abstract class Erasure extends AddInterfaces val tree1 = preErase(tree) tree1 match { case EmptyTree | TypeTree() => - tree1 setType erasure(NoSymbol, tree1.tpe) + tree1 setType specialScalaErasure(tree1.tpe) + case ArrayValue(elemtpt, trees) => + treeCopy.ArrayValue( + tree1, elemtpt setType specialScalaErasure.applyInArray(elemtpt.tpe), trees map transform) setType null case DefDef(_, _, _, _, tpt, _) => val result = super.transform(tree1) setType null - tpt.tpe = erasure(tree1.symbol, tree1.symbol.tpe).resultType + tpt.tpe = specialErasure(tree1.symbol)(tree1.symbol.tpe).resultType result case _ => super.transform(tree1) setType null @@ -1054,6 +1120,7 @@ abstract class Erasure extends AddInterfaces */ override def transform(tree: Tree): Tree = { val tree1 = preTransformer.transform(tree) + log("tree after pretransform: "+tree1) afterErasure { val tree2 = mixinTransformer.transform(tree1) debuglog("tree after addinterfaces: \n" + tree2) diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala new file mode 100644 index 0000000000..4c3972519a --- /dev/null +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -0,0 +1,159 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ +package scala.tools.nsc +package transform + +import symtab._ +import Flags._ +import scala.collection.{ mutable, immutable } +import scala.collection.mutable +import scala.tools.nsc.util.FreshNameCreator +import scala.runtime.ScalaRunTime.{ isAnyVal, isTuple } + +/** + * Perform Step 1 in the inline classes SIP: Creates extension methods for all + * methods in a value class, except parameter or super accessors, or constructors. + * + * @author Martin Odersky + * @version 2.10 + */ +abstract class ExtensionMethods extends Transform with TypingTransformers { + + import global._ // the global environment + import definitions._ // standard classes and methods + import typer.{ typed, atOwner } // methods to type trees + + /** the following two members override abstract members in Transform */ + val phaseName: String = "extmethods" + + def newTransformer(unit: CompilationUnit): Transformer = + new Extender(unit) + + /** Generate stream of possible names for the extension version of given instance method `imeth`. + * If the method is not overloaded, this stream consists of just "extension$imeth". + * If the method is overloaded, the stream has as first element "extensionX$imeth", where X is the + * index of imeth in the sequence of overloaded alternatives with the same name. This choice will + * always be picked as the name of the generated extension method. + * After this first choice, all other possible indices in the range of 0 until the number + * of overloaded alternatives are returned. The secondary choices are used to find a matching method + * in `extensionMethod` if the first name has the wrong type. We thereby gain a level of insensitivity + * of how overloaded types are ordered between phases and picklings. + */ + private def extensionNames(imeth: Symbol): Stream[Name] = + imeth.owner.info.decl(imeth.name).tpe match { + case OverloadedType(_, alts) => + val index = alts indexOf imeth + assert(index >= 0, alts+" does not contain "+imeth) + def altName(index: Int) = newTermName("extension"+index+"$"+imeth.name) + altName(index) #:: ((0 until alts.length).toStream filter (index !=) map altName) + case tpe => + assert(tpe != NoType, imeth.name+" not found in "+imeth.owner+"'s decls: "+imeth.owner.info.decls) + Stream(newTermName("extension$"+imeth.name)) + } + + /** Return the extension method that corresponds to given instance method `meth`. + */ + def extensionMethod(imeth: Symbol): Symbol = atPhase(currentRun.refchecksPhase) { + val companionInfo = imeth.owner.companionModule.info + val candidates = extensionNames(imeth) map (companionInfo.decl(_)) + val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe) + assert(matching.nonEmpty, "no extension method found for "+imeth+" among "+candidates+"/"+extensionNames(imeth)) + matching.head + } + + private def normalize(stpe: Type, clazz: Symbol): Type = stpe match { + case PolyType(tparams, restpe) => + GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe, clazz)) + case MethodType(tparams, restpe) => + restpe + case _ => + stpe + } + + class Extender(unit: CompilationUnit) extends TypingTransformer(unit) { + + private val extensionDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]() + + def extensionMethInfo(extensionMeth: Symbol, origInfo: Type, clazz: Symbol): Type = { + var newTypeParams = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth) + val thisParamType = appliedType(clazz.typeConstructor, newTypeParams map (_.tpe)) + val thisParam = extensionMeth.newValueParameter(nme.SELF, extensionMeth.pos) setInfo thisParamType + def transform(clonedType: Type): Type = clonedType match { + case MethodType(params, restpe) => + // I assume it was a bug that this was dropping params... [Martin]: No, it wasn't; it's curried. + MethodType(List(thisParam), clonedType) + case NullaryMethodType(restpe) => + MethodType(List(thisParam), restpe) + } + val GenPolyType(tparams, restpe) = origInfo cloneInfo extensionMeth + GenPolyType(tparams ::: newTypeParams, transform(restpe) substSym (clazz.typeParams, newTypeParams)) + } + + private def allParams(tpe: Type): List[Symbol] = tpe match { + case MethodType(params, res) => params ::: allParams(res) + case _ => List() + } + + override def transform(tree: Tree): Tree = { + tree match { + case Template(_, _, _) => + if (currentOwner.isDerivedValueClass) { + extensionDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] + super.transform(tree) + } else if (currentOwner.isStaticOwner) { + super.transform(tree) + } else tree + case DefDef(_, _, tparams, vparamss, _, rhs) if tree.symbol.isMethodWithExtension => + val companion = currentOwner.companionModule + val origMeth = tree.symbol + val extensionName = extensionNames(origMeth).head + val extensionMeth = companion.moduleClass.newMethod(extensionName, origMeth.pos, origMeth.flags & ~OVERRIDE & ~PROTECTED | FINAL) + .setAnnotations(origMeth.annotations) + companion.info.decls.enter(extensionMeth) + val newInfo = extensionMethInfo(extensionMeth, origMeth.info, currentOwner) + extensionMeth setInfo newInfo + log("Value class %s spawns extension method.\n Old: %s\n New: %s".format( + currentOwner, + origMeth.defString, + extensionMeth.defString)) // extensionMeth.defStringSeenAs(origInfo + + def thisParamRef = gen.mkAttributedIdent(extensionMeth.info.params.head setPos extensionMeth.pos) + val GenPolyType(extensionTpeParams, extensionMono) = extensionMeth.info + val origTpeParams = (tparams map (_.symbol)) ::: currentOwner.typeParams + val extensionBody = rhs + .substTreeSyms(origTpeParams, extensionTpeParams) + .substTreeSyms(vparamss.flatten map (_.symbol), allParams(extensionMono).tail) + .substTreeThis(currentOwner, thisParamRef) + .changeOwner((origMeth, extensionMeth)) + extensionDefs(companion) += atPos(tree.pos) { DefDef(extensionMeth, extensionBody) } + val extensionCallPrefix = Apply( + gen.mkTypeApply(gen.mkAttributedRef(companion), extensionMeth, origTpeParams map (_.tpe)), + List(This(currentOwner))) + val extensionCall = atOwner(origMeth) { + localTyper.typedPos(rhs.pos) { + (extensionCallPrefix /: vparamss) { + case (fn, params) => Apply(fn, params map (param => Ident(param.symbol))) + } + } + } + deriveDefDef(tree)(_ => extensionCall) + case _ => + super.transform(tree) + } + } + + override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = + super.transformStats(stats, exprOwner) map { + case md @ ModuleDef(_, _, _) if extensionDefs contains md.symbol => + val defns = extensionDefs(md.symbol).toList map (member => + atOwner(md.symbol)(localTyper.typedPos(md.pos.focus)(member)) + ) + extensionDefs -= md.symbol + deriveModuleDef(md)(tmpl => deriveTemplate(tmpl)(_ ++ defns)) + case stat => + stat + } + } +} diff --git a/src/compiler/scala/tools/nsc/transform/InlineErasure.scala b/src/compiler/scala/tools/nsc/transform/InlineErasure.scala new file mode 100644 index 0000000000..0af3cf732f --- /dev/null +++ b/src/compiler/scala/tools/nsc/transform/InlineErasure.scala @@ -0,0 +1,9 @@ +package scala.tools.nsc +package transform + +trait InlineErasure { self: Erasure => + + import global._ + import definitions._ + +}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index 570eaba3a9..13ca8e55bc 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -25,7 +25,7 @@ abstract class LambdaLift extends InfoTransform { if (sym.isCapturedVariable) { val symClass = tpe.typeSymbol def refType(valueRef: Map[Symbol, Symbol], objectRefClass: Symbol) = - if (isValueClass(symClass) && symClass != UnitClass) valueRef(symClass).tpe + if (isPrimitiveValueClass(symClass) && symClass != UnitClass) valueRef(symClass).tpe else if (erasedTypes) objectRefClass.tpe else appliedType(objectRefClass.typeConstructor, List(tpe)) if (sym.hasAnnotation(VolatileAttr)) refType(volatileRefClass, VolatileObjectRefClass) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index c9794cc20f..639e060812 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -86,6 +86,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * nor do they have a setter (not if they are vals anyway). The usual * logic for setting bitmaps does therefor not work for such fields. * That's why they are excluded. + * Note: The `checkinit` option does not check if transient fields are initialized. */ private def needsInitFlag(sym: Symbol) = ( settings.checkInit.value @@ -95,6 +96,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { && !sym.accessed.hasFlag(PRESUPER) && !sym.isOuterAccessor && !(sym.owner isSubClass DelayedInitClass) + && !(sym.accessed hasAnnotation TransientAttr) ) /** Maps all parts of this type that refer to implementation classes to @@ -448,7 +450,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { if ((sym.hasAccessorFlag || (sym.isTerm && !sym.isMethod)) && sym.isPrivate && !(currentOwner.isGetter && currentOwner.accessed == sym) // getter - && !definitions.isValueClass(sym.tpe.resultType.typeSymbol) + && !definitions.isPrimitiveValueClass(sym.tpe.resultType.typeSymbol) && sym.owner == templ.symbol.owner && !sym.isLazy && !tree.isDef) { @@ -520,7 +522,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { localTyper = erasure.newTyper(rootContext.make(tree, currentOwner)) afterMixin(currentOwner.owner.info)//todo: needed? - if (!currentOwner.isTrait && !isValueClass(currentOwner)) + if (!currentOwner.isTrait && !isPrimitiveValueClass(currentOwner)) addMixedinMembers(currentOwner, unit) else if (currentOwner hasFlag lateINTERFACE) addLateInterfaceMembers(currentOwner) diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala new file mode 100644 index 0000000000..ef158a71f6 --- /dev/null +++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala @@ -0,0 +1,68 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2012 LAMP/EPFL + * @author Martin odersky + */ +package scala.tools.nsc +package transform + +/** This phase maps ErasedValueTypes to the underlying unboxed representation and + * performs peephole optimizations. + */ +trait PostErasure extends InfoTransform with TypingTransformers { + + val global: Global + import global._ + import definitions._ + + val phaseName: String = "posterasure" + + def newTransformer(unit: CompilationUnit): Transformer = new PostErasureTransformer(unit) + override def changesBaseClasses = false + + object elimErasedValueType extends TypeMap { + def apply(tp: Type) = tp match { + case ErasedValueType(clazz) => erasure.underlyingOfValueClass(clazz) + case _ => mapOver(tp) + } + } + + def transformInfo(sym: Symbol, tp: Type) = elimErasedValueType(tp) + + class PostErasureTransformer(unit: CompilationUnit) extends TypingTransformer(unit) { + + override def transform(tree: Tree) = + super.transform(tree) setType elimErasedValueType(tree.tpe) match { + case // new C(arg).underlying ==> arg + Apply(sel @ Select( + Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)), + acc), List()) + if atPhase(currentRun.erasurePhase) { + tpt.tpe.typeSymbol.isDerivedValueClass && + sel.symbol == tpt.tpe.typeSymbol.firstParamAccessor + } => + if (settings.debug.value) log("Removing "+tree+" -> "+arg) + arg + case // new C(arg1) == new C(arg2) ==> arg1 == arg2 + Apply(sel @ Select( + Apply(Select(New(tpt1), nme.CONSTRUCTOR), List(arg1)), + cmp), + List(Apply(Select(New(tpt2), nme.CONSTRUCTOR), List(arg2)))) + if atPhase(currentRun.erasurePhase) { + tpt1.tpe.typeSymbol.isDerivedValueClass && + (cmp == nme.EQ || cmp == nme.NE) && + tpt2.tpe.typeSymbol == tpt1.tpe.typeSymbol + } => + val result = Apply(Select(arg1, cmp) setPos sel.pos, List(arg2)) setPos tree.pos + log("shortcircuiting equality "+tree+" -> "+result) + localTyper.typed(result) + + case // arg.asInstanceOf[T] ==> arg if arg.tpe == T + Apply(TypeApply(cast @ Select(arg, asinstanceof), List(tpt)), List()) + if cast.symbol == Object_asInstanceOf && arg.tpe =:= tpt.tpe => // !!! <:< ? + if (settings.debug.value) log("Shortening "+tree+" -> "+arg) + arg + case tree1 => + tree1 + } + } +} diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 88ad458748..7b0f5254b6 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -66,7 +66,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { import definitions.{ RootClass, BooleanClass, UnitClass, ArrayClass, - ScalaValueClasses, isValueClass, isScalaValueType, + ScalaValueClasses, isPrimitiveValueClass, isScalaValueType, SpecializedClass, RepeatedParamClass, JavaRepeatedParamClass, AnyRefClass, ObjectClass, AnyRefModule, GroupOfSpecializable, uncheckedVarianceClass, ScalaInlineClass @@ -123,14 +123,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // then pos/spec-List.scala fails - why? Does this kind of check fail // for similar reasons? Does `sym.isAbstractType` make a difference? private def isSpecializedAnyRefSubtype(tp: Type, sym: Symbol) = { - specializedOn(sym).exists(s => !isValueClass(s)) && - !isValueClass(tp.typeSymbol) && + specializedOn(sym).exists(s => !isPrimitiveValueClass(s)) && + !isPrimitiveValueClass(tp.typeSymbol) && isBoundedGeneric(tp) //(tp <:< AnyRefClass.tpe) } private def isBoundedGeneric(tp: Type) = tp match { case TypeRef(_, sym, _) if sym.isAbstractType => (tp <:< AnyRefClass.tpe) - case TypeRef(_, sym, _) => !isValueClass(sym) + case TypeRef(_, sym, _) => !isPrimitiveValueClass(sym) case _ => false } @@ -348,7 +348,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { */ def specializesClass(sym: Symbol): Symbol = { val c = sym.companionClass - if (isValueClass(c)) c else AnyRefClass + if (isPrimitiveValueClass(c)) c else AnyRefClass } /** Return the types `sym` should be specialized at. This may be some of the primitive types @@ -587,7 +587,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { " => " + sClass.defStringSeenAs(sClass.typeOfThis) ) } - polyType(newClassTParams, ClassInfoType(parents ::: extraSpecializedMixins, decls1, sClass)) + GenPolyType(newClassTParams, ClassInfoType(parents ::: extraSpecializedMixins, decls1, sClass)) } afterSpecialize(sClass setInfo specializedInfoType) @@ -818,7 +818,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // the cloneInfo is necessary so that method parameter symbols are cloned at the new owner val methodType = sym.info.resultType.instantiateTypeParams(keys ++ tps, vals ++ tps1.map(_.tpe)).cloneInfo(specMember) - specMember setInfo polyType(tps1, methodType) + specMember setInfo GenPolyType(tps1, methodType) debuglog("expanded member: " + sym + ": " + sym.info + " -> " + specMember + @@ -994,7 +994,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = (tp1, tp2) match { case (TypeRef(_, sym1, _), _) if isSpecialized(sym1) => debuglog("Unify - basic case: " + tp1 + ", " + tp2) - if (isValueClass(tp2.typeSymbol)) + if (isPrimitiveValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1)) env + ((sym1, tp2)) else if (isSpecializedAnyRefSubtype(tp2, sym1)) env + ((sym1, tp2)) // env + ((sym1, AnyRefClass.tpe)) @@ -1130,7 +1130,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { ) val newScope = newScopeWith(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz): _*) // If tparams.isEmpty, this is just the ClassInfoType. - polyType(tparams, ClassInfoType(parents1, newScope, clazz)) + GenPolyType(tparams, ClassInfoType(parents1, newScope, clazz)) case _ => tpe } @@ -1342,7 +1342,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val env = typeEnv(specMember) val residualTargs = symbol.info.typeParams zip targs collect { - case (tvar, targ) if !env.contains(tvar) || !isValueClass(env(tvar).typeSymbol) => targ + case (tvar, targ) if !env.contains(tvar) || !isPrimitiveValueClass(env(tvar).typeSymbol) => targ } ifDebug(assert(residualTargs.length == specMember.info.typeParams.length, diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index d7b4171c65..ed9fee986f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -442,7 +442,6 @@ trait ContextErrors { def UnexpectedTreeAnnotationError(tree: Tree, unexpected: Tree) = NormalTypeError(tree, "unexpected tree after typing annotation: "+ unexpected) - // TODO no test case //typedExistentialTypeTree def AbstractionFromVolatileTypeError(vd: ValDef) = issueNormalTypeError(vd, "illegal abstraction from value with volatile type "+vd.symbol.tpe) @@ -465,8 +464,7 @@ trait ContextErrors { def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) = NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun)) - // can it still happen? see test case neg/t960.scala - // TODO no test case + // can it still happen? see test case neg/overloaded-unapply.scala def OverloadedUnapplyError(tree: Tree) = issueNormalTypeError(tree, "cannot resolve overloaded unapply") @@ -499,7 +497,6 @@ trait ContextErrors { } //doTypedApply - patternMode - // TODO: missing test case def TooManyArgsPatternError(fun: Tree) = NormalTypeError(fun, "too many arguments for unapply pattern, maximum = "+definitions.MaxTupleArity) @@ -534,14 +531,13 @@ trait ContextErrors { NormalTypeError(parent, "illegal inheritance from final "+mixin) def ParentSealedInheritanceError(parent: Tree, psym: Symbol) = - NormalTypeError(parent, "illegal inheritance from sealed " + psym + ": " + context.unit.source.file.canonicalPath + " != " + psym.sourceFile.canonicalPath) + NormalTypeError(parent, "illegal inheritance from sealed " + psym ) def ParentSelfTypeConformanceError(parent: Tree, selfType: Type) = NormalTypeError(parent, "illegal inheritance;\n self-type "+selfType+" does not conform to "+ parent +"'s selftype "+parent.tpe.typeOfThis) - // TODO: missing test case def ParentInheritedTwiceError(parent: Tree, parentSym: Symbol) = NormalTypeError(parent, parentSym+" is inherited twice") @@ -572,7 +568,6 @@ trait ContextErrors { setError(tree) } - //TODO Needs test case def ConstructorPrefixError(tree: Tree, restpe: Type) = { issueNormalTypeError(tree, restpe.prefix+" is not a legal prefix for a constructor") setError(tree) @@ -597,7 +592,6 @@ trait ContextErrors { setError(tree) } - // TODO needs test case // cases where we do not necessarily return trees def DependentMethodTpeConversionToFunctionError(tree: Tree, tp: Type) = issueNormalTypeError(tree, "method with dependent type "+tp+" cannot be converted to function value") @@ -606,11 +600,9 @@ trait ContextErrors { def StarPatternWithVarargParametersError(tree: Tree) = issueNormalTypeError(tree, "star patterns must correspond with varargs parameters") - // TODO missing test case def FinitaryError(tparam: Symbol) = issueSymbolTypeError(tparam, "class graph is not finitary because type parameter "+tparam.name+" is expansively recursive") - // TODO missing test case for a second case def QualifyingClassError(tree: Tree, qual: Name) = { issueNormalTypeError(tree, if (qual.isEmpty) tree + " can be used only in a class, object, or template" @@ -778,7 +770,7 @@ trait ContextErrors { def PolymorphicExpressionInstantiationError(tree: Tree, undetparams: List[Symbol], pt: Type) = issueNormalTypeError(tree, "polymorphic expression cannot be instantiated to expected type" + - foundReqMsg(polyType(undetparams, skipImplicit(tree.tpe)), pt)) + foundReqMsg(GenPolyType(undetparams, skipImplicit(tree.tpe)), pt)) //checkCheckable def TypePatternOrIsInstanceTestError(tree: Tree, tp: Type) = diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 2c564c097f..a1ba8a2982 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -43,8 +43,7 @@ trait Contexts { self: Analyzer => * - if option `-Yno-imports` is given, nothing is imported * - if the unit is java defined, only `java.lang` is imported * - if option `-Yno-predef` is given, if the unit body has an import of Predef - * among its leading imports, or if the tree is [[scala.ScalaObject]] - * or [[scala.Predef]], `Predef` is not imported. + * among its leading imports, or if the tree is [[scala.Predef]], `Predef` is not imported. */ protected def rootImports(unit: CompilationUnit): List[Symbol] = { import definitions._ diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 0ddacf7d36..7d1198a4a2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1094,7 +1094,11 @@ trait Implicits { /** Creates a tree that calls the factory method called constructor in object reflect.Manifest */ def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree = if (args contains EmptyTree) EmptyTree - else typedPos(tree.pos.focus)(gen.mkManifestFactoryCall(full, constructor, tparg, args.toList)) + else typedPos(tree.pos.focus) { + val mani = gen.mkManifestFactoryCall(full, constructor, tparg, args.toList) + if (settings.debug.value) println("generated manifest: "+mani) // DEBUG + mani + } /** Creates a tree representing one of the singleton manifests.*/ def findSingletonManifest(name: String) = typedPos(tree.pos.focus) { @@ -1119,7 +1123,7 @@ trait Implicits { case ConstantType(value) => manifestOfType(tp1.deconst, full) case TypeRef(pre, sym, args) => - if (isValueClass(sym) || isPhantomClass(sym)) { + if (isPrimitiveValueClass(sym) || isPhantomClass(sym)) { findSingletonManifest(sym.name.toString) } else if (sym == ObjectClass || sym == AnyRefClass) { findSingletonManifest("Object") diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index c0c801910c..8b3bc253fd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -196,6 +196,10 @@ trait Infer { /* -- Error Messages --------------------------------------------------- */ def setError[T <: Tree](tree: T): T = { + if (settings.debug.value) { // DEBUG + println("set error: "+tree); + throw new Error() + } def name = newTermName("<error: " + tree.symbol + ">") def errorClass = if (context.reportErrors) context.owner.newErrorClass(name.toTypeName) else stdErrorClass def errorValue = if (context.reportErrors) context.owner.newErrorValue(name) else stdErrorValue diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 088a56cd7b..f32ad9293c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -69,6 +69,9 @@ trait MethodSynthesis { import synthesisUtil._ class ClassMethodSynthesis(val clazz: Symbol, localTyper: Typer) { + def mkThis = This(clazz) setPos clazz.pos.focus + def mkThisSelect(sym: Symbol) = atPos(clazz.pos.focus)(Select(mkThis, sym)) + private def isOverride(name: TermName) = clazzMember(name).alternatives exists (sym => !sym.isDeferred && (sym.owner != clazz)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 82bcb93965..c5fb13a5a9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -73,7 +73,7 @@ trait Namers extends MethodSynthesis { classAndNamerOfModule.clear() } - abstract class Namer(val context: Context) extends MethodSynth with NamerContextErrors { + abstract class Namer(val context: Context) extends MethodSynth with NamerContextErrors { thisNamer => import NamerErrorGen._ val typer = newTyper(context) @@ -99,6 +99,13 @@ trait Namers extends MethodSynthesis { owner.unsafeTypeParams foreach (paramContext.scope enter _) newNamer(paramContext) } + + def enclosingNamerWithScope(scope: Scope) = { + var cx = context + while (cx != NoContext && cx.scope != scope) cx = cx.outer + if (cx == NoContext || cx == context) thisNamer + else newNamer(cx) + } def enterValueParams(vparamss: List[List[ValDef]]): List[List[Symbol]] = { mmap(vparamss) { param => @@ -449,7 +456,7 @@ trait Namers extends MethodSynthesis { // The object Foo is still in scope, but because it is not compiled in current run // it should be ditched and a new one created. if (m != NoSymbol && currentRun.compiles(m)) m - else enterSyntheticSym(creator(cdef)) + else enterSyntheticSym(atPos(cdef.pos.focus)(creator(cdef))) } private def checkSelectors(tree: Import): Unit = { @@ -709,6 +716,17 @@ trait Namers extends MethodSynthesis { if (needsCycleCheck && !typer.checkNonCyclic(tree.pos, tp)) sym setInfo ErrorType } + // tree match { + // case ClassDef(_, _, _, impl) => + // val parentsOK = ( + // treeInfo.isInterface(sym, impl.body) + // || (sym eq ArrayClass) + // || (sym isSubClass AnyValClass) + // ) + // if (!parentsOK) + // ensureParent(sym, AnyRefClass) + // case _ => () + // } } def moduleClassTypeCompleter(tree: Tree) = { @@ -840,6 +858,7 @@ trait Namers extends MethodSynthesis { } val parents = typer.parentTypes(templ) map checkParent + enterSelf(templ.self) val decls = newScope @@ -890,7 +909,7 @@ trait Namers extends MethodSynthesis { val tparams0 = typer.reenterTypeParams(tparams) val resultType = templateSig(impl) - polyType(tparams0, resultType) + GenPolyType(tparams0, resultType) } private def methodSig(ddef: DefDef, mods: Modifiers, tparams: List[TypeDef], @@ -933,7 +952,7 @@ trait Namers extends MethodSynthesis { // DEPMETTODO: check not needed when they become on by default checkDependencies(restpe) - polyType( + GenPolyType( tparamSyms, // deSkolemized symbols -- TODO: check that their infos don't refer to method args? if (vparamSymss.isEmpty) NullaryMethodType(restpe) // vparamss refer (if they do) to skolemized tparams @@ -1187,7 +1206,7 @@ trait Namers extends MethodSynthesis { // However, separate compilation requires the symbol info to be // loaded to do this check, but loading the info will probably // lead to spurious cyclic errors. So omit the check. - polyType(tparamSyms, tp) + GenPolyType(tparamSyms, tp) } /** Given a case class @@ -1251,8 +1270,16 @@ trait Namers extends MethodSynthesis { if (sym.isModule) annotate(sym.moduleClass) def getSig = tree match { - case ClassDef(_, _, tparams, impl) => - createNamer(tree).classSig(tparams, impl) + case cdef @ ClassDef(_, name, tparams, impl) => + val clazz = tree.symbol + val result = createNamer(tree).classSig(tparams, impl) + clazz setInfo result + if (clazz.isDerivedValueClass) { + log("Ensuring companion for derived value class " + name + " at " + cdef.pos.show) + clazz setFlag FINAL + enclosingNamerWithScope(clazz.owner.info.decls).ensureCompanionObject(cdef) + } + result case ModuleDef(_, _, impl) => val clazz = sym.moduleClass @@ -1308,6 +1335,22 @@ trait Namers extends MethodSynthesis { } } + def includeParent(tpe: Type, parent: Symbol): Type = tpe match { + case PolyType(tparams, restpe) => + PolyType(tparams, includeParent(restpe, parent)) + case ClassInfoType(parents, decls, clazz) => + if (parents exists (_.typeSymbol == parent)) tpe + else ClassInfoType(parents :+ parent.tpe, decls, clazz) + case _ => + tpe + } + + def ensureParent(clazz: Symbol, parent: Symbol) = { + val info0 = clazz.info + val info1 = includeParent(info0, parent) + if (info0 ne info1) clazz setInfo info1 + } + class LogTransitions[S](onEnter: S => String, onExit: S => String) { val enabled = settings.debug.value @inline final def apply[T](entity: S)(body: => T): T = { @@ -1411,7 +1454,7 @@ trait Namers extends MethodSynthesis { checkNoConflict(PRIVATE, PROTECTED) // checkNoConflict(PRIVATE, OVERRIDE) // this one leads to bad error messages like #4174, so catch in refchecks // checkNoConflict(PRIVATE, FINAL) // can't do this because FINAL also means compile-time constant - checkNoConflict(ABSTRACT, FINAL) + // checkNoConflict(ABSTRACT, FINAL) // this one gives a bad error for non-@inline classes which extend AnyVal // @PP: I added this as a sanity check because these flags are supposed to be // converted to ABSOVERRIDE before arriving here. checkNoConflict(ABSTRACT, OVERRIDE) diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index e8d3b7a7de..c621497618 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -224,7 +224,7 @@ trait NamesDefaults { self: Analyzer => case Select(sp @ Super(_, _), _) if isConstr => // 'moduleQual' fixes #3207. selection of the companion module of the // superclass needs to have the same prefix as the superclass. - blockWithoutQualifier(moduleQual(baseFun.pos, sp.symbol.tpe.parents.head)) + blockWithoutQualifier(moduleQual(baseFun.pos, sp.symbol.tpe.firstParent)) // self constructor calls (in secondary constructors) case Select(tp, name) if isConstr => diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 507ffd55d7..ec42d251ff 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -525,7 +525,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R !other.isDeferred && other.isJavaDefined && { // #3622: erasure operates on uncurried types -- // note on passing sym in both cases: only sym.isType is relevant for uncurry.transformInfo - def uncurryAndErase(tp: Type) = erasure.erasure(sym, uncurry.transformInfo(sym, tp)) + // !!! erasure.erasure(sym, uncurry.transformInfo(sym, tp)) gives erreneous of inaccessible type - check whether that's still the case! + def uncurryAndErase(tp: Type) = erasure.erasure(sym)(uncurry.transformInfo(sym, tp)) val tp1 = uncurryAndErase(clazz.thisType.memberType(sym)) val tp2 = uncurryAndErase(clazz.thisType.memberType(other)) afterErasure(tp1 matches tp2) @@ -693,8 +694,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R if (abstractErrors.nonEmpty) unit.error(clazz.pos, abstractErrorMessage) - } else if (clazz.isTrait) { - // prevent abstract methods in interfaces that override final members in Object; see #4431 + } + else if (clazz.isTrait && !(clazz isSubClass AnyValClass)) { + // For non-AnyVal classes, prevent abstract methods in interfaces that override + // final members in Object; see #4431 for (decl <- clazz.info.decls.iterator) { val overridden = decl.overriddenSymbol(ObjectClass) if (overridden.isFinal) @@ -1061,7 +1064,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R def isBoolean(s: Symbol) = unboxedValueClass(s) == BooleanClass def isUnit(s: Symbol) = unboxedValueClass(s) == UnitClass def isNumeric(s: Symbol) = isNumericValueClass(unboxedValueClass(s)) || (s isSubClass ScalaNumberClass) - def isSpecial(s: Symbol) = isValueClass(unboxedValueClass(s)) || (s isSubClass ScalaNumberClass) || isMaybeValue(s) + def isSpecial(s: Symbol) = isPrimitiveValueClass(unboxedValueClass(s)) || (s isSubClass ScalaNumberClass) || isMaybeValue(s) def possibleNumericCount = onSyms(_ filter (x => isNumeric(x) || isMaybeValue(x)) size) val nullCount = onSyms(_ filter (_ == NullClass) size) @@ -1082,7 +1085,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R if (nullCount == 2) nonSensible("", true) // null == null else if (nullCount == 1) { - if (onSyms(_ exists isValueClass)) // null == 5 + if (onSyms(_ exists isPrimitiveValueClass)) // null == 5 nonSensible("", false) else if (onTrees( _ exists isNew)) // null == new AnyRef nonSensibleWarning("a fresh object", false) @@ -1122,7 +1125,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R // warn only if they have no common supertype below Object else { val common = global.lub(List(actual.tpe, receiver.tpe)) - if (common.typeSymbol == ScalaObjectClass || (ObjectClass.tpe <:< common)) + if (ObjectClass.tpe <:< common) unrelatedTypes() } } @@ -1470,7 +1473,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R if (settings.Xmigration28.value) checkMigration(sym, tree.pos) - if (currentClass != sym.owner && sym.hasLocalFlag) { + if (sym eq NoSymbol) { + unit.warning(tree.pos, "Select node has NoSymbol! " + tree + " / " + tree.tpe) + } + else if (currentClass != sym.owner && sym.hasLocalFlag) { var o = currentClass var hidden = false while (!hidden && o != sym.owner && o != sym.owner.moduleClass && !o.isPackage) { @@ -1517,6 +1523,14 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R case _ => () } + // Verify classes extending AnyVal meet the requirements + private def checkAnyValSubclass(clazz: Symbol) = { + if ((clazz isSubClass AnyValClass) && !isPrimitiveValueClass(clazz)) { + if (clazz.isTrait) + unit.error(clazz.pos, "Only classes (not traits) are allowed to extend AnyVal") + } + } + override def transform(tree: Tree): Tree = { val savedLocalTyper = localTyper val savedCurrentApplication = currentApplication @@ -1548,6 +1562,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R checkOverloadedRestrictions(currentOwner) val bridges = addVarargBridges(currentOwner) checkAllOverrides(currentOwner) + checkAnyValSubclass(currentOwner) if (bridges.nonEmpty) deriveTemplate(tree)(_ ::: bridges) else tree case dc@TypeTreeWithDeferredRefCheck() => assert(false, "adapt should have turned dc: TypeTreeWithDeferredRefCheck into tpt: TypeTree, with tpt.original == dc"); dc diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 243e685b13..4248b6f024 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -266,6 +266,9 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } transformSuperSelect(sel) + case DefDef(mods, name, tparams, vparamss, tpt, rhs) if tree.symbol.isMethodWithExtension => + treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, withInvalidOwner(transform(rhs))) + case TypeApply(sel @ Select(qual, name), args) => mayNeedProtectedAccessor(sel, args, true) diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 7559b78db3..2f4eff30d2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -39,6 +39,7 @@ trait SyntheticMethods extends ast.TreeDSL { /** Add the synthetic methods to case classes. */ def addSyntheticMethods(templ: Template, clazz0: Symbol, context: Context): Template = { + if (phase.erasedTypes) return templ @@ -48,6 +49,15 @@ trait SyntheticMethods extends ast.TreeDSL { ) import synthesizer._ + if (clazz0 == AnyValClass || isPrimitiveValueClass(clazz0)) return { + if (clazz0.info member nme.getClass_ isDeferred) { + // XXX dummy implementation for now + val getClassMethod = createMethod(nme.getClass_, getClassReturnType(clazz.tpe))(_ => NULL) + deriveTemplate(templ)(_ :+ getClassMethod) + } + else templ + } + val originalAccessors = clazz.caseFieldAccessors // private ones will have been renamed -- make sure they are entered // in the original order. @@ -77,7 +87,7 @@ trait SyntheticMethods extends ast.TreeDSL { ) def forwardToRuntime(method: Symbol): Tree = - forwardMethod(method, getMember(ScalaRunTimeModule, method.name prepend "_"))(This(clazz) :: _) + forwardMethod(method, getMember(ScalaRunTimeModule, method.name prepend "_"))(mkThis :: _) // Any member, including private def hasConcreteImpl(name: Name) = @@ -85,8 +95,8 @@ trait SyntheticMethods extends ast.TreeDSL { def hasOverridingImplementation(meth: Symbol) = { val sym = clazz.info nonPrivateMember meth.name - sym.alternatives filterNot (_ eq meth) exists { m0 => - !m0.isDeferred && !m0.isSynthetic && (typeInClazz(m0) matches typeInClazz(meth)) + sym.alternatives exists { m0 => + (m0 ne meth) && !m0.isDeferred && !m0.isSynthetic && (m0.owner != AnyValClass) && (typeInClazz(m0) matches typeInClazz(meth)) } } def readConstantValue[T](name: String, default: T = null.asInstanceOf[T]): T = { @@ -97,7 +107,7 @@ trait SyntheticMethods extends ast.TreeDSL { } def productIteratorMethod = { createMethod(nme.productIterator, iteratorOfType(accessorLub))(_ => - gen.mkMethodCall(ScalaRunTimeModule, nme.typedProductIterator, List(accessorLub), List(This(clazz))) + gen.mkMethodCall(ScalaRunTimeModule, nme.typedProductIterator, List(accessorLub), List(mkThis)) ) } def projectionMethod(accessor: Symbol, num: Int) = { @@ -111,13 +121,49 @@ trait SyntheticMethods extends ast.TreeDSL { // def productElementNameMethod = perElementMethod(nme.productElementName, StringClass.tpe)(x => LIT(x.name.toString)) + var syntheticCanEqual = false + /** The canEqual method for case classes. * def canEqual(that: Any) = that.isInstanceOf[This] */ - def canEqualMethod: Tree = ( + def canEqualMethod: Tree = { + syntheticCanEqual = true createMethod(nme.canEqual_, List(AnyClass.tpe), BooleanClass.tpe)(m => Ident(m.firstParam) IS_OBJ classExistentialType(clazz)) - ) + } + + /** (that.isInstanceOf[this.C]) + * where that is the given methods first parameter. + */ + def thatTest(eqmeth: Symbol): Tree = + gen.mkIsInstanceOf(Ident(eqmeth.firstParam), typeCaseType(clazz), true, false) + + /** (that.asInstanceOf[this.C]) + * where that is the given methods first parameter. + */ + def thatCast(eqmeth: Symbol): Tree = + gen.mkCast(Ident(eqmeth.firstParam), clazz.tpe) + + /** The equality method core for case classes and inline clases. + * 1+ args: + * (that.isInstanceOf[this.C]) && { + * val x$1 = that.asInstanceOf[this.C] + * (this.arg_1 == x$1.arg_1) && (this.arg_2 == x$1.arg_2) && ... && (x$1 canEqual this) + * } + * Drop canBuildFrom part if class is final and canBuildFrom is synthesized + */ + def equalsCore(eqmeth: Symbol, accessors: List[Symbol]) = { + val otherName = context.unit.freshTermName(clazz.name + "$") + val otherSym = eqmeth.newValue(otherName, eqmeth.pos, SYNTHETIC) setInfo clazz.tpe + val pairwise = accessors map (acc => fn(Select(mkThis, acc), acc.tpe member nme.EQ, Select(Ident(otherSym), acc))) + val canEq = gen.mkMethodCall(otherSym, nme.canEqual_, Nil, List(mkThis)) + val tests = if (clazz.isDerivedValueClass || clazz.isFinal && syntheticCanEqual) pairwise else pairwise :+ canEq + + thatTest(eqmeth) AND Block( + ValDef(otherSym, thatCast(eqmeth)), + AND(tests: _*) + ) + } /** The equality method for case classes. * 0 args: @@ -130,34 +176,34 @@ trait SyntheticMethods extends ast.TreeDSL { * } * } */ - def equalsClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => - val arg0 = Ident(m.firstParam) - val thatTest = gen.mkIsInstanceOf(arg0, classExistentialType(clazz), true, false) - val thatCast = gen.mkCast(arg0, clazz.tpe) - - def argsBody: Tree = { - val otherName = context.unit.freshTermName(clazz.name + "$") - val otherSym = m.newValue(otherName, m.pos, SYNTHETIC) setInfo clazz.tpe - val pairwise = accessors map (acc => fn(Select(This(clazz), acc), acc.tpe member nme.EQ, Select(Ident(otherSym), acc))) - val canEq = gen.mkMethodCall(otherSym, nme.canEqual_, Nil, List(This(clazz))) - def block = Block(ValDef(otherSym, thatCast), AND(pairwise :+ canEq: _*)) - - (This(clazz) ANY_EQ arg0) OR { - thatTest AND Block( - ValDef(otherSym, thatCast), - AND(pairwise :+ canEq: _*) - ) - } - } + def equalsCaseClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => if (accessors.isEmpty) - thatTest AND ((thatCast DOT nme.canEqual_)(This(clazz))) + if (clazz.isFinal) thatTest(m) + else thatTest(m) AND ((thatCast(m) DOT nme.canEqual_)(mkThis)) else - argsBody + (mkThis ANY_EQ Ident(m.firstParam)) OR equalsCore(m, accessors) + } + + /** The equality method for value classes + * def equals(that: Any) = (this.asInstanceOf[AnyRef]) eq that.asInstanceOf[AnyRef]) || { + * (that.isInstanceOf[this.C]) && { + * val x$1 = that.asInstanceOf[this.C] + * (this.underlying == that.underlying + */ + def equalsDerivedValueClassMethod: Tree = createMethod(nme.equals_, List(AnyClass.tpe), BooleanClass.tpe) { m => + equalsCore(m, List(clazz.firstParamAccessor)) + } + + /** The hashcode method for value classes + * def hashCode(): Int = this.underlying.hashCode + */ + def hashCodeDerivedValueClassMethod: Tree = createMethod(nme.hashCode_, Nil, IntClass.tpe) { m => + Select(mkThisSelect(clazz.firstParamAccessor), nme.hashCode_) } /** The _1, _2, etc. methods to implement ProductN. */ - def productNMethods = { + def productNMethods = { val accs = accessors.toIndexedSeq 1 to arity map (num => productProj(arity, num) -> (() => projectionMethod(accs(num - 1), num))) } @@ -167,7 +213,7 @@ trait SyntheticMethods extends ast.TreeDSL { List( Product_productPrefix -> (() => constantNullary(nme.productPrefix, clazz.name.decode)), Product_productArity -> (() => constantNullary(nme.productArity, arity)), - Product_productElement -> (() => perElementMethod(nme.productElement, accessorLub)(Ident)), + Product_productElement -> (() => perElementMethod(nme.productElement, accessorLub)(mkThisSelect)), Product_iterator -> (() => productIteratorMethod), Product_canEqual -> (() => canEqualMethod) // This is disabled pending a reimplementation which doesn't add any @@ -176,10 +222,19 @@ trait SyntheticMethods extends ast.TreeDSL { ) } + def valueClassMethods = List( + Any_hashCode -> (() => hashCodeDerivedValueClassMethod), + Any_equals -> (() => equalsDerivedValueClassMethod) + ) + def caseClassMethods = productMethods ++ productNMethods ++ Seq( Object_hashCode -> (() => forwardToRuntime(Object_hashCode)), Object_toString -> (() => forwardToRuntime(Object_toString)), - Object_equals -> (() => equalsClassMethod) + Object_equals -> (() => equalsCaseClassMethod) + ) + + def valueCaseClassMethods = productMethods ++ productNMethods ++ valueClassMethods ++ Seq( + Any_toString -> (() => forwardToRuntime(Object_toString)) ) def caseObjectMethods = productMethods ++ Seq( @@ -203,10 +258,14 @@ trait SyntheticMethods extends ast.TreeDSL { def synthesize(): List[Tree] = { val methods = ( - if (!clazz.isCase) Nil - else if (clazz.isModuleClass) caseObjectMethods - else caseClassMethods + if (clazz.isCase) + if (clazz.isDerivedValueClass) valueCaseClassMethods + else if (clazz.isModuleClass) caseObjectMethods + else caseClassMethods + else if (clazz.isDerivedValueClass) valueClassMethods + else Nil ) + def impls = for ((m, impl) <- methods ; if !hasOverridingImplementation(m)) yield impl() def extras = ( if (needsReadResolve) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9ff86e69eb..25f3e7af5c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -637,7 +637,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // to escape scope here, e.g. pos/t1107. I'm not sure how to properly handle this // so for now it requires the type symbol be public. && pre.typeSymbol.isPublic) - tree setType MethodType(Nil, erasure.getClassReturnType(pre)) + tree setType MethodType(Nil, getClassReturnType(pre)) else tree } @@ -1266,8 +1266,36 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } + private def validateDerivedValueClass(clazz: Symbol, body: List[Tree]) = { + if (clazz.isTrait) + unit.error(clazz.pos, "only classes (not traits) are allowed to extend AnyVal") + if (!clazz.isStatic) + unit.error(clazz.pos, "value class may not be a "+ + (if (clazz.owner.isTerm) "local class" else "member of another class")) + val constr = clazz.primaryConstructor + if ((constr hasFlag (PRIVATE | PROTECTED)) || constr.privateWithin != NoSymbol) + unit.error(constr.pos, "value class must have public primary constructor") + clazz.info.decls.toList.filter(acc => acc.isMethod && (acc hasFlag PARAMACCESSOR)) match { + case List(acc) => + def isUnderlyingAcc(sym: Symbol) = + sym == acc || acc.hasAccessorFlag && sym == acc.accessed + if (acc.accessBoundary(clazz) != RootClass) + unit.error(acc.pos, "value class needs to have a publicly accessible val parameter") + for (stat <- body) + if (!treeInfo.isAllowedInUniversalTrait(stat) && !isUnderlyingAcc(stat.symbol)) + unit.error(stat.pos, + if (stat.symbol hasFlag PARAMACCESSOR) "illegal parameter for value class" + else "this statement is not allowed in value class: "+stat) + case x => + unit.error(clazz.pos, "value class needs to have exactly one public val parameter") + } + for (tparam <- clazz.typeParams) + if (tparam hasAnnotation definitions.SpecializedClass) + unit.error(tparam.pos, "type parameter of value class may not be specialized") + } + def parentTypes(templ: Template): List[Tree] = - if (templ.parents.isEmpty) List() + if (templ.parents.isEmpty) List(atPos(templ.pos)(TypeTree(AnyRefClass.tpe))) else try { val clazz = context.owner // Normalize supertype and mixins so that supertype is always a class, not a trait. @@ -1279,9 +1307,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val supertpt1 = typedType(supertpt) if (!supertpt1.isErrorTyped) { mixins = supertpt1 :: mixins - supertpt = TypeTree(supertpt1.tpe.parents.head) setPos supertpt.pos.focus + supertpt = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus } } + if (supertpt.tpe.typeSymbol == AnyClass && firstParent.isTrait) + supertpt.tpe = AnyRefClass.tpe // Determine // - supertparams: Missing type parameters from supertype @@ -1371,12 +1401,15 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { else xs ) } + fixDuplicates(supertpt :: mixins) mapConserve (tpt => checkNoEscaping.privates(clazz, tpt)) } catch { case ex: TypeError => // fallback in case of cyclic errors // @H none of the tests enter here but I couldn't rule it out + log("Type error calculating parents in template " + templ) + log("Error: " + ex) ParentTypesError(templ, ex) List(TypeTree(AnyRefClass.tpe)) } @@ -1413,13 +1446,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (psym.isFinal) pending += ParentFinalInheritanceError(parent, psym) - if (psym.isSealed && !phase.erasedTypes) { - // AnyVal is sealed, but we have to let the value classes through manually - if (context.unit.source.file == psym.sourceFile || isValueClass(context.owner)) + if (psym.isSealed && !phase.erasedTypes) + if (context.unit.source.file == psym.sourceFile) psym addChild context.owner else pending += ParentSealedInheritanceError(parent, psym) - } + if (!(selfType <:< parent.tpe.typeOfThis) && !phase.erasedTypes && !context.owner.isSynthetic && // don't check synthetic concrete classes for virtuals (part of DEVIRTUALIZE) @@ -1485,6 +1517,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { _.typedTemplate(cdef.impl, parentTypes(cdef.impl)) } val impl2 = finishMethodSynthesis(impl1, clazz, context) + if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.firstParent.normalize.typeSymbol == AnyClass) + for (stat <- impl2.body) + if (!treeInfo.isAllowedInUniversalTrait(stat)) + unit.error(stat.pos, "this statement is not allowed in universal trait extending from class Any: "+stat) if ((clazz != ClassfileAnnotationClass) && (clazz isNonBottomSubClass ClassfileAnnotationClass)) restrictionWarning(cdef.pos, unit, @@ -1601,6 +1637,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.owner.isPackageClass) unit.error(clazz.pos, "inner classes cannot be classfile annotations") + if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType]) @@ -1609,6 +1646,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { else templ.body flatMap rewrappingWrapperTrees(namer.finishGetterSetter(Typer.this, _)) val body1 = typedStats(body, templ.symbol) + + if (clazz.isDerivedValueClass) + validateDerivedValueClass(clazz, body1) + treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe } @@ -1682,7 +1723,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { * @param rhs ... */ def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) { - debuglog("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug + log("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug def decompose(call: Tree): (Tree, List[Tree]) = call match { case Apply(fn, args) => val (superConstr, args1) = decompose(fn) @@ -1861,8 +1902,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe) } - if (meth.isPrimaryConstructor && meth.isClassConstructor && !isPastTyper && !reporter.hasErrors) - computeParamAliases(meth.owner, vparamss1, rhs1) + if (meth.isPrimaryConstructor && meth.isClassConstructor && !isPastTyper && !reporter.hasErrors && !meth.owner.isSubClass(AnyValClass)) { + // At this point in AnyVal there is no supercall, which will blow up + // in computeParamAliases; there's nothing to be computed for Anyval anyway. + computeParamAliases(meth.owner, vparamss1, rhs1) + } + if (tpt1.tpe.typeSymbol != NothingClass && !context.returnsSeen && rhs1.tpe.typeSymbol != NothingClass) rhs1 = checkDead(rhs1) @@ -1881,6 +1926,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } if (meth.isStructuralRefinementMember) checkMethodStructuralCompatible(meth) + treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType } @@ -2615,8 +2661,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { /** This is translating uses of List() into Nil. This is less * than ideal from a consistency standpoint, but it shouldn't be * altered without due caution. + * ... this also causes bootstrapping cycles if List_apply is + * forced during kind-arity checking, so it is guarded by additional + * tests to ensure we're sufficiently far along. */ - if (fun.symbol == List_apply && args.isEmpty && !forInteractive) + if (args.isEmpty && !forInteractive && fun.symbol.isInitialized && ListModule.hasCompleteInfo && (fun.symbol == List_apply)) atPos(tree.pos)(gen.mkNil setType restpe) else constfold(treeCopy.Apply(tree, fun, args1) setType ifPatternSkipFormals(restpe)) @@ -3154,7 +3203,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // as we don't know which alternative to choose... here we do map2Conserve(args, tparams) { //@M! the polytype denotes the expected kind - (arg, tparam) => typedHigherKindedType(arg, mode, polyType(tparam.typeParams, AnyClass.tpe)) + (arg, tparam) => typedHigherKindedType(arg, mode, GenPolyType(tparam.typeParams, AnyClass.tpe)) } } else // @M: there's probably something wrong when args.length != tparams.length... (triggered by bug #320) // Martin, I'm using fake trees, because, if you use args or arg.map(typedType), @@ -3217,6 +3266,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } def typedAnnotated(ann: Tree, arg1: Tree): Tree = { + def mkTypeTree(tpe: Type) = TypeTree(tpe) setOriginal tree setPos tree.pos.focus /** mode for typing the annotation itself */ val annotMode = mode & ~TYPEmode | EXPRmode @@ -3262,19 +3312,20 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { arg1 // simply drop erroneous annotations else { ann.tpe = atype - TypeTree(atype) setOriginal tree + mkTypeTree(atype) } } else { // the annotation was typechecked before - TypeTree(ann.tpe) setOriginal tree + mkTypeTree(ann.tpe) } - } else { + } + else { if (ann.tpe == null) { val annotInfo = typedAnnotation(ann, annotMode) ann.tpe = arg1.tpe.withAnnotation(annotInfo) } val atype = ann.tpe - Typed(arg1, TypeTree(atype) setOriginal tree setPos tree.pos.focus) setPos tree.pos setType atype + Typed(arg1, mkTypeTree(atype)) setPos tree.pos setType atype } } @@ -3579,7 +3630,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val Select(qual, name) = fun tryTypedArgs(args, forArgMode(fun, mode)) match { case Some(args1) => - assert((args1.length == 0) || !args1.head.tpe.isErroneous, "try typed args is ok") val qual1 = if (!pt.isError) adaptToArguments(qual, name, args1, pt, true, true) else qual @@ -3756,16 +3806,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - val owntype = - if (mix.isEmpty) { - if ((mode & SUPERCONSTRmode) != 0) - if (clazz.info.parents.isEmpty) AnyRefClass.tpe // can happen due to cyclic references ==> #1036 - else clazz.info.parents.head - else intersectionType(clazz.info.parents) - } else { - findMixinSuper(clazz.tpe) - } - + val owntype = ( + if (!mix.isEmpty) findMixinSuper(clazz.tpe) + else if ((mode & SUPERCONSTRmode) != 0) clazz.info.firstParent + else intersectionType(clazz.info.parents) + ) treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype) } @@ -4149,7 +4194,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // if symbol hasn't been fully loaded, can't check kind-arity else map2Conserve(args, tparams) { (arg, tparam) => //@M! the polytype denotes the expected kind - typedHigherKindedType(arg, mode, polyType(tparam.typeParams, AnyClass.tpe)) + typedHigherKindedType(arg, mode, GenPolyType(tparam.typeParams, AnyClass.tpe)) } val argtypes = args1 map (_.tpe) @@ -4317,7 +4362,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { case Typed(expr0, tpt @ Ident(tpnme.WILDCARD_STAR)) => val expr = typed(expr0, onlyStickyModes(mode), WildcardType) def subArrayType(pt: Type) = - if (isValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt) + if (isPrimitiveValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt) else { val tparam = context.owner freshExistential "" setInfo TypeBounds.upper(pt) newExistentialType(List(tparam), arrayType(tparam.tpe)) @@ -4362,7 +4407,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // @M maybe the well-kindedness check should be done when checking the type arguments conform to the type parameters' bounds? val args1 = if (sameLength(args, tparams)) map2Conserve(args, tparams) { //@M! the polytype denotes the expected kind - (arg, tparam) => typedHigherKindedType(arg, mode, polyType(tparam.typeParams, AnyClass.tpe)) + (arg, tparam) => typedHigherKindedType(arg, mode, GenPolyType(tparam.typeParams, AnyClass.tpe)) } else { //@M this branch is correctly hit for an overloaded polymorphic type. It also has to handle erroneous cases. // Until the right alternative for an overloaded method is known, be very liberal, @@ -4682,6 +4727,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // AnyRef, but the AnyRef type alias is entered after the scala package is // loaded and completed, so that ScalaObject is unpickled while AnyRef is not // yet defined ) + // !!! TODO - revisit now that ScalaObject is gone. result setType(restpe) } else { // must not normalize: type application must be (bounds-)checked (during RefChecks), see #2208 // during uncurry (after refchecks), all types are normalized diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index 312958feca..cc272b7b8d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -151,11 +151,10 @@ trait Unapplies extends ast.TreeDSL } def companionModuleDef(cdef: ClassDef, parents: List[Tree] = Nil, body: List[Tree] = Nil): ModuleDef = atPos(cdef.pos.focus) { - val allParents = parents :+ gen.scalaScalaObjectConstr ModuleDef( Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin), cdef.name.toTermName, - Template(allParents, emptyValDef, NoMods, Nil, List(Nil), body, cdef.impl.pos.focus)) + Template(parents, emptyValDef, NoMods, Nil, List(Nil), body, cdef.impl.pos.focus)) } private val caseMods = Modifiers(SYNTHETIC | CASE) diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 622b4db2a2..ce10ee34a2 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -23,7 +23,7 @@ import java.net.MalformedURLException * @author Stepan Koltsov */ object ClassPath { - def scalaLibrary = locate[ScalaObject] + def scalaLibrary = locate[Option[_]] def scalaCompiler = locate[Global] def infoFor[T](value: T) = info(value.getClass) diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala index fbe92e5d84..f4ce6d6ef1 100755 --- a/src/compiler/scala/tools/nsc/util/DocStrings.scala +++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala @@ -26,6 +26,14 @@ object DocStrings { if (start < str.length && isIdentifierPart(str charAt start)) skipIdent(str, start + 1) else start + /** Returns index of string `str` following `start` skipping + * sequence of identifier characters. + */ + def skipTag(str: String, start: Int): Int = + if (start < str.length && (str charAt start) == '@') skipIdent(str, start + 1) + else start + + /** Returns index of string `str` after `start` skipping longest * sequence of space and tab characters, possibly also containing * a single `*` character or the `/``**` sequence. @@ -68,38 +76,46 @@ object DocStrings { /** Produces a string index, which is a list of ``sections'', i.e * pairs of start/end positions of all tagged sections in the string. - * Every section starts with a `@` and extends to the next `@`, or - * to the end of the comment string, but excluding the final two + * Every section starts with an at sign and extends to the next at sign, + * or to the end of the comment string, but excluding the final two * characters which terminate the comment. * * Also take usecases into account - they need to expand until the next * usecase or the end of the string, as they might include other sections * of their own */ - def tagIndex(str: String, p: Int => Boolean = (idx => true)): List[(Int, Int)] = - findAll(str, 0) (idx => str(idx) == '@' && p(idx)) match { + def tagIndex(str: String, p: Int => Boolean = (idx => true)): List[(Int, Int)] = { + var indices = findAll(str, 0) (idx => str(idx) == '@' && p(idx)) + indices = mergeUsecaseSections(str, indices) + indices = mergeInheritdocSections(str, indices) + + indices match { case List() => List() - case idxs => { - val idxs2 = mergeUsecaseSections(str, idxs) - idxs2 zip (idxs2.tail ::: List(str.length - 2)) - } + case idxs => idxs zip (idxs.tail ::: List(str.length - 2)) } + } /** * Merge sections following an usecase into the usecase comment, so they * can override the parent symbol's sections */ def mergeUsecaseSections(str: String, idxs: List[Int]): List[Int] = { - idxs.find(str.substring(_).startsWith("@usecase")) match { - case Some(firstUC) => - val commentSections = idxs.take(idxs.indexOf(firstUC)) - val usecaseSections = idxs.drop(idxs.indexOf(firstUC)).filter(str.substring(_).startsWith("@usecase")) + idxs.indexWhere(str.substring(_).startsWith("@usecase")) match { + case firstUCIndex if firstUCIndex != -1 => + val commentSections = idxs.take(firstUCIndex) + val usecaseSections = idxs.drop(firstUCIndex).filter(str.substring(_).startsWith("@usecase")) commentSections ::: usecaseSections - case None => + case _ => idxs } } + /** + * Merge the inheritdoc sections, as they never make sense on their own + */ + def mergeInheritdocSections(str: String, idxs: List[Int]): List[Int] = + idxs.filterNot(str.substring(_).startsWith("@inheritdoc")) + /** Does interval `iv` start with given `tag`? */ def startsWithTag(str: String, section: (Int, Int), tag: String): Boolean = @@ -108,12 +124,11 @@ object DocStrings { def startsWithTag(str: String, start: Int, tag: String): Boolean = str.startsWith(tag, start) && !isIdentifierPart(str charAt (start + tag.length)) - /** The first start tag of a list of tag intervals, * or the end of the whole comment string - 2 if list is empty */ def startTag(str: String, sections: List[(Int, Int)]) = sections match { - case List() => str.length - 2 + case Nil => str.length - 2 case (start, _) :: _ => start } @@ -155,4 +170,46 @@ object DocStrings { idx } } + + /** A map from the section tag to section parameters */ + def sectionTagMap(str: String, sections: List[(Int, Int)]): Map[String, (Int, Int)] = + Map() ++ { + for (section <- sections) yield + extractSectionTag(str, section) -> section + } + + /** Extract the section tag, treating the section tag as an indentifier */ + def extractSectionTag(str: String, section: (Int, Int)): String = + str.substring(section._1, skipTag(str, section._1)) + + /** Extract the section parameter */ + def extractSectionParam(str: String, section: (Int, Int)): String = { + assert(str.substring(section._1).startsWith("@param") || + str.substring(section._1).startsWith("@tparam") || + str.substring(section._1).startsWith("@throws")) + + val start = skipWhitespace(str, skipTag(str, section._1)) + val finish = skipIdent(str, start) + + str.substring(start, finish) + } + + /** Extract the section text, except for the tag and comment newlines */ + def extractSectionText(str: String, section: (Int, Int)): (Int, Int) = { + if (str.substring(section._1).startsWith("@param") || + str.substring(section._1).startsWith("@tparam") || + str.substring(section._1).startsWith("@throws")) + (skipWhitespace(str, skipIdent(str, skipWhitespace(str, skipTag(str, section._1)))), section._2) + else + (skipWhitespace(str, skipTag(str, section._1)), section._2) + } + + /** Cleanup section text */ + def cleanupSectionText(str: String) = { + var result = str.trim.replaceAll("\n\\s+\\*\\s+", " \n") + while (result.endsWith("\n")) + result = result.substring(0, str.length - 1) + result + } + } diff --git a/src/compiler/scala/tools/util/color/Ansi.scala b/src/compiler/scala/tools/util/color/Ansi.scala new file mode 100644 index 0000000000..1ed43579bb --- /dev/null +++ b/src/compiler/scala/tools/util/color/Ansi.scala @@ -0,0 +1,58 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2012 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.util +package color + +import collection.mutable + +object Ansi { + final val ESC = '\u001b' // <esc> + final val LBR = '\u005b' // [ + final val CSI = new String(Array(ESC, LBR)) // control sequence introducer + final val CSI_FINAL = "m" // control sequence final byte + + def colors = List(Black, Red, Green, Yellow, Blue, Magenta, Cyan, White) + def effects = List(Reset, Bright, Faint, Italic, Underline, Blink, Inverse, Hidden, Strikethrough) + + // No, that's not the finale of "CSI: Crime Scene Investigation." + + def colorizerFor(codes: Seq[Int]): String => String = + s => ansiCodeToString(codes) + s + ansiCodeToString(0) + + def ansiCodeToString(code: Int): String = CSI + code + CSI_FINAL + def ansiCodeToString(codes: Seq[Int]): String = codes.mkString(CSI, ";", CSI_FINAL) +} + +/** An ansi control sequence. The colorize function prepends + * the control sequence to the given String and appends a + * reset sequence. + */ +class Ansi(atoms0: List[AnsiAtom]) { + val atoms = atoms0 sortBy (x => (!x.isAttr, x.isInstanceOf[AnsiBackground])) + val colorize = Ansi colorizerFor codes + + def codes = atoms map (_.code) + def /(that: AnsiAtom) = new Ansi(atoms :+ that) + // This looks redundant with / , but isn't - it is a way + // to ensure that the argument will be a background color, + // even if a foreground color is passed as an argument + // (as it will be implicitly converted.) + def on(that: AnsiBackground) = this / that + + // Convenience functions. + def reset = this / Reset + def bright = this / Bright + def faint = this / Faint + def italic = this / Italic + def underline = this / Underline + def blink = this / Blink + def inverse = this / Inverse + def hidden = this / Hidden + def strikethrough = this / Strikethrough + + // adjectives first + override def toString = atoms mkString " " +} diff --git a/src/compiler/scala/tools/util/color/AnsiAtom.scala b/src/compiler/scala/tools/util/color/AnsiAtom.scala new file mode 100644 index 0000000000..5d5490f6e9 --- /dev/null +++ b/src/compiler/scala/tools/util/color/AnsiAtom.scala @@ -0,0 +1,51 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2012 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.util +package color + +case object Reset extends AnsiAttr(0) +case object Bright extends AnsiAttr(1) +case object Faint extends AnsiAttr(2) +case object Italic extends AnsiAttr(3) +case object Underline extends AnsiAttr(4) +case object Blink extends AnsiAttr(5) +case object Inverse extends AnsiAttr(7) +case object Hidden extends AnsiAttr(8) +case object Strikethrough extends AnsiAttr(9) + +case object Black extends AnsiForeground(30) +case object Red extends AnsiForeground(31) +case object Green extends AnsiForeground(32) +case object Yellow extends AnsiForeground(33) +case object Blue extends AnsiForeground(34) +case object Magenta extends AnsiForeground(35) +case object Cyan extends AnsiForeground(36) +case object White extends AnsiForeground(37) +case object Default extends AnsiForeground(39) + +/** One piece of an ansi control sequence. Either a color + * (foreground or background) or an attribute (e.g. bright, underline.) + * Control sequences are created from AnsiAtoms with the / operator. + */ +trait AnsiAtom { + def code: Int + def isAttr: Boolean +} +sealed abstract class AnsiAttr(val code: Int) extends AnsiAtom { + final def isAttr = true +} +sealed abstract class AnsiColor(val code: Int) extends AnsiAtom { + final def isAttr = false + def flip: AnsiColor +} +sealed abstract class AnsiForeground(code: Int) extends AnsiColor(code) { + require(30 <= code && code <= 39, code) + val flip: AnsiBackground = new AnsiBackground(this) +} +sealed class AnsiBackground(val flip: AnsiForeground) extends AnsiColor(flip.code + 10) { + require(40 <= code && code <= 49, code) + override def toString = "(on " + flip + " background)" +} diff --git a/src/compiler/scala/tools/util/color/CString.scala b/src/compiler/scala/tools/util/color/CString.scala new file mode 100644 index 0000000000..d0785eaeff --- /dev/null +++ b/src/compiler/scala/tools/util/color/CString.scala @@ -0,0 +1,28 @@ +package scala.tools.util +package color + +/** A colorized String. It's difficult to achieve precise + * formatting and selective string colorization simultaneously, + * because all length-based calculations will break down in + * the face of the ansi controls. It doesn't do much yet, but + * this is here to eventually make that transparent. + */ +final class CString(val uncolorized: String, val colorized: String) { + def visibleLength = uncolorized.length + def colorizedLength = colorized.length + def show() = Console println colorized + def bytes() = colorized map (ch => ch.toByte) + def > = show() + + def append(x: CString): CString = new CString(uncolorized + x.uncolorized, colorized + x.colorized) + def +(other: CString): CString = this append other + override def toString = colorized +} + +class CStringOps(str: String) { + /** Enables for example + * println("foo" in Red) + * println("foo" in Magenta.bright) + */ + def in(ansi: Ansi): CString = new CString(str, ansi colorize str) +} diff --git a/src/compiler/scala/tools/util/color/ColorNames.scala b/src/compiler/scala/tools/util/color/ColorNames.scala new file mode 100644 index 0000000000..ff4b01a9df --- /dev/null +++ b/src/compiler/scala/tools/util/color/ColorNames.scala @@ -0,0 +1,391 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2012 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.util.color + +/** Raw data adapted from perl's Term-ExtendedColor, which is published + * under perl's Artistic license: http://dev.perl.org/licenses/artistic.html + * + * These aren't actually in use yet. + */ +trait ColorNames { + type ColorType + def translateCode(ansiCode: String): ColorType + + private implicit def liftAnsiCode(code: String): ColorType = translateCode(code) + + // Possible alternative names or aliases, also from the perl: + // + // reset, clear, normal reset all attributes + // bold, bright bold or bright, depending on implementation + // faint decreased intensity (not widely supported) + // italic, cursive italic or cursive + // underline, underscore underline + // blink slow blink + // blink_ms rapid blink (only supported in MS DOS) + // reverse, inverse, negative reverse video + // conceal conceal, or hide (not widely supported) + + // Brightest to darkest color + val red1: ColorType = "5;196" + val red2: ColorType = "5;160" + val red3: ColorType = "5;124" + val red4: ColorType = "5;088" + val red5: ColorType = "5;052" + + val green1: ColorType = "5;156" + val green2: ColorType = "5;150" + val green3: ColorType = "5;120" + val green4: ColorType = "5;114" + val green5: ColorType = "5;084" + val green6: ColorType = "5;078" + val green7: ColorType = "5;155" + val green8: ColorType = "5;149" + val green9: ColorType = "5;119" + val green10: ColorType = "5;113" + val green11: ColorType = "5;083" + val green12: ColorType = "5;077" + val green13: ColorType = "5;047" + val green14: ColorType = "5;041" + val green15: ColorType = "5;118" + val green16: ColorType = "5;112" + val green17: ColorType = "5;082" + val green18: ColorType = "5;076" + val green19: ColorType = "5;046" + val green20: ColorType = "5;040" + val green21: ColorType = "5;034" + val green22: ColorType = "5;028" + val green23: ColorType = "5;022" + val green24: ColorType = "5;107" + val green25: ColorType = "5;071" + val green26: ColorType = "5;070" + val green27: ColorType = "5;064" + val green28: ColorType = "5;065" + + val blue1: ColorType = "5;075" + val blue2: ColorType = "5;074" + val blue3: ColorType = "5;073" + val blue4: ColorType = "5;039" + val blue5: ColorType = "5;038" + val blue6: ColorType = "5;037" + val blue7: ColorType = "5;033" + val blue8: ColorType = "5;032" + val blue9: ColorType = "5;031" + val blue10: ColorType = "5;027" + val blue11: ColorType = "5;026" + val blue12: ColorType = "5;025" + val blue13: ColorType = "5;021" + val blue14: ColorType = "5;020" + val blue15: ColorType = "5;019" + val blue16: ColorType = "5;018" + val blue17: ColorType = "5;017" + + val yellow1: ColorType = "5;228" + val yellow2: ColorType = "5;222" + val yellow3: ColorType = "5;192" + val yellow4: ColorType = "5;186" + val yellow5: ColorType = "5;227" + val yellow6: ColorType = "5;221" + val yellow7: ColorType = "5;191" + val yellow8: ColorType = "5;185" + val yellow9: ColorType = "5;226" + val yellow10: ColorType = "5;220" + val yellow11: ColorType = "5;190" + val yellow12: ColorType = "5;184" + val yellow13: ColorType = "5;214" + val yellow14: ColorType = "5;178" + val yellow15: ColorType = "5;208" + val yellow16: ColorType = "5;172" + val yellow17: ColorType = "5;202" + val yellow18: ColorType = "5;166" + + val magenta1: ColorType = "5;219" + val magenta2: ColorType = "5;183" + val magenta3: ColorType = "5;218" + val magenta4: ColorType = "5;182" + val magenta5: ColorType = "5;217" + val magenta6: ColorType = "5;181" + val magenta7: ColorType = "5;213" + val magenta8: ColorType = "5;177" + val magenta9: ColorType = "5;212" + val magenta10: ColorType = "5;176" + val magenta11: ColorType = "5;211" + val magenta12: ColorType = "5;175" + val magenta13: ColorType = "5;207" + val magenta14: ColorType = "5;171" + val magenta15: ColorType = "5;205" + val magenta16: ColorType = "5;169" + val magenta17: ColorType = "5;201" + val magenta18: ColorType = "5;165" + val magenta19: ColorType = "5;200" + val magenta20: ColorType = "5;164" + val magenta21: ColorType = "5;199" + val magenta22: ColorType = "5;163" + val magenta23: ColorType = "5;198" + val magenta24: ColorType = "5;162" + val magenta25: ColorType = "5;197" + val magenta26: ColorType = "5;161" + + val gray1: ColorType = "5;255" + val gray2: ColorType = "5;254" + val gray3: ColorType = "5;253" + val gray4: ColorType = "5;252" + val gray5: ColorType = "5;251" + val gray6: ColorType = "5;250" + val gray7: ColorType = "5;249" + val gray8: ColorType = "5;248" + val gray9: ColorType = "5;247" + val gray10: ColorType = "5;246" + val gray11: ColorType = "5;245" + val gray12: ColorType = "5;244" + val gray13: ColorType = "5;243" + val gray14: ColorType = "5;242" + val gray15: ColorType = "5;241" + val gray16: ColorType = "5;240" + val gray17: ColorType = "5;239" + val gray18: ColorType = "5;238" + val gray19: ColorType = "5;237" + val gray20: ColorType = "5;236" + val gray21: ColorType = "5;235" + val gray22: ColorType = "5;234" + val gray23: ColorType = "5;233" + val gray24: ColorType = "5;232" + + val purple1: ColorType = "5;147" + val purple2: ColorType = "5;146" + val purple3: ColorType = "5;145" + val purple4: ColorType = "5;141" + val purple5: ColorType = "5;140" + val purple6: ColorType = "5;139" + val purple7: ColorType = "5;135" + val purple8: ColorType = "5;134" + val purple9: ColorType = "5;133" + val purple10: ColorType = "5;129" + val purple11: ColorType = "5;128" + val purple12: ColorType = "5;127" + val purple13: ColorType = "5;126" + val purple14: ColorType = "5;125" + val purple15: ColorType = "5;111" + val purple16: ColorType = "5;110" + val purple17: ColorType = "5;109" + val purple18: ColorType = "5;105" + val purple19: ColorType = "5;104" + val purple20: ColorType = "5;103" + val purple21: ColorType = "5;099" + val purple22: ColorType = "5;098" + val purple23: ColorType = "5;097" + val purple24: ColorType = "5;096" + val purple25: ColorType = "5;093" + val purple26: ColorType = "5;092" + val purple27: ColorType = "5;091" + val purple28: ColorType = "5;090" + val purple29: ColorType = "5;055" + val purple30: ColorType = "5;054" + + val cyan1: ColorType = "5;159" + val cyan2: ColorType = "5;158" + val cyan3: ColorType = "5;157" + val cyan4: ColorType = "5;153" + val cyan5: ColorType = "5;152" + val cyan6: ColorType = "5;151" + val cyan7: ColorType = "5;123" + val cyan8: ColorType = "5;122" + val cyan9: ColorType = "5;121" + val cyan10: ColorType = "5;117" + val cyan11: ColorType = "5;116" + val cyan12: ColorType = "5;115" + val cyan13: ColorType = "5;087" + val cyan14: ColorType = "5;086" + val cyan15: ColorType = "5;085" + val cyan16: ColorType = "5;081" + val cyan17: ColorType = "5;080" + val cyan18: ColorType = "5;079" + val cyan19: ColorType = "5;051" + val cyan20: ColorType = "5;050" + val cyan21: ColorType = "5;049" + val cyan22: ColorType = "5;045" + val cyan23: ColorType = "5;044" + val cyan24: ColorType = "5;043" + + val orange1: ColorType = "5;208" + val orange2: ColorType = "5;172" + val orange3: ColorType = "5;202" + val orange4: ColorType = "5;166" + val orange5: ColorType = "5;130" + + // Approximations of X11 color mappings + // https://secure.wikimedia.org/wikipedia/en/wiki/X11%20colors + + val aquamarine1: ColorType = "5;086" + val aquamarine3: ColorType = "5;079" + val blueviolet: ColorType = "5;057" + val cadetblue1: ColorType = "5;072" + val cadetblue2: ColorType = "5;073" + val chartreuse1: ColorType = "5;118" + val chartreuse2: ColorType = "5;082" + val chartreuse3: ColorType = "5;070" + val chartreuse4: ColorType = "5;064" + val cornflowerblue: ColorType = "5;069" + val cornsilk1: ColorType = "5;230" + val darkblue: ColorType = "5;018" + val darkcyan: ColorType = "5;036" + val darkgoldenrod: ColorType = "5;136" + val darkgreen: ColorType = "5;022" + val darkkhaki: ColorType = "5;143" + val darkmagenta1: ColorType = "5;090" + val darkmagenta2: ColorType = "5;091" + val darkolivegreen1: ColorType = "5;191" + val darkolivegreen2: ColorType = "5;155" + val darkolivegreen3: ColorType = "5;107" + val darkolivegreen4: ColorType = "5;113" + val darkolivegreen5: ColorType = "5;149" + val darkorange3: ColorType = "5;130" + val darkorange4: ColorType = "5;166" + val darkorange1: ColorType = "5;208" + val darkred1: ColorType = "5;052" + val darkred2: ColorType = "5;088" + val darkseagreen1: ColorType = "5;158" + val darkseagreen2: ColorType = "5;157" + val darkseagreen3: ColorType = "5;150" + val darkseagreen4: ColorType = "5;071" + val darkslategray1: ColorType = "5;123" + val darkslategray2: ColorType = "5;087" + val darkslategray3: ColorType = "5;116" + val darkturquoise: ColorType = "5;044" + val darkviolet: ColorType = "5;128" + val deeppink1: ColorType = "5;198" + val deeppink2: ColorType = "5;197" + val deeppink3: ColorType = "5;162" + val deeppink4: ColorType = "5;125" + val deepskyblue1: ColorType = "5;039" + val deepskyblue2: ColorType = "5;038" + val deepskyblue3: ColorType = "5;031" + val deepskyblue4: ColorType = "5;023" + val dodgerblue1: ColorType = "5;033" + val dodgerblue2: ColorType = "5;027" + val dodgerblue3: ColorType = "5;026" + val gold1: ColorType = "5;220" + val gold3: ColorType = "5;142" + val greenyellow: ColorType = "5;154" + val grey0: ColorType = "5;016" + val grey100: ColorType = "5;231" + val grey11: ColorType = "5;234" + val grey15: ColorType = "5;235" + val grey19: ColorType = "5;236" + val grey23: ColorType = "5;237" + val grey27: ColorType = "5;238" + val grey30: ColorType = "5;239" + val grey3: ColorType = "5;232" + val grey35: ColorType = "5;240" + val grey37: ColorType = "5;059" + val grey39: ColorType = "5;241" + val grey42: ColorType = "5;242" + val grey46: ColorType = "5;243" + val grey50: ColorType = "5;244" + val grey53: ColorType = "5;102" + val grey54: ColorType = "5;245" + val grey58: ColorType = "5;246" + val grey62: ColorType = "5;247" + val grey63: ColorType = "5;139" + val grey66: ColorType = "5;248" + val grey69: ColorType = "5;145" + val grey70: ColorType = "5;249" + val grey74: ColorType = "5;250" + val grey7: ColorType = "5;233" + val grey78: ColorType = "5;251" + val grey82: ColorType = "5;252" + val grey84: ColorType = "5;188" + val grey85: ColorType = "5;253" + val grey89: ColorType = "5;254" + val grey93: ColorType = "5;255" + val honeydew2: ColorType = "5;194" + val hotpink2: ColorType = "5;169" + val hotpink3: ColorType = "5;132" + val hotpink: ColorType = "5;205" + val indianred1: ColorType = "5;203" + val indianred: ColorType = "5;167" + val khaki1: ColorType = "5;228" + val khaki3: ColorType = "5;185" + val lightcoral: ColorType = "5;210" + val lightcyan1: ColorType = "5;195" + val lightcyan3: ColorType = "5;152" + val lightgoldenrod1: ColorType = "5;227" + val lightgoldenrod2: ColorType = "5;186" + val lightgoldenrod3: ColorType = "5;179" + val lightgreen: ColorType = "5;119" + val lightpink1: ColorType = "5;217" + val lightpink3: ColorType = "5;174" + val lightpink4: ColorType = "5;095" + val lightsalmon1: ColorType = "5;216" + val lightsalmon3: ColorType = "5;137" + val lightseagreen: ColorType = "5;037" + val lightskyblue1: ColorType = "5;153" + val lightskyblue3: ColorType = "5;109" + val lightslateblue: ColorType = "5;105" + val lightslategrey: ColorType = "5;103" + val lightsteelblue1: ColorType = "5;189" + val lightsteelblue3: ColorType = "5;146" + val lightsteelblue: ColorType = "5;147" + val lightyellow3: ColorType = "5;187" + val mediumorchid1: ColorType = "5;171" + val mediumorchid3: ColorType = "5;133" + val mediumorchid: ColorType = "5;134" + val mediumpurple1: ColorType = "5;141" + val mediumpurple2: ColorType = "5;135" + val mediumpurple3: ColorType = "5;097" + val mediumpurple4: ColorType = "5;060" + val mediumpurple: ColorType = "5;104" + val mediumspringgreen: ColorType = "5;049" + val mediumturquoise: ColorType = "5;080" + val mediumvioletred: ColorType = "5;126" + val mistyrose1: ColorType = "5;224" + val mistyrose3: ColorType = "5;181" + val navajowhite1: ColorType = "5;223" + val navajowhite3: ColorType = "5;144" + val navyblue: ColorType = "5;017" + val orangered1: ColorType = "5;202" + val orchid1: ColorType = "5;213" + val orchid2: ColorType = "5;212" + val orchid: ColorType = "5;170" + val palegreen1: ColorType = "5;121" + val palegreen3: ColorType = "5;077" + val paleturquoise1: ColorType = "5;159" + val paleturquoise4: ColorType = "5;066" + val palevioletred1: ColorType = "5;211" + val pink1: ColorType = "5;218" + val pink3: ColorType = "5;175" + val plum1: ColorType = "5;219" + val plum2: ColorType = "5;183" + val plum3: ColorType = "5;176" + val plum4: ColorType = "5;096" + val purple: ColorType = "5;129" + val rosybrown: ColorType = "5;138" + val royalblue1: ColorType = "5;063" + val salmon1: ColorType = "5;209" + val sandybrown: ColorType = "5;215" + val seagreen1: ColorType = "5;084" + val seagreen2: ColorType = "5;083" + val seagreen3: ColorType = "5;078" + val skyblue1: ColorType = "5;117" + val skyblue2: ColorType = "5;111" + val skyblue3: ColorType = "5;074" + val slateblue1: ColorType = "5;099" + val slateblue3: ColorType = "5;061" + val springgreen1: ColorType = "5;048" + val springgreen2: ColorType = "5;042" + val springgreen3: ColorType = "5;035" + val springgreen4: ColorType = "5;029" + val steelblue1: ColorType = "5;075" + val steelblue3: ColorType = "5;068" + val steelblue: ColorType = "5;067" + val tan: ColorType = "5;180" + val thistle1: ColorType = "5;225" + val thistle3: ColorType = "5;182" + val turquoise2: ColorType = "5;045" + val turquoise4: ColorType = "5;030" + val violet: ColorType = "5;177" + val wheat1: ColorType = "5;229" + val wheat4: ColorType = "5;101" +} diff --git a/src/compiler/scala/tools/util/color/package.scala b/src/compiler/scala/tools/util/color/package.scala new file mode 100644 index 0000000000..7c7c7dab74 --- /dev/null +++ b/src/compiler/scala/tools/util/color/package.scala @@ -0,0 +1,21 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2012 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.util + +/** + * Wrappers around ansi colors. + * + * @author Paul Phillips + * @version 2.10 + */ +package object color { + implicit def implicitLiftAnsiAtom(c: AnsiAtom): Ansi = new Ansi(List(c)) + implicit def implicitColorToBackground(c: AnsiColor): AnsiBackground = c match { + case x: AnsiBackground => x + case x: AnsiForeground => x.flip + } + implicit def implicitCStringOps(str: String): CStringOps = new CStringOps(str) +} diff --git a/src/detach/plugin/scala/tools/detach/Detach.scala b/src/detach/plugin/scala/tools/detach/Detach.scala index fee2c5a273..41a3795a49 100644 --- a/src/detach/plugin/scala/tools/detach/Detach.scala +++ b/src/detach/plugin/scala/tools/detach/Detach.scala @@ -734,7 +734,7 @@ abstract class Detach extends PluginComponent proxyOwner.newClass(clazz.pos, encode(clazz.name.decode + PROXY_SUFFIX)) iface.sourceFile = clazz.sourceFile iface setFlag (ABSTRACT | TRAIT | INTERFACE) // Java interface - val iparents = List(ObjectClass.tpe, RemoteClass.tpe, ScalaObjectClass.tpe) + val iparents = List(ObjectClass.tpe, RemoteClass.tpe) iface setInfo ClassInfoType(iparents, newScope, iface) // methods must throw RemoteException iface addAnnotation remoteAnnotationInfo @@ -744,11 +744,9 @@ abstract class Detach extends PluginComponent iclaz.sourceFile = clazz.sourceFile iclaz setFlag (SYNTHETIC | FINAL) // Variant 1: rebind/unbind - val cparents = List(UnicastRemoteObjectClass.tpe, iface.tpe, - UnreferencedClass.tpe, ScalaObjectClass.tpe) + val cparents = List(UnicastRemoteObjectClass.tpe, iface.tpe, UnreferencedClass.tpe) // Variant 2: un-/exportObject - //val cparents = List(ObjectClass.tpe, iface.tpe, - // UnreferencedClass.tpe, ScalaObjectClass.tpe) + //val cparents = List(ObjectClass.tpe, iface.tpe, UnreferencedClass.tpe) iclaz setInfo ClassInfoType(cparents, newScope, iclaz) val proxy = (iface, iclaz, new mutable.HashMap[Symbol, Symbol]) proxies(clazz) = proxy diff --git a/src/library/scala/AnyVal.scala b/src/library/scala/AnyVal.scala index cd2c04dbd8..393f0899f4 100644 --- a/src/library/scala/AnyVal.scala +++ b/src/library/scala/AnyVal.scala @@ -25,4 +25,8 @@ package scala * The ''integer types'' include the subrange types as well as [[scala.Int]] and [[scala.Long]]. * The ''floating point types'' are [[scala.Float]] and [[scala.Double]]. */ -sealed trait AnyVal +abstract class AnyVal extends Any with NotNull { + // disabled for now to make the standard build go through. + // Once we have a new strap we can uncomment this and delete the AnyVal_getClass entry in Definitions. + def getClass(): Class[_ <: AnyVal] = ??? +} diff --git a/src/library/scala/Boolean.scala b/src/library/scala/Boolean.scala index 0adcde3aba..5078e59d28 100644 --- a/src/library/scala/Boolean.scala +++ b/src/library/scala/Boolean.scala @@ -107,7 +107,7 @@ final class Boolean extends AnyVal { */ def ^(x: Boolean): Boolean = sys.error("stub") - def getClass(): Class[Boolean] = sys.error("stub") + override def getClass(): Class[Boolean] = sys.error("stub") } object Boolean extends AnyValCompanion { diff --git a/src/library/scala/BoxingConversions.scala b/src/library/scala/BoxingConversions.scala new file mode 100644 index 0000000000..fd1bd6c121 --- /dev/null +++ b/src/library/scala/BoxingConversions.scala @@ -0,0 +1,5 @@ +package scala +abstract class BoxingConversions[Boxed, Unboxed] { + def box(x: Unboxed): Boxed + def unbox(x: Boxed): Unboxed +} diff --git a/src/library/scala/Byte.scala b/src/library/scala/Byte.scala index 4923cc9786..f9c5f6003e 100644 --- a/src/library/scala/Byte.scala +++ b/src/library/scala/Byte.scala @@ -590,7 +590,7 @@ final class Byte extends AnyVal { */ def %(x: Double): Double = sys.error("stub") - def getClass(): Class[Byte] = sys.error("stub") + override def getClass(): Class[Byte] = sys.error("stub") } object Byte extends AnyValCompanion { diff --git a/src/library/scala/Char.scala b/src/library/scala/Char.scala index b4e6445899..3d459782cd 100644 --- a/src/library/scala/Char.scala +++ b/src/library/scala/Char.scala @@ -590,7 +590,7 @@ final class Char extends AnyVal { */ def %(x: Double): Double = sys.error("stub") - def getClass(): Class[Char] = sys.error("stub") + override def getClass(): Class[Char] = sys.error("stub") } object Char extends AnyValCompanion { diff --git a/src/library/scala/Double.scala b/src/library/scala/Double.scala index 68a1a01299..01414265c4 100644 --- a/src/library/scala/Double.scala +++ b/src/library/scala/Double.scala @@ -356,7 +356,7 @@ final class Double extends AnyVal { */ def %(x: Double): Double = sys.error("stub") - def getClass(): Class[Double] = sys.error("stub") + override def getClass(): Class[Double] = sys.error("stub") } object Double extends AnyValCompanion { diff --git a/src/library/scala/Equals.scala b/src/library/scala/Equals.scala index 8aff7af175..4545c21e45 100644 --- a/src/library/scala/Equals.scala +++ b/src/library/scala/Equals.scala @@ -11,7 +11,7 @@ package scala /** An interface containing operations for equality. * The only method not already present in class `AnyRef` is `canEqual`. */ -trait Equals { +trait Equals extends Any { /** A method that should be called from every well-designed equals method * that is open to be overridden in a subclass. See Programming in Scala, * Chapter 28 for discussion and design. diff --git a/src/library/scala/Float.scala b/src/library/scala/Float.scala index 709d73d408..ff5b3cb112 100644 --- a/src/library/scala/Float.scala +++ b/src/library/scala/Float.scala @@ -356,7 +356,7 @@ final class Float extends AnyVal { */ def %(x: Double): Double = sys.error("stub") - def getClass(): Class[Float] = sys.error("stub") + override def getClass(): Class[Float] = sys.error("stub") } object Float extends AnyValCompanion { diff --git a/src/library/scala/Int.scala b/src/library/scala/Int.scala index 519a0486ac..316bbced2d 100644 --- a/src/library/scala/Int.scala +++ b/src/library/scala/Int.scala @@ -590,7 +590,7 @@ final class Int extends AnyVal { */ def %(x: Double): Double = sys.error("stub") - def getClass(): Class[Int] = sys.error("stub") + override def getClass(): Class[Int] = sys.error("stub") } object Int extends AnyValCompanion { diff --git a/src/library/scala/Long.scala b/src/library/scala/Long.scala index 9c7a803f08..ce8618c22a 100644 --- a/src/library/scala/Long.scala +++ b/src/library/scala/Long.scala @@ -590,7 +590,7 @@ final class Long extends AnyVal { */ def %(x: Double): Double = sys.error("stub") - def getClass(): Class[Long] = sys.error("stub") + override def getClass(): Class[Long] = sys.error("stub") } object Long extends AnyValCompanion { diff --git a/src/library/scala/NotNull.scala b/src/library/scala/NotNull.scala index d47d47a83e..64f999a932 100644 --- a/src/library/scala/NotNull.scala +++ b/src/library/scala/NotNull.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - - package scala /** * A marker trait for things that are not allowed to be null * @since 2.5 */ -trait NotNull {} +trait NotNull extends Any {} diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index a2ee76500c..b5006e7948 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -215,7 +215,7 @@ object Predef extends LowPriorityImplicits { throw new IllegalArgumentException("requirement failed: "+ message) } - final class Ensuring[A](val __resultOfEnsuring: A) { + final class Ensuring[A](val __resultOfEnsuring: A) extends AnyVal { // `__resultOfEnsuring` must be a public val to allow inlining. // See comments in ArrowAssoc for more. @deprecated("Use __resultOfEnsuring instead", "2.10.0") @@ -226,7 +226,7 @@ object Predef extends LowPriorityImplicits { def ensuring(cond: A => Boolean): A = { assert(cond(__resultOfEnsuring)); __resultOfEnsuring } def ensuring(cond: A => Boolean, msg: => Any): A = { assert(cond(__resultOfEnsuring), msg); __resultOfEnsuring } } - implicit def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x) + @inline implicit def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x) /** `???` can be used for marking methods that remain to be implemented. * @throws A `NotImplementedError` @@ -247,7 +247,7 @@ object Predef extends LowPriorityImplicits { def unapply[A, B, C](x: Tuple3[A, B, C]): Option[Tuple3[A, B, C]] = Some(x) } - final class ArrowAssoc[A](val __leftOfArrow: A) { + final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal { // `__leftOfArrow` must be a public val to allow inlining. The val // used to be called `x`, but now goes by `__leftOfArrow`, as that // reduces the chances of a user's writing `foo.__leftOfArrow` and @@ -260,7 +260,7 @@ object Predef extends LowPriorityImplicits { @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) def →[B](y: B): Tuple2[A, B] = ->(y) } - implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) + @inline implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) // printing and reading ----------------------------------------------- @@ -386,7 +386,8 @@ object Predef extends LowPriorityImplicits { // Strings and CharSequences -------------------------------------------------------------- implicit def any2stringadd(x: Any) = new runtime.StringAdd(x) - implicit def augmentString(x: String): StringOps = new StringOps(x) + @inline implicit def any2stringfmt(x: Any) = new runtime.StringFormat(x) + @inline implicit def augmentString(x: String): StringOps = new StringOps(x) implicit def unaugmentString(x: StringOps): String = x.repr implicit def stringCanBuildFrom: CanBuildFrom[String, Char, String] = diff --git a/src/library/scala/Product.scala b/src/library/scala/Product.scala index 90ae82b6d0..1459ab9ea5 100644 --- a/src/library/scala/Product.scala +++ b/src/library/scala/Product.scala @@ -17,7 +17,7 @@ package scala * @version 1.0 * @since 2.3 */ -trait Product extends Equals { +trait Product extends Any with Equals { /** The n^th^ element of this product, 0-based. In other words, for a * product `A(x,,1,,, ..., x,,k,,)`, returns `x,,(n+1),, where `0 < n < k`. * diff --git a/src/library/scala/Product1.scala b/src/library/scala/Product1.scala index ab8b0a4505..d268b35f60 100644 --- a/src/library/scala/Product1.scala +++ b/src/library/scala/Product1.scala @@ -17,13 +17,13 @@ object Product1 { /** Product1 is a cartesian product of 1 component. * @since 2.3 */ -trait Product1[@specialized(Int, Long, Double) +T1] extends Product { +trait Product1[@specialized(Int, Long, Double) +T1] extends Any with Product { /** The arity of this product. * @return 1 */ override def productArity = 1 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product1[@specialized(Int, Long, Double) +T1] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case _ => throw new IndexOutOfBoundsException(n.toString()) } diff --git a/src/library/scala/Product10.scala b/src/library/scala/Product10.scala index 536fb2fed9..cae9e5a664 100644 --- a/src/library/scala/Product10.scala +++ b/src/library/scala/Product10.scala @@ -17,13 +17,13 @@ object Product10 { /** Product10 is a cartesian product of 10 components. * @since 2.3 */ -trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Product { +trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Any with Product { /** The arity of this product. * @return 10 */ override def productArity = 10 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Produ */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product11.scala b/src/library/scala/Product11.scala index 7d49eccc5e..0647b28414 100644 --- a/src/library/scala/Product11.scala +++ b/src/library/scala/Product11.scala @@ -17,13 +17,13 @@ object Product11 { /** Product11 is a cartesian product of 11 components. * @since 2.3 */ -trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends Product { +trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends Any with Product { /** The arity of this product. * @return 11 */ override def productArity = 11 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product12.scala b/src/library/scala/Product12.scala index 0e9c4a01a2..a080aafa7a 100644 --- a/src/library/scala/Product12.scala +++ b/src/library/scala/Product12.scala @@ -17,13 +17,13 @@ object Product12 { /** Product12 is a cartesian product of 12 components. * @since 2.3 */ -trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] extends Product { +trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] extends Any with Product { /** The arity of this product. * @return 12 */ override def productArity = 12 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] e */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product13.scala b/src/library/scala/Product13.scala index a0629201d0..425aebf3e7 100644 --- a/src/library/scala/Product13.scala +++ b/src/library/scala/Product13.scala @@ -17,13 +17,13 @@ object Product13 { /** Product13 is a cartesian product of 13 components. * @since 2.3 */ -trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13] extends Product { +trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13] extends Any with Product { /** The arity of this product. * @return 13 */ override def productArity = 13 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product14.scala b/src/library/scala/Product14.scala index 32dda81c3e..3d7e4896ef 100644 --- a/src/library/scala/Product14.scala +++ b/src/library/scala/Product14.scala @@ -17,13 +17,13 @@ object Product14 { /** Product14 is a cartesian product of 14 components. * @since 2.3 */ -trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14] extends Product { +trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14] extends Any with Product { /** The arity of this product. * @return 14 */ override def productArity = 14 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product15.scala b/src/library/scala/Product15.scala index 57851f9870..7bca7a2a1b 100644 --- a/src/library/scala/Product15.scala +++ b/src/library/scala/Product15.scala @@ -17,13 +17,13 @@ object Product15 { /** Product15 is a cartesian product of 15 components. * @since 2.3 */ -trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15] extends Product { +trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15] extends Any with Product { /** The arity of this product. * @return 15 */ override def productArity = 15 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product16.scala b/src/library/scala/Product16.scala index 75076f3b3c..c5042cbc90 100644 --- a/src/library/scala/Product16.scala +++ b/src/library/scala/Product16.scala @@ -17,13 +17,13 @@ object Product16 { /** Product16 is a cartesian product of 16 components. * @since 2.3 */ -trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16] extends Product { +trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16] extends Any with Product { /** The arity of this product. * @return 16 */ override def productArity = 16 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product17.scala b/src/library/scala/Product17.scala index 9ee6072ffe..b5651ec712 100644 --- a/src/library/scala/Product17.scala +++ b/src/library/scala/Product17.scala @@ -17,13 +17,13 @@ object Product17 { /** Product17 is a cartesian product of 17 components. * @since 2.3 */ -trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17] extends Product { +trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17] extends Any with Product { /** The arity of this product. * @return 17 */ override def productArity = 17 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product18.scala b/src/library/scala/Product18.scala index 25d0839af1..088a48ae32 100644 --- a/src/library/scala/Product18.scala +++ b/src/library/scala/Product18.scala @@ -17,13 +17,13 @@ object Product18 { /** Product18 is a cartesian product of 18 components. * @since 2.3 */ -trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18] extends Product { +trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18] extends Any with Product { /** The arity of this product. * @return 18 */ override def productArity = 18 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product19.scala b/src/library/scala/Product19.scala index 5464de7264..4f4a98c6a0 100644 --- a/src/library/scala/Product19.scala +++ b/src/library/scala/Product19.scala @@ -17,13 +17,13 @@ object Product19 { /** Product19 is a cartesian product of 19 components. * @since 2.3 */ -trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19] extends Product { +trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19] extends Any with Product { /** The arity of this product. * @return 19 */ override def productArity = 19 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product2.scala b/src/library/scala/Product2.scala index 8097245926..eb67e5d46e 100644 --- a/src/library/scala/Product2.scala +++ b/src/library/scala/Product2.scala @@ -17,13 +17,13 @@ object Product2 { /** Product2 is a cartesian product of 2 components. * @since 2.3 */ -trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Double) +T2] extends Product { +trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Double) +T2] extends Any with Product { /** The arity of this product. * @return 2 */ override def productArity = 2 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Doub */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case _ => throw new IndexOutOfBoundsException(n.toString()) diff --git a/src/library/scala/Product20.scala b/src/library/scala/Product20.scala index b094e09aca..80f63f1bb4 100644 --- a/src/library/scala/Product20.scala +++ b/src/library/scala/Product20.scala @@ -17,13 +17,13 @@ object Product20 { /** Product20 is a cartesian product of 20 components. * @since 2.3 */ -trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20] extends Product { +trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20] extends Any with Product { /** The arity of this product. * @return 20 */ override def productArity = 20 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product21.scala b/src/library/scala/Product21.scala index fa06cfb438..7056844271 100644 --- a/src/library/scala/Product21.scala +++ b/src/library/scala/Product21.scala @@ -17,13 +17,13 @@ object Product21 { /** Product21 is a cartesian product of 21 components. * @since 2.3 */ -trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21] extends Product { +trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21] extends Any with Product { /** The arity of this product. * @return 21 */ override def productArity = 21 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product22.scala b/src/library/scala/Product22.scala index 46038bf1a2..05e95f92dd 100644 --- a/src/library/scala/Product22.scala +++ b/src/library/scala/Product22.scala @@ -17,13 +17,13 @@ object Product22 { /** Product22 is a cartesian product of 22 components. * @since 2.3 */ -trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22] extends Product { +trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22] extends Any with Product { /** The arity of this product. * @return 22 */ override def productArity = 22 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product3.scala b/src/library/scala/Product3.scala index 3a4cd8fc5e..91556bb962 100644 --- a/src/library/scala/Product3.scala +++ b/src/library/scala/Product3.scala @@ -17,13 +17,13 @@ object Product3 { /** Product3 is a cartesian product of 3 components. * @since 2.3 */ -trait Product3[+T1, +T2, +T3] extends Product { +trait Product3[+T1, +T2, +T3] extends Any with Product { /** The arity of this product. * @return 3 */ override def productArity = 3 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product3[+T1, +T2, +T3] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product4.scala b/src/library/scala/Product4.scala index a4d47457fa..1f9070c155 100644 --- a/src/library/scala/Product4.scala +++ b/src/library/scala/Product4.scala @@ -17,13 +17,13 @@ object Product4 { /** Product4 is a cartesian product of 4 components. * @since 2.3 */ -trait Product4[+T1, +T2, +T3, +T4] extends Product { +trait Product4[+T1, +T2, +T3, +T4] extends Any with Product { /** The arity of this product. * @return 4 */ override def productArity = 4 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product4[+T1, +T2, +T3, +T4] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product5.scala b/src/library/scala/Product5.scala index 9f25e70af0..52dd284f55 100644 --- a/src/library/scala/Product5.scala +++ b/src/library/scala/Product5.scala @@ -17,13 +17,13 @@ object Product5 { /** Product5 is a cartesian product of 5 components. * @since 2.3 */ -trait Product5[+T1, +T2, +T3, +T4, +T5] extends Product { +trait Product5[+T1, +T2, +T3, +T4, +T5] extends Any with Product { /** The arity of this product. * @return 5 */ override def productArity = 5 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product5[+T1, +T2, +T3, +T4, +T5] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product6.scala b/src/library/scala/Product6.scala index 87fd318c68..9624bdbe3e 100644 --- a/src/library/scala/Product6.scala +++ b/src/library/scala/Product6.scala @@ -17,13 +17,13 @@ object Product6 { /** Product6 is a cartesian product of 6 components. * @since 2.3 */ -trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Product { +trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Any with Product { /** The arity of this product. * @return 6 */ override def productArity = 6 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product7.scala b/src/library/scala/Product7.scala index d074503315..36d4b149db 100644 --- a/src/library/scala/Product7.scala +++ b/src/library/scala/Product7.scala @@ -17,13 +17,13 @@ object Product7 { /** Product7 is a cartesian product of 7 components. * @since 2.3 */ -trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Product { +trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Any with Product { /** The arity of this product. * @return 7 */ override def productArity = 7 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product8.scala b/src/library/scala/Product8.scala index bd6150c235..28c78f9c89 100644 --- a/src/library/scala/Product8.scala +++ b/src/library/scala/Product8.scala @@ -17,13 +17,13 @@ object Product8 { /** Product8 is a cartesian product of 8 components. * @since 2.3 */ -trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Product { +trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Any with Product { /** The arity of this product. * @return 8 */ override def productArity = 8 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product9.scala b/src/library/scala/Product9.scala index 1f042944cc..d69c550abe 100644 --- a/src/library/scala/Product9.scala +++ b/src/library/scala/Product9.scala @@ -17,13 +17,13 @@ object Product9 { /** Product9 is a cartesian product of 9 components. * @since 2.3 */ -trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Product { +trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Any with Product { /** The arity of this product. * @return 9 */ override def productArity = 9 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Proxy.scala b/src/library/scala/Proxy.scala index 383ff5b3bb..604b2a299f 100644 --- a/src/library/scala/Proxy.scala +++ b/src/library/scala/Proxy.scala @@ -22,13 +22,15 @@ package scala * @author Matthias Zenger * @version 1.0, 26/04/2004 */ -trait Proxy { +trait Proxy extends Any { def self: Any override def hashCode: Int = self.hashCode override def equals(that: Any): Boolean = that match { - case null => false - case x: AnyRef => (x eq this) || (x eq self.asInstanceOf[AnyRef]) || (x equals self) + case null => false + case _ => + val x = that.asInstanceOf[AnyRef] + (x eq this.asInstanceOf[AnyRef]) || (x eq self.asInstanceOf[AnyRef]) || (x equals self) } override def toString = "" + self } @@ -36,7 +38,7 @@ trait Proxy { object Proxy { /** A proxy which exposes the type it is proxying for via a type parameter. */ - trait Typed[T] extends Proxy { + trait Typed[T] extends Any with Proxy { def self: T } } diff --git a/src/library/scala/ScalaObject.scala b/src/library/scala/ScalaObject.scala deleted file mode 100644 index 8da0ab2cba..0000000000 --- a/src/library/scala/ScalaObject.scala +++ /dev/null @@ -1,13 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala - -trait ScalaObject extends java.lang.Object diff --git a/src/library/scala/Serializable.scala b/src/library/scala/Serializable.scala index 9be258bb83..9b9456e0a0 100644 --- a/src/library/scala/Serializable.scala +++ b/src/library/scala/Serializable.scala @@ -11,4 +11,4 @@ package scala /** * Classes extending this trait are serializable across platforms (Java, .NET). */ -trait Serializable extends java.io.Serializable +trait Serializable extends Any with java.io.Serializable diff --git a/src/library/scala/Short.scala b/src/library/scala/Short.scala index a9210d3555..5664c3b44c 100644 --- a/src/library/scala/Short.scala +++ b/src/library/scala/Short.scala @@ -590,7 +590,7 @@ final class Short extends AnyVal { */ def %(x: Double): Double = sys.error("stub") - def getClass(): Class[Short] = sys.error("stub") + override def getClass(): Class[Short] = sys.error("stub") } object Short extends AnyValCompanion { diff --git a/src/library/scala/Tuple1.scala b/src/library/scala/Tuple1.scala index 6d31d35e51..02fdd0cba5 100644 --- a/src/library/scala/Tuple1.scala +++ b/src/library/scala/Tuple1.scala @@ -19,5 +19,5 @@ case class Tuple1[@specialized(Int, Long, Double) +T1](_1: T1) extends Product1[T1] { override def toString() = "(" + _1 + ")" - + } diff --git a/src/library/scala/Tuple10.scala b/src/library/scala/Tuple10.scala index 10d554d467..ba2a02a8b2 100644 --- a/src/library/scala/Tuple10.scala +++ b/src/library/scala/Tuple10.scala @@ -28,5 +28,5 @@ case class Tuple10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](_1: T1, _2 extends Product10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + ")" - + } diff --git a/src/library/scala/Tuple11.scala b/src/library/scala/Tuple11.scala index 2065e4f017..7f51d172d4 100644 --- a/src/library/scala/Tuple11.scala +++ b/src/library/scala/Tuple11.scala @@ -29,5 +29,5 @@ case class Tuple11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11](_1: extends Product11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + ")" - + } diff --git a/src/library/scala/Tuple12.scala b/src/library/scala/Tuple12.scala index a463986752..4bbc6a0eab 100644 --- a/src/library/scala/Tuple12.scala +++ b/src/library/scala/Tuple12.scala @@ -31,5 +31,5 @@ case class Tuple12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + ")" - + } diff --git a/src/library/scala/Tuple13.scala b/src/library/scala/Tuple13.scala index 2bee0d69ad..77bd59bf2e 100644 --- a/src/library/scala/Tuple13.scala +++ b/src/library/scala/Tuple13.scala @@ -32,5 +32,5 @@ case class Tuple13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + ")" - + } diff --git a/src/library/scala/Tuple14.scala b/src/library/scala/Tuple14.scala index 60f7c51e64..bf7a4ce016 100644 --- a/src/library/scala/Tuple14.scala +++ b/src/library/scala/Tuple14.scala @@ -33,5 +33,5 @@ case class Tuple14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + ")" - + } diff --git a/src/library/scala/Tuple15.scala b/src/library/scala/Tuple15.scala index fc8e30580b..582c359bc6 100644 --- a/src/library/scala/Tuple15.scala +++ b/src/library/scala/Tuple15.scala @@ -34,5 +34,5 @@ case class Tuple15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + ")" - + } diff --git a/src/library/scala/Tuple16.scala b/src/library/scala/Tuple16.scala index 80181f6648..a1e9a790ff 100644 --- a/src/library/scala/Tuple16.scala +++ b/src/library/scala/Tuple16.scala @@ -35,5 +35,5 @@ case class Tuple16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + ")" - + } diff --git a/src/library/scala/Tuple17.scala b/src/library/scala/Tuple17.scala index 6236122be2..f531766c18 100644 --- a/src/library/scala/Tuple17.scala +++ b/src/library/scala/Tuple17.scala @@ -36,5 +36,5 @@ case class Tuple17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + ")" - + } diff --git a/src/library/scala/Tuple18.scala b/src/library/scala/Tuple18.scala index dd6a819ac5..a96db25e4b 100644 --- a/src/library/scala/Tuple18.scala +++ b/src/library/scala/Tuple18.scala @@ -37,5 +37,5 @@ case class Tuple18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + ")" - + } diff --git a/src/library/scala/Tuple19.scala b/src/library/scala/Tuple19.scala index 65f0fd22cf..718280d68a 100644 --- a/src/library/scala/Tuple19.scala +++ b/src/library/scala/Tuple19.scala @@ -38,5 +38,5 @@ case class Tuple19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + ")" - + } diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala index 684d2266e8..b1befca4fa 100644 --- a/src/library/scala/Tuple2.scala +++ b/src/library/scala/Tuple2.scala @@ -23,7 +23,7 @@ case class Tuple2[@specialized(Int, Long, Double, Char, Boolean, AnyRef) +T1, @s extends Product2[T1, T2] { override def toString() = "(" + _1 + "," + _2 + ")" - + /** Swaps the elements of this `Tuple`. * @return a new Tuple where the first element is the second element of this Tuple and the * second element is the first element of this Tuple. diff --git a/src/library/scala/Tuple20.scala b/src/library/scala/Tuple20.scala index cf3626909d..4a44c0bb89 100644 --- a/src/library/scala/Tuple20.scala +++ b/src/library/scala/Tuple20.scala @@ -39,5 +39,5 @@ case class Tuple20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + ")" - + } diff --git a/src/library/scala/Tuple21.scala b/src/library/scala/Tuple21.scala index 78b9c585c6..580a169e39 100644 --- a/src/library/scala/Tuple21.scala +++ b/src/library/scala/Tuple21.scala @@ -40,5 +40,5 @@ case class Tuple21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + "," + _21 + ")" - + } diff --git a/src/library/scala/Tuple22.scala b/src/library/scala/Tuple22.scala index 0993dfbbc3..fd3392ddea 100644 --- a/src/library/scala/Tuple22.scala +++ b/src/library/scala/Tuple22.scala @@ -41,5 +41,5 @@ case class Tuple22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + "," + _21 + "," + _22 + ")" - + } diff --git a/src/library/scala/Tuple3.scala b/src/library/scala/Tuple3.scala index dfa0c962a2..0d5399308b 100644 --- a/src/library/scala/Tuple3.scala +++ b/src/library/scala/Tuple3.scala @@ -24,7 +24,7 @@ case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) extends Product3[T1, T2, T3] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")" - + @deprecated("Use `zipped` instead.", "2.9.0") def zip[Repr1, El1, El2, El3, To](implicit w1: T1 => TLike[El1, Repr1], diff --git a/src/library/scala/Tuple4.scala b/src/library/scala/Tuple4.scala index a919072c88..a859078bcf 100644 --- a/src/library/scala/Tuple4.scala +++ b/src/library/scala/Tuple4.scala @@ -22,5 +22,5 @@ case class Tuple4[+T1, +T2, +T3, +T4](_1: T1, _2: T2, _3: T3, _4: T4) extends Product4[T1, T2, T3, T4] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + ")" - + } diff --git a/src/library/scala/Tuple5.scala b/src/library/scala/Tuple5.scala index 6a94f48ab4..1edfb673ee 100644 --- a/src/library/scala/Tuple5.scala +++ b/src/library/scala/Tuple5.scala @@ -23,5 +23,5 @@ case class Tuple5[+T1, +T2, +T3, +T4, +T5](_1: T1, _2: T2, _3: T3, _4: T4, _5: T extends Product5[T1, T2, T3, T4, T5] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + ")" - + } diff --git a/src/library/scala/Tuple6.scala b/src/library/scala/Tuple6.scala index 34f8224627..5b74937e58 100644 --- a/src/library/scala/Tuple6.scala +++ b/src/library/scala/Tuple6.scala @@ -24,5 +24,5 @@ case class Tuple6[+T1, +T2, +T3, +T4, +T5, +T6](_1: T1, _2: T2, _3: T3, _4: T4, extends Product6[T1, T2, T3, T4, T5, T6] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + ")" - + } diff --git a/src/library/scala/Tuple7.scala b/src/library/scala/Tuple7.scala index 6fc3477ba2..a7f572e9f0 100644 --- a/src/library/scala/Tuple7.scala +++ b/src/library/scala/Tuple7.scala @@ -25,5 +25,5 @@ case class Tuple7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](_1: T1, _2: T2, _3: T3, _4: extends Product7[T1, T2, T3, T4, T5, T6, T7] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + ")" - + } diff --git a/src/library/scala/Tuple8.scala b/src/library/scala/Tuple8.scala index 1e21b684fc..9bb427d689 100644 --- a/src/library/scala/Tuple8.scala +++ b/src/library/scala/Tuple8.scala @@ -26,5 +26,5 @@ case class Tuple8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](_1: T1, _2: T2, _3: T3 extends Product8[T1, T2, T3, T4, T5, T6, T7, T8] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + ")" - + } diff --git a/src/library/scala/Tuple9.scala b/src/library/scala/Tuple9.scala index 453cea31a1..4d50539e0c 100644 --- a/src/library/scala/Tuple9.scala +++ b/src/library/scala/Tuple9.scala @@ -27,5 +27,5 @@ case class Tuple9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](_1: T1, _2: T2, _ extends Product9[T1, T2, T3, T4, T5, T6, T7, T8, T9] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + ")" - + } diff --git a/src/library/scala/Unit.scala b/src/library/scala/Unit.scala index 57970b021b..f6ed0121ab 100644 --- a/src/library/scala/Unit.scala +++ b/src/library/scala/Unit.scala @@ -17,7 +17,7 @@ package scala * method which is declared `void`. */ final class Unit extends AnyVal { - def getClass(): Class[Unit] = sys.error("stub") + override def getClass(): Class[Unit] = sys.error("stub") } object Unit extends AnyValCompanion { diff --git a/src/library/scala/collection/GenIterableLike.scala b/src/library/scala/collection/GenIterableLike.scala index 18132f0a7b..7e68733afd 100644 --- a/src/library/scala/collection/GenIterableLike.scala +++ b/src/library/scala/collection/GenIterableLike.scala @@ -34,7 +34,7 @@ import generic.{ CanBuildFrom => CBF, _ } * This is a base trait for all Scala collections that define an `iterator` * method to step through one-by-one the collection's elements. */ -trait GenIterableLike[+A, +Repr] extends GenTraversableLike[A, Repr] { +trait GenIterableLike[+A, +Repr] extends Any with GenTraversableLike[A, Repr] { def iterator: Iterator[A] diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala index 63e9543711..cb0e96fcbb 100644 --- a/src/library/scala/collection/GenSeqLike.scala +++ b/src/library/scala/collection/GenSeqLike.scala @@ -30,7 +30,7 @@ import annotation.bridge * Sequences are special cases of iterable collections of class `Iterable`. * Unlike iterables, sequences always have a defined order of elements. */ -trait GenSeqLike[+A, +Repr] extends GenIterableLike[A, Repr] with Equals with Parallelizable[A, parallel.ParSeq[A]] { +trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equals with Parallelizable[A, parallel.ParSeq[A]] { def seq: Seq[A] /** Selects an element by its index in the $coll. diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala index 1dcc0bdac7..dd5f602c41 100644 --- a/src/library/scala/collection/GenTraversableLike.scala +++ b/src/library/scala/collection/GenTraversableLike.scala @@ -53,7 +53,7 @@ import annotation.migration * @author Aleksandar Prokopec * @since 2.9 */ -trait GenTraversableLike[+A, +Repr] extends GenTraversableOnce[A] with Parallelizable[A, parallel.ParIterable[A]] { +trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with Parallelizable[A, parallel.ParIterable[A]] { def repr: Repr diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala index 305f8d768d..67ea4cdb00 100644 --- a/src/library/scala/collection/GenTraversableOnce.scala +++ b/src/library/scala/collection/GenTraversableOnce.scala @@ -41,7 +41,7 @@ package scala.collection * @author Aleksandar Prokopec * @since 2.9 */ -trait GenTraversableOnce[+A] { +trait GenTraversableOnce[+A] extends Any { def foreach[U](f: A => U): Unit @@ -124,6 +124,7 @@ trait GenTraversableOnce[+A] { * scala> val b = (a /:\ 5)(_+_) * b: Int = 15 * }}}*/ + @deprecated("use fold instead") def /:\[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = fold(z)(op) /** Applies a binary operator to a start value and all elements of this $coll, diff --git a/src/library/scala/collection/IndexedSeqLike.scala b/src/library/scala/collection/IndexedSeqLike.scala index baf5606ab5..d1f7d1cb36 100644 --- a/src/library/scala/collection/IndexedSeqLike.scala +++ b/src/library/scala/collection/IndexedSeqLike.scala @@ -37,7 +37,7 @@ import scala.annotation.tailrec * @define willNotTerminateInf * @define mayNotTerminateInf */ -trait IndexedSeqLike[+A, +Repr] extends SeqLike[A, Repr] { +trait IndexedSeqLike[+A, +Repr] extends Any with SeqLike[A, Repr] { self => def seq: IndexedSeq[A] diff --git a/src/library/scala/collection/IndexedSeqOptimized.scala b/src/library/scala/collection/IndexedSeqOptimized.scala index 196e77c91b..9d03a11db9 100755 --- a/src/library/scala/collection/IndexedSeqOptimized.scala +++ b/src/library/scala/collection/IndexedSeqOptimized.scala @@ -22,7 +22,7 @@ import scala.annotation.tailrec * @define willNotTerminateInf * @define mayNotTerminateInf */ -trait IndexedSeqOptimized[+A, +Repr] extends IndexedSeqLike[A, Repr] { self => +trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { self => override /*IterableLike*/ def isEmpty: Boolean = { length == 0 } diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala index 4b0c5662d8..73d4efe125 100644 --- a/src/library/scala/collection/IterableLike.scala +++ b/src/library/scala/collection/IterableLike.scala @@ -49,7 +49,7 @@ import annotation.bridge * @define Coll Iterable * @define coll iterable collection */ -trait IterableLike[+A, +Repr] extends Equals with TraversableLike[A, Repr] with GenIterableLike[A, Repr] { +trait IterableLike[+A, +Repr] extends Any with Equals with TraversableLike[A, Repr] with GenIterableLike[A, Repr] { self => override protected[this] def thisCollection: Iterable[A] = this.asInstanceOf[Iterable[A]] diff --git a/src/library/scala/collection/Parallelizable.scala b/src/library/scala/collection/Parallelizable.scala index 59b37aff96..5bcefb81b2 100644 --- a/src/library/scala/collection/Parallelizable.scala +++ b/src/library/scala/collection/Parallelizable.scala @@ -17,7 +17,7 @@ import parallel.Combiner * @tparam A the type of the elements in the collection * @tparam ParRepr the actual type of the collection, which has to be parallel */ -trait Parallelizable[+A, +ParRepr <: Parallel] { +trait Parallelizable[+A, +ParRepr <: Parallel] extends Any { def seq: TraversableOnce[A] diff --git a/src/library/scala/collection/SeqExtractors.scala b/src/library/scala/collection/SeqExtractors.scala new file mode 100644 index 0000000000..cb3cb27f18 --- /dev/null +++ b/src/library/scala/collection/SeqExtractors.scala @@ -0,0 +1,21 @@ +package scala.collection + +/** An extractor used to head/tail deconstruct sequences. */ +object +: { + def unapply[T,Coll <: SeqLike[T, Coll]]( + t: Coll with SeqLike[T, Coll]): Option[(T, Coll)] = + if(t.isEmpty) None + else Some(t.head -> t.tail) +} + +/** An extractor used to init/last deconstruct sequences. */ +object :+ { + /** Splits a sequence into init :+ tail. + * @returns Some(init, tail) if sequence is non-empty. + * None otherwise. + */ + def unapply[T,Coll <: SeqLike[T, Coll]]( + t: Coll with SeqLike[T, Coll]): Option[(Coll, T)] = + if(t.isEmpty) None + else Some(t.init -> t.last) +} diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index b51a37cf9e..526ea7e240 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -59,7 +59,7 @@ import scala.math.Ordering * @define orderDependent * @define orderDependentFold */ -trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] with GenSeqLike[A, Repr] with Parallelizable[A, ParSeq[A]] { self => +trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[A, Repr] with Parallelizable[A, ParSeq[A]] { self => override protected[this] def thisCollection: Seq[A] = this.asInstanceOf[Seq[A]] override protected[this] def toCollection(repr: Repr): Seq[A] = repr.asInstanceOf[Seq[A]] diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index 36d45c0c8a..0da1cfb913 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -64,7 +64,8 @@ import parallel.ParIterable * @define Coll Traversable * @define coll traversable collection */ -trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr] +trait TraversableLike[+A, +Repr] extends Any + with HasNewBuilder[A, Repr] with FilterMonadic[A, Repr] with TraversableOnce[A] with GenTraversableLike[A, Repr] diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala index 5bb2e563f6..62ea692b90 100644 --- a/src/library/scala/collection/TraversableOnce.scala +++ b/src/library/scala/collection/TraversableOnce.scala @@ -56,7 +56,7 @@ import annotation.unchecked.{ uncheckedVariance => uV } * * Note: will not terminate for infinite-sized collections. */ -trait TraversableOnce[+A] extends GenTraversableOnce[A] { +trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { self => /** Self-documenting abstract methods. */ @@ -360,6 +360,7 @@ trait TraversableOnce[+A] extends GenTraversableOnce[A] { object TraversableOnce { implicit def traversableOnceCanBuildFrom[T] = new OnceCanBuildFrom[T] implicit def wrapTraversableOnce[A](trav: TraversableOnce[A]) = new MonadOps(trav) + implicit def alternateImplicit[A](trav: TraversableOnce[A]) = new ForceImplicitAmbiguity implicit def flattenTraversableOnce[A, CC[_]](travs: TraversableOnce[CC[A]])(implicit ev: CC[A] => TraversableOnce[A]) = new FlattenOps[A](travs map ev) @@ -391,6 +392,8 @@ object TraversableOnce { } } + class ForceImplicitAmbiguity + class MonadOps[+A](trav: TraversableOnce[A]) { def map[B](f: A => B): TraversableOnce[B] = trav.toIterator map f def flatMap[B](f: A => GenTraversableOnce[B]): TraversableOnce[B] = trav.toIterator flatMap f diff --git a/src/library/scala/collection/generic/FilterMonadic.scala b/src/library/scala/collection/generic/FilterMonadic.scala index 4d6d9ec6a3..d79112d616 100755 --- a/src/library/scala/collection/generic/FilterMonadic.scala +++ b/src/library/scala/collection/generic/FilterMonadic.scala @@ -12,7 +12,7 @@ package scala.collection.generic /** A template trait that contains just the `map`, `flatMap`, `foreach` and `withFilter` methods * of trait `TraversableLike`. */ -trait FilterMonadic[+A, +Repr] { +trait FilterMonadic[+A, +Repr] extends Any { def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That def flatMap[B, That](f: A => collection.GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That def foreach[U](f: A => U): Unit diff --git a/src/library/scala/collection/generic/HasNewBuilder.scala b/src/library/scala/collection/generic/HasNewBuilder.scala index 6154a56441..8f0ce01911 100755 --- a/src/library/scala/collection/generic/HasNewBuilder.scala +++ b/src/library/scala/collection/generic/HasNewBuilder.scala @@ -10,7 +10,7 @@ package generic import mutable.Builder -trait HasNewBuilder[+A, +Repr] { +trait HasNewBuilder[+A, +Repr] extends Any { /** The builder that builds instances of Repr */ protected[this] def newBuilder: Builder[A, Repr] } diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index 9b52c8805c..f9697565de 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -40,7 +40,7 @@ import StringLike._ * @define mayNotTerminateInf * @define willNotTerminateInf */ -trait StringLike[+Repr] extends collection.IndexedSeqOptimized[Char, Repr] with Ordered[String] { +trait StringLike[+Repr] extends Any with collection.IndexedSeqOptimized[Char, Repr] with Ordered[String] { self => /** Creates a string builder buffer as builder for this class */ diff --git a/src/library/scala/collection/immutable/StringOps.scala b/src/library/scala/collection/immutable/StringOps.scala index 8612357db9..97609b4c4d 100644 --- a/src/library/scala/collection/immutable/StringOps.scala +++ b/src/library/scala/collection/immutable/StringOps.scala @@ -28,7 +28,7 @@ import mutable.StringBuilder * @define Coll StringOps * @define coll string */ -final class StringOps(override val repr: String) extends StringLike[String] { +final class StringOps(override val repr: String) extends AnyVal with StringLike[String] { override protected[this] def thisCollection: WrappedString = new WrappedString(repr) override protected[this] def toCollection(repr: String): WrappedString = new WrappedString(repr) diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala index f72ba78446..f0e4c79abf 100644 --- a/src/library/scala/collection/mutable/ArrayBuilder.scala +++ b/src/library/scala/collection/mutable/ArrayBuilder.scala @@ -76,7 +76,7 @@ object ArrayBuilder { this } - override def ++=(xs: TraversableOnce[T]): this.type = (xs: AnyRef) match { + override def ++=(xs: TraversableOnce[T]): this.type = (xs.asInstanceOf[AnyRef]) match { case xs: WrappedArray.ofRef[_] => ensureSize(this.size + xs.length) Array.copy(xs.array, 0, elems, this.size, xs.length) diff --git a/src/library/scala/collection/mutable/Ctrie.scala b/src/library/scala/collection/mutable/ConcurrentTrieMap.scala index cbec118aa9..1a44c8e423 100644 --- a/src/library/scala/collection/mutable/Ctrie.scala +++ b/src/library/scala/collection/mutable/ConcurrentTrieMap.scala @@ -13,7 +13,7 @@ package mutable import java.util.concurrent.atomic._ import collection.immutable.{ ListMap => ImmutableListMap } -import collection.parallel.mutable.ParCtrie +import collection.parallel.mutable.ParConcurrentTrieMap import generic._ import annotation.tailrec import annotation.switch @@ -31,16 +31,16 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends @inline final def CAS(old: MainNode[K, V], n: MainNode[K, V]) = INodeBase.updater.compareAndSet(this, old, n) - final def gcasRead(ct: Ctrie[K, V]): MainNode[K, V] = GCAS_READ(ct) + final def gcasRead(ct: ConcurrentTrieMap[K, V]): MainNode[K, V] = GCAS_READ(ct) - @inline final def GCAS_READ(ct: Ctrie[K, V]): MainNode[K, V] = { + @inline final def GCAS_READ(ct: ConcurrentTrieMap[K, V]): MainNode[K, V] = { val m = /*READ*/mainnode val prevval = /*READ*/m.prev if (prevval eq null) m else GCAS_Complete(m, ct) } - @tailrec private def GCAS_Complete(m: MainNode[K, V], ct: Ctrie[K, V]): MainNode[K, V] = if (m eq null) null else { + @tailrec private def GCAS_Complete(m: MainNode[K, V], ct: ConcurrentTrieMap[K, V]): MainNode[K, V] = if (m eq null) null else { // complete the GCAS val prev = /*READ*/m.prev val ctr = ct.readRoot(true) @@ -72,7 +72,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends } } - @inline final def GCAS(old: MainNode[K, V], n: MainNode[K, V], ct: Ctrie[K, V]): Boolean = { + @inline final def GCAS(old: MainNode[K, V], n: MainNode[K, V], ct: ConcurrentTrieMap[K, V]): Boolean = { n.WRITE_PREV(old) if (CAS(old, n)) { GCAS_Complete(n, ct) @@ -86,7 +86,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends nin } - final def copyToGen(ngen: Gen, ct: Ctrie[K, V]) = { + final def copyToGen(ngen: Gen, ct: ConcurrentTrieMap[K, V]) = { val nin = new INode[K, V](ngen) val main = GCAS_READ(ct) nin.WRITE(main) @@ -97,7 +97,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends * * @return true if successful, false otherwise */ - @tailrec final def rec_insert(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: Ctrie[K, V]): Boolean = { + @tailrec final def rec_insert(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: ConcurrentTrieMap[K, V]): Boolean = { val m = GCAS_READ(ct) // use -Yinline! m match { @@ -143,7 +143,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends * @param cond null - don't care if the key was there; KEY_ABSENT - key wasn't there; KEY_PRESENT - key was there; other value `v` - key must be bound to `v` * @return null if unsuccessful, Option[V] otherwise (indicating previous value bound to the key) */ - @tailrec final def rec_insertif(k: K, v: V, hc: Int, cond: AnyRef, lev: Int, parent: INode[K, V], startgen: Gen, ct: Ctrie[K, V]): Option[V] = { + @tailrec final def rec_insertif(k: K, v: V, hc: Int, cond: AnyRef, lev: Int, parent: INode[K, V], startgen: Gen, ct: ConcurrentTrieMap[K, V]): Option[V] = { val m = GCAS_READ(ct) // use -Yinline! m match { @@ -233,7 +233,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends * * @return null if no value has been found, RESTART if the operation wasn't successful, or any other value otherwise */ - @tailrec final def rec_lookup(k: K, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: Ctrie[K, V]): AnyRef = { + @tailrec final def rec_lookup(k: K, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: ConcurrentTrieMap[K, V]): AnyRef = { val m = GCAS_READ(ct) // use -Yinline! m match { @@ -276,7 +276,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends * @param v if null, will remove the key irregardless of the value; otherwise removes only if binding contains that exact key and value * @return null if not successful, an Option[V] indicating the previous value otherwise */ - final def rec_remove(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: Ctrie[K, V]): Option[V] = { + final def rec_remove(k: K, v: V, hc: Int, lev: Int, parent: INode[K, V], startgen: Gen, ct: ConcurrentTrieMap[K, V]): Option[V] = { val m = GCAS_READ(ct) // use -Yinline! m match { @@ -352,7 +352,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends } } - private def clean(nd: INode[K, V], ct: Ctrie[K, V], lev: Int) { + private def clean(nd: INode[K, V], ct: ConcurrentTrieMap[K, V], lev: Int) { val m = nd.GCAS_READ(ct) m match { case cn: CNode[K, V] => nd.GCAS(cn, cn.toCompressed(ct, lev, gen), ct) @@ -360,9 +360,9 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends } } - final def isNullInode(ct: Ctrie[K, V]) = GCAS_READ(ct) eq null + final def isNullInode(ct: ConcurrentTrieMap[K, V]) = GCAS_READ(ct) eq null - final def cachedSize(ct: Ctrie[K, V]): Int = { + final def cachedSize(ct: ConcurrentTrieMap[K, V]): Int = { val m = GCAS_READ(ct) m.cachedSize(ct) } @@ -438,7 +438,7 @@ extends MainNode[K, V] { if (updmap.size > 1) new LNode(updmap) else { val (k, v) = updmap.iterator.next - new TNode(k, v, Ctrie.computeHash(k)) // create it tombed so that it gets compressed on subsequent accesses + new TNode(k, v, ConcurrentTrieMap.computeHash(k)) // create it tombed so that it gets compressed on subsequent accesses } } def get(k: K) = listmap.get(k) @@ -455,7 +455,7 @@ extends CNodeBase[K, V] { val currsz = READ_SIZE() if (currsz != -1) currsz else { - val sz = computeSize(ct.asInstanceOf[Ctrie[K, V]]) + val sz = computeSize(ct.asInstanceOf[ConcurrentTrieMap[K, V]]) while (READ_SIZE() == -1) CAS_SIZE(-1, sz) READ_SIZE() } @@ -466,7 +466,7 @@ extends CNodeBase[K, V] { // => if there are concurrent size computations, they start // at different positions, so they are more likely to // to be independent - private def computeSize(ct: Ctrie[K, V]): Int = { + private def computeSize(ct: ConcurrentTrieMap[K, V]): Int = { var i = 0 var sz = 0 val offset = math.abs(util.Random.nextInt()) % array.length @@ -511,7 +511,7 @@ extends CNodeBase[K, V] { /** Returns a copy of this cnode such that all the i-nodes below it are copied * to the specified generation `ngen`. */ - final def renewed(ngen: Gen, ct: Ctrie[K, V]) = { + final def renewed(ngen: Gen, ct: ConcurrentTrieMap[K, V]) = { var i = 0 val arr = array val len = arr.length @@ -542,7 +542,7 @@ extends CNodeBase[K, V] { // returns the version of this node with at least some null-inodes // removed (those existing when the op began) // - if there are only null-i-nodes below, returns null - final def toCompressed(ct: Ctrie[K, V], lev: Int, gen: Gen) = { + final def toCompressed(ct: ConcurrentTrieMap[K, V], lev: Int, gen: Gen) = { var bmp = bitmap var i = 0 val arr = array @@ -594,7 +594,7 @@ private[mutable] object CNode { val yidx = (yhc >>> lev) & 0x1f val bmp = (1 << xidx) | (1 << yidx) if (xidx == yidx) { - val subinode = new INode[K, V](gen)//(Ctrie.inodeupdater) + val subinode = new INode[K, V](gen)//(ConcurrentTrieMap.inodeupdater) subinode.mainnode = dual(x, xhc, y, yhc, lev + 5, gen) new CNode(bmp, Array(subinode), gen) } else { @@ -613,7 +613,7 @@ private[mutable] case class RDCSS_Descriptor[K, V](old: INode[K, V], expectedmai } -/** A concurrent hash-trie or Ctrie is a concurrent thread-safe lock-free +/** A concurrent hash-trie or ConcurrentTrieMap is a concurrent thread-safe lock-free * implementation of a hash array mapped trie. It is used to implement the * concurrent map abstraction. It has particularly scalable concurrent insert * and remove operations and is memory-efficient. It supports O(1), atomic, @@ -627,20 +627,20 @@ private[mutable] case class RDCSS_Descriptor[K, V](old: INode[K, V], expectedmai * @since 2.10 */ @SerialVersionUID(0L - 6402774413839597105L) -final class Ctrie[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater[Ctrie[K, V], AnyRef]) +final class ConcurrentTrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater[ConcurrentTrieMap[K, V], AnyRef]) extends ConcurrentMap[K, V] - with MapLike[K, V, Ctrie[K, V]] - with CustomParallelizable[(K, V), ParCtrie[K, V]] + with MapLike[K, V, ConcurrentTrieMap[K, V]] + with CustomParallelizable[(K, V), ParConcurrentTrieMap[K, V]] with Serializable { - import Ctrie.computeHash + import ConcurrentTrieMap.computeHash private var rootupdater = rtupd @volatile var root = r def this() = this( INode.newRootNode, - AtomicReferenceFieldUpdater.newUpdater(classOf[Ctrie[K, V]], classOf[AnyRef], "root") + AtomicReferenceFieldUpdater.newUpdater(classOf[ConcurrentTrieMap[K, V]], classOf[AnyRef], "root") ) /* internal methods */ @@ -652,22 +652,22 @@ extends ConcurrentMap[K, V] out.writeObject(k) out.writeObject(v) } - out.writeObject(CtrieSerializationEnd) + out.writeObject(ConcurrentTrieMapSerializationEnd) } private def readObject(in: java.io.ObjectInputStream) { root = INode.newRootNode - rootupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[Ctrie[K, V]], classOf[AnyRef], "root") + rootupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[ConcurrentTrieMap[K, V]], classOf[AnyRef], "root") var obj: AnyRef = null do { obj = in.readObject() - if (obj != CtrieSerializationEnd) { + if (obj != ConcurrentTrieMapSerializationEnd) { val k = obj.asInstanceOf[K] val v = in.readObject().asInstanceOf[V] update(k, v) } - } while (obj != CtrieSerializationEnd) + } while (obj != ConcurrentTrieMapSerializationEnd) } @inline final def CAS_ROOT(ov: AnyRef, nv: AnyRef) = rootupdater.compareAndSet(this, ov, nv) @@ -760,37 +760,37 @@ extends ConcurrentMap[K, V] override def seq = this - override def par = new ParCtrie(this) + override def par = new ParConcurrentTrieMap(this) - override def empty: Ctrie[K, V] = new Ctrie[K, V] + override def empty: ConcurrentTrieMap[K, V] = new ConcurrentTrieMap[K, V] final def isReadOnly = rootupdater eq null final def nonReadOnly = rootupdater ne null - /** Returns a snapshot of this Ctrie. + /** Returns a snapshot of this ConcurrentTrieMap. * This operation is lock-free and linearizable. * * The snapshot is lazily updated - the first time some branch - * in the snapshot or this Ctrie are accessed, they are rewritten. + * in the snapshot or this ConcurrentTrieMap are accessed, they are rewritten. * This means that the work of rebuilding both the snapshot and this - * Ctrie is distributed across all the threads doing updates or accesses + * ConcurrentTrieMap is distributed across all the threads doing updates or accesses * subsequent to the snapshot creation. */ - @tailrec final def snapshot(): Ctrie[K, V] = { + @tailrec final def snapshot(): ConcurrentTrieMap[K, V] = { val r = RDCSS_READ_ROOT() val expmain = r.gcasRead(this) - if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new Ctrie(r.copyToGen(new Gen, this), rootupdater) + if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new ConcurrentTrieMap(r.copyToGen(new Gen, this), rootupdater) else snapshot() } - /** Returns a read-only snapshot of this Ctrie. + /** Returns a read-only snapshot of this ConcurrentTrieMap. * This operation is lock-free and linearizable. * * The snapshot is lazily updated - the first time some branch - * of this Ctrie are accessed, it is rewritten. The work of creating + * of this ConcurrentTrieMap are accessed, it is rewritten. The work of creating * the snapshot is thus distributed across subsequent updates - * and accesses on this Ctrie by all threads. + * and accesses on this ConcurrentTrieMap by all threads. * Note that the snapshot itself is never rewritten unlike when calling * the `snapshot` method, but the obtained snapshot cannot be modified. * @@ -799,7 +799,7 @@ extends ConcurrentMap[K, V] @tailrec final def readOnlySnapshot(): collection.Map[K, V] = { val r = RDCSS_READ_ROOT() val expmain = r.gcasRead(this) - if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new Ctrie(r, null) + if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new ConcurrentTrieMap(r, null) else readOnlySnapshot() } @@ -872,7 +872,7 @@ extends ConcurrentMap[K, V] def iterator: Iterator[(K, V)] = if (nonReadOnly) readOnlySnapshot().iterator - else new CtrieIterator(0, this) + else new ConcurrentTrieMapIterator(0, this) private def cachedSize() = { val r = RDCSS_READ_ROOT() @@ -883,17 +883,17 @@ extends ConcurrentMap[K, V] if (nonReadOnly) readOnlySnapshot().size else cachedSize() - override def stringPrefix = "Ctrie" + override def stringPrefix = "ConcurrentTrieMap" } -object Ctrie extends MutableMapFactory[Ctrie] { +object ConcurrentTrieMap extends MutableMapFactory[ConcurrentTrieMap] { val inodeupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[INodeBase[_, _]], classOf[MainNode[_, _]], "mainnode") - implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Ctrie[K, V]] = new MapCanBuildFrom[K, V] + implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), ConcurrentTrieMap[K, V]] = new MapCanBuildFrom[K, V] - def empty[K, V]: Ctrie[K, V] = new Ctrie[K, V] + def empty[K, V]: ConcurrentTrieMap[K, V] = new ConcurrentTrieMap[K, V] @inline final def computeHash[K](k: K): Int = { var hcode = k.hashCode @@ -905,7 +905,7 @@ object Ctrie extends MutableMapFactory[Ctrie] { } -private[collection] class CtrieIterator[K, V](var level: Int, private var ct: Ctrie[K, V], mustInit: Boolean = true) extends Iterator[(K, V)] { +private[collection] class ConcurrentTrieMapIterator[K, V](var level: Int, private var ct: ConcurrentTrieMap[K, V], mustInit: Boolean = true) extends Iterator[(K, V)] { var stack = new Array[Array[BasicNode]](7) var stackpos = new Array[Int](7) var depth = -1 @@ -971,9 +971,9 @@ private[collection] class CtrieIterator[K, V](var level: Int, private var ct: Ct } } else current = null - protected def newIterator(_lev: Int, _ct: Ctrie[K, V], _mustInit: Boolean) = new CtrieIterator[K, V](_lev, _ct, _mustInit) + protected def newIterator(_lev: Int, _ct: ConcurrentTrieMap[K, V], _mustInit: Boolean) = new ConcurrentTrieMapIterator[K, V](_lev, _ct, _mustInit) - protected def dupTo(it: CtrieIterator[K, V]) = { + protected def dupTo(it: ConcurrentTrieMapIterator[K, V]) = { it.level = this.level it.ct = this.ct it.depth = this.depth @@ -993,7 +993,7 @@ private[collection] class CtrieIterator[K, V](var level: Int, private var ct: Ct } /** Returns a sequence of iterators over subsets of this iterator. - * It's used to ease the implementation of splitters for a parallel version of the Ctrie. + * It's used to ease the implementation of splitters for a parallel version of the ConcurrentTrieMap. */ protected def subdivide(): Seq[Iterator[(K, V)]] = if (subiter ne null) { // the case where an LNode is being iterated @@ -1043,7 +1043,7 @@ private[mutable] object RestartException extends util.control.ControlThrowable /** Only used for ctrie serialization. */ @SerialVersionUID(0L - 7237891413820527142L) -private[mutable] case object CtrieSerializationEnd +private[mutable] case object ConcurrentTrieMapSerializationEnd private[mutable] object Debug { diff --git a/src/library/scala/collection/mutable/FlatArray.scala b/src/library/scala/collection/mutable/FlatArray.scala new file mode 100644 index 0000000000..a7f994bf74 --- /dev/null +++ b/src/library/scala/collection/mutable/FlatArray.scala @@ -0,0 +1,150 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + + + +package scala.collection +package mutable + +import scala.reflect.ClassManifest +import generic.CanBuildFrom + +/** + * A class representing `Array[T]`. + * + * @tparam T type of the elements in this wrapped array. + * + * @author Martin Odersky, Stephane Micheloud + * @version 1.0 + * @since 2.8 + * @define Coll WrappedArray + * @define coll wrapped array + * @define orderDependent + * @define orderDependentFold + * @define mayNotTerminateInf + * @define willNotTerminateInf + */ +abstract sealed class FlatArray[T] +extends AbstractSeq[T] + with IndexedSeq[T] + with IndexedSeqOptimized[T, FlatArray[T]] +{ + + override protected[this] def thisCollection: FlatArray[T] = this + override protected[this] def toCollection(repr: FlatArray[T]): FlatArray[T] = repr + + /** The length of the array */ + def length: Int + + /** The element at given index */ + def apply(index: Int): T + + /** Update element at given index */ + def update(index: Int, elem: T): Unit + + override def stringPrefix = "FlatArray" + + override protected[this] def newBuilder: Builder[T, FlatArray[T]] = ??? // implemented in FlatArray.Impl + + /** Clones this object, including the underlying Array. */ + override def clone: FlatArray[T] = ??? // implemented in FlatArray.Impl +} + + +/** A companion object used to create instances of `WrappedArray`. + */ +object FlatArray { + + def empty[Boxed, Unboxed](elems: Boxed*) + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): FlatArray[Boxed] = apply() + + def apply[Boxed, Unboxed](elems: Boxed*) + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): FlatArray[Boxed] = { + val b = newBuilder[Boxed, Unboxed] + b.sizeHint(elems.length) + b ++= elems + b.result + } + + def newBuilder[Boxed, Unboxed] + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): Builder[Boxed, FlatArray[Boxed]] = + new Bldr[Boxed, Unboxed](boxings, elemManifest) + + implicit def canBuildFrom[Boxed, Unboxed]( + implicit + boxings: BoxingConversions[Boxed, Unboxed], + elemManifest: ClassManifest[Unboxed]): CanBuildFrom[FlatArray[_], Boxed, FlatArray[Boxed]] = + new CanBuildFrom[FlatArray[_], Boxed, FlatArray[Boxed]] { + def apply(from: FlatArray[_]): Builder[Boxed, FlatArray[Boxed]] = + newBuilder[Boxed, Unboxed] + def apply: Builder[Boxed, FlatArray[Boxed]] = + newBuilder[Boxed, Unboxed] + } + + private class Bldr[Boxed, Unboxed](boxings: BoxingConversions[Boxed, Unboxed], manifest: ClassManifest[Unboxed]) extends Builder[Boxed, FlatArray[Boxed]] { + + private var elems: Array[Unboxed] = _ + private var capacity: Int = 0 + private var size: Int = 0 + + private def resize(size: Int) { + val newelems = manifest.newArray(size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + elems = newelems + capacity = size + } + + override def sizeHint(size: Int) { + if (capacity < size) resize(size) + } + + private def ensureSize(size: Int) { + if (capacity < size) { + var newsize = if (capacity == 0) 16 else capacity * 2 + while (newsize < size) newsize *= 2 + resize(newsize) + } + } + + def +=(elem: Boxed): this.type = { + ensureSize(size + 1) + elems(size) = boxings.unbox(elem) + size += 1 + this + } + + def clear() { + size = 0 + } + + def result(): FlatArray[Boxed] = { + if (capacity == 0 || capacity != size) resize(size) + new FlatArray.Impl(elems, boxings, manifest) + } + } + + private class Impl[Boxed, Unboxed]( + elems: Array[Unboxed], + boxings: BoxingConversions[Boxed, Unboxed], + elemManifest: ClassManifest[Unboxed]) extends FlatArray[Boxed] { + + def length = elems.length + + def apply(idx: Int): Boxed = boxings.box(elems(idx)) + + def update(idx: Int, elem: Boxed) = elems(idx) = boxings.unbox(elem) + + /** Creates new builder for this collection ==> move to subclasses + */ + override protected[this] def newBuilder: Builder[Boxed, FlatArray[Boxed]] = + new Bldr[Boxed, Unboxed](boxings, elemManifest) + + /** Clones this object, including the underlying Array. */ + override def clone: FlatArray[Boxed] = new Impl[Boxed, Unboxed](elems.clone(), boxings, elemManifest) + } +} diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 037f3b2939..96e73522b6 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -175,10 +175,10 @@ final class ListBuffer[A] } override def ++=(xs: TraversableOnce[A]): this.type = - if (xs eq this) ++= (this take size) else super.++=(xs) + if (xs.asInstanceOf[AnyRef] eq this) ++= (this take size) else super.++=(xs) override def ++=:(xs: TraversableOnce[A]): this.type = - if (xs eq this) ++=: (this take size) else super.++=:(xs) + if (xs.asInstanceOf[AnyRef] eq this) ++=: (this take size) else super.++=:(xs) /** Clears the buffer contents. */ diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala index 60a8bb1ed6..4a581f219e 100644 --- a/src/library/scala/collection/parallel/Tasks.scala +++ b/src/library/scala/collection/parallel/Tasks.scala @@ -359,7 +359,7 @@ object ThreadPoolTasks { /** An implementation of tasks objects based on the Java thread pooling API and synchronization using futures. */ -@deprecated("This implementation is not used.") +@deprecated("This implementation is not used.", "2.10.0") trait FutureThreadPoolTasks extends Tasks { import java.util.concurrent._ diff --git a/src/library/scala/collection/parallel/immutable/ParHashMap.scala b/src/library/scala/collection/parallel/immutable/ParHashMap.scala index 52d6531f9e..49b00bebdb 100644 --- a/src/library/scala/collection/parallel/immutable/ParHashMap.scala +++ b/src/library/scala/collection/parallel/immutable/ParHashMap.scala @@ -117,18 +117,6 @@ self => override def toString = "HashTrieIterator(" + sz + ")" } - /* serialization */ - - private def writeObject(out: java.io.ObjectOutputStream) { - out.defaultWriteObject - } - - private def readObject(in: java.io.ObjectInputStream) { - in.defaultReadObject - - initTaskSupport() - } - /* debug */ private[parallel] def printDebugInfo() { diff --git a/src/library/scala/collection/parallel/immutable/ParHashSet.scala b/src/library/scala/collection/parallel/immutable/ParHashSet.scala index 0a19afc426..11d92a27c9 100644 --- a/src/library/scala/collection/parallel/immutable/ParHashSet.scala +++ b/src/library/scala/collection/parallel/immutable/ParHashSet.scala @@ -112,18 +112,6 @@ self => def remaining = sz - i } - /* serialization */ - - private def writeObject(out: java.io.ObjectOutputStream) { - out.defaultWriteObject - } - - private def readObject(in: java.io.ObjectInputStream) { - in.defaultReadObject - - initTaskSupport() - } - } diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala index 364175fe41..9cac433460 100644 --- a/src/library/scala/collection/parallel/immutable/ParRange.scala +++ b/src/library/scala/collection/parallel/immutable/ParRange.scala @@ -106,18 +106,6 @@ self => } } - /* serialization */ - - private def writeObject(out: java.io.ObjectOutputStream) { - out.defaultWriteObject - } - - private def readObject(in: java.io.ObjectInputStream) { - in.defaultReadObject - - initTaskSupport() - } - } object ParRange { diff --git a/src/library/scala/collection/parallel/immutable/ParVector.scala b/src/library/scala/collection/parallel/immutable/ParVector.scala index 310b09a016..5d9c431bc1 100644 --- a/src/library/scala/collection/parallel/immutable/ParVector.scala +++ b/src/library/scala/collection/parallel/immutable/ParVector.scala @@ -78,18 +78,6 @@ extends ParSeq[T] splitted.map(v => new ParVector(v).splitter.asInstanceOf[ParVectorIterator]) } } - - /* serialization */ - - private def writeObject(out: java.io.ObjectOutputStream) { - out.defaultWriteObject - } - - private def readObject(in: java.io.ObjectInputStream) { - in.defaultReadObject - - initTaskSupport() - } } diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala index 683b7eaa9a..c33495bd39 100644 --- a/src/library/scala/collection/parallel/mutable/ParArray.scala +++ b/src/library/scala/collection/parallel/mutable/ParArray.scala @@ -675,8 +675,6 @@ self => // get raw array from arrayseq array = arrayseq.array.asInstanceOf[Array[Any]] - - initTaskSupport() } } diff --git a/src/library/scala/collection/parallel/mutable/ParCtrie.scala b/src/library/scala/collection/parallel/mutable/ParConcurrentTrieMap.scala index b4dc8beb2a..a6495161ea 100644 --- a/src/library/scala/collection/parallel/mutable/ParCtrie.scala +++ b/src/library/scala/collection/parallel/mutable/ParConcurrentTrieMap.scala @@ -20,12 +20,12 @@ import scala.collection.mutable.LNode import scala.collection.mutable.CNode import scala.collection.mutable.SNode import scala.collection.mutable.INode -import scala.collection.mutable.Ctrie -import scala.collection.mutable.CtrieIterator +import scala.collection.mutable.ConcurrentTrieMap +import scala.collection.mutable.ConcurrentTrieMapIterator -/** Parallel Ctrie collection. +/** Parallel ConcurrentTrieMap collection. * * It has its bulk operations parallelized, but uses the snapshot operation * to create the splitter. This means that parallel bulk operations can be @@ -34,24 +34,24 @@ import scala.collection.mutable.CtrieIterator * @author Aleksandar Prokopec * @since 2.10 */ -final class ParCtrie[K, V] private[collection] (private val ctrie: Ctrie[K, V]) +final class ParConcurrentTrieMap[K, V] private[collection] (private val ctrie: ConcurrentTrieMap[K, V]) extends ParMap[K, V] - with GenericParMapTemplate[K, V, ParCtrie] - with ParMapLike[K, V, ParCtrie[K, V], Ctrie[K, V]] - with ParCtrieCombiner[K, V] + with GenericParMapTemplate[K, V, ParConcurrentTrieMap] + with ParMapLike[K, V, ParConcurrentTrieMap[K, V], ConcurrentTrieMap[K, V]] + with ParConcurrentTrieMapCombiner[K, V] with Serializable { - def this() = this(new Ctrie) + def this() = this(new ConcurrentTrieMap) - override def mapCompanion: GenericParMapCompanion[ParCtrie] = ParCtrie + override def mapCompanion: GenericParMapCompanion[ParConcurrentTrieMap] = ParConcurrentTrieMap - override def empty: ParCtrie[K, V] = ParCtrie.empty + override def empty: ParConcurrentTrieMap[K, V] = ParConcurrentTrieMap.empty - protected[this] override def newCombiner = ParCtrie.newCombiner + protected[this] override def newCombiner = ParConcurrentTrieMap.newCombiner override def seq = ctrie - def splitter = new ParCtrieSplitter(0, ctrie.readOnlySnapshot().asInstanceOf[Ctrie[K, V]], true) + def splitter = new ParConcurrentTrieMapSplitter(0, ctrie.readOnlySnapshot().asInstanceOf[ConcurrentTrieMap[K, V]], true) override def clear() = ctrie.clear() @@ -87,11 +87,11 @@ extends ParMap[K, V] } } - override def stringPrefix = "ParCtrie" + override def stringPrefix = "ParConcurrentTrieMap" /* tasks */ - /** Computes Ctrie size in parallel. */ + /** Computes ConcurrentTrieMap size in parallel. */ class Size(offset: Int, howmany: Int, array: Array[BasicNode]) extends Task[Int, Size] { var result = -1 def leaf(prev: Option[Int]) = { @@ -115,30 +115,18 @@ extends ParMap[K, V] override def merge(that: Size) = result = result + that.result } - /* serialization */ - - private def writeObject(out: java.io.ObjectOutputStream) { - out.defaultWriteObject - } - - private def readObject(in: java.io.ObjectInputStream) { - in.defaultReadObject - - initTaskSupport() - } - } -private[collection] class ParCtrieSplitter[K, V](lev: Int, ct: Ctrie[K, V], mustInit: Boolean) -extends CtrieIterator[K, V](lev, ct, mustInit) +private[collection] class ParConcurrentTrieMapSplitter[K, V](lev: Int, ct: ConcurrentTrieMap[K, V], mustInit: Boolean) +extends ConcurrentTrieMapIterator[K, V](lev, ct, mustInit) with IterableSplitter[(K, V)] { // only evaluated if `remaining` is invoked (which is not used by most tasks) lazy val totalsize = ct.par.size var iterated = 0 - protected override def newIterator(_lev: Int, _ct: Ctrie[K, V], _mustInit: Boolean) = new ParCtrieSplitter[K, V](_lev, _ct, _mustInit) + protected override def newIterator(_lev: Int, _ct: ConcurrentTrieMap[K, V], _mustInit: Boolean) = new ParConcurrentTrieMapSplitter[K, V](_lev, _ct, _mustInit) override def shouldSplitFurther[S](coll: collection.parallel.ParIterable[S], parallelismLevel: Int) = { val maxsplits = 3 + Integer.highestOneBit(parallelismLevel) @@ -165,15 +153,15 @@ extends CtrieIterator[K, V](lev, ct, mustInit) } -/** Only used within the `ParCtrie`. */ -private[mutable] trait ParCtrieCombiner[K, V] extends Combiner[(K, V), ParCtrie[K, V]] { +/** Only used within the `ParConcurrentTrieMap`. */ +private[mutable] trait ParConcurrentTrieMapCombiner[K, V] extends Combiner[(K, V), ParConcurrentTrieMap[K, V]] { - def combine[N <: (K, V), NewTo >: ParCtrie[K, V]](other: Combiner[N, NewTo]): Combiner[N, NewTo] = if (this eq other) this else { + def combine[N <: (K, V), NewTo >: ParConcurrentTrieMap[K, V]](other: Combiner[N, NewTo]): Combiner[N, NewTo] = if (this eq other) this else { throw new UnsupportedOperationException("This shouldn't have been called in the first place.") - val thiz = this.asInstanceOf[ParCtrie[K, V]] - val that = other.asInstanceOf[ParCtrie[K, V]] - val result = new ParCtrie[K, V] + val thiz = this.asInstanceOf[ParConcurrentTrieMap[K, V]] + val that = other.asInstanceOf[ParConcurrentTrieMap[K, V]] + val result = new ParConcurrentTrieMap[K, V] result ++= thiz.iterator result ++= that.iterator @@ -186,13 +174,13 @@ private[mutable] trait ParCtrieCombiner[K, V] extends Combiner[(K, V), ParCtrie[ } -object ParCtrie extends ParMapFactory[ParCtrie] { +object ParConcurrentTrieMap extends ParMapFactory[ParConcurrentTrieMap] { - def empty[K, V]: ParCtrie[K, V] = new ParCtrie[K, V] + def empty[K, V]: ParConcurrentTrieMap[K, V] = new ParConcurrentTrieMap[K, V] - def newCombiner[K, V]: Combiner[(K, V), ParCtrie[K, V]] = new ParCtrie[K, V] + def newCombiner[K, V]: Combiner[(K, V), ParConcurrentTrieMap[K, V]] = new ParConcurrentTrieMap[K, V] - implicit def canBuildFrom[K, V]: CanCombineFrom[Coll, (K, V), ParCtrie[K, V]] = new CanCombineFromMap[K, V] + implicit def canBuildFrom[K, V]: CanCombineFrom[Coll, (K, V), ParConcurrentTrieMap[K, V]] = new CanCombineFromMap[K, V] } diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala index 72526aadb1..6ce6c45460 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala @@ -106,8 +106,6 @@ self => private def readObject(in: java.io.ObjectInputStream) { init[V](in, new Entry(_, _)) - - initTaskSupport() } private[parallel] override def brokenInvariants = { diff --git a/src/library/scala/collection/parallel/mutable/ParHashSet.scala b/src/library/scala/collection/parallel/mutable/ParHashSet.scala index 84b7c4e42c..e0a2ab03df 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashSet.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashSet.scala @@ -84,8 +84,6 @@ extends ParSet[T] private def readObject(in: java.io.ObjectInputStream) { init(in, x => x) - - initTaskSupport() } import collection.DebugUtils._ diff --git a/src/library/scala/math/Equiv.scala b/src/library/scala/math/Equiv.scala index 92a794578e..bd8414a18d 100644 --- a/src/library/scala/math/Equiv.scala +++ b/src/library/scala/math/Equiv.scala @@ -29,7 +29,7 @@ import java.util.Comparator * @since 2.7 */ -trait Equiv[T] { +trait Equiv[T] extends Any { /** Returns `true` iff `x` is equivalent to `y`. */ def equiv(x: T, y: T): Boolean diff --git a/src/library/scala/math/Ordered.scala b/src/library/scala/math/Ordered.scala index 53d618db63..b76030718f 100644 --- a/src/library/scala/math/Ordered.scala +++ b/src/library/scala/math/Ordered.scala @@ -50,7 +50,7 @@ package scala.math * @author Martin Odersky * @version 1.1, 2006-07-24 */ -trait Ordered[A] extends java.lang.Comparable[A] { +trait Ordered[A] extends Any with java.lang.Comparable[A] { /** Result of comparing `this` with operand `that`. * diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala index 366af34ee9..1ef1911fd3 100644 --- a/src/library/scala/package.scala +++ b/src/library/scala/package.scala @@ -64,6 +64,9 @@ package object scala { type ::[A] = scala.collection.immutable.::[A] val :: = scala.collection.immutable.:: + val +: = scala.collection.+: + val :+ = scala.collection.:+ + type Stream[+A] = scala.collection.immutable.Stream[A] val Stream = scala.collection.immutable.Stream val #:: = scala.collection.immutable.Stream.#:: diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index d393ac47fa..37be067614 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -207,18 +207,18 @@ object ClassManifest { * pass varargs as arrays into this, we get an infinitely recursive call * to boxArray. (Besides, having a separate case is more efficient) */ - def classType[T <: AnyRef](clazz: jClass[_]): ClassManifest[T] = + def classType[T](clazz: jClass[_]): ClassManifest[T] = new ClassTypeManifest[T](None, clazz, Nil) /** ClassManifest for the class type `clazz[args]`, where `clazz` is * a top-level or static class and `args` are its type arguments */ - def classType[T <: AnyRef](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] = + def classType[T](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] = new ClassTypeManifest[T](None, clazz, arg1 :: args.toList) /** ClassManifest for the class type `clazz[args]`, where `clazz` is * a class with non-package prefix type `prefix` and type arguments `args`. */ - def classType[T <: AnyRef](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] = + def classType[T](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] = new ClassTypeManifest[T](Some(prefix), clazz, args.toList) def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match { @@ -251,7 +251,7 @@ object ClassManifest { /** Manifest for the class type `clazz[args]`, where `clazz` is * a top-level or static class: todo: we should try to merge this with Manifest's class */ -private class ClassTypeManifest[T <: AnyRef]( +private class ClassTypeManifest[T]( prefix: Option[OptManifest[_]], val erasure: jClass[_], override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T] diff --git a/src/library/scala/reflect/api/Modifier.scala b/src/library/scala/reflect/api/Modifier.scala index cbfe91e59b..1b67929e15 100644 --- a/src/library/scala/reflect/api/Modifier.scala +++ b/src/library/scala/reflect/api/Modifier.scala @@ -2,7 +2,7 @@ package scala.reflect.api import collection.{ immutable, mutable } -sealed abstract class Modifier { +abstract class Modifier private[api] () { def name: String def isKeyword: Boolean def sourceString: String = if (isKeyword) "`" + name + "`" else name diff --git a/src/library/scala/reflect/api/StandardDefinitions.scala b/src/library/scala/reflect/api/StandardDefinitions.scala index e737b0ea4f..c3d989f971 100755 --- a/src/library/scala/reflect/api/StandardDefinitions.scala +++ b/src/library/scala/reflect/api/StandardDefinitions.scala @@ -61,7 +61,7 @@ trait StandardDefinitions { self: Universe => def vmSignature(sym: Symbol, info: Type): String /** Is symbol one of the value classes? */ - def isValueClass(sym: Symbol): Boolean // !!! better name? + def isPrimitiveValueClass(sym: Symbol): Boolean // !!! better name? /** Is symbol one of the numeric value classes? */ def isNumericValueClass(sym: Symbol): Boolean // !!! better name? diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 181ce85dac..a355207ff0 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -309,7 +309,7 @@ trait Trees { self: Universe => * quite frequently called modules to reduce ambiguity. */ case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) - extends ImplDef + extends ImplDef /** A common base class for ValDefs and DefDefs. */ @@ -319,8 +319,13 @@ trait Trees { self: Universe => def rhs: Tree } - /** A value definition (this includes vars as well, which differ from - * vals only in having the MUTABLE flag set in their Modifiers.) + /** Broadly speaking, a value definition. All these are encoded as ValDefs: + * + * - immutable values, e.g. "val x" + * - mutable values, e.g. "var x" - the MUTABLE flag set in mods + * - lazy values, e.g. "lazy val x" - the LAZY flag set in mods + * - method parameters, see vparamss in DefDef - the PARAM flag is set in mods + * - explicit self-types, e.g. class A { self: Bar => } - !!! not sure what is set. */ case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef @@ -390,7 +395,6 @@ trait Trees { self: Universe => // { // def bar // owner is local dummy // } - // System.err.println("TEMPLATE: " + parents) } /** Block of expressions (semicolon separated expressions) */ @@ -741,6 +745,12 @@ trait Trees { self: Universe => case t => sys.error("Not a ClassDef: " + t + "/" + t.getClass) } + def deriveModuleDef(mdef: Tree)(applyToImpl: Template => Template): ModuleDef = mdef match { + case ModuleDef(mods0, name0, impl0) => + treeCopy.ModuleDef(mdef, mods0, name0, applyToImpl(impl0)) + case t => + sys.error("Not a ModuleDef: " + t + "/" + t.getClass) + } def deriveCaseDef(cdef: Tree)(applyToBody: Tree => Tree): CaseDef = cdef match { case CaseDef(pat0, guard0, body0) => treeCopy.CaseDef(cdef, pat0, guard0, applyToBody(body0)) diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala index cc8e85b9c8..0371e2c5df 100755 --- a/src/library/scala/reflect/api/Types.scala +++ b/src/library/scala/reflect/api/Types.scala @@ -46,7 +46,7 @@ trait Types { self: Universe => /** Substitute types in `to` for corresponding occurrences of references to * symbols `from` in this type. */ - def substituteTypes(from: List[Symbol], to: List[Type]): Type // !!! Too many things with names like "subst" + def substituteTypes(from: List[Symbol], to: List[Type]): Type /** If this is a parameterized types, the type arguments. * Otherwise the empty list diff --git a/src/library/scala/runtime/ScalaNumberProxy.scala b/src/library/scala/runtime/ScalaNumberProxy.scala index 09e1611dcd..d9b9a7843f 100644 --- a/src/library/scala/runtime/ScalaNumberProxy.scala +++ b/src/library/scala/runtime/ScalaNumberProxy.scala @@ -64,12 +64,12 @@ abstract class FractionalProxy[T : Fractional] extends ScalaNumberProxy[T] with def to(end: T, step: T): NumericRange.Inclusive[T] = NumericRange.inclusive(self, end, step) } -trait OrderedProxy[T] extends Typed[T] with Ordered[T] { +trait OrderedProxy[T] extends Any with Ordered[T] with Typed[T] { protected def ord: Ordering[T] def compare(y: T) = ord.compare(self, y) } -trait RangedProxy[T] extends Typed[T] { +trait RangedProxy[T] extends Any with Typed[T] { type ResultWithoutStep def until(end: T): ResultWithoutStep diff --git a/src/library/scala/runtime/StringAdd.scala b/src/library/scala/runtime/StringAdd.scala index ae1975cb4c..a7e78ea9a3 100644 --- a/src/library/scala/runtime/StringAdd.scala +++ b/src/library/scala/runtime/StringAdd.scala @@ -8,13 +8,15 @@ package scala.runtime -final class StringAdd(self: Any) { +/** A wrapper class that adds string concatenation `+` to any value */ +final class StringAdd(val self: Any) { + + // Note: The implicit conversion from Any to StringAdd is one of two + // implicit conversions from Any to AnyRef in Predef. It is important to have at least + // two such conversions, so that silent conversions from value types to AnyRef + // are avoided. If StringFormat should become a value class, another + // implicit conversion from Any to AnyRef has to be introduced in Predef def +(other: String) = String.valueOf(self) + other - /** Returns string formatted according to given `format` string. - * Format strings are as for `String.format` - * (@see java.lang.String.format). - */ - def formatted(fmtstr: String): String = fmtstr format self } diff --git a/src/library/scala/runtime/StringFormat.scala b/src/library/scala/runtime/StringFormat.scala new file mode 100644 index 0000000000..c120cbb14d --- /dev/null +++ b/src/library/scala/runtime/StringFormat.scala @@ -0,0 +1,27 @@ +/* *\ +** ________ ___ __ ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ |_| ** +** ** +\* */ + +package scala.runtime + +/** A wrapper class that adds a `formatted` operation to any value + */ +final class StringFormat(val self: Any) { + + // Note: The implicit conversion from Any to StringFormat is one of two + // implicit conversions from Any to AnyRef in Predef. It is important to have at least + // two such conversions, so that silent conversions from value types to AnyRef + // are avoided. If StringFormat should become a value class, another + // implicit conversion from Any to AnyRef has to be introduced in Predef + + /** Returns string formatted according to given `format` string. + * Format strings are as for `String.format` + * (@see java.lang.String.format). + */ + @inline def formatted(fmtstr: String): String = fmtstr format self + +} diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index a62d74b1f6..38ca89b98b 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -15,7 +15,7 @@ import java.util.jar.Attributes.{ Name => AttributeName } /** Loads `library.properties` from the jar. */ object Properties extends PropertiesTrait { protected def propCategory = "library" - protected def pickJarBasedOn = classOf[ScalaObject] + protected def pickJarBasedOn = classOf[Option[_]] /** Scala manifest attributes. */ @@ -72,10 +72,11 @@ private[scala] trait PropertiesTrait { * it is an RC, Beta, etc. or was built from source, or if the version * cannot be read. */ - val releaseVersion = scalaPropOrNone("version.number") flatMap { s => - val segments = s split '.' - if (segments.size == 4 && segments.last == "final") Some(segments take 3 mkString ".") else None - } + val releaseVersion = + for { + v <- scalaPropOrNone("maven.version.number") + if !(v endsWith "-SNAPSHOT") + } yield v /** The development Scala version, if this is not a final release. * The precise contents are not guaranteed, but it aims to provide a @@ -85,15 +86,12 @@ private[scala] trait PropertiesTrait { * @return Some(version) if this is a non-final version, None if this * is a final release or the version cannot be read. */ - val developmentVersion = scalaPropOrNone("version.number") flatMap { s => - val segments = s split '.' - if (segments.isEmpty || segments.last == "final") - None - else if (segments.last startsWith "r") - Some(s takeWhile (ch => ch != '-')) // Cutting e.g. 2.10.0.r24774-b20110417125606 to 2.10.0.r24774 - else - Some(s) - } + val developmentVersion = + for { + v <- scalaPropOrNone("maven.version.number") + if v endsWith "-SNAPSHOT" + ov <- scalaPropOrNone("version.number") + } yield ov /** Either the development or release version if known, otherwise * the empty string. diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala index df52b34f87..cc244a5b88 100644..100755 --- a/src/library/scala/xml/Elem.scala +++ b/src/library/scala/xml/Elem.scala @@ -17,8 +17,18 @@ package scala.xml * @author Burak Emir <bqe@google.com> */ object Elem { - def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) = - new Elem(prefix, label, attributes, scope, child:_*) + /** Build an Elem, setting its minimizeEmpty property to <code>true</code> if it has no children. Note that this + * default may not be exactly what you want, as some XML dialects don't permit some elements to be minimized. + * + * @deprecated This factory method is retained for backward compatibility; please use the other one, with which you + * can specify your own preference for minimizeEmpty. + */ + @deprecated + def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*): Elem = + apply(prefix, label, attributes, scope, child.isEmpty, child: _*) + + def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, minimizeEmpty: Boolean, child: Node*): Elem = + new Elem(prefix,label,attributes,scope, minimizeEmpty, child:_*) def unapplySeq(n: Node) = n match { case _: SpecialNode | _: Group => None @@ -29,11 +39,13 @@ object Elem { /** The case class `Elem` extends the `Node` class, * providing an immutable data object representing an XML element. * - * @param prefix namespace prefix (may be null, but not the empty string) - * @param label the element name - * @param attribute the attribute map - * @param scope the scope containing the namespace bindings - * @param child the children of this node + * @param prefix namespace prefix (may be null, but not the empty string) + * @param label the element name + * @param attributes1 the attribute map + * @param scope the scope containing the namespace bindings + * @param minimizeEmpty `true` if this element should be serialized as minimized (i.e. "<el/>") when + * empty; `false` if it should be written out in long form. + * @param child the children of this node * * Copyright 2008 Google Inc. All Rights Reserved. * @author Burak Emir <bqe@google.com> @@ -43,9 +55,15 @@ class Elem( val label: String, attributes1: MetaData, override val scope: NamespaceBinding, + val minimizeEmpty: Boolean, val child: Node*) extends Node with Serializable { + @deprecated("This constructor is retained for backward compatibility. Please use the primary constructor, which lets you specify your own preference for `minimizeEmpty`.", "2.10") + def this(prefix: String, label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) = { + this(prefix, label, attributes, scope, child.isEmpty, child: _*) + } + final override def doCollectNamespaces = true final override def doTransform = true @@ -83,8 +101,9 @@ extends Node with Serializable label: String = this.label, attributes: MetaData = this.attributes, scope: NamespaceBinding = this.scope, + minimizeEmpty: Boolean = this.minimizeEmpty, child: Seq[Node] = this.child.toSeq - ): Elem = Elem(prefix, label, attributes, scope, child: _*) + ): Elem = Elem(prefix, label, attributes, scope, minimizeEmpty, child: _*) /** Returns concatenation of `text(n)` for each child `n`. */ diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala index 2ead18fe08..02e34e1bdc 100644..100755 --- a/src/library/scala/xml/Node.scala +++ b/src/library/scala/xml/Node.scala @@ -159,7 +159,7 @@ abstract class Node extends NodeSeq { * @return ... */ def buildString(stripComments: Boolean): String = - Utility.toXML(this, stripComments = stripComments).toString + Utility.serialize(this, stripComments = stripComments).toString /** * Same as `toString('''false''')`. diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala index ea39b51352..64dbd00f2f 100644..100755 --- a/src/library/scala/xml/PrettyPrinter.scala +++ b/src/library/scala/xml/PrettyPrinter.scala @@ -161,7 +161,7 @@ class PrettyPrinter(width: Int, step: Int) { case _ => val test = { val sb = new StringBuilder() - Utility.toXML(node, pscope, sb, false) + Utility.serialize(node, pscope, sb, false) if (doPreserve(node)) sb.toString else TextBuffer.fromString(sb.toString).toText(0).data } diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index fc20b892b9..9f944c0e92 100644..100755 --- a/src/library/scala/xml/Utility.scala +++ b/src/library/scala/xml/Utility.scala @@ -181,6 +181,13 @@ object Utility extends AnyRef with parsing.TokenTests { // sb.toString() // } + /** + * Serialize the provided Node to the provided StringBuilder. + * <p/> + * Note that calling this source-compatible method will result in the same old, arguably almost universally unwanted, + * behaviour. + */ + @deprecated("Please use `serialize` instead and specify a `minimizeTags` parameter", "2.10") def toXML( x: Node, pscope: NamespaceBinding = TopScope, @@ -190,29 +197,51 @@ object Utility extends AnyRef with parsing.TokenTests { preserveWhitespace: Boolean = false, minimizeTags: Boolean = false): StringBuilder = { + serialize(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, if (minimizeTags) MinimizeMode.Always else MinimizeMode.Never) + } + + /** + * Serialize an XML Node to a StringBuilder. + * + * This is essentially a minor rework of `toXML` that can't have the same name due to an unfortunate + * combination of named/default arguments and overloading. + * + * @todo use a Writer instead + */ + def serialize( + x: Node, + pscope: NamespaceBinding = TopScope, + sb: StringBuilder = new StringBuilder, + stripComments: Boolean = false, + decodeEntities: Boolean = true, + preserveWhitespace: Boolean = false, + minimizeTags: MinimizeMode.Value = MinimizeMode.Default): StringBuilder = + { x match { - case c: Comment => if (!stripComments) c buildString sb else sb - case x: SpecialNode => x buildString sb - case g: Group => - g.nodes foreach {toXML(_, x.scope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)} - sb - case _ => + case c: Comment if !stripComments => c buildString sb + case s: SpecialNode => s buildString sb + case g: Group => for (c <- g.nodes) serialize(c, g.scope, sb, minimizeTags = minimizeTags) ; sb + case el: Elem => // print tag with namespace declarations sb.append('<') - x.nameToString(sb) - if (x.attributes ne null) x.attributes.buildString(sb) - x.scope.buildString(sb, pscope) - if (x.child.isEmpty && minimizeTags) { + el.nameToString(sb) + if (el.attributes ne null) el.attributes.buildString(sb) + el.scope.buildString(sb, pscope) + if (el.child.isEmpty && + (minimizeTags == MinimizeMode.Always || + (minimizeTags == MinimizeMode.Default && el.minimizeEmpty))) + { // no children, so use short form: <xyz .../> - sb.append(" />") + sb.append("/>") } else { // children, so use long form: <xyz ...>...</xyz> sb.append('>') - sequenceToXML(x.child, x.scope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) + sequenceToXML(el.child, el.scope, sb, stripComments) sb.append("</") - x.nameToString(sb) + el.nameToString(sb) sb.append('>') } + case _ => throw new IllegalArgumentException("Don't know how to serialize a " + x.getClass.getName) } } @@ -223,20 +252,20 @@ object Utility extends AnyRef with parsing.TokenTests { stripComments: Boolean = false, decodeEntities: Boolean = true, preserveWhitespace: Boolean = false, - minimizeTags: Boolean = false): Unit = + minimizeTags: MinimizeMode.Value = MinimizeMode.Default): Unit = { if (children.isEmpty) return else if (children forall isAtomAndNotText) { // add space val it = children.iterator val f = it.next - toXML(f, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) + serialize(f, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) while (it.hasNext) { val x = it.next sb.append(' ') - toXML(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) + serialize(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) } } - else children foreach { toXML(_, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) } + else children foreach { serialize(_, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) } } /** diff --git a/src/library/scala/xml/XML.scala b/src/library/scala/xml/XML.scala index bc3033d081..4beba91899 100644..100755 --- a/src/library/scala/xml/XML.scala +++ b/src/library/scala/xml/XML.scala @@ -26,6 +26,21 @@ object Source def fromSysId(sysID: String) = new InputSource(sysID) def fromString(string: String) = fromReader(new StringReader(string)) } + +/** + * Governs how empty elements (i.e. those without child elements) should be serialized. + */ +object MinimizeMode extends Enumeration { + /** Minimize empty tags if they were originally empty when parsed, or if they were constructed with [[scala.xml.Elem]]`#minimizeEmpty` == true */ + val Default = Value + + /** Always minimize empty tags. Note that this may be problematic for XHTML, in which case [[scala.xml.Xhtml]]`#toXhtml` should be used instead. */ + val Always = Value + + /** Never minimize empty tags. */ + val Never = Value +} + import Source._ /** The object `XML` provides constants, and functions to load @@ -83,10 +98,10 @@ object XML extends XMLLoader[Elem] * @param xmlDecl if true, write xml declaration * @param doctype if not null, write doctype declaration */ - final def write(w: java.io.Writer, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType) { + final def write(w: java.io.Writer, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType, minimizeTags: MinimizeMode.Value = MinimizeMode.Default) { /* TODO: optimize by giving writer parameter to toXML*/ if (xmlDecl) w.write("<?xml version='1.0' encoding='" + enc + "'?>\n") if (doctype ne null) w.write( doctype.toString() + "\n") - w.write(Utility.toXML(node).toString) + w.write(Utility.serialize(node, minimizeTags = minimizeTags).toString) } } diff --git a/src/library/scala/xml/factory/Binder.scala b/src/library/scala/xml/factory/Binder.scala index a8b0ed585b..b4fe153bd8 100644..100755 --- a/src/library/scala/xml/factory/Binder.scala +++ b/src/library/scala/xml/factory/Binder.scala @@ -43,13 +43,13 @@ abstract class Binder(val preserveWS: Boolean) extends ValidatingMarkupHandler { result &+ text(0, x.data) case x:EntityRef => result &+ entityRef(0, x.entityName) - case _ => - elemStart(0, n.prefix, n.label, n.attributes, n.scope) + case x:Elem => + elemStart(0, x.prefix, x.label, x.attributes, x.scope) val old = result result = new NodeBuffer() - for (m <- n.child) traverse(m) - result = old &+ elem(0, n.prefix, n.label, n.attributes, n.scope, NodeSeq.fromSeq(result)).toList; - elemEnd(0, n.prefix, n.label) + for (m <- x.child) traverse(m) + result = old &+ elem(0, x.prefix, x.label, x.attributes, x.scope, x.minimizeEmpty, NodeSeq.fromSeq(result)).toList; + elemEnd(0, x.prefix, x.label) } final def validate(n: Node): Node = { diff --git a/src/library/scala/xml/parsing/ConstructingHandler.scala b/src/library/scala/xml/parsing/ConstructingHandler.scala index 60c19138c3..7e61674682 100644..100755 --- a/src/library/scala/xml/parsing/ConstructingHandler.scala +++ b/src/library/scala/xml/parsing/ConstructingHandler.scala @@ -21,8 +21,8 @@ abstract class ConstructingHandler extends MarkupHandler val preserveWS: Boolean def elem(pos: Int, pre: String, label: String, attrs: MetaData, - pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq = - Elem(pre, label, attrs, pscope, nodes:_*) + pscope: NamespaceBinding, empty: Boolean, nodes: NodeSeq): NodeSeq = + Elem(pre, label, attrs, pscope, empty, nodes:_*) def procInstr(pos: Int, target: String, txt: String) = ProcInstr(target, txt) diff --git a/src/library/scala/xml/parsing/DefaultMarkupHandler.scala b/src/library/scala/xml/parsing/DefaultMarkupHandler.scala index 699c5b2b5f..e0258ba781 100644..100755 --- a/src/library/scala/xml/parsing/DefaultMarkupHandler.scala +++ b/src/library/scala/xml/parsing/DefaultMarkupHandler.scala @@ -16,7 +16,7 @@ package parsing abstract class DefaultMarkupHandler extends MarkupHandler { def elem(pos: Int, pre: String, label: String, attrs: MetaData, - scope:NamespaceBinding, args: NodeSeq) = NodeSeq.Empty + scope:NamespaceBinding, empty: Boolean, args: NodeSeq) = NodeSeq.Empty def procInstr(pos: Int, target: String, txt: String) = NodeSeq.Empty diff --git a/src/library/scala/xml/parsing/MarkupHandler.scala b/src/library/scala/xml/parsing/MarkupHandler.scala index 87e785a98f..83db2f177d 100644..100755 --- a/src/library/scala/xml/parsing/MarkupHandler.scala +++ b/src/library/scala/xml/parsing/MarkupHandler.scala @@ -75,10 +75,11 @@ abstract class MarkupHandler extends Logged * @param pre the prefix * @param label the local name * @param attrs the attributes (metadata) + * @param empty `true` if the element was previously empty; `false` otherwise. * @param args the children of this element * @return ... */ - def elem(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, args: NodeSeq): NodeSeq + def elem(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding, empty: Boolean, args: NodeSeq): NodeSeq /** callback method invoked by MarkupParser after parsing PI. */ diff --git a/src/library/scala/xml/parsing/MarkupParser.scala b/src/library/scala/xml/parsing/MarkupParser.scala index 1de08b3025..32feaa2209 100644..100755 --- a/src/library/scala/xml/parsing/MarkupParser.scala +++ b/src/library/scala/xml/parsing/MarkupParser.scala @@ -569,7 +569,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests tmp } } - val res = handle.elem(pos, pre, local, aMap, scope, ts) + val res = handle.elem(pos, pre, local, aMap, scope, ts == NodeSeq.Empty, ts) handle.elemEnd(pos, pre, local) res } diff --git a/src/library/scala/xml/pull/XMLEventReader.scala b/src/library/scala/xml/pull/XMLEventReader.scala index f84d91d138..c764d042c8 100755 --- a/src/library/scala/xml/pull/XMLEventReader.scala +++ b/src/library/scala/xml/pull/XMLEventReader.scala @@ -81,7 +81,7 @@ extends collection.AbstractIterator[XMLEvent] // memory usage optimization return one <ignore/> for top level to satisfy // MarkupParser.document() otherwise NodeSeq.Empty private var ignoreWritten = false - final def elem(pos: Int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq = + final def elem(pos: Int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, empty: Boolean, nodes: NodeSeq): NodeSeq = if (level == 1 && !ignoreWritten) {ignoreWritten = true; <ignore/> } else NodeSeq.Empty def procInstr(pos: Int, target: String, txt: String) = setEvent(EvProcInstr(target, txt)) diff --git a/src/partest/scala/tools/partest/CompilerTest.scala b/src/partest/scala/tools/partest/CompilerTest.scala index 1cb09b433a..994928c0f6 100644 --- a/src/partest/scala/tools/partest/CompilerTest.scala +++ b/src/partest/scala/tools/partest/CompilerTest.scala @@ -19,9 +19,42 @@ abstract class CompilerTest extends DirectTest { lazy val global: Global = newCompiler() lazy val units = compilationUnits(global)(sources: _ *) + import global._ + import definitions._ override def extraSettings = "-usejavacp -d " + testOutput.path - def sources: List[String] = List(code) def show() = (sources, units).zipped foreach check + + // Override at least one of these... + def code = "" + def sources: List[String] = List(code) + + // Utility functions + + class MkType(sym: Symbol) { + def apply[M](implicit m1: Manifest[M]): Type = + if (sym eq NoSymbol) NoType + else appliedType(sym.typeConstructor, List(m1) map (x => manifestToType(x))) + } + implicit def mkMkType(sym: Symbol) = new MkType(sym) + + def allMembers(root: Symbol): List[Symbol] = { + def loop(seen: Set[Symbol], roots: List[Symbol]): List[Symbol] = { + val latest = roots flatMap (_.info.members) filterNot (seen contains _) + if (latest.isEmpty) seen.toList.sortWith(_ isLess _) + else loop(seen ++ latest, latest) + } + loop(Set(), List(root)) + } + + class SymsInPackage(pkgName: String) { + def pkg = getRequiredModule(pkgName) + def classes = allMembers(pkg) filter (_.isClass) + def modules = allMembers(pkg) filter (_.isModule) + def symbols = classes ++ terms filterNot (_ eq NoSymbol) + def terms = allMembers(pkg) filter (s => s.isTerm && !s.isConstructor) + def tparams = classes flatMap (_.info.typeParams) + def tpes = symbols map (_.tpe) distinct + } } diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 07444f8d4b..4e7f36bdc9 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -69,7 +69,7 @@ abstract class DirectTest extends App { /** Constructor/main body **/ try show() - catch { case t => println(t) ; sys.exit(1) } + catch { case t => println(t) ; t.printStackTrace ; sys.exit(1) } /** Debugger interest only below this line **/ protected def isDebug = (sys.props contains "partest.debug") || (sys.env contains "PARTEST_DEBUG") |