From 173b95031166abc96bd979360274abe8b5016fde Mon Sep 17 00:00:00 2001 From: Max Niederman Date: Sat, 18 Nov 2023 20:04:50 -0800 Subject: [PATCH 1/2] catch pinned `must_use` types in `unused_must_use` --- compiler/rustc_lint/src/unused.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 355855b8e2b3e..0ae91ac28a740 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -251,6 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { /// The root of the normal must_use lint with an optional message. Def(Span, DefId, Option), Boxed(Box), + Pinned(Box), Opaque(Box), TraitObject(Box), TupleElement(Vec<(usize, Self)>), @@ -284,6 +285,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { is_ty_must_use(cx, boxed_ty, expr, span) .map(|inner| MustUsePath::Boxed(Box::new(inner))) } + ty::Adt(def, args) if cx.tcx.lang_items().pin_type() == Some(def.did()) => { + let pinned_ty = args.type_at(0); + is_ty_must_use(cx, pinned_ty, expr, span) + .map(|inner| MustUsePath::Pinned(Box::new(inner))) + } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { elaborate( @@ -425,6 +431,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { expr_is_from_block, ); } + MustUsePath::Pinned(path) => { + let descr_pre = &format!("{descr_pre}pinned "); + emit_must_use_untranslated( + cx, + path, + descr_pre, + descr_post, + plural_len, + true, + expr_is_from_block, + ); + } MustUsePath::Opaque(path) => { let descr_pre = &format!("{descr_pre}implementer{plural_suffix} of "); emit_must_use_untranslated( From c5ed7b0ead27a9b666c2c4fc14160fba972df793 Mon Sep 17 00:00:00 2001 From: Max Niederman Date: Sat, 18 Nov 2023 21:01:02 -0800 Subject: [PATCH 2/2] add test for pinned `must_use` pointers --- tests/ui/lint/unused/must_use-pin.rs | 45 ++++++++++++++++++++++++ tests/ui/lint/unused/must_use-pin.stderr | 20 +++++++++++ 2 files changed, 65 insertions(+) create mode 100644 tests/ui/lint/unused/must_use-pin.rs create mode 100644 tests/ui/lint/unused/must_use-pin.stderr diff --git a/tests/ui/lint/unused/must_use-pin.rs b/tests/ui/lint/unused/must_use-pin.rs new file mode 100644 index 0000000000000..b08515428b1b5 --- /dev/null +++ b/tests/ui/lint/unused/must_use-pin.rs @@ -0,0 +1,45 @@ +#![deny(unused_must_use)] + +use std::{ops::Deref, pin::Pin}; + +#[must_use] +struct MustUse; + +#[must_use] +struct MustUsePtr<'a, T>(&'a T); + +impl<'a, T> Deref for MustUsePtr<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.0 + } +} + +fn pin_ref() -> Pin<&'static ()> { + Pin::new(&()) +} + +fn pin_ref_mut() -> Pin<&'static mut ()> { + Pin::new(unimplemented!()) +} + +fn pin_must_use_ptr() -> Pin> { + Pin::new(MustUsePtr(&())) +} + +fn pin_box() -> Pin> { + Box::pin(()) +} + +fn pin_box_must_use() -> Pin> { + Box::pin(MustUse) +} + +fn main() { + pin_ref(); + pin_ref_mut(); + pin_must_use_ptr(); //~ ERROR unused pinned `MustUsePtr` that must be used + pin_box(); + pin_box_must_use(); //~ ERROR unused pinned boxed `MustUse` that must be used +} diff --git a/tests/ui/lint/unused/must_use-pin.stderr b/tests/ui/lint/unused/must_use-pin.stderr new file mode 100644 index 0000000000000..c04f8fef4873f --- /dev/null +++ b/tests/ui/lint/unused/must_use-pin.stderr @@ -0,0 +1,20 @@ +error: unused pinned `MustUsePtr` that must be used + --> $DIR/must_use-pin.rs:42:5 + | +LL | pin_must_use_ptr(); + | ^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-pin.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused pinned boxed `MustUse` that must be used + --> $DIR/must_use-pin.rs:44:5 + | +LL | pin_box_must_use(); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors +