diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 533ab67053095..511e16358326d 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -259,6 +259,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { Opaque(Box), TraitObject(Box), TupleElement(Vec<(usize, Self)>), + /// `Result` + Result(Box), + /// `ControlFlow` + ControlFlow(Box), Array(Box, u64), /// The root of the unused_closures lint. Closure(Span), @@ -279,11 +283,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let parent_mod_did = cx.tcx.parent_module(expr.hir_id).to_def_id(); 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); - } match *ty.kind() { + _ if is_uninhabited(ty) => Some(MustUsePath::Suppressed), ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => { is_ty_must_use(cx, boxed, expr, span) .map(|inner| MustUsePath::Boxed(Box::new(inner))) @@ -293,21 +295,23 @@ 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<(), !>`). + // Consider `Result` (e.g. `Result<(), !>`) equivalent to `T`. ty::Adt(def, args) if cx.tcx.is_diagnostic_item(sym::Result, def.did()) - && args.type_at(0).is_unit() && is_uninhabited(args.type_at(1)) => { - Some(MustUsePath::Suppressed) + let ok_ty = args.type_at(0); + is_ty_must_use(cx, ok_ty, expr, span).map(Box::new).map(MustUsePath::Result) } - // Suppress warnings on `ControlFlow` (e.g. `ControlFlow`). + // Consider `ControlFlow` (e.g. `ControlFlow`) equivalent to `T`. ty::Adt(def, args) if cx.tcx.is_diagnostic_item(sym::ControlFlow, def.did()) - && args.type_at(1).is_unit() && is_uninhabited(args.type_at(0)) => { - Some(MustUsePath::Suppressed) + let continue_ty = args.type_at(1); + is_ty_must_use(cx, continue_ty, expr, span) + .map(Box::new) + .map(MustUsePath::ControlFlow) } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => { @@ -500,6 +504,32 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } } + MustUsePath::Result(path) => { + let descr_post = + &format!(" in a `Result` with an uninhabited error{descr_post}"); + emit_must_use_untranslated( + cx, + path, + descr_pre, + descr_post, + plural_len, + true, + expr_is_from_block, + ); + } + MustUsePath::ControlFlow(path) => { + let descr_post = + &format!(" in a `ControlFlow` with an uninhabited break {descr_post}"); + emit_must_use_untranslated( + cx, + path, + descr_pre, + descr_post, + plural_len, + true, + expr_is_from_block, + ); + } MustUsePath::Array(path, len) => { let descr_pre = &format!("{descr_pre}array{plural_suffix} of "); emit_must_use_untranslated( 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 8f63e4a7f8323..d1b47374a11b8 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs @@ -7,6 +7,11 @@ use core::ops::{ControlFlow, ControlFlow::Continue}; use dep::{MyUninhabited, MyUninhabitedNonexhaustive}; +#[must_use] +struct MustUse; + +struct Struct; + fn result_unit_unit() -> Result<(), ()> { Ok(()) } @@ -19,6 +24,14 @@ fn result_unit_never() -> Result<(), !> { Ok(()) } +fn result_struct_never() -> Result { + Ok(Struct) +} + +fn result_must_use_never() -> Result { + Ok(MustUse) +} + fn result_unit_myuninhabited() -> Result<(), MyUninhabited> { Ok(()) } @@ -80,6 +93,8 @@ fn main() { result_unit_unit(); //~ ERROR: unused `Result` that must be used result_unit_infallible(); result_unit_never(); + result_must_use_never(); //~ ERROR: unused `MustUse` in a `Result` with an uninhabited error that must be used + result_struct_never(); result_unit_myuninhabited(); result_unit_myuninhabited_nonexhaustive(); //~ ERROR: unused `Result` that must be used result_unit_assoctype(S1); 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 31d6f6bcf2bc7..b4c62c7690b49 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:80:5 + --> $DIR/must_use-result-unit-uninhabited.rs:93:5 | LL | result_unit_unit(); | ^^^^^^^^^^^^^^^^^^ @@ -15,8 +15,14 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = result_unit_unit(); | +++++++ +error: unused `MustUse` in a `Result` with an uninhabited error that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:96:5 + | +LL | result_must_use_never(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:84:5 + --> $DIR/must_use-result-unit-uninhabited.rs:99:5 | LL | result_unit_myuninhabited_nonexhaustive(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +34,7 @@ LL | let _ = result_unit_myuninhabited_nonexhaustive(); | +++++++ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:86:5 + --> $DIR/must_use-result-unit-uninhabited.rs:101:5 | LL | result_unit_assoctype(S2); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +46,7 @@ LL | let _ = result_unit_assoctype(S2); | +++++++ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:88:5 + --> $DIR/must_use-result-unit-uninhabited.rs:103:5 | LL | S2.method_use_assoc_type(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +58,7 @@ LL | let _ = S2.method_use_assoc_type(); | +++++++ error: unused `ControlFlow` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:90:5 + --> $DIR/must_use-result-unit-uninhabited.rs:105:5 | LL | controlflow_unit(); | ^^^^^^^^^^^^^^^^^^ @@ -63,7 +69,7 @@ LL | let _ = controlflow_unit(); | +++++++ error: unused `Result` that must be used - --> $DIR/must_use-result-unit-uninhabited.rs:99:9 + --> $DIR/must_use-result-unit-uninhabited.rs:114:9 | LL | self.generate(); | ^^^^^^^^^^^^^^^ @@ -74,5 +80,5 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = self.generate(); | +++++++ -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors