TL; DR:
private
declarations at a top-level scope of a package in Scala 3 are equivalent to aprivate[pkg]
in other contexts.- They are accessible to everything within the package and its subpackages, but nothing else.
In Scala 2, to place a declaration at the "package" level, one would define a "package object":
package top
package object pkg {
private val Hush = 0
val Loud = Int.MaxValue
}
Given this
- one might refer to
Loud
from anywhere with fully-qualified nametop.pkg.Loud
import top.pkg._
would pick it up- inside the package
top.pkg
one coul refer to it simply asLoud
So far, so intuitive.
In Scala 2, the semantics of private val Loud
was also intuitive. A package object
is just an object
. A private
member of an object
is only visible within that object
's scope. While the Scala compiler does some magic to make nonprivate declarations more broadly visible, access to private
members of the package object
was restricted to the object
in the ordinary way.
But Scala 3 introduces "naked" top-level declarations, which I find I use constantly.
So the declarations above might translate to:
package top.pkg
private val Hush = 0
val Loud = Int.MaxValue
There is no object
scope! So what does private even mean in this context.
I could imagine four possibilities:
private
to a virtual object scope constituted of all top-level declaraionsprivate
to the top-level of the current compilation unit (i.e. file)private
to the current compilation unit (including nested scopes)private
to the package as a whole, i.e. the same asprivate[pkg]
Playing around, it looks like #4 is the winner.
A private
top-level declaration seems visible to any code in the package, even if defined in other files or directories. It is visible from anywhere in the pkg
or subpackages of pkg
.
So now I know! And so do you!