mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Parenthesize break values containing leading label
This commit is contained in:
parent
5f37433b6c
commit
06982239a6
@ -1,7 +1,8 @@
|
||||
//! Routines the parser and pretty-printer use to classify AST nodes.
|
||||
|
||||
use crate::ast::ExprKind::*;
|
||||
use crate::{ast, token::Delimiter};
|
||||
use crate::ast::{self, MatchKind};
|
||||
use crate::token::Delimiter;
|
||||
|
||||
/// This classification determines whether various syntactic positions break out
|
||||
/// of parsing the current expression (true) or continue parsing more of the
|
||||
@ -81,6 +82,82 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the leftmost token of the given expression is the label of a
|
||||
/// labeled loop or block, such as in `'inner: loop { break 'inner 1 } + 1`.
|
||||
///
|
||||
/// Such expressions are not allowed as the value of an unlabeled break.
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// 'outer: {
|
||||
/// break 'inner: loop { break 'inner 1 } + 1; // invalid syntax
|
||||
///
|
||||
/// break 'outer 'inner: loop { break 'inner 1 } + 1; // okay
|
||||
///
|
||||
/// break ('inner: loop { break 'inner 1 } + 1); // okay
|
||||
///
|
||||
/// break ('inner: loop { break 'inner 1 }) + 1; // okay
|
||||
/// }
|
||||
/// ```
|
||||
pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
|
||||
loop {
|
||||
match &expr.kind {
|
||||
Block(_, label) | ForLoop { label, .. } | Loop(_, label, _) | While(_, _, label) => {
|
||||
return label.is_some();
|
||||
}
|
||||
|
||||
Assign(e, _, _)
|
||||
| AssignOp(_, e, _)
|
||||
| Await(e, _)
|
||||
| Binary(_, e, _)
|
||||
| Call(e, _)
|
||||
| Cast(e, _)
|
||||
| Field(e, _)
|
||||
| Index(e, _, _)
|
||||
| Match(e, _, MatchKind::Postfix)
|
||||
| Range(Some(e), _, _)
|
||||
| Try(e) => {
|
||||
expr = e;
|
||||
}
|
||||
MethodCall(method_call) => {
|
||||
expr = &method_call.receiver;
|
||||
}
|
||||
|
||||
AddrOf(..)
|
||||
| Array(..)
|
||||
| Become(..)
|
||||
| Break(..)
|
||||
| Closure(..)
|
||||
| ConstBlock(..)
|
||||
| Continue(..)
|
||||
| FormatArgs(..)
|
||||
| Gen(..)
|
||||
| If(..)
|
||||
| IncludedBytes(..)
|
||||
| InlineAsm(..)
|
||||
| Let(..)
|
||||
| Lit(..)
|
||||
| MacCall(..)
|
||||
| Match(_, _, MatchKind::Prefix)
|
||||
| OffsetOf(..)
|
||||
| Paren(..)
|
||||
| Path(..)
|
||||
| Range(None, _, _)
|
||||
| Repeat(..)
|
||||
| Ret(..)
|
||||
| Struct(..)
|
||||
| TryBlock(..)
|
||||
| Tup(..)
|
||||
| Type(..)
|
||||
| Unary(..)
|
||||
| Underscore
|
||||
| Yeet(..)
|
||||
| Yield(..)
|
||||
| Err(..)
|
||||
| Dummy => return false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum TrailingBrace<'a> {
|
||||
/// Trailing brace in a macro call, like the one in `x as *const brace! {}`.
|
||||
/// We will suggest changing the macro call to a different delimiter.
|
||||
|
@ -5,6 +5,7 @@ use ast::{ForLoopKind, MatchKind};
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||
use rustc_ast::util::parser::{self, AssocOp, Fixity};
|
||||
use rustc_ast::{self as ast, BlockCheckMode};
|
||||
@ -610,9 +611,12 @@ impl<'a> State<'a> {
|
||||
}
|
||||
if let Some(expr) = opt_expr {
|
||||
self.space();
|
||||
self.print_expr_maybe_paren(
|
||||
self.print_expr_cond_paren(
|
||||
expr,
|
||||
parser::PREC_JUMP,
|
||||
// Parenthesize if required by precedence, or in the
|
||||
// case of `break 'inner: loop { break 'inner 1 } + 1`
|
||||
expr.precedence().order() < parser::PREC_JUMP
|
||||
|| (opt_label.is_none() && classify::leading_labeled_expr(expr)),
|
||||
fixup.subsequent_subexpression(),
|
||||
);
|
||||
}
|
||||
|
@ -25,12 +25,12 @@ fn break_labeled_loop() {
|
||||
'outer: loop { break 'outer 'inner: loop { break 'inner 1; } + 1; };
|
||||
|
||||
let paren_around_break_value =
|
||||
'outer: loop { break 'inner: loop { break 'inner 1; } + 1; };
|
||||
'outer: loop { break ('inner: loop { break 'inner 1; } + 1); };
|
||||
|
||||
macro_rules! breaking { ($value:expr) => { break $value }; }
|
||||
|
||||
let paren_around_break_value =
|
||||
loop { break 'inner: loop { break 'inner 1; } + 1; };
|
||||
loop { break ('inner: loop { break 'inner 1; } + 1); };
|
||||
}
|
||||
|
||||
fn if_let() {
|
||||
|
Loading…
Reference in New Issue
Block a user