Skip to content

Commit 0492671

Browse files
Fix join_absolute_paths to work correctly depending on the platform (rust-lang#16610)
Fixes rust-lang#16607. changelog: [`join_absolute_paths`]: remove both backslashes for calls to `Path::join`.
2 parents ea45686 + f2a134b commit 0492671

File tree

5 files changed

+143
-27
lines changed

5 files changed

+143
-27
lines changed

clippy_lints/src/methods/join_absolute_paths.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::expr_or_init;
33
use clippy_utils::res::MaybeDef;
44
use clippy_utils::source::snippet;
5-
use rustc_ast::ast::LitKind;
5+
use rustc_ast::ast::{LitKind, StrStyle};
66
use rustc_errors::Applicability;
77
use rustc_hir::{Expr, ExprKind};
88
use rustc_lint::LateContext;
@@ -15,7 +15,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a
1515
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
1616
if matches!(ty.opt_diag_name(cx), Some(sym::Path | sym::PathBuf))
1717
&& let ExprKind::Lit(spanned) = expr_or_init(cx, join_arg).kind
18-
&& let LitKind::Str(symbol, _) = spanned.node
18+
&& let LitKind::Str(symbol, style) = spanned.node
1919
&& let sym_str = symbol.as_str()
2020
&& sym_str.starts_with(['/', '\\'])
2121
{
@@ -29,8 +29,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a
2929

3030
let no_separator = if sym_str.starts_with('/') {
3131
arg_str.replacen('/', "", 1)
32-
} else {
32+
} else if let StrStyle::Raw(_) = style {
3333
arg_str.replacen('\\', "", 1)
34+
} else {
35+
arg_str.replacen("\\\\", "", 1)
3436
};
3537

3638
diag.note("joining a path starting with separator will replace the path instead")
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#![allow(clippy::needless_raw_string_hashes)]
2+
#![warn(clippy::join_absolute_paths)]
3+
4+
use std::path::{Path, PathBuf};
5+
6+
fn main() {
7+
let path = Path::new("/bin");
8+
path.join("sh");
9+
//~^ join_absolute_paths
10+
11+
let path = PathBuf::from("/bin");
12+
path.join("sh");
13+
//~^ join_absolute_paths
14+
15+
let path = PathBuf::from("/bin");
16+
path.join(r#"sh"#);
17+
//~^ join_absolute_paths
18+
19+
let path = Path::new("C:\\Users");
20+
path.join("user");
21+
//~^ join_absolute_paths
22+
23+
let path = PathBuf::from("C:\\Users");
24+
path.join("user");
25+
//~^ join_absolute_paths
26+
27+
let path = PathBuf::from("C:\\Users");
28+
path.join(r#"user"#);
29+
//~^ join_absolute_paths
30+
31+
let path: &[&str] = &["/bin"];
32+
path.join("/sh");
33+
34+
let path = Path::new("/bin");
35+
path.join("sh");
36+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#![allow(clippy::needless_raw_string_hashes)]
2+
#![warn(clippy::join_absolute_paths)]
3+
4+
use std::path::{Path, PathBuf};
5+
6+
fn main() {
7+
let path = Path::new("/bin");
8+
PathBuf::from("/sh");
9+
//~^ join_absolute_paths
10+
11+
let path = PathBuf::from("/bin");
12+
PathBuf::from("/sh");
13+
//~^ join_absolute_paths
14+
15+
let path = PathBuf::from("/bin");
16+
PathBuf::from(r#"/sh"#);
17+
//~^ join_absolute_paths
18+
19+
let path = Path::new("C:\\Users");
20+
PathBuf::from("\\user");
21+
//~^ join_absolute_paths
22+
23+
let path = PathBuf::from("C:\\Users");
24+
PathBuf::from("\\user");
25+
//~^ join_absolute_paths
26+
27+
let path = PathBuf::from("C:\\Users");
28+
PathBuf::from(r#"\user"#);
29+
//~^ join_absolute_paths
30+
31+
let path: &[&str] = &["/bin"];
32+
path.join("/sh");
33+
34+
let path = Path::new("/bin");
35+
path.join("sh");
36+
}

tests/ui/join_absolute_paths.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
//@no-rustfix
2-
31
#![allow(clippy::needless_raw_string_hashes)]
42
#![warn(clippy::join_absolute_paths)]
53

@@ -10,10 +8,6 @@ fn main() {
108
path.join("/sh");
119
//~^ join_absolute_paths
1210

13-
let path = Path::new("C:\\Users");
14-
path.join("\\user");
15-
//~^ join_absolute_paths
16-
1711
let path = PathBuf::from("/bin");
1812
path.join("/sh");
1913
//~^ join_absolute_paths
@@ -22,6 +16,18 @@ fn main() {
2216
path.join(r#"/sh"#);
2317
//~^ join_absolute_paths
2418

19+
let path = Path::new("C:\\Users");
20+
path.join("\\user");
21+
//~^ join_absolute_paths
22+
23+
let path = PathBuf::from("C:\\Users");
24+
path.join("\\user");
25+
//~^ join_absolute_paths
26+
27+
let path = PathBuf::from("C:\\Users");
28+
path.join(r#"\user"#);
29+
//~^ join_absolute_paths
30+
2531
let path: &[&str] = &["/bin"];
2632
path.join("/sh");
2733

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: argument to `Path::join` starts with a path separator
2-
--> tests/ui/join_absolute_paths.rs:10:15
2+
--> tests/ui/join_absolute_paths.rs:8:15
33
|
44
LL | path.join("/sh");
55
| ^^^^^
@@ -19,7 +19,43 @@ LL + PathBuf::from("/sh");
1919
|
2020

2121
error: argument to `Path::join` starts with a path separator
22-
--> tests/ui/join_absolute_paths.rs:14:15
22+
--> tests/ui/join_absolute_paths.rs:12:15
23+
|
24+
LL | path.join("/sh");
25+
| ^^^^^
26+
|
27+
= note: joining a path starting with separator will replace the path instead
28+
help: if this is unintentional, try removing the starting separator
29+
|
30+
LL - path.join("/sh");
31+
LL + path.join("sh");
32+
|
33+
help: if this is intentional, consider using `Path::new`
34+
|
35+
LL - path.join("/sh");
36+
LL + PathBuf::from("/sh");
37+
|
38+
39+
error: argument to `Path::join` starts with a path separator
40+
--> tests/ui/join_absolute_paths.rs:16:15
41+
|
42+
LL | path.join(r#"/sh"#);
43+
| ^^^^^^^^
44+
|
45+
= note: joining a path starting with separator will replace the path instead
46+
help: if this is unintentional, try removing the starting separator
47+
|
48+
LL - path.join(r#"/sh"#);
49+
LL + path.join(r#"sh"#);
50+
|
51+
help: if this is intentional, consider using `Path::new`
52+
|
53+
LL - path.join(r#"/sh"#);
54+
LL + PathBuf::from(r#"/sh"#);
55+
|
56+
57+
error: argument to `Path::join` starts with a path separator
58+
--> tests/ui/join_absolute_paths.rs:20:15
2359
|
2460
LL | path.join("\\user");
2561
| ^^^^^^^^
@@ -28,7 +64,7 @@ LL | path.join("\\user");
2864
help: if this is unintentional, try removing the starting separator
2965
|
3066
LL - path.join("\\user");
31-
LL + path.join("\user");
67+
LL + path.join("user");
3268
|
3369
help: if this is intentional, consider using `Path::new`
3470
|
@@ -37,40 +73,40 @@ LL + PathBuf::from("\\user");
3773
|
3874

3975
error: argument to `Path::join` starts with a path separator
40-
--> tests/ui/join_absolute_paths.rs:18:15
76+
--> tests/ui/join_absolute_paths.rs:24:15
4177
|
42-
LL | path.join("/sh");
43-
| ^^^^^
78+
LL | path.join("\\user");
79+
| ^^^^^^^^
4480
|
4581
= note: joining a path starting with separator will replace the path instead
4682
help: if this is unintentional, try removing the starting separator
4783
|
48-
LL - path.join("/sh");
49-
LL + path.join("sh");
84+
LL - path.join("\\user");
85+
LL + path.join("user");
5086
|
5187
help: if this is intentional, consider using `Path::new`
5288
|
53-
LL - path.join("/sh");
54-
LL + PathBuf::from("/sh");
89+
LL - path.join("\\user");
90+
LL + PathBuf::from("\\user");
5591
|
5692

5793
error: argument to `Path::join` starts with a path separator
58-
--> tests/ui/join_absolute_paths.rs:22:15
94+
--> tests/ui/join_absolute_paths.rs:28:15
5995
|
60-
LL | path.join(r#"/sh"#);
61-
| ^^^^^^^^
96+
LL | path.join(r#"\user"#);
97+
| ^^^^^^^^^^
6298
|
6399
= note: joining a path starting with separator will replace the path instead
64100
help: if this is unintentional, try removing the starting separator
65101
|
66-
LL - path.join(r#"/sh"#);
67-
LL + path.join(r#"sh"#);
102+
LL - path.join(r#"\user"#);
103+
LL + path.join(r#"user"#);
68104
|
69105
help: if this is intentional, consider using `Path::new`
70106
|
71-
LL - path.join(r#"/sh"#);
72-
LL + PathBuf::from(r#"/sh"#);
107+
LL - path.join(r#"\user"#);
108+
LL + PathBuf::from(r#"\user"#);
73109
|
74110

75-
error: aborting due to 4 previous errors
111+
error: aborting due to 6 previous errors
76112

0 commit comments

Comments
 (0)