summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala15
-rw-r--r--test/files/pos/t7785.scala34
2 files changed, 48 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index b4ae384594..6305cbaea3 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -2847,6 +2847,9 @@ trait Types
// but pattern-matching returned the original constr0 (a bug)
// now, pattern-matching returns the most recent constr
object TypeVar {
+ private val ConstantTrue = ConstantType(Constant(true))
+ private val ConstantFalse = ConstantType(Constant(false))
+
@inline final def trace[T](action: String, msg: => String)(value: T): T = {
if (traceTypeVars) {
val s = msg match {
@@ -3003,6 +3006,7 @@ trait Types
this
else if (newArgs.size == params.size) {
val tv = TypeVar(origin, constr, newArgs, params)
+ tv.linkSuspended(this)
TypeVar.trace("applyArgs", "In " + originLocation + ", apply args " + newArgs.mkString(", ") + " to " + originName)(tv)
}
else
@@ -3065,7 +3069,16 @@ trait Types
// </region>
// ignore subtyping&equality checks while true -- see findMember
- private[Types] var suspended = false
+ // OPT: This could be Either[TypeVar, Boolean], but this encoding was chosen instead to save allocations.
+ private var _suspended: Type = TypeVar.ConstantFalse
+ private[Types] def suspended: Boolean = (_suspended: @unchecked) match {
+ case TypeVar.ConstantFalse => false
+ case TypeVar.ConstantTrue => true
+ case tv: TypeVar => tv.suspended
+ }
+ private[Types] def suspended_=(b: Boolean): Unit = _suspended = if (b) TypeVar.ConstantTrue else TypeVar.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
/** Called when a TypeVar is involved in a subtyping check. Result is whether
* this TypeVar could plausibly be a [super/sub]type of argument `tp` and if so,
diff --git a/test/files/pos/t7785.scala b/test/files/pos/t7785.scala
new file mode 100644
index 0000000000..1de693d137
--- /dev/null
+++ b/test/files/pos/t7785.scala
@@ -0,0 +1,34 @@
+import scala.language._
+
+trait R[+Repr]
+
+trait TraversableOps {
+ implicit val R: R[Nothing] = ???
+
+ // Removing the implicit parameter in both fixes the crash
+ // removing it into one only gives a valid compiler error.
+ trait OpsDup1[Repr] {
+ def force(implicit bf: R[Repr]): Any
+ }
+
+ trait Ops[Repr] extends OpsDup1[Repr] {
+ def force(implicit bf: R[Repr], dummy: DummyImplicit): Any
+ }
+
+ implicit def ct2ops[T, C[+X]](t: C[T]):
+ Ops[C[T]]
+
+ def force[T](t: Option[T]) =
+ // ct2ops(t).force
+ t.force //Fails compilation on 2.10.2.
+
+
+ /* To get a closer look at the crash:
+ :power
+ val foo = typeOf[C].member(TermName("foo"))
+ val pt = analyzer.HasMember(TermName("force"))
+ val instantiated = foo.info.finalResultType.instantiateTypeParams(foo.typeParams, foo.typeParams.map(TypeVar(_)))
+ instantiated <:< pt
+ */
+ def foo[T, C[+X]]: Ops[C[T]]
+}