diff options
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 15 | ||||
-rw-r--r-- | test/files/pos/t7785.scala | 34 |
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]] +} |