Skip to content

Commit d5975dc

Browse files
committed
Generaize canWiden to classBounds
This gives us a cheap way to bound the search of all baseclasses in testLifted.
1 parent 17f1c5f commit d5975dc

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -515,26 +515,28 @@ class TypeApplications(val self: Type) extends AnyVal {
515515
self.appliedTo(tparams map (_.typeRef)).LambdaAbstract(tparams)
516516
}
517517

518-
/** Test whether this type if od the form `B[T1, ..., Tn]`, or,
519-
* if `canWiden` if true, has a base type of the form `B[T1, ..., Bn]` where the type parameters
520-
* of `B` match one-by-one the variances of `tparams`, and where the lambda
521-
* abstracted type
518+
/** Test whether this type has a base type of the form `B[T1, ..., Bn]` where
519+
* the type parameters of `B` match one-by-one the variances of `tparams`,
520+
* and where the lambda abstracted type
522521
*
523522
* LambdaXYZ { type Apply = B[$hkArg$0, ..., $hkArg$n] }
524523
* { type $hkArg$0 = T1; ...; type $hkArg$n = Tn }
525524
*
526525
* satisfies predicate `p`. Try base types in the order of their occurrence in `baseClasses`.
527526
* A type parameter matches a variance V if it has V as its variance or if V == 0.
527+
* @param classBounds A hint to bound the search. Only types that derive from one of the
528+
* classes in classBounds are considered.
528529
*/
529-
def testLifted(tparams: List[Symbol], p: Type => Boolean, canWiden: Boolean)(implicit ctx: Context): Boolean = {
530+
def testLifted(tparams: List[Symbol], p: Type => Boolean, classBounds: List[ClassSymbol])(implicit ctx: Context): Boolean = {
530531
def tryLift(bcs: List[ClassSymbol]): Boolean = bcs match {
531532
case bc :: bcs1 =>
532533
val tp = self.baseTypeWithArgs(bc)
533534
val targs = tp.argInfos
534535
val tycon = tp.withoutArgs(targs)
535536
def variancesMatch(param1: Symbol, param2: Symbol) =
536537
param2.variance == param2.variance || param2.variance == 0
537-
if ((tycon.typeParams corresponds tparams)(variancesMatch)) {
538+
if (classBounds.exists(tycon.derivesFrom(_)) &&
539+
tycon.typeParams.corresponds(tparams)(variancesMatch)) {
538540
val expanded = tycon.EtaExpand
539541
val lifted = (expanded /: targs) { (partialInst, targ) =>
540542
val tparam = partialInst.typeParams.head
@@ -549,7 +551,7 @@ class TypeApplications(val self: Type) extends AnyVal {
549551
false
550552
}
551553
if (tparams.isEmpty) false
552-
else if (typeParams.nonEmpty) p(EtaExpand) || canWiden && tryLift(self.baseClasses)
553-
else canWiden && tryLift(self.baseClasses)
554+
else if (typeParams.nonEmpty) p(EtaExpand) || classBounds.nonEmpty && tryLift(self.baseClasses)
555+
else classBounds.nonEmpty && tryLift(self.baseClasses)
554556
}
555557
}

src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
345345
|| fourthTry(tp1, tp2)
346346
)
347347
normalPath ||
348-
needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2), canWiden = true)
348+
needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2), classBounds(tp2))
349349
}
350350
else // fast path, in particular for refinements resulting from parameterization.
351351
isSubType(tp1, skipped2) &&
@@ -453,7 +453,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
453453
isNewSubType(tp1.underlying.widenExpr, tp2) || comparePaths
454454
case tp1: RefinedType =>
455455
isNewSubType(tp1.parent, tp2) ||
456-
needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _), canWiden = false)
456+
needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _), Nil)
457457
case AndType(tp11, tp12) =>
458458
eitherIsSubType(tp11, tp2, tp12, tp2)
459459
case JavaArrayType(elem1) =>
@@ -476,9 +476,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
476476
lambda.exists && !other.isLambda &&
477477
other.testLifted(lambda.typeParams,
478478
if (inOrder) isSubType(projection.prefix, _) else isSubType(_, projection.prefix),
479-
canWiden = !inOrder)
479+
if (inOrder) Nil else classBounds(projection.prefix))
480480
}
481481

482+
/** The class symbols bounding the type of the `Apply` member of `tp` */
483+
private def classBounds(tp: Type) = tp.member(tpnme.Apply).info.classSymbols
484+
482485
/** Returns true iff either `tp11 <:< tp21` or `tp12 <:< tp22`, trying at the same time
483486
* to keep the constraint as wide as possible. Specifically, if
484487
*

0 commit comments

Comments
 (0)