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

Allow expressions to be followed by blocks in macro arguments #30679

Closed
LFalch opened this issue Jan 2, 2016 · 4 comments
Closed

Allow expressions to be followed by blocks in macro arguments #30679

LFalch opened this issue Jan 2, 2016 · 4 comments
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-feature-request Category: A feature request, i.e: not implemented / a PR.

Comments

@LFalch
Copy link

LFalch commented Jan 2, 2016

Rust macros try to be hygienic, soTo make sure you don't break Rust's syntax, it restricts what you can write after an expression, which means you can't do something like this:

macro_rules! do_if_true{
    ($e:expr $b:block) => {
        if $e $b
        else {
            println!("got false");
        }
    };
}

Since a block always has curly braces, I would expect an expression could be followed by a block but instead, you get this error:

error: `$e:expr` is followed by `$b:block`, which is not allowed for `expr` fragments

I tested this on both stable (rustc 1.5.0 (3d7cd77 2015-12-04)) and nightly (rustc 1.7.0-nightly (2b8e96d 2015-12-21)), but got the same result.

@jonas-schievink
Copy link
Contributor

Rust macros try to be hygienic, so they restrict what you write after an expression,

This doesn't have to do with hygiene, this restriction exists so macros don't break when Rust's syntax evolves.

@LFalch
Copy link
Author

LFalch commented Jan 2, 2016

Thanks, @jonas-schievink

I corrected the description.

@durka
Copy link
Contributor

durka commented Jan 3, 2016

cc @pnkfelix who was thinking (#25658 (comment)) about improving this situation by introducing a new fragment specifier.

You can currently fix your macro by not using block, e.g.:

macro_rules! do_if_true{
    ($e:expr { $($b:tt)* }) => {
        if $e { $($b)* }
        else {
            println!("got false");
        }
    };
}

But this is only legal due to a bug and AFAIK will break as soon as #30450 is implemented.

@pnkfelix pnkfelix added the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Jan 4, 2016
@Mark-Simulacrum Mark-Simulacrum added the C-feature-request Category: A feature request, i.e: not implemented / a PR. label Jul 24, 2017
@bstrie bstrie changed the title Let expressions be followed by blocks in macro arguments Allow expressions to be followed by blocks in macro arguments Feb 20, 2020
@bstrie
Copy link
Contributor

bstrie commented Feb 20, 2020

Triage: the original example still fails to compile as does durka's workaround (as anticipated), however I'll argue that the current intended way to address this is issue isn't especially onerous: change ($e:expr $b:block) to ($e:expr, $b:block) or ($e:expr; $b:block) or ($e:expr => $b:block).

The alternative suggested above would be to add a new fragment specifier, but I allege that such an addition would require an RFC. If anyone would like to pursue this further, I would suggest opening such an RFC at https://github.com/rust-lang/rfcs/.

@bstrie bstrie closed this as completed Feb 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-feature-request Category: A feature request, i.e: not implemented / a PR.
Projects
None yet
Development

No branches or pull requests

6 participants