From 2997070be183a613457bcba5a38f82a25030a19c Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 5 Oct 2025 10:23:44 -0700 Subject: [PATCH 1/7] unused_must_use: Factor out a variable for the parent module DefId This simplifies the initial conditional, and will allow reusing the variable in subsequent checks. --- compiler/rustc_lint/src/unused.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 874c435402919..e70ec18340add 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -273,13 +273,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { expr: &hir::Expr<'_>, span: Span, ) -> Option { - if ty.is_unit() - || !ty.is_inhabited_from( - cx.tcx, - cx.tcx.parent_module(expr.hir_id).to_def_id(), - cx.typing_env(), - ) - { + if ty.is_unit() { + return Some(MustUsePath::Suppressed); + } + let parent_mod_did = cx.tcx.parent_module(expr.hir_id).to_def_id(); + if !ty.is_inhabited_from(cx.tcx, parent_mod_did, cx.typing_env()) { return Some(MustUsePath::Suppressed); } From 6f89cecf3756c276dbd263810e86c13a652dbb5a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 5 Oct 2025 10:25:17 -0700 Subject: [PATCH 2/7] unused_must_use: Don't warn on `Result<(), Uninhabited>` This suppresses warnings on things like `Result<(), !>`, which helps simplify code using the common pattern of having an `Error` associated type: code will only have to check the error if there is a possibility of error. --- compiler/rustc_lint/src/unused.rs | 12 ++++ ...se_result_unit_uninhabited_extern_crate.rs | 4 ++ .../must_use-result-unit-uninhabited.rs | 55 +++++++++++++++++++ .../must_use-result-unit-uninhabited.stderr | 43 +++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 tests/ui/lint/unused/auxiliary/must_use_result_unit_uninhabited_extern_crate.rs create mode 100644 tests/ui/lint/unused/must_use-result-unit-uninhabited.rs create mode 100644 tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index e70ec18340add..0eb1e881896ba 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -291,6 +291,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { is_ty_must_use(cx, pinned_ty, expr, span) .map(|inner| MustUsePath::Pinned(Box::new(inner))) } + // Suppress warnings on `Result<(), Uninhabited>` (e.g. `Result<(), !>`). + ty::Adt(def, args) + if cx.tcx.is_diagnostic_item(sym::Result, def.did()) + && args.type_at(0).is_unit() + && !args.type_at(1).is_inhabited_from( + cx.tcx, + parent_mod_did, + cx.typing_env(), + ) => + { + Some(MustUsePath::Suppressed) + } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => { elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied()) diff --git a/tests/ui/lint/unused/auxiliary/must_use_result_unit_uninhabited_extern_crate.rs b/tests/ui/lint/unused/auxiliary/must_use_result_unit_uninhabited_extern_crate.rs new file mode 100644 index 0000000000000..a193dfa8c47bc --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/must_use_result_unit_uninhabited_extern_crate.rs @@ -0,0 +1,4 @@ +pub enum MyUninhabited {} + +#[non_exhaustive] +pub enum MyUninhabitedNonexhaustive {} diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs new file mode 100644 index 0000000000000..1a7facb91a9a7 --- /dev/null +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs @@ -0,0 +1,55 @@ +//@ edition: 2024 +//@ aux-crate:dep=must_use_result_unit_uninhabited_extern_crate.rs + +#![deny(unused_must_use)] +#![feature(never_type)] + +use dep::{MyUninhabited, MyUninhabitedNonexhaustive}; + +fn f1() -> Result<(), ()> { + Ok(()) +} + +fn f2() -> Result<(), core::convert::Infallible> { + Ok(()) +} + +fn f3() -> Result<(), !> { + Ok(()) +} + +fn f4() -> Result<(), MyUninhabited> { + Ok(()) +} + +fn f5() -> Result<(), MyUninhabitedNonexhaustive> { + Ok(()) +} + +trait AssocType { + type Error; +} + +struct S1; +impl AssocType for S1 { + type Error = !; +} + +struct S2; +impl AssocType for S2 { + type Error = (); +} + +fn f6(_: AT) -> Result<(), AT::Error> { + Ok(()) +} + +fn main() { + f1(); //~ ERROR: unused `Result` that must be used + f2(); + f3(); + f4(); + f5(); //~ ERROR: unused `Result` that must be used + f6(S1); + f6(S2); //~ ERROR: unused `Result` that must be used +} diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr new file mode 100644 index 0000000000000..0ee06b0504ad0 --- /dev/null +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr @@ -0,0 +1,43 @@ +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:48:5 + | +LL | f1(); + | ^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +note: the lint level is defined here + --> $DIR/must_use-result-unit-uninhabited.rs:4:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = f1(); + | +++++++ + +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:52:5 + | +LL | f5(); + | ^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = f5(); + | +++++++ + +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:54:5 + | +LL | f6(S2); + | ^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = f6(S2); + | +++++++ + +error: aborting due to 3 previous errors + From efd76c910ecf24329218df0fbba74293f1da4399 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 5 Oct 2025 10:45:16 -0700 Subject: [PATCH 3/7] unused_must_use: Add test for a method using an associated error type --- .../must_use-result-unit-uninhabited.rs | 21 +++++++++++++++++++ .../must_use-result-unit-uninhabited.stderr | 20 ++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs index 1a7facb91a9a7..340e4abe0cdfe 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs @@ -44,6 +44,25 @@ fn f6(_: AT) -> Result<(), AT::Error> { Ok(()) } +trait UsesAssocType { + type Error; + fn method(&self) -> Result<(), Self::Error>; +} + +impl UsesAssocType for S1 { + type Error = !; + fn method(&self) -> Result<(), Self::Error> { + Ok(()) + } +} + +impl UsesAssocType for S2 { + type Error = (); + fn method(&self) -> Result<(), Self::Error> { + Err(()) + } +} + fn main() { f1(); //~ ERROR: unused `Result` that must be used f2(); @@ -52,4 +71,6 @@ fn main() { f5(); //~ ERROR: unused `Result` that must be used f6(S1); f6(S2); //~ ERROR: unused `Result` that must be used + S1.method(); + S2.method(); //~ ERROR: unused `Result` that must be used } diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr index 0ee06b0504ad0..8e1f300f6e7ff 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr @@ -1,5 +1,5 @@ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:48:5 + --> $DIR/must_use-result-unit-uninhabited.rs:67:5 | LL | f1(); | ^^^^ @@ -16,7 +16,7 @@ LL | let _ = f1(); | +++++++ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:52:5 + --> $DIR/must_use-result-unit-uninhabited.rs:71:5 | LL | f5(); | ^^^^ @@ -28,7 +28,7 @@ LL | let _ = f5(); | +++++++ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:54:5 + --> $DIR/must_use-result-unit-uninhabited.rs:73:5 | LL | f6(S2); | ^^^^^^ @@ -39,5 +39,17 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = f6(S2); | +++++++ -error: aborting due to 3 previous errors +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:75:5 + | +LL | S2.method(); + | ^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = S2.method(); + | +++++++ + +error: aborting due to 4 previous errors From 39f59bf6a23a2912e69a8ac43e8c1e9571e7194d Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 5 Oct 2025 21:40:26 -0700 Subject: [PATCH 4/7] unused_must_use: Suppress warnings for `ControlFlow` too --- compiler/rustc_lint/src/unused.rs | 12 +++++++++++ .../must_use-result-unit-uninhabited.rs | 17 +++++++++++++++ .../must_use-result-unit-uninhabited.stderr | 21 ++++++++++++++----- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 0eb1e881896ba..936c67a76a490 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -303,6 +303,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { { Some(MustUsePath::Suppressed) } + // Suppress warnings on `ControlFlow` (e.g. `ControlFlow`). + ty::Adt(def, args) + if cx.tcx.is_diagnostic_item(sym::ControlFlow, def.did()) + && args.type_at(1).is_unit() + && !args.type_at(0).is_inhabited_from( + cx.tcx, + parent_mod_did, + cx.typing_env(), + ) => + { + Some(MustUsePath::Suppressed) + } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => { elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied()) diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs index 340e4abe0cdfe..cd319545bb305 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs @@ -4,6 +4,7 @@ #![deny(unused_must_use)] #![feature(never_type)] +use core::ops::{ControlFlow, ControlFlow::Continue}; use dep::{MyUninhabited, MyUninhabitedNonexhaustive}; fn f1() -> Result<(), ()> { @@ -63,6 +64,18 @@ impl UsesAssocType for S2 { } } +fn c1() -> ControlFlow<()> { + Continue(()) +} + +fn c2() -> ControlFlow { + Continue(()) +} + +fn c3() -> ControlFlow { + Continue(()) +} + fn main() { f1(); //~ ERROR: unused `Result` that must be used f2(); @@ -73,4 +86,8 @@ fn main() { f6(S2); //~ ERROR: unused `Result` that must be used S1.method(); S2.method(); //~ ERROR: unused `Result` that must be used + + c1(); //~ ERROR: unused `ControlFlow` that must be used + c2(); + c3(); } diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr index 8e1f300f6e7ff..cbe4749fda31b 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr @@ -1,5 +1,5 @@ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:67:5 + --> $DIR/must_use-result-unit-uninhabited.rs:80:5 | LL | f1(); | ^^^^ @@ -16,7 +16,7 @@ LL | let _ = f1(); | +++++++ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:71:5 + --> $DIR/must_use-result-unit-uninhabited.rs:84:5 | LL | f5(); | ^^^^ @@ -28,7 +28,7 @@ LL | let _ = f5(); | +++++++ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:73:5 + --> $DIR/must_use-result-unit-uninhabited.rs:86:5 | LL | f6(S2); | ^^^^^^ @@ -40,7 +40,7 @@ LL | let _ = f6(S2); | +++++++ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:75:5 + --> $DIR/must_use-result-unit-uninhabited.rs:88:5 | LL | S2.method(); | ^^^^^^^^^^^ @@ -51,5 +51,16 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = S2.method(); | +++++++ -error: aborting due to 4 previous errors +error: unused `ControlFlow` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:90:5 + | +LL | c1(); + | ^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = c1(); + | +++++++ + +error: aborting due to 5 previous errors From 339caa11c7a71890047d0eeab2e6ba6a17673b49 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 6 Oct 2025 08:06:48 -0700 Subject: [PATCH 5/7] unused_must_use: Rename test functions to reflect what they test This makes it easier to review without cross-referencing each test function with its invocation. --- .../must_use-result-unit-uninhabited.rs | 50 +++++++++---------- .../must_use-result-unit-uninhabited.stderr | 30 +++++------ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs index cd319545bb305..d0dd8d2372092 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs @@ -7,23 +7,23 @@ use core::ops::{ControlFlow, ControlFlow::Continue}; use dep::{MyUninhabited, MyUninhabitedNonexhaustive}; -fn f1() -> Result<(), ()> { +fn result_unit_unit() -> Result<(), ()> { Ok(()) } -fn f2() -> Result<(), core::convert::Infallible> { +fn result_unit_infallible() -> Result<(), core::convert::Infallible> { Ok(()) } -fn f3() -> Result<(), !> { +fn result_unit_never() -> Result<(), !> { Ok(()) } -fn f4() -> Result<(), MyUninhabited> { +fn result_unit_myuninhabited() -> Result<(), MyUninhabited> { Ok(()) } -fn f5() -> Result<(), MyUninhabitedNonexhaustive> { +fn result_unit_myuninhabited_nonexhaustive() -> Result<(), MyUninhabitedNonexhaustive> { Ok(()) } @@ -41,53 +41,53 @@ impl AssocType for S2 { type Error = (); } -fn f6(_: AT) -> Result<(), AT::Error> { +fn result_unit_assoctype(_: AT) -> Result<(), AT::Error> { Ok(()) } trait UsesAssocType { type Error; - fn method(&self) -> Result<(), Self::Error>; + fn method_use_assoc_type(&self) -> Result<(), Self::Error>; } impl UsesAssocType for S1 { type Error = !; - fn method(&self) -> Result<(), Self::Error> { + fn method_use_assoc_type(&self) -> Result<(), Self::Error> { Ok(()) } } impl UsesAssocType for S2 { type Error = (); - fn method(&self) -> Result<(), Self::Error> { + fn method_use_assoc_type(&self) -> Result<(), Self::Error> { Err(()) } } -fn c1() -> ControlFlow<()> { +fn controlflow_unit() -> ControlFlow<()> { Continue(()) } -fn c2() -> ControlFlow { +fn controlflow_infallible_unit() -> ControlFlow { Continue(()) } -fn c3() -> ControlFlow { +fn controlflow_never() -> ControlFlow { Continue(()) } fn main() { - f1(); //~ ERROR: unused `Result` that must be used - f2(); - f3(); - f4(); - f5(); //~ ERROR: unused `Result` that must be used - f6(S1); - f6(S2); //~ ERROR: unused `Result` that must be used - S1.method(); - S2.method(); //~ ERROR: unused `Result` that must be used - - c1(); //~ ERROR: unused `ControlFlow` that must be used - c2(); - c3(); + result_unit_unit(); //~ ERROR: unused `Result` that must be used + result_unit_infallible(); + result_unit_never(); + result_unit_myuninhabited(); + result_unit_myuninhabited_nonexhaustive(); //~ ERROR: unused `Result` that must be used + result_unit_assoctype(S1); + result_unit_assoctype(S2); //~ ERROR: unused `Result` that must be used + S1.method_use_assoc_type(); + S2.method_use_assoc_type(); //~ ERROR: unused `Result` that must be used + + controlflow_unit(); //~ ERROR: unused `ControlFlow` that must be used + controlflow_infallible_unit(); + controlflow_never(); } diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr index cbe4749fda31b..90ac44d0c6c6f 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr @@ -1,8 +1,8 @@ error: unused `Result` that must be used --> $DIR/must_use-result-unit-uninhabited.rs:80:5 | -LL | f1(); - | ^^^^ +LL | result_unit_unit(); + | ^^^^^^^^^^^^^^^^^^ | = note: this `Result` may be an `Err` variant, which should be handled note: the lint level is defined here @@ -12,54 +12,54 @@ LL | #![deny(unused_must_use)] | ^^^^^^^^^^^^^^^ help: use `let _ = ...` to ignore the resulting value | -LL | let _ = f1(); +LL | let _ = result_unit_unit(); | +++++++ error: unused `Result` that must be used --> $DIR/must_use-result-unit-uninhabited.rs:84:5 | -LL | f5(); - | ^^^^ +LL | result_unit_myuninhabited_nonexhaustive(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this `Result` may be an `Err` variant, which should be handled help: use `let _ = ...` to ignore the resulting value | -LL | let _ = f5(); +LL | let _ = result_unit_myuninhabited_nonexhaustive(); | +++++++ error: unused `Result` that must be used --> $DIR/must_use-result-unit-uninhabited.rs:86:5 | -LL | f6(S2); - | ^^^^^^ +LL | result_unit_assoctype(S2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this `Result` may be an `Err` variant, which should be handled help: use `let _ = ...` to ignore the resulting value | -LL | let _ = f6(S2); +LL | let _ = result_unit_assoctype(S2); | +++++++ error: unused `Result` that must be used --> $DIR/must_use-result-unit-uninhabited.rs:88:5 | -LL | S2.method(); - | ^^^^^^^^^^^ +LL | S2.method_use_assoc_type(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this `Result` may be an `Err` variant, which should be handled help: use `let _ = ...` to ignore the resulting value | -LL | let _ = S2.method(); +LL | let _ = S2.method_use_assoc_type(); | +++++++ error: unused `ControlFlow` that must be used --> $DIR/must_use-result-unit-uninhabited.rs:90:5 | -LL | c1(); - | ^^^^ +LL | controlflow_unit(); + | ^^^^^^^^^^^^^^^^^^ | help: use `let _ = ...` to ignore the resulting value | -LL | let _ = c1(); +LL | let _ = controlflow_unit(); | +++++++ error: aborting due to 5 previous errors From 2d95dfd5a93531996b41b210480accd0cb199b73 Mon Sep 17 00:00:00 2001 From: niacdoial Date: Mon, 6 Oct 2025 08:21:34 -0700 Subject: [PATCH 6/7] unused_must_use: Add extra test for types that are still generic --- .../unused/must_use-result-unit-uninhabited.rs | 8 ++++++++ .../unused/must_use-result-unit-uninhabited.stderr | 14 +++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs index d0dd8d2372092..8f63e4a7f8323 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs @@ -91,3 +91,11 @@ fn main() { controlflow_infallible_unit(); controlflow_never(); } + +trait AssocTypeBeforeMonomorphisation { + type Error; + fn generate(&self) -> Result<(), Self::Error>; + fn process(&self) { + self.generate(); //~ ERROR: unused `Result` that must be used + } +} diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr index 90ac44d0c6c6f..31d6f6bcf2bc7 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr @@ -62,5 +62,17 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = controlflow_unit(); | +++++++ -error: aborting due to 5 previous errors +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:99:9 + | +LL | self.generate(); + | ^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = self.generate(); + | +++++++ + +error: aborting due to 6 previous errors From 7aa7ecc98234144dcdde6e2e9326ac806c0f36c3 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 10 Oct 2025 13:13:49 -0700 Subject: [PATCH 7/7] Factor out a helper function to check if a type is uninhabited --- compiler/rustc_lint/src/unused.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 936c67a76a490..cac373b3271a6 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -277,7 +277,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { return Some(MustUsePath::Suppressed); } let parent_mod_did = cx.tcx.parent_module(expr.hir_id).to_def_id(); - if !ty.is_inhabited_from(cx.tcx, parent_mod_did, cx.typing_env()) { + let is_uninhabited = + |t: Ty<'tcx>| !t.is_inhabited_from(cx.tcx, parent_mod_did, cx.typing_env()); + if is_uninhabited(ty) { return Some(MustUsePath::Suppressed); } @@ -295,11 +297,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ty::Adt(def, args) if cx.tcx.is_diagnostic_item(sym::Result, def.did()) && args.type_at(0).is_unit() - && !args.type_at(1).is_inhabited_from( - cx.tcx, - parent_mod_did, - cx.typing_env(), - ) => + && is_uninhabited(args.type_at(1)) => { Some(MustUsePath::Suppressed) } @@ -307,11 +305,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ty::Adt(def, args) if cx.tcx.is_diagnostic_item(sym::ControlFlow, def.did()) && args.type_at(1).is_unit() - && !args.type_at(0).is_inhabited_from( - cx.tcx, - parent_mod_did, - cx.typing_env(), - ) => + && is_uninhabited(args.type_at(0)) => { Some(MustUsePath::Suppressed) }