[swift-evolution] [Discussion] access control modifier inconsistency
Gwynne Raskind
gwynne at darkrainfall.org
Mon Jun 20 03:40:51 CDT 2016
I'd strongly favor correcting this inconsistency; I’ve run into it and been confused until I remembered the semantics more than once. I would much prefer always explicitly specifying the access modifier to receive its effect (versus changing the documentation) - in short I agree that extensions should be internal until declared otherwise.
-- Gwynne Raskind
> On Jun 20, 2016, at 03:35, Adrian Zubarev via swift-evolution <swift-evolution at swift.org> wrote:
>
> Everyone does feel comfortable with implicit public extensions?
>
>
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 19. Juni 2016 um 09:18:35, Adrian Zubarev (adrian.zubarev at devandartist.com <mailto:adrian.zubarev at devandartist.com>) schrieb:
>
>> One problem I found with the mentioned suggestion of mine is this:
>>
>> public protocol A {}
>>
>> public class B {}
>>
>> // 'public' modifier cannot be used with
>> // extensions that declare protocol conformances
>> public extension B: A {}
>> Why is that like this?
>> Can this be fixed?
>> Implicit public extension feels odd and is inconsistent if you ask me.
>> Any statement to the pitched suggestion?
>>
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>>
>> Am 17. Juni 2016 um 11:28:18, Adrian Zubarev (adrian.zubarev at devandartist.com <mailto:adrian.zubarev at devandartist.com>) schrieb:
>>
>>> I’ve spotted some inconsistency on access control modifier I’d like to discuss in this thread (the behavior is not groundbreaking but inconsistent from readers and developers view perspective).
>>>
>>> Why are extensions not marked as public in public apis when the module is imported?
>>>
>>> Any type members added in an extension have the same default access level as type members declared in the original type being extended. If you extend a public or internal type, any new type members you add will have a default access level of internal. If you extend a private type, any new type members you add will have a default access level of private.
>>>
>>> Alternatively, you can mark an extension with an explicit access level modifier (for example, private extension) to set a new default access level for all members defined within the extension. This new default can still be overridden within the extension for individual type members.
>>>
>>> Source: Apple Inc. The Swift Programming Language (Swift 2.2).
>>> This does not tell us how the access control modifier works on extensions. Here are three examples:
>>> public struct A {}
>>>
>>> /* implicitly internal */ extension A {}
>>>
>>> // This extension won't be exported
>>> as soon as at least one member modifier of an extension is public (if the extended type allows that and is also public), the extension itself becomes implicitly public:
>>> public struct B {}
>>>
>>> /* implicitly public */ extension B {
>>>
>>> public func foo() {}
>>>
>>> /* implicitly internal */ func boo() {}
>>> }
>>>
>>> // This extension will be exported as
>>>
>>> extension B {
>>>
>>> public func foo()
>>> }
>>> This is inconsistent to other types, because you can not leave out the modifier for instance on classes, then add a public member and assume that your class is implicitly public! The compiler knows that and provides a correct warning that the mentioned class is internal.
>>>
>>> public struct C {}
>>>
>>> public extension C {
>>>
>>> public func foo() {}
>>>
>>> /* implicitly internal */ func boo() {}
>>> }
>>>
>>> // This extension will be exported as
>>>
>>> /* public is missing here */ extension C {
>>>
>>> public func foo()
>>> }
>>> Extensions seem to behave differently and its behaviors is inconsistent and not documented.
>>>
>>> protocols has explicit public modifier on its members when the module is imported. However, 'public' modifier cannot be used in protocols is how the compiler treat modifiers in protocols on declaration.
>>>
>>> public protocol D {
>>>
>>> func doSomething()
>>> }
>>> Protocol D will be exported as:
>>>
>>> public protocol D {
>>>
>>> public func doSomething()
>>> }
>>> Here is my suggestion:
>>>
>>> Fix the behavior for extensions and document it correctly:
>>>
>>> public struct B {}
>>>
>>> /* implicitly public */ extension B {
>>>
>>> public func foo() {}
>>>
>>> /* implicitly internal */ func boo() {}
>>> }
>>> Such an extension should not be implicitly public and behave like other types and stay implicitly internal.
>>> The compiler should provide a warning for the foo() function: Declaring a public function for an internal type
>>> Extensions should have explicit public modifier like other types if the extension was marked as public and was imported into an other project/module.
>>> This inconsistent behavior is source breaking and I’d suggest this change to happen in Swift 3!
>>> Remove public modifier from imported protocols OR document this behavior correctly!
>>>
>>>
>>>
>>> --
>>> Adrian Zubarev
>>> Sent with Airmail
>>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160620/4d21da7a/attachment.html>
More information about the swift-evolution
mailing list