I have some questions about mangling, specifically about function type mangling.
Looking at Mangling.rst, I noticed that function types are mangled with one "kind" modifier:
// From Mangling.rst:
type ::= function-signature 'c' // function type (escaping)
type ::= function-signature 'X' FUNCTION-KIND // special function type
FUNCTION-KIND ::= 'f' // @thin function type
FUNCTION-KIND ::= 'U' // uncurried function type (currently not used)
FUNCTION-KIND ::= 'K' // @auto_closure function type (noescape)
FUNCTION-KIND ::= 'B' // objc block function type
FUNCTION-KIND ::= 'L' // objc block function type (escaping) (DWARF only; otherwise use 'B')
FUNCTION-KIND ::= 'C' // C function pointer type
FUNCTION-KIND ::= 'A' // @auto_closure function type (escaping)
FUNCTION-KIND ::= 'E' // function type (noescape)
However, in practice, function types can have many modifiers. Some information about modifiers may be lost during mangling.
// The type of `f` has multiple modifiers.
func foo(_ f: @convention(c) @autoclosure () -> Void) -> Void {}
$ swift-demangle s6mangle3fooyyyyXCF
$s6mangle3fooyyyyXCF ---> mangle.foo(@convention(c) () -> ()) -> ()
// Lost information about `@noescape` and `@autoclosure`.
Questions:
What is the significance of type mangling? Is it used by tools like LLDB to show the types of variables when debugging?
Is it desirable/important to accurately mangle all modifiers for a function type? Mangling semantically-impactful modifiers seems more important than less impactful modifiers (e.g. @convention(c) may be heavier than @noescape).
Context: I started a patch to implement type mangling for @differentiable functions, and noticed that the current mangling scheme leads to an explosion of function type modifier combinations.
A more flexible scheme could encode multiple modifiers. Sketch:
// Old: modifier is coupled with function type.
// Some modifier information is lost.
kind=ThinFunctionType
kind=ArgumentTuple
kind=Type
kind=Structure
kind=Module, text="Swift"
kind=Identifier, text="Float"
kind=ReturnType
kind=Type
kind=Structure
kind=Module, text="Swift"
kind=Identifier, text="Float"
// New: modifiers are in a separate list.
// Modifier list can be run-length encoded, possibly in a
// backwards-compatible way.
kind=FunctionType
kind=FunctionTypeModifiers
kind=ThinFunction
kind=EscapingFunction
kind=DifferentiableFunction
kind=ArgumentTuple
kind=Type
kind=Structure
kind=Module, text="Swift"
kind=Identifier, text="Float"
kind=ReturnType
kind=Type
kind=Structure
kind=Module, text="Swift"
kind=Identifier, text="Float"
But I'm not sure about the use cases for mangling. If mangling modifiers isn't important, then I suppose there's no need for a more flexible scheme.
I'm not an expert, but there are a few things to remember.
Mangling must uniquely distinguish overloadable declarations in any ways they can be overloadable, since it's used for symbol names, indexing, and compact references to entities at runtime.
Mangling of existing decls must be stable across changes to other decls (library evolution) and changes to the compiler (ABI stability) when compiling with -enable-library-evolution. (Therefore you can't say "oh, this has no overloads, so I'm going to give it a simpler mangling. This comes up sometimes.)
Mangling is used by LLDB to describe types, but I forget how. :-/
Mangling is used to disambiguate overloads, to construct runtime metadata and to show types in lldb as you suggest.
Since @convention(c) functions do not have a context, escaping/noescape has no significance in the type system. However, not being able to express @convention(c) @autoclosure is a bug, albeit one that has no practical consequences. Perhaps we should not allow @convention(foo) @autoclosure at all. Do you mind filing a bug so that we can revisit this some day?
Thanks for the swift replies! The purpose of mangling makes sense.
Some concrete follow-up questions:
Is it worth pursuing a more flexible scheme for mangling a list of function type modifiers? And is it possible to do so in a backwards-compatible way? Please see my post above.
Regarding @differentiable functions: which @differentiable + @xxx modifier combinations would you recommend mangling in the current scheme?