@@ -1715,14 +1715,19 @@ impl<'a> State<'a> {
17151715 self . ann . post ( self , AnnNode :: Block ( blk) )
17161716 }
17171717
1718+ /// Print a `let pats = scrutinee` expression.
17181719 pub fn print_let ( & mut self , pats : & [ P < ast:: Pat > ] , scrutinee : & ast:: Expr ) -> io:: Result < ( ) > {
17191720 self . s . word ( "let " ) ?;
17201721
17211722 self . print_pats ( pats) ?;
17221723 self . s . space ( ) ?;
17231724
17241725 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+ )
17261731 }
17271732
17281733 fn print_else ( & mut self , els : Option < & ast:: Expr > ) -> io:: Result < ( ) > {
@@ -1794,30 +1799,30 @@ impl<'a> State<'a> {
17941799 }
17951800
17961801 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)
18061803 }
18071804
18081805 /// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
18091806 /// `if cond { ... }`.
18101807 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 {
18121814 // These cases need parens due to the parse error observed in #26461: `if return {}`
18131815 // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
18141816 ast:: ExprKind :: Closure ( ..) |
18151817 ast:: ExprKind :: Ret ( ..) |
18161818 ast:: ExprKind :: Break ( ..) => true ,
18171819
18181820 _ => parser:: contains_exterior_struct_lit ( expr) ,
1819- } ;
1821+ }
1822+ }
18201823
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 < ( ) > {
18211826 if needs_par {
18221827 self . popen ( ) ?;
18231828 }
@@ -1949,6 +1954,17 @@ impl<'a> State<'a> {
19491954 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
19501955 ( & ast:: ExprKind :: Cast { .. } , ast:: BinOpKind :: Lt ) |
19511956 ( & 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+ }
19521968 _ => left_prec,
19531969 } ;
19541970
0 commit comments