@@ -3,8 +3,18 @@ package core
3
3
4
4
import Types ._
5
5
import scala .util .hashing .{ MurmurHash3 => hashing }
6
+ import annotation .tailrec
6
7
7
8
object Hashable {
9
+
10
+ /** A null terminated list of BindingTypes. We use `null` here for efficiency */
11
+ class Binders (val tp : BindingType , val next : Binders )
12
+
13
+ /** A null terminated list of pairs of BindingTypes. Used for isomorphism tests. */
14
+ class BinderPairs (tp1 : BindingType , tp2 : BindingType , next : BinderPairs ) {
15
+ @ tailrec final def matches (t1 : Type , t2 : Type ): Boolean =
16
+ (t1 `eq` tp1) && (t2 `eq` tp2) || next != null && next.matches(t1, t2)
17
+ }
8
18
9
19
/** A hash value indicating that the underlying type is not
10
20
* cached in uniques.
@@ -33,26 +43,29 @@ trait Hashable {
33
43
protected final def finishHash (hashCode : Int , arity : Int ): Int =
34
44
avoidSpecialHashes(hashing.finalizeHash(hashCode, arity))
35
45
36
- final def identityHash = avoidSpecialHashes(System .identityHashCode(this ))
46
+ final def typeHash (bs : Binders , tp : Type ) =
47
+ if (bs == null || tp.stableHash) tp.hash else tp.computeHash(bs)
48
+
49
+ def identityHash (bs : Binders ) = avoidSpecialHashes(System .identityHashCode(this ))
37
50
38
- protected def finishHash (seed : Int , arity : Int , tp : Type ): Int = {
39
- val elemHash = tp.hash
51
+ protected def finishHash (bs : Binders , seed : Int , arity : Int , tp : Type ): Int = {
52
+ val elemHash = typeHash(bs, tp)
40
53
if (elemHash == NotCached ) return NotCached
41
54
finishHash(hashing.mix(seed, elemHash), arity + 1 )
42
55
}
43
56
44
- protected def finishHash (seed : Int , arity : Int , tp1 : Type , tp2 : Type ): Int = {
45
- val elemHash = tp1.hash
57
+ protected def finishHash (bs : Binders , seed : Int , arity : Int , tp1 : Type , tp2 : Type ): Int = {
58
+ val elemHash = typeHash(bs, tp1)
46
59
if (elemHash == NotCached ) return NotCached
47
- finishHash(hashing.mix(seed, elemHash), arity + 1 , tp2)
60
+ finishHash(bs, hashing.mix(seed, elemHash), arity + 1 , tp2)
48
61
}
49
62
50
- protected def finishHash (seed : Int , arity : Int , tps : List [Type ]): Int = {
63
+ protected def finishHash (bs : Binders , seed : Int , arity : Int , tps : List [Type ]): Int = {
51
64
var h = seed
52
65
var xs = tps
53
66
var len = arity
54
67
while (xs.nonEmpty) {
55
- val elemHash = xs.head.hash
68
+ val elemHash = typeHash(bs, xs.head)
56
69
if (elemHash == NotCached ) return NotCached
57
70
h = hashing.mix(h, elemHash)
58
71
xs = xs.tail
@@ -61,33 +74,33 @@ trait Hashable {
61
74
finishHash(h, len)
62
75
}
63
76
64
- protected def finishHash (seed : Int , arity : Int , tp : Type , tps : List [Type ]): Int = {
65
- val elemHash = tp.hash
77
+ protected def finishHash (bs : Binders , seed : Int , arity : Int , tp : Type , tps : List [Type ]): Int = {
78
+ val elemHash = typeHash(bs, tp)
66
79
if (elemHash == NotCached ) return NotCached
67
- finishHash(hashing.mix(seed, elemHash), arity + 1 , tps)
80
+ finishHash(bs, hashing.mix(seed, elemHash), arity + 1 , tps)
68
81
}
69
82
83
+
70
84
protected final def doHash (x : Any ): Int =
71
85
finishHash(hashing.mix(hashSeed, x.hashCode), 1 )
72
86
73
- protected final def doHash (tp : Type ): Int =
74
- finishHash(hashSeed, 0 , tp)
75
-
76
- protected final def doHash (x1 : Any , tp2 : Type ): Int =
77
- finishHash(hashing.mix(hashSeed, x1.hashCode), 1 , tp2)
87
+ protected final def doHash (bs : Binders , tp : Type ): Int =
88
+ finishHash(bs, hashSeed, 0 , tp)
78
89
79
- protected final def doHash (tp1 : Type , tp2 : Type ): Int =
80
- finishHash(hashSeed, 0 , tp1 , tp2)
90
+ protected final def doHash (bs : Binders , x1 : Any , tp2 : Type ): Int =
91
+ finishHash(bs, hashing.mix( hashSeed, x1.hashCode), 1 , tp2)
81
92
82
- protected final def doHash (x1 : Any , tp2 : Type , tp3 : Type ): Int =
83
- finishHash(hashing.mix(hashSeed, x1.hashCode), 1 , tp2, tp3 )
93
+ protected final def doHash (bs : Binders , tp1 : Type , tp2 : Type ): Int =
94
+ finishHash(bs, hashSeed, 0 , tp1, tp2 )
84
95
85
- protected final def doHash (tp1 : Type , tps2 : List [ Type ] ): Int =
86
- finishHash(hashSeed, 0 , tp1, tps2 )
96
+ protected final def doHash (bs : Binders , x1 : Any , tp2 : Type , tp3 : Type ): Int =
97
+ finishHash(bs, hashing.mix( hashSeed, x1.hashCode), 1 , tp2, tp3 )
87
98
88
- protected final def doHash (x1 : Any , tp2 : Type , tps3 : List [Type ]): Int =
89
- finishHash(hashing.mix(hashSeed, x1.hashCode), 1 , tp2, tps3 )
99
+ protected final def doHash (bs : Binders , tp1 : Type , tps2 : List [Type ]): Int =
100
+ finishHash(bs, hashSeed, 0 , tp1, tps2 )
90
101
102
+ protected final def doHash (bs : Binders , x1 : Any , tp2 : Type , tps3 : List [Type ]): Int =
103
+ finishHash(bs, hashing.mix(hashSeed, x1.hashCode), 1 , tp2, tps3)
91
104
92
105
protected final def doHash (x1 : Int , x2 : Int ): Int =
93
106
finishHash(hashing.mix(hashing.mix(hashSeed, x1), x2), 1 )
@@ -96,7 +109,7 @@ trait Hashable {
96
109
if (elemHash == NotCached ) NotCached
97
110
else avoidSpecialHashes(elemHash + delta)
98
111
99
- private def avoidSpecialHashes (h : Int ) =
112
+ protected def avoidSpecialHashes (h : Int ) =
100
113
if (h == NotCached ) NotCachedAlt
101
114
else if (h == HashUnknown ) HashUnknownAlt
102
115
else h
0 commit comments