summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2010-01-13 15:44:11 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2010-01-13 15:44:11 +0000
commit28c75a82ea610fb5a61e53c0a031c2d64a399af5 (patch)
tree55a6f6aa47b7c51761753b42cda30919666645b0
parent4f2bcd1af4fc12765aea7975a97357274087d392 (diff)
downloadscala-28c75a82ea610fb5a61e53c0a031c2d64a399af5.tar.gz
scala-28c75a82ea610fb5a61e53c0a031c2d64a399af5.tar.bz2
scala-28c75a82ea610fb5a61e53c0a031c2d64a399af5.zip
closes #2421: more complete fix, now also check...
closes #2421: more complete fix, now also check validity of inferred type arguments for expressions inferred for implicit values review by odersky
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala3
-rw-r--r--test/files/neg/t2421b.check4
-rw-r--r--test/files/neg/t2421b.scala17
-rw-r--r--test/files/pos/t2421b.scala19
5 files changed, 51 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 9657cea101..c4464010c1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -459,7 +459,9 @@ self: Analyzer =>
if (traceImplicits) println("tvars = "+tvars+"/"+(tvars map (_.constr)))
val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt),
false, lubDepth(List(itree2.tpe, pt)))
- checkBounds(itree2.pos, NoPrefix, NoSymbol, undetParams, targs, "inferred ") // #2421
+
+ // #2421: check that we correctly instantiated type parameters outside of the implicit tree:
+ checkBounds(itree2.pos, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
// filter out failures from type inference, don't want to remove them from undetParams!
// we must be conservative in leaving type params in undetparams
@@ -472,6 +474,11 @@ self: Analyzer =>
val subst = new TreeTypeSubstituter(okParams, okArgs)
subst traverse itree2
+ // #2421b: since type inference (which may have been performed during implicit search)
+ // does not check whether inferred arguments meet the bounds of the corresponding parameter (see note in solvedTypes),
+ // must check again here:
+ typed1(itree2, EXPRmode, wildPt)
+
val result = new SearchResult(itree2, subst)
incCounter(foundImplicits)
if (traceImplicits) println("RESULT = "+result)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 1397aa06eb..621b6dce11 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -159,6 +159,9 @@ trait Infer {
if (!solve(tvars, tparams, variances, upper, depth)) {
// no panic, it's good enough to just guess a solution, we'll find out
// later whether it works.
+// @M danger, Will Robinson! this means that you should never trust inferred type arguments!
+// need to call checkBounds on the args/typars or type1 on the tree for the expression that results from type inference
+// see e.g., #2421: implicit search had been ignoring this caveat
// throw new DeferredNoInstance(() =>
// "no solution exists for constraints"+(tvars map boundsString))
}
diff --git a/test/files/neg/t2421b.check b/test/files/neg/t2421b.check
new file mode 100644
index 0000000000..f666a7d9d7
--- /dev/null
+++ b/test/files/neg/t2421b.check
@@ -0,0 +1,4 @@
+t2421b.scala:12: error: could not find implicit value for parameter aa: Test.F[Test.A]
+ f
+ ^
+one error found \ No newline at end of file
diff --git a/test/files/neg/t2421b.scala b/test/files/neg/t2421b.scala
new file mode 100644
index 0000000000..d8159a8c37
--- /dev/null
+++ b/test/files/neg/t2421b.scala
@@ -0,0 +1,17 @@
+object Test {
+ class A
+ class B
+ class C
+ class F[X]
+
+ def f(implicit aa: F[A]) = println(aa)
+
+ // implicit def a : F[A] = new F[A]()
+ implicit def b[X <: B] = new F[X]()
+
+ f
+}
+
+/* bug:
+error: type arguments [Test2.A] do not conform to method b's type parameter bounds [X <: Test2.B]
+*/ \ No newline at end of file
diff --git a/test/files/pos/t2421b.scala b/test/files/pos/t2421b.scala
new file mode 100644
index 0000000000..0df3461662
--- /dev/null
+++ b/test/files/pos/t2421b.scala
@@ -0,0 +1,19 @@
+object Test {
+ class A
+ class B
+ class C
+ class F[X]
+
+ def f(implicit aa: F[A]) = println(aa)
+
+ implicit def a : F[A] = new F[A]()
+ implicit def b[X <: B] = new F[X]()
+
+ f
+}
+/* bug:
+error: ambiguous implicit values:
+ both method b in object Test1 of type [X <: Test1.B]Test1.F[X]
+ and method a in object Test1 of type => Test1.F[Test1.A]
+ match expected type Test1.F[Test1.A]
+*/