fix: search_is_some suggests wrongly inside macro
This commit is contained in:
parent
1c64211aee
commit
222ebd0535
6 changed files with 73 additions and 5 deletions
|
|
@ -6,9 +6,9 @@ use crate::ty::expr_sig;
|
|||
use crate::{get_parent_expr_for_hir, higher};
|
||||
use rustc_ast::ast;
|
||||
use rustc_ast::util::parser::AssocOp;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
|
||||
use rustc_hir::{self as hir, Closure, ExprKind, HirId, MutTy, Node, TyKind};
|
||||
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
|
||||
use rustc_lint::{EarlyContext, LateContext, LintContext};
|
||||
use rustc_middle::hir::place::ProjectionKind;
|
||||
|
|
@ -753,8 +753,10 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
|
|||
let mut visitor = DerefDelegate {
|
||||
cx,
|
||||
closure_span: closure.span,
|
||||
closure_arg_id: closure_body.params[0].pat.hir_id,
|
||||
closure_arg_is_type_annotated_double_ref,
|
||||
next_pos: closure.span.lo(),
|
||||
checked_borrows: FxHashSet::default(),
|
||||
suggestion_start: String::new(),
|
||||
applicability: Applicability::MachineApplicable,
|
||||
};
|
||||
|
|
@ -780,10 +782,15 @@ struct DerefDelegate<'a, 'tcx> {
|
|||
cx: &'a LateContext<'tcx>,
|
||||
/// The span of the input closure to adapt
|
||||
closure_span: Span,
|
||||
/// The `hir_id` of the closure argument being checked
|
||||
closure_arg_id: HirId,
|
||||
/// Indicates if the arg of the closure is a type annotated double reference
|
||||
closure_arg_is_type_annotated_double_ref: bool,
|
||||
/// last position of the span to gradually build the suggestion
|
||||
next_pos: BytePos,
|
||||
/// `hir_id`s that has been checked. This is used to avoid checking the same `hir_id` multiple
|
||||
/// times when inside macro expansions.
|
||||
checked_borrows: FxHashSet<HirId>,
|
||||
/// starting part of the gradually built suggestion
|
||||
suggestion_start: String,
|
||||
/// confidence on the built suggestion
|
||||
|
|
@ -847,9 +854,15 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
#[expect(clippy::too_many_lines)]
|
||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
|
||||
if let PlaceBase::Local(id) = cmt.place.base {
|
||||
let span = self.cx.tcx.hir_span(cmt.hir_id);
|
||||
if !self.checked_borrows.insert(cmt.hir_id) {
|
||||
// already checked this span and hir_id, skip
|
||||
return;
|
||||
}
|
||||
|
||||
let start_span = Span::new(self.next_pos, span.lo(), span.ctxt(), None);
|
||||
let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
|
||||
|
||||
|
|
@ -858,7 +871,12 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
// full identifier that includes projection (i.e.: `fp.field`)
|
||||
let ident_str_with_proj = snippet(self.cx, span, "..").to_string();
|
||||
|
||||
if cmt.place.projections.is_empty() {
|
||||
// Make sure to get in all projections if we're on a `matches!`
|
||||
if let Node::Pat(pat) = self.cx.tcx.hir_node(id)
|
||||
&& pat.hir_id != self.closure_arg_id
|
||||
{
|
||||
let _ = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
|
||||
} else if cmt.place.projections.is_empty() {
|
||||
// handle item without any projection, that needs an explicit borrowing
|
||||
// i.e.: suggest `&x` instead of `x`
|
||||
let _: fmt::Result = write!(self.suggestion_start, "{start_snip}&{ident_str}");
|
||||
|
|
|
|||
|
|
@ -87,3 +87,18 @@ fn is_none() {
|
|||
let _ = (0..1).find(some_closure).is_none();
|
||||
//~^ search_is_some
|
||||
}
|
||||
|
||||
#[allow(clippy::match_like_matches_macro)]
|
||||
fn issue15102() {
|
||||
let values = [None, Some(3)];
|
||||
let has_even = values
|
||||
//~^ search_is_some
|
||||
.iter()
|
||||
.find(|v| match v {
|
||||
Some(x) if x % 2 == 0 => true,
|
||||
_ => false,
|
||||
})
|
||||
.is_some();
|
||||
|
||||
println!("{has_even}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,5 +90,20 @@ error: called `is_none()` after searching an `Iterator` with `find`
|
|||
LL | let _ = (0..1).find(some_closure).is_none();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(some_closure)`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: called `is_some()` after searching an `Iterator` with `find`
|
||||
--> tests/ui/search_is_some.rs:94:20
|
||||
|
|
||||
LL | let has_even = values
|
||||
| ____________________^
|
||||
LL | |
|
||||
LL | | .iter()
|
||||
LL | | .find(|v| match v {
|
||||
... |
|
||||
LL | | })
|
||||
LL | | .is_some();
|
||||
| |__________________^
|
||||
|
|
||||
= help: this is more succinctly expressed by calling `any()`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -289,3 +289,10 @@ mod issue9120 {
|
|||
//~^ search_is_some
|
||||
}
|
||||
}
|
||||
|
||||
fn issue15102() {
|
||||
let values = [None, Some(3)];
|
||||
let has_even = values.iter().any(|v| matches!(&v, Some(x) if x % 2 == 0));
|
||||
//~^ search_is_some
|
||||
println!("{has_even}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,3 +297,10 @@ mod issue9120 {
|
|||
//~^ search_is_some
|
||||
}
|
||||
}
|
||||
|
||||
fn issue15102() {
|
||||
let values = [None, Some(3)];
|
||||
let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some();
|
||||
//~^ search_is_some
|
||||
println!("{has_even}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -289,5 +289,11 @@ error: called `is_some()` after searching an `Iterator` with `find`
|
|||
LL | let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))`
|
||||
|
||||
error: aborting due to 46 previous errors
|
||||
error: called `is_some()` after searching an `Iterator` with `find`
|
||||
--> tests/ui/search_is_some_fixable_some.rs:303:34
|
||||
|
|
||||
LL | let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| matches!(&v, Some(x) if x % 2 == 0))`
|
||||
|
||||
error: aborting due to 47 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue