Fix handling of unmatched angle brackets in parser
This commit is contained in:
parent
4e219e6335
commit
6a6a605a61
7 changed files with 120 additions and 37 deletions
|
@ -352,29 +352,38 @@ impl<'a> Parser<'a> {
|
||||||
debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
|
debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
|
||||||
match self.parse_angle_args() {
|
match self.parse_angle_args() {
|
||||||
Ok(args) => Ok(args),
|
Ok(args) => Ok(args),
|
||||||
Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
|
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());
|
||||||
|
|
||||||
|
// Eat the unmatched angle brackets.
|
||||||
|
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
|
// Cancel error from being unable to find `>`. We know the error
|
||||||
// must have been this due to a non-zero unmatched angle bracket
|
// must have been this due to a non-zero unmatched angle bracket
|
||||||
// count.
|
// count.
|
||||||
e.cancel();
|
e.cancel();
|
||||||
|
|
||||||
// Swap `self` with our backup of the parser state before attempting to parse
|
|
||||||
// generic arguments.
|
|
||||||
let snapshot = mem::replace(self, snapshot.unwrap());
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
|
"parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
|
||||||
snapshot.count={:?}",
|
snapshot.count={:?}",
|
||||||
snapshot.unmatched_angle_bracket_count,
|
snapshot.unmatched_angle_bracket_count,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Eat the unmatched angle brackets.
|
|
||||||
for _ in 0..snapshot.unmatched_angle_bracket_count {
|
|
||||||
self.eat_lt();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a span over ${unmatched angle bracket count} characters.
|
// Make a span over ${unmatched angle bracket count} characters.
|
||||||
let span = lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
|
// 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(
|
self.struct_span_err(
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
|
@ -396,6 +405,7 @@ impl<'a> Parser<'a> {
|
||||||
// Try again without unmatched angle bracket characters.
|
// Try again without unmatched angle bracket characters.
|
||||||
self.parse_angle_args()
|
self.parse_angle_args()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Err(e) => Err(e),
|
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…
Add table
Add a link
Reference in a new issue