Actually, let’s be clear for other readers. When we say “@inlinable is dangerous if you have a stable ABI”, what do we mean?
@inlinable has two effects. Firstly, it makes the implementation of this method public and able to be inlined into the caller. Secondly, it forces you to make everything it calls @usableFromInline. Each of these has an ABI effect.
Working backwards: every symbol you tag with @usableFromInline is now part of your public ABI. For ABI stability purposes it is as though this method is public. You can only evolve it in ways that are compatible with being a public function (which is to say, you cannot really evolve its signature, but you can change its implementation). This is obviously a big burden, and it may also be a surprise to some folks.
However, the method body being public is a bigger deal. Because callers are allowed to inline the method body, you have to assume that any future user of your library will not use the code you shipped in your library, but will instead use the first-ever version that they inlined. This means that, if there are bugs in that function, they are there forever. If that function needs to call different interfaces: tough, the old interfaces must continue to work. Essentially, you need to be very confident that this function isn’t going to need to be totally rewritten, because you can’t do that anymore.
In library evolution mode, @inlinable methods are standing in a hall of mirrors. They can be changed, but the previous versions of them live on in callers, and so the previous versions must still work. This means, in practice, only trivial changes are acceptable. This is a huge burden.