Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression in macro hygiene for recursive macros #29746

Closed
ExpHP opened this issue Nov 10, 2015 · 2 comments
Closed

Regression in macro hygiene for recursive macros #29746

ExpHP opened this issue Nov 10, 2015 · 2 comments
Labels
regression-from-stable-to-beta Performance or correctness regression from stable to beta.

Comments

@ExpHP
Copy link
Contributor

ExpHP commented Nov 10, 2015

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.

@ghost
Copy link

ghost commented Nov 10, 2015

This is also a regression from stable to beta.

@bluss bluss added the regression-from-stable-to-beta Performance or correctness regression from stable to beta. label Nov 10, 2015
@petrochenkov
Copy link
Contributor

I'm not sure what exactly happens, but I have a patch fixing it :D
Will submit ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
regression-from-stable-to-beta Performance or correctness regression from stable to beta.
Projects
None yet
Development

No branches or pull requests

3 participants