summaryrefslogtreecommitdiff
path: root/src/compiler
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 /src/compiler
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.
Diffstat (limited to 'src/compiler')
-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
3 files changed, 51 insertions, 29 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: ? }