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
This commit is contained in:
bors 2024-02-26 11:31:44 +00:00
commit 8929853df7
2 changed files with 36 additions and 9 deletions

View File

@ -17,6 +17,7 @@
use triomphe::Arc; use triomphe::Arc;
use typed_arena::Arena; use typed_arena::Arena;
use crate::Interner;
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase,
diagnostics::match_check::{ diagnostics::match_check::{
@ -149,17 +150,18 @@ fn validate_call(
None => return, None => return,
}; };
if filter_map_next_checker let checker = filter_map_next_checker.get_or_insert_with(|| {
.get_or_insert_with(|| { FilterMapNextChecker::new(&self.owner.resolver(db.upcast()), db)
FilterMapNextChecker::new(&self.owner.resolver(db.upcast()), db) });
})
.check(call_id, receiver, &callee) if checker.check(call_id, receiver, &callee).is_some() {
.is_some()
{
self.diagnostics.push(BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { self.diagnostics.push(BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap {
method_call_expr: call_id, 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>, filter_map_function_id: Option<hir_def::FunctionId>,
next_function_id: Option<hir_def::FunctionId>, next_function_id: Option<hir_def::FunctionId>,
prev_filter_map_expr_id: Option<ExprId>, prev_filter_map_expr_id: Option<ExprId>,
prev_receiver_ty: Option<chalk_ir::Ty<Interner>>,
} }
impl FilterMapNextChecker { impl FilterMapNextChecker {
@ -417,7 +420,12 @@ fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self {
), ),
None => (None, None), 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() // check for instances of .filter_map(..).next()
@ -434,7 +442,11 @@ fn check(
if *function_id == self.next_function_id? { if *function_id == self.next_function_id? {
if let Some(prev_filter_map_expr_id) = self.prev_filter_map_expr_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(()); return Some(());
} }
} }

View File

@ -80,6 +80,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] #[test]
fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() { fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() {
check_diagnostics( check_diagnostics(