-1 on this proposal, because I think I disagree with how I view the authors view access control, and IMO it doesn't align with how the language has done it in the past either. The fundamental problem that it solves is that some code should be able to access certain APIs. In a perfect world everyone would magically have a precise set of clients that could call them and they'd list those out, but in reality we've decided that the approximations that people are typically fine with include things like "everyone can use this" (public
), "only I can use this" (private
), and two also fairly common ways of organizing code, "I pasted a bunch of stuff in a file and it should be able to see each other" (fileprivate
) and "let all the files in this target access each other" (internal
). We then shut down discussion of adding additional broad scopes like these, because we figured that if someone wanted wanted them they should just make do with the ones we had provided.
In the meantime, we also added one specific access modifier, @_spi
, to precisely control the list of of clients rather than providing broad control. This has actually been pretty popular! There are a lot of APIs that only really have one or two clients, but that are separated from each other in ways that don't make the existing scopes a good fit.
Anyways, this proposal suggests another access control modifier, package
, which does scoping on the package level. If we look at this from a purely access control perspective, why should we consider packages special? People organize their code in all sorts of ways, not just packages. A lot of people don't use SPM at all, as has been mentioned in this thread. I don't actually think this unit of organization is any better than say "directory
" (where all files in the same directory can access each other) or "bundleid
" (where clients sharing the same reverse DNS prefix can access each other). Lots of projects are organized in a way where this would be about as useful as package
. People group their code in all sorts of ways and I think if we actually feel like doing this properly we should just take @davedelong's suggestion let people pick their own custom access modifiers that fit their project the best. I feel like a lot of people who are asking for @_spi
to be more powerful are really asking for "I have some sort of internal API and a specific type of client in mind, let me specify who I think those should be and if we both agree to be adults by opting in to this internal API boundary then they can access it".
Additionally, I feel like too much of the motivation for the proposal (and the subsequent arguments in this thread) is to make compiler things line up at the expense of how most users actually care about access control. We shouldn't pick an access control scope because it allows for eliding some inter-module resilience boundaries inside of a package, or because we want to minimize the number of public symbols exported from a binary. There's been a lot of pushback on the concept of "arbitrary clients". I think some of it comes from a place of being unhappy that this requires these things to be exposed publicly ABI-wise and reduces opportunities for optimizations. I feel like the authors have decided that packages are a convenient place to do some sort of intra-module grouping for the compiler and feel that it's also a workable place to do some access control work to make it happen. I don't actually think it's the wrong abstraction for a lot of code, but I think this proposal blesses this grouping specifically for reasons that aren't all that unique or compelling if you measure them up to the previous access control modifiers we had. And, I mean, a lot of what you view to be an ad-hoc coupling is a completely sane relationship for my organization. I mean, there are all sorts of things that are totally reasonable to support in Swift but are far more similar to @_spi
than package
. I don't think there is any static grouping that can the range of access control people look for in their projects.
I think if we move ahead with this it should come as an instance of a more general solution that allows developers to make their own classification based on their project's needs, and if it so happens that we can only make access modifiers like package
fast and someone's directoryprivate
access control expends all its benefits at compile time and doesn't end up making things any faster than public
does so be it.