- Proposal: SE-NNNN
- Author: Alejandro Alonso
- Review Manager: TBD
- Status: Awaiting review
- Implementation: apple/swift#28555
- Previous Review: SE-0262 Demangle Function, Returned for Revision
Introduce a new function, demangle
, that takes a mangled Swift symbol, like $sSS7cStringSSSPys4Int8VG_tcfC
, and output the human readable Swift symbol, like Swift.String.init(cString: Swift.UnsafePointer<Swift.Int8>) -> Swift.String
. Along with the introduction of this function, we're also going to introduce a new module LowLevel
that provides similar functionality to Swift.
Swift-evolution thread: Demangle Function
Currently in Swift, if a user is given an unreadable mangled symbol, they're most likely to use the swift-demangle
tool to get the demangled version. However, this is a little awkward when you want to demangle a symbol in-process in Swift. One could create a new Process
from Foundation and set it up to launch a new process within the process to use swift-demangle
, but we can certainly make this a lot easier.
The LowLevel
module will add the following function:
// Given a mangled Swift symbol, return the demangled symbol.
public func demangle(
_ mangledName: String,
isSimplified: Bool = false
) -> String?
Examples:
import LowLevel
print(demangle("$s8Demangle3FooV")!) // Demangle.Foo
print(demangle("$sSi")!) // Swift.Int
print(demangle("Hello World!") ?? "Not a valid symbol!") // Not a valid symbol!
If one were to pass a string that wasn't a valid Swift mangled symbol, like abc123
, then the (String) -> String?
would simply return nil to indicate failure.
This implementation relies on the Swift runtime function swift_demangle
which accepts symbols that start with _T
, _T0
, $S
, and $s
.
These are completely new standard library functions, thus source compatibility is unaffected.
These are completely new standard library functions, thus ABI compatibility is unaffected.
These are completely new standard library functions, thus API resilience is unaffected.
We could choose to only provide one of the proposed functions, but each of these brings unique purposes. The trivial take a string and return a string version is a very simplistic version in cases where maybe you're not worried about allocating new memory, and the buffer variants where you don't want to alloc new memory and want to pass in some memory you've already allocated.
The swift_demangle
runtime function has an extra flags
parameter, but currently it is not being used for anything. In the future if that function ever supports any flags, it would make sense to introduce new overloads or something similar to expose those flags to the standard library as well. E.g.
public func demangle(_ input: String, flags: DemangleFlags) -> String
public func demangle(
_ input: String,
into buffer: UnsafeMutableBufferPointer<Int8>,
flags: DemangleFlags
) -> Int?
where DemangleFlags
could be an enum, OptionSet
, [DemangleFlag]
, etc.