[swift-evolution] [swift-evolution-announce] [Review] SE-0025 Scoped Access Level

Nicola Salmoria nicola.salmoria at gmail.com
Tue Mar 1 13:57:29 CST 2016


> > On Feb 29, 2016, at 8:08 PM, Ilya Belenkiy<ilya.belenkiy at gmail.com(mailto:ilya.belenkiy at gmail.com)>wrote:
> > 
> > This is one interoperation. Here is another that makes it fit perfectly well:
> > 
> > - public: exports symbol to all files
> > - internal: exports symbol to module files
> > - private: exports symbol to one file containing the scope
> > - scoped: no export
> > 
> I disagree. The conceptual model is file scoping.
> 
> `public` - available in any source file within the module and in external source files that link the module
> `internal` - available in any source file within the module
> `private` - available in its own source file
> 
> 
> The addition of `local` adds a new conceptual model around access control: lexical scoping. This type of scoping also actively works against various Swift patterns that are fairly common: using extensions to implement protocol conformance.

I find it insteresting that you are mentioning this to motvate your disagreement of the proposal, because it’s precisely the reason I gave to motivate my support.

> 
> > struct TypeA {
> > vara:String
> > }
> > 
> > extensionTypeA:StringLiteralConvertible{
> > init(stringLiteral value:String) {
> > self.a= value
> > }
> > 
> > init(extendedGraphemeClusterLiteral value:String) {
> > self.a= value
> > }
> > 
> > init(unicodeScalarLiteral value:String) {
> > self.a= value
> > }
> > }
> > 
> When `a` on type `TypeA` is declared as `local`, this pattern is no longer possible. Thus I find the use cases for `local`, as presented in the proposal, extremely limited in real use cases.

Indeed, `local`wouldn’t be useful with such a layout. But what about this:

struct TypeA {
    local var a: String

    init(var a: String) {
        self.a = a
    }
}

extensionTypeA:StringLiteralConvertible{
    init(stringLiteral value:String) {
        self.init(a: value)
    }

    init(extendedGraphemeClusterLiteral value:String) {
        self.init(a: value)
    }

    init(unicodeScalarLiteral value:String) {
        self.init(a: value)
    }
}

With this change, `a` has become an implementation detail that nobody—nobody!—can access directly, not even methods of the type itself, can access, unless they are declared in the same scope.

Of course this is just a toy example; but in real world cases where you need to guarantee invariants, having `local`would mean that to verify the correctness of your code you would only need to look at the immediate surroundings, instead of having to check the whole file.

> 
> Now, if the proposal was to have `local` be scoped to the type that defines it, thus allowing extensions access to it, then it becomes more interesting, and has many more applicable use cases while still allowing the use case defined in the proposal.
> 
> -David

I would find such an access control quite useless. Types can be extended by anyone, so declaring some member `private`in the C++ sense would be the same as declaring it public—everyone would be able to access it just by defining an ad-hoc extension.

—
Nicola



More information about the swift-evolution mailing list