-
Notifications
You must be signed in to change notification settings - Fork 68
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
Accept an arbitrary expression that returns a callable object in #[darling(with)]
#309
Comments
One advantage of the closure approach is that closures and paths are syntactically disjoint - there is no way to confuse the two. That allows I would want to make sure the passed-in closure didn't have access to any locals, so I'm thinking the generated code would be something like... EDIT: This doesn't work as-written; there are type annotations needed in the closure that are missing. Adding the annotation automatically seems possible but ugly. struct Thing {
#[darling(with = |meta| parse_with_alts(meta))]
demo: Stuff
}
impl FromMeta for Thing {
fn from_meta(meta: &Meta) -> Result<Self> {
// PROBLEM: We need a return type for this function, but if someone uses
// `with` in conjunction with `map` or `and_then`, we might not know the
// interim return type.
fn with_wrapper__demo(__meta: &Meta) -> Result<Stuff> {
let closure = |meta| parse_with_alts(meta);
// POSSIBLE SOLUTION: Add postfix call here, so that this function
// will always have the return type of the field.
closure(__meta)
}
// rest of the generated method goes here...
}
} A change here needs to take #305 into consideration, since that is also bothering me about |
To make sure the closure doesn't capture anything it's possible to just require it to be assignable to a function pointer: let closure: fn(_) -> _ = |meta| ...; This way the closure also has access to the generic parameters if there are any on the struct/enum under the Btw I don't see any ambiguity and problems with the compatibility this change may cause. Since today the syntax is limited to function paths, which are just a subset of an expression that returns a "callable object". |
TIL; thanks for sharing that. A revised version of this is then... struct Thing {
#[darling(with = |meta| parse_with_alts(meta))]
demo: Stuff
}
impl FromMeta for Thing {
fn from_meta(meta: &Meta) -> Result<Self> {
let with_closure__demo: fn(&Meta) -> _ = |meta| parse_with_alts(meta);
// rest of the generated method goes here,
// using that `with_closure__demo` as if it was the passed path
}
} |
I've posted a WIP PR for this #310 |
It's not a big issue, but just an inconvenience. Here is an example of this problem that I have.
I need to configure parsing with some parameterization necessary for validation and error messages. Currently to do that you always need to define a separate function item that accepts a
&syn::Meta
and returns aResult
. It would be better if I could just write an expression that returns a closure to invoke in the#[darling(with)]
directly like this:The main goal is to provide additional context for the parser function passed to
with
, and also keep that config as close to the field as possible lexically.The text was updated successfully, but these errors were encountered: