summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-08-24 16:20:34 +0000
committerMartin Odersky <odersky@gmail.com>2009-08-24 16:20:34 +0000
commitc1df5090b9b2857b5a78e3da381baf6e2dac45e8 (patch)
tree89ce9b2faefb86842d66e1969d0ae64840a45e11
parent99705d852dfd39986a91dfb13b9f9be090f7f41a (diff)
downloadscala-c1df5090b9b2857b5a78e3da381baf6e2dac45e8.tar.gz
scala-c1df5090b9b2857b5a78e3da381baf6e2dac45e8.tar.bz2
scala-c1df5090b9b2857b5a78e3da381baf6e2dac45e8.zip
Refined manifest checking in preparation for ar...
Refined manifest checking in preparation for arrays with manifests change.
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala33
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala39
-rw-r--r--src/library/scala/reflect/Manifest.scala142
-rw-r--r--src/library/scala/runtime/BoxedArray.scala3
5 files changed, 123 insertions, 102 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index ffe6cb30ca..71f005a98a 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -179,10 +179,10 @@ trait Definitions {
def methodCache_add = getMember(MethodCacheClass, nme.add_)
// scala.reflect
- lazy val ManifestClass = getClass("scala.reflect.Manifest")
- lazy val ManifestModule = getModule("scala.reflect.Manifest")
- lazy val FullManifestClass = getClass("scala.reflect.FullManifest")
- lazy val FullManifestModule = getModule("scala.reflect.FullManifest")
+ lazy val PartialManifestClass = getClass("scala.reflect.ClassManifest")
+ lazy val PartialManifestModule = getModule("scala.reflect.ClassManifest")
+ lazy val FullManifestClass = getClass("scala.reflect.Manifest")
+ lazy val FullManifestModule = getModule("scala.reflect.Manifest")
lazy val OptManifestClass = getClass("scala.reflect.OptManifest")
lazy val NoManifest = getModule("scala.reflect.NoManifest")
lazy val CodeClass = getClass(sn.Code)
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 05aa3be60b..7af0c4f56c 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -385,15 +385,32 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
// when calling into java varargs, make sure it's an array - see bug #1360
def forceToArray(arg: Tree) = {
val Typed(tree, _) = arg
- lazy val isTraversable = tree.tpe.baseClasses contains TraversableClass
- lazy val toArray = tree.tpe member nme.toArray
-
- if (isJava && isTraversable && toArray != NoSymbol)
- Apply(gen.mkAttributedSelect(tree, toArray), Nil) setType tree.tpe.memberType(toArray)
- else
- tree
+ if (!isJava || tree.tpe.typeSymbol == ArrayClass) tree
+ else {
+ val traversableTpe = tree.tpe.baseType(TraversableClass)
+ val toArray = tree.tpe member nme.toArray
+ if (traversableTpe != NoType && toArray != NoSymbol) {
+ val arguments =
+ if (toArray.tpe.paramTypes.isEmpty) List() // !!! old style toArray
+ else { // new style, with manifest
+ val manifestOpt = localTyper.findManifest(tree.tpe.typeArgs.head, false)
+ if (manifestOpt.tree.isEmpty) {
+ unit.error(tree.pos, "cannot find class manifest for element type of "+tree.tpe)
+ List(Literal(Constant(null)))
+ } else {
+ List(manifestOpt.tree)
+ }
+ }
+ atPhase(phase.next) {
+ localTyper.typed {
+ atPos(pos) {
+ Apply(gen.mkAttributedSelect(tree, toArray), arguments)
+ }
+ }
+ }
+ } else tree
+ }
}
-
if (args.isEmpty)
List(mkArrayValue(args))
else {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 66fc389807..9d3cccab37 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -70,7 +70,8 @@ self: Analyzer =>
* by such an instance?
*/
def isManifest(pt: Type): Boolean = pt.dealias match {
- case TypeRef(_, ManifestClass, List(_)) |
+ case TypeRef(_, PartialManifestClass, List(_)) |
+ TypeRef(_, FullManifestClass, List(_)) |
TypeRef(_, OptManifestClass, List(_)) => true
case TypeRef(_, tsym, _) => tsym.isAbstractType && isManifest(pt.bounds.lo)
case _ => false
@@ -476,7 +477,7 @@ self: Analyzer =>
else {
/** The list of all applicable infos which are not improved upon by `best`. */
val competing = applicable.keySet dropWhile (alt => best == alt || improves(best, alt))
- if (!competing.isEmpty) ambiguousImplicitError(best, competing.iterator.next, "both", "and", "") // !!! streamline when new collection is there
+ if (!competing.isEmpty) ambiguousImplicitError(best, competing.head, "both", "and", "")
// Also check that applicable infos that did not get selected are not
// in (a companion object of) a subclass of (a companion object of) the class
@@ -580,10 +581,10 @@ self: Analyzer =>
/** The manifest corresponding to type `pt`, provided `pt` is an instance of Manifest.
*/
- private def implicitManifest(pt: Type): Tree = pt match {
+ private def implicitManifest(pt: Type): Tree = pt.dealias match {
case TypeRef(_, FullManifestClass, List(arg)) =>
manifestOfType(arg, true)
- case TypeRef(_, ManifestClass, List(arg)) =>
+ case TypeRef(_, PartialManifestClass, List(arg)) =>
manifestOfType(arg, false)
case TypeRef(_, OptManifestClass, List(arg)) =>
val itree = manifestOfType(arg, false)
@@ -598,7 +599,7 @@ self: Analyzer =>
* reflect.Manifest for type 'tp'. An EmptyTree is returned if
* no manifest is found. todo: make this instantiate take type params as well?
*/
- private def manifestOfType(tp: Type, full: Boolean): Tree = {
+ def manifestOfType(tp: Type, full: Boolean): Tree = {
/** Creates a tree that calls the factory method called constructor in object reflect.Manifest */
def manifestFactoryCall(constructor: String, args: Tree*): Tree =
@@ -607,24 +608,24 @@ self: Analyzer =>
typed { atPos(tree.pos.focus) {
Apply(
TypeApply(
- Select(gen.mkAttributedRef(if (full) FullManifestModule else ManifestModule), constructor),
+ Select(gen.mkAttributedRef(if (full) FullManifestModule else PartialManifestModule), constructor),
List(TypeTree(tp))
),
args.toList
)
}}
- /** Re-wraps a type in a manifest before calling inferImplicit on th e result */
- def findManifest(tp: Type, manifestClass: Symbol = if (full) FullManifestClass else ManifestClass) =
+ /** Re-wraps a type in a manifest before calling inferImplicit on the result */
+ def findManifest(tp: Type, manifestClass: Symbol = if (full) FullManifestClass else PartialManifestClass) =
inferImplicit(tree, appliedType(manifestClass.typeConstructor, List(tp)), true, false, context).tree
- def findArgManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass)
+ def findSubManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass)
- tp.normalize match {
+ def mot(tp0: Type): Tree = tp0.normalize match {
case ThisType(_) | SingleType(_, _) =>
- manifestFactoryCall("singleType", gen.mkAttributedQualifier(tp))
+ manifestFactoryCall("singleType", gen.mkAttributedQualifier(tp0))
case ConstantType(value) =>
- findManifest(tp.deconst)
+ manifestOfType(tp0.deconst, full)
case TypeRef(pre, sym, args) =>
if (isValueClass(sym)) {
typed { atPos(tree.pos.focus) {
@@ -632,27 +633,31 @@ self: Analyzer =>
}}
}
else if (sym.isClass) {
- val suffix = gen.mkClassOf(tp) :: (args map findArgManifest)
+ val suffix = gen.mkClassOf(tp0) :: (args map findSubManifest)
manifestFactoryCall(
"classType",
(if ((pre eq NoPrefix) || pre.typeSymbol.isStaticOwner) suffix
- else findManifest(pre) :: suffix): _*)
+ else findSubManifest(pre) :: suffix): _*)
}
- else if (sym.isTypeParameterOrSkolem) {
+ else if (sym.isTypeParameterOrSkolem || sym.isExistential) {
EmptyTree // a manifest should have been found by normal searchImplicit
}
else {
manifestFactoryCall(
"abstractType",
- findManifest(pre) :: Literal(sym.name.toString) :: findManifest(tp.bounds.hi) :: (args map findArgManifest): _*)
+ findSubManifest(pre) :: Literal(sym.name.toString) :: findManifest(tp0.bounds.hi) :: (args map findSubManifest): _*)
}
case RefinedType(parents, decls) =>
// refinement is not generated yet
if (parents.length == 1) findManifest(parents.head)
- else manifestFactoryCall("intersectionType", parents map (findManifest(_)): _*)
+ else manifestFactoryCall("intersectionType", parents map (findSubManifest(_)): _*)
+ case ExistentialType(tparams, result) =>
+ mot(result)
case _ =>
EmptyTree
}
+
+ mot(tp)
}
/** An extractor for types of the form ? { name: ? }
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index 6a99a2af79..161e60d6d8 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -25,64 +25,11 @@ import scala.runtime._
* </p>
*/
@serializable
-trait Manifest[T] extends OptManifest[T] {
-
- /** A class representing the type U to which T would be erased. Note
- * that there is no subtyping relationship between T and U. */
- def erasure: Predef.Class[_]
-
- /** Tests whether the type represented by this manifest is a subtype of
- * the type represented by `that' manifest. BE AWARE: the current
- * implementation is an approximation, as the test is done on the
- * erasure of the type. */
- def <:<(that: Manifest[_]): Boolean = {
- def subtype(sub: Predef.Class[_], sup: Predef.Class[_]): Boolean = {
- val subSuperClass = sub.getSuperclass
- val subSuperInterfaces = sub.getInterfaces.toList
- val subSuper =
- (if (subSuperClass == null) Nil else List(subSuperClass)) ::: subSuperInterfaces
- (subSuper contains sup) || (subSuper exists (subtype(_, sup)))
- }
- def subargs(args1: List[OptManifest[_]], args2: List[OptManifest[_]]): Boolean = {
- (args1 zip args2) forall {
- case (x: Manifest[_], y: Manifest[_]) => x <:< y // !!! [Martin] this is wrong, need to take variance into account
- case (NoManifest, NoManifest) => true
- case _ => false
- }
- }
- (this.erasure == that.erasure || subtype(this.erasure, that.erasure)) &&
- subargs(this.typeArguments, that.typeArguments)
- }
-
- /** Tests whether the type represented by this manifest is a supertype
- * of the type represented by `that' manifest. BE AWARE: the current
- * implementation is an approximation, as the test is done on the
- * erasure of the type. */
- def >:>(that: Manifest[_]): Boolean =
- that <:< this
-
- /** Tests whether the type represented by this manifest is equal to the
- * type represented by `that' manifest. BE AWARE: the current
- * implementation is an approximation, as the test is done on the
- * erasure of the type. */
- override def equals(that: Any): Boolean = that match {
- case m: Manifest[_] => this.erasure == m.erasure
- case _ => false
- }
-
- def newArray(len: Int): BoxedArray[T] = {
- // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests
- new BoxedObjectArray(java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[AnyRef]])
- .asInstanceOf[BoxedArray[T]]
- }
-
- def typeArguments: List[OptManifest[_]] = List()
-
- protected def argString = if (typeArguments.isEmpty) "" else typeArguments.mkString("[", ", ", "]")
-
+trait Manifest[T] extends ClassManifest[T] {
+ override def typeArguments: List[Manifest[_]] = List()
}
-/** <p>
+/** <ps>
* This object is used by the compiler and <b>should not be used in client
* code</b>. The object <code>Manifest</code> defines factory methods for
* manifests.
@@ -94,31 +41,84 @@ trait Manifest[T] extends OptManifest[T] {
*/
object Manifest {
- val Byte = FullManifest.Byte
- val Short = FullManifest.Short
- val Char = FullManifest.Char
- val Int = FullManifest.Int
- val Long = FullManifest.Long
- val Float = FullManifest.Float
- val Double = FullManifest.Double
- val Boolean = FullManifest.Boolean
- val Unit = FullManifest.Unit
+ val Byte = new (Manifest[Byte] @serializable) {
+ def erasure = java.lang.Byte.TYPE
+ override def toString = "Byte"
+ override def newArray(len: Int): BoxedArray[Byte] = new BoxedByteArray(new Array[Byte](len))
+ }
+
+ val Short = new (Manifest[Short] @serializable) {
+ def erasure = java.lang.Short.TYPE
+ override def toString = "Short"
+ override def newArray(len: Int): BoxedArray[Short] = new BoxedShortArray(new Array[Short](len))
+ }
- def singleType[T](value: Any): FullManifest[T] = FullManifest.singleType(value)
+ val Char = new (Manifest[Char] @serializable) {
+ def erasure = java.lang.Character.TYPE
+ override def toString = "Char"
+ override def newArray(len: Int): BoxedArray[Char] = new BoxedCharArray(new Array[Char](len))
+ }
- /** Manifest for the class type `clazz[args]', where `clazz' is
+ val Int = new (Manifest[Int] @serializable) {
+ def erasure = java.lang.Integer.TYPE
+ override def toString = "Int"
+ override def newArray(len: Int): BoxedArray[Int] = new BoxedIntArray(new Array[Int](len))
+ }
+
+ val Long = new (Manifest[Long] @serializable) {
+ def erasure = java.lang.Long.TYPE
+ override def toString = "Long"
+ override def newArray(len: Int): BoxedArray[Long] = new BoxedLongArray(new Array[Long](len))
+ }
+
+ val Float = new (Manifest[Float] @serializable) {
+ def erasure = java.lang.Float.TYPE
+ override def toString = "Float"
+ override def newArray(len: Int): BoxedArray[Float] = new BoxedFloatArray(new Array[Float](len))
+ }
+
+ val Double = new (Manifest[Double] @serializable) {
+ def erasure = java.lang.Double.TYPE
+ override def toString = "Double"
+ override def newArray(len: Int): BoxedArray[Double] = new BoxedDoubleArray(new Array[Double](len))
+ }
+
+ val Boolean = new (Manifest[Boolean] @serializable) {
+ def erasure = java.lang.Boolean.TYPE
+ override def toString = "Boolean"
+ override def newArray(len: Int): BoxedArray[Boolean] = new BoxedBooleanArray(new Array[Boolean](len))
+ }
+
+ val Unit = new (Manifest[Unit] @serializable) {
+ def erasure = java.lang.Void.TYPE
+ override def toString = "Unit"
+ override def newArray(len: Int): BoxedArray[Unit] = new BoxedUnitArray(new Array[Unit](len))
+ }
+
+ /** Manifest for the singleton type `value.type'. */
+ def singleType[T](value: Any): Manifest[T] =
+ new (Manifest[T] @serializable) {
+ lazy val erasure =
+ value match {
+ case anyRefValue: AnyRef => anyRefValue.getClass
+ case anyValue => error("There is no singleton type for AnyVal values")
+ }
+ override lazy val toString = value.toString + ".type"
+ }
+
+ /** Manifest for the class type `clazz', where `clazz' is
* a top-level or static class. */
- def classType[T](clazz: Predef.Class[_], args: OptManifest[_]*): Manifest[T] =
+ def classType[T](clazz: Predef.Class[T], args: Manifest[_]*): Manifest[T] =
classType(None, clazz, args: _*)
/** Manifest for the class type `clazz[args]', where `clazz' is
* a top-level or static class. */
- def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: OptManifest[_]*): Manifest[T] =
+ def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
classType(Some(prefix), clazz, args: _*)
/** Manifest for the class type `clazz[args]', where `clazz' is
* a top-level or static class. */
- def classType[T](prefix: Option[Manifest[_]], clazz: Predef.Class[_], args: OptManifest[_]*): Manifest[T] =
+ def classType[T](prefix: Option[Manifest[_]], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
new (Manifest[T] @serializable) {
def erasure = clazz
override val typeArguments = args.toList
@@ -131,7 +131,7 @@ object Manifest {
/** Manifest for the abstract type `prefix # name'. `upperBound' is not
* strictly necessary as it could be obtained by reflection. It was
* added so that erasure can be calculated without reflection. */
- def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_], args: OptManifest[_]*): Manifest[T] =
+ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Manifest[_], args: Manifest[_]*): Manifest[T] =
new (Manifest[T] @serializable) {
def erasure = upperBound.erasure
override val typeArguments = args.toList
diff --git a/src/library/scala/runtime/BoxedArray.scala b/src/library/scala/runtime/BoxedArray.scala
index ecb402297d..6cac7f1113 100644
--- a/src/library/scala/runtime/BoxedArray.scala
+++ b/src/library/scala/runtime/BoxedArray.scala
@@ -57,13 +57,12 @@ abstract class BoxedArray[A] extends Vector[A] with VectorTemplate[A, BoxedArray
* Example: Array(Array(1, 2), Array(3, 4)).deep.toString
* prints: Array(Array(1, 2), Array(3, 4))
*/
- def deep: Vector[Any] = new Vector[Any] {
+ def deep: collection.Vector[Any] = new collection.Vector[Any] {
def length = self.length
def apply(idx: Int): Any = self.apply(idx) match {
case elem: AnyRef if ScalaRunTime.isArray(elem) => ScalaRunTime.boxArray(elem).deep
case elem => elem
}
- def update(idx: Int, elem: Any) = error("Result of deep cannot be updated.")
override def stringPrefix = "Array"
}