Skip to content

Commit 5920fa3

Browse files
committed
Auto merge of #8844 - smoelius:fixed-paths, r=Alexendoo
Check `.fixed` paths' existence in `run_ui` This PR adds a test to check that there exists a `.fixed` file for every `.stderr` file in `tests/ui` that mentions a `MachineApplicable` lint. The test leverages `compiletest-rs`'s `rustfix_coverage` option. I tried to add `.fixed` files where they appeared to be missing. However, 38 exceptional `.rs` files remain. Several of those include comments indicating that they are exceptions, though not all do. Apologies, as I have not tried to associate the 38 files with GH issues. (I think that would be a lot of work, and I worry about linking the wrong issue.) changelog: none
2 parents 1dd5547 + 6027255 commit 5920fa3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1772
-439
lines changed

tests/compile-test.rs

+85-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![feature(test)] // compiletest_rs requires this attribute
22
#![feature(once_cell)]
3+
#![feature(is_sorted)]
34
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
45
#![warn(rust_2018_idioms, unused_lifetimes)]
56

@@ -166,7 +167,8 @@ fn base_config(test_dir: &str) -> compiletest::Config {
166167
}
167168

168169
fn run_ui() {
169-
let config = base_config("ui");
170+
let mut config = base_config("ui");
171+
config.rustfix_coverage = true;
170172
// use tests/clippy.toml
171173
let _g = VarGuard::set("CARGO_MANIFEST_DIR", fs::canonicalize("tests").unwrap());
172174
let _threads = VarGuard::set(
@@ -179,6 +181,7 @@ fn run_ui() {
179181
}),
180182
);
181183
compiletest::run_tests(&config);
184+
check_rustfix_coverage();
182185
}
183186

184187
fn run_internal_tests() {
@@ -341,6 +344,87 @@ fn compile_test() {
341344
run_internal_tests();
342345
}
343346

347+
const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[
348+
"assign_ops2.rs",
349+
"cast_size_32bit.rs",
350+
"char_lit_as_u8.rs",
351+
"cmp_owned/without_suggestion.rs",
352+
"dbg_macro.rs",
353+
"deref_addrof_double_trigger.rs",
354+
"doc/unbalanced_ticks.rs",
355+
"eprint_with_newline.rs",
356+
"explicit_counter_loop.rs",
357+
"iter_skip_next_unfixable.rs",
358+
"let_and_return.rs",
359+
"literals.rs",
360+
"map_flatten.rs",
361+
"map_unwrap_or.rs",
362+
"match_bool.rs",
363+
"mem_replace_macro.rs",
364+
"needless_arbitrary_self_type_unfixable.rs",
365+
"needless_borrow_pat.rs",
366+
"needless_for_each_unfixable.rs",
367+
"nonminimal_bool.rs",
368+
"print_literal.rs",
369+
"print_with_newline.rs",
370+
"redundant_static_lifetimes_multiple.rs",
371+
"ref_binding_to_reference.rs",
372+
"repl_uninit.rs",
373+
"result_map_unit_fn_unfixable.rs",
374+
"search_is_some.rs",
375+
"single_component_path_imports_nested_first.rs",
376+
"string_add.rs",
377+
"toplevel_ref_arg_non_rustfix.rs",
378+
"unit_arg.rs",
379+
"unnecessary_clone.rs",
380+
"unnecessary_lazy_eval_unfixable.rs",
381+
"write_literal.rs",
382+
"write_literal_2.rs",
383+
"write_with_newline.rs",
384+
];
385+
386+
fn check_rustfix_coverage() {
387+
let missing_coverage_path = Path::new("target/debug/test/ui/rustfix_missing_coverage.txt");
388+
389+
if let Ok(missing_coverage_contents) = std::fs::read_to_string(missing_coverage_path) {
390+
assert!(RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS.iter().is_sorted_by_key(Path::new));
391+
392+
for rs_path in missing_coverage_contents.lines() {
393+
if Path::new(rs_path).starts_with("tests/ui/crashes") {
394+
continue;
395+
}
396+
let filename = Path::new(rs_path).strip_prefix("tests/ui/").unwrap();
397+
assert!(
398+
RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS
399+
.binary_search_by_key(&filename, Path::new)
400+
.is_ok(),
401+
"`{}` runs `MachineApplicable` diagnostics but is missing a `run-rustfix` annotation. \
402+
Please either add `// run-rustfix` at the top of the file or add the file to \
403+
`RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS` in `tests/compile-test.rs`.",
404+
rs_path,
405+
);
406+
}
407+
}
408+
}
409+
410+
#[test]
411+
fn rustfix_coverage_known_exceptions_accuracy() {
412+
for filename in RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS {
413+
let rs_path = Path::new("tests/ui").join(filename);
414+
assert!(
415+
rs_path.exists(),
416+
"`{}` does not exists",
417+
rs_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
418+
);
419+
let fixed_path = rs_path.with_extension("fixed");
420+
assert!(
421+
!fixed_path.exists(),
422+
"`{}` exists",
423+
fixed_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
424+
);
425+
}
426+
}
427+
344428
/// Restores an env var on drop
345429
#[must_use]
346430
struct VarGuard {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// run-rustfix
2+
#![deny(clippy::bind_instead_of_map)]
3+
#![allow(clippy::blocks_in_if_conditions)]
4+
5+
pub fn main() {
6+
let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() });
7+
let _ = Some("42").and_then(|s| if s.len() < 42 { None } else { Some(s.len()) });
8+
9+
let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len() });
10+
let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Err(()) } else { Ok(s.len()) });
11+
12+
let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 } else { s.len() });
13+
let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Ok(()) } else { Err(s.len()) });
14+
15+
hard_example();
16+
macro_example();
17+
}
18+
19+
fn hard_example() {
20+
Some("42").map(|s| {
21+
if {
22+
if s == "43" {
23+
return 43;
24+
}
25+
s == "42"
26+
} {
27+
return 45;
28+
}
29+
match s.len() {
30+
10 => 2,
31+
20 => {
32+
if foo() {
33+
return {
34+
if foo() {
35+
return 20;
36+
}
37+
println!("foo");
38+
3
39+
};
40+
}
41+
20
42+
},
43+
40 => 30,
44+
_ => 1,
45+
}
46+
});
47+
}
48+
49+
fn foo() -> bool {
50+
true
51+
}
52+
53+
macro_rules! m {
54+
() => {
55+
Some(10)
56+
};
57+
}
58+
59+
fn macro_example() {
60+
let _ = Some("").and_then(|s| if s.len() == 20 { m!() } else { Some(20) });
61+
let _ = Some("").map(|s| if s.len() == 20 { m!() } else { Some(20) });
62+
}

