From d351448404595e4564e60933e66d4a939656fc38 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 27 Feb 2026 16:46:44 +0100 Subject: [PATCH 1/2] add more tests for `unused_results` lints --- tests/ui/lint/unused/unused-result.rs | 14 +++++++++ tests/ui/lint/unused/unused-result.stderr | 36 +++++++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/tests/ui/lint/unused/unused-result.rs b/tests/ui/lint/unused/unused-result.rs index e283eaa88dd13..9dc18ff6243d2 100644 --- a/tests/ui/lint/unused/unused-result.rs +++ b/tests/ui/lint/unused/unused-result.rs @@ -3,12 +3,16 @@ //~^ NOTE: the lint level is defined here //~| NOTE: the lint level is defined here +use std::ops::ControlFlow; + #[must_use] enum MustUse { Test } #[must_use = "some message"] enum MustUseMsg { Test2 } +enum Nothing {} + fn foo() -> T { panic!() } fn bar() -> isize { return foo::(); } @@ -39,4 +43,14 @@ fn main() { let _ = foo::(); let _ = foo::(); let _ = foo::(); + + (); + ((), ()); //~ ERROR: unused result of type + Ok::<(), Nothing>(()); + ControlFlow::::Continue(()); + ((), Ok::<(), Nothing>(()), ((((), ())), ((),))); //~ ERROR: unused result of type + foo::(); + + ((), 1); //~ ERROR: unused result of type `((), i32)` + (1, ()); //~ ERROR: unused result of type `(i32, ())` } diff --git a/tests/ui/lint/unused/unused-result.stderr b/tests/ui/lint/unused/unused-result.stderr index f42995a65d13e..27d7d57bc6eb4 100644 --- a/tests/ui/lint/unused/unused-result.stderr +++ b/tests/ui/lint/unused/unused-result.stderr @@ -1,5 +1,5 @@ error: unused `MustUse` that must be used - --> $DIR/unused-result.rs:21:5 + --> $DIR/unused-result.rs:25:5 | LL | foo::(); | ^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | let _ = foo::(); | +++++++ error: unused `MustUseMsg` that must be used - --> $DIR/unused-result.rs:22:5 + --> $DIR/unused-result.rs:26:5 | LL | foo::(); | ^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | let _ = foo::(); | +++++++ error: unused result of type `isize` - --> $DIR/unused-result.rs:34:5 + --> $DIR/unused-result.rs:38:5 | LL | foo::(); | ^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | #![deny(unused_results, unused_must_use)] | ^^^^^^^^^^^^^^ error: unused `MustUse` that must be used - --> $DIR/unused-result.rs:35:5 + --> $DIR/unused-result.rs:39:5 | LL | foo::(); | ^^^^^^^^^^^^^^^^ @@ -50,7 +50,7 @@ LL | let _ = foo::(); | +++++++ error: unused `MustUseMsg` that must be used - --> $DIR/unused-result.rs:36:5 + --> $DIR/unused-result.rs:40:5 | LL | foo::(); | ^^^^^^^^^^^^^^^^^^^ @@ -61,5 +61,29 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = foo::(); | +++++++ -error: aborting due to 5 previous errors +error: unused result of type `((), ())` + --> $DIR/unused-result.rs:48:5 + | +LL | ((), ()); + | ^^^^^^^^^ + +error: unused result of type `((), Result<(), Nothing>, (((), ()), ((),)))` + --> $DIR/unused-result.rs:51:5 + | +LL | ((), Ok::<(), Nothing>(()), ((((), ())), ((),))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused result of type `((), i32)` + --> $DIR/unused-result.rs:54:5 + | +LL | ((), 1); + | ^^^^^^^^ + +error: unused result of type `(i32, ())` + --> $DIR/unused-result.rs:55:5 + | +LL | (1, ()); + | ^^^^^^^^ + +error: aborting due to 9 previous errors From 8958cb974dd6931219888d272d9b83c4db1b7a01 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 27 Feb 2026 16:37:31 +0100 Subject: [PATCH 2/2] don't emit `unused_results` lint for tuples of trivial types --- compiler/rustc_lint/src/unused/must_use.rs | 32 +++++++++++----------- tests/ui/lint/unused/unused-result.rs | 5 ++-- tests/ui/lint/unused/unused-result.stderr | 18 ++---------- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index f37cf4c8dc8c0..9eb45666442fc 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -108,13 +108,6 @@ impl IsTyMustUse { _ => self, } } - - fn yes(self) -> Option { - match self { - Self::Yes(must_use_path) => Some(must_use_path), - _ => None, - } - } } /// A path through a type to a `must_use` source. Contains useful info for the lint. @@ -254,16 +247,23 @@ pub fn is_ty_must_use<'tcx>( // Default to `expr`. let elem_exprs = elem_exprs.iter().chain(iter::repeat(expr)); - let nested_must_use = tys - .iter() - .zip(elem_exprs) - .enumerate() - .filter_map(|(i, (ty, expr))| { - is_ty_must_use(cx, ty, expr, simplify_uninhabited).yes().map(|path| (i, path)) - }) - .collect::>(); + let mut all_trivial = true; + let mut nested_must_use = Vec::new(); + + tys.iter().zip(elem_exprs).enumerate().for_each(|(i, (ty, expr))| { + let must_use = is_ty_must_use(cx, ty, expr, simplify_uninhabited); + + all_trivial &= matches!(must_use, IsTyMustUse::Trivial); + if let IsTyMustUse::Yes(path) = must_use { + nested_must_use.push((i, path)); + } + }); - if !nested_must_use.is_empty() { + if all_trivial { + // If all tuple elements are trivial, mark the whole tuple as such. + // i.e. don't emit `unused_results` for types such as `((), ())` + IsTyMustUse::Trivial + } else if !nested_must_use.is_empty() { IsTyMustUse::Yes(MustUsePath::TupleElement(nested_must_use)) } else { IsTyMustUse::No diff --git a/tests/ui/lint/unused/unused-result.rs b/tests/ui/lint/unused/unused-result.rs index 9dc18ff6243d2..bfc9d61bb9c88 100644 --- a/tests/ui/lint/unused/unused-result.rs +++ b/tests/ui/lint/unused/unused-result.rs @@ -44,11 +44,12 @@ fn main() { let _ = foo::(); let _ = foo::(); + // "trivial" types (); - ((), ()); //~ ERROR: unused result of type + ((), ()); Ok::<(), Nothing>(()); ControlFlow::::Continue(()); - ((), Ok::<(), Nothing>(()), ((((), ())), ((),))); //~ ERROR: unused result of type + ((), Ok::<(), Nothing>(()), ((((), ())), ((),))); foo::(); ((), 1); //~ ERROR: unused result of type `((), i32)` diff --git a/tests/ui/lint/unused/unused-result.stderr b/tests/ui/lint/unused/unused-result.stderr index 27d7d57bc6eb4..b584733ba1cb4 100644 --- a/tests/ui/lint/unused/unused-result.stderr +++ b/tests/ui/lint/unused/unused-result.stderr @@ -61,29 +61,17 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = foo::(); | +++++++ -error: unused result of type `((), ())` - --> $DIR/unused-result.rs:48:5 - | -LL | ((), ()); - | ^^^^^^^^^ - -error: unused result of type `((), Result<(), Nothing>, (((), ()), ((),)))` - --> $DIR/unused-result.rs:51:5 - | -LL | ((), Ok::<(), Nothing>(()), ((((), ())), ((),))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: unused result of type `((), i32)` - --> $DIR/unused-result.rs:54:5 + --> $DIR/unused-result.rs:55:5 | LL | ((), 1); | ^^^^^^^^ error: unused result of type `(i32, ())` - --> $DIR/unused-result.rs:55:5 + --> $DIR/unused-result.rs:56:5 | LL | (1, ()); | ^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors