Skip to content

Commit

Permalink
useless_asref: no lint if in a closure to change the ref depth (#14090
Browse files Browse the repository at this point in the history
)

Removing the `.as_ref()` or `.as_mut()` as the top-level expression in a
closure may change the type of the result. In this case, it may be
better not to lint rather than proposing a fix that would not work.

changelog: [`useless_asref`]: do not remove the `.as_ref()` or
`.as_mut()` call if this would change the type of the enclosing closure

Fix #14088
  • Loading branch information
Centri3 authored Feb 7, 2025
2 parents f6d23c8 + 16e2196 commit 0d3bf65
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 6 deletions.
19 changes: 13 additions & 6 deletions clippy_lints/src/methods/useless_asref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty);
let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty);
if base_rcv_ty == base_res_ty && rcv_depth >= res_depth {
// allow the `as_ref` or `as_mut` if it is followed by another method call
if let Some(parent) = get_parent_expr(cx, expr)
&& let hir::ExprKind::MethodCall(segment, ..) = parent.kind
&& segment.ident.span != expr.span
{
return;
if let Some(parent) = get_parent_expr(cx, expr) {
// allow the `as_ref` or `as_mut` if it is followed by another method call
if let hir::ExprKind::MethodCall(segment, ..) = parent.kind
&& segment.ident.span != expr.span
{
return;
}

// allow the `as_ref` or `as_mut` if they belong to a closure that changes
// the number of references
if matches!(parent.kind, hir::ExprKind::Closure(..)) && rcv_depth != res_depth {
return;
}
}

let mut applicability = Applicability::MachineApplicable;
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/useless_asref.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ fn issue_12528() {
let _ = opt.as_ref().map(RcWeak::clone);
}

fn issue_14088() {
let s = Some("foo");
let _: Option<&str> = s.as_ref().map(|x| x.as_ref());
}

fn main() {
not_ok();
ok();
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/useless_asref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ fn issue_12528() {
let _ = opt.as_ref().map(RcWeak::clone);
}

fn issue_14088() {
let s = Some("foo");
let _: Option<&str> = s.as_ref().map(|x| x.as_ref());
}

fn main() {
not_ok();
ok();
Expand Down

0 comments on commit 0d3bf65

Please sign in to comment.