Skip to content

Instantly share code, notes, and snippets.

@erica
Last active July 5, 2020 19:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erica/45dfb7f742df98668b0fb69229894c20 to your computer and use it in GitHub Desktop.
Save erica/45dfb7f742df98668b0fb69229894c20 to your computer and use it in GitHub Desktop.

Expanding available to introduce discouraged

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: Discussion thread topic for that proposal

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment