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 #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.