Let lint_dropping_references give the suggestion if possible.

This commit is contained in:
surechen 2024-05-25 09:55:49 +08:00
parent 5870f1ccbb
commit ca68c93135
7 changed files with 261 additions and 13 deletions

View File

@ -238,6 +238,7 @@ lint_dropping_copy_types = calls to `std::mem::drop` with a value that implement
lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
.label = argument has type `{$arg_ty}` .label = argument has type `{$arg_ty}`
.note = use `let _ = ...` to ignore the expression or result .note = use `let _ = ...` to ignore the expression or result
.suggestion = use `let _ = ...` to ignore the expression or result
lint_duplicate_macro_attribute = lint_duplicate_macro_attribute =
duplicated attribute duplicated attribute

View File

@ -5,7 +5,7 @@
use crate::{ use crate::{
lints::{ lints::{
DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, IgnoreDropSuggestion,
UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion,
}, },
LateContext, LateLintPass, LintContext, LateContext, LateLintPass, LintContext,
@ -148,12 +148,24 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
let arg_ty = cx.typeck_results().expr_ty(arg); let arg_ty = cx.typeck_results().expr_ty(arg);
let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env); let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env);
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
let sugg = if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0)
&& let Node::Stmt(stmt) = node
&& let StmtKind::Semi(e) = stmt.kind
&& e.hir_id == expr.hir_id
{
IgnoreDropSuggestion::Suggestion {
start_span: expr.span.shrink_to_lo().until(arg.span),
end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
}
} else {
IgnoreDropSuggestion::Note
};
match fn_name { match fn_name {
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => { sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
cx.emit_span_lint( cx.emit_span_lint(
DROPPING_REFERENCES, DROPPING_REFERENCES,
expr.span, expr.span,
DropRefDiag { arg_ty, label: arg.span }, DropRefDiag { arg_ty, label: arg.span, sugg },
); );
} }
sym::mem_forget if arg_ty.is_ref() => { sym::mem_forget if arg_ty.is_ref() => {

View File

@ -656,14 +656,28 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> {
pub end_span: Span, pub end_span: Span,
} }
#[derive(Subdiagnostic)]
pub enum IgnoreDropSuggestion {
#[note(lint_note)]
Note,
#[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
Suggestion {
#[suggestion_part(code = "let _ = ")]
start_span: Span,
#[suggestion_part(code = "")]
end_span: Span,
},
}
// drop_forget_useless.rs // drop_forget_useless.rs
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(lint_dropping_references)] #[diag(lint_dropping_references)]
#[note]
pub struct DropRefDiag<'a> { pub struct DropRefDiag<'a> {
pub arg_ty: Ty<'a>, pub arg_ty: Ty<'a>,
#[label] #[label]
pub label: Span, pub label: Span,
#[subdiagnostic]
pub sugg: IgnoreDropSuggestion,
} }
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]

View File

@ -0,0 +1,31 @@
//@ check-fail
//@ run-rustfix
#![deny(dropping_references)]
struct SomeStruct;
fn main() {
let _ = &SomeStruct; //~ ERROR calls to `std::mem::drop`
let mut owned1 = SomeStruct;
let _ = &owned1; //~ ERROR calls to `std::mem::drop`
let _ = &&owned1; //~ ERROR calls to `std::mem::drop`
let _ = &mut owned1; //~ ERROR calls to `std::mem::drop`
drop(owned1);
let reference1 = &SomeStruct;
let _ = reference1; //~ ERROR calls to `std::mem::drop`
let reference2 = &mut SomeStruct;
let _ = reference2; //~ ERROR calls to `std::mem::drop`
let ref reference3 = SomeStruct;
let _ = reference3; //~ ERROR calls to `std::mem::drop`
}
#[allow(dead_code)]
fn test_generic_fn_drop<T>(val: T) {
let _ = &val; //~ ERROR calls to `std::mem::drop`
drop(val);
}

View File

@ -0,0 +1,31 @@
//@ check-fail
//@ run-rustfix
#![deny(dropping_references)]
struct SomeStruct;
fn main() {
drop(&SomeStruct); //~ ERROR calls to `std::mem::drop`
let mut owned1 = SomeStruct;
drop(&owned1); //~ ERROR calls to `std::mem::drop`
drop(&&owned1); //~ ERROR calls to `std::mem::drop`
drop(&mut owned1); //~ ERROR calls to `std::mem::drop`
drop(owned1);
let reference1 = &SomeStruct;
drop(reference1); //~ ERROR calls to `std::mem::drop`
let reference2 = &mut SomeStruct;
drop(reference2); //~ ERROR calls to `std::mem::drop`
let ref reference3 = SomeStruct;
drop(reference3); //~ ERROR calls to `std::mem::drop`
}
#[allow(dead_code)]
fn test_generic_fn_drop<T>(val: T) {
drop(&val); //~ ERROR calls to `std::mem::drop`
drop(val);
}

View File

