parser: ensure let stmt compound assignment removal suggestion respect codepoint boundaries

Previously we would try to issue a suggestion for `let x <op>= 1`, i.e.
a compound assignment within a `let` binding, to remove the `<op>`. The
suggestion code unfortunately incorrectly assumed that the `<op>` is an
exactly-1-byte ASCII character, but this assumption is incorrect because
we also recover Unicode-confusables like `=` as `-=`. In this example,
the suggestion code used a `+ BytePos(1)` to calculate the span of the
`<op>` codepoint that looks like `-` but the mult-byte Unicode
look-alike would cause the suggested removal span to be inside a
multi-byte codepoint boundary, triggering a codepoint boundary
assertion.

Issue: <https://github.com/rust-lang/rust/issues/128845>
This commit is contained in:
许杰友 Jieyou Xu (Joe) 2024-08-09 05:48:52 +00:00
parent 92520a9d4d
commit d65f1316bb

View File

@ -408,10 +408,14 @@ impl<'a> Parser<'a> {
fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<P<Expr>>> {
let eq_consumed = match self.token.kind {
token::BinOpEq(..) => {
// Recover `let x <op>= 1` as `let x = 1`
// Recover `let x <op>= 1` as `let x = 1` We must not use `+ BytePos(1)` here
// because `<op>` can be a multi-byte lookalike that was recovered, e.g. `=` (the
// `` is a U+2796 Heavy Minus Sign Unicode Character) that was recovered as a
// `-=`.
let extra_op_span = self.psess.source_map().start_point(self.token.span);
self.dcx().emit_err(errors::CompoundAssignmentExpressionInLet {
span: self.token.span,
suggestion: self.token.span.with_hi(self.token.span.lo() + BytePos(1)),
suggestion: extra_op_span,
});
self.bump();
true