Merge remote-tracking branch 'upstream/master' into rustup

This commit is contained in:
flip1995 2021-01-15 10:02:28 +01:00
commit 9bd037d0b5
No known key found for this signature in database
GPG key ID: 1CA0DF2AF59D68A5
105 changed files with 2300 additions and 270 deletions

View file

@ -94,3 +94,19 @@ macro_rules! large_enum_variant {
}
};
}
#[macro_export]
macro_rules! field_reassign_with_default {
() => {
#[derive(Default)]
struct A {
pub i: i32,
pub j: i64,
}
fn lint() {
let mut a: A = Default::default();
a.i = 42;
a;
}
};
}

View file

@ -4,6 +4,7 @@
#![crate_type = "proc-macro"]
#![feature(repr128, proc_macro_quote)]
#![allow(incomplete_features)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::eq_op)]
extern crate proc_macro;
@ -23,3 +24,20 @@ pub fn derive(_: TokenStream) -> TokenStream {
};
output
}
#[proc_macro_derive(FieldReassignWithDefault)]
pub fn derive_foo(_input: TokenStream) -> TokenStream {
quote! {
#[derive(Default)]
struct A {
pub i: i32,
pub j: i64,
}
#[automatically_derived]
fn lint() {
let mut a: A = Default::default();
a.i = 42;
a;
}
}
}

View file

@ -12,6 +12,10 @@ fn main() {
(&1u8 as *const u8) as *const u16;
(&mut 1u8 as *mut u8) as *mut u16;
// cast to more-strictly-aligned type, but with the `pointer::cast` function.
(&1u8 as *const u8).cast::<u16>();
(&mut 1u8 as *mut u8).cast::<u16>();
/* These should be ok */
// not a pointer type

View file

@ -12,5 +12,17 @@ error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1
LL | (&mut 1u8 as *mut u8) as *mut u16;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes)
--> $DIR/cast_alignment.rs:16:5
|
LL | (&1u8 as *const u8).cast::<u16>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes)
--> $DIR/cast_alignment.rs:17:5
|
LL | (&mut 1u8 as *mut u8).cast::<u16>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors

View file

@ -5,7 +5,8 @@
clippy::redundant_clone,
clippy::deref_addrof,
clippy::no_effect,
clippy::unnecessary_operation
clippy::unnecessary_operation,
clippy::vec_init_then_push
)]
use std::cell::RefCell;

View file

@ -5,7 +5,8 @@
clippy::redundant_clone,
clippy::deref_addrof,
clippy::no_effect,
clippy::unnecessary_operation
clippy::unnecessary_operation,
clippy::vec_init_then_push
)]
use std::cell::RefCell;

View file

@ -1,5 +1,5 @@
error: using `clone` on type `i32` which implements the `Copy` trait
--> $DIR/clone_on_copy.rs:22:5
--> $DIR/clone_on_copy.rs:23:5
|
LL | 42.clone();
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
@ -7,25 +7,25 @@ LL | 42.clone();
= note: `-D clippy::clone-on-copy` implied by `-D warnings`
error: using `clone` on type `i32` which implements the `Copy` trait
--> $DIR/clone_on_copy.rs:26:5
--> $DIR/clone_on_copy.rs:27:5
|
LL | (&42).clone();
| ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)`
error: using `clone` on type `i32` which implements the `Copy` trait
--> $DIR/clone_on_copy.rs:29:5
--> $DIR/clone_on_copy.rs:30:5
|
LL | rc.borrow().clone();
| ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()`
error: using `clone` on type `char` which implements the `Copy` trait
--> $DIR/clone_on_copy.rs:35:14
--> $DIR/clone_on_copy.rs:36:14
|
LL | is_ascii('z'.clone());
| ^^^^^^^^^^^ help: try removing the `clone` call: `'z'`
error: using `clone` on type `i32` which implements the `Copy` trait
--> $DIR/clone_on_copy.rs:39:14
--> $DIR/clone_on_copy.rs:40:14
|
LL | vec.push(42.clone());
| ^^^^^^^^^^ help: try removing the `clone` call: `42`

View file

