A simple alternative is to use Option instead of peoject_replace: playground
Note that this may little increases the size of Inner if R is greater than R::Send. (project_replace allows small size optimizations like this.)
By the way, if you don't need the return value of project_replace, I recommend using Pin::set method instead:
In this case the issue is that you need the value already in the enum to construct the next value, and ultimately that's just an inherently unsafe operation. What happens if req.send() panics while you're moving the value? With take_mut, your process is aborted. Using a dummy value is one answer to the "what happens if it panics" question.
I recommend introducig a Done state that stores that the future is currently finished and using that as your dummy vaue. Then you can also move to that state when the future is done and get a fused future for free.
Note that if you really want to use take_mut, it can be done with an unsafe block.
Your take_pin would indeed be unsound because it moves the T which has been pinned. If you used it while the enum was in the Future state, that would be bad. Of course, if the enum is in the Request state, no fields are pinned and hence it would be safe in that situation, but your take_pin method can't tell whether that's the case or not. You have to use an unsafe block to promise that you're in the later case, and not the former.