From c1df5090b9b2857b5a78e3da381baf6e2dac45e8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 24 Aug 2009 16:20:34 +0000 Subject: Refined manifest checking in preparation for ar... Refined manifest checking in preparation for arrays with manifests change. --- .../scala/tools/nsc/symtab/Definitions.scala | 8 ++--- .../scala/tools/nsc/transform/UnCurry.scala | 33 +++++++++++++----- .../scala/tools/nsc/typechecker/Implicits.scala | 39 ++++++++++++---------- 3 files changed, 51 insertions(+), 29 deletions(-) (limited to 'src/compiler') 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: ? } -- cgit v1.2.3