diff --git a/include/swift/AST/DiagnosticGroups.def b/include/swift/AST/DiagnosticGroups.def index 4f55336d1ed97..fc61388da63da 100644 --- a/include/swift/AST/DiagnosticGroups.def +++ b/include/swift/AST/DiagnosticGroups.def @@ -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" diff --git a/include/swift/AST/DiagnosticsSIL.def b/include/swift/AST/DiagnosticsSIL.def index 0b744c0debd19..62130ee28929a 100644 --- a/include/swift/AST/DiagnosticsSIL.def +++ b/include/swift/AST/DiagnosticsSIL.def @@ -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, diff --git a/userdocs/diagnostics/actor-isolated-call.md b/userdocs/diagnostics/actor-isolated-call.md index aed3d3ceb27fc..f92dc96d57d05 100644 --- a/userdocs/diagnostics/actor-isolated-call.md +++ b/userdocs/diagnostics/actor-isolated-call.md @@ -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. diff --git a/userdocs/diagnostics/conformance-isolation.md b/userdocs/diagnostics/conformance-isolation.md index a2db04fb953e9..857f35602ced1 100644 --- a/userdocs/diagnostics/conformance-isolation.md +++ b/userdocs/diagnostics/conformance-isolation.md @@ -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. diff --git a/userdocs/diagnostics/diagnostic-descriptions.md b/userdocs/diagnostics/diagnostic-descriptions.md deleted file mode 100644 index 5f20bec345374..0000000000000 --- a/userdocs/diagnostics/diagnostic-descriptions.md +++ /dev/null @@ -1,42 +0,0 @@ -# Diagnostic descriptions - - - -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 - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- diff --git a/userdocs/diagnostics/diagnostic-groups.md b/userdocs/diagnostics/diagnostic-groups.md index 609e732c154d5..df0fd6710e979 100644 --- a/userdocs/diagnostics/diagnostic-groups.md +++ b/userdocs/diagnostics/diagnostic-groups.md @@ -2,14 +2,14 @@ -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 ` - upgrades warnings in the specified group to errors - `-Wwarning ` - 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 ``` +## Groups with warnings +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- -## Topics +## Topics +- +- +- +- +- - +- - - - - - +- +- - - +- +- +- +- +- +- +- +- +- +- +- +- - - +- +- - - +- +- diff --git a/userdocs/diagnostics/diagnostics.md b/userdocs/diagnostics/diagnostics.md index 0f0af419265d4..88d473d445b08 100644 --- a/userdocs/diagnostics/diagnostics.md +++ b/userdocs/diagnostics/diagnostics.md @@ -9,6 +9,5 @@ Documentation on diagnostics emitted by the compiler and settings that control t ## Topics -- - - diff --git a/userdocs/diagnostics/dynamic-callable-requirements.md b/userdocs/diagnostics/dynamic-callable-requirements.md index 82ff8c5605481..8c5ba7a3c8f85 100644 --- a/userdocs/diagnostics/dynamic-callable-requirements.md +++ b/userdocs/diagnostics/dynamic-callable-requirements.md @@ -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. \ No newline at end of file +- 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) diff --git a/userdocs/diagnostics/error-in-future-swift-version.md b/userdocs/diagnostics/error-in-future-swift-version.md index c10ca6e9807dc..40bf9f9e5a35f 100644 --- a/userdocs/diagnostics/error-in-future-swift-version.md +++ b/userdocs/diagnostics/error-in-future-swift-version.md @@ -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. diff --git a/userdocs/diagnostics/exclusivity-violation.md b/userdocs/diagnostics/exclusivity-violation.md index 6c01fc1839ecd..b4043ae15452c 100644 --- a/userdocs/diagnostics/exclusivity-violation.md +++ b/userdocs/diagnostics/exclusivity-violation.md @@ -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. \ No newline at end of file +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/ diff --git a/userdocs/diagnostics/existential-member-access-limitations.md b/userdocs/diagnostics/existential-member-access-limitations.md index 4ae0be9fd5881..4a0b68ab595d9 100644 --- a/userdocs/diagnostics/existential-member-access-limitations.md +++ b/userdocs/diagnostics/existential-member-access-limitations.md @@ -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 diff --git a/userdocs/diagnostics/implementation-only-deprecated.md b/userdocs/diagnostics/implementation-only-deprecated.md index d93c65c771f1e..a3b75295c4887 100644 --- a/userdocs/diagnostics/implementation-only-deprecated.md +++ b/userdocs/diagnostics/implementation-only-deprecated.md @@ -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/ diff --git a/userdocs/diagnostics/isolated-conformances.md b/userdocs/diagnostics/isolated-conformances.md index f89d6360e0295..722ac064068ce 100644 --- a/userdocs/diagnostics/isolated-conformances.md +++ b/userdocs/diagnostics/isolated-conformances.md @@ -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. diff --git a/userdocs/diagnostics/module-not-testable.md b/userdocs/diagnostics/module-not-testable.md index 3e37850ec0279..afc1d4f433838 100644 --- a/userdocs/diagnostics/module-not-testable.md +++ b/userdocs/diagnostics/module-not-testable.md @@ -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. \ No newline at end of file +`@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. diff --git a/userdocs/diagnostics/multiple-inheritance.md b/userdocs/diagnostics/multiple-inheritance.md index a7d955d30a8c5..20611c5357869 100644 --- a/userdocs/diagnostics/multiple-inheritance.md +++ b/userdocs/diagnostics/multiple-inheritance.md @@ -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][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] -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_. +[#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 diff --git a/userdocs/diagnostics/mutable-global-variable.md b/userdocs/diagnostics/mutable-global-variable.md index b20fc2abd786a..a2daf76672691 100644 --- a/userdocs/diagnostics/mutable-global-variable.md +++ b/userdocs/diagnostics/mutable-global-variable.md @@ -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() } -``` \ No newline at end of file +``` diff --git a/userdocs/diagnostics/nominal-types.md b/userdocs/diagnostics/nominal-types.md index bd3c55312ece5..1326b64323dfc 100644 --- a/userdocs/diagnostics/nominal-types.md +++ b/userdocs/diagnostics/nominal-types.md @@ -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_. \ No newline at end of file +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 diff --git a/userdocs/diagnostics/opaque-type-inference.md b/userdocs/diagnostics/opaque-type-inference.md index ebf63955530f5..d06b1b27406ff 100644 --- a/userdocs/diagnostics/opaque-type-inference.md +++ b/userdocs/diagnostics/opaque-type-inference.md @@ -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 diff --git a/userdocs/diagnostics/performance-hints.md b/userdocs/diagnostics/performance-hints.md index a50f49502864a..d3874832a1ff3 100644 --- a/userdocs/diagnostics/performance-hints.md +++ b/userdocs/diagnostics/performance-hints.md @@ -1,3 +1,3 @@ -# Swift Performance Hint: Function returning Array or Dictionary type +# Performance hints (PerformanceHints) -- TODO: Docs +## Overview diff --git a/userdocs/diagnostics/property-wrapper-requirements.md b/userdocs/diagnostics/property-wrapper-requirements.md index 5dc125652f4e8..bda47f5a3737a 100644 --- a/userdocs/diagnostics/property-wrapper-requirements.md +++ b/userdocs/diagnostics/property-wrapper-requirements.md @@ -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. \ No newline at end of file +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. diff --git a/userdocs/diagnostics/protocol-type-non-conformance.md b/userdocs/diagnostics/protocol-type-non-conformance.md index 11771460941e1..c7793542bd704 100644 --- a/userdocs/diagnostics/protocol-type-non-conformance.md +++ b/userdocs/diagnostics/protocol-type-non-conformance.md @@ -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 diff --git a/userdocs/diagnostics/result-builder-methods.md b/userdocs/diagnostics/result-builder-methods.md index 896f415d3062f..9101d14b1168b 100644 --- a/userdocs/diagnostics/result-builder-methods.md +++ b/userdocs/diagnostics/result-builder-methods.md @@ -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 diff --git a/userdocs/diagnostics/sendable-closure-captures.md b/userdocs/diagnostics/sendable-closure-captures.md index fdf9d90d95417..b54c85f73feae 100644 --- a/userdocs/diagnostics/sendable-closure-captures.md +++ b/userdocs/diagnostics/sendable-closure-captures.md @@ -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) } diff --git a/userdocs/diagnostics/sendable-metatypes.md b/userdocs/diagnostics/sendable-metatypes.md index eeb2321910f83..f08cc6926fb6a 100644 --- a/userdocs/diagnostics/sendable-metatypes.md +++ b/userdocs/diagnostics/sendable-metatypes.md @@ -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. \ No newline at end of file +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. diff --git a/userdocs/diagnostics/sending-closure-risks-data-race.md b/userdocs/diagnostics/sending-closure-risks-data-race.md index e287bec3b7751..b51618a59d797 100644 --- a/userdocs/diagnostics/sending-closure-risks-data-race.md +++ b/userdocs/diagnostics/sending-closure-risks-data-race.md @@ -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. diff --git a/userdocs/diagnostics/sending-risks-data-race.md b/userdocs/diagnostics/sending-risks-data-race.md index 46418ca327c8d..d1f76d696a590 100644 --- a/userdocs/diagnostics/sending-risks-data-race.md +++ b/userdocs/diagnostics/sending-risks-data-race.md @@ -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) diff --git a/userdocs/diagnostics/string-interpolation-conformance.md b/userdocs/diagnostics/string-interpolation-conformance.md index 27b8072f62766..ec6ab986dfa74 100644 --- a/userdocs/diagnostics/string-interpolation-conformance.md +++ b/userdocs/diagnostics/string-interpolation-conformance.md @@ -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. diff --git a/userdocs/diagnostics/temporary-pointers.md b/userdocs/diagnostics/temporary-pointers.md index feee3e798bd02..677a5ca503235 100644 --- a/userdocs/diagnostics/temporary-pointers.md +++ b/userdocs/diagnostics/temporary-pointers.md @@ -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. - diff --git a/userdocs/diagnostics/trailing-closure-matching.md b/userdocs/diagnostics/trailing-closure-matching.md index f1ce7c0fdf939..374282935f23e 100644 --- a/userdocs/diagnostics/trailing-closure-matching.md +++ b/userdocs/diagnostics/trailing-closure-matching.md @@ -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) diff --git a/userdocs/diagnostics/upcoming-language-features.md b/userdocs/diagnostics/upcoming-language-features.md index ec3cb9d7850ba..06a47503625e3 100644 --- a/userdocs/diagnostics/upcoming-language-features.md +++ b/userdocs/diagnostics/upcoming-language-features.md @@ -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 :migrate`. - ## Topics - - - - diff --git a/utils/generate-doc-index.swift b/utils/generate-doc-index.swift index b9396bd803867..631e0e69c4e9a 100755 --- a/utils/generate-doc-index.swift +++ b/utils/generate-doc-index.swift @@ -5,50 +5,26 @@ import Foundation let usage = """ ./\(CommandLine.arguments[0]) [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 - - - -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 -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 ` - upgrades warnings in the specified group to errors - `-Wwarning ` - 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 `. 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 :migrate`. +""" +let topicsHeader = "\n\n## Topics\n" -## Topics - +let swiftIncludeDir = "include/swift" -""" +let groupsFileName = "\(swiftIncludeDir)/AST/DiagnosticGroups.def" +let groupRegex = /GROUP\((?[a-zA-Z]+), "(?.+)"\)/ -let groupsFileName = "include/swift/AST/DiagnosticGroups.def" -let groupRegex = /GROUP\(([a-zA-Z]+), ".+"\)/ - -let featuresFileName = "include/swift/Basic/Features.def" -let featuresRegex = /UPCOMING_FEATURE\(([a-zA-Z]+), .+\)/ +let featuresFileName = "\(swiftIncludeDir)/Basic/Features.def" +let featuresRegex = /UPCOMING_FEATURE\((?[a-zA-Z]+), .+\)/ let nameRegex = /# .+ \((?[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() } + + let featuresHandle = try createIndex(name: featuresDocFileName, header: featuresHeader) + defer { try? featuresHandle.close() } - func generateIndex() throws { - let notesHandle = try createIndex(name: notesDocFileName, header: notesHeader) - defer { try? notesHandle.close() } + let groupsWithWarnings = try groupNamesWithWarnings() + let docs = try retrieveDocs(groupsWithWarnings).sorted { a, b in + return a.title < b.title + } - let groupsHandle = try createIndex(name: groupsDocFileName, header: groupsHeader) - defer { try? groupsHandle.close() } + try groupsHandle.write(contentsOf: "\n\n## Groups with warnings\n".data(using: .utf8)!) + for doc in docs where doc.kind == .groupWithWarnings { + let ref = "- \n" + try groupsHandle.write(contentsOf: ref.data(using: .utf8)!) + } - let featuresHandle = try createIndex(name: featuresDocFileName, header: featuresHeader) - defer { try? featuresHandle.close() } + try groupsHandle.write(contentsOf: topicsHeader.data(using: .utf8)!) + try featuresHandle.write(contentsOf: topicsHeader.data(using: .utf8)!) - let docs = try retrieveDocs().sorted { a, b in - return a.title < b.title + 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 = "- \n" + try handle.write(contentsOf: ref.data(using: .utf8)!) + } +} - let ref = "- \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 createIndex(name: String, header: String) throws -> FileHandle { - let path = "\(outputDir)/\(name)" +func retrieveDocs(_ groupsWithWarnings: Set) 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) + } - if FileManager.default.fileExists(atPath: path) { - try FileManager.default.removeItem(atPath: path) + 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) } - 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 + 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)) } - func matches(in fileName: String, with regex: Regex<(Substring, Substring)>) throws -> Set { - let file = try String(contentsOfFile: "\(swiftSourceDir)/\(fileName)", encoding: .utf8) + return docs +} - var matches: Set = [] - for line in file.components(separatedBy: .newlines) { - if let match = try? regex.firstMatch(in: line) { - matches.insert(String(match.1)) +func groupNamesWithWarnings() throws -> Set { + let includePath = "\(swiftSourceDir)/\(swiftIncludeDir)" + let defPaths = try FileManager.default.subpathsOfDirectory(atPath: includePath) + .compactMap { subpath in + if subpath.hasSuffix(".def") { + return "\(includePath)/\(subpath)" } + return nil } - return matches + enum WarningGroupState { + case outside, inside, name } - func retrieveDocs() throws -> [UserDoc] { - let groups = try matches(in: groupsFileName, with: groupRegex) - let features = try matches(in: featuresFileName, with: featuresRegex) + var groups: Set = [] + for path in defPaths { + let file = try String(contentsOfFile: path, encoding: .utf8) - var docs: [UserDoc] = [] + var state = WarningGroupState.outside + for line in file.components(separatedBy: .newlines) { + var line = Substring(line) - 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 - } + switch state { + case .outside: + if !line.hasPrefix("GROUPED_WARNING") { + continue + } + + state = .inside + fallthrough - let file = try String(contentsOfFile: "\(swiftSourceDir)/\(docsDir)/\(name)", encoding: .utf8) + case .inside: + guard let index = line.firstIndex(of: ",") else { + continue + } + line = line[index...].dropFirst() - if let match = try? nameRegex.prefixMatch(in: file) { - let groupName = String(match.name) + state = .name + fallthrough - let kind: UserDoc.Kind - if features.contains(groupName) { - kind = .feature - } else if groups.contains(groupName) { - kind = .group - } else { - kind = .note + case .name: + if let index = line.firstIndex(of: ",") { + line = line[..(in path: String, with regex: Regex, _ transform: (Regex.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'" + } + } +}