Skip to content
Closed
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
13 changes: 13 additions & 0 deletions compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
is_ty_must_use(cx, pinned_ty, expr, span)
.map(|inner| MustUsePath::Pinned(Box::new(inner)))
}
ty::Adt(def, args)
// Do not warn against `Result<T, !>` (or in general when `E` is uninhabitted)
// being unused, unless `T` must be used.
if cx.tcx.is_diagnostic_item(sym::Result, def.did())
&& !args.type_at(1).is_inhabited_from(
cx.tcx,
cx.tcx.parent_module(expr.hir_id).to_def_id(),
cx.typing_env(),
) =>
{
is_ty_must_use(cx, args.type_at(0), expr, span)
}

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())
Expand Down
31 changes: 31 additions & 0 deletions tests/ui/lint/unused/must-use-uninhabited-result-e.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// This test checks for uninhabited error type in a result interacts with must
// use lint. Ideally we don't want to lint on `Result<T, !>` as something that
// must be used, because it's equivalent to `T`. However, we need to make sure
// that if there are other reasons for the lint, we still emit it.
//
// See also: <https://github.com/rust-lang/rust/issues/65861>.
//
//@ aux-build:../../../pattern/usefulness/auxiliary/empty.rs
//@ check-pass
#![warn(unused)]
#![feature(never_type)]

extern crate empty;

fn main() {
Ok::<_, std::convert::Infallible>(());
Ok::<_, empty::EmptyForeignEnum>(());
Ok::<_, empty::VisiblyUninhabitedForeignStruct>(());
Ok::<_, empty::SecretlyUninhabitedForeignStruct>(()); //~ warn: unused `Result` that must be used
Ok::<_, !>(());

Ok::<_, !>(Important); //~ warn: unused `Important` that must be used

very_important(); //~ warn: unused return value of `very_important` that must be used
}

#[must_use]
struct Important;

#[must_use]
fn very_important() -> Result<(), !> { Ok(()) }
42 changes: 42 additions & 0 deletions tests/ui/lint/unused/must-use-uninhabited-result-e.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
warning: unused `Result` that must be used
--> $DIR/must-use-uninhabited-result-e.rs:19:5
|
LL | Ok::<_, empty::SecretlyUninhabitedForeignStruct>(());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this `Result` may be an `Err` variant, which should be handled
note: the lint level is defined here
--> $DIR/must-use-uninhabited-result-e.rs:10:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_must_use)]` implied by `#[warn(unused)]`
help: use `let _ = ...` to ignore the resulting value
|
LL | let _ = Ok::<_, empty::SecretlyUninhabitedForeignStruct>(());
| +++++++

warning: unused `Important` that must be used
--> $DIR/must-use-uninhabited-result-e.rs:22:5
|
LL | Ok::<_, !>(Important);
| ^^^^^^^^^^^^^^^^^^^^^
|
help: use `let _ = ...` to ignore the resulting value
|
LL | let _ = Ok::<_, !>(Important);
| +++++++

warning: unused return value of `very_important` that must be used
--> $DIR/must-use-uninhabited-result-e.rs:24:5
|
LL | very_important();
| ^^^^^^^^^^^^^^^^
|
help: use `let _ = ...` to ignore the resulting value
|
LL | let _ = very_important();
| +++++++

warning: 3 warnings emitted

Loading