Skip to content

Commit 28c75a8

Browse files
author
Adriaan Moors
committed
closes scala#2421: more complete fix, now also check...
closes scala#2421: more complete fix, now also check validity of inferred type arguments for expressions inferred for implicit values review by odersky
1 parent 4f2bcd1 commit 28c75a8

File tree

5 files changed

+51
-1
lines changed

5 files changed

+51
-1
lines changed

src/compiler/scala/tools/nsc/typechecker/Implicits.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,9 @@ self: Analyzer =>
459459
if (traceImplicits) println("tvars = "+tvars+"/"+(tvars map (_.constr)))
460460
val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt),
461461
false, lubDepth(List(itree2.tpe, pt)))
462-
checkBounds(itree2.pos, NoPrefix, NoSymbol, undetParams, targs, "inferred ") // #2421
462+
463+
// #2421: check that we correctly instantiated type parameters outside of the implicit tree:
464+
checkBounds(itree2.pos, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
463465

464466
// filter out failures from type inference, don't want to remove them from undetParams!
465467
// we must be conservative in leaving type params in undetparams
@@ -472,6 +474,11 @@ self: Analyzer =>
472474
val subst = new TreeTypeSubstituter(okParams, okArgs)
473475
subst traverse itree2
474476

477+
// #2421b: since type inference (which may have been performed during implicit search)
478+
// does not check whether inferred arguments meet the bounds of the corresponding parameter (see note in solvedTypes),
479+
// must check again here:
480+
typed1(itree2, EXPRmode, wildPt)
481+
475482
val result = new SearchResult(itree2, subst)
476483
incCounter(foundImplicits)
477484
if (traceImplicits) println("RESULT = "+result)

src/compiler/scala/tools/nsc/typechecker/Infer.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ trait Infer {
159159
if (!solve(tvars, tparams, variances, upper, depth)) {
160160
// no panic, it's good enough to just guess a solution, we'll find out
161161
// later whether it works.
162+
// @M danger, Will Robinson! this means that you should never trust inferred type arguments!
163+
// need to call checkBounds on the args/typars or type1 on the tree for the expression that results from type inference
164+
// see e.g., #2421: implicit search had been ignoring this caveat
162165
// throw new DeferredNoInstance(() =>
163166
// "no solution exists for constraints"+(tvars map boundsString))
164167
}

test/files/neg/t2421b.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
t2421b.scala:12: error: could not find implicit value for parameter aa: Test.F[Test.A]
2+
f
3+
^
4+
one error found

test/files/neg/t2421b.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
object Test {
2+
class A
3+
class B
4+
class C
5+
class F[X]
6+
7+
def f(implicit aa: F[A]) = println(aa)
8+
9+
// implicit def a : F[A] = new F[A]()
10+
implicit def b[X <: B] = new F[X]()
11+
12+
f
13+
}
14+
15+
/* bug:
16+
error: type arguments [Test2.A] do not conform to method b's type parameter bounds [X <: Test2.B]
17+
*/

test/files/pos/t2421b.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
object Test {
2+
class A
3+
class B
4+
class C
5+
class F[X]
6+
7+
def f(implicit aa: F[A]) = println(aa)
8+
9+
implicit def a : F[A] = new F[A]()
10+
implicit def b[X <: B] = new F[X]()
11+
12+
f
13+
}
14+
/* bug:
15+
error: ambiguous implicit values:
16+
both method b in object Test1 of type [X <: Test1.B]Test1.F[X]
17+
and method a in object Test1 of type => Test1.F[Test1.A]
18+
match expected type Test1.F[Test1.A]
19+
*/

0 commit comments

Comments
 (0)