// Regression test for #53789. // // check-pass use std::cmp::Ord; use std::collections::BTreeMap; use std::ops::Range; macro_rules! valuetree { () => { type ValueTree = ::Value; }; } macro_rules! product_unpack { ($factor: pat) => { ($factor,) }; ($($factor: pat),*) => { ( $( $factor ),* ) }; ($($factor: pat),*,) => { ( $( $factor ),* ) }; } macro_rules! product_type { ($factor: ty) => { ($factor,) }; ($($factor: ty),*) => { ( $( $factor, )* ) }; ($($factor: ty),*,) => { ( $( $factor, )* ) }; } macro_rules! default { ($type: ty, $val: expr) => { impl Default for $type { fn default() -> Self { $val.into() } } }; } // Pervasive internal sugar macro_rules! mapfn { ($(#[$meta:meta])* [$($vis:tt)*] fn $name:ident[$($gen:tt)*]($parm:ident: $input:ty) -> $output:ty { $($body:tt)* }) => { $(#[$meta])* #[derive(Clone, Copy)] $($vis)* struct $name; impl $($gen)* statics::MapFn<$input> for $name { type Output = $output; } } } macro_rules! opaque_strategy_wrapper { ($(#[$smeta:meta])* pub struct $stratname:ident [$($sgen:tt)*][$($swhere:tt)*] ($innerstrat:ty) -> $stratvtty:ty; $(#[$vmeta:meta])* pub struct $vtname:ident [$($vgen:tt)*][$($vwhere:tt)*] ($innervt:ty) -> $actualty:ty; ) => { $(#[$smeta])* struct $stratname $($sgen)* (std::marker::PhantomData<(K, V)>) $($swhere)*; $(#[$vmeta])* struct $vtname $($vgen)* ($innervt) $($vwhere)*; impl $($sgen)* Strategy for $stratname $($sgen)* $($swhere)* { type Value = $stratvtty; } impl $($vgen)* ValueTree for $vtname $($vgen)* $($vwhere)* { type Value = $actualty; } } } trait ValueTree { type Value; } trait Strategy { type Value: ValueTree; } #[derive(Clone)] struct VecStrategy { element: T, size: Range, } fn vec(element: T, size: Range) -> VecStrategy { VecStrategy { element: element, size: size } } type ValueFor = <::Value as ValueTree>::Value; trait Arbitrary<'a>: Sized { fn arbitrary_with(args: Self::Parameters) -> Self::Strategy; type Parameters: Default; type Strategy: Strategy; type ValueTree: ValueTree; } type StrategyFor = StrategyType<'static, A>; type StrategyType<'a, A> = >::Strategy; //#[derive(Clone, PartialEq, Eq, Hash, Debug, From, Into)] struct SizeBounds(Range); default!(SizeBounds, 0..100); impl From> for SizeBounds { fn from(high: Range) -> Self { unimplemented!() } } impl From for Range { fn from(high: SizeBounds) -> Self { unimplemented!() } } fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters) -> StrategyType<'a, A> { unimplemented!() } impl Strategy for (K, V) where ::Value: Ord, { type Value = TupleValueTree<(K, V)>; } impl ValueTree for TupleValueTree<(K, V)> where ::Value: Ord, { type Value = BTreeMapValueTree; } #[derive(Clone)] struct VecValueTree { elements: Vec, } #[derive(Clone, Copy)] struct TupleValueTree { tree: T, } opaque_strategy_wrapper! { #[derive(Clone)] pub struct BTreeMapStrategy[] [where K : Strategy, V : Strategy, ValueFor : Ord]( statics::Filter, VecToBTreeMap>, MinSize>) -> BTreeMapValueTree; #[derive(Clone)] pub struct BTreeMapValueTree[] [where K : ValueTree, V : ValueTree, K::Value : Ord]( statics::Filter>, VecToBTreeMap>, MinSize>) -> BTreeMap; } type RangedParams2 = product_type![SizeBounds, A, B]; impl<'a, A, B> Arbitrary<'a> for BTreeMap where A: Arbitrary<'static> + Ord, B: Arbitrary<'static>, StrategyFor: 'static, StrategyFor: 'static, { valuetree!(); type Parameters = RangedParams2; type Strategy = BTreeMapStrategy; fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { let product_unpack![range, a, b] = args; btree_map(any_with::(a), any_with::(b), range.into()) } } #[derive(Clone, Copy)] struct MinSize(usize); mapfn! { [] fn VecToBTreeMap[] (vec: Vec<(K, V)>) -> BTreeMap { vec.into_iter().collect() } } fn btree_map( key: K, value: V, size: Range, ) -> BTreeMapStrategy where ValueFor: Ord, { unimplemented!() } mod statics { pub(super) trait MapFn { type Output; } #[derive(Clone)] pub struct Filter { source: S, fun: F, } impl Filter { pub fn new(source: S, whence: String, filter: F) -> Self { unimplemented!() } } #[derive(Clone)] pub struct Map { source: S, fun: F, } impl Map { pub fn new(source: S, fun: F) -> Self { unimplemented!() } } } fn main() {}