Skip to content

Commit

Permalink
Merge pull request #1702 from dtolnay/preclet
Browse files Browse the repository at this point in the history
Create a new precedence level for Expr::Let
  • Loading branch information
dtolnay committed Jul 7, 2024
2 parents 2959338 + 1f9e082 commit ff022f5
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 23 deletions.
22 changes: 2 additions & 20 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3253,30 +3253,12 @@ pub(crate) mod printing {
};

// These cases require parenthesization independently of precedence.
match (&*e.left, &e.op) {
if let BinOp::Lt(_) | BinOp::Shl(_) = &e.op {
// `x as i32 < y` has the parser thinking that `i32 < y` is the
// beginning of a path type. It starts trying to parse `x as (i32 <
// y ...` instead of `(x as i32) < ...`. We need to convince it
// _not_ to do that.
(_, BinOp::Lt(_) | BinOp::Shl(_)) if classify::confusable_with_adjacent_lt(&e.left) => {
left_needs_group = true;
}

// We are given `(let _ = a) OP b`.
//
// - When `OP <= LAnd` we should print `let _ = a OP b` to avoid
// redundant parens as the parser will interpret this as `(let _ =
// a) OP b`.
//
// - Otherwise, e.g. when we have `(let a = b) < c` in AST, parens
// are required since the parser would interpret `let a = b < c`
// as `let a = (b < c)`. To achieve this, we force parens.
#[cfg(feature = "full")]
(Expr::Let(_), _) if binop_prec > Precedence::And => {
left_needs_group = true;
}

_ => {}
left_needs_group |= classify::confusable_with_adjacent_lt(&e.left);
}

print_subexpression(
Expand Down
8 changes: 6 additions & 2 deletions src/fixup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ impl FixupContext {
/// "let chain".
pub fn needs_group_as_let_scrutinee(self, expr: &Expr) -> bool {
self.parenthesize_exterior_struct_lit && classify::confusable_with_adjacent_block(expr)
|| self.trailing_precedence(expr) <= Precedence::And
|| self.trailing_precedence(expr) < Precedence::Let
}

/// Determines the effective precedence of a left subexpression. Some
Expand All @@ -265,7 +265,11 @@ impl FixupContext {
match expr {
// Increase precedence of expressions that extend to the end of
// current statement or group.
Expr::Break(_) | Expr::Closure(_) | Expr::Return(_) | Expr::Yield(_) => {
Expr::Break(_)
| Expr::Closure(_)
| Expr::Let(_)
| Expr::Return(_)
| Expr::Yield(_) => {
return Precedence::Prefix;
}
Expr::Range(e) if e.start.is_none() => return Precedence::Prefix,
Expand Down
6 changes: 5 additions & 1 deletion src/precedence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub(crate) enum Precedence {
Or,
// &&
And,
// let
#[cfg(feature = "printing")]
Let,
// == != < > <= >=
Compare,
// |
Expand Down Expand Up @@ -97,8 +100,9 @@ impl Precedence {
Expr::Assign(_) => Precedence::Assign,
Expr::Range(_) => Precedence::Range,
Expr::Binary(e) => Precedence::of_binop(&e.op),
Expr::Let(_) => Precedence::Let,
Expr::Cast(_) => Precedence::Cast,
Expr::Let(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix,
Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix,

Expr::Array(_)
| Expr::Async(_)
Expand Down

0 comments on commit ff022f5

Please sign in to comment.