Idea: pub(impl) visibility modifier on methods

Idea: pub(impl) Visibility Modifier on Methods

The Problem

I find myself often in need of utility methods for single or a small set of methods. However, I usually find it disturbing that theoretically other methods could call those utility methods and that I am in need of docs to make sure they are not called out of place from within the other methods of the same type.

Current "Solutions" and their Problems

  • Create new submodule to encapsulate those utility methods and their purposeful users:
    • Inline submodules create a lot of indentation.
    • Out-of-line submodules require yet another file.
    • Both above solutions create a lot of friction in a code base and I usually try to avoid them.
  • Nested inner functions:
    • Nested functions of methods can be used to create utility functions that can only be used within that function. However, it is not possible to share those inner functions between a (small) set of user functions.
    • Furthermore nested inner functions are ... functions and not methods which again causes lots of friction.
    • Causes a lot of unnecessary indentation.
  • Using closures:
    • This is very similar to the above nested inner functions but with the difference of capturing state among which can be self itself. Closures for this purpose however, come with their own set of problems.

The Solution (?)

Now I thought: How cool would it be to have a pub(impl) visibility modifier that you could put on methods to be only visible within the same impl block? Then I could group methods and their utilities in the same impl block and be fine with it. It would perfectly fit into the design along pub(crate), pub(super), pub(path) etc. and also make impl blocks even more versatile.

Was there already such a proposal? How do you like this idea? Are there any problems with it that I do not yet see? Is it RFC worthy?

This is something I've wanted on occasion. It fits in nicely with restrictions. By the end of the year I hope to have the implementation split up such that it can be reviewed more incrementally, as that's the holdup.

I think offering this functionality might be bad for the language, because it would encourage users to write methods that don't need to be methods, and as a consequence,

  • run into borrow checking problems due to borrowing all of self when not necessary
  • stick too hard to “object-oriented” design where everything is associated with one type, rather than freely using many functions and incidental structs.

(Of course, non-method associated functions exist, but it's not obvious to the beginner that there's actual value in using the more verbose and strange Self::foo() calls.)

I think it's important to use and appreciate free functions, and to not try to narrow down privacy to at or below a single type, because many things in Rust are best done by using many types to create one abstraction, and anything which adds friction to adding another type (such as needing to increase the visibility of something to make it visible in the module) will hurt that workflow.

That said, I do see the value of being able to write a narrow-scoped helper function next to the functions or methods it uses. I'm just not sure this outweighs the disadvantages.

5 Likes

I think it's unnecessarily precise, and overly cautious.

There was a lot of discussion about similar need to restrict visibility within crates that lead to pub(in module) syntax, which ended up being very rarely used, and that was for crate-wide visibility, not even same-file visibility.

I think in practice such small utility functions will have very specific functionality that won't be useful outside of their single purpose anyway, so the risk of accidental over-reuse is low. Module visibility is still a pretty small scope, so you'd need to have really big and hairy modules to lose track of usage within a single file. You can still deal with this with good naming of the functions, and if in doubt, check uses with rust-analyzer.

2 Likes

I do kind of wish there was a scope that was “visible in this module but not submodules” for these kinds of helpers, but I understand that that breaks the idea that refactoring into a submodule is a free action.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.