Skip to content

Commit 52d1ebb

Browse files
authored
Merge pull request #1808 from dtolnay/ifbreak
Fix `if break x {}`
2 parents 6baa793 + 7fbb4ae commit 52d1ebb

File tree

1 file changed

+70
-26
lines changed

1 file changed

+70
-26
lines changed

src/classify.rs

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -70,58 +70,103 @@ pub(crate) fn requires_comma_to_be_match_arm(expr: &Expr) -> bool {
7070
#[cfg(all(feature = "printing", feature = "full"))]
7171
pub(crate) fn confusable_with_adjacent_block(mut expr: &Expr) -> bool {
7272
let mut stack = Vec::new();
73+
let mut jump = false;
74+
let mut tokens_right_of_empty_stack = false;
7375

7476
while let Some(next) = match expr {
7577
Expr::Assign(e) => {
76-
stack.push(&e.right);
77-
Some(&e.left)
78+
stack.push((jump, &e.right));
79+
Some((jump, &e.left))
80+
}
81+
Expr::Await(e) => {
82+
tokens_right_of_empty_stack |= stack.is_empty();
83+
Some((jump, &e.base))
7884
}
79-
Expr::Await(e) => Some(&e.base),
8085
Expr::Binary(e) => {
81-
stack.push(&e.right);
82-
Some(&e.left)
86+
stack.push((jump, &e.right));
87+
Some((jump, &e.left))
8388
}
8489
Expr::Break(e) => {
85-
if let Some(Expr::Block(_)) = e.expr.as_deref() {
90+
if let Some(value) = &e.expr {
91+
if let Expr::Block(_) = **value {
92+
return true;
93+
}
94+
Some((true, value))
95+
} else {
96+
stack.pop()
97+
}
98+
}
99+
Expr::Call(e) => {
100+
tokens_right_of_empty_stack |= stack.is_empty();
101+
Some((jump, &e.func))
102+
}
103+
Expr::Cast(e) => {
104+
tokens_right_of_empty_stack |= stack.is_empty();
105+
Some((jump, &e.expr))
106+
}
107+
Expr::Closure(e) => Some((true, &e.body)),
108+
Expr::Field(e) => {
109+
tokens_right_of_empty_stack |= stack.is_empty();
110+
Some((jump, &e.base))
111+
}
112+
Expr::Index(e) => {
113+
tokens_right_of_empty_stack |= stack.is_empty();
114+
Some((jump, &e.expr))
115+
}
116+
Expr::MethodCall(e) => {
117+
tokens_right_of_empty_stack |= stack.is_empty();
118+
Some((jump, &e.receiver))
119+
}
120+
Expr::Path(_) => {
121+
if jump && stack.is_empty() && !tokens_right_of_empty_stack {
86122
return true;
87123
}
88124
stack.pop()
89125
}
90-
Expr::Call(e) => Some(&e.func),
91-
Expr::Cast(e) => Some(&e.expr),
92-
Expr::Closure(e) => Some(&e.body),
93-
Expr::Field(e) => Some(&e.base),
94-
Expr::Index(e) => Some(&e.expr),
95-
Expr::MethodCall(e) => Some(&e.receiver),
96126
Expr::Range(e) => {
97127
if let Some(Expr::Block(_)) = e.end.as_deref() {
98128
return true;
99129
}
100130
match (&e.start, &e.end) {
101-
(Some(start), end) => {
102-
stack.extend(end);
103-
Some(start)
131+
(Some(start), Some(end)) => {
132+
stack.push((jump, end));
133+
Some((jump, start))
134+
}
135+
(Some(start), None) => {
136+
tokens_right_of_empty_stack |= stack.is_empty();
137+
Some((jump, start))
104138
}
105-
(None, Some(end)) => Some(end),
139+
(None, Some(end)) => Some((jump, end)),
106140
(None, None) => stack.pop(),
107141
}
108142
}
109-
Expr::RawAddr(e) => Some(&e.expr),
110-
Expr::Reference(e) => Some(&e.expr),
143+
Expr::RawAddr(e) => Some((jump, &e.expr)),
144+
Expr::Reference(e) => Some((jump, &e.expr)),
111145
Expr::Return(e) => {
112-
if e.expr.is_none() && stack.is_empty() {
146+
if e.expr.is_none() && stack.is_empty() && !tokens_right_of_empty_stack {
113147
return true;
114148
}
115-
stack.pop()
149+
if let Some(value) = &e.expr {
150+
Some((true, value))
151+
} else {
152+
stack.pop()
153+
}
116154
}
117155
Expr::Struct(_) => return true,
118-
Expr::Try(e) => Some(&e.expr),
119-
Expr::Unary(e) => Some(&e.expr),
156+
Expr::Try(e) => {
157+
tokens_right_of_empty_stack |= stack.is_empty();
158+
Some((jump, &e.expr))
159+
}
160+
Expr::Unary(e) => Some((jump, &e.expr)),
120161
Expr::Yield(e) => {
121-
if e.expr.is_none() && stack.is_empty() {
162+
if e.expr.is_none() && stack.is_empty() && !tokens_right_of_empty_stack {
122163
return true;
123164
}
124-
stack.pop()
165+
if let Some(value) = &e.expr {
166+
Some((true, value))
167+
} else {
168+
stack.pop()
169+
}
125170
}
126171

127172
Expr::Array(_)
@@ -139,15 +184,14 @@ pub(crate) fn confusable_with_adjacent_block(mut expr: &Expr) -> bool {
139184
| Expr::Macro(_)
140185
| Expr::Match(_)
141186
| Expr::Paren(_)
142-
| Expr::Path(_)
143187
| Expr::Repeat(_)
144188
| Expr::TryBlock(_)
145189
| Expr::Tuple(_)
146190
| Expr::Unsafe(_)
147191
| Expr::Verbatim(_)
148192
| Expr::While(_) => stack.pop(),
149193
} {
150-
expr = next;
194+
(jump, expr) = next;
151195
}
152196

153197
false

0 commit comments

Comments
 (0)