> 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