Repository: rust-itertools/itertools (rust)

Issue:
Allow `iproduct` to be called like `itertools__iproduct!(..)`
Currently (itertools 0.9) it appears as if I have to use the `iproduct` macro like this:

```rust
use itertools::iproduct;
iproduct!(-1..=1,-1..=1,-1..=1,-1..=1)
```

It would be nice to be able to also use it like so:

```rust
itertools::iproduct!(-1..=1,-1..=1,-1..=1,-1..=1)
```

But doing so returns an error like:

```
error: cannot find macro `iproduct` in this scope
  --> src/bin/day17.rs:79:9
   |
79 |         itertools::iproduct!(-1..=1,-1..=1,-1..=1)
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
```

Having a gander at the source, I think that this is trivial to fix by namespacing the recursive calls to `iproduct` so that it doesn't need to be in scope outside of the macro.

Pull request description:
Make macros more hygienic and callable without importing them
Fixes #506

Patch:
diff --git a/src/lib.rs b/src/lib.rs
index d214910..0f9dba4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -253,16 +253,16 @@ macro_rules! iproduct {
         $I
     );
     (@flatten $I:expr, $J:expr, $($K:expr,)*) => (
-        iproduct!(@flatten $crate::cons_tuples(iproduct!($I, $J)), $($K,)*)
+        $crate::iproduct!(@flatten $crate::cons_tuples($crate::iproduct!($I, $J)), $($K,)*)
     );
     ($I:expr) => (
         $crate::__std_iter::IntoIterator::into_iter($I)
     );
     ($I:expr, $J:expr) => (
-        $crate::Itertools::cartesian_product(iproduct!($I), iproduct!($J))
+        $crate::Itertools::cartesian_product($crate::iproduct!($I), $crate::iproduct!($J))
     );
     ($I:expr, $J:expr, $($K:expr),+) => (
-        iproduct!(@flatten iproduct!($I, $J), $($K,)+)
+        $crate::iproduct!(@flatten $crate::iproduct!($I, $J), $($K,)+)
     );
 }
 
@@ -313,7 +313,7 @@ macro_rules! izip {
 
     // The "b" identifier is a different identifier on each recursion level thanks to hygiene.
     ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => {
-        izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*)
+        $crate::izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*)
     };
 
     // unary
@@ -323,18 +323,18 @@ macro_rules! izip {
 
     // binary
     ($first:expr, $second:expr $(,)*) => {
-        izip!($first)
+        $crate::izip!($first)
             .zip($second)
     };
 
     // n-ary where n > 2
     ( $first:expr $( , $rest:expr )* $(,)* ) => {
-        izip!($first)
+        $crate::izip!($first)
             $(
                 .zip($rest)
             )*
             .map(
-                izip!(@closure a => (a) $( , $rest )*)
+                $crate::izip!(@closure a => (a) $( , $rest )*)
             )
     };
 }


Test patch:
diff --git a/tests/macros_hygiene.rs b/tests/macros_hygiene.rs
new file mode 100644
index 0000000..d111124
--- /dev/null
+++ b/tests/macros_hygiene.rs
@@ -0,0 +1,13 @@
+#[test]
+fn iproduct_hygiene() {
+    let _ = itertools::iproduct!(0..6);
+    let _ = itertools::iproduct!(0..6, 0..9);
+    let _ = itertools::iproduct!(0..6, 0..9, 0..12);
+}
+
+#[test]
+fn izip_hygiene() {
+    let _ = itertools::izip!(0..6);
+    let _ = itertools::izip!(0..6, 0..9);
+    let _ = itertools::izip!(0..6, 0..9, 0..12);
+}