aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-08-06 12:48:28 +0200
committerMartin Odersky <odersky@gmail.com>2013-08-06 12:48:28 +0200
commit2985d1806b66d4bf59807f35a6427b81ef66961e (patch)
tree7564a183711cd993eff378469e37a3ac28c61513 /src/dotty/tools/dotc/core/Types.scala
parent71e59bb45db6f9f8abd8d42041583d56c88fe289 (diff)
downloaddotty-2985d1806b66d4bf59807f35a6427b81ef66961e.tar.gz
dotty-2985d1806b66d4bf59807f35a6427b81ef66961e.tar.bz2
dotty-2985d1806b66d4bf59807f35a6427b81ef66961e.zip
Refined treatment of unapply
Diffstat (limited to 'src/dotty/tools/dotc/core/Types.scala')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala52
1 files changed, 47 insertions, 5 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 07f3f284f..ff0f2e990 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -940,6 +940,31 @@ object Types {
*/
def varianceOf(tp: Type): FlagSet = ???
+ type VarianceMap = Map[TypeVar, Int]
+
+ /** All occurrences of type vars in this type that satisfy predicate
+ * `include` mapped to their variances (-1/0/1) in this type, where
+ * -1 means: only covariant occurrences
+ * +1 means: only covariant occurrences
+ * 0 means: mixed or non-variant occurrences
+ */
+ def variances(include: TypeVar => Boolean)(implicit ctx: Context): VarianceMap = {
+ val accu = new TypeAccumulator[VarianceMap] {
+ def apply(vmap: VarianceMap, t: Type): VarianceMap = t match {
+ case t: TypeVar if include(t) =>
+ vmap get t match {
+ case Some(v) =>
+ if (v == variance) vmap else vmap updated (t, 0)
+ case None =>
+ vmap updated (t, variance)
+ }
+ case _ =>
+ foldOver(vmap, t)
+ }
+ }
+ accu(Map.empty, this)
+ }
+
// ----- hashing ------------------------------------------------------
/** customized hash code of this type.
@@ -2086,6 +2111,8 @@ object Types {
protected def apply(x: T, annot: Annotation): T = x // don't go into annotations
+ protected var variance = 1
+
def foldOver(x: T, tp: Type): T = tp match {
case tp: NamedType =>
this(x, tp.prefix)
@@ -2097,21 +2124,36 @@ object Types {
this(this(x, tp.parent), tp.refinedInfo)
case tp @ MethodType(pnames, ptypes) =>
- this((x /: ptypes)(this), tp.resultType)
+ variance = -variance
+ val y = (x /: ptypes)(this)
+ variance = -variance
+ this(y, tp.resultType)
case ExprType(restpe) =>
this(x, restpe)
case tp @ PolyType(pnames) =>
- this((x /: tp.paramBounds)(this), tp.resultType)
+ variance = -variance
+ val y = (x /: tp.paramBounds)(this)
+ variance = -variance
+ this(y, tp.resultType)
case SuperType(thistp, supertp) =>
this(this(x, thistp), supertp)
case TypeBounds(lo, hi) =>
- if (lo eq hi) this(x, lo)
- else this(this(x, lo), hi)
-
+ if (lo eq hi) {
+ val saved = variance
+ variance = 0
+ try this(x, lo)
+ finally variance = saved
+ }
+ else {
+ variance = -variance
+ val y = this(x, lo)
+ variance = -variance
+ this(y, hi)
+ }
case AnnotatedType(annot, underlying) =>
this(this(x, annot), underlying)