@ -3,6 +3,8 @@
#[rustfmt::skip]
#[warn(clippy::collapsible_if)]
#[warn(clippy::collapsible_else_if)]
fn main() {
let x = "hello";
let y = "world";

View file

@ -3,6 +3,8 @@
#[rustfmt::skip]
#[warn(clippy::collapsible_if)]
#[warn(clippy::collapsible_else_if)]
fn main() {
let x = "hello";
let y = "world";

View file

@ -1,5 +1,5 @@
error: this `else { if .. }` block can be collapsed
--> $DIR/collapsible_else_if.rs:12:12
--> $DIR/collapsible_else_if.rs:14:12
|
LL | } else {
| ____________^
@ -9,7 +9,7 @@ LL | | }
LL | | }
| |_____^
|
= note: `-D clippy::collapsible-if` implied by `-D warnings`
= note: `-D clippy::collapsible-else-if` implied by `-D warnings`
help: collapse nested if block
|
LL | } else if y == "world" {
@ -18,7 +18,7 @@ LL | }
|
error: this `else { if .. }` block can be collapsed
--> $DIR/collapsible_else_if.rs:20:12
--> $DIR/collapsible_else_if.rs:22:12
|
LL | } else {
| ____________^
@ -36,7 +36,7 @@ LL | }
|
error: this `else { if .. }` block can be collapsed
--> $DIR/collapsible_else_if.rs:28:12
--> $DIR/collapsible_else_if.rs:30:12
|
LL | } else {
| ____________^
@ -59,7 +59,7 @@ LL | }
|
error: this `else { if .. }` block can be collapsed
--> $DIR/collapsible_else_if.rs:39:12
--> $DIR/collapsible_else_if.rs:41:12
|
LL | } else {
| ____________^
@ -82,7 +82,7 @@ LL | }
|
error: this `else { if .. }` block can be collapsed
--> $DIR/collapsible_else_if.rs:50:12
--> $DIR/collapsible_else_if.rs:52:12
|
LL | } else {
| ____________^
@ -105,7 +105,7 @@ LL | }
|
error: this `else { if .. }` block can be collapsed
--> $DIR/collapsible_else_if.rs:61:12
--> $DIR/collapsible_else_if.rs:63:12
|
LL | } else {
| ____________^
@ -128,7 +128,7 @@ LL | }
|
error: this `else { if .. }` block can be collapsed
--> $DIR/collapsible_else_if.rs:72:12
--> $DIR/collapsible_else_if.rs:74:12
|
LL | } else {
| ____________^

View file

@ -1,6 +1,7 @@
#![allow(dead_code)]
#![warn(clippy::empty_enum)]
// Enable never type to test empty enum lint
#![feature(never_type)]
enum Empty {}
fn main() {}

View file

@ -1,5 +1,5 @@
error: enum with no variants
--> $DIR/empty_enum.rs:4:1
--> $DIR/empty_enum.rs:5:1
|
LL | enum Empty {}
| ^^^^^^^^^^^^^

View file

@ -0,0 +1,7 @@
#![allow(dead_code)]
#![warn(clippy::empty_enum)]
// `never_type` is not enabled; this test has no stderr file
enum Empty {}
fn main() {}

View file

@ -182,3 +182,23 @@ pub extern "C" fn do_not_warn_me(_c_pointer: Box<String>) -> () {}
#[rustfmt::skip] // Forces rustfmt to not add ABI
pub extern fn do_not_warn_me_no_abi(_c_pointer: Box<String>) -> () {}
// Issue #4804 - default implementation in trait
mod issue4804 {
trait DefaultTraitImplTest {
// don't warn on `self`
fn default_impl(self: Box<Self>) -> u32 {
5
}
// warn on `x: Box<u32>`
fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
4
}
}
trait WarnTrait {
// warn on `x: Box<u32>`
fn foo(x: Box<u32>) {}
}
}

View file

@ -12,5 +12,17 @@ error: local variable doesn't need to be boxed here
LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
| ^^^^^^^^^^^
error: aborting due to 2 previous errors
error: local variable doesn't need to be boxed here
--> $DIR/escape_analysis.rs:195:44
|
LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
| ^
error: local variable doesn't need to be boxed here
--> $DIR/escape_analysis.rs:202:16
|
LL | fn foo(x: Box<u32>) {}
| ^
error: aborting due to 4 previous errors

View file

