@@ -1417,6 +1417,9 @@ object Types {
1417
1417
/** Compute hashcode relative to enclosing binders `bs` */
1418
1418
def computeHash (bs : Binders ): Int
1419
1419
1420
+ /** Is the `hash` of this type the same for all possible sequences of enclosing binders? */
1421
+ def stableHash : Boolean = true
1422
+
1420
1423
} // end Type
1421
1424
1422
1425
// ----- Type categories ----------------------------------------------
@@ -1566,6 +1569,7 @@ object Types {
1566
1569
private [this ] var lastDenotation : Denotation = null
1567
1570
private [this ] var lastSymbol : Symbol = null
1568
1571
private [this ] var checkedPeriod : Period = Nowhere
1572
+ private [this ] var myStableHash : Byte = 0
1569
1573
1570
1574
// Invariants:
1571
1575
// (1) checkedPeriod != Nowhere => lastDenotation != null
@@ -2038,6 +2042,11 @@ object Types {
2038
2042
2039
2043
override def computeHash (bs : Binders ) = doHash(bs, designator, prefix)
2040
2044
2045
+ override def stableHash = {
2046
+ if (myStableHash == 0 ) myStableHash = if (prefix.stableHash) 1 else - 1
2047
+ myStableHash > 0
2048
+ }
2049
+
2041
2050
override def eql (that : Type ) = this eq that // safe because named types are hash-consed separately
2042
2051
}
2043
2052
@@ -2289,6 +2298,7 @@ object Types {
2289
2298
else parent
2290
2299
2291
2300
override def computeHash (bs : Binders ) = doHash(bs, refinedName, refinedInfo, parent)
2301
+ override def stableHash = refinedInfo.stableHash && parent.stableHash
2292
2302
2293
2303
override def eql (that : Type ) = that match {
2294
2304
case that : RefinedType =>
@@ -2362,6 +2372,11 @@ object Types {
2362
2372
2363
2373
override def computeHash (bs : Binders ) = doHash(new Binders (this , bs), parent)
2364
2374
2375
+ override def stableHash = false
2376
+ // this is a conservative observation. By construction RecTypes contain at least
2377
+ // one RecThis occurrence. Since `stableHash` does not keep track of enclosing
2378
+ // bound types, it will return "unstable" for this occurrence and this would propagate.
2379
+
2365
2380
override def eql (that : Type ) = that match {
2366
2381
case that : RecType => parent.eq(that.parent)
2367
2382
case _ => false
@@ -2414,7 +2429,7 @@ object Types {
2414
2429
2415
2430
// --- AndType/OrType ---------------------------------------------------------------
2416
2431
2417
- trait AndOrType extends ValueType { // todo: check where we can simplify using AndOrType
2432
+ abstract class AndOrType extends CachedGroundType with ValueType {
2418
2433
def tp1 : Type
2419
2434
def tp2 : Type
2420
2435
def isAnd : Boolean
@@ -2450,9 +2465,22 @@ object Types {
2450
2465
}
2451
2466
myBaseClasses
2452
2467
}
2468
+
2469
+ override def computeHash (bs : Binders ) = doHash(bs, tp1, tp2)
2470
+ override def stableHash = tp1.stableHash && tp2.stableHash
2471
+
2472
+ override def eql (that : Type ) = that match {
2473
+ case that : AndOrType => isAnd == that.isAnd && tp1.eq(that.tp1) && tp2.eq(that.tp2)
2474
+ case _ => false
2475
+ }
2476
+
2477
+ override def iso (that : Any , bs : BinderPairs ) = that match {
2478
+ case that : AndOrType => isAnd == that.isAnd && tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs)
2479
+ case _ => false
2480
+ }
2453
2481
}
2454
2482
2455
- abstract case class AndType (tp1 : Type , tp2 : Type ) extends CachedGroundType with AndOrType {
2483
+ abstract case class AndType (tp1 : Type , tp2 : Type ) extends AndOrType {
2456
2484
2457
2485
def isAnd = true
2458
2486
@@ -2466,18 +2494,6 @@ object Types {
2466
2494
2467
2495
def derivedAndOrType (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type =
2468
2496
derivedAndType(tp1, tp2)
2469
-
2470
- override def computeHash (bs : Binders ) = doHash(bs, tp1, tp2)
2471
-
2472
- override def eql (that : Type ) = that match {
2473
- case that : AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
2474
- case _ => false
2475
- }
2476
-
2477
- override def iso (that : Any , bs : BinderPairs ) = that match {
2478
- case that : AndType => tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs)
2479
- case _ => false
2480
- }
2481
2497
}
2482
2498
2483
2499
final class CachedAndType (tp1 : Type , tp2 : Type ) extends AndType (tp1, tp2)
@@ -2506,7 +2522,7 @@ object Types {
2506
2522
if (checkValid) apply(tp1, tp2) else unchecked(tp1, tp2)
2507
2523
}
2508
2524
2509
- abstract case class OrType (tp1 : Type , tp2 : Type ) extends CachedGroundType with AndOrType {
2525
+ abstract case class OrType (tp1 : Type , tp2 : Type ) extends AndOrType {
2510
2526
2511
2527
assert(tp1.isInstanceOf [ValueTypeOrWildcard ] &&
2512
2528
tp2.isInstanceOf [ValueTypeOrWildcard ], s " $tp1 $tp2" )
@@ -2532,18 +2548,6 @@ object Types {
2532
2548
2533
2549
def derivedAndOrType (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type =
2534
2550
derivedOrType(tp1, tp2)
2535
-
2536
- override def computeHash (bs : Binders ) = doHash(bs, tp1, tp2)
2537
-
2538
- override def eql (that : Type ) = that match {
2539
- case that : OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
2540
- case _ => false
2541
- }
2542
-
2543
- override def iso (that : Any , bs : BinderPairs ) = that match {
2544
- case that : OrType => tp1.equals(that.tp1, bs) && tp2.equals(that.tp2, bs)
2545
- case _ => false
2546
- }
2547
2551
}
2548
2552
2549
2553
final class CachedOrType (tp1 : Type , tp2 : Type ) extends OrType (tp1, tp2)
@@ -2605,6 +2609,7 @@ object Types {
2605
2609
if (resType eq this .resType) this else ExprType (resType)
2606
2610
2607
2611
override def computeHash (bs : Binders ) = doHash(bs, resType)
2612
+ override def stableHash = resType.stableHash
2608
2613
2609
2614
override def eql (that : Type ) = that match {
2610
2615
case that : ExprType => resType.eq(that.resType)
@@ -2693,10 +2698,11 @@ object Types {
2693
2698
abstract class HKLambda extends CachedProxyType with LambdaType {
2694
2699
final override def underlying (implicit ctx : Context ) = resType
2695
2700
2696
- final override def computeHash (bs : Binders ) =
2701
+ override def computeHash (bs : Binders ) =
2697
2702
doHash(new Binders (this , bs), paramNames, resType, paramInfos)
2703
+ override def stableHash = resType.stableHash && paramInfos.stableHash
2698
2704
2699
- final override def eql (that : Type ) = that match {
2705
+ override def eql (that : Type ) = that match {
2700
2706
case that : HKLambda =>
2701
2707
paramNames.equals(that.paramNames) &&
2702
2708
paramInfos.equals(that.paramInfos) &&
@@ -3128,6 +3134,7 @@ object Types {
3128
3134
3129
3135
private [this ] var validSuper : Period = Nowhere
3130
3136
private [this ] var cachedSuper : Type = _
3137
+ private [this ] var myStableHash : Byte = 0
3131
3138
3132
3139
override def underlying (implicit ctx : Context ): Type = tycon
3133
3140
@@ -3173,6 +3180,12 @@ object Types {
3173
3180
else tycon.appliedTo(args)
3174
3181
3175
3182
override def computeHash (bs : Binders ) = doHash(bs, tycon, args)
3183
+
3184
+ override def stableHash = {
3185
+ if (myStableHash == 0 ) myStableHash = if (tycon.stableHash && args.stableHash) 1 else - 1
3186
+ myStableHash > 0
3187
+ }
3188
+
3176
3189
override def eql (that : Type ) = this `eq` that // safe because applied types are hash-consed separately
3177
3190
3178
3191
final override def iso (that : Any , bs : BinderPairs ) = that match {
@@ -3198,6 +3211,7 @@ object Types {
3198
3211
type BT <: Type
3199
3212
val binder : BT
3200
3213
def copyBoundType (bt : BT ): Type
3214
+ override def stableHash = false
3201
3215
}
3202
3216
3203
3217
abstract class ParamRef extends BoundType {
@@ -3469,6 +3483,7 @@ object Types {
3469
3483
else ClassInfo (prefix, cls, classParents, decls, selfInfo)
3470
3484
3471
3485
override def computeHash (bs : Binders ) = doHash(bs, cls, prefix)
3486
+ override def stableHash = prefix.stableHash && classParents.stableHash
3472
3487
3473
3488
override def eql (that : Type ) = that match {
3474
3489
case that : ClassInfo =>
@@ -3562,6 +3577,7 @@ object Types {
3562
3577
}
3563
3578
3564
3579
override def computeHash (bs : Binders ) = doHash(bs, lo, hi)
3580
+ override def stableHash = lo.stableHash && hi.stableHash
3565
3581
3566
3582
override def iso (that : Any , bs : BinderPairs ): Boolean = that match {
3567
3583
case that : TypeAlias => false
@@ -3585,6 +3601,7 @@ object Types {
3585
3601
if (alias eq this .alias) this else TypeAlias (alias)
3586
3602
3587
3603
override def computeHash (bs : Binders ) = doHash(bs, alias)
3604
+ override def stableHash = alias.stableHash
3588
3605
3589
3606
override def iso (that : Any , bs : BinderPairs ): Boolean = that match {
3590
3607
case that : TypeAlias => alias.equals(that.alias, bs)
@@ -3649,6 +3666,7 @@ object Types {
3649
3666
if (elemtp eq this .elemType) this else JavaArrayType (elemtp)
3650
3667
3651
3668
override def computeHash (bs : Binders ) = doHash(bs, elemType)
3669
+ override def stableHash = elemType.stableHash
3652
3670
3653
3671
override def eql (that : Type ) = that match {
3654
3672
case that : JavaArrayType => elemType.eq(that.elemType)
@@ -3717,6 +3735,7 @@ object Types {
3717
3735
else WildcardType (optBounds.asInstanceOf [TypeBounds ])
3718
3736
3719
3737
override def computeHash (bs : Binders ) = doHash(bs, optBounds)
3738
+ override def stableHash = optBounds.stableHash
3720
3739
3721
3740
override def eql (that : Type ) = that match {
3722
3741
case that : WildcardType => optBounds.eq(that.optBounds)
@@ -4510,7 +4529,9 @@ object Types {
4510
4529
4511
4530
implicit def decorateTypeApplications (tpe : Type ): TypeApplications = new TypeApplications (tpe)
4512
4531
4513
- implicit class listEquals (val tps1 : List [Type ]) extends AnyVal {
4532
+ implicit class typeListDeco (val tps1 : List [Type ]) extends AnyVal {
4533
+ @ tailrec def stableHash : Boolean =
4534
+ tps1.isEmpty || tps1.head.stableHash && tps1.tail.stableHash
4514
4535
@ tailrec def equalElements (tps2 : List [Type ], bs : BinderPairs ): Boolean =
4515
4536
(tps1 `eq` tps2) || {
4516
4537
if (tps1.isEmpty) tps2.isEmpty
0 commit comments