> Charles we've diverged from the actual issue at hand to nitpick my English.  
> Read the code (that std::min tho!).  We have a problem here and no obvious 
> solution that doesn't involve special-casing parts of this proposal.

I think it might be more helpful to think of it this way:

1. The mental model has generally been that, absent a specific access control 
keyword, a member is as visible as the enclosing type, except that it is never 
automatically `public`.

2. Because of the way the old public/internal/private access control model was 
defined, this was equivalent to applying the enclosing type's access control 
keyword to the member. Therefore, that was the implementation model chosen by 
the compiler.

3. However, now that we have a scope-dependent access control level, these two 
models provide divergent behavior, and we must use a different implementation 
model. (We know that the old implementation model is not an accurate match for 
the mental model because scoped `private` provides sensical behavior in the 
mental model, but nonsensical behavior in the implementation model.)

4. We understand what the effect of this new implementation model *should* be: 
The members of the private type should be as visible as the private type, 
unless they are themselves marked private.

5. However, we're not exactly sure how this new model should be implemented, 
and core team guidance is probably necessary. In particular, these children of 
`private` types have a somewhat mysterious new property: their visibility 
cannot be accurately described by any existing access control keyword. It's not 
clear how to cope with that. (The easiest solution―add a new access control 
level which is basically "private to me and my parent"―won't do the trick: 
members of nested types, like `z` in `private struct X { struct Y { var z: Int 
} }`, should be visible two levels up. The visibility of these members is 
genuinely complicated and context-specific.)

6. With the core team tied up at WWDC, you may want to temporarily forbid the 
use of `private` on a type and revisit the matter when people are less busy; if 
necessary, we could even ship Swift 3 that way. Or you may want to consider 
making a guess as to a good implementation model to apply. Two suggestions for 
alternate implementation models:

a. Introduce a `parent` access level, meaning "visible in scopes within this 
file where the parent is visible", which is between `fileprivate` and 
`private`. Just as `internal` is the maximum inherited access level, `parent` 
is the minimum, so the members of a `private` type would inherit `parent` 
visibility. `parent` might be an entirely compiler-internal concept, with no 
utterable access control keyword.

b. Instead of inheriting an access control modifier's visibility, always set 
unspecified ones to `internal`, but make sure they stay effectively invisible 
in scopes where their parent is not visible. Introduce a warning or error for 
*explicitly* specifying a modifier that exceeds the parent's visibility, but 
don't emit it for implicit `internal`s.

c. Combine the two: `parent` means "visible wherever the parent is, whether 
within this file or not, except not public", and is *always* the default access 
level if nothing else is specified. (`parent` doesn't fit neatly into the 
access control hierarchy, but on the other hand, it's the closest match to the 
mental model.)

A final note: I usually try not to complain about accepted proposals, but I'll 
make an exception this time. I pointed out during the discussion and review 
that this proposal was unclear and that scoped `private` was quite different 
from our existing access control behaviors. I won't claim that I predicted this 
problem, but I'm not surprised to find that we're running into it.

-- 
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to