@ -0,0 +1,119 @@
error: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references-can-fixed.rs:9:5
|
LL | drop(&SomeStruct);
| ^^^^^-----------^
| |
| argument has type `&SomeStruct`
|
note: the lint level is defined here
--> $DIR/dropping_references-can-fixed.rs:4:9
|
LL | #![deny(dropping_references)]
| ^^^^^^^^^^^^^^^^^^^
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&SomeStruct);
LL + let _ = &SomeStruct;
|
error: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references-can-fixed.rs:12:5
|
LL | drop(&owned1);
| ^^^^^-------^
| |
| argument has type `&SomeStruct`
|
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&owned1);
LL + let _ = &owned1;
|
error: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references-can-fixed.rs:13:5
|
LL | drop(&&owned1);
| ^^^^^--------^
| |
| argument has type `&&SomeStruct`
|
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&&owned1);
LL + let _ = &&owned1;
|
error: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references-can-fixed.rs:14:5
|
LL | drop(&mut owned1);
| ^^^^^-----------^
| |
| argument has type `&mut SomeStruct`
|
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&mut owned1);
LL + let _ = &mut owned1;
|
error: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references-can-fixed.rs:18:5
|
LL | drop(reference1);
| ^^^^^----------^
| |
| argument has type `&SomeStruct`
|
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(reference1);
LL + let _ = reference1;
|
error: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references-can-fixed.rs:21:5
|
LL | drop(reference2);
| ^^^^^----------^
| |
| argument has type `&mut SomeStruct`
|
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(reference2);
LL + let _ = reference2;
|
error: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references-can-fixed.rs:24:5
|
LL | drop(reference3);
| ^^^^^----------^
| |
| argument has type `&SomeStruct`
|
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(reference3);
LL + let _ = reference3;
|
error: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references-can-fixed.rs:29:5
|
LL | drop(&val);
| ^^^^^----^
| |
| argument has type `&T`
|
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&val);
LL + let _ = &val;
|
error: aborting due to 8 previous errors

View File

@ -6,12 +6,16 @@ LL | drop(&SomeStruct);
| | | |
| argument has type `&SomeStruct` | argument has type `&SomeStruct`
| |
= note: use `let _ = ...` to ignore the expression or result
note: the lint level is defined here note: the lint level is defined here
--> $DIR/dropping_references.rs:3:9 --> $DIR/dropping_references.rs:3:9
| |
LL | #![warn(dropping_references)] LL | #![warn(dropping_references)]
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&SomeStruct);
LL + let _ = &SomeStruct;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:11:5 --> $DIR/dropping_references.rs:11:5
@ -21,7 +25,11 @@ LL | drop(&owned1);
| | | |
| argument has type `&SomeStruct` | argument has type `&SomeStruct`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&owned1);
LL + let _ = &owned1;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:12:5 --> $DIR/dropping_references.rs:12:5
@ -31,7 +39,11 @@ LL | drop(&&owned1);
| | | |
| argument has type `&&SomeStruct` | argument has type `&&SomeStruct`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&&owned1);
LL + let _ = &&owned1;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:13:5 --> $DIR/dropping_references.rs:13:5
@ -41,7 +53,11 @@ LL | drop(&mut owned1);
| | | |
| argument has type `&mut SomeStruct` | argument has type `&mut SomeStruct`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&mut owned1);
LL + let _ = &mut owned1;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:17:5 --> $DIR/dropping_references.rs:17:5
@ -51,7 +67,11 @@ LL | drop(reference1);
| | | |
| argument has type `&SomeStruct` | argument has type `&SomeStruct`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - drop(reference1);
LL + let _ = reference1;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:20:5 --> $DIR/dropping_references.rs:20:5
@ -61,7 +81,11 @@ LL | drop(reference2);
| | | |
| argument has type `&mut SomeStruct` | argument has type `&mut SomeStruct`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - drop(reference2);
LL + let _ = reference2;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:23:5 --> $DIR/dropping_references.rs:23:5
@ -71,7 +95,11 @@ LL | drop(reference3);
| | | |
| argument has type `&SomeStruct` | argument has type `&SomeStruct`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - drop(reference3);
LL + let _ = reference3;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:28:5 --> $DIR/dropping_references.rs:28:5
@ -81,7 +109,11 @@ LL | drop(&val);
| | | |
| argument has type `&T` | argument has type `&T`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - drop(&val);
LL + let _ = &val;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:36:5 --> $DIR/dropping_references.rs:36:5
@ -91,7 +123,11 @@ LL | std::mem::drop(&SomeStruct);
| | | |
| argument has type `&SomeStruct` | argument has type `&SomeStruct`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - std::mem::drop(&SomeStruct);
LL + let _ = &SomeStruct;
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:91:13 --> $DIR/dropping_references.rs:91:13
@ -101,7 +137,11 @@ LL | drop(println_and(&13));
| | | |
| argument has type `&i32` | argument has type `&i32`
| |
= note: use `let _ = ...` to ignore the expression or result help: use `let _ = ...` to ignore the expression or result
|
LL - drop(println_and(&13));
LL + let _ = println_and(&13);
|
warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
--> $DIR/dropping_references.rs:94:14 --> $DIR/dropping_references.rs:94:14