Seems to be read wrong by my ClangImporter.
My understanding (possibly incorrect) is the behavior is "as expected" if you haven't modified your
unsigned long gets imported as
CUnsignedLong as per
CUnsignedLong = UInt as you mentioned for non-Windows and non-x86_64 platforms at the moment, so it gets translated to
UInt has the same width as
Int. It is a bit mysterious as to why it is
i16 and not
If you think about the mapping, there are lots of different kinds of types. There are built-ins atoms like
unsigned int etc, there are built-in composites (like function types, which have a bunch of argument types and one return type), there are "core" typedefs (like
uint32_t, this is somewhat fuzzy but you get what I mean), and there are user-defined types and typedefs.
If you think of a type as a tree structure, the built-in atoms are the leaves of the tree.
BuiltinMappedTypes.def describes how Clang's built-in atoms translate to Swift (technically, these are just called builtins), barring special
Following the tree structure, translating types between languages is like writing a tree interpreter.
- There is a Clang type -> Swift type tree interpreter in
- There are Swift type -> Clang type tree interpreters in
ClangTypeConverter.cpp (these are very similar, so you just look at one without worrying about why there are two of them).
What is confusing me is this, I thought that
MappedTypes.def determined the mapping, but this is only used in one place I can see,
MappedTypes.def is essentially a list of special-cases that are handled for better user ergonomics (I might be wrong on the purpose, maybe @jrose can describe it better). For example, typedefs can be imported as the underlying type (i.e. erasure-on-import) or they can be translated to typealiases in Swift (i.e. transliteration-on-import). With these specific types, we want to make sure that no new typealiases are introduced, instead, we hard-code what they get imported to. For example, if a platform header defines
typedef int32_t int because it has 32-bit ints. As a base assumption, let's assume that
int gets imported as
Int (hopefully uncontroversial). Then we do not want the typedef to be erased (e.g. functions that look like they take
int32_t arguments look like they take
Int arguments in Swift), and we do not want to introduce a new typealias like
typealias Int32 = Int. Instead, we want to make sure that
int32_t gets mapped to
Int32, which is a struct in the stdlib, directly without any extra indirection from a typealias. Since this doesn't fit cleanly into the two most common import strategies, and we care about ergonomics, and this is probably a more scalable solution than modifying headers with attributes for every platform we care about, we hardcode these.