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

This commit is contained in:
Philipp Krones 2024-07-25 18:09:52 +02:00
commit 9f53fc32cf
No known key found for this signature in database
GPG key ID: 1CA0DF2AF59D68A5
298 changed files with 4937 additions and 5233 deletions

View file

@ -1,95 +1,184 @@
error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
error: casts from `bool` to `u8` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:8:13
|
LL | let _ = true as u8;
| ^^^^^^^^^^ help: try: `u8::from(true)`
| ^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
= note: `-D clippy::cast-lossless` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
help: use `u8::from` instead
|
LL | let _ = u8::from(true);
| ~~~~~~~~~~~~~~
error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
error: casts from `bool` to `u16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:9:13
|
LL | let _ = true as u16;
| ^^^^^^^^^^^ help: try: `u16::from(true)`
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u16::from` instead
|
LL | let _ = u16::from(true);
| ~~~~~~~~~~~~~~~
error: casting `bool` to `u32` is more cleanly stated with `u32::from(_)`
error: casts from `bool` to `u32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:10:13
|
LL | let _ = true as u32;
| ^^^^^^^^^^^ help: try: `u32::from(true)`
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u32::from` instead
|
LL | let _ = u32::from(true);
| ~~~~~~~~~~~~~~~
error: casting `bool` to `u64` is more cleanly stated with `u64::from(_)`
error: casts from `bool` to `u64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:11:13
|
LL | let _ = true as u64;
| ^^^^^^^^^^^ help: try: `u64::from(true)`
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u64::from` instead
|
LL | let _ = u64::from(true);
| ~~~~~~~~~~~~~~~
error: casting `bool` to `u128` is more cleanly stated with `u128::from(_)`
error: casts from `bool` to `u128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:12:13
|
LL | let _ = true as u128;
| ^^^^^^^^^^^^ help: try: `u128::from(true)`
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u128::from` instead
|
LL | let _ = u128::from(true);
| ~~~~~~~~~~~~~~~~
error: casting `bool` to `usize` is more cleanly stated with `usize::from(_)`
error: casts from `bool` to `usize` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:13:13
|
LL | let _ = true as usize;
| ^^^^^^^^^^^^^ help: try: `usize::from(true)`
| ^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `usize::from` instead
|
LL | let _ = usize::from(true);
| ~~~~~~~~~~~~~~~~~
error: casting `bool` to `i8` is more cleanly stated with `i8::from(_)`
error: casts from `bool` to `i8` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:15:13
|
LL | let _ = true as i8;
| ^^^^^^^^^^ help: try: `i8::from(true)`
| ^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i8::from` instead
|
LL | let _ = i8::from(true);
| ~~~~~~~~~~~~~~
error: casting `bool` to `i16` is more cleanly stated with `i16::from(_)`
error: casts from `bool` to `i16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:16:13
|
LL | let _ = true as i16;
| ^^^^^^^^^^^ help: try: `i16::from(true)`
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i16::from` instead
|
LL | let _ = i16::from(true);
| ~~~~~~~~~~~~~~~
error: casting `bool` to `i32` is more cleanly stated with `i32::from(_)`
error: casts from `bool` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:17:13
|
LL | let _ = true as i32;
| ^^^^^^^^^^^ help: try: `i32::from(true)`
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i32::from` instead
|
LL | let _ = i32::from(true);
| ~~~~~~~~~~~~~~~
error: casting `bool` to `i64` is more cleanly stated with `i64::from(_)`
error: casts from `bool` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:18:13
|
LL | let _ = true as i64;
| ^^^^^^^^^^^ help: try: `i64::from(true)`
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i64::from` instead
|
LL | let _ = i64::from(true);
| ~~~~~~~~~~~~~~~
error: casting `bool` to `i128` is more cleanly stated with `i128::from(_)`
error: casts from `bool` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:19:13
|
LL | let _ = true as i128;
| ^^^^^^^^^^^^ help: try: `i128::from(true)`
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | let _ = i128::from(true);
| ~~~~~~~~~~~~~~~~
error: casting `bool` to `isize` is more cleanly stated with `isize::from(_)`
error: casts from `bool` to `isize` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:20:13
|
LL | let _ = true as isize;
| ^^^^^^^^^^^^^ help: try: `isize::from(true)`
| ^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `isize::from` instead
|
LL | let _ = isize::from(true);
| ~~~~~~~~~~~~~~~~~
error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
error: casts from `bool` to `u16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:23:13
|
LL | let _ = (true | false) as u16;
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)`
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u16::from` instead
|
LL | let _ = u16::from(true | false);
| ~~~~~~~~~~~~~~~~~~~~~~~
error: casting `bool` to `U8` is more cleanly stated with `U8::from(_)`
error: casts from `bool` to `u8` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:25:13
|
LL | let _ = true as U8;
| ^^^^^^^^^^ help: try: `U8::from(true)`
| ^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `U8::from` instead
|
LL | let _ = U8::from(true);
| ~~~~~~~~~~~~~~
error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
error: casts from `bool` to `u8` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_bool.rs:53:13
|
LL | let _ = true as u8;
| ^^^^^^^^^^ help: try: `u8::from(true)`
| ^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u8::from` instead
|
LL | let _ = u8::from(true);
| ~~~~~~~~~~~~~~
error: aborting due to 15 previous errors

View file

@ -1,83 +1,160 @@
error: casting `i8` to `f32` may become silently lossy if you later change the type
error: casts from `i8` to `f32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:12:13
|
LL | let _ = x0 as f32;
| ^^^^^^^^^ help: try: `f32::from(x0)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
= note: `-D clippy::cast-lossless` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
help: use `f32::from` instead
|
LL | let _ = f32::from(x0);
| ~~~~~~~~~~~~~
error: casting `i8` to `f64` may become silently lossy if you later change the type
error: casts from `i8` to `f64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:13:13
|
LL | let _ = x0 as f64;
| ^^^^^^^^^ help: try: `f64::from(x0)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f64::from` instead
|
LL | let _ = f64::from(x0);
| ~~~~~~~~~~~~~
error: casting `i8` to `F32` may become silently lossy if you later change the type
error: casts from `i8` to `f32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:14:13
|
LL | let _ = x0 as F32;
| ^^^^^^^^^ help: try: `F32::from(x0)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `F32::from` instead
|
LL | let _ = F32::from(x0);
| ~~~~~~~~~~~~~
error: casting `i8` to `F64` may become silently lossy if you later change the type
error: casts from `i8` to `f64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:15:13
|
LL | let _ = x0 as F64;
| ^^^^^^^^^ help: try: `F64::from(x0)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `F64::from` instead
|
LL | let _ = F64::from(x0);
| ~~~~~~~~~~~~~
error: casting `u8` to `f32` may become silently lossy if you later change the type
error: casts from `u8` to `f32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:17:13
|
LL | let _ = x1 as f32;
| ^^^^^^^^^ help: try: `f32::from(x1)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f32::from` instead
|
LL | let _ = f32::from(x1);
| ~~~~~~~~~~~~~
error: casting `u8` to `f64` may become silently lossy if you later change the type
error: casts from `u8` to `f64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:18:13
|
LL | let _ = x1 as f64;
| ^^^^^^^^^ help: try: `f64::from(x1)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f64::from` instead
|
LL | let _ = f64::from(x1);
| ~~~~~~~~~~~~~
error: casting `i16` to `f32` may become silently lossy if you later change the type
error: casts from `i16` to `f32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:20:13
|
LL | let _ = x2 as f32;
| ^^^^^^^^^ help: try: `f32::from(x2)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f32::from` instead
|
LL | let _ = f32::from(x2);
| ~~~~~~~~~~~~~
error: casting `i16` to `f64` may become silently lossy if you later change the type
error: casts from `i16` to `f64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:21:13
|
LL | let _ = x2 as f64;
| ^^^^^^^^^ help: try: `f64::from(x2)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f64::from` instead
|
LL | let _ = f64::from(x2);
| ~~~~~~~~~~~~~
error: casting `u16` to `f32` may become silently lossy if you later change the type
error: casts from `u16` to `f32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:23:13
|
LL | let _ = x3 as f32;
| ^^^^^^^^^ help: try: `f32::from(x3)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f32::from` instead
|
LL | let _ = f32::from(x3);
| ~~~~~~~~~~~~~
error: casting `u16` to `f64` may become silently lossy if you later change the type
error: casts from `u16` to `f64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:24:13
|
LL | let _ = x3 as f64;
| ^^^^^^^^^ help: try: `f64::from(x3)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f64::from` instead
|
LL | let _ = f64::from(x3);
| ~~~~~~~~~~~~~
error: casting `i32` to `f64` may become silently lossy if you later change the type
error: casts from `i32` to `f64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:26:13
|
LL | let _ = x4 as f64;
| ^^^^^^^^^ help: try: `f64::from(x4)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f64::from` instead
|
LL | let _ = f64::from(x4);
| ~~~~~~~~~~~~~
error: casting `u32` to `f64` may become silently lossy if you later change the type
error: casts from `u32` to `f64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:28:13
|
LL | let _ = x5 as f64;
| ^^^^^^^^^ help: try: `f64::from(x5)`
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f64::from` instead
|
LL | let _ = f64::from(x5);
| ~~~~~~~~~~~~~
error: casting `f32` to `f64` may become silently lossy if you later change the type
error: casts from `f32` to `f64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_float.rs:31:13
|
LL | let _ = 1.0f32 as f64;
| ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)`
| ^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `f64::from` instead
|
LL | let _ = f64::from(1.0f32);
| ~~~~~~~~~~~~~~~~~
error: aborting due to 13 previous errors

View file

@ -1,39 +1,93 @@
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
#![warn(clippy::cast_lossless)]
type I64 = i64;
type U128 = u128;
type I64Alias = i64;
fn main() {
// Test clippy::cast_lossless with casts to integer types
let _ = i16::from(1i8);
let _ = i32::from(1i8);
let _ = i64::from(1i8);
let _ = i16::from(1u8);
let _ = i32::from(1u8);
let _ = i64::from(1u8);
let _ = u16::from(1u8);
let _ = u32::from(1u8);
let _ = u64::from(1u8);
let _ = i32::from(1i16);
let _ = i64::from(1i16);
let _ = i32::from(1u16);
let _ = i64::from(1u16);
let _ = u32::from(1u16);
let _ = u64::from(1u16);
let _ = i64::from(1i32);
let _ = i64::from(1u32);
let _ = u64::from(1u32);
u16::from(0u8);
//~^ cast_lossless
i16::from(0u8);
//~^ cast_lossless
u32::from(0u8);
//~^ cast_lossless
i32::from(0u8);
//~^ cast_lossless
u64::from(0u8);
//~^ cast_lossless
i64::from(0u8);
//~^ cast_lossless
u128::from(0u8);
//~^ cast_lossless
i128::from(0u8);
//~^ cast_lossless
u32::from(0u16);
//~^ cast_lossless
i32::from(0u16);
//~^ cast_lossless
u64::from(0u16);
//~^ cast_lossless
i64::from(0u16);
//~^ cast_lossless
u128::from(0u16);
//~^ cast_lossless
i128::from(0u16);
//~^ cast_lossless
u64::from(0u32);
//~^ cast_lossless
i64::from(0u32);
//~^ cast_lossless
u128::from(0u32);
//~^ cast_lossless
i128::from(0u32);
//~^ cast_lossless
u128::from(0u64);
//~^ cast_lossless
i128::from(0u64);
//~^ cast_lossless
i16::from(0i8);
//~^ cast_lossless
i32::from(0i8);
//~^ cast_lossless
i64::from(0i8);
//~^ cast_lossless
i128::from(0i8);
//~^ cast_lossless
i32::from(0i16);
//~^ cast_lossless
i64::from(0i16);
//~^ cast_lossless
i128::from(0i16);
//~^ cast_lossless
i64::from(0i32);
//~^ cast_lossless
i128::from(0i32);
//~^ cast_lossless
i128::from(0i64);
//~^ cast_lossless
// Test with an expression wrapped in parens
let _ = u16::from(1u8 + 1u8);
//~^ cast_lossless
let _ = I64::from(1i8);
let _ = I64Alias::from(1i8);
//~^ cast_lossless
// Do not lint if destination type is u128
// see https://github.com/rust-lang/rust-clippy/issues/12492
let _ = 1u8 as u128;
let _ = 1u8 as U128;
let _: u16 = 0u8.into();
//~^ cast_lossless
let _: i16 = (-1i8).into();
//~^ cast_lossless
let _: u16 = (1u8 + 2).into();
//~^ cast_lossless
let _: u32 = (1i8 as u16).into();
//~^ cast_lossless
}
// The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const,
@ -68,5 +122,30 @@ fn issue11458() {
}
let x = 10_u128;
let _ = i32::from(sign_cast!(x, u8, i8));
//~^ cast_lossless
let _ = i32::from(sign_cast!(x, u8, i8) + 1);
//~^ cast_lossless
}
fn issue12695() {
macro_rules! in_macro {
() => {
u32::from(1u8)
//~^ cast_lossless
};
}
let _ = in_macro!();
}
fn ty_from_macro() {
macro_rules! ty {
() => {
u32
};
}
let _ = <ty!()>::from(0u8);
}
const IN_CONST: u64 = 0u8 as u64;

View file

@ -1,39 +1,93 @@
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
#![warn(clippy::cast_lossless)]
type I64 = i64;
type U128 = u128;
type I64Alias = i64;
fn main() {
// Test clippy::cast_lossless with casts to integer types
let _ = 1i8 as i16;
let _ = 1i8 as i32;
let _ = 1i8 as i64;
let _ = 1u8 as i16;
let _ = 1u8 as i32;
let _ = 1u8 as i64;
let _ = 1u8 as u16;
let _ = 1u8 as u32;
let _ = 1u8 as u64;
let _ = 1i16 as i32;
let _ = 1i16 as i64;
let _ = 1u16 as i32;
let _ = 1u16 as i64;
let _ = 1u16 as u32;
let _ = 1u16 as u64;
let _ = 1i32 as i64;
let _ = 1u32 as i64;
let _ = 1u32 as u64;
0u8 as u16;
//~^ cast_lossless
0u8 as i16;
//~^ cast_lossless
0u8 as u32;
//~^ cast_lossless
0u8 as i32;
//~^ cast_lossless
0u8 as u64;
//~^ cast_lossless
0u8 as i64;
//~^ cast_lossless
0u8 as u128;
//~^ cast_lossless
0u8 as i128;
//~^ cast_lossless
0u16 as u32;
//~^ cast_lossless
0u16 as i32;
//~^ cast_lossless
0u16 as u64;
//~^ cast_lossless
0u16 as i64;
//~^ cast_lossless
0u16 as u128;
//~^ cast_lossless
0u16 as i128;
//~^ cast_lossless
0u32 as u64;
//~^ cast_lossless
0u32 as i64;
//~^ cast_lossless
0u32 as u128;
//~^ cast_lossless
0u32 as i128;
//~^ cast_lossless
0u64 as u128;
//~^ cast_lossless
0u64 as i128;
//~^ cast_lossless
0i8 as i16;
//~^ cast_lossless
0i8 as i32;
//~^ cast_lossless
0i8 as i64;
//~^ cast_lossless
0i8 as i128;
//~^ cast_lossless
0i16 as i32;
//~^ cast_lossless
0i16 as i64;
//~^ cast_lossless
0i16 as i128;
//~^ cast_lossless
0i32 as i64;
//~^ cast_lossless
0i32 as i128;
//~^ cast_lossless
0i64 as i128;
//~^ cast_lossless
// Test with an expression wrapped in parens
let _ = (1u8 + 1u8) as u16;
//~^ cast_lossless
let _ = 1i8 as I64;
let _ = 1i8 as I64Alias;
//~^ cast_lossless
// Do not lint if destination type is u128
// see https://github.com/rust-lang/rust-clippy/issues/12492
let _ = 1u8 as u128;
let _ = 1u8 as U128;
let _: u16 = 0u8 as _;
//~^ cast_lossless
let _: i16 = -1i8 as _;
//~^ cast_lossless
let _: u16 = (1u8 + 2) as _;
//~^ cast_lossless
let _: u32 = 1i8 as u16 as _;
//~^ cast_lossless
}
// The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const,
@ -68,5 +122,30 @@ fn issue11458() {
}
let x = 10_u128;
let _ = sign_cast!(x, u8, i8) as i32;
//~^ cast_lossless
let _ = (sign_cast!(x, u8, i8) + 1) as i32;
//~^ cast_lossless
}
fn issue12695() {
macro_rules! in_macro {
() => {
1u8 as u32
//~^ cast_lossless
};
}
let _ = in_macro!();
}
fn ty_from_macro() {
macro_rules! ty {
() => {
u32
};
}
let _ = 0u8 as ty!();
}
const IN_CONST: u64 = 0u8 as u64;

View file

@ -1,137 +1,488 @@
error: casting `i8` to `i16` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:9:13
error: casts from `u8` to `u16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:8:5
|
LL | let _ = 1i8 as i16;
| ^^^^^^^^^^ help: try: `i16::from(1i8)`
LL | 0u8 as u16;
| ^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
= note: `-D clippy::cast-lossless` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
error: casting `i8` to `i32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:10:13
help: use `u16::from` instead
|
LL | let _ = 1i8 as i32;
| ^^^^^^^^^^ help: try: `i32::from(1i8)`
LL | u16::from(0u8);
| ~~~~~~~~~~~~~~
error: casting `i8` to `i64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:11:13
error: casts from `u8` to `i16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:10:5
|
LL | let _ = 1i8 as i64;
| ^^^^^^^^^^ help: try: `i64::from(1i8)`
error: casting `u8` to `i16` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:12:13
LL | 0u8 as i16;
| ^^^^^^^^^^
|
LL | let _ = 1u8 as i16;
| ^^^^^^^^^^ help: try: `i16::from(1u8)`
error: casting `u8` to `i32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:13:13
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i16::from` instead
|
LL | let _ = 1u8 as i32;
| ^^^^^^^^^^ help: try: `i32::from(1u8)`
LL | i16::from(0u8);
| ~~~~~~~~~~~~~~
error: casting `u8` to `i64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:14:13
error: casts from `u8` to `u32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:12:5
|
LL | let _ = 1u8 as i64;
| ^^^^^^^^^^ help: try: `i64::from(1u8)`
error: casting `u8` to `u16` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:15:13
LL | 0u8 as u32;
| ^^^^^^^^^^
|
LL | let _ = 1u8 as u16;
| ^^^^^^^^^^ help: try: `u16::from(1u8)`
error: casting `u8` to `u32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:16:13
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u32::from` instead
|
LL | let _ = 1u8 as u32;
| ^^^^^^^^^^ help: try: `u32::from(1u8)`
LL | u32::from(0u8);
| ~~~~~~~~~~~~~~
error: casting `u8` to `u64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:17:13
error: casts from `u8` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:14:5
|
LL | let _ = 1u8 as u64;
| ^^^^^^^^^^ help: try: `u64::from(1u8)`
error: casting `i16` to `i32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:18:13
LL | 0u8 as i32;
| ^^^^^^^^^^
|
LL | let _ = 1i16 as i32;
| ^^^^^^^^^^^ help: try: `i32::from(1i16)`
error: casting `i16` to `i64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:19:13
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i32::from` instead
|
LL | let _ = 1i16 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1i16)`
LL | i32::from(0u8);
| ~~~~~~~~~~~~~~
error: casting `u16` to `i32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:20:13
error: casts from `u8` to `u64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:16:5
|
LL | let _ = 1u16 as i32;
| ^^^^^^^^^^^ help: try: `i32::from(1u16)`
error: casting `u16` to `i64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:21:13
LL | 0u8 as u64;
| ^^^^^^^^^^
|
LL | let _ = 1u16 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1u16)`
error: casting `u16` to `u32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:22:13
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u64::from` instead
|
LL | let _ = 1u16 as u32;
| ^^^^^^^^^^^ help: try: `u32::from(1u16)`
LL | u64::from(0u8);
| ~~~~~~~~~~~~~~
error: casting `u16` to `u64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:23:13
error: casts from `u8` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:18:5
|
LL | let _ = 1u16 as u64;
| ^^^^^^^^^^^ help: try: `u64::from(1u16)`
error: casting `i32` to `i64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:24:13
LL | 0u8 as i64;
| ^^^^^^^^^^
|
LL | let _ = 1i32 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1i32)`
error: casting `u32` to `i64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:25:13
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i64::from` instead
|
LL | let _ = 1u32 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1u32)`
LL | i64::from(0u8);
| ~~~~~~~~~~~~~~
error: casting `u32` to `u64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:26:13
error: casts from `u8` to `u128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:20:5
|
LL | let _ = 1u32 as u64;
| ^^^^^^^^^^^ help: try: `u64::from(1u32)`
LL | 0u8 as u128;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u128::from` instead
|
LL | u128::from(0u8);
| ~~~~~~~~~~~~~~~
error: casting `u8` to `u16` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:29:13
error: casts from `u8` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:22:5
|
LL | 0u8 as i128;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | i128::from(0u8);
| ~~~~~~~~~~~~~~~
error: casts from `u16` to `u32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:25:5
|
LL | 0u16 as u32;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u32::from` instead
|
LL | u32::from(0u16);
| ~~~~~~~~~~~~~~~
error: casts from `u16` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:27:5
|
LL | 0u16 as i32;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i32::from` instead
|
LL | i32::from(0u16);
| ~~~~~~~~~~~~~~~
error: casts from `u16` to `u64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:29:5
|
LL | 0u16 as u64;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u64::from` instead
|
LL | u64::from(0u16);
| ~~~~~~~~~~~~~~~
error: casts from `u16` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:31:5
|
LL | 0u16 as i64;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i64::from` instead
|
LL | i64::from(0u16);
| ~~~~~~~~~~~~~~~
error: casts from `u16` to `u128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:33:5
|
LL | 0u16 as u128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u128::from` instead
|
LL | u128::from(0u16);
| ~~~~~~~~~~~~~~~~
error: casts from `u16` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:35:5
|
LL | 0u16 as i128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | i128::from(0u16);
| ~~~~~~~~~~~~~~~~
error: casts from `u32` to `u64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:38:5
|
LL | 0u32 as u64;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u64::from` instead
|
LL | u64::from(0u32);
| ~~~~~~~~~~~~~~~
error: casts from `u32` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:40:5
|
LL | 0u32 as i64;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i64::from` instead
|
LL | i64::from(0u32);
| ~~~~~~~~~~~~~~~
error: casts from `u32` to `u128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:42:5
|
LL | 0u32 as u128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u128::from` instead
|
LL | u128::from(0u32);
| ~~~~~~~~~~~~~~~~
error: casts from `u32` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:44:5
|
LL | 0u32 as i128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | i128::from(0u32);
| ~~~~~~~~~~~~~~~~
error: casts from `u64` to `u128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:47:5
|
LL | 0u64 as u128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u128::from` instead
|
LL | u128::from(0u64);
| ~~~~~~~~~~~~~~~~
error: casts from `u64` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:49:5
|
LL | 0u64 as i128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | i128::from(0u64);
| ~~~~~~~~~~~~~~~~
error: casts from `i8` to `i16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:52:5
|
LL | 0i8 as i16;
| ^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i16::from` instead
|
LL | i16::from(0i8);
| ~~~~~~~~~~~~~~
error: casts from `i8` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:54:5
|
LL | 0i8 as i32;
| ^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i32::from` instead
|
LL | i32::from(0i8);
| ~~~~~~~~~~~~~~
error: casts from `i8` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:56:5
|
LL | 0i8 as i64;
| ^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i64::from` instead
|
LL | i64::from(0i8);
| ~~~~~~~~~~~~~~
error: casts from `i8` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:58:5
|
LL | 0i8 as i128;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | i128::from(0i8);
| ~~~~~~~~~~~~~~~
error: casts from `i16` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:61:5
|
LL | 0i16 as i32;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i32::from` instead
|
LL | i32::from(0i16);
| ~~~~~~~~~~~~~~~
error: casts from `i16` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:63:5
|
LL | 0i16 as i64;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i64::from` instead
|
LL | i64::from(0i16);
| ~~~~~~~~~~~~~~~
error: casts from `i16` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:65:5
|
LL | 0i16 as i128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | i128::from(0i16);
| ~~~~~~~~~~~~~~~~
error: casts from `i32` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:68:5
|
LL | 0i32 as i64;
| ^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i64::from` instead
|
LL | i64::from(0i32);
| ~~~~~~~~~~~~~~~
error: casts from `i32` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:70:5
|
LL | 0i32 as i128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | i128::from(0i32);
| ~~~~~~~~~~~~~~~~
error: casts from `i64` to `i128` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:73:5
|
LL | 0i64 as i128;
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i128::from` instead
|
LL | i128::from(0i64);
| ~~~~~~~~~~~~~~~~
error: casts from `u8` to `u16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:77:13
|
LL | let _ = (1u8 + 1u8) as u16;
| ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)`
error: casting `i8` to `I64` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:31:13
| ^^^^^^^^^^^^^^^^^^
|
LL | let _ = 1i8 as I64;
| ^^^^^^^^^^ help: try: `I64::from(1i8)`
= help: an `as` cast can become silently lossy if the types change in the future
help: use `u16::from` instead
|
LL | let _ = u16::from(1u8 + 1u8);
| ~~~~~~~~~~~~~~~~~~~~
error: casting `i8` to `i32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:70:13
error: casts from `i8` to `i64` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:80:13
|
LL | let _ = 1i8 as I64Alias;
| ^^^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `I64Alias::from` instead
|
LL | let _ = I64Alias::from(1i8);
| ~~~~~~~~~~~~~~~~~~~
error: casts from `u8` to `u16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:83:18
|
LL | let _: u16 = 0u8 as _;
| ^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `Into::into` instead
|
LL | let _: u16 = 0u8.into();
| ~~~~~~~~~~
error: casts from `i8` to `i16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:85:18
|
LL | let _: i16 = -1i8 as _;
| ^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `Into::into` instead
|
LL | let _: i16 = (-1i8).into();
| ~~~~~~~~~~~~~
error: casts from `u8` to `u16` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:87:18
|
LL | let _: u16 = (1u8 + 2) as _;
| ^^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `Into::into` instead
|
LL | let _: u16 = (1u8 + 2).into();
| ~~~~~~~~~~~~~~~~
error: casts from `u16` to `u32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:89:18
|
LL | let _: u32 = 1i8 as u16 as _;
| ^^^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `Into::into` instead
|
LL | let _: u32 = (1i8 as u16).into();
| ~~~~~~~~~~~~~~~~~~~
error: casts from `i8` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:124:13
|
LL | let _ = sign_cast!(x, u8, i8) as i32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8))`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i32::from` instead
|
LL | let _ = i32::from(sign_cast!(x, u8, i8));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: casting `i8` to `i32` may become silently lossy if you later change the type
--> tests/ui/cast_lossless_integer.rs:71:13
error: casts from `i8` to `i32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:126:13
|
LL | let _ = (sign_cast!(x, u8, i8) + 1) as i32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8) + 1)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `i32::from` instead
|
LL | let _ = i32::from(sign_cast!(x, u8, i8) + 1);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 22 previous errors
error: casts from `u8` to `u32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:133:13
|
LL | 1u8 as u32
| ^^^^^^^^^^
...
LL | let _ = in_macro!();
| ----------- in this macro invocation
|
= help: an `as` cast can become silently lossy if the types change in the future
= note: this error originates in the macro `in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use `u32::from` instead
|
LL | u32::from(1u8)
|
error: casts from `u8` to `u32` can be expressed infallibly using `From`
--> tests/ui/cast_lossless_integer.rs:148:13
|
LL | let _ = 0u8 as ty!();
| ^^^^^^^^^^^^
|
= help: an `as` cast can become silently lossy if the types change in the future
help: use `<ty!()>::from` instead
|
LL | let _ = <ty!()>::from(0u8);
| ~~~~~~~~~~~~~~~~~~
error: aborting due to 40 previous errors

View file

@ -1,11 +0,0 @@
#![deny(clippy::implicit_hasher)]
use std::collections::HashSet;
fn main() {}
pub fn ice_3717<S: ::std::hash::BuildHasher + Default>(_: &HashSet<usize, S>) {
//~^ ERROR: parameter of type `HashSet` should be generalized over different hashers
let _ = [0u8; 0];
let _: HashSet<usize> = HashSet::default();
}

View file

@ -1,5 +1,7 @@
#![deny(clippy::implicit_hasher)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
use std::collections::HashSet;
fn main() {}

View file

@ -1,5 +1,5 @@
error: parameter of type `HashSet` should be generalized over different hashers
--> tests/ui/crashes/ice-3717.rs:7:21
--> tests/ui/crashes/ice-3717.rs:9:21
|
LL | pub fn ice_3717(_: &HashSet<usize>) {
| ^^^^^^^^^^^^^^

View file

@ -45,7 +45,7 @@ fn main() {
let _ = unsafe { *core::ptr::addr_of!(a) };
let _repeat = [0; 64];
// do NOT lint for array as sematic differences with/out `*&`.
// do NOT lint for array as semantic differences with/out `*&`.
let _arr = *&[0, 1, 2, 3, 4];
}

View file

@ -45,7 +45,7 @@ fn main() {
let _ = unsafe { *core::ptr::addr_of!(a) };
let _repeat = *&[0; 64];
// do NOT lint for array as sematic differences with/out `*&`.
// do NOT lint for array as semantic differences with/out `*&`.
let _arr = *&[0, 1, 2, 3, 4];
}

View file

@ -1,295 +0,0 @@
#![allow(dead_code)]
use std::collections::HashMap;
#[derive(Default)]
struct FooDefault<'a> {
a: bool,
b: i32,
c: u64,
d: Vec<i32>,
e: FooND1,
f: FooND2,
g: HashMap<i32, i32>,
h: (i32, Vec<i32>),
i: [Vec<i32>; 3],
j: [i32; 5],
k: Option<i32>,
l: &'a [i32],
}
#[derive(Default)]
struct TupleDefault(bool, i32, u64);
struct FooND1 {
a: bool,
}
impl std::default::Default for FooND1 {
fn default() -> Self {
Self { a: true }
}
}
struct FooND2 {
a: i32,
}
impl std::default::Default for FooND2 {
fn default() -> Self {
Self { a: 5 }
}
}
struct FooNDNew {
a: bool,
}
impl FooNDNew {
fn new() -> Self {
Self { a: true }
}
}
impl Default for FooNDNew {
fn default() -> Self {
Self::new()
}
}
struct FooNDVec(Vec<i32>);
impl Default for FooNDVec {
fn default() -> Self {
Self(vec![5, 12])
}
}
#[derive(Default)]
struct StrDefault<'a>(&'a str);
#[derive(Default)]
struct AlreadyDerived(i32, bool);
macro_rules! mac {
() => {
0
};
($e:expr) => {
struct X(u32);
impl Default for X {
fn default() -> Self {
Self($e)
}
}
};
}
mac!(0);
#[derive(Default)]
struct Y(u32);
struct RustIssue26925<T> {
a: Option<T>,
}
// We should watch out for cases where a manual impl is needed because a
// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
// For example, a struct with Option<T> does not require T: Default, but a derive adds
// that type bound anyways. So until #26925 get fixed we should disable lint
// for the following case
impl<T> Default for RustIssue26925<T> {
fn default() -> Self {
Self { a: None }
}
}
struct SpecializedImpl<A, B> {
a: A,
b: B,
}
impl<T: Default> Default for SpecializedImpl<T, T> {
fn default() -> Self {
Self {
a: T::default(),
b: T::default(),
}
}
}
#[derive(Default)]
struct WithoutSelfCurly {
a: bool,
}
#[derive(Default)]
struct WithoutSelfParan(bool);
// https://github.com/rust-lang/rust-clippy/issues/7655
pub struct SpecializedImpl2<T> {
v: Vec<T>,
}
impl Default for SpecializedImpl2<String> {
fn default() -> Self {
Self { v: Vec::new() }
}
}
// https://github.com/rust-lang/rust-clippy/issues/7654
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
}
/// `#000000`
impl Default for Color {
fn default() -> Self {
Color { r: 0, g: 0, b: 0 }
}
}
pub struct Color2 {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl Default for Color2 {
/// `#000000`
fn default() -> Self {
Self { r: 0, g: 0, b: 0 }
}
}
#[derive(Default)]
pub struct RepeatDefault1 {
a: [i8; 32],
}
pub struct RepeatDefault2 {
a: [i8; 33],
}
impl Default for RepeatDefault2 {
fn default() -> Self {
RepeatDefault2 { a: [0; 33] }
}
}
// https://github.com/rust-lang/rust-clippy/issues/7753
pub enum IntOrString {
Int(i32),
String(String),
}
impl Default for IntOrString {
fn default() -> Self {
IntOrString::Int(0)
}
}
#[derive(Default)]
pub enum SimpleEnum {
Foo,
#[default]
Bar,
}
pub enum NonExhaustiveEnum {
Foo,
#[non_exhaustive]
Bar,
}
impl Default for NonExhaustiveEnum {
fn default() -> Self {
NonExhaustiveEnum::Bar
}
}
// https://github.com/rust-lang/rust-clippy/issues/10396
#[derive(Default)]
struct DefaultType;
struct GenericType<T = DefaultType> {
t: T,
}
impl Default for GenericType {
fn default() -> Self {
Self { t: Default::default() }
}
}
struct InnerGenericType<T> {
t: T,
}
impl Default for InnerGenericType<DefaultType> {
fn default() -> Self {
Self { t: Default::default() }
}
}
struct OtherGenericType<T = DefaultType> {
inner: InnerGenericType<T>,
}
impl Default for OtherGenericType {
fn default() -> Self {
Self {
inner: Default::default(),
}
}
}
mod issue10158 {
pub trait T {}
#[derive(Default)]
pub struct S {}
impl T for S {}
pub struct Outer {
pub inner: Box<dyn T>,
}
impl Default for Outer {
fn default() -> Self {
Outer {
// Box::<S>::default() adjusts to Box<dyn T>
inner: Box::<S>::default(),
}
}
}
}
mod issue11368 {
pub struct A {
a: u32,
}
impl Default for A {
#[track_caller]
fn default() -> Self {
Self { a: 0 }
}
}
}
fn main() {}

View file

@ -1,5 +1,7 @@
#![allow(dead_code)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
use std::collections::HashMap;
struct FooDefault<'a> {

View file

@ -1,5 +1,5 @@
error: this `impl` can be derived
--> tests/ui/derivable_impls.rs:20:1
--> tests/ui/derivable_impls.rs:22:1
|
LL | / impl std::default::Default for FooDefault<'_> {
LL | | fn default() -> Self {
@ -20,7 +20,7 @@ LL | struct FooDefault<'a> {
|
error: this `impl` can be derived
--> tests/ui/derivable_impls.rs:41:1
--> tests/ui/derivable_impls.rs:43:1
|
LL | / impl std::default::Default for TupleDefault {
LL | | fn default() -> Self {
@ -37,7 +37,7 @@ LL | struct TupleDefault(bool, i32, u64);
|
error: this `impl` can be derived
--> tests/ui/derivable_impls.rs:93:1
--> tests/ui/derivable_impls.rs:95:1
|
LL | / impl Default for StrDefault<'_> {
LL | | fn default() -> Self {
@ -54,7 +54,7 @@ LL | struct StrDefault<'a>(&'a str);
|
error: this `impl` can be derived
--> tests/ui/derivable_impls.rs:119:1
--> tests/ui/derivable_impls.rs:121:1
|
LL | / impl Default for Y {
LL | | fn default() -> Self {
@ -71,7 +71,7 @@ LL | struct Y(u32);
|
error: this `impl` can be derived
--> tests/ui/derivable_impls.rs:158:1
--> tests/ui/derivable_impls.rs:160:1
|
LL | / impl Default for WithoutSelfCurly {
LL | | fn default() -> Self {
@ -88,7 +88,7 @@ LL | struct WithoutSelfCurly {
|
error: this `impl` can be derived
--> tests/ui/derivable_impls.rs:166:1
--> tests/ui/derivable_impls.rs:168:1
|
LL | / impl Default for WithoutSelfParan {
LL | | fn default() -> Self {
@ -105,7 +105,7 @@ LL | struct WithoutSelfParan(bool);
|
error: this `impl` can be derived
--> tests/ui/derivable_impls.rs:216:1
--> tests/ui/derivable_impls.rs:218:1
|
LL | / impl Default for RepeatDefault1 {
LL | | fn default() -> Self {
@ -122,7 +122,7 @@ LL | pub struct RepeatDefault1 {
|
error: this `impl` can be derived
--> tests/ui/derivable_impls.rs:250:1
--> tests/ui/derivable_impls.rs:252:1
|
LL | / impl Default for SimpleEnum {
LL | | fn default() -> Self {

View file

@ -1,7 +1,6 @@
#![allow(clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, dead_code)]
#![warn(clippy::expl_impl_clone_on_copy)]
#[derive(Copy)]
struct Qux;

View file

@ -1,5 +1,5 @@
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:8:1
--> tests/ui/derive.rs:7:1
|
LL | / impl Clone for Qux {
LL | |
@ -10,7 +10,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:8:1
--> tests/ui/derive.rs:7:1
|
LL | / impl Clone for Qux {
LL | |
@ -23,7 +23,7 @@ LL | | }
= help: to override `-D warnings` add `#[allow(clippy::expl_impl_clone_on_copy)]`
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:33:1
--> tests/ui/derive.rs:32:1
|
LL | / impl<'a> Clone for Lt<'a> {
LL | |
@ -34,7 +34,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:33:1
--> tests/ui/derive.rs:32:1
|
LL | / impl<'a> Clone for Lt<'a> {
LL | |
@ -45,7 +45,7 @@ LL | | }
| |_^
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:45:1
--> tests/ui/derive.rs:44:1
|
LL | / impl Clone for BigArray {
LL | |
@ -56,7 +56,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:45:1
--> tests/ui/derive.rs:44:1
|
LL | / impl Clone for BigArray {
LL | |
@ -67,7 +67,7 @@ LL | | }
| |_^
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:57:1
--> tests/ui/derive.rs:56:1
|
LL | / impl Clone for FnPtr {
LL | |
@ -78,7 +78,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:57:1
--> tests/ui/derive.rs:56:1
|
LL | / impl Clone for FnPtr {
LL | |
@ -89,7 +89,7 @@ LL | | }
| |_^
error: you are implementing `Clone` explicitly on a `Copy` type
--> tests/ui/derive.rs:78:1
--> tests/ui/derive.rs:77:1
|
LL | / impl<T: Clone> Clone for Generic2<T> {
LL | |
@ -100,7 +100,7 @@ LL | | }
| |_^
|
note: consider deriving `Clone` or removing `Copy`
--> tests/ui/derive.rs:78:1
--> tests/ui/derive.rs:77:1
|
LL | / impl<T: Clone> Clone for Generic2<T> {
LL | |

View file

@ -54,21 +54,24 @@ fn test_units() {
/// This tests allowed identifiers.
/// KiB MiB GiB TiB PiB EiB
/// DirectX
/// AccessKit
/// CoreFoundation CoreGraphics CoreText
/// Direct2D Direct3D DirectWrite DirectX
/// ECMAScript
/// GPLv2 GPLv3
/// GitHub GitLab
/// IPv4 IPv6
/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
/// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript
/// WebAssembly
/// NaN NaNs
/// OAuth GraphQL
/// OCaml
/// OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
/// WebGL WebGL2 WebGPU
/// OpenAL OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
/// OpenType
/// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport
/// TensorFlow
/// TrueType
/// iOS macOS FreeBSD
/// iOS macOS FreeBSD NetBSD OpenBSD
/// TeX LaTeX BibTeX BibLaTeX
/// MinGW
/// CamelCase (see also #2395)

View file

@ -54,21 +54,24 @@ fn test_units() {
/// This tests allowed identifiers.
/// KiB MiB GiB TiB PiB EiB
/// DirectX
/// AccessKit
/// CoreFoundation CoreGraphics CoreText
/// Direct2D Direct3D DirectWrite DirectX
/// ECMAScript
/// GPLv2 GPLv3
/// GitHub GitLab
/// IPv4 IPv6
/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
/// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript
/// WebAssembly
/// NaN NaNs
/// OAuth GraphQL
/// OCaml
/// OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
/// WebGL WebGL2 WebGPU
/// OpenAL OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
/// OpenType
/// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport
/// TensorFlow
/// TrueType
/// iOS macOS FreeBSD
/// iOS macOS FreeBSD NetBSD OpenBSD
/// TeX LaTeX BibTeX BibLaTeX
/// MinGW
/// CamelCase (see also #2395)

View file

@ -133,7 +133,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:75:5
--> tests/ui/doc/doc-fixable.rs:78:5
|
LL | /// be_sure_we_got_to_the_end_of_it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -144,7 +144,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:92:5
--> tests/ui/doc/doc-fixable.rs:95:5
|
LL | /// be_sure_we_got_to_the_end_of_it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -155,7 +155,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:100:8
--> tests/ui/doc/doc-fixable.rs:103:8
|
LL | /// ## CamelCaseThing
| ^^^^^^^^^^^^^^
@ -166,7 +166,7 @@ LL | /// ## `CamelCaseThing`
| ~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:103:7
--> tests/ui/doc/doc-fixable.rs:106:7
|
LL | /// # CamelCaseThing
| ^^^^^^^^^^^^^^
@ -177,7 +177,7 @@ LL | /// # `CamelCaseThing`
| ~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:105:22
--> tests/ui/doc/doc-fixable.rs:108:22
|
LL | /// Not a title #897 CamelCaseThing
| ^^^^^^^^^^^^^^
@ -188,7 +188,7 @@ LL | /// Not a title #897 `CamelCaseThing`
| ~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:106:5
--> tests/ui/doc/doc-fixable.rs:109:5
|
LL | /// be_sure_we_got_to_the_end_of_it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -199,7 +199,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:113:5
--> tests/ui/doc/doc-fixable.rs:116:5
|
LL | /// be_sure_we_got_to_the_end_of_it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -210,7 +210,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:126:5
--> tests/ui/doc/doc-fixable.rs:129:5
|
LL | /// be_sure_we_got_to_the_end_of_it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -221,7 +221,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:137:43
--> tests/ui/doc/doc-fixable.rs:140:43
|
LL | /** E.g., serialization of an empty list: FooBar
| ^^^^^^
@ -232,7 +232,7 @@ LL | /** E.g., serialization of an empty list: `FooBar`
| ~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:142:5
--> tests/ui/doc/doc-fixable.rs:145:5
|
LL | And BarQuz too.
| ^^^^^^
@ -243,7 +243,7 @@ LL | And `BarQuz` too.
| ~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:143:1
--> tests/ui/doc/doc-fixable.rs:146:1
|
LL | be_sure_we_got_to_the_end_of_it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -254,7 +254,7 @@ LL | `be_sure_we_got_to_the_end_of_it`
|
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:148:43
--> tests/ui/doc/doc-fixable.rs:151:43
|
LL | /** E.g., serialization of an empty list: FooBar
| ^^^^^^
@ -265,7 +265,7 @@ LL | /** E.g., serialization of an empty list: `FooBar`
| ~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:153:5
--> tests/ui/doc/doc-fixable.rs:156:5
|
LL | And BarQuz too.
| ^^^^^^
@ -276,7 +276,7 @@ LL | And `BarQuz` too.
| ~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:154:1
--> tests/ui/doc/doc-fixable.rs:157:1
|
LL | be_sure_we_got_to_the_end_of_it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -287,7 +287,7 @@ LL | `be_sure_we_got_to_the_end_of_it`
|
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:165:5
--> tests/ui/doc/doc-fixable.rs:168:5
|
LL | /// be_sure_we_got_to_the_end_of_it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -298,7 +298,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:184:22
--> tests/ui/doc/doc-fixable.rs:187:22
|
LL | /// An iterator over mycrate::Collection's values.
| ^^^^^^^^^^^^^^^^^^^
@ -309,7 +309,7 @@ LL | /// An iterator over `mycrate::Collection`'s values.
| ~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:208:34
--> tests/ui/doc/doc-fixable.rs:211:34
|
LL | /// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint
| ^^^^^^^^^^^^^^^
@ -320,7 +320,7 @@ LL | /// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint`
| ~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:231:22
--> tests/ui/doc/doc-fixable.rs:234:22
|
LL | /// There is no try (do() or do_not()).
| ^^^^
@ -331,7 +331,7 @@ LL | /// There is no try (`do()` or do_not()).
| ~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:231:30
--> tests/ui/doc/doc-fixable.rs:234:30
|
LL | /// There is no try (do() or do_not()).
| ^^^^^^^^
@ -342,7 +342,7 @@ LL | /// There is no try (do() or `do_not()`).
| ~~~~~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:234:5
--> tests/ui/doc/doc-fixable.rs:237:5
|
LL | /// ABes
| ^^^^
@ -353,7 +353,7 @@ LL | /// `ABes`
| ~~~~~~
error: item in documentation is missing backticks
--> tests/ui/doc/doc-fixable.rs:240:9
--> tests/ui/doc/doc-fixable.rs:243:9
|
LL | /// foo()
| ^^^^^
@ -364,7 +364,7 @@ LL | /// `foo()`
| ~~~~~~~
error: you should put bare URLs between `<`/`>` or make a proper Markdown link
--> tests/ui/doc/doc-fixable.rs:244:5
--> tests/ui/doc/doc-fixable.rs:247:5
|
LL | /// https://github.com/rust-lang/rust-clippy/pull/12836
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<https://github.com/rust-lang/rust-clippy/pull/12836>`

View file

@ -78,4 +78,8 @@ fn main() {
const NEG_INF1: f32 = -1.0e+33f32;
const NEG_INF2: f64 = -1.0e+3300f64;
const NEG_INF3: f32 = -3.40282357e+38_f32;
// issue #12954
const _: f64 = 3.0;
const _: f64 = 3.0000000000000000;
}

View file

@ -78,4 +78,8 @@ fn main() {
const NEG_INF1: f32 = -1.0e+33f32;
const NEG_INF2: f64 = -1.0e+3300f64;
const NEG_INF3: f32 = -3.40282357e+38_f32;
// issue #12954
const _: f64 = 3.0000000000000000e+00;
const _: f64 = 3.0000000000000000;
}

View file

@ -91,5 +91,11 @@ error: float has excessive precision
LL | let _ = 1.000_000_000_000_001e-324_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64`
error: aborting due to 15 previous errors
error: float has excessive precision
--> tests/ui/excessive_precision.rs:83:20
|
LL | const _: f64 = 3.0000000000000000e+00;
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `3.0`
error: aborting due to 16 previous errors

View file

@ -25,6 +25,14 @@ fn main() {
let _ = 1.5_f64.sqrt();
let _ = 1.5_f64.powi(3);
macro_rules! m {
($e:expr) => {
5.5 - $e
};
}
let _ = (1f32 + m!(2.0)).exp2();
// Cases where the lint shouldn't be applied
let _ = x.powf(2.1);
let _ = x.powf(-2.1);

View file

@ -25,6 +25,14 @@ fn main() {
let _ = 1.5_f64.powf(1.0 / 2.0);
let _ = 1.5_f64.powf(3.0);
macro_rules! m {
($e:expr) => {
5.5 - $e
};
}
let _ = 2f32.powf(1f32 + m!(2.0));
// Cases where the lint shouldn't be applied
let _ = x.powf(2.1);
let _ = x.powf(-2.1);

View file

@ -119,76 +119,82 @@ LL | let _ = 1.5_f64.powf(3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.powi(3)`
error: exponent for bases 2 and e can be computed more accurately
--> tests/ui/floating_point_powf.rs:35:13
--> tests/ui/floating_point_powf.rs:34:13
|
LL | let _ = 2f32.powf(1f32 + m!(2.0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(1f32 + m!(2.0)).exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> tests/ui/floating_point_powf.rs:43:13
|
LL | let _ = 2f64.powf(x);
| ^^^^^^^^^^^^ help: consider using: `x.exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> tests/ui/floating_point_powf.rs:36:13
--> tests/ui/floating_point_powf.rs:44:13
|
LL | let _ = 2f64.powf(3.1);
| ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> tests/ui/floating_point_powf.rs:37:13
--> tests/ui/floating_point_powf.rs:45:13
|
LL | let _ = 2f64.powf(-3.1);
| ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()`
error: exponent for bases 2 and e can be computed more accurately
--> tests/ui/floating_point_powf.rs:38:13
--> tests/ui/floating_point_powf.rs:46:13
|
LL | let _ = std::f64::consts::E.powf(x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
error: exponent for bases 2 and e can be computed more accurately
--> tests/ui/floating_point_powf.rs:39:13
--> tests/ui/floating_point_powf.rs:47:13
|
LL | let _ = std::f64::consts::E.powf(3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()`
error: exponent for bases 2 and e can be computed more accurately
--> tests/ui/floating_point_powf.rs:40:13
--> tests/ui/floating_point_powf.rs:48:13
|
LL | let _ = std::f64::consts::E.powf(-3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()`
error: square-root of a number can be computed more efficiently and accurately
--> tests/ui/floating_point_powf.rs:41:13
--> tests/ui/floating_point_powf.rs:49:13
|
LL | let _ = x.powf(1.0 / 2.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
error: cube-root of a number can be computed more accurately
--> tests/ui/floating_point_powf.rs:42:13
--> tests/ui/floating_point_powf.rs:50:13
|
LL | let _ = x.powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
error: exponentiation with integer powers can be computed more efficiently
--> tests/ui/floating_point_powf.rs:43:13
--> tests/ui/floating_point_powf.rs:51:13
|
LL | let _ = x.powf(3.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
error: exponentiation with integer powers can be computed more efficiently
--> tests/ui/floating_point_powf.rs:44:13
--> tests/ui/floating_point_powf.rs:52:13
|
LL | let _ = x.powf(-2.0);
| ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
error: exponentiation with integer powers can be computed more efficiently
--> tests/ui/floating_point_powf.rs:45:13
--> tests/ui/floating_point_powf.rs:53:13
|
LL | let _ = x.powf(-2_147_483_648.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)`
error: exponentiation with integer powers can be computed more efficiently
--> tests/ui/floating_point_powf.rs:46:13
--> tests/ui/floating_point_powf.rs:54:13
|
LL | let _ = x.powf(2_147_483_647.0);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)`
error: aborting due to 31 previous errors
error: aborting due to 32 previous errors

View file

@ -1,177 +0,0 @@
#![deny(clippy::index_refutable_slice)]
#![allow(clippy::uninlined_format_args)]
enum SomeEnum<T> {
One(T),
Two(T),
Three(T),
Four(T),
}
fn lintable_examples() {
// Try with reference
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some([slice_0, ..]) = slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{}", slice_0);
}
// Try with copy
let slice: Option<[u32; 3]> = Some([1, 2, 3]);
if let Some([slice_0, ..]) = slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{}", slice_0);
}
// Try with long slice and small indices
let slice: Option<[u32; 9]> = Some([1, 2, 3, 4, 5, 6, 7, 8, 9]);
if let Some([slice_0, _, slice_2, ..]) = slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{}", slice_2);
println!("{}", slice_0);
}
// Multiple bindings
let slice_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([5, 6, 7]);
if let SomeEnum::One([slice_0, ..]) | SomeEnum::Three([slice_0, ..]) = slice_wrapped {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{}", slice_0);
}
// Two lintable slices in one if let
let a_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([9, 5, 1]);
let b_wrapped: Option<[u32; 2]> = Some([4, 6]);
if let (SomeEnum::Three([_, _, a_2, ..]), Some([_, b_1, ..])) = (a_wrapped, b_wrapped) {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
//~| ERROR: this binding can be a slice pattern to avoid indexing
println!("{} -> {}", a_2, b_1);
}
// This requires the slice values to be borrowed as the slice values can only be
// borrowed and `String` doesn't implement copy
let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]);
if let Some([_, ref slice_1, ..]) = slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{:?}", slice_1);
}
println!("{:?}", slice);
// This should not suggest using the `ref` keyword as the scrutinee is already
// a reference
let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]);
if let Some([slice_0, ..]) = &slice {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
println!("{:?}", slice_0);
}
println!("{:?}", slice);
}
fn slice_index_above_limit() {
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice) = slice {
// Would cause a panic, IDK
println!("{}", slice[7]);
}
}
fn slice_is_used() {
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice) = slice {
println!("{:?}", slice.len());
}
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice) = slice {
println!("{:?}", slice.to_vec());
}
let opt: Option<[String; 2]> = Some([String::from("Hello"), String::from("world")]);
if let Some(slice) = opt {
if !slice.is_empty() {
println!("first: {}", slice[0]);
}
}
}
/// The slice is used by an external function and should therefore not be linted
fn check_slice_as_arg() {
fn is_interesting<T>(slice: &[T; 2]) -> bool {
!slice.is_empty()
}
let slice_wrapped: Option<[String; 2]> = Some([String::from("Hello"), String::from("world")]);
if let Some(slice) = &slice_wrapped {
if is_interesting(slice) {
println!("This is interesting {}", slice[0]);
}
}
println!("{:?}", slice_wrapped);
}
fn check_slice_in_struct() {
#[derive(Debug)]
struct Wrapper<'a> {
inner: Option<&'a [String]>,
is_awesome: bool,
}
impl<'a> Wrapper<'a> {
fn is_super_awesome(&self) -> bool {
self.is_awesome
}
}
let inner = &[String::from("New"), String::from("World")];
let wrap = Wrapper {
inner: Some(inner),
is_awesome: true,
};
// Test 1: Field access
if let Some([slice_0, ..]) = wrap.inner {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
if wrap.is_awesome {
println!("This is awesome! {}", slice_0);
}
}
// Test 2: function access
if let Some([slice_0, ..]) = wrap.inner {
//~^ ERROR: this binding can be a slice pattern to avoid indexing
if wrap.is_super_awesome() {
println!("This is super awesome! {}", slice_0);
}
}
println!("Complete wrap: {:?}", wrap);
}
/// This would be a nice additional feature to have in the future, but adding it
/// now would make the PR too large. This is therefore only a test that we don't
/// lint cases we can't make a reasonable suggestion for
fn mutable_slice_index() {
// Mut access
let mut slice: Option<[String; 1]> = Some([String::from("Penguin")]);
if let Some(ref mut slice) = slice {
slice[0] = String::from("Mr. Penguin");
}
println!("Use after modification: {:?}", slice);
// Mut access on reference
let mut slice: Option<[String; 1]> = Some([String::from("Cat")]);
if let Some(slice) = &mut slice {
slice[0] = String::from("Lord Meow Meow");
}
println!("Use after modification: {:?}", slice);
}
/// The lint will ignore bindings with sub patterns as it would be hard
/// to build correct suggestions for these instances :)
fn binding_with_sub_pattern() {
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice @ [_, _, _]) = slice {
println!("{:?}", slice[2]);
}
}
fn main() {}

View file

@ -1,6 +1,8 @@
#![deny(clippy::index_refutable_slice)]
#![allow(clippy::uninlined_format_args)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
enum SomeEnum<T> {
One(T),
Two(T),

View file

@ -1,5 +1,5 @@
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:14:17
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:16:17
|
LL | if let Some(slice) = slice {
| ^^^^^
@ -19,7 +19,7 @@ LL | println!("{}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:21:17
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:23:17
|
LL | if let Some(slice) = slice {
| ^^^^^
@ -34,7 +34,7 @@ LL | println!("{}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:28:17
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:30:17
|
LL | if let Some(slice) = slice {
| ^^^^^
@ -50,7 +50,7 @@ LL ~ println!("{}", slice_0);
|
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:36:26
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:38:26
|
LL | if let SomeEnum::One(slice) | SomeEnum::Three(slice) = slice_wrapped {
| ^^^^^
@ -65,7 +65,7 @@ LL | println!("{}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:44:29
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:46:29
|
LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) {
| ^
@ -80,7 +80,7 @@ LL | println!("{} -> {}", a_2, b[1]);
| ~~~
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:44:38
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:46:38
|
LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) {
| ^
@ -95,7 +95,7 @@ LL | println!("{} -> {}", a[2], b_1);
| ~~~
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:53:21
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:55:21
|
LL | if let Some(ref slice) = slice {
| ^^^^^
@ -110,7 +110,7 @@ LL | println!("{:?}", slice_1);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:62:17
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:64:17
|
LL | if let Some(slice) = &slice {
| ^^^^^
@ -125,7 +125,7 @@ LL | println!("{:?}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:132:17
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:134:17
|
LL | if let Some(slice) = wrap.inner {
| ^^^^^
@ -140,7 +140,7 @@ LL | println!("This is awesome! {}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:140:17
--> tests/ui/index_refutable_slice/if_let_slice_binding.rs:142:17
|
LL | if let Some(slice) = wrap.inner {
| ^^^^^

View file

@ -1,29 +0,0 @@
#![deny(clippy::index_refutable_slice)]
extern crate if_chain;
use if_chain::if_chain;
macro_rules! if_let_slice_macro {
() => {
// This would normally be linted
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some(slice) = slice {
println!("{}", slice[0]);
}
};
}
fn main() {
// Don't lint this
if_let_slice_macro!();
// Do lint this
if_chain! {
let slice: Option<&[u32]> = Some(&[1, 2, 3]);
if let Some([slice_0, ..]) = slice;
//~^ ERROR: this binding can be a slice pattern to avoid indexing
then {
println!("{}", slice_0);
}
}
}

View file

@ -1,5 +1,7 @@
#![deny(clippy::index_refutable_slice)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
extern crate if_chain;
use if_chain::if_chain;

View file

@ -1,5 +1,5 @@
error: this binding can be a slice pattern to avoid indexing
--> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:23:21
--> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:25:21
|
LL | if let Some(slice) = slice;
| ^^^^^

View file

@ -1,196 +0,0 @@
#![warn(clippy::let_unit_value)]
#![allow(unused, clippy::no_effect, clippy::needless_late_init, path_statements)]
macro_rules! let_and_return {
($n:expr) => {{
let ret = $n;
}};
}
fn main() {
println!("x");
let _y = 1; // this is fine
let _z = ((), 1); // this as well
if true {
// do not lint this, since () is explicit
let _a = ();
let () = dummy();
let () = ();
() = dummy();
() = ();
let _a: () = ();
let _a: () = dummy();
}
consume_units_with_for_loop(); // should be fine as well
multiline_sugg();
let_and_return!(()) // should be fine
}
fn dummy() {}
// Related to issue #1964
fn consume_units_with_for_loop() {
// `for_let_unit` lint should not be triggered by consuming them using for loop.
let v = vec![(), (), ()];
let mut count = 0;
for _ in v {
count += 1;
}
assert_eq!(count, 3);
// Same for consuming from some other Iterator<Item = ()>.
let (tx, rx) = ::std::sync::mpsc::channel();
tx.send(()).unwrap();
drop(tx);
count = 0;
for _ in rx.iter() {
count += 1;
}
assert_eq!(count, 1);
}
fn multiline_sugg() {
let v: Vec<u8> = vec![2];
v
.into_iter()
.map(|i| i * 2)
.filter(|i| i % 2 == 0)
.map(|_| ())
.next()
.unwrap();
}
#[derive(Copy, Clone)]
pub struct ContainsUnit(()); // should be fine
fn _returns_generic() {
fn f<T>() -> T {
unimplemented!()
}
fn f2<T, U>(_: T) -> U {
unimplemented!()
}
fn f3<T>(x: T) -> T {
x
}
fn f5<T: Default>(x: bool) -> Option<T> {
x.then(|| T::default())
}
let _: () = f();
let x: () = f();
let _: () = f2(0i32);
let x: () = f2(0i32);
let _: () = f3(());
let x: () = f3(());
fn f4<T>(mut x: Vec<T>) -> T {
x.pop().unwrap()
}
let _: () = f4(vec![()]);
let x: () = f4(vec![()]);
let _: () = {
let x = 5;
f2(x)
};
let _: () = if true { f() } else { f2(0) };
let x: () = if true { f() } else { f2(0) };
match Some(0) {
None => f2(1),
Some(0) => f(),
Some(1) => f2(3),
Some(_) => (),
};
let _: () = f5(true).unwrap();
#[allow(clippy::let_unit_value)]
{
let x = f();
let y;
let z;
match 0 {
0 => {
y = f();
z = f();
},
1 => {
println!("test");
y = f();
z = f3(());
},
_ => panic!(),
}
let x1;
let x2;
if true {
x1 = f();
x2 = x1;
} else {
x2 = f();
x1 = x2;
}
let opt;
match f5(true) {
Some(x) => opt = x,
None => panic!(),
};
#[warn(clippy::let_unit_value)]
{
let _: () = x;
let _: () = y;
let _: () = z;
let _: () = x1;
let _: () = x2;
let _: () = opt;
}
}
let () = f();
}
fn attributes() {
fn f() {}
#[allow(clippy::let_unit_value)]
let _ = f();
#[expect(clippy::let_unit_value)]
let _ = f();
}
async fn issue10433() {
let _pending: () = std::future::pending().await;
}
pub async fn issue11502(a: ()) {}
pub fn issue12594() {
fn returns_unit() {}
fn returns_result<T>(res: T) -> Result<T, ()> {
Ok(res)
}
fn actual_test() {
// create first a unit value'd value
returns_unit();
returns_result(()).unwrap();
returns_result(()).unwrap();
// make sure we replace only the first variable
let res = 1;
returns_result(res).unwrap();
}
}

View file

@ -1,6 +1,8 @@
#![warn(clippy::let_unit_value)]
#![allow(unused, clippy::no_effect, clippy::needless_late_init, path_statements)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
macro_rules! let_and_return {
($n:expr) => {{
let ret = $n;

View file

@ -1,5 +1,5 @@
error: this let-binding has unit value
--> tests/ui/let_unit.rs:11:5
--> tests/ui/let_unit.rs:13:5
|
LL | let _x = println!("x");
| ^^^^^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `println!("x");`
@ -8,7 +8,7 @@ LL | let _x = println!("x");
= help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
error: this let-binding has unit value
--> tests/ui/let_unit.rs:59:5
--> tests/ui/let_unit.rs:61:5
|
LL | / let _ = v
LL | | .into_iter()
@ -31,7 +31,7 @@ LL + .unwrap();
|
error: this let-binding has unit value
--> tests/ui/let_unit.rs:108:5
--> tests/ui/let_unit.rs:110:5
|
LL | / let x = match Some(0) {
LL | | None => f2(1),
@ -52,7 +52,7 @@ LL + };
|
error: this let-binding has unit value
--> tests/ui/let_unit.rs:189:9
--> tests/ui/let_unit.rs:191:9
|
LL | let res = returns_unit();
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,76 +0,0 @@
//@revisions: edition2018 edition2021
//@[edition2018] edition:2018
//@[edition2021] edition:2021
#![warn(clippy::manual_assert)]
#![allow(dead_code, unused_doc_comments)]
#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]
macro_rules! one {
() => {
1
};
}
fn main() {
let a = vec![1, 2, 3];
let c = Some(2);
if !a.is_empty()
&& a.len() == 3
&& c.is_some()
&& !a.is_empty()
&& a.len() == 3
&& !a.is_empty()
&& a.len() == 3
&& !a.is_empty()
&& a.len() == 3
{
panic!("qaqaq{:?}", a);
}
assert!(a.is_empty(), "qaqaq{:?}", a);
assert!(a.is_empty(), "qwqwq");
if a.len() == 3 {
println!("qwq");
println!("qwq");
println!("qwq");
}
if let Some(b) = c {
panic!("orz {}", b);
}
if a.len() == 3 {
panic!("qaqaq");
} else {
println!("qwq");
}
let b = vec![1, 2, 3];
assert!(!b.is_empty(), "panic1");
assert!(!(b.is_empty() && a.is_empty()), "panic2");
assert!(!(a.is_empty() && !b.is_empty()), "panic3");
assert!(!(b.is_empty() || a.is_empty()), "panic4");
assert!(!(a.is_empty() || !b.is_empty()), "panic5");
assert!(!a.is_empty(), "with expansion {}", one!());
if a.is_empty() {
let _ = 0;
} else if a.len() == 1 {
panic!("panic6");
}
}
fn issue7730(a: u8) {
// Suggestion should preserve comment
// comment
/* this is a
multiline
comment */
/// Doc comment
// comment after `panic!`
assert!(!(a > 2), "panic with comment");
}
fn issue12505() {
struct Foo<T, const N: usize>(T);
impl<T, const N: usize> Foo<T, N> {
const BAR: () = assert!(!(N == 0), );
}
}

View file

@ -1,5 +1,5 @@
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:30:5
--> tests/ui/manual_assert.rs:32:5
|
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
@ -10,7 +10,7 @@ LL | | }
= help: to override `-D warnings` add `#[allow(clippy::manual_assert)]`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:33:5
--> tests/ui/manual_assert.rs:35:5
|
LL | / if !a.is_empty() {
LL | | panic!("qwqwq");
@ -18,7 +18,7 @@ LL | | }
| |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:50:5
--> tests/ui/manual_assert.rs:52:5
|
LL | / if b.is_empty() {
LL | | panic!("panic1");
@ -26,7 +26,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:53:5
--> tests/ui/manual_assert.rs:55:5
|
LL | / if b.is_empty() && a.is_empty() {
LL | | panic!("panic2");
@ -34,7 +34,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:56:5
--> tests/ui/manual_assert.rs:58:5
|
LL | / if a.is_empty() && !b.is_empty() {
LL | | panic!("panic3");
@ -42,7 +42,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:59:5
--> tests/ui/manual_assert.rs:61:5
|
LL | / if b.is_empty() || a.is_empty() {
LL | | panic!("panic4");
@ -50,7 +50,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:62:5
--> tests/ui/manual_assert.rs:64:5
|
LL | / if a.is_empty() || !b.is_empty() {
LL | | panic!("panic5");
@ -58,7 +58,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:65:5
--> tests/ui/manual_assert.rs:67:5
|
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
@ -66,7 +66,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:77:5
--> tests/ui/manual_assert.rs:79:5
|
LL | / if a > 2 {
LL | | // comment
@ -83,7 +83,7 @@ LL | assert!(!(a > 2), "panic with comment");
|
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:91:25
--> tests/ui/manual_assert.rs:93:25
|
LL | const BAR: () = if N == 0 {
| _________________________^

View file

@ -1,76 +0,0 @@
//@revisions: edition2018 edition2021
//@[edition2018] edition:2018
//@[edition2021] edition:2021
#![warn(clippy::manual_assert)]
#![allow(dead_code, unused_doc_comments)]
#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]
macro_rules! one {
() => {
1
};
}
fn main() {
let a = vec![1, 2, 3];
let c = Some(2);
if !a.is_empty()
&& a.len() == 3
&& c.is_some()
&& !a.is_empty()
&& a.len() == 3
&& !a.is_empty()
&& a.len() == 3
&& !a.is_empty()
&& a.len() == 3
{
panic!("qaqaq{:?}", a);
}
assert!(a.is_empty(), "qaqaq{:?}", a);
assert!(a.is_empty(), "qwqwq");
if a.len() == 3 {
println!("qwq");
println!("qwq");
println!("qwq");
}
if let Some(b) = c {
panic!("orz {}", b);
}
if a.len() == 3 {
panic!("qaqaq");
} else {
println!("qwq");
}
let b = vec![1, 2, 3];
assert!(!b.is_empty(), "panic1");
assert!(!(b.is_empty() && a.is_empty()), "panic2");
assert!(!(a.is_empty() && !b.is_empty()), "panic3");
assert!(!(b.is_empty() || a.is_empty()), "panic4");
assert!(!(a.is_empty() || !b.is_empty()), "panic5");
assert!(!a.is_empty(), "with expansion {}", one!());
if a.is_empty() {
let _ = 0;
} else if a.len() == 1 {
panic!("panic6");
}
}
fn issue7730(a: u8) {
// Suggestion should preserve comment
// comment
/* this is a
multiline
comment */
/// Doc comment
// comment after `panic!`
assert!(!(a > 2), "panic with comment");
}
fn issue12505() {
struct Foo<T, const N: usize>(T);
impl<T, const N: usize> Foo<T, N> {
const BAR: () = assert!(!(N == 0), );
}
}

View file

@ -1,5 +1,5 @@
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:30:5
--> tests/ui/manual_assert.rs:32:5
|
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
@ -10,7 +10,7 @@ LL | | }
= help: to override `-D warnings` add `#[allow(clippy::manual_assert)]`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:33:5
--> tests/ui/manual_assert.rs:35:5
|
LL | / if !a.is_empty() {
LL | | panic!("qwqwq");
@ -18,7 +18,7 @@ LL | | }
| |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:50:5
--> tests/ui/manual_assert.rs:52:5
|
LL | / if b.is_empty() {
LL | | panic!("panic1");
@ -26,7 +26,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:53:5
--> tests/ui/manual_assert.rs:55:5
|
LL | / if b.is_empty() && a.is_empty() {
LL | | panic!("panic2");
@ -34,7 +34,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:56:5
--> tests/ui/manual_assert.rs:58:5
|
LL | / if a.is_empty() && !b.is_empty() {
LL | | panic!("panic3");
@ -42,7 +42,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:59:5
--> tests/ui/manual_assert.rs:61:5
|
LL | / if b.is_empty() || a.is_empty() {
LL | | panic!("panic4");
@ -50,7 +50,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:62:5
--> tests/ui/manual_assert.rs:64:5
|
LL | / if a.is_empty() || !b.is_empty() {
LL | | panic!("panic5");
@ -58,7 +58,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:65:5
--> tests/ui/manual_assert.rs:67:5
|
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
@ -66,7 +66,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:77:5
--> tests/ui/manual_assert.rs:79:5
|
LL | / if a > 2 {
LL | | // comment
@ -83,7 +83,7 @@ LL | assert!(!(a > 2), "panic with comment");
|
error: only a `panic!` in `if`-then statement
--> tests/ui/manual_assert.rs:91:25
--> tests/ui/manual_assert.rs:93:25
|
LL | const BAR: () = if N == 0 {
| _________________________^

View file

@ -2,6 +2,8 @@
//@[edition2018] edition:2018
//@[edition2021] edition:2021
//@no-rustfix: need to change the suggestion to a multipart suggestion
#![warn(clippy::manual_assert)]
#![allow(dead_code, unused_doc_comments)]
#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]

View file

@ -1,115 +0,0 @@
#![warn(clippy::manual_async_fn)]
#![allow(clippy::needless_pub_self, unused)]
use std::future::Future;
async fn fut() -> i32 { 42 }
#[rustfmt::skip]
async fn fut2() -> i32 { 42 }
#[rustfmt::skip]
async fn fut3() -> i32 { 42 }
async fn empty_fut() {}
#[rustfmt::skip]
async fn empty_fut2() {}
#[rustfmt::skip]
async fn empty_fut3() {}
async fn core_fut() -> i32 { 42 }
// should be ignored
fn has_other_stmts() -> impl core::future::Future<Output = i32> {
let _ = 42;
async move { 42 }
}
// should be ignored
fn not_fut() -> i32 {
42
}
// should be ignored
async fn already_async() -> impl Future<Output = i32> {
async { 42 }
}
struct S;
impl S {
async fn inh_fut() -> i32 {
// NOTE: this code is here just to check that the indentation is correct in the suggested fix
let a = 42;
let b = 21;
if a < b {
let c = 21;
let d = 42;
if c < d {
let _ = 42;
}
}
42
}
// should be ignored
fn not_fut(&self) -> i32 {
42
}
// should be ignored
fn has_other_stmts() -> impl core::future::Future<Output = i32> {
let _ = 42;
async move { 42 }
}
// should be ignored
async fn already_async(&self) -> impl Future<Output = i32> {
async { 42 }
}
}
// Tests related to lifetime capture
async fn elided(_: &i32) -> i32 { 42 }
// should be ignored
fn elided_not_bound(_: &i32) -> impl Future<Output = i32> {
async { 42 }
}
async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 { 42 }
// should be ignored
#[allow(clippy::needless_lifetimes)]
fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> {
async { 42 }
}
// should be ignored
mod issue_5765 {
use std::future::Future;
struct A;
impl A {
fn f(&self) -> impl Future<Output = ()> {
async {}
}
}
fn test() {
let _future = {
let a = A;
a.f()
};
}
}
pub async fn issue_10450() -> i32 { 42 }
pub(crate) async fn issue_10450_2() -> i32 { 42 }
pub(self) async fn issue_10450_3() -> i32 { 42 }
fn main() {}

View file

@ -1,6 +1,8 @@
#![warn(clippy::manual_async_fn)]
#![allow(clippy::needless_pub_self, unused)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
use std::future::Future;
fn fut() -> impl Future<Output = i32> {

View file

@ -1,5 +1,5 @@
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:6:1
--> tests/ui/manual_async_fn.rs:8:1
|
LL | fn fut() -> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -16,7 +16,7 @@ LL | fn fut() -> impl Future<Output = i32> { 42 }
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:11:1
--> tests/ui/manual_async_fn.rs:13:1
|
LL | fn fut2() ->impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -31,7 +31,7 @@ LL | fn fut2() ->impl Future<Output = i32> { 42 }
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:16:1
--> tests/ui/manual_async_fn.rs:18:1
|
LL | fn fut3()-> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -46,7 +46,7 @@ LL | fn fut3()-> impl Future<Output = i32> { 42 }
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:20:1
--> tests/ui/manual_async_fn.rs:22:1
|
LL | fn empty_fut() -> impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -61,7 +61,7 @@ LL | fn empty_fut() -> impl Future<Output = ()> {}
| ~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:25:1
--> tests/ui/manual_async_fn.rs:27:1
|
LL | fn empty_fut2() ->impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -76,7 +76,7 @@ LL | fn empty_fut2() ->impl Future<Output = ()> {}
| ~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:30:1
--> tests/ui/manual_async_fn.rs:32:1
|
LL | fn empty_fut3()-> impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -91,7 +91,7 @@ LL | fn empty_fut3()-> impl Future<Output = ()> {}
| ~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:34:1
--> tests/ui/manual_async_fn.rs:36:1
|
LL | fn core_fut() -> impl core::future::Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -106,7 +106,7 @@ LL | fn core_fut() -> impl core::future::Future<Output = i32> { 42 }
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:56:5
--> tests/ui/manual_async_fn.rs:58:5
|
LL | fn inh_fut() -> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -133,7 +133,7 @@ LL + }
|
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:91:1
--> tests/ui/manual_async_fn.rs:93:1
|
LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -148,7 +148,7 @@ LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { 42 }
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:100:1
--> tests/ui/manual_async_fn.rs:102:1
|
LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -163,7 +163,7 @@ LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> +
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:129:1
--> tests/ui/manual_async_fn.rs:131:1
|
LL | pub fn issue_10450() -> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -178,7 +178,7 @@ LL | pub fn issue_10450() -> impl Future<Output = i32> { 42 }
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:133:1
--> tests/ui/manual_async_fn.rs:135:1
|
LL | pub(crate) fn issue_10450_2() -> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -193,7 +193,7 @@ LL | pub(crate) fn issue_10450_2() -> impl Future<Output = i32> { 42 }
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
--> tests/ui/manual_async_fn.rs:137:1
--> tests/ui/manual_async_fn.rs:139:1
|
LL | pub(self) fn issue_10450_3() -> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,144 +0,0 @@
#![warn(clippy::manual_split_once)]
#![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)]
extern crate itertools;
#[allow(unused_imports)]
use itertools::Itertools;
fn main() {
let _ = "key=value".splitn(2, '=').nth(2);
let _ = "key=value".split_once('=').unwrap().1;
let _ = "key=value".split_once('=').unwrap().1;
let (_, _) = "key=value".split_once('=').unwrap();
let s = String::from("key=value");
let _ = s.split_once('=').unwrap().1;
let s = Box::<str>::from("key=value");
let _ = s.split_once('=').unwrap().1;
let s = &"key=value";
let _ = s.split_once('=').unwrap().1;
fn _f(s: &str) -> Option<&str> {
let _ = s.split_once('=')?.1;
let _ = s.split_once('=')?.1;
let _ = s.rsplit_once('=')?.0;
let _ = s.rsplit_once('=')?.0;
None
}
// Don't lint, slices don't have `split_once`
let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
// `rsplitn` gives the results in the reverse order of `rsplit_once`
let _ = "key=value".rsplit_once('=').unwrap().0;
let (_, _) = "key=value".rsplit_once('=').map(|(x, y)| (y, x)).unwrap();
let _ = s.rsplit_once('=').map(|x| x.0);
}
fn indirect() -> Option<()> {
let (l, r) = "a.b.c".split_once('.').unwrap();
let (l, r) = "a.b.c".split_once('.')?;
let (l, r) = "a.b.c".rsplit_once('.').unwrap();
let (l, r) = "a.b.c".rsplit_once('.')?;
// could lint, currently doesn't
let mut iter = "a.b.c".splitn(2, '.');
let other = 1;
let l = iter.next()?;
let r = iter.next()?;
let mut iter = "a.b.c".splitn(2, '.');
let mut mut_binding = iter.next()?;
let r = iter.next()?;
let mut iter = "a.b.c".splitn(2, '.');
let tuple = (iter.next()?, iter.next()?);
// should not lint
let mut missing_unwrap = "a.b.c".splitn(2, '.');
let l = missing_unwrap.next();
let r = missing_unwrap.next();
let mut mixed_unrap = "a.b.c".splitn(2, '.');
let unwrap = mixed_unrap.next().unwrap();
let question_mark = mixed_unrap.next()?;
let mut iter = "a.b.c".splitn(2, '.');
let same_name = iter.next()?;
let same_name = iter.next()?;
let mut iter = "a.b.c".splitn(2, '.');
let shadows_existing = "d";
let shadows_existing = iter.next()?;
let r = iter.next()?;
let mut iter = "a.b.c".splitn(2, '.');
let becomes_shadowed = iter.next()?;
let becomes_shadowed = "d";
let r = iter.next()?;
let mut iter = "a.b.c".splitn(2, '.');
let l = iter.next()?;
let r = iter.next()?;
let third_usage = iter.next()?;
let mut n_three = "a.b.c".splitn(3, '.');
let l = n_three.next()?;
let r = n_three.next()?;
let mut iter = "a.b.c".splitn(2, '.');
{
let in_block = iter.next()?;
}
let r = iter.next()?;
let mut lacks_binding = "a.b.c".splitn(2, '.');
let _ = lacks_binding.next()?;
let r = lacks_binding.next()?;
let mut mapped = "a.b.c".splitn(2, '.').map(|_| "~");
let l = iter.next()?;
let r = iter.next()?;
let mut assigned = "";
let mut iter = "a.b.c".splitn(2, '.');
let l = iter.next()?;
assigned = iter.next()?;
None
}
#[clippy::msrv = "1.51"]
fn _msrv_1_51() {
// `str::split_once` was stabilized in 1.52. Do not lint this
let _ = "key=value".splitn(2, '=').nth(1).unwrap();
let mut iter = "a.b.c".splitn(2, '.');
let a = iter.next().unwrap();
let b = iter.next().unwrap();
}
#[clippy::msrv = "1.52"]
fn _msrv_1_52() {
let _ = "key=value".split_once('=').unwrap().1;
let (a, b) = "a.b.c".split_once('.').unwrap();
}

View file

@ -1,6 +1,8 @@
#![warn(clippy::manual_split_once)]
#![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
extern crate itertools;
#[allow(unused_imports)]

View file

@ -1,5 +1,5 @@
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:11:13
--> tests/ui/manual_split_once.rs:13:13
|
LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1`
@ -8,79 +8,79 @@ LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap();
= help: to override `-D warnings` add `#[allow(clippy::manual_split_once)]`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:12:13
--> tests/ui/manual_split_once.rs:14:13
|
LL | let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:13:18
--> tests/ui/manual_split_once.rs:15:18
|
LL | let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=')`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:16:13
--> tests/ui/manual_split_once.rs:18:13
|
LL | let _ = s.splitn(2, '=').nth(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:19:13
--> tests/ui/manual_split_once.rs:21:13
|
LL | let _ = s.splitn(2, '=').nth(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:22:13
--> tests/ui/manual_split_once.rs:24:13
|
LL | let _ = s.splitn(2, '=').skip(1).next().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:25:17
--> tests/ui/manual_split_once.rs:27:17
|
LL | let _ = s.splitn(2, '=').nth(1)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=')?.1`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:26:17
--> tests/ui/manual_split_once.rs:28:17
|
LL | let _ = s.splitn(2, '=').skip(1).next()?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=')?.1`
error: manual implementation of `rsplit_once`
--> tests/ui/manual_split_once.rs:27:17
--> tests/ui/manual_split_once.rs:29:17
|
LL | let _ = s.rsplitn(2, '=').nth(1)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=')?.0`
error: manual implementation of `rsplit_once`
--> tests/ui/manual_split_once.rs:28:17
--> tests/ui/manual_split_once.rs:30:17
|
LL | let _ = s.rsplitn(2, '=').skip(1).next()?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=')?.0`
error: manual implementation of `rsplit_once`
--> tests/ui/manual_split_once.rs:36:13
--> tests/ui/manual_split_once.rs:38:13
|
LL | let _ = "key=value".rsplitn(2, '=').nth(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".rsplit_once('=').unwrap().0`
error: manual implementation of `rsplit_once`
--> tests/ui/manual_split_once.rs:37:18
--> tests/ui/manual_split_once.rs:39:18
|
LL | let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".rsplit_once('=').map(|(x, y)| (y, x))`
error: manual implementation of `rsplit_once`
--> tests/ui/manual_split_once.rs:38:13
--> tests/ui/manual_split_once.rs:40:13
|
LL | let _ = s.rsplitn(2, '=').nth(1);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=').map(|x| x.0)`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:42:5
--> tests/ui/manual_split_once.rs:44:5
|
LL | let mut iter = "a.b.c".splitn(2, '.');
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -103,7 +103,7 @@ LL - let r = iter.next().unwrap();
|
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:46:5
--> tests/ui/manual_split_once.rs:48:5
|
LL | let mut iter = "a.b.c".splitn(2, '.');
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -126,7 +126,7 @@ LL - let r = iter.next()?;
|
error: manual implementation of `rsplit_once`
--> tests/ui/manual_split_once.rs:50:5
--> tests/ui/manual_split_once.rs:52:5
|
LL | let mut iter = "a.b.c".rsplitn(2, '.');
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -149,7 +149,7 @@ LL - let l = iter.next().unwrap();
|
error: manual implementation of `rsplit_once`
--> tests/ui/manual_split_once.rs:54:5
--> tests/ui/manual_split_once.rs:56:5
|
LL | let mut iter = "a.b.c".rsplitn(2, '.');
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -172,13 +172,13 @@ LL - let l = iter.next()?;
|
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:139:13
--> tests/ui/manual_split_once.rs:141:13
|
LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1`
error: manual implementation of `split_once`
--> tests/ui/manual_split_once.rs:141:5
--> tests/ui/manual_split_once.rs:143:5
|
LL | let mut iter = "a.b.c".splitn(2, '.');
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -234,4 +234,20 @@ fn implicit_deref_ref() {
};
}
mod issue_13018 {
use std::collections::HashMap;
type RefName = i32;
pub fn get(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
if let Some(names) = index.get(&id) { names } else { &[] }
}
pub fn get_match(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
match index.get(&id) {
Some(names) => names,
None => &[],
}
}
}
fn main() {}

View file

@ -284,4 +284,20 @@ fn implicit_deref_ref() {
};
}
mod issue_13018 {
use std::collections::HashMap;
type RefName = i32;
pub fn get(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
if let Some(names) = index.get(&id) { names } else { &[] }
}
pub fn get_match(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
match index.get(&id) {
Some(names) => names,
None => &[],
}
}
}
fn main() {}

View file

@ -1,258 +0,0 @@
#![warn(clippy::match_same_arms)]
#![allow(
clippy::disallowed_names,
clippy::diverging_sub_expression,
clippy::uninlined_format_args,
clippy::match_single_binding,
clippy::match_like_matches_macro
)]
fn bar<T>(_: T) {}
fn foo() -> bool {
unimplemented!()
}
fn match_same_arms() {
let _ = match 42 {
_ => {
foo();
let mut a = 42 + [23].len() as i32;
if true {
a += 7;
}
a = -31 - a;
a
},
};
//~^^^^^^^^^^^^^^^^^^^ ERROR: this match arm has an identical body to the `_` wildcard arm
let _ = match 42 {
51 | 42 => foo(), //~ ERROR: this match arm has an identical body to another arm
_ => true,
};
let _ = match Some(42) {
None | Some(_) => 24, //~ ERROR: this match arm has an identical body to another arm
};
let _ = match Some(42) {
Some(foo) => 24,
None => 24,
};
let _ = match Some(42) {
Some(42) => 24,
Some(a) => 24, // bindings are different
None => 0,
};
let _ = match Some(42) {
Some(a) if a > 0 => 24,
Some(a) => 24, // one arm has a guard
None => 0,
};
match (Some(42), Some(42)) {
(None, Some(a)) | (Some(a), None) => bar(a), //~ ERROR: this match arm has an identical body to another arm
_ => (),
}
// No warning because guards are different
let _ = match Some(42) {
Some(a) if a == 42 => a,
Some(a) if a == 24 => a,
Some(_) => 24,
None => 0,
};
let _ = match (Some(42), Some(42)) {
(None, Some(a)) | (Some(a), None) if a == 42 => a, //~ ERROR: this match arm has an identical body to another arm
_ => 0,
};
match (Some(42), Some(42)) {
(Some(a), ..) | (.., Some(a)) => bar(a), //~ ERROR: this match arm has an identical body to another arm
_ => (),
}
let _ = match Some(()) {
Some(()) => 0.0,
None => -0.0,
};
match (Some(42), Some("")) {
(Some(a), None) => bar(a),
(None, Some(a)) => bar(a), // bindings have different types
_ => (),
}
let x: Result<i32, &str> = Ok(3);
// No warning because of the guard.
match x {
Ok(x) if x * x == 64 => println!("ok"),
Ok(_) => println!("ok"),
Err(_) => println!("err"),
}
// This used to be a false positive; see issue #1996.
match x {
Ok(3) => println!("ok"),
Ok(x) if x * x == 64 => println!("ok 64"),
Ok(_) => println!("ok"),
Err(_) => println!("err"),
}
match (x, Some(1i32)) {
(Ok(x), Some(_)) | (Ok(_), Some(x)) => println!("ok {}", x), //~ ERROR: this match arm has an identical body to another arm
_ => println!("err"),
}
// No warning; different types for `x`.
match (x, Some(1.0f64)) {
(Ok(x), Some(_)) => println!("ok {}", x),
(Ok(_), Some(x)) => println!("ok {}", x),
_ => println!("err"),
}
// False negative #2251.
match x {
Ok(_tmp) => println!("ok"),
Ok(_) | Ok(3) => println!("ok"), //~ ERROR: this match arm has an identical body to another arm
Err(_) => {
unreachable!();
},
}
// False positive #1390
macro_rules! empty {
($e:expr) => {};
}
match 0 {
0 => {
empty!(0);
},
1 => {
empty!(1);
},
x => {
empty!(x);
},
};
// still lint if the tokens are the same
match 0 {
1 | 0 => {
empty!(0);
},
x => {
empty!(x);
},
}
//~^^^^^^^ ERROR: this match arm has an identical body to another arm
match_expr_like_matches_macro_priority();
}
fn match_expr_like_matches_macro_priority() {
enum E {
A,
B,
C,
}
let x = E::A;
let _ans = match x {
E::A => false,
E::B => false,
_ => true,
};
}
fn main() {
let _ = match Some(0) {
Some(0) => 0,
Some(1) => 1,
#[cfg(feature = "foo")]
Some(2) => 2,
_ => 1,
};
enum Foo {
X(u32),
Y(u32),
Z(u32),
}
// Don't lint. `Foo::X(0)` and `Foo::Z(_)` overlap with the arm in between.
let _ = match Foo::X(0) {
Foo::X(0) => 1,
Foo::X(_) | Foo::Y(_) | Foo::Z(0) => 2,
Foo::Z(_) => 1,
_ => 0,
};
// Suggest moving `Foo::Z(_)` up.
let _ = match Foo::X(0) {
Foo::X(0) | Foo::Z(_) => 1, //~ ERROR: this match arm has an identical body to another arm
Foo::X(_) | Foo::Y(_) => 2,
_ => 0,
};
// Suggest moving `Foo::X(0)` down.
let _ = match Foo::X(0) {
Foo::Y(_) | Foo::Z(0) => 2,
Foo::Z(_) | Foo::X(0) => 1, //~ ERROR: this match arm has an identical body to another arm
_ => 0,
};
// Don't lint.
let _ = match 0 {
-2 => 1,
-5..=50 => 2,
-150..=88 => 1,
_ => 3,
};
struct Bar {
x: u32,
y: u32,
z: u32,
}
// Lint.
let _ = match None {
Some(Bar { y: 10, z: 0, .. }) => 2,
None => 50,
Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. }) => 1, //~ ERROR: this match arm has an identical body to another arm
_ => 200,
};
let _ = match 0 {
0 => todo!(),
1 => todo!(),
2 => core::convert::identity::<u32>(todo!()),
3 => core::convert::identity::<u32>(todo!()),
_ => 5,
};
let _ = match 0 {
1 | 0 => cfg!(not_enable),
_ => false,
};
}
// issue #8919, fixed on https://github.com/rust-lang/rust/pull/97312
mod with_lifetime {
enum MaybeStaticStr<'a> {
Static(&'static str),
Borrowed(&'a str),
}
impl<'a> MaybeStaticStr<'a> {
fn get(&self) -> &'a str {
match *self {
MaybeStaticStr::Borrowed(s) | MaybeStaticStr::Static(s) => s,
//~^ ERROR: this match arm has an identical body to another arm
}
}
}
}

View file

@ -6,6 +6,9 @@
clippy::match_single_binding,
clippy::match_like_matches_macro
)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
fn bar<T>(_: T) {}
fn foo() -> bool {
unimplemented!()

View file

@ -1,5 +1,5 @@
error: this match arm has an identical body to the `_` wildcard arm
--> tests/ui/match_same_arms2.rs:16:9
--> tests/ui/match_same_arms2.rs:19:9
|
LL | / 42 => {
LL | | foo();
@ -12,7 +12,7 @@ LL | | _ => {
|
= help: or try changing either arm body
note: `_` wildcard arm here
--> tests/ui/match_same_arms2.rs:25:9
--> tests/ui/match_same_arms2.rs:28:9
|
LL | / _ => {
LL | | foo();
@ -26,7 +26,7 @@ LL | | },
= help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:39:9
--> tests/ui/match_same_arms2.rs:42:9
|
LL | 51 => foo(),
| ^^^^^^^^^^^
@ -42,7 +42,7 @@ LL - 42 => foo(),
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:45:9
--> tests/ui/match_same_arms2.rs:48:9
|
LL | None => 24,
| ^^^^^^^^^^
@ -58,7 +58,7 @@ LL - Some(_) => 24,
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:67:9
--> tests/ui/match_same_arms2.rs:70:9
|
LL | (None, Some(a)) => bar(a),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -74,7 +74,7 @@ LL - (Some(a), None) => bar(a),
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:81:9
--> tests/ui/match_same_arms2.rs:84:9
|
LL | (None, Some(a)) if a == 42 => a,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -90,7 +90,7 @@ LL - (Some(a), None) if a == 42 => a,
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:86:9
--> tests/ui/match_same_arms2.rs:89:9
|
LL | (Some(a), ..) => bar(a),
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -106,7 +106,7 @@ LL - (.., Some(a)) => bar(a),
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:120:9
--> tests/ui/match_same_arms2.rs:123:9
|
LL | (Ok(x), Some(_)) => println!("ok {}", x),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -122,7 +122,7 @@ LL - (Ok(_), Some(x)) => println!("ok {}", x),
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:136:9
--> tests/ui/match_same_arms2.rs:139:9
|
LL | Ok(_) => println!("ok"),
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -138,7 +138,7 @@ LL - Ok(3) => println!("ok"),
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:163:9
--> tests/ui/match_same_arms2.rs:166:9
|
LL | / 1 => {
LL | | empty!(0);
@ -158,7 +158,7 @@ LL - },
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:214:9
--> tests/ui/match_same_arms2.rs:217:9
|
LL | Foo::X(0) => 1,
| ^^^^^^^^^^^^^^
@ -174,7 +174,7 @@ LL - Foo::Z(_) => 1,
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:224:9
--> tests/ui/match_same_arms2.rs:227:9
|
LL | Foo::Z(_) => 1,
| ^^^^^^^^^^^^^^
@ -190,7 +190,7 @@ LL - Foo::X(0) => 1,
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:247:9
--> tests/ui/match_same_arms2.rs:250:9
|
LL | Some(Bar { y: 0, x: 5, .. }) => 1,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -206,7 +206,7 @@ LL - Some(Bar { x: 0, y: 5, .. }) => 1,
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:261:9
--> tests/ui/match_same_arms2.rs:264:9
|
LL | 1 => cfg!(not_enable),
| ^^^^^^^^^^^^^^^^^^^^^
@ -222,7 +222,7 @@ LL - 0 => cfg!(not_enable),
|
error: this match arm has an identical body to another arm
--> tests/ui/match_same_arms2.rs:277:17
--> tests/ui/match_same_arms2.rs:280:17
|
LL | MaybeStaticStr::Borrowed(s) => s,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -193,11 +193,5 @@ error: this ident consists of a single char
LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
| ^
error: this ident consists of a single char
--> tests/ui/min_ident_chars.rs:93:41
|
LL | struct Array<T, const N: usize>([T; N]);
| ^
error: aborting due to 33 previous errors
error: aborting due to 32 previous errors

View file

@ -200,7 +200,7 @@ mod with_ty_alias {
}
// NOTE: When checking the type of a function param, make sure it is not an alias with
// `AliasTyKind::Projection` before calling `TyCtxt::type_of` to find out what the actual type
// is. Because the associate ty could have no default, therefore would cause ICE, as demostrated
// is. Because the associate ty could have no default, therefore would cause ICE, as demonstrated
// in this test.
const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
}

View file

@ -200,7 +200,7 @@ mod with_ty_alias {
}
// NOTE: When checking the type of a function param, make sure it is not an alias with
// `AliasTyKind::Projection` before calling `TyCtxt::type_of` to find out what the actual type
// is. Because the associate ty could have no default, therefore would cause ICE, as demostrated
// is. Because the associate ty could have no default, therefore would cause ICE, as demonstrated
// in this test.
fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
}

View file

@ -10,7 +10,7 @@
/// unimplemented!();
/// }
/// ```
///
///
/// With an explicit return type it should lint too
/// ```edition2015
/// fn main() -> () {
@ -18,7 +18,7 @@
/// unimplemented!();
/// }
/// ```
///
///
/// This should, too.
/// ```rust
/// fn main() {
@ -26,7 +26,7 @@
/// unimplemented!();
/// }
/// ```
///
///
/// This one too.
/// ```no_run
/// // the fn is not always the first line

View file

@ -52,3 +52,21 @@ struct S<'a> {
fn from_field<'a>(s: &'a mut S<'a>) -> Option<&'a mut usize> {
s.opt.as_deref_mut()
}
mod issue_non_copy_13077 {
pub fn something(mut maybe_side_effect: Option<&mut String>) {
for _ in 0..10 {
let _ = S {
field: other(maybe_side_effect.as_deref_mut()),
};
}
}
fn other(_maybe_side_effect: Option<&mut String>) {
unimplemented!()
}
pub struct S {
pub field: (),
}
}

View file

@ -52,3 +52,21 @@ struct S<'a> {
fn from_field<'a>(s: &'a mut S<'a>) -> Option<&'a mut usize> {
s.opt.as_deref_mut()
}
mod issue_non_copy_13077 {
pub fn something(mut maybe_side_effect: Option<&mut String>) {
for _ in 0..10 {
let _ = S {
field: other(maybe_side_effect.as_deref_mut()),
};
}
}
fn other(_maybe_side_effect: Option<&mut String>) {
unimplemented!()
}
pub struct S {
pub field: (),
}
}

View file

@ -318,4 +318,51 @@ fn host_effect() {
Add::<i32>::add(1, 1).add(i32::MIN);
}
mod issue_10228 {
struct Entry;
impl Entry {
fn or_insert(self, _default: i32) {}
fn or_default(self) {
// Don't lint, suggested code is an infinite recursion
self.or_insert(Default::default())
}
}
}
// issue #12973
fn fn_call_in_nested_expr() {
struct Foo {
val: String,
}
fn f() -> i32 {
1
}
let opt: Option<i32> = Some(1);
//~v ERROR: use of `unwrap_or` followed by a function call
let _ = opt.unwrap_or_else(f); // suggest `.unwrap_or_else(f)`
//
//~v ERROR: use of `unwrap_or` followed by a function call
let _ = opt.unwrap_or_else(|| f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
//
//~v ERROR: use of `unwrap_or` followed by a function call
let _ = opt.unwrap_or_else(|| {
let x = f();
x + 1
});
//~v ERROR: use of `map_or` followed by a function call
let _ = opt.map_or_else(|| f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
//
//~v ERROR: use of `unwrap_or` to construct default value
let _ = opt.unwrap_or_default();
let opt_foo = Some(Foo {
val: String::from("123"),
});
//~v ERROR: use of `unwrap_or` followed by a function call
let _ = opt_foo.unwrap_or_else(|| Foo { val: String::default() });
}
fn main() {}

View file

@ -318,4 +318,51 @@ fn host_effect() {
Add::<i32>::add(1, 1).add(i32::MIN);
}
mod issue_10228 {
struct Entry;
impl Entry {
fn or_insert(self, _default: i32) {}
fn or_default(self) {
// Don't lint, suggested code is an infinite recursion
self.or_insert(Default::default())
}
}
}
// issue #12973
fn fn_call_in_nested_expr() {
struct Foo {
val: String,
}
fn f() -> i32 {
1
}
let opt: Option<i32> = Some(1);
//~v ERROR: use of `unwrap_or` followed by a function call
let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)`
//
//~v ERROR: use of `unwrap_or` followed by a function call
let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
//
//~v ERROR: use of `unwrap_or` followed by a function call
let _ = opt.unwrap_or({
let x = f();
x + 1
});
//~v ERROR: use of `map_or` followed by a function call
let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
//
//~v ERROR: use of `unwrap_or` to construct default value
let _ = opt.unwrap_or({ i32::default() });
let opt_foo = Some(Foo {
val: String::from("123"),
});
//~v ERROR: use of `unwrap_or` followed by a function call
let _ = opt_foo.unwrap_or(Foo { val: String::default() });
}
fn main() {}

View file

@ -196,5 +196,53 @@ error: use of `unwrap_or_else` to construct default value
LL | let _ = stringy.unwrap_or_else(String::new);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
error: aborting due to 32 previous errors
error: use of `unwrap_or` followed by a function call
--> tests/ui/or_fun_call.rs:345:17
|
LL | let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)`
| ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(f)`
error: use of `unwrap_or` followed by a function call
--> tests/ui/or_fun_call.rs:348:17
|
LL | let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
| ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| f() + 1)`
error: use of `unwrap_or` followed by a function call
--> tests/ui/or_fun_call.rs:351:17
|
LL | let _ = opt.unwrap_or({
| _________________^
LL | | let x = f();
LL | | x + 1
LL | | });
| |______^
|
help: try
|
LL ~ let _ = opt.unwrap_or_else(|| {
LL + let x = f();
LL + x + 1
LL ~ });
|
error: use of `map_or` followed by a function call
--> tests/ui/or_fun_call.rs:356:17
|
LL | let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| f() + 1, |v| v)`
error: use of `unwrap_or` to construct default value
--> tests/ui/or_fun_call.rs:359:17
|
LL | let _ = opt.unwrap_or({ i32::default() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
--> tests/ui/or_fun_call.rs:365:21
|
LL | let _ = opt_foo.unwrap_or(Foo { val: String::default() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Foo { val: String::default() })`
error: aborting due to 38 previous errors

View file

@ -1,6 +1,7 @@
use std::path::PathBuf;
#[warn(clippy::all, clippy::path_buf_push_overwrite)]
#[warn(clippy::path_buf_push_overwrite)]
#[allow(clippy::pathbuf_init_then_push)]
fn main() {
let mut x = PathBuf::from("/foo");
x.push("bar");

View file

@ -1,6 +1,7 @@
use std::path::PathBuf;
#[warn(clippy::all, clippy::path_buf_push_overwrite)]
#[warn(clippy::path_buf_push_overwrite)]
#[allow(clippy::pathbuf_init_then_push)]
fn main() {
let mut x = PathBuf::from("/foo");
x.push("/bar");

View file

@ -1,5 +1,5 @@
error: calling `push` with '/' or '\' (file system root) will overwrite the previous path definition
--> tests/ui/path_buf_push_overwrite.rs:6:12
--> tests/ui/path_buf_push_overwrite.rs:7:12
|
LL | x.push("/bar");
| ^^^^^^ help: try: `"bar"`

View file

@ -0,0 +1,22 @@
#![warn(clippy::pathbuf_init_then_push)]
use std::path::PathBuf;
fn main() {
let mut path_buf = PathBuf::from("foo");
path_buf = PathBuf::from("foo").join("bar");
let bar = "bar";
path_buf = PathBuf::from("foo").join(bar);
let mut path_buf = PathBuf::from("foo").join("bar").join("buz");
let mut x = PathBuf::new();
println!("{}", x.display());
x.push("Duck");
let mut path_buf = PathBuf::new();
#[cfg(cats)]
path_buf.push("foo");
}

View file

@ -0,0 +1,26 @@
#![warn(clippy::pathbuf_init_then_push)]
use std::path::PathBuf;
fn main() {
let mut path_buf = PathBuf::new(); //~ ERROR: calls to `push` immediately after creation
path_buf.push("foo");
path_buf = PathBuf::from("foo"); //~ ERROR: calls to `push` immediately after creation
path_buf.push("bar");
let bar = "bar";
path_buf = PathBuf::from("foo"); //~ ERROR: calls to `push` immediately after creation
path_buf.push(bar);
let mut path_buf = PathBuf::from("foo").join("bar"); //~ ERROR: calls to `push` immediately after creation
path_buf.push("buz");
let mut x = PathBuf::new();
println!("{}", x.display());
x.push("Duck");
let mut path_buf = PathBuf::new();
#[cfg(cats)]
path_buf.push("foo");
}

View file

@ -0,0 +1,33 @@
error: calls to `push` immediately after creation
--> tests/ui/pathbuf_init_then_push.rs:6:5
|
LL | / let mut path_buf = PathBuf::new();
LL | | path_buf.push("foo");
| |_________________________^ help: consider using the `.join()`: `let mut path_buf = PathBuf::from("foo");`
|
= note: `-D clippy::pathbuf-init-then-push` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::pathbuf_init_then_push)]`
error: calls to `push` immediately after creation
--> tests/ui/pathbuf_init_then_push.rs:9:5
|
LL | / path_buf = PathBuf::from("foo");
LL | | path_buf.push("bar");
| |_________________________^ help: consider using the `.join()`: `path_buf = PathBuf::from("foo").join("bar");`
error: calls to `push` immediately after creation
--> tests/ui/pathbuf_init_then_push.rs:13:5
|
LL | / path_buf = PathBuf::from("foo");
LL | | path_buf.push(bar);
| |_______________________^ help: consider using the `.join()`: `path_buf = PathBuf::from("foo").join(bar);`
error: calls to `push` immediately after creation
--> tests/ui/pathbuf_init_then_push.rs:16:5
|
LL | / let mut path_buf = PathBuf::from("foo").join("bar");
LL | | path_buf.push("buz");
| |_________________________^ help: consider using the `.join()`: `let mut path_buf = PathBuf::from("foo").join("bar").join("buz");`
error: aborting due to 4 previous errors

View file

@ -46,6 +46,10 @@ fn main() {
let _ = external!($ptr as *const u32);
}
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
v as _
}
#[clippy::msrv = "1.64"]
fn _msrv_1_64() {
let ptr: *const u32 = &42_u32;

View file

@ -46,6 +46,10 @@ fn main() {
let _ = external!($ptr as *const u32);
}
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
v as _
}
#[clippy::msrv = "1.64"]
fn _msrv_1_64() {
let ptr: *const u32 = &42_u32;

View file

@ -32,13 +32,13 @@ LL | let _ = mut_ptr as *const u32;
| ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
error: `as` casting between raw pointers while changing only its constness
--> tests/ui/ptr_cast_constness.rs:64:13
--> tests/ui/ptr_cast_constness.rs:68:13
|
LL | let _ = ptr as *mut u32;
| ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
error: `as` casting between raw pointers while changing only its constness
--> tests/ui/ptr_cast_constness.rs:65:13
--> tests/ui/ptr_cast_constness.rs:69:13
|
LL | let _ = mut_ptr as *const u32;
| ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`

View file

@ -3,6 +3,7 @@
#![allow(
clippy::drop_non_drop,
clippy::implicit_clone,
clippy::pathbuf_init_then_push,
clippy::uninlined_format_args,
clippy::unnecessary_literal_unwrap
)]

View file

@ -3,6 +3,7 @@
#![allow(
clippy::drop_non_drop,
clippy::implicit_clone,
clippy::pathbuf_init_then_push,
clippy::uninlined_format_args,
clippy::unnecessary_literal_unwrap
)]

View file

@ -1,11 +1,11 @@
error: redundant clone
--> tests/ui/redundant_clone.rs:14:42
--> tests/ui/redundant_clone.rs:15:42
|
LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
| ^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:14:14
--> tests/ui/redundant_clone.rs:15:14
|
LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -13,169 +13,169 @@ LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
= help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]`
error: redundant clone
--> tests/ui/redundant_clone.rs:17:15
--> tests/ui/redundant_clone.rs:18:15
|
LL | let _s = s.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:17:14
--> tests/ui/redundant_clone.rs:18:14
|
LL | let _s = s.clone();
| ^
error: redundant clone
--> tests/ui/redundant_clone.rs:20:15
--> tests/ui/redundant_clone.rs:21:15
|
LL | let _s = s.to_string();
| ^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:20:14
--> tests/ui/redundant_clone.rs:21:14
|
LL | let _s = s.to_string();
| ^
error: redundant clone
--> tests/ui/redundant_clone.rs:23:15
--> tests/ui/redundant_clone.rs:24:15
|
LL | let _s = s.to_owned();
| ^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:23:14
--> tests/ui/redundant_clone.rs:24:14
|
LL | let _s = s.to_owned();
| ^
error: redundant clone
--> tests/ui/redundant_clone.rs:25:42
--> tests/ui/redundant_clone.rs:26:42
|
LL | let _s = Path::new("/a/b/").join("c").to_owned();
| ^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:25:14
--> tests/ui/redundant_clone.rs:26:14
|
LL | let _s = Path::new("/a/b/").join("c").to_owned();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: redundant clone
--> tests/ui/redundant_clone.rs:27:42
--> tests/ui/redundant_clone.rs:28:42
|
LL | let _s = Path::new("/a/b/").join("c").to_path_buf();
| ^^^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:27:14
--> tests/ui/redundant_clone.rs:28:14
|
LL | let _s = Path::new("/a/b/").join("c").to_path_buf();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: redundant clone
--> tests/ui/redundant_clone.rs:29:29
--> tests/ui/redundant_clone.rs:30:29
|
LL | let _s = OsString::new().to_owned();
| ^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:29:14
--> tests/ui/redundant_clone.rs:30:14
|
LL | let _s = OsString::new().to_owned();
| ^^^^^^^^^^^^^^^
error: redundant clone
--> tests/ui/redundant_clone.rs:31:29
--> tests/ui/redundant_clone.rs:32:29
|
LL | let _s = OsString::new().to_os_string();
| ^^^^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:31:14
--> tests/ui/redundant_clone.rs:32:14
|
LL | let _s = OsString::new().to_os_string();
| ^^^^^^^^^^^^^^^
error: redundant clone
--> tests/ui/redundant_clone.rs:42:19
--> tests/ui/redundant_clone.rs:43:19
|
LL | let _t = tup.0.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:42:14
--> tests/ui/redundant_clone.rs:43:14
|
LL | let _t = tup.0.clone();
| ^^^^^
error: redundant clone
--> tests/ui/redundant_clone.rs:74:25
--> tests/ui/redundant_clone.rs:75:25
|
LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) }
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:74:24
--> tests/ui/redundant_clone.rs:75:24
|
LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) }
| ^
error: redundant clone
--> tests/ui/redundant_clone.rs:131:15
|
LL | let _s = s.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:131:14
|
LL | let _s = s.clone();
| ^
error: redundant clone
--> tests/ui/redundant_clone.rs:132:15
|
LL | let _t = t.clone();
LL | let _s = s.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:132:14
|
LL | let _s = s.clone();
| ^
error: redundant clone
--> tests/ui/redundant_clone.rs:133:15
|
LL | let _t = t.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:133:14
|
LL | let _t = t.clone();
| ^
error: redundant clone
--> tests/ui/redundant_clone.rs:142:19
--> tests/ui/redundant_clone.rs:143:19
|
LL | let _f = f.clone();
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:142:18
--> tests/ui/redundant_clone.rs:143:18
|
LL | let _f = f.clone();
| ^
error: redundant clone
--> tests/ui/redundant_clone.rs:154:14
--> tests/ui/redundant_clone.rs:155:14
|
LL | let y = x.clone().join("matthias");
| ^^^^^^^^ help: remove this
|
note: cloned value is neither consumed nor mutated
--> tests/ui/redundant_clone.rs:154:13
--> tests/ui/redundant_clone.rs:155:13
|
LL | let y = x.clone().join("matthias");
| ^^^^^^^^^
error: redundant clone
--> tests/ui/redundant_clone.rs:208:11
--> tests/ui/redundant_clone.rs:209:11
|
LL | foo(&x.clone(), move || {
| ^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/redundant_clone.rs:208:10
--> tests/ui/redundant_clone.rs:209:10
|
LL | foo(&x.clone(), move || {
| ^

View file

@ -1,144 +0,0 @@
#![warn(clippy::significant_drop_tightening)]
use std::sync::Mutex;
pub fn complex_return_triggers_the_lint() -> i32 {
fn foo() -> i32 {
1
}
let mutex = Mutex::new(1);
let lock = mutex.lock().unwrap();
let _ = *lock;
let _ = *lock;
drop(lock);
foo()
}
pub fn issue_10413() {
let mutex = Mutex::new(Some(1));
let opt = Some(1);
if opt.is_some() {
let lock = mutex.lock().unwrap();
let _ = *lock;
if opt.is_some() {
let _ = *lock;
}
}
}
pub fn issue_11128() {
use std::mem::drop as unlock;
struct Foo {
droppable: Option<Vec<i32>>,
mutex: Mutex<Vec<i32>>,
}
impl Drop for Foo {
fn drop(&mut self) {
if let Some(droppable) = self.droppable.take() {
let lock = self.mutex.lock().unwrap();
let idx_opt = lock.iter().copied().find(|el| Some(el) == droppable.first());
if let Some(idx) = idx_opt {
let local_droppable = vec![lock.first().copied().unwrap_or_default()];
unlock(lock);
drop(local_droppable);
}
}
}
}
}
pub fn issue_11160() -> bool {
let mutex = Mutex::new(1i32);
let lock = mutex.lock().unwrap();
let _ = lock.abs();
true
}
pub fn issue_11189() {
struct Number {
pub value: u32,
}
fn do_something() -> Result<(), ()> {
let number = Mutex::new(Number { value: 1 });
let number2 = Mutex::new(Number { value: 2 });
let number3 = Mutex::new(Number { value: 3 });
let mut lock = number.lock().unwrap();
let mut lock2 = number2.lock().unwrap();
let mut lock3 = number3.lock().unwrap();
lock.value += 1;
lock2.value += 1;
lock3.value += 1;
drop((lock, lock2, lock3));
Ok(())
}
}
pub fn path_return_can_be_ignored() -> i32 {
let mutex = Mutex::new(1);
let lock = mutex.lock().unwrap();
let rslt = *lock;
let _ = *lock;
rslt
}
pub fn post_bindings_can_be_ignored() {
let mutex = Mutex::new(1);
let lock = mutex.lock().unwrap();
let rslt = *lock;
let another = rslt;
let _ = another;
}
pub fn unnecessary_contention_with_multiple_owned_results() {
{
let mutex = Mutex::new(1i32);
let lock = mutex.lock().unwrap();
let _ = lock.abs();
let _ = lock.is_positive();
}
{
let mutex = Mutex::new(1i32);
let lock = mutex.lock().unwrap();
let rslt0 = lock.abs();
let rslt1 = lock.is_positive();
drop(lock);
do_heavy_computation_that_takes_time((rslt0, rslt1));
}
}
pub fn unnecessary_contention_with_single_owned_results() {
{
let mutex = Mutex::new(1i32);
let lock = mutex.lock().unwrap();
let _ = lock.abs();
}
{
let mutex = Mutex::new(vec![1i32]);
let mut lock = mutex.lock().unwrap();
lock.clear();
}
{
let mutex = Mutex::new(1i32);
let rslt0 = mutex.lock().unwrap().abs();
do_heavy_computation_that_takes_time(rslt0);
}
{
let mutex = Mutex::new(vec![1i32]);
mutex.lock().unwrap().clear();
do_heavy_computation_that_takes_time(());
}
}
// Marker used for illustration purposes.
pub fn do_heavy_computation_that_takes_time<T>(_: T) {}
fn main() {}

View file

@ -1,5 +1,7 @@
#![warn(clippy::significant_drop_tightening)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
use std::sync::Mutex;
pub fn complex_return_triggers_the_lint() -> i32 {

View file

@ -1,5 +1,5 @@
error: temporary with significant `Drop` can be early dropped
--> tests/ui/significant_drop_tightening.rs:10:9
--> tests/ui/significant_drop_tightening.rs:12:9
|
LL | pub fn complex_return_triggers_the_lint() -> i32 {
| __________________________________________________-
@ -24,7 +24,7 @@ LL + drop(lock);
|
error: temporary with significant `Drop` can be early dropped
--> tests/ui/significant_drop_tightening.rs:104:13
--> tests/ui/significant_drop_tightening.rs:106:13
|
LL | / {
LL | | let mutex = Mutex::new(1i32);
@ -44,7 +44,7 @@ LL + drop(lock);
|
error: temporary with significant `Drop` can be early dropped
--> tests/ui/significant_drop_tightening.rs:125:13
--> tests/ui/significant_drop_tightening.rs:127:13
|
LL | / {
LL | | let mutex = Mutex::new(1i32);
@ -67,7 +67,7 @@ LL - let rslt0 = lock.abs();
|
error: temporary with significant `Drop` can be early dropped
--> tests/ui/significant_drop_tightening.rs:131:17
--> tests/ui/significant_drop_tightening.rs:133:17
|
LL | / {
LL | | let mutex = Mutex::new(vec![1i32]);

View file

@ -57,4 +57,12 @@ fn main() {
}
};
}
// Should lint with correct suggestion (issue #12782)
let res_void: Result<bool, bool> = Ok(true);
{
let (Ok(mut _x) | Err(mut _x)) = res_void;
let ptr: *const bool = std::ptr::null();
}
}

View file

@ -54,4 +54,11 @@ fn main() {
}
};
}
// Should lint with correct suggestion (issue #12782)
let res_void: Result<bool, bool> = Ok(true);
for (Ok(mut _x) | Err(mut _x)) in [res_void] {
let ptr: *const bool = std::ptr::null();
}
}

View file

@ -83,5 +83,21 @@ LL + };
LL + }
|
error: aborting due to 7 previous errors
error: for loop over a single element
--> tests/ui/single_element_loop.rs:61:5
|
LL | / for (Ok(mut _x) | Err(mut _x)) in [res_void] {
LL | | let ptr: *const bool = std::ptr::null();
LL | | }
| |_____^
|
help: try
|
LL ~ {
LL + let (Ok(mut _x) | Err(mut _x)) = res_void;
LL + let ptr: *const bool = std::ptr::null();
LL + }
|
error: aborting due to 8 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
--> tests/ui/temporary_assignment.rs:48:5
--> tests/ui/temporary_assignment.rs:47:5
|
LL | Struct { field: 0 }.field = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -8,7 +8,7 @@ LL | Struct { field: 0 }.field = 1;
= help: to override `-D warnings` add `#[allow(clippy::temporary_assignment)]`
error: assignment to temporary
--> tests/ui/temporary_assignment.rs:51:5
--> tests/ui/temporary_assignment.rs:50:5
|
LL | / MultiStruct {
LL | |
@ -19,13 +19,13 @@ LL | | .field = 1;
| |______________^
error: assignment to temporary
--> tests/ui/temporary_assignment.rs:57:5
--> tests/ui/temporary_assignment.rs:56:5
|
LL | ArrayStruct { array: [0] }.array[0] = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: assignment to temporary
--> tests/ui/temporary_assignment.rs:59:5
--> tests/ui/temporary_assignment.rs:58:5
|
LL | (0, 0).0 = 1;
| ^^^^^^^^^^^^

View file

@ -0,0 +1,8 @@
//@compile-flags: -C incremental=target/debug/test/incr
// see https://github.com/rust-lang/rust-clippy/issues/10969
fn main() {
let s = "Hello, world!";
println!("{}", s);
}

View file

@ -0,0 +1,8 @@
//@compile-flags: -C incremental=target/debug/test/incr
// see https://github.com/rust-lang/rust-clippy/issues/10969
fn main() {
let s = "Hello, world!";
println!("{}", s.to_string());
}

View file

@ -0,0 +1,11 @@
error: `to_string` applied to a type that implements `Display` in `println!` args
--> tests/ui/to_string_in_format_args_incremental.rs:7:21
|
LL | println!("{}", s.to_string());
| ^^^^^^^^^^^^ help: remove this
|
= note: `-D clippy::to-string-in-format-args` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::to_string_in_format_args)]`
error: aborting due to 1 previous error

View file

@ -36,4 +36,6 @@ fn main() {
// do not lint in external macro
external!(let ref _y = 42;);
fn f(#[allow(clippy::toplevel_ref_arg)] ref x: i32) {}
}

View file

@ -36,4 +36,6 @@ fn main() {
// do not lint in external macro
external!(let ref _y = 42;);
fn f(#[allow(clippy::toplevel_ref_arg)] ref x: i32) {}
}

View file

@ -1,17 +1,19 @@
#![warn(clippy::transmute_ptr_to_ptr)]
#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
use std::mem::transmute;
// Make sure we can modify lifetimes, which is one of the recommended uses
// of transmute
// Make sure we can do static lifetime transmutes
unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T {
std::mem::transmute::<&'a T, &'static T>(t)
transmute::<&'a T, &'static T>(t)
}
// Make sure we can do non-static lifetime transmutes
unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T {
std::mem::transmute::<&'a T, &'b T>(t)
transmute::<&'a T, &'b T>(t)
}
struct LifetimeParam<'a> {
@ -27,39 +29,40 @@ fn transmute_ptr_to_ptr() {
let mut_ptr = &mut 1u32 as *mut u32;
unsafe {
// pointer-to-pointer transmutes; bad
let _: *const f32 = ptr as *const f32;
//~^ ERROR: transmute from a pointer to a pointer
//~| NOTE: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
let _: *mut f32 = mut_ptr as *mut f32;
//~^ ERROR: transmute from a pointer to a pointer
let _: *const f32 = ptr.cast::<f32>();
//~^ transmute_ptr_to_ptr
let _: *mut f32 = mut_ptr.cast::<f32>();
//~^ transmute_ptr_to_ptr
// ref-ref transmutes; bad
let _: &f32 = &*(&1u32 as *const u32 as *const f32);
//~^ ERROR: transmute from a reference to a reference
//~^ transmute_ptr_to_ptr
let _: &f32 = &*(&1f64 as *const f64 as *const f32);
//~^ ERROR: transmute from a reference to a reference
//~^ transmute_ptr_to_ptr
//:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not
// the same type
let _: &mut f32 = &mut *(&mut 1u32 as *mut u32 as *mut f32);
//~^ ERROR: transmute from a reference to a reference
//~^ transmute_ptr_to_ptr
let _: &GenericParam<f32> = &*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>);
//~^ ERROR: transmute from a reference to a reference
//~^ transmute_ptr_to_ptr
let u64_ref: &u64 = &0u64;
let u8_ref: &u8 = unsafe { &*(u64_ref as *const u64 as *const u8) };
//~^ ERROR: transmute from a reference to a reference
let u8_ref: &u8 = &*(u64_ref as *const u64 as *const u8);
//~^ transmute_ptr_to_ptr
let _: *const u32 = mut_ptr.cast_const();
//~^ transmute_ptr_to_ptr
let _: *mut u32 = ptr.cast_mut();
//~^ transmute_ptr_to_ptr
}
// these are recommendations for solving the above; if these lint we need to update
// those suggestions
let _ = ptr as *const f32;
let _ = mut_ptr as *mut f32;
let _ = unsafe { &*(&1u32 as *const u32 as *const f32) };
let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) };
// transmute internal lifetimes, should not lint
let s = "hello world".to_owned();
let lp = LifetimeParam { s: &s };
let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) };
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) };
let _: &LifetimeParam<'static> = unsafe { transmute(&lp) };
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) };
}
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
unsafe { v as *const &() }
//~^ transmute_ptr_to_ptr
}
// dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959)
@ -67,7 +70,37 @@ const _: &() = {
struct Zst;
let zst = &Zst;
unsafe { std::mem::transmute::<&'static Zst, &'static ()>(zst) }
unsafe { transmute::<&'static Zst, &'static ()>(zst) }
};
#[clippy::msrv = "1.37"]
fn msrv_1_37(ptr: *const u8) {
unsafe {
let _: *const i8 = ptr as *const i8;
}
}
#[clippy::msrv = "1.38"]
fn msrv_1_38(ptr: *const u8) {
unsafe {
let _: *const i8 = ptr.cast::<i8>();
}
}
#[clippy::msrv = "1.64"]
fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) {
unsafe {
let _: *mut u8 = ptr as *mut u8;
let _: *const u8 = mut_ptr as *const u8;
}
}
#[clippy::msrv = "1.65"]
fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) {
unsafe {
let _: *mut u8 = ptr.cast_mut();
let _: *const u8 = mut_ptr.cast_const();
}
}
fn main() {}

View file

@ -1,17 +1,19 @@
#![warn(clippy::transmute_ptr_to_ptr)]
#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
use std::mem::transmute;
// Make sure we can modify lifetimes, which is one of the recommended uses
// of transmute
// Make sure we can do static lifetime transmutes
unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T {
std::mem::transmute::<&'a T, &'static T>(t)
transmute::<&'a T, &'static T>(t)
}
// Make sure we can do non-static lifetime transmutes
unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T {
std::mem::transmute::<&'a T, &'b T>(t)
transmute::<&'a T, &'b T>(t)
}
struct LifetimeParam<'a> {
@ -27,39 +29,40 @@ fn transmute_ptr_to_ptr() {
let mut_ptr = &mut 1u32 as *mut u32;
unsafe {
// pointer-to-pointer transmutes; bad
let _: *const f32 = std::mem::transmute(ptr);
//~^ ERROR: transmute from a pointer to a pointer
//~| NOTE: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
let _: *mut f32 = std::mem::transmute(mut_ptr);
//~^ ERROR: transmute from a pointer to a pointer
let _: *const f32 = transmute(ptr);
//~^ transmute_ptr_to_ptr
let _: *mut f32 = transmute(mut_ptr);
//~^ transmute_ptr_to_ptr
// ref-ref transmutes; bad
let _: &f32 = std::mem::transmute(&1u32);
//~^ ERROR: transmute from a reference to a reference
let _: &f32 = std::mem::transmute(&1f64);
//~^ ERROR: transmute from a reference to a reference
let _: &f32 = transmute(&1u32);
//~^ transmute_ptr_to_ptr
let _: &f32 = transmute(&1f64);
//~^ transmute_ptr_to_ptr
//:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not
// the same type
let _: &mut f32 = std::mem::transmute(&mut 1u32);
//~^ ERROR: transmute from a reference to a reference
let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
//~^ ERROR: transmute from a reference to a reference
let _: &mut f32 = transmute(&mut 1u32);
//~^ transmute_ptr_to_ptr
let _: &GenericParam<f32> = transmute(&GenericParam { t: 1u32 });
//~^ transmute_ptr_to_ptr
let u64_ref: &u64 = &0u64;
let u8_ref: &u8 = unsafe { std::mem::transmute(u64_ref) };
//~^ ERROR: transmute from a reference to a reference
let u8_ref: &u8 = transmute(u64_ref);
//~^ transmute_ptr_to_ptr
let _: *const u32 = transmute(mut_ptr);
//~^ transmute_ptr_to_ptr
let _: *mut u32 = transmute(ptr);
//~^ transmute_ptr_to_ptr
}
// these are recommendations for solving the above; if these lint we need to update
// those suggestions
let _ = ptr as *const f32;
let _ = mut_ptr as *mut f32;
let _ = unsafe { &*(&1u32 as *const u32 as *const f32) };
let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) };
// transmute internal lifetimes, should not lint
let s = "hello world".to_owned();
let lp = LifetimeParam { s: &s };
let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) };
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) };
let _: &LifetimeParam<'static> = unsafe { transmute(&lp) };
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) };
}
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
unsafe { transmute(v) }
//~^ transmute_ptr_to_ptr
}
// dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959)
@ -67,7 +70,37 @@ const _: &() = {
struct Zst;
let zst = &Zst;
unsafe { std::mem::transmute::<&'static Zst, &'static ()>(zst) }
unsafe { transmute::<&'static Zst, &'static ()>(zst) }
};
#[clippy::msrv = "1.37"]
fn msrv_1_37(ptr: *const u8) {
unsafe {
let _: *const i8 = transmute(ptr);
}
}
#[clippy::msrv = "1.38"]
fn msrv_1_38(ptr: *const u8) {
unsafe {
let _: *const i8 = transmute(ptr);
}
}
#[clippy::msrv = "1.64"]
fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) {
unsafe {
let _: *mut u8 = transmute(ptr);
let _: *const u8 = transmute(mut_ptr);
}
}
#[clippy::msrv = "1.65"]
fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) {
unsafe {
let _: *mut u8 = transmute(ptr);
let _: *const u8 = transmute(mut_ptr);
}
}
fn main() {}

View file

@ -1,47 +1,155 @@
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:30:29
--> tests/ui/transmute_ptr_to_ptr.rs:32:29
|
LL | let _: *const f32 = std::mem::transmute(ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32`
LL | let _: *const f32 = transmute(ptr);
| ^^^^^^^^^^^^^^
|
= note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ptr)]`
help: use `pointer::cast` instead
|
LL | let _: *const f32 = ptr.cast::<f32>();
| ~~~~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:33:27
--> tests/ui/transmute_ptr_to_ptr.rs:34:27
|
LL | let _: *mut f32 = std::mem::transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32`
LL | let _: *mut f32 = transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^
|
help: use `pointer::cast` instead
|
LL | let _: *mut f32 = mut_ptr.cast::<f32>();
| ~~~~~~~~~~~~~~~~~~~~~
error: transmute from a reference to a reference
--> tests/ui/transmute_ptr_to_ptr.rs:36:23
--> tests/ui/transmute_ptr_to_ptr.rs:37:23
|
LL | let _: &f32 = std::mem::transmute(&1u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)`
LL | let _: &f32 = transmute(&1u32);
| ^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)`
error: transmute from a reference to a reference
--> tests/ui/transmute_ptr_to_ptr.rs:38:23
--> tests/ui/transmute_ptr_to_ptr.rs:39:23
|
LL | let _: &f32 = std::mem::transmute(&1f64);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f64 as *const f64 as *const f32)`
LL | let _: &f32 = transmute(&1f64);
| ^^^^^^^^^^^^^^^^ help: try: `&*(&1f64 as *const f64 as *const f32)`
error: transmute from a reference to a reference
--> tests/ui/transmute_ptr_to_ptr.rs:42:27
--> tests/ui/transmute_ptr_to_ptr.rs:43:27
|
LL | let _: &mut f32 = std::mem::transmute(&mut 1u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)`
LL | let _: &mut f32 = transmute(&mut 1u32);
| ^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)`
error: transmute from a reference to a reference
--> tests/ui/transmute_ptr_to_ptr.rs:44:37
--> tests/ui/transmute_ptr_to_ptr.rs:45:37
|
LL | let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>)`
LL | let _: &GenericParam<f32> = transmute(&GenericParam { t: 1u32 });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>)`
error: transmute from a reference to a reference
--> tests/ui/transmute_ptr_to_ptr.rs:47:36
--> tests/ui/transmute_ptr_to_ptr.rs:48:27
|
LL | let u8_ref: &u8 = unsafe { std::mem::transmute(u64_ref) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(u64_ref as *const u64 as *const u8)`
LL | let u8_ref: &u8 = transmute(u64_ref);
| ^^^^^^^^^^^^^^^^^^ help: try: `&*(u64_ref as *const u64 as *const u8)`
error: aborting due to 7 previous errors
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:50:29
|
LL | let _: *const u32 = transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^
|
help: use `pointer::cast_const` instead
|
LL | let _: *const u32 = mut_ptr.cast_const();
| ~~~~~~~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:52:27
|
LL | let _: *mut u32 = transmute(ptr);
| ^^^^^^^^^^^^^^
|
help: use `pointer::cast_mut` instead
|
LL | let _: *mut u32 = ptr.cast_mut();
| ~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:64:14
|
LL | unsafe { transmute(v) }
| ^^^^^^^^^^^^
|
help: use an `as` cast instead
|
LL | unsafe { v as *const &() }
| ~~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:79:28
|
LL | let _: *const i8 = transmute(ptr);
| ^^^^^^^^^^^^^^
|
help: use an `as` cast instead
|
LL | let _: *const i8 = ptr as *const i8;
| ~~~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:86:28
|
LL | let _: *const i8 = transmute(ptr);
| ^^^^^^^^^^^^^^
|
help: use `pointer::cast` instead
|
LL | let _: *const i8 = ptr.cast::<i8>();
| ~~~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:93:26
|
LL | let _: *mut u8 = transmute(ptr);
| ^^^^^^^^^^^^^^
|
help: use an `as` cast instead
|
LL | let _: *mut u8 = ptr as *mut u8;
| ~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:94:28
|
LL | let _: *const u8 = transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^
|
help: use an `as` cast instead
|
LL | let _: *const u8 = mut_ptr as *const u8;
| ~~~~~~~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:101:26
|
LL | let _: *mut u8 = transmute(ptr);
| ^^^^^^^^^^^^^^
|
help: use `pointer::cast_mut` instead
|
LL | let _: *mut u8 = ptr.cast_mut();
| ~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmute_ptr_to_ptr.rs:102:28
|
LL | let _: *const u8 = transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^
|
help: use `pointer::cast_const` instead
|
LL | let _: *const u8 = mut_ptr.cast_const();
| ~~~~~~~~~~~~~~~~~~~~
error: aborting due to 16 previous errors

View file

@ -18,7 +18,7 @@ fn main() {
let ptr_i32 = usize::MAX as *const i32;
// e has type *T, U is *U_0, and either U_0: Sized ...
let _ptr_i8_transmute = unsafe { ptr_i32 as *const i8 };
let _ptr_i8_transmute = unsafe { ptr_i32.cast::<i8>() };
let _ptr_i8 = ptr_i32 as *const i8;
let slice_ptr = &[0, 1, 2, 3] as *const [i32];

View file

@ -11,16 +11,25 @@ error: transmute from a pointer to a pointer
--> tests/ui/transmutes_expressible_as_ptr_casts.rs:21:38
|
LL | let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as *const i8`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ptr)]`
help: use `pointer::cast` instead
|
LL | let _ptr_i8_transmute = unsafe { ptr_i32.cast::<i8>() };
| ~~~~~~~~~~~~~~~~~~~~
error: transmute from a pointer to a pointer
--> tests/ui/transmutes_expressible_as_ptr_casts.rs:27:46
|
LL | let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u32]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: use an `as` cast instead
|
LL | let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u32] };
| ~~~~~~~~~~~~~~~~~~~~~~~~~
error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead
--> tests/ui/transmutes_expressible_as_ptr_casts.rs:33:50

View file

@ -1,13 +0,0 @@
#![allow(dead_code, unused_variables)]
#![warn(clippy::cast_lossless)]
// should not warn on lossy casting in constant types
// because not supported yet
const C: i32 = 42;
const C_I64: i64 = C as i64;
fn main() {
// should suggest i64::from(c)
let c: i32 = 42;
let c_i64: i64 = i64::from(c);
}

View file

@ -1,13 +0,0 @@
#![allow(dead_code, unused_variables)]
#![warn(clippy::cast_lossless)]
// should not warn on lossy casting in constant types
// because not supported yet
const C: i32 = 42;
const C_I64: i64 = C as i64;
fn main() {
// should suggest i64::from(c)
let c: i32 = 42;
let c_i64: i64 = c as i64;
}

View file

@ -1,11 +0,0 @@
error: casting `i32` to `i64` may become silently lossy if you later change the type
--> tests/ui/types.rs:12:22
|
LL | let c_i64: i64 = c as i64;
| ^^^^^^^^ help: try: `i64::from(c)`
|
= note: `-D clippy::cast-lossless` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
error: aborting due to 1 previous error

View file

@ -1,201 +0,0 @@
#![allow(unused_assignments)]
#![warn(clippy::unnecessary_to_owned)]
#[allow(dead_code)]
#[derive(Clone, Copy)]
enum FileType {
Account,
PrivateKey,
Certificate,
}
fn main() {
let path = std::path::Path::new("x");
let _ = check_files(&[(FileType::Account, path)]);
let _ = check_files_vec(vec![(FileType::Account, path)]);
// negative tests
let _ = check_files_ref(&[(FileType::Account, path)]);
let _ = check_files_mut(&[(FileType::Account, path)]);
let _ = check_files_ref_mut(&[(FileType::Account, path)]);
let _ = check_files_self_and_arg(&[(FileType::Account, path)]);
let _ = check_files_mut_path_buf(&[(FileType::Account, std::path::PathBuf::new())]);
check_mut_iteratee_and_modify_inner_variable();
}
// `check_files` and its variants are based on:
// https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
fn check_files(files: &[(FileType, &std::path::Path)]) -> bool {
for (t, path) in files {
let other = match get_file_path(t) {
Ok(p) => p,
Err(_) => {
return false;
},
};
if !path.is_file() || !other.is_file() {
return false;
}
}
true
}
fn check_files_vec(files: Vec<(FileType, &std::path::Path)>) -> bool {
for (t, path) in files.iter() {
let other = match get_file_path(t) {
Ok(p) => p,
Err(_) => {
return false;
},
};
if !path.is_file() || !other.is_file() {
return false;
}
}
true
}
fn check_files_ref(files: &[(FileType, &std::path::Path)]) -> bool {
for (ref t, path) in files.iter().copied() {
let other = match get_file_path(t) {
Ok(p) => p,
Err(_) => {
return false;
},
};
if !path.is_file() || !other.is_file() {
return false;
}
}
true
}
#[allow(unused_assignments)]
fn check_files_mut(files: &[(FileType, &std::path::Path)]) -> bool {
for (mut t, path) in files.iter().copied() {
t = FileType::PrivateKey;
let other = match get_file_path(&t) {
Ok(p) => p,
Err(_) => {
return false;
},
};
if !path.is_file() || !other.is_file() {
return false;
}
}
true
}
fn check_files_ref_mut(files: &[(FileType, &std::path::Path)]) -> bool {
for (ref mut t, path) in files.iter().copied() {
*t = FileType::PrivateKey;
let other = match get_file_path(t) {
Ok(p) => p,
Err(_) => {
return false;
},
};
if !path.is_file() || !other.is_file() {
return false;
}
}
true
}
fn check_files_self_and_arg(files: &[(FileType, &std::path::Path)]) -> bool {
for (t, path) in files.iter().copied() {
let other = match get_file_path(&t) {
Ok(p) => p,
Err(_) => {
return false;
},
};
if !path.join(path).is_file() || !other.is_file() {
return false;
}
}
true
}
#[allow(unused_assignments)]
fn check_files_mut_path_buf(files: &[(FileType, std::path::PathBuf)]) -> bool {
for (mut t, path) in files.iter().cloned() {
t = FileType::PrivateKey;
let other = match get_file_path(&t) {
Ok(p) => p,
Err(_) => {
return false;
},
};
if !path.is_file() || !other.is_file() {
return false;
}
}
true
}
fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
Ok(std::path::PathBuf::new())
}
// Issue 12098
// https://github.com/rust-lang/rust-clippy/issues/12098
// no message emits
fn check_mut_iteratee_and_modify_inner_variable() {
struct Test {
list: Vec<String>,
mut_this: bool,
}
impl Test {
fn list(&self) -> &[String] {
&self.list
}
}
let mut test = Test {
list: vec![String::from("foo"), String::from("bar")],
mut_this: false,
};
for _item in test.list().to_vec() {
println!("{}", _item);
test.mut_this = true;
{
test.mut_this = true;
}
}
}
mod issue_12821 {
fn foo() {
let v: Vec<_> = "hello".chars().collect();
for c in v.iter() {
//~^ ERROR: unnecessary use of `cloned`
println!("{c}"); // should not suggest to remove `&`
}
}
fn bar() {
let v: Vec<_> = "hello".chars().collect();
for c in v.iter() {
//~^ ERROR: unnecessary use of `cloned`
let ref_c = c; //~ HELP: remove any references to the binding
println!("{ref_c}");
}
}
fn baz() {
let v: Vec<_> = "hello".chars().enumerate().collect();
for (i, c) in v.iter() {
//~^ ERROR: unnecessary use of `cloned`
let ref_c = c; //~ HELP: remove any references to the binding
let ref_i = i;
println!("{i} {ref_c}"); // should not suggest to remove `&` from `i`
}
}
}

View file

@ -1,6 +1,8 @@
#![allow(unused_assignments)]
#![warn(clippy::unnecessary_to_owned)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
#[allow(dead_code)]
#[derive(Clone, Copy)]
enum FileType {

View file

@ -1,5 +1,5 @@
error: unnecessary use of `copied`
--> tests/ui/unnecessary_iter_cloned.rs:31:22
--> tests/ui/unnecessary_iter_cloned.rs:33:22
|
LL | for (t, path) in files.iter().copied() {
| ^^^^^^^^^^^^^^^^^^^^^
@ -17,7 +17,7 @@ LL + let other = match get_file_path(t) {
|
error: unnecessary use of `copied`
--> tests/ui/unnecessary_iter_cloned.rs:46:22
--> tests/ui/unnecessary_iter_cloned.rs:48:22
|
LL | for (t, path) in files.iter().copied() {
| ^^^^^^^^^^^^^^^^^^^^^
@ -33,13 +33,13 @@ LL + let other = match get_file_path(t) {
|
error: unnecessary use of `cloned`
--> tests/ui/unnecessary_iter_cloned.rs:177:18
--> tests/ui/unnecessary_iter_cloned.rs:179:18
|
LL | for c in v.iter().cloned() {
| ^^^^^^^^^^^^^^^^^ help: use: `v.iter()`
error: unnecessary use of `cloned`
--> tests/ui/unnecessary_iter_cloned.rs:185:18
--> tests/ui/unnecessary_iter_cloned.rs:187:18
|
LL | for c in v.iter().cloned() {
| ^^^^^^^^^^^^^^^^^
@ -55,7 +55,7 @@ LL + let ref_c = c;
|
error: unnecessary use of `cloned`
--> tests/ui/unnecessary_iter_cloned.rs:194:23
--> tests/ui/unnecessary_iter_cloned.rs:196:23
|
LL | for (i, c) in v.iter().cloned() {
| ^^^^^^^^^^^^^^^^^

View file

@ -26,6 +26,11 @@ struct V {
f: u32,
}
struct W {
f1: u32,
f2: u32,
}
impl Clone for V {
fn clone(&self) -> Self {
// Lint: `Self` implements `Copy`
@ -68,4 +73,69 @@ fn main() {
// Should lint: the result of an expression is mutable and temporary
let p = &mut *Box::new(T { f: 5 });
// Should lint: all fields of `q` would be consumed anyway
let q = W { f1: 42, f2: 1337 };
let r = q;
// Should not lint: not all fields of `t` from same source
let s = W { f1: 1337, f2: 42 };
let t = W { f1: s.f1, f2: r.f2 };
// Should not lint: different fields of `s` assigned
let u = W { f1: s.f2, f2: s.f1 };
// Should lint: all fields of `v` would be consumed anyway
let v = W { f1: 42, f2: 1337 };
let w = v;
// Should not lint: source differs between fields and base
let x = W { f1: 42, f2: 1337 };
let y = W { f1: w.f1, ..x };
// Should lint: range desugars to struct
let r1 = 0..5;
let r2 = r1;
references();
shorthand();
}
fn references() {
// Should not lint as `a` is not mutable
let a = W { f1: 42, f2: 1337 };
let b = &mut W { f1: a.f1, f2: a.f2 };
// Should lint as `d` is a shared reference
let c = W { f1: 42, f2: 1337 };
let d = &c;
// Should not lint as `e` is not mutable
let e = W { f1: 42, f2: 1337 };
let f = &mut W { f1: e.f1, ..e };
// Should lint as `h` is a shared reference
let g = W { f1: 42, f2: 1337 };
let h = &g;
// Should not lint as `j` is copy
let i = V { f: 0x1701d };
let j = &V { ..i };
// Should not lint as `k` is copy
let k = V { f: 0x1701d };
let l = &V { f: k.f };
}
fn shorthand() {
struct S1 {
a: i32,
b: i32,
}
let a = 42;
let s = S1 { a: 3, b: 4 };
// Should not lint: `a` is not from `s`
let s = S1 { a, b: s.b };
}

View file

@ -26,6 +26,11 @@ struct V {
f: u32,
}
struct W {
f1: u32,
f2: u32,
}
impl Clone for V {
fn clone(&self) -> Self {
// Lint: `Self` implements `Copy`
@ -72,4 +77,69 @@ fn main() {
let p = &mut T {
..*Box::new(T { f: 5 })
};
// Should lint: all fields of `q` would be consumed anyway
let q = W { f1: 42, f2: 1337 };
let r = W { f1: q.f1, f2: q.f2 };
// Should not lint: not all fields of `t` from same source
let s = W { f1: 1337, f2: 42 };
let t = W { f1: s.f1, f2: r.f2 };
// Should not lint: different fields of `s` assigned
let u = W { f1: s.f2, f2: s.f1 };
// Should lint: all fields of `v` would be consumed anyway
let v = W { f1: 42, f2: 1337 };
let w = W { f1: v.f1, ..v };
// Should not lint: source differs between fields and base
let x = W { f1: 42, f2: 1337 };
let y = W { f1: w.f1, ..x };
// Should lint: range desugars to struct
let r1 = 0..5;
let r2 = r1.start..r1.end;
references();
shorthand();
}
fn references() {
// Should not lint as `a` is not mutable
let a = W { f1: 42, f2: 1337 };
let b = &mut W { f1: a.f1, f2: a.f2 };
// Should lint as `d` is a shared reference
let c = W { f1: 42, f2: 1337 };
let d = &W { f1: c.f1, f2: c.f2 };
// Should not lint as `e` is not mutable
let e = W { f1: 42, f2: 1337 };
let f = &mut W { f1: e.f1, ..e };
// Should lint as `h` is a shared reference
let g = W { f1: 42, f2: 1337 };
let h = &W { f1: g.f1, ..g };
// Should not lint as `j` is copy
let i = V { f: 0x1701d };
let j = &V { ..i };
// Should not lint as `k` is copy
let k = V { f: 0x1701d };
let l = &V { f: k.f };
}
fn shorthand() {
struct S1 {
a: i32,
b: i32,
}
let a = 42;
let s = S1 { a: 3, b: 4 };
// Should not lint: `a` is not from `s`
let s = S1 { a, b: s.b };
}

View file

@ -1,5 +1,5 @@
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:32:9
--> tests/ui/unnecessary_struct_initialization.rs:37:9
|
LL | Self { ..*self }
| ^^^^^^^^^^^^^^^^ help: replace with: `*self`
@ -8,25 +8,25 @@ LL | Self { ..*self }
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_struct_initialization)]`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:39:17
--> tests/ui/unnecessary_struct_initialization.rs:44:17
|
LL | let mut b = S { ..a };
| ^^^^^^^^^ help: replace with: `a`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:42:18
--> tests/ui/unnecessary_struct_initialization.rs:47:18
|
LL | let c = &mut S { ..b };
| ^^^^^^^^^ help: replace with: `b`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:50:14
--> tests/ui/unnecessary_struct_initialization.rs:55:14
|
LL | let g = &S { ..f };
| ^^^^^^^^^ help: replace with: `f`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:53:18
--> tests/ui/unnecessary_struct_initialization.rs:58:18
|
LL | let h = &mut S {
| __________________^
@ -35,7 +35,7 @@ LL | | };
| |_____^ help: replace with: `*Box::new(S { f: String::from("foo") })`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:72:18
--> tests/ui/unnecessary_struct_initialization.rs:77:18
|
LL | let p = &mut T {
| __________________^
@ -43,5 +43,35 @@ LL | | ..*Box::new(T { f: 5 })
LL | | };
| |_____^ help: replace with: `*Box::new(T { f: 5 })`
error: aborting due to 6 previous errors
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:83:13
|
LL | let r = W { f1: q.f1, f2: q.f2 };
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `q`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:94:13
|
LL | let w = W { f1: v.f1, ..v };
| ^^^^^^^^^^^^^^^^^^^ help: replace with: `v`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:102:14
|
LL | let r2 = r1.start..r1.end;
| ^^^^^^^^^^^^^^^^ help: replace with: `r1`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:115:14
|
LL | let d = &W { f1: c.f1, f2: c.f2 };
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `c`
error: unnecessary struct building
--> tests/ui/unnecessary_struct_initialization.rs:123:14
|
LL | let h = &W { f1: g.f1, ..g };
| ^^^^^^^^^^^^^^^^^^^ help: replace with: `g`
error: aborting due to 11 previous errors

View file

@ -1,587 +0,0 @@
#![allow(
clippy::needless_borrow,
clippy::needless_borrows_for_generic_args,
clippy::ptr_arg,
clippy::manual_async_fn,
clippy::needless_lifetimes
)]
#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
use std::borrow::Cow;
use std::ffi::{CStr, CString, OsStr, OsString};
use std::ops::Deref;
#[derive(Clone)]
struct X(String);
impl Deref for X {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl AsRef<str> for X {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for X {
fn to_string(&self) -> String {
self.0.to_string()
}
}
impl X {
fn join(&self, other: impl AsRef<str>) -> Self {
let mut s = self.0.clone();
s.push_str(other.as_ref());
Self(s)
}
}
#[allow(dead_code)]
#[derive(Clone)]
enum FileType {
Account,
PrivateKey,
Certificate,
}
fn main() {
let c_str = CStr::from_bytes_with_nul(&[0]).unwrap();
let os_str = OsStr::new("x");
let path = std::path::Path::new("x");
let s = "x";
let array = ["x"];
let array_ref = &["x"];
let slice = &["x"][..];
let x = X(String::from("x"));
let x_ref = &x;
require_c_str(&Cow::from(c_str));
require_c_str(c_str);
require_os_str(os_str);
require_os_str(&Cow::from(os_str));
require_os_str(os_str);
require_path(path);
require_path(&Cow::from(path));
require_path(path);
require_str(s);
require_str(&Cow::from(s));
require_str(s);
require_str(x_ref.as_ref());
require_slice(slice);
require_slice(&Cow::from(slice));
require_slice(array.as_ref());
require_slice(array_ref.as_ref());
require_slice(slice);
require_slice(&x_ref.to_owned()); // No longer flagged because of #8759.
require_x(&Cow::<X>::Owned(x.clone()));
require_x(&x_ref.to_owned()); // No longer flagged because of #8759.
require_deref_c_str(c_str);
require_deref_os_str(os_str);
require_deref_path(path);
require_deref_str(s);
require_deref_slice(slice);
require_impl_deref_c_str(c_str);
require_impl_deref_os_str(os_str);
require_impl_deref_path(path);
require_impl_deref_str(s);
require_impl_deref_slice(slice);
require_deref_str_slice(s, slice);
require_deref_slice_str(slice, s);
require_as_ref_c_str(c_str);
require_as_ref_os_str(os_str);
require_as_ref_path(path);
require_as_ref_str(s);
require_as_ref_str(&x);
require_as_ref_slice(array);
require_as_ref_slice(array_ref);
require_as_ref_slice(slice);
require_impl_as_ref_c_str(c_str);
require_impl_as_ref_os_str(os_str);
require_impl_as_ref_path(path);
require_impl_as_ref_str(s);
require_impl_as_ref_str(&x);
require_impl_as_ref_slice(array);
require_impl_as_ref_slice(array_ref);
require_impl_as_ref_slice(slice);
require_as_ref_str_slice(s, array);
require_as_ref_str_slice(s, array_ref);
require_as_ref_str_slice(s, slice);
require_as_ref_slice_str(array, s);
require_as_ref_slice_str(array_ref, s);
require_as_ref_slice_str(slice, s);
let _ = x.join(x_ref);
let _ = slice.iter().copied();
let _ = slice.iter().copied();
let _ = [std::path::PathBuf::new()][..].iter().cloned();
let _ = [std::path::PathBuf::new()][..].iter().cloned();
let _ = slice.iter().copied();
let _ = slice.iter().copied();
let _ = [std::path::PathBuf::new()][..].iter().cloned();
let _ = [std::path::PathBuf::new()][..].iter().cloned();
let _ = check_files(&[FileType::Account]);
// negative tests
require_string(&s.to_string());
require_string(&Cow::from(s).into_owned());
require_string(&s.to_owned());
require_string(&x_ref.to_string());
// `X` isn't copy.
require_slice(&x.to_owned());
require_deref_slice(x.to_owned());
// The following should be flagged by `redundant_clone`, but not by this lint.
require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap());
require_os_str(&OsString::from("x"));
require_path(&std::path::PathBuf::from("x"));
require_str(&String::from("x"));
require_slice(&[String::from("x")]);
let slice = [0u8; 1024];
let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8");
let _ref_str: &str = core::str::from_utf8(b"foo").unwrap();
let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap();
// Expression is of type `&String`, can't suggest `str::from_utf8` here
let _ref_string = &String::from_utf8(b"foo".to_vec()).unwrap();
macro_rules! arg_from_macro {
() => {
b"foo".to_vec()
};
}
macro_rules! string_from_utf8_from_macro {
() => {
&String::from_utf8(b"foo".to_vec()).unwrap()
};
}
let _ref_str: &str = &String::from_utf8(arg_from_macro!()).unwrap();
let _ref_str: &str = string_from_utf8_from_macro!();
}
fn require_c_str(_: &CStr) {}
fn require_os_str(_: &OsStr) {}
fn require_path(_: &std::path::Path) {}
fn require_str(_: &str) {}
fn require_slice<T>(_: &[T]) {}
fn require_x(_: &X) {}
fn require_deref_c_str<T: Deref<Target = CStr>>(_: T) {}
fn require_deref_os_str<T: Deref<Target = OsStr>>(_: T) {}
fn require_deref_path<T: Deref<Target = std::path::Path>>(_: T) {}
fn require_deref_str<T: Deref<Target = str>>(_: T) {}
fn require_deref_slice<T, U: Deref<Target = [T]>>(_: U) {}
fn require_impl_deref_c_str(_: impl Deref<Target = CStr>) {}
fn require_impl_deref_os_str(_: impl Deref<Target = OsStr>) {}
fn require_impl_deref_path(_: impl Deref<Target = std::path::Path>) {}
fn require_impl_deref_str(_: impl Deref<Target = str>) {}
fn require_impl_deref_slice<T>(_: impl Deref<Target = [T]>) {}
fn require_deref_str_slice<T: Deref<Target = str>, U, V: Deref<Target = [U]>>(_: T, _: V) {}
fn require_deref_slice_str<T, U: Deref<Target = [T]>, V: Deref<Target = str>>(_: U, _: V) {}
fn require_as_ref_c_str<T: AsRef<CStr>>(_: T) {}
fn require_as_ref_os_str<T: AsRef<OsStr>>(_: T) {}
fn require_as_ref_path<T: AsRef<std::path::Path>>(_: T) {}
fn require_as_ref_str<T: AsRef<str>>(_: T) {}
fn require_as_ref_slice<T, U: AsRef<[T]>>(_: U) {}
fn require_impl_as_ref_c_str(_: impl AsRef<CStr>) {}
fn require_impl_as_ref_os_str(_: impl AsRef<OsStr>) {}
fn require_impl_as_ref_path(_: impl AsRef<std::path::Path>) {}
fn require_impl_as_ref_str(_: impl AsRef<str>) {}
fn require_impl_as_ref_slice<T>(_: impl AsRef<[T]>) {}
fn require_as_ref_str_slice<T: AsRef<str>, U, V: AsRef<[U]>>(_: T, _: V) {}
fn require_as_ref_slice_str<T, U: AsRef<[T]>, V: AsRef<str>>(_: U, _: V) {}
// `check_files` is based on:
// https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
fn check_files(file_types: &[FileType]) -> bool {
for t in file_types {
let path = match get_file_path(t) {
Ok(p) => p,
Err(_) => {
return false;
},
};
if !path.is_file() {
return false;
}
}
true
}
fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
Ok(std::path::PathBuf::new())
}
fn require_string(_: &String) {}
#[clippy::msrv = "1.35"]
fn _msrv_1_35() {
// `copied` was stabilized in 1.36, so clippy should use `cloned`.
let _ = &["x"][..].iter().cloned();
}
#[clippy::msrv = "1.36"]
fn _msrv_1_36() {
let _ = &["x"][..].iter().copied();
}
// https://github.com/rust-lang/rust-clippy/issues/8507
mod issue_8507 {
#![allow(dead_code)]
struct Opaque<P>(P);
pub trait Abstracted {}
impl<P> Abstracted for Opaque<P> {}
fn build<P>(p: P) -> Opaque<P>
where
P: AsRef<str>,
{
Opaque(p)
}
// Should not lint.
fn test_str(s: &str) -> Box<dyn Abstracted> {
Box::new(build(s.to_string()))
}
// Should not lint.
fn test_x(x: super::X) -> Box<dyn Abstracted> {
Box::new(build(x))
}
#[derive(Clone, Copy)]
struct Y(&'static str);
impl AsRef<str> for Y {
fn as_ref(&self) -> &str {
self.0
}
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for Y {
fn to_string(&self) -> String {
self.0.to_string()
}
}
// Should lint because Y is copy.
fn test_y(y: Y) -> Box<dyn Abstracted> {
Box::new(build(y))
}
}
// https://github.com/rust-lang/rust-clippy/issues/8759
mod issue_8759 {
#![allow(dead_code)]
#[derive(Default)]
struct View {}
impl std::borrow::ToOwned for View {
type Owned = View;
fn to_owned(&self) -> Self::Owned {
View {}
}
}
#[derive(Default)]
struct RenderWindow {
default_view: View,
}
impl RenderWindow {
fn default_view(&self) -> &View {
&self.default_view
}
fn set_view(&mut self, _view: &View) {}
}
fn main() {
let mut rw = RenderWindow::default();
rw.set_view(&rw.default_view().to_owned());
}
}
mod issue_8759_variant {
#![allow(dead_code)]
#[derive(Clone, Default)]
struct View {}
#[derive(Default)]
struct RenderWindow {
default_view: View,
}
impl RenderWindow {
fn default_view(&self) -> &View {
&self.default_view
}
fn set_view(&mut self, _view: &View) {}
}
fn main() {
let mut rw = RenderWindow::default();
rw.set_view(&rw.default_view().to_owned());
}
}
mod issue_9317 {
#![allow(dead_code)]
struct Bytes {}
#[allow(clippy::to_string_trait_impl)]
impl ToString for Bytes {
fn to_string(&self) -> String {
"123".to_string()
}
}
impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
&[1, 2, 3]
}
}
fn consume<C: AsRef<[u8]>>(c: C) {
let _ = c;
}
pub fn main() {
let b = Bytes {};
// Should not lint.
consume(b.to_string());
}
}
mod issue_9351 {
#![allow(dead_code)]
use std::ops::Deref;
use std::path::{Path, PathBuf};
fn require_deref_path<T: Deref<Target = std::path::Path>>(x: T) -> T {
x
}
fn generic_arg_used_elsewhere<T: AsRef<Path>>(_x: T, _y: T) {}
fn id<T: AsRef<str>>(x: T) -> T {
x
}
fn predicates_are_satisfied(_x: impl std::fmt::Write) {}
// Should lint
fn single_return() -> impl AsRef<str> {
id("abc")
}
// Should not lint
fn multiple_returns(b: bool) -> impl AsRef<str> {
if b {
return String::new();
}
id("abc".to_string())
}
struct S1(String);
// Should not lint
fn fields1() -> S1 {
S1(id("abc".to_string()))
}
struct S2 {
s: String,
}
// Should not lint
fn fields2() {
let mut s = S2 { s: "abc".into() };
s.s = id("abc".to_string());
}
pub fn main() {
let path = std::path::Path::new("x");
let path_buf = path.to_owned();
// Should not lint.
let _x: PathBuf = require_deref_path(path.to_owned());
generic_arg_used_elsewhere(path.to_owned(), path_buf);
predicates_are_satisfied(id("abc".to_string()));
}
}
mod issue_9504 {
#![allow(dead_code)]
async fn foo<S: AsRef<str>>(_: S) {}
async fn bar() {
foo(std::path::PathBuf::new().to_string_lossy().to_string()).await;
}
}
mod issue_9771a {
#![allow(dead_code)]
use std::marker::PhantomData;
pub struct Key<K: AsRef<[u8]>, V: ?Sized>(K, PhantomData<V>);
impl<K: AsRef<[u8]>, V: ?Sized> Key<K, V> {
pub fn new(key: K) -> Key<K, V> {
Key(key, PhantomData)
}
}
pub fn pkh(pkh: &[u8]) -> Key<Vec<u8>, String> {
Key::new([b"pkh-", pkh].concat().to_vec())
}
}
mod issue_9771b {
#![allow(dead_code)]
pub struct Key<K: AsRef<[u8]>>(K);
pub fn from(c: &[u8]) -> Key<Vec<u8>> {
let v = [c].concat();
Key(v.to_vec())
}
}
// This is a watered down version of the code in: https://github.com/oxigraph/rio
// The ICE is triggered by the call to `to_owned` on this line:
// https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
mod issue_10021 {
#![allow(unused)]
pub struct Iri<T>(T);
impl<T: AsRef<str>> Iri<T> {
pub fn parse(iri: T) -> Result<Self, ()> {
unimplemented!()
}
}
pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
let base_iri = Iri::parse(url.to_owned())?;
Ok(())
}
}
mod issue_10033 {
#![allow(dead_code)]
use std::fmt::Display;
use std::ops::Deref;
fn _main() {
let f = Foo;
// Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does
// deref to `str`)
foo(&f.to_string());
}
fn foo(s: &str) {
println!("{}", s);
}
struct Foo;
impl Deref for Foo {
type Target = str;
fn deref(&self) -> &Self::Target {
"str"
}
}
impl Display for Foo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Foo")
}
}
}
mod issue_11952 {
use core::future::{Future, IntoFuture};
fn foo<'a, T: AsRef<[u8]>>(x: T, y: &'a i32) -> impl 'a + Future<Output = Result<(), ()>> {
async move {
let _y = y;
Ok(())
}
}
fn bar() {
IntoFuture::into_future(foo([], &0));
}
}
fn borrow_checks() {
use std::borrow::Borrow;
use std::collections::HashSet;
fn inner(a: &[&str]) {
let mut s = HashSet::from([vec!["a"]]);
s.remove(a); //~ ERROR: unnecessary use of `to_vec`
}
let mut s = HashSet::from(["a".to_string()]);
s.remove("b"); //~ ERROR: unnecessary use of `to_owned`
s.remove("b"); //~ ERROR: unnecessary use of `to_string`
// Should not warn.
s.remove("b");
let mut s = HashSet::from([vec!["a"]]);
s.remove(["b"].as_slice()); //~ ERROR: unnecessary use of `to_vec`
s.remove((&["b"]).as_slice()); //~ ERROR: unnecessary use of `to_vec`
// Should not warn.
s.remove(&["b"].to_vec().clone());
s.remove(["a"].as_slice());
trait SetExt {
fn foo<Q: Borrow<str>>(&self, _: &String);
}
impl<K> SetExt for HashSet<K> {
fn foo<Q: Borrow<str>>(&self, _: &String) {}
}
// Should not lint!
HashSet::<i32>::new().foo::<&str>(&"".to_owned());
HashSet::<String>::new().get(&1.to_string());
}

View file

@ -7,6 +7,8 @@
)]
#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
//@no-rustfix: need to change the suggestion to a multipart suggestion
use std::borrow::Cow;
use std::ffi::{CStr, CString, OsStr, OsString};
use std::ops::Deref;

View file

@ -1,11 +1,11 @@
error: redundant clone
--> tests/ui/unnecessary_to_owned.rs:155:64
--> tests/ui/unnecessary_to_owned.rs:157:64
|
LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
| ^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/unnecessary_to_owned.rs:155:20
--> tests/ui/unnecessary_to_owned.rs:157:20
|
LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -13,55 +13,55 @@ LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned())
= help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]`
error: redundant clone
--> tests/ui/unnecessary_to_owned.rs:156:40
--> tests/ui/unnecessary_to_owned.rs:158:40
|
LL | require_os_str(&OsString::from("x").to_os_string());
| ^^^^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/unnecessary_to_owned.rs:156:21
--> tests/ui/unnecessary_to_owned.rs:158:21
|
LL | require_os_str(&OsString::from("x").to_os_string());
| ^^^^^^^^^^^^^^^^^^^
error: redundant clone
--> tests/ui/unnecessary_to_owned.rs:157:48
--> tests/ui/unnecessary_to_owned.rs:159:48
|
LL | require_path(&std::path::PathBuf::from("x").to_path_buf());
| ^^^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/unnecessary_to_owned.rs:157:19
--> tests/ui/unnecessary_to_owned.rs:159:19
|
LL | require_path(&std::path::PathBuf::from("x").to_path_buf());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: redundant clone
--> tests/ui/unnecessary_to_owned.rs:158:35
--> tests/ui/unnecessary_to_owned.rs:160:35
|
LL | require_str(&String::from("x").to_string());
| ^^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/unnecessary_to_owned.rs:158:18
--> tests/ui/unnecessary_to_owned.rs:160:18
|
LL | require_str(&String::from("x").to_string());
| ^^^^^^^^^^^^^^^^^
error: redundant clone
--> tests/ui/unnecessary_to_owned.rs:159:39
--> tests/ui/unnecessary_to_owned.rs:161:39
|
LL | require_slice(&[String::from("x")].to_owned());
| ^^^^^^^^^^^ help: remove this
|
note: this value is dropped without further use
--> tests/ui/unnecessary_to_owned.rs:159:20
--> tests/ui/unnecessary_to_owned.rs:161:20
|
LL | require_slice(&[String::from("x")].to_owned());
| ^^^^^^^^^^^^^^^^^^^
error: unnecessary use of `into_owned`
--> tests/ui/unnecessary_to_owned.rs:64:36
--> tests/ui/unnecessary_to_owned.rs:66:36
|
LL | require_c_str(&Cow::from(c_str).into_owned());
| ^^^^^^^^^^^^^ help: remove this
@ -70,415 +70,415 @@ LL | require_c_str(&Cow::from(c_str).into_owned());
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:65:19
--> tests/ui/unnecessary_to_owned.rs:67:19
|
LL | require_c_str(&c_str.to_owned());
| ^^^^^^^^^^^^^^^^^ help: use: `c_str`
error: unnecessary use of `to_os_string`
--> tests/ui/unnecessary_to_owned.rs:67:20
--> tests/ui/unnecessary_to_owned.rs:69:20
|
LL | require_os_str(&os_str.to_os_string());
| ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str`
error: unnecessary use of `into_owned`
--> tests/ui/unnecessary_to_owned.rs:68:38
--> tests/ui/unnecessary_to_owned.rs:70:38
|
LL | require_os_str(&Cow::from(os_str).into_owned());
| ^^^^^^^^^^^^^ help: remove this
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:69:20
--> tests/ui/unnecessary_to_owned.rs:71:20
|
LL | require_os_str(&os_str.to_owned());
| ^^^^^^^^^^^^^^^^^^ help: use: `os_str`
error: unnecessary use of `to_path_buf`
--> tests/ui/unnecessary_to_owned.rs:71:18
--> tests/ui/unnecessary_to_owned.rs:73:18
|
LL | require_path(&path.to_path_buf());
| ^^^^^^^^^^^^^^^^^^^ help: use: `path`
error: unnecessary use of `into_owned`
--> tests/ui/unnecessary_to_owned.rs:72:34
--> tests/ui/unnecessary_to_owned.rs:74:34
|
LL | require_path(&Cow::from(path).into_owned());
| ^^^^^^^^^^^^^ help: remove this
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:73:18
--> tests/ui/unnecessary_to_owned.rs:75:18
|
LL | require_path(&path.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `path`
error: unnecessary use of `to_string`
--> tests/ui/unnecessary_to_owned.rs:75:17
--> tests/ui/unnecessary_to_owned.rs:77:17
|
LL | require_str(&s.to_string());
| ^^^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `into_owned`
--> tests/ui/unnecessary_to_owned.rs:76:30
--> tests/ui/unnecessary_to_owned.rs:78:30
|
LL | require_str(&Cow::from(s).into_owned());
| ^^^^^^^^^^^^^ help: remove this
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:77:17
--> tests/ui/unnecessary_to_owned.rs:79:17
|
LL | require_str(&s.to_owned());
| ^^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_string`
--> tests/ui/unnecessary_to_owned.rs:78:17
--> tests/ui/unnecessary_to_owned.rs:80:17
|
LL | require_str(&x_ref.to_string());
| ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:80:19
--> tests/ui/unnecessary_to_owned.rs:82:19
|
LL | require_slice(&slice.to_vec());
| ^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `into_owned`
--> tests/ui/unnecessary_to_owned.rs:81:36
--> tests/ui/unnecessary_to_owned.rs:83:36
|
LL | require_slice(&Cow::from(slice).into_owned());
| ^^^^^^^^^^^^^ help: remove this
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:82:19
--> tests/ui/unnecessary_to_owned.rs:84:19
|
LL | require_slice(&array.to_owned());
| ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:83:19
--> tests/ui/unnecessary_to_owned.rs:85:19
|
LL | require_slice(&array_ref.to_owned());
| ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:84:19
--> tests/ui/unnecessary_to_owned.rs:86:19
|
LL | require_slice(&slice.to_owned());
| ^^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `into_owned`
--> tests/ui/unnecessary_to_owned.rs:87:42
--> tests/ui/unnecessary_to_owned.rs:89:42
|
LL | require_x(&Cow::<X>::Owned(x.clone()).into_owned());
| ^^^^^^^^^^^^^ help: remove this
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:90:25
--> tests/ui/unnecessary_to_owned.rs:92:25
|
LL | require_deref_c_str(c_str.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `c_str`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:91:26
--> tests/ui/unnecessary_to_owned.rs:93:26
|
LL | require_deref_os_str(os_str.to_owned());
| ^^^^^^^^^^^^^^^^^ help: use: `os_str`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:92:24
--> tests/ui/unnecessary_to_owned.rs:94:24
|
LL | require_deref_path(path.to_owned());
| ^^^^^^^^^^^^^^^ help: use: `path`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:93:23
--> tests/ui/unnecessary_to_owned.rs:95:23
|
LL | require_deref_str(s.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:94:25
--> tests/ui/unnecessary_to_owned.rs:96:25
|
LL | require_deref_slice(slice.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:96:30
--> tests/ui/unnecessary_to_owned.rs:98:30
|
LL | require_impl_deref_c_str(c_str.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `c_str`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:97:31
--> tests/ui/unnecessary_to_owned.rs:99:31
|
LL | require_impl_deref_os_str(os_str.to_owned());
| ^^^^^^^^^^^^^^^^^ help: use: `os_str`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:98:29
--> tests/ui/unnecessary_to_owned.rs:100:29
|
LL | require_impl_deref_path(path.to_owned());
| ^^^^^^^^^^^^^^^ help: use: `path`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:99:28
--> tests/ui/unnecessary_to_owned.rs:101:28
|
LL | require_impl_deref_str(s.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:100:30
--> tests/ui/unnecessary_to_owned.rs:102:30
|
LL | require_impl_deref_slice(slice.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:102:29
--> tests/ui/unnecessary_to_owned.rs:104:29
|
LL | require_deref_str_slice(s.to_owned(), slice.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:102:43
--> tests/ui/unnecessary_to_owned.rs:104:43
|
LL | require_deref_str_slice(s.to_owned(), slice.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:103:29
--> tests/ui/unnecessary_to_owned.rs:105:29
|
LL | require_deref_slice_str(slice.to_owned(), s.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:103:47
--> tests/ui/unnecessary_to_owned.rs:105:47
|
LL | require_deref_slice_str(slice.to_owned(), s.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:105:26
--> tests/ui/unnecessary_to_owned.rs:107:26
|
LL | require_as_ref_c_str(c_str.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `c_str`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:106:27
--> tests/ui/unnecessary_to_owned.rs:108:27
|
LL | require_as_ref_os_str(os_str.to_owned());
| ^^^^^^^^^^^^^^^^^ help: use: `os_str`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:107:25
--> tests/ui/unnecessary_to_owned.rs:109:25
|
LL | require_as_ref_path(path.to_owned());
| ^^^^^^^^^^^^^^^ help: use: `path`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:108:24
--> tests/ui/unnecessary_to_owned.rs:110:24
|
LL | require_as_ref_str(s.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:109:24
--> tests/ui/unnecessary_to_owned.rs:111:24
|
LL | require_as_ref_str(x.to_owned());
| ^^^^^^^^^^^^ help: use: `&x`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:110:26
--> tests/ui/unnecessary_to_owned.rs:112:26
|
LL | require_as_ref_slice(array.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `array`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:111:26
--> tests/ui/unnecessary_to_owned.rs:113:26
|
LL | require_as_ref_slice(array_ref.to_owned());
| ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:112:26
--> tests/ui/unnecessary_to_owned.rs:114:26
|
LL | require_as_ref_slice(slice.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:114:31
--> tests/ui/unnecessary_to_owned.rs:116:31
|
LL | require_impl_as_ref_c_str(c_str.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `c_str`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:115:32
--> tests/ui/unnecessary_to_owned.rs:117:32
|
LL | require_impl_as_ref_os_str(os_str.to_owned());
| ^^^^^^^^^^^^^^^^^ help: use: `os_str`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:116:30
--> tests/ui/unnecessary_to_owned.rs:118:30
|
LL | require_impl_as_ref_path(path.to_owned());
| ^^^^^^^^^^^^^^^ help: use: `path`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:117:29
--> tests/ui/unnecessary_to_owned.rs:119:29
|
LL | require_impl_as_ref_str(s.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:118:29
--> tests/ui/unnecessary_to_owned.rs:120:29
|
LL | require_impl_as_ref_str(x.to_owned());
| ^^^^^^^^^^^^ help: use: `&x`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:119:31
--> tests/ui/unnecessary_to_owned.rs:121:31
|
LL | require_impl_as_ref_slice(array.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `array`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:120:31
--> tests/ui/unnecessary_to_owned.rs:122:31
|
LL | require_impl_as_ref_slice(array_ref.to_owned());
| ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:121:31
--> tests/ui/unnecessary_to_owned.rs:123:31
|
LL | require_impl_as_ref_slice(slice.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:123:30
|
LL | require_as_ref_str_slice(s.to_owned(), array.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:123:44
|
LL | require_as_ref_str_slice(s.to_owned(), array.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `array`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:124:30
|
LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:124:44
|
LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
| ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:125:30
|
LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned());
LL | require_as_ref_str_slice(s.to_owned(), array.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:125:44
|
LL | require_as_ref_str_slice(s.to_owned(), array.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `array`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:126:30
|
LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:126:44
|
LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
| ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:127:30
|
LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:127:44
|
LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:126:30
--> tests/ui/unnecessary_to_owned.rs:128:30
|
LL | require_as_ref_slice_str(array.to_owned(), s.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `array`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:126:48
--> tests/ui/unnecessary_to_owned.rs:128:48
|
LL | require_as_ref_slice_str(array.to_owned(), s.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:127:30
--> tests/ui/unnecessary_to_owned.rs:129:30
|
LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
| ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:127:52
--> tests/ui/unnecessary_to_owned.rs:129:52
|
LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:128:30
--> tests/ui/unnecessary_to_owned.rs:130:30
|
LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned());
| ^^^^^^^^^^^^^^^^ help: use: `slice`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:128:48
--> tests/ui/unnecessary_to_owned.rs:130:48
|
LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned());
| ^^^^^^^^^^^^ help: use: `s`
error: unnecessary use of `to_string`
--> tests/ui/unnecessary_to_owned.rs:130:20
--> tests/ui/unnecessary_to_owned.rs:132:20
|
LL | let _ = x.join(&x_ref.to_string());
| ^^^^^^^^^^^^^^^^^^ help: use: `x_ref`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:132:13
--> tests/ui/unnecessary_to_owned.rs:134:13
|
LL | let _ = slice.to_vec().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:133:13
--> tests/ui/unnecessary_to_owned.rs:135:13
|
LL | let _ = slice.to_owned().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:134:13
--> tests/ui/unnecessary_to_owned.rs:136:13
|
LL | let _ = [std::path::PathBuf::new()][..].to_vec().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:135:13
--> tests/ui/unnecessary_to_owned.rs:137:13
|
LL | let _ = [std::path::PathBuf::new()][..].to_owned().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:137:13
--> tests/ui/unnecessary_to_owned.rs:139:13
|
LL | let _ = IntoIterator::into_iter(slice.to_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:138:13
--> tests/ui/unnecessary_to_owned.rs:140:13
|
LL | let _ = IntoIterator::into_iter(slice.to_owned());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:139:13
--> tests/ui/unnecessary_to_owned.rs:141:13
|
LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:140:13
--> tests/ui/unnecessary_to_owned.rs:142:13
|
LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
error: allocating a new `String` only to create a temporary `&str` from it
--> tests/ui/unnecessary_to_owned.rs:162:26
--> tests/ui/unnecessary_to_owned.rs:164:26
|
LL | let _ref_str: &str = &String::from_utf8(slice.to_vec()).expect("not UTF-8");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -490,7 +490,7 @@ LL + let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8");
|
error: allocating a new `String` only to create a temporary `&str` from it
--> tests/ui/unnecessary_to_owned.rs:163:26
--> tests/ui/unnecessary_to_owned.rs:165:26
|
LL | let _ref_str: &str = &String::from_utf8(b"foo".to_vec()).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -502,7 +502,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo").unwrap();
|
error: allocating a new `String` only to create a temporary `&str` from it
--> tests/ui/unnecessary_to_owned.rs:164:26
--> tests/ui/unnecessary_to_owned.rs:166:26
|
LL | let _ref_str: &str = &String::from_utf8(b"foo".as_slice().to_owned()).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -514,7 +514,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap();
|
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:221:14
--> tests/ui/unnecessary_to_owned.rs:223:14
|
LL | for t in file_types.to_vec() {
| ^^^^^^^^^^^^^^^^^^^
@ -530,61 +530,61 @@ LL + let path = match get_file_path(t) {
|
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:244:14
--> tests/ui/unnecessary_to_owned.rs:246:14
|
LL | let _ = &["x"][..].to_vec().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().cloned()`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:249:14
--> tests/ui/unnecessary_to_owned.rs:251:14
|
LL | let _ = &["x"][..].to_vec().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()`
error: unnecessary use of `to_string`
--> tests/ui/unnecessary_to_owned.rs:297:24
--> tests/ui/unnecessary_to_owned.rs:299:24
|
LL | Box::new(build(y.to_string()))
| ^^^^^^^^^^^^^ help: use: `y`
error: unnecessary use of `to_string`
--> tests/ui/unnecessary_to_owned.rs:406:12
--> tests/ui/unnecessary_to_owned.rs:408:12
|
LL | id("abc".to_string())
| ^^^^^^^^^^^^^^^^^ help: use: `"abc"`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:549:37
--> tests/ui/unnecessary_to_owned.rs:551:37
|
LL | IntoFuture::into_future(foo([].to_vec(), &0));
| ^^^^^^^^^^^ help: use: `[]`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:559:18
--> tests/ui/unnecessary_to_owned.rs:561:18
|
LL | s.remove(&a.to_vec());
| ^^^^^^^^^^^ help: replace it with: `a`
error: unnecessary use of `to_owned`
--> tests/ui/unnecessary_to_owned.rs:563:14
--> tests/ui/unnecessary_to_owned.rs:565:14
|
LL | s.remove(&"b".to_owned());
| ^^^^^^^^^^^^^^^ help: replace it with: `"b"`
error: unnecessary use of `to_string`
--> tests/ui/unnecessary_to_owned.rs:564:14
--> tests/ui/unnecessary_to_owned.rs:566:14
|
LL | s.remove(&"b".to_string());
| ^^^^^^^^^^^^^^^^ help: replace it with: `"b"`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:569:14
--> tests/ui/unnecessary_to_owned.rs:571:14
|
LL | s.remove(&["b"].to_vec());
| ^^^^^^^^^^^^^^^ help: replace it with: `["b"].as_slice()`
error: unnecessary use of `to_vec`
--> tests/ui/unnecessary_to_owned.rs:570:14
--> tests/ui/unnecessary_to_owned.rs:572:14
|
LL | s.remove(&(&["b"]).to_vec());
| ^^^^^^^^^^^^^^^^^^ help: replace it with: `(&["b"]).as_slice()`

Some files were not shown because too many files have changed in this diff Show more