Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make lint: lint_dropping_references lint_forgetting_copy_types lint_forgetting_references give suggestion if possible. #125531

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
51 changes: 32 additions & 19 deletions compiler/rustc_lint/src/drop_forget_useless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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
Expand Down
41 changes: 24 additions & 17 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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)]
Expand Down
24 changes: 20 additions & 4 deletions tests/ui/lint/dropping_copy_types.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
31 changes: 31 additions & 0 deletions tests/ui/lint/dropping_references-can-fixed.fixed
Original file line number Diff line number Diff line change
@@ -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);
}
31 changes: 31 additions & 0 deletions tests/ui/lint/dropping_references-can-fixed.rs
Original file line number Diff line number Diff line change
@@ -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);
}
Loading
Loading