New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-2925] Inconsistent linking in debug vs. release builds w/ public method in extension of internal protocol #45519
Comments
I thought we had locked down on this entirely by now, but reworking access control might have let some cases slip through again. (It's not an unreasonable feature request either, but it's one that needs more work and probably some design.) |
Comment by Thomas Catterall (JIRA) Just encountered this using a framework exposing a public set of protocol conformances to an internal extension ``` extension MyProtocol { The framework always builds fine, but in release builds the app target that imports the framework fails to find the protocol witness table or the extension. I assume this is something to do with optimisations. Is the bug described in this comment the same as this ticket or shall I create a new one? Swift 3, Xcode 8.1 8B62 (App Store) |
Yes, that looks like a manifestation of the same bug. |
To be clear, this is not supported at the moment. It's more than just something being marked with the "wrong" visibility; it's about not exposing details of MyProtocol to other modules. |
Going forward, does that mean that the fix for this bug is one that will prevent these examples from compiling at all, and that we should write a Swift evolution proposal to design this properly once additive proposals are ready to be accepted again? |
Heads up this is still an issue with Xcode 9.2's bundled Swift |
The conformance should be rejected. The default implementation is not sufficiently visible and thus cannot witness a public protocol requirement. |
@swift-ci create |
Attachment: Download
Environment
Apple Swift version 3.0 (swiftlang-800.0.46.2 clang-800.0.38)
Additional Detail from JIRA
md5: 82c10c0bdffe3fe1b4f8be7579763da4
is duplicated by:
Issue Description:
Imagine the following scenario (see the attached ZIP for a small self-contained Swift PM example):
A module contains one or more concrete types that are public (let's call one
ConcreteType
).The module also contains an internal protocol with some methods (let's call the protocol
InternalProtocol
). The concrete types are extended to conform to this protocol for use elsewhere within the module:An extension of the protocol itself is made to provide default implementations of some of those methods. Even though the protocol itself is internal, one of these methods is declared public so that it will be visible externally. (In other words, we want the protocol to be invisible to external users, but we want to provide one of those methods to them as if it were defined on the concrete type extensions, to share its default implementation across all of the concrete types without duplication:
Another module imports the above module and tries to call the method described above (
let c = ConcreteType(); c.publicBar()
).When building in debug mode, this compiles, links, and executes as expected:
When building in release mode, compilation of all sources succeeds but a failure occurs at link time:
It appears that some symbol hiding/stripping that occurs in release builds is causing the extension method on the internal protocol to not be found, even though the method itself is public?
(Looking more closely, it's interesting that it's suggesting that I may have meant a generic specialization when there are no generics involved in this example...)
In any case, the difference in behavior between debug/release builds seems to be a bug. If I'm understanding what's going on correctly, one of two things should be happening:
1. This kind of visibility mixing should be allowed, and the public method on the internal protocol extension should be exposed for other modules to link to, or
2. This kind of visibility mixing should not be allowed, and the error should be emitted at compile time in both debug and release builds, rather than leading to harder-to-diagnose linker errors.
I don't have a deep enough understanding of the Swift compiler to know which of the above is correct, but my preference would be for #1, because it allows for some convenient selective member hiding while reducing code duplication. More real-world context can be found here <https://github.com/apple/swift-protobuf/issues/70\>; see also the pull request that fixes it for the diff of what had to be changed <https://github.com/apple/swift-protobuf/pull/71\>.
The text was updated successfully, but these errors were encountered: