about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-29 14:05:30 +0000
committerbors <bors@rust-lang.org>2024-05-29 14:05:30 +0000
commita83f933a9da258cf037e3cab37cd486bfd861a7d (patch)
tree2c73f7beb8a55093adbb0d68f7079b8aef6ae719
parentf2e1a3a80ae54734e1a3d306f31c2caebb05de9b (diff)
parent9d1ed80a8af72ad6918809861697e76ec38df178 (diff)
downloadrust-a83f933a9da258cf037e3cab37cd486bfd861a7d.tar.gz
rust-a83f933a9da258cf037e3cab37cd486bfd861a7d.zip
Auto merge of #125531 - surechen:make_suggestion_for_note_like_drop_lint, r=Urgau
Make lint: `lint_dropping_references` `lint_forgetting_copy_types` `lint_forgetting_references` give suggestion if possible.

This is a follow-up PR of  #125433. When it's merged, I want change lint `dropping_copy_types` to use the same `Subdiagnostic` struct `UseLetUnderscoreIgnoreSuggestion` which is added in this PR.

Hi, Thank you(`@Urgau` ) again for your help in the previous PR.  If your time permits, please also take a look at this one.

r? compiler

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->
-rw-r--r--compiler/rustc_lint/messages.ftl8
-rw-r--r--compiler/rustc_lint/src/drop_forget_useless.rs51
-rw-r--r--compiler/rustc_lint/src/lints.rs41
-rw-r--r--tests/ui/lint/dropping_copy_types.stderr24
-rw-r--r--tests/ui/lint/dropping_references-can-fixed.fixed31
-rw-r--r--tests/ui/lint/dropping_references-can-fixed.rs31
-rw-r--r--tests/ui/lint/dropping_references-can-fixed.stderr119
-rw-r--r--tests/ui/lint/dropping_references.stderr60
-rw-r--r--tests/ui/lint/forgetting_copy_types-can-fixed.fixed22
-rw-r--r--tests/ui/lint/forgetting_copy_types-can-fixed.rs22
-rw-r--r--tests/ui/lint/forgetting_copy_types-can-fixed.stderr49
-rw-r--r--tests/ui/lint/forgetting_copy_types.stderr48
-rw-r--r--tests/ui/lint/forgetting_references-can-fixed.fixed40
-rw-r--r--tests/ui/lint/forgetting_references-can-fixed.rs40
-rw-r--r--tests/ui/lint/forgetting_references-can-fixed.stderr133
-rw-r--r--tests/ui/lint/forgetting_references.rs10
-rw-r--r--tests/ui/lint/forgetting_references.stderr88
17 files changed, 743 insertions, 74 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index d2b1f50d79c..fb71cb60140 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -232,12 +232,9 @@ lint_drop_trait_constraints =
 
 lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` 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_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
 
 lint_duplicate_macro_attribute =
     duplicated attribute
@@ -272,10 +269,9 @@ lint_for_loops_over_fallibles =
 
 lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing
     .label = argument has type `{$arg_ty}`
-    .note = use `let _ = ...` to ignore the expression or result
+
 lint_forgetting_references = calls to `std::mem::forget` 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
 
 lint_hidden_glob_reexport = private item shadows public glob re-export
     .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here
@@ -894,6 +890,8 @@ lint_unused_op = unused {$op} that must be used
 
 lint_unused_result = unused result of type `{$ty}`
 
+lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result
+
 lint_variant_size_differences =
     enum variant is more than three times larger ({$largest} bytes) than the next largest
 
diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs
index 02d324520b8..eea0898d83f 100644
--- a/compiler/rustc_lint/src/drop_forget_useless.rs
+++ b/compiler/rustc_lint/src/drop_forget_useless.rs
@@ -5,8 +5,8 @@ use rustc_span::sym;
 
 use crate::{
     lints::{
-        DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag,
-        UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion,
+        DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag,
+        UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion,
     },
     LateContext, LateLintPass, LintContext,
 };
@@ -148,46 +148,59 @@ 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 let_underscore_ignore_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
+                {
+                    UseLetUnderscoreIgnoreSuggestion::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 {
+                    UseLetUnderscoreIgnoreSuggestion::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: let_underscore_ignore_sugg() },
                     );
                 }
                 sym::mem_forget if arg_ty.is_ref() => {
                     cx.emit_span_lint(
                         FORGETTING_REFERENCES,
                         expr.span,
-                        ForgetRefDiag { arg_ty, label: arg.span },
+                        ForgetRefDiag {
+                            arg_ty,
+                            label: arg.span,
+                            sugg: let_underscore_ignore_sugg(),
+                        },
                     );
                 }
                 sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
-                    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
-                    {
-                        DropCopySuggestion::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 {
-                        DropCopySuggestion::Note
-                    };
-
                     cx.emit_span_lint(
                         DROPPING_COPY_TYPES,
                         expr.span,
-                        DropCopyDiag { arg_ty, label: arg.span, sugg },
+                        DropCopyDiag {
+                            arg_ty,
+                            label: arg.span,
+                            sugg: let_underscore_ignore_sugg(),
+                        },
                     );
                 }
                 sym::mem_forget if is_copy => {
                     cx.emit_span_lint(
                         FORGETTING_COPY_TYPES,
                         expr.span,
-                        ForgetCopyDiag { arg_ty, label: arg.span },
+                        ForgetCopyDiag {
+                            arg_ty,
+                            label: arg.span,
+                            sugg: let_underscore_ignore_sugg(),
+                        },
                     );
                 }
                 sym::mem_drop
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index c365e68ba44..84d46ef3b65 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -656,14 +656,32 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> {
     pub end_span: Span,
 }
 
+#[derive(Subdiagnostic)]
+pub enum UseLetUnderscoreIgnoreSuggestion {
+    #[note(lint_use_let_underscore_ignore_suggestion)]
+    Note,
+    #[multipart_suggestion(
+        lint_use_let_underscore_ignore_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: UseLetUnderscoreIgnoreSuggestion,
 }
 
 #[derive(LintDiagnostic)]
@@ -673,38 +691,27 @@ pub struct DropCopyDiag<'a> {
     #[label]
     pub label: Span,
     #[subdiagnostic]
-    pub sugg: DropCopySuggestion,
-}
-
-#[derive(Subdiagnostic)]
-pub enum DropCopySuggestion {
-    #[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,
-    },
+    pub sugg: UseLetUnderscoreIgnoreSuggestion,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(lint_forgetting_references)]
-#[note]
 pub struct ForgetRefDiag<'a> {
     pub arg_ty: Ty<'a>,
     #[label]
     pub label: Span,
+    #[subdiagnostic]
+    pub sugg: UseLetUnderscoreIgnoreSuggestion,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(lint_forgetting_copy_types)]
-#[note]
 pub struct ForgetCopyDiag<'a> {
     pub arg_ty: Ty<'a>,
     #[label]
     pub label: Span,
+    #[subdiagnostic]
+    pub sugg: UseLetUnderscoreIgnoreSuggestion,
 }
 
 #[derive(LintDiagnostic)]
diff --git a/tests/ui/lint/dropping_copy_types.stderr b/tests/ui/lint/dropping_copy_types.stderr
index bdeb0c290fe..41aa66a4efc 100644
--- a/tests/ui/lint/dropping_copy_types.stderr
+++ b/tests/ui/lint/dropping_copy_types.stderr
@@ -39,8 +39,12 @@ LL |     drop(s3);
    |          |
    |          argument has type `&SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
    = note: `#[warn(dropping_references)]` on by default
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     drop(s3);
+LL +     let _ = s3;
+   |
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
   --> $DIR/dropping_copy_types.rs:37:5
