[swift-evolution] [Discussion] access control modifier inconsistency

Adrian Zubarev adrian.zubarev at devandartist.com
Sun Jun 19 02:18:29 CDT 2016


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) 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160619/762af2c8/attachment.html>


More information about the swift-evolution mailing list