Skip to content

[Sema] Improve diagnostics for access level of protocol witness in extension. #22235

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
merged 1 commit into from
Feb 8, 2019

Conversation

dingobye
Copy link
Contributor

@dingobye dingobye commented Jan 30, 2019

If the access level of a protocol witness does not satisfies a requirement, the compiler always suggests marking it as the required level. This is not suitable when the witness is in an extension whose specified access level is less than the required level, since the fixit fights with other warnings in this case. This patch identifies such case and produces improved diagnostics.

Consider the following example, if we follow the original notes to mark foo and bar as 'internal', we would get further warnings redundant 'internal' modifier and conflict with extension's default access, respectively. The diagnostics improved by this patch makes more sense. It uses removal (instead of replacement) fix-it for foo, and suggests moving bar to another extension.

protocol Proto {
  func foo()
  func bar()
}

public struct S : Proto {}

internal extension S {
  private func foo() {} // note: mark the instance method as 'internal' to satisfy the requirement
  ^^^^^^^^
- internel
}

private extension S {
  private func bar() {}
- note: mark the instance method as 'internal' to satisfy the requirement
+ note: move the instance method to another extension where it can be declared 'internal' to satisfy the requirement
}

Resolves SR-9793.

@xwu
Copy link
Collaborator

xwu commented Jan 30, 2019

In your examples:

  • the first diagnostic is correct as-is and is more succinct than the proposed change
  • as to the second diagnostic, moving may not be possible if the method requires other members private to the extension--it would be more helpful to suggest marking the existing extension and the method as internal (that is, simply change the diagnostic to say "mark the extension and instance method as 'internal'")

@dingobye
Copy link
Contributor Author

@xwu Thanks for your inputs!

If we follow the first one to update the code (i.e., replacing 'private' by 'internal'), we would get another warning as shown below.

internal extension S {
  internal func foo() {} // warning: 'internal' modifier is redundant for instance method declared in an internal extension
}

So it makes sense to improve the diagnostics. If the proposed message is not concise, I have it rephrased as remove 'private' modifier of the instance method to satisfy the requirement. How does it sound?

@dingobye
Copy link
Contributor Author

dingobye commented Jan 30, 2019

For the second one, I don't quite get your idea. I believe after the method is moved to another extension in the same file, it still can use those members declared 'private' in the original extension.

For your advised change (i.e., marking extension as 'internal'), it may be a problem when other members in extension adopt the default access level. For the following example, after marking extension as 'internal', baz() would be unexpectedly changed from 'fileprivate' to 'internal'.

private extension S {
  private func bar() {}
  func baz() { print("I am fileprivate") }
}

@dingobye
Copy link
Contributor Author

dingobye commented Feb 5, 2019

@jrose-apple Hi Jordan, would you take a look at this, please?

@jrose-apple
Copy link
Contributor

I think I'd split the difference on @xwu's first point by using the existing text but the removal fix-it. For the second point I agree with @dingobye; with SE-0169 this should always be possible.

@jrose-apple
Copy link
Contributor

The implementation looks pretty good to me!

…tension.

If the access level of a protocol witness does not satisfies a requirement,
the compiler suggests marking it as the required level.  This is not suitable
when the witness is in an extension whose specified access level is less than
the required level, since the fixit fights with other warnings in this case.
This patch identifies such case and produces improved diagnostics.

Resolves: SR-9793
@dingobye
Copy link
Contributor Author

dingobye commented Feb 6, 2019

Thanks for the reply, Jordan! I updated the code as suggested.

@jrose-apple
Copy link
Contributor

This looks good to me! @xwu, are you convinced?

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Feb 6, 2019

Build failed
Swift Test Linux Platform
Git Sha - 5e4420a6a88267b6ebe3fd8051497a097412954f

@swift-ci
Copy link
Contributor

swift-ci commented Feb 6, 2019

Build failed
Swift Test OS X Platform
Git Sha - 5e4420a6a88267b6ebe3fd8051497a097412954f

@xwu
Copy link
Collaborator

xwu commented Feb 7, 2019

👍

@xwu
Copy link
Collaborator

xwu commented Feb 7, 2019

@swift-ci Please test OS X platform

@jrose-apple jrose-apple merged commit 0f493a6 into swiftlang:master Feb 8, 2019
CodaFi added a commit to CodaFi/swift that referenced this pull request Nov 13, 2019
swiftlang#22235 added an assert that was a little overzealous about
the structure of access control attributes in the AST.  It used to
always expect that we reached diagnoseWitnessFixAccessLevel when there
was an explicit mismatch in user-written access markers.  But declarations
may also have their access levels rewritten and their access attributes
stripped if they are invalid.  If you can get all of these to occur by
the time you diagnose the witness, you see no attribute for a witness
with insufficient ACLs for a requirement and crash.

Relax the assert by using the formal access level and resolve rdar://56818960
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