What is the correct way to propagate errors? - error-handling

I'm trying to learn Rust, but I am faced with a difficulty when I implement the fmt::Display trait for one of my types. I want to do something like this:
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(");
some_helper_function(self.t1, self.ctx, f);
write!(f, " ");
some_helper_function(self.t2, self.ctx, f);
write!(f, ")")
}
All of these functions return fmt::Result, but this will be ignored. What is correct way for propagating the error result upward?

For every function call you check if the return is an Err object or not. If it's an Err object you return from the function, if not you continue.
There's a convenient macro in the standard library, called try! which does exactly this.
So your code would become something like this:
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "("));
try!(some_helper_function(self.t1, self.ctx, f));
try!(write!(f, " "));
try!(some_helper_function(self.t2, self.ctx, f));
try!(write!(f, ")"))
}

Andrea P's answer is spot on for how to fix this. I wanted to add on to this part though:
All of these functions return fmt::Result, but this will be ignored.
Note that the compiler tries really hard to help you here:
fn important() -> Result<u8, ()> {
Err(())
}
fn main() {
important();
}
Will produce this warning by default:
warning: unused result which must be used, #[warn(unused_must_use)] on by default
important();
^~~~~~~~~~~~
You can even make it so that all warnings become errors by adding this to your crate:
#![deny(unused_must_use)]

Related

Testing serialize/deserialize functions for serde "with" attribute

