From 28751286a894071e8c0639c6623c676bfdece386 Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Sat, 22 Nov 2025 16:34:18 +0800 Subject: [PATCH] Fix skipiter not applicable in autoderef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example --- **std example**: ```rust fn foo(nums: std::rc::Rc<[i32]>) { nums.$0 } ``` --- **minicore example**: ```rust struct Foo; impl Foo { fn iter(&self) -> Iter { Iter } } impl IntoIterator for &Foo { type Item = (); type IntoIter = Iter; fn into_iter(self) -> Self::IntoIter { Iter } } struct Ref; impl core::ops::Deref for Ref { type Target = Foo; fn deref(&self) -> &Self::Target { &Foo } } struct Iter; impl Iterator for Iter { type Item = (); fn next(&mut self) -> Option { None } } fn foo() { Ref.$0 } ``` **Before this PR** ```text me deref() (use core::ops::Deref) fn(&self) -> &::Target me into_iter() (as IntoIterator) fn(self) -> ::IntoIter me iter() fn(&self) -> Iter ``` **After this PR** ```text me deref() (use core::ops::Deref) fn(&self) -> &::Target me into_iter() (as IntoIterator) fn(self) -> ::IntoIter me iter() fn(&self) -> Iter me iter().by_ref() (as Iterator) fn(&mut self) -> &mut Self me iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter me iter().next() (as Iterator) fn(&mut self) -> Option<::Item> me iter().nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> ``` --- crates/ide-completion/src/completions/dot.rs | 40 ++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs index c9f4405872..9c2e0dcf1c 100644 --- a/crates/ide-completion/src/completions/dot.rs +++ b/crates/ide-completion/src/completions/dot.rs @@ -91,9 +91,9 @@ pub(crate) fn complete_dot( // its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`. // Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid let iter = receiver_ty - .strip_references() - .add_reference(hir::Mutability::Shared) - .into_iterator_iter(ctx.db) + .autoderef(ctx.db) + .map(|ty| ty.strip_references().add_reference(hir::Mutability::Shared)) + .find_map(|ty| ty.into_iterator_iter(ctx.db)) .map(|ty| (ty, SmolStr::new_static("iter()"))); // Does ::IntoIter` exist? let into_iter = || { @@ -1466,6 +1466,40 @@ fn foo() { me into_iter().nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> "#]], ); + check_no_kw( + r#" +//- minicore: iterator, deref +struct Foo; +impl Foo { fn iter(&self) -> Iter { Iter } } +impl IntoIterator for &Foo { + type Item = (); + type IntoIter = Iter; + fn into_iter(self) -> Self::IntoIter { Iter } +} +struct Ref; +impl core::ops::Deref for Ref { + type Target = Foo; + fn deref(&self) -> &Self::Target { &Foo } +} +struct Iter; +impl Iterator for Iter { + type Item = (); + fn next(&mut self) -> Option { None } +} +fn foo() { + Ref.$0 +} +"#, + expect![[r#" + me deref() (use core::ops::Deref) fn(&self) -> &::Target + me into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me iter() fn(&self) -> Iter + me iter().by_ref() (as Iterator) fn(&mut self) -> &mut Self + me iter().into_iter() (as IntoIterator) fn(self) -> ::IntoIter + me iter().next() (as Iterator) fn(&mut self) -> Option<::Item> + me iter().nth(…) (as Iterator) fn(&mut self, usize) -> Option<::Item> + "#]], + ); } #[test]