summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2014-02-09 17:16:17 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2014-02-09 17:16:17 -0800
commit01d53a0aea8a62b93f9b6dc04d0565d1a59419ce (patch)
tree0a15f7be7542af654debddaaf57e89010c273b97 /src
parent73784d78fdbd4feb07a8446a8336dd203c1be866 (diff)
parent1cf1bae75db5f178026f6602e9a062484fa73a86 (diff)
downloadscala-01d53a0aea8a62b93f9b6dc04d0565d1a59419ce.tar.gz
scala-01d53a0aea8a62b93f9b6dc04d0565d1a59419ce.tar.bz2
scala-01d53a0aea8a62b93f9b6dc04d0565d1a59419ce.zip
Merge pull request #3484 from retronym/ticket/8237
SI-8237 Avoid cyclic constraints when inferring hk type args
Diffstat (limited to 'src')
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala24
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala8
2 files changed, 27 insertions, 5 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 74b2208278..2d4e0b3b34 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -2905,6 +2905,8 @@ trait Types
override def params: List[Symbol] = zippedArgs map (_._1)
override def typeArgs: List[Type] = zippedArgs map (_._2)
+
+ override def safeToString: String = super.safeToString + typeArgs.map(_.safeToString).mkString("[", ", ", "]")
}
trait UntouchableTypeVar extends TypeVar {
@@ -3025,15 +3027,19 @@ trait Types
def addLoBound(tp: Type, isNumericBound: Boolean = false) {
assert(tp != this, tp) // implies there is a cycle somewhere (?)
//println("addLoBound: "+(safeToString, debugString(tp))) //DEBUG
- undoLog record this
- constr.addLoBound(tp, isNumericBound)
+ if (!sharesConstraints(tp)) {
+ undoLog record this
+ constr.addLoBound(tp, isNumericBound)
+ }
}
def addHiBound(tp: Type, isNumericBound: Boolean = false) {
// assert(tp != this)
//println("addHiBound: "+(safeToString, debugString(tp))) //DEBUG
- undoLog record this
- constr.addHiBound(tp, isNumericBound)
+ if (!sharesConstraints(tp)) {
+ undoLog record this
+ constr.addHiBound(tp, isNumericBound)
+ }
}
// </region>
@@ -3045,6 +3051,16 @@ trait Types
case ConstantTrue => true
case tv: TypeVar => tv.suspended
}
+
+ /** `AppliedTypeVar`s share the same `TypeConstraint` with the `HKTypeVar` that it was spawned from.
+ * A type inference session can also have more than one ATV.
+ * If we don't detect that, we end up with "cyclic constraint" when we try to instantiate type parameters
+ * after solving in, pos/t8237
+ */
+ protected final def sharesConstraints(other: Type): Boolean = other match {
+ case other: TypeVar => constr == other.constr // SI-8237 avoid cycles. Details in pos/t8237.scala
+ case _ => false
+ }
private[Types] def suspended_=(b: Boolean): Unit = _suspended = if (b) ConstantTrue else ConstantFalse
// SI-7785 Link the suspended attribute of a TypeVar created in, say, a TypeMap (e.g. AsSeenFrom) to its originator
private[Types] def linkSuspended(origin: TypeVar): Unit = _suspended = origin
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
index e2159d30f5..564cbb1ce3 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
@@ -257,6 +257,12 @@ private[internal] trait TypeConstraints {
// println("solving "+tvars+"/"+tparams+"/"+(tparams map (_.info)))
foreach3(tvars, tparams, variances)(solveOne)
- tvars forall (tv => tv.instWithinBounds || util.andFalse(log(s"Inferred type for ${tv.originString} does not conform to bounds: ${tv.constr}")))
+
+ def logBounds(tv: TypeVar) = log {
+ val what = if (!tv.instValid) "is invalid" else s"does not conform to bounds: ${tv.constr}"
+ s"Inferred type for ${tv.originString} (${tv.inst}) $what"
+ }
+
+ tvars forall (tv => tv.instWithinBounds || util.andFalse(logBounds(tv)))
}
}