Refactoring to use `constant_context

Use `constant_context`, `.is_str()` and `builtin_index()` to simplify.
This commit is contained in:
Takayuki Nakata 2020-07-14 00:11:10 +09:00
parent 780a4c87de
commit f2419b9d62

View File

@ -1,12 +1,9 @@
use crate::consts::{miri_to_const, Constant};
use crate::consts::{constant_context, Constant};
use crate::utils::{in_macro, is_type_diagnostic_item, snippet, span_lint_and_sugg, walk_ptrs_ty};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! {
@ -44,10 +41,11 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
if_chain! {
if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
if path.ident.name == sym!(repeat);
if is_once(cx, &args[1]) && !in_macro(args[0].span);
if let Some(Constant::Int(1)) = constant_context(cx, cx.tables()).expr(&args[1]);
if !in_macro(args[0].span);
then {
let ty = walk_ptrs_ty(cx.tables().expr_ty(&args[0]));
if is_str(ty){
if ty.is_str() {
span_lint_and_sugg(
cx,
REPEAT_ONCE,
@ -57,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
format!("{}.to_string()", snippet(cx, args[0].span, r#""...""#)),
Applicability::MachineApplicable,
);
} else if is_slice(ty) {
} else if let Some(_) = ty.builtin_index() {
span_lint_and_sugg(
cx,
REPEAT_ONCE,
@ -82,45 +80,3 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
}
}
}
fn is_once<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> bool {
match expr.kind {
ExprKind::Lit(ref lit) => {
if let LitKind::Int(ref lit_content, _) = lit.node {
*lit_content == 1
} else {
false
}
},
ExprKind::Path(rustc_hir::QPath::Resolved(None, path)) => {
if let Res::Def(DefKind::Const, def_id) = path.res {
let ty = cx.tcx.type_of(def_id);
let con = cx
.tcx
.const_eval_poly(def_id)
.ok()
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty))
.unwrap();
let con = miri_to_const(con);
con == Some(Constant::Int(1))
} else {
false
}
},
_ => false,
}
}
fn is_str(ty: Ty<'_>) -> bool {
match ty.kind {
ty::Str => true,
_ => false,
}
}
fn is_slice(ty: Ty<'_>) -> bool {
match ty.kind {
ty::Slice(..) | ty::Array(..) => true,
_ => false,
}
}