From c2bcf2ec054b3c20b9addd9d1dd6de286de7f6c3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 12 Jun 2014 15:53:47 +0200 Subject: 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. --- src/dotty/tools/dotc/config/Config.scala | 7 ++++++- src/dotty/tools/dotc/core/Types.scala | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'src/dotty/tools/dotc') diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala index c247699da..906d17380 100644 --- a/src/dotty/tools/dotc/config/Config.scala +++ b/src/dotty/tools/dotc/config/Config.scala @@ -27,7 +27,7 @@ object Config { /** Show subtype traces for all deep subtype recursions */ final val traceDeepSubTypeRecursions = false - final val verboseExplainSubtype = true + final val verboseExplainSubtype = false /** When set, use new signature-based matching. * Advantantage of doing so: It's supposed to be faster @@ -43,4 +43,9 @@ object Config { * for large constraints. */ final val trackConstrDeps = true + + /** Check that variances of lambda arguments match the + * variance of the underlying lambda class. + */ + final val checkLambdaVariance = false } \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index dda5134c1..24586f412 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1420,6 +1420,19 @@ object Types { override def underlying(implicit ctx: Context) = parent + private def checkInst(implicit ctx: Context): this.type = { + if (Config.checkLambdaVariance) + refinedInfo match { + case refinedInfo: TypeBounds if refinedInfo.variance != 0 && refinedName.isLambdaArgName => + val cls = parent.LambdaClass(forcing = false) + if (cls.exists) + assert(refinedInfo.variance == cls.typeParams.apply(refinedName.lambdaArgIndex).variance, + s"variance mismatch for $this, $cls, ${cls.typeParams}, ${cls.typeParams.apply(refinedName.lambdaArgIndex).variance}, ${refinedInfo.variance}") + case _ => + } + this + } + /** Derived refined type, with a twist: A refinement with a higher-kinded type param placeholder * is transformed to a refinement of the original type parameter if that one exists. */ @@ -1476,10 +1489,10 @@ object Types { else make(RefinedType(parent, names.head, infoFns.head), names.tail, infoFns.tail) def apply(parent: Type, name: Name, infoFn: RefinedType => Type)(implicit ctx: Context): RefinedType = - ctx.base.uniqueRefinedTypes.enterIfNew(new CachedRefinedType(parent, name, infoFn)) + ctx.base.uniqueRefinedTypes.enterIfNew(new CachedRefinedType(parent, name, infoFn)).checkInst def apply(parent: Type, name: Name, info: Type)(implicit ctx: Context): RefinedType = { - ctx.base.uniqueRefinedTypes.enterIfNew(parent, name, info) + ctx.base.uniqueRefinedTypes.enterIfNew(parent, name, info).checkInst } } -- cgit v1.2.3