-
Notifications
You must be signed in to change notification settings - Fork 82
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
structured errors instead of String
#60
Comments
I'd go with 3. I'm not sure how much code for the error type we are talking about, but I'd be surprised if it ended up being more than 50 lines or so, with most of them trait impls. I wouldn't worry about the "matching on errors" case, as it's not really possible right now anyway. (Aside from comparing the strings, which, given a Display impl, users can still do.) |
Ok. Hm, if someone wants to wrap that error they would either need one variant for each builder Here is a supposedly core + stable-compliant draft: #[derive(Display)]
pub enum FooBuilderError<'a> {
// pre-defined errors:
UnitializedField(&'static str),
// ...
//////////////////////////////
// user-defined errors:
CustomDefault(&'static str, &'a Display),
// ^~~ by convention the first entry could be the field ident?
// ...
} Pre-defined errors could refer to field idents via But user-defined errors should be able to do dynamic stuff. Without collections on core + stable we are then left with a reference to some trait like So here are two problems I see with that draft:
I currently think we won't get any farther than that - at least on stable + core. Do I maybe miss something? So maybe we could have one definition which targets As a side note: Speaking of |
Hm, if we are generating builder-specific error definitions anyway, we could allow users some flexibility - at least in theory. I'm quite skeptical that this would blow up the public API and learning curve of derive_builder significantly. Anyway some annotation could tell derive_builder that the custom default error will always be Currently I don't believe that this would lead to a nice API, but I may be wrong. PS: These builder-specific errors would also be harder to migrate to a more centralized definition in the future - in case proc_macros would be allowed to export items at some point. |
I was thinking of a pretty abstract I would not make this a complicated API at all – the struct should probably only have one impl: |
Ok, so basically just a newtype then. That would be more forward-compatible, if we keep adding more failure modes. With the enum based approach, each new variant would be a breaking change. So this is a strong argument for a plain newtype (or a I still think the newtype could just wrap I do plan to add user defined filters for fields which could then emit custom errors with dynamic information. We could support this with #[cfg(no_std)]
struct FooBuilderError(String)
#[cfg(not(no_std))]
struct FooBuilderError(&'static str) Going all I haven't made up my mind and would like to collect some possible use cases for custom error messages and see how important it is to have this flexibility. Of course the longer we wait the more painful the breaking change might be for other people.. I feel like the current custom defaults are unlikely to error. We should revisit this question at latest when we come to those user defined filters or something similar. |
Yeah, wrapping a string but no exposing it on std is a nice way to add
nicer error messages.
Colin Kiegel <notifications@github.com> schrieb am So. 26. März 2017 um
16:37:
… Ok, so basically just a newtype then. That would be more
forward-compatible, if we keep adding more failure modes. With the enum
based approach, each new variant would be a breaking change. So this is a
strong argument for a plain newtype (or a Other variant for all future
failure modes). Ok, let's assume we do the plain newtype.
I still think the newtype could just wrap String *on std* then, no? As
mentioned before, I don't consider performance the primary concern on the
Err-path if Result is used idiomatically.
I *do* plan to add user defined filters for fields which could then emit
custom errors with dynamic information. `1277.0.0.1` is not a valid IP
address, the first byte `1277` is not within the range `0...255` instead
of not a valid IP address, the first byte is not within the range
`0...255`.
We could support this with
#[cfg(no_std)]struct FooBuilderError(String)
#[cfg(not(no_std))]struct FooBuilderError(&'static str)
Going all &'static str is less flexible (and a breaking change), but also
less complex to document/learn/implement. :-)
I haven't made up my mind and would like to collect some possible use
cases for custom error messages and see how important it is to have this
flexibility. Of course the longer we wait the more painful the breaking
change might be for other people..
I feel like the current custom defaults are unlikely to error. We should
revisit this question at latest when we come to those user defined filters
or something similar.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#60 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AABOX-0woDiRbBd5qCohNYM_UJD6_Ursks5rpngugaJpZM4MpMi1>
.
|
Ok, cool. :-) We should also think about which traits we want to implement. Since we do code generation, each trait we add later would be a breaking change - the user could have already just impl'd this trait.
|
Hm, that question applies to the builder, too. I already had the idea to introduce a |
Hm, there may be a trick to get around the limitation of proc_macro crates not being able to export items. It would involve another crate to re-export the custom derive (+additional items). I haven't tried it yet. |
The The |
Hm, returning the builder for inspection is an interesting idea! However, I don't think we can easily report multiple errors at once. We would need to return a vector of errors, because it could be 1...n. I believe it's better to pick and report only one error. The |
@TedDriggs points out in #67 that there is a need to
I think that's an important observation. If we introduce structured errors, what will be our story for custom structured errors? Do we require users to wrap a (private) build function or implement their own? Or is there some clever way to let users manipulate the errors we emit, including their type? |
FYI, I think I now know how to make a proc-macro crate that exports things: Check out from_variants for an example of it in action, courtesy of the serde team. |
Ok, cool. I'd be interested in your experience, because my current attempt #94 got stuck due to some |
I'm working on an embedded crate at the moment (no_std and no allocator, so no |
I had an idea for this one: We could accept the path to an error type as an attribute and use that in the build function return type. #[derive(Builder)]
#[builder(build_fn(error = "crate::Error"))]
pub struct MyStruct { my_field: String } As long as there's an This way, |
The
build
method currently returnsResult<Foo, String>
. But representing errors asString
is not very rustic.It's also a show-stopper for using
derive_builder
with#![no_std]
on the stable toolchain. The reason is thatString
onno_std
requires thecollections
crate, which is marked as unstable.These are already two reasons that representing errors as
String
is not optimal.Proposal
Find a way to return structured errors instead of
Strings
. Onstd
they should implement the usualfmt
traits. Onno_std
they should be compliant with the stable toolchain.Questions
The main question is, how do we get the structured errors into scope? This is unfortunately not straightforward, since
derive_builder
is a proc_macro crate.So we need to work around that limitation somehow. These ideas come to my mind right now
derive_builder_common
crate, which just exports traits / types / impls and must then be imported by any user ofderive_builder
.derive_builder
to emit the traits / types / impls directly into the target crate.derive_builder
could generate unique error definitions for that struct.All these approaches have their own drawbacks.
derive_builder
. The out-of-the-box experience is a bit impaired.cc @killercup
The text was updated successfully, but these errors were encountered: