From 95f74c2a999b20ee5f6ddbe6e14511872e8c227f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 1 Jan 2015 14:47:52 +0100 Subject: Provide the correct levels for RefinedThis types. --- src/dotty/tools/dotc/core/Substituters.scala | 9 +++++++-- src/dotty/tools/dotc/core/TypeApplications.scala | 4 ++-- src/dotty/tools/dotc/core/TypeComparer.scala | 4 ++-- src/dotty/tools/dotc/core/TypeOps.scala | 17 ++++++++++++++++- src/dotty/tools/dotc/core/Types.scala | 10 +++++++--- src/dotty/tools/dotc/core/pickling/UnPickler.scala | 14 +++----------- src/dotty/tools/dotc/typer/Typer.scala | 2 +- 7 files changed, 38 insertions(+), 22 deletions(-) (limited to 'src/dotty/tools') diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala index 205188507..119aca569 100644 --- a/src/dotty/tools/dotc/core/Substituters.scala +++ b/src/dotty/tools/dotc/core/Substituters.scala @@ -181,8 +181,13 @@ trait Substituters { this: Context => final def substThis(tp: Type, from: RefinedType, to: Type, theMap: SubstRefinedThisMap): Type = tp match { - case tp @ RefinedThis(rt, _) => - if (rt eq from) to else tp + 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: NamedType => if (tp.currentSymbol.isStatic) tp else tp.derivedSelect(substThis(tp.prefix, from, to, theMap)) diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 6443c5054..21aa5960e 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -409,7 +409,7 @@ class TypeApplications(val self: Type) extends AnyVal { def replacements(rt: RefinedType): List[Type] = for (sym <- boundSyms) - yield TypeRef(RefinedThis(rt), correspondingParamName(sym)) + yield TypeRef(RefinedThis(rt, 0), correspondingParamName(sym)) def rewrite(tp: Type): Type = tp match { case tp @ RefinedType(parent, name: TypeName) => @@ -453,7 +453,7 @@ class TypeApplications(val self: Type) extends AnyVal { val lambda = defn.lambdaTrait(boundSyms.map(_.variance)) val substitutedRHS = (rt: RefinedType) => { val argRefs = boundSyms.indices.toList.map(i => - RefinedThis(rt).select(tpnme.lambdaArgName(i))) + RefinedThis(rt, 0).select(tpnme.lambdaArgName(i))) tp.subst(boundSyms, argRefs).bounds.withVariance(1) } val res = RefinedType(lambda.typeRef, tpnme.Apply, substitutedRHS) diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index b8cc45fa7..85c57b744 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -309,7 +309,7 @@ class TypeComparer(initctx: Context) extends DotClass { } private def narrowRefined(tp: Type): Type = tp match { - case tp: RefinedType => RefinedThis(tp) + case tp: RefinedType => RefinedThis(tp, 0) // !!! TODO check that we can drop narrowRefined entirely case _ => tp } @@ -323,7 +323,7 @@ class TypeComparer(initctx: Context) extends DotClass { def rebaseFrom(prefix: Type): Type = { rebaseQual(prefix, tp.name, considerBoth = true) match { case rt: RefinedType if rt ne prefix => - tp.derivedSelect(RefinedThis(rt)).dealias // dealias to short-circuit cycles spanning type aliases or LazyRefs + tp.derivedSelect(RefinedThis(rt, 0)).dealias // dealias to short-circuit cycles spanning type aliases or LazyRefs case _ => tp } } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 260e2f6d6..88f495f47 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -330,7 +330,22 @@ 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 469e8ca01..d1b2e8f1e 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1805,7 +1805,7 @@ object Types { && !parent.isLambda) derivedRefinedType(parent.EtaExpand, refinedName, refinedInfo) else - RefinedType(parent, refinedName, rt => refinedInfo.substThis(this, RefinedThis(rt))) + RefinedType(parent, refinedName, rt => refinedInfo.substThis(this, RefinedThis(rt, -1))) // !!! TODO: replace with simply `refinedInfo` } override def equals(that: Any) = that match { @@ -2201,10 +2201,14 @@ object Types { override def computeHash = doHash(paramNum, binder) } - case class RefinedThis(binder: RefinedType, level: Int = 0) extends BoundType with SingletonType { + /** A reference to the `this` of an enclosing refined type. + * @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 { type BT = RefinedType override def underlying(implicit ctx: Context) = binder - def copyBoundType(bt: BT) = RefinedThis(bt) + def copyBoundType(bt: BT) = RefinedThis(bt, level) // need to customize hashCode and equals to prevent infinite recursion for // refinements that refer to the refinement type via this diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 728048700..2bea977f7 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -158,9 +158,6 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: /** A map from symbols to their associated `decls` scopes */ private val symScopes = mutable.AnyRefMap[Symbol, Scope]() - /** A map from refinement classes to their associated refinement types */ - private val refinementTypes = mutable.AnyRefMap[Symbol, RefinedType]() - protected def errorBadSignature(msg: String, original: Option[RuntimeException] = None)(implicit ctx: Context) = { val ex = new BadSignature( sm"""error reading Scala signature of $classRoot from $source: @@ -612,9 +609,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: case NOPREFIXtpe => NoPrefix case THIStpe => - val cls = readSymbolRef().asClass - if (isRefinementClass(cls)) RefinedThis(refinementTypes(cls)) - else cls.thisType + readSymbolRef().thisType case SINGLEtpe => val pre = readTypeRef() val sym = readDisambiguatedSymbolRef(_.info.isParameterless) @@ -666,11 +661,8 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: if (decls.isEmpty) parent else { def addRefinement(tp: Type, sym: Symbol) = - RefinedType(tp, sym.name, sym.info) - val result = (parent /: decls.toList)(addRefinement).asInstanceOf[RefinedType] - assert(!refinementTypes.isDefinedAt(clazz), clazz + "/" + decls) - refinementTypes(clazz) = result - result + RefinedType(tp, sym.name, ctx.thisToRefinedThis(_, clazz, 0)(sym.info)) + (parent /: decls.toList)(addRefinement).asInstanceOf[RefinedType] } case CLASSINFOtpe => val clazz = readSymbolRef() diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 0ff47b36d..dd05fea3f 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, rt => rinfo.substThis(refineCls, RefinedThis(rt))) + RefinedType(parent, rsym.name, ctx.thisToRefinedThis(_, refineCls, 0)(rinfo)) // todo later: check that refinement is within bounds } val res = cpy.RefinedTypeTree(tree)(tpt1, refinements1) withType -- cgit v1.2.3