Skip to content

Commit a87540a

Browse files
committed
Add binders parameter to all hashcode computations
1 parent 2dbf413 commit a87540a

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
@@ -1394,15 +1394,18 @@ object Types {
13941394
*/
13951395
def simplified(implicit ctx: Context) = ctx.simplify(this, null)
13961396

1397+
/** Equality used for hash-consing; uses `eq` on all recursive invocations.
1398+
*/
1399+
def eql(that: Type): Boolean = this.equals(that)
1400+
13971401
/** customized hash code of this type.
13981402
* NotCached for uncached types. Cached types
13991403
* compute hash and use it as the type's hashCode.
14001404
*/
14011405
def hash: Int
14021406

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

14071410
} // end Type
14081411

@@ -1440,34 +1443,33 @@ object Types {
14401443
private[this] var myHash = HashUnknown
14411444
final def hash = {
14421445
if (myHash == HashUnknown) {
1443-
myHash = computeHash
1446+
myHash = computeHash(null)
14441447
assert(myHash != HashUnknown)
14451448
}
14461449
myHash
14471450
}
14481451
override final def hashCode =
14491452
if (hash == NotCached) System.identityHashCode(this) else hash
1450-
def computeHash: Int
14511453
}
14521454

14531455
/** Instances of this class are cached and are proxies. */
14541456
abstract class CachedProxyType extends TypeProxy with CachedType {
14551457
protected[this] var myHash = HashUnknown
14561458
final def hash = {
14571459
if (myHash == HashUnknown) {
1458-
myHash = computeHash
1460+
myHash = computeHash(null)
14591461
assert(myHash != HashUnknown)
14601462
}
14611463
myHash
14621464
}
14631465
override final def hashCode =
14641466
if (hash == NotCached) System.identityHashCode(this) else hash
1465-
def computeHash: Int
14661467
}
14671468

