@@ -301,8 +301,11 @@ object Types {
301
301
}
302
302
303
303
/** Does this type occur as a part of type `that`? */
304
- final def occursIn (that : Type )(implicit ctx : Context ): Boolean =
305
- that existsPart (this == _)
304
+ def occursIn (that : Type )(implicit ctx : Context ): Boolean =
305
+ that.existsPart(this == _)
306
+
307
+ /** Does this type not refer to TypeParamRefs or uninstantiated TypeVars? */
308
+ final def isGround (implicit ctx : Context ): Boolean = true
306
309
307
310
/** Is this a type of a repeated parameter? */
308
311
def isRepeatedParam (implicit ctx : Context ): Boolean =
@@ -3271,6 +3274,17 @@ object Types {
3271
3274
private [this ] var cachedSuper : Type = _
3272
3275
private [this ] var myStableHash : Byte = 0
3273
3276
3277
+ private [this ] var isGroundKnown : Boolean = false
3278
+ private [this ] var isGroundCache : Boolean = _
3279
+
3280
+ def isGround (acc : TypeAccumulator [Boolean ])(implicit ctx : Context ): Boolean = {
3281
+ if (! isGroundKnown) {
3282
+ isGroundCache = acc.foldOver(false , this )
3283
+ isGroundKnown = true
3284
+ }
3285
+ isGroundCache
3286
+ }
3287
+
3274
3288
override def underlying (implicit ctx : Context ): Type = tycon
3275
3289
3276
3290
override def superType (implicit ctx : Context ): Type = {
@@ -3414,6 +3428,11 @@ object Types {
3414
3428
def kindString = " Type"
3415
3429
def copyBoundType (bt : BT ) = bt.paramRefs(paramNum)
3416
3430
3431
+ /** Optimized version of occursIn, avoid quadratic blowup when solving
3432
+ * constraints over large ground types.
3433
+ */
3434
+ override def occursIn (that : Type )(implicit ctx : Context ) = ! that.isGround && super .occursIn(that)
3435
+
3417
3436
/** Looking only at the structure of `bound`, is one of the following true?
3418
3437
* - fromBelow and param <:< bound
3419
3438
* - !fromBelow and param >:> bound
@@ -4777,6 +4796,17 @@ object Types {
4777
4796
}
4778
4797
}
4779
4798
4799
+ class isGroundAccumulator (implicit ctx : Context ) extends TypeAccumulator [Boolean ] {
4800
+ def apply (x : Boolean , tp : Type ) = x || {
4801
+ tp match {
4802
+ case _ : TypeParamRef => false
4803
+ case tp : TypeVar => apply(x, tp.underlying)
4804
+ case tp : AppliedType => tp.isGround(this )
4805
+ case _ => foldOver(x, tp)
4806
+ }
4807
+ }
4808
+ }
4809
+
4780
4810
// ----- Name Filters --------------------------------------------------
4781
4811
4782
4812
/** A name filter selects or discards a member name of a type `pre`.
0 commit comments