There are a couple of distinct axes here that I can think of:
- Context: does the function carry a context (via pointer or otherwise).
- Calling convention: how are arguments passed and return values received (i.e. which registers/positions on the stack are used).
If you consider this as a table:
@convention(block) is kinda' complicated, methinks. You probably want to read the Clang docs on blocks to understand it, in case you're interested.)
A function is said to have "a thin calling convention" if it doesn't carry around a context (I think this is compiler-internal terminology and not user facing). This means that both
@convention(c) functions and
@convention(thin) functions have "a thin calling convention".
It mentions that you can annotate functions that work like the ones in C with the "
@convention(c) " attribute.
Yes, but you probably don't want to do this unless you're doing FFI (directly or via some other library).
I'm assuming that C functions have (nearly) no context besides their parameter types and return types.
Yes, but I feel that the terminology in this sentence conflates two (related) things. C function types are entirely described by their parameter types and return types. An
@convention(c) function (value) does not carry a context.
What richness do Swift functions have (by default) that prevent them from being automatically compatible with C function pointers?
There's two different things -- the calling convention and the context. There's a recent blog post which has some interesting tidbits about the register usage in Swift's native calling convention.
(I'm wondering so a type idea I have could hook into that context someday.)
That sounds at least a little bit risky -- I'm not entirely sure of all the guarantees that are made, what potential things you might assume, and how they could break if you do unsafe shenanigans with the context. Probably best if more experienced people can chime in with opinions here.