about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-02 19:02:47 +0000
committerbors <bors@rust-lang.org>2023-08-02 19:02:47 +0000
commit7af5ea14fc9a68037ec695e992559ac93e5f98a5 (patch)
tree6f0eb3f95fab6bcc3449e30189d65580ed4f10b3
parent78f5e0d3ec539675941e80fd7ce9468c39f0e4b6 (diff)
parent71c54137eadc730d01fe15c17df8bf3ba5d3b04b (diff)
downloadrust-7af5ea14fc9a68037ec695e992559ac93e5f98a5.tar.gz
rust-7af5ea14fc9a68037ec695e992559ac93e5f98a5.zip
Auto merge of #11252 - Centri3:#11245, r=xFrednet
[`unwrap_used`]: Do not lint unwrapping on `!` or never-like enums

Fixes #11245

changelog: [`unwrap_used`]: Do not lint unwrapping on `!` or never-like enums
changelog: [`expect_used`]: Do not lint unwrapping on `!` or never-like enums
-rw-r--r--clippy_lints/src/methods/expect_used.rs44
-rw-r--r--clippy_lints/src/methods/mod.rs39
-rw-r--r--clippy_lints/src/methods/unwrap_expect_used.rs83
-rw-r--r--clippy_lints/src/methods/unwrap_used.rs53
-rw-r--r--clippy_utils/src/ty.rs5
-rw-r--r--tests/ui-toml/expect_used/expect_used.stderr4
-rw-r--r--tests/ui-toml/unwrap_used/unwrap_used.stderr39
-rw-r--r--tests/ui/expect.stderr6
-rw-r--r--tests/ui/get_unwrap.stderr39
-rw-r--r--tests/ui/unwrap.stderr9
-rw-r--r--tests/ui/unwrap_expect_used.rs11
-rw-r--r--tests/ui/unwrap_expect_used.stderr24
12 files changed, 207 insertions, 149 deletions
diff --git a/clippy_lints/src/methods/expect_used.rs b/clippy_lints/src/methods/expect_used.rs
deleted file mode 100644
index 614610335a1..00000000000
--- a/clippy_lints/src/methods/expect_used.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_in_cfg_test, is_in_test_function};
-use rustc_hir as hir;
-use rustc_lint::LateContext;
-use rustc_span::sym;
-
-use super::EXPECT_USED;
-
-/// lint use of `expect()` or `expect_err` for `Result` and `expect()` for `Option`.
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    recv: &hir::Expr<'_>,
-    is_err: bool,
-    allow_expect_in_tests: bool,
-) {
-    let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
-
-    let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) && !is_err {
-        Some((EXPECT_USED, "an `Option`", "None", ""))
-    } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) {
-        Some((EXPECT_USED, "a `Result`", if is_err { "Ok" } else { "Err" }, "an "))
-    } else {
-        None
-    };
-
-    let method = if is_err { "expect_err" } else { "expect" };
-
-    if allow_expect_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
-        return;
-    }
-
-    if let Some((lint, kind, none_value, none_prefix)) = mess {
-        span_lint_and_help(
-            cx,
-            lint,
-            expr.span,
-            &format!("used `{method}()` on {kind} value"),
-            None,
-            &format!("if this value is {none_prefix}`{none_value}`, it will panic"),
-        );
-    }
-}
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 62d565bcc5c..17483656cec 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -17,7 +17,6 @@ mod collapsible_str_replace;
 mod drain_collect;
 mod err_expect;
 mod expect_fun_call;
-mod expect_used;
 mod extend_with_drain;
 mod filetype_is_file;
 mod filter_map;
@@ -105,7 +104,7 @@ mod unnecessary_lazy_eval;
 mod unnecessary_literal_unwrap;
 mod unnecessary_sort_by;
 mod unnecessary_to_owned;
-mod unwrap_used;
+mod unwrap_expect_used;
 mod useless_asref;
 mod utils;
 mod vec_resize_to_zero;
@@ -3948,13 +3947,27 @@ impl Methods {
                     match method_call(recv) {
                         Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv),
                         Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv),
