I’ll counterpropose a syntax I’ve brought up a few places before for @inlinable(always): @abi(none). Since this attribute only affects the ABI, adding it to the @abi attribute keeps related concerns syntactically similar. It also naturally conveys to the reader that it can be safely ignored if you’re not trying to understand the ABI of a module. And it’s hopefully clear that it is incompatible with the @abi(func foo() syntax that defines a different ABI name for the symbol (since there is no actual ABI being produced).
The motivation for @inlinable(never)seems to be based around three use cases:
- Allowing external linking. This seems better served by other language/ecosystem features, like SwiftPM/dynamic linking,
publicsymbols, and@c @implementation. I’m don’t see how these existing features are insufficient to cover this use-case. - Stabilizing the public ABI across code changes. This feels better placed at the build system level (like we have today with library evolution). Manually identifying places in your code that need to be marked as non-inlinable externally seems like a recipe for extremely fragile builds. Maintaining ABI stability using library evolution mode is already quite challenging, and having to manually spell out the constraints would make it even more complex.
- Build performance hacks. This use case feels very clearly like the responsibility of the build system to configure. For example, it could maintain a memory of which function implementation changes led to the longest incremental compiles and use that to configure the compilation process to temporarily stabilize those functions to speed up future compilation. This kind of thing would not need any sort of source-level feature to activate it and would therefore keep the source code focused on implementation rather than configuration.
Finally, the table at the bottom of the document does a good job of explaining the different combinations of @inline and @inlinable, but it does not explain when each of those combinations would be applicable. I think if we had a better idea of the value of each one, it could inform a different syntax that leaves fewer different behaviors for users of the language to understand while preserving the most useful options.