diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index b3efb87a4a26a..a3b782d651d3f 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -408,10 +408,14 @@ impl<'a> Parser<'a> {
fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option
>> {
let eq_consumed = match self.token.kind {
token::BinOpEq(..) => {
- // Recover `let x = 1` as `let x = 1`
+ // Recover `let x = 1` as `let x = 1` We must not use `+ BytePos(1)` here
+ // because `` 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
diff --git a/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs b/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs
new file mode 100644
index 0000000000000..1affee5678e44
--- /dev/null
+++ b/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs
@@ -0,0 +1,16 @@
+//! Previously we would try to issue a suggestion for `let x = 1`, i.e. a compound assignment
+//! within a `let` binding, to remove the ``. The suggestion code unfortunately incorrectly
+//! assumed that the `` 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 `` 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: rust-lang/rust#128845
+
+fn main() {
+ // Adapted from #128845 but with irrelevant components removed and simplified.
+ let x ➖= 1;
+ //~^ ERROR unknown start of token: \u{2796}
+ //~| ERROR: can't reassign to an uninitialized variable
+}
diff --git a/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr b/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr
new file mode 100644
index 0000000000000..59716d69b50f9
--- /dev/null
+++ b/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr
@@ -0,0 +1,26 @@
+error: unknown start of token: \u{2796}
+ --> $DIR/suggest-remove-compount-assign-let-ice.rs:13:11
+ |
+LL | let x ➖= 1;
+ | ^^
+ |
+help: Unicode character '➖' (Heavy Minus Sign) looks like '-' (Minus/Hyphen), but it is not
+ |
+LL | let x -= 1;
+ | ~
+
+error: can't reassign to an uninitialized variable
+ --> $DIR/suggest-remove-compount-assign-let-ice.rs:13:11
+ |
+LL | let x ➖= 1;
+ | ^^^
+ |
+ = help: if you meant to overwrite, remove the `let` binding
+help: initialize the variable
+ |
+LL - let x ➖= 1;
+LL + let x = 1;
+ |
+
+error: aborting due to 2 previous errors
+