diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 6e15f06a76de0..ba47ebd68cbf5 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -67,7 +67,7 @@ struct ArenaChunk { unsafe impl<#[may_dangle] T> Drop for ArenaChunk { fn drop(&mut self) { - unsafe { Box::from_raw(self.storage.as_mut()) }; + unsafe { drop(Box::from_raw(self.storage.as_mut())) } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index e990c771bdf50..9bcf672672a97 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1534,8 +1534,29 @@ pub struct UnusedOp<'a> { pub op: &'a str, #[label] pub label: Span, - #[suggestion(style = "verbose", code = "let _ = ", applicability = "maybe-incorrect")] - pub suggestion: Span, + #[subdiagnostic] + 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)] @@ -1578,15 +1599,25 @@ pub struct UnusedDef<'a, 'b> { } #[derive(Subdiagnostic)] -#[suggestion( - lint_suggestion, - style = "verbose", - code = "let _ = ", - applicability = "maybe-incorrect" -)] -pub struct UnusedDefSuggestion { - #[primary_span] - pub span: Span, + +pub enum UnusedDefSuggestion { + #[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, + }, } // Needed because of def_path_str diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 04df23c736b0d..9861610612fb0 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1,7 +1,8 @@ use crate::lints::{ PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag, UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim, - UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult, + UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion, + UnusedResult, }; use crate::Lint; 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 { 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 { return; @@ -113,6 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { expr.span, "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 @@ -125,13 +135,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span); let type_lint_emitted_or_suppressed = match must_use_result { Some(path) => { - emit_must_use_untranslated(cx, &path, "", "", 1, false); + emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block); true } 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 { // We don't warn about unused unit or uninhabited types. @@ -176,7 +186,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { UnusedOp { op: must_use_op, 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; @@ -186,7 +203,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { 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 { hir::ExprKind::Call(ref callee, _) => { match callee.kind { @@ -207,7 +228,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { _ => None, }; 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 { false } @@ -350,6 +378,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { span: Span, descr_pre_path: &str, descr_post_path: &str, + expr_is_from_block: bool, ) -> bool { is_def_must_use(cx, def_id, span) .map(|must_use_path| { @@ -360,6 +389,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_post_path, 1, false, + expr_is_from_block, ) }) .is_some() @@ -373,6 +403,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_post: &str, plural_len: usize, is_inner: bool, + expr_is_from_block: bool, ) { let plural_suffix = pluralize!(plural_len); @@ -380,21 +411,51 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { MustUsePath::Suppressed => {} MustUsePath::Boxed(path) => { 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) => { 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) => { 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) => { for (index, path) in elems { let descr_post = &format!(" in tuple element {}", index); 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, plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)), true, + expr_is_from_block, ); } MustUsePath::Closure(span) => { @@ -433,8 +495,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { cx, def_id: *def_id, note: *reason, - suggestion: (!is_inner) - .then_some(UnusedDefSuggestion { span: span.shrink_to_lo() }), + suggestion: (!is_inner).then_some(if expr_is_from_block { + UnusedDefSuggestion::BlockTailExpr { + before_span: span.shrink_to_lo(), + after_span: span.shrink_to_hi(), + } + } else { + UnusedDefSuggestion::NormalExpr { span: span.shrink_to_lo() } + }), }, ); } diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 8266e899011cb..80289ca08c3fc 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -308,7 +308,7 @@ mod prim_never {} /// /// ```no_run /// // 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 diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index c02cd99cc4477..ee885adfeee61 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1001,7 +1001,7 @@ fn nonnull_tagged_pointer_with_provenance() { assert_eq!(p.tag(), 3); 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. #[repr(transparent)] diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 8266e899011cb..80289ca08c3fc 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -308,7 +308,7 @@ mod prim_never {} /// /// ```no_run /// // 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 diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed index 575dadde90630..ac55ab5a8e2d1 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed @@ -2,6 +2,7 @@ #![warn(clippy::transmute_ptr_to_ref)] #![allow(clippy::match_single_binding)] +#![allow(unused_must_use)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*p; @@ -38,7 +39,7 @@ fn _issue1231() { type Bar<'a> = &'a u8; 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 { diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs index 4238ff804780e..901a3e90dbecc 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs @@ -2,6 +2,7 @@ #![warn(clippy::transmute_ptr_to_ref)] #![allow(clippy::match_single_binding)] +#![allow(unused_must_use)] unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = std::mem::transmute(p); @@ -38,7 +39,7 @@ fn _issue1231() { type Bar<'a> = &'a u8; 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 { diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr index b3e6c09d2d7a1..68007edc41028 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr @@ -1,5 +1,5 @@ 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); | ^^^^^^^^^^^^^^^^^^^^^^ 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` 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); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` 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); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` 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); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut 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); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const 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); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut 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); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` 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 = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` 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) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` 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) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` +LL | let _ = unsafe { std::mem::transmute::<_, Bar>(raw) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` 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), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&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), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&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), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b 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), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b 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); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` 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); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::()` 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), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&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), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b 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); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` 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); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const 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), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &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), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs index 03113585d1464..366930a831c88 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs @@ -10,7 +10,7 @@ fn fill(v: &mut i32) { } 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() { diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr index 2ba8116cadc24..6c41add60ef4a 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance) --> $DIR/storage_dead_dangling.rs:LL:CC | -LL | unsafe { &mut *(LEAK as *mut i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance) +LL | let _ = unsafe { &mut *(LEAK as *mut i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ 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: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs index e606d8b283c8a..59781f023661c 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs @@ -2,6 +2,6 @@ #[allow(deprecated, invalid_value)] fn main() { - unsafe { std::mem::uninitialized::() }; + let _ = unsafe { std::mem::uninitialized::() }; //~^ ERROR: attempted to instantiate uninhabited type `!` } diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr index 150128ba2a41c..f2cc343032627 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr @@ -1,8 +1,8 @@ error: abnormal termination: aborted execution: attempted to instantiate uninhabited type `!` --> $DIR/uninit_uninhabited_type.rs:LL:CC | -LL | unsafe { std::mem::uninitialized::() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` +LL | let _ = unsafe { std::mem::uninitialized::() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` | = note: inside `main` at $DIR/uninit_uninhabited_type.rs:LL:CC diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs index 6d9ae14c5c479..e9c6e464e88cf 100644 --- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs +++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs @@ -1,5 +1,5 @@ #[allow(deprecated, invalid_value)] fn main() { - unsafe { std::mem::zeroed::() }; + let _ = unsafe { std::mem::zeroed::() }; //~^ ERROR: attempted to zero-initialize type `fn()`, which is invalid } diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr index 9d44ba9f746ad..77d5822804315 100644 --- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr +++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr @@ -1,8 +1,8 @@ error: abnormal termination: aborted execution: attempted to zero-initialize type `fn()`, which is invalid --> $DIR/zero_fn_ptr.rs:LL:CC | -LL | unsafe { std::mem::zeroed::() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid +LL | let _ = unsafe { std::mem::zeroed::() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid | = note: inside `main` at $DIR/zero_fn_ptr.rs:LL:CC diff --git a/tests/ui/issues/issue-1460.stderr b/tests/ui/issues/issue-1460.stderr index eb7661fad56db..d4a8c8955e233 100644 --- a/tests/ui/issues/issue-1460.stderr +++ b/tests/ui/issues/issue-1460.stderr @@ -1,8 +1,8 @@ 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 { }}; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: closures are lazy and do nothing unless called = note: `#[warn(unused_must_use)]` on by default diff --git a/tests/ui/lint/unused/must-use-block-expr.fixed b/tests/ui/lint/unused/must-use-block-expr.fixed new file mode 100644 index 0000000000000..642012812bd2a --- /dev/null +++ b/tests/ui/lint/unused/must-use-block-expr.fixed @@ -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 + }; +} diff --git a/tests/ui/lint/unused/must-use-block-expr.rs b/tests/ui/lint/unused/must-use-block-expr.rs new file mode 100644 index 0000000000000..e0a680aa07d08 --- /dev/null +++ b/tests/ui/lint/unused/must-use-block-expr.rs @@ -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 + }; +} diff --git a/tests/ui/lint/unused/must-use-block-expr.stderr b/tests/ui/lint/unused/must-use-block-expr.stderr new file mode 100644 index 0000000000000..d821beb1d92e7 --- /dev/null +++ b/tests/ui/lint/unused/must-use-block-expr.stderr @@ -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 +