Do not trigger inefficient_to_string after Rust 1.82
Starting with Rust version 1.82.0, the compiler generates similar code with
and without the `with_ref` cfg:
```rust
fn f(x: impl IntoIterator<Item = String>) {
for y in x { println!("{y}"); }
}
fn main() {
#[cfg(with_ref)]
let a = ["foo", "bar"].iter().map(|&s| s.to_string());
#[cfg(not(with_ref))]
let a = ["foo", "bar"].iter().map(|s| s.to_string());
f(a);
}
```
The generated code is strictly identical with `-O`, and identical modulo
some minor reordering without.
This commit is contained in:
parent
d99cf5c083
commit
951d35eeb6
8 changed files with 36 additions and 11 deletions
|
|
@ -845,6 +845,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
|
|||
* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into)
|
||||
* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
|
||||
* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
|
||||
* [`inefficient_to_string`](https://rust-lang.github.io/rust-clippy/master/index.html#inefficient_to_string)
|
||||
* [`io_other_error`](https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error)
|
||||
* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map)
|
||||
* [`legacy_numeric_constants`](https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants)
|
||||
|
|
|
|||
|
|
@ -741,6 +741,7 @@ define_Conf! {
|
|||
from_over_into,
|
||||
if_then_some_else_none,
|
||||
index_refutable_slice,
|
||||
inefficient_to_string,
|
||||
io_other_error,
|
||||
iter_kv_map,
|
||||
legacy_numeric_constants,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::{is_type_lang_item, peel_and_count_ty_refs};
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -16,6 +17,7 @@ pub fn check(
|
|||
method_name: Symbol,
|
||||
receiver: &hir::Expr<'_>,
|
||||
args: &[hir::Expr<'_>],
|
||||
msrv: Msrv,
|
||||
) {
|
||||
if args.is_empty()
|
||||
&& method_name == sym::to_string
|
||||
|
|
@ -26,6 +28,8 @@ pub fn check(
|
|||
&& let self_ty = args.type_at(0)
|
||||
&& let (deref_self_ty, deref_count, _) = peel_and_count_ty_refs(self_ty)
|
||||
&& deref_count >= 1
|
||||
// Since Rust 1.82, the specialized `ToString` is properly called
|
||||
&& !msrv.meets(cx, msrvs::SPECIALIZED_TO_STRING_FOR_REFS)
|
||||
&& specializes_tostring(cx, deref_self_ty)
|
||||
{
|
||||
span_lint_and_then(
|
||||
|
|
|
|||
|
|
@ -477,6 +477,9 @@ declare_clippy_lint! {
|
|||
/// ### What it does
|
||||
/// Checks for usage of `ok().expect(..)`.
|
||||
///
|
||||
/// Note: This lint only triggers for code marked compatible
|
||||
/// with versions of the compiler older than Rust 1.82.0.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Because you usually call `expect()` on the `Result`
|
||||
/// directly to get a better error message.
|
||||
|
|
@ -1080,9 +1083,9 @@ declare_clippy_lint! {
|
|||
/// `T` implements `ToString` directly (like `&&str` or `&&String`).
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// This bypasses the specialized implementation of
|
||||
/// `ToString` and instead goes through the more expensive string formatting
|
||||
/// facilities.
|
||||
/// In versions of the compiler before Rust 1.82.0, this bypasses the specialized
|
||||
/// implementation of`ToString` and instead goes through the more expensive string
|
||||
/// formatting facilities.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```no_run
|
||||
|
|
@ -4868,7 +4871,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
|||
);
|
||||
clone_on_copy::check(cx, expr, method_call.ident.name, receiver, args);
|
||||
clone_on_ref_ptr::check(cx, expr, method_call.ident.name, receiver, args);
|
||||
inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args);
|
||||
inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args, self.msrv);
|
||||
single_char_add_str::check(cx, expr, receiver, args);
|
||||
into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, receiver);
|
||||
unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, self.msrv);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ msrv_aliases! {
|
|||
1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL }
|
||||
1,84,0 { CONST_OPTION_AS_SLICE, MANUAL_DANGLING_PTR }
|
||||
1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP }
|
||||
1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP }
|
||||
1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP, SPECIALIZED_TO_STRING_FOR_REFS }
|
||||
1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION, DURATION_ABS_DIFF }
|
||||
1,80,0 { BOX_INTO_ITER, LAZY_CELL }
|
||||
1,77,0 { C_STR_LITERALS }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[clippy::msrv = "1.81"]
|
||||
fn main() {
|
||||
let rstr: &str = "hello";
|
||||
let rrstr: &&str = &rstr;
|
||||
|
|
@ -34,3 +35,10 @@ fn main() {
|
|||
let _: String = (**rrrcow).to_string();
|
||||
//~^ inefficient_to_string
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.82"]
|
||||
fn sufficient_msrv() {
|
||||
let rstr: &str = "hello";
|
||||
let rrstr: &&str = &rstr;
|
||||
let _: String = rrstr.to_string();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[clippy::msrv = "1.81"]
|
||||
fn main() {
|
||||
let rstr: &str = "hello";
|
||||
let rrstr: &&str = &rstr;
|
||||
|
|
@ -34,3 +35,10 @@ fn main() {
|
|||
let _: String = rrrcow.to_string();
|
||||
//~^ inefficient_to_string
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.82"]
|
||||
fn sufficient_msrv() {
|
||||
let rstr: &str = "hello";
|
||||
let rrstr: &&str = &rstr;
|
||||
let _: String = rrstr.to_string();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: calling `to_string` on `&&str`
|
||||
--> tests/ui/inefficient_to_string.rs:10:21
|
||||
--> tests/ui/inefficient_to_string.rs:11:21
|
||||
|
|
||||
LL | let _: String = rrstr.to_string();
|
||||
| ^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrstr).to_string()`
|
||||
|
|
@ -12,7 +12,7 @@ LL | #![deny(clippy::inefficient_to_string)]
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: calling `to_string` on `&&&str`
|
||||
--> tests/ui/inefficient_to_string.rs:12:21
|
||||
--> tests/ui/inefficient_to_string.rs:13:21
|
||||
|
|
||||
LL | let _: String = rrrstr.to_string();
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrstr).to_string()`
|
||||
|
|
@ -20,7 +20,7 @@ LL | let _: String = rrrstr.to_string();
|
|||
= help: `&&str` implements `ToString` through a slower blanket impl, but `str` has a fast specialization of `ToString`
|
||||
|
||||
error: calling `to_string` on `&&std::string::String`
|
||||
--> tests/ui/inefficient_to_string.rs:21:21
|
||||
--> tests/ui/inefficient_to_string.rs:22:21
|
||||
|
|
||||
LL | let _: String = rrstring.to_string();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrstring).to_string()`
|
||||
|
|
@ -28,7 +28,7 @@ LL | let _: String = rrstring.to_string();
|
|||
= help: `&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString`
|
||||
|
||||
error: calling `to_string` on `&&&std::string::String`
|
||||
--> tests/ui/inefficient_to_string.rs:23:21
|
||||
--> tests/ui/inefficient_to_string.rs:24:21
|
||||
|
|
||||
LL | let _: String = rrrstring.to_string();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrstring).to_string()`
|
||||
|
|
@ -36,7 +36,7 @@ LL | let _: String = rrrstring.to_string();
|
|||
= help: `&&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString`
|
||||
|
||||
error: calling `to_string` on `&&std::borrow::Cow<'_, str>`
|
||||
--> tests/ui/inefficient_to_string.rs:32:21
|
||||
--> tests/ui/inefficient_to_string.rs:33:21
|
||||
|
|
||||
LL | let _: String = rrcow.to_string();
|
||||
| ^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrcow).to_string()`
|
||||
|
|
@ -44,7 +44,7 @@ LL | let _: String = rrcow.to_string();
|
|||
= help: `&std::borrow::Cow<'_, str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<'_, str>` has a fast specialization of `ToString`
|
||||
|
||||
error: calling `to_string` on `&&&std::borrow::Cow<'_, str>`
|
||||
--> tests/ui/inefficient_to_string.rs:34:21
|
||||
--> tests/ui/inefficient_to_string.rs:35:21
|
||||
|
|
||||
LL | let _: String = rrrcow.to_string();
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrcow).to_string()`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue