Merge pull request #85026 from bnbarham/user-doc-cleanup

Cleanup user docs
This commit is contained in:
Ben Barham
2025-10-23 14:04:52 -07:00
committed by GitHub
31 changed files with 397 additions and 242 deletions

View File

@@ -44,6 +44,7 @@ GROUP(ActorIsolatedCall, "actor-isolated-call")
GROUP(AlwaysAvailableDomain, "always-available-domain")
GROUP(AvailabilityUnrecognizedName, "availability-unrecognized-name")
GROUP(ClangDeclarationImport, "clang-declaration-import")
GROUP(CompilationCaching, "compilation-caching")
GROUP(ConformanceIsolation, "conformance-isolation")
GROUP(DeprecatedDeclaration, "deprecated-declaration")
GROUP(DynamicCallable, "dynamic-callable-requirements")
@@ -52,6 +53,7 @@ GROUP(ErrorInFutureSwiftVersion, "error-in-future-swift-version")
GROUP(ExclusivityViolation, "exclusivity-violation")
GROUP(ExistentialAny, "existential-any")
GROUP(ExistentialMemberAccess, "existential-member-access-limitations")
GROUP(ExistentialType, "existential-type")
GROUP(ImplementationOnlyDeprecated, "implementation-only-deprecated")
GROUP(IsolatedConformances, "isolated-conformances")
GROUP(MemberImportVisibility, "member-import-visibility")
@@ -63,12 +65,16 @@ GROUP(MutableGlobalVariable, "mutable-global-variable")
GROUP(NominalTypes, "nominal-types")
GROUP(NonisolatedNonsendingByDefault, "nonisolated-nonsending-by-default")
GROUP(OpaqueTypeInference, "opaque-type-inference")
GROUP(PerformanceHints, "performance-hints")
GROUP(PreconcurrencyImport, "preconcurrency-import")
GROUP(PropertyWrappers, "property-wrapper-requirements")
GROUP(ProtocolTypeNonConformance, "protocol-type-non-conformance")
GROUP(RegionIsolation, "region-isolation")
GROUP(ResultBuilderMethods, "result-builder-methods")
GROUP(ReturnTypeImplicitCopy, "return-type-implicit-copy")
GROUP(SendableClosureCaptures, "sendable-closure-captures")
GROUP(SendableMetatypes, "sendable-metatypes")
GROUP(SendingClosureRisksDataRace, "sending-closure-risks-data-race")
GROUP(SendingRisksDataRace, "sending-risks-data-race")
GROUP(StrictLanguageFeatures, "strict-language-features")
GROUP(StrictMemorySafety, "strict-memory-safety")
@@ -76,14 +82,13 @@ GROUP(StringInterpolationConformance, "string-interpolation-conformance")
GROUP(TemporaryPointers, "temporary-pointers")
GROUP(TrailingClosureMatching, "trailing-closure-matching")
GROUP(UnknownWarningGroup, "unknown-warning-group")
GROUP(CompilationCaching, "compilation-caching")
GROUP(WeakMutability, "weak-mutability")
GROUP(PerformanceHints, "performance-hints")
GROUP(ReturnTypeImplicitCopy, "return-type-implicit-copy")
GROUP_LINK(PerformanceHints, ReturnTypeImplicitCopy)
GROUP(ExistentialType, "existential-type")
GROUP_LINK(PerformanceHints, ExistentialType)
GROUP_LINK(PerformanceHints, ReturnTypeImplicitCopy)
GROUP_LINK(RegionIsolation, SendingClosureRisksDataRace)
GROUP_LINK(RegionIsolation, SendingRisksDataRace)
#define UNDEFINE_DIAGNOSTIC_GROUPS_MACROS
#include "swift/AST/DefineDiagnosticGroupsMacros.h"

View File

@@ -1075,7 +1075,7 @@ NOTE(regionbasedisolation_typed_tns_passed_to_sending, none,
"causing races inbetween %0 uses and uses reachable from the callee",
(StringRef, Type))
ERROR(regionbasedisolation_typed_tns_passed_sending_closure, none,
GROUPED_ERROR(regionbasedisolation_typed_tns_passed_sending_closure, SendingClosureRisksDataRace, none,
"passing closure as a 'sending' parameter risks causing data races between %0 and concurrent execution of the closure",
(StringRef))
NOTE(regionbasedisolation_typed_tns_passed_to_sending_closure_helper_have_value, none,

View File

@@ -1,4 +1,6 @@
# Calling an actor-isolated method from a synchronous nonisolated context
# Calling an actor-isolated method from a synchronous nonisolated context (ActorIsolatedCall)
## Overview
Accessing actor-isolated state from outside the actor can cause data races in your program. Resolve this error by calling actor-isolated functions on the actor.

View File

@@ -1,4 +1,6 @@
# Protocol conformances crossing into actor-isolated code
# Protocol conformances crossing into actor-isolated code (ConformanceIsolation)
## Overview
Protocol conformances crossing into actor-isolated code can cause data races in your program. Resolve this error by ensuring access to isolated state is always done within the actor.

View File

@@ -1,42 +0,0 @@
# Diagnostic descriptions
<!-- This file is auto-generated via `swift swift/utils/generate-doc-index.swift` -->
Detailed explanations for various compiler diagnostics.
## Overview
Swift diagnostics are classified into errors and warnings. Warnings can only be silenced in an
intentional manner, e.g., adding `_ =` for an unused function result.
Some diagnostics have more detailed explanations available. These include a `[#Name]` inline and
reference to this documentation at the end of the compiler output on the command line, or is
presented specially within your IDE of choice. See below for the full list of these notes.
## Topics
- <doc:dynamic-callable-requirements>
- <doc:trailing-closure-matching>
- <doc:actor-isolated-call>
- <doc:sendable-closure-captures>
- <doc:string-interpolation-conformance>
- <doc:isolated-conformances>
- <doc:error-in-future-swift-version>
- <doc:module-not-testable>
- <doc:multiple-inheritance>
- <doc:nominal-types>
- <doc:property-wrapper-requirements>
- <doc:protocol-type-non-conformance>
- <doc:exclusivity-violation>
- <doc:conformance-isolation>
- <doc:result-builder-methods>
- <doc:sendable-metatypes>
- <doc:sending-closure-risks-data-race>
- <doc:sending-risks-data-race>
- <doc:temporary-pointers>
- <doc:opaque-type-inference>
- <doc:mutable-global-variable>
- <doc:existential-member-access-limitations>
- <doc:performance-hints>

View File

@@ -2,14 +2,14 @@
<!-- This file is auto-generated via `swift swift/utils/generate-doc-index.swift` -->
Diagnostic groups allow controlling the behavior of warnings in a more precise manner.
Detailed explanations for various compiler diagnostics.
## Overview
Diagnostic groups collect some number of diagnostics together under a common group name. This allows
for extra documentation to help explain relevant language concepts, as well as the ability to
control the behavior of warnings in a more precise manner:
control the behavior of warnings in a more precise manner (when that group contains warnings):
- `-Werror <group>` - upgrades warnings in the specified group to errors
- `-Wwarning <group>` - indicates that warnings in the specified group should remain warnings, even
if they were previously upgraded to errors
@@ -24,18 +24,59 @@ Or upgrade all warnings except deprecated declaration to errors:
-warnings-as-errors -Wwarning DeprecatedDeclaration
```
## Topics
## Groups with warnings
- <doc:always-available-domain>
- <doc:trailing-closure-matching>
- <doc:compilation-caching>
- <doc:string-interpolation-conformance>
- <doc:deprecated-declaration>
- <doc:implementation-only-deprecated>
- <doc:embedded-restrictions>
- <doc:preconcurrency-import>
- <doc:clang-declaration-import>
- <doc:missing-module-on-known-paths>
- <doc:isolated-conformances>
- <doc:error-in-future-swift-version>
- <doc:module-version-missing>
- <doc:result-builder-methods>
- <doc:strict-language-features>
- <doc:strict-memory-safety>
- <doc:unknown-warning-group>
## Topics
- <doc:dynamic-callable-requirements>
- <doc:always-available-domain>
- <doc:trailing-closure-matching>
- <doc:actor-isolated-call>
- <doc:sendable-closure-captures>
- <doc:compilation-caching>
- <doc:string-interpolation-conformance>
- <doc:deprecated-declaration>
- <doc:implementation-only-deprecated>
- <doc:embedded-restrictions>
- <doc:preconcurrency-import>
- <doc:clang-declaration-import>
- <doc:isolated-conformances>
- <doc:error-in-future-swift-version>
- <doc:missing-module-on-known-paths>
- <doc:module-version-missing>
- <doc:module-not-testable>
- <doc:multiple-inheritance>
- <doc:nominal-types>
- <doc:exclusivity-violation>
- <doc:performance-hints>
- <doc:property-wrapper-requirements>
- <doc:conformance-isolation>
- <doc:protocol-type-non-conformance>
- <doc:result-builder-methods>
- <doc:sendable-metatypes>
- <doc:sending-closure-risks-data-race>
- <doc:sending-risks-data-race>
- <doc:strict-language-features>
- <doc:strict-memory-safety>
- <doc:temporary-pointers>
- <doc:opaque-type-inference>
- <doc:unknown-warning-group>
- <doc:availability-unrecognized-name>
- <doc:mutable-global-variable>
- <doc:existential-member-access-limitations>

View File

@@ -9,6 +9,5 @@ Documentation on diagnostics emitted by the compiler and settings that control t
## Topics
- <doc:diagnostic-descriptions>
- <doc:diagnostic-groups>
- <doc:upcoming-language-features>

View File

@@ -1,4 +1,7 @@
# @dynamicCallable Implementation Requirements
# @dynamicCallable implementation requirements (DynamicCallable)
## Overview
If a type is marked with the `@dynamicCallable` attribute, it must provide a valid implementation of `dynamicallyCall(withArguments:)`, `dynamicallyCall(withKeywordArguments:)`, or both. If it fails to do so, an error will be reported at compile-time. Note that an implementation of `dynamicallyCall(withKeywordArguments:)` is required to support calls with keyword arguments.
To be considered valid, an implementation of `dynamicallyCall(withArguments:)` must:
@@ -10,4 +13,8 @@ To be considered valid, an implementation of `dynamicallyCall(withKeywordArgumen
- Be an instance method. `static` or `class` implementations are not allowed.
- Have an argument type which conforms to the `ExpressibleByDictionaryLiteral` protocol. This can be `Dictionary`, `KeyValuePairs` (which may be used to support duplicated keyword arguments), or some other conforming type.
- The `Key` associated type of the argument type must conform to the `ExpressibleByStringLiteral` protocol. This type is used to represent the dynamic argument keywords.
- The `Value` associated type of the argument type and the return type of `dynamicallyCall(withKeywordArguments:)` may be any valid types.
- The `Value` associated type of the argument type and the return type of `dynamicallyCall(withKeywordArguments:)` may be any valid types.
## See also
- [SE-0216](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0216-dynamic-callable.md)

View File

@@ -1,4 +1,6 @@
# Language mode and tools version
# Language mode and tools version (ErrorInFutureSwiftVersion)
## Overview
Swift language mode and Swift compiler tools version are distinct concepts. One compiler version can support multiple language modes.
@@ -7,6 +9,6 @@ There are two related kinds of "Swift version" that are distinct:
* Swift tools version: the version number of the compiler itself. For example, the Swift 5.6 compiler was introduced in March 2022.
* Swift language mode version: the language mode version with which we are providing source compatibility. For example, the Swift 5 language mode is the most current language mode version supported by Swift tools version 5.10.
The Swift tools support multiple Swift language modes. All Swift tools versions between 5.0 and 5.10 support three Swift language modes: 4, 4.2, and 5. The Swift 6.0 compiler supports four Swift language modes: 4, 4.2, 5, and 6. Swift language modes are opt-in; when you use a tools version that supports a new language mode, your code will not build with the new language mode until you set that language mode in your build settings with `-swift-version X`.
The Swift tools support multiple Swift language modes. All Swift tools versions between 5.0 and 5.10 support three Swift language modes: 4, 4.2, and 5. The Swift 6.0 compiler supports four Swift language modes: 4, 4.2, 5, and 6. Swift language modes are opt-in; when you use a tools version that supports a new language mode, your code will not build with the new language mode until you set that language mode in your build settings with `-language-mode X`.
A warning suffixed with `this is an error in the Swift 6 language mode` means that once you migrate to that language mode in your code, the warning will be promoted to an error. These warnings primarily come from enabling upcoming features that are enabled by default in that language mode version, but errors may also be staged in as warnings until the next language mode to maintain source compatibility when fixing compiler bugs.

View File

@@ -1,4 +1,6 @@
# Overlapping accesses, but operation requires exclusive access
# Overlapping accesses, but operation requires exclusive access (ExclusivityViolation)
## Overview
Swift requires exclusive access to a variable in order to modify that variable. An error is reported if a program attempts to access a variable while it is already in the process of being accessed via another name. These issues can often be resolved by making a local copy of a variable before modifying it.
@@ -58,4 +60,10 @@ var toAppend = numbers
numbers.append(removingFrom: &toAppend)
```
Exclusivity checks play an important role in enforcing memory safety and enabling compiler optimizations. To learn more, see [Swift 5 Exclusivity Enforcement](https://www.swift.org/blog/swift-5-exclusivity/) on the Swift.org blog.
Exclusivity checks play an important role in enforcing memory safety and enabling compiler optimizations. See the Swift.org [blog][exclusivity-enforcement] to learn more.
## See Also
- [Swift 5 exclusivity enforcement][exclusivity-enforcement]
[exclusivity-enforcement]: https://www.swift.org/blog/swift-5-exclusivity/

View File

@@ -1,4 +1,4 @@
# Using Protocol Members with References to `Self` or `Self`-rooted Associated Types
# Using protocol members with references to `Self` or `Self`-rooted associated types (ExistentialMemberAccess)
Protocol requirements and protocol extension members may be accessed via a conformance constraint on a generic parameter, an opaque result type, or via the protocol type itself:
@@ -51,4 +51,16 @@ func duplicateShape(_ shape: Shape) -> Shape {
}
```
Most use cases involving usage of protocol members that fall under the above restriction can instead be supported by constrained generics, opaque result types, or manual type-erasing wrappers. To learn more, see the sections on [protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html), [generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html), and [opaque types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) in the Language Guide. For a better understanding of existential types in particular, and an in-depth exploration of the relationships among these built-in abstraction models, we recommend reading the [design document for improving the UI of the generics model](https://forums.swift.org/t/improving-the-ui-of-generics/22814).
Most use cases involving usage of protocol members that fall under the above restriction can instead be supported by constrained generics, opaque result types, or manual type-erasing wrappers. To learn more, see the sections on [protocols], [generics], and [opaque types][opaque-types] in the Language Guide. For a better understanding of existential types in particular, and an in-depth exploration of the relationships among these built-in abstraction models, we recommend reading [design document for improving the UI of the generics model][improving-generics-ui].
## See Also
- [Generics][generics]
- [Improving the UI of generics][improving-generics-ui]
- [Opaque Types][opaque-types]
- [Protocols][protocols]
[generics]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics
[improving-generics-ui]: https://forums.swift.org/t/improving-the-ui-of-generics/22814
[opaque-types]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/opaquetypes
[protocols]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols

View File

@@ -2,11 +2,12 @@
Warnings that identify `import` declarations with the `@_implementationOnly` attribute.
## Overview
When applied to `import` declarations, the compiler-internal attribute `@_implementationOnly` attempts prevents declarations from the imported module from being exposed in the ABI or public interface of the dependent module. This attribute became deprecated when support for access levels on `import` declarations was introduced with [SE-0409].
One reason `@_implementationOnly import` is deprecated is that it is unsafe when used in modules that are built _without_ [library evolution] enabled. For example, suppose the following code were part of a library named `Foo`:
One reason `@_implementationOnly import` is deprecated is that it is unsafe when used in modules that are built _without_ [library evolution][library-evolution] enabled. For example, suppose the following code were part of a library named `Foo`:
```swift
// Library `Foo`
@@ -19,5 +20,10 @@ public struct Bar {
If `Foo` is not compiled with library evolution, then the memory layout of values of `Bar` must be known at compile time in clients of `Foo`. However, the `@_implementationOnly import` of `ImplementationDetail` prevents clients from being able to look up `Baz` which is a type that contributes to the layout of `Foo`. As a result, the layout of `Foo` will be miscalculated resulting in undefined behavior.
## See Also
- [SE-0409: Access level on imports][SE-0409]
- [Library evolution][library-evolution]
[SE-0409]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md
[library evolution]: https://www.swift.org/blog/library-evolution/
[library-evolution]: https://www.swift.org/blog/library-evolution/

View File

@@ -1,4 +1,6 @@
# Isolated conformances
# Isolated conformances (IsolatedConformances)
## Overview
Using an isolated conformance from outside the actor can cause data races in your program. Resolve these errors by only using isolated conformances within the actor.

View File

@@ -1,5 +1,7 @@
# Module not testable
# Module not testable (ModuleNotTestable)
## Overview
Modules imported using `@testable import` must have been compiled using the `-enable-testing` compiler flag.
`@testable import` allows clients of a module to access `internal` API when writing tests. A `@testable import` will report an error if the imported module was not compiled with the `-enable-testing` compiler flag. Use of `-enable-testing` is recommended only in debug builds or other builds not intended for production use.
`@testable import` allows clients of a module to access `internal` API when writing tests. A `@testable import` will report an error if the imported module was not compiled with the `-enable-testing` compiler flag. Use of `-enable-testing` is recommended only in debug builds or other builds not intended for production use.

View File

@@ -1,17 +1,19 @@
# Multiple Inheritance
# Multiple inheritance (MultipleInheritance)
## Overview
In some programming languages, a class can inherit the interface of multiple base classes. Known as multiple inheritance, this feature can add significant complexity to the language and is unsupported in Swift. Instead, Swift allows composition of interfaces using protocols.
Consider the following example:
```swift
protocol Utensil {
protocol Utensil {
var name: String { get }
}
}
protocol ServingUtensil: Utensil {
func serve()
}
}
extension ServingUtensil {
func serve() { /* Default implementation. */ }
@@ -32,6 +34,16 @@ struct Ladle: ServingUtensil, Spoon { /* ... */ }
Swift protocols can declare interfaces that must be implemented by each conforming type (like abstract class members in other programming languages such as C# or Java), and they can also provide overridable default implementations for those requirements in protocol extensions.
When class inheritance and protocol conformances are used together, subclasses inherit protocol conformances from base classes, introducing additional complexity. For example, the default implementation of a protocol requirement not overridden in the conforming base class also cannot be overridden in any subclass ([#42725](https://github.com/apple/swift/issues/42725)).
When class inheritance and protocol conformances are used together, subclasses inherit protocol conformances from base classes, introducing additional complexity. For example, the default implementation of a protocol requirement not overridden in the conforming base class also cannot be overridden in any subclass ([#42725]).
To learn more about defining and adopting protocols, see the [Protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html) section in _The Swift Programming Language_. To learn more about class inheritance, see the [Inheritance](https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html) section in _The Swift Programming Language_.
To learn more about defining and adopting protocols, see the [Protocols][protocols] section in _The Swift Programming Language_. To learn more about class inheritance, see the [Inheritance][inheritance] section in _The Swift Programming Language_.
## See Also
- [GitHub issue #42725][#42725]
- [Inheritance][inheritance]
- [Protocols][protocols]
[#42725]: https://github.com/apple/swift/issues/42725
[inheritance]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/inheritance
[protocols]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols

View File

@@ -1,4 +1,7 @@
# Unsafe mutable global and static variables
# Unsafe mutable global and static variables (MutableGlobalVariable)
## Overview
Mutable global and static variables that can be accessed from anywhere can cause data races in your program. Resolve this error by making the state immutable or protecting it with a global actor.
@@ -46,7 +49,7 @@ This code is also diagnosed under complete concurrency checking. Even though the
```swift
class MyModel {
@MainActor
static let shared = MyModel()
static let shared = MyModel()
}
```
@@ -57,4 +60,4 @@ Alternatively, isolate the `MyModel` class to the main actor, which will also ma
class MyModel {
static let shared = MyModel()
}
```
```

View File

@@ -1,4 +1,6 @@
# Nominal Types
# Nominal types (NominalTypes)
## Overview
In Swift, a type is considered a nominal type if it has been explicitly named by a declaration somewhere in code. Examples of nominal types include classes, structures and enumerations. Nominal types are an important concept in Swift because they may conform to protocols, be extended, and have values created using the initializer syntax `MyType()`.
@@ -6,4 +8,10 @@ In contrast, non-nominal types do not have these capabilities. Many are obtained
Since a protocol is named by a declaration in code, it may conform to (in other words, refine) other protocols and it may be extended. However, when written as the type of a constant or variable such as `let value: MyProtocol`, the name refers to a distinct, non-nominal existential type that provides a "box" for a value of any concrete type that conforms to the protocol. The existential type itself does not conform to any protocols and cannot be extended, and a value cannot be created using the initializer syntax `MyProtocol()`.
For more on using existential types, see [Protocols as Types](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID275) in _The Swift Programming Language_.
For more on using existential types, see [Protocols as Types][protocols-as-types] in _The Swift Programming Language_.
## See Also
- [Protocols as Types][protocols-as-types]
[protocols-as-types]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols#Protocols-as-Types

View File

@@ -1,4 +1,6 @@
# Underlying Type Inference for Opaque Result Types
# Underlying type inference for opaque result types (OpaqueTypeInference)
## Overview
Opaque result types are a useful tool for abstracting the return type of a function or subscript, or type of a property. Although the concrete underlying type of an opaque type is hidden from clients, it is still inferred by the compiler, which enforces certain usage requirements:
@@ -64,5 +66,10 @@ func bar(_ x: Int) -> some Equatable { // OK, the underlying type can be inferre
}
```
To learn more about opaque result types, see the [Opaque Types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) section of _The Swift Programming Language_.
To learn more about opaque result types, see the [Opaque Types][opaque-types] section of _The Swift Programming Language_.
## See Also
- [Opaque Types][opaque-types]
[opaque-types]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/opaquetypes

View File

@@ -1,3 +1,3 @@
# Swift Performance Hint: Function returning Array or Dictionary type
# Performance hints (PerformanceHints)
- TODO: Docs
## Overview

View File

@@ -1,6 +1,9 @@
# Property Wrapper Implementation Requirements
# Property wrapper implementation requirements (PropertyWrappers)
## Overview
If a type is marked with the `@propertyWrapper` attribute, it must meet certain requirements to be a valid property wrapper.
First, all property wrapper types must have a property named `wrappedValue`. This property cannot be static and must have the same access level as the property wrapper type. If the property wrapper provides a `projectedValue` property, it is subject to the same requirements.
Second, none of a property wrapper's initializers may be failable. Additionally, if a property wrapper initializer has a `wrappedValue` parameter, the type of that parameter must either be the same as the type of the `wrappedValue` property or an `@autoclosure` of that type.
Second, none of a property wrapper's initializers may be failable. Additionally, if a property wrapper initializer has a `wrappedValue` parameter, the type of that parameter must either be the same as the type of the `wrappedValue` property or an `@autoclosure` of that type.

View File

@@ -1,8 +1,10 @@
# Protocol Types Cannot Conform to Protocols
# Protocol types cannot conform to protocols (ProtocolTypeNonConformance)
## Overview
In Swift, a protocol that does not have `Self` or associated type requirements can be used as a type. You can use a variable or constant of a protocol type, also called an __existential type__, to hold a value of any conforming type:
```swift
```swift
protocol Animal {
func makeNoise()
static var species: String { get }
@@ -89,4 +91,10 @@ struct Habitat {
}
```
For more on using existential types, see [Protocols as Types](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID275) in _The Swift Programming Language_.
For more on using existential types, see [Protocols as Types][protocols-as-types] in _The Swift Programming Language_.
## See Also
- [Protocols as Types][protocols-as-types]
[protocols-as-types]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols#Protocols-as-Types

View File

@@ -1,4 +1,6 @@
# Result Builder Methods
# Result builder methods (ResultBuilderMethods)
## Overview
To be useful as a result builder, a result builder type must provide a
sufficient subset of function-building methods that enable the transformation of

View File

@@ -1,4 +1,6 @@
# Captures in a `@Sendable` closure
# Captures in a `@Sendable` closure (SendableClosureCaptures)
## Overview
`@Sendable` closures can be called multiple times concurrently, so any captured values must also be safe to access concurrently. To prevent data races, the compiler prevents capturing mutable values in a `@Sendable` closure.
@@ -12,7 +14,7 @@ func callConcurrently(
func capture() {
var result = 0
result += 1
callConcurrently {
print(result)
}
@@ -53,7 +55,7 @@ If the type of the capture is `Sendable` and the closure only needs the value of
func capture() {
var result = 0
result += 1
callConcurrently { [result] in
print(result)
}

View File

@@ -1,4 +1,6 @@
# Sendable metatypes
# Sendable metatypes (SendableMetatypes)
## Overview
Types that are shared in concurrent code generally need to conform to `Sendable`. The same is true in generic code when sharing parameters of a generic parameter `T`. For example, the given code will produce an error under strict concurrency checking
@@ -59,4 +61,4 @@ func test(c: C) {
```
The conformance of `C` to `P` can only be used on the main actor, so it cannot be provided to `doSomethingStatic`, which calls the conformance from a different concurrent task.
The conformance of `C` to `P` can only be used on the main actor, so it cannot be provided to `doSomethingStatic`, which calls the conformance from a different concurrent task.

View File

@@ -1,4 +1,6 @@
# Sending closure risks causing data races
# Sending closure risks causing data races (SendingClosureRisksDataRace)
## Overview
Sharing mutable state between concurrent tasks can cause data races in your program. Resolve this error by only accessing mutable state in one task at a time.

View File

@@ -1,4 +1,6 @@
# Sending value risks causing data races
# Sending value risks causing data races (SendingRisksDataRace)
## Overview
Sharing mutable state between concurrent tasks can cause data races in your program. Resolve this error by only accessing mutable state in one task at a time.
@@ -9,7 +11,7 @@ For example, if a value can be accessed from the main actor, it's invalid to sen
```swift
class Person {
var name: String = ""
func printNameConcurrently() async {
print(name)
}
@@ -36,7 +38,7 @@ The most common fix is to change the `async` method to run on the caller's actor
```swift
class Person {
var name: String = ""
nonisolated(nonsending)
func printNameConcurrently() async {
print(name)

View File

@@ -1,4 +1,7 @@
# Conforming to `StringInterpolationProtocol`
# Conforming to `StringInterpolationProtocol` (StringInterpolationConformance)
## Overview
A type conforming to `ExpressibleByStringInterpolation` uses a helper type called `StringInterpolation` to perform its interpolation. Many types can use `DefaultStringInterpolation`, which implements `String`'s interpolation behavior. Types can also implement custom behavior by providing their own type conforming to `StringInterpolationProtocol`.
In addition to its formal requirements, `init(literalCapacity:interpolationCount:)` and `appendLiteral(_:)`, `StringInterpolationProtocol` has an additional, informal requirement, `appendInterpolation`. String interpolations using `\()` syntax are translated into calls to matching `appendInterpolation` methods.

View File

@@ -1,4 +1,7 @@
# Temporary Pointers
# Temporary pointers (TemporaryPointers)
## Overview
A temporary, or ephemeral, pointer in Swift is a pointer which is introduced by an implicit function argument conversion and is only valid for the lifetime of the function call it appears in. There are a few ways to create a temporary pointer:
- Using an inout-to-pointer conversion by passing an argument with `&`:
@@ -61,4 +64,3 @@ let ptr = withUnsafePointer(to: &x) { $0 }
This code is invalid because the pointer to `x` is only valid until `withUnsafePointer` returns, but it escapes the closure when it is returned and assigned to `ptr`.
To learn more about correctly using unsafe pointer APIs, see the Swift standard library documentation of `UnsafePointer` and related types.

View File

@@ -1,11 +1,13 @@
# Argument Matching for Trailing Closures
# Argument matching for trailing closures (TrailingClosureMatching)
## Overview
Where trailing closures are used to pass one or more arguments to a function, the argument label for the first trailing closure is always omitted:
```swift
func animate(
withDuration duration: Double,
animations: () -> Void,
withDuration duration: Double,
animations: () -> Void,
completion: (() -> Void)? = nil
) { /* ... */ }
@@ -40,8 +42,8 @@ When scanning forwards to match an unlabeled trailing closure argument, the comp
```swift
func animate(
withDuration duration: Double = 1.0,
animations: () -> Void,
withDuration duration: Double = 1.0,
animations: () -> Void,
completion: (() -> Void)? = nil
) { /* ... */ }
@@ -60,7 +62,7 @@ animate {
For source compatibility in Swift 5, the compiler will attempt to apply *both* the new forward scanning rule and the old backward scanning rule when it encounters a function call with a single trailing closure. If the forward and backward scans produce *different valid* matches of arguments to parameters, the compiler will prefer the result of the backward scanning rule and produce a warning. To silence this warning, rewrite the function call to label the argument explicitly without using trailing closure syntax.
## Structural Resemblance to a Function Type
## Structural resemblance to a function type
A parameter structurally resembles a function type if both of the following are true:
@@ -73,7 +75,7 @@ The adjusted type of the parameter is the parameter's type as it appears in the
2. If the parameter is variadic, look at the base element type.
3. Remove all outer "optional" types.
## Heuristic for Skipping Parameters
## Heuristic for skipping parameters
To maintain source compatibility, the forward scanning rule applies an additional heuristic when matching trailing closure arguments. If:
@@ -107,4 +109,7 @@ showAlert(message: "Hello, World!") {
}
```
To learn more about argument matching for trailing closures, see [Swift Evolution Proposal SE-0286](https://github.com/apple/swift-evolution/blob/master/proposals/0286-forward-scan-trailing-closures.md).
## See Also
- [SE-0279: Multiple trailing closures](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0279-multiple-trailing-closures.md)
- [SE-0286: Forward-scan matching for trailing closures](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0286-forward-scan-trailing-closures.md)

View File

@@ -16,9 +16,7 @@ Some upcoming features have an additional "migration" mode, where the compiler w
with fix-its to help migrate to that mode. This can be enabled with `-enable-upcoming-feature
<feature>:migrate`.
## Topics
- <doc:existential-any>
- <doc:member-import-visibility>
- <doc:nonisolated-nonsending-by-default>

View File

@@ -5,50 +5,26 @@ import Foundation
let usage = """
./\(CommandLine.arguments[0]) <swift-source-directory> [output-directory]
Generates index files for diagnostics notes, groups, and upcoming features.
Generates index files for diagnostics groups and upcoming features.
"""
let docsDir = "userdocs/diagnostics"
let topLevelFileName = "diagnostics.md"
let notesDocFileName = "diagnostic-descriptions.md"
let notesHeader = """
# Diagnostic descriptions
let groupsDocFileName = "diagnostic-groups.md"
let groupsHeader = """
# Diagnostic groups
<!-- This file is auto-generated via `swift swift/utils/generate-doc-index.swift` -->
Detailed explanations for various compiler diagnostics.
## Overview
Swift diagnostics are classified into errors and warnings. Warnings can only be silenced in an
intentional manner, e.g., adding `_ =` for an unused function result.
Some diagnostics have more detailed explanations available. These include a `[#Name]` inline and
reference to this documentation at the end of the compiler output on the command line, or is
presented specially within your IDE of choice. See below for the full list of these notes.
## Topics
"""
let groupsDocFileName = "diagnostic-groups.md"
let groupsHeader = """
# Diagnostic groups
<!-- This file is auto-generated via `swift swift/utils/generate-doc-index.swift` -->
Diagnostic groups allow controlling the behavior of warnings in a more precise manner.
## Overview
Diagnostic groups collect some number of diagnostics together under a common group name. This allows
for extra documentation to help explain relevant language concepts, as well as the ability to
control the behavior of warnings in a more precise manner:
control the behavior of warnings in a more precise manner (when that group contains warnings):
- `-Werror <group>` - upgrades warnings in the specified group to errors
- `-Wwarning <group>` - indicates that warnings in the specified group should remain warnings, even
if they were previously upgraded to errors
@@ -62,11 +38,6 @@ Or upgrade all warnings except deprecated declaration to errors:
```sh
-warnings-as-errors -Wwarning DeprecatedDeclaration
```
## Topics
"""
let featuresDocFileName = "upcoming-language-features.md"
@@ -88,18 +59,17 @@ enabled on the command line with `-enable-upcoming-feature <feature>`.
Some upcoming features have an additional "migration" mode, where the compiler will emit warnings
with fix-its to help migrate to that mode. This can be enabled with `-enable-upcoming-feature
<feature>:migrate`.
## Topics
"""
let groupsFileName = "include/swift/AST/DiagnosticGroups.def"
let groupRegex = /GROUP\(([a-zA-Z]+), ".+"\)/
let topicsHeader = "\n\n## Topics\n"
let featuresFileName = "include/swift/Basic/Features.def"
let featuresRegex = /UPCOMING_FEATURE\(([a-zA-Z]+), .+\)/
let swiftIncludeDir = "include/swift"
let groupsFileName = "\(swiftIncludeDir)/AST/DiagnosticGroups.def"
let groupRegex = /GROUP\((?<name>[a-zA-Z]+), "(?<file>.+)"\)/
let featuresFileName = "\(swiftIncludeDir)/Basic/Features.def"
let featuresRegex = /UPCOMING_FEATURE\((?<name>[a-zA-Z]+), .+\)/
let nameRegex = /# .+ \((?<name>[a-zA-Z]+)\)/
@@ -117,122 +87,185 @@ if !args.isEmpty {
outputDir = "\(swiftSourceDir)/\(docsDir)"
}
let generator = GenerateUserDocs(swiftSourceDir: swiftSourceDir, outputDir: outputDir)
do {
try generator.generateIndex()
try generateIndex()
} catch {
print("error: \(error)")
exit(1)
}
struct GenerateUserDocs {
let swiftSourceDir: String
let outputDir: String
func generateIndex() throws {
let groupsHandle = try createIndex(name: groupsDocFileName, header: groupsHeader)
defer { try? groupsHandle.close() }
func generateIndex() throws {
let notesHandle = try createIndex(name: notesDocFileName, header: notesHeader)
defer { try? notesHandle.close() }
let featuresHandle = try createIndex(name: featuresDocFileName, header: featuresHeader)
defer { try? featuresHandle.close() }
let groupsHandle = try createIndex(name: groupsDocFileName, header: groupsHeader)
defer { try? groupsHandle.close() }
let groupsWithWarnings = try groupNamesWithWarnings()
let docs = try retrieveDocs(groupsWithWarnings).sorted { a, b in
return a.title < b.title
}
let featuresHandle = try createIndex(name: featuresDocFileName, header: featuresHeader)
defer { try? featuresHandle.close() }
try groupsHandle.write(contentsOf: "\n\n## Groups with warnings\n".data(using: .utf8)!)
for doc in docs where doc.kind == .groupWithWarnings {
let ref = "- <doc:\(doc.name.dropLast(3))>\n"
try groupsHandle.write(contentsOf: ref.data(using: .utf8)!)
}
let docs = try retrieveDocs().sorted { a, b in
return a.title < b.title
try groupsHandle.write(contentsOf: topicsHeader.data(using: .utf8)!)
try featuresHandle.write(contentsOf: topicsHeader.data(using: .utf8)!)
for doc in docs {
let handle: FileHandle
switch doc.kind {
case .group, .groupWithWarnings:
handle = groupsHandle
case .feature:
handle = featuresHandle
}
for doc in docs {
let handle: FileHandle
switch doc.kind {
case .note:
handle = notesHandle
case .group:
handle = groupsHandle
case .feature:
handle = featuresHandle
let ref = "- <doc:\(doc.name.dropLast(3))>\n"
try handle.write(contentsOf: ref.data(using: .utf8)!)
}
}
func createIndex(name: String, header: String) throws -> FileHandle {
let path = "\(outputDir)/\(name)"
if FileManager.default.fileExists(atPath: path) {
try FileManager.default.removeItem(atPath: path)
}
FileManager.default.createFile(atPath: path, contents: nil)
let handle = try FileHandle(forWritingTo: URL(filePath: path))
try handle.write(contentsOf: header.data(using: .utf8)!)
return handle
}
func retrieveDocs(_ groupsWithWarnings: Set<String>) throws -> [UserDoc] {
let groups = Dictionary(try matches(in: "\(swiftSourceDir)/\(groupsFileName)", with: groupRegex) {
(file: String($0.file), name: String($0.name))
}, uniquingKeysWith: { a, b in a })
let features = Set(try matches(in: "\(swiftSourceDir)/\(featuresFileName)", with: featuresRegex) {
String($0.1)
})
var docs: [UserDoc] = []
let files = try FileManager.default.contentsOfDirectory(atPath: "\(swiftSourceDir)/\(docsDir)")
for name in files {
if !name.hasSuffix(".md")
|| name.hasSuffix(topLevelFileName)
|| name.hasSuffix(groupsDocFileName)
|| name.hasSuffix(featuresDocFileName) {
continue
}
guard let groupName = groups[String(name.dropLast(3))] else {
throw GenerationError.unknownGroup(file: name)
}
let path = try String(contentsOfFile: "\(swiftSourceDir)/\(docsDir)/\(name)", encoding: .utf8)
guard let match = try? nameRegex.prefixMatch(in: path) else {
throw GenerationError.missingGroup(name: groupName, file: name)
}
let titleGroupName = String(match.name)
if groupName != titleGroupName {
throw GenerationError.incorrectGroup(defsName: groupName, titleName: titleGroupName, file: name)
}
let kind: UserDoc.Kind
if features.contains(groupName) {
kind = .feature
} else if groupsWithWarnings.contains(groupName) {
kind = .groupWithWarnings
} else {
kind = .group
}
docs.append(UserDoc(name: name, title: String(match.0), kind: kind))
}
return docs
}
func groupNamesWithWarnings() throws -> Set<String> {
let includePath = "\(swiftSourceDir)/\(swiftIncludeDir)"
let defPaths = try FileManager.default.subpathsOfDirectory(atPath: includePath)
.compactMap { subpath in
if subpath.hasSuffix(".def") {
return "\(includePath)/\(subpath)"
}
let ref = "- <doc:\(doc.name.dropLast(3))>\n"
try handle.write(contentsOf: ref.data(using: .utf8)!)
return nil
}
enum WarningGroupState {
case outside, inside, name
}
func createIndex(name: String, header: String) throws -> FileHandle {
let path = "\(outputDir)/\(name)"
var groups: Set<String> = []
for path in defPaths {
let file = try String(contentsOfFile: path, encoding: .utf8)
if FileManager.default.fileExists(atPath: path) {
try FileManager.default.removeItem(atPath: path)
}
FileManager.default.createFile(atPath: path, contents: nil)
let handle = try FileHandle(forWritingTo: URL(filePath: path))
try handle.write(contentsOf: header.data(using: .utf8)!)
return handle
}
func matches(in fileName: String, with regex: Regex<(Substring, Substring)>) throws -> Set<String> {
let file = try String(contentsOfFile: "\(swiftSourceDir)/\(fileName)", encoding: .utf8)
var matches: Set<String> = []
var state = WarningGroupState.outside
for line in file.components(separatedBy: .newlines) {
if let match = try? regex.firstMatch(in: line) {
matches.insert(String(match.1))
}
}
var line = Substring(line)
return matches
}
func retrieveDocs() throws -> [UserDoc] {
let groups = try matches(in: groupsFileName, with: groupRegex)
let features = try matches(in: featuresFileName, with: featuresRegex)
var docs: [UserDoc] = []
let files = try FileManager.default.contentsOfDirectory(atPath: "\(swiftSourceDir)/\(docsDir)")
for name in files {
if !name.hasSuffix(".md")
|| name.hasSuffix(topLevelFileName)
|| name.hasSuffix(notesDocFileName)
|| name.hasSuffix(groupsDocFileName)
|| name.hasSuffix(featuresDocFileName) {
continue
}
let file = try String(contentsOfFile: "\(swiftSourceDir)/\(docsDir)/\(name)", encoding: .utf8)
if let match = try? nameRegex.prefixMatch(in: file) {
let groupName = String(match.name)
let kind: UserDoc.Kind
if features.contains(groupName) {
kind = .feature
} else if groups.contains(groupName) {
kind = .group
} else {
kind = .note
switch state {
case .outside:
if !line.hasPrefix("GROUPED_WARNING") {
continue
}
docs.append(UserDoc(name: name, title: String(match.0), kind: kind))
} else {
if let newlineIndex = file.firstIndex(of: "\n") {
docs.append(UserDoc(name: name, title: String(file[..<newlineIndex]), kind: .note))
} else {
docs.append(UserDoc(name: name, title: file, kind: .note))
state = .inside
fallthrough
case .inside:
guard let index = line.firstIndex(of: ",") else {
continue
}
line = line[index...].dropFirst()
state = .name
fallthrough
case .name:
if let index = line.firstIndex(of: ",") {
line = line[..<index]
}
line = line.trimmingPrefix { $0.isWhitespace }
if line.isEmpty {
continue
}
groups.insert(String(line))
state = .outside
}
}
return docs
}
return groups
}
func matches<R, E>(in path: String, with regex: Regex<R>, _ transform: (Regex<R>.Match) -> E) throws -> [E] {
let file = try String(contentsOfFile: path, encoding: .utf8)
var matches = [E]()
for line in file.components(separatedBy: .newlines) {
if let match = try? regex.firstMatch(in: line) {
matches.append(transform(match))
}
}
return matches
}
struct UserDoc {
enum Kind {
case note
case group
case groupWithWarnings
case feature
}
@@ -240,3 +273,20 @@ struct UserDoc {
let title: String
let kind: Kind
}
enum GenerationError: CustomStringConvertible, Error {
case incorrectGroup(defsName: String, titleName: String, file: String)
case missingGroup(name:String, file: String)
case unknownGroup(file: String)
var description: String {
switch self {
case .incorrectGroup(let defsName, let titleName, let file):
return "The title in '\(file)' contains the name '\(titleName)', but it should be '\(defsName)' as per 'DiagnosticGroups.def'"
case .missingGroup(let name, let file):
return "The title in '\(file)' does not end with a group name, add ' (\(name))' to the end of the title"
case .unknownGroup(let file):
return "'\(file)' has no corresponding listing in 'DiagnosticGroups.def'"
}
}
}