Comment by ashf023
IMO pushing ifs up makes sense when the condition is enforceable by the type system, e.g. in the Option<Walrus> vs Walrus example, and when doing so makes the function's purpose more clear, or gives callers more flexibility. I think it's generally intuitive when writing code - can I use the type system to guard this rather than checking in my function, and should this function decide what happens in the unexpected cases?
Pushing fors down is usually not that relevant in Rust if all it achieves is inlining. The compiler can do that for you, or you can force it to, while improving reusability. It can make sense if there's more optimization potential with a loop e.g. lifting some logic outside the loop, and the compiler doesn't catch that. I also would avoid doing this in a way that doesn't work well with iterators, e.g. taking and returning a Vec.