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

Macro input future proofing #20563

Merged
merged 5 commits into from
Jan 7, 2015
Merged

Macro input future proofing #20563

merged 5 commits into from
Jan 7, 2015

Conversation

emberian
Copy link
Member

@emberian emberian commented Jan 5, 2015

Implements RFC 550 (rust-lang/rfcs#550)

@rust-highfive
Copy link
Collaborator

r? @pnkfelix

(rust_highfive has picked a reviewer for you, use r? to override)

See RFC 550 (rust-lang/rfcs#550) for the motivation
and details.

If this breaks your code, add one of the listed tokens after the relevant
non-terminal in your matcher.

[breaking-change]
fn check_matcher(cx: &mut ExtCtxt, matcher: &[TokenTree], follow: &Token) {
use print::pprust::token_to_string;

// 1. If there are no tokens in M, accept
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case doesn't need to exist, does it?

@nikomatsakis
Copy link
Contributor

OK, reviewed. Algorithm seems close but not quite right, particularly around adjacent non-terminals (which can't be soundly permitted without a FIRST set) and the repeaters.

@nikomatsakis
Copy link
Contributor

@cmr I'm ok with => in the follow sets of types and expressions. @alexcrichton points out that for expressions we kind of are stuck with it anyway because of _ if foo => in patterns. Also, given that we want to add type ascription, an expression can always end in a type, so it makes sets for the follow sets of the two to be the same.

@nikomatsakis
Copy link
Contributor

Sorry, that was too strong. And we don't need type ascription, we already have expr as Type. So really just follow(expr) <= follow(type) (I think), and since => is in follow(expr), should be present for type as well.

@alexcrichton alexcrichton added this to the 1.0 alpha milestone Jan 6, 2015
@SimonSapin
Copy link
Contributor

I use this macro a lot:

macro_rules! is_match {
    ($value:expr, $($pattern:pat)|+) => {
        match $value {
            $($pattern)|+ => true,
            _ => false
        }
    }
}

But it now gives error: $pattern:patis followed by|, which is not allowed for pat fragments. Why is this specific pair not allowed? Is there a work-around?

@SimonSapin
Copy link
Contributor

For what it’s worth, upgrading rust-url to the latest nightly is blocked on this.

@emberian
Copy link
Member Author

emberian commented Jan 9, 2015

@SimonSapin that combination is disallowed to provide for extending patterns with |-alternation in the future. Right now, | in "pattern" is handled entirely by match.

The only tokens allowed to follow pat at the moment are =>, ,, and =.

@SimonSapin
Copy link
Contributor

@cmr, so there is no way to write a macro the accepts multiple patterns with the same syntax as match? I don’t care if it’s with $($pattern:pat)|+ or with a single $pattern:pat, but making it impossible is a pretty bad regression.

@alexcrichton
Copy link
Member

@SimonSapin thanks for pointing this out! We were deliberately quite conservative in choosing the "follow sets" for this RFC as we can always expand them over time! For patterns specifically, I think we must allow | in the follow set because we could never extend the grammar of a pattern to include a | token (it would cause many ambiguities today).

If you'd like, you could open a PR modifying the relevant code to have a bit more discussion (someone should validate my thinking)

SimonSapin added a commit to SimonSapin/rust that referenced this pull request Jan 9, 2015
Per rust-lang#20563 (comment)

This enables writing macros that accept `$($pattern:pat)|+` and expand to the same thing in a `match` statement. See for example [the `matches!` macro](https://github.com/SimonSapin/rust-std-candidates#the-matches-macro).
@SimonSapin
Copy link
Contributor

Ok, @huonw suggested a work around that I’m happy with:

#[macro_export]
macro_rules! matches {
    ($expression: expr, $($pattern:tt)+) => {
        _tt_as_expr_hack! {
            match $expression {
                $($pattern)+ => true,
                _ => false
            }
        }
    }
}


/// Work around "error: unexpected token: `an interpolated tt`", whatever that means.
#[macro_export]
macro_rules! _tt_as_expr_hack {
    ($value:expr) => ($value)
}

tt allows sneaking another match arm in, which isn’t great, but better than picking a random ASCII character for the delimiter.

matches!("foo", "bar" | "baz" => 42 > 9000, "fuzz");

alkor added a commit to alkor/rust-http that referenced this pull request Jan 11, 2015
alkor added a commit to alkor/rust-http that referenced this pull request Jan 11, 2015
Semicolon after ty is no longer supported.
See rust-lang/rust#20563
alkor added a commit to alkor/rust that referenced this pull request Jan 12, 2015
Also, update description of macro invocation syntax:
after rust-lang#20563 there is
a number of additional limitations on macro syntax.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants