What's the best way to do flow control in Rust?

this is the use case

enum Flow {
  Continue,
  Return,
}

async fn check_one() -> Result<Flow, anyhow::Error> {
  if this_is_long().await? == "Bad" {
    return Ok(Flow::Return);
  }
  Ok(Flow::Continue)
}

async fn run() -> Result<(), anyhow::Error> {
  if check_one().await? == Flow::Return {
    return Ok(());
  }
  if check_two().await? == Flow::Return {
    return Ok(());
  }
  actually_run().await?;
  Ok(());
}

This is a lot of boilerplate and possibly unidiomatic but I don't know of any alternatives (besides inlining which really hurts code clarity)

I'm not really sure what you're trying to do, but there's this for you to take a look at ControlFlow in std::ops - Rust

2 Likes

You could probably make the ControlFlow enum work, although the way your code is architected would probably be tricky to make something clean.

1 Like

I think the best solution here is combining the two errors

enum Error {
  User(UserError),
  Internal(anyhow::Error),
}

async fn run_infallible() {
  if let Err(err) = run() {
    err.handle();
  }
}

async fn run() -> Result<(), Error> {
  check_one().await?;
  check_two().await?;
  run().await?;
}