aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala2
-rw-r--r--src/dotty/tools/dotc/core/Substituters.scala18
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala34
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala44
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala4
-rw-r--r--src/dotty/tools/dotc/core/Types.scala119
-rw-r--r--src/dotty/tools/dotc/core/Uniques.scala13
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala15
-rw-r--r--src/dotty/tools/dotc/core/transform/Erasure.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala2
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)
}