]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/clippy/clippy_lints/src/functions/result.rs
Merge commit 'f4850f7292efa33759b4f7f9b7621268979e9914' into clippyup
[rust.git] / src / tools / clippy / clippy_lints / src / functions / result.rs
index 5c63fb2acb117f08f729c1658edcd6ff9041aa4e..f7e30b051a694a84d6be001e103f067a804d58b7 100644 (file)
@@ -2,12 +2,12 @@
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Adt, Ty};
 use rustc_span::{sym, Span};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
-use clippy_utils::ty::{approx_ty_size, is_type_diagnostic_item};
+use clippy_utils::ty::{approx_ty_size, is_type_diagnostic_item, AdtVariantInfo};
 
 use super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR};
 
@@ -84,17 +84,57 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S
 }
 
 fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) {
-    let ty_size = approx_ty_size(cx, err_ty);
-    if ty_size >= large_err_threshold {
-        span_lint_and_then(
-            cx,
-            RESULT_LARGE_ERR,
-            hir_ty_span,
-            "the `Err`-variant returned from this function is very large",
-            |diag: &mut Diagnostic| {
-                diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes"));
-                diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
-            },
-        );
+    if_chain! {
+        if let Adt(adt, subst) = err_ty.kind();
+        if let Some(local_def_id) = err_ty.ty_adt_def().expect("already checked this is adt").did().as_local();
+        if let Some(hir::Node::Item(item)) = cx
+            .tcx
+            .hir()
+            .find_by_def_id(local_def_id);
+        if let hir::ItemKind::Enum(ref def, _) = item.kind;
+        then {
+            let variants_size = AdtVariantInfo::new(cx, *adt, subst);
+            if variants_size[0].size >= large_err_threshold {
+                span_lint_and_then(
+                    cx,
+                    RESULT_LARGE_ERR,
+                    hir_ty_span,
+                    "the `Err`-variant returned from this function is very large",
+                    |diag| {
+                        diag.span_label(
+                            def.variants[variants_size[0].ind].span,
+                            format!("the largest variant contains at least {} bytes", variants_size[0].size),
+                        );
+
+                        for variant in &variants_size[1..] {
+                            if variant.size >= large_err_threshold {
+                                let variant_def = &def.variants[variant.ind];
+                                diag.span_label(
+                                    variant_def.span,
+                                    format!("the variant `{}` contains at least {} bytes", variant_def.ident, variant.size),
+                                );
+                            }
+                        }
+
+                        diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
+                    }
+                );
+            }
+        }
+        else {
+            let ty_size = approx_ty_size(cx, err_ty);
+            if ty_size >= large_err_threshold {
+                span_lint_and_then(
+                    cx,
+                    RESULT_LARGE_ERR,
+                    hir_ty_span,
+                    "the `Err`-variant returned from this function is very large",
+                    |diag: &mut Diagnostic| {
+                        diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes"));
+                        diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
+                    },
+                );
+            }
+        }
     }
 }