about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-01-27 17:41:02 +0000
committerGitHub <noreply@github.com>2025-01-27 17:41:02 +0000
commitda33e7ce8a91333851d31f9438556604b65f6c10 (patch)
treeea97d4b3928b2fb3b7b1b3d4483adfc823959f27
parent8ed922785e32202e540d690bc6ceb8bbc7669857 (diff)
parentb4508dc406f0def337bb4a6590f45dd0327a068e (diff)
downloadrust-da33e7ce8a91333851d31f9438556604b65f6c10.tar.gz
rust-da33e7ce8a91333851d31f9438556604b65f6c10.zip
Merge pull request #19050 from ChayimFriedman2/iter-self
fix: Don't suggest `into_iter().method()` on iterators
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs26
2 files changed, 36 insertions, 1 deletions
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index dbcef6fb1e2..a38c0211e87 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -4961,6 +4961,17 @@ impl Type {
         self.normalize_trait_assoc_type(db, &[], iterator_item.into())
     }
 
+    pub fn impls_iterator(self, db: &dyn HirDatabase) -> bool {
+        let Some(iterator_trait) =
+            db.lang_item(self.env.krate, LangItem::Iterator).and_then(|it| it.as_trait())
+        else {
+            return false;
+        };
+        let canonical_ty =
+            Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
+        method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, iterator_trait)
+    }
+
     /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
     pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option<Type> {
         let trait_ = db.lang_item(self.env.krate, LangItem::IntoIterIntoIter).and_then(|it| {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
index d12654665ce..0557265f235 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
@@ -89,7 +89,7 @@ pub(crate) fn complete_dot(
         acc.add_method(ctx, dot_access, func, None, None)
     });
 
-    if ctx.config.enable_auto_iter {
+    if ctx.config.enable_auto_iter && !receiver_ty.strip_references().impls_iterator(ctx.db) {
         // FIXME:
         // Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
         // its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
@@ -1505,4 +1505,28 @@ fn main() {
 "#]],
         );
     }
+
+    #[test]
+    fn no_iter_suggestion_on_iterator() {
+        check_no_kw(
+            r#"
+//- minicore: iterator
+struct MyIter;
+impl Iterator for MyIter {
+    type Item = ();
+    fn next(&mut self) -> Option<Self::Item> { None }
+}
+
+fn main() {
+    MyIter.$0
+}
+"#,
+            expect![[r#"
+                me by_ref() (as Iterator)                             fn(&mut self) -> &mut Self
+                me into_iter() (as IntoIterator)    fn(self) -> <Self as IntoIterator>::IntoIter
+                me next() (as Iterator)        fn(&mut self) -> Option<<Self as Iterator>::Item>
+                me nth(…) (as Iterator) fn(&mut self, usize) -> Option<<Self as Iterator>::Item>
+            "#]],
+        );
+    }
 }