Skip to content

Commit 6290a65

Browse files
committed
Add binders parameter to all hashcode computations
1 parent f00e883 commit 6290a65

File tree

5 files changed

+71
-60
lines changed

5 files changed

+71
-60
lines changed

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

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import scala.util.hashing.{ MurmurHash3 => hashing }
66

77
object Hashable {
88

9+
type Binders = Array[BindingType]
10+
911
/** A hash value indicating that the underlying type is not
1012
* cached in uniques.
1113
*/
@@ -33,26 +35,29 @@ trait Hashable {
3335
protected final def finishHash(hashCode: Int, arity: Int): Int =
3436
avoidSpecialHashes(hashing.finalizeHash(hashCode, arity))
3537

36-
final def identityHash = avoidSpecialHashes(System.identityHashCode(this))
38+
final def typeHash(bs: Binders, tp: Type) =
39+
if (bs == null) tp.hash else tp.computeHash(bs)
40+
41+
def identityHash(bs: Binders) = avoidSpecialHashes(System.identityHashCode(this))
3742

38-
protected def finishHash(seed: Int, arity: Int, tp: Type): Int = {
39-
val elemHash = tp.hash
43+
protected def finishHash(bs: Binders, seed: Int, arity: Int, tp: Type): Int = {
44+
val elemHash = typeHash(bs, tp)
4045
if (elemHash == NotCached) return NotCached
4146
finishHash(hashing.mix(seed, elemHash), arity + 1)
4247
}
4348

44-
protected def finishHash(seed: Int, arity: Int, tp1: Type, tp2: Type): Int = {
45-
val elemHash = tp1.hash
49+
protected def finishHash(bs: Binders, seed: Int, arity: Int, tp1: Type, tp2: Type): Int = {
50+
val elemHash = typeHash(bs, tp1)
4651
if (elemHash == NotCached) return NotCached
47-
finishHash(hashing.mix(seed, elemHash), arity + 1, tp2)
52+
finishHash(bs, hashing.mix(seed, elemHash), arity + 1, tp2)
4853
}
4954

50-
protected def finishHash(seed: Int, arity: Int, tps: List[Type]): Int = {
55+
protected def finishHash(bs: Binders, seed: Int, arity: Int, tps: List[Type]): Int = {
5156
var h = seed
5257
var xs = tps
5358
var len = arity
5459
while (xs.nonEmpty) {
55-
val elemHash = xs.head.hash
60+
val elemHash = typeHash(bs, xs.head)
5661
if (elemHash == NotCached) return NotCached
5762
h = hashing.mix(h, elemHash)
5863
xs = xs.tail
@@ -61,35 +66,35 @@ trait Hashable {
6166
finishHash(h, len)
6267
}
6368

64-
protected def finishHash(seed: Int, arity: Int, tp: Type, tps: List[Type]): Int = {
65-
val elemHash = tp.hash
69+
protected def finishHash(bs: Binders, seed: Int, arity: Int, tp: Type, tps: List[Type]): Int = {
70+
val elemHash = typeHash(bs, tp)
6671
if (elemHash == NotCached) return NotCached
67-
finishHash(hashing.mix(seed, elemHash), arity + 1, tps)
72+
finishHash(bs, hashing.mix(seed, elemHash), arity + 1, tps)
6873
}
6974

7075
protected final def doHash(x: Any): Int =
7176
finishHash(hashing.mix(hashSeed, x.hashCode), 1)
7277

73-
protected final def doHash(tp: Type): Int =
74-
finishHash(hashSeed, 0, tp)
78+
protected final def doHash(bs: Binders, tp: Type): Int =
79+
finishHash(bs, hashSeed, 0, tp)
7580

76-
protected final def doHash(x1: Any, tp2: Type): Int =
77-
finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2)
81+
protected final def doHash(bs: Binders, x1: Any, tp2: Type): Int =
82+
finishHash(bs, hashing.mix(hashSeed, x1.hashCode), 1, tp2)
7883

79-
protected final def doHash(tp1: Type, tp2: Type): Int =
80-
finishHash(hashSeed, 0, tp1, tp2)
84+
protected final def doHash(bs: Binders, tp1: Type, tp2: Type): Int =
85+
finishHash(bs, hashSeed, 0, tp1, tp2)
8186

82-
protected final def doHash(x1: Any, tp2: Type, tp3: Type): Int =
83-
finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2, tp3)
87+
protected final def doHash(bs: Binders, x1: Any, tp2: Type, tp3: Type): Int =
88+
finishHash(bs, hashing.mix(hashSeed, x1.hashCode), 1, tp2, tp3)
8489

85-
protected final def doHash(tp1: Type, tps2: List[Type]): Int =
86-
finishHash(hashSeed, 0, tp1, tps2)
90+
protected final def doHash(bs: Binders, tp1: Type, tps2: List[Type]): Int =
91+
finishHash(bs, hashSeed, 0, tp1, tps2)
8792

88-
protected final def doHash(x1: Any, tp2: Type, tps3: List[Type]): Int =
89-
finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2, tps3)
93+
protected final def doHash(bs: Binders, x1: Any, tp2: Type, tps3: List[Type]): Int =
94+
finishHash(bs, hashing.mix(hashSeed, x1.hashCode), 1, tp2, tps3)
9095

9196

92-
protected final def doHash(x1: Int, x2: Int): Int =
97+
protected final def doHash(bs: Binders, x1: Int, x2: Int): Int =
9398
finishHash(hashing.mix(hashing.mix(hashSeed, x1), x2), 1)
9499

95100
protected final def addDelta(elemHash: Int, delta: Int) =

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(bs: Hashable.Binders) = doHash(bs, tycon, erasedUnderlying)
8282
}
8383

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

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

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,15 +1399,18 @@ object Types {
13991399
*/
14001400
def simplified(implicit ctx: Context) = ctx.simplify(this, null)
14011401

1402+
/** Equality used for hash-consing; uses `eq` on all recursive invocations.
1403+
*/
1404+
def eql(that: Type): Boolean = this.equals(that)
1405+
14021406
/** customized hash code of this type.
14031407
* NotCached for uncached types. Cached types
14041408
* compute hash and use it as the type's hashCode.
14051409
*/
14061410
def hash: Int
14071411

1408-
/** Equality used for hash-consing; uses `eq` on all recursive invocations.
1409-
*/
1410-
def eql(that: Type): Boolean = this.equals(that)
1412+
/** Compute hashcode relative to enclosing binders `bs` */
1413+
def computeHash(bs: Binders): Int
14111414

14121415
} // end Type
14131416

@@ -1445,34 +1448,33 @@ object Types {
14451448
private[this] var myHash = HashUnknown
14461449
final def hash = {
14471450
if (myHash == HashUnknown) {
1448-
myHash = computeHash
1451+
myHash = computeHash(null)
14491452
assert(myHash != HashUnknown)
14501453
}
14511454
myHash
14521455
}
14531456
override final def hashCode =
14541457
if (hash == NotCached) System.identityHashCode(this) else hash
1455-
def computeHash: Int
14561458
}
14571459

14581460
/** Instances of this class are cached and are proxies. */
14591461
abstract class CachedProxyType extends TypeProxy with CachedType {
14601462
protected[this] var myHash = HashUnknown
14611463
final def hash = {
14621464
if (myHash == HashUnknown) {
1463-
myHash = computeHash
1465+
myHash = computeHash(null)
14641466
assert(myHash != HashUnknown)
14651467
}
14661468
myHash
14671469
}
14681470
override final def hashCode =
14691471
if (hash == NotCached) System.identityHashCode(this) else hash
1470-
def computeHash: Int
14711472
}
14721473

14731474
/** Instances of this class are uncached and are not proxies. */
14741475
abstract class UncachedGroundType extends Type {
14751476
final def hash = NotCached
1477+
final def computeHash(bs: Binders) = NotCached
14761478
if (monitored) {
14771479
record(s"uncachable")
14781480
record(s"uncachable: $getClass")
@@ -1482,6 +1484,7 @@ object Types {
14821484
/** Instances of this class are uncached and are proxies. */
14831485
abstract class UncachedProxyType extends TypeProxy {
14841486
final def hash = NotCached
1487+
final def computeHash(bs: Binders) = NotCached
14851488
if (monitored) {
14861489
record(s"uncachable")
14871490
record(s"uncachable: $getClass")
@@ -2025,7 +2028,7 @@ object Types {
20252028
false
20262029
}
20272030

2028-
override def computeHash = unsupported("computeHash")
2031+
override def computeHash(bs: Binders) = doHash(bs, designator, prefix)
20292032

20302033
override def eql(that: Type) = this eq that // safe because named types are hash-consed separately
20312034
}
@@ -2149,7 +2152,7 @@ object Types {
21492152
// can happen in IDE if `cls` is stale
21502153
}
21512154

2152-
override def computeHash = doHash(tref)
2155+
override def computeHash(bs: Binders) = doHash(bs, tref)
21532156

21542157
override def eql(that: Type) = that match {
21552158
case that: ThisType => tref.eq(that.tref)
@@ -2177,7 +2180,7 @@ object Types {
21772180
if ((thistpe eq this.thistpe) && (supertpe eq this.supertpe)) this
21782181
else SuperType(thistpe, supertpe)
21792182

2180-
override def computeHash = doHash(thistpe, supertpe)
2183+
override def computeHash(bs: Binders) = doHash(bs, thistpe, supertpe)
21812184

21822185
override def eql(that: Type) = that match {
21832186
case that: SuperType => thistpe.eq(that.thistpe) && supertpe.eq(that.supertpe)
@@ -2198,7 +2201,7 @@ object Types {
21982201
abstract case class ConstantType(value: Constant) extends CachedProxyType with SingletonType {
21992202
override def underlying(implicit ctx: Context) = value.tpe
22002203

2201-
override def computeHash = doHash(value)
2204+
override def computeHash(bs: Binders) = doHash(value)
22022205
}
22032206

22042207
final class CachedConstantType(value: Constant) extends ConstantType(value)
@@ -2262,7 +2265,7 @@ object Types {
22622265
if (parent.member(refinedName).exists) derivedRefinedType(parent, refinedName, refinedInfo)
22632266
else parent
22642267

2265-
override def computeHash = doHash(refinedName, refinedInfo, parent)
2268+
override def computeHash(bs: Binders) = doHash(bs, refinedName, refinedInfo, parent)
22662269

22672270
override def eql(that: Type) = that match {
22682271
case that: RefinedType =>
@@ -2326,7 +2329,7 @@ object Types {
23262329
refacc.apply(false, tp)
23272330
}
23282331

2329-
override def computeHash = doHash(parent)
2332+
override def computeHash(bs: Binders) = doHash(bs, parent)
23302333

23312334
override def equals(that: Any) = that match {
23322335
case that: RecType => parent == that.parent
@@ -2432,7 +2435,7 @@ object Types {
24322435
def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
24332436
derivedAndType(tp1, tp2)
24342437

2435-
override def computeHash = doHash(tp1, tp2)
2438+
override def computeHash(bs: Binders) = doHash(bs, tp1, tp2)
24362439

24372440
override def eql(that: Type) = that match {
24382441
case that: AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
@@ -2493,7 +2496,7 @@ object Types {
24932496
def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
24942497
derivedOrType(tp1, tp2)
24952498

2496-
override def computeHash = doHash(tp1, tp2)
2499+
override def computeHash(bs: Binders) = doHash(bs, tp1, tp2)
24972500

24982501
override def eql(that: Type) = that match {
24992502
case that: OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
@@ -2559,7 +2562,7 @@ object Types {
25592562
def derivedExprType(resType: Type)(implicit ctx: Context) =
25602563
if (resType eq this.resType) this else ExprType(resType)
25612564

2562-
override def computeHash = doHash(resType)
2565+
override def computeHash(bs: Binders) = doHash(bs, resType)
25632566

25642567
override def eql(that: Type) = that match {
25652568
case that: ExprType => resType.eq(that.resType)
@@ -2643,7 +2646,7 @@ object Types {
26432646
abstract class HKLambda extends CachedProxyType with LambdaType {
26442647
final override def underlying(implicit ctx: Context) = resType
26452648

2646-
final override def computeHash = doHash(paramNames, resType, paramInfos)
2649+
final override def computeHash(bs: Binders) = doHash(bs, paramNames, resType, paramInfos)
26472650

26482651
final override def equals(that: Any) = that match {
26492652
case that: HKLambda =>
@@ -3119,12 +3122,13 @@ object Types {
31193122
def derivedAppliedType(tycon: Type, args: List[Type])(implicit ctx: Context): Type =
31203123
if ((tycon eq this.tycon) && (args eq this.args)) this
31213124
else tycon.appliedTo(args)
3125+
3126+
override def computeHash(bs: Binders) = doHash(bs, tycon, args)
3127+
override def eql(that: Type) = this `eq` that // safe because applied types are hash-consed separately
31223128
}
31233129

31243130
final class CachedAppliedType(tycon: Type, args: List[Type], hc: Int) extends AppliedType(tycon, args) {
31253131
myHash = hc
3126-
override def computeHash = unsupported("computeHash")
3127-
override def eql(that: Type) = this eq that // safe because applied types are hash-consed separately
31283132
}
31293133

31303134
object AppliedType {
@@ -3140,6 +3144,8 @@ object Types {
31403144
type BT <: Type
31413145
val binder: BT
31423146
def copyBoundType(bt: BT): Type
3147+
override def identityHash(bs: Binders) =
3148+
if (bs == null) super.identityHash(bs) else ???
31433149
}
31443150

31453151
abstract class ParamRef extends BoundType {
@@ -3153,7 +3159,7 @@ object Types {
31533159
else infos(paramNum)
31543160
}
31553161

3156-
override def computeHash = doHash(paramNum, binder.identityHash)
3162+
override def computeHash(bs: Binders) = doHash(bs, paramNum, binder.identityHash(bs))
31573163

31583164
override def equals(that: Any) = that match {
31593165
case that: ParamRef => binder.eq(that.binder) && paramNum == that.paramNum
@@ -3210,7 +3216,7 @@ object Types {
32103216

32113217
// need to customize hashCode and equals to prevent infinite recursion
32123218
// between RecTypes and RecRefs.
3213-
override def computeHash = addDelta(binder.identityHash, 41)
3219+
override def computeHash(bs: Binders) = addDelta(binder.identityHash(bs), 41)
32143220

32153221
override def equals(that: Any) = that match {
32163222
case that: RecThis => binder.eq(that.binder)
@@ -3231,7 +3237,7 @@ object Types {
32313237
override def underlying(implicit ctx: Context) = info
32323238
def derivedSkolemType(info: Type)(implicit ctx: Context) =
32333239
if (info eq this.info) this else SkolemType(info)
3234-
override def hashCode: Int = identityHash
3240+
override def hashCode: Int = System.identityHashCode(this)
32353241
override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
32363242

32373243
def withName(name: Name): this.type = { myRepr = name; this }
@@ -3337,7 +3343,7 @@ object Types {
33373343
}
33383344
}
33393345

3340-
override def computeHash: Int = identityHash
3346+
override def computeHash(bs: Binders): Int = identityHash(bs)
33413347
override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
33423348

33433349
override def toString = {
@@ -3412,7 +3418,7 @@ object Types {
34123418
if ((prefix eq this.prefix) && (classParents eq this.classParents) && (decls eq this.decls) && (selfInfo eq this.selfInfo)) this
34133419
else ClassInfo(prefix, cls, classParents, decls, selfInfo)
34143420

3415-
override def computeHash = doHash(cls, prefix)
3421+
override def computeHash(bs: Binders) = doHash(bs, cls, prefix)
34163422

34173423
override def eql(that: Type) = that match {
34183424
case that: ClassInfo =>
@@ -3495,7 +3501,7 @@ object Types {
34953501
case _ => super.| (that)
34963502
}
34973503

3498-
override def computeHash = doHash(lo, hi)
3504+
override def computeHash(bs: Binders) = doHash(bs, lo, hi)
34993505

35003506
override def equals(that: Any): Boolean = that match {
35013507
case that: TypeAlias => false
@@ -3518,7 +3524,7 @@ object Types {
35183524
def derivedTypeAlias(alias: Type)(implicit ctx: Context) =
35193525
if (alias eq this.alias) this else TypeAlias(alias)
35203526

3521-
override def computeHash = doHash(alias)
3527+
override def computeHash(bs: Binders) = doHash(bs, alias)
35223528

35233529
override def equals(that: Any): Boolean = that match {
35243530
case that: TypeAlias => alias == that.alias
@@ -3577,7 +3583,7 @@ object Types {
35773583
def derivedJavaArrayType(elemtp: Type)(implicit ctx: Context) =
35783584
if (elemtp eq this.elemType) this else JavaArrayType(elemtp)
35793585

3580-
override def computeHash = doHash(elemType)
3586+
override def computeHash(bs: Binders) = doHash(bs, elemType)
35813587

35823588
override def eql(that: Type) = that match {
35833589
case that: JavaArrayType => elemType.eq(that.elemType)
@@ -3595,12 +3601,12 @@ object Types {
35953601
/** Sentinel for "missing type" */
35963602
@sharable case object NoType extends CachedGroundType {
35973603
override def exists = false
3598-
override def computeHash = hashSeed
3604+
override def computeHash(bs: Binders) = hashSeed
35993605
}
36003606

36013607
/** Missing prefix */
36023608
@sharable case object NoPrefix extends CachedGroundType {
3603-
override def computeHash = hashSeed
3609+
override def computeHash(bs: Binders) = hashSeed
36043610
}
36053611

36063612
/** A common superclass of `ErrorType` and `TryDynamicCallSite`. Instances of this
@@ -3640,7 +3646,7 @@ object Types {
36403646
else if (!optBounds.exists) WildcardType
36413647
else WildcardType(optBounds.asInstanceOf[TypeBounds])
36423648

3643-
override def computeHash = doHash(optBounds)
3649+
override def computeHash(bs: Binders) = doHash(bs, optBounds)
36443650

36453651
override def eql(that: Type) = that match {
36463652
case that: WildcardType => optBounds.eq(that.optBounds)

0 commit comments

Comments
 (0)