summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-03-17 19:16:19 +0000
committerMartin Odersky <odersky@gmail.com>2009-03-17 19:16:19 +0000
commit9a4199709d2c3c910dbbe17bffdac97df69b1d8f (patch)
treec5ec122bb4215657ab241d3958a2813e3ac0100a
parent36bf7cb302fe3df9cb654567b9fc3443cb2cc5ff (diff)
downloadscala-9a4199709d2c3c910dbbe17bffdac97df69b1d8f.tar.gz
scala-9a4199709d2c3c910dbbe17bffdac97df69b1d8f.tar.bz2
scala-9a4199709d2c3c910dbbe17bffdac97df69b1d8f.zip
chyanged implicits so that implicit Builder pat...
chyanged implicits so that implicit Builder pattern works.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Variances.scala2
-rw-r--r--test/files/jvm/typerep.scala4
-rwxr-xr-xtest/files/jvm5/typerep.scala6
-rw-r--r--test/files/neg/bug550.check2
-rwxr-xr-xtest/files/pos/builders.scala66
8 files changed, 92 insertions, 16 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 6d91179c3d..0efdc6fbe2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -52,6 +52,16 @@ self: Analyzer =>
search.result
}
+ /** If type `pt` an instance of Manifest or OptManifest, or an abstract type lower-bounded
+ * by such an instance?
+ */
+ def isManifest(pt: Type): Boolean = pt match {
+ case TypeRef(_, ManifestClass, List(_)) |
+ TypeRef(_, OptManifestClass, List(_)) => true
+ case TypeRef(_, tsym, _) => tsym.isAbstractType && isManifest(pt.bounds.lo)
+ case _ => false
+ }
+
/** The result of an implicit search
* @param tree The tree representing the implicit
* @param subst A substituter that represents the undetermined type parameters
@@ -234,7 +244,7 @@ self: Analyzer =>
private def typedImplicit(info: ImplicitInfo): SearchResult =
context.openImplicits find (dominates(pt, _)) match {
case Some(pending) =>
- println("Pending implicit "+pending+" dominates "+pt)
+ //println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams)
throw DivergentImplicit
SearchFailure
case None =>
@@ -273,9 +283,7 @@ self: Analyzer =>
def approximate(tp: Type) =
tp.instantiateTypeParams(undetParams, undetParams map (_ => WildcardType))
- /** Instantiated `pt' so that covariant occurrences of undetermined
- * type parameters are replaced by Any, and all other occurrences
- * are replaced by Nothing
+ /** Instantiated `pt' so that undetermined type parameters are replaced by wildcards
*/
val wildPt = approximate(pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index db43125ccc..1a07103e24 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -524,7 +524,7 @@ trait Infer {
*/
def adjustTypeArgs(tparams: List[Symbol], targs: List[Type], restpe: Type, uninstantiated: ListBuffer[Symbol]): List[Type] =
List.map2(tparams, targs) {(tparam, targ) =>
- if (targ.typeSymbol == NothingClass && (varianceInType(restpe)(tparam) & COVARIANT) == 0) {
+ if (targ.typeSymbol == NothingClass && (restpe == WildcardType || (varianceInType(restpe)(tparam) & COVARIANT) == 0)) {
uninstantiated += tparam
tparam.tpe
} else if (targ.typeSymbol == RepeatedParamClass) {
@@ -943,12 +943,12 @@ trait Infer {
val targs = exprTypeArgs(tparams, tree.tpe, pt)
val uninstantiated = new ListBuffer[Symbol]
val detargs = if (keepNothings) targs
- else adjustTypeArgs(tparams, targs, pt, uninstantiated)
+ else adjustTypeArgs(tparams, targs, WildcardType, uninstantiated)
val undetparams = uninstantiated.toList
val detparams = tparams remove (undetparams contains _)
substExpr(tree, detparams, detargs, pt)
if (inferInfo)
- println("inferred expr instance "+tree)
+ println("inferred expr instance "+tree+", detargs = "+detargs+", undetparams = "+undetparams)
undetparams
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 955bd9ee4c..55ad496c94 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -747,7 +747,11 @@ trait Typers { self: Analyzer =>
case mt: ImplicitMethodType if ((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) => // (4.1)
if (!context.undetparams.isEmpty && (mode & POLYmode) == 0) { // (9)
context.undetparams = inferExprInstance(
- tree, context.extractUndetparams(), pt, false)
+ tree, context.extractUndetparams(), pt, mt.paramTypes exists isManifest)
+ // if we are looking for a manifest, instantiate type to Nothing anyway,
+ // as we would get amnbiguity errors otherwise. Example
+ // Looking for a manifest of Nil: This mas many potential types,
+ // so we need to instantiate to minimal type List[Nothing].
}
val typer1 = constrTyperIf(treeInfo.isSelfOrSuperConstrCall(tree))
typer1.typed(typer1.applyImplicitArgs(tree), mode, pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Variances.scala b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
index cc68373f40..a02b4b04a1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Variances.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
@@ -74,8 +74,6 @@ trait Variances {
varianceInType(attrib.atp)(tparam)
}
-
-
/** Compute variance of type parameter <code>tparam</code> in type <code>tp</code>. */
def varianceInType(tp: Type)(tparam: Symbol): Int = tp match {
case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) | ConstantType(_) =>
diff --git a/test/files/jvm/typerep.scala b/test/files/jvm/typerep.scala
index b133d7ce99..47bd335d32 100644
--- a/test/files/jvm/typerep.scala
+++ b/test/files/jvm/typerep.scala
@@ -58,7 +58,7 @@ object testOptions {
val x: Option[Int] = Some(2)
println(getType(x))
println(getType(Some(Some(3))))
- println(getType(None))
+ println(getType(None: Option[Int]))
val y: Option[Int] = None
println(getType(y))
println
@@ -68,7 +68,7 @@ object testLists {
println(getType(List(3)))
println(getType(3 :: Nil))
println(getType(List(List(3))))
- println(getType(Nil))
+ println(getType(Nil: List[Int]))
println(getType(List(1, "abc")))
println
}
diff --git a/test/files/jvm5/typerep.scala b/test/files/jvm5/typerep.scala
index 3519a617a7..fc94817adf 100755
--- a/test/files/jvm5/typerep.scala
+++ b/test/files/jvm5/typerep.scala
@@ -59,8 +59,8 @@ object testOptions {
println(getType(x))
println(getType(Some(Some(3))))
println(getType(Some(List(3))))
- //println(getType(Some(None))) // error: no implicit argument matching parameter type TypeRep[object None] was foun
- println(getType(None))
+ //println(getType(Some(None: List[Int]))) // error: no implicit argument matching parameter type TypeRep[object None] was foun
+ println(getType(None: Option[Int]))
val y: Option[Int] = None
println(getType(y))
println
@@ -70,7 +70,7 @@ object testLists {
println(getType(List(3)))
println(getType(3 :: Nil))
println(getType(List(List(3))))
- println(getType(Nil))
+ println(getType(Nil: List[Int]))
println(getType(List(1, "abc")))
println
}
diff --git a/test/files/neg/bug550.check b/test/files/neg/bug550.check
index 8f1a5c0e5a..252580a327 100644
--- a/test/files/neg/bug550.check
+++ b/test/files/neg/bug550.check
@@ -1,7 +1,7 @@
bug550.scala:6: error: class List takes type parameters
def sum[a](xs: List)(implicit m: Monoid[a]): a =
^
-bug550.scala:8: error: no implicit argument matching parameter type Monoid[Nothing] was found.
+bug550.scala:8: error: no implicit argument matching parameter type Monoid[a] was found.
sum(List(1,2,3))
^
two errors found
diff --git a/test/files/pos/builders.scala b/test/files/pos/builders.scala
new file mode 100755
index 0000000000..0b620769c0
--- /dev/null
+++ b/test/files/pos/builders.scala
@@ -0,0 +1,66 @@
+object builders {
+
+ trait Builder[-From, +To, -Elem] {
+ def += (elem: Elem)
+ def result: To
+ }
+
+ implicit def iterableBuilder[A, B] = new Builder[Iterable[A], Iterable[B], B] {
+ println("new iterable builder")
+ private val buf = new scala.collection.mutable.ListBuffer[B]
+ def += (elem: B) { buf += elem }
+ def result: Iterable[B] = buf.toList
+ }
+
+ implicit def listBuilder[A, B] = new Builder[List[A], List[B], B] {
+ println("new list builder")
+ private val buf = new scala.collection.mutable.ListBuffer[B]
+ def += (elem: B) { buf += elem }
+ def result: List[B] = buf.toList
+ }
+/*
+ def fill[A, Dim1, Dim2, Coll](n1: Int, n2: Int, elem: A)(implicit b1: Builder[Coll, Dim1, A], b2: Builder[Coll, Dim2, Dim1]) = {
+ for (i <- 0 until n1) {
+ for (j <- 0 until n2) {
+ b1 += elem
+ }
+ b2 += b1.result
+ }
+ b2.result
+ }
+*/
+/*
+ implicit def arrayBuilder[A, B] = new Builder[Array[A], Array[B], B] {
+ println("new arr ay builder")
+ private val buf = new scala.collection.mutable.ListBuffer[B]
+ def += (elem: B) { buf += elem }
+ def result: Array[B] = buf.toArray
+ }
+*/
+ class Iter[A, C](elems: List[A]) {
+ def ++ [B >: A, D](xs: Iterable[B])(implicit b: Builder[C, D, B]): D = {
+ for (x <- elems) b += x
+ for (x <- xs) b += x
+ b.result
+ }
+ def map[B, D](f: A => B)(implicit b: Builder[C, D, B]): D = {
+ for (x <- elems) b += f(x)
+ b.result
+ }
+ }
+
+ def main(args : Array[String]) : Unit = {
+ val x1 = new Iter[Int, List[Int]](List(1, 2, 3))
+// val x2 = new Iter[Int, Array[Int]](List(1, 2, 3))
+ val x3 = new Iter[Int, Iterable[Int]](List(1, 2, 3))
+ val y1: List[Int] = x1.map (_ + 1)
+// val y2: Array[Int] = x2.map (_ + 1)
+ val y3: Iterable[Int] = x3.map (_ + 1)
+ val z1: List[Int] = y1
+// val z2: Array[Int] = y2
+ val z3: Iterable[Int] = y3
+ println(z1)
+// println(z2)
+ println(z3)
+ }
+}