Skip to content

Commit f50cb20

Browse files
committed
Make rewritings of hk applications configurable
Beta-reduce only if `Config.simplifyApplications` is true. Turning off beta-reduction revealed two problems which are also fixed in this commit: 1. Bad treatement of higher-kinded argyments in cyclicity checking 2. Wrong variance for higher-kinded arguments in TypeAccumulator
1 parent 1443fd4 commit f50cb20

File tree

4 files changed

+42
-18
lines changed

4 files changed

+42
-18
lines changed

src/dotty/tools/dotc/config/Config.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ object Config {
9898
*/
9999
final val splitProjections = false
100100

101+
/** If this flag is on, always rewrite an application `S[Ts]` where `S` is an alias for
102+
* `[Xs] -> U` to `[Xs := Ts]U`. If this flag is off, the rewriting is only done if `S` is a
103+
* reference to an instantiated parameter. Turning this flag on was observed to
104+
* give a ~6% speedup on the JUnit test suite.
105+
*/
106+
final val simplifyApplications = true
107+
101108
/** Initial size of superId table */
102109
final val InitialSuperIdsSize = 4096
103110

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

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -469,18 +469,21 @@ class TypeApplications(val self: Type) extends AnyVal {
469469
case dealiased: TypeLambda =>
470470
def tryReduce =
471471
if (!args.exists(_.isInstanceOf[TypeBounds])) {
472-
val reduced = dealiased.instantiate(args)
473-
if (dealiased eq stripped) reduced
474-
else reduced match {
475-
case AppliedType(tycon, args) if variancesConform(typParams, tycon.typeParams) =>
476-
// Reducing is safe for type inference, as kind of type constructor does not change
477-
//println(i"reduced: $reduced instead of ${HKApply(self, args)}")
478-
reduced
472+
val followAlias = stripped match {
473+
case stripped: TypeRef =>
474+
stripped.symbol.is(BaseTypeArg)
479475
case _ =>
480-
// Reducing changes kind, keep hk application instead
481-
//println(i"fallback: ${HKApply(self, args)} instead of $reduced")
482-
HKApply(self, args)
476+
Config.simplifyApplications && {
477+
dealiased.resType match {
478+
case AppliedType(tyconBody, _) =>
479+
variancesConform(typParams, tyconBody.typeParams)
480+
// Reducing is safe for type inference, as kind of type constructor does not change
481+
case _ => false
482+
}
483+
}
483484
}
485+
if ((dealiased eq stripped) || followAlias) dealiased.instantiate(args)
486+
else HKApply(self, args)
484487
}
485488
else dealiased.resType match {
486489
case AppliedType(tycon, args1) if tycon.safeDealias ne tycon =>
@@ -665,11 +668,6 @@ class TypeApplications(val self: Type) extends AnyVal {
665668
}
666669
}
667670

668-
final def typeConstructor(implicit ctx: Context): Type = self.stripTypeVar match {
669-
case AppliedType(tycon, _) => tycon
670-
case self => self
671-
}
672-
673671
/** If this is the image of a type argument; recover the type argument,
674672
* otherwise NoType.
675673
*/

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3422,8 +3422,9 @@ object Types {
34223422
case tp: HKApply =>
34233423
def mapArg(arg: Type, tparam: TypeParamInfo): Type = {
34243424
val saved = variance
3425-
if (tparam.paramVariance < 0) variance = -variance
3426-
else if (tparam.paramVariance == 0) variance = 0
3425+
val pvariance = tparam.paramVariance
3426+
if (pvariance < 0) variance = -variance
3427+
else if (pvariance == 0) variance = 0
34273428
try this(arg)
34283429
finally variance = saved
34293430
}
@@ -3629,7 +3630,23 @@ object Types {
36293630
this(x, prefix)
36303631

36313632
case tp @ HKApply(tycon, args) =>
3632-
foldOver(this(x, tycon), args)
3633+
def foldArgs(x: T, tparams: List[TypeParamInfo], args: List[Type]): T =
3634+
if (args.isEmpty) {
3635+
assert(tparams.isEmpty)
3636+
x
3637+
}
3638+
else {
3639+
val tparam = tparams.head
3640+
val saved = variance
3641+
val pvariance = tparam.paramVariance
3642+
if (pvariance < 0) variance = -variance
3643+
else if (pvariance == 0) variance = 0
3644+
val acc =
3645+
try this(x, args.head)
3646+
finally variance = saved
3647+
foldArgs(acc, tparams.tail, args.tail)
3648+
}
3649+
foldArgs(this(x, tycon), tp.typeParams, args)
36333650

36343651
case tp: AndOrType =>
36353652
this(this(x, tp.tp1), tp.tp2)

src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ object Checking {
204204
tp.derivedRefinedType(this(parent), name, this(rinfo, nestedCycleOK, nestedCycleOK))
205205
case tp: RecType =>
206206
tp.rebind(this(tp.parent))
207+
case tp @ HKApply(tycon, args) =>
208+
tp.derivedAppliedType(this(tycon), args.map(this(_, nestedCycleOK, nestedCycleOK)))
207209
case tp @ TypeRef(pre, name) =>
208210
try {
209211
// A prefix is interesting if it might contain (transitively) a reference

0 commit comments

Comments
 (0)