4 ms·
Errors are for the regular case when the program detected that something wasn't allowed or set up right and the program did everything right (by returning an e
by dannymi 3y ago
Errors are for the regular case when the program detected that something wasn't allowed or set up right and the program did everything right (by returning an error). Why then do you need the rs source code file&line of the place where everything went right? What about all the other places where everything went right? Wanna log those, too? :)
What will the end user do with rs source code file&line?
I read the example on the page. What they want to do is return which argument of `add` the error was with. Well, then introduce an `AddError` (or I guess it could be a more generic `BinaryOperationError`) like this: `struct AddError { argument_1: Option<...>, argument_2: Option<...> }` and return that error from `add`. Then you can even have it return errors due to both arguments at the same time.
One use case of the crate would be if you made a mistake and something actually shouldn't be an error but should be a panic, and you wanna find where it is in order to change it to a panic. So, debugging.
- IshKebab 3y ago> What will the end user do with rs source code file&line? Google it.
- JoelJacobson 3y agoAuthor of `wherr` here. The idea is to minimise the effort needed to debug programs that already make use of the `?` operator, when the underlying error doesn't already contain file and line information, where the error is possibly coming from code of of your own control. Sure, you could catch such errors and return a refined error type, but that's more code, which might be what you want in the end, but this is for the code that currently makes use of the simple `?` operator. Once the file and line where the error is returned has been identified (using `wherr`), it might be a good idea, like you suggest, to introduce a new error type or refine the existing one. But maybe the error is fine as it is, and you just needed to know where it came from, to fix some bug, that when fixed, will cause the error to not happen any longer. Basically, when feeling confident an error cannot happen, some people use `.unwrap()` or `.expect()`, which *do* reveal the file and line, but then the program also panics. This might be what you want, but if you're developing a library, you probably most times want to let the "user" (the developer using the library) decide what course of action to take, based on the error. However, that "user" might not be at all interested in the file and line information of where the error originates from in your library source code, since the user might not be capable of fixing the possible bug anyway. But maybe the user wants to file a bug report, and then it would be helpful to know the file and line information. > What about all the other places where everything went right? Wanna log those, too? :) If everything went right, the Ok(val) is simply returned as Ok(val) unchanged, see `wherr/src/lib.rs`: match result { Ok(val) => Ok(val), ...
- dannymi 3y agoThis crate is nice to have for debugging. Thank you for writing it. I just had the case already over the past decades where everyone wants to turn every error into Java backtraces (even when not in Java ;) ) and want to emphasize that this is almost never what one should do in regular operation. As you said, unwrap() and expect() and panic!() do that for the "definitely a bug" case already. And, there, it's correct. >probably most times want to let the "user" (the developer using the library) decide what course of action to take, based on the error. I agree. >But maybe the user wants to file a bug report, and then it would be helpful to know the file and line information. In my opinion this belongs in the debug information (i.e. dwarf or similar) then. You can also store dwarf debug info outside of the object file. >> What about all the other places where everything went right? Wanna log those, too? :) >If everything went right, the Ok(val) is simply returned as Ok(val) unchanged, see `wherr/src/lib.rs`: match result { Ok(val) => Ok(val), ... I see. But what I meant is that if the Err case of a regular Result value is enriched like this, why not the Ok case? After all, the programmer (user of your crate) could have erroneously returned Ok where they should have returned Err. Would only be consistent. I know that that isn't easily possible there. That brings me back to "all result::Result construction sites should show up in dwarf debug info". I use debuggers less than I should. But thinking about it that's silly. We should be able to use debuggers to debug problems, including problems like this.
- dannymi 3y agoOpen bug report about inability to set a breakpoint on Err: https://github.com/rust-lang/rust/issues/54144 https://github.com/rust-lang/rust/issues/54144
- simiones 3y agoIt seems that you are trying to take the position that Ok/Err are similar to if/else in that neither is more or less expected than the other. The very names chosen in Rust show that this is not how most think about these two cases. Returning Err is for cases that the developer considered errors, abnormal situations. This attitude that the happy-case and the error-case paths are equivalent and should be treated the same is bizarre and seems to be contradicted by virtually every language choice, even in communities that profess it. Go is probably the most notorious example of professing "errors are just regular values" and refusing to add any error-handling constructs to the language; and yet, even in Go, errors are called, well, `error`s and there are explicit patterns that everyone follows that would never be considered acceptable for regular values (such as naming all error values "err" and reusing the "err" variable to hold any error returned by any function in the same context - try that with a "ret" to hold any non-err return value and see how many people accept your code).