-                        _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
+                        _ => unwrap_expect_used::check(
+                            cx,
+                            expr,
+                            recv,
+                            false,
+                            self.allow_expect_in_tests,
+                            unwrap_expect_used::Variant::Expect,
+                        ),
                     }
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                 },
                 ("expect_err", [_]) => {
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
-                    expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests);
+                    unwrap_expect_used::check(
+                        cx,
+                        expr,
+                        recv,
+                        true,
+                        self.allow_expect_in_tests,
+                        unwrap_expect_used::Variant::Expect,
+                    );
                 },
                 ("extend", [arg]) => {
                     string_extend_chars::check(cx, expr, recv, arg);
@@ -4180,11 +4193,25 @@ impl Methods {
                         _ => {},
                     }
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
-                    unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests);
+                    unwrap_expect_used::check(
+                        cx,
+                        expr,
+                        recv,
+                        false,
+                        self.allow_unwrap_in_tests,
+                        unwrap_expect_used::Variant::Unwrap,
+                    );
                 },
                 ("unwrap_err", []) => {
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
-                    unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests);
+                    unwrap_expect_used::check(
+                        cx,
+                        expr,
+                        recv,
+                        true,
+                        self.allow_unwrap_in_tests,
+                        unwrap_expect_used::Variant::Unwrap,
+                    );
                 },
                 ("unwrap_or", [u_arg]) => {
                     match method_call(recv) {
diff --git a/clippy_lints/src/methods/unwrap_expect_used.rs b/clippy_lints/src/methods/unwrap_expect_used.rs
new file mode 100644
index 00000000000..7bd16b473ce
--- /dev/null
+++ b/clippy_lints/src/methods/unwrap_expect_used.rs
@@ -0,0 +1,83 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::{is_never_like, is_type_diagnostic_item};
+use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, Lint};
+use rustc_middle::ty;
+use rustc_span::sym;
+
+use super::{EXPECT_USED, UNWRAP_USED};
+
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub(super) enum Variant {
+    Unwrap,
+    Expect,
+}
+
+impl Variant {
+    fn method_name(self, is_err: bool) -> &'static str {
+        match (self, is_err) {
+            (Variant::Unwrap, true) => "unwrap_err",
+            (Variant::Unwrap, false) => "unwrap",
+            (Variant::Expect, true) => "expect_err",
+            (Variant::Expect, false) => "expect",
+        }
+    }
+
+    fn lint(self) -> &'static Lint {
+        match self {
+            Variant::Unwrap => UNWRAP_USED,
+            Variant::Expect => EXPECT_USED,
+        }
+    }
+}
+
+/// Lint usage of `unwrap` or `unwrap_err` for `Result` and `unwrap()` for `Option` (and their
+/// `expect` counterparts).
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    recv: &Expr<'_>,
+    is_err: bool,
+    allow_unwrap_in_tests: bool,
+    variant: Variant,
+) {
+    let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+
+    let (kind, none_value, none_prefix) = if is_type_diagnostic_item(cx, ty, sym::Option) && !is_err {
+        ("an `Option`", "None", "")
+    } else if is_type_diagnostic_item(cx, ty, sym::Result)
+        && let ty::Adt(_, substs) = ty.kind()
+        && let Some(t_or_e_ty) = substs[usize::from(!is_err)].as_type()
+    {
+        if is_never_like(t_or_e_ty) {
+            return;
+        }
+
+        ("a `Result`", if is_err { "Ok" } else { "Err" }, "an ")
+    } else {
+        return;
+    };
+
+    let method_suffix = if is_err { "_err" } else { "" };
+
+    if allow_unwrap_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
+        return;
+    }
+
+    span_lint_and_then(
+        cx,
+        variant.lint(),
+        expr.span,
+        &format!("used `{}()` on {kind} value", variant.method_name(is_err)),
+        |diag| {
+            diag.note(format!("if this value is {none_prefix}`{none_value}`, it will panic"));
+
+            if variant == Variant::Unwrap && is_lint_allowed(cx, EXPECT_USED, expr.hir_id) {
+                diag.help(format!(
+                    "consider using `expect{method_suffix}()` to provide a better panic message"
+                ));
+            }
+        },
+    );
+}
diff --git a/clippy_lints/src/methods/unwrap_used.rs b/clippy_lints/src/methods/unwrap_used.rs
deleted file mode 100644
index 5e4c3daee64..00000000000
--- a/clippy_lints/src/methods/unwrap_used.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
-use rustc_hir as hir;
-use rustc_lint::LateContext;
-use rustc_span::sym;
-
-use super::{EXPECT_USED, UNWRAP_USED};
-
-/// lint use of `unwrap()` or `unwrap_err` for `Result` and `unwrap()` for `Option`.
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    recv: &hir::Expr<'_>,
-    is_err: bool,
-    allow_unwrap_in_tests: bool,
-) {
-    let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
-
-    let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) && !is_err {
-        Some((UNWRAP_USED, "an `Option`", "None", ""))
-    } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) {
-        Some((UNWRAP_USED, "a `Result`", if is_err { "Ok" } else { "Err" }, "an "))
-    } else {
-        None
-    };
-
-    let method_suffix = if is_err { "_err" } else { "" };
-
-    if allow_unwrap_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
-        return;
-    }
-
-    if let Some((lint, kind, none_value, none_prefix)) = mess {
-        let help = if is_lint_allowed(cx, EXPECT_USED, expr.hir_id) {
-            format!(
-                "if you don't want to handle the `{none_value}` case gracefully, consider \
-                using `expect{method_suffix}()` to provide a better panic message"
-            )
-        } else {
-            format!("if this value is {none_prefix}`{none_value}`, it will panic")
-        };
-
-        span_lint_and_help(
-            cx,
-            lint,
-            expr.span,
-            &format!("used `unwrap{method_suffix}()` on {kind} value"),
-            None,
-            &help,
-        );
-    }
-}
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index d0e15aa8bb3..98e163abc58 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -1093,6 +1093,11 @@ fn assert_generic_args_match<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, args: &[Generi
     }
 }
 
