1
Fork 0

Emit both subexp and standalone sugg for postfix

This solves the TODO.
This commit is contained in:
Noah Lev 2022-02-17 14:52:52 -08:00
parent 7287f929b9
commit 62b8ea67b7
4 changed files with 70 additions and 31 deletions

View file

@ -160,8 +160,10 @@ impl AttemptLocalParseRecovery {
/// C-style `i++`, `--i`, etc. /// C-style `i++`, `--i`, etc.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
struct IncDecRecovery { struct IncDecRecovery {
/// This increment/decrement is not a subexpression. /// Is this increment/decrement its own statement?
standalone: bool, ///
/// This is `None` when we are unsure.
standalone: Option<bool>,
/// Is this an increment or decrement? /// Is this an increment or decrement?
op: IncOrDec, op: IncOrDec,
/// Is this pre- or postfix? /// Is this pre- or postfix?
@ -1225,7 +1227,7 @@ impl<'a> Parser<'a> {
prev_is_semi: bool, prev_is_semi: bool,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let kind = IncDecRecovery { let kind = IncDecRecovery {
standalone: prev_is_semi, standalone: Some(prev_is_semi),
op: IncOrDec::Inc, op: IncOrDec::Inc,
fixity: UnaryFixity::Pre, fixity: UnaryFixity::Pre,
}; };
@ -1237,13 +1239,9 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
operand_expr: P<Expr>, operand_expr: P<Expr>,
op_span: Span, op_span: Span,
prev_is_semi: bool,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let kind = IncDecRecovery { let kind =
standalone: prev_is_semi, IncDecRecovery { standalone: None, op: IncOrDec::Inc, fixity: UnaryFixity::Post };
op: IncOrDec::Inc,
fixity: UnaryFixity::Post,
};
self.recover_from_inc_dec(operand_expr, kind, op_span) self.recover_from_inc_dec(operand_expr, kind, op_span)
} }
@ -1272,25 +1270,44 @@ impl<'a> Parser<'a> {
UnaryFixity::Post => (base.span.shrink_to_lo(), op_span), UnaryFixity::Post => (base.span.shrink_to_lo(), op_span),
}; };
if kind.standalone { match kind.standalone {
self.inc_dec_standalone_recovery(err, kind, spans) Some(true) => self.inc_dec_standalone_recovery(&mut err, kind, spans, false),
} else { Some(false) => {
let Ok(base_src) = self.span_to_snippet(base.span) let Ok(base_src) = self.span_to_snippet(base.span)
else { return help_base_case(err, base) }; else { return help_base_case(err, base) };
match kind.fixity { match kind.fixity {
UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, err, kind, spans), UnaryFixity::Pre => {
UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, err, kind, spans), self.prefix_inc_dec_suggest(base_src, &mut err, kind, spans)
}
UnaryFixity::Post => {
self.postfix_inc_dec_suggest(base_src, &mut err, kind, spans)
}
}
}
None => {
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, &mut err, kind, spans)
}
UnaryFixity::Post => {
self.postfix_inc_dec_suggest(base_src, &mut err, kind, spans)
}
}
self.inc_dec_standalone_recovery(&mut err, kind, spans, true)
} }
} }
Err(err)
} }
fn prefix_inc_dec_suggest( fn prefix_inc_dec_suggest(
&mut self, &mut self,
base_src: String, base_src: String,
mut err: DiagnosticBuilder<'a>, err: &mut DiagnosticBuilder<'a>,
kind: IncDecRecovery, kind: IncDecRecovery,
(pre_span, post_span): (Span, Span), (pre_span, post_span): (Span, Span),
) -> PResult<'a, P<Expr>> { ) {
err.multipart_suggestion( err.multipart_suggestion(
&format!("use `{}= 1` instead", kind.op.chr()), &format!("use `{}= 1` instead", kind.op.chr()),
vec![ vec![
@ -1299,16 +1316,15 @@ impl<'a> Parser<'a> {
], ],
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
Err(err)
} }
fn postfix_inc_dec_suggest( fn postfix_inc_dec_suggest(
&mut self, &mut self,
base_src: String, base_src: String,
mut err: DiagnosticBuilder<'a>, err: &mut DiagnosticBuilder<'a>,
kind: IncDecRecovery, kind: IncDecRecovery,
(pre_span, post_span): (Span, Span), (pre_span, post_span): (Span, Span),
) -> PResult<'a, P<Expr>> { ) {
err.multipart_suggestion( err.multipart_suggestion(
&format!("use `{}= 1` instead", kind.op.chr()), &format!("use `{}= 1` instead", kind.op.chr()),
vec![ vec![
@ -1317,21 +1333,31 @@ impl<'a> Parser<'a> {
], ],
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
Err(err)
} }
fn inc_dec_standalone_recovery( fn inc_dec_standalone_recovery(
&mut self, &mut self,
mut err: DiagnosticBuilder<'a>, err: &mut DiagnosticBuilder<'a>,
kind: IncDecRecovery, kind: IncDecRecovery,
(pre_span, post_span): (Span, Span), (pre_span, post_span): (Span, Span),
) -> PResult<'a, P<Expr>> { maybe_not_standalone: bool,
) {
let msg = if maybe_not_standalone {
"or, if you don't need to use it as an expression, change it to this".to_owned()
} else {
format!("use `{}= 1` instead", kind.op.chr())
};
let applicability = if maybe_not_standalone {
// FIXME: Unspecified isn't right, but it's the least wrong option
Applicability::Unspecified
} else {
Applicability::MachineApplicable
};
err.multipart_suggestion( err.multipart_suggestion(
&format!("use `{}= 1` instead", kind.op.chr()), &msg,
vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))], vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))],
Applicability::MachineApplicable, applicability,
); );
Err(err)
} }
/// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`. /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.

