Also worth noting is smallvec and compact_str crates. These are useful when you most of the time have small data that you want inline, but are OK with falling back to heap allocation for the occasional outlier.
I have used both inside structs to optimise cache usage. For these uses i tend to use rather short smallvec.
And smallvec in particular is also useful on the stack in a larger variant in hot functions where you might have a Vec that almost always is less than (say) 32 elements, but the program should gracefully handle the occasional long case. I found this offered a small speed up in some batch data processing code I wrote.
Not really. Heapless uses compile time sized backing buffers to implement Vec, string etc with a max upper size. You would typically use heapless with a statically allocated variable, but it is possible to use it on the stack too.
Alloca is different and allocates a dynamically sized block on the stack. Rust doesn't really support alloca, but there is a crate for it that works by calling through a helper function in C: https://lib.rs/crates/alloca