Moving something out of a hashmap and then back into it isn't cheap.
No, move the entire hashmap. That might sound like a big deal, but it's not: It's heap allocated, which means you always access it via a pointer. Moving just moves the pointer. That's the cheapest possible move you can get, especially given your CPU probably cached it.
Not sure what you mean -- hashmaps are heap allocated.
In practice, it would be "copy the data to the stack, leaving the original in-place, then make sure to copy the mutated version back to the original location". The stack consumption of that approach would be worrisome.
The stack plane doesn't move anywhere. Unlike C++, rust's moves are always conceptually destructive. And it doesn't necessarily mean that all of the memory is copied either. If you move an entire hashmap, it's no longer usable within the original scope you were originally using it in, unless and until you move it back later. So conceptually, it's a move. But when it's compiled, that's a different story. Usually you're just copying a pointer, i.e. 8 bytes on 64-bit. The original pointer at its original location doesn't need to be deleted, the compiler simply doesn't provide any means for you to read from the original pointer's memory location, even though it's still a valid pointer until overwritten, which is allowed to happen after the move. This is different from a clone, which duplicates the entire hashmap, and THAT is expensive. There is no pointer aliasing in safe rust.
This is where the big-system biases of some of the Rust community work against it, and what fuels the certainty of C programmers that C is the right language for tiny devices. In C there would be no question -- you'd just look up the data in the map and return a pointer to it. Very efficient, no needless waste of several hundred bytes of precious stack space or any need to find some other memory region to copy it into.
You're still doing the exact same thing in rust, the only change is the semantics.
You say that "moves in Rust are cheap" but whether that's true is extremely context-dependent, and it's basically always the case that a pointer is even cheaper.
The context is pretty easy to understand though, and rust-analyzer makes it obvious even if you don't, namely by looking at its size. For example, if I stack allocate a very large array, which in rust is a slice, then a move would indeed be costly if the compiler determines that it's necessary to actually memcpy it first. But if in doubt, I can Box<T> it if I really need to move it, and then the move is guaranteed to be cheap.
Though most people don't even need to have that deep of an understanding of it, and can acquire that understanding over time (as I did) as it becomes necessary. When I started with rust, I didn't know what a heap or a stack was, other than how to overflow it with recursion. I had already been using rust for about a year before I even started calling myself a developer though, so go figure.
Unfortunately, the risks of the C approach are very well-understood, and my point in the post with which I entered this discussion was that Rust can be just as good for space and cycle-efficient low-level code as C while also providing significant security and safety benefits.
The thing with rust though, is it's very easy to do this, and even easier to iterate on it. The main problem with rust is that the way it does things is so different from other languages that seasoned developers tend to have a hard time with it, hence the learning curve. Think English as a second language vs just being a native English speaker. Everybody who isn't a native speaker thinks it's hard, where the native speakers think it's easy. Same thing with Mandarin. This also explains the struggle you're having here -- you're used to thinking one way, but the language asks you to think in another way.
This is why C++ developers often say that rust requires you to do a lot of planning before you can even begin prototyping, so it's too time-consuming, etc, even going as far as to make whole youtube videos about how much planning they have to go through to write rust, so the language is a waste of time.
Rust developers, like me, will straight up deny that. Why? Well, we find that we don't really have to plan anything. I think the best way I can describe it, in my particular case, is it's more about almost instinctively knowing what I shouldn't do more than it's about knowing what I should do, probably because rust makes what you shouldn't do a lot more obvious, even though it's also a "shouldn't do" in basically every language. That could come in the form of C and C++ being, when you declare a variable, it's mutable unless you say otherwise. In rust, it's immutable unless you say otherwise. And what ends up happening is that as those C and C++ developers become more experienced, they habitually start every variable declaration with 'const' just as I habitually always start it with 'let' rather than 'let mut'. Early mistakes snowball, so avoid doing the wrong thing early.
Speak of the time it takes to code, there's been a lot of research done on this, and at this point it's a foregone conclusion: Systems developers are more productive in rust. Like...a lot more. Google did a writeup on the reasons why this is the case a while back, where seasoned C++ developers will swear that this must be false because their attempt at rust some months ago taught them otherwise.
You see what I'm getting at?
There are plenty of people who understand the constraints of writing code on a device with 64K total RAM and a 1K stack who are writing Rust code and ensuring that the language is a good fit.
Oh like embedded? Actually I've done a fair bit of that, especially on nodemcu, fixed size stack allocator in tow. When you use no-std in rust, you've got all of that fine-grained control. Using the standard library is where you give up some of it, but only insofar as whatever it is that you don't understand about the particular standard library functions you're using. If in doubt, and you're using vscode+rust-analyzer, control-click the standard library function, and there's the source for it.