summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_parse/src/parser/diagnostics.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:32 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:32 +0000
commit4547b622d8d29df964fa2914213088b148c498fc (patch)
tree9fc6b25f3c3add6b745be9a2400a6e96140046e9 /compiler/rustc_parse/src/parser/diagnostics.rs
parentReleasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz
rustc-4547b622d8d29df964fa2914213088b148c498fc.zip
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_parse/src/parser/diagnostics.rs')
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs85
1 files changed, 57 insertions, 28 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 309717350..c316a4dd6 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -18,6 +18,7 @@ use crate::errors::{
};
use crate::lexer::UnmatchedBrace;
+use crate::parser;
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
@@ -37,11 +38,10 @@ use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
-use std::ops::{Deref, DerefMut};
-
use std::mem::take;
-
-use crate::parser;
+use std::ops::{Deref, DerefMut};
+use thin_vec::{thin_vec, ThinVec};
+use tracing::{debug, trace};
/// Creates a placeholder argument.
pub(super) fn dummy_arg(ident: Ident) -> Param {
@@ -65,7 +65,7 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
pub(super) trait RecoverQPath: Sized + 'static {
const PATH_STYLE: PathStyle = PathStyle::Expr;
fn to_ty(&self) -> Option<P<Ty>>;
- fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self;
+ fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self;
}
impl RecoverQPath for Ty {
@@ -73,7 +73,7 @@ impl RecoverQPath for Ty {
fn to_ty(&self) -> Option<P<Ty>> {
Some(P(self.clone()))
}
- fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
+ fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
Self {
span: path.span,
kind: TyKind::Path(qself, path),
@@ -87,7 +87,7 @@ impl RecoverQPath for Pat {
fn to_ty(&self) -> Option<P<Ty>> {
self.to_ty()
}
- fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
+ fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
Self {
span: path.span,
kind: PatKind::Path(qself, path),
@@ -101,7 +101,7 @@ impl RecoverQPath for Expr {
fn to_ty(&self) -> Option<P<Ty>> {
self.to_ty()
}
- fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
+ fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
Self {
span: path.span,
kind: ExprKind::Path(qself, path),
@@ -224,9 +224,9 @@ impl MultiSugg {
}
}
-// SnapshotParser is used to create a snapshot of the parser
-// without causing duplicate errors being emitted when the `Parser`
-// is dropped.
+/// SnapshotParser is used to create a snapshot of the parser
+/// without causing duplicate errors being emitted when the `Parser`
+/// is dropped.
pub struct SnapshotParser<'a> {
parser: Parser<'a>,
unclosed_delims: Vec<UnmatchedBrace>,
@@ -638,8 +638,11 @@ impl<'a> Parser<'a> {
// field: value,
// }
let mut snapshot = self.create_snapshot_for_diagnostic();
- let path =
- Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None };
+ let path = Path {
+ segments: ThinVec::new(),
+ span: self.prev_token.span.shrink_to_lo(),
+ tokens: None,
+ };
let struct_expr = snapshot.parse_struct_expr(None, path, false);
let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
return Some(match (struct_expr, block_tail) {
@@ -769,6 +772,10 @@ impl<'a> Parser<'a> {
segment: &PathSegment,
end: &[&TokenKind],
) -> bool {
+ if !self.may_recover() {
+ return false;
+ }
+
// This function is intended to be invoked after parsing a path segment where there are two
// cases:
//
@@ -863,6 +870,10 @@ impl<'a> Parser<'a> {
/// Check if a method call with an intended turbofish has been written without surrounding
/// angle brackets.
pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) {
+ if !self.may_recover() {
+ return;
+ }
+
if token::ModSep == self.token.kind && segment.args.is_none() {
let snapshot = self.create_snapshot_for_diagnostic();
self.bump();
@@ -926,7 +937,7 @@ impl<'a> Parser<'a> {
if self.eat(&token::Gt) {
e.span_suggestion_verbose(
binop.span.shrink_to_lo(),
- fluent::parser_sugg_turbofish_syntax,
+ fluent::parse_sugg_turbofish_syntax,
"::",
Applicability::MaybeIncorrect,
)
@@ -962,7 +973,7 @@ impl<'a> Parser<'a> {
inner_op: &Expr,
outer_op: &Spanned<AssocOp>,
) -> bool /* advanced the cursor */ {
- if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
+ if let ExprKind::Binary(op, l1, r1) = &inner_op.kind {
if let ExprKind::Field(_, ident) = l1.kind
&& ident.as_str().parse::<i32>().is_err()
&& !matches!(r1.kind, ExprKind::Lit(_))
@@ -1068,8 +1079,8 @@ impl<'a> Parser<'a> {
let mk_err_expr = |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err)));
- match inner_op.kind {
- ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => {
+ match &inner_op.kind {
+ ExprKind::Binary(op, l1, r1) if op.node.is_comparison() => {
let mut err = ComparisonOperatorsCannotBeChained {
span: vec![op.span, self.prev_token.span],
suggest_turbofish: None,
@@ -1226,8 +1237,8 @@ impl<'a> Parser<'a> {
let bounds = self.parse_generic_bounds(None)?;
let sum_span = ty.span.to(self.prev_token.span);
- let sub = match ty.kind {
- TyKind::Rptr(ref lifetime, ref mut_ty) => {
+ let sub = match &ty.kind {
+ TyKind::Rptr(lifetime, mut_ty) => {
let sum_with_parens = pprust::to_string(|s| {
s.s.word("&");
s.print_opt_lifetime(lifetime);
@@ -1396,6 +1407,10 @@ impl<'a> Parser<'a> {
&mut self,
base: P<T>,
) -> PResult<'a, P<T>> {
+ if !self.may_recover() {
+ return Ok(base);
+ }
+
// Do not add `::` to expected tokens.
if self.token == token::ModSep {
if let Some(ty) = base.to_ty() {
@@ -1414,7 +1429,7 @@ impl<'a> Parser<'a> {
) -> PResult<'a, P<T>> {
self.expect(&token::ModSep)?;
- let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP, tokens: None };
+ let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None };
self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?;
path.span = ty_span.to(self.prev_token.span);
@@ -1425,7 +1440,7 @@ impl<'a> Parser<'a> {
});
let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
- Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path)))
+ Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path)))
}
pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
@@ -1641,15 +1656,29 @@ impl<'a> Parser<'a> {
(token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => {
self.bump();
+ let sm = self.sess.source_map();
+ let left = begin_par_sp;
+ let right = self.prev_token.span;
+ let left_snippet = if let Ok(snip) = sm.span_to_prev_source(left) &&
+ !snip.ends_with(' ') {
+ " ".to_string()
+ } else {
+ "".to_string()
+ };
+
+ let right_snippet = if let Ok(snip) = sm.span_to_next_source(right) &&
+ !snip.starts_with(' ') {
+ " ".to_string()
+ } else {
+ "".to_string()
+ };
+
self.sess.emit_err(ParenthesesInForHead {
- span: vec![begin_par_sp, self.prev_token.span],
+ span: vec![left, right],
// With e.g. `for (x) in y)` this would replace `(x) in y)`
// with `x) in y)` which is syntactically invalid.
// However, this is prevented before we get here.
- sugg: ParenthesesInForHeadSugg {
- left: begin_par_sp,
- right: self.prev_token.span,
- },
+ sugg: ParenthesesInForHeadSugg { left, right, left_snippet, right_snippet },
});
// Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
@@ -2408,7 +2437,7 @@ impl<'a> Parser<'a> {
None,
Path {
span: new_span,
- segments: vec![
+ segments: thin_vec![
PathSegment::from_ident(*old_ident),
PathSegment::from_ident(*ident),
],
@@ -2536,7 +2565,7 @@ impl<'a> Parser<'a> {
if let [a, b] = segments {
let (a_span, b_span) = (a.span(), b.span());
let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
- if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") {
+ if self.span_to_snippet(between_span).as_deref() == Ok(":: ") {
return Err(DoubleColonInBound {
span: path.span.shrink_to_hi(),
between: between_span,