Skip to content

Commit f88cf02

Browse files
committed
Move unclosed delim errors to separate function
1 parent a49368f commit f88cf02

File tree

2 files changed

+62
-63
lines changed

2 files changed

+62
-63
lines changed

Diff for: compiler/rustc_parse/src/lexer/tokentrees.rs

+58-53
Original file line numberDiff line numberDiff line change
@@ -117,59 +117,8 @@ impl<'a> TokenTreesReader<'a> {
117117
// We stop at any delimiter so we can try to recover if the user
118118
// uses an incorrect delimiter.
119119
let (tts, res) = self.parse_token_trees(/* is_delimited */ true);
120-
if let Err(mut errs) = res {
121-
// If there are unclosed delims, see if there are diff markers and if so, point them
122-
// out instead of complaining about the unclosed delims.
123-
let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None);
124-
let mut diff_errs = vec![];
125-
// Suggest removing a `{` we think appears in an `if`/`while` condition
126-
// We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but
127-
// we have no way of tracking this in the lexer itself, so we piggyback on the parser
128-
let mut in_cond = false;
129-
while parser.token != token::Eof {
130-
if let Err(diff_err) = parser.err_diff_marker() {
131-
diff_errs.push(diff_err);
132-
} else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) {
133-
in_cond = true;
134-
} else if matches!(
135-
parser.token.kind,
136-
token::CloseDelim(Delimiter::Brace) | token::FatArrow
137-
) {
138-
// end of the `if`/`while` body, or the end of a `match` guard
139-
in_cond = false;
140-
} else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) {
141-
// Store the `&&` and `let` to use their spans later when creating the diagnostic
142-
let maybe_andand = parser.look_ahead(1, |t| t.clone());
143-
let maybe_let = parser.look_ahead(2, |t| t.clone());
144-
if maybe_andand == token::OpenDelim(Delimiter::Brace) {
145-
// This might be the beginning of the `if`/`while` body (i.e., the end of the condition)
146-
in_cond = false;
147-
} else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) {
148-
let mut err = parser.struct_span_err(
149-
parser.token.span,
150-
"found a `{` in the middle of a let-chain",
151-
);
152-
err.span_suggestion(
153-
parser.token.span,
154-
"consider removing this brace to parse the `let` as part of the same chain",
155-
"", Applicability::MachineApplicable
156-
);
157-
err.span_note(
158-
maybe_andand.span.to(maybe_let.span),
159-
"you might have meant to continue the let-chain here",
160-
);
161-
errs.push(err);
162-
}
163-
}
164-
parser.bump();
165-
}
166-
if !diff_errs.is_empty() {
167-
errs.iter_mut().for_each(|err| {
168-
err.delay_as_bug();
169-
});
170-
return Err(diff_errs);
171-
}
172-
return Err(errs);
120+
if let Err(errs) = res {
121+
return Err(self.unclosed_delim_err(tts, errs));
173122
}
174123

175124
// Expand to cover the entire delimited token tree
@@ -256,6 +205,62 @@ impl<'a> TokenTreesReader<'a> {
256205
Ok(TokenTree::Delimited(delim_span, open_delim, tts))
257206
}
258207

208+
fn unclosed_delim_err(&mut self, tts: TokenStream, mut errs: Vec<PErr<'a>>) -> Vec<PErr<'a>> {
209+
// If there are unclosed delims, see if there are diff markers and if so, point them
210+
// out instead of complaining about the unclosed delims.
211+
let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None);
212+
let mut diff_errs = vec![];
213+
// Suggest removing a `{` we think appears in an `if`/`while` condition
214+
// We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but
215+
// we have no way of tracking this in the lexer itself, so we piggyback on the parser
216+
let mut in_cond = false;
217+
while parser.token != token::Eof {
218+
if let Err(diff_err) = parser.err_diff_marker() {
219+
diff_errs.push(diff_err);
220+
} else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) {
221+
in_cond = true;
222+
} else if matches!(
223+
parser.token.kind,
224+
token::CloseDelim(Delimiter::Brace) | token::FatArrow
225+
) {
226+
// end of the `if`/`while` body, or the end of a `match` guard
227+
in_cond = false;
228+
} else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) {
229+
// Store the `&&` and `let` to use their spans later when creating the diagnostic
230+
let maybe_andand = parser.look_ahead(1, |t| t.clone());
231+
let maybe_let = parser.look_ahead(2, |t| t.clone());
232+
if maybe_andand == token::OpenDelim(Delimiter::Brace) {
233+
// This might be the beginning of the `if`/`while` body (i.e., the end of the condition)
234+
in_cond = false;
235+
} else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) {
236+
let mut err = parser.struct_span_err(
237+
parser.token.span,
238+
"found a `{` in the middle of a let-chain",
239+
);
240+
err.span_suggestion(
241+
parser.token.span,
242+
"consider removing this brace to parse the `let` as part of the same chain",
243+
"",
244+
Applicability::MachineApplicable,
245+
);
246+
err.span_label(
247+
maybe_andand.span.to(maybe_let.span),
248+
"you might have meant to continue the let-chain here",
249+
);
250+
errs.push(err);
251+
}
252+
}
253+
parser.bump();
254+
}
255+
if !diff_errs.is_empty() {
256+
errs.iter_mut().for_each(|err| {
257+
err.delay_as_bug();
258+
});
259+
return diff_errs;
260+
}
261+
return errs;
262+
}
263+
259264
fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> {
260265
// An unexpected closing delimiter (i.e., there is no
261266
// matching opening delimiter).

Diff for: tests/ui/parser/brace-in-let-chain.stderr

+4-10
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,9 @@ error: found a `{` in the middle of a let-chain
3838
|
3939
LL | && let () = () {
4040
| ^
41-
|
42-
note: you might have meant to continue the let-chain here
43-
--> $DIR/brace-in-let-chain.rs:15:9
44-
|
4541
LL | && let () = ()
46-
| ^^^^^^
42+
| ------ you might have meant to continue the let-chain here
43+
|
4744
help: consider removing this brace to parse the `let` as part of the same chain
4845
|
4946
LL - && let () = () {
@@ -55,12 +52,9 @@ error: found a `{` in the middle of a let-chain
5552
|
5653
LL | && let () = () {
5754
| ^
58-
|
59-
note: you might have meant to continue the let-chain here
60-
--> $DIR/brace-in-let-chain.rs:7:9
61-
|
6255
LL | && let () = ()
63-
| ^^^^^^
56+
| ------ you might have meant to continue the let-chain here
57+
|
6458
help: consider removing this brace to parse the `let` as part of the same chain
6559
|
6660
LL - && let () = () {

0 commit comments

Comments
 (0)