Rust's closures do not heap allocate unless you box them, like any other struct, because closures are sugar for a struct + a function, that's correct.
(and yes, there are three types of closures, because they need to know if they take said struct by reference, by mutable reference, or by owner.)