View file

@ -273,9 +273,7 @@ impl<'a> Parser<'a> {
let op_span = self.prev_token.span.to(self.token.span); let op_span = self.prev_token.span.to(self.token.span);
// Eat the second `+` // Eat the second `+`
self.bump(); self.bump();
// TODO: implement lhs = self.maybe_recover_from_postfix_increment(lhs, op_span)?;
let start_is_semi = false;
lhs = self.maybe_recover_from_postfix_increment(lhs, op_span, start_is_semi)?;
continue; continue;
} }

View file

@ -8,6 +8,11 @@ help: use `+= 1` instead
| |
LL | { let tmp = i; i += 1; tmp }; LL | { let tmp = i; i += 1; tmp };
| +++++++++++ ~~~~~~~~~~~~~~~ | +++++++++++ ~~~~~~~~~~~~~~~
help: or, if you don't need to use it as an expression, change it to this
|
LL - i++;
LL + i += 1;
|
error: Rust has no postfix increment operator error: Rust has no postfix increment operator
--> $DIR/increment-autofix.rs:11:12 --> $DIR/increment-autofix.rs:11:12
@ -19,6 +24,11 @@ help: use `+= 1` instead
| |
LL | while { let tmp = i; i += 1; tmp } < 5 { LL | while { let tmp = i; i += 1; tmp } < 5 {
| +++++++++++ ~~~~~~~~~~~~~~~ | +++++++++++ ~~~~~~~~~~~~~~~
help: or, if you don't need to use it as an expression, change it to this
|
LL - while i++ < 5 {
LL + while i += 1 < 5 {
|
error: Rust has no prefix increment operator error: Rust has no prefix increment operator
--> $DIR/increment-autofix.rs:19:5 --> $DIR/increment-autofix.rs:19:5

View file

@ -8,6 +8,11 @@ help: use `+= 1` instead
| |
LL | { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp }; LL | { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp };
| +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~ | +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~
help: or, if you don't need to use it as an expression, change it to this
|
LL - foo.bar.qux++;
LL + foo.bar.qux += 1;
|
error: Rust has no prefix increment operator error: Rust has no prefix increment operator
--> $DIR/increment-notfixed.rs:18:5 --> $DIR/increment-notfixed.rs:18:5