1*69942c0aSMiguel Ojeda // SPDX-License-Identifier: Apache-2.0 OR MIT
2*69942c0aSMiguel Ojeda
3808c999fSMiguel Ojeda use crate::classify;
4808c999fSMiguel Ojeda use crate::expr::Expr;
5808c999fSMiguel Ojeda #[cfg(feature = "full")]
6808c999fSMiguel Ojeda use crate::expr::{
7808c999fSMiguel Ojeda ExprBreak, ExprRange, ExprRawAddr, ExprReference, ExprReturn, ExprUnary, ExprYield,
8808c999fSMiguel Ojeda };
9808c999fSMiguel Ojeda use crate::precedence::Precedence;
10808c999fSMiguel Ojeda #[cfg(feature = "full")]
11808c999fSMiguel Ojeda use crate::ty::ReturnType;
12808c999fSMiguel Ojeda
13808c999fSMiguel Ojeda pub(crate) struct FixupContext {
14808c999fSMiguel Ojeda #[cfg(feature = "full")]
15808c999fSMiguel Ojeda previous_operator: Precedence,
16808c999fSMiguel Ojeda #[cfg(feature = "full")]
17808c999fSMiguel Ojeda next_operator: Precedence,
18808c999fSMiguel Ojeda
19808c999fSMiguel Ojeda // Print expression such that it can be parsed back as a statement
20808c999fSMiguel Ojeda // consisting of the original expression.
21808c999fSMiguel Ojeda //
22808c999fSMiguel Ojeda // The effect of this is for binary operators in statement position to set
23808c999fSMiguel Ojeda // `leftmost_subexpression_in_stmt` when printing their left-hand operand.
24808c999fSMiguel Ojeda //
25808c999fSMiguel Ojeda // (match x {}) - 1; // match needs parens when LHS of binary operator
26808c999fSMiguel Ojeda //
27808c999fSMiguel Ojeda // match x {}; // not when its own statement
28808c999fSMiguel Ojeda //
29808c999fSMiguel Ojeda #[cfg(feature = "full")]
30808c999fSMiguel Ojeda stmt: bool,
31808c999fSMiguel Ojeda
32808c999fSMiguel Ojeda // This is the difference between:
33808c999fSMiguel Ojeda //
34808c999fSMiguel Ojeda // (match x {}) - 1; // subexpression needs parens
35808c999fSMiguel Ojeda //
36808c999fSMiguel Ojeda // let _ = match x {} - 1; // no parens
37808c999fSMiguel Ojeda //
38808c999fSMiguel Ojeda // There are 3 distinguishable contexts in which `print_expr` might be
39808c999fSMiguel Ojeda // called with the expression `$match` as its argument, where `$match`
40808c999fSMiguel Ojeda // represents an expression of kind `ExprKind::Match`:
41808c999fSMiguel Ojeda //
42808c999fSMiguel Ojeda // - stmt=false leftmost_subexpression_in_stmt=false
43808c999fSMiguel Ojeda //
44808c999fSMiguel Ojeda // Example: `let _ = $match - 1;`
45808c999fSMiguel Ojeda //
46808c999fSMiguel Ojeda // No parentheses required.
47808c999fSMiguel Ojeda //
48808c999fSMiguel Ojeda // - stmt=false leftmost_subexpression_in_stmt=true
49808c999fSMiguel Ojeda //
50808c999fSMiguel Ojeda // Example: `$match - 1;`
51808c999fSMiguel Ojeda //
52808c999fSMiguel Ojeda // Must parenthesize `($match)`, otherwise parsing back the output as a
53808c999fSMiguel Ojeda // statement would terminate the statement after the closing brace of
54808c999fSMiguel Ojeda // the match, parsing `-1;` as a separate statement.
55808c999fSMiguel Ojeda //
56808c999fSMiguel Ojeda // - stmt=true leftmost_subexpression_in_stmt=false
57808c999fSMiguel Ojeda //
58808c999fSMiguel Ojeda // Example: `$match;`
59808c999fSMiguel Ojeda //
60808c999fSMiguel Ojeda // No parentheses required.
61808c999fSMiguel Ojeda #[cfg(feature = "full")]
62808c999fSMiguel Ojeda leftmost_subexpression_in_stmt: bool,
63808c999fSMiguel Ojeda
64808c999fSMiguel Ojeda // Print expression such that it can be parsed as a match arm.
65808c999fSMiguel Ojeda //
66808c999fSMiguel Ojeda // This is almost equivalent to `stmt`, but the grammar diverges a tiny bit
67808c999fSMiguel Ojeda // between statements and match arms when it comes to braced macro calls.
68808c999fSMiguel Ojeda // Macro calls with brace delimiter terminate a statement without a
69808c999fSMiguel Ojeda // semicolon, but do not terminate a match-arm without comma.
70808c999fSMiguel Ojeda //
71808c999fSMiguel Ojeda // m! {} - 1; // two statements: a macro call followed by -1 literal
72808c999fSMiguel Ojeda //
73808c999fSMiguel Ojeda // match () {
74808c999fSMiguel Ojeda // _ => m! {} - 1, // binary subtraction operator
75808c999fSMiguel Ojeda // }
76808c999fSMiguel Ojeda //
77808c999fSMiguel Ojeda #[cfg(feature = "full")]
78808c999fSMiguel Ojeda match_arm: bool,
79808c999fSMiguel Ojeda
80808c999fSMiguel Ojeda // This is almost equivalent to `leftmost_subexpression_in_stmt`, other than
81808c999fSMiguel Ojeda // for braced macro calls.
82808c999fSMiguel Ojeda //
83808c999fSMiguel Ojeda // If we have `m! {} - 1` as an expression, the leftmost subexpression
84808c999fSMiguel Ojeda // `m! {}` will need to be parenthesized in the statement case but not the
85808c999fSMiguel Ojeda // match-arm case.
86808c999fSMiguel Ojeda //
87808c999fSMiguel Ojeda // (m! {}) - 1; // subexpression needs parens
88808c999fSMiguel Ojeda //
89808c999fSMiguel Ojeda // match () {
90808c999fSMiguel Ojeda // _ => m! {} - 1, // no parens
91808c999fSMiguel Ojeda // }
92808c999fSMiguel Ojeda //
93808c999fSMiguel Ojeda #[cfg(feature = "full")]
94808c999fSMiguel Ojeda leftmost_subexpression_in_match_arm: bool,
95808c999fSMiguel Ojeda
96808c999fSMiguel Ojeda // This is the difference between:
97808c999fSMiguel Ojeda //
98808c999fSMiguel Ojeda // if let _ = (Struct {}) {} // needs parens
99808c999fSMiguel Ojeda //
100808c999fSMiguel Ojeda // match () {
101808c999fSMiguel Ojeda // () if let _ = Struct {} => {} // no parens
102808c999fSMiguel Ojeda // }
103808c999fSMiguel Ojeda //
104808c999fSMiguel Ojeda #[cfg(feature = "full")]
105808c999fSMiguel Ojeda condition: bool,
106808c999fSMiguel Ojeda
107808c999fSMiguel Ojeda // This is the difference between:
108808c999fSMiguel Ojeda //
109808c999fSMiguel Ojeda // if break Struct {} == (break) {} // needs parens
110808c999fSMiguel Ojeda //
111808c999fSMiguel Ojeda // if break break == Struct {} {} // no parens
112808c999fSMiguel Ojeda //
113808c999fSMiguel Ojeda #[cfg(feature = "full")]
114808c999fSMiguel Ojeda rightmost_subexpression_in_condition: bool,
115808c999fSMiguel Ojeda
116808c999fSMiguel Ojeda // This is the difference between:
117808c999fSMiguel Ojeda //
118808c999fSMiguel Ojeda // if break ({ x }).field + 1 {} needs parens
119808c999fSMiguel Ojeda //
120808c999fSMiguel Ojeda // if break 1 + { x }.field {} // no parens
121808c999fSMiguel Ojeda //
122808c999fSMiguel Ojeda #[cfg(feature = "full")]
123808c999fSMiguel Ojeda leftmost_subexpression_in_optional_operand: bool,
124808c999fSMiguel Ojeda
125808c999fSMiguel Ojeda // This is the difference between:
126808c999fSMiguel Ojeda //
127808c999fSMiguel Ojeda // let _ = (return) - 1; // without paren, this would return -1
128808c999fSMiguel Ojeda //
129808c999fSMiguel Ojeda // let _ = return + 1; // no paren because '+' cannot begin expr
130808c999fSMiguel Ojeda //
131808c999fSMiguel Ojeda #[cfg(feature = "full")]
132808c999fSMiguel Ojeda next_operator_can_begin_expr: bool,
133808c999fSMiguel Ojeda
134808c999fSMiguel Ojeda // This is the difference between:
135808c999fSMiguel Ojeda //
136808c999fSMiguel Ojeda // let _ = 1 + return 1; // no parens if rightmost subexpression
137808c999fSMiguel Ojeda //
138808c999fSMiguel Ojeda // let _ = 1 + (return 1) + 1; // needs parens
139808c999fSMiguel Ojeda //
140808c999fSMiguel Ojeda #[cfg(feature = "full")]
141808c999fSMiguel Ojeda next_operator_can_continue_expr: bool,
142808c999fSMiguel Ojeda
143808c999fSMiguel Ojeda // This is the difference between:
144808c999fSMiguel Ojeda //
145808c999fSMiguel Ojeda // let _ = x as u8 + T;
146808c999fSMiguel Ojeda //
147808c999fSMiguel Ojeda // let _ = (x as u8) < T;
148808c999fSMiguel Ojeda //
149808c999fSMiguel Ojeda // Without parens, the latter would want to parse `u8<T...` as a type.
150808c999fSMiguel Ojeda next_operator_can_begin_generics: bool,
151808c999fSMiguel Ojeda }
152808c999fSMiguel Ojeda
153808c999fSMiguel Ojeda impl FixupContext {
154808c999fSMiguel Ojeda /// The default amount of fixing is minimal fixing. Fixups should be turned
155808c999fSMiguel Ojeda /// on in a targeted fashion where needed.
156808c999fSMiguel Ojeda pub const NONE: Self = FixupContext {
157808c999fSMiguel Ojeda #[cfg(feature = "full")]
158808c999fSMiguel Ojeda previous_operator: Precedence::MIN,
159808c999fSMiguel Ojeda #[cfg(feature = "full")]
160808c999fSMiguel Ojeda next_operator: Precedence::MIN,
161808c999fSMiguel Ojeda #[cfg(feature = "full")]
162808c999fSMiguel Ojeda stmt: false,
163808c999fSMiguel Ojeda #[cfg(feature = "full")]
164808c999fSMiguel Ojeda leftmost_subexpression_in_stmt: false,
165808c999fSMiguel Ojeda #[cfg(feature = "full")]
166808c999fSMiguel Ojeda match_arm: false,
167808c999fSMiguel Ojeda #[cfg(feature = "full")]
168808c999fSMiguel Ojeda leftmost_subexpression_in_match_arm: false,
169808c999fSMiguel Ojeda #[cfg(feature = "full")]
170808c999fSMiguel Ojeda condition: false,
171808c999fSMiguel Ojeda #[cfg(feature = "full")]
172808c999fSMiguel Ojeda rightmost_subexpression_in_condition: false,
173808c999fSMiguel Ojeda #[cfg(feature = "full")]
174808c999fSMiguel Ojeda leftmost_subexpression_in_optional_operand: false,
175808c999fSMiguel Ojeda #[cfg(feature = "full")]
176808c999fSMiguel Ojeda next_operator_can_begin_expr: false,
177808c999fSMiguel Ojeda #[cfg(feature = "full")]
178808c999fSMiguel Ojeda next_operator_can_continue_expr: false,
179808c999fSMiguel Ojeda next_operator_can_begin_generics: false,
180808c999fSMiguel Ojeda };
181808c999fSMiguel Ojeda
182808c999fSMiguel Ojeda /// Create the initial fixup for printing an expression in statement
183808c999fSMiguel Ojeda /// position.
184808c999fSMiguel Ojeda #[cfg(feature = "full")]
new_stmt() -> Self185808c999fSMiguel Ojeda pub fn new_stmt() -> Self {
186808c999fSMiguel Ojeda FixupContext {
187808c999fSMiguel Ojeda stmt: true,
188808c999fSMiguel Ojeda ..FixupContext::NONE
189808c999fSMiguel Ojeda }
190808c999fSMiguel Ojeda }
191808c999fSMiguel Ojeda
192808c999fSMiguel Ojeda /// Create the initial fixup for printing an expression as the right-hand
193808c999fSMiguel Ojeda /// side of a match arm.
194808c999fSMiguel Ojeda #[cfg(feature = "full")]
new_match_arm() -> Self195808c999fSMiguel Ojeda pub fn new_match_arm() -> Self {
196808c999fSMiguel Ojeda FixupContext {
197808c999fSMiguel Ojeda match_arm: true,
198808c999fSMiguel Ojeda ..FixupContext::NONE
199808c999fSMiguel Ojeda }
200808c999fSMiguel Ojeda }
201808c999fSMiguel Ojeda
202808c999fSMiguel Ojeda /// Create the initial fixup for printing an expression as the "condition"
203808c999fSMiguel Ojeda /// of an `if` or `while`. There are a few other positions which are
204808c999fSMiguel Ojeda /// grammatically equivalent and also use this, such as the iterator
205808c999fSMiguel Ojeda /// expression in `for` and the scrutinee in `match`.
206808c999fSMiguel Ojeda #[cfg(feature = "full")]
new_condition() -> Self207808c999fSMiguel Ojeda pub fn new_condition() -> Self {
208808c999fSMiguel Ojeda FixupContext {
209808c999fSMiguel Ojeda condition: true,
210808c999fSMiguel Ojeda rightmost_subexpression_in_condition: true,
211808c999fSMiguel Ojeda ..FixupContext::NONE
212808c999fSMiguel Ojeda }
213808c999fSMiguel Ojeda }
214808c999fSMiguel Ojeda
215808c999fSMiguel Ojeda /// Transform this fixup into the one that should apply when printing the
216808c999fSMiguel Ojeda /// leftmost subexpression of the current expression.
217808c999fSMiguel Ojeda ///
218808c999fSMiguel Ojeda /// The leftmost subexpression is any subexpression that has the same first
219808c999fSMiguel Ojeda /// token as the current expression, but has a different last token.
220808c999fSMiguel Ojeda ///
221808c999fSMiguel Ojeda /// For example in `$a + $b` and `$a.method()`, the subexpression `$a` is a
222808c999fSMiguel Ojeda /// leftmost subexpression.
223808c999fSMiguel Ojeda ///
224808c999fSMiguel Ojeda /// Not every expression has a leftmost subexpression. For example neither
225808c999fSMiguel Ojeda /// `-$a` nor `[$a]` have one.
leftmost_subexpression_with_operator( self, expr: &Expr, #[cfg(feature = "full")] next_operator_can_begin_expr: bool, next_operator_can_begin_generics: bool, #[cfg(feature = "full")] precedence: Precedence, ) -> (Precedence, Self)226808c999fSMiguel Ojeda pub fn leftmost_subexpression_with_operator(
227808c999fSMiguel Ojeda self,
228808c999fSMiguel Ojeda expr: &Expr,
229808c999fSMiguel Ojeda #[cfg(feature = "full")] next_operator_can_begin_expr: bool,
230808c999fSMiguel Ojeda next_operator_can_begin_generics: bool,
231808c999fSMiguel Ojeda #[cfg(feature = "full")] precedence: Precedence,
232808c999fSMiguel Ojeda ) -> (Precedence, Self) {
233808c999fSMiguel Ojeda let fixup = FixupContext {
234808c999fSMiguel Ojeda #[cfg(feature = "full")]
235808c999fSMiguel Ojeda next_operator: precedence,
236808c999fSMiguel Ojeda #[cfg(feature = "full")]
237808c999fSMiguel Ojeda stmt: false,
238808c999fSMiguel Ojeda #[cfg(feature = "full")]
239808c999fSMiguel Ojeda leftmost_subexpression_in_stmt: self.stmt || self.leftmost_subexpression_in_stmt,
240808c999fSMiguel Ojeda #[cfg(feature = "full")]
241808c999fSMiguel Ojeda match_arm: false,
242808c999fSMiguel Ojeda #[cfg(feature = "full")]
243808c999fSMiguel Ojeda leftmost_subexpression_in_match_arm: self.match_arm
244808c999fSMiguel Ojeda || self.leftmost_subexpression_in_match_arm,
245808c999fSMiguel Ojeda #[cfg(feature = "full")]
246808c999fSMiguel Ojeda rightmost_subexpression_in_condition: false,
247808c999fSMiguel Ojeda #[cfg(feature = "full")]
248808c999fSMiguel Ojeda next_operator_can_begin_expr,
249808c999fSMiguel Ojeda #[cfg(feature = "full")]
250808c999fSMiguel Ojeda next_operator_can_continue_expr: true,
251808c999fSMiguel Ojeda next_operator_can_begin_generics,
252808c999fSMiguel Ojeda ..self
253808c999fSMiguel Ojeda };
254808c999fSMiguel Ojeda
255808c999fSMiguel Ojeda (fixup.leftmost_subexpression_precedence(expr), fixup)
256808c999fSMiguel Ojeda }
257808c999fSMiguel Ojeda
258808c999fSMiguel Ojeda /// Transform this fixup into the one that should apply when printing a
259808c999fSMiguel Ojeda /// leftmost subexpression followed by a `.` or `?` token, which confer
260808c999fSMiguel Ojeda /// different statement boundary rules compared to other leftmost
261808c999fSMiguel Ojeda /// subexpressions.
leftmost_subexpression_with_dot(self, expr: &Expr) -> (Precedence, Self)262808c999fSMiguel Ojeda pub fn leftmost_subexpression_with_dot(self, expr: &Expr) -> (Precedence, Self) {
263808c999fSMiguel Ojeda let fixup = FixupContext {
264808c999fSMiguel Ojeda #[cfg(feature = "full")]
265808c999fSMiguel Ojeda next_operator: Precedence::Unambiguous,
266808c999fSMiguel Ojeda #[cfg(feature = "full")]
267808c999fSMiguel Ojeda stmt: self.stmt || self.leftmost_subexpression_in_stmt,
268808c999fSMiguel Ojeda #[cfg(feature = "full")]
269808c999fSMiguel Ojeda leftmost_subexpression_in_stmt: false,
270808c999fSMiguel Ojeda #[cfg(feature = "full")]
271808c999fSMiguel Ojeda match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm,
272808c999fSMiguel Ojeda #[cfg(feature = "full")]
273808c999fSMiguel Ojeda leftmost_subexpression_in_match_arm: false,
274808c999fSMiguel Ojeda #[cfg(feature = "full")]
275808c999fSMiguel Ojeda rightmost_subexpression_in_condition: false,
276808c999fSMiguel Ojeda #[cfg(feature = "full")]
277808c999fSMiguel Ojeda next_operator_can_begin_expr: false,
278808c999fSMiguel Ojeda #[cfg(feature = "full")]
279808c999fSMiguel Ojeda next_operator_can_continue_expr: true,
280808c999fSMiguel Ojeda next_operator_can_begin_generics: false,
281808c999fSMiguel Ojeda ..self
282808c999fSMiguel Ojeda };
283808c999fSMiguel Ojeda
284808c999fSMiguel Ojeda (fixup.leftmost_subexpression_precedence(expr), fixup)
285808c999fSMiguel Ojeda }
286808c999fSMiguel Ojeda
leftmost_subexpression_precedence(self, expr: &Expr) -> Precedence287808c999fSMiguel Ojeda fn leftmost_subexpression_precedence(self, expr: &Expr) -> Precedence {
288808c999fSMiguel Ojeda #[cfg(feature = "full")]
289808c999fSMiguel Ojeda if !self.next_operator_can_begin_expr || self.next_operator == Precedence::Range {
290808c999fSMiguel Ojeda if let Scan::Bailout = scan_right(expr, self, Precedence::MIN, 0, 0) {
291808c999fSMiguel Ojeda if scan_left(expr, self) {
292808c999fSMiguel Ojeda return Precedence::Unambiguous;
293808c999fSMiguel Ojeda }
294808c999fSMiguel Ojeda }
295808c999fSMiguel Ojeda }
296808c999fSMiguel Ojeda
297808c999fSMiguel Ojeda self.precedence(expr)
298808c999fSMiguel Ojeda }
299808c999fSMiguel Ojeda
300808c999fSMiguel Ojeda /// Transform this fixup into the one that should apply when printing the
301808c999fSMiguel Ojeda /// rightmost subexpression of the current expression.
302808c999fSMiguel Ojeda ///
303808c999fSMiguel Ojeda /// The rightmost subexpression is any subexpression that has a different
304808c999fSMiguel Ojeda /// first token than the current expression, but has the same last token.
305808c999fSMiguel Ojeda ///
306808c999fSMiguel Ojeda /// For example in `$a + $b` and `-$b`, the subexpression `$b` is a
307808c999fSMiguel Ojeda /// rightmost subexpression.
308808c999fSMiguel Ojeda ///
309808c999fSMiguel Ojeda /// Not every expression has a rightmost subexpression. For example neither
310808c999fSMiguel Ojeda /// `[$b]` nor `$a.f($b)` have one.
rightmost_subexpression( self, expr: &Expr, #[cfg(feature = "full")] precedence: Precedence, ) -> (Precedence, Self)311808c999fSMiguel Ojeda pub fn rightmost_subexpression(
312808c999fSMiguel Ojeda self,
313808c999fSMiguel Ojeda expr: &Expr,
314808c999fSMiguel Ojeda #[cfg(feature = "full")] precedence: Precedence,
315808c999fSMiguel Ojeda ) -> (Precedence, Self) {
316808c999fSMiguel Ojeda let fixup = self.rightmost_subexpression_fixup(
317808c999fSMiguel Ojeda #[cfg(feature = "full")]
318808c999fSMiguel Ojeda false,
319808c999fSMiguel Ojeda #[cfg(feature = "full")]
320808c999fSMiguel Ojeda false,
321808c999fSMiguel Ojeda #[cfg(feature = "full")]
322808c999fSMiguel Ojeda precedence,
323808c999fSMiguel Ojeda );
324808c999fSMiguel Ojeda (fixup.rightmost_subexpression_precedence(expr), fixup)
325808c999fSMiguel Ojeda }
326808c999fSMiguel Ojeda
rightmost_subexpression_fixup( self, #[cfg(feature = "full")] reset_allow_struct: bool, #[cfg(feature = "full")] optional_operand: bool, #[cfg(feature = "full")] precedence: Precedence, ) -> Self327808c999fSMiguel Ojeda pub fn rightmost_subexpression_fixup(
328808c999fSMiguel Ojeda self,
329808c999fSMiguel Ojeda #[cfg(feature = "full")] reset_allow_struct: bool,
330808c999fSMiguel Ojeda #[cfg(feature = "full")] optional_operand: bool,
331808c999fSMiguel Ojeda #[cfg(feature = "full")] precedence: Precedence,
332808c999fSMiguel Ojeda ) -> Self {
333808c999fSMiguel Ojeda FixupContext {
334808c999fSMiguel Ojeda #[cfg(feature = "full")]
335808c999fSMiguel Ojeda previous_operator: precedence,
336808c999fSMiguel Ojeda #[cfg(feature = "full")]
337808c999fSMiguel Ojeda stmt: false,
338808c999fSMiguel Ojeda #[cfg(feature = "full")]
339808c999fSMiguel Ojeda leftmost_subexpression_in_stmt: false,
340808c999fSMiguel Ojeda #[cfg(feature = "full")]
341808c999fSMiguel Ojeda match_arm: false,
342808c999fSMiguel Ojeda #[cfg(feature = "full")]
343808c999fSMiguel Ojeda leftmost_subexpression_in_match_arm: false,
344808c999fSMiguel Ojeda #[cfg(feature = "full")]
345808c999fSMiguel Ojeda condition: self.condition && !reset_allow_struct,
346808c999fSMiguel Ojeda #[cfg(feature = "full")]
347808c999fSMiguel Ojeda leftmost_subexpression_in_optional_operand: self.condition && optional_operand,
348808c999fSMiguel Ojeda ..self
349808c999fSMiguel Ojeda }
350808c999fSMiguel Ojeda }
351808c999fSMiguel Ojeda
rightmost_subexpression_precedence(self, expr: &Expr) -> Precedence352808c999fSMiguel Ojeda pub fn rightmost_subexpression_precedence(self, expr: &Expr) -> Precedence {
353808c999fSMiguel Ojeda let default_prec = self.precedence(expr);
354808c999fSMiguel Ojeda
355808c999fSMiguel Ojeda #[cfg(feature = "full")]
356808c999fSMiguel Ojeda if match self.previous_operator {
357808c999fSMiguel Ojeda Precedence::Assign | Precedence::Let | Precedence::Prefix => {
358808c999fSMiguel Ojeda default_prec < self.previous_operator
359808c999fSMiguel Ojeda }
360808c999fSMiguel Ojeda _ => default_prec <= self.previous_operator,
361808c999fSMiguel Ojeda } && match self.next_operator {
362808c999fSMiguel Ojeda Precedence::Range | Precedence::Or | Precedence::And => true,
363808c999fSMiguel Ojeda _ => !self.next_operator_can_begin_expr,
364808c999fSMiguel Ojeda } {
365808c999fSMiguel Ojeda if let Scan::Bailout | Scan::Fail = scan_right(expr, self, self.previous_operator, 1, 0)
366808c999fSMiguel Ojeda {
367808c999fSMiguel Ojeda if scan_left(expr, self) {
368808c999fSMiguel Ojeda return Precedence::Prefix;
369808c999fSMiguel Ojeda }
370808c999fSMiguel Ojeda }
371808c999fSMiguel Ojeda }
372808c999fSMiguel Ojeda
373808c999fSMiguel Ojeda default_prec
374808c999fSMiguel Ojeda }
375808c999fSMiguel Ojeda
376808c999fSMiguel Ojeda /// Determine whether parentheses are needed around the given expression to
377808c999fSMiguel Ojeda /// head off the early termination of a statement or condition.
378808c999fSMiguel Ojeda #[cfg(feature = "full")]
parenthesize(self, expr: &Expr) -> bool379808c999fSMiguel Ojeda pub fn parenthesize(self, expr: &Expr) -> bool {
380808c999fSMiguel Ojeda (self.leftmost_subexpression_in_stmt && !classify::requires_semi_to_be_stmt(expr))
381808c999fSMiguel Ojeda || ((self.stmt || self.leftmost_subexpression_in_stmt) && matches!(expr, Expr::Let(_)))
382808c999fSMiguel Ojeda || (self.leftmost_subexpression_in_match_arm
383808c999fSMiguel Ojeda && !classify::requires_comma_to_be_match_arm(expr))
384808c999fSMiguel Ojeda || (self.condition && matches!(expr, Expr::Struct(_)))
385808c999fSMiguel Ojeda || (self.rightmost_subexpression_in_condition
386808c999fSMiguel Ojeda && matches!(
387808c999fSMiguel Ojeda expr,
388808c999fSMiguel Ojeda Expr::Return(ExprReturn { expr: None, .. })
389808c999fSMiguel Ojeda | Expr::Yield(ExprYield { expr: None, .. })
390808c999fSMiguel Ojeda ))
391808c999fSMiguel Ojeda || (self.rightmost_subexpression_in_condition
392808c999fSMiguel Ojeda && !self.condition
393808c999fSMiguel Ojeda && matches!(
394808c999fSMiguel Ojeda expr,
395808c999fSMiguel Ojeda Expr::Break(ExprBreak { expr: None, .. })
396808c999fSMiguel Ojeda | Expr::Path(_)
397808c999fSMiguel Ojeda | Expr::Range(ExprRange { end: None, .. })
398808c999fSMiguel Ojeda ))
399808c999fSMiguel Ojeda || (self.leftmost_subexpression_in_optional_operand
400808c999fSMiguel Ojeda && matches!(expr, Expr::Block(expr) if expr.attrs.is_empty() && expr.label.is_none()))
401808c999fSMiguel Ojeda }
402808c999fSMiguel Ojeda
403808c999fSMiguel Ojeda /// Determines the effective precedence of a subexpression. Some expressions
404808c999fSMiguel Ojeda /// have higher or lower precedence when adjacent to particular operators.
precedence(self, expr: &Expr) -> Precedence405808c999fSMiguel Ojeda fn precedence(self, expr: &Expr) -> Precedence {
406808c999fSMiguel Ojeda #[cfg(feature = "full")]
407808c999fSMiguel Ojeda if self.next_operator_can_begin_expr {
408808c999fSMiguel Ojeda // Decrease precedence of value-less jumps when followed by an
409808c999fSMiguel Ojeda // operator that would otherwise get interpreted as beginning a
410808c999fSMiguel Ojeda // value for the jump.
411808c999fSMiguel Ojeda if let Expr::Break(ExprBreak { expr: None, .. })
412808c999fSMiguel Ojeda | Expr::Return(ExprReturn { expr: None, .. })
413808c999fSMiguel Ojeda | Expr::Yield(ExprYield { expr: None, .. }) = expr
414808c999fSMiguel Ojeda {
415808c999fSMiguel Ojeda return Precedence::Jump;
416808c999fSMiguel Ojeda }
417808c999fSMiguel Ojeda }
418808c999fSMiguel Ojeda
419808c999fSMiguel Ojeda #[cfg(feature = "full")]
420808c999fSMiguel Ojeda if !self.next_operator_can_continue_expr {
421808c999fSMiguel Ojeda match expr {
422808c999fSMiguel Ojeda // Increase precedence of expressions that extend to the end of
423808c999fSMiguel Ojeda // current statement or group.
424808c999fSMiguel Ojeda Expr::Break(_)
425808c999fSMiguel Ojeda | Expr::Closure(_)
426808c999fSMiguel Ojeda | Expr::Let(_)
427808c999fSMiguel Ojeda | Expr::Return(_)
428808c999fSMiguel Ojeda | Expr::Yield(_) => {
429808c999fSMiguel Ojeda return Precedence::Prefix;
430808c999fSMiguel Ojeda }
431808c999fSMiguel Ojeda Expr::Range(e) if e.start.is_none() => return Precedence::Prefix,
432808c999fSMiguel Ojeda _ => {}
433808c999fSMiguel Ojeda }
434808c999fSMiguel Ojeda }
435808c999fSMiguel Ojeda
436808c999fSMiguel Ojeda if self.next_operator_can_begin_generics {
437808c999fSMiguel Ojeda if let Expr::Cast(cast) = expr {
438808c999fSMiguel Ojeda if classify::trailing_unparameterized_path(&cast.ty) {
439808c999fSMiguel Ojeda return Precedence::MIN;
440808c999fSMiguel Ojeda }
441808c999fSMiguel Ojeda }
442808c999fSMiguel Ojeda }
443808c999fSMiguel Ojeda
444808c999fSMiguel Ojeda Precedence::of(expr)
445808c999fSMiguel Ojeda }
446808c999fSMiguel Ojeda }
447808c999fSMiguel Ojeda
448808c999fSMiguel Ojeda impl Copy for FixupContext {}
449808c999fSMiguel Ojeda
450808c999fSMiguel Ojeda impl Clone for FixupContext {
clone(&self) -> Self451808c999fSMiguel Ojeda fn clone(&self) -> Self {
452808c999fSMiguel Ojeda *self
453808c999fSMiguel Ojeda }
454808c999fSMiguel Ojeda }
455808c999fSMiguel Ojeda
456808c999fSMiguel Ojeda #[cfg(feature = "full")]
457808c999fSMiguel Ojeda enum Scan {
458808c999fSMiguel Ojeda Fail,
459808c999fSMiguel Ojeda Bailout,
460808c999fSMiguel Ojeda Consume,
461808c999fSMiguel Ojeda }
462808c999fSMiguel Ojeda
463808c999fSMiguel Ojeda #[cfg(feature = "full")]
464808c999fSMiguel Ojeda impl Copy for Scan {}
465808c999fSMiguel Ojeda
466808c999fSMiguel Ojeda #[cfg(feature = "full")]
467808c999fSMiguel Ojeda impl Clone for Scan {
clone(&self) -> Self468808c999fSMiguel Ojeda fn clone(&self) -> Self {
469808c999fSMiguel Ojeda *self
470808c999fSMiguel Ojeda }
471808c999fSMiguel Ojeda }
472808c999fSMiguel Ojeda
473808c999fSMiguel Ojeda #[cfg(feature = "full")]
474808c999fSMiguel Ojeda impl PartialEq for Scan {
eq(&self, other: &Self) -> bool475808c999fSMiguel Ojeda fn eq(&self, other: &Self) -> bool {
476808c999fSMiguel Ojeda *self as u8 == *other as u8
477808c999fSMiguel Ojeda }
478808c999fSMiguel Ojeda }
479808c999fSMiguel Ojeda
480808c999fSMiguel Ojeda #[cfg(feature = "full")]
scan_left(expr: &Expr, fixup: FixupContext) -> bool481808c999fSMiguel Ojeda fn scan_left(expr: &Expr, fixup: FixupContext) -> bool {
482808c999fSMiguel Ojeda match expr {
483808c999fSMiguel Ojeda Expr::Assign(_) => fixup.previous_operator <= Precedence::Assign,
484808c999fSMiguel Ojeda Expr::Binary(e) => match Precedence::of_binop(&e.op) {
485808c999fSMiguel Ojeda Precedence::Assign => fixup.previous_operator <= Precedence::Assign,
486808c999fSMiguel Ojeda binop_prec => fixup.previous_operator < binop_prec,
487808c999fSMiguel Ojeda },
488808c999fSMiguel Ojeda Expr::Cast(_) => fixup.previous_operator < Precedence::Cast,
489808c999fSMiguel Ojeda Expr::Range(e) => e.start.is_none() || fixup.previous_operator < Precedence::Assign,
490808c999fSMiguel Ojeda _ => true,
491808c999fSMiguel Ojeda }
492808c999fSMiguel Ojeda }
493808c999fSMiguel Ojeda
494808c999fSMiguel Ojeda #[cfg(feature = "full")]
scan_right( expr: &Expr, fixup: FixupContext, precedence: Precedence, fail_offset: u8, bailout_offset: u8, ) -> Scan495808c999fSMiguel Ojeda fn scan_right(
496808c999fSMiguel Ojeda expr: &Expr,
497808c999fSMiguel Ojeda fixup: FixupContext,
498808c999fSMiguel Ojeda precedence: Precedence,
499808c999fSMiguel Ojeda fail_offset: u8,
500808c999fSMiguel Ojeda bailout_offset: u8,
501808c999fSMiguel Ojeda ) -> Scan {
502808c999fSMiguel Ojeda let consume_by_precedence = if match precedence {
503808c999fSMiguel Ojeda Precedence::Assign | Precedence::Compare => precedence <= fixup.next_operator,
504808c999fSMiguel Ojeda _ => precedence < fixup.next_operator,
505808c999fSMiguel Ojeda } || fixup.next_operator == Precedence::MIN
506808c999fSMiguel Ojeda {
507808c999fSMiguel Ojeda Scan::Consume
508808c999fSMiguel Ojeda } else {
509808c999fSMiguel Ojeda Scan::Bailout
510808c999fSMiguel Ojeda };
511808c999fSMiguel Ojeda if fixup.parenthesize(expr) {
512808c999fSMiguel Ojeda return consume_by_precedence;
513808c999fSMiguel Ojeda }
514808c999fSMiguel Ojeda match expr {
515808c999fSMiguel Ojeda Expr::Assign(e) if e.attrs.is_empty() => {
516808c999fSMiguel Ojeda if match fixup.next_operator {
517808c999fSMiguel Ojeda Precedence::Unambiguous => fail_offset >= 2,
518808c999fSMiguel Ojeda _ => bailout_offset >= 1,
519808c999fSMiguel Ojeda } {
520808c999fSMiguel Ojeda return Scan::Consume;
521808c999fSMiguel Ojeda }
522808c999fSMiguel Ojeda let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign);
523808c999fSMiguel Ojeda let scan = scan_right(
524808c999fSMiguel Ojeda &e.right,
525808c999fSMiguel Ojeda right_fixup,
526808c999fSMiguel Ojeda Precedence::Assign,
527808c999fSMiguel Ojeda match fixup.next_operator {
528808c999fSMiguel Ojeda Precedence::Unambiguous => fail_offset,
529808c999fSMiguel Ojeda _ => 1,
530808c999fSMiguel Ojeda },
531808c999fSMiguel Ojeda 1,
532808c999fSMiguel Ojeda );
533808c999fSMiguel Ojeda if let Scan::Bailout | Scan::Consume = scan {
534808c999fSMiguel Ojeda Scan::Consume
535808c999fSMiguel Ojeda } else if let Precedence::Unambiguous = fixup.next_operator {
536808c999fSMiguel Ojeda Scan::Fail
537808c999fSMiguel Ojeda } else {
538808c999fSMiguel Ojeda Scan::Bailout
539808c999fSMiguel Ojeda }
540808c999fSMiguel Ojeda }
541808c999fSMiguel Ojeda Expr::Binary(e) if e.attrs.is_empty() => {
542808c999fSMiguel Ojeda if match fixup.next_operator {
543808c999fSMiguel Ojeda Precedence::Unambiguous => {
544808c999fSMiguel Ojeda fail_offset >= 2
545808c999fSMiguel Ojeda && (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
546808c999fSMiguel Ojeda }
547808c999fSMiguel Ojeda _ => bailout_offset >= 1,
548808c999fSMiguel Ojeda } {
549808c999fSMiguel Ojeda return Scan::Consume;
550808c999fSMiguel Ojeda }
551808c999fSMiguel Ojeda let binop_prec = Precedence::of_binop(&e.op);
552808c999fSMiguel Ojeda if binop_prec == Precedence::Compare && fixup.next_operator == Precedence::Compare {
553808c999fSMiguel Ojeda return Scan::Consume;
554808c999fSMiguel Ojeda }
555808c999fSMiguel Ojeda let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec);
556808c999fSMiguel Ojeda let scan = scan_right(
557808c999fSMiguel Ojeda &e.right,
558808c999fSMiguel Ojeda right_fixup,
559808c999fSMiguel Ojeda binop_prec,
560808c999fSMiguel Ojeda match fixup.next_operator {
561808c999fSMiguel Ojeda Precedence::Unambiguous => fail_offset,
562808c999fSMiguel Ojeda _ => 1,
563808c999fSMiguel Ojeda },
564808c999fSMiguel Ojeda consume_by_precedence as u8 - Scan::Bailout as u8,
565808c999fSMiguel Ojeda );
566808c999fSMiguel Ojeda match scan {
567808c999fSMiguel Ojeda Scan::Fail => {}
568808c999fSMiguel Ojeda Scan::Bailout => return consume_by_precedence,
569808c999fSMiguel Ojeda Scan::Consume => return Scan::Consume,
570808c999fSMiguel Ojeda }
571808c999fSMiguel Ojeda let right_needs_group = binop_prec != Precedence::Assign
572808c999fSMiguel Ojeda && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
573808c999fSMiguel Ojeda if right_needs_group {
574808c999fSMiguel Ojeda consume_by_precedence
575808c999fSMiguel Ojeda } else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
576808c999fSMiguel Ojeda Scan::Fail
577808c999fSMiguel Ojeda } else {
578808c999fSMiguel Ojeda Scan::Bailout
579808c999fSMiguel Ojeda }
580808c999fSMiguel Ojeda }
581808c999fSMiguel Ojeda Expr::RawAddr(ExprRawAddr { expr, .. })
582808c999fSMiguel Ojeda | Expr::Reference(ExprReference { expr, .. })
583808c999fSMiguel Ojeda | Expr::Unary(ExprUnary { expr, .. }) => {
584808c999fSMiguel Ojeda if match fixup.next_operator {
585808c999fSMiguel Ojeda Precedence::Unambiguous => {
586808c999fSMiguel Ojeda fail_offset >= 2
587808c999fSMiguel Ojeda && (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
588808c999fSMiguel Ojeda }
589808c999fSMiguel Ojeda _ => bailout_offset >= 1,
590808c999fSMiguel Ojeda } {
591808c999fSMiguel Ojeda return Scan::Consume;
592808c999fSMiguel Ojeda }
593808c999fSMiguel Ojeda let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Prefix);
594808c999fSMiguel Ojeda let scan = scan_right(
595808c999fSMiguel Ojeda expr,
596808c999fSMiguel Ojeda right_fixup,
597808c999fSMiguel Ojeda precedence,
598808c999fSMiguel Ojeda match fixup.next_operator {
599808c999fSMiguel Ojeda Precedence::Unambiguous => fail_offset,
600808c999fSMiguel Ojeda _ => 1,
601808c999fSMiguel Ojeda },
602808c999fSMiguel Ojeda consume_by_precedence as u8 - Scan::Bailout as u8,
603808c999fSMiguel Ojeda );
604808c999fSMiguel Ojeda match scan {
605808c999fSMiguel Ojeda Scan::Fail => {}
606808c999fSMiguel Ojeda Scan::Bailout => return consume_by_precedence,
607808c999fSMiguel Ojeda Scan::Consume => return Scan::Consume,
608808c999fSMiguel Ojeda }
609808c999fSMiguel Ojeda if right_fixup.rightmost_subexpression_precedence(expr) < Precedence::Prefix {
610808c999fSMiguel Ojeda consume_by_precedence
611808c999fSMiguel Ojeda } else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
612808c999fSMiguel Ojeda Scan::Fail
613808c999fSMiguel Ojeda } else {
614808c999fSMiguel Ojeda Scan::Bailout
615808c999fSMiguel Ojeda }
616808c999fSMiguel Ojeda }
617808c999fSMiguel Ojeda Expr::Range(e) if e.attrs.is_empty() => match &e.end {
618808c999fSMiguel Ojeda Some(end) => {
619808c999fSMiguel Ojeda if fail_offset >= 2 {
620808c999fSMiguel Ojeda return Scan::Consume;
621808c999fSMiguel Ojeda }
622808c999fSMiguel Ojeda let right_fixup =
623808c999fSMiguel Ojeda fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
624808c999fSMiguel Ojeda let scan = scan_right(
625808c999fSMiguel Ojeda end,
626808c999fSMiguel Ojeda right_fixup,
627808c999fSMiguel Ojeda Precedence::Range,
628808c999fSMiguel Ojeda fail_offset,
629808c999fSMiguel Ojeda match fixup.next_operator {
630808c999fSMiguel Ojeda Precedence::Assign | Precedence::Range => 0,
631808c999fSMiguel Ojeda _ => 1,
632808c999fSMiguel Ojeda },
633808c999fSMiguel Ojeda );
634808c999fSMiguel Ojeda if match (scan, fixup.next_operator) {
635808c999fSMiguel Ojeda (Scan::Fail, _) => false,
636808c999fSMiguel Ojeda (Scan::Bailout, Precedence::Assign | Precedence::Range) => false,
637808c999fSMiguel Ojeda (Scan::Bailout | Scan::Consume, _) => true,
638808c999fSMiguel Ojeda } {
639808c999fSMiguel Ojeda return Scan::Consume;
640808c999fSMiguel Ojeda }
641808c999fSMiguel Ojeda if right_fixup.rightmost_subexpression_precedence(end) <= Precedence::Range {
642808c999fSMiguel Ojeda Scan::Consume
643808c999fSMiguel Ojeda } else {
644808c999fSMiguel Ojeda Scan::Fail
645808c999fSMiguel Ojeda }
646808c999fSMiguel Ojeda }
647808c999fSMiguel Ojeda None => {
648808c999fSMiguel Ojeda if fixup.next_operator_can_begin_expr {
649808c999fSMiguel Ojeda Scan::Consume
650808c999fSMiguel Ojeda } else {
651808c999fSMiguel Ojeda Scan::Fail
652808c999fSMiguel Ojeda }
653808c999fSMiguel Ojeda }
654808c999fSMiguel Ojeda },
655808c999fSMiguel Ojeda Expr::Break(e) => match &e.expr {
656808c999fSMiguel Ojeda Some(value) => {
657808c999fSMiguel Ojeda if bailout_offset >= 1 || e.label.is_none() && classify::expr_leading_label(value) {
658808c999fSMiguel Ojeda return Scan::Consume;
659808c999fSMiguel Ojeda }
660808c999fSMiguel Ojeda let right_fixup = fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump);
661808c999fSMiguel Ojeda match scan_right(value, right_fixup, Precedence::Jump, 1, 1) {
662808c999fSMiguel Ojeda Scan::Fail => Scan::Bailout,
663808c999fSMiguel Ojeda Scan::Bailout | Scan::Consume => Scan::Consume,
664808c999fSMiguel Ojeda }
665808c999fSMiguel Ojeda }
666808c999fSMiguel Ojeda None => match fixup.next_operator {
667808c999fSMiguel Ojeda Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
668808c999fSMiguel Ojeda _ => Scan::Consume,
669808c999fSMiguel Ojeda },
670808c999fSMiguel Ojeda },
671808c999fSMiguel Ojeda Expr::Return(ExprReturn { expr, .. }) | Expr::Yield(ExprYield { expr, .. }) => match expr {
672808c999fSMiguel Ojeda Some(e) => {
673808c999fSMiguel Ojeda if bailout_offset >= 1 {
674808c999fSMiguel Ojeda return Scan::Consume;
675808c999fSMiguel Ojeda }
676808c999fSMiguel Ojeda let right_fixup =
677808c999fSMiguel Ojeda fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump);
678808c999fSMiguel Ojeda match scan_right(e, right_fixup, Precedence::Jump, 1, 1) {
679808c999fSMiguel Ojeda Scan::Fail => Scan::Bailout,
680808c999fSMiguel Ojeda Scan::Bailout | Scan::Consume => Scan::Consume,
681808c999fSMiguel Ojeda }
682808c999fSMiguel Ojeda }
683808c999fSMiguel Ojeda None => match fixup.next_operator {
684808c999fSMiguel Ojeda Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
685808c999fSMiguel Ojeda _ => Scan::Consume,
686808c999fSMiguel Ojeda },
687808c999fSMiguel Ojeda },
688808c999fSMiguel Ojeda Expr::Closure(e) => {
689808c999fSMiguel Ojeda if matches!(e.output, ReturnType::Default)
690808c999fSMiguel Ojeda || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
691808c999fSMiguel Ojeda {
692808c999fSMiguel Ojeda if bailout_offset >= 1 {
693808c999fSMiguel Ojeda return Scan::Consume;
694808c999fSMiguel Ojeda }
695808c999fSMiguel Ojeda let right_fixup =
696808c999fSMiguel Ojeda fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump);
697808c999fSMiguel Ojeda match scan_right(&e.body, right_fixup, Precedence::Jump, 1, 1) {
698808c999fSMiguel Ojeda Scan::Fail => Scan::Bailout,
699808c999fSMiguel Ojeda Scan::Bailout | Scan::Consume => Scan::Consume,
700808c999fSMiguel Ojeda }
701808c999fSMiguel Ojeda } else {
702808c999fSMiguel Ojeda Scan::Consume
703808c999fSMiguel Ojeda }
704808c999fSMiguel Ojeda }
705808c999fSMiguel Ojeda Expr::Let(e) => {
706808c999fSMiguel Ojeda if bailout_offset >= 1 {
707808c999fSMiguel Ojeda return Scan::Consume;
708808c999fSMiguel Ojeda }
709808c999fSMiguel Ojeda let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Let);
710808c999fSMiguel Ojeda let scan = scan_right(
711808c999fSMiguel Ojeda &e.expr,
712808c999fSMiguel Ojeda right_fixup,
713808c999fSMiguel Ojeda Precedence::Let,
714808c999fSMiguel Ojeda 1,
715808c999fSMiguel Ojeda if fixup.next_operator < Precedence::Let {
716808c999fSMiguel Ojeda 0
717808c999fSMiguel Ojeda } else {
718808c999fSMiguel Ojeda 1
719808c999fSMiguel Ojeda },
720808c999fSMiguel Ojeda );
721808c999fSMiguel Ojeda match scan {
722808c999fSMiguel Ojeda Scan::Fail | Scan::Bailout if fixup.next_operator < Precedence::Let => {
723808c999fSMiguel Ojeda return Scan::Bailout;
724808c999fSMiguel Ojeda }
725808c999fSMiguel Ojeda Scan::Consume => return Scan::Consume,
726808c999fSMiguel Ojeda _ => {}
727808c999fSMiguel Ojeda }
728808c999fSMiguel Ojeda if right_fixup.rightmost_subexpression_precedence(&e.expr) < Precedence::Let {
729808c999fSMiguel Ojeda Scan::Consume
730808c999fSMiguel Ojeda } else if let Scan::Fail = scan {
731808c999fSMiguel Ojeda Scan::Bailout
732808c999fSMiguel Ojeda } else {
733808c999fSMiguel Ojeda Scan::Consume
734808c999fSMiguel Ojeda }
735808c999fSMiguel Ojeda }
736808c999fSMiguel Ojeda Expr::Array(_)
737808c999fSMiguel Ojeda | Expr::Assign(_)
738808c999fSMiguel Ojeda | Expr::Async(_)
739808c999fSMiguel Ojeda | Expr::Await(_)
740808c999fSMiguel Ojeda | Expr::Binary(_)
741808c999fSMiguel Ojeda | Expr::Block(_)
742808c999fSMiguel Ojeda | Expr::Call(_)
743808c999fSMiguel Ojeda | Expr::Cast(_)
744808c999fSMiguel Ojeda | Expr::Const(_)
745808c999fSMiguel Ojeda | Expr::Continue(_)
746808c999fSMiguel Ojeda | Expr::Field(_)
747808c999fSMiguel Ojeda | Expr::ForLoop(_)
748808c999fSMiguel Ojeda | Expr::Group(_)
749808c999fSMiguel Ojeda | Expr::If(_)
750808c999fSMiguel Ojeda | Expr::Index(_)
751808c999fSMiguel Ojeda | Expr::Infer(_)
752808c999fSMiguel Ojeda | Expr::Lit(_)
753808c999fSMiguel Ojeda | Expr::Loop(_)
754808c999fSMiguel Ojeda | Expr::Macro(_)
755808c999fSMiguel Ojeda | Expr::Match(_)
756808c999fSMiguel Ojeda | Expr::MethodCall(_)
757808c999fSMiguel Ojeda | Expr::Paren(_)
758808c999fSMiguel Ojeda | Expr::Path(_)
759808c999fSMiguel Ojeda | Expr::Range(_)
760808c999fSMiguel Ojeda | Expr::Repeat(_)
761808c999fSMiguel Ojeda | Expr::Struct(_)
762808c999fSMiguel Ojeda | Expr::Try(_)
763808c999fSMiguel Ojeda | Expr::TryBlock(_)
764808c999fSMiguel Ojeda | Expr::Tuple(_)
765808c999fSMiguel Ojeda | Expr::Unsafe(_)
766808c999fSMiguel Ojeda | Expr::Verbatim(_)
767808c999fSMiguel Ojeda | Expr::While(_) => match fixup.next_operator {
768808c999fSMiguel Ojeda Precedence::Assign | Precedence::Range if precedence == Precedence::Range => Scan::Fail,
769808c999fSMiguel Ojeda _ if precedence == Precedence::Let && fixup.next_operator < Precedence::Let => {
770808c999fSMiguel Ojeda Scan::Fail
771808c999fSMiguel Ojeda }
772808c999fSMiguel Ojeda _ => consume_by_precedence,
773808c999fSMiguel Ojeda },
774808c999fSMiguel Ojeda }
775808c999fSMiguel Ojeda }
776