From 14f6eb056f9959f178134762e0c6ce78e1dccc28 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 3 Jan 2015 19:08:03 +0100 Subject: 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. --- src/dotty/tools/dotc/core/Substituters.scala | 80 +++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 8 deletions(-) (limited to 'src/dotty/tools/dotc/core/Substituters.scala') 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 -- cgit v1.2.3