@@ -64,7 +68,11 @@ LL |     drop(s5);
    |          |
    |          argument has type `&SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     drop(s5);
+LL +     let _ = s5;
+   |
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
   --> $DIR/dropping_copy_types.rs:50:5
@@ -74,7 +82,11 @@ LL |     drop(a2);
    |          |
    |          argument has type `&AnotherStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     drop(a2);
+LL +     let _ = a2;
+   |
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
   --> $DIR/dropping_copy_types.rs:52:5
@@ -84,7 +96,11 @@ LL |     drop(a4);
    |          |
    |          argument has type `&AnotherStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     drop(a4);
+LL +     let _ = a4;
+   |
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
   --> $DIR/dropping_copy_types.rs:71:13
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<T>(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<T>(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
diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.fixed b/tests/ui/lint/forgetting_copy_types-can-fixed.fixed
new file mode 100644
index 00000000000..c5d65ecc1d4
--- /dev/null
+++ b/tests/ui/lint/forgetting_copy_types-can-fixed.fixed
@@ -0,0 +1,22 @@
+//@ check-fail
+//@ run-rustfix
+
+#![deny(forgetting_copy_types)]
+#![allow(unused_mut)]
+#![allow(unused_imports)]
+
+use std::vec::Vec;
+use std::mem::forget;
+
+#[derive(Copy, Clone)]
+struct SomeStruct;
+
+fn main() {
+    let s1 = SomeStruct {};
+    let s2 = s1;
+    let mut s3 = s1;
+
+    let _ = s1; //~ ERROR calls to `std::mem::forget`
+    let _ = s2; //~ ERROR calls to `std::mem::forget`
+    let _ = s3; //~ ERROR calls to `std::mem::forget`
+}
diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.rs b/tests/ui/lint/forgetting_copy_types-can-fixed.rs
new file mode 100644
index 00000000000..c5572294280
--- /dev/null
+++ b/tests/ui/lint/forgetting_copy_types-can-fixed.rs
@@ -0,0 +1,22 @@
+//@ check-fail
+//@ run-rustfix
+
+#![deny(forgetting_copy_types)]
+#![allow(unused_mut)]
+#![allow(unused_imports)]
+
+use std::vec::Vec;
+use std::mem::forget;
+
+#[derive(Copy, Clone)]
+struct SomeStruct;
+
+fn main() {
+    let s1 = SomeStruct {};
+    let s2 = s1;
+    let mut s3 = s1;
+
+    forget(s1); //~ ERROR calls to `std::mem::forget`
+    forget(s2); //~ ERROR calls to `std::mem::forget`
+    forget(s3); //~ ERROR calls to `std::mem::forget`
+}
diff --git a/tests/ui/lint/forgetting_copy_types-can-fixed.stderr b/tests/ui/lint/forgetting_copy_types-can-fixed.stderr
new file mode 100644
index 00000000000..cb7bbf02222
--- /dev/null
+++ b/tests/ui/lint/forgetting_copy_types-can-fixed.stderr
@@ -0,0 +1,49 @@
+error: calls to `std::mem::forget` with a value that implements `Copy` does nothing
+  --> $DIR/forgetting_copy_types-can-fixed.rs:19:5
+   |
+LL |     forget(s1);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `SomeStruct`
+   |
+note: the lint level is defined here
+  --> $DIR/forgetting_copy_types-can-fixed.rs:4:9
+   |
+LL | #![deny(forgetting_copy_types)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(s1);
+LL +     let _ = s1;
+   |
+
+error: calls to `std::mem::forget` with a value that implements `Copy` does nothing
+  --> $DIR/forgetting_copy_types-can-fixed.rs:20:5
+   |
+LL |     forget(s2);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(s2);
+LL +     let _ = s2;
+   |
+
+error: calls to `std::mem::forget` with a value that implements `Copy` does nothing
+  --> $DIR/forgetting_copy_types-can-fixed.rs:21:5
+   |
+LL |     forget(s3);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(s3);
+LL +     let _ = s3;
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/forgetting_copy_types.stderr b/tests/ui/lint/forgetting_copy_types.stderr
index 36d1ef5c53e..980ee6caba2 100644
--- a/tests/ui/lint/forgetting_copy_types.stderr
+++ b/tests/ui/lint/forgetting_copy_types.stderr
@@ -6,12 +6,16 @@ LL |     forget(s1);
    |            |
    |            argument has type `SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
   --> $DIR/forgetting_copy_types.rs:3:9
    |
 LL | #![warn(forgetting_copy_types)]
    |         ^^^^^^^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(s1);
+LL +     let _ = s1;
+   |
 
 warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
   --> $DIR/forgetting_copy_types.rs:35:5
@@ -21,7 +25,11 @@ LL |     forget(s2);
    |            |
    |            argument has type `SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(s2);
+LL +     let _ = s2;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_copy_types.rs:36:5
@@ -31,8 +39,12 @@ LL |     forget(s3);
    |            |
    |            argument has type `&SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
    = note: `#[warn(forgetting_references)]` on by default
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(s3);
+LL +     let _ = s3;
+   |
 
 warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
   --> $DIR/forgetting_copy_types.rs:37:5
@@ -42,7 +54,11 @@ LL |     forget(s4);
    |            |
    |            argument has type `SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(s4);
+LL +     let _ = s4;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_copy_types.rs:38:5
@@ -52,7 +68,11 @@ LL |     forget(s5);
    |            |
    |            argument has type `&SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(s5);
+LL +     let _ = s5;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_copy_types.rs:50:5
@@ -62,7 +82,11 @@ LL |     forget(a2);
    |            |
    |            argument has type `&AnotherStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(a2);
+LL +     let _ = a2;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_copy_types.rs:52:5
@@ -72,7 +96,11 @@ LL |     forget(a3);
    |            |
    |            argument has type `&AnotherStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(a3);
