Skip to content
6 changes: 3 additions & 3 deletions compiler/rustc_parse/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ pub(crate) enum InvalidComparisonOperatorSub {
pub(crate) struct InvalidLogicalOperator {
#[primary_span]
pub span: Span,
pub incorrect: String,
pub incorrect: Symbol,
#[subdiagnostic]
pub sub: InvalidLogicalOperatorSub,
}
Expand Down Expand Up @@ -797,7 +797,7 @@ pub(crate) struct EqFieldInit {

#[derive(Diagnostic)]
#[diag("unexpected token: `...`")]
pub(crate) struct DotDotDot {
pub(crate) struct DotDotDotExprOp {
#[primary_span]
#[suggestion(
"use `..` for an exclusive range",
Expand All @@ -816,7 +816,7 @@ pub(crate) struct DotDotDot {

#[derive(Diagnostic)]
#[diag("unexpected token: `<-`")]
pub(crate) struct LeftArrowOperator {
pub(crate) struct LArrowExprOp {
#[primary_span]
#[suggestion(
"if you meant to write a comparison against a negative value, add a space in between `<` and `-`",
Expand Down
214 changes: 0 additions & 214 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,64 +141,6 @@ impl AttemptLocalParseRecovery {
}
}

/// Information for emitting suggestions and recovering from
/// C-style `i++`, `--i`, etc.
#[derive(Debug, Copy, Clone)]
struct IncDecRecovery {
/// Is this increment/decrement its own statement?
standalone: IsStandalone,
/// Is this an increment or decrement?
op: IncOrDec,
/// Is this pre- or postfix?
fixity: UnaryFixity,
}

/// Is an increment or decrement expression its own statement?
#[derive(Debug, Copy, Clone)]
enum IsStandalone {
/// It's standalone, i.e., its own statement.
Standalone,
/// It's a subexpression, i.e., *not* standalone.
Subexpr,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum IncOrDec {
Inc,
Dec,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum UnaryFixity {
Pre,
Post,
}

impl IncOrDec {
fn chr(&self) -> char {
match self {
Self::Inc => '+',
Self::Dec => '-',
}
}

fn name(&self) -> &'static str {
match self {
Self::Inc => "increment",
Self::Dec => "decrement",
}
}
}

impl std::fmt::Display for UnaryFixity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Pre => write!(f, "prefix"),
Self::Post => write!(f, "postfix"),
}
}
}

/// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`.
///
/// This is a specialized version of [`Symbol::find_similar`] that constructs an error when a
Expand All @@ -211,22 +153,6 @@ fn find_similar_kw(lookup: Ident, candidates: &[Symbol]) -> Option<MisspelledKw>
})
}

struct MultiSugg {
msg: String,
patches: Vec<(Span, String)>,
applicability: Applicability,
}

impl MultiSugg {
fn emit(self, err: &mut Diag<'_>) {
err.multipart_suggestion(self.msg, self.patches, self.applicability);
}

fn emit_verbose(self, err: &mut Diag<'_>) {
err.multipart_suggestion(self.msg, self.patches, self.applicability);
}
}

/// SnapshotParser is used to create a snapshot of the parser
/// without causing duplicate errors being emitted when the `Parser`
/// is dropped.
Expand Down Expand Up @@ -1669,146 +1595,6 @@ impl<'a> Parser<'a> {
Ok(())
}

pub(super) fn recover_from_prefix_increment(
&mut self,
operand_expr: Box<Expr>,
op_span: Span,
start_stmt: bool,
) -> PResult<'a, Box<Expr>> {
let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr };
let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
self.recover_from_inc_dec(operand_expr, kind, op_span)
}

pub(super) fn recover_from_postfix_increment(
&mut self,
operand_expr: Box<Expr>,
op_span: Span,
start_stmt: bool,
) -> PResult<'a, Box<Expr>> {
let kind = IncDecRecovery {
standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
op: IncOrDec::Inc,
fixity: UnaryFixity::Post,
};
self.recover_from_inc_dec(operand_expr, kind, op_span)
}

pub(super) fn recover_from_postfix_decrement(
&mut self,
operand_expr: Box<Expr>,
op_span: Span,
start_stmt: bool,
) -> PResult<'a, Box<Expr>> {
let kind = IncDecRecovery {
standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
op: IncOrDec::Dec,
fixity: UnaryFixity::Post,
};
self.recover_from_inc_dec(operand_expr, kind, op_span)
}

fn recover_from_inc_dec(
&mut self,
base: Box<Expr>,
kind: IncDecRecovery,
op_span: Span,
) -> PResult<'a, Box<Expr>> {
let mut err = self.dcx().struct_span_err(
op_span,
format!("Rust has no {} {} operator", kind.fixity, kind.op.name()),
);
err.span_label(op_span, format!("not a valid {} operator", kind.fixity));

let help_base_case = |mut err: Diag<'_, _>, base| {
err.help(format!("use `{}= 1` instead", kind.op.chr()));
err.emit();
Ok(base)
};

// (pre, post)
let spans = match kind.fixity {
UnaryFixity::Pre => (op_span, base.span.shrink_to_hi()),
UnaryFixity::Post => (base.span.shrink_to_lo(), op_span),
};

match kind.standalone {
IsStandalone::Standalone => {
self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
}
IsStandalone::Subexpr => {
let Ok(base_src) = self.span_to_snippet(base.span) else {
return help_base_case(err, base);
};
match kind.fixity {
UnaryFixity::Pre => {
self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
}
UnaryFixity::Post => {
// won't suggest since we can not handle the precedences
// for example: `a + b++` has been parsed (a + b)++ and we can not suggest here
if !matches!(base.kind, ExprKind::Binary(_, _, _)) {
self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
}
}
}
}
}
Err(err)
}

fn prefix_inc_dec_suggest(
&mut self,
base_src: String,
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> MultiSugg {
MultiSugg {
msg: format!("use `{}= 1` instead", kind.op.chr()),
patches: vec![
(pre_span, "{ ".to_string()),
(post_span, format!(" {}= 1; {} }}", kind.op.chr(), base_src)),
],
applicability: Applicability::MachineApplicable,
}
}

fn postfix_inc_dec_suggest(
&mut self,
base_src: String,
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> MultiSugg {
let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" };
MultiSugg {
msg: format!("use `{}= 1` instead", kind.op.chr()),
patches: vec![
(pre_span, format!("{{ let {tmp_var} = ")),
(post_span, format!("; {} {}= 1; {} }}", base_src, kind.op.chr(), tmp_var)),
],
applicability: Applicability::HasPlaceholders,
}
}

fn inc_dec_standalone_suggest(
&mut self,
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> MultiSugg {
let mut patches = Vec::new();

if !pre_span.is_empty() {
patches.push((pre_span, String::new()));
}

patches.push((post_span, format!(" {}= 1", kind.op.chr())));
MultiSugg {
msg: format!("use `{}= 1` instead", kind.op.chr()),
patches,
applicability: Applicability::MachineApplicable,
}
}

/// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
/// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem`
/// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
Expand Down
Loading
Loading