Check .fixed paths' existence in run_ui

This commit is contained in:
Samuel E. Moelius III 2022-05-19 09:03:38 -04:00
parent a5ece8132f
commit 911eb1f4cd
49 changed files with 1478 additions and 127 deletions

View file

@ -1,5 +1,6 @@
#![feature(test)] // compiletest_rs requires this attribute
#![feature(once_cell)]
#![feature(is_sorted)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
@ -162,8 +163,8 @@ fn base_config(test_dir: &str) -> compiletest::Config {
}
fn run_ui() {
let config = base_config("ui");
// use tests/clippy.toml
let mut config = base_config("ui");
config.rustfix_coverage = true;
let _g = VarGuard::set("CARGO_MANIFEST_DIR", fs::canonicalize("tests").unwrap());
let _threads = VarGuard::set(
"RUST_TEST_THREADS",
@ -175,6 +176,7 @@ fn run_ui() {
}),
);
compiletest::run_tests(&config);
check_rustfix_coverage();
}
fn run_internal_tests() {
@ -337,6 +339,82 @@ fn compile_test() {
run_internal_tests();
}
const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[
"assign_ops2.rs",
"cast_size_32bit.rs",
"char_lit_as_u8.rs",
"cmp_owned/without_suggestion.rs",
"crashes/ice-6250.rs",
"crashes/ice-6251.rs",
"dbg_macro.rs",
"deref_addrof_double_trigger.rs",
"doc/unbalanced_ticks.rs",
"eprint_with_newline.rs",
"explicit_counter_loop.rs",
"iter_skip_next_unfixable.rs",
"let_and_return.rs",
"literals.rs",
"map_flatten.rs",
"map_unwrap_or.rs",
"match_bool.rs",
"mem_replace_macro.rs",
"needless_arbitrary_self_type_unfixable.rs",
"needless_borrow_pat.rs",
"needless_for_each_unfixable.rs",
"nonminimal_bool.rs",
"print_literal.rs",
"print_with_newline.rs",
"redundant_static_lifetimes_multiple.rs",
"ref_binding_to_reference.rs",
"repl_uninit.rs",
"result_map_unit_fn_unfixable.rs",
"search_is_some.rs",
"single_component_path_imports_nested_first.rs",
"string_add.rs",
"toplevel_ref_arg_non_rustfix.rs",
"unit_arg.rs",
"unnecessary_clone.rs",
"unnecessary_lazy_eval_unfixable.rs",
"write_literal.rs",
"write_literal_2.rs",
"write_with_newline.rs",
];
fn check_rustfix_coverage() {
let missing_coverage_path = Path::new("target/debug/test/ui/rustfix_missing_coverage.txt");
if let Ok(missing_coverage_contents) = std::fs::read_to_string(missing_coverage_path) {
assert!(RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS.is_sorted());
for rs_path in missing_coverage_contents.lines() {
let filename = rs_path.strip_prefix("tests/ui/").unwrap();
assert!(
RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS.binary_search(&filename).is_ok(),
"`{}` runs `MachineApplicable` diagnostics but is missing a `run-rustfix` annotation",
rs_path,
);
}
}
}
#[test]
fn rustfix_coverage_known_exceptions_accuracy() {
for filename in RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS {
let rs_path = Path::new("tests/ui").join(filename);
assert!(
rs_path.exists(),
"`{}` does not exists",
rs_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
);
let fixed_path = rs_path.with_extension("fixed");
assert!(
!fixed_path.exists(),
"`{}` exists",
fixed_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
);
}
}
/// Restores an env var on drop
#[must_use]
struct VarGuard {

View file

@ -0,0 +1,62 @@
// run-rustfix
#![deny(clippy::bind_instead_of_map)]
#![allow(clippy::blocks_in_if_conditions)]
pub fn main() {
let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() });
let _ = Some("42").and_then(|s| if s.len() < 42 { None } else { Some(s.len()) });
let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len() });
let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Err(()) } else { Ok(s.len()) });
let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 } else { s.len() });
let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Ok(()) } else { Err(s.len()) });
hard_example();
macro_example();
}
fn hard_example() {
Some("42").map(|s| {
if {
if s == "43" {
return 43;
}
s == "42"
} {
return 45;
}
match s.len() {
10 => 2,
20 => {
if foo() {
return {
if foo() {
return 20;
}
println!("foo");
3
};
}
20
},
40 => 30,
_ => 1,
}
});
}
fn foo() -> bool {
true
}
macro_rules! m {
() => {
Some(10)
};
}
fn macro_example() {
let _ = Some("").and_then(|s| if s.len() == 20 { m!() } else { Some(20) });
let _ = Some("").map(|s| if s.len() == 20 { m!() } else { Some(20) });
}

View file

@ -1,3 +1,4 @@
// run-rustfix
#![deny(clippy::bind_instead_of_map)]
#![allow(clippy::blocks_in_if_conditions)]

View file

