@@ -1715,14 +1715,19 @@ impl<'a> State<'a> {
1715
1715
self . ann . post ( self , AnnNode :: Block ( blk) )
1716
1716
}
1717
1717
1718
+ /// Print a `let pats = scrutinee` expression.
1718
1719
pub fn print_let ( & mut self , pats : & [ P < ast:: Pat > ] , scrutinee : & ast:: Expr ) -> io:: Result < ( ) > {
1719
1720
self . s . word ( "let " ) ?;
1720
1721
1721
1722
self . print_pats ( pats) ?;
1722
1723
self . s . space ( ) ?;
1723
1724
1724
1725
self . word_space ( "=" ) ?;
1725
- self . print_expr_as_cond ( scrutinee)
1726
+ self . print_expr_cond_paren (
1727
+ scrutinee,
1728
+ Self :: cond_needs_par ( scrutinee)
1729
+ || parser:: needs_par_as_let_scrutinee ( scrutinee. precedence ( ) . order ( ) )
1730
+ )
1726
1731
}
1727
1732
1728
1733
fn print_else ( & mut self , els : Option < & ast:: Expr > ) -> io:: Result < ( ) > {
@@ -1794,30 +1799,30 @@ impl<'a> State<'a> {
1794
1799
}
1795
1800
1796
1801
pub fn print_expr_maybe_paren ( & mut self , expr : & ast:: Expr , prec : i8 ) -> io:: Result < ( ) > {
1797
- let needs_par = expr. precedence ( ) . order ( ) < prec;
1798
- if needs_par {
1799
- self . popen ( ) ?;
1800
- }
1801
- self . print_expr ( expr) ?;
1802
- if needs_par {
1803
- self . pclose ( ) ?;
1804
- }
1805
- Ok ( ( ) )
1802
+ self . print_expr_cond_paren ( expr, expr. precedence ( ) . order ( ) < prec)
1806
1803
}
1807
1804
1808
1805
/// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
1809
1806
/// `if cond { ... }`.
1810
1807
pub fn print_expr_as_cond ( & mut self , expr : & ast:: Expr ) -> io:: Result < ( ) > {
1811
- let needs_par = match expr. node {
1808
+ self . print_expr_cond_paren ( expr, Self :: cond_needs_par ( expr) )
1809
+ }
1810
+
1811
+ /// Does `expr` need parenthesis when printed in a condition position?
1812
+ fn cond_needs_par ( expr : & ast:: Expr ) -> bool {
1813
+ match expr. node {
1812
1814
// These cases need parens due to the parse error observed in #26461: `if return {}`
1813
1815
// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1814
1816
ast:: ExprKind :: Closure ( ..) |
1815
1817
ast:: ExprKind :: Ret ( ..) |
1816
1818
ast:: ExprKind :: Break ( ..) => true ,
1817
1819
1818
1820
_ => parser:: contains_exterior_struct_lit ( expr) ,
1819
- } ;
1821
+ }
1822
+ }
1820
1823
1824
+ /// Print `expr` or `(expr)` when `needs_par` holds.
1825
+ fn print_expr_cond_paren ( & mut self , expr : & ast:: Expr , needs_par : bool ) -> io:: Result < ( ) > {
1821
1826
if needs_par {
1822
1827
self . popen ( ) ?;
1823
1828
}
@@ -1949,6 +1954,17 @@ impl<'a> State<'a> {
1949
1954
// of `(x as i32) < ...`. We need to convince it _not_ to do that.
1950
1955
( & ast:: ExprKind :: Cast { .. } , ast:: BinOpKind :: Lt ) |
1951
1956
( & ast:: ExprKind :: Cast { .. } , ast:: BinOpKind :: Shl ) => parser:: PREC_FORCE_PAREN ,
1957
+ // We are given `(let _ = a) OP b`.
1958
+ //
1959
+ // - When `OP <= LAnd` we should print `let _ = a OP b` to avoid redundant parens
1960
+ // as the parser will interpret this as `(let _ = a) OP b`.
1961
+ //
1962
+ // - Otherwise, e.g. when we have `(let a = b) < c` in AST,
1963
+ // parens are required since the parser would interpret `let a = b < c` as
1964
+ // `let a = (b < c)`. To achieve this, we force parens.
1965
+ ( & ast:: ExprKind :: Let { .. } , _) if !parser:: needs_par_as_let_scrutinee ( prec) => {
1966
+ parser:: PREC_FORCE_PAREN
1967
+ }
1952
1968
_ => left_prec,
1953
1969
} ;
1954
1970
0 commit comments