Skip to content

Commit fb3aeda

Browse files
committed
Move hashing to separate object
This is a first step of a larger refactoring, where hashing and equality need to have algorithms that detect that isomorphic BindingTypes are equal. Without this, there is no good way to deal with recursive higher-kinded types, as we cannot detect that a type has already been added to a constraint or that a subtype test was already performed.
1 parent 39980f3 commit fb3aeda

File tree

7 files changed

+100
-101
lines changed

7 files changed

+100
-101
lines changed

compiler/src/dotty/tools/dotc/core/Hashable.scala renamed to compiler/src/dotty/tools/dotc/core/Hashing.scala

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,24 @@ package core
44
import Types._
55
import scala.util.hashing.{ MurmurHash3 => hashing }
66

7-
object Hashable {
7+
abstract class Hashing {
8+
import Hashing._
89

9-
/** A hash value indicating that the underlying type is not
10-
* cached in uniques.
11-
*/
12-
final val NotCached = 0
13-
14-
/** An alternative value returned from `hash` if the
15-
* computed hashCode would be `NotCached`.
16-
*/
17-
private[core] final val NotCachedAlt = Int.MinValue
18-
19-
/** A value that indicates that the hash code is unknown
20-
*/
21-
private[core] final val HashUnknown = 1234
22-
23-
/** An alternative value if computeHash would otherwise yield HashUnknown
24-
*/
25-
private[core] final val HashUnknownAlt = 4321
26-
}
27-
28-
trait Hashable {
29-
import Hashable._
30-
31-
protected def hashSeed: Int = getClass.hashCode
32-
33-
protected final def finishHash(hashCode: Int, arity: Int): Int =
10+
final def finishHash(hashCode: Int, arity: Int): Int =
3411
avoidSpecialHashes(hashing.finalizeHash(hashCode, arity))
3512

36-
final def identityHash = avoidSpecialHashes(System.identityHashCode(this))
13+
protected def typeHash(tp: Type) = tp.hash
14+
15+
final def identityHash(tp: Type) = avoidSpecialHashes(System.identityHashCode(tp))
3716

3817
protected def finishHash(seed: Int, arity: Int, tp: Type): Int = {
39-
val elemHash = tp.hash
18+
val elemHash = typeHash(tp)
4019
if (elemHash == NotCached) return NotCached
4120
finishHash(hashing.mix(seed, elemHash), arity + 1)
4221
}
4322

4423
protected def finishHash(seed: Int, arity: Int, tp1: Type, tp2: Type): Int = {
45-
val elemHash = tp1.hash
24+
val elemHash = typeHash(tp1)
4625
if (elemHash == NotCached) return NotCached
4726
finishHash(hashing.mix(seed, elemHash), arity + 1, tp2)
4827
}
@@ -52,7 +31,7 @@ trait Hashable {
5231
var xs = tps
5332
var len = arity
5433
while (xs.nonEmpty) {
55-
val elemHash = xs.head.hash
34+
val elemHash = typeHash(xs.head)
5635
if (elemHash == NotCached) return NotCached
5736
h = hashing.mix(h, elemHash)
5837
xs = xs.tail
@@ -62,37 +41,36 @@ trait Hashable {
6241
}
6342

6443
protected def finishHash(seed: Int, arity: Int, tp: Type, tps: List[Type]): Int = {
65-
val elemHash = tp.hash
44+
val elemHash = typeHash(tp)
6645
if (elemHash == NotCached) return NotCached
6746
finishHash(hashing.mix(seed, elemHash), arity + 1, tps)
6847
}
6948

70-
protected final def doHash(x: Any): Int =
71-
finishHash(hashing.mix(hashSeed, x.hashCode), 1)
49+
final def doHash(clazz: Class[_], x: Any): Int =
50+
finishHash(hashing.mix(clazz.hashCode, x.hashCode), 1)
7251

73-
protected final def doHash(tp: Type): Int =
74-
finishHash(hashSeed, 0, tp)
52+
final def doHash(clazz: Class[_], tp: Type): Int =
53+
finishHash(clazz.hashCode, 0, tp)
7554

76-
protected final def doHash(x1: Any, tp2: Type): Int =
77-
finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2)
55+
final def doHash(clazz: Class[_], x1: Any, tp2: Type): Int =
56+
finishHash(hashing.mix(clazz.hashCode, x1.hashCode), 1, tp2)
7857

79-
protected final def doHash(tp1: Type, tp2: Type): Int =
80-
finishHash(hashSeed, 0, tp1, tp2)
58+
final def doHash(clazz: Class[_], tp1: Type, tp2: Type): Int =
59+
finishHash(clazz.hashCode, 0, tp1, tp2)
8160

82-
protected final def doHash(x1: Any, tp2: Type, tp3: Type): Int =
83-
finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2, tp3)
61+
final def doHash(clazz: Class[_], x1: Any, tp2: Type, tp3: Type): Int =
62+
finishHash(hashing.mix(clazz.hashCode, x1.hashCode), 1, tp2, tp3)
8463

85-
protected final def doHash(tp1: Type, tps2: List[Type]): Int =
86-
finishHash(hashSeed, 0, tp1, tps2)
64+
final def doHash(clazz: Class[_], tp1: Type, tps2: List[Type]): Int =
65+
finishHash(clazz.hashCode, 0, tp1, tps2)
8766

88-
protected final def doHash(x1: Any, tp2: Type, tps3: List[Type]): Int =
89-
finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2, tps3)
67+
final def doHash(clazz: Class[_], x1: Any, tp2: Type, tps3: List[Type]): Int =
68+
finishHash(hashing.mix(clazz.hashCode, x1.hashCode), 1, tp2, tps3)
9069

70+
final def doHash(clazz: Class[_], x1: Int, x2: Int): Int =
71+
finishHash(hashing.mix(hashing.mix(clazz.hashCode, x1), x2), 1)
9172

92-
protected final def doHash(x1: Int, x2: Int): Int =
93-
finishHash(hashing.mix(hashing.mix(hashSeed, x1), x2), 1)
94-
95-
protected final def addDelta(elemHash: Int, delta: Int) =
73+
final def addDelta(elemHash: Int, delta: Int) =
9674
if (elemHash == NotCached) NotCached
9775
else avoidSpecialHashes(elemHash + delta)
9876

@@ -101,3 +79,25 @@ trait Hashable {
10179
else if (h == HashUnknown) HashUnknownAlt
10280
else h
10381
}
82+
83+
object Hashing extends Hashing {
84+
85+
/** A hash value indicating that the underlying type is not
86+
* cached in uniques.
87+
*/
88+
final val NotCached = 0
89+
90+
/** An alternative value returned from `hash` if the
91+
* computed hashCode would be `NotCached`.
92+
*/
93+
private[core] final val NotCachedAlt = Int.MinValue
94+
95+
/** A value that indicates that the hash code is unknown
96+
*/
97+
private[core] final val HashUnknown = 1234
98+
99+
/** An alternative value if computeHash would otherwise yield HashUnknown
100+
*/
101+
private[core] final val HashUnknownAlt = 4321
102+
}
103+

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ object TypeErasure {
7878
*/
7979
abstract case class ErasedValueType(tycon: TypeRef, erasedUnderlying: Type)
8080
extends CachedGroundType with ValueType {
81-
override def computeHash = doHash(tycon, erasedUnderlying)
81+
override def computeHash(h: Hashing) = h.doHash(getClass, tycon, erasedUnderlying)
8282
}
8383

8484
final class CachedErasedValueType(tycon: TypeRef, erasedUnderlying: Type)

0 commit comments

Comments
 (0)