summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Variances.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-12-31 12:38:13 -0800
committerPaul Phillips <paulp@improving.org>2013-01-09 12:11:13 -0800
commit57aa63bf5e30784877c370b5d1525592943d560f (patch)
treec90ca6d00e211d26aba1d1b6360fd915914de198 /src/reflect/scala/reflect/internal/Variances.scala
parent91d8584fde15140972f7d6037d632bc24fc50f94 (diff)
downloadscala-57aa63bf5e30784877c370b5d1525592943d560f.tar.gz
scala-57aa63bf5e30784877c370b5d1525592943d560f.tar.bz2
scala-57aa63bf5e30784877c370b5d1525592943d560f.zip
Moved VariantTypeMap into Variances.
Diffstat (limited to 'src/reflect/scala/reflect/internal/Variances.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Variances.scala74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala
index 6560f088c5..a619d7bef7 100644
--- a/src/reflect/scala/reflect/internal/Variances.scala
+++ b/src/reflect/scala/reflect/internal/Variances.scala
@@ -14,6 +14,80 @@ import scala.collection.{ mutable, immutable }
trait Variances {
self: SymbolTable =>
+ /** Used by ExistentialExtrapolation and adaptConstrPattern().
+ * TODO - eliminate duplication with all the rest.
+ */
+ trait VariantTypeMap extends TypeMap {
+ private[this] var _variance: Variance = Covariant
+
+ override def variance = _variance
+ def variance_=(x: Variance) = _variance = x
+
+ override protected def noChangeToSymbols(origSyms: List[Symbol]) =
+ //OPT inline from forall to save on #closures
+ origSyms match {
+ case sym :: rest =>
+ val v = variance
+ if (sym.isAliasType) variance = Invariant
+ val result = this(sym.info)
+ variance = v
+ (result eq sym.info) && noChangeToSymbols(rest)
+ case _ =>
+ true
+ }
+
+ override protected def mapOverArgs(args: List[Type], tparams: List[Symbol]): List[Type] =
+ map2Conserve(args, tparams) { (arg, tparam) =>
+ val v = variance
+ if (tparam.isContravariant) variance = variance.flip
+ else if (!tparam.isCovariant) variance = Invariant
+ val arg1 = this(arg)
+ variance = v
+ arg1
+ }
+
+ /** Map this function over given type */
+ override def mapOver(tp: Type): Type = tp match {
+ case MethodType(params, result) =>
+ variance = variance.flip
+ val params1 = mapOver(params)
+ variance = variance.flip
+ val result1 = this(result)
+ if ((params1 eq params) && (result1 eq result)) tp
+ else copyMethodType(tp, params1, result1.substSym(params, params1))
+ case PolyType(tparams, result) =>
+ variance = variance.flip
+ val tparams1 = mapOver(tparams)
+ variance = variance.flip
+ val result1 = this(result)
+ if ((tparams1 eq tparams) && (result1 eq result)) tp
+ else PolyType(tparams1, result1.substSym(tparams, tparams1))
+ case TypeBounds(lo, hi) =>
+ variance = variance.flip
+ val lo1 = this(lo)
+ variance = variance.flip
+ val hi1 = this(hi)
+ if ((lo1 eq lo) && (hi1 eq hi)) tp
+ else TypeBounds(lo1, hi1)
+ case tr @ TypeRef(pre, sym, args) =>
+ val pre1 = this(pre)
+ val args1 =
+ if (args.isEmpty)
+ args
+ else if (variance.isInvariant) // fast & safe path: don't need to look at typeparams
+ args mapConserve this
+ else {
+ val tparams = sym.typeParams
+ if (tparams.isEmpty) args
+ else mapOverArgs(args, tparams)
+ }
+ if ((pre1 eq pre) && (args1 eq args)) tp
+ else copyTypeRef(tp, pre1, tr.coevolveSym(pre1), args1)
+ case _ =>
+ super.mapOver(tp)
+ }
+ }
+
/** Used in Refchecks.
* TODO - eliminate duplication with varianceInType
*/