14681469
/** Instances of this class are uncached and are not proxies. */
14691470
abstract class UncachedGroundType extends Type {
14701471
final def hash = NotCached
1472+
final def computeHash(bs: Binders) = NotCached
14711473
if (monitored) {
14721474
record(s"uncachable")
14731475
record(s"uncachable: $getClass")
@@ -1477,6 +1479,7 @@ object Types {
14771479
/** Instances of this class are uncached and are proxies. */
14781480
abstract class UncachedProxyType extends TypeProxy {
14791481
final def hash = NotCached
1482+
final def computeHash(bs: Binders) = NotCached
14801483
if (monitored) {
14811484
record(s"uncachable")
14821485
record(s"uncachable: $getClass")
@@ -2016,7 +2019,7 @@ object Types {
20162019
false
20172020
}
20182021

2019-
override def computeHash = unsupported("computeHash")
2022+
override def computeHash(bs: Binders) = doHash(bs, designator, prefix)
20202023

20212024
override def eql(that: Type) = this eq that // safe because named types are hash-consed separately
20222025
}
@@ -2140,7 +2143,7 @@ object Types {
21402143
// can happen in IDE if `cls` is stale
21412144
}
21422145

2143-
override def computeHash = doHash(tref)
2146+
override def computeHash(bs: Binders) = doHash(bs, tref)
21442147

21452148
override def eql(that: Type) = that match {
21462149
case that: ThisType => tref.eq(that.tref)
@@ -2168,7 +2171,7 @@ object Types {
21682171
if ((thistpe eq this.thistpe) && (supertpe eq this.supertpe)) this
21692172
else SuperType(thistpe, supertpe)
21702173

2171-
override def computeHash = doHash(thistpe, supertpe)
2174+
override def computeHash(bs: Binders) = doHash(bs, thistpe, supertpe)
21722175

21732176
override def eql(that: Type) = that match {
21742177
case that: SuperType => thistpe.eq(that.thistpe) && supertpe.eq(that.supertpe)
@@ -2189,7 +2192,7 @@ object Types {
21892192
abstract case class ConstantType(value: Constant) extends CachedProxyType with SingletonType {
21902193
override def underlying(implicit ctx: Context) = value.tpe
21912194

2192-
override def computeHash = doHash(value)
2195+
override def computeHash(bs: Binders) = doHash(value)
21932196
}
21942197

21952198
final class CachedConstantType(value: Constant) extends ConstantType(value)
@@ -2253,7 +2256,7 @@ object Types {
22532256
if (parent.member(refinedName).exists) derivedRefinedType(parent, refinedName, refinedInfo)
22542257
else parent
22552258

2256-
override def computeHash = doHash(refinedName, refinedInfo, parent)
2259+
override def computeHash(bs: Binders) = doHash(bs, refinedName, refinedInfo, parent)
22572260

22582261
override def eql(that: Type) = that match {
22592262
case that: RefinedType =>
@@ -2317,7 +2320,7 @@ object Types {
23172320
refacc.apply(false, tp)
23182321
}
23192322

2320-
override def computeHash = doHash(parent)
2323+
override def computeHash(bs: Binders) = doHash(bs, parent)
23212324

23222325
override def equals(that: Any) = that match {
23232326
case that: RecType => parent == that.parent
@@ -2423,7 +2426,7 @@ object Types {
24232426
def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
24242427
derivedAndType(tp1, tp2)
24252428

2426-
override def computeHash = doHash(tp1, tp2)
2429+
override def computeHash(bs: Binders) = doHash(bs, tp1, tp2)
24272430

24282431
override def eql(that: Type) = that match {
24292432
case that: AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
@@ -2484,7 +2487,7 @@ object Types {
24842487
def derivedAndOrType(tp1: Type, tp2: Type)(implicit ctx: Context): Type =
24852488
derivedOrType(tp1, tp2)
24862489

2487-
override def computeHash = doHash(tp1, tp2)
2490+
override def computeHash(bs: Binders) = doHash(bs, tp1, tp2)
24882491

24892492
override def eql(that: Type) = that match {
24902493
case that: OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
@@ -2550,7 +2553,7 @@ object Types {
25502553
def derivedExprType(resType: Type)(implicit ctx: Context) =
25512554
if (resType eq this.resType) this else ExprType(resType)
25522555

2553-
override def computeHash = doHash(resType)
2556+
override def computeHash(bs: Binders) = doHash(bs, resType)
25542557

25552558
override def eql(that: Type) = that match {
25562559
case that: ExprType => resType.eq(that.resType)
@@ -2634,7 +2637,7 @@ object Types {
26342637
abstract class HKLambda extends CachedProxyType with LambdaType {
26352638
final override def underlying(implicit ctx: Context) = resType
26362639

2637-
final override def computeHash = doHash(paramNames, resType, paramInfos)
2640+
final override def computeHash(bs: Binders) = doHash(bs, paramNames, resType, paramInfos)
26382641

26392642
final override def equals(that: Any) = that match {
26402643
case that: HKLambda =>
@@ -3110,12 +3113,13 @@ object Types {
31103113
def derivedAppliedType(tycon: Type, args: List[Type])(implicit ctx: Context): Type =
31113114
if ((tycon eq this.tycon) && (args eq this.args)) this
31123115
else tycon.appliedTo(args)
3116+
3117+
override def computeHash(bs: Binders) = doHash(bs, tycon, args)
3118+
override def eql(that: Type) = this `eq` that // safe because applied types are hash-consed separately
31133119
}
31143120

31153121
final class CachedAppliedType(tycon: Type, args: List[Type], hc: Int) extends AppliedType(tycon, args) {
31163122
myHash = hc
3117-
override def computeHash = unsupported("computeHash")
3118-
override def eql(that: Type) = this eq that // safe because applied types are hash-consed separately
31193123
}
31203124

31213125
object AppliedType {
@@ -3131,6 +3135,8 @@ object Types {
31313135
type BT <: Type
31323136
val binder: BT
31333137
def copyBoundType(bt: BT): Type
3138+
override def identityHash(bs: Binders) =
3139+
if (bs == null) super.identityHash(bs) else ???
31343140
}
31353141

31363142
abstract class ParamRef extends BoundType {
@@ -3144,7 +3150,7 @@ object Types {
31443150
else infos(paramNum)
31453151
}
31463152

3147-
override def computeHash = doHash(paramNum, binder.identityHash)
3153+
override def computeHash(bs: Binders) = doHash(bs, paramNum, binder.identityHash(bs))
31483154

31493155
override def equals(that: Any) = that match {
31503156
case that: ParamRef => binder.eq(that.binder) && paramNum == that.paramNum
@@ -3201,7 +3207,7 @@ object Types {
32013207

32023208
// need to customize hashCode and equals to prevent infinite recursion
32033209
// between RecTypes and RecRefs.
3204-
override def computeHash = addDelta(binder.identityHash, 41)
3210+
override def computeHash(bs: Binders) = addDelta(binder.identityHash(bs), 41)
32053211

32063212
override def equals(that: Any) = that match {
32073213
case that: RecThis => binder.eq(that.binder)
@@ -3222,7 +3228,7 @@ object Types {
32223228
override def underlying(implicit ctx: Context) = info
32233229
def derivedSkolemType(info: Type)(implicit ctx: Context) =
32243230
if (info eq this.info) this else SkolemType(info)
3225-
override def hashCode: Int = identityHash
3231+
override def hashCode: Int = System.identityHashCode(this)
32263232
override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
32273233

32283234
def withName(name: Name): this.type = { myRepr = name; this }
@@ -3328,7 +3334,7 @@ object Types {
33283334
}
33293335
}
33303336

3331-
override def computeHash: Int = identityHash
3337+
override def computeHash(bs: Binders): Int = identityHash(bs)
33323338
override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
33333339

33343340
override def toString = {
@@ -3403,7 +3409,7 @@ object Types {
34033409
if ((prefix eq this.prefix) && (classParents eq this.classParents) && (decls eq this.decls) && (selfInfo eq this.selfInfo)) this
34043410
else ClassInfo(prefix, cls, classParents, decls, selfInfo)
34053411

3406-
override def computeHash = doHash(cls, prefix)
3412+
override def computeHash(bs: Binders) = doHash(bs, cls, prefix)
34073413

34083414
override def eql(that: Type) = that match {
34093415
case that: ClassInfo =>
@@ -3486,7 +3492,7 @@ object Types {
34863492
case _ => super.| (that)
34873493
}
34883494

3489-
override def computeHash = doHash(lo, hi)
3495+
override def computeHash(bs: Binders) = doHash(bs, lo, hi)
34903496

34913497
override def equals(that: Any): Boolean = that match {
34923498
case that: TypeAlias => false
@@ -3509,7 +3515,7 @@ object Types {
35093515
def derivedTypeAlias(alias: Type)(implicit ctx: Context) =
35103516
if (alias eq this.alias) this else TypeAlias(alias)
35113517

3512-
override def computeHash = doHash(alias)
3518+
override def computeHash(bs: Binders) = doHash(bs, alias)
35133519

35143520
override def equals(that: Any): Boolean = that match {
35153521
case that: TypeAlias => alias == that.alias
@@ -3568,7 +3574,7 @@ object Types {
35683574
def derivedJavaArrayType(elemtp: Type)(implicit ctx: Context) =
35693575
if (elemtp eq this.elemType) this else JavaArrayType(elemtp)
35703576

3571-
override def computeHash = doHash(elemType)
3577+
override def computeHash(bs: Binders) = doHash(bs, elemType)
35723578

35733579
override def eql(that: Type) = that match {
35743580
case that: JavaArrayType => elemType.eq(that.elemType)
@@ -3586,12 +3592,12 @@ object Types {
35863592
/** Sentinel for "missing type" */
35873593
@sharable case object NoType extends CachedGroundType {
35883594
override def exists = false
3589-
override def computeHash = hashSeed
3595+
override def computeHash(bs: Binders) = hashSeed
35903596
}
35913597

35923598
/** Missing prefix */
35933599
@sharable case object NoPrefix extends CachedGroundType {
3594-
override def computeHash = hashSeed
3600+
override def computeHash(bs: Binders) = hashSeed
35953601
}
35963602

35973603
/** A common superclass of `ErrorType` and `TryDynamicCallSite`. Instances of this
@@ -3631,7 +3637,7 @@ object Types {
36313637
else if (!optBounds.exists) WildcardType
36323638
else WildcardType(optBounds.asInstanceOf[TypeBounds])
36333639

3634-
override def computeHash = doHash(optBounds)
3640+
override def computeHash(bs: Binders) = doHash(bs, optBounds)
36353641

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

0 commit comments

Comments
 (0)