Skip to content

AST: Stop diagnosing potentially unavailable declarations in unavailable contexts #80705

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
Apr 11, 2025

Conversation

tshortli
Copy link
Contributor

@tshortli tshortli commented Apr 10, 2025

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 #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.

@tshortli
Copy link
Contributor Author

@swift-ci please test

@tshortli tshortli force-pushed the unavailable-and-introduced branch from 46a23b8 to 4d24fb9 Compare April 10, 2025 21:43
@tshortli tshortli changed the title AST: Track platform unavailability and introduction as separate constraints AST: Stop diagnosing potentially unavailable declarations in unavailable contexts Apr 10, 2025
@tshortli
Copy link
Contributor Author

@swift-ci please test

@tshortli
Copy link
Contributor Author

@swift-ci please test source compatibility

Copy link
Contributor

@beccadax beccadax left a comment

Choose a reason for hiding this comment

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

Since there's a (hopefully small) potential for source breaks here, please write this up in CHANGELOG.md.

Otherwise this LGTM, assuming source compatibility tests don't turn up any problems.

@tshortli
Copy link
Contributor Author

Source compatibility tests passed: https://ci.swift.org/job/swift-PR-source-compat-suite-macos/2375/

@tshortli tshortli force-pushed the unavailable-and-introduced branch 2 times, most recently from 85c8739 to 8dabb22 Compare April 11, 2025 18:50
…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.
@tshortli tshortli force-pushed the unavailable-and-introduced branch from 8dabb22 to ae21f8d Compare April 11, 2025 18:50
@tshortli
Copy link
Contributor Author

@swift-ci please smoke test

@tshortli tshortli enabled auto-merge April 11, 2025 18:50
@tshortli
Copy link
Contributor Author

Thanks for the review @beccadax - I've updated CHANGELOG.md and also added a constraints test that demonstrates the new potential for ambiguity. Fortunately, platform introduction-based disambiguation has always been an unreliable technique (for clients that have a high enough deployment target, the reference will still be ambiguous) so I'm pretty confident this source break should be small.

@tshortli tshortli requested a review from beccadax April 11, 2025 18:53
@tshortli tshortli merged commit b278783 into swiftlang:main Apr 11, 2025
3 checks passed
@tshortli tshortli deleted the unavailable-and-introduced branch April 11, 2025 23:47
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.

2 participants