-
Notifications
You must be signed in to change notification settings - Fork 10.5k
AST/Sema: Continue adopting AvailabilityConstraint #79260
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
AST/Sema: Continue adopting AvailabilityConstraint #79260
Conversation
0841b68
to
1db5896
Compare
var prop2: Int32 { | ||
didSet { | ||
_ = prop2 // expected-error {{'prop2' is unavailable}} | ||
_ = prop2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@beccadax I wanted to give you a heads up about the changes I'm making to this test since you just added it. The behavior that the test was reproducing before was incorrect, since the context of the methods in the @objc @implementation extension
are themselves as unavailable as the properties and therefore the diagnostic should be supressed. After the refactoring in this PR to adopt some of my new shared infrastructure, the suppression of the diagnostics is working more consistently.
I do think we'll want to start diagnosing when an @objc @implementation extension
is less available than the interface it's implementing. As it stands, this allows a back door into calling arbitrary unavailable code which ought to be unreachable.
c62bfdd
to
c1e6063
Compare
427434d
to
2400e9c
Compare
swiftlang/swift-package-manager#8289 @swift-ci please smoke test |
2400e9c
to
b9b9b19
Compare
@swift-ci please smoke test |
swiftlang/swift-package-manager#8291 @swift-ci please smoke test |
2a4a96e
to
0382dea
Compare
@swift-ci please smoke test |
0382dea
to
54cb2a2
Compare
@swift-ci please test |
@swift-ci please test source compatibility debug |
@swift-ci please build toolchain macOS |
Switch to calling `swift::getAvailabilityConstraintsForDecl()` to get the unsatisfied availability constraints that should be diagnosed. This was intended to be NFC, but it turns out it fixed a bug in the recently introduced objc_implementation_direct_to_storage.swift test. In the test, the stored properties are as unavailable as the context that is accessing them so the accesses should not be diagnosed. However, this test demonstrates a bigger issue with `@objc @implementation`, which is that it allows the implementations of Obj-C interfaces to be less available than the interface, which effectively provides an availability checking loophole that can be used to invoke unavailable code.
When building up AvailabilityContexts, we assume that all of the enclosing decls have already been accounted for in the AvailabilityContext that we are constraining. Therefore, it doesn't make sense to merge availability constraints from the enclosing extension of the target decl.
Replaces `getUnsatisfiedAvailabilityConstraint()`. NFC.
Query for availability constraints instead of calling getVersionAvailability().
54cb2a2
to
e804c93
Compare
@swift-ci please test |
…raints. Potential unavailability of a declaration is always diagnosed in a context that does not have a sufficient platform introduction constraint, even if that context is also unavailable on that platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. The fix is to allow the constraint engine to track multiple kinds of constraints per-domain which in turn ensures that the platform introduction of an availability context can be further refined even if that context is also unavailable. A better fix would be to stop diagnosing potential unavailability entirely in unavailable contexts but that change is out of scope for the 6.2 release. Resolves rdar://147945883.
…raints. Potential unavailability of a declaration is always diagnosed in a context that does not have a sufficient platform introduction constraint, even if that context is also unavailable on that platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. The fix is to allow the constraint engine to track multiple kinds of constraints per-domain which in turn ensures that the platform introduction of an availability context can be further refined even if that context is also unavailable. A better fix would be to stop diagnosing potential unavailability entirely in unavailable contexts but that change is out of scope for the 6.2 release. Resolves rdar://147945883.
…raints Potential unavailability of a declaration is always diagnosed in a context that does not have a sufficient platform introduction constraint, even if that context is also unavailable on that platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. We could try to match the behavior from previous releases, but it's actually tricky to match the behavior well enough in the new availability checking architecture to fully fix source compatibility. Consequently, it seems like the best fix is actually to address this long standing issue and stop diagnosing potential unavailability in unavailable contexts. The main risk of this approach is source compatibility for regions of unavailable code. It's theoretically possible that restricting available declarations by introduction version in unavailable contexts is important to prevent ambiguities during overload resolution in some codebases. If we find that is a problem that is too prevalent, we may have to take a different approach. Resolves rdar://147945883.
…ble contexts. Potential unavailability of a declaration has always been diagnosed in contexts that do not have a sufficient platform introduction constraint, even when those contexts are also unavailable on the target platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. We could try to match the behavior from previous releases, but it's actually tricky to match the behavior well enough in the new availability checking architecture to fully fix source compatibility. Consequently, it seems like the best fix is actually to address this long standing issue and stop diagnosing potential unavailability in unavailable contexts. The main risk of this approach is source compatibility for regions of unavailable code. It's theoretically possible that restricting available declarations by introduction version in unavailable contexts is important to prevent ambiguities during overload resolution in some codebases. If we find that is a problem that is too prevalent, we may have to take a different approach. Resolves rdar://147945883.
…ble contexts. Potential unavailability of a declaration has always been diagnosed in contexts that do not have a sufficient platform introduction constraint, even when those contexts are also unavailable on the target platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. We could try to match the behavior from previous releases, but it's actually tricky to match the behavior well enough in the new availability checking architecture to fully fix source compatibility. Consequently, it seems like the best fix is actually to address this long standing issue and stop diagnosing potential unavailability in unavailable contexts. The main risk of this approach is source compatibility for regions of unavailable code. It's theoretically possible that restricting available declarations by introduction version in unavailable contexts is important to prevent ambiguities during overload resolution in some codebases. If we find that is a problem that is too prevalent, we may have to take a different approach. Resolves rdar://147945883.
…ble contexts. Potential unavailability of a declaration has always been diagnosed in contexts that do not have a sufficient platform introduction constraint, even when those contexts are also unavailable on the target platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. We could try to match the behavior from previous releases, but it's actually tricky to match the behavior well enough in the new availability checking architecture to fully fix source compatibility. Consequently, it seems like the best fix is actually to address this long standing issue and stop diagnosing potential unavailability in unavailable contexts. The main risk of this approach is source compatibility for regions of unavailable code. It's theoretically possible that restricting available declarations by introduction version in unavailable contexts is important to prevent ambiguities during overload resolution in some codebases. If we find that is a problem that is too prevalent, we may have to take a different approach. Resolves rdar://147945883.
…ble contexts. Potential unavailability of a declaration has always been diagnosed in contexts that do not have a sufficient platform introduction constraint, even when those contexts are also unavailable on the target platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. We could try to match the behavior from previous releases, but it's actually tricky to match the behavior well enough in the new availability checking architecture to fully fix source compatibility. Consequently, it seems like the best fix is actually to address this long standing issue and stop diagnosing potential unavailability in unavailable contexts. The main risk of this approach is source compatibility for regions of unavailable code. It's theoretically possible that restricting available declarations by introduction version in unavailable contexts is important to prevent ambiguities during overload resolution in some codebases. If we find that is a problem that is too prevalent, we may have to take a different approach. Resolves rdar://147945883.
…ble contexts. Potential unavailability of a declaration has always been diagnosed in contexts that do not have a sufficient platform introduction constraint, even when those contexts are also unavailable on the target platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. We could try to match the behavior from previous releases, but it's actually tricky to match the behavior well enough in the new availability checking architecture to fully fix source compatibility. Consequently, it seems like the best fix is actually to address this long standing issue and stop diagnosing potential unavailability in unavailable contexts. The main risk of this approach is source compatibility for regions of unavailable code. It's theoretically possible that restricting available declarations by introduction version in unavailable contexts is important to prevent ambiguities during overload resolution in some codebases. If we find that is a problem that is too prevalent, we may have to take a different approach. Resolves rdar://147945883.
…ble contexts. Potential unavailability of a declaration has always been diagnosed in contexts that do not have a sufficient platform introduction constraint, even when those contexts are also unavailable on the target platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in swiftlang#79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. We could try to match the behavior from previous releases, but it's actually tricky to match the behavior well enough in the new availability checking architecture to fully fix source compatibility. Consequently, it seems like the best fix is actually to address this long standing issue and stop diagnosing potential unavailability in unavailable contexts. The main risk of this approach is source compatibility for regions of unavailable code. It's theoretically possible that restricting available declarations by introduction version in unavailable contexts is important to prevent ambiguities during overload resolution in some codebases. If we find that is a problem that is too prevalent, we may have to take a different approach. Resolves rdar://147945883.
Builds on top of #79249 by reimplementing various availability diagnostics and queries on top of
swift::getAvailabilityConstraintsForDecl()
.