Serde derive macros come with the ability to control how a field is serialized/deserialized through the #[serde(with = "module")] field attribute. The "module" should have serialize and deserialize functions with the right arguments and return types.
An example that unfortunately got a bit too contrived:
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, PartialEq, Eq)]
pub struct StringPair(String, String);
mod stringpair_serde {
pub fn serialize<S>(sp: &super::StringPair, ser: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
ser.serialize_str(format!("{}:{}", sp.0, sp.1).as_str())
}
pub fn deserialize<'de, D>(d: D) -> Result<super::StringPair, D::Error>
where
D: serde::Deserializer<'de>,
{
d.deserialize_str(Visitor)
}
struct Visitor;
impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = super::StringPair;
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "a pair of strings separated by colon (:)")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(s.split_once(":")
.map(|tup| super::StringPair(tup.0.to_string(), tup.1.to_string()))
.unwrap_or(Default::default()))
}
}
}
#[derive(Serialize, Deserialize)]
struct UsesStringPair {
// Other fields ...
#[serde(with = "stringpair_serde")]
pub stringpair: StringPair,
}
fn main() {
let usp = UsesStringPair {
stringpair: StringPair("foo".to_string(), "bar".to_string()),
};
assert_eq!(
serde_json::json!(&usp).to_string(),
r#"{"stringpair":"foo:bar"}"#
);
let usp: UsesStringPair = serde_json::from_str(r#"{"stringpair":"baz:qux"}"#).unwrap();
assert_eq!(
usp.stringpair,
StringPair("baz".to_string(), "qux".to_string())
)
}
Testing derived serialization for UsesStringPair is trivial with simple assertions. But I have looked at serde_test example as that makes sense to me too.
However, I want to be able to independently test the stringpair_serde::{serialize, deserialize} functions (e.g. if my crate provides just mycrate::StringPair and mycrate::stringpair_serde, and UsesStringPair is for the crate users to implement).
One way I've looked into is creating a serde_json::Serializer (using new, requires a io::Write implementation, which I couldn't figure out how to create and use trivially, but that's a separate question) and calling serialize with the created Serializer, then making assertions on the result as before. However, that does not test any/all implementations of serde::Serializer, just the one provided in serde_json.
I'm wondering if there's a method like in the serde_test example that works for ser/deser functions provided by a module.

Why does the ? operator report the error "the trait bound NoneError: Error is not satisfied"?

The ? operator at line 9 works OK, but if I use the same logic on the same type in line 19, it blows up.
use std::error::Error;
use walkdir::WalkDir;
fn main() -> Result<(), Box<dyn Error>> {
let valid_entries = WalkDir::new("/tmp")
.into_iter()
.flat_map(|e| e)
.flat_map(|e| {
let name = e.file_name().to_str()?; // <-- this works
if name.contains(".txt") {
Some(e)
} else {
None
}
});
for entry in valid_entries {
println!("This file matches: {:?}", entry);
let name_to_str = entry.file_name().to_str()?; // <-- this blows up
// ...
}
Ok(())
}
The errors are a little cryptic for me to interpret:
error[E0277]: the trait bound `std::option::NoneError: std::error::Error` is not satisfied
--> src/main.rs:19:53
|
26 | let name_to_str = entry.file_name().to_str()?;
| ^ the trait `std::error::Error` is not implemented for `std::option::NoneError`
|
= note: required because of the requirements on the impl of `std::convert::From<std::option::NoneError>` for `std::boxed::Box<dyn std::error::Error>`
= note: required by `std::convert::From::from`
Why is the ? operator blowing up while iterating valid_entries?
The ? can be used to check-and-return any type that implements the Try trait (still unstable). The only implementations in std of those are Option<T> and Result<T, E> (plus some Future-related impls that are not relevant to this discussion). This means that you can use the ? operator in any function that returns Result<T, E> or Option<T>.
But you cannot mix-n-match those. That is, if your function returns a Result<T, E> you cannot use the ? in a value of type Option<T>. Or vice versa.
The reason your first ? works is because you are inside a flat_map() that returns Option<String> and all goes well. The second one, however, is in a function that returns a Result<(), Box<dyn Error>> so you can't use ? with an Option<String>.
The solution is simply to deal with the None in your Option<String> in another way:
Doing a match / if let Some(x) to handle the error separately.
Converting into a Result<String, Error> and use ?, for example with .ok_or(std::io::ErrorKind::InvalidData)?;.
Similar to 2, but take advantage of the impl From<&str> for Box<dyn Error> and do .ok_or("invalid file name").
Giving a default value, with Option::unwrap_or() or similar.
Doing unwrap() and panicking if None.
Ok, but what does this error mean? The idea is that actually you are able to use ? with an Option<T> that returns a Result<T, E>, as long as your E implements From<std::option::NoneError>. Unfortunately, NoneError is still unstable, too, so you can't implement From<NoneError> in your code using the stable compiler. Nevertheless, the E in your code is Box<dyn Error>, and the compiler would be happy to do the boxing as long as NoneError implements Error, but...
error[E0277]: the trait bound `std::option::NoneError: std::error::Error` is not satisfied

How do I use the Option::ok_or() method correctly?

I'm trying to understand how to use the question mark operator for error handling in Rust. I have this code:
fn main() -> Result<(), &'static str> {
let foo: i32 = Some("1")
.ok_or(Err("error 1"))?
.parse()
.or(Err("error 2"))?;
Ok(())
}
This code can not be compiled for some reason:
error[E0277]: the trait bound `&str: std::convert::From<std::result::Result<_, &str>>` is not satisfied
--> src/main.rs:2:20
|
2 | let foo: i32 = Some("1")
| ____________________^
3 | | .ok_or(Err("error 1"))?
| |_______________________________^ the trait `std::convert::From<std::result::Result<_, &str>>` is not implemented for `&str`
|
= note: required by `std::convert::From::from`
The Rust book has an example usage of the question mark operator:
use std::io;
use std::io::Read;
use std::fs::File;
fn read_username_from_file() -> Result<String, io::Error> {
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?;
Ok(s)
}
In my opinion, it doesn't differ much from my example in sense of handling errors. I cannot see a reason for my code to be invalid. If the From trait should be implemented for all kinds of Result why does the code from the Rust book work fine?
Unlike or, ok_or takes an E, not a full Result<T, E> (because it wouldn't have anything to do if passed an Ok). Just pass the error string directly:
fn main() -> Result<(), &'static str> {
let foo: i32 = Some("1")
.ok_or("error 1")?
.parse()
.or(Err("error 2"))?;
Ok(())
}
The reason the error message mentions the From trait is because ? implicitly uses From to convert the expression's error type into the return value's error type. If it worked, .ok_or(Err("error 1")) would return a value of Result<&'static str, Result<_, &'static str>> (_ could be almost anything, since Err doesn't specify). The ? operator attempts to find an implementation of From that would convert Result<_, &'static str> (the expression's error type) into &'static str (the return value's error type). Since no such From implementation exists, the compiler emits an error.

Figuring out return type of closure

I'm having troubles figuring out the type signature of the fn filter function in following example.
The Node and Descendant definition is just there for syntax . It's not meant to do anything!
use std::iter::Filter;
#[derive(Clone)]
pub struct Node<'a> {
s: &'a str,
}
pub struct Descendants<'a>{
iter: Node<'a>
}
impl<'a> Iterator for Descendants<'a> {
type Item = Node<'a>;
fn next(&mut self) -> Option<Node<'a>> {
Some(Node {s: self.iter.s})
}
}
impl<'a> Node<'a> {
pub fn descendants(&self) -> Descendants<'a> {
Descendants{ iter: Node{s: self.s} }
}
pub fn filter(&self, criteria: &str) -> Filter<Descendants<'a>, fn(&'a Node<'a>)->bool > {
self.descendants()
.filter(|node| node.s == "meh")
}
}
fn main() {
let doc = Node{s: "str"};
}
(Playground link)
The error I get is following:
<anon>:27:28: 27:34 error: the type of this value must be known in this context
<anon>:27 .filter(|node| node.s == "meh")
^~~~~~
<anon>:27:21: 27:43 error: mismatched types:
expected `fn(&Node<'_>) -> bool`,
found `[closure <anon>:27:21: 27:43]`
(expected fn pointer,
found closure) [E0308]
<anon>:27 .filter(|node| node.s == "meh")
^~~~~~~~~~~~~~~~~~~~~~
<anon>:27:14: 27:44 error: type mismatch: the type `fn(&Node<'_>) -> bool` implements the trait `core::ops::FnMut<(&Node<'_>,)>`, but the trait `for<'r> core::ops::FnMut<(&'r Node<'_>,)>` is required (expected concrete lifetime, found bound lifetime parameter ) [E0281]
<anon>:27 .filter(|node| node.s == "meh")
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:27:14: 27:44 error: type mismatch resolving `for<'r> <fn(&Node<'_>) -> bool as core::ops::FnOnce<(&'r Node<'_>,)>>::Output == bool`:
expected bound lifetime parameter ,
found concrete lifetime [E0271]
<anon>:27 .filter(|node| node.s == "meh")
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 4 previous errors
playpen: application terminated with error code 101
When I as per this question Correct way to return an Iterator? I tried to replace pub fn filter(&self, criteria: &str) -> Filter<Descendants<'a>, fn(&'a Node<'a>)->bool > with pub fn filter(&self, criteria: &str) -> () I get
<anon>:26:9: 27:44 error: mismatched types:
expected `()`,
found `core::iter::Filter<Descendants<'_>, [closure <anon>:27:21: 27:43]>`
What I'm supposed to replace closure with?
Alternatively, if it's too hard and finicky to return a Filter, how do I write the Wrapper for fn filter() return type?
I clearly remember that this was answered before a few times (I even wrote about it in an answer a few minutes before) but I can't find a link now, so here it goes.
The problem with your code is that you use a closure as filter() argument:
.filter(|node| node.s == "meh")
Unboxed closures in Rust are implemented as anonymous types which, naturally, can't be named, so there is no way to write a signature of a function which returns an iterator which uses a closure. That's what the error message you're getting is about:
expected `fn(&Node<'_>) -> bool`,
found `[closure <anon>:27:21: 27:43]`
(expected fn pointer,
found closure) [E0308]
There are several ways around this, one of them is to use trait objects:
pub fn filter<'b>(&'b self, criteria: &'b str) -> Box<Iterator<Item=Node<'a>+'b>>
{
Box::new(self.descendants().filter(move |node| node.s == criteria))
}
Given that your closure has a non-empty environment, this is the only way for your code to work. If your closure didn't capture anything, you could use a static function whose type can be written out:
pub fn filter(&self) -> Filter<Descendants<'a>, fn(&Node<'a>) -> bool> {
fn filter_fn<'b>(node: &Node<'b>) -> bool {
node.s == "meh"
}
self.descendants().filter(filter_fn)
}

