Skip to content

Commit 6f1d763

Browse files
committed
Do not parenthesize exterior struct lit inside match guards
1 parent 7f314ac commit 6f1d763

File tree

4 files changed

+150
-75
lines changed

4 files changed

+150
-75
lines changed

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod item;
77

88
use crate::pp::Breaks::{Consistent, Inconsistent};
99
use crate::pp::{self, Breaks};
10+
use crate::pprust::state::expr::FixupContext;
1011
use rustc_ast::attr::AttrIdGenerator;
1112
use rustc_ast::ptr::P;
1213
use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
@@ -798,7 +799,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
798799
}
799800

800801
fn expr_to_string(&self, e: &ast::Expr) -> String {
801-
Self::to_string(|s| s.print_expr(e))
802+
Self::to_string(|s| s.print_expr(e, FixupContext::default()))
802803
}
803804

804805
fn meta_item_lit_to_string(&self, lit: &ast::MetaItemLit) -> String {
@@ -903,7 +904,7 @@ impl<'a> State<'a> {
903904
}
904905

905906
fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
906-
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
907+
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e, FixupContext::default()), |e| e.span)
907908
}
908909

909910
pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) {
@@ -940,7 +941,7 @@ impl<'a> State<'a> {
940941
match generic_arg {
941942
GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
942943
GenericArg::Type(ty) => self.print_type(ty),
943-
GenericArg::Const(ct) => self.print_expr(&ct.value),
944+
GenericArg::Const(ct) => self.print_expr(&ct.value, FixupContext::default()),
944945
}
945946
}
946947

@@ -1007,12 +1008,12 @@ impl<'a> State<'a> {
10071008
self.word("[");
10081009
self.print_type(ty);
10091010
self.word("; ");
1010-
self.print_expr(&length.value);
1011+
self.print_expr(&length.value, FixupContext::default());
10111012
self.word("]");
10121013
}
10131014
ast::TyKind::Typeof(e) => {
10141015
self.word("typeof(");
1015-
self.print_expr(&e.value);
1016+
self.print_expr(&e.value, FixupContext::default());
10161017
self.word(")");
10171018
}
10181019
ast::TyKind::Infer => {
@@ -1068,7 +1069,7 @@ impl<'a> State<'a> {
10681069
if let Some((init, els)) = loc.kind.init_else_opt() {
10691070
self.nbsp();
10701071
self.word_space("=");
1071-
self.print_expr(init);
1072+
self.print_expr(init, FixupContext::default());
10721073
if let Some(els) = els {
10731074
self.cbox(INDENT_UNIT);
10741075
self.ibox(INDENT_UNIT);
@@ -1082,14 +1083,14 @@ impl<'a> State<'a> {
10821083
ast::StmtKind::Item(item) => self.print_item(item),
10831084
ast::StmtKind::Expr(expr) => {
10841085
self.space_if_not_bol();
1085-
self.print_expr_outer_attr_style(expr, false);
1086+
self.print_expr_outer_attr_style(expr, false, FixupContext::default());
10861087
if classify::expr_requires_semi_to_be_stmt(expr) {
10871088
self.word(";");
10881089
}
10891090
}
10901091
ast::StmtKind::Semi(expr) => {
10911092
self.space_if_not_bol();
1092-
self.print_expr_outer_attr_style(expr, false);
1093+
self.print_expr_outer_attr_style(expr, false, FixupContext::default());
10931094
self.word(";");
10941095
}
10951096
ast::StmtKind::Empty => {
@@ -1141,7 +1142,7 @@ impl<'a> State<'a> {
11411142
ast::StmtKind::Expr(expr) if i == blk.stmts.len() - 1 => {
11421143
self.maybe_print_comment(st.span.lo());
11431144
self.space_if_not_bol();
1144-
self.print_expr_outer_attr_style(expr, false);
1145+
self.print_expr_outer_attr_style(expr, false, FixupContext::default());
11451146
self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
11461147
}
11471148
_ => self.print_stmt(st),
@@ -1154,15 +1155,40 @@ impl<'a> State<'a> {
11541155
}
11551156

11561157
/// Print a `let pat = expr` expression.
1157-
fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) {
1158+
///
1159+
/// Parentheses are inserted surrounding `expr` if a round-trip through the
1160+
/// parser would otherwise work out the wrong way in a condition position.
1161+
///
1162+
/// For example each of the following would mean the wrong thing without
1163+
/// parentheses.
1164+
///
1165+
/// ```ignore
1166+
/// if let _ = (Struct {}) {}
1167+
///
1168+
/// if let _ = (true && false) {}
1169+
/// ```
1170+
///
1171+
/// In a match guard, the second case still requires parens, but the first
1172+
/// case no longer does because anything until `=>` is considered part of
1173+
/// the match guard expression. Parsing of the expression is not terminated
1174+
/// by `{` in that position.
1175+
///
1176+
/// ```ignore
1177+
/// match () {
1178+
/// () if let _ = Struct {} => {}
1179+
/// () if let _ = (true && false) => {}
1180+
/// }
1181+
/// ```
1182+
fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, fixup: FixupContext) {
11581183
self.word("let ");
11591184
self.print_pat(pat);
11601185
self.space();
11611186
self.word_space("=");
11621187
self.print_expr_cond_paren(
11631188
expr,
1164-
parser::contains_exterior_struct_lit(expr)
1189+
fixup.parenthesize_exterior_struct_lit && parser::contains_exterior_struct_lit(expr)
11651190
|| parser::needs_par_as_let_scrutinee(expr.precedence().order()),
1191+
FixupContext::default(),
11661192
);
11671193
}
11681194

@@ -1210,7 +1236,7 @@ impl<'a> State<'a> {
12101236
print_reg_or_class(s, reg);
12111237
s.pclose();
12121238
s.space();
1213-
s.print_expr(expr);
1239+
s.print_expr(expr, FixupContext::default());
12141240
}
12151241
InlineAsmOperand::Out { reg, late, expr } => {
12161242
s.word(if *late { "lateout" } else { "out" });
@@ -1219,7 +1245,7 @@ impl<'a> State<'a> {
12191245
s.pclose();
12201246
s.space();
12211247
match expr {
1222-
Some(expr) => s.print_expr(expr),
1248+
Some(expr) => s.print_expr(expr, FixupContext::default()),
12231249
None => s.word("_"),
12241250
}
12251251
}
@@ -1229,26 +1255,26 @@ impl<'a> State<'a> {
12291255
print_reg_or_class(s, reg);
12301256
s.pclose();
12311257
s.space();
1232-
s.print_expr(expr);
1258+
s.print_expr(expr, FixupContext::default());
12331259
}
12341260
InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
12351261
s.word(if *late { "inlateout" } else { "inout" });
12361262
s.popen();
12371263
print_reg_or_class(s, reg);
12381264
s.pclose();
12391265
s.space();
1240-
s.print_expr(in_expr);
1266+
s.print_expr(in_expr, FixupContext::default());
12411267
s.space();
12421268
s.word_space("=>");
12431269
match out_expr {
1244-
Some(out_expr) => s.print_expr(out_expr),
1270+
Some(out_expr) => s.print_expr(out_expr, FixupContext::default()),
12451271
None => s.word("_"),
12461272
}
12471273
}
12481274
InlineAsmOperand::Const { anon_const } => {
12491275
s.word("const");
12501276
s.space();
1251-
s.print_expr(&anon_const.value);
1277+
s.print_expr(&anon_const.value, FixupContext::default());
12521278
}
12531279
InlineAsmOperand::Sym { sym } => {
12541280
s.word("sym");
@@ -1442,18 +1468,18 @@ impl<'a> State<'a> {
14421468
self.print_pat(inner);
14431469
}
14441470
}
1445-
PatKind::Lit(e) => self.print_expr(e),
1471+
PatKind::Lit(e) => self.print_expr(e, FixupContext::default()),
14461472
PatKind::Range(begin, end, Spanned { node: end_kind, .. }) => {
14471473
if let Some(e) = begin {
1448-
self.print_expr(e);
1474+
self.print_expr(e, FixupContext::default());
14491475
}
14501476
match end_kind {
14511477
RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."),
14521478
RangeEnd::Included(RangeSyntax::DotDotEq) => self.word("..="),
14531479
RangeEnd::Excluded => self.word(".."),
14541480
}
14551481
if let Some(e) = end {
1456-
self.print_expr(e);
1482+
self.print_expr(e, FixupContext::default());
14571483
}
14581484
}
14591485
PatKind::Slice(elts) => {
@@ -1607,7 +1633,7 @@ impl<'a> State<'a> {
16071633
if let Some(default) = default {
16081634
s.space();
16091635
s.word_space("=");
1610-
s.print_expr(&default.value);
1636+
s.print_expr(&default.value, FixupContext::default());
16111637
}
16121638
}
16131639
}

0 commit comments

Comments
 (0)