Conciliating Rust results with a C-idiomatic Out<Error>
parameter
#113
-
This is basically an interesting discussion that stemmed from questions asked by @fjarri over #95. Some contextThe gist of it is that, given fn returns_option() -> Option<…>;
fn returns_result() -> Result<…, …>; and some Rust code calling into these sequentially, e.g., fn api_func (error: Option<Out<'_, Error>>)
-> Option<usize>
{
let x = returns_option()…?;
let y = returns_result()…?;
Some(x + y)
} they had defined the following helpers: fn write_error (_msg: &'_ str, _error: Option<Out<'_, Error>>) { … }
pub
trait Reportable<T> {
fn report_error (self, msg: &'_ str, error: Option<Out<'_, Error>>)
-> Option<T>
;
}
impl<T, E : Display> Reportable<T> for Result<T, E> { … }
impl<T> Reportable<T> for Option<T> { … } thanks to which they ended up with: Stage 0 / initial statefn api_func (error: Option<Out<'_, Error>>)
-> Option<usize>
{
let x = returns_option().report_error("returns_option()", error)?;
let y = returns_result().report_error("returns_result()", error)?;
Some(x + y)
} But this yields ownership-sematic-related errors about "use of moved value, |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
Stage 1The most direct way to tackle the problem is then to use pub
fn api_func (error: Option<Out<'_, Error>>)
-> Option<usize>
{
+ let error = &mut { error };
let x = returns_option().report_error("returns_option()", error)?;
let y = returns_result().report_error("returns_result()", error)?;
Some(x + y)
} and then tweak the helpers accordingly. This does work, but @fjarri pointed out that borrowing the pub
fn api_func (error: Option<Out<'_, Error>>)
-> Option<usize>
{
let error = &mut { error };
let _ = returns_option().report_error("returns_option()", error) ;
+ ^
let y = returns_result().report_error("returns_result()", error)?;
Some(y)
} This, alas, compiles fine. |
Beta Was this translation helpful? Give feedback.
-
Stage 2 (
|
Beta Was this translation helpful? Give feedback.
-
Final stageNow, from the previous stage, the idea is now to try and reach stable Rust. But, given that we're gonna be feeding all this to a This thus yields what I think is the final and cleanest solution: pub
fn api_func (error: Option<Out<'_, Error>>)
-> Option<usize>
{
error.try_(|| {
let x = returns_option().context("returns_option()")?;
let y = returns_result().context("returns_result()")?;
Ok(x + y)
})
}
|
Beta Was this translation helpful? Give feedback.
Final stage
Now, from the previous stage, the idea is now to try and reach stable Rust.
try { … }
blocks, especially-> Result
-yielding ones, can easily be emulated by a macro that hides an inner closure.But, given that we're gonna be feeding all this to a
error.…(…)
API nonetheless, why not make such API directly take such a closure, and skip themacro
noise / complexity layer directly?This thus yields what I think is the final and cleanest solution: