Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upReplace unwrap() in doctests with `?` #323
Conversation
- `ParseError` is handled with the ? operator - Some other specific results are unwrapped with `expect()`
|
Why are there so many |
|
@KiChjang They define lines of code that we want to consider in the tests but hide in the documented output. This is needed here to hide the boilerplate. The code needs to be wrapped in a function that returns a result in order to use the |
budziq
commented
May 9, 2017
|
There seam to be few |
Can you specify where? Note that lines hidden from the docs do not need to have their errors captured. Moreover, a good part of the unwraps still around are unwrapping
That would be debatable. Although a |
budziq left a comment •
There are still dome
Well the point of the referenced lib-blitz issue #312 seams to be centered around promoting correct error handling in rust in general and unwrapping
I completely agree. Just from the perspective of user who has tried to work with |
| /// assert!(url.path_segments_mut().is_err()); | ||
| /// | ||
| /// let mut url = Url::parse("http://example.net/foo/index.html").unwrap(); | ||
| /// let mut url = Url::parse("http://example.net/foo/index.html")?; | ||
| /// url.path_segments_mut().unwrap().pop().push("img").push("2/100%.png"); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Enet4
May 9, 2017
•
Author
Contributor
That is something I would resolve in another PR: path_segments_mut returns Result<_,()>. With the API like this, we cannot capture it with the ? without mapping the error or rolling a custom error type. Note that using () as error type is not recommended by the Rust API guidelines (C-MEANINGFUL-ERR).
The same issue reproduces across your other mentions.
| /// # use url::{Url, ParseError}; | ||
| /// | ||
| /// # fn run() -> Result<(), ParseError> { | ||
| /// let mut url = Url::parse("https://github.com/servo/rust-url/")?; | ||
| /// url.path_segments_mut().unwrap().clear().push("logout"); |
This comment has been minimized.
This comment has been minimized.
| /// # use url::{Url, ParseError}; | ||
| /// | ||
| /// # fn run() -> Result<(), ParseError> { | ||
| /// let mut url = Url::parse("https://github.com/servo/rust-url/")?; | ||
| /// url.path_segments_mut().unwrap().push("pulls"); |
This comment has been minimized.
This comment has been minimized.
| /// url.path_segments_mut().unwrap().push("pulls"); | ||
| /// assert_eq!(url.as_str(), "https://github.com/servo/rust-url//pulls"); | ||
| /// | ||
| /// let mut url = Url::parse("https://github.com/servo/rust-url/").unwrap(); | ||
| /// let mut url = Url::parse("https://github.com/servo/rust-url/")?; | ||
| /// url.path_segments_mut().unwrap().pop_if_empty().push("pulls"); |
This comment has been minimized.
This comment has been minimized.
| /// # use url::{Url, ParseError}; | ||
| /// | ||
| /// # fn run() -> Result<(), ParseError> { | ||
| /// let mut url = Url::parse("https://github.com/")?; | ||
| /// let org = "servo"; | ||
| /// let repo = "rust-url"; | ||
| /// let issue_number = "188"; | ||
| /// url.path_segments_mut().unwrap().extend(&[org, repo, "issues", issue_number]); |
This comment has been minimized.
This comment has been minimized.
| /// # use url::{Url, ParseError}; | ||
| /// | ||
| /// # fn run() -> Result<(), ParseError> { | ||
| /// let mut url = Url::parse("https://github.com/servo")?; | ||
| /// url.path_segments_mut().unwrap().extend(&["..", "rust-url", ".", "pulls"]); |
This comment has been minimized.
This comment has been minimized.
dtolnay
commented
May 12, 2017
|
Yes the But as it is, |
|
Ok, I will look into them today, possibly devising an error type for the purpose. I also wish to help addressing #299, since it appears we could highly benefit from better error handling. Update: All right, all unwraps should be gone. I also found a |
- Add `CannotBeBaseError` struct to examples involving cannot-be-a-base URLs, map unit errors to this type; - Replace previous `path_segment().expect()` with `CannotBeBaseError` mapping; - replace try! with ? in url.with_defaul_port example.
dtolnay
commented
May 12, 2017
|
Thanks! That eliminates the remainder of the Some of these have a bit more error-handling noise than I would find valuable. For example the following one from use url::Url;
use std::error::Error;
use std::fmt;
#[derive(Debug)]
struct CannotBeBaseError;
impl fmt::Display for CannotBeBaseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.description())
}
}
impl Error for CannotBeBaseError {
fn description(&self) -> &str { "cannot be a base" }
}
let mut url = Url::parse("https://github.com/servo/rust-url/")?;
url.path_segments_mut().map_err(|_| CannotBeBaseError)?
.clear().push("logout");
assert_eq!(url.as_str(), "https://github.com/logout");Since use url::Url;
let mut url = Url::parse("https://github.com/servo/rust-url/")?;
url.path_segments_mut().map_err(|_| "cannot be a base")?
.clear().push("logout");
assert_eq!(url.as_str(), "https://github.com/logout"); |
|
I agree that the current approach is verbose (not to mention that it definitely looks like something that should have been an error variant in the first place!). I'll follow the advice of using |
- Remove verbose `CannotBeBase` error in examples, use a `&'static str` instead.
dtolnay left a comment
|
Great work. Thanks for sticking with this! |
bjorn3 left a comment
|
|
| @@ -44,6 +45,8 @@ assert!(issue_list_url.path_segments().map(|c| c.collect::<Vec<_>>()) == | |||
| assert!(issue_list_url.query() == Some("labels=E-easy&state=open")); | |||
| assert!(issue_list_url.fragment() == None); | |||
| assert!(!issue_list_url.cannot_be_a_base()); | |||
| # Ok(()) | |||
| # } | |||
This comment has been minimized.
This comment has been minimized.
| let data_url = Url::parse("data:text/plain,Hello?World#").unwrap(); | ||
| # fn run() -> Result<(), ParseError> { |
This comment has been minimized.
This comment has been minimized.
- add `run().unwrap()` to all result-guarded doctests
|
@bjorn3 Oops, you are right! I appended calls to |
|
This looks great. Thanks all! @bors-servo r+ |
|
|
Replace unwrap() in doctests with `?` Fixes #312. - All results yielding `ParseError` in the doctests should now be handled with the ? operator. - Some other specific results are ~unwrapped with `expect()`~ mapped to a placeholder string message, such as in URLs that are not _cannot-be-a-base_. Users are then expected to adjust this mapping depending on their use case. Once #299 is resolved, we'll be able to propagate these normally. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/323) <!-- Reviewable:end -->
|
|
Enet4 commentedMay 5, 2017
•
edited
Fixes #312.
ParseErrorin the doctests should now be handled with the ? operator.unwrapped withmapped to a placeholder string message, such as in URLs that are not cannot-be-a-base. Users are then expected to adjust this mapping depending on their use case. Once #299 is resolved, we'll be able to propagate these normally.expect()This change is