rust-lang / rust-lang/reference

The definition of fragment specifier is inconsistent

Open
#2,265 12 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-macros
Dominant language
Rust
Stars
1.6k
Forks
607
PR merge metrics
PR metrics pending

Description

Consider this example:

macro_rules! test{
    ($id:ident, $e:expr)=>{
        $id.$e
    }
}
fn main() {
  let a = (1,);
  test!(a,0);
}

The compiler reports an error

error: unexpected token: `expr` metavariable
 --> src/main.rs:3:13
  |
3 |         $id.$e
  |             ^^
...
8 |   test!(a,0);
  |   ---------- in this macro invocation
  |
  = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)

IIUC, the reason can be interpreted by the syntax

Valid fragment specifiers are:

$e is defined as an expr fragment specifier, which can match LiteralExpression; however, the valid syntax of Tuple indexing expressions is defined as

TupleIndexingExpressionExpression . TUPLE_INDEX

The component following . is TUPLE_INDEX in which an Expression cannot appear. So, this is the reason for the error, which is ruled by syntax.

However, see the definition of path

path: a TypePath

This is a fixed version by https://github.com/rust-lang/reference/pull/2248

A TypePath is

TypePath → ::? TypePathSegment ( :: TypePathSegment )*

Instead, a path in an expression should be

PathExpression
PathInExpression
| QualifiedPathInExpression

The path that appears in an expression doesn't expect the syntax TypePath, that is, the following code should have had a similar error as the first example:

macro_rules! test2{
    ($id:ident,$p:path)=>{
        $id = $p;
    }
}
mod S{
    pub const I:i32 = 0;
}
fn main() {
  let mut i = 0;
  test2!(i,S::I);
}

However, this code is ok.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by comparing the Reference definitions for macro fragment specifiers, expressions, paths, TypePath, and PathExpression linked in the issue. Trace how the expr and path examples fit those grammars, then clarify the inconsistent definitions and add or update an example showing the intended behavior. Done means the relevant grammar and prose consistently describe both cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.