Skip to content

Commit c2bcf2e

Browse files
committed
Optionally check variance of Lambda classes.
Make sure that Lambda Arg refinements have the same variance as the Lambda classes they instantiate. Controlled by a Config parameter.
1 parent a77a4f6 commit c2bcf2e

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ object Config {
2727
/** Show subtype traces for all deep subtype recursions */
2828
final val traceDeepSubTypeRecursions = false
2929

30-
final val verboseExplainSubtype = true
30+
final val verboseExplainSubtype = false
3131

3232
/** When set, use new signature-based matching.
3333
* Advantantage of doing so: It's supposed to be faster
@@ -43,4 +43,9 @@ object Config {
4343
* for large constraints.
4444
*/
4545
final val trackConstrDeps = true
46+
47+
/** Check that variances of lambda arguments match the
48+
* variance of the underlying lambda class.
49+
*/
50+
final val checkLambdaVariance = false
4651
}

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,19 @@ object Types {
14201420

14211421
override def underlying(implicit ctx: Context) = parent
14221422

1423+
private def checkInst(implicit ctx: Context): this.type = {
1424+
if (Config.checkLambdaVariance)
1425+
refinedInfo match {
1426+
case refinedInfo: TypeBounds if refinedInfo.variance != 0 && refinedName.isLambdaArgName =>
1427+
val cls = parent.LambdaClass(forcing = false)
1428+
if (cls.exists)
1429+
assert(refinedInfo.variance == cls.typeParams.apply(refinedName.lambdaArgIndex).variance,
1430+
s"variance mismatch for $this, $cls, ${cls.typeParams}, ${cls.typeParams.apply(refinedName.lambdaArgIndex).variance}, ${refinedInfo.variance}")
1431+
case _ =>
1432+
}
1433+
this
1434+
}
1435+
14231436
/** Derived refined type, with a twist: A refinement with a higher-kinded type param placeholder
14241437
* is transformed to a refinement of the original type parameter if that one exists.
14251438
*/
@@ -1476,10 +1489,10 @@ object Types {
14761489
else make(RefinedType(parent, names.head, infoFns.head), names.tail, infoFns.tail)
14771490

14781491
def apply(parent: Type, name: Name, infoFn: RefinedType => Type)(implicit ctx: Context): RefinedType =
1479-
ctx.base.uniqueRefinedTypes.enterIfNew(new CachedRefinedType(parent, name, infoFn))
1492+
ctx.base.uniqueRefinedTypes.enterIfNew(new CachedRefinedType(parent, name, infoFn)).checkInst
14801493

14811494
def apply(parent: Type, name: Name, info: Type)(implicit ctx: Context): RefinedType = {
1482-
ctx.base.uniqueRefinedTypes.enterIfNew(parent, name, info)
1495+
ctx.base.uniqueRefinedTypes.enterIfNew(parent, name, info).checkInst
14831496
}
14841497
}
14851498

0 commit comments

Comments
 (0)