@ -1,11 +1,11 @@
error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`
--> $DIR/bind_instead_of_map_multipart.rs:5:13
--> $DIR/bind_instead_of_map_multipart.rs:6:13
|
LL | let _ = Some("42").and_then(|s| if s.len() < 42 { Some(0) } else { Some(s.len()) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/bind_instead_of_map_multipart.rs:1:9
--> $DIR/bind_instead_of_map_multipart.rs:2:9
|
LL | #![deny(clippy::bind_instead_of_map)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -15,7 +15,7 @@ LL | let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() });
| ~~~ ~ ~~~~~~~
error: using `Result.and_then(|x| Ok(y))`, which is more succinctly expressed as `map(|x| y)`
--> $DIR/bind_instead_of_map_multipart.rs:8:13
--> $DIR/bind_instead_of_map_multipart.rs:9:13
|
LL | let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Ok(0) } else { Ok(s.len()) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -26,7 +26,7 @@ LL | let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len()
| ~~~ ~ ~~~~~~~
error: using `Result.or_else(|x| Err(y))`, which is more succinctly expressed as `map_err(|x| y)`
--> $DIR/bind_instead_of_map_multipart.rs:11:13
--> $DIR/bind_instead_of_map_multipart.rs:12:13
|
LL | let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Err(s.len() + 20) } else { Err(s.len()) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -37,7 +37,7 @@ LL | let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 }
| ~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~
error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`
--> $DIR/bind_instead_of_map_multipart.rs:19:5
--> $DIR/bind_instead_of_map_multipart.rs:20:5
|
LL | / Some("42").and_then(|s| {
LL | | if {
@ -59,7 +59,7 @@ LL | s == "42"
...
error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`
--> $DIR/bind_instead_of_map_multipart.rs:60:13
--> $DIR/bind_instead_of_map_multipart.rs:61:13
|
LL | let _ = Some("").and_then(|s| if s.len() == 20 { Some(m!()) } else { Some(Some(20)) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,12 @@
// run-rustfix
#![allow(dead_code)]
#[derive(Default)]
struct A<T> {
a: Vec<A<T>>,
b: T,
}
fn main() {
if Ok::<_, ()>(A::<String>::default()).is_ok() {}
}

View file

@ -1,3 +1,6 @@
// run-rustfix
#![allow(dead_code)]
#[derive(Default)]
struct A<T> {
a: Vec<A<T>>,

View file

@ -1,5 +1,5 @@
error: redundant pattern matching, consider using `is_ok()`
--> $DIR/ice-7169.rs:8:12
--> $DIR/ice-7169.rs:11:12
|
LL | if let Ok(_) = Ok::<_, ()>(A::<String>::default()) {}
| -------^^^^^-------------------------------------- help: try this: `if Ok::<_, ()>(A::<String>::default()).is_ok()`

View file

@ -0,0 +1,7 @@
// run-rustfix
fn _f(s: &str) -> Option<()> {
let _ = s[1..].split('.').next()?;
Some(())
}
fn main() {}

View file

@ -1,3 +1,4 @@
// run-rustfix
fn _f(s: &str) -> Option<()> {
let _ = s[1..].splitn(2, '.').next()?;
Some(())

View file

@ -1,5 +1,5 @@
error: unnecessary use of `splitn`
--> $DIR/ice-8250.rs:2:13
--> $DIR/ice-8250.rs:3:13
|
LL | let _ = s[1..].splitn(2, '.').next()?;
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s[1..].split('.')`

View file

@ -0,0 +1,9 @@
// run-rustfix
#![warn(clippy::let_unit_value)]
fn f() {}
static FN: fn() = f;
fn main() {
FN();
}

View file

@ -1,3 +1,4 @@
// run-rustfix
#![warn(clippy::let_unit_value)]
fn f() {}

View file

@ -1,5 +1,5 @@
error: this let-binding has unit value
--> $DIR/ice-8821.rs:7:5
--> $DIR/ice-8821.rs:8:5
|
LL | let _: () = FN();
| ^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `FN();`

View file

@ -0,0 +1,118 @@
// run-rustfix
#![warn(clippy::implicit_clone)]
#![allow(clippy::clone_on_copy, clippy::redundant_clone)]
use std::borrow::Borrow;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;
fn return_owned_from_slice(slice: &[u32]) -> Vec<u32> {
slice.to_owned()
}
pub fn own_same<T>(v: T) -> T
where
T: ToOwned<Owned = T>,
{
v.to_owned()
}
pub fn own_same_from_ref<T>(v: &T) -> T
where
T: ToOwned<Owned = T>,
{
v.to_owned()
}
pub fn own_different<T, U>(v: T) -> U
where
T: ToOwned<Owned = U>,
{
v.to_owned()
}
#[derive(Copy, Clone)]
struct Kitten;
impl Kitten {
// badly named method
fn to_vec(self) -> Kitten {
Kitten {}
}
}
impl Borrow<BorrowedKitten> for Kitten {
fn borrow(&self) -> &BorrowedKitten {
static VALUE: BorrowedKitten = BorrowedKitten {};
&VALUE
}
}
struct BorrowedKitten;
impl ToOwned for BorrowedKitten {
type Owned = Kitten;
fn to_owned(&self) -> Kitten {
Kitten {}
}
}
mod weird {
#[allow(clippy::ptr_arg)]
pub fn to_vec(v: &Vec<u32>) -> Vec<u32> {
v.clone()
}
}
fn main() {
let vec = vec![5];
let _ = return_owned_from_slice(&vec);
let _ = vec.clone();
let _ = vec.clone();
let vec_ref = &vec;
let _ = return_owned_from_slice(vec_ref);
let _ = vec_ref.clone();
let _ = vec_ref.clone();
// we expect no lint for this
let _ = weird::to_vec(&vec);
// we expect no lints for this
let slice: &[u32] = &[1, 2, 3, 4, 5];
let _ = return_owned_from_slice(slice);
let _ = slice.to_owned();
let _ = slice.to_vec();
let str = "hello world".to_string();
let _ = str.clone();
// testing w/ an arbitrary type
let kitten = Kitten {};
let _ = kitten.clone();
let _ = own_same_from_ref(&kitten);
// this shouln't lint
let _ = kitten.to_vec();
// we expect no lints for this
let borrowed = BorrowedKitten {};
let _ = borrowed.to_owned();
let pathbuf = PathBuf::new();
let _ = pathbuf.clone();
let _ = pathbuf.clone();
let os_string = OsString::from("foo");
let _ = os_string.clone();
let _ = os_string.clone();
// we expect no lints for this
let os_str = OsStr::new("foo");
let _ = os_str.to_owned();
let _ = os_str.to_os_string();
// issue #8227
let pathbuf_ref = &pathbuf;
let pathbuf_ref = &pathbuf_ref;
let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&PathBuf`
let _ = (*pathbuf_ref).clone();
let pathbuf_ref = &pathbuf_ref;
let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf`
let _ = (**pathbuf_ref).clone();
}

View file

@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::implicit_clone)]
#![allow(clippy::redundant_clone)]
#![allow(clippy::clone_on_copy, clippy::redundant_clone)]
use std::borrow::Borrow;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;

View file

@ -1,5 +1,5 @@
error: implicitly cloning a `Vec` by calling `to_owned` on its dereferenced type
--> $DIR/implicit_clone.rs:65:13
--> $DIR/implicit_clone.rs:66:13
|
LL | let _ = vec.to_owned();
| ^^^^^^^^^^^^^^ help: consider using: `vec.clone()`
@ -7,67 +7,67 @@ LL | let _ = vec.to_owned();
= note: `-D clippy::implicit-clone` implied by `-D warnings`
error: implicitly cloning a `Vec` by calling `to_vec` on its dereferenced type
--> $DIR/implicit_clone.rs:66:13
--> $DIR/implicit_clone.rs:67:13
|
LL | let _ = vec.to_vec();
| ^^^^^^^^^^^^ help: consider using: `vec.clone()`
error: implicitly cloning a `Vec` by calling `to_owned` on its dereferenced type
--> $DIR/implicit_clone.rs:70:13
--> $DIR/implicit_clone.rs:71:13
|
LL | let _ = vec_ref.to_owned();
| ^^^^^^^^^^^^^^^^^^ help: consider using: `vec_ref.clone()`
error: implicitly cloning a `Vec` by calling `to_vec` on its dereferenced type
--> $DIR/implicit_clone.rs:71:13
--> $DIR/implicit_clone.rs:72:13
|
LL | let _ = vec_ref.to_vec();
| ^^^^^^^^^^^^^^^^ help: consider using: `vec_ref.clone()`
error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type
--> $DIR/implicit_clone.rs:83:13
--> $DIR/implicit_clone.rs:84:13
|
LL | let _ = str.to_owned();
| ^^^^^^^^^^^^^^ help: consider using: `str.clone()`
error: implicitly cloning a `Kitten` by calling `to_owned` on its dereferenced type
--> $DIR/implicit_clone.rs:87:13
--> $DIR/implicit_clone.rs:88:13
|
LL | let _ = kitten.to_owned();
| ^^^^^^^^^^^^^^^^^ help: consider using: `kitten.clone()`
error: implicitly cloning a `PathBuf` by calling `to_owned` on its dereferenced type
--> $DIR/implicit_clone.rs:97:13
--> $DIR/implicit_clone.rs:98:13
|
LL | let _ = pathbuf.to_owned();
| ^^^^^^^^^^^^^^^^^^ help: consider using: `pathbuf.clone()`
error: implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenced type
--> $DIR/implicit_clone.rs:98:13
--> $DIR/implicit_clone.rs:99:13
|
LL | let _ = pathbuf.to_path_buf();
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `pathbuf.clone()`
error: implicitly cloning a `OsString` by calling `to_owned` on its dereferenced type
--> $DIR/implicit_clone.rs:101:13
--> $DIR/implicit_clone.rs:102:13
|
LL | let _ = os_string.to_owned();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `os_string.clone()`
error: implicitly cloning a `OsString` by calling `to_os_string` on its dereferenced type
--> $DIR/implicit_clone.rs:102:13
--> $DIR/implicit_clone.rs:103:13
|
LL | let _ = os_string.to_os_string();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `os_string.clone()`
error: implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenced type
--> $DIR/implicit_clone.rs:113:13
--> $DIR/implicit_clone.rs:114:13
|
LL | let _ = pathbuf_ref.to_path_buf();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(*pathbuf_ref).clone()`
error: implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenced type
--> $DIR/implicit_clone.rs:116:13
--> $DIR/implicit_clone.rs:117:13
|
LL | let _ = pathbuf_ref.to_path_buf();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(**pathbuf_ref).clone()`

26
tests/ui/issue_2356.fixed Normal file
View file

@ -0,0 +1,26 @@
// run-rustfix
#![deny(clippy::while_let_on_iterator)]
#![allow(unused_mut)]
use std::iter::Iterator;
struct Foo;
impl Foo {
fn foo1<I: Iterator<Item = usize>>(mut it: I) {
while let Some(_) = it.next() {
println!("{:?}", it.size_hint());
}
}
fn foo2<I: Iterator<Item = usize>>(mut it: I) {
for e in it {
println!("{:?}", e);
}
}
}
fn main() {
Foo::foo1(vec![].into_iter());
Foo::foo2(vec![].into_iter());
}

View file

@ -1,4 +1,6 @@
// run-rustfix
#![deny(clippy::while_let_on_iterator)]
#![allow(unused_mut)]
use std::iter::Iterator;

View file

@ -1,11 +1,11 @@
error: this loop could be written as a `for` loop
--> $DIR/issue_2356.rs:15:9
--> $DIR/issue_2356.rs:17:9
|
LL | while let Some(e) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for e in it`
|
note: the lint level is defined here
--> $DIR/issue_2356.rs:1:9
--> $DIR/issue_2356.rs:2:9
|
LL | #![deny(clippy::while_let_on_iterator)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,118 @@
// run-rustfix
#![warn(clippy::match_ref_pats)]
#![allow(dead_code, unused_variables, clippy::equatable_if_let, clippy::enum_variant_names)]
fn ref_pats() {
{
let v = &Some(0);
match *v {
Some(v) => println!("{:?}", v),
None => println!("none"),
}
match v {
// This doesn't trigger; we have a different pattern.
&Some(v) => println!("some"),
other => println!("other"),
}
}
let tup = &(1, 2);
match tup {
&(v, 1) => println!("{}", v),
_ => println!("none"),
}
// Special case: using `&` both in expr and pats.
let w = Some(0);
match w {
Some(v) => println!("{:?}", v),
None => println!("none"),
}
// False positive: only wildcard pattern.
let w = Some(0);
#[allow(clippy::match_single_binding)]
match w {
_ => println!("none"),
}
let a = &Some(0);
if a.is_none() {
println!("none");
}
let b = Some(0);
if b.is_none() {
println!("none");
}
}
mod ice_3719 {
macro_rules! foo_variant(
($idx:expr) => (Foo::get($idx).unwrap())
);
enum Foo {
A,
B,
}
impl Foo {
fn get(idx: u8) -> Option<&'static Self> {
match idx {
0 => Some(&Foo::A),
1 => Some(&Foo::B),
_ => None,
}
}
}
fn ice_3719() {
// ICE #3719
match foo_variant!(0) {
&Foo::A => println!("A"),
_ => println!("Wild"),
}
}
}
mod issue_7740 {
macro_rules! foobar_variant(
($idx:expr) => (FooBar::get($idx).unwrap())
);
enum FooBar {
Foo,
Bar,
FooBar,
BarFoo,
}
impl FooBar {
fn get(idx: u8) -> Option<&'static Self> {
match idx {
0 => Some(&FooBar::Foo),
1 => Some(&FooBar::Bar),
2 => Some(&FooBar::FooBar),
3 => Some(&FooBar::BarFoo),
_ => None,
}
}
}
fn issue_7740() {
// Issue #7740
match *foobar_variant!(0) {
FooBar::Foo => println!("Foo"),
FooBar::Bar => println!("Bar"),
FooBar::FooBar => println!("FooBar"),
_ => println!("Wild"),
}
// This shouldn't trigger
if let &FooBar::BarFoo = foobar_variant!(3) {
println!("BarFoo");
} else {
println!("Wild");
}
}
}
fn main() {}

View file

@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::match_ref_pats)]
#![allow(clippy::equatable_if_let, clippy::enum_variant_names)]
#![allow(dead_code, unused_variables, clippy::equatable_if_let, clippy::enum_variant_names)]
fn ref_pats() {
{

View file

@ -1,5 +1,5 @@
error: you don't need to add `&` to all patterns
--> $DIR/match_ref_pats.rs:7:9
--> $DIR/match_ref_pats.rs:8:9
|
LL | / match v {
LL | | &Some(v) => println!("{:?}", v),
@ -16,7 +16,7 @@ LL ~ None => println!("none"),
|
error: you don't need to add `&` to both the expression and the patterns
--> $DIR/match_ref_pats.rs:24:5
--> $DIR/match_ref_pats.rs:25:5
|
LL | / match &w {
LL | | &Some(v) => println!("{:?}", v),
@ -32,7 +32,7 @@ LL ~ None => println!("none"),
|
error: redundant pattern matching, consider using `is_none()`
--> $DIR/match_ref_pats.rs:36:12
--> $DIR/match_ref_pats.rs:37:12
|
LL | if let &None = a {
| -------^^^^^---- help: try this: `if a.is_none()`
@ -40,13 +40,13 @@ LL | if let &None = a {
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_none()`
--> $DIR/match_ref_pats.rs:41:12
--> $DIR/match_ref_pats.rs:42:12
|
LL | if let &None = &b {
| -------^^^^^----- help: try this: `if b.is_none()`
error: you don't need to add `&` to all patterns
--> $DIR/match_ref_pats.rs:101:9
--> $DIR/match_ref_pats.rs:102:9
|
LL | / match foobar_variant!(0) {
LL | | &FooBar::Foo => println!("Foo"),

View file

@ -0,0 +1,186 @@
// run-rustfix
#![warn(clippy::match_str_case_mismatch)]
#![allow(dead_code)]
// Valid
fn as_str_match() {
let var = "BAR";
match var.to_ascii_lowercase().as_str() {
"foo" => {},
"bar" => {},
_ => {},
}
}
fn non_alphabetic() {
let var = "~!@#$%^&*()-_=+FOO";
match var.to_ascii_lowercase().as_str() {
"1234567890" => {},
"~!@#$%^&*()-_=+foo" => {},
"\n\r\t\x7F" => {},
_ => {},
}
}
fn unicode_cased() {
let var = "ВОДЫ";
match var.to_lowercase().as_str() {
"" => {},
"νερό" => {},
"воды" => {},
"" => {},
_ => {},
}
}
fn titlecase() {
let var = "BarDz";
match var.to_lowercase().as_str() {
"foolj" => {},
"bardz" => {},
_ => {},
}
}
fn no_case_equivalent() {
let var = "barʁ";
match var.to_uppercase().as_str() {
"FOOɕ" => {},
"BARʁ" => {},
_ => {},
}
}
fn addrof_unary_match() {
let var = "BAR";
match &*var.to_ascii_lowercase() {
"foo" => {},
"bar" => {},
_ => {},
}
}
fn alternating_chain() {
let var = "BAR";
match &*var
.to_ascii_lowercase()
.to_uppercase()
.to_lowercase()
.to_ascii_uppercase()
{
"FOO" => {},
"BAR" => {},
_ => {},
}
}
fn unrelated_method() {
struct Item {
a: String,
}
impl Item {
#[allow(clippy::wrong_self_convention)]
fn to_lowercase(self) -> String {
self.a
}
}
let item = Item { a: String::from("BAR") };
match &*item.to_lowercase() {
"FOO" => {},
"BAR" => {},
_ => {},
}
}
// Invalid
fn as_str_match_mismatch() {
let var = "BAR";
match var.to_ascii_lowercase().as_str() {
"foo" => {},
"bar" => {},
_ => {},
}
}
fn non_alphabetic_mismatch() {
let var = "~!@#$%^&*()-_=+FOO";
match var.to_ascii_lowercase().as_str() {
"1234567890" => {},
"~!@#$%^&*()-_=+foo" => {},
"\n\r\t\x7F" => {},
_ => {},
}
}
fn unicode_cased_mismatch() {
let var = "ВОДЫ";
match var.to_lowercase().as_str() {
"" => {},
"νερό" => {},
"воды" => {},
"" => {},
_ => {},
}
}
fn titlecase_mismatch() {
let var = "BarDz";
match var.to_lowercase().as_str() {
"foolj" => {},
"bardz" => {},
_ => {},
}
}
fn no_case_equivalent_mismatch() {
let var = "barʁ";
match var.to_uppercase().as_str() {
"FOOɕ" => {},
"BARʁ" => {},
_ => {},
}
}
fn addrof_unary_match_mismatch() {
let var = "BAR";
match &*var.to_ascii_lowercase() {
"foo" => {},
"bar" => {},
_ => {},
}
}
fn alternating_chain_mismatch() {
let var = "BAR";
match &*var
.to_ascii_lowercase()
.to_uppercase()
.to_lowercase()
.to_ascii_uppercase()
{
"FOO" => {},
"BAR" => {},
_ => {},
}
}
fn main() {}

View file

@ -1,4 +1,6 @@
// run-rustfix
#![warn(clippy::match_str_case_mismatch)]
#![allow(dead_code)]
// Valid

View file

@ -1,5 +1,5 @@
error: this `match` arm has a differing case than its expression
--> $DIR/match_str_case_mismatch.rs:111:9
--> $DIR/match_str_case_mismatch.rs:113:9
|
LL | "Bar" => {},
| ^^^^^
@ -11,7 +11,7 @@ LL | "bar" => {},
| ~~~~~
error: this `match` arm has a differing case than its expression
--> $DIR/match_str_case_mismatch.rs:121:9
--> $DIR/match_str_case_mismatch.rs:123:9
|
LL | "~!@#$%^&*()-_=+Foo" => {},
| ^^^^^^^^^^^^^^^^^^^^
@ -22,7 +22,7 @@ LL | "~!@#$%^&*()-_=+foo" => {},
| ~~~~~~~~~~~~~~~~~~~~
error: this `match` arm has a differing case than its expression
--> $DIR/match_str_case_mismatch.rs:133:9
--> $DIR/match_str_case_mismatch.rs:135:9
|
LL | "Воды" => {},
| ^^^^^^
@ -33,7 +33,7 @@ LL | "воды" => {},
| ~~~~~~
error: this `match` arm has a differing case than its expression
--> $DIR/match_str_case_mismatch.rs:144:9
--> $DIR/match_str_case_mismatch.rs:146:9
|
LL | "barDz" => {},
| ^^^^^^
@ -44,7 +44,7 @@ LL | "bardz" => {},
| ~~~~~~
error: this `match` arm has a differing case than its expression
--> $DIR/match_str_case_mismatch.rs:154:9
--> $DIR/match_str_case_mismatch.rs:156:9
|
LL | "bARʁ" => {},
| ^^^^^^
@ -55,7 +55,7 @@ LL | "BARʁ" => {},
| ~~~~~~
error: this `match` arm has a differing case than its expression
--> $DIR/match_str_case_mismatch.rs:164:9
--> $DIR/match_str_case_mismatch.rs:166:9
|
LL | "Bar" => {},
| ^^^^^
@ -66,7 +66,7 @@ LL | "bar" => {},
| ~~~~~
error: this `match` arm has a differing case than its expression
--> $DIR/match_str_case_mismatch.rs:179:9
--> $DIR/match_str_case_mismatch.rs:181:9
|
LL | "bAR" => {},
| ^^^^^

View file

@ -0,0 +1,232 @@
// run-rustfix
#![feature(let_chains)]
#![allow(unused, clippy::nonminimal_bool, clippy::let_unit_value, clippy::let_and_return)]
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::rc::Rc;
struct SignificantDrop;
impl std::ops::Drop for SignificantDrop {
fn drop(&mut self) {
println!("dropped");
}
}
fn main() {
let n = 1;
let a = match n {
1 => "one",
_ => {
"two"
},
};
let b = if n == 3 {
"four"
} else {
"five"
};
let d = if true {
let temp = 5;
temp
} else {
15
};
let e = if true {
format!("{} {}", a, b)
} else {
format!("{}", n)
};
let f = match 1 {
1 => "three",
_ => return,
}; // has semi
let g: usize = if true {
5
} else {
panic!();
};
// Drop order only matters if both are significant
let y = SignificantDrop;
let x = 1;
let y = 1;
let x = SignificantDrop;
// types that should be considered insignificant
let y = 1;
let y = "2";
let y = String::new();
let y = vec![3.0];
let y = HashMap::<usize, usize>::new();
let y = BTreeMap::<usize, usize>::new();
let y = HashSet::<usize>::new();
let y = BTreeSet::<usize>::new();
let y = Box::new(4);
let x = SignificantDrop;
}
async fn in_async() -> &'static str {
async fn f() -> &'static str {
"one"
}
let n = 1;
let a = match n {
1 => f().await,
_ => {
"two"
},
};
a
}
const fn in_const() -> &'static str {
const fn f() -> &'static str {
"one"
}
let n = 1;
let a = match n {
1 => f(),
_ => {
"two"
},
};
a
}
fn does_not_lint() {
let z;
if false {
z = 1;
}
let x;
let y;
if true {
x = 1;
} else {
y = 1;
}
let mut x;
if true {
x = 5;
x = 10 / x;
} else {
x = 2;
}
let x;
let _ = match 1 {
1 => x = 10,
_ => x = 20,
};
// using tuples would be possible, but not always preferable
let x;
let y;
if true {
x = 1;
y = 2;
} else {
x = 3;
y = 4;
}
// could match with a smarter heuristic to avoid multiple assignments
let x;
if true {
let mut y = 5;
y = 6;
x = y;
} else {
x = 2;
}
let (x, y);
if true {
x = 1;
} else {
x = 2;
}
y = 3;
macro_rules! assign {
($i:ident) => {
$i = 1;
};
}
let x;
assign!(x);
let x;
if true {
assign!(x);
} else {
x = 2;
}
macro_rules! in_macro {
() => {
let x;
x = 1;
let x;
if true {
x = 1;
} else {
x = 2;
}
};
}
in_macro!();
// ignore if-lets - https://github.com/rust-lang/rust-clippy/issues/8613
let x;
if let Some(n) = Some("v") {
x = 1;
} else {
x = 2;
}
let x;
if true && let Some(n) = Some("let chains too") {
x = 1;
} else {
x = 2;
}
// ignore mut bindings
// https://github.com/shepmaster/twox-hash/blob/b169c16d86eb8ea4a296b0acb9d00ca7e3c3005f/src/sixty_four.rs#L88-L93
// https://github.com/dtolnay/thiserror/blob/21c26903e29cb92ba1a7ff11e82ae2001646b60d/tests/test_generics.rs#L91-L100
let mut x: usize;
x = 1;
x = 2;
x = 3;
// should not move the declaration if `x` has a significant drop, and there
// is another binding with a significant drop between it and the first usage
let x;
let y = SignificantDrop;
x = SignificantDrop;
}

