What follows is a proposal draft for initial feedback. This is a link to a gist version. The gist will be updated as feedback from community members is processed. The cut-and-paste into this post will not.
We would greatly appreciate your thoughtful feedback on this pitch. Thank you.
Expanding available
to introduce discouraged
- Proposal: SE-nnnnnnnn
- Authors: Erica Sadun, Chris Lattner
- Review Manager: TBD
- Status: Awaiting implementation
Introduction
Swift's available
attribute documents characteristics of a declaration's lifecycle. The attribute specifies when a declaration became available on a given platform, and if it's been deprecated, obsoleted, or renamed. We feel there's room to further nuance available
. This proposal expands available
to introduce discouraged
, making declarations harder to accidentally use.
Swift-evolution thread: Proposing to expand available
to introduce discouraged
Motivation
Public declarations exist for many reasons. Most typically, you want to create nice things. You expand your API surface, granting callers access to your declarations. That's not the only reason, though. Sometimes you expose implementation details when a declaration must be public. At other times, declarations are needed for compatibility, even when there's a newer more preferred approach.
As an API designer, you may want to steer adopters away from certain declarations. We believe you should be able to communicate when declarations are visible but should not be used. Your development environment should be able to pick up these cues and help coders to avoid using those calls.
For example, initializer requirements in the LiteralConvertible
protocols are redundant with the initializers on the type conforming to the protocols. They are meant to be implemented, but not called. Marking them discouraged
documents this reality. It also helps the development environment hide the discouraged declarations from cues like code completion.
You may also want to discourage a declaration that has been modernized or redesigned. Even when the original form is required for compatibility and cannot be deprecated, discouraging older forms helps move coders to newer declarations.
Discouraging visible-but-not-meant-for-use declarations provides tangible benefits:
- It increases coding safety.
- It supports clarity, as the current uses of
available
do, by co-locating availability status information with code documentation. - It offers a way to connect a declaration with development environment policy. A discouraged declaration may be warned or hidden from code completion depending on the implementation provided in an IDE.
Proposed solution
We propose to extend available
, introducing discouraged
. A discouraged declaration is publicly accessible but not meant for general use.
Detailed design
The available
attribute currently supports the following arguments:
Argument | Description |
---|---|
introduced |
The first platform or language version that supported the declaration. |
renamed |
A name that entirely replaces the old declaration, emitting a compile-time error. |
message |
A message to display when emitting a warning or error for deprecated and obsoleted declarations. |
deprecated |
The first platform or language version where the declaration was deprecated. |
obsoleted |
The first platform or language version where the declaration was removed and can no longer be used. |
unavailable |
Indicates a declaration is not available for a given platform. |
For example:
@available(swift, introduced: 4.0, message: "Please use failable String.init?(_:UTF8View) when in Swift 3.2 mode")
@available(swift, deprecated: 5.0, renamed: "firstIndex(of:)")
@available(*, deprecated, message: "all index distances are now of type Int")
@available(iOS 14.0, watchOS 7.0, tvOS 14.0, *)
@available(OSX, unavailable)
Our proposed design expands available
.
Argument | Description |
---|---|
discouraged |
A message to display that describes why this declaration is discouraged |
Here's what this might look like. For implementation details, the message explains the circumstances leading to discouraging use. For updated and refactored APIs, the message drives "what to use" over "why this is discouraged".
@available(*, discouraged: "`_ShapeView` not for public use")
@available(*, discouraged: "`IntersectionSolver` is O(N^2). Use `ConfluenceSolver` instead.")
@available(discouraged: "Use newer Combine-based publisher instead")
IDE integration
Discouraged declarations can be enforced by the IDE experience in several ways:
- They could be suppressed from code completion or only show up in code completion once they are the only unambiguous option.
- They could given a strikethrough treatment.
Further, the new discouraged
argument can be picked up and integrated into Quick Help.
Source compatibility
This change is purely additive and will not affect source compatibility.
Effect on ABI stability
No effect.
Effect on API resilience
No effect.
Alternatives considered
Not accepting the proposal and leaving availability
as currently designed.