Rollup merge of #128865 - jieyouxu:unicurd, r=Urgau
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. The fix is to use `SourceMap::start_point(token_span)` which properly accounts for codepoint boundaries. Fixes #128845. cc #128790 r? ````@fmease````
This commit is contained in:
commit
665a1a4b55
3 changed files with 48 additions and 2 deletions
|
@ -408,10 +408,14 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<P<Expr>>> {
|
fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<P<Expr>>> {
|
||||||
let eq_consumed = match self.token.kind {
|
let eq_consumed = match self.token.kind {
|
||||||
token::BinOpEq(..) => {
|
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 {
|
self.dcx().emit_err(errors::CompoundAssignmentExpressionInLet {
|
||||||
span: self.token.span,
|
span: self.token.span,
|
||||||
suggestion: self.token.span.with_hi(self.token.span.lo() + BytePos(1)),
|
suggestion: extra_op_span,
|
||||||
});
|
});
|
||||||
self.bump();
|
self.bump();
|
||||||
true
|
true
|
||||||
|
|
16
tests/ui/parser/suggest-remove-compount-assign-let-ice.rs
Normal file
16
tests/ui/parser/suggest-remove-compount-assign-let-ice.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
//! 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: 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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue