Recover extra trailing angle brackets in struct definition
This commit applies the existing 'extra angle bracket recovery' logic when parsing fields in struct definitions. This allows us to continue parsing the struct's fields, avoiding spurious 'missing field' errors in code that tries to use the struct.
This commit is contained in:
parent
7750c3d46b
commit
765bd47fa0
@ -376,7 +376,14 @@ impl<'a> Parser<'a> {
|
||||
/// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
|
||||
/// ^^ help: remove extra angle brackets
|
||||
/// ```
|
||||
pub(super) fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) {
|
||||
///
|
||||
/// If `true` is returned, then trailing brackets were recovered, tokens were consumed
|
||||
/// up until one of the tokens in 'end' was encountered, and an error was emitted.
|
||||
pub(super) fn check_trailing_angle_brackets(
|
||||
&mut self,
|
||||
segment: &PathSegment,
|
||||
end: &[&TokenKind],
|
||||
) -> bool {
|
||||
// This function is intended to be invoked after parsing a path segment where there are two
|
||||
// cases:
|
||||
//
|
||||
@ -409,7 +416,7 @@ impl<'a> Parser<'a> {
|
||||
parsed_angle_bracket_args,
|
||||
);
|
||||
if !parsed_angle_bracket_args {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Keep the span at the start so we can highlight the sequence of `>` characters to be
|
||||
@ -447,18 +454,18 @@ impl<'a> Parser<'a> {
|
||||
number_of_gt, number_of_shr,
|
||||
);
|
||||
if number_of_gt < 1 && number_of_shr < 1 {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finally, double check that we have our end token as otherwise this is the
|
||||
// second case.
|
||||
if self.look_ahead(position, |t| {
|
||||
trace!("check_trailing_angle_brackets: t={:?}", t);
|
||||
*t == end
|
||||
end.contains(&&t.kind)
|
||||
}) {
|
||||
// Eat from where we started until the end token so that parsing can continue
|
||||
// as if we didn't have those extra angle brackets.
|
||||
self.eat_to_tokens(&[&end]);
|
||||
self.eat_to_tokens(end);
|
||||
let span = lo.until(self.token.span);
|
||||
|
||||
let total_num_of_gt = number_of_gt + number_of_shr * 2;
|
||||
@ -473,7 +480,9 @@ impl<'a> Parser<'a> {
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Check to see if a pair of chained operators looks like an attempt at chained comparison,
|
||||
|
@ -867,7 +867,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let fn_span_lo = self.token.span;
|
||||
let segment = self.parse_path_segment(PathStyle::Expr)?;
|
||||
self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
|
||||
self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]);
|
||||
|
||||
if self.check(&token::OpenDelim(token::Paren)) {
|
||||
// Method call `expr.f()`
|
||||
|
@ -9,7 +9,7 @@ use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind,
|
||||
use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
|
||||
use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind};
|
||||
use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
|
||||
use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind};
|
||||
use rustc_ast::ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
|
||||
use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, TokenKind};
|
||||
@ -1262,6 +1262,25 @@ impl<'a> Parser<'a> {
|
||||
sp,
|
||||
&format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)),
|
||||
);
|
||||
|
||||
// Try to recover extra trailing angle brackets
|
||||
let mut recovered = false;
|
||||
if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind {
|
||||
if let Some(last_segment) = segments.last() {
|
||||
recovered = self.check_trailing_angle_brackets(
|
||||
last_segment,
|
||||
&[&token::Comma, &token::CloseDelim(token::Brace)],
|
||||
);
|
||||
if recovered {
|
||||
// Handle a case like `Vec<u8>>,` where we can continue parsing fields
|
||||
// after the comma
|
||||
self.eat(&token::Comma);
|
||||
// `check_trailing_angle_brackets` already emitted a nicer error
|
||||
err.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.token.is_ident() {
|
||||
// This is likely another field; emit the diagnostic and keep going
|
||||
err.span_suggestion(
|
||||
@ -1271,6 +1290,14 @@ impl<'a> Parser<'a> {
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
recovered = true;
|
||||
}
|
||||
|
||||
if recovered {
|
||||
// Make sure an error was emitted (either by recovering an angle bracket,
|
||||
// or by finding an identifier as the next token), since we're
|
||||
// going to continue parsing
|
||||
assert!(self.sess.span_diagnostic.has_errors());
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ impl<'a> Parser<'a> {
|
||||
// `PathStyle::Expr` is only provided at the root invocation and never in
|
||||
// `parse_path_segment` to recurse and therefore can be checked to maintain
|
||||
// this invariant.
|
||||
self.check_trailing_angle_brackets(&segment, token::ModSep);
|
||||
self.check_trailing_angle_brackets(&segment, &[&token::ModSep]);
|
||||
}
|
||||
segments.push(segment);
|
||||
|
||||
|
14
src/test/ui/parser/recover-field-extra-angle-brackets.rs
Normal file
14
src/test/ui/parser/recover-field-extra-angle-brackets.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// Tests that we recover from extra trailing angle brackets
|
||||
// in a struct field
|
||||
|
||||
struct BadStruct {
|
||||
first: Vec<u8>>, //~ ERROR unmatched angle bracket
|
||||
second: bool
|
||||
}
|
||||
|
||||
fn bar(val: BadStruct) {
|
||||
val.first;
|
||||
val.second;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,8 @@
|
||||
error: unmatched angle bracket
|
||||
--> $DIR/recover-field-extra-angle-brackets.rs:5:19
|
||||
|
|
||||
LL | first: Vec<u8>>,
|
||||
| ^ help: remove extra angle bracket
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
x
Reference in New Issue
Block a user