From ca68c931351a83f6a796cd9861b5af56dd0c0704 Mon Sep 17 00:00:00 2001 From: surechen Date: Sat, 25 May 2024 09:55:49 +0800 Subject: [PATCH] Let lint_dropping_references give the suggestion if possible. --- compiler/rustc_lint/messages.ftl | 1 + .../rustc_lint/src/drop_forget_useless.rs | 16 ++- compiler/rustc_lint/src/lints.rs | 16 ++- .../lint/dropping_references-can-fixed.fixed | 31 +++++ .../ui/lint/dropping_references-can-fixed.rs | 31 +++++ .../lint/dropping_references-can-fixed.stderr | 119 ++++++++++++++++++ tests/ui/lint/dropping_references.stderr | 60 +++++++-- 7 files changed, 261 insertions(+), 13 deletions(-) create mode 100644 tests/ui/lint/dropping_references-can-fixed.fixed create mode 100644 tests/ui/lint/dropping_references-can-fixed.rs create mode 100644 tests/ui/lint/dropping_references-can-fixed.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d2b1f50d79c..805001718ea 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -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 .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result + .suggestion = use `let _ = ...` to ignore the expression or result lint_duplicate_macro_attribute = duplicated attribute diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 02d324520b8..3166556448b 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -5,7 +5,7 @@ use rustc_span::sym; use crate::{ lints::{ - DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, + DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, IgnoreDropSuggestion, UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, }, LateContext, LateLintPass, LintContext, @@ -148,12 +148,24 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { let arg_ty = cx.typeck_results().expr_ty(arg); 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 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 { sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => { cx.emit_span_lint( DROPPING_REFERENCES, expr.span, - DropRefDiag { arg_ty, label: arg.span }, + DropRefDiag { arg_ty, label: arg.span, sugg }, ); } sym::mem_forget if arg_ty.is_ref() => { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c365e68ba44..1c061ce25a6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -656,14 +656,28 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> { 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 #[derive(LintDiagnostic)] #[diag(lint_dropping_references)] -#[note] pub struct DropRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: IgnoreDropSuggestion, } #[derive(LintDiagnostic)] diff --git a/tests/ui/lint/dropping_references-can-fixed.fixed b/tests/ui/lint/dropping_references-can-fixed.fixed new file mode 100644 index 00000000000..f704d3c72df --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.fixed @@ -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(val: T) { + let _ = &val; //~ ERROR calls to `std::mem::drop` + drop(val); +} diff --git a/tests/ui/lint/dropping_references-can-fixed.rs b/tests/ui/lint/dropping_references-can-fixed.rs new file mode 100644 index 00000000000..70d1c16d66b --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.rs @@ -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(val: T) { + drop(&val); //~ ERROR calls to `std::mem::drop` + drop(val); +} diff --git a/tests/ui/lint/dropping_references-can-fixed.stderr b/tests/ui/lint/dropping_references-can-fixed.stderr new file mode 100644 index 00000000000..42cdb81b524 --- /dev/null +++ b/tests/ui/lint/dropping_references-can-fixed.stderr @@ -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 + diff --git a/tests/ui/lint/dropping_references.stderr b/tests/ui/lint/dropping_references.stderr index 7e25a46216e..312334b82ad 100644 --- a/tests/ui/lint/dropping_references.stderr +++ b/tests/ui/lint/dropping_references.stderr @@ -6,12 +6,16 @@ LL | drop(&SomeStruct); | | | argument has type `&SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/dropping_references.rs:3:9 | 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 --> $DIR/dropping_references.rs:11:5 @@ -21,7 +25,11 @@ LL | drop(&owned1); | | | 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 --> $DIR/dropping_references.rs:12:5 @@ -31,7 +39,11 @@ LL | drop(&&owned1); | | | 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 --> $DIR/dropping_references.rs:13:5 @@ -41,7 +53,11 @@ LL | drop(&mut owned1); | | | 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 --> $DIR/dropping_references.rs:17:5 @@ -51,7 +67,11 @@ LL | drop(reference1); | | | 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 --> $DIR/dropping_references.rs:20:5 @@ -61,7 +81,11 @@ LL | drop(reference2); | | | 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 --> $DIR/dropping_references.rs:23:5 @@ -71,7 +95,11 @@ LL | drop(reference3); | | | 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 --> $DIR/dropping_references.rs:28:5 @@ -81,7 +109,11 @@ LL | drop(&val); | | | 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 --> $DIR/dropping_references.rs:36:5 @@ -91,7 +123,11 @@ LL | std::mem::drop(&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 --> $DIR/dropping_references.rs:91:13 @@ -101,7 +137,11 @@ LL | drop(println_and(&13)); | | | 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 --> $DIR/dropping_references.rs:94:14