From a09e143b7fd1c6b433386d45e9c5ae3548819b59 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 14 Jan 2014 13:37:26 +0100 Subject: SI-8146 Fix non-deterministic <:< for deeply nested types In the interests of keeping subtyping decidable [1], 152563b added some bookkeeping to `isSubType` to detect cycles. However, this was based on a hash set containing instances of `SubTypePair`, and that class had inconsistencies between its `hashCode` (in terms of `Type#hashCode`) and `equals` (in terms of `=:=`). This inconsistency can be seen in: scala> trait C { def apply: (Int @unchecked) } defined trait C scala> val intUnchecked = typeOf[C].decls.head.info.finalResultType intUnchecked: $r.intp.global.Type = Int @unchecked scala> val p1 = new SubTypePair(intUnchecked, intUnchecked) p1: $r.intp.global.SubTypePair = Int @unchecked <: val p2 = new SubTypePair(intUnchecked.withoutAnnotations, intUnchecked.withoutAnnotations) p2: $r.intp.global.SubTypePair = Int <: p1 == p2 res0: Boolean = true scala> p1.hashCode == p2.hashCode res1: Boolean = false This commit switches to using `Type#==`, by way of the standard case class equality. The risk here is that you could find a subtyping computation that progresses in such a manner that we don't detect the cycle. It would need to produce an infinite stream of representations for types that were `=:=` but not `==`. If that happened, we'd fail to terminate, rather than judging the relationship as `false`. [1] http://research.microsoft.com/pubs/64041/fool2007.pdf --- src/reflect/scala/reflect/runtime/JavaUniverseForce.scala | 1 + 1 file changed, 1 insertion(+) (limited to 'src/reflect/scala/reflect/runtime/JavaUniverseForce.scala') diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index c87995275f..a2d3206156 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -198,6 +198,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.ErroneousCollector this.adaptToNewRunMap // inaccessible: this.commonOwnerMapObj + this.SubTypePair this.SymbolKind this.NoSymbol this.CyclicReference -- cgit v1.2.3