-
-
Notifications
You must be signed in to change notification settings - Fork 226
Add Erased Convert Error Type #644
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
Conversation
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-644 |
Generally these error APIs are not very sophisticated by design, as they add complexity in a part of the library that hardly benefits from it. And I'd definitely like to keep the API clutter down to a minimum (e.g. additional type
Can you demonstrate an example that requires it? Rust's Also keep in mind current changes in #645 which is a bugfix. |
I thought it's a bit better implementation of #525 , by separating error type into sendable and non-sendable part (since Godot types are currently non-sendable). I noticed the former is slow (writing string), particularly if conversion is retried again (eg. multiple dispatch). Kinda work around it, but it's not satisfactory IMO. And now that i have some free time, i can work it to my satisfaction 😅 With naming, it can be worked out later. It's definitely not |
But can you show concretely in which situation this is a problem, with code? Values are currently erased via
I'm not concerned about naming, but about APIs becoming more complex than necessary. See also here for detailed reasoning.
Now I'm curious, how did you notice it, did you measure it? Not that I don't believe it, but I'm wondering if this is something worth optimizing 🙂 |
Casting a sufficiently complex value should suffice. Probably not very heavy, but
Mostly because i had configuration struct that can be multiple types (int/float, string/bytes, file, (non)null, etc). Multiply that by however many values, and it's hitting pretty hard. Especially if the actual value is long to print (like an entire file in If there's a |
Fair enough, however this alone doesn't justify making the API more complex. Even if we use an erased value (as And removing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice if you could rebase it on top of #645.
If you add type erasure, why not use Option<Variant>
directly as the value? dyn Debug
is less useful...
Please also keep API changes to a minimum. Would be cool if we didn't need a separate ErasedConvertError
🙂
}) if with_source => format!( | ||
"\n Source: {}{}{}", | ||
e, | ||
if v.is_empty() { "" } else { ": " }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use variables here.
Convert { | ||
erased_error: ErasedConvertError, | ||
value: String, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be nicer to have single ConvertError
, no erased one. Then this enumerator could be kept simple, as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't compile because ConvertError
is no longer Send
, so i have to work around that.
Should the type be hidden from user? It can be accessed by |
87f915e
to
3093bac
Compare
At the risk of repeating myself 😀
It would be good to justify any addition to the API (here I understand the technical limitation (general errors not being |
The (slow) code looks something like this: if let Ok(v) = GString::try_from_variant(&var) {
// Argument is a text
} else if let Ok(v) = PackedByteArray::try_from_variant(&var) {
// Argument is a binary data
} else if let Ok(v) = <Gd<FileAccess>>::try_from_variant(&var) {
// Argument is a file
} else if let v = <Gd<SomeType>>::try_from_variant(&var) {
// Let's clone from our type instead
} else {
// Return an error
} And that's not the worst one. Let's say there are 8 You're right though, it's not strictly necessary. It's just a ok addition, with some edge case making printing and discarding the same error 8 times. |
As mentioned, I agree about the performance. But my last question was specifically about Minor thing, you can use |
For readability, it's almost unchanging. Except for error conversion. let s = String::try_from_variant(&v).map_err(|v| v.into_erased())?; There can be a convenience trait impl for Oh and btw, the erased type is no longer public. |
Did you consider making pub struct GenericConvertError<V> {
kind: ErrorKind,
value: Option<V>,
}
pub type ConvertError = GenericConvertError<Variant>;
pub type ErasedConvertError = GenericConvertError<String>; I'm not sure if this is better, mostly just a question. It does avoid a separate type for |
As I understood, the chain that led to the proposed solution is:
We will likely face the same problem in any error that includes values (could e.g. affect We have different concrete errors like |
3093bac
to
646630a
Compare
Rebased. @Dheatly23 any update here? I'd like to consolidate some of the errors soon -- so even as-is, the PR would be good as a first design on which we can iterate. Could you also fix the tests? |
(I quickly need to test something, will close and reopen) |
646630a
to
c6fa0f1
Compare
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-644 |
Regarding tests, i don't understand why it fails. For example, i don't touch anything close to test Edit: (Kinda) found it. It apparently tries to clone invalid object. Maybe it can work if it skips calling if pointer is null. |
c6fa0f1
to
6a39968
Compare
6a39968
to
c2514d8
Compare
Thank you! I'll merge this for now, but keep in mind that the API may still evolve once we try to unify the different error types. Maybe there's a way to avoid the type-state pattern for this specific error 🙂 |
Erased error type is useful to separate non-sendable values in
ConvertError
with sendable error type. But the trade-off is some data might be gone in conversion.For now it does not report the value, though this might change. Also in the future
ConvertError
can be made richer without sacrificing eg. sendability.