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

Add macro_rules fragment class for "expressions that can be followed by {" #1463

Open
pnkfelix opened this issue Jan 15, 2016 · 14 comments
Open
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@pnkfelix
Copy link
Member

(spawned off of #1384 (comment) )

I've been leaving links to the above comment in all sorts of places, so I finally decided it was time to open an RFC issue for this idea.

Namely, to add some fragment class, which I'll call pred for now, that represents "the subset of expressions that do not have { in their follow set, and thus the presence of a { as the next token tells the parser that it is definitely done parsing the expression."

In particular, this is the subset of expressions that we use for the test in an if test { then } else { other }

Such an fragment class would be useful for writing macro_rules! that naturally want a { to come after them in the input pattern.

We used to superficially "allow" such macros, but they didn't actually work in general; see rust-lang/rust#26739

@Stebalien
Copy link
Contributor

FYI, this covers more than predicates:

// Does it cover `let x = y` (a predicate?) or just `y`?
while let x = y {
}

// no predicate in sight
for a in b {
}

@pnkfelix
Copy link
Member Author

@Stebalien I am not quite sure how to interpret your comment.

For example, while let x = y { ... } is not the result of composing while <expr> { ... } with some internal let x = y ... let x = y is not an expression. Instead, while let is its own expression construct in Rust's grammar.

@Stebalien
Copy link
Contributor

Sorry, I meant to write "covers more than predicates" instead of "covers more than pred". My point was that neither y nor b are predicates (although let x = y technically acts like a predicate but that's not really that important) so we'll need to think of some better name. However, after re-reading your post, you clearly realized this so I'm just going to shut up now...

@pnkfelix
Copy link
Member Author

@Stebalien ah yes; the name pred may not be ideal, since in cases like the ones you name, its not that the expression in question returns a boolean, but rather e.g. for while let returns an enum (and we're matching a particular variant), or for for a in b, the b needs to return something that implements IntoIterator -- so the connection to pred there is certainly tenuous at best.

Really the most attractive thing about the token pred to me is just that it is short. I don't know if it really has all that much else going for it...

@durka
Copy link
Contributor

durka commented Jan 18, 2016

I might be having a brain fart, but what situations in the current grammar have expressions followed by {? I guess struct literals are path { ... }, and a path is an expr. Is that it?

In terms of bikeshedding the name:

  • pred
    • I actually like it okay
    • it's easy to explain by analogy to if $p:pred { $($body:tt)* }
  • nbe or nbex
    • stands for No-Block Expr or No-Brace Expr
    • tt is precedent for using acronyms as fragment specifiers
    • src/grammar refers to this construct as expr_nostruct, if I'm reading it right, so another acronym could be exns
  • ...wanted to put more ideas here, but I can't think of any right now

Another crazy idea is "silent adaptation" -- if you put $e:expr { in a macro rule, it becomes a matcher for a moelarry instead of a full expr. This is probably a bad idea.

@pnkfelix
Copy link
Member Author

if you put $e:expr { in a macro rule, it becomes a matcher for a moelarry instead of a full expr. This is probably a bad idea

Yeah, it probably is bad; consider e.g. the macro pattern $a:expr $($b:expr)* { stuff }*. Is the $b still an nbe? If so, how about $a ?

@Stebalien
Copy link
Contributor

@pnkfelix IMO, that's unambiguous. $a is an nbe because it might be followed by an expression (which could start with {). $b is an nbe because it's repeated.

@pnkfelix
Copy link
Member Author

@Stebalien in that case I think we would be better served by a separately named fragment class. Having the potentially matched forms of a NT depend on patterns potentially arbitrarily far ahead in the macro LHS seems bad

@Stebalien
Copy link
Contributor

@pnkfelix

potentially arbitrarily far ahead

Unless I'm mistaken, it only depends on the next pattern. However, I'm certainly not opposed to making it explicit (I just can't think of a name).

@pnkfelix
Copy link
Member Author

Sorry I think my example failed to express what I'm concerned about; look e.g. at:

$a:expr $(, $b:expr )* { stuff }

(Where I have now added a comma before $b so that we don't worry the two exprs right next to each other)

In this case, a { may still come right after the $a, but the reader must look at the whole of the LHS to see it. That's what I am concerned with.

In this case, a `

@Stebalien
Copy link
Contributor

Ah. I see. Yes, that's a problem.

Steven Allen

@durka
Copy link
Contributor

durka commented Feb 4, 2016

As part of this RFC (or maybe a separate one), can we expand a couple of follow sets with things they should logically already include, for macro writing convenience?

  • types (and therefore paths) can be followed by blocks (see: return types of functions/closures). Indeed, OpenDelim(Bracket) is already in FOLLOW(ty/path), but Interpolated(NtBlock(_)) should be as well.
  • patterns can be followed by colons (see: let bindings, function/closure arguments). So FOLLOW(pat) should include Colon.

Did I miss any?

@pnkfelix
Copy link
Member Author

pnkfelix commented Feb 4, 2016

@durka those sounds like good things, but I would put them in a separate RFC. Actually I'd put them into an amendment of the macro-future proofing RFC -- that is likely to ensure that it gets approved faster.

@durka
Copy link
Contributor

durka commented Feb 8, 2016

See #1494.

@nrc nrc added the T-lang Relevant to the language team, which will review and decide on the RFC. label Aug 18, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

4 participants