blob: 9f38460357ba6b5e6924d23103bdb1fe4f9c3141 [file] [log] [blame]
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::implements_trait;
use clippy_utils::{is_expr_used_or_unified, match_def_path, paths};
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_span::{sym, Span};
use super::SEEK_TO_START_INSTEAD_OF_REWIND;
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
recv: &'tcx Expr<'_>,
arg: &'tcx Expr<'_>,
name_span: Span,
) {
// Get receiver type
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
if is_expr_used_or_unified(cx.tcx, expr) {
return;
}
if let Some(seek_trait_id) = cx.tcx.get_diagnostic_item(sym::IoSeek)
&& implements_trait(cx, ty, seek_trait_id, &[])
&& let ExprKind::Call(func, args1) = arg.kind
&& let ExprKind::Path(ref path) = func.kind
&& let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
&& match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START)
&& args1.len() == 1
&& let ExprKind::Lit(lit) = args1[0].kind
&& let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
{
let method_call_span = expr.span.with_lo(name_span.lo());
span_lint_and_then(
cx,
SEEK_TO_START_INSTEAD_OF_REWIND,
method_call_span,
"used `seek` to go to the start of the stream",
|diag| {
let app = Applicability::MachineApplicable;
diag.span_suggestion(method_call_span, "replace with", "rewind()", app);
},
);
}
}