Extend unused_must_use to cover block exprs

This commit is contained in:
许杰友 Jieyou Xu (Joe) 2023-06-11 23:44:28 +08:00
parent 314c39d2ea
commit 72b3b58efc
No known key found for this signature in database
GPG Key ID: C5FD5D32014FDB47
19 changed files with 289 additions and 65 deletions

View File

@ -67,7 +67,7 @@ struct ArenaChunk<T = u8> {
unsafe impl<#[may_dangle] T> Drop for ArenaChunk<T> { unsafe impl<#[may_dangle] T> Drop for ArenaChunk<T> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { Box::from_raw(self.storage.as_mut()) }; unsafe { drop(Box::from_raw(self.storage.as_mut())) }
} }
} }

View File

@ -1534,8 +1534,29 @@ pub struct UnusedOp<'a> {
pub op: &'a str, pub op: &'a str,
#[label] #[label]
pub label: Span, pub label: Span,
#[suggestion(style = "verbose", code = "let _ = ", applicability = "maybe-incorrect")] #[subdiagnostic]
pub suggestion: Span, pub suggestion: UnusedOpSuggestion,
}
#[derive(Subdiagnostic)]
pub enum UnusedOpSuggestion {
#[suggestion(
lint_suggestion,
style = "verbose",
code = "let _ = ",
applicability = "maybe-incorrect"
)]
NormalExpr {
#[primary_span]
span: Span,
},
#[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
BlockTailExpr {
#[suggestion_part(code = "let _ = ")]
before_span: Span,
#[suggestion_part(code = ";")]
after_span: Span,
},
} }
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
@ -1578,15 +1599,25 @@ pub struct UnusedDef<'a, 'b> {
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
#[suggestion(
lint_suggestion, pub enum UnusedDefSuggestion {
style = "verbose", #[suggestion(
code = "let _ = ", lint_suggestion,
applicability = "maybe-incorrect" style = "verbose",
)] code = "let _ = ",
pub struct UnusedDefSuggestion { applicability = "maybe-incorrect"
#[primary_span] )]
pub span: Span, NormalExpr {
#[primary_span]
span: Span,
},
#[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
BlockTailExpr {
#[suggestion_part(code = "let _ = ")]
before_span: Span,
#[suggestion_part(code = ";")]
after_span: Span,
},
} }
// Needed because of def_path_str // Needed because of def_path_str

View File

