aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala1
-rw-r--r--src/dotty/tools/dotc/core/Scopes.scala10
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala31
-rw-r--r--src/dotty/tools/dotc/core/Types.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala40
-rw-r--r--test/test/ShowClassTests.scala4
-rw-r--r--tests/pos/typers.scala15
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