+/// Returns whether `ty` is never-like; i.e., `!` (never) or an enum with zero variants.
+pub fn is_never_like(ty: Ty<'_>) -> bool {
+    ty.is_never() || (ty.is_enum() && ty.ty_adt_def().is_some_and(|def| def.variants().is_empty()))
+}
+
 /// Makes the projection type for the named associated type in the given impl or trait impl.
 ///
 /// This function is for associated types which are "known" to exist, and as such, will only return
diff --git a/tests/ui-toml/expect_used/expect_used.stderr b/tests/ui-toml/expect_used/expect_used.stderr
index 9eef0e1bfaa..815d009350f 100644
--- a/tests/ui-toml/expect_used/expect_used.stderr
+++ b/tests/ui-toml/expect_used/expect_used.stderr
@@ -4,7 +4,7 @@ error: used `expect()` on an `Option` value
 LL |     let _ = opt.expect("");
    |             ^^^^^^^^^^^^^^
    |
-   = help: if this value is `None`, it will panic
+   = note: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `expect()` on a `Result` value
@@ -13,7 +13,7 @@ error: used `expect()` on a `Result` value
 LL |     let _ = res.expect("");
    |             ^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Err`, it will panic
+   = note: if this value is an `Err`, it will panic
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui-toml/unwrap_used/unwrap_used.stderr b/tests/ui-toml/unwrap_used/unwrap_used.stderr
index 4c9bdfa9dba..10219beaf97 100644
--- a/tests/ui-toml/unwrap_used/unwrap_used.stderr
+++ b/tests/ui-toml/unwrap_used/unwrap_used.stderr
@@ -12,7 +12,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = boxed_slice.get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
@@ -27,7 +28,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:40:17
@@ -41,7 +43,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:41:17
@@ -55,7 +58,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:42:17
@@ -69,7 +73,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:43:17
@@ -83,7 +88,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:47:21
@@ -97,7 +103,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:52:9
@@ -111,7 +118,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:53:9
@@ -125,7 +133,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:54:9
@@ -139,7 +148,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:55:9
@@ -153,7 +163,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:67:17
@@ -167,7 +178,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:68:17
@@ -181,7 +193,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:75:13
diff --git a/tests/ui/expect.stderr b/tests/ui/expect.stderr
index be340340d47..f787fa973a3 100644
--- a/tests/ui/expect.stderr
+++ b/tests/ui/expect.stderr
@@ -4,7 +4,7 @@ error: used `expect()` on an `Option` value
 LL |     let _ = opt.expect("");
    |             ^^^^^^^^^^^^^^
    |
-   = help: if this value is `None`, it will panic
+   = note: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `expect()` on a `Result` value
@@ -13,7 +13,7 @@ error: used `expect()` on a `Result` value
 LL |     let _ = res.expect("");
    |             ^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Err`, it will panic
+   = note: if this value is an `Err`, it will panic
 
 error: used `expect_err()` on a `Result` value
   --> $DIR/expect.rs:12:13
