diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 17390f830ecf..128f884d53aa 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -674,10 +674,7 @@ object SymDenotations { final def isAccessibleFrom(pre: Type, superAccess: Boolean = false, whyNot: StringBuffer = null)(implicit ctx: Context): Boolean = { /** Are we inside definition of `boundary`? */ - def accessWithin(boundary: Symbol) = - ctx.owner.isContainedIn(boundary) && - (!(this is JavaDefined) || // disregard package nesting for Java - ctx.owner.enclosingPackageClass == boundary.enclosingPackageClass) + def accessWithin(boundary: Symbol) = ctx.owner.isContainedIn(boundary) /** Are we within definition of linked class of `boundary`? */ def accessWithinLinked(boundary: Symbol) = { @@ -733,7 +730,9 @@ object SymDenotations { ( !(this is Local) || (owner is ImplClass) // allow private local accesses to impl class members || isCorrectThisType(pre) - ) + ) && + (!(this.is(Private) && owner.is(Package)) || + owner == ctx.owner.enclosingPackageClass) || (this is Protected) && ( superAccess || pre.isInstanceOf[ThisType] diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 59210fde2ea7..483140e3069a 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -195,19 +195,30 @@ trait TypeAssigner { TryDynamicCallType } else { val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists) + var packageAccess = false val what = alts match { case Nil => - name.toString + i"$name cannot be accessed as a member of $pre" case sym :: Nil => - if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated + if (sym.owner.is(Package)) { + packageAccess = true + i"${sym.showLocated} cannot be accessed" + } + else { + val symStr = if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated + i"$symStr cannot be accessed as a member of $pre" + } case _ => - em"none of the overloaded alternatives named $name" + em"none of the overloaded alternatives named $name can be accessed as members of $pre" } - val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else "" + val where = + if (!ctx.owner.exists) "" + else if (packageAccess) i" from nested ${ctx.owner.enclosingPackageClass}" + else i" from ${ctx.owner.enclosingClass}" val whyNot = new StringBuffer alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) if (tpe.isError) tpe - else errorType(ex"$what cannot be accessed as a member of $pre$where.$whyNot", pos) + else errorType(ex"$what$where.$whyNot", pos) } } else ctx.makePackageObjPrefixExplicit(tpe withDenot d) diff --git a/tests/neg/i3339.scala b/tests/neg/i3339.scala new file mode 100644 index 000000000000..7494df2b6f99 --- /dev/null +++ b/tests/neg/i3339.scala @@ -0,0 +1,11 @@ +package outer { + private class A + + package inner { + object Test { + def main(args: Array[String]): Unit = { + println(new A) // error: cannot access + } + } + } +}