Skip to content

Commit

Permalink
Let lint_forgetting_references give the suggestion if possible
Browse files Browse the repository at this point in the history
  • Loading branch information
surechen committed May 25, 2024
1 parent d0d0a45 commit 078441c
Show file tree
Hide file tree
Showing 9 changed files with 336 additions and 25 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ lint_forgetting_copy_types = calls to `std::mem::forget` with a value that imple
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
.suggestion = use `let _ = ...` to ignore the expression or result
lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label}
.label = this {$label} contains {$count ->
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_lint/src/drop_forget_useless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use rustc_span::sym;

use crate::{
lints::{
DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, IgnoreDropSuggestion,
UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion,
DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag,
UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion,
},
LateContext, LateLintPass, LintContext,
};
Expand Down Expand Up @@ -152,12 +152,12 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
&& let StmtKind::Semi(e) = stmt.kind
&& e.hir_id == expr.hir_id
{
IgnoreDropSuggestion::Suggestion {
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 {
IgnoreDropSuggestion::Note
UseLetUnderscoreIgnoreSuggestion::Note
};
match fn_name {
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
Expand All @@ -171,7 +171,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
cx.emit_span_lint(
FORGETTING_REFERENCES,
expr.span,
ForgetRefDiag { arg_ty, label: arg.span },
ForgetRefDiag { arg_ty, label: arg.span, sugg },
);
}
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> {
}

#[derive(Subdiagnostic)]
pub enum IgnoreDropSuggestion {
pub enum UseLetUnderscoreIgnoreSuggestion {
#[note(lint_note)]
Note,
#[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
Expand All @@ -678,7 +678,7 @@ pub struct DropRefDiag<'a> {
#[label]
pub label: Span,
#[subdiagnostic]
pub sugg: IgnoreDropSuggestion,
pub sugg: UseLetUnderscoreIgnoreSuggestion,
}

#[derive(LintDiagnostic)]
Expand All @@ -692,11 +692,12 @@ pub struct DropCopyDiag<'a> {

#[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)]
Expand All @@ -706,7 +707,7 @@ pub struct ForgetCopyDiag<'a> {
#[label]
pub label: Span,
#[subdiagnostic]
pub sugg: IgnoreDropSuggestion,
pub sugg: UseLetUnderscoreIgnoreSuggestion,
}

#[derive(LintDiagnostic)]
Expand Down
30 changes: 25 additions & 5 deletions tests/ui/lint/forgetting_copy_types.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -39,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
Expand All @@ -64,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
Expand All @@ -74,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
Expand All @@ -84,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
Expand All @@ -94,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

40 changes: 40 additions & 0 deletions tests/ui/lint/forgetting_references-can-fixed.fixed
Original file line number Diff line number Diff line change
@@ -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`
}
40 changes: 40 additions & 0 deletions tests/ui/lint/forgetting_references-can-fixed.rs
Original file line number Diff line number Diff line change
@@ -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`
}
133 changes: 133 additions & 0 deletions tests/ui/lint/forgetting_references-can-fixed.stderr
Original file line number Diff line number Diff line change
@@ -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

10 changes: 10 additions & 0 deletions tests/ui/lint/forgetting_references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
Loading

0 comments on commit 078441c

Please sign in to comment.