aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
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
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')
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala10
-rw-r--r--src/dotty/tools/dotc/core/Types.scala52
2 files changed, 52 insertions, 10 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index bde325897..df0173467 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -142,7 +142,7 @@ class Definitions(implicit ctx: Context) {
ScalaPackageClass, tpnme.Null, AbstractFinal, List(AnyRefAlias.typeConstructor)).entered
lazy val PredefModule = requiredModule("scala.Predef")
- lazy val NilModule = requiredModule("scala.collection.immutable.Nil")
+ lazy val NilModule = requiredModule("scala.collection.immutable.Nil")
// lazy val FunctionClass: ClassSymbol = requiredClass("scala.Function")
lazy val SingletonClass: ClassSymbol =
@@ -330,7 +330,7 @@ class Definitions(implicit ctx: Context) {
* - v_i are the variances of the bound symbols (i.e. +, -, or empty).
* - _$hk$i are hgiher-kinded parameter names, which are special treated in type application.
*/
- def hkTrait(variances: List[Int]) = {
+ def hkTrait(vcs: List[Int]) = {
def varianceSuffix(v: Int) = v match {
case -1 => "N"
@@ -348,14 +348,14 @@ class Definitions(implicit ctx: Context) {
def complete(denot: SymDenotation): Unit = {
val cls = denot.asClass.classSymbol
val paramDecls = newScope
- for ((v, i) <- variances.zipWithIndex)
+ for ((v, i) <- vcs.zipWithIndex)
newTypeParam(cls, tpnme.higherKindedParamName(i), varianceFlags(v), paramDecls)
denot.info = ClassInfo(ScalaPackageClass.thisType, cls, List(ObjectClass.typeConstructor), paramDecls)
}
}
val traitName =
- tpnme.higherKindedTraitName(variances.length) ++ (variances map varianceSuffix).mkString
+ tpnme.higherKindedTraitName(vcs.length) ++ (vcs map varianceSuffix).mkString
def createTrait = {
val cls = ctx.newClassSymbol(
@@ -367,7 +367,7 @@ class Definitions(implicit ctx: Context) {
cls
}
- hkTraitOfArity.getOrElseUpdate(variances, createTrait)
+ hkTraitOfArity.getOrElseUpdate(vcs, createTrait)
}
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)