From 65fc3d49b0585b469d020095a34bfa7861ff0b6a Mon Sep 17 00:00:00 2001 From: Philippe-Cholet <44676486+Philippe-Cholet@users.noreply.github.com> Date: Tue, 21 May 2024 11:07:13 +0200 Subject: [PATCH 1/2] Macro hygiene of `chain!` If someone has a module named `core` and uses `itertools::chain!` then there is a conflict! I improve our macro hygiene test by adding (empty) modules with all the names we might be tempted to use. Without changing `core` in `chain!`, the test failed! --- src/lib.rs | 8 ++++---- tests/macros_hygiene.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f4de79c50..1a847d42b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -393,16 +393,16 @@ macro_rules! izip { /// ``` macro_rules! chain { () => { - core::iter::empty() + $crate::__std_iter::empty() }; ($first:expr $(, $rest:expr )* $(,)?) => { { - let iter = core::iter::IntoIterator::into_iter($first); + let iter = $crate::__std_iter::IntoIterator::into_iter($first); $( let iter = - core::iter::Iterator::chain( + $crate::__std_iter::Iterator::chain( iter, - core::iter::IntoIterator::into_iter($rest)); + $crate::__std_iter::IntoIterator::into_iter($rest)); )* iter } diff --git a/tests/macros_hygiene.rs b/tests/macros_hygiene.rs index 20b59fba8..e6e895555 100644 --- a/tests/macros_hygiene.rs +++ b/tests/macros_hygiene.rs @@ -1,3 +1,8 @@ +mod alloc {} +mod core {} +mod either {} +mod std {} + #[test] fn iproduct_hygiene() { let _ = itertools::iproduct!(); @@ -12,3 +17,11 @@ fn izip_hygiene() { let _ = itertools::izip!(0..6, 0..9); let _ = itertools::izip!(0..6, 0..9, 0..12); } + +#[test] +fn chain_hygiene() { + let _: ::std::iter::Empty = itertools::chain!(); + let _ = itertools::chain!(0..6); + let _ = itertools::chain!(0..6, 0..9); + let _ = itertools::chain!(0..6, 0..9, 0..12); +} From 4588c02537d93ab10a50efbee160972562ec8123 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet <44676486+Philippe-Cholet@users.noreply.github.com> Date: Tue, 21 May 2024 11:13:44 +0200 Subject: [PATCH 2/2] Macro hygiene: qualified paths only Is conflict with `.map` and `.zip` absolutely impossible? --- src/lib.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1a847d42b..018f877e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -262,7 +262,10 @@ macro_rules! iproduct { $crate::__std_iter::once(()) ); ($I:expr $(,)?) => ( - $crate::__std_iter::IntoIterator::into_iter($I).map(|elt| (elt,)) + $crate::__std_iter::Iterator::map( + $crate::__std_iter::IntoIterator::into_iter($I), + |elt| (elt,) + ) ); ($I:expr, $J:expr $(,)?) => ( $crate::Itertools::cartesian_product( @@ -330,19 +333,24 @@ macro_rules! izip { // binary ($first:expr, $second:expr $(,)*) => { - $crate::izip!($first) - .zip($second) + $crate::__std_iter::Iterator::zip( + $crate::__std_iter::IntoIterator::into_iter($first), + $second, + ) }; // n-ary where n > 2 ( $first:expr $( , $rest:expr )* $(,)* ) => { - $crate::izip!($first) + { + let iter = $crate::__std_iter::IntoIterator::into_iter($first); $( - .zip($rest) + let iter = $crate::__std_iter::Iterator::zip(iter, $rest); )* - .map( + $crate::__std_iter::Iterator::map( + iter, $crate::izip!(@closure a => (a) $( , $rest )*) ) + } }; }