aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-10-09 12:36:43 +0200
committerMartin Odersky <odersky@gmail.com>2013-10-09 12:36:43 +0200
commit0fc19e0e1ef7b56f9ca0649fde35765892cf1a53 (patch)
treed037ee483a3c89218acf35983006dd8bc4336b46 /src/dotty/tools/dotc/core/Types.scala
parent16c1ddd3bb86c61890418b8394d44486e7bbd9dd (diff)
downloaddotty-0fc19e0e1ef7b56f9ca0649fde35765892cf1a53.tar.gz
dotty-0fc19e0e1ef7b56f9ca0649fde35765892cf1a53.tar.bz2
dotty-0fc19e0e1ef7b56f9ca0649fde35765892cf1a53.zip
Cleanup of new scheme for handling local type parameters and type members.
If a type parameter or local type member is co/contravariant, its instantiation is a special alias type that remembers the variance. These alias types can be refined with subtypes in subclasses and intersection and union translate to their bounds.
Diffstat (limited to 'src/dotty/tools/dotc/core/Types.scala')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala56
1 files changed, 36 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 978c39cc9..b5cd8c3ee 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -843,9 +843,9 @@ object Types {
*/
final def toBounds(tparam: Symbol)(implicit ctx: Context): TypeBounds = {
val v = tparam.variance
- if (v > 0) TypeBounds.upper(this)
- else if (v < 0) TypeBounds.lower(this)
- else TypeAlias(this)
+ if (v > 0 && !(tparam is Local)) TypeBounds.upper(this)
+ else if (v < 0 && !(tparam is Local)) TypeBounds.lower(this)
+ else TypeAlias(this, v)
}
/** The type arguments of the base type instance wrt `base` of this type */
@@ -893,11 +893,13 @@ object Types {
*/
final def argType(tparam: Symbol)(implicit ctx: Context): Type = this match {
case TypeBounds(lo, hi) =>
- val v = tparam.variance
- if (v > 0 && (lo isRef defn.NothingClass)) hi
- else if (v < 0 && (hi isRef defn.AnyClass)) lo
- else if (v == 0 && (lo eq hi)) lo
- else NoType
+ if (lo eq hi) hi
+ else {
+ val v = tparam.variance
+ if (v > 0 && (lo isRef defn.NothingClass)) hi
+ else if (v < 0 && (hi isRef defn.AnyClass)) lo
+ else NoType
+ }
case _ =>
NoType
}
@@ -1978,31 +1980,34 @@ object Types {
assert(lo.isInstanceOf[TermType], lo+" "+lo.getClass)
assert(hi.isInstanceOf[TermType], hi+" "+hi.getClass)
+ def variance: Int = 0
+
override def underlying(implicit ctx: Context): Type = hi
- def derivedTypeBounds(lo: Type, hi: Type)(implicit ctx: Context) =
- if ((lo eq this.lo) && (hi eq this.hi)) this
- else TypeBounds(lo, hi)
+ def derivedTypeBounds(lo: Type, hi: Type, variance: Int = this.variance)(implicit ctx: Context) =
+ if ((lo eq this.lo) && (hi eq this.hi) && (variance == this.variance)) this
+ else TypeBounds(lo, hi, variance)
def contains(tp: Type)(implicit ctx: Context) = lo <:< tp && tp <:< hi
def &(that: TypeBounds)(implicit ctx: Context): TypeBounds =
- derivedTypeBounds(this.lo | that.lo, this.hi & that.hi)
+ derivedTypeBounds(this.lo | that.lo, this.hi & that.hi, (this.variance + that.variance) / 2)
def | (that: TypeBounds)(implicit ctx: Context): TypeBounds =
- derivedTypeBounds(this.lo & that.lo, this.hi | that.hi)
+ derivedTypeBounds(this.lo & that.lo, this.hi | that.hi, (this.variance + that.variance) / 2)
override def & (that: Type)(implicit ctx: Context) = that match {
case that: TypeBounds => this & that
- case that: ClassInfo => this & that.bounds
+ case _ => super.& (that)
}
override def | (that: Type)(implicit ctx: Context) = that match {
case that: TypeBounds => this | that
+ case _ => super.| (that)
}
def map(f: Type => Type)(implicit ctx: Context): TypeBounds =
- TypeBounds(f(lo), f(hi))
+ derivedTypeBounds(f(lo), f(hi))
/** Given a higher-kinded abstract type
*
@@ -2051,17 +2056,28 @@ object Types {
}
final class CachedTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi)
+ final class CoTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi) {
+ override def variance = 1
+ }
+ final class ContraTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi) {
+ override def variance = -1
+ }
object TypeBounds {
def empty(implicit ctx: Context) = apply(defn.NothingType, defn.AnyType)
- def upper(hi: Type)(implicit ctx: Context) = apply(defn.NothingType, hi)
- def lower(lo: Type)(implicit ctx: Context) = apply(lo, defn.AnyType)
- def apply(lo: Type, hi: Type)(implicit ctx: Context) =
- unique(new CachedTypeBounds(lo, hi))
+ def upper(hi: Type, variance: Int = 0)(implicit ctx: Context) = apply(defn.NothingType, hi, variance)
+ def lower(lo: Type, variance: Int = 0)(implicit ctx: Context) = apply(lo, defn.AnyType, variance)
+ //def apply(lo: Type, hi: Type)(implicit ctx: Context): TypeBounds = apply(lo, hi, 0)
+ def apply(lo: Type, hi: Type, variance: Int = 0)(implicit ctx: Context): TypeBounds =
+ unique(
+ if (variance == 0) new CachedTypeBounds(lo, hi)
+ else if (variance == 1) new CoTypeBounds(lo, hi)
+ else new ContraTypeBounds(lo, hi)
+ )
}
object TypeAlias {
- def apply(tp: Type)(implicit ctx: Context) = TypeBounds(tp, tp)
+ def apply(tp: Type, variance: Int = 0)(implicit ctx: Context) = TypeBounds(tp, tp, variance)
def unapply(tp: Type): Option[Type] = tp match {
case TypeBounds(lo, hi) if lo eq hi => Some(lo)
case _ => None