diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index 6c8a1875165..612deb7e88f 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -17,6 +17,7 @@ use triomphe::Arc; use typed_arena::Arena; +use crate::Interner; use crate::{ db::HirDatabase, diagnostics::match_check::{ @@ -149,17 +150,18 @@ fn validate_call( None => return, }; - if filter_map_next_checker - .get_or_insert_with(|| { - FilterMapNextChecker::new(&self.owner.resolver(db.upcast()), db) - }) - .check(call_id, receiver, &callee) - .is_some() - { + let checker = filter_map_next_checker.get_or_insert_with(|| { + FilterMapNextChecker::new(&self.owner.resolver(db.upcast()), db) + }); + + if checker.check(call_id, receiver, &callee).is_some() { self.diagnostics.push(BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr: call_id, }); } + + let receiver_ty = self.infer[receiver.clone()].strip_references().clone(); + checker.prev_receiver_ty = Some(receiver_ty); } } @@ -393,6 +395,7 @@ struct FilterMapNextChecker { filter_map_function_id: Option, next_function_id: Option, prev_filter_map_expr_id: Option, + prev_receiver_ty: Option>, } impl FilterMapNextChecker { @@ -417,7 +420,12 @@ fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self { ), None => (None, None), }; - Self { filter_map_function_id, next_function_id, prev_filter_map_expr_id: None } + Self { + filter_map_function_id, + next_function_id, + prev_filter_map_expr_id: None, + prev_receiver_ty: None, + } } // check for instances of .filter_map(..).next() @@ -434,7 +442,9 @@ fn check( if *function_id == self.next_function_id? { if let Some(prev_filter_map_expr_id) = self.prev_filter_map_expr_id { - if *receiver_expr_id == prev_filter_map_expr_id { + let is_dyn_trait = + self.prev_receiver_ty.clone().map_or(false, |it| it.dyn_trait().is_some()); + if *receiver_expr_id == prev_filter_map_expr_id && !is_dyn_trait { return Some(()); } }