-
Notifications
You must be signed in to change notification settings - Fork 4
Argument parsing errors should have designated Error enum variant #28
Comments
This is intended. Argument parsing is part of the command's code that's first executed before running the actual body of the command. Failure to parse arguments constitutes as a user error, since it is the user's responsibility to parse arguments (the To clarify, dispatch errors originate from the framework, user errors from the commands. |
Yeah I can see why it happens. I can't quite interpret what you think of the proposal though - do you agree that this behavior is confusing and a designated error enum variant might be beneficial, or is this a "working as intended" situation? In other words, would a PR about this issue be accepted? |
The latter, "working as intended." The current error enum makes the origin of the errors from either the framework or commands clear, and allows the two to be handled separately: fn handle_dispatch_error(err: DispatchError) {
// ....
}
// Assuming the user defined a custom error type called `MyError`
fn handle_my_error(err: MyError) {
// ...
}
let error = ...;
match error {
Error::Dispatch(err) => handle_dispatch_error(err),
Error::User(err) => handle_my_error(err)
} If the user error was merged into Therefore, I don't believe that this is an issue that ought to be fixed. Besides that, how would we distinguish argument errors from other errors returned from commands? By default, the error type for commands is |
I see your concern about error handling being more difficult with the Error enum variants merged. I think there is a misconception here. My idea was not to merge the variants, but to add a new variant. Either to Error: pub enum Error {
Dispatch(DispatchError),
Argument(ArgumentError<Box<dyn std::error::Error>>), // <--
User(E),
} or to DispatchError: pub enum DispatchError {
NormalMessage,
PrefixOnly(String),
InvalidCommandName(String),
CheckFailed(String, Reason),
ArgumentError(ArgumentError<Box<dyn std::error::Error>>), // <--
} (Not sure yet which one of the two is more ergonomic for the user. Also, Funnily enough, the motivation behind this change is of the same kind as the concern you expressed: merging argument parsing errors and user-thrown errors into the same Have I understood and addressed your concern? |
I understood your request to separate argument errors from
That is what I meant by merging into enum CommandError<E> {
Argument(ArgumentError<Box<dyn std::error::Error>>),
Normal(E),
} and use it instead of a plain |
Ah, now I understand how you envisioned users to handle argument parsing errors. Either call
The generated function would yield a What I personally like about this approach in comparison to the other two you presented (downcasting and custom error type):
By the way, to be clear: It is not my intention to force through my subjective opinion on this topic. I merely want to ensure that my idea and its (dis)advantages are fully understood and considered before the accept/reject decision is made. |
Looking from that angle, I like it, actually. I disagreed with your original proposal a lot, but reusing |
I don't think such a trait impl is needed. The generated command code can embed the user code like this: let result: Result<(), USERERROR> = async {
// USER CODE HERE
}.await;
result.map_err(FrameworkError::User) |
Ah, then I have no more issues with this. You're free to open a pull request. |
Currently, when a user gives too many arguments to a command, or too few, or their input was malformed, serenity bubbles up the error as a
Error::User
. However, the error doesn't happen in user code at all; it happens in serenity's dispatch glue code. I think it would be more intuitive and more useful to bubble up argument parsing errors asError::Dispatch
Edit: we decided that a new designated Error enum variant
Error::Argument(ArgumentError)
for argument parsing errors is betterThe text was updated successfully, but these errors were encountered: