aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-01-10 17:47:55 +0100
committerMartin Odersky <odersky@gmail.com>2015-01-10 17:47:55 +0100
commit97aced07f273a31be69fd771a4e900a8e0cfa43a (patch)
tree5d97ce7b5da0dd2dcfec601d616e530129958faa /src/dotty/tools
parent5f35b11ceb228e7a803263490f2d8e8a22ee2fe6 (diff)
downloaddotty-97aced07f273a31be69fd771a4e900a8e0cfa43a.tar.gz
dotty-97aced07f273a31be69fd771a4e900a8e0cfa43a.tar.bz2
dotty-97aced07f273a31be69fd771a4e900a8e0cfa43a.zip
Reverting the idea that RefinedThis types take levels.
In the end, this did not buy us anything. What matters is that - we can reliably identify RefinedThis types pointing to a given refinement type. Making sure that the `binder` field of q RefinedThis type in a refinedInfo is always the containing refined type is good enough for that. - we take care to rebind RefinedThis types in isSubType. This was leaky before, is handled now better in the new isSubType. So, in the end, adding a level was a needless complication. Also, as a next step we should be able to identify skolem types and RefinedThis types.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/Substituters.scala71
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala39
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala6
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala15
-rw-r--r--src/dotty/tools/dotc/core/Types.scala63
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala8
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala2
8 files changed, 48 insertions, 163 deletions
diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala
index 9fd01ab56..76264519f 100644
--- a/src/dotty/tools/dotc/core/Substituters.scala
+++ b/src/dotty/tools/dotc/core/Substituters.scala
@@ -183,13 +183,8 @@ trait Substituters { this: Context =>
// the target type from RefinedThis.
final def substThis0(tp: Type, from: RefinedType, to: Type, theMap: SubstRefinedThisMap0): Type =
tp match {
- case tp @ RefinedThis(rt, level) =>
- if (rt eq from)
- to match { // !!! TODO drop
- case RefinedThis(rt1, -1) => RefinedThis(rt1, level)
- case _ => to
- }
- else tp
+ case tp @ RefinedThis(rt) =>
+ if (rt eq from) to else tp
case tp: NamedType =>
if (tp.currentSymbol.isStatic) tp
else tp.derivedSelect(substThis0(tp.prefix, from, to, theMap))
@@ -202,29 +197,6 @@ trait Substituters { this: Context =>
case _ =>
(if (theMap != null) theMap else new SubstRefinedThisMap0(from, to))
.mapOver(tp)
- }
-
- final def substRefinedThis(tp: Type, level: Int, to: Type, theMap: SubstRefinedThisMap): Type =
- tp match {
- case tp @ RefinedThis(rt, l) if l == level =>
- to
- case tp: NamedType =>
- if (tp.currentSymbol.isStatic) tp
- else tp.derivedSelect(substRefinedThis(tp.prefix, level, to, theMap))
- case _: ThisType | _: BoundType | NoPrefix =>
- tp
- case tp: RefinedType =>
- tp.derivedRefinedType(
- substRefinedThis(tp.parent, level, to, theMap), tp.refinedName,
- substRefinedThis(tp.refinedInfo, level + 1, to, theMap))
- case tp: TypeAlias =>
- tp.derivedTypeAlias(substRefinedThis(tp.alias, level, to, theMap))
- case _ =>
- val m = if (theMap != null) theMap else new SubstRefinedThisMap(to)
- val saved = m.level
- m.level = level
- try m.mapOver(tp)
- finally m.level = saved
}
final def substParam(tp: Type, from: ParamType, to: Type, theMap: SubstParamMap): Type =
@@ -300,11 +272,6 @@ trait Substituters { this: Context =>
def apply(tp: Type): Type = substThis0(tp, from, to, this)
}
- final class SubstRefinedThisMap(to: Type) extends DeepTypeMap {
- var level: Int = 0
- def apply(tp: Type): Type = substRefinedThis(tp, level, to, this)
- }
-
final class SubstParamMap(from: ParamType, to: Type) extends DeepTypeMap {
def apply(tp: Type) = substParam(tp, from, to, this)
}
@@ -312,38 +279,4 @@ trait Substituters { this: Context =>
final class SubstParamsMap(from: BindingType, to: List[Type]) extends DeepTypeMap {
def apply(tp: Type) = substParams(tp, from, to, this)
}
-
- /** Substitute every occurrence of symbol `from_i` with `RefinedThis(leve).select(to_i)`
- * where level represents the nesting level of the occurrence (i.e. number
- * of refinedInfos between substituted type and the occurrence.
- * TODO: Drop `rt` once it is dropped from RefinedThis
- * TODO: Apply to enclosing refined type instead of refined info. That way we
- * can optimize for types not containing any RefinedThis
- */
- final class SubstWithRefinedSelectMap(rt: RefinedType, from: List[Symbol], to: List[TypeName]) extends DeepTypeMap {
- private var level = 0
- def apply(tp: Type): Type = tp match {
- case tp: NamedType =>
- val sym = tp.symbol
- var fs = from
- var ts = to
- while (fs.nonEmpty) {
- if (fs.head eq sym)
- return RefinedThis(rt, level).select(ts.head)
- fs = fs.tail
- ts = ts.tail
- }
- if (sym.isStatic && !existsStatic(from)) tp
- else tp.derivedSelect(apply(tp.prefix))
- case tp: RefinedType =>
- val parent1 = apply(tp.parent)
- level += 1
- try tp.derivedRefinedType(parent1, tp.refinedName, apply(tp.refinedInfo))
- finally level -= 1
- case tp: TypeAlias =>
- tp.derivedTypeAlias(apply(tp.alias))
- case _ =>
- mapOver(tp)
- }
- }
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index e71226b68..b29022281 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -373,29 +373,27 @@ class TypeApplications(val self: Type) extends AnyVal {
case _ => firstBaseArgInfo(defn.SeqClass)
}
- def containsRefinedThis(level: Int)(implicit ctx: Context): Boolean = {
- def recur(tp: Type, level: Int): Boolean = tp.stripTypeVar match {
- case RefinedThis(rt, `level`) =>
- true
+ def containsRefinedThis(target: Type)(implicit ctx: Context): Boolean = {
+ def recur(tp: Type): Boolean = tp.stripTypeVar match {
+ case RefinedThis(tp) =>
+ tp eq target
case tp: NamedType =>
tp.info match {
- case TypeAlias(alias) => recur(alias, level)
- case _ => !tp.symbol.isStatic && recur(tp.prefix, level)
+ case TypeAlias(alias) => recur(alias)
+ case _ => !tp.symbol.isStatic && recur(tp.prefix)
}
case tp: RefinedType =>
- recur(tp.refinedInfo, level + 1) ||
- recur(tp.parent, level)
+ recur(tp.refinedInfo) || recur(tp.parent)
case tp: TypeBounds =>
- recur(tp.lo, level) ||
- recur(tp.hi, level)
+ recur(tp.lo) || recur(tp.hi)
case tp: AnnotatedType =>
- recur(tp.underlying, level)
+ recur(tp.underlying)
case tp: AndOrType =>
- recur(tp.tp1, level) || recur(tp.tp2, level)
+ recur(tp.tp1) || recur(tp.tp2)
case _ =>
false
}
- recur(self, level)
+ recur(self)
}
/** Given a type alias
@@ -432,14 +430,16 @@ class TypeApplications(val self: Type) extends AnyVal {
if (bsyms.isEmpty) {
val correspondingNames = correspondingParamName.values.toSet
+ def replacements(rt: RefinedType): List[Type] =
+ for (sym <- boundSyms)
+ yield TypeRef(RefinedThis(rt), correspondingParamName(sym))
+
def rewrite(tp: Type): Type = tp match {
case tp @ RefinedType(parent, name: TypeName) =>
if (correspondingNames contains name) rewrite(parent)
else RefinedType(
- rewrite(parent),
- name,
- new ctx.SubstWithRefinedSelectMap(
- _, boundSyms, boundSyms map correspondingParamName)(tp.refinedInfo))
+ rewrite(parent), name,
+ rt => tp.refinedInfo.subst(boundSyms, replacements(rt)))
case tp =>
tp
}
@@ -474,8 +474,9 @@ class TypeApplications(val self: Type) extends AnyVal {
def expand(tp: Type) = {
val lambda = defn.lambdaTrait(boundSyms.map(_.variance))
val substitutedRHS = (rt: RefinedType) => {
- val argNames = boundSyms.indices.toList.map(tpnme.lambdaArgName)
- new ctx.SubstWithRefinedSelectMap(rt, boundSyms, argNames)(tp).bounds.withVariance(1)
+ val argRefs = boundSyms.indices.toList.map(i =>
+ RefinedThis(rt).select(tpnme.lambdaArgName(i)))
+ tp.subst(boundSyms, argRefs).bounds.withVariance(1)
}
val res = RefinedType(lambda.typeRef, tpnme.Apply, substitutedRHS)
//println(i"lambda abstract $self wrt $boundSyms%, % --> $res")
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 8717a45df..8a810741a 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -258,9 +258,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
}
}
comparePolyParam
- case tp1: RefinedThis =>
+ case RefinedThis(rt1) =>
tp2 match {
- case tp2: RefinedThis if tp1.level == tp2.level => true
+ case RefinedThis(rt2) if rt1 == rt2 => true
case _ => thirdTry(tp1, tp2)
}
case tp1: BoundType =>
@@ -525,7 +525,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
try {
def rebindNeeded = tp2.refinementRefersToThis
val base = if (rebindNeeded) ensureSingleton(tp1) else tp1
- val rinfo2 = if (rebindNeeded) tp2.refinedInfo.substRefinedThis(0, base) else tp2.refinedInfo
+ val rinfo2 = if (rebindNeeded) tp2.refinedInfo.substThis0(tp2, base) else tp2.refinedInfo
def qualifies(m: SingleDenotation) = isSubType(m.info, rinfo2)
def memberMatches(mbr: Denotation): Boolean = mbr match { // inlined hasAltWith for performance
case mbr: SingleDenotation => qualifies(mbr)
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index 6fc7314c2..3e04eb037 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -331,21 +331,6 @@ trait TypeOps { this: Context =>
parentRefs
}
- /** Map `C.this` types where `C` is `refineCls` to RefinedThis types with given level.
- * The level gets adjusted for nested refined types.
- */
- def thisToRefinedThis(rt: RefinedType, refineCls: Symbol, level: Int): TypeMap = new TypeMap {
- def apply(tp: Type): Type = tp match {
- case tp: ThisType if tp.cls eq refineCls => RefinedThis(rt, level)
- case tp: RefinedType =>
- tp.derivedRefinedType(
- this(tp.parent), tp.refinedName,
- thisToRefinedThis(rt, refineCls, level + 1)(tp.refinedInfo))
- case _ =>
- mapOver(tp)
- }
- }
-
/** An argument bounds violation is a triple consisting of
* - the argument tree
* - a string "upper" or "lower" indicating which bound is violated
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index d64e7340e..933f56cb4 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -436,12 +436,9 @@ object Types {
}
def goRefined(tp: RefinedType) = {
val pdenot = go(tp.parent)
- val rinfo = pre match {
- case pre: RefinedType => tp.refinedInfo.substThis0(tp, RefinedThis(pre, -1))
- case _ =>
- if (tp.refinementRefersToThis) tp.refinedInfo.substRefinedThis(0, pre)
- else tp.refinedInfo
- }
+ val rinfo =
+ if (tp.refinementRefersToThis) tp.refinedInfo.substThis0(tp, pre)
+ else tp.refinedInfo
if (name.isTypeName) { // simplified case that runs more efficiently
val jointInfo = if (rinfo.isAlias) rinfo else pdenot.info & rinfo
pdenot.asSingleDenotation.derivedSingleDenotation(pdenot.symbol, jointInfo)
@@ -777,12 +774,12 @@ object Types {
case TypeAlias(tp) =>
if (!pre.refinementRefersToThis) tp
else tp match {
- case TypeRef(RefinedThis(_, 0), alias) => lookupRefined(alias)
+ case TypeRef(RefinedThis(`pre`), alias) => lookupRefined(alias)
case _ => NoType
}
case _ => loop(pre.parent)
}
- case RefinedThis(rt, _) =>
+ case RefinedThis(rt) =>
rt.lookupRefined(name)
case pre: WildcardType =>
WildcardType
@@ -947,10 +944,6 @@ object Types {
final def substThis0(rt: RefinedType, tp: Type)(implicit ctx: Context): Type =
ctx.substThis0(this, rt, tp, null)
- /** Substitute all occurrences of `RefinedThis(level)` by `tp` */
- final def substRefinedThis(level: Int, to: Type)(implicit ctx: Context): Type =
- ctx.substRefinedThis(this, level, to, null)
-
/** Substitute a bound type by some other type */
final def substParam(from: ParamType, to: Type)(implicit ctx: Context): Type =
ctx.substParam(this, from, to, null)
@@ -1750,49 +1743,15 @@ object Types {
def refinementRefersToThis(implicit ctx: Context): Boolean = {
if (!refinementRefersToThisKnown) {
- refinementRefersToThisCache = refinedInfo.containsRefinedThis(0)
+ refinementRefersToThisCache = refinedInfo.containsRefinedThis(this)
refinementRefersToThisKnown = true
}
refinementRefersToThisCache
}
-
- def checkLevel(implicit ctx: Context): Unit = {
- val checkAccu = new TypeAccumulator[Unit] {
- var level = 0
- def apply(x: Unit, tp: Type) = tp.stripTypeVar match {
- case RefinedThis(rt, l) =>
- def dominates(tp: Type, rt: RefinedType): Boolean =
- (tp eq rt) || {
- tp match {
- case RefinedType(parent, _) => dominates(parent, rt)
- case _ => false
- }
- }
- if (rt eq RefinedType.this) assert(l == level, RefinedType.this)
- case tp: RefinedType =>
- level += 1
- apply(x, tp.refinedInfo)
- level -= 1
- apply(x, tp.parent)
- case tp: TypeBounds =>
- apply(x, tp.lo)
- apply(x, tp.hi)
- case tp: AnnotatedType =>
- apply(x, tp.underlying)
- case tp: AndOrType =>
- apply(x, tp.tp1)
- apply(x, tp.tp2)
- case _ =>
- foldOver(x, tp)
- }
- }
- checkAccu((), refinedInfo)
- }
override def underlying(implicit ctx: Context) = parent
private def checkInst(implicit ctx: Context): this.type = {
- checkLevel
if (Config.checkLambdaVariance)
refinedInfo match {
case refinedInfo: TypeBounds if refinedInfo.variance != 0 && refinedName.isLambdaArgName =>
@@ -1820,7 +1779,7 @@ object Types {
derivedRefinedType(parent.EtaExpand, refinedName, refinedInfo)
else
if (false) RefinedType(parent, refinedName, refinedInfo)
- else RefinedType(parent, refinedName, rt => refinedInfo.substThis0(this, RefinedThis(rt, -1))) // !!! TODO: replace with simply `refinedInfo`
+ else RefinedType(parent, refinedName, rt => refinedInfo.substThis0(this, RefinedThis(rt)))
}
override def equals(that: Any) = that match {
@@ -2222,11 +2181,11 @@ object Types {
* @param level The number of enclosing refined types between
* the `this` reference and its target.
*/
- case class RefinedThis(binder: RefinedType, level: Int) extends BoundType with SingletonType {
+ case class RefinedThis(binder: RefinedType) extends BoundType with SingletonType {
type BT = RefinedType
override def underlying(implicit ctx: Context) = binder
- def copyBoundType(bt: BT) = RefinedThis(bt, level)
-
+ def copyBoundType(bt: BT) = RefinedThis(bt)
+
// need to customize hashCode and equals to prevent infinite recursion for
// refinements that refer to the refinement type via this
override def computeHash = addDelta(binder.identityHash, 41)
@@ -2234,7 +2193,7 @@ object Types {
case that: RefinedThis => this.binder eq that.binder
case _ => false
}
- override def toString = s"RefinedThis($level, ${binder.hashCode})"
+ override def toString = s"RefinedThis(${binder.hashCode})"
}
// ------------ Type variables ----------------------------------------
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 2bea977f7..62ad39c07 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -660,8 +660,12 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
val parent = parents.reduceLeft(AndType(_, _))
if (decls.isEmpty) parent
else {
- def addRefinement(tp: Type, sym: Symbol) =
- RefinedType(tp, sym.name, ctx.thisToRefinedThis(_, clazz, 0)(sym.info))
+ def addRefinement(tp: Type, sym: Symbol) = {
+ def subst(info: Type, rt: RefinedType) =
+ if (clazz.isClass) info.substThis(clazz.asClass, RefinedThis(rt))
+ else info // turns out some symbols read into `clazz` are not classes, not sure why this is the case.
+ RefinedType(tp, sym.name, subst(sym.info, _))
+ }
(parent /: decls.toList)(addRefinement).asInstanceOf[RefinedType]
}
case CLASSINFOtpe =>
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index fd6ba44a7..77a308bba 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -207,8 +207,11 @@ class PlainPrinter(_ctx: Context) extends Printer {
toText(value)
case MethodParam(mt, idx) =>
nameString(mt.paramNames(idx))
- case RefinedThis(_, level) =>
- s"this<$level>"
+ case sk: RefinedThis =>
+ sk.binder match {
+ case rt: RefinedType => s"${nameString(rt.typeSymbol)}{...}.this"
+ case _ => "<skolem>"
+ }
}
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index dd05fea3f..0ff47b36d 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -791,7 +791,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
checkRefinementNonCyclic(refinement, refineCls, seen)
val rsym = refinement.symbol
val rinfo = if (rsym is Accessor) rsym.info.resultType else rsym.info
- RefinedType(parent, rsym.name, ctx.thisToRefinedThis(_, refineCls, 0)(rinfo))
+ RefinedType(parent, rsym.name, rt => rinfo.substThis(refineCls, RefinedThis(rt)))
// todo later: check that refinement is within bounds
}
val res = cpy.RefinedTypeTree(tree)(tpt1, refinements1) withType