diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2010-01-13 15:44:11 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2010-01-13 15:44:11 +0000 |
commit | 28c75a82ea610fb5a61e53c0a031c2d64a399af5 (patch) | |
tree | 55a6f6aa47b7c51761753b42cda30919666645b0 | |
parent | 4f2bcd1af4fc12765aea7975a97357274087d392 (diff) | |
download | scala-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.scala | 9 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 3 | ||||
-rw-r--r-- | test/files/neg/t2421b.check | 4 | ||||
-rw-r--r-- | test/files/neg/t2421b.scala | 17 | ||||
-rw-r--r-- | test/files/pos/t2421b.scala | 19 |
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] +*/ |