View file

@ -1,5 +1,6 @@
// run-rustfix
#![feature(let_chains)]
#![allow(unused, clippy::nonminimal_bool, clippy::let_unit_value)]
#![allow(unused, clippy::nonminimal_bool, clippy::let_unit_value, clippy::let_and_return)]
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::rc::Rc;

View file

@ -1,5 +1,5 @@
error: unneeded late initialization
--> $DIR/needless_late_init.rs:15:5
--> $DIR/needless_late_init.rs:16:5
|
LL | let a;
| ^^^^^^
@ -21,7 +21,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:24:5
--> $DIR/needless_late_init.rs:25:5
|
LL | let b;
| ^^^^^^
@ -42,7 +42,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:31:5
--> $DIR/needless_late_init.rs:32:5
|
LL | let d;
| ^^^^^^
@ -63,7 +63,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:39:5
--> $DIR/needless_late_init.rs:40:5
|
LL | let e;
| ^^^^^^
@ -84,7 +84,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:46:5
--> $DIR/needless_late_init.rs:47:5
|
LL | let f;
| ^^^^^^
@ -100,7 +100,7 @@ LL + 1 => "three",
|
error: unneeded late initialization
--> $DIR/needless_late_init.rs:52:5
--> $DIR/needless_late_init.rs:53:5
|
LL | let g: usize;
| ^^^^^^^^^^^^^
@ -120,7 +120,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:60:5
--> $DIR/needless_late_init.rs:61:5
|
LL | let x;
| ^^^^^^ created here
@ -134,7 +134,7 @@ LL | let x = 1;
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:64:5
--> $DIR/needless_late_init.rs:65:5
|
LL | let x;
| ^^^^^^ created here
@ -148,7 +148,7 @@ LL | let x = SignificantDrop;
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:68:5
--> $DIR/needless_late_init.rs:69:5
|
LL | let x;
| ^^^^^^ created here
@ -162,7 +162,7 @@ LL | let x = SignificantDrop;
| ~~~~~
error: unneeded late initialization
--> $DIR/needless_late_init.rs:87:5
--> $DIR/needless_late_init.rs:88:5
|
LL | let a;
| ^^^^^^
@ -183,7 +183,7 @@ LL | };
| +
error: unneeded late initialization
--> $DIR/needless_late_init.rs:104:5
--> $DIR/needless_late_init.rs:105:5
|
LL | let a;
| ^^^^^^

