use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::BinOpKind;
use rustc_hir::{BorrowKind, Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::map::Map;
+use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
declare_clippy_lint! {
- /// **What it does:**
+ /// ### What it does
/// Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using
/// the pattern's length.
///
- /// **Why is this bad?**
+ /// ### Why is this bad?
/// Using `str:strip_{prefix,suffix}` is safer and may have better performance as there is no
/// slicing which may panic and the compiler does not need to insert this panic code. It is
/// also sometimes more readable as it removes the need for duplicating or storing the pattern
/// used by `str::{starts,ends}_with` and in the slicing.
///
- /// **Known problems:**
- /// None.
- ///
- /// **Example:**
- ///
+ /// ### Example
/// ```rust
/// let s = "hello, world!";
/// if s.starts_with("hello, ") {
/// assert_eq!(end.to_uppercase(), "WORLD!");
/// }
/// ```
+ #[clippy::version = "1.48.0"]
pub MANUAL_STRIP,
complexity,
"suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing"
impl<'tcx> LateLintPass<'tcx> for ManualStrip {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if !meets_msrv(self.msrv.as_ref(), &msrvs::STR_STRIP_PREFIX) {
+ if !meets_msrv(self.msrv, msrvs::STR_STRIP_PREFIX) {
return;
}
if_chain! {
- if let ExprKind::If(cond, then, _) = &expr.kind;
- if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind;
+ if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr);
+ if let ExprKind::MethodCall(_, [target_arg, pattern], _) = cond.kind;
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id);
if let ExprKind::Path(target_path) = &target_arg.kind;
then {
// Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
if_chain! {
- if let ExprKind::MethodCall(_, _, [arg], _) = expr.kind;
+ if let ExprKind::MethodCall(_, [arg], _) = expr.kind;
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if match_def_path(cx, method_def_id, &paths::STR_LEN);
then {
}
impl<'a, 'tcx> Visitor<'tcx> for StrippingFinder<'a, 'tcx> {
- type Map = Map<'tcx>;
- fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
- NestedVisitorMap::None
- }
-
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
if_chain! {
if is_ref_str(self.cx, ex);
let unref = peel_ref(ex);
if let ExprKind::Index(indexed, index) = &unref.kind;
- if let Some(higher::Range { start, end, .. }) = higher::range(index);
+ if let Some(higher::Range { start, end, .. }) = higher::Range::hir(index);
if let ExprKind::Path(path) = &indexed.kind;
if self.cx.qpath_res(path, ex.hir_id) == self.target;
then {