Result

Result<T, E>は処理が無事完了したかを表現する為の型です。正常に終了した場合Ok<T>、何かしらエラーが起きた場合Err<E>を返します。

let ok: Result<i32, &str> = Ok(33);
let err: Result<i32, &str> = Err("fatal error");

Result<T, E>はモジュールなどに合わせてエイリアス化されている事が多いです。エイリアスにはtypeを使います。

enum FooError {
  AError,
  BError,
}

type FooResult<T> = Result<T, FooError>;

? 演算子

Resultを返す関数呼び出しの後ろに?を置くと、Ok<T>の時は::unwrapのようにTを返しますが、Err<E>が返却された時は即時returnになります。

fn return_ok<'a>() -> Result<&'a str, &'a str> {
  Ok("foo")
}

fn scope<'a>() -> Result<&'a str, &'a str> {
  let foo = return_ok()?;

  println!("{}", foo);

  Ok(foo)
}

fn main() {
  #[allow(unused_must_use)]
  scope();
}

return_okResult型を返す為だけの関数で、scopeは単にそれを実行する為の関数です。scopeを用意した理由は、?は戻り値がResultな関数の中でしか使えません。

また?Err<E>な時、単にそれを返すのではなくFrom::fromEを渡して実行した結果を返します。なので以下のようにエラー列挙型にまとめるといった事ができます。

struct FooError;
struct BarError;

#[derive(Debug, PartialEq, Eq)]
enum AError<'a> {
  FooError(&'a str),
  BarError(&'a str),
}

impl<'a> From<FooError> for AError<'a> {
  fn from(_error: FooError) -> Self {
    AError::FooError("FooError")
  }
}

impl<'a> From<BarError> for AError<'a> {
  fn from(_error: BarError) -> Self {
    AError::BarError("BarError")
  }
}

fn return_err<'a>() -> Result<&'a str, FooError> {
  Err(FooError)
}

fn scope<'a>() -> Result<&'a str, AError<'a>> {
  let _ = return_err()?;

  unreachable!();
}

fn main() {
  assert_eq!(scope().unwrap_err(), AError::FooError("FooError"));
}

return_errは必ずエラーを返す関数です。impl<'a> From<FooError> for AError<'a>によってFooErrorからAErrorに変換できるようにしてる為、この場合AError::FooErrorEとして返ります。