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

Macros attempting to expand to multiple items silently only expand to the first one #8012

Closed
paulstansifer opened this issue Jul 23, 2013 · 6 comments · Fixed by #9673
Closed
Labels
A-syntaxext Area: Syntax extensions

Comments

@paulstansifer
Copy link
Contributor

Users who want a macro that expands to a collection items are required to wrap the RHS in {} in order to get them to expand to a whole block. However, if they fail to do so, they unexpectedly just get the first item of the block, rather than an error message.

macro_rules! print_if_nonzero(
    ($msg:expr, $($field:ident),*) => ( /*{*/
        $(
            if t.$field != 0 {
                println($msg);
            }
        )*
    /*}*/ )
)

struct T { x: int, y: int }

fn main() {
    let t = T { x: 0, y: 0 };
    print_if_nonzero!("hello", x, y);
}

...expands to...

fn main() { let t = T{x: 0, y: 0,}; if t.x != 0 { println("hello"); }; }
@paulstansifer
Copy link
Contributor Author

Thanks to kmc on IRC for reporting this.

@bstrie
Copy link
Contributor

bstrie commented Jul 24, 2013

Perhaps this is really just another plaintive cry for someone to tackle #4375.

@huonw
Copy link
Member

huonw commented Aug 5, 2013

Smaller testcase:

rusti> macro_rules! t( () => { println("hi"); println("oops"); }) t!()
hi
()

@nejucomo
Copy link

I don't understand how this is different than #4375. If not justification for the distinction is given, can we mark this as a duplicate?

@paulstansifer
Copy link
Contributor Author

This source of this problem probably isn't specific to items. I'm worried
that there's a lurking (if minor) usability problem in the lack of erroring
out in this case.

@kmcallister
Copy link
Contributor

Yeah, jason_ on IRC provided this example using tuples:

macro_rules! omg(($n:expr) => ($n,$n+1))
omg!(100) // => 100, not (100, 101)

bors added a commit that referenced this issue Oct 2, 2013
That is, only a single expression or item gets parsed, so if there are
any extra tokens (e.g. the start of another item/expression) the user
should be told, rather than silently dropping them.

An example:

    macro_rules! foo {
        () => {
            println("hi");
            println("bye);
        }
    }

would expand to just `println("hi")`, which is almost certainly not
what the programmer wanted.

Fixes #8012.
@huonw huonw closed this as completed in 8284df9 Oct 2, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-syntaxext Area: Syntax extensions
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants