From e8a160c8c64354b12423b908067a1ba328d6248f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 24 Oct 2013 20:09:30 +0200 Subject: Fixed problem in handing of self types. Self types were not taken into account when doing a typedIdent. The fix in typedIdent caused as CyclicReference when typing the self type itself. This in turn is fixed by distinguishing more carefully in denotNamed in Namer which context we are in. --- src/dotty/tools/dotc/core/SymDenotations.scala | 1 + src/dotty/tools/dotc/core/Types.scala | 4 +++- src/dotty/tools/dotc/typer/Applications.scala | 8 ++++---- src/dotty/tools/dotc/typer/Namer.scala | 11 ++++++++--- src/dotty/tools/dotc/typer/Typer.scala | 14 ++++++-------- tests/pos/selftypes.scala | 20 ++++++++++++++++++++ 6 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 tests/pos/selftypes.scala diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index ab58ec3b0..9c5970596 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -107,6 +107,7 @@ object SymDenotations { myFlags |= Touched Context.theBase.initialCtx.debugTraceIndented(s"completing ${this.debugString}") { + // println("completing " + debugString) try completer.complete(this) // !!! DEBUG catch { case ex: java.io.IOException => diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 9b1c73bbd..0edb4b0cc 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -2414,7 +2414,9 @@ object Types { .stripMargin) class CyclicReference(val denot: SymDenotation) - extends FatalTypeError(s"cyclic reference involving $denot") + extends FatalTypeError(s"cyclic reference involving $denot") { + printStackTrace() + } class MergeError(msg: String) extends FatalTypeError(msg) diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 648713571..0abaa17fe 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -204,10 +204,10 @@ trait Applications extends Compatibility { self: Typer => def findDefault(cx: Context): Type = { if (cx eq NoContext) NoType else if (cx.scope != cx.outer.scope && - cx.denotsNamed(methRef.name) - .filterWithPredicate(_.symbol == meth).exists) { - val denot = cx.denotsNamed(getterName).toDenot(NoPrefix) - NamedType(NoPrefix, getterName).withDenot(denot) + cx.denotNamed(methRef.name).hasAltWith(_.symbol == meth)) { + val denot = cx.denotNamed(getterName) + assert(denot.exists) + NamedType(cx.owner.thisType, getterName).withDenot(denot) } else findDefault(cx.outer) } findDefault(ctx) diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 79b1750dc..fb2aef90d 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -26,9 +26,14 @@ trait NamerContextOps { this: Context => sym } - def denotsNamed(name: Name): PreDenotation = - if (owner.isClass) owner.asClass.membersNamed(name) - else scope.denotsNamed(name) + def denotNamed(name: Name): Denotation = + if (owner.isClass) + if (outer.owner == owner) + owner.thisType.member(name) + else // we are in the outermost context belonging to a class; self is invisible here. See inClassContext. + owner.findMember(name, owner.thisType, EmptyFlags) + else + scope.denotsNamed(name).toDenot(NoPrefix) def effectiveScope = if (owner != null && owner.isClass) owner.asClass.decls diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index bb3e1052a..a22d128e3 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -269,8 +269,8 @@ class Typer extends Namer with Applications with Implicits { /** Is (some alternative of) the given predenotation `denot` * defined in current compilation unit? */ - def isDefinedInCurrentUnit(denot: PreDenotation): Boolean = denot match { - case DenotUnion(d1, d2) => isDefinedInCurrentUnit(d1) || isDefinedInCurrentUnit(d2) + def isDefinedInCurrentUnit(denot: Denotation): Boolean = denot match { + case MultiDenotation(d1, d2) => isDefinedInCurrentUnit(d1) || isDefinedInCurrentUnit(d2) case denot: SingleDenotation => denot.symbol.sourceFile == ctx.source } @@ -279,13 +279,11 @@ class Typer extends Namer with Applications with Implicits { else { val outer = ctx.outer if ((ctx.scope ne outer.scope) || (ctx.owner ne outer.owner)) { - val defDenots = ctx.denotsNamed(name) - if (defDenots.exists) { + val defDenot = ctx.denotNamed(name) + if (defDenot.exists) { val curOwner = ctx.owner - val pre = curOwner.thisType - val defDenot = defDenots toDenot pre - val found = NamedType(pre, name) withDenot defDenot - if (!(curOwner is Package) || (defDenot.symbol is Package) || isDefinedInCurrentUnit(defDenots)) + val found = NamedType(curOwner.thisType, name) withDenot defDenot + if (!(curOwner is Package) || (defDenot.symbol is Package) || isDefinedInCurrentUnit(defDenot)) return checkNewOrShadowed(found, definition) // no need to go further out, we found highest prec entry else if (prevPrec < packageClause) return findRef(found, packageClause, ctx)(outer) diff --git a/tests/pos/selftypes.scala b/tests/pos/selftypes.scala new file mode 100644 index 000000000..243405f77 --- /dev/null +++ b/tests/pos/selftypes.scala @@ -0,0 +1,20 @@ +object selftypes { + + trait A { self: AB => + + type AA = List[this.BX] + + class AX + + } + + trait B { self: AB => + + type BB = AA + + class BX + } + + class AB extends A with B + +} \ No newline at end of file -- cgit v1.2.3