diff options
author | odersky <odersky@gmail.com> | 2014-12-17 10:34:38 +0100 |
---|---|---|
committer | odersky <odersky@gmail.com> | 2014-12-17 10:34:38 +0100 |
commit | 3a68e50073e9c4cef06c44e1dec7e3e492eb3274 (patch) | |
tree | 570c7ab8cd4fd88351a212192ad6de05c6887d6e /src/dotty | |
parent | ca03148fd5ba8b83cfa949f033eeaa82d45a9842 (diff) | |
parent | 7c1e76d085734697ccc17c4b21f59c15e078e0aa (diff) | |
download | dotty-3a68e50073e9c4cef06c44e1dec7e3e492eb3274.tar.gz dotty-3a68e50073e9c4cef06c44e1dec7e3e492eb3274.tar.bz2 dotty-3a68e50073e9c4cef06c44e1dec7e3e492eb3274.zip |
Merge pull request #270 from dotty-staging/change/type-aliases
Change/type aliases
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/core/Constraint.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Substituters.scala | 40 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 13 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 149 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Uniques.scala | 25 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 38 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ProtoTypes.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 |
11 files changed, 144 insertions, 147 deletions
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala index 339dbb64a..e241794d0 100644 --- a/src/dotty/tools/dotc/core/Constraint.scala +++ b/src/dotty/tools/dotc/core/Constraint.scala @@ -24,7 +24,9 @@ object Constraint { private val addDep: DepDelta = (_ + _) private val removeDep: DepDelta = (_ - _) - private val NoTypeBounds = new TypeBounds(WildcardType, WildcardType){} + private val NoTypeBounds = new TypeBounds(WildcardType, WildcardType) { + override def computeHash = unsupported("computeHash") + } /** An accumulator that changes dependencies on `param`. * @param param The parameter to which changed dependencies refer. @@ -70,7 +72,7 @@ import Constraint._ * @param dependents a map from PolyTypes to arrays of Sets of PolyParams. * The i'th set in an array corresponding to polytype `pt` contains * those dependent `PolyParam`s `dp` that have `PolyParam(pt, i)` in their bounds in - * significant position. A position is significant if solving the + * significant position. A position is significant if solving the * constraint for `(pt, i)` with a type higher than its lower bound * would lead to a constraint for `dp` that was not looser than * the existing constraint. Specifically, it means that all poly params diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 805b7660c..98a71dd98 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -528,13 +528,13 @@ object Contexts { private[core] val uniqueNamedTypes = new NamedTypeUniques /** A table for hash consing unique type bounds */ - private[core] val uniqueTypeBounds = new TypeBoundsUniques + private[core] val uniqueTypeAliases = new TypeAliasUniques private def uniqueSets = Map( "uniques" -> uniques, "uniqueRefinedTypes" -> uniqueRefinedTypes, "uniqueNamedTypes" -> uniqueNamedTypes, - "uniqueTypeBounds" -> uniqueTypeBounds) + "uniqueTypeAliases" -> uniqueTypeAliases) /** A map that associates label and size of all uniques sets */ def uniquesSizes: Map[String, Int] = uniqueSets.mapValues(_.size) diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala index 02d09d542..02810733a 100644 --- a/src/dotty/tools/dotc/core/Substituters.scala +++ b/src/dotty/tools/dotc/core/Substituters.scala @@ -18,8 +18,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(subst(tp.parent, from, to, theMap), tp.refinedName, subst(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(subst(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(subst(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new SubstBindingMap(from, to)) .mapOver(tp) @@ -36,8 +36,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(subst1(tp.parent, from, to, theMap), tp.refinedName, subst1(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(subst1(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(subst1(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new Subst1Map(from, to)) .mapOver(tp) @@ -56,8 +56,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(subst2(tp.parent, from1, to1, from2, to2, theMap), tp.refinedName, subst2(tp.refinedInfo, from1, to1, from2, to2, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(subst2(tp.lo, from1, to1, from2, to2, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(subst2(tp.alias, from1, to1, from2, to2, theMap)) case _ => (if (theMap != null) theMap else new Subst2Map(from1, to1, from2, to2)) .mapOver(tp) @@ -81,8 +81,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(subst(tp.parent, from, to, theMap), tp.refinedName, subst(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(subst(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(subst(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new SubstMap(from, to)) .mapOver(tp) @@ -115,8 +115,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(substDealias(tp.parent, from, to, theMap), tp.refinedName, substDealias(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(substDealias(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(substDealias(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new SubstDealiasMap(from, to)) .mapOver(tp) @@ -154,8 +154,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(substSym(tp.parent, from, to, theMap), tp.refinedName, substSym(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(substSym(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(substSym(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new SubstSymMap(from, to)) .mapOver(tp) @@ -172,8 +172,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(substThis(tp.parent, from, to, theMap), tp.refinedName, substThis(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(substThis(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(substThis(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new SubstThisMap(from, to)) .mapOver(tp) @@ -190,8 +190,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(substThis(tp.parent, from, to, theMap), tp.refinedName, substThis(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(substThis(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(substThis(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new SubstRefinedThisMap(from, to)) .mapOver(tp) @@ -208,8 +208,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(substParam(tp.parent, from, to, theMap), tp.refinedName, substParam(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(substParam(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(substParam(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new SubstParamMap(from, to)) .mapOver(tp) @@ -226,8 +226,8 @@ trait Substituters { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(substParams(tp.parent, from, to, theMap), tp.refinedName, substParams(tp.refinedInfo, from, to, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(substParams(tp.lo, from, to, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(substParams(tp.alias, from, to, theMap)) case _ => (if (theMap != null) theMap else new SubstParamsMap(from, to)) .mapOver(tp) diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 874928fcc..6443c5054 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -62,7 +62,7 @@ class TypeApplications(val self: Type) extends AnyVal { case tp: RefinedType => val tparams = tp.parent.typeParams tp.refinedInfo match { - case TypeBounds(lo, hi) if lo eq hi => tparams.filterNot(_.name == tp.refinedName) + case rinfo: TypeAlias => tparams.filterNot(_.name == tp.refinedName) case _ => tparams } case tp: SingletonType => @@ -353,9 +353,9 @@ class TypeApplications(val self: Type) extends AnyVal { * for a contravariant type-parameter becomes L. */ final def argInfo(tparam: Symbol, interpolate: Boolean = true)(implicit ctx: Context): Type = self match { + case self: TypeAlias => self.alias case TypeBounds(lo, hi) => - if (lo eq hi) hi - else if (interpolate) { + if (interpolate) { val v = tparam.variance if (v > 0 && (lo isRef defn.NothingClass)) hi else if (v < 0 && (hi isRef defn.AnyClass)) lo diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 42af31553..09087ac6c 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -667,8 +667,8 @@ class TypeComparer(initctx: Context) extends DotClass { { // special case for situations like: // foo <: C { type T = foo.T } tp2.refinedInfo match { - case TypeBounds(lo, hi) if lo eq hi => - !ctx.phase.erasedTypes && (tp1r select name) =:= lo + case rinfo: TypeAlias => + !ctx.phase.erasedTypes && (tp1r select name) =:= rinfo.alias case _ => false } }) diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 2b129ebf5..8190b8cb6 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -43,8 +43,8 @@ trait TypeOps { this: Context => asSeenFrom(tp.parent, pre, cls, theMap), tp.refinedName, asSeenFrom(tp.refinedInfo, pre, cls, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(asSeenFrom(tp.lo, pre, cls, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(asSeenFrom(tp.alias, pre, cls, theMap)) case _ => (if (theMap != null) theMap else new AsSeenFromMap(pre, cls)) .mapOver(tp) @@ -73,8 +73,8 @@ trait TypeOps { this: Context => tp case tp: RefinedType => tp.derivedRefinedType(simplify(tp.parent, theMap), tp.refinedName, simplify(tp.refinedInfo, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => - tp.derivedTypeAlias(simplify(tp.lo, theMap)) + case tp: TypeAlias => + tp.derivedTypeAlias(simplify(tp.alias, theMap)) case AndType(l, r) => simplify(l, theMap) & simplify(r, theMap) case OrType(l, r) => @@ -144,9 +144,10 @@ trait TypeOps { this: Context => def needsChecking(tp: Type, isPart: Boolean): Boolean = tp match { case tp: TypeRef => tp.info match { + case TypeAlias(alias) => + needsChecking(alias, isPart) case TypeBounds(lo, hi) => - if (lo eq hi) needsChecking(hi, isPart) - else isPart || tp.controlled(isVolatile(hi)) + isPart || tp.controlled(isVolatile(hi)) case _ => false } case tp: RefinedType => diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 3100be9a0..473b23f7b 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -104,8 +104,8 @@ object Types { */ def isRef(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar match { case this1: TypeRef => - this1.info match { // see comment in Namers/typeDefSig - case TypeBounds(lo, hi) if lo eq hi => hi.isRef(sym) + this1.info match { // see comment in Namer#typeDefSig + case TypeAlias(tp) => tp.isRef(sym) case _ => this1.symbol eq sym } case this1: RefinedType => @@ -193,10 +193,7 @@ object Types { } /** Is this an alias TypeBounds? */ - def isAlias: Boolean = this match { - case TypeBounds(lo, hi) => lo eq hi - case _ => false - } + def isAlias: Boolean = this.isInstanceOf[TypeAlias] /** Is this type a transitive refinement of the given type? * This is true if the type consists of 0 or more refinements or other @@ -669,7 +666,7 @@ object Types { final def dealias(implicit ctx: Context): Type = this match { case tp: TypeRef => tp.info match { - case TypeBounds(lo, hi) if lo eq hi => hi.dealias + case TypeAlias(tp) => tp.dealias case _ => tp } case tp: TypeVar => @@ -753,7 +750,7 @@ object Types { def dependsOnRefinedThis(tp: Type): Boolean = tp.stripTypeVar match { case tp @ TypeRef(RefinedThis(rt), _) if rt refines this => tp.info match { - case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi) + case TypeAlias(alias) => dependsOnRefinedThis(alias) case _ => true } case RefinedThis(rt) => rt refines this @@ -770,7 +767,7 @@ object Types { case pre: RefinedType => if (pre.refinedName ne name) loop(pre.parent) else this.member(name).info match { - case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi + case TypeAlias(tp) if !dependsOnRefinedThis(tp) => tp case _ => NoType } case RefinedThis(rt) => @@ -1926,7 +1923,7 @@ object Types { case MethodParam(`thisMethodType`, _) => true case tp @ TypeRef(MethodParam(`thisMethodType`, _), name) => tp.info match { // follow type arguments to avoid dependency - case TypeBounds(lo, hi) if lo eq hi => apply(x, hi) + case TypeAlias(tp)=> apply(x, tp) case _ => true } case _ => @@ -2412,42 +2409,33 @@ object Types { override def underlying(implicit ctx: Context): Type = 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) - - /** pre: this is a type alias */ - def derivedTypeAlias(tp: Type, variance: Int = this.variance)(implicit ctx: Context) = - if (lo eq tp) this - else TypeAlias(tp, variance) + /** The non-alias type bounds type with given bounds */ + def derivedTypeBounds(lo: Type, hi: Type)(implicit ctx: Context) = + if ((lo eq this.lo) && (hi eq this.hi) && (variance == 0)) this + else TypeBounds(lo, hi) /** If this is an alias, a derived alias with the new variance, * Otherwise the type itself. */ - def withVariance(variance: Int)(implicit ctx: Context) = - if (lo ne hi) this - else derivedTypeBounds(lo, hi, variance) + def withVariance(variance: Int)(implicit ctx: Context) = this match { + case tp: TypeAlias => tp.derivedTypeAlias(tp.alias, variance) + case _ => this + } def contains(tp: Type)(implicit ctx: Context) = tp match { case tp: TypeBounds => lo <:< tp.lo && tp.hi <:< hi case _ => lo <:< tp && tp <:< hi } - def & (that: TypeBounds)(implicit ctx: Context): TypeBounds = { - val v = this commonVariance that - if (v != 0 && (this.lo eq this.hi) && (that.lo eq that.hi)) - if (v > 0) derivedTypeAlias(this.hi & that.hi, v) - else derivedTypeAlias(this.lo | that.lo, v) - else derivedTypeBounds(this.lo | that.lo, this.hi & that.hi, v) - } + def & (that: TypeBounds)(implicit ctx: Context): TypeBounds = + if (this.lo <:< that.lo && that.hi <:< this.hi) that + else if (that.lo <:< this.lo && this.hi <:< that.hi) this + else TypeBounds(this.lo | that.lo, this.hi & that.hi) - def | (that: TypeBounds)(implicit ctx: Context): TypeBounds = { - val v = this commonVariance that - if (v != 0 && (this.lo eq this.hi) && (that.lo eq that.hi)) - if (v > 0) derivedTypeAlias(this.hi | that.hi, v) - else derivedTypeAlias(this.lo & that.lo, v) - else derivedTypeBounds(this.lo & that.lo, this.hi | that.hi, v) - } + def | (that: TypeBounds)(implicit ctx: Context): TypeBounds = + if (this.lo <:< that.lo && that.hi <:< this.hi) this + else if (that.lo <:< this.lo && this.hi <:< that.hi) that + else TypeBounds(this.lo & that.lo, this.hi | that.hi) override def & (that: Type)(implicit ctx: Context) = that match { case that: TypeBounds => this & that @@ -2462,38 +2450,60 @@ object Types { /** If this type and that type have the same variance, this variance, otherwise 0 */ final def commonVariance(that: TypeBounds): Int = (this.variance + that.variance) / 2 + override def equals(that: Any): Boolean = that match { + case that: TypeBounds => + (this.lo eq that.lo) && (this.hi eq that.hi) && this.variance == that.variance + case _ => + false + } + override def toString = if (lo eq hi) s"TypeAlias($lo)" else s"TypeBounds($lo, $hi)" - - override def computeHash = unsupported("computeHash") } - class CachedTypeBounds(lo: Type, hi: Type, hc: Int) extends TypeBounds(lo, hi) { - myHash = hc + class RealTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi) { + override def computeHash = doHash(variance, lo, hi) } - final class CoTypeBounds(lo: Type, hi: Type, hc: Int) extends CachedTypeBounds(lo, hi, hc) { - override def variance = 1 - override def toString = "Co" + super.toString + abstract class TypeAlias(val alias: Type, override val variance: Int) extends TypeBounds(alias, alias) { + /** pre: this is a type alias */ + def derivedTypeAlias(tp: Type, variance: Int = this.variance)(implicit ctx: Context) = + if (lo eq tp) this + else TypeAlias(tp, variance) + + override def & (that: TypeBounds)(implicit ctx: Context): TypeBounds = { + val v = this commonVariance that + if (v > 0) derivedTypeAlias(this.hi & that.hi, v) + else if (v < 0) derivedTypeAlias(this.lo | that.lo, v) + else super.& (that) + } + + override def | (that: TypeBounds)(implicit ctx: Context): TypeBounds = { + val v = this commonVariance that + if (v > 0) derivedTypeAlias(this.hi | that.hi, v) + else if (v < 0) derivedTypeAlias(this.lo & that.lo, v) + else super.| (that) + } } - final class ContraTypeBounds(lo: Type, hi: Type, hc: Int) extends CachedTypeBounds(lo, hi, hc) { - override def variance = -1 - override def toString = "Contra" + super.toString + class CachedTypeAlias(alias: Type, variance: Int, hc: Int) extends TypeAlias(alias, variance) { + myHash = hc + override def computeHash = doHash(variance, lo, hi) } object TypeBounds { - def apply(lo: Type, hi: Type, variance: Int = 0)(implicit ctx: Context): TypeBounds = - ctx.uniqueTypeBounds.enterIfNew(lo, hi, variance) + def apply(lo: Type, hi: Type)(implicit ctx: Context): TypeBounds = + unique(new RealTypeBounds(lo, hi)) def empty(implicit ctx: Context) = apply(defn.NothingType, defn.AnyType) - 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 upper(hi: Type)(implicit ctx: Context) = apply(defn.NothingType, hi) + def lower(lo: Type)(implicit ctx: Context) = apply(lo, defn.AnyType) } object TypeAlias { - 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) + def apply(alias: Type, variance: Int = 0)(implicit ctx: Context) = + ctx.uniqueTypeAliases.enterIfNew(alias, variance) + def unapply(tp: TypeAlias): Option[Type] = tp match { + case tp: TypeAlias => Some(tp.alias) case _ => None } } @@ -2650,24 +2660,18 @@ object Types { case tp: RefinedType => tp.derivedRefinedType(this(tp.parent), tp.refinedName, this(tp.refinedInfo)) + case tp: TypeAlias => + val saved = variance + variance = variance * tp.variance + val alias1 = this(tp.alias) + variance = saved + tp.derivedTypeAlias(alias1) + case tp: TypeBounds => - def mapOverBounds = { - val lo = tp.lo - val hi = tp.hi - if (lo eq hi) { - val saved = variance - variance = variance * tp.variance - val lo1 = this(lo) - variance = saved - tp.derivedTypeAlias(lo1) - } else { - variance = -variance - val lo1 = this(lo) - variance = -variance - tp.derivedTypeBounds(lo1, this(hi)) - } - } - mapOverBounds + variance = -variance + val lo1 = this(tp.lo) + variance = -variance + tp.derivedTypeBounds(lo1, this(tp.hi)) case tp: MethodType => def mapOverMethod = { @@ -2917,12 +2921,7 @@ object Types { def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = name.isTypeName && { val mbr = pre.member(name) - (mbr.symbol is Deferred) && { - mbr.info match { - case TypeBounds(lo, hi) => lo ne hi - case _ => false - } - } + (mbr.symbol is Deferred) && mbr.info.isInstanceOf[RealTypeBounds] } } diff --git a/src/dotty/tools/dotc/core/Uniques.scala b/src/dotty/tools/dotc/core/Uniques.scala index 0ade58193..fcf2df30b 100644 --- a/src/dotty/tools/dotc/core/Uniques.scala +++ b/src/dotty/tools/dotc/core/Uniques.scala @@ -65,30 +65,27 @@ object Uniques { } } - final class TypeBoundsUniques extends HashSet[TypeBounds](initialUniquesCapacity) with Hashable { - override def hash(x: TypeBounds): Int = x.hash + final class TypeAliasUniques extends HashSet[TypeAlias](initialUniquesCapacity) with Hashable { + override def hash(x: TypeAlias): Int = x.hash - private def findPrevious(h: Int, lo: Type, hi: Type, variance: Int): TypeBounds = { + private def findPrevious(h: Int, alias: Type, variance: Int): TypeAlias = { var e = findEntryByHash(h) while (e != null) { - if ((e.lo eq lo) && (e.hi eq hi) && (e.variance == variance)) return e + if ((e.alias eq alias) && (e.variance == variance)) return e e = nextEntryByHash(h) } e } - def enterIfNew(lo: Type, hi: Type, variance: Int): TypeBounds = { - val h = doHash(variance, lo, hi) - if (monitored) recordCaching(h, classOf[TypeBounds]) - def newBounds = - if (variance == 0) new CachedTypeBounds(lo, hi, h) - else if (variance == 1) new CoTypeBounds(lo, hi, h) - else new ContraTypeBounds(lo, hi, h) - if (h == NotCached) newBounds + def enterIfNew(alias: Type, variance: Int): TypeAlias = { + val h = doHash(variance, alias) + if (monitored) recordCaching(h, classOf[TypeAlias]) + def newAlias = new CachedTypeAlias(alias, variance, h) + if (h == NotCached) newAlias else { - val r = findPrevious(h, lo, hi, variance) + val r = findPrevious(h, alias, variance) if (r ne null) r - else addEntryAfterScan(newBounds) + else addEntryAfterScan(newAlias) } } } diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index 56b5100b1..1354b8926 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -63,26 +63,24 @@ object Checking { * break direct cycle with a LazyRef for legal, F-bounded cycles. */ def checkInfo(tp: Type): Type = tp match { + case tp @ TypeAlias(alias) => + try tp.derivedTypeAlias(apply(alias)) + finally { + where = "alias" + lastChecked = alias + } case tp @ TypeBounds(lo, hi) => - if (lo eq hi) - try tp.derivedTypeAlias(apply(lo)) - finally { - where = "alias" - lastChecked = lo - } - else { - val lo1 = try apply(lo) finally { - where = "lower bound" - lastChecked = lo - } - val saved = nestedCycleOK - nestedCycleOK = true - try tp.derivedTypeBounds(lo1, apply(hi)) - finally { - nestedCycleOK = saved - where = "upper bound" - lastChecked = hi - } + val lo1 = try apply(lo) finally { + where = "lower bound" + lastChecked = lo + } + val saved = nestedCycleOK + nestedCycleOK = true + try tp.derivedTypeBounds(lo1, apply(hi)) + finally { + nestedCycleOK = saved + where = "upper bound" + lastChecked = hi } case _ => tp @@ -277,7 +275,7 @@ trait Checking { tp.derivedRefinedType(tp.parent, tp.refinedName, checkFeasible(tp.refinedInfo, pos, where)) case tp @ TypeBounds(lo, hi) if !(lo <:< hi) => ctx.error(d"no type exists between low bound $lo and high bound $hi$where", pos) - tp.derivedTypeAlias(hi) + TypeAlias(hi) case _ => tp } diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala index 8d29916fa..98300f0b0 100644 --- a/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -373,8 +373,8 @@ object ProtoTypes { else tp.derivedSelect(wildApprox(tp.prefix, theMap)) case tp: RefinedType => // default case, inlined for speed tp.derivedRefinedType(wildApprox(tp.parent, theMap), tp.refinedName, wildApprox(tp.refinedInfo, theMap)) - case tp: TypeBounds if tp.lo eq tp.hi => // default case, inlined for speed - tp.derivedTypeAlias(wildApprox(tp.lo, theMap)) + case tp: TypeAlias => // default case, inlined for speed + tp.derivedTypeAlias(wildApprox(tp.alias, theMap)) case tp @ PolyParam(poly, pnum) => ctx.typerState.constraint.at(tp) match { case bounds: TypeBounds => wildApprox(WildcardType(bounds)) diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 9c0af8a6d..97c959a7a 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -355,7 +355,7 @@ trait TypeAssigner { tree.withType(ExprType(result.tpe)) def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context) = - tree.withType(TypeBounds(lo.tpe, hi.tpe)) + tree.withType(if (lo eq hi) TypeAlias(lo.tpe) else TypeBounds(lo.tpe, hi.tpe)) def assignType(tree: untpd.Bind, sym: Symbol)(implicit ctx: Context) = tree.withType(NamedType.withFixedSym(NoPrefix, sym)) |