Skip to content

Commit 232f65a

Browse files
committed
Add BinderPairs parameter when testing equality
1 parent a87540a commit 232f65a

File tree

3 files changed

+142
-36
lines changed

3 files changed

+142
-36
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import scala.util.hashing.{ MurmurHash3 => hashing }
66

77
object Hashable {
88

9-
type Binders = Array[BindingType]
9+
class Binders(tp: BindingType, next: Binders)
10+
class BinderPairs(tp1: BindingType, tp2: BindingType, next: BinderPairs)
1011

1112
/** A hash value indicating that the underlying type is not
1213
* cached in uniques.

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

Lines changed: 122 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,16 @@ object Types {
13941394
*/
13951395
def simplified(implicit ctx: Context) = ctx.simplify(this, null)
13961396

1397+
final override def equals(that: Any) = this.equals(that, null)
1398+
1399+
final def equals(that: Any, bs: BinderPairs): Boolean =
1400+
(this `eq` that.asInstanceOf[AnyRef]) || this.iso(that, bs)
1401+
1402+
/** Is `this` isomorphic to that, using comparer `e`?
1403+
* It is assumed that `this ne that`.
1404+
*/
1405+
def iso(that: Any, bs: BinderPairs): Boolean = false
1406+
13971407
/** Equality used for hash-consing; uses `eq` on all recursive invocations.
13981408
*/
13991409
def eql(that: Type): Boolean = this.equals(that)
@@ -1513,7 +1523,14 @@ object Types {
15131523
/** A marker trait for types that bind other types that refer to them.
15141524
* Instances are: LambdaType, RecType.
15151525
*/
1516-
trait BindingType extends Type
1526+
trait BindingType extends Type {
1527+
1528+
override def identityHash(bs: Binders) =
1529+
if (bs == null) super.identityHash(bs) else ???
1530+
1531+
def equalBinder(that: BindingType, bs: BinderPairs): Boolean =
1532+
(this `eq` that) /* || ??? */
1533+
}
15171534

15181535
/** A trait for proto-types, used as expected types in typer */
15191536
trait ProtoType extends Type {
@@ -2011,10 +2028,10 @@ object Types {
20112028
}
20122029
}
20132030

2014-
override def equals(that: Any) = that match {
2031+
override def iso(that: Any, bs: BinderPairs): Boolean = that match {
20152032
case that: NamedType =>
2016-
this.designator == that.designator &&
2017-
this.prefix == that.prefix
2033+
designator == that.designator &&
2034+
prefix.equals(that.prefix, bs)
20182035
case _ =>
20192036
false
20202037
}
@@ -2149,6 +2166,11 @@ object Types {
21492166
case that: ThisType => tref.eq(that.tref)
21502167
case _ => false
21512168
}
2169+
2170+
override def iso(that: Any, bs: BinderPairs): Boolean = that match {
2171+
case that: ThisType => tref.equals(that.tref, bs)
2172+
case _ => false
2173+
}
21522174
}
21532175

21542176
final class CachedThisType(tref: TypeRef) extends ThisType(tref)
@@ -2177,6 +2199,12 @@ object Types {
21772199
case that: SuperType => thistpe.eq(that.thistpe) && supertpe.eq(that.supertpe)
21782200
case _ => false
21792201
}
2202+
2203+
override def iso(that: Any, bs: BinderPairs): Boolean = that match {
2204+
case that: SuperType =>
2205+
thistpe.equals(that.thistpe, bs) && supertpe.equals(that.supertpe, bs)
2206+
case _ => false
2207+
}
21802208
}
21812209

21822210
final class CachedSuperType(thistpe: Type, supertpe: Type) extends SuperType(thistpe, supertpe)
@@ -2193,6 +2221,11 @@ object Types {
21932221
override def underlying(implicit ctx: Context) = value.tpe
21942222

21952223
override def computeHash(bs: Binders) = doHash(value)
2224+
2225+
override def iso(that: Any, bs: BinderPairs): Boolean = that match {
2226+
case that: ConstantType => value.equals(that.value)
2227+
case _ => false
2228+
}
21962229
}
21972230

21982231
final class CachedConstantType(value: Constant) extends ConstantType(value)
@@ -2219,7 +2252,6 @@ object Types {
22192252
def evaluating = computed && myRef == null
22202253
override def underlying(implicit ctx: Context) = ref
22212254
override def toString = s"LazyRef(${if (computed) myRef else "..."})"
2222-
override def equals(other: Any) = this.eq(other.asInstanceOf[AnyRef])
22232255
override def hashCode = System.identityHashCode(this)
22242256
}
22252257

@@ -2265,6 +2297,14 @@ object Types {
22652297
parent.eq(that.parent)
22662298
case _ => false
22672299
}
2300+
2301+
override def iso(that: Any, bs: BinderPairs): Boolean = that match {
2302+
case that: RefinedType =>
2303+
refinedName.eq(that.refinedName) &&
2304+
refinedInfo.equals(that.refinedInfo, bs) &&
2305+
parent.equals(that.parent, bs)
2306+
case _ => false
2307+
}
22682308
}
22692309

