Skip to content

Commit 226f135

Browse files
committed
Move PathBufPushOverwrite into Methods lint group
1 parent 0cc01ce commit 226f135

File tree

6 files changed

+76
-76
lines changed

6 files changed

+76
-76
lines changed

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ store.register_lints(&[
344344
methods::OPTION_MAP_OR_NONE,
345345
methods::OR_FUN_CALL,
346346
methods::OR_THEN_UNWRAP,
347+
methods::PATH_BUF_PUSH_OVERWRITE,
347348
methods::RESULT_MAP_OR_INTO_OPTION,
348349
methods::SEARCH_IS_SOME,
349350
methods::SHOULD_IMPLEMENT_TRAIT,
@@ -460,7 +461,6 @@ store.register_lints(&[
460461
partialeq_to_none::PARTIALEQ_TO_NONE,
461462
pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE,
462463
pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF,
463-
path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE,
464464
pattern_type_mismatch::PATTERN_TYPE_MISMATCH,
465465
precedence::PRECEDENCE,
466466
ptr::CMP_NULL,

clippy_lints/src/lib.register_nursery.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
1717
LintId::of(methods::ITER_ON_EMPTY_COLLECTIONS),
1818
LintId::of(methods::ITER_ON_SINGLE_ITEMS),
1919
LintId::of(methods::ITER_WITH_DRAIN),
20+
LintId::of(methods::PATH_BUF_PUSH_OVERWRITE),
2021
LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
2122
LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
2223
LintId::of(mutex_atomic::MUTEX_ATOMIC),
@@ -25,7 +26,6 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
2526
LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
2627
LintId::of(only_used_in_recursion::ONLY_USED_IN_RECURSION),
2728
LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
28-
LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
2929
LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
3030
LintId::of(regex::TRIVIAL_REGEX),
3131
LintId::of(strings::STRING_LIT_AS_BYTES),

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,6 @@ mod panic_unimplemented;
324324
mod partialeq_ne_impl;
325325
mod partialeq_to_none;
326326
mod pass_by_ref_or_value;
327-
mod path_buf_push_overwrite;
328327
mod pattern_type_mismatch;
329328
mod precedence;
330329
mod ptr;
@@ -727,7 +726,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
727726
store.register_late_pass(|| Box::new(assertions_on_constants::AssertionsOnConstants));
728727
store.register_late_pass(|| Box::new(assertions_on_result_states::AssertionsOnResultStates));
729728
store.register_late_pass(|| Box::new(transmuting_null::TransmutingNull));
730-
store.register_late_pass(|| Box::new(path_buf_push_overwrite::PathBufPushOverwrite));
731729
store.register_late_pass(|| Box::new(inherent_to_string::InherentToString));
732730
let max_trait_bounds = conf.max_trait_bounds;
733731
store.register_late_pass(move || Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));

clippy_lints/src/methods/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ mod option_map_or_none;
6363
mod option_map_unwrap_or;
6464
mod or_fun_call;
6565
mod or_then_unwrap;
66+
mod path_buf_push_overwrite;
6667
mod search_is_some;
6768
mod single_char_add_str;
6869
mod single_char_insert_string;
@@ -2701,6 +2702,38 @@ declare_clippy_lint! {
27012702
"nonsensical combination of options for opening a file"
27022703
}
27032704

2705+
declare_clippy_lint! {
2706+
/// ### What it does
2707+
///* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push)
2708+
/// calls on `PathBuf` that can cause overwrites.
2709+
///
2710+
/// ### Why is this bad?
2711+
/// Calling `push` with a root path at the start can overwrite the
2712+
/// previous defined path.
2713+
///
2714+
/// ### Example
2715+
/// ```rust
2716+
/// use std::path::PathBuf;
2717+
///
2718+
/// let mut x = PathBuf::from("/foo");
2719+
/// x.push("/bar");
2720+
/// assert_eq!(x, PathBuf::from("/bar"));
2721+
/// ```
2722+
/// Could be written:
2723+
///
2724+
/// ```rust
2725+
/// use std::path::PathBuf;
2726+
///
2727+
/// let mut x = PathBuf::from("/foo");
2728+
/// x.push("bar");
2729+
/// assert_eq!(x, PathBuf::from("/foo/bar"));
2730+
/// ```
2731+
#[clippy::version = "1.36.0"]
2732+
pub PATH_BUF_PUSH_OVERWRITE,
2733+
nursery,
2734+
"calling `push` with file system root on `PathBuf` can overwrite it"
2735+
}
2736+
27042737
pub struct Methods {
27052738
avoid_breaking_exported_api: bool,
27062739
msrv: Option<RustcVersion>,
@@ -2814,6 +2847,7 @@ impl_lint_pass!(Methods => [
28142847
MAP_ERR_IGNORE,
28152848
MUT_MUTEX_LOCK,
28162849
NONSENSICAL_OPEN_OPTIONS,
2850+
PATH_BUF_PUSH_OVERWRITE,
28172851
]);
28182852

28192853
/// Extracts a method call name, args, and `Span` of the method name.
@@ -3199,6 +3233,9 @@ impl Methods {
31993233
unnecessary_lazy_eval::check(cx, expr, recv, arg, "or");
32003234
}
32013235
},
3236+
("push", [arg]) => {
3237+
path_buf_push_overwrite::check(cx, expr, arg);
3238+
},
32023239
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
32033240
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
32043241
suspicious_splitn::check(cx, name, expr, recv, count);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::ty::is_type_diagnostic_item;
3+
use if_chain::if_chain;
4+
use rustc_ast::ast::LitKind;
5+
use rustc_errors::Applicability;
6+
use rustc_hir::{Expr, ExprKind};
7+
use rustc_lint::LateContext;
8+
use rustc_span::symbol::sym;
9+
use std::path::{Component, Path};
10+
11+
use super::PATH_BUF_PUSH_OVERWRITE;
12+
13+
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) {
14+
if_chain! {
15+
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
16+
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
17+
if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::PathBuf);
18+
if let ExprKind::Lit(ref lit) = arg.kind;
19+
if let LitKind::Str(ref path_lit, _) = lit.node;
20+
if let pushed_path = Path::new(path_lit.as_str());
21+
if let Some(pushed_path_lit) = pushed_path.to_str();
22+
if pushed_path.has_root();
23+
if let Some(root) = pushed_path.components().next();
24+
if root == Component::RootDir;
25+
then {
26+
span_lint_and_sugg(
27+
cx,
28+
PATH_BUF_PUSH_OVERWRITE,
29+
lit.span,
30+
"calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition",
31+
"try",
32+
format!("\"{}\"", pushed_path_lit.trim_start_matches(|c| c == '/' || c == '\\')),
33+
Applicability::MachineApplicable,
34+
);
35+
}
36+
}
37+
}

clippy_lints/src/path_buf_push_overwrite.rs

Lines changed: 0 additions & 72 deletions
This file was deleted.

0 commit comments

Comments
 (0)