Implementing a "cautious" take_while using Peekable

I'd like to use Peekable as the basis for a new cautious_take_while operation that acts like take_while from IteratorExt but without consuming the first failed item. (There's a side question of whether this is a good idea, and whether there are better ways to accomplish this goal in Rust -- I'd be happy for hints in that direction, but mostly I'm trying to understand where my code is breaking).
The API I'm trying to enable is basically:
let mut chars = "abcdefg.".chars().peekable();
let abc : String = chars.by_ref().cautious_take_while(|&x| x != 'd');
let defg : String = chars.by_ref().cautious_take_while(|&x| x != '.');
// yielding (abc = "abc", defg = "defg")
I've taken a crack at creating a MCVE here, but I'm getting:
:10:5: 10:19 error: cannot move out of borrowed content
:10 chars.by_ref().cautious_take_while(|&x| x != '.');
As far as I can tell, I'm following the same pattern as Rust's own TakeWhile in terms of my function signatures, but I'm seeing different different behavior from the borrow checker. Can someone point out what I'm doing wrong?
The funny thing with by_ref() is that it returns a mutable reference to itself:
pub trait IteratorExt: Iterator + Sized {
fn by_ref(&mut self) -> &mut Self { self }
}
It works because the Iterator trait is implemented for the mutable pointer to Iterator type. Smart!
impl<'a, I> Iterator for &'a mut I where I: Iterator, I: ?Sized { ... }
The standard take_while function works because it uses the trait Iterator, that is automatically resolved to &mut Peekable<T>.
But your code does not work because Peekable is a struct, not a trait, so your CautiousTakeWhileable must specify the type, and you are trying to take ownership of it, but you cannot, because you have a mutable pointer.
Solution, do not take a Peekable<T> but &mut Peekable<T>. You will need to specify the lifetime too:
impl <'a, T: Iterator, P> Iterator for CautiousTakeWhile<&'a mut Peekable<T>, P>
where P: FnMut(&T::Item) -> bool {
//...
}
impl <'a, T: Iterator> CautiousTakeWhileable for &'a mut Peekable<T> {
fn cautious_take_while<P>(self, f: P) -> CautiousTakeWhile<&'a mut Peekable<T>, P>
where P: FnMut(&T::Item) -> bool {
CautiousTakeWhile{inner: self, condition: f,}
}
}
A curious side effect of this solution is that now by_ref is not needed, because cautious_take_while() takes a mutable reference, so it does not steal ownership. The by_ref() call is needed for take_while() because it can take either Peekable<T> or &mut Peekable<T>, and it defaults to the first one. With the by_ref() call it will resolve to the second one.
And now that I finally understand it, I think it might be a good idea to change the definition of struct CautiousTakeWhile to include the peekable bit into the struct itself. The difficulty is that the lifetime has to be specified manually, if I'm right. Something like:
struct CautiousTakeWhile<'a, T: Iterator + 'a, P>
where T::Item : 'a {
inner: &'a mut Peekable<T>,
condition: P,
}
trait CautiousTakeWhileable<'a, T>: Iterator {
fn cautious_take_while<P>(self, P) -> CautiousTakeWhile<'a, T, P> where
P: FnMut(&Self::Item) -> bool;
}
and the rest is more or less straightforward.
This was a tricky one! I'll lead with the meat of the code, then attempt to explain it (if I understand it...). It's also the ugly, unsugared version, as I wanted to reduce incidental complexity.
use std::iter::Peekable;
fn main() {
let mut chars = "abcdefg.".chars().peekable();
let abc: String = CautiousTakeWhile{inner: chars.by_ref(), condition: |&x| x != 'd'}.collect();
let defg: String = CautiousTakeWhile{inner: chars.by_ref(), condition: |&x| x != '.'}.collect();
println!("{}, {}", abc, defg);
}
struct CautiousTakeWhile<'a, I, P> //'
where I::Item: 'a, //'
I: Iterator + 'a, //'
P: FnMut(&I::Item) -> bool,
{
inner: &'a mut Peekable<I>, //'
condition: P,
}
impl<'a, I, P> Iterator for CautiousTakeWhile<'a, I, P>
where I::Item: 'a, //'
I: Iterator + 'a, //'
P: FnMut(&I::Item) -> bool
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
let return_next =
match self.inner.peek() {
Some(ref v) => (self.condition)(v),
_ => false,
};
if return_next { self.inner.next() } else { None }
}
}
Actually, Rodrigo seems to have a good explanation, so I'll defer to that, unless you'd like me to explain something specific.