View file

@ -0,0 +1,111 @@
// run-rustfix
#![allow(unused, clippy::diverging_sub_expression)]
#![warn(clippy::nonminimal_bool)]
fn methods_with_negation() {
let a: Option<i32> = unimplemented!();
let b: Result<i32, i32> = unimplemented!();
let _ = a.is_some();
let _ = a.is_none();
let _ = a.is_none();
let _ = a.is_some();
let _ = b.is_err();
let _ = b.is_ok();
let _ = b.is_ok();
let _ = b.is_err();
let c = false;
let _ = a.is_none() || c;
let _ = a.is_none() && c;
let _ = !(!c ^ c) || a.is_none();
let _ = (!c ^ c) || a.is_none();
let _ = !c ^ c || a.is_none();
}
// Simplified versions of https://github.com/rust-lang/rust-clippy/issues/2638
// clippy::nonminimal_bool should only check the built-in Result and Some type, not
// any other types like the following.
enum CustomResultOk<E> {
Ok,
Err(E),
}
enum CustomResultErr<E> {
Ok,
Err(E),
}
enum CustomSomeSome<T> {
Some(T),
None,
}
enum CustomSomeNone<T> {
Some(T),
None,
}
impl<E> CustomResultOk<E> {
pub fn is_ok(&self) -> bool {
true
}
}
impl<E> CustomResultErr<E> {
pub fn is_err(&self) -> bool {
true
}
}
impl<T> CustomSomeSome<T> {
pub fn is_some(&self) -> bool {
true
}
}
impl<T> CustomSomeNone<T> {
pub fn is_none(&self) -> bool {
true
}
}
fn dont_warn_for_custom_methods_with_negation() {
let res = CustomResultOk::Err("Error");
// Should not warn and suggest 'is_err()' because the type does not
// implement is_err().
if !res.is_ok() {}
let res = CustomResultErr::Err("Error");
// Should not warn and suggest 'is_ok()' because the type does not
// implement is_ok().
if !res.is_err() {}
let res = CustomSomeSome::Some("thing");
// Should not warn and suggest 'is_none()' because the type does not
// implement is_none().
if !res.is_some() {}
let res = CustomSomeNone::Some("thing");
// Should not warn and suggest 'is_some()' because the type does not
// implement is_some().
if !res.is_none() {}
}
// Only Built-in Result and Some types should suggest the negated alternative
fn warn_for_built_in_methods_with_negation() {
let res: Result<usize, usize> = Ok(1);
if res.is_err() {}
if res.is_ok() {}
let res = Some(1);
if res.is_none() {}
if res.is_some() {}
}
#[allow(clippy::neg_cmp_op_on_partial_ord)]
fn dont_warn_for_negated_partial_ord_comparison() {
let a: f64 = unimplemented!();
let b: f64 = unimplemented!();
let _ = !(a < b);
let _ = !(a <= b);
let _ = !(a > b);
let _ = !(a >= b);
}
fn main() {}

