Is there a way to tell a function (function A) called by another function (function B) to return out of function A from B?

I am trying to do some refactoring from my codebase?

I have code like this:

fn foo() -> Result<Value, String> 
let query_result: QueryResult<...> = <query to the database>
let value: Value = if query_result.is_err() {
   let err_msg = query_result.err().unwrap().to_string();
   return Err(format!("Error in Foo: {err_msg}")); 
} else {
   query_result.unwrap() 
}; 
value

This code is essentially the pattern I follow to add error handling. I am trying to make a function to do this, but I don't want to panic out of the function and instead return the value. I assume this would be very difficult as Rust doesn't support returning multiple types. I could make an enum, but I would have to have a way to tell the function calling the unwrap function to return Err(format!("Error in Foo: {err_msg}")); . Thank you in advance for any help any of yall can provide.

I don’t quite follow what you’re asking for, but you can simplify the code you posted like this:

fn foo() -> Result<Value, String> {
    let query_result: QueryResult<...> = <query to the database>;
    query_result.map_err(|e| format!("Error in Foo: {}", e.to_string()));
}

You also might find the ? operator useful, as it’s designed to help with error propagation.


If you want to pull this out into a separate function, you can do something like this:

fn format_err<T,E:Display>(result: Result<T,E>, context: &str)->Result<T, String> {
    result.map_err(|e| format!("Error in {context}: {e}"))
}

fn foo() -> Result<Value, String> {
    let query_result: QueryResult<...> = <query to the database>;
    let value: Value = format_err(query_result, "Foo")?;
    // Do something with `value`
    Ok(value)
}
6 Likes

Oh thank you. Doesn't the ? operator panic when there is an error from the result?

Another way analogous to a separate function is to implement

impl From<(Tuple, Of, Context)> for CustomErrorType { .. }

And then you can do things like

fn foo() -> Result<Value, CustomErrorType> {
    let value = query_result.map_err(|e| ("foo", e))?;
}

Larger example here. It is a lot of boilerplate. It's also not applicable if your error type is just String, since you can't write the From implementation in that case.


No, res? on a res: Result is roughly equivalent to

match res {
    Ok(value) => value,
    Err(e) => return Err(e.into()),
}
2 Likes

thank you

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.