aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Substituters.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-01-03 19:08:03 +0100
committerMartin Odersky <odersky@gmail.com>2015-01-03 19:08:03 +0100
commit14f6eb056f9959f178134762e0c6ce78e1dccc28 (patch)
treee5bb86e185a023604890c1c03252906e7e4e5aab /src/dotty/tools/dotc/core/Substituters.scala
parenta7a603fc8ec431b261e7bceddfb61a935d8ad07b (diff)
downloaddotty-14f6eb056f9959f178134762e0c6ce78e1dccc28.tar.gz
dotty-14f6eb056f9959f178134762e0c6ce78e1dccc28.tar.bz2
dotty-14f6eb056f9959f178134762e0c6ce78e1dccc28.zip
Make findMember depend on RefinedThis level.
When doing a findMember we now look at the level of a RefinedThis instead of its `rt` field. This required several fixes to how levels are assigned to RefinedThis types.
Diffstat (limited to 'src/dotty/tools/dotc/core/Substituters.scala')
-rw-r--r--src/dotty/tools/dotc/core/Substituters.scala80
1 files changed, 72 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala
index 119aca569..9fd01ab56 100644
--- a/src/dotty/tools/dotc/core/Substituters.scala
+++ b/src/dotty/tools/dotc/core/Substituters.scala
@@ -1,6 +1,6 @@
package dotty.tools.dotc.core
-import Types._, Symbols._, Contexts._
+import Types._, Symbols._, Contexts._, Names._
/** Substitution operations on types. See the corresponding `subst` and
* `substThis` methods on class Type for an explanation.
@@ -179,7 +179,9 @@ trait Substituters { this: Context =>
.mapOver(tp)
}
- final def substThis(tp: Type, from: RefinedType, to: Type, theMap: SubstRefinedThisMap): Type =
+ // !!! TODO remove once we are sure new RefinedThis scheme works and we drop the ref to
+ // 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)
@@ -190,16 +192,39 @@ trait Substituters { this: Context =>
else tp
case tp: NamedType =>
if (tp.currentSymbol.isStatic) tp
- else tp.derivedSelect(substThis(tp.prefix, from, to, theMap))
+ else tp.derivedSelect(substThis0(tp.prefix, from, to, theMap))
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
- tp.derivedRefinedType(substThis(tp.parent, from, to, theMap), tp.refinedName, substThis(tp.refinedInfo, from, to, theMap))
+ tp.derivedRefinedType(substThis0(tp.parent, from, to, theMap), tp.refinedName, substThis0(tp.refinedInfo, from, to, theMap))
case tp: TypeAlias =>
- tp.derivedTypeAlias(substThis(tp.alias, from, to, theMap))
+ tp.derivedTypeAlias(substThis0(tp.alias, from, to, theMap))
case _ =>
- (if (theMap != null) theMap else new SubstRefinedThisMap(from, to))
+ (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 =
@@ -271,8 +296,13 @@ trait Substituters { this: Context =>
def apply(tp: Type): Type = substThis(tp, from, to, this)
}
- final class SubstRefinedThisMap(from: RefinedType, to: Type) extends DeepTypeMap {
- def apply(tp: Type): Type = substThis(tp, from, to, this)
+ final class SubstRefinedThisMap0(from: RefinedType, to: Type) extends DeepTypeMap {
+ 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 {
@@ -282,4 +312,38 @@ 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