TL; DR:
privatedeclarations 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
Loudfrom anywhere with fully-qualified nametop.pkg.Loud import top.pkg._would pick it up- inside the package
top.pkgone 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:
privateto a virtual object scope constituted of all top-level declaraionsprivateto the top-level of the current compilation unit (i.e. file)privateto the current compilation unit (including nested scopes)privateto 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!