diff options
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Scopes.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 31 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 40 | ||||
-rw-r--r-- | test/test/ShowClassTests.scala | 4 | ||||
-rw-r--r-- | tests/pos/typers.scala | 15 |
7 files changed, 69 insertions, 34 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 889396e1c..79899f70a 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -518,7 +518,6 @@ object Denotations { if (denots.containsSig(signature)) NoDenotation else this def mapInherited(ownDenots: PreDenotation, prevDenots: PreDenotation, pre: Type)(implicit ctx: Context): SingleDenotation = if (hasUniqueSym && prevDenots.containsSym(symbol)) NoDenotation - else if (overlaps(Private)) NoDenotation else if (isType) filterDisjoint(ownDenots).asSeenFrom(pre) else asSeenFrom(pre).filterDisjoint(ownDenots) final def filterExcluded(excluded: FlagSet)(implicit ctx: Context): SingleDenotation = diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala index b1b81c4a9..ef1ddc8b3 100644 --- a/src/dotty/tools/dotc/core/Scopes.scala +++ b/src/dotty/tools/dotc/core/Scopes.scala @@ -14,6 +14,7 @@ import Periods._ import Decorators._ import Contexts._ import Denotations._ +import SymDenotations._ import printing.Texts._ import printing.Printer import SymDenotations.NoDenotation @@ -102,11 +103,12 @@ object Scopes { } /** The denotation set of all the symbols with given name in this scope */ - final def denotsNamed(name: Name)(implicit ctx: Context): PreDenotation = { + final def denotsNamed(name: Name, select: SymDenotation => Boolean = selectAll)(implicit ctx: Context): PreDenotation = { var syms: PreDenotation = NoDenotation var e = lookupEntry(name) while (e != null) { - syms = syms union e.sym.denot + val d = e.sym.denot + if (select(d)) syms = syms union d e = lookupNextEntry(e) } syms @@ -340,6 +342,10 @@ object Scopes { */ def scopeTransform(owner: Symbol)(op: => MutableScope): MutableScope = op + val selectAll: SymDenotation => Boolean = Function.const(true) + val selectPrivate: SymDenotation => Boolean = d => (d is Flags.Private) + val selectNonPrivate: SymDenotation => Boolean = d => !(d is Flags.Private) + /** The empty scope (immutable). */ object EmptyScope extends Scope { diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index a3ce8af6e..c36727c2b 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -385,9 +385,9 @@ object SymDenotations { /** Are we inside definition of `boundary`? */ def accessWithin(boundary: Symbol) = - owner.isContainedIn(boundary) && + ctx.owner.isContainedIn(boundary) && (!(this is JavaDefined) || // disregard package nesting for Java - owner.enclosingPackage == boundary.enclosingPackage) + ctx.owner.enclosingPackage == boundary.enclosingPackage) /** Are we within definition of linked class of `boundary`? */ def accessWithinLinked(boundary: Symbol) = { @@ -938,21 +938,30 @@ object SymDenotations { * The elements of the returned pre-denotation all * have existing symbols. */ - final def membersNamed(name: Name)(implicit ctx: Context): PreDenotation = + final def membersNamed(name: Name)(implicit ctx: Context): PreDenotation = { + val privates = decls.denotsNamed(name, selectPrivate) + privates union nonPrivateMembersNamed(name).filterDisjoint(privates) + } + + /** All non-private members of this class that have the given name. + * The elements of the returned pre-denotation all + * have existing symbols. + */ + final def nonPrivateMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = if (Config.cacheMembersNamed) { var denots: PreDenotation = memberCache lookup name if (denots == null) { - denots = computeMembersNamed(name) + denots = computeNPMembersNamed(name) memberCache enter (name, denots) } denots - } else computeMembersNamed(name) + } else computeNPMembersNamed(name) - private def computeMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = + private def computeNPMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = if (!classSymbol.hasChildren || !Config.useFingerPrints || (memberFingerPrint contains name)) { - val ownDenots = decls.denotsNamed(name) + val ownDenots = decls.denotsNamed(name, selectNonPrivate) if (debugTrace) // DEBUG println(s"$this.member($name), ownDenots = $ownDenots") def collect(denots: PreDenotation, parents: List[TypeRef]): PreDenotation = parents match { @@ -973,10 +982,10 @@ object SymDenotations { else collect(ownDenots, classParents) } else NoDenotation - override final def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation = - //ctx.typeComparer.traceIndented(s"($this).findMember($name, $pre)") { // DEBUG - membersNamed(name).filterExcluded(excluded).asSeenFrom(pre).toDenot(pre) - //} + override final def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation = { + val raw = if (excluded is Private) nonPrivateMembersNamed(name) else membersNamed(name) + raw.filterExcluded(excluded).asSeenFrom(pre).toDenot(pre) + } private[this] var baseTypeCache: java.util.HashMap[CachedType, Type] = null private[this] var baseTypeValid: RunId = NoRunId diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 64fa4d3ec..9d3cf898d 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -596,7 +596,7 @@ object Types { def underlyingIfRepeated(implicit ctx: Context): Type = this.translateParameterized(defn.RepeatedParamClass, defn.SeqClass) - /** If this is a (possibly aliased, annotated, and parameterized) reference to + /** If this is a (possibly aliased, annotated, and/or parameterized) reference to * a class, the class type ref, otherwise NoType. */ def underlyingClassRef(implicit ctx: Context): Type = dealias match { diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 4117b0384..730314bda 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -89,8 +89,7 @@ class Typer extends Namer with Applications with Implicits { */ def checkedSelectionType(qual1: Tree, tree: untpd.RefTree)(implicit ctx: Context): Type = { val ownType = selectionType(qual1.tpe.widenIfUnstable, tree.name, tree.pos) - if (!ownType.isError) checkAccessible(ownType, qual1.isInstanceOf[Super], tree.pos) - ownType + checkAccessible(ownType, qual1.isInstanceOf[Super], tree.pos) } /** Check that Java statics and packages can only be used in selections. @@ -102,7 +101,8 @@ class Typer extends Namer with Applications with Implicits { } /** If `tpe` is a named type, check that its denotation is accessible in the - * current context. + * 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 => @@ -110,21 +110,27 @@ class Typer extends Namer with Applications with Implicits { val name = tpe.name val d = tpe.denot.accessibleFrom(pre, superAccess) if (!d.exists) { - val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists) - val where = pre.typeSymbol - val what = alts match { - case Nil => - name.toString - case sym :: Nil => - if (sym.owner == where) sym.show else sym.showLocated - case _ => - i"none of the overloaded alternatives named $name" + val d2 = pre.nonPrivateMember(name) + if (reallyExists(d2)) + checkAccessible(pre.select(name, d2), superAccess, pos) + else { + val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists) + val where = pre.typeSymbol + val what = alts match { + case Nil => + name.toString + case sym :: Nil => + if (sym.owner == where) sym.show else sym.showLocated + case _ => + i"none of the overloaded alternatives named $name" + } + val whyNot = new StringBuffer + val addendum = + alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) + if (!tpe.isError) + ctx.error(i"$what cannot be accessed from $pre.$whyNot", pos) + ErrorType } - val whyNot = new StringBuffer - val addendum = - alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) - ctx.error(i"$what cannot be accessed from $pre.$whyNot", pos) - ErrorType } else if (d.symbol is TypeParamAccessor) // always dereference type param accessors checkAccessible(d.info.bounds.hi, superAccess, pos) diff --git a/test/test/ShowClassTests.scala b/test/test/ShowClassTests.scala index 93d8213c6..f36d38d43 100644 --- a/test/test/ShowClassTests.scala +++ b/test/test/ShowClassTests.scala @@ -122,12 +122,12 @@ class ShowClassTests extends DottyTest { */ @Test def showScala() = { - showPackage("scala", 1) + showPackage("scala", 3) } @Test def loadDotty() = { - showPackage("dotty", 2) + showPackage("dotty", 6) } diff --git a/tests/pos/typers.scala b/tests/pos/typers.scala index c3101ea2c..fd2cc9b74 100644 --- a/tests/pos/typers.scala +++ b/tests/pos/typers.scala @@ -63,5 +63,20 @@ object typers { class Refinements { val y: C { type T; val key: T; def process(x: T): Int } } + + object Accessibility { + + class A { + val x: String = "abc" + } + + class B extends A { + private def x: Int = 1 + } + + val b: B = new B + val y = b.x + + } }
\ No newline at end of file |