Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #16647 - Young-Flash:fix_replace_filter_map_next_with_find_map, r=Veykril
fix: replace_filter_map_next_with_find_map shouldn't work for dyn trait close https://github.com/rust-lang/rust-analyzer/issues/16596
bors 2024-02-26
parent e1983d2 · parent 7a58a23 · commit 8929853
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs30
-rw-r--r--crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs15
2 files changed, 36 insertions, 9 deletions
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 6c8a187516..1a134e6d78 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -17,6 +17,7 @@ use tracing::debug;
use triomphe::Arc;
use typed_arena::Arena;
+use crate::Interner;
use crate::{
db::HirDatabase,
diagnostics::match_check::{
@@ -149,17 +150,18 @@ impl ExprValidator {
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();
+ checker.prev_receiver_ty = Some(receiver_ty);
}
}
@@ -393,6 +395,7 @@ struct FilterMapNextChecker {
filter_map_function_id: Option<hir_def::FunctionId>,
next_function_id: Option<hir_def::FunctionId>,
prev_filter_map_expr_id: Option<ExprId>,
+ prev_receiver_ty: Option<chalk_ir::Ty<Interner>>,
}
impl FilterMapNextChecker {
@@ -417,7 +420,12 @@ impl FilterMapNextChecker {
),
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,11 @@ impl FilterMapNextChecker {
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
+ .as_ref()
+ .map_or(false, |it| it.strip_references().dyn_trait().is_some());
+ if *receiver_expr_id == prev_filter_map_expr_id && !is_dyn_trait {
return Some(());
}
}
diff --git a/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs b/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
index 6d3dcf31ab..87932bf989 100644
--- a/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
+++ b/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
@@ -81,6 +81,21 @@ fn foo() {
}
#[test]
+ fn replace_filter_map_next_dont_work_for_not_sized_issues_16596() {
+ check_diagnostics(
+ r#"
+//- minicore: iterators
+fn foo() {
+ let mut j = [0].into_iter();
+ let i: &mut dyn Iterator<Item = i32> = &mut j;
+ let dummy_fn = |v| (v > 0).then_some(v + 1);
+ let _res = i.filter_map(dummy_fn).next();
+}
+"#,
+ );
+ }
+
+ #[test]
fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() {
check_diagnostics(
r#"