funcmap/lib.rs
1//! [](https://github.com/matthias-stemmler/funcmap)
2//! [](https://crates.io/crates/funcmap)
3//! [](https://docs.rs/funcmap/latest/funcmap/)
4//! [](https://github.com/matthias-stemmler/funcmap/blob/main/LICENSE-APACHE)
5//! [](https://blog.rust-lang.org/releases/1.82.0)
6//!
7//! Derivable functorial mappings for Rust
8//!
9//! This crate provides the [`FuncMap`] trait (and its fallible version
10//! [`TryFuncMap`]) that can be automatically derived for a type that is generic
11//! over a type parameter. It provides a method that applies a given closure to
12//! all (potentially nested) occurrences of the type parameter within the type,
13//! removing the need to write verbose mapping code.
14//!
15//! Concretely, given a generic type `Foo<T>` and an `FnMut(A) -> B` closure,
16//! it can turn any value of type `Foo<A>` into a value of type `Foo<B>`. This
17//! is called a *functorial mapping* following the *functor* design pattern of
18//! functional programming.
19//!
20//! # Basic Usage
21//!
22//! Suppose you have a type that is generic over some type parameter `T` and
23//! contains a `T` in various places:
24//! ```
25//! struct Foo<T> {
26//! value: T,
27//! more_values: Vec<T>,
28//! }
29//! ```
30//!
31//! Now suppose you want to turn a `Foo<i32>` into a `Foo<String>` by converting
32//! each [`i32`] contained in the type into a [`String`] by applying
33//! [`to_string`](ToString::to_string). You can do this by deriving the
34//! [`FuncMap`] trait provided by this crate and then invoking its
35//! [`func_map`](FuncMap::func_map) method like this:
36//! ```
37//! # use funcmap::FuncMap;
38//! #[derive(FuncMap)]
39//! struct Foo<T> {
40//! value: T,
41//! more_values: Vec<T>,
42//! }
43//!
44//! let foo = Foo {
45//! value: 1,
46//! more_values: vec![2, 3, 4],
47//! };
48//!
49//! let bar = foo.func_map(|v| v.to_string());
50//!
51//! assert_eq!(bar.value, "1");
52//! assert_eq!(bar.more_values, vec!["2", "3", "4"]);
53//! ```
54//!
55//! The expression `foo.func_map(|v| v.to_string())` is equivalent to this:
56//! ```
57//! # use funcmap::FuncMap;
58//! # #[derive(FuncMap, Clone, Debug, PartialEq)]
59//! # struct Foo<T> {
60//! # value: T,
61//! # more_values: Vec<T>,
62//! # }
63//! #
64//! # let foo = Foo {
65//! # value: 1,
66//! # more_values: vec![2, 3, 4],
67//! # };
68//! #
69//! # let foo_orig = foo.clone();
70//! #
71//! # let bar =
72//! Foo {
73//! value: foo.value.to_string(),
74//! more_values: foo.more_values.into_iter().map(|v| v.to_string()).collect()
75//! }
76//! #
77//! # ;
78//! #
79//! # assert_eq!(foo_orig.func_map(|v| v.to_string()), bar);
80//! ```
81//!
82//! This way, you avoid writing boilerplate mapping code, especially in cases
83//! where your type contains many and/or deeply nested occurrences of `T`.
84//!
85//! This works for both structs and enums and many ways of nesting `T` within
86//! your type such as arrays, tuples and many types from the standard library as
87//! well as your own types as long as they implement [`FuncMap`] themselves.
88//!
89//! Note that the purpose of the `funcmap` crate is just to provide utility
90//! functionality, so
91//! - you shouldn't depend on any of the items it exports in your public API,
92//! - it shouldn't be necessary to use bounds on the traits it exports anywhere
93//! except in generic implementations of those same traits.
94//!
95//! For a more detailed explanation and more features, see the following
96//! sections. Everything stated about [`FuncMap`] applies to [`TryFuncMap`]
97//! as well unless mentioned otherwise.
98//!
99//! For larger examples, see the `examples` folder in the crate repository.
100//!
101//! # How It Works
102//!
103//! The [`FuncMap`] trait has two required parameters (and one optional
104//! parameter, see below) that refer to the source and target type,
105//! respectively, of the closures to be used as mapping functions. The
106//! associated type [`Output`](FuncMap::Output) defines the overall output type
107//! of the mapping.
108//!
109//! Concretely, if you derive [`FuncMap`] for a type `Foo<T>`, then
110//! ```
111//! # use funcmap::FuncMap;
112//! #
113//! # #[derive(FuncMap)]
114//! # struct Foo<T>(T);
115//! #
116//! # enum A {}
117//! # enum B {}
118//! #
119//! # fn test() where
120//! Foo<A>: FuncMap<A, B, Output = Foo<B>>
121//! # {}
122//! ```
123//! holds for any two types `A` and `B`. The choice of `A` and `B` is only
124//! restricted by any trait bounds on `T` in the definition of `Foo<T>` and
125//! [`FuncMap`] and [`Sized`] trait bounds needed for the mapping of inner
126//! types, see below.
127//!
128//! The [`FuncMap`] derive macro supports both structs and enums. For structs,
129//! both tuple structs and structs with named fields are supported. When mapping
130//! an enum, the variant stays the same while the variant's fields are mapped
131//! just like the fields of a struct.
132//!
133//! Suppose you derive [`FuncMap`] for a type that is generic over `T` and then
134//! apply [`func_map`](FuncMap::func_map) to a value of that type, providing an
135//! `FnMut(A) -> B` closure:
136//! ```
137//! # use funcmap::FuncMap;
138//! #[derive(FuncMap)]
139//! struct Foo<T> {
140//! // ...
141//! # _value: T,
142//! }
143//!
144//! let foo = Foo {
145//! // ...
146//! # _value: ()
147//! };
148//!
149//! let bar = foo.func_map(|v| { /* ... */ });
150//! ```
151//!
152//! First of all, any field of `Foo<T>` whose type doesn't depend on `T` is left
153//! untouched.
154//!
155//! For any field whose type depends on `T`, the following types are supported:
156//! * arrays: `[T0; N]`, where `T0` is a type depending on `T`
157//! * tuples of arbitrary length: `(T0, ..., Tn)` where at least one of the `Ti`
158//! depends on `T`
159//! * named generic types: `Bar<T0, ..., Tn>` where at least one of the `Ti`
160//! depends on `T`
161//!
162//! In the case of a named generic type, the derived implementation of
163//! [`FuncMap`] for `Foo<T>` carries the appropriate trait bounds to allow for
164//! recursive application of [`func_map`](FuncMap::func_map) on
165//! `Bar<T0, ..., Tn>`. In order to fulfill these trait bounds,
166//! `Bar<T0, ..., Tn>` must satisfy one of these conditions:
167//! * It is a type from the standard library for which this crate provides an
168//! implementation of [`FuncMap`], such as [`Vec<T>`].
169//! * It is a type defined in your crate for which [`FuncMap`] is derived.
170//! * It is a type defined in your crate for which you implement [`FuncMap`]
171//! manually.
172//!
173//! Other types depending on `T` such as references (e.g. `&'a T`) or function
174//! pointers (e.g. `fn() -> T`) are not supported. This doesn't mean that `T`
175//! itself cannot be a reference type (it can), but just that it cannot occur
176//! behind a reference within `Foo<T>`.
177//!
178//! You can have a look at the code generated by the [`FuncMap`] derive macro
179//! by using [`cargo-expand`](https://github.com/dtolnay/cargo-expand).
180//!
181//! ## Caveats
182//!
183//! ### [`FuncMap`] Trait Bounds
184//!
185//! When deriving [`FuncMap`] for a type `Foo<T>` that has a field of type
186//! `Bar<T>` where `Bar<T>` *doesn't* implement [`FuncMap`], the derive macro
187//! won't fail, nor will it just *assume* that `Bar<T>` implements [`FuncMap`],
188//! which would cause a compile error within the derived implementation.
189//!
190//! The reason is that the derive macro cannot know whether `Bar<T>` implements
191//! [`FuncMap`] and it needs to deal with the fact that `Bar<T>` could implement
192//! [`FuncMap`] for *some* types `T` while it doesn't implement it for others.
193//!
194//! So what it does instead is add an appropriate trait bound to the derived
195//! implementation that looks like this:
196//! ```
197//! # use funcmap::FuncMap;
198//! #
199//! # struct Foo<T>(Bar<T>);
200//! # struct Bar<T>(T);
201//! #
202//! impl<A, B> FuncMap<A, B> for Foo<A>
203//! where
204//! Bar<A>: FuncMap<A, B, Output = Bar<B>>
205//! {
206//! type Output = Foo<B>;
207//!
208//! // ...
209//! # fn func_map<F>(self, f: F) -> Self::Output
210//! # where
211//! # F: FnMut(A) -> B
212//! # {
213//! # Foo(self.0.func_map(f))
214//! # }
215//! }
216//! ```
217//! This trait bound on `Bar<A>` puts an implicit condition on `A` and `B`. More
218//! precisely, `Foo<A>` implements [`FuncMap<A, B>`] only for those `A` and `B`
219//! where `Bar<A>` also implements [`FuncMap<A, B>`]. If `Bar<T>` doesn't
220//! implement [`FuncMap`] *at all*, this condition is never satisfied. In this
221//! case, the derived implementation still compiles but doesn't add any
222//! functionality.
223//!
224//! **Note:** If your crate's public API contains types deriving [`FuncMap`],
225//! this creates a
226//! [semver hazard](https://doc.rust-lang.org/cargo/reference/semver.html)
227//! because a change to the type of a field (even a private one) may cause
228//! bounds to be added to implementations of [`FuncMap`] for the type, which is
229//! a breaking change.
230//!
231//! ### [`Sized`] Trait Bounds
232//!
233//! The trait [`FuncMap<A, B>`] puts [`Sized`] bounds on the type parameters `A`
234//! and `B` as well as any type `Foo<A>` it is implemented for and the
235//! corresponding output type `Foo<B>`.
236//!
237//! Derived implementations of [`FuncMap`] additionally require the types of all
238//! the fields of `Foo<A>` and `Foo<B>` to be [`Sized`]. In the case of a type
239//! depending on `A` (in `Foo<A>`) or `B` (in the output), this is implicit in
240//! the [`FuncMap`] trait bounds mentioned in the previous section. For types
241//! that don't depend on `A` or `B`, the [`FuncMap`] derive macro adds an
242//! explicit [`Sized`] bound to the derived implementation.
243//!
244//! This is again because a field could have a type `Bar<T>` that is generic
245//! over another type parameter `T` different from `A` and `B` and `Bar<T>`
246//! could be [`Sized`] for *some* `T` but not for others. So the implementation
247//! applies only to those types `T` where all the fields are [`Sized`].
248//!
249//! ### Types Implementing [`Drop`]
250//!
251//! Deriving [`FuncMap`] is only possible for types that do not implement
252//! [`Drop`] because the derived implementation for a type needs to move out of
253//! the fields of the type, which isn't possible for [`Drop`] types. Trying to
254//! derive [`FuncMap`] for types implementing [`Drop`] leads to a compile error.
255//! (Strictly speaking, it would technically be possible if all the fields were
256//! [`Copy`], but in this case it would very likely make no sense anyway for the
257//! reasons described
258//! [here](https://doc.rust-lang.org/std/marker/trait.Copy.html#when-cant-my-type-be-copy),
259//! so it is still disallowed.)
260//!
261//! However, if a type `Foo<T>` implements [`Drop`], you can still implement
262//! [`FuncMap`] for `Foo<T>` manually. For instance, in the case where all the
263//! fields of `Foo<T>` have types implementing [`Default`], you can move out of
264//! the fields using [`core::mem::take`] like this:
265//! ```
266//! use funcmap::FuncMap;
267//!
268//! // cannot `#[derive(FuncMap)]` because `Foo<T>: Drop`
269//! struct Foo<T> {
270//! value: T,
271//! }
272//!
273//! impl<T> Drop for Foo<T> {
274//! fn drop(&mut self) {
275//! // apply some cleanup logic
276//! }
277//! }
278//!
279//! impl<A, B> FuncMap<A, B> for Foo<A>
280//! where
281//! A: Default,
282//! {
283//! type Output = Foo<B>;
284//!
285//! fn func_map<F>(mut self, mut f: F) -> Self::Output
286//! where
287//! F: FnMut(A) -> B,
288//! {
289//! Foo {
290//! value: f(core::mem::take(&mut self.value)),
291//! }
292//! }
293//! }
294//! ```
295//! In case a field of `Foo<T>` has a type `Bar<T>` that doesn't implement
296//! [`Default`], it may be possible to replace it with `Option<Bar<T>>`, which
297//! implements [`Default`].
298//!
299//! ### Recursive Types
300//!
301//! The [`FuncMap`] derive macro doesn't support recursive types for two
302//! reasons:
303//! - an infinite recursion while evaluating
304//! [`FuncMap` trait bounds](#funcmap-trait-bounds)
305//! - an infinite recursion while determining closure types
306//!
307//! If you need to implement [`FuncMap`] for a recursive type, you can do it
308//! manually using closure trait objects like this:
309//! ```
310//! # use funcmap::FuncMap;
311//! #
312//! // example of a recursive type
313//! #[derive(Debug, PartialEq)]
314//! enum List<T> {
315//! Nil,
316//! Cons(T, Box<List<T>>),
317//! }
318//!
319//! impl<A, B> FuncMap<A, B> for List<A> {
320//! type Output = List<B>;
321//!
322//! fn func_map<F>(self, mut f: F) -> Self::Output
323//! where
324//! F: FnMut(A) -> B,
325//! {
326//! match self {
327//! List::Nil => List::Nil,
328//! List::Cons(head, boxed_tail) => List::Cons(
329//! f(head),
330//! boxed_tail.func_map(|tail| tail.func_map(&mut f as &mut dyn FnMut(_) -> _)),
331//! ),
332//! }
333//! }
334//! }
335//!
336//! let list = List::Cons(10, Box::new(List::Cons(20, Box::new(List::Nil))));
337//!
338//! assert_eq!(
339//! list.func_map(|v| v + 1),
340//! List::Cons(11, Box::new(List::Cons(21, Box::new(List::Nil))))
341//! );
342//! ```
343//!
344//! # Fallible Mappings
345//!
346//! The closure passed to the [`func_map`](FuncMap::func_map) method must not
347//! fail. If you have a closure that can fail, you can use the [`TryFuncMap`]
348//! trait and its method [`try_func_map`](TryFuncMap::try_func_map) instead.
349//! [`TryFuncMap`] can be derived in the same way and for the same types as
350//! [`FuncMap`].
351//!
352//! The [`try_func_map`](TryFuncMap::try_func_map) method takes a
353//! closure returning a [`Result<B, E>`] for some error type `E` and returns a
354//! result with the same error type `E`:
355//! ```
356//! use funcmap::TryFuncMap;
357//! use std::num::{IntErrorKind, ParseIntError};
358//!
359//! #[derive(Debug, TryFuncMap)]
360//! struct Foo<T> {
361//! value1: T,
362//! value2: T,
363//! value3: T,
364//! }
365//!
366//! let foo = Foo {
367//! value1: "42", // can be parsed as i32
368//! value2: "1a", // cannot be parsed as i32 -> IntErrorKind::InvalidDigit
369//! value3: "", // cannot be parsed as i32 -> IntErrorKind::Empty
370//! };
371//!
372//! let bar: Result<Foo<i32>, ParseIntError> = foo.try_func_map(|v| v.parse());
373//!
374//! assert!(bar.is_err());
375//! assert_eq!(*bar.unwrap_err().kind(), IntErrorKind::InvalidDigit);
376//! ```
377//!
378//! As you can see in the example, when there are multiple errors,
379//! [`try_func_map`](TryFuncMap::try_func_map) returns the first one according
380//! to the order of the fields in the definition of `Foo<T>`.
381//!
382//! # Multiple Type Parameters
383//!
384//! When a type is generic over multiple type parameters, then the [`FuncMap`]
385//! derive macro will by default generate separate implementations for mapping
386//! over each type parameter.
387//!
388//! This can create an ambiguity that is resolved by using the [`TypeParam`]
389//! marker type as a third parameter to [`FuncMap`] to specify which type
390//! parameter to map over.
391//!
392//! To see why this is necessary, consider a type `Foo<S, T>` with two type
393//! parameters. Then there are two ways of applying an `FnMut(A) -> B` closure
394//! to the type `Foo<A, A>`:
395//! - mapping over the type parameter `S`, producing a `Foo<B, A>`
396//! - mapping over the type parameter `T`, producing a `Foo<A, B>`
397//!
398//! Since both cannot be handled by a single implementation of `FuncMap<A, B>`
399//! for `Foo<A>`, the [`FuncMap`] trait has a third parameter `P` to distinguish
400//! between the two. This parameter is instantiated with the types
401//! [`TypeParam<0>`] and [`TypeParam<1>`], respectively, so that
402//! ```
403//! # use funcmap::{FuncMap, TypeParam};
404//! #
405//! # #[derive(FuncMap)]
406//! # struct Foo<S, T>(S, T);
407//! #
408//! # enum A {}
409//! # enum B {}
410//! #
411//! # fn test() where
412//! Foo<A, A>: FuncMap<A, B, TypeParam<0>, Output = Foo<B, A>>,
413//! Foo<A, A>: FuncMap<A, B, TypeParam<1>, Output = Foo<A, B>>
414//! # {}
415//! ```
416//! This distinction is done purely on the type system level, so
417//! [`TypeParam<const N: usize>`] is a pure marker type of which no values
418//! exist. The number `N` specifies the 0-based index of the type parameter to
419//! map over. If the type has any lifetime parameters, they are not counted, so
420//! even for `Foo<'a, S, T>`,
421//! - `TypeParam<0>` refers to `S`
422//! - `TypeParam<1>` refers to `T`
423//!
424//! Note that while lifetime parameters aren't counted, const generics are. The
425//! reason for this is that when the derive macro looks at arguments of nested
426//! types, it may not be able to distinguish const arguments from type arguments
427//! syntactically. So, for `Foo<'a, const N: usize, S, const M: usize, T>`,
428//! - `TypeParam<1>` refers to `S`
429//! - `TypeParam<3>` refers to `T`
430//!
431//! and `TypeParam<0>` and `TypeParam<2>` are not used at all.
432//!
433//! The `P` parameter of [`FuncMap`] defaults to `TypeParam<0>`, so it can be
434//! ignored completely in case there is only a single type parameter, at least
435//! if it's not preceded by a const generic.
436//!
437//! Note that when calling [`func_map`](FuncMap::func_map), the correct type
438//! for `P` can often be inferred:
439//! ```
440//! # use funcmap::FuncMap;
441//! # #[derive(Debug, PartialEq)]
442//! #[derive(FuncMap)]
443//! struct Foo<S, T> {
444//! s: S,
445//! t: T,
446//! }
447//!
448//! let foo = Foo { s: 42, t: "Hello" };
449//!
450//! // Here `P` is inferred as `TypeParam<1>`
451//! let bar = foo.func_map(ToString::to_string);
452//! #
453//! # assert_eq!(bar, Foo { s: 42, t: String::from("Hello") });
454//! ```
455//!
456//! When it cannot be inferred, it can be cumbersome to specify explicitly
457//! because it's the *trait* [`FuncMap`] that is generic over `P`, not its
458//! method [`func_map`](FuncMap::func_map). To mitigate this, the [`FuncMap`]
459//! trait has another method [`func_map_over`](FuncMap::func_map_over) that does
460//! exactly the same thing as [`func_map`](FuncMap::func_map) but allows you to
461//! specify the type parameter marker `P` explicitly:
462//! ```
463//! # use funcmap::{FuncMap, TypeParam};
464//! #
465//! # #[derive(Copy, Clone)]
466//! #[derive(FuncMap, Debug, PartialEq)]
467//! struct Foo<S, T> {
468//! s: S,
469//! t: T,
470//! }
471//!
472//! let foo = Foo { s: 42, t: 42 };
473//!
474//! let bar = foo.func_map_over::<TypeParam<1>, _>(|x| x + 1);
475//! // Equivalent to: FuncMap::<_, _, TypeParam<1>>::func_map(foo, |x| x + 1);
476//! // This would be ambiguous: let bar = foo.func_map(|x| x + 1);
477//!
478//! assert_eq!(bar, Foo { s: 42, t: 43 });
479//! # assert_eq!(
480//! # FuncMap::<_, _, TypeParam<1>>::func_map(foo, |x| x + 1),
481//! # Foo { s: 42, t: 43 }
482//! # );
483//! ```
484//!
485//! Note that you need to write `func_map_over::<TypeParam<1>, _>` rather than
486//! just `func_map_over::<TypeParam<1>>` because
487//! [`func_map_over`](FuncMap::func_map_over) has a second parameter that is the
488//! type of the given closure.
489//!
490//! To improve readability and make your code more robust to changes, it is
491//! recommended to define type aliases for the markers that convey the meaning
492//! of the corresponding types and abstract away their concrete indices:
493//! ```
494//! # use funcmap::{FuncMap, TypeParam};
495//! #
496//! type WidthParam = TypeParam<0>;
497//! type HeightParam = TypeParam<1>;
498//!
499//! #[derive(FuncMap, Debug, PartialEq)]
500//! struct Size<W, H> {
501//! width: W,
502//! height: H
503//! }
504//!
505//! let normal = Size { width: 100, height: 100 };
506//! let skewed = normal
507//! .func_map_over::<WidthParam, _>(|w| w * 2)
508//! .func_map_over::<HeightParam, _>(|h| h * 3);
509//!
510//! assert_eq!(skewed, Size { width: 200, height: 300 });
511//! ```
512//!
513//! By default, implementations for all type parameters are generated. You can
514//! restrict this to only a subset of the type parameters by configuration as
515//! described in the next section. This becomes necessary if any of the type
516//! parameters occur within the type in a way that's not supported by the
517//! [`FuncMap`] derive macro.
518//!
519//! ## Caveat: Type Aliases
520//!
521//! Suppose a type `Foo<T>` has a field whose type has multiple type parameters:
522//! ```
523//! # #[derive(funcmap::FuncMap)]
524//! # struct Bar<T, U, V>(T, U, V);
525//! #
526//! # #[derive(funcmap::FuncMap)]
527//! struct Foo<T> {
528//! value: Bar<T, i32, T>,
529//! }
530//! ```
531//!
532//! Then the derived implementation of [`FuncMap`] for `Foo<T>` delegates to the
533//! [`FuncMap`] implementation of `Bar<T, U, V>` using the marker types
534//! [`TypeParam<N>`], where `N` is the 0-based index of the respective type
535//! parameter of `Bar<T, U, V>`. In the example, `Bar<T, i32, T>` will be mapped
536//! using
537//! - [`TypeParam<0>`] to map over the first instance of `T`,
538//! - [`TypeParam<2>`] to map over the second instance of `T`.
539//!
540//! Now if `Bar<T, U, V>` happens to be an alias for a type where `T`, `U` and
541//! `V` appear at different positions within its list of type parameters, this
542//! will not work. For instance, if
543//! ```
544//! # struct Baz<T, U, V, W>(T, U, V, W);
545//! type Bar<T, U, V> = Baz<i32, V, U, T>;
546//! ```
547//!
548//! then a [`FuncMap`] implementation of the right-hand side will map over `T`,
549//! say, using [`TypeParam<3>`], not [`TypeParam<0>`].
550//!
551//! Consequently, when deriving [`FuncMap`] for a type whose definition uses
552//! type aliases, make sure to follow the
553//!
554//! **Rule:** Every type parameter of the alias (or at least the ones that are
555//! instantiated with a type parameter over which [`FuncMap`] is derived) must
556//! have the same index among the type parameters of the alias as within the
557//! type parameters of the type the alias stands for.
558//!
559//! Remember that lifetime parameters are not counted, so this is fine, for
560//! example:
561//! ```
562//! # struct Baz<'a, T>(&'a T);
563//! type Bar<T> = Baz<'static, T>;
564//! ```
565//!
566//! # Customizing Derive Behavior
567//!
568//! When deriving [`FuncMap`] or [`TryFuncMap`] for a type, you can change the
569//! default behavior of the derive macro through the optional `#[funcmap]`
570//! helper attribute. This attribute may only be applied to the type itself, not
571//! to its fields or variants:
572//! ```
573//! # use funcmap as my_funcmap;
574//! # use funcmap::{FuncMap, TryFuncMap};
575//! #[derive(FuncMap, TryFuncMap)]
576//! #[funcmap(crate = "my_funcmap", params(S, T))] // options are explained below
577//! struct Foo<S, T, U> {
578//! value1: S,
579//! value2: T,
580//! value3: U,
581//! }
582//! ```
583//!
584//! Options can also be put into separate `#[funcmap]` attributes, so the
585//! following is equivalent:
586//! ```
587//! # use funcmap as my_funcmap;
588//! # use funcmap::{FuncMap, TryFuncMap};
589//! #[derive(FuncMap, TryFuncMap)]
590//! #[funcmap(crate = "my_funcmap")]
591//! #[funcmap(params(S))]
592//! #[funcmap(params(T))]
593//! struct Foo<S, T, U> {
594//! value1: S,
595//! value2: T,
596//! value3: U,
597//! }
598//! ```
599//!
600//! Note that this way of customizing the derive macro doesn't distinguish
601//! between [`FuncMap`] and [`TryFuncMap`]. The options are always the same for
602//! both.
603//!
604//! The following options are available:
605//!
606//! ## `#[funcmap(crate = "...")`
607//!
608//! This defines the path to the `funcmap` crate instance to use when referring
609//! to `funcmap` APIs from generated implementations. This will only be needed
610//! in rare cases, e.g. when you rename `funcmap` in the `dependencies` section
611//! of your `Cargo.toml` or invoke a re-exported `funcmap` derive in a public
612//! macro.
613//!
614//! ## `#[funcmap(params(...))]`
615//!
616//! If a type has [multiple type parameters](#multiple-type-parameters), this
617//! defines for which of the type parameters an implementation should be
618//! generated by providing a comma-separated list of type parameters. If the
619//! `params` option is omitted, the default behavior is that implementations for
620//! *all* type parameters are generated.
621//!
622//! This is especially useful if you need to exclude a type parameter because it
623//! occurs within a type in a way unsuitable for deriving `FuncMap`:
624//! ```
625//! # use funcmap::FuncMap;
626//! #[derive(FuncMap)]
627//! #[funcmap(params(S, T))]
628//! struct Foo<'a, S, T, U> {
629//! value: S,
630//! more_values: Vec<T>,
631//! reference: &'a U,
632//! }
633//! ```
634//!
635//! Here, without the line `#[funcmap(params(S, T))]`, the [`FuncMap`] derive
636//! macro would try to generate implementations for all three type parameters
637//! `S`, `T` and `U`, and fail because `U` occurs within `Foo` behind a
638//! reference, which is not supported, see [How It Works](#how-it-works).
639//!
640//! The `params` option can also be used to decrease compile time when a
641//! `FuncMap` implementation for some type parameter is not needed.
642//!
643//! # Manually Implementing [`FuncMap`] and [`TryFuncMap`]
644//!
645//! Even though implementations of the traits in this crate are usually meant to
646//! be derived automatically, it can become necessary for you to implement the
647//! traits manually in some cases, for instance
648//! - when a type in your crate has a field depending on a type parameter in a
649//! way that isn't supported by the [`FuncMap`] and [`TryFuncMap`] derive
650//! macros, e.g. when you implement a low-level primitive such as your custom
651//! version of [`Vec<T>`],
652//! - when you need a [`FuncMap`] or [`TryFuncMap`] implementation for a type in
653//! a third-party crate that doesn't provide one.
654//!
655//! In the latter case, since you cannot implement nor derive the trait for a
656//! third-party type due to the orphan rule, you can provide your own wrapper
657//! around it (following the *newtype* pattern) and implement the trait manually
658//! for the wrapper type:
659//! ```
660//! # use funcmap::FuncMap;
661//! #
662//! // Pretend that this is an external crate, not a module
663//! mod third_party {
664//! # #[derive(Debug, PartialEq)]
665//! pub struct List<T> {
666//! // ...
667//! # pub value: Option<T>,
668//! }
669//!
670//! impl<A> List<A> {
671//! pub fn map<B>(self, f: impl FnMut(A) -> B) -> List<B> {
672//! // ...
673//! # List { value: self.value.map(f) }
674//! }
675//! }
676//! }
677//!
678//! // In your crate:
679//! # #[derive(Debug, PartialEq)]
680//! struct MyList<T>(third_party::List<T>);
681//!
682//! impl<A, B> FuncMap<A, B> for MyList<A> {
683//! type Output = MyList<B>;
684//!
685//! fn func_map<F>(self, f: F) -> Self::Output
686//! where
687//! F: FnMut(A) -> B,
688//! {
689//! MyList(self.0.map(f))
690//! }
691//! }
692//!
693//! // Now you can derive `FuncMap` for types containing a `MyList<T>`:
694//! # #[derive(Debug, PartialEq)]
695//! #[derive(FuncMap)]
696//! struct Foo<T> {
697//! list: MyList<T>,
698//! }
699//! #
700//! # let list = Foo {
701//! # list: MyList(third_party::List {
702//! # value: Some(1)
703//! # })
704//! # };
705//! #
706//! # assert_eq!(
707//! # list.func_map(|v| v.to_string()),
708//! # Foo {
709//! # list: MyList(third_party::List {
710//! # value: Some(String::from("1"))
711//! # })
712//! # }
713//! # );
714//! ```
715//!
716//! For details on the exact contract to uphold when writing manual
717//! implementations, see the API documentations of [`FuncMap`] and
718//! [`TryFuncMap`].
719//!
720//! Note that if you have already implemented [`TryFuncMap`] for a type, you can
721//! then always implement [`FuncMap`] like this:
722//! ```
723//! use funcmap::{FuncMap, TryFuncMap};
724//!
725//! # #[derive(Debug, PartialEq)]
726//! struct Foo<T> {
727//! // ...
728//! # value: T,
729//! }
730//!
731//! impl<A, B> TryFuncMap<A, B> for Foo<A> {
732//! type Output = Foo<B>;
733//!
734//! // ...
735//! #
736//! # fn try_func_map<E, F>(self, mut f: F) -> Result<Self::Output, E>
737//! # where
738//! # F: FnMut(A) -> Result<B, E>,
739//! # {
740//! # Ok(Foo {
741//! # value: f(self.value)?
742//! # })
743//! # }
744//! }
745//!
746//! impl<A, B> FuncMap<A, B> for Foo<A> {
747//! type Output = Foo<B>;
748//!
749//! fn func_map<F>(self, mut f: F) -> Self::Output
750//! where
751//! F: FnMut(A) -> B,
752//! {
753//! self.try_func_map::<core::convert::Infallible, _>(|x| Ok(f(x))).unwrap()
754//! }
755//! }
756//! #
757//! # let foo = Foo { value: 42 };
758//! # assert_eq!(foo.func_map(|x| x + 1), Foo { value: 43 });
759//! ```
760//!
761//! # `no_std` Support
762//!
763//! `funcmap` has a Cargo feature named `std` that is enabled by default and
764//! provides implementations of [`FuncMap`] and [`TryFuncMap`] for many types
765//! from the [standard library](`std`). In order to use `funcmap` in a `no_std`
766//! context, modify your dependency on `funcmap` in `Cargo.toml` to opt out of
767//! default features:
768//! ```toml
769//! [dependencies]
770//! funcmap = { version = "...", default-features = false }
771//! ```
772//!
773//! In this case, only implementations for types in the [`core`] library are
774//! provided. Note that this excludes implementations for all standard library
775//! types that involve heap memory allocation, such as [`Box<T>`] or [`Vec<T>`].
776//! In order to opt back in to these implementations, you can enable the `alloc`
777//! Cargo feature:
778//! ```toml
779//! [dependencies]
780//! funcmap = { version = "...", default-features = false, features = ["alloc"] }
781//! ```
782//!
783//! This will provide implementations for many types in the [`alloc`] library.
784//!
785//! # Functional Programming Background
786//!
787//! The idea of `funcmap` is based on the *functor* design pattern from
788//! functional programming, which in turn is inspired from the notion of a
789//! functor in category theory.
790//!
791//! Basically, `F` is a functor if
792//! 1. it associates each type `T` with a new type `F(T)`
793//! 2. it associates each function
794//! ```plain
795//! f: A -> B
796//! ```
797//! with a function
798//! ```plain
799//! F(f): F(A) -> F(B)
800//! ```
801//! such that the following *functor laws* are satisfied:
802//! - `F(id) = id` where `id` is the identity function on `A`, respectively
803//! `F(A)`
804//! - `F(g . f) = F(g) . F(f)` for any two functions `f: A -> B` and
805//! `g: B -> C`, where `g . f` denotes function composition
806//!
807//! In languages with higher-kinded types such as Haskell, this property of
808//! being a functor is expressed as a *type class* (similar to a trait) called
809//! [Functor](https://wiki.haskell.org/Functor) that the higher-kinded type `F`
810//! is an instance of.
811//!
812//! In Rust, property 1. is satisfied for every type `Foo<T>` that is generic
813//! over a type parameter `T` because it associates each type `T` with a new
814//! type `Foo<T>`, at least for those types `T` that satisfy all trait bounds
815//! that `Foo<T>` imposes on `T`.
816//!
817//! Property 2. is where the [`FuncMap`] trait comes into play. As there are no
818//! higher-kinded types in Rust as of now, it cannot be expressed by `Foo`
819//! itself implementing a trait, because while `Foo<T>` is a type for every `T`,
820//! `Foo` itself (without the `<T>`) isn't something one can reason about within
821//! the Rust type system. However, one can say that `Foo` is a functor if and
822//! only if
823//! ```
824//! # use funcmap::FuncMap;
825//! #
826//! # #[derive(FuncMap)]
827//! # struct Foo<T>(T);
828//! #
829//! # enum A {}
830//! # enum B {}
831//! #
832//! # fn test() where
833//! Foo<A>: FuncMap<A, B, Output = Foo<B>>
834//! # {}
835//! ```
836//! holds for all types `A` and `B` for which `Foo<T>` exists. The function
837//! `Foo<A> -> Foo<B>` associated with a function `f: A -> B` (in Rust:
838//! `f: impl FnMut(A) -> B`) by property 2. is then provided by the
839//! [`func_map`](FuncMap::func_map) method as the function
840//! ```
841//! # use funcmap::FuncMap;
842//! #
843//! # #[derive(FuncMap)]
844//! # struct Foo<T>(T);
845//! #
846//! # enum A {}
847//! # enum B {}
848//! #
849//! # fn test(f: impl FnMut(A) -> B) -> impl FnOnce(Foo<A>) -> Foo<B> {
850//! |x: Foo<A>| x.func_map(f)
851//! # }
852//! ```
853//! So deriving the [`FuncMap`] trait for `Foo<T>` can be viewed as deriving
854//! Property 2. from Property 1. or equivalently, deriving a (hypothetical)
855//! *Functor* trait for the (hypothetical) higher-kinded type `Foo`.
856//!
857//! In fact, the name of the [`func_map`](FuncMap::func_map) method is inspired
858//! from the
859//! [`fmap`](https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-Functor.html#v:fmap)
860//! function of Haskell's `Functor` type class.
861//!
862//! # Edition support
863//!
864//! This crate supports all Rust editions. There is one caveat, however: When deriving [`FuncMap`] for a type in edition
865//! 2015 code that contains an identifier that is a keyword from edition 2018 onwards, i.e. one of `async`, `await`,
866//! `dyn` and `try`, the identifier has to be written as a raw identifier in the type definition:
867//! ```edition2015
868//! # use funcmap::FuncMap;
869//! #
870//! #[derive(FuncMap)]
871//! struct Foo<T> {
872//! r#async: T, // this would fail with `async` instead of `r#async`
873//! }
874//!
875//! let foo = Foo {
876//! async: 1,
877//! };
878//!
879//! let bar = foo.func_map(|v| v.to_string());
880//!
881//! assert_eq!(bar.async, "1");
882//! ```
883//!
884//! # Minimum Supported Rust Version (MSRV) Policy
885//!
886//! The current MSRV of this crate is `1.82`.
887//!
888//! Increasing the MSRV of this crate is *not* considered a breaking change.
889//! However, in such cases there will be at least a minor version bump.
890//!
891//! Each version of this crate will support at least the four latest stable Rust
892//! versions at the time it is published.
893
894#![cfg_attr(not(feature = "std"), no_std)]
895#![deny(missing_copy_implementations)]
896#![deny(missing_debug_implementations)]
897#![deny(missing_docs)]
898#![deny(unreachable_pub)]
899#![deny(unused_crate_dependencies)]
900#![deny(unused_extern_crates)]
901#![deny(unused_lifetimes)]
902#![deny(unused_qualifications)]
903#![deny(clippy::all)]
904#![deny(clippy::pedantic)]
905#![deny(clippy::cargo_common_metadata)]
906#![deny(clippy::multiple_crate_versions)]
907#![deny(clippy::rest_pat_in_fully_bound_structs)]
908#![deny(clippy::use_debug)]
909#![allow(clippy::module_name_repetitions)]
910#![deny(rustdoc::broken_intra_doc_links)]
911#![deny(rustdoc::private_intra_doc_links)]
912#![deny(rustdoc::invalid_codeblock_attributes)]
913#![deny(rustdoc::invalid_rust_codeblocks)]
914#![deny(rustdoc::bare_urls)]
915
916mod array;
917mod impls_core;
918
919#[cfg(doc)]
920extern crate alloc;
921
922#[cfg(feature = "alloc")]
923mod impls_alloc;
924
925#[cfg(feature = "std")]
926mod impls_std;
927
928use core::fmt::{self, Display, Formatter};
929
930/// Functorial mapping of a generic type over any of its type parameters
931///
932/// # Deriving [`FuncMap`]
933///
934/// In most cases, implementations of this trait can and should be derived
935/// automatically:
936/// ```
937/// # use funcmap::FuncMap;
938/// #
939/// #[derive(FuncMap)]
940/// struct Foo<T> {
941/// // ...
942/// # value: T,
943/// }
944/// ```
945///
946/// See the [crate-level documentation](crate) for details.
947///
948/// # Manually Implementing [`FuncMap`]
949///
950/// If you need to implement [`FuncMap`] manually, make sure to uphold the
951/// following contract:
952///
953/// Let `Foo` be a type that is generic over the type or const parameters
954/// `T0, ..., Tn`.
955///
956/// If `Foo` implements [`FuncMap<A, B, TypeParam<N>>`], then
957/// - `N` must be in the range `0..=n`.
958/// - The parameter of `Foo` at index `N` (not counting lifetime parameters)
959/// must be `A`. In particular, it must be a type parameter, not a const
960/// generic.
961/// - `Foo::Output` must be `Foo` with the parameter at index `N` replaced with
962/// `B`.
963///
964/// Furthermore:
965/// - [`func_map_over`](Self::func_map_over) must behave in exactly the same way
966/// as [`func_map`](Self::func_map). This is the default behavior and must not
967/// be changed.
968/// - When implementing [`FuncMap`] for different marker types [`TypeParam<N>`]
969/// and [`TypeParam<M>`], the result of mapping over both type parameters in
970/// sequence must not depend on the order of the two mappings, i.e.
971/// ```
972/// # use funcmap::{FuncMap, TypeParam};
973/// #
974/// # #[derive(FuncMap, Copy, Clone, Debug, PartialEq)]
975/// # struct Foo<T, U>(T, U);
976/// #
977/// # const N: usize = 0;
978/// # const M: usize = 1;
979/// #
980/// # let foo = Foo(42, 43);
981/// # let f = |x| x + 1;
982/// # let g = |x| x * 2;
983/// #
984/// # assert!(
985/// foo.func_map_over::<TypeParam<N>, _>(f)
986/// .func_map_over::<TypeParam<M>, _>(g)
987///
988/// // must be equivalent to
989/// # ==
990///
991/// foo.func_map_over::<TypeParam<M>, _>(g)
992/// .func_map_over::<TypeParam<N>, _>(f)
993/// # );
994/// ```
995pub trait FuncMap<A, B, P = TypeParam<0>>: Sized
996where
997 P: FuncMarker<P>,
998{
999 /// The output type of the functorial mapping
1000 ///
1001 /// This is `Self` with the parameter at index `N` replaced with `B`, where
1002 /// `N` is such that `P` is `TypeParam<N>`.
1003 ///
1004 /// In the simplest case of a type with just a single type parameter, if
1005 /// `Self` is `Foo<A>`, then this is `Foo<B>`.
1006 type Output;
1007
1008 /// Applies the closure `f` to `self` in a functorial way
1009 fn func_map<F>(self, f: F) -> Self::Output
1010 where
1011 F: FnMut(A) -> B;
1012
1013 /// Applies the closure `f` to `self` in a functorial way, allowing explicit
1014 /// specification of the marker type `P`
1015 ///
1016 /// This is a convenience method that has the exact same functionality as
1017 /// [`func_map`](Self::func_map) but can be used to specify the marker type
1018 /// `P` in a convenient way in cases where it is ambiguous.
1019 ///
1020 /// So if you have
1021 /// ```
1022 /// # use funcmap::FuncMap;
1023 /// #
1024 /// #[derive(FuncMap, Debug, PartialEq)]
1025 /// struct Foo<S, T> {
1026 /// s: S,
1027 /// t: T,
1028 /// }
1029 ///
1030 /// let foo = Foo {
1031 /// s: 42,
1032 /// t: 42,
1033 /// };
1034 /// ```
1035 /// then instead of writing
1036 /// ```
1037 /// # use funcmap::{FuncMap, TypeParam};
1038 /// #
1039 /// # #[derive(FuncMap, Debug, PartialEq)]
1040 /// # struct Foo<S, T> {
1041 /// # s: S,
1042 /// # t: T,
1043 /// # }
1044 /// #
1045 /// # let foo = Foo {
1046 /// # s: 42,
1047 /// # t: 42,
1048 /// # };
1049 /// #
1050 /// let bar = FuncMap::<_, _, TypeParam<1>>::func_map(foo, |v| v + 1);
1051 /// assert_eq!(bar, Foo { s: 42, t: 43 });
1052 /// ```
1053 ///
1054 /// you can more conveniently write
1055 ///
1056 /// ```
1057 /// # use funcmap::{FuncMap, TypeParam};
1058 /// #
1059 /// # #[derive(FuncMap, Debug, PartialEq)]
1060 /// # struct Foo<S, T> {
1061 /// # s: S,
1062 /// # t: T,
1063 /// # }
1064 /// #
1065 /// # let foo = Foo {
1066 /// # s: 42,
1067 /// # t: 42,
1068 /// # };
1069 /// #
1070 /// let bar = foo.func_map_over::<TypeParam<1>, _>(|v| v + 1);
1071 /// assert_eq!(bar, Foo { s: 42, t: 43 });
1072 /// ```
1073 ///
1074 /// This lets you chain method calls more easily as in
1075 /// ```
1076 /// # use funcmap::{FuncMap, TypeParam};
1077 /// #
1078 /// # #[derive(FuncMap, Debug, PartialEq)]
1079 /// # struct Foo<S, T> {
1080 /// # s: S,
1081 /// # t: T,
1082 /// # }
1083 /// #
1084 /// # let foo = Foo {
1085 /// # s: 42,
1086 /// # t: 42,
1087 /// # };
1088 /// #
1089 /// foo.func_map_over::<TypeParam<0>, _>(|v| v + 1)
1090 /// .func_map_over::<TypeParam<1>, _>(|v| v + 1)
1091 /// # ;
1092 /// ```
1093 ///
1094 /// Note that you still need to specify the inferred type `_` for the
1095 /// closure type `F`.
1096 fn func_map_over<Q, F>(self, f: F) -> Self::Output
1097 where
1098 F: FnMut(A) -> B,
1099 Q: FuncMarker<P>,
1100 {
1101 self.func_map(f)
1102 }
1103}
1104
1105/// Fallible functorial mapping of a generic type over any of its type
1106/// parameters
1107///
1108/// # Deriving [`TryFuncMap`]
1109///
1110/// In most cases, implementations of this trait can and should be derived
1111/// automatically:
1112/// ```
1113/// # use funcmap::TryFuncMap;
1114/// #
1115/// #[derive(TryFuncMap)]
1116/// struct Foo<T> {
1117/// // ...
1118/// # value: T,
1119/// }
1120/// ```
1121///
1122/// See the [crate-level documentation](crate) for details.
1123///
1124/// # Manually Implementing [`TryFuncMap`]
1125///
1126/// If you need to implement [`TryFuncMap`] manually, make sure to uphold the
1127/// following contract:
1128///
1129/// Let `Foo` be a type that is generic over the type or const parameters
1130/// `T0, ..., Tn`.
1131///
1132/// If `Foo` implements [`TryFuncMap<A, B, TypeParam<N>>`], then
1133/// - `N` must be in the range `0..=n`.
1134/// - The parameter of `Foo` at index `N` (not counting lifetime parameters)
1135/// must be `A`. In particular, it must be a type parameter, not a const
1136/// generic.
1137/// - `Foo::Output` must be `Foo` with the parameter at index `N` replaced with
1138/// `B`.
1139///
1140/// Furthermore:
1141/// - [`try_func_map_over`](Self::try_func_map_over) must behave in exactly the
1142/// same way as [`try_func_map`](Self::try_func_map). This is the default
1143/// behavior and must not be changed.
1144/// - If the closure provided to [`try_func_map`](Self::try_func_map) fails,
1145/// then the result must be the first error according to the order of the
1146/// fields in the definition of `Foo`:
1147/// ```
1148/// # use funcmap::TryFuncMap;
1149/// # use std::num::{IntErrorKind, ParseIntError};
1150/// #
1151/// #[derive(TryFuncMap, Copy, Clone, Debug, PartialEq)]
1152/// struct Foo<T> {
1153/// value1: T,
1154/// value2: T,
1155/// }
1156///
1157/// let foo = Foo {
1158/// value1: "1a",
1159/// value2: ""
1160/// };
1161///
1162/// let result: Result<Foo<i32>, ParseIntError> = foo.try_func_map(|v| v.parse());
1163///
1164/// assert!(result.is_err());
1165/// assert_eq!(*result.unwrap_err().kind(), IntErrorKind::InvalidDigit);
1166/// ```
1167/// - When implementing [`TryFuncMap`] for different marker types
1168/// [`TypeParam<N>`] and [`TypeParam<M>`], the result of mapping over both
1169/// type parameters in sequence must not depend on the order of the two
1170/// mappings, i.e.
1171/// ```
1172/// # use funcmap::{TryFuncMap, TypeParam};
1173/// #
1174/// # #[derive(TryFuncMap, Copy, Clone, Debug, PartialEq)]
1175/// # struct Foo<T, U>(T, U);
1176/// #
1177/// # const N: usize = 0;
1178/// # const M: usize = 1;
1179/// #
1180/// # let foo = Foo(42, 43);
1181/// # let f = |x| Ok::<_, ()>(x + 1);
1182/// # let g = |x| Ok::<_, ()>(x * 2);
1183/// #
1184/// # assert!(
1185/// foo.try_func_map_over::<TypeParam<N>, _, _>(f)
1186/// .and_then(|x| x.try_func_map_over::<TypeParam<M>, _, _>(g))
1187///
1188/// // must be equivalent to
1189/// # ==
1190///
1191/// foo.try_func_map_over::<TypeParam<M>, _, _>(g)
1192/// .and_then(|x| x.try_func_map_over::<TypeParam<N>, _, _>(f))
1193/// # );
1194/// ```
1195pub trait TryFuncMap<A, B, P = TypeParam<0>>: Sized
1196where
1197 P: FuncMarker<P>,
1198{
1199 /// The output type of the functorial mapping
1200 ///
1201 /// This is `Self` with the parameter at index `N` replaced with `B`, where
1202 /// `N` is such that `P` is `TypeParam<N>`.
1203 ///
1204 /// In the simplest case of a type with just a single type parameter, if
1205 /// `Self` is `Foo<A>`, then this is `Foo<B>`.
1206 type Output;
1207
1208 /// Tries to apply the closure `f` to `self` in a functorial way
1209 ///
1210 /// # Errors
1211 /// Fails if and only if `f` fails, returning the first error according to
1212 /// the order of the fields in the definition of `Self`
1213 fn try_func_map<E, F>(self, f: F) -> Result<Self::Output, E>
1214 where
1215 F: FnMut(A) -> Result<B, E>;
1216
1217 /// Tries to apply the closure `f` to `self` in a functorial way, allowing
1218 /// explicit specification of the marker type `P`
1219 ///
1220 /// This is a convenience method that has the exact same functionality as
1221 /// [`try_func_map`](Self::try_func_map) but can be used to specify the
1222 /// marker type `P` in a convenient way in cases where it is ambiguous.
1223 ///
1224 /// So if you have
1225 /// ```
1226 /// # use funcmap::TryFuncMap;
1227 /// #
1228 /// #[derive(TryFuncMap, Debug, PartialEq)]
1229 /// struct Foo<S, T> {
1230 /// s: S,
1231 /// t: T,
1232 /// }
1233 ///
1234 /// let foo = Foo {
1235 /// s: "42",
1236 /// t: "42",
1237 /// };
1238 /// ```
1239 /// then instead of writing
1240 /// ```
1241 /// # use funcmap::{TryFuncMap, TypeParam};
1242 /// #
1243 /// # #[derive(TryFuncMap, Debug, PartialEq)]
1244 /// # struct Foo<S, T> {
1245 /// # s: S,
1246 /// # t: T,
1247 /// # }
1248 /// #
1249 /// # let foo = Foo {
1250 /// # s: "42",
1251 /// # t: "42",
1252 /// # };
1253 /// #
1254 /// let bar = TryFuncMap::<_, _, TypeParam<1>>::try_func_map(foo, |v| v.parse::<i32>());
1255 /// assert_eq!(bar, Ok(Foo { s: "42", t: 42 }));
1256 /// ```
1257 ///
1258 /// you can more conveniently write
1259 ///
1260 /// ```
1261 /// # use funcmap::{TryFuncMap, TypeParam};
1262 /// #
1263 /// # #[derive(TryFuncMap, Debug, PartialEq)]
1264 /// # struct Foo<S, T> {
1265 /// # s: S,
1266 /// # t: T,
1267 /// # }
1268 /// #
1269 /// # let foo = Foo {
1270 /// # s: "42",
1271 /// # t: "42",
1272 /// # };
1273 /// #
1274 /// let bar = foo.try_func_map_over::<TypeParam<1>, _, _>(|v| v.parse::<i32>());
1275 /// assert_eq!(bar, Ok(Foo { s: "42", t: 42 }));
1276 /// ```
1277 ///
1278 /// This lets you chain method calls more easily as in
1279 /// ```
1280 /// # use funcmap::{TryFuncMap, TypeParam};
1281 /// #
1282 /// # #[derive(TryFuncMap, Debug, PartialEq)]
1283 /// # struct Foo<S, T> {
1284 /// # s: S,
1285 /// # t: T,
1286 /// # }
1287 /// #
1288 /// # let foo = Foo {
1289 /// # s: "42",
1290 /// # t: "42",
1291 /// # };
1292 /// #
1293 /// foo.try_func_map_over::<TypeParam<0>, _, _>(|v| v.parse::<i32>())
1294 /// .and_then(|foo| foo.try_func_map_over::<TypeParam<1>, _, _>(|v| v.parse::<i32>()))
1295 /// # ;
1296 /// ```
1297 ///
1298 /// Note that you still need to specify the inferred type `_` for the
1299 /// error type `E` and the closure type `F`.
1300 ///
1301 /// # Errors
1302 /// Fails if and only if `f` fails, returning the first error according to
1303 /// the order of the fields in the definition of `Self`
1304 fn try_func_map_over<Q, E, F>(self, f: F) -> Result<Self::Output, E>
1305 where
1306 F: FnMut(A) -> Result<B, E>,
1307 Q: FuncMarker<P>,
1308 {
1309 self.try_func_map(f)
1310 }
1311}
1312
1313pub use funcmap_derive::FuncMap;
1314
1315pub use funcmap_derive::TryFuncMap;
1316
1317/// Marker type specifying one of multiple type parameters to map over
1318///
1319/// The const generic `N` is the zero-based index of the type parameter, not
1320/// counting lifetime parameters, but counting const generics.
1321///
1322/// For example, for a type `Foo<'a, S, T>`,
1323/// - [`TypeParam<0>`] refers to `S` and
1324/// - [`TypeParam<1>`] refers to `T`
1325///
1326/// and for a type `Foo<'a, const N: usize, S, const M: usize, T>`,
1327/// - [`TypeParam<1>`] refers to `S` and
1328/// - [`TypeParam<3>`] refers to `T`
1329#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1330pub enum TypeParam<const N: usize> {}
1331
1332impl<const N: usize> Display for TypeParam<N> {
1333 fn fmt(&self, _: &mut Formatter<'_>) -> fmt::Result {
1334 match *self {}
1335 }
1336}
1337
1338/// Marker trait for marker types specifying what to map over
1339///
1340/// This is only implemented by the marker types [`TypeParam<N>`] and is used to
1341/// restrict the choice of types for the `P` type parameter of
1342/// [`FuncMap<A, B, P>`] and [`TryFuncMap<A, B, P>`].
1343///
1344/// Note that [`FuncMarker<P>`] is itself generic over `P` and for all
1345/// implementations, the type parameter `P` is the implementing type itself.
1346/// This way, from `Q: FuncMarker<P>` it can be inferred that `Q == P`, which is
1347/// used in the [`FuncMap::func_map_over`] and [`TryFuncMap::try_func_map_over`]
1348/// methods.
1349///
1350/// This trait is sealed and cannot be implemented outside of `funcmap`.
1351pub trait FuncMarker<P>: private::Sealed<P> {}
1352
1353// Note that from `Q: FuncMarker<P>`
1354// - if `Q` is known, then the compiler can infer `P`,
1355// - yet if `P` is known, then the compiler *cannot* infer `Q`
1356//
1357// This way, we force the user to make `Q` explicit when using
1358// [`FuncMap::func_map_over`] and [`TryFuncMap::try_func_map_over`] because that
1359// is the whole purpose of these methods. If `Q` could be inferred, then it
1360// wouldn't be needed and using [`FuncMap::func_map`] respectively
1361// [`TryFuncMap::try_func_map`] would be more idiomatic.
1362impl<const N: usize> FuncMarker<TypeParam<N>> for TypeParam<N> {}
1363
1364/// Making [`FuncMarker`] a sealed trait
1365mod private {
1366 use super::TypeParam;
1367
1368 /// Private supertrait of [`FuncMarker<P>`](super::FuncMarker)
1369 pub trait Sealed<P> {}
1370
1371 impl<const N: usize> Sealed<TypeParam<N>> for TypeParam<N> {}
1372}
1373
1374/// Marker trait with a blanket implementation for all types that implement
1375/// [`Drop`]
1376///
1377/// The [`FuncMap`] derive macro produces an implementation of this trait (in
1378/// addition to an implementation of [`FuncMap`]), asserting that the type
1379/// doesn't implement [`Drop`] because otherwise there would be conflicting
1380/// implementations of this trait.
1381///
1382/// This is necessary because derived implementation of [`FuncMap`] need to move
1383/// out of fields, which isn't possible for types implementing [`Drop`].
1384#[doc(hidden)]
1385#[allow(non_camel_case_types)]
1386pub trait FuncMap_cannot_be_derived_for_types_implementing_Drop {}
1387
1388#[allow(drop_bounds)]
1389impl<T> FuncMap_cannot_be_derived_for_types_implementing_Drop for T where T: Drop + ?Sized {}
1390
1391/// Marker trait with a blanket implementation for all types that implement
1392/// [`Drop`]
1393///
1394/// The [`TryFuncMap`] derive macro produces an implementation of this trait (in
1395/// addition to an implementation of [`TryFuncMap`]), asserting that the type
1396/// doesn't implement [`Drop`] because otherwise there would be conflicting
1397/// implementations of this trait.
1398///
1399/// This is necessary because derived implementation of [`TryFuncMap`] need to
1400/// move out of fields, which isn't possible for types implementing [`Drop`].
1401#[doc(hidden)]
1402#[allow(non_camel_case_types)]
1403pub trait TryFuncMap_cannot_be_derived_for_types_implementing_Drop {}
1404
1405#[allow(drop_bounds)]
1406impl<T> TryFuncMap_cannot_be_derived_for_types_implementing_Drop for T where T: Drop + ?Sized {}