1
0
mirror of https://github.com/danog/strum.git synced 2024-11-30 04:28:59 +01:00

Add Iterator trait bounds to IntoEnumIterator (#314)

The concrete Iterator type for all implementations of
IntoEnumIterator is guaranteed to implement these traits, because
the only implementor is the `#[derive(EnumIter)]` macro, which
emits an impl for each for the generated {EnumType}Iter struct.

However, when using IntoEnumIterator as a generic constraint, the
concrete type is not known, so the impl of these traits cannot be
inferred by the type checker with out additional help.

Here are some examples, using Itertools::cartesian_product() as
the motivator, because it requires `Iterator + Clone`:

// We know this function will work, but it fails to type check
// without these additional trait bounds on IntoEnumIterator.
pub fn example_broken<T: Clone + IntoEnumIterator, U: Clone + IntoEnumIterator>(
) -> impl Iterator<Item = (T, U)> + Clone {
    T::iter().cartesian_product(U::iter())
}

// It's possible to add where constraints at the use point to
// workaround the issue, without this change.
// This version will typecheck.
pub fn example_workaround<T: Clone + IntoEnumIterator, U: Clone + IntoEnumIterator>(
) -> impl Iterator<Item = (T, U)>
where
    <T as IntoEnumIterator>::Iterator: Clone,
    <U as IntoEnumIterator>::Iterator: Clone,
{
    T::iter().cartesian_product(U::iter())
}
This commit is contained in:
Josh Channings 2023-12-03 00:28:57 +00:00 committed by GitHub
parent 62c1150844
commit ffe8873ae7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -30,6 +30,8 @@
// only for documentation purposes // only for documentation purposes
pub mod additional_attributes; pub mod additional_attributes;
use core::iter::FusedIterator;
#[cfg(feature = "phf")] #[cfg(feature = "phf")]
#[doc(hidden)] #[doc(hidden)]
pub use phf as _private_phf_reexport_for_macro_if_phf_feature; pub use phf as _private_phf_reexport_for_macro_if_phf_feature;
@ -96,7 +98,7 @@ impl std::error::Error for ParseError {
/// generic_iterator::<Color, _>(|color| println!("{:?}", color)); /// generic_iterator::<Color, _>(|color| println!("{:?}", color));
/// ``` /// ```
pub trait IntoEnumIterator: Sized { pub trait IntoEnumIterator: Sized {
type Iterator: Iterator<Item = Self>; type Iterator: Iterator<Item = Self> + Clone + DoubleEndedIterator + ExactSizeIterator + FusedIterator;
fn iter() -> Self::Iterator; fn iter() -> Self::Iterator;
} }