diff options
-rw-r--r-- | crates/hir_def/src/path.rs | 1 | ||||
-rw-r--r-- | crates/hir_expand/src/name.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/expr.rs | 34 |
3 files changed, 31 insertions, 7 deletions
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index e34cd7f2f..84ea09b53 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -304,6 +304,7 @@ pub use hir_expand::name as __name; | |||
304 | #[macro_export] | 304 | #[macro_export] |
305 | macro_rules! __known_path { | 305 | macro_rules! __known_path { |
306 | (core::iter::IntoIterator) => {}; | 306 | (core::iter::IntoIterator) => {}; |
307 | (core::iter::Iterator) => {}; | ||
307 | (core::result::Result) => {}; | 308 | (core::result::Result) => {}; |
308 | (core::option::Option) => {}; | 309 | (core::option::Option) => {}; |
309 | (core::ops::Range) => {}; | 310 | (core::ops::Range) => {}; |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index d692cec14..c7609e90d 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -186,6 +186,9 @@ pub mod known { | |||
186 | Neg, | 186 | Neg, |
187 | Not, | 187 | Not, |
188 | Index, | 188 | Index, |
189 | // Components of known path (function name) | ||
190 | filter_map, | ||
191 | next, | ||
189 | // Builtin macros | 192 | // Builtin macros |
190 | file, | 193 | file, |
191 | column, | 194 | column, |
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()); |