Closed
Description
Possible regression in nightly from stable 1.4 with respect to the use of macro hygiene to recursively construct patterns and expressions.
Code:
// zip!(a1,a2,a3,a4) is equivalent to:
// a1.zip(a2).zip(a3).zip(a4).map(|(((x1,x2),x3),x4)| (x1,x2,x3,x4))
macro_rules! zip {
// Entry point
([$a:expr, $b:expr, $($rest:expr),*]) => {
zip!([$($rest),*], $a.zip($b), (x,y), [x,y])
};
// Intermediate steps to build the zipped expression, the match pattern, and
// and the output tuple of the closure, using macro hygene to repeatedly
// introduce new variables named 'x'.
([$a:expr, $($rest:expr),*], $zip:expr, $pat:pat, [$($flat:expr),*]) => {
zip!([$($rest),*], $zip.zip($a), ($pat,x), [$($flat),*, x])
};
// Final step
([], $zip:expr, $pat:pat, [$($flat:expr),+]) => {
$zip.map(|$pat| ($($flat),+))
};
// Comma
([$a:expr], $zip:expr, $pat:pat, [$($flat:expr),*]) => {
zip!([$a,], $zip, $pat, [$($flat),*])
};
}
fn main() {
let p1 = vec![1i32, 2].into_iter();
let p2 = vec!["10", "20"].into_iter();
let p3 = vec![100u16, 200].into_iter();
let p4 = vec![1000i64, 2000].into_iter();
let e = zip!([p1,p2,p3,p4]).collect::<Vec<_>>();
assert_eq!(e[0], (1i32,"10",100u16,1000i64));
}
On stable:
Successful build and run
On nightly:
<anon>:14:42: 14:43 error: mismatched types:
expected `i32`,
found `u16`
(expected i32,
found u16) [E0308]
<anon>:14 zip!([$($rest),*], $zip.zip($a), ($pat,x), [$($flat),*, x])
^
<anon>:14:3: 14:62 note: in this expansion of zip! (defined in <anon>)
<anon>:24:3: 24:40 note: in this expansion of zip! (defined in <anon>)
<anon>:14:3: 14:62 note: in this expansion of zip! (defined in <anon>)
<anon>:7:3: 7:47 note: in this expansion of zip! (defined in <anon>)
<anon>:34:10: 34:29 note: in this expansion of zip! (defined in <anon>)
<anon>:14:42: 14:43 help: see the detailed explanation for E0308
<anon>:14:42: 14:43 error: mismatched types:
expected `i64`,
found `i32`
(expected i64,
found i32) [E0308]
<anon>:14 zip!([$($rest),*], $zip.zip($a), ($pat,x), [$($flat),*, x])
^
<anon>:14:3: 14:62 note: in this expansion of zip! (defined in <anon>)
<anon>:24:3: 24:40 note: in this expansion of zip! (defined in <anon>)
<anon>:14:3: 14:62 note: in this expansion of zip! (defined in <anon>)
<anon>:7:3: 7:47 note: in this expansion of zip! (defined in <anon>)
<anon>:34:10: 34:29 note: in this expansion of zip! (defined in <anon>)
<anon>:14:42: 14:43 help: see the detailed explanation for E0308
<std macros>:5:22: 5:33 error: mismatched types:
expected `(i32, &str, u16, i32)`,
found `(i32, &str, u16, i64)`
(expected i32,
found i64) [E0308]
<std macros>:5 if ! ( * left_val == * right_val ) {
^~~~~~~~~~~
<anon>:35:2: 35:47 note: in this expansion of assert_eq! (defined in <std macros>)
<std macros>:5:22: 5:33 help: see the detailed explanation for E0308
error: aborting due to 3 previous errors
playpen: application terminated with error code 101
Note: When all vecs in the example are the same type, the error does not occur.
A simpler (but far more contrived) example can be found here: http://is.gd/EHUV1z
A git bisect identified this commit in PR#28642.