-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking issue for error source iterators #58520
Comments
My preference before stabilizing would be to make changes to make it more like the original failure design, which I still prefer. There should be one iterator, it should begin from this error type, and its name should be |
I like the idea of a convenient interface to iterate sources. However, the interface feels unergonomic as mentioned in #58289 (comment). Additionally I think this should not be stabilized before #53487 |
Yeah, my first iteration (pun) had only |
These iterators are really good. I have long relied on the With these iterators I can get the equivalent of let display_chain: String = error
.iter_sources()
.fold(format!("Error: {}", error), |mut s, e| {
s.push_str(&format!("\nCaused by: {}", e));
s
}); These iterators does not solve the entire problem. But they make it a bit easier to implement. |
So, any changes needed here? I really want this to be stabilized |
I think a few changes are needed before this can be stabilized:
|
my 2¢: I think the simplest (for users) implementation is a single
This leaves the option open of an |
I agree with @withoutboats and @derekdreery. I had to carefully read the docs for each method before I figured out how they differed. Moreover, I suspect it will be quite difficult to pick names for both methods that are easy to remember and distinguish. Having one method and requiring the caller to use |
It does seem that many users found the terminology
As I said previously, I don't think names like |
I agree I do fully agree that |
Is this set in stone. I think Could the naming convention be changed to " |
To give some more context on why I would like it to be called When I'm reading the documentation for some object with methods, when I see an |
Hmm, this works: impl<'a> IntoIterator for &'a (dyn Error + 'static) {
type Item = &'a (dyn Error + 'static);
type IntoIter = ErrorIter<'a>;
fn into_iter(self) -> Self::IntoIter {
ErrorIter {
current: Some(self),
}
}
} let mut iter = <&(dyn Error + 'static) as IntoIterator>::into_iter(&err); or for e in err.borrow() as &(dyn Error) {
eprintln!("{}", e);
} and |
@haraldh We can add that impl, but I don't think we should (and it seems completely circular to add it just to justify naming the method |
Agreed |
I'd like to point to the issues discussing the addition (#48420) and stabilization (#50894) of
In the end, the rationale was:
I'd like to throw two naming ideas into the ring that might be considered for further debate:
I'd also like to propose to rename the |
Sorry if this was brought up earlier, I tried to read the RFC/issues, and didn't see it brought up. What is the intent of how to handle older code that overrides Should these errors be changed to implement |
IMO all new errors should only implement |
If we were to do this, could we make an effort to submit PRs to popular crates using More generally (and slightly OT), is there a mechanism for the community to help crate maintainers with stuff like this? |
Opened a PR with this suggestion: #65557 |
So, it seems, that even Path::ancestors() includes itself. So, to avoid confusion and simplify it more, I reduced PR #65557 to only have Rationale:
|
I like the name The docs should mention the |
Here we go: #81705 |
To produce an error iterator `std::error::Chain` one had to call `<dyn Error>::chain()`, which was not very ergonomic, because you have to manually cast to a trait object, if you didn't already have one with the type erased. ``` let mut iter = (&my_error as &(dyn Error)).chain(); // or let mut iter = <dyn Error>::chain(&my_error); // or let mut iter = Error::chain(&my_error); ``` The `chain()` method can't be implemented on the Error trait, because of rust-lang#69161 `Chain::new()` replaces `<dyn Error>::chain()` as a good alternative without confusing users, why they can't use `my_error.chain()` directly. The `Error::sources()` method doesn't have this problem, so implement it more efficiently, than one could achieve this with `Chain::new().skip(1)`. Related: rust-lang#58520
I think @haraldh touched on a reason to consider both a method that iterates over // Valid for any `&E: Error + ?Sized`
fn sources(&self) -> Chain<'_> {}
// Valid only for `&E: Error + Sized + 'static`
fn chain(&self) -> Chain<'_> where Self: Sized + 'static {} So you could write a maximally compatible method to display an error using fn render(err: impl Error) {
fn render_inner(err: impl Error) { .. }
render_inner(&err);
for source in err.sources() {
render_inner(source);
}
} but you couldn't write that same implementation using You could argue that's a bit of a forced difference though, because in practice I think non- |
Shouldn't the iterator proper implement |
That's not obvious. There is no documented requirement on https://doc.rust-lang.org/1.53.0/std/error/trait.Error.html#method.source that it behave in a fused way. |
Apologies if I'm misinterpreting something, but once the |
Nothing says the error can't change its mind about what its source is: impl Error for SillyError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
if rand::int() == 1 { Some(&self.source) } else { None }
}
} |
Is it a requirement for fused iterators to not involve randomness? All I'm saying is that |
I guess my example might still not be enough as |
Some papercuts on error::Error Renames the chain method, since I chain could mean anything and doesn't refer to a chain of sources (cc rust-lang#58520) (and adds a comment explaining why sources is not a provided method on Error). Renames arguments to the request method from `req` to `demand` since the type is `Demand` rather than Request or Requisition. r? `@yaahc`
Some papercuts on error::Error Renames the chain method, since I chain could mean anything and doesn't refer to a chain of sources (cc rust-lang#58520) (and adds a comment explaining why sources is not a provided method on Error). Renames arguments to the request method from `req` to `demand` since the type is `Demand` rather than Request or Requisition. r? ``@yaahc``
In #100955, I renamed |
I recently discovered that |
Another solution is to make |
…dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
…dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
…dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
…dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
…dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
…dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
…dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
…dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
Rollup merge of rust-lang#127091 - Sky9x:fused-error-sources-iter, r=dtolnay impl FusedIterator and a size hint for the error sources iter cc tracking issue rust-lang#58520
This covers the
<dyn Error>::iter_chain
and<dyn Error>::iter_sources
methods added in #58289.The text was updated successfully, but these errors were encountered: