diff options
author | Martin Odersky <odersky@gmail.com> | 2010-04-23 12:31:33 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2010-04-23 12:31:33 +0000 |
commit | 618b55fa8e1185eec27b93b5451d0331901828a2 (patch) | |
tree | 2644aa55ea99ddea2bcc6702977f5de29c763a81 | |
parent | e4716c234d718379e5213abcc19b431a6d906b79 (diff) | |
download | scala-618b55fa8e1185eec27b93b5451d0331901828a2.tar.gz scala-618b55fa8e1185eec27b93b5451d0331901828a2.tar.bz2 scala-618b55fa8e1185eec27b93b5451d0331901828a2.zip |
Fixed implicits problem in specs; Manifest[Clas...
Fixed implicits problem in specs; Manifest[Class[_]] can now be
generated. review by dubochet.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 45 | ||||
-rw-r--r-- | src/library/scala/reflect/Manifest.scala | 15 | ||||
-rw-r--r-- | test/files/pos/implicits.scala | 5 |
3 files changed, 26 insertions, 39 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 4c07e50da9..2858f4298c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -784,7 +784,6 @@ self: Analyzer => inferImplicit(tree, appliedType(manifestClass.typeConstructor, List(tp)), true, false, context).tree def findSubManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass) - def findElemManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else PartialManifestClass) def mot(tp0: Type): Tree = { val tp1 = tp0.normalize @@ -801,39 +800,26 @@ self: Analyzer => } else if (sym == RepeatedParamClass || sym == ByNameParamClass) { EmptyTree } else if (sym == ArrayClass && args.length == 1) { - manifestFactoryCall("arrayType", args.head, findElemManifest(args.head)) + manifestFactoryCall("arrayType", args.head, findManifest(args.head)) } else if (sym.isClass) { - val suffix = gen.mkClassOf(tp1) :: (args map findSubManifest) + val classarg0 = gen.mkClassOf(tp1) + val classarg = tp match { + case ExistentialType(_, _) => + TypeApply(Select(classarg0, Any_asInstanceOf), + List(TypeTree(appliedType(ClassClass.typeConstructor, List(tp))))) + case _ => + classarg0 + } + val suffix = classarg :: (args map findSubManifest) manifestFactoryCall( "classType", tp, (if ((pre eq NoPrefix) || pre.typeSymbol.isStaticOwner) suffix else findSubManifest(pre) :: suffix): _*) - } else { - EmptyTree -/* the following is dropped because it is dangerous - * - if (sym.isAbstractType) { - if (sym.isExistentiallyBound) - EmptyTree // todo: change to existential parameter manifest - else if (sym.isTypeParameterOrSkolem) - EmptyTree // a manifest should have been found by normal searchImplicit - else { - // The following is tricky! We want to find the parameterized version of - // what will become the erasure of the upper bound. - // But there is a case where the erasure is not a superclass of the current type: - // Any erases to Object. So an abstract type having Any as upper bound will not see - // Object as a baseType. That's why we do the basetype trick only when we must, - // i.e. when the baseclass is parameterized. - var era = erasure.erasure(tp1) - if (era.typeSymbol.typeParams.nonEmpty) - era = tp1.baseType(era.typeSymbol) - manifestFactoryCall( - "abstractType", tp, - findSubManifest(pre) :: Literal(sym.name.toString) :: gen.mkClassOf(era) :: (args map findSubManifest): _*) - } + } else if (sym.isExistentiallyBound && full) { + manifestFactoryCall("wildcardType", tp, + findManifest(tp.bounds.lo), findManifest(tp.bounds.hi)) } else { EmptyTree // a manifest should have been found by normal searchImplicit -*/ } case RefinedType(parents, decls) => // refinement is not generated yet @@ -841,10 +827,7 @@ self: Analyzer => else if (full) manifestFactoryCall("intersectionType", tp, parents map (findSubManifest(_)): _*) else mot(erasure.erasure.intersectionDominator(parents)) case ExistentialType(tparams, result) => - existentialAbstraction(tparams, result) match { - case ExistentialType(_, _) => mot(result) - case t => mot(t) - } + mot(tp1.skolemizeExistential) case _ => EmptyTree } diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index b7cb86e1bd..d718011ff9 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -245,16 +245,15 @@ object Manifest { override def toString = prefix.toString+"#"+name+argString } - /** 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. - * todo: remove after next bootstrap + /** Manifest for the unknown type `_ >: L <: U' in an existential. */ - def abstractType[T](prefix: Manifest[_], name: String, upperbound: ClassManifest[_], args: Manifest[_]*): Manifest[T] = + def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] = new (Manifest[T] @serializable) { - def erasure = upperbound.erasure - override val typeArguments = args.toList - override def toString = prefix.toString+"#"+name+argString + def erasure = upperBound.erasure + override def toString = + "_" + + (if (lowerBound eq Nothing) "" else " >: "+lowerBound) + + (if (upperBound eq Nothing) "" else " <: "+upperBound) } /** Manifest for the intersection type `parents_0 with ... with parents_n'. */ diff --git a/test/files/pos/implicits.scala b/test/files/pos/implicits.scala index 3939a28398..960c265e55 100644 --- a/test/files/pos/implicits.scala +++ b/test/files/pos/implicits.scala @@ -82,3 +82,8 @@ package foo2709 { } } } + +// Problem with specs +object specsProblem { + println(implicitly[Manifest[Class[_]]]) +} |