From e65c060d78db59c5f21cb13f4ec322e407f0a642 Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Wed, 3 May 2023 22:32:52 +0900 Subject: [PATCH] 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 3189fcf7ff9..a7c6f8c5d8c 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -756,6 +756,11 @@ pub fn is_numeric_lit(&self) -> bool { ) } + /// 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 5316dde6096..94d200188ea 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -567,6 +567,22 @@ pub(crate) fn parse_block_tail( 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 00000000000..a5e0098544d --- /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 00000000000..72e400fba0a --- /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 +