fn foo() -> (usize, Result<(),()>) { (0, Ok(())) }
let (a, err) = foo(); err?; // propigate error
let (b, _) = foo(); // discard error
Or more typically, you might use one of the many fn s such as unwrap_or, unwrap_or_else, unwrap_or_default, etc. - to provide your own appropriate default value. I usually find that useful default values are often caller specific anyways (and doesn't require remembering which fns return which default values on error): fn foo() -> Result<usize> { Ok(1) }
fn bar() -> Option<usize> { None }
let val = foo().unwrap_or(3); // val == 1
let val = bar().unwrap_or(4); // val == 4
Alternatively you can use out parameters, which occasionally crops up in Rust's own stdlib: let mut line = String::new();
let _ = buf_read.read_line(&mut line);
// ...use line, even if there was an error...
Also, the "error" type might contain values itself, although you're certainly not ignoring the error if you use it: // https://doc.rust-lang.org/std/ffi/struct.OsString.html#method.into_string
match os_string.into_string() {
Ok(string) => println!("Valid UTF8 string: {}", string),
Err(os_string) => println!("Invalid UTF8: {:?}", os_string),
}Community habits and language frictions matter a lot. In Go, doing the equivalent of `Result` requires custom private types for every combination, with private fields and accessor methods that protect against misuse. And you still only gain runtime safety. And they can still make a zero-valued var and use it without "initialization" (unless you use private types, which are an even bigger pain for a variety of reasons). Any other approach makes it trivial to bypass - public fields can just be accessed, multiple returns can be ignored, etc. In Rust, the community and language make `Result` common, and then you gain compile-time safety in most cases, and warnings in all others (AFAIK, as Result is annotated as "must use", so you get a warning or a `_ =` as a visible marker that you're ignoring something).
---
tl;dr multiple returns of course bypass this, but in practice you won't see that in Rust unless it's intended to allow ignoring the error. Underscores on out-param funcs are a good point, but they're also fairly rare / serve as a visual warning of shenaniganry.
let _ = something_returning_Result();
This does not even give a warning.Just to clarify: the "let _ = ..." construct is the explicit way of suppressing the warning in Rust. You acknowledge that there is indeed a return value but you choose to ignore it. Just calling the function without explicitly discarding the Result will give you a warning.
let value = unsafe {
match result {
Ok(value) => value,
_ => hint::unreachable_unchecked()
}
};
At this point, the fact that you've skipped an error check should be abundantly clear to anyone reading your code.