View file

@ -1,3 +1,4 @@
// run-rustfix
#![allow(unused, clippy::diverging_sub_expression)]
#![warn(clippy::nonminimal_bool)]

View file

@ -1,5 +1,5 @@
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:8:13
--> $DIR/nonminimal_bool_methods.rs:9:13
|
LL | let _ = !a.is_some();
| ^^^^^^^^^^^^ help: try: `a.is_none()`
@ -7,73 +7,73 @@ LL | let _ = !a.is_some();
= note: `-D clippy::nonminimal-bool` implied by `-D warnings`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:10:13
--> $DIR/nonminimal_bool_methods.rs:11:13
|
LL | let _ = !a.is_none();
| ^^^^^^^^^^^^ help: try: `a.is_some()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:12:13
--> $DIR/nonminimal_bool_methods.rs:13:13
|
LL | let _ = !b.is_err();
| ^^^^^^^^^^^ help: try: `b.is_ok()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:14:13
--> $DIR/nonminimal_bool_methods.rs:15:13
|
LL | let _ = !b.is_ok();
| ^^^^^^^^^^ help: try: `b.is_err()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:16:13
--> $DIR/nonminimal_bool_methods.rs:17:13
|
LL | let _ = !(a.is_some() && !c);
| ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() || c`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:17:13
--> $DIR/nonminimal_bool_methods.rs:18:13
|
LL | let _ = !(a.is_some() || !c);
| ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() && c`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:18:26
--> $DIR/nonminimal_bool_methods.rs:19:26
|
LL | let _ = !(!c ^ c) || !a.is_some();
| ^^^^^^^^^^^^ help: try: `a.is_none()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:19:25
--> $DIR/nonminimal_bool_methods.rs:20:25
|
LL | let _ = (!c ^ c) || !a.is_some();
| ^^^^^^^^^^^^ help: try: `a.is_none()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:20:23
--> $DIR/nonminimal_bool_methods.rs:21:23
|
LL | let _ = !c ^ c || !a.is_some();
| ^^^^^^^^^^^^ help: try: `a.is_none()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:92:8
--> $DIR/nonminimal_bool_methods.rs:93:8
|
LL | if !res.is_ok() {}
| ^^^^^^^^^^^^ help: try: `res.is_err()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:93:8
--> $DIR/nonminimal_bool_methods.rs:94:8
|
LL | if !res.is_err() {}
| ^^^^^^^^^^^^^ help: try: `res.is_ok()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:96:8
--> $DIR/nonminimal_bool_methods.rs:97:8
|
LL | if !res.is_some() {}
| ^^^^^^^^^^^^^^ help: try: `res.is_none()`
error: this boolean expression can be simplified
--> $DIR/nonminimal_bool_methods.rs:97:8
--> $DIR/nonminimal_bool_methods.rs:98:8
|
LL | if !res.is_none() {}
| ^^^^^^^^^^^^^^ help: try: `res.is_some()`

28
tests/ui/rc_buffer.fixed Normal file
View file

@ -0,0 +1,28 @@
// run-rustfix
#![warn(clippy::rc_buffer)]
#![allow(dead_code, unused_imports)]
use std::cell::RefCell;
use std::ffi::OsString;
use std::path::PathBuf;
use std::rc::Rc;
struct S {
// triggers lint
bad1: Rc<str>,
bad2: Rc<std::path::Path>,
bad3: Rc<[u8]>,
bad4: Rc<std::ffi::OsStr>,
// does not trigger lint
good1: Rc<RefCell<String>>,
}
// triggers lint
fn func_bad1(_: Rc<str>) {}
fn func_bad2(_: Rc<std::path::Path>) {}
fn func_bad3(_: Rc<[u8]>) {}
fn func_bad4(_: Rc<std::ffi::OsStr>) {}
// does not trigger lint
fn func_good1(_: Rc<RefCell<String>>) {}
fn main() {}

View file

@ -1,4 +1,6 @@
// run-rustfix
#![warn(clippy::rc_buffer)]
#![allow(dead_code, unused_imports)]
use std::cell::RefCell;
use std::ffi::OsString;

View file