tests/ui/bind_instead_of_map_multipart.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// run-rustfix
12
#![deny(clippy::bind_instead_of_map)]
23
#![allow(clippy::blocks_in_if_conditions)]
34

tests/ui/bind_instead_of_map_multipart.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`
2-
--> $DIR/bind_instead_of_map_multipart.rs:5:13
2+
--> $DIR/bind_instead_of_map_multipart.rs:6:13
33
|
44
LL | let _ = Some("42").and_then(|s| if s.len() < 42 { Some(0) } else { Some(s.len()) });
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
note: the lint level is defined here
8-
--> $DIR/bind_instead_of_map_multipart.rs:1:9
8+
--> $DIR/bind_instead_of_map_multipart.rs:2:9
99
|
1010
LL | #![deny(clippy::bind_instead_of_map)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() });
1515
| ~~~ ~ ~~~~~~~
1616

1717
error: using `Result.and_then(|x| Ok(y))`, which is more succinctly expressed as `map(|x| y)`
18-
--> $DIR/bind_instead_of_map_multipart.rs:8:13
18+
--> $DIR/bind_instead_of_map_multipart.rs:9:13
1919
|
2020
LL | let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Ok(0) } else { Ok(s.len()) });
2121
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL | let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len()
2626
| ~~~ ~ ~~~~~~~
2727

2828
error: using `Result.or_else(|x| Err(y))`, which is more succinctly expressed as `map_err(|x| y)`
29-
--> $DIR/bind_instead_of_map_multipart.rs:11:13
29+
--> $DIR/bind_instead_of_map_multipart.rs:12:13
3030
|
3131
LL | let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Err(s.len() + 20) } else { Err(s.len()) });
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL | let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 }
3737
| ~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~
3838

3939
error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`
40-
--> $DIR/bind_instead_of_map_multipart.rs:19:5
40+
--> $DIR/bind_instead_of_map_multipart.rs:20:5
4141
|
4242
LL | / Some("42").and_then(|s| {
4343
LL | | if {
@@ -59,7 +59,7 @@ LL | s == "42"
5959
...
6060

6161
error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`
62-
--> $DIR/bind_instead_of_map_multipart.rs:60:13
62+
--> $DIR/bind_instead_of_map_multipart.rs:61:13
6363
|
6464
LL | let _ = Some("").and_then(|s| if s.len() == 20 { Some(m!()) } else { Some(Some(20)) });
6565
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/implicit_clone.fixed

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// run-rustfix
2+
#![warn(clippy::implicit_clone)]
3+
#![allow(clippy::clone_on_copy, clippy::redundant_clone)]
4+
use std::borrow::Borrow;
5+
use std::ffi::{OsStr, OsString};
6+
use std::path::PathBuf;
7+
8+
fn return_owned_from_slice(slice: &[u32]) -> Vec<u32> {
9+
slice.to_owned()
10+
}
11+
12+
pub fn own_same<T>(v: T) -> T
13+
where
14+
T: ToOwned<Owned = T>,
15+
{
16+
v.to_owned()
17+
}
18+
19+
pub fn own_same_from_ref<T>(v: &T) -> T
20+
where
21+
T: ToOwned<Owned = T>,
22+
{
23+
v.to_owned()
24+
}
25+
26+
pub fn own_different<T, U>(v: T) -> U
27+
where
28+
T: ToOwned<Owned = U>,
29+
{
30+
v.to_owned()
31+
}
32+
33+
#[derive(Copy, Clone)]
34+
struct Kitten;
35+
impl Kitten {
36+
// badly named method
37+
fn to_vec(self) -> Kitten {
38+
Kitten {}
39+
}
40+
}
41+
impl Borrow<BorrowedKitten> for Kitten {
42+
fn borrow(&self) -> &BorrowedKitten {
43+
static VALUE: BorrowedKitten = BorrowedKitten {};
44+
&VALUE
45+
}
46+
}
47+
48+
struct BorrowedKitten;
49+
impl ToOwned for BorrowedKitten {
50+
type Owned = Kitten;
51+
fn to_owned(&self) -> Kitten {
52+
Kitten {}
53+
}
54+
}
55+
56+
mod weird {
57+
#[allow(clippy::ptr_arg)]
58+
pub fn to_vec(v: &Vec<u32>) -> Vec<u32> {
59+
v.clone()
60+
}
61+
}
62+
63+
fn main() {
64+
let vec = vec![5];
65+
let _ = return_owned_from_slice(&vec);
66+
let _ = vec.clone();
67+
let _ = vec.clone();
68+
69+
let vec_ref = &vec;
70+
let _ = return_owned_from_slice(vec_ref);
71+
let _ = vec_ref.clone();
72+
let _ = vec_ref.clone();
73+
74+
// we expect no lint for this
75+
let _ = weird::to_vec(&vec);
76+
77+
// we expect no lints for this
78+
let slice: &[u32] = &[1, 2, 3, 4, 5];
79+
let _ = return_owned_from_slice(slice);
80+
let _ = slice.to_owned();
81+
let _ = slice.to_vec();
82+
83+
let str = "hello world".to_string();
84+
let _ = str.clone();
85+
86+
// testing w/ an arbitrary type
87+
let kitten = Kitten {};
88+
let _ = kitten.clone();
89+
let _ = own_same_from_ref(&kitten);
90+
// this shouln't lint
91+
let _ = kitten.to_vec();
92+
93+
// we expect no lints for this
94+
let borrowed = BorrowedKitten {};
95+
let _ = borrowed.to_owned();
96+
97+
let pathbuf = PathBuf::new();
98+
let _ = pathbuf.clone();
99+
let _ = pathbuf.clone();
100+
101+
let os_string = OsString::from("foo");
102+
let _ = os_string.clone();
103+
let _ = os_string.clone();
104+
105+
// we expect no lints for this
106+
let os_str = OsStr::new("foo");
107+
let _ = os_str.to_owned();
108+
let _ = os_str.to_os_string();
109+
110+
// issue #8227
111+
let pathbuf_ref = &pathbuf;
112+
let pathbuf_ref = &pathbuf_ref;
113+
let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&PathBuf`
114+
let _ = (*pathbuf_ref).clone();
115+
let pathbuf_ref = &pathbuf_ref;
116+
let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf`
117+
let _ = (**pathbuf_ref).clone();
118+
}

tests/ui/implicit_clone.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
// run-rustfix
12
#![warn(clippy::implicit_clone)]
2-
#![allow(clippy::redundant_clone)]
3+
#![allow(clippy::clone_on_copy, clippy::redundant_clone)]
34
use std::borrow::Borrow;
45
use std::ffi::{OsStr, OsString};
56
use std::path::PathBuf;

0 commit comments

Comments
 (0)