+LL +     let _ = a3;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_copy_types.rs:53:5
@@ -82,7 +110,11 @@ LL |     forget(a4);
    |            |
    |            argument has type `&AnotherStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(a4);
+LL +     let _ = a4;
+   |
 
 warning: 8 warnings emitted
 
diff --git a/tests/ui/lint/forgetting_references-can-fixed.fixed b/tests/ui/lint/forgetting_references-can-fixed.fixed
new file mode 100644
index 00000000000..64475f04284
--- /dev/null
+++ b/tests/ui/lint/forgetting_references-can-fixed.fixed
@@ -0,0 +1,40 @@
+//@ check-fail
+//@ run-rustfix
+
+#![deny(forgetting_references)]
+
+use std::mem::forget;
+
+struct SomeStruct;
+
+fn main() {
+    let _ = &SomeStruct; //~ ERROR calls to `std::mem::forget`
+
+    let mut owned = SomeStruct;
+    let _ = &owned; //~ ERROR calls to `std::mem::forget`
+    let _ = &&owned; //~ ERROR calls to `std::mem::forget`
+    let _ = &mut owned; //~ ERROR calls to `std::mem::forget`
+    forget(owned);
+
+    let reference1 = &SomeStruct;
+    let _ = &*reference1; //~ ERROR calls to `std::mem::forget`
+
+    let reference2 = &mut SomeStruct;
+    let _ = reference2; //~ ERROR calls to `std::mem::forget`
+
+    let ref reference3 = SomeStruct;
+    let _ = reference3; //~ ERROR calls to `std::mem::forget`
+}
+
+#[allow(dead_code)]
+fn test_generic_fn_forget<T>(val: T) {
+    let _ = &val; //~ ERROR calls to `std::mem::forget`
+    forget(val);
+}
+
+#[allow(dead_code)]
+fn test_similarly_named_function() {
+    fn forget<T>(_val: T) {}
+    forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name
+    let _ = &SomeStruct; //~ ERROR calls to `std::mem::forget`
+}
diff --git a/tests/ui/lint/forgetting_references-can-fixed.rs b/tests/ui/lint/forgetting_references-can-fixed.rs
new file mode 100644
index 00000000000..4c9ef541d34
--- /dev/null
+++ b/tests/ui/lint/forgetting_references-can-fixed.rs
@@ -0,0 +1,40 @@
+//@ check-fail
+//@ run-rustfix
+
+#![deny(forgetting_references)]
+
+use std::mem::forget;
+
+struct SomeStruct;
+
+fn main() {
+    forget(&SomeStruct); //~ ERROR calls to `std::mem::forget`
+
+    let mut owned = SomeStruct;
+    forget(&owned); //~ ERROR calls to `std::mem::forget`
+    forget(&&owned); //~ ERROR calls to `std::mem::forget`
+    forget(&mut owned); //~ ERROR calls to `std::mem::forget`
+    forget(owned);
+
+    let reference1 = &SomeStruct;
+    forget(&*reference1); //~ ERROR calls to `std::mem::forget`
+
+    let reference2 = &mut SomeStruct;
+    forget(reference2); //~ ERROR calls to `std::mem::forget`
+
+    let ref reference3 = SomeStruct;
+    forget(reference3); //~ ERROR calls to `std::mem::forget`
+}
+
+#[allow(dead_code)]
+fn test_generic_fn_forget<T>(val: T) {
+    forget(&val); //~ ERROR calls to `std::mem::forget`
+    forget(val);
+}
+
+#[allow(dead_code)]
+fn test_similarly_named_function() {
+    fn forget<T>(_val: T) {}
+    forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name
+    std::mem::forget(&SomeStruct); //~ ERROR calls to `std::mem::forget`
+}
diff --git a/tests/ui/lint/forgetting_references-can-fixed.stderr b/tests/ui/lint/forgetting_references-can-fixed.stderr
new file mode 100644
index 00000000000..05eb636ab45
--- /dev/null
+++ b/tests/ui/lint/forgetting_references-can-fixed.stderr
@@ -0,0 +1,133 @@
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:11:5
+   |
+LL |     forget(&SomeStruct);
+   |     ^^^^^^^-----------^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+note: the lint level is defined here
+  --> $DIR/forgetting_references-can-fixed.rs:4:9
+   |
+LL | #![deny(forgetting_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&SomeStruct);
+LL +     let _ = &SomeStruct;
+   |
+
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:14:5
+   |
+LL |     forget(&owned);
+   |     ^^^^^^^------^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&owned);
+LL +     let _ = &owned;
+   |
+
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:15:5
+   |
+LL |     forget(&&owned);
+   |     ^^^^^^^-------^
+   |            |
+   |            argument has type `&&SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&&owned);
+LL +     let _ = &&owned;
+   |
+
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:16:5
+   |
+LL |     forget(&mut owned);
+   |     ^^^^^^^----------^
+   |            |
+   |            argument has type `&mut SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&mut owned);
+LL +     let _ = &mut owned;
+   |
+
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:20:5
+   |
+LL |     forget(&*reference1);
+   |     ^^^^^^^------------^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&*reference1);
+LL +     let _ = &*reference1;
+   |
+
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:23:5
+   |
+LL |     forget(reference2);
+   |     ^^^^^^^----------^
+   |            |
+   |            argument has type `&mut SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(reference2);
+LL +     let _ = reference2;
+   |
+
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:26:5
+   |
+LL |     forget(reference3);
+   |     ^^^^^^^----------^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(reference3);
+LL +     let _ = reference3;
+   |
+
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:31:5
+   |
+LL |     forget(&val);
+   |     ^^^^^^^----^
+   |            |
+   |            argument has type `&T`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&val);
+LL +     let _ = &val;
+   |
+
+error: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references-can-fixed.rs:39:5
+   |
+LL |     std::mem::forget(&SomeStruct);
+   |     ^^^^^^^^^^^^^^^^^-----------^
+   |                      |
+   |                      argument has type `&SomeStruct`
+   |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     std::mem::forget(&SomeStruct);
+LL +     let _ = &SomeStruct;
+   |
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/lint/forgetting_references.rs b/tests/ui/lint/forgetting_references.rs
index ecfa23ee497..d0ec2a77ab1 100644
--- a/tests/ui/lint/forgetting_references.rs
+++ b/tests/ui/lint/forgetting_references.rs
@@ -23,6 +23,16 @@ fn main() {
 
     let ref reference3 = SomeStruct;
     forget(reference3); //~ WARN calls to `std::mem::forget`
+
+    let ref reference4 = SomeStruct;
+
+    let a = 1;
+    match a {
+        1 => forget(&*reference1), //~ WARN calls to `std::mem::forget`
+        2 => forget(reference3), //~ WARN calls to `std::mem::forget`
+        3 => forget(reference4), //~ WARN calls to `std::mem::forget`
+        _ => {}
+    }
 }
 
 #[allow(dead_code)]
