Rollup merge of #110955 - fee1-dead-contrib:sus-operation, r=compiler-errors
uplift `clippy::clone_double_ref` as `suspicious_double_ref_op` Split from #109842. r? ``@compiler-errors``
This commit is contained in:
commit
40c4ed4994
21 changed files with 237 additions and 200 deletions
|
@ -40,7 +40,6 @@ use regex::Regex;
|
|||
use tempfile::Builder as TempFileBuilder;
|
||||
|
||||
use itertools::Itertools;
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::OnceCell;
|
||||
use std::collections::BTreeSet;
|
||||
use std::ffi::OsString;
|
||||
|
@ -576,17 +575,17 @@ fn link_dwarf_object<'a>(
|
|||
|
||||
impl<Relocations> ThorinSession<Relocations> {
|
||||
fn alloc_mmap(&self, data: Mmap) -> &Mmap {
|
||||
(*self.arena_mmap.alloc(data)).borrow()
|
||||
&*self.arena_mmap.alloc(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Relocations> thorin::Session<Relocations> for ThorinSession<Relocations> {
|
||||
fn alloc_data(&self, data: Vec<u8>) -> &[u8] {
|
||||
(*self.arena_data.alloc(data)).borrow()
|
||||
&*self.arena_data.alloc(data)
|
||||
}
|
||||
|
||||
fn alloc_relocation(&self, data: Relocations) -> &Relocations {
|
||||
(*self.arena_relocations.alloc(data)).borrow()
|
||||
&*self.arena_relocations.alloc(data)
|
||||
}
|
||||
|
||||
fn read_input(&self, path: &Path) -> std::io::Result<&[u8]> {
|
||||
|
|
|
@ -50,6 +50,14 @@ lint_deprecated_lint_name =
|
|||
lint_renamed_or_removed_lint = {$msg}
|
||||
.suggestion = use the new name
|
||||
|
||||
lint_suspicious_double_ref_op =
|
||||
using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
|
||||
*[should_not_happen] [{$op}]
|
||||
[deref] dereferencing
|
||||
[borrow] borrowing
|
||||
[clone] cloning
|
||||
} the inner type
|
||||
|
||||
lint_unknown_lint =
|
||||
unknown lint: `{$name}`
|
||||
.suggestion = did you mean
|
||||
|
|
|
@ -1150,6 +1150,14 @@ pub struct NoopMethodCallDiag<'a> {
|
|||
pub label: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_suspicious_double_ref_op)]
|
||||
pub struct SuspiciousDoubleRefDiag<'a> {
|
||||
pub call: Symbol,
|
||||
pub ty: Ty<'a>,
|
||||
pub op: &'static str,
|
||||
}
|
||||
|
||||
// pass_by_value.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_pass_by_value)]
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use crate::context::LintContext;
|
||||
use crate::lints::NoopMethodCallDiag;
|
||||
use crate::lints::{NoopMethodCallDiag, SuspiciousDoubleRefDiag};
|
||||
use crate::LateContext;
|
||||
use crate::LateLintPass;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
declare_lint! {
|
||||
|
@ -35,14 +36,44 @@ declare_lint! {
|
|||
"detects the use of well-known noop methods"
|
||||
}
|
||||
|
||||
declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL]);
|
||||
declare_lint! {
|
||||
/// The `suspicious_double_ref_op` lint checks for usage of `.clone()`/`.borrow()`/`.deref()`
|
||||
/// on an `&&T` when `T: !Deref/Borrow/Clone`, which means the call will return the inner `&T`,
|
||||
/// instead of performing the operation on the underlying `T` and can be confusing.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![allow(unused)]
|
||||
/// struct Foo;
|
||||
/// let foo = &&Foo;
|
||||
/// let clone: &Foo = foo.clone();
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Since `Foo` doesn't implement `Clone`, running `.clone()` only dereferences the double
|
||||
/// reference, instead of cloning the inner type which should be what was intended.
|
||||
pub SUSPICIOUS_DOUBLE_REF_OP,
|
||||
Warn,
|
||||
"suspicious call of trait method on `&&T`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL, SUSPICIOUS_DOUBLE_REF_OP]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
// We only care about method calls.
|
||||
let ExprKind::MethodCall(call, receiver, ..) = &expr.kind else {
|
||||
return
|
||||
let ExprKind::MethodCall(call, receiver, _, call_span) = &expr.kind else {
|
||||
return;
|
||||
};
|
||||
|
||||
if call_span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
|
||||
// traits and ignore any other method call.
|
||||
let did = match cx.typeck_results().type_dependent_def(expr.hir_id) {
|
||||
|
@ -70,25 +101,39 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
|||
};
|
||||
// (Re)check that it implements the noop diagnostic.
|
||||
let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };
|
||||
if !matches!(
|
||||
name,
|
||||
sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let op = match name {
|
||||
sym::noop_method_borrow => "borrow",
|
||||
sym::noop_method_clone => "clone",
|
||||
sym::noop_method_deref => "deref",
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let receiver_ty = cx.typeck_results().expr_ty(receiver);
|
||||
let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
|
||||
if receiver_ty != expr_ty {
|
||||
// This lint will only trigger if the receiver type and resulting expression \
|
||||
// type are the same, implying that the method call is unnecessary.
|
||||
let arg_adjustments = cx.typeck_results().expr_adjustments(receiver);
|
||||
|
||||
// If there is any user defined auto-deref step, then we don't want to warn.
|
||||
// https://github.com/rust-lang/rust-clippy/issues/9272
|
||||
if arg_adjustments.iter().any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
let expr_span = expr.span;
|
||||
let span = expr_span.with_lo(receiver.span.hi());
|
||||
cx.emit_spanned_lint(
|
||||
NOOP_METHOD_CALL,
|
||||
span,
|
||||
NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span },
|
||||
);
|
||||
|
||||
if receiver_ty == expr_ty {
|
||||
cx.emit_spanned_lint(
|
||||
NOOP_METHOD_CALL,
|
||||
span,
|
||||
NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span },
|
||||
);
|
||||
} else {
|
||||
cx.emit_spanned_lint(
|
||||
SUSPICIOUS_DOUBLE_REF_OP,
|
||||
span,
|
||||
SuspiciousDoubleRefDiag { call: call.ident.name, ty: expr_ty, op },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue