Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
308 views
in Technique[技术] by (71.8m points)

rust - How to Return a Result with generic error

I want to write a function that reads the contents of a file, and raises an error if it fails. I want to call this function from a python script, so I'm including some mentions of Python below in case it might be relevant.

As I have tried showing in the comments, more work might happen that raises other types of errors, so if it is possible I would like to use a generic error if this is possible in Rust(?). How can I return the error so it can be handled and wrapped in a python error as shown in do_work? Not sure if my approach that is resulting in the error below is in the right direction.

fn work_with_text() -> Result<(), dyn std::error::Error> {
    let content = match std::fs::read_to_string("text.txt") {
        Ok(t) => t,
        Err(e) => return Err(e),
    };
    // do something with content that may cause another type of error (rusqlite error)
    Ok(())
}
    

#[pyfunction]
fn do_work(_py: Python) -> PyResult<u32> {
    match work_with_text() {
        Ok(_) => (0),
        Err(e) => {
            let gil = Python::acquire_gil();
            let py = gil.python();
            let error_message = format!("Error happened {}", e.to_string());
            PyIOError::new_err(error_message).restore(py);
            return Err(PyErr::fetch(py));
        }
    };

    // ...
}

error:

1   | ...                   fn work_with_text() -> Result<(), dyn std::error::Error> {
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn std::error::Error + 'static)`
question from:https://stackoverflow.com/questions/65845532/how-to-return-a-result-with-generic-error

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your current version does not work because trait objects don't have a statically known size, which means the compiler doesn't know how much space to allocate for them on the stack, so you can't use unsized types as function arguments or return values unless you make them sized by putting them behind a pointer.

Fixed example:

fn work_with_text() -> Result<(), Box<dyn std::error::Error>> {
    let content = std::fs::read_to_string("text.txt")?;
    // do something with content that may cause another type of error (rusqlite error)
    Ok(())
}

Having a Box<dyn std::error::Error> also allows you to return a wide variety of errors from your function since most error types can be automatically converted into a Box<dyn std::error::Error> via the ? operator.

If you'd like to get a deeper understanding of both sizedness and error handling in Rust I highly recommend reading Sizedness in Rust and Error Handling in Rust.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...