What's stopping zig for adopting c abi for function calls

For structs i understand why the abi is unstable but for function i don’t see why the abi is unstable since zig doesn’t pass any hidden context or this pointer ?

Internal functions without a stable ABI can bring huge optimization benefits, which LLVM can already achieve.
Unused function parameters can be removed directly.
Struct pointer parameters can be optimized to pass by value, especially when a struct pointer is passed in but only part of its fields are used.
Passing large structs by value can be optimized to passing by reference, which is what Zig used to do with PRO. Even though it’s been removed, there are still lots of safe opportunities to apply this optimization.
When passing parameters, you can also largely ignore the platform ABI rules and make heavy use of registers.

Nitpicking, but technically there is no such thing as a “C ABI”, ABIs are defined by CPU and OS vendors, C (and all other) compilers can only follow those ABI conventions, otherwise they couldn’t talk to operating system functions.

And since Zig definitely can talk to operating systems, it must support those “target ABIs” too (and it does via extern and export).

For regular Zig functions I guess the main problem is that Zig has builtin types that are not easily expressable in C (like wide integers, AFAIK even in C there are all sorts of ABI problems with int128_t, and I guess also with C23’s _BitInt(N) - e.g. even what’s commonly called “C ABI” covers only a small subset of the C type system… and then Zig has optionals, error unions and tagged unions which all don’t easily map to C-style ABIs unless you define the underlying memory layout (which isn’t fixed either, e.g. optional pointers don’t need an extra ‘valid’ boolean because the special null-pointer value can be used for that). Oh, and then there are slices too…

Just speculating here of course, but C is the rare high level language without builtin ‘compound types’ (with the notable exception of _Complex, which is so completely alien to the rest of the language that I have no idea how it ever ended up in the C standard) - while languages like Zig or Rust have all sorts of ‘opaque struct types’ which would need to define their interior layout, which then in turn would introduce a rigidness that’s simply counterproductive for “internal” function calls.

.inline as a calling convention is one thing that would be (technically) prevented by adopting the C ABI for function calls. Of course, having a function that leaves symbol present in your binary that could be called from C and inlining some or all of the calls of a function are not mutually exclusive…

that’s also another thing: in order to allow comptime monomorphization to play nicely with debug symbols and so forth, Zig function names are “mangled” (i.e. currently this means “deduplicated across comptime instantiations by appending stuff”). you can’t export a generic function, but you can export an instantiation of it.