Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 39 additions & 9 deletions compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
Opaque(Box<Self>),
TraitObject(Box<Self>),
TupleElement(Vec<(usize, Self)>),
/// `Result<T, Uninhabited>`
Result(Box<Self>),
/// `ControlFlow<Uninhabited, T>`
ControlFlow(Box<Self>),
Array(Box<Self>, u64),
/// The root of the unused_closures lint.
Closure(Span),
Expand All @@ -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)))
Expand All @@ -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<T, Uninhabited>` (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<Uninhabited, ()>` (e.g. `ControlFlow<!, ()>`).
// Consider `ControlFlow<Uninhabited, T>` (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, .. }) => {
Expand Down Expand Up @@ -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(
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/lint/unused/must_use-result-unit-uninhabited.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand All @@ -19,6 +24,14 @@ fn result_unit_never() -> Result<(), !> {
Ok(())
}

fn result_struct_never() -> Result<Struct, !> {
Ok(Struct)
}

fn result_must_use_never() -> Result<MustUse, !> {
Ok(MustUse)
}

fn result_unit_myuninhabited() -> Result<(), MyUninhabited> {
Ok(())
}
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 13 additions & 7 deletions tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr
Original file line number Diff line number Diff line change
@@ -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();
| ^^^^^^^^^^^^^^^^^^
Expand All @@ -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();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -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);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -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();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -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();
| ^^^^^^^^^^^^^^^^^^
Expand All @@ -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();
| ^^^^^^^^^^^^^^^
Expand All @@ -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

Loading