proptest/arbitrary/
traits.rs

1//-
2// Copyright 2017, 2018 The proptest developers
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10use core::fmt;
11
12use crate::strategy::Strategy;
13
14//==============================================================================
15// Arbitrary trait
16//==============================================================================
17
18/// Arbitrary determines a canonical [`Strategy`] for the implementing type.
19///
20/// It provides the method `arbitrary_with` which generates a `Strategy` for
21/// producing arbitrary values of the implementing type *(`Self`)*. In general,
22/// these strategies will produce the entire set of values possible for the
23/// type, up to some size limitation or constraints set by their parameters.
24/// When this is not desired, strategies to produce the desired values can be
25/// built by combining [`Strategy`]s as described in the crate documentation.
26///
27/// This trait analogous to
28/// [Haskell QuickCheck's implementation of `Arbitrary`][HaskellQC].
29/// In this interpretation of `Arbitrary`, `Strategy` is the equivalent of
30/// the `Gen` monad. Unlike in QuickCheck, `Arbitrary` is not a core component;
31/// types do not need to implement `Arbitrary` unless one wants to use
32/// [`any`](fn.any.html) or other free functions in this module.
33///
34/// `Arbitrary` currently only works for types which represent owned data as
35/// opposed to borrowed data. This is a fundamental restriction of `proptest`
36/// which may be lifted in the future as the [generic associated types (GAT)]
37/// feature of Rust is implemented and stabilized.
38///
39/// [generic associated types (GAT)]: https://github.com/rust-lang/rust/issues/44265
40///
41/// [`Strategy`]: ../strategy/trait.Strategy.html
42///
43/// [HaskellQC]:
44/// https://hackage.haskell.org/package/QuickCheck/docs/Test-QuickCheck-Arbitrary.html
45pub trait Arbitrary: Sized + fmt::Debug {
46    /// The type of parameters that [`arbitrary_with`] accepts for configuration
47    /// of the generated [`Strategy`]. Parameters must implement [`Default`].
48    ///
49    /// [`arbitrary_with`]: trait.Arbitrary.html#tymethod.arbitrary_with
50    ///
51    /// [`Strategy`]: ../strategy/trait.Strategy.html
52    /// [`Default`]:
53    ///     https://doc.rust-lang.org/nightly/std/default/trait.Default.html
54    type Parameters: Default;
55
56    /// Generates a [`Strategy`] for producing arbitrary values
57    /// of type the implementing type (`Self`).
58    ///
59    /// Calling this for the type `X` is the equivalent of using
60    /// [`X::arbitrary_with(Default::default())`].
61    ///
62    /// This method is defined in the trait for optimization for the
63    /// default if you want to do that. It is a logic error to not
64    /// preserve the semantics when overriding.
65    ///
66    /// [`Strategy`]: ../strategy/trait.Strategy.html
67    /// [`X::arbitrary_with(Default::default())`]:
68    ///     trait.Arbitrary.html#tymethod.arbitrary_with
69    fn arbitrary() -> Self::Strategy {
70        Self::arbitrary_with(Default::default())
71    }
72
73    /// Generates a [`Strategy`] for producing arbitrary values of type the
74    /// implementing type (`Self`). The strategy is passed the arguments given
75    /// in args.
76    ///
77    /// If you wish to use the [`default()`] arguments,
78    /// use [`arbitrary`] instead.
79    ///
80    /// [`Strategy`]: ../strategy/trait.Strategy.html
81    ///
82    /// [`arbitrary`]: trait.Arbitrary.html#method.arbitrary
83    ///
84    /// [`default()`]:
85    ///     https://doc.rust-lang.org/nightly/std/default/trait.Default.html
86    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy;
87
88    /// The type of [`Strategy`] used to generate values of type `Self`.
89    ///
90    /// [`Strategy`]: ../strategy/trait.Strategy.html
91    type Strategy: Strategy<Value = Self>;
92}
93
94//==============================================================================
95// Type aliases for associated types
96//==============================================================================
97
98/// `StrategyFor` allows you to mention the type of [`Strategy`] for the input
99/// type `A` without directly using associated types or without resorting to
100/// existential types. This way, if implementation of [`Arbitrary`] changes,
101/// your tests should not break. This can be especially beneficial when the
102/// type of `Strategy` that you are dealing with is very long in name
103/// (the case with generics).
104///
105/// [`Arbitrary`]: trait.Arbitrary.html
106/// [`Strategy`]: ../strategy/trait.Strategy.html
107pub type StrategyFor<A> = <A as Arbitrary>::Strategy;
108
109/// `ParamsFor` allows you to mention the type of [`Parameters`] for the input
110/// type `A` without directly using associated types or without resorting to
111/// existential types. This way, if implementation of [`Arbitrary`] changes,
112/// your tests should not break.
113///
114/// [`Parameters`]: trait.Arbitrary.html#associatedtype.Parameters
115/// [`Arbitrary`]: trait.Arbitrary.html
116/// [`Strategy`]: ../strategy/trait.Strategy.html
117pub type ParamsFor<A> = <A as Arbitrary>::Parameters;
118
119//==============================================================================
120// Free functions that people should use
121//==============================================================================
122
123/// Generates a [`Strategy`] producing [`Arbitrary`][trait Arbitrary] values of
124/// `A`. Unlike [`arbitrary`][fn arbitrary], it should be used for being
125/// explicit on what `A` is. For clarity, this may be a good idea.
126///
127/// Use this version instead of [`arbitrary`][fn arbitrary] if you want to be
128/// clear which type you want to generate a `Strategy` for, or if you don't
129/// have an anchoring type for type inference to work with.
130///
131/// If you want to customize how the strategy is generated, use
132/// [`any_with::<A>(args)`] where `args` are any arguments accepted by
133/// the `Arbitrary` impl in question.
134///
135/// # Example
136///
137/// The function can be used as:
138///
139/// ```rust
140/// use proptest::prelude::*;
141///
142/// proptest! {
143///     fn reverse_reverse_is_identity(ref vec in any::<Vec<u32>>()) {
144///         let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
145///         prop_assert_eq!(vec, &vec2);
146///     }
147/// }
148///
149/// fn main() {
150///     reverse_reverse_is_identity();
151/// }
152/// ```
153///
154/// [`any_with::<A>(args)`]: fn.any_with.html
155/// [fn arbitrary]: fn.arbitrary.html
156/// [trait Arbitrary]: trait.Arbitrary.html
157/// [`Strategy`]: ../strategy/trait.Strategy.html
158#[must_use = "strategies do nothing unless used"]
159pub fn any<A: Arbitrary>() -> StrategyFor<A> {
160    // ^-- We use a shorter name so that turbofish becomes more ergonomic.
161    A::arbitrary()
162}
163
164/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
165/// given configuration arguments passed in `args`. Unlike [`arbitrary_with`],
166/// it should be used for being explicit on what `A` is.
167/// For clarity, this may be a good idea.
168///
169/// Use this version instead of [`arbitrary_with`] if you want to be clear which
170/// type you want to generate a `Strategy` for, or if you don't have an anchoring
171/// type for type inference to work with.
172///
173/// If you don't want to specify any arguments and instead use the default
174/// behavior, you should use [`any::<A>()`].
175///
176/// # Example
177///
178/// The function can be used as:
179///
180/// ```rust
181/// use proptest::prelude::*;
182/// use proptest::collection::size_range;
183///
184/// proptest! {
185///     fn reverse_reverse_is_identity
186///         (ref vec in any_with::<Vec<u32>>(size_range(1000).lift()))
187///     {
188///         let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
189///         prop_assert_eq!(vec, &vec2);
190///     }
191/// }
192///
193/// fn main() {
194///     reverse_reverse_is_identity();
195/// }
196/// ```
197///
198/// [`any::<A>()`]: fn.any.html
199/// [`arbitrary_with`]: fn.arbitrary_with.html
200/// [`Arbitrary`]: trait.Arbitrary.html
201/// [`Strategy`]: ../strategy/trait.Strategy.html
202#[must_use = "strategies do nothing unless used"]
203pub fn any_with<A: Arbitrary>(args: ParamsFor<A>) -> StrategyFor<A> {
204    // ^-- We use a shorter name so that turbofish becomes more ergonomic.
205    A::arbitrary_with(args)
206}
207
208/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A`.
209/// Works better with type inference than [`any::<A>()`].
210///
211/// With this version, you shouldn't need to specify any of the (many) type
212/// parameters explicitly. This can have a positive effect on type inference.
213/// However, if you want specify `A`, you should use [`any::<A>()`] instead.
214///
215/// For clarity, it is often a good idea to specify the type generated, and
216/// so using [`any::<A>()`] can be a good idea.
217///
218/// If you want to customize how the strategy is generated, use
219/// [`arbitrary_with(args)`] where `args` is of type
220/// `<A as Arbitrary>::Parameters`.
221///
222/// # Example
223///
224/// The function can be used as:
225///
226/// ```rust
227/// extern crate proptest;
228/// use proptest::arbitrary::{arbitrary, StrategyFor};
229///
230/// fn gen_vec_usize() -> StrategyFor<Vec<usize>> {
231///     arbitrary()
232/// }
233///
234/// # fn main() {}
235/// ```
236///
237/// [`arbitrary_with(args)`]: fn.arbitrary_with.html
238/// [`any::<A>()`]: fn.any.html
239/// [`Arbitrary`]: trait.Arbitrary.html
240/// [`Strategy`]: ../strategy/trait.Strategy.html
241#[must_use = "strategies do nothing unless used"]
242pub fn arbitrary<A, S>() -> S
243where
244    // The backlinking here cause an injection which helps type inference.
245    S: Strategy<Value = A>,
246    A: Arbitrary<Strategy = S>,
247{
248    A::arbitrary()
249}
250
251/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
252/// given configuration arguments passed in `args`.
253/// Works better with type inference than [`any_with::<A>(args)`].
254///
255/// With this version, you shouldn't need to specify any of the (many) type
256/// parameters explicitly. This can have a positive effect on type inference.
257/// However, if you want specify `A`, you should use
258/// [`any_with::<A>(args)`] instead.
259///
260/// For clarity, it is often a good idea to specify the type generated, and
261/// so using [`any_with::<A>(args)`] can be a good idea.
262///
263/// If you don't want to specify any arguments and instead use the default
264/// behavior, you should use [`arbitrary()`].
265///
266/// # Example
267///
268/// The function can be used as:
269///
270/// ```rust
271/// extern crate proptest;
272/// use proptest::arbitrary::{arbitrary_with, StrategyFor};
273/// use proptest::collection::size_range;
274///
275/// fn gen_vec_10_u32() -> StrategyFor<Vec<u32>> {
276///     arbitrary_with(size_range(10).lift())
277/// }
278///
279/// # fn main() {}
280/// ```
281///
282/// [`any_with::<A>(args)`]: fn.any_with.html
283/// [`arbitrary()`]: fn.arbitrary.html
284/// [`Arbitrary`]: trait.Arbitrary.html
285/// [`Strategy`]: ../strategy/trait.Strategy.html
286#[must_use = "strategies do nothing unless used"]
287pub fn arbitrary_with<A, S, P>(args: P) -> S
288where
289    P: Default,
290    // The backlinking here cause an injection which helps type inference.
291    S: Strategy<Value = A>,
292    A: Arbitrary<Strategy = S, Parameters = P>,
293{
294    A::arbitrary_with(args)
295}