Skip to content

Commit 3512530

Browse files
committed
Structural hashes for dependent types
Make hashes structural for dependent types. Two isomorphic types should give the same hash even if there are dependencies to BindingTypes.
1 parent 39f3b16 commit 3512530

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

compiler/src/dotty/tools/dotc/core/Hashing.scala

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ abstract class Hashing {
1212

1313
protected def typeHash(tp: Type) = tp.hash
1414

15-
final def identityHash(tp: Type) = avoidSpecialHashes(System.identityHashCode(tp))
15+
def identityHash(tp: Type) = avoidSpecialHashes(System.identityHashCode(tp))
1616

1717
protected def finishHash(seed: Int, arity: Int, tp: Type): Int = {
1818
val elemHash = typeHash(tp)
@@ -78,6 +78,29 @@ abstract class Hashing {
7878
if (h == NotCached) NotCachedAlt
7979
else if (h == HashUnknown) HashUnknownAlt
8080
else h
81+
82+
val binders: Array[BindingType] = Array()
83+
84+
private class WithBinders(override val binders: Array[BindingType]) extends Hashing {
85+
86+
override def typeHash(tp: Type) = tp.computeHash(this)
87+
88+
override def identityHash(tp: Type) = {
89+
var idx = 0
90+
while (idx < binders.length && (binders(idx) `ne` tp))
91+
idx += 1
92+
avoidSpecialHashes(
93+
if (idx < binders.length) idx * 31
94+
else System.identityHashCode(binders))
95+
}
96+
}
97+
98+
def withBinder(binder: BindingType): Hashing = {
99+
val newBinders = new Array[BindingType](binders.length + 1)
100+
Array.copy(binders, 0, newBinders, 0, binders.length)
101+
newBinders(binders.length) = binder
102+
new WithBinders(newBinders)
103+
}
81104
}
82105

83106
object Hashing extends Hashing {

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,9 @@ object Types {
14081408
*/
14091409
def eql(that: Type): Boolean = this.equals(that)
14101410

1411+
/** Compute `hash` using given `Hashing` */
1412+
def computeHash(h: Hashing): Int
1413+
14111414
} // end Type
14121415

14131416
// ----- Type categories ----------------------------------------------
@@ -1451,7 +1454,6 @@ object Types {
14511454
}
14521455
override final def hashCode =
14531456
if (hash == Hashing.NotCached) System.identityHashCode(this) else hash
1454-
def computeHash(h: Hashing): Int
14551457
}
14561458

14571459
/** Instances of this class are cached and are proxies. */
@@ -1466,25 +1468,26 @@ object Types {
14661468
}
14671469
override final def hashCode =
14681470
if (hash == Hashing.NotCached) System.identityHashCode(this) else hash
1469-
def computeHash(h: Hashing): Int
14701471
}
14711472

14721473
/** Instances of this class are uncached and are not proxies. */
14731474
abstract class UncachedGroundType extends Type {
1474-
final def hash = Hashing.NotCached
14751475
if (monitored) {
14761476
record(s"uncachable")
14771477
record(s"uncachable: $getClass")
14781478
}
1479+
final def hash = Hashing.NotCached
1480+
final def computeHash(h: Hashing): Int = Hashing.NotCached
14791481
}
14801482

14811483
/** Instances of this class are uncached and are proxies. */
14821484
abstract class UncachedProxyType extends TypeProxy {
1483-
final def hash = Hashing.NotCached
14841485
if (monitored) {
14851486
record(s"uncachable")
14861487
record(s"uncachable: $getClass")
14871488
}
1489+
final def hash = Hashing.NotCached
1490+
final def computeHash(h: Hashing): Int = Hashing.NotCached
14881491
}
14891492

14901493
/** A marker trait for types that apply only to type symbols */

0 commit comments

Comments
 (0)