@@ -21,7 +21,7 @@ error: used `expect_err()` on a `Result` value
 LL |     let _ = res.expect_err("");
    |             ^^^^^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Ok`, it will panic
+   = note: if this value is an `Ok`, it will panic
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr
index c567ed319b5..19dc9071fe7 100644
--- a/tests/ui/get_unwrap.stderr
+++ b/tests/ui/get_unwrap.stderr
@@ -16,7 +16,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = boxed_slice.get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
@@ -31,7 +32,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:40:17
@@ -45,7 +47,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:41:17
@@ -59,7 +62,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:42:17
@@ -73,7 +77,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:43:17
@@ -87,7 +92,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:47:21
@@ -101,7 +107,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:52:9
@@ -115,7 +122,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:53:9
@@ -129,7 +137,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:54:9
@@ -143,7 +152,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:55:9
@@ -157,7 +167,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:67:17
@@ -171,7 +182,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:68:17
@@ -185,7 +197,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:78:24
diff --git a/tests/ui/unwrap.stderr b/tests/ui/unwrap.stderr
index 3796d942ff9..41db819f6fb 100644
--- a/tests/ui/unwrap.stderr
+++ b/tests/ui/unwrap.stderr
@@ -4,7 +4,8 @@ error: used `unwrap()` on an `Option` value
 LL |     let _ = opt.unwrap();
    |             ^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: used `unwrap()` on a `Result` value
@@ -13,7 +14,8 @@ error: used `unwrap()` on a `Result` value
 LL |     let _ = res.unwrap();
    |             ^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is an `Err`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: used `unwrap_err()` on a `Result` value
   --> $DIR/unwrap.rs:12:13
@@ -21,7 +23,8 @@ error: used `unwrap_err()` on a `Result` value
 LL |     let _ = res.unwrap_err();
    |             ^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `Ok` case gracefully, consider using `expect_err()` to provide a better panic message
+   = note: if this value is an `Ok`, it will panic
+   = help: consider using `expect_err()` to provide a better panic message
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/unwrap_expect_used.rs b/tests/ui/unwrap_expect_used.rs
index 7f57efc53c9..26f92ccdefa 100644
--- a/tests/ui/unwrap_expect_used.rs
+++ b/tests/ui/unwrap_expect_used.rs
@@ -1,5 +1,8 @@
 #![warn(clippy::unwrap_used, clippy::expect_used)]
 #![allow(clippy::unnecessary_literal_unwrap)]
+#![feature(never_type)]
+
+use std::convert::Infallible;
 
 trait OptionExt {
     type Item;
@@ -28,6 +31,14 @@ fn main() {
     Some(3).unwrap_err();
     Some(3).expect_err("Hellow none!");
 
+    // Issue #11245: The `Err` variant can never be constructed so do not lint this.
+    let x: Result<(), !> = Ok(());
+    x.unwrap();
+    x.expect("is `!` (never)");
+    let x: Result<(), Infallible> = Ok(());
+    x.unwrap();
+    x.expect("is never-like (0 variants)");
+
     let a: Result<i32, i32> = Ok(3);
     a.unwrap();
     a.expect("Hello world!");
diff --git a/tests/ui/unwrap_expect_used.stderr b/tests/ui/unwrap_expect_used.stderr
index 1a551ab5ab8..f66e47612ad 100644
--- a/tests/ui/unwrap_expect_used.stderr
+++ b/tests/ui/unwrap_expect_used.stderr
@@ -1,52 +1,52 @@
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_expect_used.rs:24:5
+  --> $DIR/unwrap_expect_used.rs:27:5
    |
 LL |     Some(3).unwrap();
    |     ^^^^^^^^^^^^^^^^
    |
-   = help: if this value is `None`, it will panic
+   = note: if this value is `None`, it will panic
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: used `expect()` on an `Option` value
-  --> $DIR/unwrap_expect_used.rs:25:5
+  --> $DIR/unwrap_expect_used.rs:28:5
    |
 LL |     Some(3).expect("Hello world!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if this value is `None`, it will panic
+   = note: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `unwrap()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:32:5
+  --> $DIR/unwrap_expect_used.rs:43:5
    |
 LL |     a.unwrap();
    |     ^^^^^^^^^^
    |
-   = help: if this value is an `Err`, it will panic
+   = note: if this value is an `Err`, it will panic
 
 error: used `expect()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:33:5
+  --> $DIR/unwrap_expect_used.rs:44:5
    |
 LL |     a.expect("Hello world!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Err`, it will panic
+   = note: if this value is an `Err`, it will panic
 
 error: used `unwrap_err()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:34:5
+  --> $DIR/unwrap_expect_used.rs:45:5
    |
 LL |     a.unwrap_err();
    |     ^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Ok`, it will panic
+   = note: if this value is an `Ok`, it will panic
 
 error: used `expect_err()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:35:5
+  --> $DIR/unwrap_expect_used.rs:46:5
    |
 LL |     a.expect_err("Hello error!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Ok`, it will panic
+   = note: if this value is an `Ok`, it will panic
 
 error: aborting due to 6 previous errors