aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-06-12 15:53:47 +0200
committerMartin Odersky <odersky@gmail.com>2014-06-12 15:53:54 +0200
commitc2bcf2ec054b3c20b9addd9d1dd6de286de7f6c3 (patch)
tree3879424bc27a0bea89e8f5cb6792e8dcde4a5d5f /src/dotty/tools/dotc
parenta77a4f6d8bd8f9990eac23859c399abb3b93df7c (diff)
downloaddotty-c2bcf2ec054b3c20b9addd9d1dd6de286de7f6c3.tar.gz
dotty-c2bcf2ec054b3c20b9addd9d1dd6de286de7f6c3.tar.bz2
dotty-c2bcf2ec054b3c20b9addd9d1dd6de286de7f6c3.zip
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.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/config/Config.scala7
-rw-r--r--src/dotty/tools/dotc/core/Types.scala17
2 files changed, 21 insertions, 3 deletions
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
}
}