22702310
class CachedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)
@@ -2322,13 +2362,14 @@ object Types {
23222362

23232363
override def computeHash(bs: Binders) = doHash(bs, parent)
23242364

2325-
override def equals(that: Any) = that match {
2326-
case that: RecType => parent == that.parent
2365+
override def eql(that: Type) = that match {
2366+
case that: RecType => parent.eq(that.parent)
23272367
case _ => false
23282368
}
23292369

2330-
override def eql(that: Type) = that match {
2331-
case that: RecType => parent.eq(that.parent)
2370+
override def iso(that: Any, bs: BinderPairs) = that match {
2371+
case that: RecType =>
2372+
parent.equals(that.parent, bs/*!!!*/)
23322373
case _ => false
23332374
}
23342375

@@ -2432,6 +2473,11 @@ object Types {
24322473
case that: AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
24332474
case _ => false
24342475
}
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+
}
24352481
}
24362482

24372483
final class CachedAndType(tp1: Type, tp2: Type) extends AndType(tp1, tp2)
@@ -2493,6 +2539,11 @@ object Types {
24932539
case that: OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
24942540
case _ => false
24952541
}
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+
}
24962547
}
24972548

24982549
final class CachedOrType(tp1: Type, tp2: Type) extends OrType(tp1, tp2)
@@ -2559,6 +2610,11 @@ object Types {
25592610
case that: ExprType => resType.eq(that.resType)
25602611
case _ => false
25612612
}
2613+
2614+
override def iso(that: Any, bs: BinderPairs) = that match {
2615+
case that: ExprType => resType.equals(that.resType, bs)
2616+
case _ => false
2617+
}
25622618
}
25632619

