Skip to content

Commit 8c7ccdc

Browse files
committed
Identify methods using functions ids rather than string names
1 parent 920e57b commit 8c7ccdc

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

crates/hir_def/src/path.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ pub use hir_expand::name as __name;
304304
#[macro_export]
305305
macro_rules! __known_path {
306306
(core::iter::IntoIterator) => {};
307+
(core::iter::Iterator) => {};
307308
(core::result::Result) => {};
308309
(core::option::Option) => {};
309310
(core::ops::Range) => {};

crates/hir_expand/src/name.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ pub mod known {
186186
Neg,
187187
Not,
188188
Index,
189+
// Components of known path (function name)
190+
filter_map,
191+
next,
189192
// Builtin macros
190193
file,
191194
column,

crates/hir_ty/src/diagnostics/expr.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
33
use std::sync::Arc;
44

5-
use hir_def::{expr::Statement, path::path, resolver::HasResolver, AdtId, DefWithBodyId};
6-
use hir_expand::diagnostics::DiagnosticSink;
5+
use hir_def::{AdtId, AssocItemId, DefWithBodyId, expr::Statement, path::path, resolver::HasResolver};
6+
use hir_expand::{diagnostics::DiagnosticSink, name};
77
use rustc_hash::FxHashSet;
88
use syntax::{ast, AstPtr};
99

@@ -155,19 +155,39 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
155155
}
156156

157157
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()
158176
let body = db.body(self.owner.into());
159177
let mut prev = None;
160-
161178
for (id, expr) in body.exprs.iter() {
162-
if let Expr::MethodCall { receiver, method_name, args, .. } = expr {
163-
let method_name = format!("{}", method_name);
179+
if let Expr::MethodCall { receiver, .. } = expr {
180+
let function_id = match self.infer.method_resolution(id) {
181+
Some(id) => id,
182+
None => continue,
183+
};
164184

165-
if method_name == "filter_map" && args.len() == 1 {
185+
if function_id == *filter_map_function_id {
166186
prev = Some(id);
167187
continue;
168188
}
169189

170-
if method_name == "next" {
190+
if function_id == *next_function_id {
171191
if let Some(filter_map_id) = prev {
172192
if *receiver == filter_map_id {
173193
let (_, source_map) = db.body_with_source_map(self.owner.into());

0 commit comments

Comments
 (0)