@ -1,7 +1,8 @@
use crate::lints::{ use crate::lints::{
PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag, PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim, UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim,
UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult, UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
UnusedResult,
}; };
use crate::Lint; use crate::Lint;
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -93,7 +94,15 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
impl<'tcx> LateLintPass<'tcx> for UnusedResults { impl<'tcx> LateLintPass<'tcx> for UnusedResults {
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
let hir::StmtKind::Semi(expr) = s.kind else { return; }; let hir::StmtKind::Semi(mut expr) = s.kind else { return; };
let mut expr_is_from_block = false;
while let hir::ExprKind::Block(blk, ..) = expr.kind
&& let hir::Block { expr: Some(e), .. } = blk
{
expr = e;
expr_is_from_block = true;
}
if let hir::ExprKind::Ret(..) = expr.kind { if let hir::ExprKind::Ret(..) = expr.kind {
return; return;
@ -113,6 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
expr.span, expr.span,
"output of future returned by ", "output of future returned by ",
"", "",
expr_is_from_block,
) )
{ {
// We have a bare `foo().await;` on an opaque type from an async function that was // We have a bare `foo().await;` on an opaque type from an async function that was
@ -125,13 +135,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span); let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span);
let type_lint_emitted_or_suppressed = match must_use_result { let type_lint_emitted_or_suppressed = match must_use_result {
Some(path) => { Some(path) => {
emit_must_use_untranslated(cx, &path, "", "", 1, false); emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block);
true true
} }
None => false, None => false,
}; };
let fn_warned = check_fn_must_use(cx, expr); let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block);
if !fn_warned && type_lint_emitted_or_suppressed { if !fn_warned && type_lint_emitted_or_suppressed {
// We don't warn about unused unit or uninhabited types. // We don't warn about unused unit or uninhabited types.
@ -176,7 +186,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
UnusedOp { UnusedOp {
op: must_use_op, op: must_use_op,
label: expr.span, label: expr.span,
suggestion: expr.span.shrink_to_lo(), suggestion: if expr_is_from_block {
UnusedOpSuggestion::BlockTailExpr {
before_span: expr.span.shrink_to_lo(),
after_span: expr.span.shrink_to_hi(),
}
} else {
UnusedOpSuggestion::NormalExpr { span: expr.span.shrink_to_lo() }
},
}, },
); );
op_warned = true; op_warned = true;
@ -186,7 +203,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
cx.emit_spanned_lint(UNUSED_RESULTS, s.span, UnusedResult { ty }); cx.emit_spanned_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
} }
fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { fn check_fn_must_use(
cx: &LateContext<'_>,
expr: &hir::Expr<'_>,
expr_is_from_block: bool,
) -> bool {
let maybe_def_id = match expr.kind { let maybe_def_id = match expr.kind {
hir::ExprKind::Call(ref callee, _) => { hir::ExprKind::Call(ref callee, _) => {
match callee.kind { match callee.kind {
@ -207,7 +228,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
_ => None, _ => None,
}; };
if let Some(def_id) = maybe_def_id { if let Some(def_id) = maybe_def_id {
check_must_use_def(cx, def_id, expr.span, "return value of ", "") check_must_use_def(
cx,
def_id,
expr.span,
"return value of ",
"",
expr_is_from_block,
)
} else { } else {
false false
} }
@ -350,6 +378,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
span: Span, span: Span,
descr_pre_path: &str, descr_pre_path: &str,
descr_post_path: &str, descr_post_path: &str,
expr_is_from_block: bool,
) -> bool { ) -> bool {
is_def_must_use(cx, def_id, span) is_def_must_use(cx, def_id, span)
.map(|must_use_path| { .map(|must_use_path| {
@ -360,6 +389,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
descr_post_path, descr_post_path,
1, 1,
false, false,
expr_is_from_block,
) )
}) })
.is_some() .is_some()
@ -373,6 +403,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
descr_post: &str, descr_post: &str,
plural_len: usize, plural_len: usize,
is_inner: bool, is_inner: bool,
expr_is_from_block: bool,
) { ) {
let plural_suffix = pluralize!(plural_len); let plural_suffix = pluralize!(plural_len);
@ -380,21 +411,51 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
MustUsePath::Suppressed => {} MustUsePath::Suppressed => {}
MustUsePath::Boxed(path) => { MustUsePath::Boxed(path) => {
let descr_pre = &format!("{}boxed ", descr_pre); let descr_pre = &format!("{}boxed ", descr_pre);
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); emit_must_use_untranslated(
cx,
path,
descr_pre,
descr_post,
plural_len,
true,
expr_is_from_block,
);
} }
MustUsePath::Opaque(path) => { MustUsePath::Opaque(path) => {
let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix); let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix);
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); emit_must_use_untranslated(
cx,
path,
descr_pre,
descr_post,
plural_len,
true,
expr_is_from_block,
);
} }
MustUsePath::TraitObject(path) => { MustUsePath::TraitObject(path) => {
let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post); let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post);
emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true); emit_must_use_untranslated(
cx,
path,
descr_pre,
descr_post,
plural_len,
true,
expr_is_from_block,
);
} }
MustUsePath::TupleElement(elems) => { MustUsePath::TupleElement(elems) => {
for (index, path) in elems { for (index, path) in elems {
let descr_post = &format!(" in tuple element {}", index); let descr_post = &format!(" in tuple element {}", index);
emit_must_use_untranslated( emit_must_use_untranslated(
cx, path, descr_pre, descr_post, plural_len, true, cx,
path,
descr_pre,
descr_post,
plural_len,
true,
expr_is_from_block,
); );
} }
} }
@ -407,6 +468,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
descr_post, descr_post,
plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)), plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
true, true,
expr_is_from_block,
); );
} }
MustUsePath::Closure(span) => { MustUsePath::Closure(span) => {
@ -433,8 +495,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
cx, cx,
def_id: *def_id, def_id: *def_id,
note: *reason, note: *reason,
suggestion: (!is_inner) suggestion: (!is_inner).then_some(if expr_is_from_block {
.then_some(UnusedDefSuggestion { span: span.shrink_to_lo() }), UnusedDefSuggestion::BlockTailExpr {
before_span: span.shrink_to_lo(),
after_span: span.shrink_to_hi(),
}
} else {
UnusedDefSuggestion::NormalExpr { span: span.shrink_to_lo() }
}),
}, },
); );
} }

