Skip to content
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

Support arbitrary 🥁 collections #155

Open
jyn514 opened this issue Jun 23, 2023 · 3 comments
Open

Support arbitrary 🥁 collections #155

jyn514 opened this issue Jun 23, 2023 · 3 comments

Comments

@jyn514
Copy link
Contributor

jyn514 commented Jun 23, 2023

I would like to be able to derive(Arbitrary) on a custom struct that happens to contain various collections that aren't in std (e.g. DashMap, SmallVec). I could add optional dependencies on dashmap and smallvec directly to the arbitrary crate, but I'd prefer to do this more generically so that it works for any collection.

I tried to do that as follows:

impl<'a, T: Arbitrary<'a>, C: FromIterator<T>> Arbitrary<'a> for C {
    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
        u.arbitrary_iter().collect()
    }
}

which didn't work:

 1  error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
     --> /Users/jyn/src/arbitrary/src/lib.rs:1158:10
      |
 1158 | impl<'a, T: Arbitrary<'a>, C: FromIterator<T>> Arbitrary<'a> for C {
      |          ^ unconstrained type parameter

I have two questions:

  1. Before I spent more time on it, is this a feature you're interested in?
  2. Do you have suggestions for how to get it working?
@jyn514
Copy link
Contributor Author

jyn514 commented Jun 23, 2023

ok, I think this idea cannot work.

impl<'a, T: Arbitrary<'a>, C: std::iter::FromIterator<T> + std::iter::IntoIterator<Item = T>> Arbitrary<'a> for C {
    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
        u.arbitrary_iter().collect()
    }
}
 1  error[E0119]: conflicting implementations of trait `Arbitrary<'_>` for type `()`
     --> /Users/jyn/src/arbitrary/src/lib.rs:1157:1
      |
 283  | impl<'a> Arbitrary<'a> for () {
      | ----------------------------- first implementation here
 ...
 1157 | impl<'a, T: Arbitrary<'a>, C: std::iter::FromIterator<T> + std::iter::IntoIterator<Item = T>> Arbitrary<'a> for C {
      | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflict
      |
      = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions

@Manishearth
Copy link
Member

You can only commit to a single blanket impl per trait, and it severely restricts downstream impls, so I'm opposed to introducing any new blanket impl.

However, this may be possible by instead introducing a #[from_iterator] field attribute (perhaps with a T parameter though I suspect inference will usually work) that tweaks the methods used to construct the type.

@jyn514
Copy link
Contributor Author

jyn514 commented Jun 30, 2023

i ended up not needing this (turns out smallvec already supports arbitrary and i needed custom logic for my dashmap struct anyway) but i don't mind keeping the issue open if you're interested in #[from_iterator].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants