summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Suereth <Joshua.Suereth@gmail.com>2012-10-11 05:21:59 -0700
committerJosh Suereth <Joshua.Suereth@gmail.com>2012-10-11 05:21:59 -0700
commit1d8469d5ddf1b9ae4addd5c8a69cf08db470e143 (patch)
tree8491dd51ebf6ba808d6b247c4fd1483dee3e2cb4
parent557a9bd1309d2de6679e158769955cce3da6433b (diff)
parentee7f1e8a82fcb81d5ff2b017daf52fc929ce9444 (diff)
downloadscala-1d8469d5ddf1b9ae4addd5c8a69cf08db470e143.tar.gz
scala-1d8469d5ddf1b9ae4addd5c8a69cf08db470e143.tar.bz2
scala-1d8469d5ddf1b9ae4addd5c8a69cf08db470e143.zip
Merge pull request #1490 from paulp/issue/6499
Fix for SI-6499, regression in type inference.
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala36
-rw-r--r--test/files/pos/t6499.scala3
2 files changed, 32 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
}
}
diff --git a/test/files/pos/t6499.scala b/test/files/pos/t6499.scala
new file mode 100644
index 0000000000..db376572ee
--- /dev/null
+++ b/test/files/pos/t6499.scala
@@ -0,0 +1,3 @@
+object Test {
+ Map(): Map[_, Int] with Map[_, Int]
+}