diff --git a/tests/ui/lint/forgetting_references.stderr b/tests/ui/lint/forgetting_references.stderr
index 5624b690789..afd5030a680 100644
--- a/tests/ui/lint/forgetting_references.stderr
+++ b/tests/ui/lint/forgetting_references.stderr
@@ -6,12 +6,16 @@ LL |     forget(&SomeStruct);
    |            |
    |            argument has type `&SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
   --> $DIR/forgetting_references.rs:3:9
    |
 LL | #![warn(forgetting_references)]
    |         ^^^^^^^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&SomeStruct);
+LL +     let _ = &SomeStruct;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_references.rs:13:5
@@ -21,7 +25,11 @@ LL |     forget(&owned);
    |            |
    |            argument has type `&SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&owned);
+LL +     let _ = &owned;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_references.rs:14:5
@@ -31,7 +39,11 @@ LL |     forget(&&owned);
    |            |
    |            argument has type `&&SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&&owned);
+LL +     let _ = &&owned;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_references.rs:15:5
@@ -41,7 +53,11 @@ LL |     forget(&mut owned);
    |            |
    |            argument has type `&mut SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&mut owned);
+LL +     let _ = &mut owned;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_references.rs:19:5
@@ -51,7 +67,11 @@ LL |     forget(&*reference1);
    |            |
    |            argument has type `&SomeStruct`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&*reference1);