@ -1,5 +1,18 @@
// aux-build:proc_macro_derive.rs
// aux-build:macro_rules.rs
#![warn(clippy::field_reassign_with_default)]
#[macro_use]
extern crate proc_macro_derive;
#[macro_use]
extern crate macro_rules;
// Don't lint on derives that derive `Default`
// See https://github.com/rust-lang/rust-clippy/issues/6545
#[derive(FieldReassignWithDefault)]
struct DerivedStruct;
#[derive(Default)]
struct A {
i: i32,
@ -11,6 +24,11 @@ struct B {
j: i64,
}
#[derive(Default)]
struct C {
i: Vec<i32>,
j: i64,
}
/// Implements .next() that returns a different number each time.
struct SideEffect(i32);
@ -111,6 +129,13 @@ fn main() {
// don't lint - some private fields
let mut x = m::F::default();
x.a = 1;
// don't expand macros in the suggestion (#6522)
let mut a: C = C::default();
a.i = vec![1];
// Don't lint in external macros
field_reassign_with_default!();
}
mod m {

View file

@ -1,75 +1,87 @@
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:30:5
--> $DIR/field_reassign_with_default.rs:48:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
= note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
note: consider initializing the variable with `A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:29:5
note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:47:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:70:5
--> $DIR/field_reassign_with_default.rs:88:5
|
LL | a.j = 43;
| ^^^^^^^^^
|
note: consider initializing the variable with `A { j: 43, i: 42 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:69:5
note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:87:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:75:5
--> $DIR/field_reassign_with_default.rs:93:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
note: consider initializing the variable with `A { i: 42, j: 44 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:74:5
note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:92:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:81:5
--> $DIR/field_reassign_with_default.rs:99:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
note: consider initializing the variable with `A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:80:5
note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:98:5
|
LL | let mut a = A::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:91:5
--> $DIR/field_reassign_with_default.rs:109:5
|
LL | a.i = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: consider initializing the variable with `A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:90:5
note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:108:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:95:5
--> $DIR/field_reassign_with_default.rs:113:5
|
LL | a.i = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: consider initializing the variable with `A { i: Default::default(), j: 45 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:94:5
note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:112:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:135:5
|
LL | a.i = vec![1];
| ^^^^^^^^^^^^^^
|
note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:134:5
|
LL | let mut a: C = C::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 7 previous errors

View file

@ -1,12 +1,8 @@
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
--> $DIR/from_over_into.rs:6:1
|
LL | / impl Into<StringWrapper> for String {
LL | | fn into(self) -> StringWrapper {
LL | | StringWrapper(self)
LL | | }
LL | | }
| |_^
LL | impl Into<StringWrapper> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::from-over-into` implied by `-D warnings`
= help: consider to implement `From` instead

View file

@ -1,6 +1,7 @@
#![warn(clippy::if_same_then_else)]
#![allow(
clippy::blacklisted_name,
clippy::collapsible_else_if,
clippy::collapsible_if,
clippy::ifs_same_cond,
clippy::needless_return,

View file

@ -1,5 +1,5 @@
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:20:12
--> $DIR/if_same_then_else2.rs:21:12
|
LL | } else {
| ____________^
@ -13,7 +13,7 @@ LL | | }
|
= note: `-D clippy::if-same-then-else` implied by `-D warnings`
note: same as this
--> $DIR/if_same_then_else2.rs:11:13
--> $DIR/if_same_then_else2.rs:12:13
|
LL | if true {
| _____________^
@ -26,7 +26,7 @@ LL | | } else {
| |_____^
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:34:12
--> $DIR/if_same_then_else2.rs:35:12
|
LL | } else {
| ____________^
@ -36,7 +36,7 @@ LL | | }
| |_____^
|
note: same as this
--> $DIR/if_same_then_else2.rs:32:13
--> $DIR/if_same_then_else2.rs:33:13
|
LL | if true {
| _____________^
@ -45,7 +45,7 @@ LL | | } else {
| |_____^
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:41:12
--> $DIR/if_same_then_else2.rs:42:12
|
LL | } else {
| ____________^
@ -55,7 +55,7 @@ LL | | }
| |_____^
|
note: same as this
--> $DIR/if_same_then_else2.rs:39:13
--> $DIR/if_same_then_else2.rs:40:13
|
LL | if true {
| _____________^
@ -64,7 +64,7 @@ LL | | } else {
| |_____^
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:91:12
--> $DIR/if_same_then_else2.rs:92:12
|
LL | } else {
| ____________^
@ -74,7 +74,7 @@ LL | | };
| |_____^
|
note: same as this
--> $DIR/if_same_then_else2.rs:89:21
--> $DIR/if_same_then_else2.rs:90:21
|
LL | let _ = if true {
| _____________________^
@ -83,7 +83,7 @@ LL | | } else {
| |_____^
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:98:12
--> $DIR/if_same_then_else2.rs:99:12
|
LL | } else {
| ____________^
@ -93,7 +93,7 @@ LL | | }
| |_____^
|
note: same as this
--> $DIR/if_same_then_else2.rs:96:13
--> $DIR/if_same_then_else2.rs:97:13
|
LL | if true {
| _____________^
@ -102,7 +102,7 @@ LL | | } else {
| |_____^
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:123:12
--> $DIR/if_same_then_else2.rs:124:12
|
LL | } else {
| ____________^
@ -112,7 +112,7 @@ LL | | }
| |_____^
|
note: same as this
--> $DIR/if_same_then_else2.rs:120:20
--> $DIR/if_same_then_else2.rs:121:20
|
LL | } else if true {
| ____________________^

View file

@ -0,0 +1,163 @@
// run-rustfix
#![warn(clippy::needless_question_mark)]
#![allow(clippy::needless_return, clippy::unnecessary_unwrap, dead_code, unused_must_use)]
#![feature(custom_inner_attributes)]
struct TO {
magic: Option<usize>,
}
struct TR {
magic: Result<usize, bool>,
}
fn simple_option_bad1(to: TO) -> Option<usize> {
// return as a statement
return to.magic;
}
// formatting will add a semi-colon, which would make
// this identical to the test case above
#[rustfmt::skip]
fn simple_option_bad2(to: TO) -> Option<usize> {
// return as an expression
return to.magic
}
fn simple_option_bad3(to: TO) -> Option<usize> {
// block value "return"
to.magic
}
fn simple_option_bad4(to: Option<TO>) -> Option<usize> {
// single line closure
to.and_then(|t| t.magic)
}
// formatting this will remove the block brackets, making
// this test identical to the one above
#[rustfmt::skip]
fn simple_option_bad5(to: Option<TO>) -> Option<usize> {
// closure with body
to.and_then(|t| {
t.magic
})
}
fn simple_result_bad1(tr: TR) -> Result<usize, bool> {
return tr.magic;
}
// formatting will add a semi-colon, which would make
// this identical to the test case above
#[rustfmt::skip]
fn simple_result_bad2(tr: TR) -> Result<usize, bool> {
return tr.magic
}
fn simple_result_bad3(tr: TR) -> Result<usize, bool> {
tr.magic
}
fn simple_result_bad4(tr: Result<TR, bool>) -> Result<usize, bool> {
tr.and_then(|t| t.magic)
}
// formatting this will remove the block brackets, making
// this test identical to the one above
#[rustfmt::skip]
fn simple_result_bad5(tr: Result<TR, bool>) -> Result<usize, bool> {
tr.and_then(|t| {
t.magic
})
}
fn also_bad(tr: Result<TR, bool>) -> Result<usize, bool> {
if tr.is_ok() {
let t = tr.unwrap();
return t.magic;
}
Err(false)
}
fn false_positive_test<U, T>(x: Result<(), U>) -> Result<(), T>
where
T: From<U>,
{
Ok(x?)
}
fn main() {}
mod question_mark_none {
#![clippy::msrv = "1.12.0"]
fn needless_question_mark_option() -> Option<usize> {
struct TO {
magic: Option<usize>,
}
let to = TO { magic: None };
Some(to.magic?) // should not be triggered
}
fn needless_question_mark_result() -> Result<usize, bool> {
struct TO {
magic: Result<usize, bool>,
}
let to = TO { magic: Ok(1_usize) };
Ok(to.magic?) // should not be triggered
}
fn main() {
needless_question_mark_option();
needless_question_mark_result();
}
}
mod question_mark_result {
#![clippy::msrv = "1.21.0"]
fn needless_question_mark_option() -> Option<usize> {
struct TO {
magic: Option<usize>,
}
let to = TO { magic: None };
Some(to.magic?) // should not be triggered
}
fn needless_question_mark_result() -> Result<usize, bool> {
struct TO {
magic: Result<usize, bool>,
}
let to = TO { magic: Ok(1_usize) };
to.magic // should be triggered
}
fn main() {
needless_question_mark_option();
needless_question_mark_result();
}
}
mod question_mark_both {
#![clippy::msrv = "1.22.0"]
fn needless_question_mark_option() -> Option<usize> {
struct TO {
magic: Option<usize>,
}
let to = TO { magic: None };
to.magic // should be triggered
}
fn needless_question_mark_result() -> Result<usize, bool> {
struct TO {
magic: Result<usize, bool>,
}
let to = TO { magic: Ok(1_usize) };
to.magic // should be triggered
}
fn main() {
needless_question_mark_option();
needless_question_mark_result();
}
}

View file

@ -0,0 +1,163 @@
// run-rustfix
#![warn(clippy::needless_question_mark)]
#![allow(clippy::needless_return, clippy::unnecessary_unwrap, dead_code, unused_must_use)]
#![feature(custom_inner_attributes)]
struct TO {
magic: Option<usize>,
}
struct TR {
magic: Result<usize, bool>,
}
fn simple_option_bad1(to: TO) -> Option<usize> {
// return as a statement
return Some(to.magic?);
}
// formatting will add a semi-colon, which would make
// this identical to the test case above
#[rustfmt::skip]
fn simple_option_bad2(to: TO) -> Option<usize> {
// return as an expression
return Some(to.magic?)
}
fn simple_option_bad3(to: TO) -> Option<usize> {
// block value "return"
Some(to.magic?)
}
fn simple_option_bad4(to: Option<TO>) -> Option<usize> {
// single line closure
to.and_then(|t| Some(t.magic?))
}
// formatting this will remove the block brackets, making
// this test identical to the one above
#[rustfmt::skip]
fn simple_option_bad5(to: Option<TO>) -> Option<usize> {
// closure with body
to.and_then(|t| {
Some(t.magic?)
})
}
fn simple_result_bad1(tr: TR) -> Result<usize, bool> {
return Ok(tr.magic?);
}
// formatting will add a semi-colon, which would make
// this identical to the test case above
#[rustfmt::skip]
fn simple_result_bad2(tr: TR) -> Result<usize, bool> {
return Ok(tr.magic?)
}
fn simple_result_bad3(tr: TR) -> Result<usize, bool> {
Ok(tr.magic?)
}
fn simple_result_bad4(tr: Result<TR, bool>) -> Result<usize, bool> {
tr.and_then(|t| Ok(t.magic?))
}
// formatting this will remove the block brackets, making
// this test identical to the one above
#[rustfmt::skip]
fn simple_result_bad5(tr: Result<TR, bool>) -> Result<usize, bool> {
tr.and_then(|t| {
Ok(t.magic?)
})
}
fn also_bad(tr: Result<TR, bool>) -> Result<usize, bool> {
if tr.is_ok() {
let t = tr.unwrap();
return Ok(t.magic?);
}
Err(false)
}
fn false_positive_test<U, T>(x: Result<(), U>) -> Result<(), T>
where
T: From<U>,
{
Ok(x?)
}
fn main() {}
mod question_mark_none {
#![clippy::msrv = "1.12.0"]
fn needless_question_mark_option() -> Option<usize> {
struct TO {
magic: Option<usize>,
}
let to = TO { magic: None };
Some(to.magic?) // should not be triggered
}
fn needless_question_mark_result() -> Result<usize, bool> {
struct TO {
magic: Result<usize, bool>,
}
let to = TO { magic: Ok(1_usize) };
Ok(to.magic?) // should not be triggered
}
fn main() {
needless_question_mark_option();
needless_question_mark_result();
}
}
mod question_mark_result {
#![clippy::msrv = "1.21.0"]
fn needless_question_mark_option() -> Option<usize> {
struct TO {
magic: Option<usize>,
}
let to = TO { magic: None };
Some(to.magic?) // should not be triggered
}
fn needless_question_mark_result() -> Result<usize, bool> {
struct TO {
magic: Result<usize, bool>,
}
let to = TO { magic: Ok(1_usize) };
Ok(to.magic?) // should be triggered
}
fn main() {
needless_question_mark_option();
needless_question_mark_result();
}
}
mod question_mark_both {
#![clippy::msrv = "1.22.0"]
fn needless_question_mark_option() -> Option<usize> {
struct TO {
magic: Option<usize>,
}
let to = TO { magic: None };
Some(to.magic?) // should be triggered
}
fn needless_question_mark_result() -> Result<usize, bool> {
struct TO {
magic: Result<usize, bool>,
}
let to = TO { magic: Ok(1_usize) };
Ok(to.magic?) // should be triggered
}
fn main() {
needless_question_mark_option();
needless_question_mark_result();
}
}

View file

@ -0,0 +1,88 @@
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:17:12
|
LL | return Some(to.magic?);
| ^^^^^^^^^^^^^^^ help: try: `to.magic`
|
= note: `-D clippy::needless-question-mark` implied by `-D warnings`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:25:12
|
LL | return Some(to.magic?)
| ^^^^^^^^^^^^^^^ help: try: `to.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:30:5
|
LL | Some(to.magic?)
| ^^^^^^^^^^^^^^^ help: try: `to.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:35:21
|
LL | to.and_then(|t| Some(t.magic?))
| ^^^^^^^^^^^^^^ help: try: `t.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:44:9
|
LL | Some(t.magic?)
| ^^^^^^^^^^^^^^ help: try: `t.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:49:12
|
LL | return Ok(tr.magic?);
| ^^^^^^^^^^^^^ help: try: `tr.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:56:12
|
LL | return Ok(tr.magic?)
| ^^^^^^^^^^^^^ help: try: `tr.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:60:5
|
LL | Ok(tr.magic?)
| ^^^^^^^^^^^^^ help: try: `tr.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:64:21
|
LL | tr.and_then(|t| Ok(t.magic?))
| ^^^^^^^^^^^^ help: try: `t.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:72:9
|
LL | Ok(t.magic?)
| ^^^^^^^^^^^^ help: try: `t.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:79:16
|
LL | return Ok(t.magic?);
| ^^^^^^^^^^^^ help: try: `t.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:132:9
|
LL | Ok(to.magic?) // should be triggered
| ^^^^^^^^^^^^^ help: try: `to.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:148:9
|
LL | Some(to.magic?) // should be triggered
| ^^^^^^^^^^^^^^^ help: try: `to.magic`
error: Question mark operator is useless here
--> $DIR/needless_question_mark.rs:156:9
|
LL | Ok(to.magic?) // should be triggered
| ^^^^^^^^^^^^^ help: try: `to.magic`
error: aborting due to 14 previous errors

50
tests/ui/ptr_as_ptr.fixed Normal file
View file

@ -0,0 +1,50 @@
// run-rustfix
#![warn(clippy::ptr_as_ptr)]
#![feature(custom_inner_attributes)]
fn main() {
let ptr: *const u32 = &42_u32;
let mut_ptr: *mut u32 = &mut 42_u32;
let _ = ptr.cast::<i32>();
let _ = mut_ptr.cast::<i32>();
// Make sure the lint can handle the difference in their operator precedences.
unsafe {
let ptr_ptr: *const *const u32 = &ptr;
let _ = (*ptr_ptr).cast::<i32>();
}
// Changes in mutability. Do not lint this.
let _ = ptr as *mut i32;
let _ = mut_ptr as *const i32;
// `pointer::cast` cannot perform unsized coercions unlike `as`. Do not lint this.
let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4];
let _ = ptr_of_array as *const [u32];
let _ = ptr_of_array as *const dyn std::fmt::Debug;
// Ensure the lint doesn't produce unnecessary turbofish for inferred types.
let _: *const i32 = ptr.cast();
let _: *mut i32 = mut_ptr.cast();
}
fn _msrv_1_37() {
#![clippy::msrv = "1.37"]
let ptr: *const u32 = &42_u32;
let mut_ptr: *mut u32 = &mut 42_u32;
// `pointer::cast` was stabilized in 1.38. Do not lint this
let _ = ptr as *const i32;
let _ = mut_ptr as *mut i32;
}
fn _msrv_1_38() {
#![clippy::msrv = "1.38"]
let ptr: *const u32 = &42_u32;
let mut_ptr: *mut u32 = &mut 42_u32;
let _ = ptr.cast::<i32>();
let _ = mut_ptr.cast::<i32>();
}

50
tests/ui/ptr_as_ptr.rs Normal file
View file

@ -0,0 +1,50 @@
// run-rustfix
#![warn(clippy::ptr_as_ptr)]
#![feature(custom_inner_attributes)]
fn main() {
let ptr: *const u32 = &42_u32;
let mut_ptr: *mut u32 = &mut 42_u32;
let _ = ptr as *const i32;
let _ = mut_ptr as *mut i32;
// Make sure the lint can handle the difference in their operator precedences.
unsafe {
let ptr_ptr: *const *const u32 = &ptr;
let _ = *ptr_ptr as *const i32;
}
// Changes in mutability. Do not lint this.
let _ = ptr as *mut i32;
let _ = mut_ptr as *const i32;
// `pointer::cast` cannot perform unsized coercions unlike `as`. Do not lint this.
let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4];
let _ = ptr_of_array as *const [u32];
let _ = ptr_of_array as *const dyn std::fmt::Debug;
// Ensure the lint doesn't produce unnecessary turbofish for inferred types.
let _: *const i32 = ptr as *const _;
let _: *mut i32 = mut_ptr as _;
}
fn _msrv_1_37() {
#![clippy::msrv = "1.37"]
let ptr: *const u32 = &42_u32;
let mut_ptr: *mut u32 = &mut 42_u32;
// `pointer::cast` was stabilized in 1.38. Do not lint this
let _ = ptr as *const i32;
let _ = mut_ptr as *mut i32;
}
fn _msrv_1_38() {
#![clippy::msrv = "1.38"]
let ptr: *const u32 = &42_u32;
let mut_ptr: *mut u32 = &mut 42_u32;
let _ = ptr as *const i32;
let _ = mut_ptr as *mut i32;
}

View file

@ -0,0 +1,46 @@
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:10:13
|
LL | let _ = ptr as *const i32;
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
|
= note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:11:13
|
LL | let _ = mut_ptr as *mut i32;
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:16:17
|
LL | let _ = *ptr_ptr as *const i32;
| ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:29:25
|
LL | let _: *const i32 = ptr as *const _;
| ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:30:23
|
LL | let _: *mut i32 = mut_ptr as _;
| ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:48:13
|
LL | let _ = ptr as *const i32;
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
error: `as` casting between raw pointers without changing its mutability
--> $DIR/ptr_as_ptr.rs:49:13
|
LL | let _ = mut_ptr as *mut i32;
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
error: aborting due to 7 previous errors

View file

@ -1,5 +1,4 @@
#![warn(clippy::temporary_assignment)]
#![allow(const_item_mutation)]
use std::ops::{Deref, DerefMut};

View file

@ -1,5 +1,5 @@
error: assignment to temporary
--> $DIR/temporary_assignment.rs:48:5
--> $DIR/temporary_assignment.rs:47:5
|
LL | Struct { field: 0 }.field = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -7,7 +7,7 @@ LL | Struct { field: 0 }.field = 1;
= note: `-D clippy::temporary-assignment` implied by `-D warnings`
error: assignment to temporary
--> $DIR/temporary_assignment.rs:49:5
--> $DIR/temporary_assignment.rs:48:5
|
LL | / MultiStruct {
LL | | structure: Struct { field: 0 },
@ -17,13 +17,13 @@ LL | | .field = 1;
| |______________^
error: assignment to temporary
--> $DIR/temporary_assignment.rs:54:5
--> $DIR/temporary_assignment.rs:53:5
|
LL | ArrayStruct { array: [0] }.array[0] = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: assignment to temporary
--> $DIR/temporary_assignment.rs:55:5
--> $DIR/temporary_assignment.rs:54:5
|
LL | (0, 0).0 = 1;
| ^^^^^^^^^^^^

View file

@ -2,7 +2,7 @@
// aux-build:macro_rules.rs
#![deny(clippy::try_err)]
#![allow(clippy::unnecessary_wraps)]
#![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
#[macro_use]
extern crate macro_rules;

View file

@ -2,7 +2,7 @@
// aux-build:macro_rules.rs
#![deny(clippy::try_err)]
#![allow(clippy::unnecessary_wraps)]
#![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
#[macro_use]
extern crate macro_rules;

View file

@ -5,7 +5,8 @@
unused_variables,
clippy::unused_unit,
clippy::unnecessary_wraps,
clippy::or_fun_call
clippy::or_fun_call,
clippy::needless_question_mark
)]
use std::fmt::Debug;

View file

@ -1,5 +1,5 @@
error: passing a unit value to a function
--> $DIR/unit_arg.rs:30:5
--> $DIR/unit_arg.rs:31:5
|
LL | / foo({
LL | | 1;
@ -20,7 +20,7 @@ LL | foo(());
|
error: passing a unit value to a function
--> $DIR/unit_arg.rs:33:5
--> $DIR/unit_arg.rs:34:5
|
LL | foo(foo(1));
| ^^^^^^^^^^^
@ -32,7 +32,7 @@ LL | foo(());
|
error: passing a unit value to a function
--> $DIR/unit_arg.rs:34:5
--> $DIR/unit_arg.rs:35:5
|
LL | / foo({
LL | | foo(1);
@ -54,7 +54,7 @@ LL | foo(());
|
error: passing a unit value to a function
--> $DIR/unit_arg.rs:39:5
--> $DIR/unit_arg.rs:40:5
|
LL | / b.bar({
LL | | 1;
@ -74,7 +74,7 @@ LL | b.bar(());
|
error: passing unit values to a function
--> $DIR/unit_arg.rs:42:5
--> $DIR/unit_arg.rs:43:5
|
LL | taking_multiple_units(foo(0), foo(1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -87,7 +87,7 @@ LL | taking_multiple_units((), ());
|
error: passing unit values to a function
--> $DIR/unit_arg.rs:43:5
--> $DIR/unit_arg.rs:44:5
|
LL | / taking_multiple_units(foo(0), {
LL | | foo(1);
@ -110,7 +110,7 @@ LL | taking_multiple_units((), ());
|
error: passing unit values to a function
--> $DIR/unit_arg.rs:47:5
--> $DIR/unit_arg.rs:48:5
|
LL | / taking_multiple_units(
LL | | {
@ -140,7 +140,7 @@ LL | foo(2);
...
error: passing a unit value to a function
--> $DIR/unit_arg.rs:58:13
--> $DIR/unit_arg.rs:59:13
|
LL | None.or(Some(foo(2)));
| ^^^^^^^^^^^^
@ -154,7 +154,7 @@ LL | });
|
error: passing a unit value to a function
--> $DIR/unit_arg.rs:61:5
--> $DIR/unit_arg.rs:62:5
|
LL | foo(foo(()))
| ^^^^^^^^^^^^
@ -166,7 +166,7 @@ LL | foo(())
|
error: passing a unit value to a function
--> $DIR/unit_arg.rs:94:5
--> $DIR/unit_arg.rs:95:5
|
LL | Some(foo(1))
| ^^^^^^^^^^^^

View file

@ -0,0 +1,21 @@
#![allow(unused_variables)]
#![warn(clippy::vec_init_then_push)]
fn main() {
let mut def_err: Vec<u32> = Default::default();
def_err.push(0);
let mut new_err = Vec::<u32>::new();
new_err.push(1);
let mut cap_err = Vec::with_capacity(2);
cap_err.push(0);
cap_err.push(1);
cap_err.push(2);
let mut cap_ok = Vec::with_capacity(10);
cap_ok.push(0);
new_err = Vec::new();
new_err.push(0);
}

View file

@ -0,0 +1,34 @@
error: calls to `push` immediately after creation
--> $DIR/vec_init_then_push.rs:5:5
|
LL | / let mut def_err: Vec<u32> = Default::default();
LL | | def_err.push(0);
| |____________________^ help: consider using the `vec![]` macro: `let mut def_err: Vec<u32> = vec![..];`
|
= note: `-D clippy::vec-init-then-push` implied by `-D warnings`
error: calls to `push` immediately after creation
--> $DIR/vec_init_then_push.rs:8:5
|
LL | / let mut new_err = Vec::<u32>::new();
LL | | new_err.push(1);
| |____________________^ help: consider using the `vec![]` macro: `let mut new_err = vec![..];`
error: calls to `push` immediately after creation
--> $DIR/vec_init_then_push.rs:11:5
|
LL | / let mut cap_err = Vec::with_capacity(2);
LL | | cap_err.push(0);
LL | | cap_err.push(1);
LL | | cap_err.push(2);
| |____________________^ help: consider using the `vec![]` macro: `let mut cap_err = vec![..];`
error: calls to `push` immediately after creation
--> $DIR/vec_init_then_push.rs:19:5
|
LL | / new_err = Vec::new();
LL | | new_err.push(0);
| |____________________^ help: consider using the `vec![]` macro: `new_err = vec![..];`
error: aborting due to 4 previous errors

View file

@ -94,7 +94,8 @@ mod issue6307 {
trait T: Sized {
fn as_i32(self) {}
fn as_u32(&self) {}
fn into_i32(&self) {}
fn into_i32(self) {}
fn into_i32_ref(&self) {}
fn into_u32(self) {}
fn is_i32(self) {}
fn is_u32(&self) {}
@ -117,7 +118,32 @@ mod issue6307 {
trait U {
fn as_i32(self);
fn as_u32(&self);
fn into_i32(&self);
fn into_i32(self);
fn into_i32_ref(&self);
fn into_u32(self);
fn is_i32(self);
fn is_u32(&self);
fn to_i32(self);
fn to_u32(&self);
fn from_i32(self);
// check whether the lint can be allowed at the function level
#[allow(clippy::wrong_self_convention)]
fn from_cake(self);
// test for false positives
fn as_(self);
fn into_(&self);
fn is_(self);
fn to_(self);
fn from_(self);
fn to_mut(&mut self);
}
trait C: Copy {
fn as_i32(self);
fn as_u32(&self);
fn into_i32(self);
fn into_i32_ref(&self);
fn into_u32(self);
fn is_i32(self);
fn is_u32(&self);

View file

@ -79,58 +79,70 @@ LL | fn as_i32(self) {}
| ^^^^
error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:97:21
--> $DIR/wrong_self_convention.rs:98:25
|
LL | fn into_i32(&self) {}
| ^^^^^
LL | fn into_i32_ref(&self) {}
| ^^^^^
error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:99:19
--> $DIR/wrong_self_convention.rs:100:19
|
LL | fn is_i32(self) {}
| ^^^^
error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:101:19
--> $DIR/wrong_self_convention.rs:102:19
|
LL | fn to_i32(self) {}
| ^^^^
error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:103:21
--> $DIR/wrong_self_convention.rs:104:21
|
LL | fn from_i32(self) {}
| ^^^^
error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:118:19
--> $DIR/wrong_self_convention.rs:119:19
|
LL | fn as_i32(self);
| ^^^^
error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:120:21
--> $DIR/wrong_self_convention.rs:122:25
|
LL | fn into_i32(&self);
| ^^^^^
LL | fn into_i32_ref(&self);
| ^^^^^
error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:122:19
--> $DIR/wrong_self_convention.rs:124:19
|
LL | fn is_i32(self);
| ^^^^
error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:124:19
--> $DIR/wrong_self_convention.rs:126:19
|
LL | fn to_i32(self);
| ^^^^
error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:126:21
--> $DIR/wrong_self_convention.rs:128:21
|
LL | fn from_i32(self);
| ^^^^
error: aborting due to 22 previous errors
error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:146:25
|
LL | fn into_i32_ref(&self);
| ^^^^^
error: methods called `from_*` usually take no self; consider choosing a less ambiguous name
--> $DIR/wrong_self_convention.rs:152:21
|
LL | fn from_i32(self);
| ^^^^
error: aborting due to 24 previous errors