@ -1,5 +1,5 @@
error: usage of `Rc<T>` when T is a buffer type
--> $DIR/rc_buffer.rs:10:11
--> $DIR/rc_buffer.rs:12:11
|
LL | bad1: Rc<String>,
| ^^^^^^^^^^ help: try: `Rc<str>`
@ -7,43 +7,43 @@ LL | bad1: Rc<String>,
= note: `-D clippy::rc-buffer` implied by `-D warnings`
error: usage of `Rc<T>` when T is a buffer type
--> $DIR/rc_buffer.rs:11:11
--> $DIR/rc_buffer.rs:13:11
|
LL | bad2: Rc<PathBuf>,
| ^^^^^^^^^^^ help: try: `Rc<std::path::Path>`
error: usage of `Rc<T>` when T is a buffer type
--> $DIR/rc_buffer.rs:12:11
--> $DIR/rc_buffer.rs:14:11
|
LL | bad3: Rc<Vec<u8>>,
| ^^^^^^^^^^^ help: try: `Rc<[u8]>`
error: usage of `Rc<T>` when T is a buffer type
--> $DIR/rc_buffer.rs:13:11
--> $DIR/rc_buffer.rs:15:11
|
LL | bad4: Rc<OsString>,
| ^^^^^^^^^^^^ help: try: `Rc<std::ffi::OsStr>`
error: usage of `Rc<T>` when T is a buffer type
--> $DIR/rc_buffer.rs:19:17
--> $DIR/rc_buffer.rs:21:17
|
LL | fn func_bad1(_: Rc<String>) {}
| ^^^^^^^^^^ help: try: `Rc<str>`
error: usage of `Rc<T>` when T is a buffer type
--> $DIR/rc_buffer.rs:20:17
--> $DIR/rc_buffer.rs:22:17
|
LL | fn func_bad2(_: Rc<PathBuf>) {}
| ^^^^^^^^^^^ help: try: `Rc<std::path::Path>`
error: usage of `Rc<T>` when T is a buffer type
--> $DIR/rc_buffer.rs:21:17
--> $DIR/rc_buffer.rs:23:17
|
LL | fn func_bad3(_: Rc<Vec<u8>>) {}
| ^^^^^^^^^^^ help: try: `Rc<[u8]>`
error: usage of `Rc<T>` when T is a buffer type
--> $DIR/rc_buffer.rs:22:17
--> $DIR/rc_buffer.rs:24:17
|
LL | fn func_bad4(_: Rc<OsString>) {}
| ^^^^^^^^^^^^ help: try: `Rc<std::ffi::OsStr>`

View file

@ -0,0 +1,27 @@
// run-rustfix
#![warn(clippy::rc_buffer)]
#![allow(dead_code, unused_imports)]
use std::ffi::OsString;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
struct S {
// triggers lint
bad1: Arc<str>,
bad2: Arc<std::path::Path>,
bad3: Arc<[u8]>,
bad4: Arc<std::ffi::OsStr>,
// does not trigger lint
good1: Arc<Mutex<String>>,
}
// triggers lint
fn func_bad1(_: Arc<str>) {}
fn func_bad2(_: Arc<std::path::Path>) {}
fn func_bad3(_: Arc<[u8]>) {}
fn func_bad4(_: Arc<std::ffi::OsStr>) {}
// does not trigger lint
fn func_good1(_: Arc<Mutex<String>>) {}
fn main() {}

View file

@ -1,4 +1,6 @@
// run-rustfix
#![warn(clippy::rc_buffer)]
#![allow(dead_code, unused_imports)]
use std::ffi::OsString;
use std::path::PathBuf;

View file

@ -1,5 +1,5 @@
error: usage of `Arc<T>` when T is a buffer type
--> $DIR/rc_buffer_arc.rs:9:11
--> $DIR/rc_buffer_arc.rs:11:11
|
LL | bad1: Arc<String>,
| ^^^^^^^^^^^ help: try: `Arc<str>`
@ -7,43 +7,43 @@ LL | bad1: Arc<String>,
= note: `-D clippy::rc-buffer` implied by `-D warnings`
error: usage of `Arc<T>` when T is a buffer type
--> $DIR/rc_buffer_arc.rs:10:11
--> $DIR/rc_buffer_arc.rs:12:11
|
LL | bad2: Arc<PathBuf>,
| ^^^^^^^^^^^^ help: try: `Arc<std::path::Path>`
error: usage of `Arc<T>` when T is a buffer type
--> $DIR/rc_buffer_arc.rs:11:11
--> $DIR/rc_buffer_arc.rs:13:11
|
LL | bad3: Arc<Vec<u8>>,
| ^^^^^^^^^^^^ help: try: `Arc<[u8]>`
error: usage of `Arc<T>` when T is a buffer type
--> $DIR/rc_buffer_arc.rs:12:11
--> $DIR/rc_buffer_arc.rs:14:11
|
LL | bad4: Arc<OsString>,
| ^^^^^^^^^^^^^ help: try: `Arc<std::ffi::OsStr>`
error: usage of `Arc<T>` when T is a buffer type
--> $DIR/rc_buffer_arc.rs:18:17
--> $DIR/rc_buffer_arc.rs:20:17
|
LL | fn func_bad1(_: Arc<String>) {}
| ^^^^^^^^^^^ help: try: `Arc<str>`
error: usage of `Arc<T>` when T is a buffer type
--> $DIR/rc_buffer_arc.rs:19:17
--> $DIR/rc_buffer_arc.rs:21:17
|
LL | fn func_bad2(_: Arc<PathBuf>) {}
| ^^^^^^^^^^^^ help: try: `Arc<std::path::Path>`
error: usage of `Arc<T>` when T is a buffer type
--> $DIR/rc_buffer_arc.rs:20:17
--> $DIR/rc_buffer_arc.rs:22:17
|
LL | fn func_bad3(_: Arc<Vec<u8>>) {}
| ^^^^^^^^^^^^ help: try: `Arc<[u8]>`
error: usage of `Arc<T>` when T is a buffer type
--> $DIR/rc_buffer_arc.rs:21:17
--> $DIR/rc_buffer_arc.rs:23:17
|
LL | fn func_bad4(_: Arc<OsString>) {}
| ^^^^^^^^^^^^^ help: try: `Arc<std::ffi::OsStr>`

View file

