aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs34
1 files changed, 27 insertions, 7 deletions
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index b87557ff5..16bbd48fb 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -2,8 +2,8 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{expr::Statement, path::path, resolver::HasResolver, AdtId, DefWithBodyId}; 5use hir_def::{AdtId, AssocItemId, DefWithBodyId, expr::Statement, path::path, resolver::HasResolver};
6use hir_expand::diagnostics::DiagnosticSink; 6use hir_expand::{diagnostics::DiagnosticSink, name};
7use rustc_hash::FxHashSet; 7use rustc_hash::FxHashSet;
8use syntax::{ast, AstPtr}; 8use syntax::{ast, AstPtr};
9 9
@@ -155,19 +155,39 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
155 } 155 }
156 156
157 fn check_for_filter_map_next(&mut self, db: &dyn HirDatabase) { 157 fn check_for_filter_map_next(&mut self, db: &dyn HirDatabase) {
158 // Find the FunctionIds for Iterator::filter_map and Iterator::next
159 let iterator_path = path![core::iter::Iterator];
160 let resolver = self.owner.resolver(db.upcast());
161 let iterator_trait_id = match resolver.resolve_known_trait(db.upcast(), &iterator_path) {
162 Some(id) => id,
163 None => return,
164 };
165 let iterator_trait_items = &db.trait_data(iterator_trait_id).items;
166 let filter_map_function_id = match iterator_trait_items.iter().find(|item| item.0 == name![filter_map]) {
167 Some((_, AssocItemId::FunctionId(id))) => id,
168 _ => return,
169 };
170 let next_function_id = match iterator_trait_items.iter().find(|item| item.0 == name![next]) {
171 Some((_, AssocItemId::FunctionId(id))) => id,
172 _ => return,
173 };
174
175 // Search function body for instances of .filter_map(..).next()
158 let body = db.body(self.owner.into()); 176 let body = db.body(self.owner.into());
159 let mut prev = None; 177 let mut prev = None;
160
161 for (id, expr) in body.exprs.iter() { 178 for (id, expr) in body.exprs.iter() {
162 if let Expr::MethodCall { receiver, method_name, args, .. } = expr { 179 if let Expr::MethodCall { receiver, .. } = expr {
163 let method_name = format!("{}", method_name); 180 let function_id = match self.infer.method_resolution(id) {
181 Some(id) => id,
182 None => continue,
183 };
164 184
165 if method_name == "filter_map" && args.len() == 1 { 185 if function_id == *filter_map_function_id {
166 prev = Some(id); 186 prev = Some(id);
167 continue; 187 continue;
168 } 188 }
169 189
170 if method_name == "next" { 190 if function_id == *next_function_id {
171 if let Some(filter_map_id) = prev { 191 if let Some(filter_map_id) = prev {
172 if *receiver == filter_map_id { 192 if *receiver == filter_map_id {
173 let (_, source_map) = db.body_with_source_map(self.owner.into()); 193 let (_, source_map) = db.body_with_source_map(self.owner.into());