View File

@ -308,7 +308,7 @@ mod prim_never {}
/// ///
/// ```no_run /// ```no_run
/// // Undefined behaviour /// // Undefined behaviour
/// unsafe { char::from_u32_unchecked(0x110000) }; /// let _ = unsafe { char::from_u32_unchecked(0x110000) };
/// ``` /// ```
/// ///
/// USVs are also the exact set of values that may be encoded in UTF-8. Because /// USVs are also the exact set of values that may be encoded in UTF-8. Because

View File

@ -1001,7 +1001,7 @@ fn nonnull_tagged_pointer_with_provenance() {
assert_eq!(p.tag(), 3); assert_eq!(p.tag(), 3);
assert_eq!(unsafe { *p.pointer().as_ptr() }, 10); assert_eq!(unsafe { *p.pointer().as_ptr() }, 10);
unsafe { Box::from_raw(p.pointer().as_ptr()) }; unsafe { drop(Box::from_raw(p.pointer().as_ptr())) };
/// A non-null pointer type which carries several bits of metadata and maintains provenance. /// A non-null pointer type which carries several bits of metadata and maintains provenance.
#[repr(transparent)] #[repr(transparent)]

View File

@ -308,7 +308,7 @@ mod prim_never {}
/// ///
/// ```no_run /// ```no_run
/// // Undefined behaviour /// // Undefined behaviour
/// unsafe { char::from_u32_unchecked(0x110000) }; /// let _ = unsafe { char::from_u32_unchecked(0x110000) };
/// ``` /// ```
/// ///
/// USVs are also the exact set of values that may be encoded in UTF-8. Because /// USVs are also the exact set of values that may be encoded in UTF-8. Because

View File

@ -2,6 +2,7 @@
#![warn(clippy::transmute_ptr_to_ref)] #![warn(clippy::transmute_ptr_to_ref)]
#![allow(clippy::match_single_binding)] #![allow(clippy::match_single_binding)]
#![allow(unused_must_use)]
unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
let _: &T = &*p; let _: &T = &*p;
@ -38,7 +39,7 @@ fn _issue1231() {
type Bar<'a> = &'a u8; type Bar<'a> = &'a u8;
let raw = 42 as *const i32; let raw = 42 as *const i32;
unsafe { &*(raw as *const u8) }; let _ = unsafe { &*(raw as *const u8) };
} }
unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 {

View File

@ -2,6 +2,7 @@
#![warn(clippy::transmute_ptr_to_ref)] #![warn(clippy::transmute_ptr_to_ref)]
#![allow(clippy::match_single_binding)] #![allow(clippy::match_single_binding)]
#![allow(unused_must_use)]
unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) { unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
let _: &T = std::mem::transmute(p); let _: &T = std::mem::transmute(p);
@ -38,7 +39,7 @@ fn _issue1231() {
type Bar<'a> = &'a u8; type Bar<'a> = &'a u8;
let raw = 42 as *const i32; let raw = 42 as *const i32;
unsafe { std::mem::transmute::<_, Bar>(raw) }; let _ = unsafe { std::mem::transmute::<_, Bar>(raw) };
} }
unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 {

View File

@ -1,5 +1,5 @@
error: transmute from a pointer type (`*const T`) to a reference type (`&T`) error: transmute from a pointer type (`*const T`) to a reference type (`&T`)
--> $DIR/transmute_ptr_to_ref.rs:7:17 --> $DIR/transmute_ptr_to_ref.rs:8:17
| |
LL | let _: &T = std::mem::transmute(p); LL | let _: &T = std::mem::transmute(p);
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p`
@ -7,127 +7,127 @@ LL | let _: &T = std::mem::transmute(p);
= note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings` = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings`
error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
--> $DIR/transmute_ptr_to_ref.rs:10:21 --> $DIR/transmute_ptr_to_ref.rs:11:21
| |
LL | let _: &mut T = std::mem::transmute(m); LL | let _: &mut T = std::mem::transmute(m);
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m`
error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) error: transmute from a pointer type (`*mut T`) to a reference type (`&T`)
--> $DIR/transmute_ptr_to_ref.rs:13:17 --> $DIR/transmute_ptr_to_ref.rs:14:17
| |
LL | let _: &T = std::mem::transmute(m); LL | let _: &T = std::mem::transmute(m);
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m`
error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
--> $DIR/transmute_ptr_to_ref.rs:16:21 --> $DIR/transmute_ptr_to_ref.rs:17:21
| |
LL | let _: &mut T = std::mem::transmute(p as *mut T); LL | let _: &mut T = std::mem::transmute(p as *mut T);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)`
error: transmute from a pointer type (`*const U`) to a reference type (`&T`) error: transmute from a pointer type (`*const U`) to a reference type (`&T`)
--> $DIR/transmute_ptr_to_ref.rs:19:17 --> $DIR/transmute_ptr_to_ref.rs:20:17
| |
LL | let _: &T = std::mem::transmute(o); LL | let _: &T = std::mem::transmute(o);
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)`
error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`)
--> $DIR/transmute_ptr_to_ref.rs:22:21 --> $DIR/transmute_ptr_to_ref.rs:23:21
| |
LL | let _: &mut T = std::mem::transmute(om); LL | let _: &mut T = std::mem::transmute(om);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)`
error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) error: transmute from a pointer type (`*mut U`) to a reference type (`&T`)
--> $DIR/transmute_ptr_to_ref.rs:25:17 --> $DIR/transmute_ptr_to_ref.rs:26:17
| |
LL | let _: &T = std::mem::transmute(om); LL | let _: &T = std::mem::transmute(om);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)`
error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`) error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`)
--> $DIR/transmute_ptr_to_ref.rs:35:32 --> $DIR/transmute_ptr_to_ref.rs:36:32
| |
LL | let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; LL | let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<_>>()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<_>>()`
error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`) error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`)
--> $DIR/transmute_ptr_to_ref.rs:37:33 --> $DIR/transmute_ptr_to_ref.rs:38:33
| |
LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<&_>>()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<&_>>()`
error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`)
--> $DIR/transmute_ptr_to_ref.rs:41:14 --> $DIR/transmute_ptr_to_ref.rs:42:22
| |
LL | unsafe { std::mem::transmute::<_, Bar>(raw) }; LL | let _ = unsafe { std::mem::transmute::<_, Bar>(raw) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)`
error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
--> $DIR/transmute_ptr_to_ref.rs:46:14 --> $DIR/transmute_ptr_to_ref.rs:47:14
| |
LL | 0 => std::mem::transmute(x), LL | 0 => std::mem::transmute(x),
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
--> $DIR/transmute_ptr_to_ref.rs:47:14 --> $DIR/transmute_ptr_to_ref.rs:48:14
| |
LL | 1 => std::mem::transmute(y), LL | 1 => std::mem::transmute(y),
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()`
error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
--> $DIR/transmute_ptr_to_ref.rs:48:14 --> $DIR/transmute_ptr_to_ref.rs:49:14
| |
LL | 2 => std::mem::transmute::<_, &&'b u32>(x), LL | 2 => std::mem::transmute::<_, &&'b u32>(x),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
--> $DIR/transmute_ptr_to_ref.rs:49:14 --> $DIR/transmute_ptr_to_ref.rs:50:14
| |
LL | _ => std::mem::transmute::<_, &&'b u32>(y), LL | _ => std::mem::transmute::<_, &&'b u32>(y),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()`
error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
--> $DIR/transmute_ptr_to_ref.rs:57:19 --> $DIR/transmute_ptr_to_ref.rs:58:19
| |
LL | let _: &u32 = std::mem::transmute(a); LL | let _: &u32 = std::mem::transmute(a);
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
--> $DIR/transmute_ptr_to_ref.rs:58:19 --> $DIR/transmute_ptr_to_ref.rs:59:19
| |
LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); LL | let _: &u32 = std::mem::transmute::<_, &u32>(a);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::<u32>()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::<u32>()`
error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
--> $DIR/transmute_ptr_to_ref.rs:60:14 --> $DIR/transmute_ptr_to_ref.rs:61:14
| |
LL | 0 => std::mem::transmute(x), LL | 0 => std::mem::transmute(x),
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
--> $DIR/transmute_ptr_to_ref.rs:61:14 --> $DIR/transmute_ptr_to_ref.rs:62:14
| |
LL | _ => std::mem::transmute::<_, &&'b u32>(x), LL | _ => std::mem::transmute::<_, &&'b u32>(x),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
--> $DIR/transmute_ptr_to_ref.rs:69:19 --> $DIR/transmute_ptr_to_ref.rs:70:19
| |
LL | let _: &u32 = std::mem::transmute(a); LL | let _: &u32 = std::mem::transmute(a);
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
--> $DIR/transmute_ptr_to_ref.rs:70:19 --> $DIR/transmute_ptr_to_ref.rs:71:19
| |
LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); LL | let _: &u32 = std::mem::transmute::<_, &u32>(a);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)`
error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
--> $DIR/transmute_ptr_to_ref.rs:72:14 --> $DIR/transmute_ptr_to_ref.rs:73:14
| |
LL | 0 => std::mem::transmute(x), LL | 0 => std::mem::transmute(x),
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)`
error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
--> $DIR/transmute_ptr_to_ref.rs:73:14 --> $DIR/transmute_ptr_to_ref.rs:74:14
| |
LL | _ => std::mem::transmute::<_, &&'b u32>(x), LL | _ => std::mem::transmute::<_, &&'b u32>(x),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)`

