From e65c060d78db59c5f21cb13f4ec322e407f0a642 Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Wed, 3 May 2023 22:32:52 +0900 Subject: [PATCH 1/4] Detect Python-like slicing and suggest how to fix Fix #108215 --- compiler/rustc_ast/src/token.rs | 5 +++++ compiler/rustc_parse/src/parser/stmt.rs | 16 ++++++++++++++++ .../range-index-instead-of-colon.rs | 8 ++++++++ .../range-index-instead-of-colon.stderr | 18 ++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 tests/ui/suggestions/range-index-instead-of-colon.rs create mode 100644 tests/ui/suggestions/range-index-instead-of-colon.stderr diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 3189fcf7ff9bf..a7c6f8c5d8c26 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -756,6 +756,11 @@ impl Token { ) } + /// Returns `true` if the token is the integer literal. + pub fn is_integer_lit(&self) -> bool { + matches!(self.kind, Literal(Lit { kind: LitKind::Integer, .. })) + } + /// Returns `true` if the token is a non-raw identifier for which `pred` holds. pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool { match self.ident() { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 5316dde609605..94d200188eafb 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -567,6 +567,22 @@ impl<'a> Parser<'a> { snapshot.recover_diff_marker(); } if self.token == token::Colon { + // if a previous and next token of the current one is + // integer literal (e.g. `1:42`), it's likely a range + // expression for Pythonistas and we can suggest so. + if self.prev_token.is_integer_lit() + && self.look_ahead(1, |token| token.is_integer_lit()) + { + // TODO(hkmatsumoto): Might be better to trigger + // this only when parsing an index expression. + err.span_suggestion_verbose( + self.token.span, + "you might have meant to make a slice with range index", + "..", + Applicability::MaybeIncorrect, + ); + } + // if next token is following a colon, it's likely a path // and we can suggest a path separator self.bump(); diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs new file mode 100644 index 0000000000000..a5e0098544db3 --- /dev/null +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -0,0 +1,8 @@ +// edition:2021 + +fn main() { + &[1, 2, 3][1:2]; + //~^ ERROR: expected one of + //~| HELP: you might have meant to make a slice with range index + //~| HELP: maybe write a path separator here +} \ No newline at end of file diff --git a/tests/ui/suggestions/range-index-instead-of-colon.stderr b/tests/ui/suggestions/range-index-instead-of-colon.stderr new file mode 100644 index 0000000000000..72e400fba0ac8 --- /dev/null +++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr @@ -0,0 +1,18 @@ +error: expected one of `.`, `?`, `]`, or an operator, found `:` + --> $DIR/range-index-instead-of-colon.rs:4:17 + | +LL | &[1, 2, 3][1:2]; + | ^ expected one of `.`, `?`, `]`, or an operator + | + = note: type ascription syntax has been removed, see issue #101728 +help: you might have meant to make a slice with range index + | +LL | &[1, 2, 3][1..2]; + | ~~ +help: maybe write a path separator here + | +LL | &[1, 2, 3][1::2]; + | ~~ + +error: aborting due to previous error + From 61c3e4d56ecc77899095590d9fd03ffc39e9849e Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Wed, 3 May 2023 22:54:22 +0900 Subject: [PATCH 2/4] Make tidy test happy --- compiler/rustc_parse/src/parser/stmt.rs | 2 +- tests/ui/suggestions/range-index-instead-of-colon.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 94d200188eafb..71db5609edc2e 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -573,7 +573,7 @@ impl<'a> Parser<'a> { if self.prev_token.is_integer_lit() && self.look_ahead(1, |token| token.is_integer_lit()) { - // TODO(hkmatsumoto): Might be better to trigger + // FIXME(hkmatsumoto): Might be better to trigger // this only when parsing an index expression. err.span_suggestion_verbose( self.token.span, diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs index a5e0098544db3..f183590d2c7a2 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.rs +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -5,4 +5,4 @@ fn main() { //~^ ERROR: expected one of //~| HELP: you might have meant to make a slice with range index //~| HELP: maybe write a path separator here -} \ No newline at end of file +} From 730d299354f7ef09d8e30609110fc499e0e22d71 Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Tue, 16 May 2023 14:53:05 +0900 Subject: [PATCH 3/4] Address review feedbacks Also addressed merge conflicts upon rebasing. --- compiler/rustc_parse/src/parser/stmt.rs | 33 ++++++++++--------- .../range-index-instead-of-colon.rs | 1 - .../range-index-instead-of-colon.stderr | 7 +--- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 71db5609edc2e..391a4777bd944 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -571,6 +571,7 @@ impl<'a> Parser<'a> { // integer literal (e.g. `1:42`), it's likely a range // expression for Pythonistas and we can suggest so. if self.prev_token.is_integer_lit() + && self.may_recover() && self.look_ahead(1, |token| token.is_integer_lit()) { // FIXME(hkmatsumoto): Might be better to trigger @@ -581,22 +582,22 @@ impl<'a> Parser<'a> { "..", Applicability::MaybeIncorrect, ); - } - - // if next token is following a colon, it's likely a path - // and we can suggest a path separator - self.bump(); - if self.token.span.lo() == self.prev_token.span.hi() { - err.span_suggestion_verbose( - self.prev_token.span, - "maybe write a path separator here", - "::", - Applicability::MaybeIncorrect, - ); - } - if self.sess.unstable_features.is_nightly_build() { - // FIXME(Nilstrieb): Remove this again after a few months. - err.note("type ascription syntax has been removed, see issue #101728 "); + } else { + // if next token is following a colon, it's likely a path + // and we can suggest a path separator + self.bump(); + if self.token.span.lo() == self.prev_token.span.hi() { + err.span_suggestion_verbose( + self.prev_token.span, + "maybe write a path separator here", + "::", + Applicability::MaybeIncorrect, + ); + } + if self.sess.unstable_features.is_nightly_build() { + // FIXME(Nilstrieb): Remove this again after a few months. + err.note("type ascription syntax has been removed, see issue #101728 "); + } } } diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs index f183590d2c7a2..0805102de7844 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.rs +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -4,5 +4,4 @@ fn main() { &[1, 2, 3][1:2]; //~^ ERROR: expected one of //~| HELP: you might have meant to make a slice with range index - //~| HELP: maybe write a path separator here } diff --git a/tests/ui/suggestions/range-index-instead-of-colon.stderr b/tests/ui/suggestions/range-index-instead-of-colon.stderr index 72e400fba0ac8..c7a12e9e4fb15 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.stderr +++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr @@ -4,15 +4,10 @@ error: expected one of `.`, `?`, `]`, or an operator, found `:` LL | &[1, 2, 3][1:2]; | ^ expected one of `.`, `?`, `]`, or an operator | - = note: type ascription syntax has been removed, see issue #101728 help: you might have meant to make a slice with range index | LL | &[1, 2, 3][1..2]; | ~~ -help: maybe write a path separator here - | -LL | &[1, 2, 3][1::2]; - | ~~ -error: aborting due to previous error +error: aborting due to 1 previous error From acec70de9b0b76cb5b077b030360fa217ccdcdec Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Mon, 27 Nov 2023 22:18:03 +0900 Subject: [PATCH 4/4] Change help message to make some sense in broader context --- compiler/rustc_parse/src/parser/stmt.rs | 2 +- tests/ui/suggestions/range-index-instead-of-colon.rs | 2 +- tests/ui/suggestions/range-index-instead-of-colon.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 391a4777bd944..620ba4a3cb363 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -578,7 +578,7 @@ impl<'a> Parser<'a> { // this only when parsing an index expression. err.span_suggestion_verbose( self.token.span, - "you might have meant to make a slice with range index", + "you might have meant a range expression", "..", Applicability::MaybeIncorrect, ); diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs index 0805102de7844..3267527ecf2a7 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.rs +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -3,5 +3,5 @@ fn main() { &[1, 2, 3][1:2]; //~^ ERROR: expected one of - //~| HELP: you might have meant to make a slice with range index + //~| HELP: you might have meant a range expression } diff --git a/tests/ui/suggestions/range-index-instead-of-colon.stderr b/tests/ui/suggestions/range-index-instead-of-colon.stderr index c7a12e9e4fb15..df29356cc16b3 100644 --- a/tests/ui/suggestions/range-index-instead-of-colon.stderr +++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr @@ -4,7 +4,7 @@ error: expected one of `.`, `?`, `]`, or an operator, found `:` LL | &[1, 2, 3][1:2]; | ^ expected one of `.`, `?`, `]`, or an operator | -help: you might have meant to make a slice with range index +help: you might have meant a range expression | LL | &[1, 2, 3][1..2]; | ~~