Skip to content

Commit 239fb8f

Browse files
committed
Make ParamRefs unique types.
They were case classes before, but not uniquely hashed. This meant that the hash cons sepcialization for AppliedTypes failed to work in many cases. since ParamRef arguments were not `eq` to each other. Consequently, we got timeouts for compiling stdlib.
1 parent ce5290f commit 239fb8f

File tree

3 files changed

+36
-14
lines changed

3 files changed

+36
-14
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,12 +463,12 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
463463
(poly, entries) <- boundsMap.toList
464464
n <- 0 until paramCount(entries)
465465
if entries(n).exists
466-
} yield TypeParamRef(poly, n)
466+
} yield TypeParamRef.uncached(poly, n)
467467

468468
def forallParams(p: TypeParamRef => Boolean): Boolean = {
469469
boundsMap.foreachBinding { (poly, entries) =>
470470
for (i <- 0 until paramCount(entries))
471-
if (isBounds(entries(i)) && !p(TypeParamRef(poly, i))) return false
471+
if (isBounds(entries(i)) && !p(TypeParamRef.uncached(poly, i))) return false
472472
}
473473
true
474474
}

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

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2634,7 +2634,7 @@ object Types {
26342634
def paramNames: List[ThisName]
26352635
def paramInfos: List[PInfo]
26362636
def resType: Type
2637-
def newParamRef(n: Int): ParamRefType
2637+
def newParamRef(n: Int)(implicit ctx: Context): ParamRefType
26382638

26392639
override def resultType(implicit ctx: Context) = resType
26402640

@@ -2648,7 +2648,12 @@ object Types {
26482648
final def isTypeLambda = isInstanceOf[TypeLambda]
26492649
final def isHigherKinded = isInstanceOf[TypeProxy]
26502650

2651-
lazy val paramRefs: List[ParamRefType] = paramNames.indices.toList.map(newParamRef)
2651+
private var myParamRefs: List[ParamRefType] = null
2652+
2653+
def paramRefs(implicit ctx: Context): List[ParamRefType] = {
2654+
if (myParamRefs == null) myParamRefs = paramNames.indices.toList.map(newParamRef)
2655+
myParamRefs
2656+
}
26522657

26532658
protected def computeSignature(implicit ctx: Context) = resultSignature
26542659

@@ -2809,7 +2814,7 @@ object Types {
28092814
*/
28102815
def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps
28112816

2812-
def newParamRef(n: Int) = TermParamRef(this, n)
2817+
def newParamRef(n: Int)(implicit ctx: Context) = TermParamRef(this, n)
28132818
}
28142819

28152820
abstract case class MethodType(paramNames: List[TermName])(
@@ -2964,7 +2969,7 @@ object Types {
29642969
def isDependent(implicit ctx: Context): Boolean = true
29652970
def isParamDependent(implicit ctx: Context): Boolean = true
29662971

2967-
def newParamRef(n: Int) = TypeParamRef(this, n)
2972+
def newParamRef(n: Int)(implicit ctx: Context) = TypeParamRef(this, n)
29682973

29692974
lazy val typeParams: List[LambdaParam] =
29702975
paramNames.indices.toList.map(new LambdaParam(this, _))
@@ -3122,7 +3127,7 @@ object Types {
31223127
def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = paramInfo
31233128
def paramInfoOrCompleter(implicit ctx: Context): Type = paramInfo
31243129
def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance
3125-
def toArg: Type = TypeParamRef(tl, n)
3130+
def toArg(implicit ctx: Context): Type = TypeParamRef(tl, n)
31263131
def paramRef(implicit ctx: Context): Type = TypeParamRef(tl, n)
31273132
}
31283133

@@ -3336,7 +3341,7 @@ object Types {
33363341
abstract class BoundType extends CachedProxyType with ValueType {
33373342
type BT <: Type
33383343
val binder: BT
3339-
def copyBoundType(bt: BT): Type
3344+
def copyBoundType(bt: BT)(implicit ctx: Context): Type
33403345
}
33413346

33423347
abstract class ParamRef extends BoundType {
@@ -3365,14 +3370,21 @@ object Types {
33653370
}
33663371
}
33673372

3368-
case class TermParamRef(binder: TermLambda, paramNum: Int) extends ParamRef {
3373+
abstract case class TermParamRef(binder: TermLambda, paramNum: Int) extends ParamRef {
33693374
type BT = TermLambda
3370-
def copyBoundType(bt: BT) = TermParamRef(bt, paramNum)
3375+
def copyBoundType(bt: BT)(implicit ctx: Context) = TermParamRef(bt, paramNum)
3376+
}
3377+
3378+
class CachedTermParamRef(binder: TermLambda, paramNum: Int) extends TermParamRef(binder, paramNum)
3379+
3380+
object TermParamRef {
3381+
def apply(binder: TermLambda, paramNum: Int)(implicit ctx: Context) =
3382+
unique(new CachedTermParamRef(binder, paramNum))
33713383
}
33723384

3373-
case class TypeParamRef(binder: TypeLambda, paramNum: Int) extends ParamRef {
3385+
abstract case class TypeParamRef(binder: TypeLambda, paramNum: Int) extends ParamRef {
33743386
type BT = TypeLambda
3375-
def copyBoundType(bt: BT) = TypeParamRef(bt, paramNum)
3387+
def copyBoundType(bt: BT)(implicit ctx: Context) = TypeParamRef(bt, paramNum)
33763388

33773389
/** Looking only at the structure of `bound`, is one of the following true?
33783390
* - fromBelow and param <:< bound
@@ -3388,11 +3400,21 @@ object Types {
33883400
}
33893401
}
33903402

3403+
class ConcreteTypeParamRef(binder: TypeLambda, paramNum: Int) extends TypeParamRef(binder, paramNum)
3404+
3405+
object TypeParamRef {
3406+
def apply(binder: TypeLambda, paramNum: Int)(implicit ctx: Context) =
3407+
unique(new ConcreteTypeParamRef(binder, paramNum))
3408+
3409+
def uncached(binder: TypeLambda, paramNum: Int) =
3410+
new ConcreteTypeParamRef(binder: TypeLambda, paramNum: Int)
3411+
}
3412+
33913413
/** a self-reference to an enclosing recursive type. */
33923414
case class RecThis(binder: RecType) extends BoundType with SingletonType {
33933415
type BT = RecType
33943416
override def underlying(implicit ctx: Context) = binder
3395-
def copyBoundType(bt: BT) = RecThis(bt)
3417+
def copyBoundType(bt: BT)(implicit ctx: Context) = RecThis(bt)
33963418

33973419
// need to customize hashCode and equals to prevent infinite recursion
33983420
// between RecTypes and RecRefs.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
409409
def addTyped(arg: Arg, formal: Type): Type => Type = {
410410
addArg(typedArg(arg, formal), formal)
411411
if (methodType.isParamDependent)
412-
safeSubstParam(_, methodType.paramRefs(n), typeOfArg(arg))
412+
safeSubstParam(_, methodType.paramRefs.apply(n), typeOfArg(arg))
413413
else identity
414414
}
415415

0 commit comments

Comments
 (0)