diff options
author | Paul Phillips <paulp@improving.org> | 2012-10-10 10:57:14 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-10-10 15:06:03 -0700 |
commit | ee7f1e8a82fcb81d5ff2b017daf52fc929ce9444 (patch) | |
tree | 8491dd51ebf6ba808d6b247c4fd1483dee3e2cb4 /src | |
parent | 557a9bd1309d2de6679e158769955cce3da6433b (diff) | |
download | scala-ee7f1e8a82fcb81d5ff2b017daf52fc929ce9444.tar.gz scala-ee7f1e8a82fcb81d5ff2b017daf52fc929ce9444.tar.bz2 scala-ee7f1e8a82fcb81d5ff2b017daf52fc929ce9444.zip |
Fix for SI-6499, regression in type inference.
I can't do any better than a reproduced comment:
For some reason which is still a bit fuzzy, we must let Nothing
through as a lower bound despite the fact that Nothing is always
a lower bound. My current supposition is that the side-effecting
type constraint accumulation mechanism depends on these subtype
tests being performed to make forward progress when there are
mutally recursive type vars. See pos/t6367 and pos/t6499 for the
competing test cases.
Diffstat (limited to 'src')
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 0e8665ee84..ab33c29153 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3922,7 +3922,17 @@ trait Types extends api.Types { self: SymbolTable => def avoidWiden: Boolean = avoidWidening def addLoBound(tp: Type, isNumericBound: Boolean = false) { - if (!lobounds.contains(tp)) { + // For some reason which is still a bit fuzzy, we must let Nothing through as + // a lower bound despite the fact that Nothing is always a lower bound. My current + // supposition is that the side-effecting type constraint accumulation mechanism + // depends on these subtype tests being performed to make forward progress when + // there are mutally recursive type vars. + // See pos/t6367 and pos/t6499 for the competing test cases. + val mustConsider = tp.typeSymbol match { + case NothingClass => true + case _ => !(lobounds contains tp) + } + if (mustConsider) { if (isNumericBound && isNumericValueType(tp)) { if (numlo == NoType || isNumericSubType(numlo, tp)) numlo = tp @@ -3942,7 +3952,13 @@ trait Types extends api.Types { self: SymbolTable => } def addHiBound(tp: Type, isNumericBound: Boolean = false) { - if (!hibounds.contains(tp)) { + // My current test case only demonstrates the need to let Nothing through as + // a lower bound, but I suspect the situation is symmetrical. + val mustConsider = tp.typeSymbol match { + case AnyClass => true + case _ => !(hibounds contains tp) + } + if (mustConsider) { checkWidening(tp) if (isNumericBound && isNumericValueType(tp)) { if (numhi == NoType || isNumericSubType(tp, numhi)) @@ -6316,21 +6332,26 @@ trait Types extends api.Types { self: SymbolTable => }) if (!cyclic) { if (up) { - if (bound.typeSymbol != AnyClass) + if (bound.typeSymbol != AnyClass) { + log(s"$tvar addHiBound $bound.instantiateTypeParams($tparams, $tvars)") tvar addHiBound bound.instantiateTypeParams(tparams, tvars) + } for (tparam2 <- tparams) tparam2.info.bounds.lo.dealias match { case TypeRef(_, `tparam`, _) => + log(s"$tvar addHiBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)") tvar addHiBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars) case _ => } } else { if (bound.typeSymbol != NothingClass && bound.typeSymbol != tparam) { + log(s"$tvar addLoBound $bound.instantiateTypeParams($tparams, $tvars)") tvar addLoBound bound.instantiateTypeParams(tparams, tvars) } for (tparam2 <- tparams) tparam2.info.bounds.hi.dealias match { case TypeRef(_, `tparam`, _) => + log(s"$tvar addLoBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)") tvar addLoBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars) case _ => } @@ -6339,14 +6360,15 @@ trait Types extends api.Types { self: SymbolTable => tvar.constr.inst = NoType // necessary because hibounds/lobounds may contain tvar //println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen))) - - tvar setInst ( + val newInst = ( if (up) { if (depth != AnyDepth) glb(tvar.constr.hiBounds, depth) else glb(tvar.constr.hiBounds) } else { if (depth != AnyDepth) lub(tvar.constr.loBounds, depth) else lub(tvar.constr.loBounds) - }) - + } + ) + log(s"$tvar setInst $newInst") + tvar setInst newInst //Console.println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen))+" = "+tvar.constr.inst)//@MDEBUG } } |