View File

@ -10,7 +10,7 @@ fn fill(v: &mut i32) {
} }
fn evil() { fn evil() {
unsafe { &mut *(LEAK as *mut i32) }; //~ ERROR: is a dangling pointer let _ = unsafe { &mut *(LEAK as *mut i32) }; //~ ERROR: is a dangling pointer
} }
fn main() { fn main() {

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance) error: Undefined Behavior: dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
--> $DIR/storage_dead_dangling.rs:LL:CC --> $DIR/storage_dead_dangling.rs:LL:CC
| |
LL | unsafe { &mut *(LEAK as *mut i32) }; LL | let _ = unsafe { &mut *(LEAK as *mut i32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance) | ^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
| |
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -2,6 +2,6 @@
#[allow(deprecated, invalid_value)] #[allow(deprecated, invalid_value)]
fn main() { fn main() {
unsafe { std::mem::uninitialized::<!>() }; let _ = unsafe { std::mem::uninitialized::<!>() };
//~^ ERROR: attempted to instantiate uninhabited type `!` //~^ ERROR: attempted to instantiate uninhabited type `!`
} }

View File

@ -1,8 +1,8 @@
error: abnormal termination: aborted execution: attempted to instantiate uninhabited type `!` error: abnormal termination: aborted execution: attempted to instantiate uninhabited type `!`
--> $DIR/uninit_uninhabited_type.rs:LL:CC --> $DIR/uninit_uninhabited_type.rs:LL:CC
| |
LL | unsafe { std::mem::uninitialized::<!>() }; LL | let _ = unsafe { std::mem::uninitialized::<!>() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
| |
= note: inside `main` at $DIR/uninit_uninhabited_type.rs:LL:CC = note: inside `main` at $DIR/uninit_uninhabited_type.rs:LL:CC

View File

@ -1,5 +1,5 @@
#[allow(deprecated, invalid_value)] #[allow(deprecated, invalid_value)]
fn main() { fn main() {
unsafe { std::mem::zeroed::<fn()>() }; let _ = unsafe { std::mem::zeroed::<fn()>() };
//~^ ERROR: attempted to zero-initialize type `fn()`, which is invalid //~^ ERROR: attempted to zero-initialize type `fn()`, which is invalid
} }

View File

@ -1,8 +1,8 @@
error: abnormal termination: aborted execution: attempted to zero-initialize type `fn()`, which is invalid error: abnormal termination: aborted execution: attempted to zero-initialize type `fn()`, which is invalid
--> $DIR/zero_fn_ptr.rs:LL:CC --> $DIR/zero_fn_ptr.rs:LL:CC
| |
LL | unsafe { std::mem::zeroed::<fn()>() }; LL | let _ = unsafe { std::mem::zeroed::<fn()>() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid | ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid
| |
= note: inside `main` at $DIR/zero_fn_ptr.rs:LL:CC = note: inside `main` at $DIR/zero_fn_ptr.rs:LL:CC

View File

@ -1,8 +1,8 @@
warning: unused closure that must be used warning: unused closure that must be used
--> $DIR/issue-1460.rs:6:5 --> $DIR/issue-1460.rs:6:6
| |
LL | {|i: u32| if 1 == i { }}; LL | {|i: u32| if 1 == i { }};
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
| |
= note: closures are lazy and do nothing unless called = note: closures are lazy and do nothing unless called
= note: `#[warn(unused_must_use)]` on by default = note: `#[warn(unused_must_use)]` on by default

View File

@ -0,0 +1,36 @@
// run-rustfix
// check-pass
#![warn(unused_must_use)]
#[must_use]
fn foo() -> i32 {
42
}
fn bar() {
{
let _ = foo();
//~^ WARN unused return value
}
}
fn baz() {
{
let _ = foo();
//~^ WARN unused return value
};
}
fn main() {
bar();
baz();
{
let _ = 1 + 2;
//~^ WARN unused arithmetic operation
}
{
let _ = 1 + 2;
//~^ WARN unused arithmetic operation
};
}

View File

@ -0,0 +1,36 @@
// run-rustfix
// check-pass
#![warn(unused_must_use)]
#[must_use]
fn foo() -> i32 {
42
}
fn bar() {
{
foo();
//~^ WARN unused return value
}
}
fn baz() {
{
foo()
//~^ WARN unused return value
};
}
fn main() {
bar();
baz();
{
1 + 2;
//~^ WARN unused arithmetic operation
}
{
1 + 2
//~^ WARN unused arithmetic operation
};
}

View File

@ -0,0 +1,51 @@
warning: unused return value of `foo` that must be used
--> $DIR/must-use-block-expr.rs:13:9
|
LL | foo();
| ^^^^^
|
note: the lint level is defined here
--> $DIR/must-use-block-expr.rs:4:9
|
LL | #![warn(unused_must_use)]
| ^^^^^^^^^^^^^^^
help: use `let _ = ...` to ignore the resulting value
|
LL | let _ = foo();
| +++++++
warning: unused return value of `foo` that must be used
--> $DIR/must-use-block-expr.rs:20:9
|
LL | foo()
| ^^^^^
|
help: use `let _ = ...` to ignore the resulting value
|
LL | let _ = foo();
| +++++++ +
warning: unused arithmetic operation that must be used
--> $DIR/must-use-block-expr.rs:29:9
|
LL | 1 + 2;
| ^^^^^ the arithmetic operation produces a value
|
help: use `let _ = ...` to ignore the resulting value
|
LL | let _ = 1 + 2;
| +++++++
warning: unused arithmetic operation that must be used
--> $DIR/must-use-block-expr.rs:33:9
|
LL | 1 + 2
| ^^^^^ the arithmetic operation produces a value
|
help: use `let _ = ...` to ignore the resulting value
|
LL | let _ = 1 + 2;
| +++++++ +
warning: 4 warnings emitted