From f196e074c41f7ccde118dcf6764898a2c26fda3a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 4 Mar 2014 13:49:45 +0100 Subject: Fix of #39 Two fixes: 1) Avoid the infinite recursion in checkAccessible if the accessibility check fails. 2) Make accessibility succeed for the test, and in general if the target denotation does not have a symbol. Added original test in pos and a negative test which makes accessibility fail. --- src/dotty/tools/dotc/core/Denotations.scala | 2 +- src/dotty/tools/dotc/typer/Typer.scala | 69 +++++++++++++++-------------- 2 files changed, 37 insertions(+), 34 deletions(-) (limited to 'src/dotty') diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 9c8de3829..00b6815e7 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -393,7 +393,7 @@ object Denotations { exists && p(this) def accessibleFrom(pre: Type, superAccess: Boolean)(implicit ctx: Context): Denotation = - if (symbol isAccessibleFrom (pre, superAccess)) this else NoDenotation + if (!symbol.exists || symbol.isAccessibleFrom(pre, superAccess)) this else NoDenotation def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation = if (sig matches signature) this else NoDenotation diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 96fe73e7d..6cc3a226e 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -116,40 +116,43 @@ class Typer extends Namer with Applications with Implicits { * current context. Return the type with those alternatives as denotations * which are accessible. */ - def checkAccessible(tpe: Type, superAccess: Boolean, pos: Position)(implicit ctx: Context): Type = tpe match { - case tpe: NamedType => - val pre = tpe.prefix - val name = tpe.name - val d = tpe.denot.accessibleFrom(pre, superAccess) - if (!d.exists) { - val d2 = pre.nonPrivateMember(name) - if (reallyExists(d2) && (d2 ne tpe.denot)) - checkAccessible(pre.select(name, d2), superAccess, pos) - else { - val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists) - val what = alts match { - case Nil => - name.toString - case sym :: Nil => - if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated - case _ => - i"none of the overloaded alternatives named $name" + def checkAccessible(tpe: Type, superAccess: Boolean, pos: Position)(implicit ctx: Context): Type = { + def test(tpe: Type, firstTry: Boolean): Type = tpe match { + case tpe: NamedType => + val pre = tpe.prefix + val name = tpe.name + val d = tpe.denot.accessibleFrom(pre, superAccess) + if (!d.exists) { + // it could be that we found an inaccessbile private member, but there is + // an inherited non-private member with the same name and signature. + val d2 = pre.nonPrivateMember(name) + if (reallyExists(d2) && firstTry) test(pre.select(name, d2), false) + else { + val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists) + val what = alts match { + case Nil => + name.toString + case sym :: Nil => + if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated + case _ => + i"none of the overloaded alternatives named $name" + } + val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else "" + val whyNot = new StringBuffer + val addendum = + alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) + if (!tpe.isError) + ctx.error(i"$what cannot be accessed as a member of $pre$where.$whyNot", pos) + ErrorType } - val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else "" - val whyNot = new StringBuffer - val addendum = - alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) - if (!tpe.isError) - ctx.error(i"$what cannot be accessed as a member of $pre$where.$whyNot", pos) - ErrorType - } - } - else if (d.symbol is TypeParamAccessor) // always dereference type param accessors - checkAccessible(d.info.bounds.hi, superAccess, pos) - else - tpe withDenot d - case _ => - tpe + } else if (d.symbol is TypeParamAccessor) // always dereference type param accessors + checkAccessible(d.info.bounds.hi, superAccess, pos) + else + tpe withDenot d + case _ => + tpe + } + test(tpe, true) } /** The enclosing class, except if we are in a super call, in which case -- cgit v1.2.3