Skip to content

Commit 9f4166f

Browse files
authored
Merge pull request #3735 from dotty-staging/fix-#3339-1
Fix #3339: Disallow accesses to private package members from nested pkgs
2 parents 55f8819 + 894d779 commit 9f4166f

File tree

3 files changed

+31
-10
lines changed

3 files changed

+31
-10
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -674,10 +674,7 @@ object SymDenotations {
674674
final def isAccessibleFrom(pre: Type, superAccess: Boolean = false, whyNot: StringBuffer = null)(implicit ctx: Context): Boolean = {
675675

676676
/** Are we inside definition of `boundary`? */
677-
def accessWithin(boundary: Symbol) =
678-
ctx.owner.isContainedIn(boundary) &&
679-
(!(this is JavaDefined) || // disregard package nesting for Java
680-
ctx.owner.enclosingPackageClass == boundary.enclosingPackageClass)
677+
def accessWithin(boundary: Symbol) = ctx.owner.isContainedIn(boundary)
681678

682679
/** Are we within definition of linked class of `boundary`? */
683680
def accessWithinLinked(boundary: Symbol) = {
@@ -733,7 +730,9 @@ object SymDenotations {
733730
( !(this is Local)
734731
|| (owner is ImplClass) // allow private local accesses to impl class members
735732
|| isCorrectThisType(pre)
736-
)
733+
) &&
734+
(!(this.is(Private) && owner.is(Package)) ||
735+
owner == ctx.owner.enclosingPackageClass)
737736
|| (this is Protected) &&
738737
( superAccess
739738
|| pre.isInstanceOf[ThisType]

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,19 +195,30 @@ trait TypeAssigner {
195195
TryDynamicCallType
196196
} else {
197197
val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists)
198+
var packageAccess = false
198199
val what = alts match {
199200
case Nil =>
200-
name.toString
201+
i"$name cannot be accessed as a member of $pre"
201202
case sym :: Nil =>
202-
if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated
203+
if (sym.owner.is(Package)) {
204+
packageAccess = true
205+
i"${sym.showLocated} cannot be accessed"
206+
}
207+
else {
208+
val symStr = if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated
209+
i"$symStr cannot be accessed as a member of $pre"
210+
}
203211
case _ =>
204-
em"none of the overloaded alternatives named $name"
212+
em"none of the overloaded alternatives named $name can be accessed as members of $pre"
205213
}
206-
val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else ""
214+
val where =
215+
if (!ctx.owner.exists) ""
216+
else if (packageAccess) i" from nested ${ctx.owner.enclosingPackageClass}"
217+
else i" from ${ctx.owner.enclosingClass}"
207218
val whyNot = new StringBuffer
208219
alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot))
209220
if (tpe.isError) tpe
210-
else errorType(ex"$what cannot be accessed as a member of $pre$where.$whyNot", pos)
221+
else errorType(ex"$what$where.$whyNot", pos)
211222
}
212223
}
213224
else ctx.makePackageObjPrefixExplicit(tpe withDenot d)

tests/neg/i3339.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package outer {
2+
private class A
3+
4+
package inner {
5+
object Test {
6+
def main(args: Array[String]): Unit = {
7+
println(new A) // error: cannot access
8+
}
9+
}
10+
}
11+
}

0 commit comments

Comments
 (0)