-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial implementation of
result_large_err
- Loading branch information
Showing
13 changed files
with
401 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
use rustc_errors::Diagnostic; | ||
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_span::{sym, Span}; | ||
use rustc_typeck::hir_ty_to_ty; | ||
|
||
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 super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR}; | ||
|
||
/// The type of the `Err`-variant in a `std::result::Result` returned by the | ||
/// given `FnDecl` | ||
fn result_err_ty<'tcx>( | ||
cx: &LateContext<'tcx>, | ||
decl: &hir::FnDecl<'tcx>, | ||
item_span: Span, | ||
) -> Option<(&'tcx hir::Ty<'tcx>, Ty<'tcx>)> { | ||
if !in_external_macro(cx.sess(), item_span) | ||
&& let hir::FnRetTy::Return(hir_ty) = decl.output | ||
&& let ty = hir_ty_to_ty(cx.tcx, hir_ty) | ||
&& is_type_diagnostic_item(cx, ty, sym::Result) | ||
&& let ty::Adt(_, substs) = ty.kind() | ||
{ | ||
let err_ty = substs.type_at(1); | ||
Some((hir_ty, err_ty)) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) { | ||
if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind | ||
&& let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.span) | ||
{ | ||
if cx.access_levels.is_exported(item.def_id) { | ||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); | ||
check_result_unit_err(cx, err_ty, fn_header_span); | ||
} | ||
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold); | ||
} | ||
} | ||
|
||
pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64) { | ||
// Don't lint if method is a trait's implementation, we can't do anything about those | ||
if let hir::ImplItemKind::Fn(ref sig, _) = item.kind | ||
&& let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.span) | ||
&& trait_ref_of_method(cx, item.def_id).is_none() | ||
{ | ||
if cx.access_levels.is_exported(item.def_id) { | ||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); | ||
check_result_unit_err(cx, err_ty, fn_header_span); | ||
} | ||
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold); | ||
} | ||
} | ||
|
||
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64) { | ||
if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { | ||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); | ||
if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.span) { | ||
if cx.access_levels.is_exported(item.def_id) { | ||
check_result_unit_err(cx, err_ty, fn_header_span); | ||
} | ||
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold); | ||
} | ||
} | ||
} | ||
|
||
fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: Span) { | ||
if err_ty.is_unit() { | ||
span_lint_and_help( | ||
cx, | ||
RESULT_UNIT_ERR, | ||
fn_header_span, | ||
"this returns a `Result<_, ()>`", | ||
None, | ||
"use a custom `Error` type instead", | ||
); | ||
} | ||
} | ||
|
||
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}>`")); | ||
}, | ||
); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.