Skip to content
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