summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2010-04-23 12:31:33 +0000
committerMartin Odersky <odersky@gmail.com>2010-04-23 12:31:33 +0000
commit618b55fa8e1185eec27b93b5451d0331901828a2 (patch)
tree2644aa55ea99ddea2bcc6702977f5de29c763a81
parente4716c234d718379e5213abcc19b431a6d906b79 (diff)
downloadscala-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.scala45
-rw-r--r--src/library/scala/reflect/Manifest.scala15
-rw-r--r--test/files/pos/implicits.scala5
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[_]]])
+}