diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-02-09 17:16:17 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-02-09 17:16:17 -0800 |
commit | 01d53a0aea8a62b93f9b6dc04d0565d1a59419ce (patch) | |
tree | 0a15f7be7542af654debddaaf57e89010c273b97 /src | |
parent | 73784d78fdbd4feb07a8446a8336dd203c1be866 (diff) | |
parent | 1cf1bae75db5f178026f6602e9a062484fa73a86 (diff) | |
download | scala-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.scala | 24 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala | 8 |
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))) } } |