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-8092] Using a class defined in multiple frameworks by prefixing explicitly #50625
Comments
This is behaving as designed, since it turns out in practice people don't know what framework most declarations come from. If the OperationQueue defined in FrameworkA really is internal, then someone referring to FrameworkA.OperationQueue shouldn't even really know about it. Making this change would also potentially be very source-breaking. I could see it as some kind of linter option instead, once we have a place for checks like that. |
Comment by Somu (JIRA) Thanks Jordan for responding quickly, just a few thoughts (I could be wrong) Since in the code we prefix explicitly ( let oq = FrameworkA.OperationQueue() ) specifying the FrameworkA, I thought it might help if the compiler threw an error since the class is internal and the user has requested for something that is internal explicitly. If it wasn't prefixed I agree, the class that is visible should be used. Example2: For example if a class X was an internal class in FrameworkA and it was explicitly referenced in the code, the following compilation error is thrown. FrameworkA: class X {} //Internal class App: let x2 = FrameworkA.X() //Module 'FrameworkA' has no member named 'X' In Example2, the compiler throws an error saying that there is no member X, however it seems to behave differently in Example1 when there is a class defined in multiple frameworks and the user explicitly requests for FrameworkA's class, Foundation's class is used. I felt some potential bugs could be caught at compile time instead of being surprised at runtime. Note: These are just my thoughts and I could be wrong. |
The main argument against this is what I said initially: people don't know which module actually contains a declaration. Thus you might expect someone to write In most cases, this will still be a compiler error because the two types will have different interfaces. That is, both your OperationQueue and the one in Foundation have no-argument initializers, but they probably have very different methods and properties. |
Comment by Somu (JIRA) Thanks a lot Jordan for patiently responding, expressing my thoughts on it. 1. I agree the user might not know where a framework is defined, but in some cases the user might want know their own framework and might want something specific, so when a user requests for something specific (almost like forced unwrapping or using unsafe pointers) and if the class user requested for is inaccessible, it would be nice if the compiler throws the error rather than giving something that user didn't request for. I feel that explicitly referencing using the dot operator is there for this specific reason to allow the user to specify which one the user wants. 2. I also agree with regards to the example UIKit.IndexPath, UIKit imports Foundation and eventually it boils down to Foundation.IndexPath. 3. Presently the compiler is throws an error when user specifies an internal class defined in a framework (which is inaccessible), would be nice to be consistent for other class names defined in multiple frameworks when user explicitly specifies the framework name using dot operator. 4. In my case FrameworkA's OperationQueue was actually inheriting Foundation.OperationQueue so it makes it even harder to spot the issue at runtime. So it wasn't caught at compile time and since I didn't add any new methods didn't realise and thought the compiler would give the instance that I requested for. I felt others might encounter this scenario. |
Additional Detail from JIRA
md5: c892f9ffbf3361730c6c5302e5f40971
Issue Description:
Example:
OperationQueue is a public class that is defined in Foundation framework
Assume a class OperationQueue is also defined in FrameworkA, but is not made public.
Creating a variable by explicitly specifying FrameworkA.OperationQueue refers to Foundation.OperationQueue and doesn't throw a compilation error though FrameworkA.OperationQueue is not accessible.
FrameworkA:
App:
Problem:
The above mentioned code doesn't throw a compilation error even when prefixed explicitly as FrameworkA.OperationQueue, though the explicitly mentioned class is inaccessible because it internal.
This is misleading to the user, as the user might think it is FrameworkA's class that is used because the user had mentioned explicitly the framework's name.
*
It would be nice if the compiler can throw an error if the class explicitly mentioned is not accessible.
Tested on:
Xcode 9.4
Swift 4.1
iOS 11.4
Links:
Was discussed in Swift Forums: https://forums.swift.org/t/typealias-pointing-to-inaccessible-class-in-framework/13954
The text was updated successfully, but these errors were encountered: