From d562f487c92698cb901df89cab0682ec2cbef222 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Fri, 12 Nov 2021 01:47:43 +0900 Subject: [PATCH] suggest `&str.chars()` on attempt to `&str.iter()` check if `String` or `&String` or `&str` Update compiler/rustc_typeck/src/check/method/suggest.rs Co-authored-by: Esteban Kuber remove some trailing whitespace --- .../rustc_typeck/src/check/method/suggest.rs | 20 ++++++++ src/test/ui/suggest-using-chars.rs | 7 +++ src/test/ui/suggest-using-chars.stderr | 48 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/test/ui/suggest-using-chars.rs create mode 100644 src/test/ui/suggest-using-chars.stderr diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 71cd8a43329c5..661ced952c736 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -478,6 +478,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut label_span_not_found = || { if unsatisfied_predicates.is_empty() { err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); + let is_string_or_ref_str = match actual.kind() { + ty::Ref(_, ty, _) => { + ty.is_str() + || matches!( + ty.kind(), + ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did) + ) + } + ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did), + _ => false, + }; + if is_string_or_ref_str && item_name.name == sym::iter { + err.span_suggestion_verbose( + item_name.span, + "because of the in-memory representation of `&str`, to obtain \ + an `Iterator` over each of its codepoint use method `chars`", + String::from("chars"), + Applicability::MachineApplicable, + ); + } if let ty::Adt(adt, _) = rcvr_ty.kind() { let mut inherent_impls_candidate = self .tcx diff --git a/src/test/ui/suggest-using-chars.rs b/src/test/ui/suggest-using-chars.rs new file mode 100644 index 0000000000000..95732881baf09 --- /dev/null +++ b/src/test/ui/suggest-using-chars.rs @@ -0,0 +1,7 @@ +pub fn main() { + let _ = "foo".iter(); //~ ERROR no method named `iter` found for reference `&'static str` in the current scope + let _ = "foo".foo(); //~ ERROR no method named `foo` found for reference `&'static str` in the current scope + let _ = String::from("bar").iter(); //~ ERROR no method named `iter` found for struct `String` in the current scope + let _ = (&String::from("bar")).iter(); //~ ERROR no method named `iter` found for reference `&String` in the current scope + let _ = 0.iter(); //~ ERROR no method named `iter` found for type `{integer}` in the current scope +} diff --git a/src/test/ui/suggest-using-chars.stderr b/src/test/ui/suggest-using-chars.stderr new file mode 100644 index 0000000000000..99bcfb08a0892 --- /dev/null +++ b/src/test/ui/suggest-using-chars.stderr @@ -0,0 +1,48 @@ +error[E0599]: no method named `iter` found for reference `&'static str` in the current scope + --> $DIR/suggest-using-chars.rs:2:19 + | +LL | let _ = "foo".iter(); + | ^^^^ method not found in `&'static str` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = "foo".chars(); + | ~~~~~ + +error[E0599]: no method named `foo` found for reference `&'static str` in the current scope + --> $DIR/suggest-using-chars.rs:3:19 + | +LL | let _ = "foo".foo(); + | ^^^ method not found in `&'static str` + +error[E0599]: no method named `iter` found for struct `String` in the current scope + --> $DIR/suggest-using-chars.rs:4:33 + | +LL | let _ = String::from("bar").iter(); + | ^^^^ method not found in `String` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = String::from("bar").chars(); + | ~~~~~ + +error[E0599]: no method named `iter` found for reference `&String` in the current scope + --> $DIR/suggest-using-chars.rs:5:36 + | +LL | let _ = (&String::from("bar")).iter(); + | ^^^^ method not found in `&String` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = (&String::from("bar")).chars(); + | ~~~~~ + +error[E0599]: no method named `iter` found for type `{integer}` in the current scope + --> $DIR/suggest-using-chars.rs:6:15 + | +LL | let _ = 0.iter(); + | ^^^^ method not found in `{integer}` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`.