Skip to content

[Diagnostics] Improve diagnostics on invalid open extensions #38989

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

Merged

Conversation

mininny
Copy link
Contributor

@mininny mininny commented Aug 21, 2021

Using 'open' as default access for an extension results in the following error:

open extension AClass { // Extensions cannot use 'open' as their default access; use 'public'
// Replace 'open' with 'public'
    @objc func functionA()

Applying the autocorrect and making the function as open instead, the code is changed to this and warning is emitted:

public extension AClass {
    @objc open func functionA() // 'open' modifier conflicts with extension's default access of 'public'

where the warning holds no purpose because the 'open' modifier still works. (It seems like this is the case for other types of this conflict, i.e. public function in a private extension, and the function is still publicly visible. Similar thing can be observed in classes, i.e. a private class with a public variable, and no warning is shown there)

To remove the warning, you have to now remove the 'public' modifier like this:

extension PublicClass {
    @objc open func functionC()

I think we can improve these diagnostics to something like this to make this more convenient:

open extension AClass { // Extensions cannot use 'open' as their default access; remove the default access and mark methods as 'open' instead // remove 'open'
    @objc func functionA() // add 'open' ← maybe?

Resolves SR-15071

@mininny mininny force-pushed the improve-open-extension-diagnostic branch from 6c948b6 to 19a0821 Compare August 22, 2021 09:36
@mininny mininny force-pushed the improve-open-extension-diagnostic branch from 19a0821 to 55557be Compare August 24, 2021 15:13
for (auto Member : extension->getMembers()) {
if (auto *VD = dyn_cast<ValueDecl>(Member)) {
if (VD->getAttrs().hasAttribute<AccessControlAttr>())
return;
Copy link
Contributor

@varungandhi-apple varungandhi-apple Aug 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return;
continue;

Also, to catch this, I recommend shuffling the order of members in the test case, so that we make sure we emit fix-its for later members even if we skip it for members in-between.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems logical 👍 I fixed the test cases as well :)

@mininny mininny force-pushed the improve-open-extension-diagnostic branch 2 times, most recently from 31f7707 to 24dbd85 Compare August 28, 2021 08:55
private var G: Int { 3 } // Okay
}

import Foundation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to use of this import Foundation, you should use -sdk %clang-importer-sdk in the third RUN line, since we don't need the "real" Foundation, the fake one in the test suite should be good enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that existed, thanks :) Added and pushed!

@mininny mininny force-pushed the improve-open-extension-diagnostic branch from 24dbd85 to 2b2cd54 Compare August 31, 2021 15:00
@varungandhi-apple
Copy link
Contributor

@swift-ci smoke test

@mininny
Copy link
Contributor Author

mininny commented Sep 1, 2021

It seems like the use of import Foundation isn't passing on non-macOS platforms. Is there something I should look into?

@varungandhi-apple
Copy link
Contributor

Hmm, the test needs REQUIRES: objc_interop to be able to use @objc. One thing you could do is split this test out into a new file (say open_objc.swift) which has REQUIRES: objc_interop and import Foundation. Since ObjC interop is not turned on for Linux, that test will not be run.

@@ -1499,7 +1499,7 @@ ERROR(access_control_extension_more,none,
"be declared %select{%error|fileprivate|internal|public|%error}2",
(AccessLevel, DescriptiveDeclKind, AccessLevel))
ERROR(access_control_extension_open,none,
"extensions cannot use 'open' as their default access; use 'public'",
"extensions cannot be marked 'open'; mark individual members as 'open' instead",
Copy link
Collaborator

@xwu xwu Sep 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Mark" works but I don't know that we use this term very often in Swift diagnostics. How about "declare" as above and below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good! Fixed 👍

@mininny mininny force-pushed the improve-open-extension-diagnostic branch from 2b2cd54 to 84c42a8 Compare September 7, 2021 14:12
@xwu
Copy link
Collaborator

xwu commented Sep 7, 2021

@swift-ci smoke test

@mininny mininny force-pushed the improve-open-extension-diagnostic branch from 84c42a8 to 0b48569 Compare September 8, 2021 09:31
@mininny
Copy link
Contributor Author

mininny commented Sep 8, 2021

Can someone run the tests again please? :)

@LucianoPAlmeida
Copy link
Contributor

@swift-ci smoke test

@varungandhi-apple varungandhi-apple merged commit a1b6469 into swiftlang:main Sep 8, 2021
@mininny mininny deleted the improve-open-extension-diagnostic branch September 8, 2021 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants