aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_def/src/path.rs1
-rw-r--r--crates/hir_expand/src/name.rs3
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs34
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]
305macro_rules! __known_path { 305macro_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
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());