Skip to content

Commit

Permalink
Add Iterator trait bounds to IntoEnumIterator (#314)
Browse files Browse the repository at this point in the history
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())
}
  • Loading branch information
joshchngs authored Dec 3, 2023
1 parent 62c1150 commit ffe8873
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion strum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
// only for documentation purposes
pub mod additional_attributes;

use core::iter::FusedIterator;

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

fn iter() -> Self::Iterator;
}
Expand Down

0 comments on commit ffe8873

Please sign in to comment.