rust-lang / rust-lang/reference

Figure out how to better define let chain grammar

Open
#1,811 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

The let chain grammar has some issues, and could use some improvement.

The let chain grammar doesn't handle the minimum precedence of chains of associative operators (see prec_let_scrutinee_needs_par). The ExcludedConditions doesn't explain how "deep" the exclusion goes in terms of the AST. For example, naively:

#[cfg(false)]
fn f() -> Range<i32> {
    let mut z = 0;
    if let r = 1+z=1 {}
    todo!()
}

// Contrast this with `if 1+z=1 {}` which is OK since it doesn't have the
// minimum precedence restriction.

The Scrutinee here could be parsed as arithmetic plus of 1 and z=1 (assignment expression, whose value is unit). The ExcludedConditions doesn't explain that the minimum precedence applies to the RHS of the add expression. Similar to https://github.com/rust-lang/reference/issues/1808, the parser keeps track of a minimum precedence for some period of time (while parsing a chain of associative operators I believe), but there are many places where sub-expressions ignore this minimum precedence (I think all sub-expressions except for associative operators?).

I don't know how to specify that. One option is to define a variant of Expression that excludes the relevant expressions, and has a new set of associative operator expressions that have the appropriate exclusions. Like IfCondArithmeticOrLogicalExpression -> IfCondExpression + IfCondExpression | ... and IfCondExpression is the set of restricted expressions. However, I'm concerned this will result in a very large duplication of the Expression sub-grammar.


In https://hackmd.io/@ehuss/S1juwZuyxl I also sketched out a grammar that made LetExpression an actual expression, but only in a ConditionExpression. I don't know if that would help with anything. I think the current Restrictions::ALLOW_LET restriction is correctly captured in the grammar, but it could use more scrutiny.


The range expression exclusion is a little odd since it allows ranges that don't have a LHS. I think it is fine as it is, but it seemed quite unusual and could use some more inspection.


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 reading the let-chain grammar in the Rust Reference alongside compiler/rustc_ast/src/util/parser.rs, especially prec_let_scrutinee_needs_par and ExcludedConditions. Compare the grammar with the examples in this issue and the linked Reference issue and HackMD sketch. Done means the precedence and exclusion rules are specified precisely, including associative operators, ranges, and ALLOW_LET.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, documentation
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.