+LL +     let _ = &*reference1;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_references.rs:22:5
@@ -61,7 +81,11 @@ LL |     forget(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 -     forget(reference2);
+LL +     let _ = reference2;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
   --> $DIR/forgetting_references.rs:25:5
@@ -71,27 +95,69 @@ LL |     forget(reference3);
    |            |
    |            argument has type `&SomeStruct`
    |
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(reference3);
+LL +     let _ = reference3;
+   |
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:31:14
+   |
+LL |         1 => forget(&*reference1),
+   |              ^^^^^^^------------^
+   |                     |
+   |                     argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:32:14
+   |
+LL |         2 => forget(reference3),
+   |              ^^^^^^^----------^
+   |                     |
+   |                     argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:33:14
+   |
+LL |         3 => forget(reference4),
+   |              ^^^^^^^----------^
+   |                     |
+   |                     argument has type `&SomeStruct`
+   |
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forgetting_references.rs:30:5
+  --> $DIR/forgetting_references.rs:40:5
    |
 LL |     forget(&val);
    |     ^^^^^^^----^
    |            |
    |            argument has type `&T`
    |
-   = note: use `let _ = ...` to ignore the expression or result
+help: use `let _ = ...` to ignore the expression or result
+   |
+LL -     forget(&val);
+LL +     let _ = &val;
+   |
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forgetting_references.rs:38:5
+  --> $DIR/forgetting_references.rs:48:5
    |
 LL |     std::mem::forget(&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::forget(&SomeStruct);
+LL +     let _ = &SomeStruct;
+   |
 
-warning: 9 warnings emitted
+warning: 12 warnings emitted