Files
Chris Adamson 89ca059bd8 Fix link and parameter documentation errors in Swift stdlib source (#89911)
rdar://172117819 (Fix link and parameter documentation errors in Swift
stdlib source)

While working on #88061, I found about 300 DocC errors in the stdlib
source doc comments, which show up as warnings when building the docs
with `docc`, and results in incomplete documentation. The problems
generally fall into a few common groups:
* **Incorrect parameter name**: These occur when a DocC `- Parameter:`
tag uses a name different from what's in the signature (for example,
using `lhs` and `rhs` to document an `=(_:_:)` operator that actually
names its parameters `a` and `b`), or it uses the outer name rather than
the inner name.
* **Out-of-module links**: DocC can only create links within a symbol's
module. The standard library is actually a collection of several
modules, with most of what we think of as the stdlib in `core`, but
there's also important stuff in `concurrency`, `observation`, etc. And
the within-own-module rule means that, for example, docs on `Actor`
can't create double-backtick links to `Hashable`, because that's
attempting to link from `concurrency` to `core`. I've generally just
demoted these to code-voice.
* **Link disambiguation**: If a given symbol has many overloads, DocC
uses a [disambiguation
syntax](https://www.swift.org/documentation/docc/linking-to-symbols-and-other-content#Ambiguous-Symbol-Links)
to distinguish between versions with different parameter types, generic
conformances, etc. In cases where there was a clear intent to link to a
specific version, I added the most appropriate disambiguation link. In
other cases, particularly where a doc might be speaking generally to any
relevant flavor of a `doFoo()` method, I demoted the link to code voice,
since there isn't a "right" disambiguation to choose in these cases.
* **Parameters to closures**: DocC has no syntax for cases where a
closure parameter itself takes one or more parameters. Generally, the
safest approach is to describe these parameters in the documentation of
the closure parameter, and this is the only option when the parameter
isn't named. In cases where the parameter is named (like `buffer` in the
trailing closure for several flavors of `withMemoryRebound()`),
@d-ronnqvist suggested using the DocC term list syntax to give the
secondary parameter a slight indentation, which is probably what the
original author would have wanted.

I'm adding the following people as reviewers just so they're aware I'm
stomping around in their code:
* @ktoso  (distributed, runtimemodule)
* @phausler  (observation)
* @al45tair and @carlpeto (runtimemodule - Carl may have just done the
DocC formatting)
* @Azoy  (atomics, ref)
* @jmschonfeld  (range)
* @natecook1000  (range)
* @airspeedswift  (set)
* @glessard  (rawspan)
* @milseman  (string.index)

This PR only changes comments, not declarations or code.
2026-07-04 04:24:20 -07:00

129 lines
5.0 KiB
Swift

//===--- Mangling.swift --------------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Defines functions and types allowing to handle Swift's mangling scheme.
//
//===----------------------------------------------------------------------===//
import Swift
#if os(anyAppleOS)
internal import Darwin
#elseif os(Windows)
internal import ucrt
#elseif canImport(Glibc)
internal import Glibc
#elseif canImport(Musl)
internal import Musl
#endif
@_implementationOnly import BacktracingImpl.Runtime
// - MARK: Demangling
/// Given a mangled Swift symbol, demangle it into a human readable format.
///
/// If the provided string is not a valid mangled swift identifier this function will throw.
/// If mangling succeeds the returned string will contain a demangled human-readable representation of the identifier.
///
/// - Parameters:
/// - mangledName: A mangled Swift symbol.
/// - Returns: A human readable demangled Swift symbol.
/// - Throws: When the demangling fails for any reason.
/// - Warning: The demangled output is lossy is not not guaranteed to be stable across Swift versions.
/// Future versions of Swift may choose to print more (or less) information in the demangled format.
@available(SwiftStdlib 6.4, *)
public func demangle(_ mangledName: String) throws(DemanglingError) -> String {
var demangledLength: size_t = 0
let demangled: UnsafeMutablePointer<CChar>? = _swift_runtime_demangle_allocate(
mangledName, mangledName.utf8.count,
&demangledLength,
/*flags=*/0
)
guard demangledLength > 0 else {
assert(demangled == nil)
throw .invalidSymbol
}
defer { free(demangled) }
return try UnsafeBufferPointer(start: demangled, count: demangledLength)
.withMemoryRebound(to: UTF8.CodeUnit.self) { (buffer: UnsafeBufferPointer<UTF8.CodeUnit>) throws(DemanglingError) -> String in
guard let demangledSpan = try? UTF8Span(validating: buffer.span) else {
throw DemanglingError.invalidSymbol
}
return String(copying: demangledSpan)
}
}
/// Given a mangled Swift symbol, demangle it into a human readable format into the prepared output span.
///
/// If the provided bytes are not a valid mangled swift name, the output span will be initialized with zero elements.
/// If mangling succeeds the output span will contain the resulting demangled string.
/// A successfully demangled string is _not_ null terminated, and its length is communicated by the `initializedCount`
/// of the output span.
///
/// The demangled output may be _truncated_ if the output span's capacity is insufficient for the
/// demangled output string! You can detect this situation by inspecting the thrown ``DemanglingError``,
/// for the ``DemanglingError/truncated(requiredBufferSize:)`` case.
///
/// - Parameters:
/// - mangledName: A mangled Swift symbol.
/// - output: A pre-allocated span to demangle the Swift symbol into.
/// - Throws: When the demangling failed entirely, and the output span will not have been written to.
/// - Warning: The demangled output is lossy is not not guaranteed to be stable across Swift versions.
/// Future versions of Swift may choose to print more (or less) information in the demangled format.
@available(SwiftStdlib 6.4, *)
public func demangle(
_ mangledName: borrowing UTF8Span,
into output: inout OutputSpan<UTF8.CodeUnit>
) throws(DemanglingError) {
var outputCapacity = output.capacity
let requiredBufferSize = output.withUnsafeMutableBufferPointer { outputBufferUInt8, initializedOutputLength in
outputBufferUInt8.withMemoryRebound(to: Int8.self) { outputBuffer in
mangledName.span.withUnsafeBytes { mangledNamePtr in
let requiredBufferSize = _swift_runtime_demangle(
mangledNamePtr.baseAddress, mangledName.count,
outputBuffer.baseAddress, &outputCapacity,
/*flags=*/0)
initializedOutputLength = outputCapacity
return requiredBufferSize
}
}
}
guard requiredBufferSize > 0 else {
throw DemanglingError.invalidSymbol
}
// If the buffer size is still equal to the buffer count, the demangle was
// successful.
guard requiredBufferSize <= output.capacity else {
throw DemanglingError.truncated(requiredBufferSize: requiredBufferSize)
}
return // OK!
}
/// Error thrown to indicate failure to demangle a Swift symbol.
@available(SwiftStdlib 6.4, *)
public enum DemanglingError: Error {
/// Demangling resulted in truncating the result. The payload value is the
/// number of bytes necessary for a full demangle.
case truncated(requiredBufferSize: Int)
/// The passed Swift mangled symbol was invalid.
case invalidSymbol
}