From 6d8903ae5f3d3a16a96e0a3e3f32ce88d7998392 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Thu, 29 Sep 2022 18:44:45 +0900 Subject: [PATCH] fix: infer for-loop item type with `IntoIterator` and `Iterator` --- crates/hir-expand/src/name.rs | 1 + crates/hir-ty/src/infer.rs | 6 ++++++ crates/hir-ty/src/infer/expr.rs | 4 +++- crates/hir-ty/src/tests/traits.rs | 12 +++++++++++- crates/ide/src/inlay_hints.rs | 9 ++++++++- 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 4ce21a57967..2679a1c3602 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -263,6 +263,7 @@ macro_rules! known_names { Iterator, IntoIterator, Item, + IntoIter, Try, Ok, Future, diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 039824694ac..25179afaca7 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -883,6 +883,12 @@ fn resolve_lang_item(&self, name: Name) -> Option { fn resolve_into_iter_item(&self) -> Option { let path = path![core::iter::IntoIterator]; let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; + self.db.trait_data(trait_).associated_type_by_name(&name![IntoIter]) + } + + fn resolve_iterator_item(&self) -> Option { + let path = path![core::iter::Iterator]; + let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; self.db.trait_data(trait_).associated_type_by_name(&name![Item]) } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index e3d6be23e65..2643baf8a32 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -207,8 +207,10 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { } &Expr::For { iterable, body, pat, label } => { let iterable_ty = self.infer_expr(iterable, &Expectation::none()); - let pat_ty = + let into_iter_ty = self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); + let pat_ty = + self.resolve_associated_type(into_iter_ty, self.resolve_iterator_item()); self.infer_pat(pat, &pat_ty, BindingMode::default()); self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| { diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 21a86319763..555b6972fb7 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -279,6 +279,10 @@ fn test() { pub mod iter { pub trait IntoIterator { type Item; + type IntoIter: Iterator; + } + pub trait Iterator { + type Item; } } pub mod prelude { @@ -297,7 +301,13 @@ pub fn push(&mut self, t: T) { } } impl IntoIterator for Vec { - type Item=T; + type Item = T; + type IntoIter = IntoIter; + } + + struct IntoIter {} + impl Iterator for IntoIter { + type Item = T; } } "#, diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 08363d21e89..34d8bf67a30 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -2024,7 +2024,14 @@ pub fn push(&mut self, t: T) {} } impl IntoIterator for Vec { - type Item=T; + type Item = T; + type IntoIter = IntoIter; +} + +struct IntoIter {} + +impl Iterator for IntoIter { + type Item = T; } fn main() {