Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions book/src/lint_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions clippy_config/src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions clippy_lints/src/methods/inefficient_to_string.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand All @@ -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(
Expand Down
11 changes: 7 additions & 4 deletions clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion clippy_utils/src/msrvs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/inefficient_to_string.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::borrow::Cow;

#[clippy::msrv = "1.81"]
fn main() {
let rstr: &str = "hello";
let rrstr: &&str = &rstr;
Expand Down Expand Up @@ -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();
}
8 changes: 8 additions & 0 deletions tests/ui/inefficient_to_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::borrow::Cow;

#[clippy::msrv = "1.81"]
fn main() {
let rstr: &str = "hello";
let rrstr: &&str = &rstr;
Expand Down Expand Up @@ -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();
}
12 changes: 6 additions & 6 deletions tests/ui/inefficient_to_string.stderr
Original file line number Diff line number Diff line change
@@ -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()`
Expand All @@ -12,39 +12,39 @@ 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()`
|
= 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()`
|
= 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()`
|
= 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()`
|
= 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()`
Expand Down