arbitrary
arbitrary copied to clipboard
Allow custom arbitrary methods for fields in the custom derive
Sometimes a field of a struct doesn't implement arbitrary and it is either impossible to do (because it is from another crate, for example) or undesired.
We should support some kind of attribute to either use the Default::default
implementation for the type, when we "don't care" about that field, or supply an arbitrary function that has the same signature as Arbitrary::arbitrary
to be used instead.
This is all possible to do when implementing Arbitrary
by hand, in the sense that you can always stuff whatever code inside the impl. But this seems common enough and simple enough that we may want to support it in the custom derive.
Straw person syntax:
#[derive(Arbitrary)]
struct MyThing {
// This doesn't actually matter, just a diagnostic message, so don't
// waste input bytes on it.
#[arbitrary(default)]
diagnostic: String,
// This is a type defined by a foreign crate and doesn't implement
// Arbitrary. Because of orphan rules, we can't implement Arbitrary
// for it, so instead we have a one-off function.
#[arbitrary(arbitrary = arbitrary_foreign_type)]
foreign: foreign_crate::ForeignType,
}
fn arbitrary_foreign_type(u: &mut Unstructured)
-> Result<foreign_crate::ForeignType>
{
// ...
}
The open question in my mind is how to deal with the other, optional Arbtirary
methods? e.g. arbitrary_take_rest
, shrink
, and size_hint
. Should we assume the default implementations in this case? Should we also allow providing custom implementations for them?
Any thoughts @Manishearth?
+cc @bnjbvr
No strong thoughts, we can allow multiple methods for overriding it perhaps.
Is this still in the pipeline? Would significantly simplify my use case testing reasonably complex serde structures.
AFAIK, no one has ever started implementing this. It seems like it is generally wanted/useful, so if you want to take a shot at implementing it, I would be happy to review/give feedback/etc.
in cases where it's only the orphan rules prevent deriving Arbitrary, we could do a remote derive like serde does. I also like the idea of a function override as described before, and there's not full overlap
I would love to have this. Otherwise it's almost impossible to apply Arbitrary in a big project, because there is always 2-3% of fields, that are not like others.
FYI: I created ArbitraryExt crate which provides a temporal workaround for this problem.
Would you like to turn that into a pull request for this crate?
@fitzgen Sure.
For now, ArbitraryExt
is a quick and dirty prototype. E.g. I just applied it to my code base, it I quickly found that a few things are missing. Once I implement everything I need and test it against a large code base, I will port it to Arbitrary
and open a PR. I'll keep you updated.
@fitzgen Ok, I've opened a PR: https://github.com/rust-fuzz/arbitrary/pull/129
This can be marked as resolved (since https://github.com/rust-fuzz/arbitrary/pull/129 is merged)