diff options
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/diagnostics/expr.rs | 34 |
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 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{expr::Statement, path::path, resolver::HasResolver, AdtId, DefWithBodyId}; | 5 | use hir_def::{AdtId, AssocItemId, DefWithBodyId, expr::Statement, path::path, resolver::HasResolver}; |
6 | use hir_expand::diagnostics::DiagnosticSink; | 6 | use hir_expand::{diagnostics::DiagnosticSink, name}; |
7 | use rustc_hash::FxHashSet; | 7 | use rustc_hash::FxHashSet; |
8 | use syntax::{ast, AstPtr}; | 8 | use 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()); |