"public within module" modifier

In Scala, the visibility modifiers are public (default), private, protected, protected[scope] and private[scope]. Using modifiers like private with no scope allows the compiler to detect dead code - which I assume is relatively easy, as you just need to verify that there are no references to a symbol in the generated bytecode.

This works well on symbols that are indeed meant to be private and aren’t exposed to other files, packages or libraries - but many developers work on Scala applications, where most things are public or package-scoped, and there is little to no tooling that would detect unused definitions there.

Applications often don’t publish Scala APIs, but rather get packaged into Docker images, or anything else which only requires public access to a Main object.

I think It would be great if we could specify that a symbol is not to be used outside the current module, or outside the current project (I assume the latter would be difficult to implement, given the compiler has no knowledge of build tools).

This could be done either with a compiler setting (project/module-wide), which would be applied to all definitions in that module, or with a new visibility modifier (Rust’s pub(crate) has similar semantics), or presumably an annotation of some sort.

Tooling (ideally: the compiler) could then analyze references to such a symbol, and if it doesn’t find any, emit a warning - “this method is unused in this project” or similar.

I think this would allow for finding code paths that are long dead, especially in larger projects - one unused method may be the only user of other methods (even private ones), so the only reason they’re still in the code would be that a method is seemingly public - even though it can’t possibly be used outside the project, as it’s not being published.

I would appreciate feedback on this idea, especially from the compiler teams - if this sounds like something possible and desirable in Scala, I can try to write an official SIP :slight_smile:

6 Likes

I’ve seen a project about that - https://github.com/rorygraves/ScalaClean but I’ve no idea about its current status

Related: Idea: App mode for the compiler

1 Like

It’s much more specific, but could the dead-code elimination in ScalaJS help here? You specify your entrypoints and it eliminates any code that is not reachable from those entrypoints.

2 Likes

My point is not to just eliminate the code from the result, but to also know what code it was so it can be removed :slight_smile:

2 Likes

Late reply. Yes wasn’t suggesting it automatically remove it, but was curious if the existing code could be reused for this purpose. If it can remove it because it knows it’s unused, I would think it would be able to return a list of variables/methods that aren’t used.

1 Like