diff options
-rw-r--r-- | src/dotty/tools/dotc/ast/tpd.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Substituters.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 34 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 44 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 119 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Uniques.scala | 13 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/transform/Erasure.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inferencing.scala | 2 |
10 files changed, 178 insertions, 75 deletions
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 8b9e0c12e..911283d5a 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -116,7 +116,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } case tp: RefinedType => val tp1 @ RefinedType(parent1, _) = mapOver(tp) - if (tp1.refinedInfo existsPart toAvoid) { + if (tp1.compactInfo existsPart toAvoid) { typr.println(s"dropping refinement from $tp1") parent1 } diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala index 944931698..2b4b8c167 100644 --- a/src/dotty/tools/dotc/core/Substituters.scala +++ b/src/dotty/tools/dotc/core/Substituters.scala @@ -17,7 +17,7 @@ trait Substituters { this: Context => case _: ThisType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(subst(tp.parent, from, to, map), tp.refinedName, subst(tp.refinedInfo, from, to, map)) + tp.derivedRefinedType(subst(tp.parent, from, to, map), tp.refinedName, subst(tp.compactInfo, from, to, map)) case _ => (if (map != null) map else new SubstBindingMap(from, to)) .mapOver(tp) @@ -33,7 +33,7 @@ trait Substituters { this: Context => case _: ThisType | _: BoundType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(subst1(tp.parent, from, to, map), tp.refinedName, subst1(tp.refinedInfo, from, to, map)) + tp.derivedRefinedType(subst1(tp.parent, from, to, map), tp.refinedName, subst1(tp.compactInfo, from, to, map)) case _ => (if (map != null) map else new Subst1Map(from, to)) .mapOver(tp) @@ -51,7 +51,7 @@ trait Substituters { this: Context => case _: ThisType | _: BoundType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(subst2(tp.parent, from1, to1, from2, to2, map), tp.refinedName, subst2(tp.refinedInfo, from1, to1, from2, to2, map)) + tp.derivedRefinedType(subst2(tp.parent, from1, to1, from2, to2, map), tp.refinedName, subst2(tp.compactInfo, from1, to1, from2, to2, map)) case _ => (if (map != null) map else new Subst2Map(from1, to1, from2, to2)) .mapOver(tp) @@ -74,7 +74,7 @@ trait Substituters { this: Context => case _: ThisType | _: BoundType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(subst(tp.parent, from, to, map), tp.refinedName, subst(tp.refinedInfo, from, to, map)) + tp.derivedRefinedType(subst(tp.parent, from, to, map), tp.refinedName, subst(tp.compactInfo, from, to, map)) case _ => (if (map != null) map else new SubstMap(from, to)) .mapOver(tp) @@ -97,7 +97,7 @@ trait Substituters { this: Context => case _: ThisType | _: BoundType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(substSym(tp.parent, from, to, map), tp.refinedName, substSym(tp.refinedInfo, from, to, map)) + tp.derivedRefinedType(substSym(tp.parent, from, to, map), tp.refinedName, substSym(tp.compactInfo, from, to, map)) case _ => (if (map != null) map else new SubstSymMap(from, to)) .mapOver(tp) @@ -113,7 +113,7 @@ trait Substituters { this: Context => case _: BoundType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(substThis(tp.parent, from, to, map), tp.refinedName, substThis(tp.refinedInfo, from, to, map)) + tp.derivedRefinedType(substThis(tp.parent, from, to, map), tp.refinedName, substThis(tp.compactInfo, from, to, map)) case _ => (if (map != null) map else new SubstThisMap(from, to)) .mapOver(tp) @@ -129,7 +129,7 @@ trait Substituters { this: Context => case _: ThisType | _: BoundType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(substThis(tp.parent, from, to, map), tp.refinedName, substThis(tp.refinedInfo, from, to, map)) + tp.derivedRefinedType(substThis(tp.parent, from, to, map), tp.refinedName, substThis(tp.compactInfo, from, to, map)) case _ => (if (map != null) map else new SubstRefinedThisMap(from, to)) .mapOver(tp) @@ -145,7 +145,7 @@ trait Substituters { this: Context => case _: ThisType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(substParam(tp.parent, from, to, map), tp.refinedName, substParam(tp.refinedInfo, from, to, map)) + tp.derivedRefinedType(substParam(tp.parent, from, to, map), tp.refinedName, substParam(tp.compactInfo, from, to, map)) case _ => (if (map != null) map else new SubstParamMap(from, to)) .mapOver(tp) @@ -161,7 +161,7 @@ trait Substituters { this: Context => case _: ThisType | NoPrefix | _: RefinedThis => tp case tp: RefinedType => - tp.derivedRefinedType(substParams(tp.parent, from, to, map), tp.refinedName, substParams(tp.refinedInfo, from, to, map)) + tp.derivedRefinedType(substParams(tp.parent, from, to, map), tp.refinedName, substParams(tp.compactInfo, from, to, map)) case _ => (if (map != null) map 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 9f742fcc2..7ecabe6f5 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -92,7 +92,7 @@ class TypeApplications(val self: Type) extends AnyVal { println(s"precomplete decls = ${self.typeSymbol.decls.toList.map(_.denot).mkString("\n ")}") } val tparam = tparams.head - val tp1 = RefinedType(tp, tparam.name, arg.toBounds(tparam)) + val tp1 = tp.paramRefinement(tparam, arg) recur(tp1, tparams.tail, args1) case nil => tp } @@ -122,17 +122,20 @@ class TypeApplications(val self: Type) extends AnyVal { final def appliedTo(arg: Type)(implicit ctx: Context): Type = appliedTo(arg :: Nil) final def appliedTo(arg1: Type, arg2: Type)(implicit ctx: Context): Type = appliedTo(arg1 :: arg2 :: Nil) - /** Turn this type, which is used as an argument for - * type parameter `tparam`, into a TypeBounds RHS + /** Add a refinement to this type, which reflects `arg` being used as an argument for + * type parameter `tparam`. */ - final def toBounds(tparam: Symbol)(implicit ctx: Context): TypeBounds = self match { - case self: TypeBounds => // this can happen for wildcard args - self + final def paramRefinement(tparam: Symbol, arg: Type)(implicit ctx: Context): RefinedType = arg match { + case arg: TypeBounds => // this can happen for wildcard args + RefinedType(self, tparam.name, arg) case _ => val v = tparam.variance - if (v > 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.upper(self) - else if (v < 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.lower(self) - else TypeAlias(self, v) + if (v > 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) + RefinedType(self, tparam.name, TypeBounds.upper(arg)) + else if (v < 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) + RefinedType(self, tparam.name, TypeBounds.lower(arg)) + else + RefinedType.compact(self, tparam.name, arg, v) } /** The type arguments of the base type instance wrt `base` of this type */ @@ -171,7 +174,7 @@ class TypeApplications(val self: Type) extends AnyVal { if (tparams == null) tparams = tycon.typeParams if (buf.size < tparams.length) { val tparam = tparams(buf.size) - if (name == tparam.name) buf += tp.refinedInfo.argType(tparam) + if (name == tparam.name) buf += tp.argTypeOfRefinement(tparam) else null } else null } @@ -210,6 +213,17 @@ class TypeApplications(val self: Type) extends AnyVal { NoType } + /** If the refinement is the image of a type argument to type parameter `tparam`, + * recover the type argument, otherwise NoType. + */ + final def argTypeOfRefinement(tparam: Symbol)(implicit ctx: Context): Type = self match { + case self: RefinedType => + if (self.isAliasRefinement) self.compactInfo + else self.refinedInfo.argType(tparam) + case _ => + NoType + } + /** The element type of a sequence or array */ def elemType(implicit ctx: Context): Type = firstBaseTypeArg(defn.SeqClass) orElse firstBaseTypeArg(defn.ArrayClass) diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 777ac0f3a..070daf64d 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -166,7 +166,7 @@ class TypeComparer(initctx: Context) extends DotClass { override def stopAtStatic = true def apply(tp: Type) = mapOver { tp match { - case tp: RefinedType if param occursIn tp.refinedInfo => tp.parent + case tp: RefinedType if param occursIn tp.compactInfo => tp.parent case _ => tp } } @@ -408,7 +408,7 @@ class TypeComparer(initctx: Context) extends DotClass { case tp1 @ RefinedType(parent1, name1) if !(seen contains name1) => tp2 match { case tp2 @ RefinedType(parent2, name2) if nameMatches(name1, name2, tp1, tp2) => - if (isSubType(tp1.refinedInfo, tp2.refinedInfo)) + if (refinementIsSubType(tp1, tp2)) matchRefinements(parent1, parent2, seen + name1) else NoType case _ => tp2 @@ -418,7 +418,7 @@ class TypeComparer(initctx: Context) extends DotClass { def compareRefined: Boolean = tp1.widen match { case tp1 @ RefinedType(parent1, name1) if nameMatches(name1, name2, tp1, tp2) => // optimized case; all info on tp1.name2 is in refinement tp1.refinedInfo. - isSubType(tp1.refinedInfo, tp2.refinedInfo) && { + refinementIsSubType(tp1, tp2) && { val ancestor2 = matchRefinements(parent1, parent2, Set.empty + name1) ancestor2.exists && isSubType(tp1, ancestor2) } @@ -426,15 +426,9 @@ class TypeComparer(initctx: Context) extends DotClass { def hasMatchingMember(name: Name): Boolean = /*>|>*/ ctx.traceIndented(s"hasMatchingMember($name) ${tp1.member(name)}", subtyping) /*<|<*/ ( tp1.member(name).hasAltWith(alt => isSubType(alt.info, tp2.refinedInfo)) || - { // special case for situations like: - // foo <: C { type T = foo.T } - tp2.refinedInfo match { - case TypeBounds(lo, hi) if lo eq hi => - val ref = tp1 select name - isSubType(ref, lo) && isSubType(hi, ref) - case _ => false - } - } + // special case for situations like: + // foo <: C { type T = foo.T } + tp2.isAliasRefinement && (tp1 select name) =:= tp2.compactInfo || name.isHkParamName && { val idx = name.hkParamIndex @@ -487,7 +481,7 @@ class TypeComparer(initctx: Context) extends DotClass { case tp2 @ TypeBounds(lo2, hi2) => def compareTypeBounds = tp1 match { case tp1 @ TypeBounds(lo1, hi1) => - val v = tp1.variance + tp2.variance + val v = tp1.variance + tp2.variance // !!! todo: revisit ((v > 0) || (lo2 isRef NothingClass) || isSubType(lo2, lo1)) && ((v < 0) || (hi2 isRef AnyClass) || isSubType(hi1, hi2)) case tp1: ClassInfo => @@ -528,6 +522,19 @@ class TypeComparer(initctx: Context) extends DotClass { false } + def refinementIsSubType(rt1: RefinedType, rt2: RefinedType): Boolean = { + if (rt1 eq rt2) return true + if (rt1.isAliasRefinement) + if (rt2.isAliasRefinement) { + if (rt2.boundsVariance > 0 && rt1.boundsVariance >= 0) + return isSubType(rt1.compactInfo, rt2.compactInfo) + else if (rt2.boundsVariance < 0 && rt1.boundsVariance <= 0) + return isSubType(rt2.compactInfo, rt1.compactInfo) + } + // todo: handle case where rt2.compactInfo is a type bounds + isSubType(rt1.refinedInfo, rt2.refinedInfo) + } + /** Like tp1 <:< tp2, but returns false immediately if we know that * the case was covered previouslky during subtyping. */ @@ -915,9 +922,14 @@ class TypeComparer(initctx: Context) extends DotClass { // gives =:= types), but it keeps the type smaller. tp2 match { case tp2: RefinedType if tp1.refinedName == tp2.refinedName => - tp1.derivedRefinedType( - tp1.parent & tp2.parent, tp1.refinedName, - tp1.refinedInfo & tp2.refinedInfo) + val commonParent = tp1.parent & tp2.parent + val commonName = tp1.refinedName + if (refinementIsSubType(tp1, tp2)) + tp1.derivedRefinedType(commonParent, commonName, tp1.compactInfo) + else if (refinementIsSubType(tp2, tp1)) + tp1.derivedRefinedType(commonParent, commonName, tp2.compactInfo) + else + RefinedType(commonParent, commonName, tp1.refinedInfo & tp2.refinedInfo) case _ => NoType } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index afa39f2a3..96071107f 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -35,7 +35,7 @@ trait TypeOps { this: Context => tp.derivedRefinedType( asSeenFrom(tp.parent, pre, cls, theMap), tp.refinedName, - asSeenFrom(tp.refinedInfo, pre, cls, theMap)) + asSeenFrom(tp.compactInfo, pre, cls, theMap)) case _ => (if (theMap != null) theMap else new AsSeenFromMap(pre, cls)) .mapOver(tp) @@ -57,7 +57,7 @@ trait TypeOps { this: Context => case _: ThisType | _: BoundType | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(simplify(tp.parent, theMap), tp.refinedName, simplify(tp.refinedInfo, theMap)) + tp.derivedRefinedType(simplify(tp.parent, theMap), tp.refinedName, simplify(tp.compactInfo, theMap)) case AndType(l, r) => simplify(l, theMap) & simplify(r, theMap) case OrType(l, r) => diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index aab70a61b..68e79cbb8 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -620,10 +620,8 @@ object Types { def lookupRefined(pre: Type, name: Name)(implicit ctx: Context): Type = pre.stripTypeVar match { case pre: RefinedType => if (pre.refinedName ne name) lookupRefined(pre.parent, name) - else pre.refinedInfo match { - case TypeBounds(lo, hi) if lo eq hi => hi - case _ => NoType - } + else if (pre.isAliasRefinement) pre.compactInfo + else NoType case pre: WildcardType => WildcardType case _ => @@ -1282,14 +1280,40 @@ object Types { abstract case class RefinedType(parent: Type, refinedName: Name) extends CachedProxyType with BindingType with ValueType { - val refinedInfo: Type + /** The compact info: avoid having a TypeBounds for aliases. + * The full TypeBounds form is reconstituted in refinedInfo + */ + val compactInfo: Type + + /** If this is an encoded alias type, its variance */ + def boundsVariance: Int + + /** Is the refinement an alias type? */ + def isAliasRefinement = refinedName.isTypeName && !compactInfo.isInstanceOf[TypeType] + + /** The refinement in standardized form (for a type alias or abstract type, + * this is always a TypeBounds + */ + def refinedInfo(implicit ctx: Context): Type = + if (isAliasRefinement) TypeAlias(compactInfo, boundsVariance) + else compactInfo + + if (monitored) + compactInfo match { + case TypeBounds(lo, hi) => assert(lo ne hi) + record("surviving type bounds") + assert(lo ne hi) + case _ => + if (isAliasRefinement) record("alias refinements") + else record("plain refinements") + } override def underlying(implicit ctx: Context) = parent /** Derived refined type, with a twist: A refinement with a higher-kinded type param placeholder * is transformed to a refinement of the original type parameter if that one exists. */ - def derivedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)(implicit ctx: Context): RefinedType = { + def derivedRefinedType(parent: Type, refinedName: Name, compactInfo: Type)(implicit ctx: Context): RefinedType = { lazy val underlyingTypeParams = parent.safeUnderlyingTypeParams lazy val originalTypeParam = underlyingTypeParams(refinedName.hkParamIndex) @@ -1301,50 +1325,95 @@ object Types { else TypeBounds(hkBounds.lo, hkBounds.hi) } - if ((parent eq this.parent) && (refinedName eq this.refinedName) && (refinedInfo eq this.refinedInfo)) + if ((parent eq this.parent) && (refinedName eq this.refinedName) && (compactInfo eq this.compactInfo)) this else if ( refinedName.isHkParamName // && { println(s"deriving $refinedName $parent $underlyingTypeParams"); true } && refinedName.hkParamIndex < underlyingTypeParams.length && originalTypeParam.name != refinedName) - derivedRefinedType(parent, originalTypeParam.name, adjustedHKRefinedInfo(refinedInfo.bounds)) + RefinedType(parent, originalTypeParam.name, adjustedHKRefinedInfo(refinedInfo.bounds)) else - RefinedType(parent, refinedName, rt => refinedInfo.substThis(this, RefinedThis(rt))) + RefinedType.compact(parent, refinedName, compactInfo, boundsVariance, this) } override def equals(that: Any) = that match { case that: RefinedType => this.parent == that.parent && this.refinedName == that.refinedName && - this.refinedInfo == that.refinedInfo + this.compactInfo == that.compactInfo && + this.boundsVariance == that.boundsVariance case _ => false } - override def computeHash = doHash(refinedName, refinedInfo, parent) - override def toString = s"RefinedType($parent, $refinedName, $refinedInfo)" + override def computeHash = addDelta(doHash(refinedName, compactInfo, parent), boundsVariance) + override def toString = s"RefinedType($parent, $refinedName, $compactInfo)" + } + + /** Main implementation class of refined type */ + class DerivedRefinedType(parent: Type, refinedName: Name, cinfo: Type, derivedFrom: Type)(implicit ctx: Context) extends RefinedType(parent, refinedName) { + val compactInfo = derivedFrom match { + case rt: RefinedType => cinfo.substThis(rt, RefinedThis(this)) + case _ => cinfo + } + def boundsVariance = 0 } - class CachedRefinedType(parent: Type, refinedName: Name, infoFn: RefinedType => Type) extends RefinedType(parent, refinedName) { - val refinedInfo = infoFn(this) + /** Implementation class for covariant alias refinements */ + class CoRefinedType(parent: Type, refinedName: Name, cinfo: Type, derivedFrom: Type)(implicit ctx: Context) + extends DerivedRefinedType(parent, refinedName, cinfo, derivedFrom) { + override def boundsVariance = +1 } + /** Implementation class for contravariant alias refinements */ + class ContraRefinedType(parent: Type, refinedName: Name, cinfo: Type, derivedFrom: Type)(implicit ctx: Context) + extends DerivedRefinedType(parent, refinedName, cinfo, derivedFrom) { + override def boundsVariance = -1 + } + + /** A dummy refined type used for bootstrapping when the refined info is given as a function + * from the refined type itself. + */ + class DummyRefinedType(parent: Type, name: Name) + extends RefinedType(parent, name) { + override def computeHash = NotCached + val compactInfo = NoType + val boundsVariance = 0 + } + +/* class PreHashedRefinedType(parent: Type, refinedName: Name, override val refinedInfo: Type, hc: Int) extends RefinedType(parent, refinedName) { myHash = hc override def computeHash = unsupported("computeHash") } - +*/ object RefinedType { def make(parent: Type, names: List[Name], infoFns: List[RefinedType => Type])(implicit ctx: Context): Type = if (names.isEmpty) parent else make(RefinedType(parent, names.head, infoFns.head), names.tail, infoFns.tail) - def apply(parent: Type, name: Name, infoFn: RefinedType => Type)(implicit ctx: Context): RefinedType = - ctx.base.uniqueRefinedTypes.enterIfNew(new CachedRefinedType(parent, name, infoFn)) + def apply(parent: Type, name: Name, infoFn: RefinedType => Type)(implicit ctx: Context): RefinedType = { + val dummy = new DummyRefinedType(parent, name) + apply(parent, name, infoFn(dummy), dummy) + } - def apply(parent: Type, name: Name, info: Type)(implicit ctx: Context): RefinedType = { - ctx.base.uniqueRefinedTypes.enterIfNew(parent, name, info) + def apply(parent: Type, name: Name, info: Type, derivedFrom: Type = NoType)(implicit ctx: Context): RefinedType = { + info match { + case bounds @ TypeBounds(lo, hi) if lo eq hi => + assert(name.isTypeName) + compact(parent, name, hi, bounds.variance, derivedFrom) + case _ => + compact(parent, name, info, 0, derivedFrom) + } } + + def compact(parent: Type, name: Name, compactInfo: Type, boundsVariance: Int, derivedFrom: Type = NoType)(implicit ctx: Context): RefinedType = + ctx.base.uniqueRefinedTypes.enterIfNew { + if (boundsVariance == 0) new DerivedRefinedType(parent, name, compactInfo, derivedFrom) + else if (boundsVariance > 0) new CoRefinedType(parent, name, compactInfo, derivedFrom) + else new ContraRefinedType(parent, name, compactInfo, derivedFrom) + } + // ctx.base.uniqueRefinedTypes.enterIfNew(parent, name, info) } // --- AndType/OrType --------------------------------------------------------------- @@ -1806,7 +1875,7 @@ object Types { private def computeSelfType(base: Type, tparams: List[TypeSymbol])(implicit ctx: Context): Type = tparams match { case tparam :: tparams1 => computeSelfType( - RefinedType(base, tparam.name, TypeRef(cls.thisType, tparam).toBounds(tparam)), + base.paramRefinement(tparam, TypeRef(cls.thisType, tparam)), tparams1) case nil => base @@ -1946,6 +2015,7 @@ object Types { override def variance = 1 override def toString = "Co" + super.toString } + final class ContraTypeBounds(lo: Type, hi: Type, hc: Int) extends CachedTypeBounds(lo, hi, hc) { override def variance = -1 override def toString = "Contra" + super.toString @@ -2099,7 +2169,7 @@ object Types { | NoPrefix => tp case tp: RefinedType => - tp.derivedRefinedType(this(tp.parent), tp.refinedName, this(tp.refinedInfo)) + tp.derivedRefinedType(this(tp.parent), tp.refinedName, this(tp.compactInfo)) case tp @ MethodType(pnames, ptypes) => variance = -variance @@ -2223,7 +2293,12 @@ object Types { | NoPrefix => x case tp: RefinedType => - this(this(x, tp.parent), tp.refinedInfo) + val y = this(x, tp.parent) + val saved = variance + if (tp.isAliasRefinement) variance = variance * tp.boundsVariance + val result = this(y, tp.compactInfo) + variance = saved + result case tp @ MethodType(pnames, ptypes) => variance = -variance diff --git a/src/dotty/tools/dotc/core/Uniques.scala b/src/dotty/tools/dotc/core/Uniques.scala index 9ad736c9c..f05b7821d 100644 --- a/src/dotty/tools/dotc/core/Uniques.scala +++ b/src/dotty/tools/dotc/core/Uniques.scala @@ -92,20 +92,21 @@ object Uniques { } } + /** Todo: clean up once the initialization scheme for refined types is decided */ final class RefinedUniques extends HashSet[RefinedType]("uniqueRefinedTypes", initialUniquesCapacity) with Hashable { - override val hashSeed = classOf[CachedRefinedType].hashCode // some types start life as CachedRefinedTypes, need to have same hash seed +// override val hashSeed = classOf[DerivedRefinedType].hashCode // some types start life as DerivedRefinedTypes, need to have same hash seed override def hash(x: RefinedType): Int = x.hash - private def findPrevious(h: Int, parent: Type, refinedName: Name, refinedInfo: Type): RefinedType = { + private def findPrevious(h: Int, parent: Type, refinedName: Name, compactInfo: Type): RefinedType = { var e = findEntryByHash(h) while (e != null) { - if ((e.parent == parent) && (e.refinedName eq refinedName) && (e.refinedInfo == refinedInfo)) + if ((e.parent == parent) && (e.refinedName eq refinedName) && (e.compactInfo == compactInfo)) return e e = nextEntryByHash(h) } e } - +/* def enterIfNew(parent: Type, refinedName: Name, refinedInfo: Type): RefinedType = { val h = doHash(refinedName, refinedInfo, parent) def newType = new PreHashedRefinedType(parent, refinedName, refinedInfo, h) @@ -116,12 +117,12 @@ object Uniques { if (r ne null) r else addEntryAfterScan(newType) } } - +*/ def enterIfNew(rt: RefinedType) = { if (monitored) recordCaching(rt) if (rt.hash == NotCached) rt else { - val r = findPrevious(rt.hash, rt.parent, rt.refinedName, rt.refinedInfo) + val r = findPrevious(rt.hash, rt.parent, rt.refinedName, rt.compactInfo) if (r ne null) r else addEntryAfterScan(rt) } } diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 78a91b2ef..e5cbdf53b 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -560,15 +560,16 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: def elim(tp: Type): Type = tp match { case tp @ RefinedType(parent, name) => val parent1 = elim(tp.parent) - tp.refinedInfo match { - case TypeAlias(info: TypeRef) if boundSyms contains info.symbol => - RefinedType(parent1, name, info.symbol.info) + tp.compactInfo match { case info: TypeRef if boundSyms contains info.symbol => val info1 = info.symbol.info - assert(info1.derivesFrom(defn.SingletonClass)) - RefinedType(parent1, name, info1.mapReduceAnd(removeSingleton)(_ & _)) - case info => - tp.derivedRefinedType(parent1, name, info) + if (tp.isAliasRefinement) RefinedType(parent1, name, info1) + else { + assert(info1.derivesFrom(defn.SingletonClass)) + RefinedType(parent1, name, info1.mapReduceAnd(removeSingleton)(_ & _)) + } + case cinfo => + tp.derivedRefinedType(parent1, name, cinfo) } case _ => tp diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala index 34f339d9a..80f2b3941 100644 --- a/src/dotty/tools/dotc/core/transform/Erasure.scala +++ b/src/dotty/tools/dotc/core/transform/Erasure.scala @@ -115,7 +115,7 @@ object Erasure { if (parent isRef defn.ArrayClass) eraseArray(tp) match { case tp1: RefinedType if tp1.parent isRef defn.ArrayClass => - sigName(tp1.refinedInfo) ++ "[]" + sigName(tp1.compactInfo) ++ "[]" case tp1 => sigName(tp1) } diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index a313f70ac..75316da59 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -551,7 +551,7 @@ object Inferencing { case _: ThisType | _: BoundType | NoPrefix => // default case, inlined for speed tp case tp: RefinedType => // default case, inlined for speed - tp.derivedRefinedType(wildApprox(tp.parent, theMap), tp.refinedName, wildApprox(tp.refinedInfo, theMap)) + tp.derivedRefinedType(wildApprox(tp.parent, theMap), tp.refinedName, wildApprox(tp.compactInfo, theMap)) case _ => (if (theMap != null) theMap else new WildApproxMap).mapOver(tp) } |