mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
Fix handling of unmatched angle brackets in parser
This commit is contained in:
parent
4e219e6335
commit
6a6a605a61
@ -352,49 +352,59 @@ impl<'a> Parser<'a> {
|
||||
debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
|
||||
match self.parse_angle_args() {
|
||||
Ok(args) => Ok(args),
|
||||
Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
|
||||
// Cancel error from being unable to find `>`. We know the error
|
||||
// must have been this due to a non-zero unmatched angle bracket
|
||||
// count.
|
||||
e.cancel();
|
||||
|
||||
Err(mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
|
||||
// Swap `self` with our backup of the parser state before attempting to parse
|
||||
// generic arguments.
|
||||
let snapshot = mem::replace(self, snapshot.unwrap());
|
||||
|
||||
debug!(
|
||||
"parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
|
||||
snapshot.count={:?}",
|
||||
snapshot.unmatched_angle_bracket_count,
|
||||
);
|
||||
|
||||
// Eat the unmatched angle brackets.
|
||||
for _ in 0..snapshot.unmatched_angle_bracket_count {
|
||||
self.eat_lt();
|
||||
let all_angle_brackets = (0..snapshot.unmatched_angle_bracket_count)
|
||||
.fold(true, |a, _| a && self.eat_lt());
|
||||
|
||||
if !all_angle_brackets {
|
||||
// If there are other tokens in between the extraneous `<`s, we cannot simply
|
||||
// suggest to remove them. This check also prevents us from accidentally ending
|
||||
// up in the middle of a multibyte character (issue #84104).
|
||||
let _ = mem::replace(self, snapshot);
|
||||
Err(e)
|
||||
} else {
|
||||
// Cancel error from being unable to find `>`. We know the error
|
||||
// must have been this due to a non-zero unmatched angle bracket
|
||||
// count.
|
||||
e.cancel();
|
||||
|
||||
debug!(
|
||||
"parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
|
||||
snapshot.count={:?}",
|
||||
snapshot.unmatched_angle_bracket_count,
|
||||
);
|
||||
|
||||
// Make a span over ${unmatched angle bracket count} characters.
|
||||
// This is safe because `all_angle_brackets` ensures that there are only `<`s,
|
||||
// i.e. no multibyte characters, in this range.
|
||||
let span =
|
||||
lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
|
||||
self.struct_span_err(
|
||||
span,
|
||||
&format!(
|
||||
"unmatched angle bracket{}",
|
||||
pluralize!(snapshot.unmatched_angle_bracket_count)
|
||||
),
|
||||
)
|
||||
.span_suggestion(
|
||||
span,
|
||||
&format!(
|
||||
"remove extra angle bracket{}",
|
||||
pluralize!(snapshot.unmatched_angle_bracket_count)
|
||||
),
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
|
||||
// Try again without unmatched angle bracket characters.
|
||||
self.parse_angle_args()
|
||||
}
|
||||
|
||||
// Make a span over ${unmatched angle bracket count} characters.
|
||||
let span = lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
|
||||
self.struct_span_err(
|
||||
span,
|
||||
&format!(
|
||||
"unmatched angle bracket{}",
|
||||
pluralize!(snapshot.unmatched_angle_bracket_count)
|
||||
),
|
||||
)
|
||||
.span_suggestion(
|
||||
span,
|
||||
&format!(
|
||||
"remove extra angle bracket{}",
|
||||
pluralize!(snapshot.unmatched_angle_bracket_count)
|
||||
),
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
|
||||
// Try again without unmatched angle bracket characters.
|
||||
self.parse_angle_args()
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
|
3
src/test/ui/parser/issue-84104.rs
Normal file
3
src/test/ui/parser/issue-84104.rs
Normal file
@ -0,0 +1,3 @@
|
||||
// error-pattern: this file contains an unclosed delimiter
|
||||
// error-pattern: expected one of
|
||||
#[i=i::<ښܖ<
|
16
src/test/ui/parser/issue-84104.stderr
Normal file
16
src/test/ui/parser/issue-84104.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/issue-84104.rs:3:13
|
||||
|
|
||||
LL | #[i=i::<ښܖ<
|
||||
| - ^
|
||||
| |
|
||||
| unclosed delimiter
|
||||
|
||||
error: expected one of `>`, a const expression, lifetime, or type, found `]`
|
||||
--> $DIR/issue-84104.rs:3:13
|
||||
|
|
||||
LL | #[i=i::<ښܖ<
|
||||
| ^ expected one of `>`, a const expression, lifetime, or type
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
9
src/test/ui/parser/unmatched-langle-1.rs
Normal file
9
src/test/ui/parser/unmatched-langle-1.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// Check that a suggestion is issued if there are too many `<`s in a
|
||||
// generic argument list, and that the parser recovers properly.
|
||||
|
||||
fn main() {
|
||||
foo::<<<<Ty<i32>>();
|
||||
//~^ ERROR: unmatched angle brackets
|
||||
//~| ERROR: cannot find function `foo` in this scope [E0425]
|
||||
//~| ERROR: cannot find type `Ty` in this scope [E0412]
|
||||
}
|
22
src/test/ui/parser/unmatched-langle-1.stderr
Normal file
22
src/test/ui/parser/unmatched-langle-1.stderr
Normal file
@ -0,0 +1,22 @@
|
||||
error: unmatched angle brackets
|
||||
--> $DIR/unmatched-langle-1.rs:5:10
|
||||
|
|
||||
LL | foo::<<<<Ty<i32>>();
|
||||
| ^^^ help: remove extra angle brackets
|
||||
|
||||
error[E0425]: cannot find function `foo` in this scope
|
||||
--> $DIR/unmatched-langle-1.rs:5:5
|
||||
|
|
||||
LL | foo::<<<<Ty<i32>>();
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0412]: cannot find type `Ty` in this scope
|
||||
--> $DIR/unmatched-langle-1.rs:5:14
|
||||
|
|
||||
LL | foo::<<<<Ty<i32>>();
|
||||
| ^^ not found in this scope
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0412, E0425.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
15
src/test/ui/parser/unmatched-langle-2.rs
Normal file
15
src/test/ui/parser/unmatched-langle-2.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// When there are too many opening `<`s, the compiler would previously
|
||||
// suggest nonsense if the `<`s were interspersed with other tokens:
|
||||
//
|
||||
// error: unmatched angle brackets
|
||||
// --> unmatched-langle.rs:2:10
|
||||
// |
|
||||
// 2 | foo::<Ty<<<i32>();
|
||||
// | ^^^ help: remove extra angle brackets
|
||||
//
|
||||
// This test makes sure that this is no longer happening.
|
||||
|
||||
fn main() {
|
||||
foo::<Ty<<<i32>();
|
||||
//~^ ERROR: expected `::`, found `(`
|
||||
}
|
8
src/test/ui/parser/unmatched-langle-2.stderr
Normal file
8
src/test/ui/parser/unmatched-langle-2.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: expected `::`, found `(`
|
||||
--> $DIR/unmatched-langle-2.rs:13:20
|
||||
|
|
||||
LL | foo::<Ty<<<i32>();
|
||||
| ^ expected `::`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user