@ -0,0 +1,209 @@
// run-rustfix
#![warn(clippy::suspicious_operation_groupings)]
#![allow(dead_code, unused_parens, clippy::eq_op)]
struct Vec3 {
x: f64,
y: f64,
z: f64,
}
impl Eq for Vec3 {}
impl PartialEq for Vec3 {
fn eq(&self, other: &Self) -> bool {
// This should trigger the lint because `self.x` is compared to `other.y`
self.x == other.x && self.y == other.y && self.z == other.z
}
}
struct S {
a: i32,
b: i32,
c: i32,
d: i32,
}
fn buggy_ab_cmp(s1: &S, s2: &S) -> bool {
// There's no `s1.b`
s1.a < s2.a && s1.b < s2.b
}
struct SaOnly {
a: i32,
}
impl S {
fn a(&self) -> i32 {
0
}
}
fn do_not_give_bad_suggestions_for_this_unusual_expr(s1: &S, s2: &SaOnly) -> bool {
// This is superficially similar to `buggy_ab_cmp`, but we should not suggest
// `s2.b` since that is invalid.
s1.a < s2.a && s1.a() < s1.b
}
fn do_not_give_bad_suggestions_for_this_macro_expr(s1: &S, s2: &SaOnly) -> bool {
macro_rules! s1 {
() => {
S {
a: 1,
b: 1,
c: 1,
d: 1,
}
};
}
// This is superficially similar to `buggy_ab_cmp`, but we should not suggest
// `s2.b` since that is invalid.
s1.a < s2.a && s1!().a < s1.b
}
fn do_not_give_bad_suggestions_for_this_incorrect_expr(s1: &S, s2: &SaOnly) -> bool {
// There's two `s1.b`, but we should not suggest `s2.b` since that is invalid
s1.a < s2.a && s1.b < s1.b
}
fn permissable(s1: &S, s2: &S) -> bool {
// Something like this seems like it might actually be what is desired.
s1.a == s2.b
}
fn non_boolean_operators(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + s1.d * s2.d
}
fn odd_number_of_pairs(s1: &S, s2: &S) -> i32 {
// There's no `s2.b`
s1.a * s2.a + s1.b * s2.b + s1.c * s2.c
}
fn not_caught_by_eq_op_middle_change_left(s1: &S, s2: &S) -> i32 {
// There's no `s1.b`
s1.a * s2.a + s1.b * s2.b + s1.c * s2.c
}
fn not_caught_by_eq_op_middle_change_right(s1: &S, s2: &S) -> i32 {
// There's no `s2.b`
s1.a * s2.a + s1.b * s2.b + s1.c * s2.c
}
fn not_caught_by_eq_op_start(s1: &S, s2: &S) -> i32 {
// There's no `s2.a`
s1.a * s2.a + s1.b * s2.b + s1.c * s2.c
}
fn not_caught_by_eq_op_end(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
s1.a * s2.a + s1.b * s2.b + s1.c * s2.c
}
fn the_cross_product_should_not_lint(s1: &S, s2: &S) -> (i32, i32, i32) {
(
s1.b * s2.c - s1.c * s2.b,
s1.c * s2.a - s1.a * s2.c,
s1.a * s2.b - s1.b * s2.a,
)
}
fn outer_parens_simple(s1: &S, s2: &S) -> i32 {
// There's no `s2.b`
(s1.a * s2.a + s1.b * s2.b)
}
fn outer_parens(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
(s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + s1.d * s2.d)
}
fn inner_parens(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
(s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.c) + (s1.d * s2.d)
}
fn outer_and_some_inner_parens(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.c) + (s1.d * s2.d))
}
fn all_parens_balanced_tree(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
(((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.c) + (s1.d * s2.d)))
}
fn all_parens_left_tree(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
(((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.c)) + (s1.d * s2.d))
}
fn all_parens_right_tree(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.c) + (s1.d * s2.d)))
}
fn inside_other_binop_expression(s1: &S, s2: &S) -> i32 {
// There's no `s1.b`
(s1.a * s2.a + s1.b * s2.b) / 2
}
fn inside_function_call(s1: &S, s2: &S) -> i32 {
// There's no `s1.b`
i32::swap_bytes(s1.a * s2.a + s1.b * s2.b)
}
fn inside_larger_boolean_expression(s1: &S, s2: &S) -> bool {
// There's no `s1.c`
s1.a > 0 && s1.b > 0 && s1.c == s2.c && s1.d == s2.d
}
fn inside_larger_boolean_expression_with_unsorted_ops(s1: &S, s2: &S) -> bool {
// There's no `s1.c`
s1.a > 0 && s1.c == s2.c && s1.b > 0 && s1.d == s2.d
}
struct Nested {
inner: ((i32,), (i32,), (i32,)),
}
fn changed_middle_ident(n1: &Nested, n2: &Nested) -> bool {
// There's no `n2.inner.2.0`
(n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
}
// `eq_op` should catch this one.
fn changed_initial_ident(n1: &Nested, n2: &Nested) -> bool {
// There's no `n2.inner.0.0`
(n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
}
fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool {
if strict {
s1.a < s2.a && s1.b < s2.b
} else {
// There's no `s1.b` in this subexpression
s1.a <= s2.a && s1.b <= s2.b
}
}
fn inside_an_if_statement(s1: &mut S, s2: &S) {
// There's no `s1.b`
if s1.a < s2.a && s1.b < s2.b {
s1.c = s2.c;
}
}
fn maximum_unary_minus_right_tree(s1: &S, s2: &S) -> i32 {
// There's no `s2.c`
-(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.c) + -(-s1.d * -s2.d)))
}
fn unary_minus_and_an_if_expression(s1: &S, s2: &S) -> i32 {
// There's no `s1.b`
-(if -s1.a < -s2.a && -s1.b < -s2.b { s1.c } else { s2.a })
}
fn main() {}

View file