25642620
final class CachedExprType(resultType: Type) extends ExprType(resultType)
@@ -2639,30 +2695,31 @@ object Types {
26392695

26402696
final override def computeHash(bs: Binders) = doHash(bs, paramNames, resType, paramInfos)
26412697

2642-
final override def equals(that: Any) = that match {
2698+
final override def eql(that: Type) = that match {
26432699
case that: HKLambda =>
2644-
paramNames == that.paramNames &&
2645-
paramInfos == that.paramInfos &&
2646-
resType == that.resType &&
2700+
paramNames.equals(that.paramNames) &&
2701+
paramInfos.equals(that.paramInfos) &&
2702+
resType.equals(that.resType) &&
26472703
companion.eq(that.companion)
26482704
case _ =>
26492705
false
26502706
}
26512707

2652-
final override def eql(that: Type) = that match {
2708+
final override def iso(that: Any, bs: BinderPairs) = that match {
26532709
case that: HKLambda =>
2654-
paramNames.equals(that.paramNames) &&
2655-
paramInfos.equals(that.paramInfos) &&
2656-
resType.equals(that.resType) &&
2657-
companion.eq(that.companion)
2710+
paramNames.eqElements(that.paramNames) &&
2711+
companion.eq(that.companion) && {
2712+
val bs1 = bs
2713+
paramInfos.equalElements(that.paramInfos, bs1) &&
2714+
resType.equals(that.resType, bs1)
2715+
}
26582716
case _ =>
26592717
false
26602718
}
26612719
}
26622720

26632721
abstract class MethodOrPoly extends UncachedGroundType with LambdaType with MethodicType {
26642722
final override def hashCode = System.identityHashCode(this)
2665-
final override def equals(other: Any) = this `eq` other.asInstanceOf[AnyRef]
26662723
}
26672724

26682725
trait TermLambda extends LambdaType { thisLambdaType =>
@@ -3116,6 +3173,11 @@ object Types {
31163173

31173174
override def computeHash(bs: Binders) = doHash(bs, tycon, args)
31183175
override def eql(that: Type) = this `eq` that // safe because applied types are hash-consed separately
3176+
3177+
final override def iso(that: Any, bs: BinderPairs) = that match {
3178+
case that: AppliedType => tycon.equals(that.tycon, bs) && args.equalElements(that.args, bs)
3179+
case _ => false
3180+
}
31193181
}
31203182

31213183
final class CachedAppliedType(tycon: Type, args: List[Type], hc: Int) extends AppliedType(tycon, args) {
@@ -3135,8 +3197,6 @@ object Types {
31353197
type BT <: Type
31363198
val binder: BT
31373199
def copyBoundType(bt: BT): Type
3138-
override def identityHash(bs: Binders) =
3139-
if (bs == null) super.identityHash(bs) else ???
31403200
}
31413201

31423202
abstract class ParamRef extends BoundType {
@@ -3152,8 +3212,8 @@ object Types {
31523212

31533213
override def computeHash(bs: Binders) = doHash(bs, paramNum, binder.identityHash(bs))
31543214

3155-
override def equals(that: Any) = that match {
3156-
case that: ParamRef => binder.eq(that.binder) && paramNum == that.paramNum
3215+
override def iso(that: Any, bs: BinderPairs) = that match {
3216+
case that: ParamRef => binder.equalBinder(that.binder, bs) && paramNum == that.paramNum
31573217
case _ => false
31583218
}
31593219

@@ -3209,8 +3269,8 @@ object Types {
32093269
// between RecTypes and RecRefs.
32103270
override def computeHash(bs: Binders) = addDelta(binder.identityHash(bs), 41)
32113271

3212-
override def equals(that: Any) = that match {
3213-
case that: RecThis => binder.eq(that.binder)
3272+
override def iso(that: Any, bs: BinderPairs) = that match {
3273+
case that: RecThis => binder.equalBinder(that.binder, bs)
32143274
case _ => false
32153275
}
32163276

@@ -3229,7 +3289,6 @@ object Types {
32293289
def derivedSkolemType(info: Type)(implicit ctx: Context) =
32303290
if (info eq this.info) this else SkolemType(info)
32313291
override def hashCode: Int = System.identityHashCode(this)
3232-
override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
32333292

32343293
def withName(name: Name): this.type = { myRepr = name; this }
32353294

@@ -3335,7 +3394,6 @@ object Types {
33353394
}
33363395

33373396
override def computeHash(bs: Binders): Int = identityHash(bs)
3338-
override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
33393397

33403398
override def toString = {
33413399
def instStr = if (inst.exists) s" -> $inst" else ""
@@ -3421,6 +3479,16 @@ object Types {
34213479
case _ => false
34223480
}
34233481

3482+
override def iso(that: Any, bs: BinderPairs) = that match {
3483+
case that: ClassInfo =>
3484+
prefix.equals(that.prefix, bs) &&
3485+
cls.eq(that.cls) &&
3486+
classParents.equalElements(that.classParents, bs) &&
3487+
decls.eq(that.decls) &&
3488+
selfInfo.eq(that.selfInfo)
3489+
case _ => false
3490+
}
3491+
34243492
override def toString = s"ClassInfo($prefix, $cls, $classParents)"
34253493
}
34263494

@@ -3494,9 +3562,9 @@ object Types {
34943562

34953563
override def computeHash(bs: Binders) = doHash(bs, lo, hi)
34963564

3497-
override def equals(that: Any): Boolean = that match {
3565+
override def iso(that: Any, bs: BinderPairs): Boolean = that match {
34983566
case that: TypeAlias => false
3499-
case that: TypeBounds => lo == that.lo && hi == that.hi
3567+
case that: TypeBounds => lo.equals(that.lo, bs) && hi.equals(that.hi, bs)
35003568
case _ => false
35013569
}
35023570

@@ -3517,8 +3585,8 @@ object Types {
35173585

35183586
override def computeHash(bs: Binders) = doHash(bs, alias)
35193587

3520-
override def equals(that: Any): Boolean = that match {
3521-
case that: TypeAlias => alias == that.alias
3588+
override def iso(that: Any, bs: BinderPairs): Boolean = that match {
3589+
case that: TypeAlias => alias.equals(that.alias, bs)
35223590
case _ => false
35233591
}
35243592

@@ -3560,6 +3628,11 @@ object Types {
35603628
derivedAnnotatedType(tpe.stripTypeVar, annot)
35613629

35623630
override def stripAnnots(implicit ctx: Context): Type = tpe.stripAnnots
3631+
3632+
override def iso(that: Any, bs: BinderPairs): Boolean = that match {
3633+
case that: AnnotatedType => tpe.equals(that.tpe, bs) && (annot `eq` that.annot)
3634+
case _ => false
3635+
}
35633636
}
35643637

35653638
object AnnotatedType {
@@ -3580,6 +3653,11 @@ object Types {
35803653
case that: JavaArrayType => elemType.eq(that.elemType)
35813654
case _ => false
35823655
}
3656+
3657+
override def iso(that: Any, bs: BinderPairs) = that match {
3658+
case that: JavaArrayType => elemType.equals(that.elemType, bs)
3659+
case _ => false
3660+
}
35833661
}
35843662
final class CachedJavaArrayType(elemType: Type) extends JavaArrayType(elemType)
35853663
object JavaArrayType {
@@ -3643,6 +3721,11 @@ object Types {
36433721
case that: WildcardType => optBounds.eq(that.optBounds)
36443722
case _ => false
36453723
}
3724+
3725+
override def iso(that: Any, bs: BinderPairs) = that match {
3726+
case that: WildcardType => optBounds.equals(that.optBounds, bs)
3727+
case _ => false
3728+
}
36463729
}
36473730

36483731
final class CachedWildcardType(optBounds: Type) extends WildcardType(optBounds)
@@ -4425,4 +4508,12 @@ object Types {
44254508
// ----- Decorator implicits --------------------------------------------
44264509

44274510
implicit def decorateTypeApplications(tpe: Type): TypeApplications = new TypeApplications(tpe)
4511+
4512+
implicit class listEquals(val tps1: List[Type]) extends AnyVal {
4513+
@tailrec def equalElements(tps2: List[Type], bs: BinderPairs): Boolean =
4514+
(tps1 `eq` tps2) || {
4515+
if (tps1.isEmpty) tps2.isEmpty
4516+
else tps2.nonEmpty && tps1.head.equals(tps2.head, bs) && tps1.tail.equalElements(tps2.tail, bs)
4517+
}
4518+
}
44284519
}

compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,12 @@ object ProtoTypes {
118118
if ((name eq this.name) && (memberProto eq this.memberProto) && (compat eq this.compat)) this
119119
else SelectionProto(name, memberProto, compat, privateOK)
120120

121-
override def equals(that: Any): Boolean = that match {
121+
override def iso(that: Any, bs: Hashable.BinderPairs): Boolean = that match {
122122
case that: SelectionProto =>
123-
(name eq that.name) && (memberProto == that.memberProto) && (compat eq that.compat) && (privateOK == that.privateOK)
123+
(name `eq` that.name) &&
124+
memberProto.equals(that.memberProto, bs) &&
125+
(compat `eq` that.compat) &&
126+
(privateOK == that.privateOK)
124127
case _ =>
125128
false
126129
}
@@ -397,9 +400,20 @@ object ProtoTypes {
397400
tt.withType(new TypeVar(tl.paramRefs(n), state, tt, ctx.owner))
398401
}
399402

400-
val added =
401-
if (state.constraint contains tl) tl.newLikeThis(tl.paramNames, tl.paramInfos, tl.resultType)
403+
/** Ensure that `tl` is not already in constraint, make a copy of necessary */
404+
def ensureFresh(tl: TypeLambda): TypeLambda =
405+
if (state.constraint contains tl) {
406+
var paramInfos = tl.paramInfos
407+
if (tl.isInstanceOf[HKLambda]) {
408+
// HKLambdas care hash-consed, need to create an artificial difference by adding
409+
// a LazyRef to a bound.
410+
val TypeBounds(lo, hi) :: pinfos1 = tl.paramInfos
411+
paramInfos = TypeBounds(lo, LazyRef(_ => hi)) :: pinfos1
412+
}
413+
ensureFresh(tl.newLikeThis(tl.paramNames, paramInfos, tl.resultType))
414+
}
402415
else tl
416+
val added = ensureFresh(tl)
403417
val tvars = if (addTypeVars) newTypeVars(added) else Nil
404418
ctx.typeComparer.addToConstraint(added, tvars.tpes.asInstanceOf[List[TypeVar]])
405419
(added, tvars)

0 commit comments

Comments
 (0)