summaryrefslogtreecommitdiffstats
path: root/vendor/proptest/src/arbitrary/functor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/proptest/src/arbitrary/functor.rs')
-rw-r--r--vendor/proptest/src/arbitrary/functor.rs220
1 files changed, 220 insertions, 0 deletions
diff --git a/vendor/proptest/src/arbitrary/functor.rs b/vendor/proptest/src/arbitrary/functor.rs
new file mode 100644
index 000000000..153ce9949
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/functor.rs
@@ -0,0 +1,220 @@
+//-
+// Copyright 2017, 2018 The proptest developers
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Provides higher order `Arbitrary` traits.
+//! This is mainly for use by `proptest_derive`.
+//!
+//! ## Stability note
+//!
+//! This trait is mainly defined for `proptest_derive` to simplify the
+//! mechanics of deriving recursive types. If you have custom containers
+//! and want to support recursive for those, it is a good idea to implement
+//! this trait.
+//!
+//! There are clearer and terser ways that work better with
+//! inference such as using `proptest::collection::vec(..)`
+//! to achieve the same result.
+//!
+//! For these reasons, the traits here are deliberately
+//! not exported in a convenient way.
+
+use crate::std_facade::fmt;
+
+use crate::strategy::{BoxedStrategy, Strategy};
+
+/// `ArbitraryF1` lets you lift a [`Strategy`] to unary
+/// type constructors such as `Box`, `Vec`, and `Option`.
+///
+/// The trait corresponds to
+/// [Haskell QuickCheck's `Arbitrary1` type class][HaskellQC].
+///
+/// [HaskellQC]:
+/// https://hackage.haskell.org/package/QuickCheck-2.10.1/docs/Test-QuickCheck-Arbitrary.html#t:Arbitrary1
+///
+/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+pub trait ArbitraryF1<A: fmt::Debug>: fmt::Debug + Sized {
+ //==========================================================================
+ // Implementation note #1
+ //==========================================================================
+ // It might be better to do this with generic associated types by
+ // having an associated type:
+ //
+ // `type Strategy<A>: Strategy<Value = Self>;`
+ //
+ // But with this setup we will likely loose the ability to add bounds
+ // such as `Hash + Eq` on `A` which is needed for `HashSet`. We might
+ // be able to regain this ability with a ConstraintKinds feature.
+ //
+ // This alternate formulation will likely work better with type inference.
+ //
+ //==========================================================================
+ // Implementation note #2
+ //==========================================================================
+ //
+ // Until `-> impl Trait` has been stabilized, `BoxedStrategy` must be
+ // used. This incurs an unfortunate performance penalty - but since
+ // we are dealing with testing, it is better to provide slowed down and
+ // somewhat less general functionality than no functionality at all.
+ // Implementations should just use `.boxed()` in the end.
+ //==========================================================================
+
+ /// The type of parameters that [`lift1_with`] accepts for
+ /// configuration of the lifted and generated [`Strategy`]. Parameters
+ /// must implement [`Default`].
+ ///
+ /// [`lift1_with`]:
+ /// trait.ArbitraryF1.html#tymethod.lift1_with
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ /// [`Default`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ type Parameters: Default;
+
+ /// Lifts a given [`Strategy`] to a new [`Strategy`] for the (presumably)
+ /// bigger type. This is useful for lifting a `Strategy` for `SomeType`
+ /// to a container such as `Vec<SomeType>`.
+ ///
+ /// Calling this for the type `X` is the equivalent of using
+ /// [`X::lift1_with(base, Default::default())`].
+ ///
+ /// This method is defined in the trait for optimization for the
+ /// default if you want to do that. It is a logic error to not
+ /// preserve the semantics when overriding.
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`X::lift1_with(base, Default::default())`]:
+ /// trait.ArbitraryF1.html#tymethod.lift1_with
+ fn lift1<AS>(base: AS) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ {
+ Self::lift1_with(base, Self::Parameters::default())
+ }
+
+ /// Lifts a given [`Strategy`] to a new [`Strategy`] for the (presumably)
+ /// bigger type. This is useful for lifting a `Strategy` for `SomeType`
+ /// to a container such as `Vec` of `SomeType`. The composite strategy is
+ /// passed the arguments given in `args`.
+ ///
+ /// If you wish to use the [`default()`] arguments,
+ /// use [`lift1`] instead.
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`lift1`]: trait.ArbitraryF1.html#method.lift1
+ ///
+ /// [`default()`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ fn lift1_with<AS>(base: AS, args: Self::Parameters) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static;
+}
+
+/// `ArbitraryF2` lets you lift [`Strategy`] to binary
+/// type constructors such as `Result`, `HashMap`.
+///
+/// The trait corresponds to
+/// [Haskell QuickCheck's `Arbitrary2` type class][HaskellQC].
+///
+/// [HaskellQC]:
+/// https://hackage.haskell.org/package/QuickCheck-2.10.1/docs/Test-QuickCheck-Arbitrary.html#t:Arbitrary2
+///
+/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+pub trait ArbitraryF2<A: fmt::Debug, B: fmt::Debug>:
+ fmt::Debug + Sized
+{
+ /// The type of parameters that [`lift2_with`] accepts for
+ /// configuration of the lifted and generated [`Strategy`]. Parameters
+ /// must implement [`Default`].
+ ///
+ /// [`lift2_with`]: trait.ArbitraryF2.html#tymethod.lift2_with
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`Default`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ type Parameters: Default;
+
+ /// Lifts two given strategies to a new [`Strategy`] for the (presumably)
+ /// bigger type. This is useful for lifting a `Strategy` for `Type1`
+ /// and one for `Type2` to a container such as `HashMap<Type1, Type2>`.
+ ///
+ /// Calling this for the type `X` is the equivalent of using
+ /// [`X::lift2_with(base, Default::default())`].
+ ///
+ /// This method is defined in the trait for optimization for the
+ /// default if you want to do that. It is a logic error to not
+ /// preserve the semantics when overriding.
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`X::lift2_with(base, Default::default())`]:
+ /// trait.Arbitrary.html#tymethod.lift2_with
+ fn lift2<AS, BS>(fst: AS, snd: BS) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ Self::lift2_with(fst, snd, Self::Parameters::default())
+ }
+
+ /// Lifts two given strategies to a new [`Strategy`] for the (presumably)
+ /// bigger type. This is useful for lifting a `Strategy` for `Type1`
+ /// and one for `Type2` to a container such as `HashMap<Type1, Type2>`.
+ /// The composite strategy is passed the arguments given in `args`.
+ ///
+ /// If you wish to use the [`default()`] arguments,
+ /// use [`lift2`] instead.
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`lift2`]: trait.ArbitraryF2.html#method.lift2
+ ///
+ /// [`default()`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static;
+}
+
+macro_rules! lift1 {
+ ([$($bounds : tt)*] $typ: ty, $params: ty;
+ $base: ident, $args: ident => $logic: expr) => {
+ impl<A: ::core::fmt::Debug + $($bounds)*>
+ $crate::arbitrary::functor::ArbitraryF1<A>
+ for $typ {
+ type Parameters = $params;
+
+ fn lift1_with<S>($base: S, $args: Self::Parameters)
+ -> $crate::strategy::BoxedStrategy<Self>
+ where
+ S: $crate::strategy::Strategy<Value = A> + 'static
+ {
+ $crate::strategy::Strategy::boxed($logic)
+ }
+ }
+ };
+ ([$($bounds : tt)*] $typ: ty; $base: ident => $logic: expr) => {
+ lift1!([$($bounds)*] $typ, (); $base, _args => $logic);
+ };
+ ([$($bounds : tt)*] $typ: ty; $mapper: expr) => {
+ lift1!(['static + $($bounds)*] $typ; base =>
+ $crate::strategy::Strategy::prop_map(base, $mapper));
+ };
+ ([$($bounds : tt)*] $typ: ty) => {
+ lift1!(['static + $($bounds)*] $typ; base =>
+ $crate::strategy::Strategy::prop_map_into(base));
+ };
+}