diff options
author | Paul Phillips <paulp@improving.org> | 2012-12-31 12:38:13 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-01-09 12:11:13 -0800 |
commit | 57aa63bf5e30784877c370b5d1525592943d560f (patch) | |
tree | c90ca6d00e211d26aba1d1b6360fd915914de198 /src/reflect/scala/reflect/internal/Variances.scala | |
parent | 91d8584fde15140972f7d6037d632bc24fc50f94 (diff) | |
download | scala-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.scala | 74 |
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 */ |