@@ -18,6 +18,7 @@ import Decorators._
18
18
import Denotations ._
19
19
import Periods ._
20
20
import CheckRealizable ._
21
+ import Variances .{Variance , varianceFromInt , varianceToInt }
21
22
import util .Stats ._
22
23
import util .SimpleIdentitySet
23
24
import reporting .diagnostic .Message
@@ -29,7 +30,8 @@ import Hashable._
29
30
import Uniques ._
30
31
import collection .mutable
31
32
import config .Config
32
- import annotation .tailrec
33
+ import annotation .{tailrec , constructorOnly }
34
+
33
35
import language .implicitConversions
34
36
import scala .util .hashing .{ MurmurHash3 => hashing }
35
37
import config .Printers .{core , typr }
@@ -1670,7 +1672,7 @@ object Types {
1670
1672
def computeHash (bs : Binders ): Int
1671
1673
1672
1674
/** Is the `hash` of this type the same for all possible sequences of enclosing binders? */
1673
- def stableHash : Boolean = true
1675
+ def hashIsStable : Boolean = true
1674
1676
}
1675
1677
1676
1678
// end Type
@@ -2331,8 +2333,8 @@ object Types {
2331
2333
2332
2334
override def computeHash (bs : Binders ): Int = doHash(bs, designator, prefix)
2333
2335
2334
- override def stableHash : Boolean = {
2335
- if (myStableHash == 0 ) myStableHash = if (prefix.stableHash ) 1 else - 1
2336
+ override def hashIsStable : Boolean = {
2337
+ if (myStableHash == 0 ) myStableHash = if (prefix.hashIsStable ) 1 else - 1
2336
2338
myStableHash > 0
2337
2339
}
2338
2340
@@ -2616,7 +2618,7 @@ object Types {
2616
2618
else parent
2617
2619
2618
2620
override def computeHash (bs : Binders ): Int = doHash(bs, refinedName, refinedInfo, parent)
2619
- override def stableHash : Boolean = refinedInfo.stableHash && parent.stableHash
2621
+ override def hashIsStable : Boolean = refinedInfo.hashIsStable && parent.hashIsStable
2620
2622
2621
2623
override def eql (that : Type ): Boolean = that match {
2622
2624
case that : RefinedType =>
@@ -2717,7 +2719,7 @@ object Types {
2717
2719
2718
2720
override def computeHash (bs : Binders ): Int = doHash(new Binders (this , bs), parent)
2719
2721
2720
- override def stableHash : Boolean = false
2722
+ override def hashIsStable : Boolean = false
2721
2723
// this is a conservative observation. By construction RecTypes contain at least
2722
2724
// one RecThis occurrence. Since `stableHash` does not keep track of enclosing
2723
2725
// bound types, it will return "unstable" for this occurrence and this would propagate.
@@ -3025,7 +3027,7 @@ object Types {
3025
3027
if (resType eq this .resType) this else ExprType (resType)
3026
3028
3027
3029
override def computeHash (bs : Binders ): Int = doHash(bs, resType)
3028
- override def stableHash : Boolean = resType.stableHash
3030
+ override def hashIsStable : Boolean = resType.hashIsStable
3029
3031
3030
3032
override def eql (that : Type ): Boolean = that match {
3031
3033
case that : ExprType => resType.eq(that.resType)
@@ -3110,38 +3112,19 @@ object Types {
3110
3112
if ((paramNames eq this .paramNames) && (paramInfos eq this .paramInfos) && (resType eq this .resType)) this
3111
3113
else newLikeThis(paramNames, paramInfos, resType)
3112
3114
3113
- final def newLikeThis (paramNames : List [ThisName ], paramInfos : List [PInfo ], resType : Type )(implicit ctx : Context ): This =
3115
+ def newLikeThis (paramNames : List [ThisName ], paramInfos : List [PInfo ], resType : Type )(implicit ctx : Context ): This =
3114
3116
companion(paramNames)(
3115
3117
x => paramInfos.mapConserve(_.subst(this , x).asInstanceOf [PInfo ]),
3116
3118
x => resType.subst(this , x))
3117
3119
3118
3120
protected def prefixString : String
3119
- final override def toString : String = s " $prefixString( $paramNames, $paramInfos, $resType) "
3121
+ override def toString : String = s " $prefixString( $paramNames, $paramInfos, $resType) "
3120
3122
}
3121
3123
3122
3124
abstract class HKLambda extends CachedProxyType with LambdaType {
3123
3125
final override def underlying (implicit ctx : Context ): Type = resType
3124
-
3125
- override def computeHash (bs : Binders ): Int =
3126
- doHash(new Binders (this , bs), paramNames, resType, paramInfos)
3127
-
3128
- override def stableHash : Boolean = resType.stableHash && paramInfos.stableHash
3129
-
3126
+ final override def hashIsStable : Boolean = resType.hashIsStable && paramInfos.hashIsStable
3130
3127
final override def equals (that : Any ): Boolean = equals(that, null )
3131
-
3132
- // No definition of `eql` --> fall back on equals, which calls iso
3133
-
3134
- final override def iso (that : Any , bs : BinderPairs ): Boolean = that match {
3135
- case that : HKLambda =>
3136
- paramNames.eqElements(that.paramNames) &&
3137
- companion.eq(that.companion) && {
3138
- val bs1 = new BinderPairs (this , that, bs)
3139
- paramInfos.equalElements(that.paramInfos, bs1) &&
3140
- resType.equals(that.resType, bs1)
3141
- }
3142
- case _ =>
3143
- false
3144
- }
3145
3128
}
3146
3129
3147
3130
abstract class MethodOrPoly extends UncachedGroundType with LambdaType with MethodicType {
@@ -3430,8 +3413,12 @@ object Types {
3430
3413
3431
3414
def newParamRef (n : Int ): TypeParamRef = new TypeParamRefImpl (this , n)
3432
3415
3433
- @ threadUnsafe lazy val typeParams : List [LambdaParam ] =
3434
- paramNames.indices.toList.map(new LambdaParam (this , _))
3416
+ protected var myTypeParams : List [LambdaParam ] = null
3417
+
3418
+ def typeParams : List [LambdaParam ] =
3419
+ if myTypeParams == null then
3420
+ myTypeParams = paramNames.indices.toList.map(new LambdaParam (this , _))
3421
+ myTypeParams
3435
3422
3436
3423
def derivedLambdaAbstraction (paramNames : List [TypeName ], paramInfos : List [TypeBounds ], resType : Type )(implicit ctx : Context ): Type =
3437
3424
resType match {
@@ -3457,7 +3444,7 @@ object Types {
3457
3444
* @param resultTypeExp A function that, given the polytype itself, returns the
3458
3445
* result type `T`.
3459
3446
*/
3460
- class HKTypeLambda (val paramNames : List [TypeName ])(
3447
+ class HKTypeLambda (val paramNames : List [TypeName ], @ constructorOnly variances : List [ Variance ] )(
3461
3448
paramInfosExp : HKTypeLambda => List [TypeBounds ], resultTypeExp : HKTypeLambda => Type )
3462
3449
extends HKLambda with TypeLambda {
3463
3450
type This = HKTypeLambda
@@ -3469,7 +3456,49 @@ object Types {
3469
3456
assert(resType.isInstanceOf [TermType ], this )
3470
3457
assert(paramNames.nonEmpty)
3471
3458
3459
+ private def setVariances (tparams : List [LambdaParam ], vs : List [Variance ]): Unit =
3460
+ if tparams.nonEmpty then
3461
+ tparams.head.setVariance(vs.head)
3462
+ setVariances(tparams.tail, vs.tail)
3463
+
3464
+ val isVariant = variances.nonEmpty
3465
+ if isVariant then setVariances(typeParams, variances)
3466
+
3467
+ def givenVariances =
3468
+ if isVariant then typeParams.map(_.paramVariance)
3469
+ else Nil
3470
+
3471
+ override def computeHash (bs : Binders ): Int =
3472
+ doHash(new Binders (this , bs), givenVariances ::: paramNames, resType, paramInfos)
3473
+
3474
+ // No definition of `eql` --> fall back on equals, which calls iso
3475
+
3476
+ final override def iso (that : Any , bs : BinderPairs ): Boolean = that match {
3477
+ case that : HKTypeLambda =>
3478
+ paramNames.eqElements(that.paramNames)
3479
+ && isVariant == that.isVariant
3480
+ && (! isVariant
3481
+ || typeParams.corresponds(that.typeParams)((x, y) =>
3482
+ x.paramVariance == y.paramVariance))
3483
+ && {
3484
+ val bs1 = new BinderPairs (this , that, bs)
3485
+ paramInfos.equalElements(that.paramInfos, bs1) &&
3486
+ resType.equals(that.resType, bs1)
3487
+ }
3488
+ case _ =>
3489
+ false
3490
+ }
3491
+
3492
+ override def newLikeThis (paramNames : List [ThisName ], paramInfos : List [PInfo ], resType : Type )(implicit ctx : Context ): This =
3493
+ HKTypeLambda (paramNames, givenVariances)(
3494
+ x => paramInfos.mapConserve(_.subst(this , x).asInstanceOf [PInfo ]),
3495
+ x => resType.subst(this , x))
3496
+
3472
3497
protected def prefixString : String = " HKTypeLambda"
3498
+ final override def toString : String =
3499
+ if isVariant then
3500
+ s " HKTypeLambda( $paramNames, $paramInfos, $resType, ${givenVariances.map(_.flagsString)}) "
3501
+ else super .toString
3473
3502
}
3474
3503
3475
3504
/** The type of a polymorphic method. It has the same form as HKTypeLambda,
@@ -3519,7 +3548,12 @@ object Types {
3519
3548
def apply (paramNames : List [TypeName ])(
3520
3549
paramInfosExp : HKTypeLambda => List [TypeBounds ],
3521
3550
resultTypeExp : HKTypeLambda => Type )(implicit ctx : Context ): HKTypeLambda =
3522
- unique(new HKTypeLambda (paramNames)(paramInfosExp, resultTypeExp))
3551
+ apply(paramNames, Nil )(paramInfosExp, resultTypeExp)
3552
+
3553
+ def apply (paramNames : List [TypeName ], variances : List [Variance ])(
3554
+ paramInfosExp : HKTypeLambda => List [TypeBounds ],
3555
+ resultTypeExp : HKTypeLambda => Type )(implicit ctx : Context ): HKTypeLambda =
3556
+ unique(new HKTypeLambda (paramNames, variances)(paramInfosExp, resultTypeExp))
3523
3557
3524
3558
def unapply (tl : HKTypeLambda ): Some [(List [LambdaParam ], Type )] =
3525
3559
Some ((tl.typeParams, tl.resType))
@@ -3580,13 +3614,21 @@ object Types {
3580
3614
/** The parameter of a type lambda */
3581
3615
case class LambdaParam (tl : TypeLambda , n : Int ) extends ParamInfo {
3582
3616
type ThisName = TypeName
3617
+
3583
3618
def isTypeParam (implicit ctx : Context ): Boolean = tl.paramNames.head.isTypeName
3584
3619
def paramName (implicit ctx : Context ): tl.ThisName = tl.paramNames(n)
3585
3620
def paramInfo (implicit ctx : Context ): tl.PInfo = tl.paramInfos(n)
3586
3621
def paramInfoAsSeenFrom (pre : Type )(implicit ctx : Context ): tl.PInfo = paramInfo
3587
3622
def paramInfoOrCompleter (implicit ctx : Context ): Type = paramInfo
3588
3623
def paramVarianceSign (implicit ctx : Context ): Int = tl.paramNames(n).variance
3589
3624
def paramRef (implicit ctx : Context ): Type = tl.paramRefs(n)
3625
+
3626
+ private var myVariance : FlagSet = UndefinedFlags
3627
+ def setVariance (v : Variance ): Unit = myVariance = v
3628
+ def paramVariance : Variance =
3629
+ if myVariance == UndefinedFlags then
3630
+ myVariance = varianceFromInt(tl.paramNames(n).variance)
3631
+ myVariance
3590
3632
}
3591
3633
3592
3634
/** A type application `C[T_1, ..., T_n]` */
@@ -3758,8 +3800,8 @@ object Types {
3758
3800
3759
3801
override def computeHash (bs : Binders ): Int = doHash(bs, tycon, args)
3760
3802
3761
- override def stableHash : Boolean = {
3762
- if (myStableHash == 0 ) myStableHash = if (tycon.stableHash && args.stableHash ) 1 else - 1
3803
+ override def hashIsStable : Boolean = {
3804
+ if (myStableHash == 0 ) myStableHash = if (tycon.hashIsStable && args.hashIsStable ) 1 else - 1
3763
3805
myStableHash > 0
3764
3806
}
3765
3807
@@ -3790,7 +3832,7 @@ object Types {
3790
3832
type BT <: Type
3791
3833
val binder : BT
3792
3834
def copyBoundType (bt : BT ): Type
3793
- override def stableHash : Boolean = false
3835
+ override def hashIsStable : Boolean = false
3794
3836
}
3795
3837
3796
3838
abstract class ParamRef extends BoundType {
@@ -4193,7 +4235,7 @@ object Types {
4193
4235
else ClassInfo (prefix, cls, classParents, decls, selfInfo)
4194
4236
4195
4237
override def computeHash (bs : Binders ): Int = doHash(bs, cls, prefix)
4196
- override def stableHash : Boolean = prefix.stableHash && classParents.stableHash
4238
+ override def hashIsStable : Boolean = prefix.hashIsStable && classParents.hashIsStable
4197
4239
4198
4240
override def eql (that : Type ): Boolean = that match {
4199
4241
case that : ClassInfo =>
@@ -4290,7 +4332,7 @@ object Types {
4290
4332
}
4291
4333
4292
4334
override def computeHash (bs : Binders ): Int = doHash(bs, lo, hi)
4293
- override def stableHash : Boolean = lo.stableHash && hi.stableHash
4335
+ override def hashIsStable : Boolean = lo.hashIsStable && hi.hashIsStable
4294
4336
4295
4337
override def equals (that : Any ): Boolean = equals(that, null )
4296
4338
@@ -4315,7 +4357,7 @@ object Types {
4315
4357
def derivedAlias (alias : Type )(implicit ctx : Context ): AliasingBounds
4316
4358
4317
4359
override def computeHash (bs : Binders ): Int = doHash(bs, alias)
4318
- override def stableHash : Boolean = alias.stableHash
4360
+ override def hashIsStable : Boolean = alias.hashIsStable
4319
4361
4320
4362
override def iso (that : Any , bs : BinderPairs ): Boolean = that match {
4321
4363
case that : AliasingBounds => this .isTypeAlias == that.isTypeAlias && alias.equals(that.alias, bs)
@@ -4416,7 +4458,7 @@ object Types {
4416
4458
if (elemtp eq this .elemType) this else JavaArrayType (elemtp)
4417
4459
4418
4460
override def computeHash (bs : Binders ): Int = doHash(bs, elemType)
4419
- override def stableHash : Boolean = elemType.stableHash
4461
+ override def hashIsStable : Boolean = elemType.hashIsStable
4420
4462
4421
4463
override def eql (that : Type ): Boolean = that match {
4422
4464
case that : JavaArrayType => elemType.eq(that.elemType)
@@ -4479,7 +4521,7 @@ object Types {
4479
4521
else WildcardType (optBounds.asInstanceOf [TypeBounds ])
4480
4522
4481
4523
override def computeHash (bs : Binders ): Int = doHash(bs, optBounds)
4482
- override def stableHash : Boolean = optBounds.stableHash
4524
+ override def hashIsStable : Boolean = optBounds.hashIsStable
4483
4525
4484
4526
override def eql (that : Type ): Boolean = that match {
4485
4527
case that : WildcardType => optBounds.eq(that.optBounds)
@@ -5386,8 +5428,8 @@ object Types {
5386
5428
implicit def decorateTypeApplications (tpe : Type ): TypeApplications = new TypeApplications (tpe)
5387
5429
5388
5430
implicit class typeListDeco (val tps1 : List [Type ]) extends AnyVal {
5389
- @ tailrec def stableHash : Boolean =
5390
- tps1.isEmpty || tps1.head.stableHash && tps1.tail.stableHash
5431
+ @ tailrec def hashIsStable : Boolean =
5432
+ tps1.isEmpty || tps1.head.hashIsStable && tps1.tail.hashIsStable
5391
5433
@ tailrec def equalElements (tps2 : List [Type ], bs : BinderPairs ): Boolean =
5392
5434
(tps1 `eq` tps2) || {
5393
5435
if (tps1.isEmpty) tps2.isEmpty
0 commit comments