@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::suspicious_operation_groupings)]
#![allow(clippy::eq_op)]
#![allow(dead_code, unused_parens, clippy::eq_op)]
struct Vec3 {
x: f64,

View file

@ -1,5 +1,5 @@
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:15:9
--> $DIR/suspicious_operation_groupings.rs:16:9
|
LL | self.x == other.y && self.y == other.y && self.z == other.z
| ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x`
@ -7,151 +7,151 @@ LL | self.x == other.y && self.y == other.y && self.z == other.z
= note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:28:20
--> $DIR/suspicious_operation_groupings.rs:29:20
|
LL | s1.a < s2.a && s1.a < s2.b
| ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:76:33
--> $DIR/suspicious_operation_groupings.rs:77:33
|
LL | s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:81:19
--> $DIR/suspicious_operation_groupings.rs:82:19
|
LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
| ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:81:19
--> $DIR/suspicious_operation_groupings.rs:82:19
|
LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
| ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:86:19
--> $DIR/suspicious_operation_groupings.rs:87:19
|
LL | s1.a * s2.a + s2.b * s2.b + s1.c * s2.c
| ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:91:19
--> $DIR/suspicious_operation_groupings.rs:92:19
|
LL | s1.a * s2.a + s1.b * s1.b + s1.c * s2.c
| ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:96:5
--> $DIR/suspicious_operation_groupings.rs:97:5
|
LL | s1.a * s1.a + s1.b * s2.b + s1.c * s2.c
| ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:101:33
--> $DIR/suspicious_operation_groupings.rs:102:33
|
LL | s1.a * s2.a + s1.b * s2.b + s1.c * s1.c
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:114:20
--> $DIR/suspicious_operation_groupings.rs:115:20
|
LL | (s1.a * s2.a + s1.b * s1.b)
| ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:119:34
--> $DIR/suspicious_operation_groupings.rs:120:34
|
LL | (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d)
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:124:38
--> $DIR/suspicious_operation_groupings.rs:125:38
|
LL | (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:129:39
--> $DIR/suspicious_operation_groupings.rs:130:39
|
LL | ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:134:42
--> $DIR/suspicious_operation_groupings.rs:135:42
|
LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:134:42
--> $DIR/suspicious_operation_groupings.rs:135:42
|
LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:139:40
--> $DIR/suspicious_operation_groupings.rs:140:40
|
LL | (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d))
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:144:40
--> $DIR/suspicious_operation_groupings.rs:145:40
|
LL | ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)))
| ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:149:20
--> $DIR/suspicious_operation_groupings.rs:150:20
|
LL | (s1.a * s2.a + s2.b * s2.b) / 2
| ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:154:35
--> $DIR/suspicious_operation_groupings.rs:155:35
|
LL | i32::swap_bytes(s1.a * s2.a + s2.b * s2.b)
| ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:159:29
--> $DIR/suspicious_operation_groupings.rs:160:29
|
LL | s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d
| ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:164:17
--> $DIR/suspicious_operation_groupings.rs:165:17
|
LL | s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d
| ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:173:77
--> $DIR/suspicious_operation_groupings.rs:174:77
|
LL | (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:187:25
--> $DIR/suspicious_operation_groupings.rs:188:25
|
LL | s1.a <= s2.a && s1.a <= s2.b
| ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:193:23
--> $DIR/suspicious_operation_groupings.rs:194:23
|
LL | if s1.a < s2.a && s1.a < s2.b {
| ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:200:48
--> $DIR/suspicious_operation_groupings.rs:201:48
|
LL | -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d)))
| ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c`
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:205:27
--> $DIR/suspicious_operation_groupings.rs:206:27
|
LL | -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
| ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b`

36
tests/ui/unicode.fixed Normal file
View file

@ -0,0 +1,36 @@
// run-rustfix
#[warn(clippy::invisible_characters)]
fn zero() {
print!("Here >\u{200B}< is a ZWS, and \u{200B}another");
print!("This\u{200B}is\u{200B}fine");
print!("Here >\u{AD}< is a SHY, and \u{AD}another");
print!("This\u{ad}is\u{ad}fine");
print!("Here >\u{2060}< is a WJ, and \u{2060}another");
print!("This\u{2060}is\u{2060}fine");
}
#[warn(clippy::unicode_not_nfc)]
fn canon() {
print!("̀àh?");
print!("a\u{0300}h?"); // also ok
}
#[warn(clippy::non_ascii_literal)]
fn uni() {
print!("\u{dc}ben!");
print!("\u{DC}ben!"); // this is ok
}
// issue 8013
#[warn(clippy::non_ascii_literal)]
fn single_quote() {
const _EMPTY_BLOCK: char = '\u{25b1}';
const _FULL_BLOCK: char = '\u{25b0}';
}
fn main() {
zero();
uni();
canon();
single_quote();
}

View file

@ -1,3 +1,4 @@
// run-rustfix
#[warn(clippy::invisible_characters)]
fn zero() {
print!("Here >< is a ZWS, and another");

View file

@ -1,5 +1,5 @@
error: invisible character detected
--> $DIR/unicode.rs:3:12
--> $DIR/unicode.rs:4:12
|
LL | print!("Here >< is a ZWS, and another");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{200B}< is a ZWS, and /u{200B}another"`
@ -7,19 +7,19 @@ LL | print!("Here >< is a ZWS, and another");
= note: `-D clippy::invisible-characters` implied by `-D warnings`
error: invisible character detected
--> $DIR/unicode.rs:5:12
--> $DIR/unicode.rs:6:12
|
LL | print!("Here >­< is a SHY, and ­another");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{AD}< is a SHY, and /u{AD}another"`
error: invisible character detected
--> $DIR/unicode.rs:7:12
--> $DIR/unicode.rs:8:12
|
LL | print!("Here >< is a WJ, and another");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{2060}< is a WJ, and /u{2060}another"`
error: non-NFC Unicode sequence detected
--> $DIR/unicode.rs:13:12
--> $DIR/unicode.rs:14:12
|
LL | print!("̀àh?");
| ^^^^^ help: consider replacing the string with: `"̀àh?"`
@ -27,7 +27,7 @@ LL | print!("̀àh?");
= note: `-D clippy::unicode-not-nfc` implied by `-D warnings`
error: literal non-ASCII character detected
--> $DIR/unicode.rs:19:12
--> $DIR/unicode.rs:20:12
|
LL | print!("Üben!");
| ^^^^^^^ help: consider replacing the string with: `"/u{dc}ben!"`
@ -35,13 +35,13 @@ LL | print!("Üben!");
= note: `-D clippy::non-ascii-literal` implied by `-D warnings`
error: literal non-ASCII character detected
--> $DIR/unicode.rs:26:32
--> $DIR/unicode.rs:27:32
|
LL | const _EMPTY_BLOCK: char = '▱';
| ^^^ help: consider replacing the string with: `'/u{25b1}'`
error: literal non-ASCII character detected
--> $DIR/unicode.rs:27:31
--> $DIR/unicode.rs:28:31
|
LL | const _FULL_BLOCK: char = '▰';
| ^^^ help: consider replacing the string with: `'/u{25b0}'`

View file

@ -0,0 +1,30 @@
// run-rustfix
#![warn(clippy::unit_arg)]
#![allow(clippy::no_effect, unused_must_use, unused_variables)]
use std::fmt::Debug;
fn foo<T: Debug>(t: T) {
println!("{:?}", t);
}
fn foo3<T1: Debug, T2: Debug, T3: Debug>(t1: T1, t2: T2, t3: T3) {
println!("{:?}, {:?}, {:?}", t1, t2, t3);
}
fn bad() {
foo(());
foo3((), 2, 2);
foo(0);
taking_two_units((), ());
foo(0);
foo(1);
taking_three_units((), (), ());
}
fn taking_two_units(a: (), b: ()) {}
fn taking_three_units(a: (), b: (), c: ()) {}
fn main() {
bad();
}

View file

@ -1,3 +1,4 @@
// run-rustfix
#![warn(clippy::unit_arg)]
#![allow(clippy::no_effect, unused_must_use, unused_variables)]

View file

@ -1,5 +1,5 @@
error: passing a unit value to a function
--> $DIR/unit_arg_empty_blocks.rs:15:5
--> $DIR/unit_arg_empty_blocks.rs:16:5
|
LL | foo({});
| ^^^^--^
@ -9,7 +9,7 @@ LL | foo({});
= note: `-D clippy::unit-arg` implied by `-D warnings`
error: passing a unit value to a function
--> $DIR/unit_arg_empty_blocks.rs:16:5
--> $DIR/unit_arg_empty_blocks.rs:17:5
|
LL | foo3({}, 2, 2);
| ^^^^^--^^^^^^^
@ -17,7 +17,7 @@ LL | foo3({}, 2, 2);
| help: use a unit literal instead: `()`
error: passing unit values to a function
--> $DIR/unit_arg_empty_blocks.rs:17:5
--> $DIR/unit_arg_empty_blocks.rs:18:5
|
LL | taking_two_units({}, foo(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -29,7 +29,7 @@ LL ~ taking_two_units((), ());
|
error: passing unit values to a function
--> $DIR/unit_arg_empty_blocks.rs:18:5
--> $DIR/unit_arg_empty_blocks.rs:19:5
|
LL | taking_three_units({}, foo(0), foo(1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,40 @@
// run-rustfix
#![warn(clippy::unnecessary_cast)]
#![allow(unused_must_use, clippy::no_effect)]
#[rustfmt::skip]
fn main() {
// Test cast_unnecessary
1_i32;
1_f32;
false;
&1i32 as &i32;
-1_i32;
- 1_i32;
-1_f32;
1_i32;
1_f32;
// macro version
macro_rules! foo {
($a:ident, $b:ident) => {
#[allow(unused)]
pub fn $a() -> $b {
1 as $b
}
};
}
foo!(a, i32);
foo!(b, f32);
foo!(c, f64);
// do not lint cast to cfg-dependant type
1 as std::os::raw::c_char;
// do not lint cast to alias type
1 as I32Alias;
&1 as &I32Alias;
}
type I32Alias = i32;

View file

@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::unnecessary_cast)]
#![allow(clippy::no_effect)]
#![allow(unused_must_use, clippy::no_effect)]
#[rustfmt::skip]
fn main() {

View file

@ -1,5 +1,5 @@
error: casting integer literal to `i32` is unnecessary
--> $DIR/unnecessary_cast.rs:7:5
--> $DIR/unnecessary_cast.rs:8:5
|
LL | 1i32 as i32;
| ^^^^^^^^^^^ help: try: `1_i32`
@ -7,43 +7,43 @@ LL | 1i32 as i32;
= note: `-D clippy::unnecessary-cast` implied by `-D warnings`
error: casting float literal to `f32` is unnecessary
--> $DIR/unnecessary_cast.rs:8:5
--> $DIR/unnecessary_cast.rs:9:5
|
LL | 1f32 as f32;
| ^^^^^^^^^^^ help: try: `1_f32`
error: casting to the same type is unnecessary (`bool` -> `bool`)
--> $DIR/unnecessary_cast.rs:9:5
--> $DIR/unnecessary_cast.rs:10:5
|
LL | false as bool;
| ^^^^^^^^^^^^^ help: try: `false`
error: casting integer literal to `i32` is unnecessary
--> $DIR/unnecessary_cast.rs:12:5
--> $DIR/unnecessary_cast.rs:13:5
|
LL | -1_i32 as i32;
| ^^^^^^^^^^^^^ help: try: `-1_i32`
error: casting integer literal to `i32` is unnecessary
--> $DIR/unnecessary_cast.rs:13:5
--> $DIR/unnecessary_cast.rs:14:5
|
LL | - 1_i32 as i32;
| ^^^^^^^^^^^^^^ help: try: `- 1_i32`
error: casting float literal to `f32` is unnecessary
--> $DIR/unnecessary_cast.rs:14:5
--> $DIR/unnecessary_cast.rs:15:5
|
LL | -1f32 as f32;
| ^^^^^^^^^^^^ help: try: `-1_f32`
error: casting integer literal to `i32` is unnecessary
--> $DIR/unnecessary_cast.rs:15:5
--> $DIR/unnecessary_cast.rs:16:5
|
LL | 1_i32 as i32;
| ^^^^^^^^^^^^ help: try: `1_i32`
error: casting float literal to `f32` is unnecessary
--> $DIR/unnecessary_cast.rs:16:5
--> $DIR/unnecessary_cast.rs:17:5
|
LL | 1_f32 as f32;
| ^^^^^^^^^^^^ help: try: `1_f32`