fix(rc_buffer): don't touch the path to Rc/Arc in the suggestion (#15803)
Fixes https://github.com/rust-lang/rust-clippy/issues/15802 changelog: [`rc_buffer`]: don't touch the path to `Rc`/`Arc` in the suggestion
This commit is contained in:
commit
663ef9b31b
7 changed files with 244 additions and 151 deletions
|
|
@ -1,115 +1,74 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::qpath_generic_tys;
|
||||
use clippy_utils::res::{MaybeDef, MaybeResPath};
|
||||
use clippy_utils::res::MaybeResPath;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, QPath, TyKind};
|
||||
use rustc_hir::{QPath, Ty, TyKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::symbol::sym;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
use super::RC_BUFFER;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
|
||||
let app = Applicability::Unspecified;
|
||||
let name = cx.tcx.get_diagnostic_name(def_id);
|
||||
if name == Some(sym::Rc) {
|
||||
if let Some(alternate) = match_buffer_type(cx, qpath) {
|
||||
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
RC_BUFFER,
|
||||
hir_ty.span,
|
||||
"usage of `Rc<T>` when T is a buffer type",
|
||||
|diag| {
|
||||
diag.span_suggestion(hir_ty.span, "try", format!("Rc<{alternate}>"), app);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
let Some(ty) = qpath_generic_tys(qpath).next() else {
|
||||
return false;
|
||||
};
|
||||
if !ty.basic_res().is_diag_item(cx, sym::Vec) {
|
||||
return false;
|
||||
}
|
||||
let TyKind::Path(qpath) = &ty.kind else { return false };
|
||||
let inner_span = match qpath_generic_tys(qpath).next() {
|
||||
Some(ty) => ty.span,
|
||||
None => return false,
|
||||
};
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
RC_BUFFER,
|
||||
hir_ty.span,
|
||||
"usage of `Rc<T>` when T is a buffer type",
|
||||
|diag| {
|
||||
let mut applicability = app;
|
||||
diag.span_suggestion(
|
||||
hir_ty.span,
|
||||
"try",
|
||||
format!(
|
||||
"Rc<[{}]>",
|
||||
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
|
||||
),
|
||||
app,
|
||||
);
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}
|
||||
} else if name == Some(sym::Arc) {
|
||||
if let Some(alternate) = match_buffer_type(cx, qpath) {
|
||||
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
RC_BUFFER,
|
||||
hir_ty.span,
|
||||
"usage of `Arc<T>` when T is a buffer type",
|
||||
|diag| {
|
||||
diag.span_suggestion(hir_ty.span, "try", format!("Arc<{alternate}>"), app);
|
||||
},
|
||||
);
|
||||
} else if let Some(ty) = qpath_generic_tys(qpath).next() {
|
||||
if !ty.basic_res().is_diag_item(cx, sym::Vec) {
|
||||
return false;
|
||||
}
|
||||
let TyKind::Path(qpath) = &ty.kind else { return false };
|
||||
let inner_span = match qpath_generic_tys(qpath).next() {
|
||||
Some(ty) => ty.span,
|
||||
None => return false,
|
||||
};
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
RC_BUFFER,
|
||||
hir_ty.span,
|
||||
"usage of `Arc<T>` when T is a buffer type",
|
||||
|diag| {
|
||||
let mut applicability = app;
|
||||
diag.span_suggestion(
|
||||
hir_ty.span,
|
||||
"try",
|
||||
format!(
|
||||
"Arc<[{}]>",
|
||||
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
|
||||
),
|
||||
app,
|
||||
);
|
||||
},
|
||||
);
|
||||
return true;
|
||||
}
|
||||
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
|
||||
let mut app = Applicability::Unspecified;
|
||||
let kind = match cx.tcx.get_diagnostic_name(def_id) {
|
||||
Some(sym::Rc) => RcKind::Rc,
|
||||
Some(sym::Arc) => RcKind::Arc,
|
||||
_ => return false,
|
||||
};
|
||||
if let Some(ty) = qpath_generic_tys(qpath).next()
|
||||
&& let Some(alternate) = match_buffer_type(cx, ty, &mut app)
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
RC_BUFFER,
|
||||
hir_ty.span,
|
||||
format!("usage of `{kind}<T>` when `T` is a buffer type"),
|
||||
|diag| {
|
||||
diag.span_suggestion_verbose(ty.span, "try", alternate, app);
|
||||
},
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
|
||||
let ty = qpath_generic_tys(qpath).next()?;
|
||||
enum RcKind {
|
||||
Rc,
|
||||
Arc,
|
||||
}
|
||||
|
||||
impl fmt::Display for RcKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Rc => f.write_str("Rc"),
|
||||
Self::Arc => f.write_str("Arc"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn match_buffer_type(
|
||||
cx: &LateContext<'_>,
|
||||
ty: &Ty<'_>,
|
||||
applicability: &mut Applicability,
|
||||
) -> Option<Cow<'static, str>> {
|
||||
let id = ty.basic_res().opt_def_id()?;
|
||||
let path = match cx.tcx.get_diagnostic_name(id) {
|
||||
Some(sym::OsString) => "std::ffi::OsStr",
|
||||
Some(sym::PathBuf) => "std::path::Path",
|
||||
_ if Some(id) == cx.tcx.lang_items().string() => "str",
|
||||
Some(sym::OsString) => "std::ffi::OsStr".into(),
|
||||
Some(sym::PathBuf) => "std::path::Path".into(),
|
||||
Some(sym::Vec) => {
|
||||
let TyKind::Path(vec_qpath) = &ty.kind else {
|
||||
return None;
|
||||
};
|
||||
let vec_generic_ty = qpath_generic_tys(vec_qpath).next()?;
|
||||
let snippet = snippet_with_applicability(cx, vec_generic_ty.span, "_", applicability);
|
||||
format!("[{snippet}]").into()
|
||||
},
|
||||
_ if Some(id) == cx.tcx.lang_items().string() => "str".into(),
|
||||
_ => return None,
|
||||
};
|
||||
Some(path)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::rc_buffer)]
|
||||
#![allow(dead_code, unused_imports)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::OsString;
|
||||
|
|
@ -32,4 +31,9 @@ fn func_bad4(_: Rc<std::ffi::OsStr>) {}
|
|||
// does not trigger lint
|
||||
fn func_good1(_: Rc<RefCell<String>>) {}
|
||||
|
||||
mod issue_15802 {
|
||||
fn foo(_: std::rc::Rc<[u8]>) {}
|
||||
//~^ rc_buffer
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::rc_buffer)]
|
||||
#![allow(dead_code, unused_imports)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::OsString;
|
||||
|
|
@ -32,4 +31,9 @@ fn func_bad4(_: Rc<OsString>) {}
|
|||
// does not trigger lint
|
||||
fn func_good1(_: Rc<RefCell<String>>) {}
|
||||
|
||||
mod issue_15802 {
|
||||
fn foo(_: std::rc::Rc<Vec<u8>>) {}
|
||||
//~^ rc_buffer
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,112 @@
|
|||
error: usage of `Rc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:11:11
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:10:11
|
||||
|
|
||||
LL | bad1: Rc<String>,
|
||||
| ^^^^^^^^^^ help: try: `Rc<str>`
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::rc-buffer` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::rc_buffer)]`
|
||||
help: try
|
||||
|
|
||||
LL - bad1: Rc<String>,
|
||||
LL + bad1: Rc<str>,
|
||||
|
|
||||
|
||||
error: usage of `Rc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:13:11
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:12:11
|
||||
|
|
||||
LL | bad2: Rc<PathBuf>,
|
||||
| ^^^^^^^^^^^ help: try: `Rc<std::path::Path>`
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - bad2: Rc<PathBuf>,
|
||||
LL + bad2: Rc<std::path::Path>,
|
||||
|
|
||||
|
||||
error: usage of `Rc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:15:11
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:14:11
|
||||
|
|
||||
LL | bad3: Rc<Vec<u8>>,
|
||||
| ^^^^^^^^^^^ help: try: `Rc<[u8]>`
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - bad3: Rc<Vec<u8>>,
|
||||
LL + bad3: Rc<[u8]>,
|
||||
|
|
||||
|
||||
error: usage of `Rc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:17:11
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:16:11
|
||||
|
|
||||
LL | bad4: Rc<OsString>,
|
||||
| ^^^^^^^^^^^^ help: try: `Rc<std::ffi::OsStr>`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - bad4: Rc<OsString>,
|
||||
LL + bad4: Rc<std::ffi::OsStr>,
|
||||
|
|
||||
|
||||
error: usage of `Rc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:24:17
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:23:17
|
||||
|
|
||||
LL | fn func_bad1(_: Rc<String>) {}
|
||||
| ^^^^^^^^^^ help: try: `Rc<str>`
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn func_bad1(_: Rc<String>) {}
|
||||
LL + fn func_bad1(_: Rc<str>) {}
|
||||
|
|
||||
|
||||
error: usage of `Rc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:26:17
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:25:17
|
||||
|
|
||||
LL | fn func_bad2(_: Rc<PathBuf>) {}
|
||||
| ^^^^^^^^^^^ help: try: `Rc<std::path::Path>`
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn func_bad2(_: Rc<PathBuf>) {}
|
||||
LL + fn func_bad2(_: Rc<std::path::Path>) {}
|
||||
|
|
||||
|
||||
error: usage of `Rc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:28:17
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:27:17
|
||||
|
|
||||
LL | fn func_bad3(_: Rc<Vec<u8>>) {}
|
||||
| ^^^^^^^^^^^ help: try: `Rc<[u8]>`
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn func_bad3(_: Rc<Vec<u8>>) {}
|
||||
LL + fn func_bad3(_: Rc<[u8]>) {}
|
||||
|
|
||||
|
||||
error: usage of `Rc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:30:17
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:29:17
|
||||
|
|
||||
LL | fn func_bad4(_: Rc<OsString>) {}
|
||||
| ^^^^^^^^^^^^ help: try: `Rc<std::ffi::OsStr>`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn func_bad4(_: Rc<OsString>) {}
|
||||
LL + fn func_bad4(_: Rc<std::ffi::OsStr>) {}
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: usage of `Rc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer.rs:35:15
|
||||
|
|
||||
LL | fn foo(_: std::rc::Rc<Vec<u8>>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn foo(_: std::rc::Rc<Vec<u8>>) {}
|
||||
LL + fn foo(_: std::rc::Rc<[u8]>) {}
|
||||
|
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::rc_buffer)]
|
||||
#![allow(dead_code, unused_imports)]
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
|
|
@ -31,4 +30,9 @@ fn func_bad4(_: Arc<std::ffi::OsStr>) {}
|
|||
// does not trigger lint
|
||||
fn func_good1(_: Arc<Mutex<String>>) {}
|
||||
|
||||
mod issue_15802 {
|
||||
fn foo(_: std::sync::Arc<[u8]>) {}
|
||||
//~^ rc_buffer
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::rc_buffer)]
|
||||
#![allow(dead_code, unused_imports)]
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
|
|
@ -31,4 +30,9 @@ fn func_bad4(_: Arc<OsString>) {}
|
|||
// does not trigger lint
|
||||
fn func_good1(_: Arc<Mutex<String>>) {}
|
||||
|
||||
mod issue_15802 {
|
||||
fn foo(_: std::sync::Arc<Vec<u8>>) {}
|
||||
//~^ rc_buffer
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,112 @@
|
|||
error: usage of `Arc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:10:11
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:9:11
|
||||
|
|
||||
LL | bad1: Arc<String>,
|
||||
| ^^^^^^^^^^^ help: try: `Arc<str>`
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::rc-buffer` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::rc_buffer)]`
|
||||
help: try
|
||||
|
|
||||
LL - bad1: Arc<String>,
|
||||
LL + bad1: Arc<str>,
|
||||
|
|
||||
|
||||
error: usage of `Arc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:12:11
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:11:11
|
||||
|
|
||||
LL | bad2: Arc<PathBuf>,
|
||||
| ^^^^^^^^^^^^ help: try: `Arc<std::path::Path>`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - bad2: Arc<PathBuf>,
|
||||
LL + bad2: Arc<std::path::Path>,
|
||||
|
|
||||
|
||||
error: usage of `Arc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:14:11
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:13:11
|
||||
|
|
||||
LL | bad3: Arc<Vec<u8>>,
|
||||
| ^^^^^^^^^^^^ help: try: `Arc<[u8]>`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - bad3: Arc<Vec<u8>>,
|
||||
LL + bad3: Arc<[u8]>,
|
||||
|
|
||||
|
||||
error: usage of `Arc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:16:11
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:15:11
|
||||
|
|
||||
LL | bad4: Arc<OsString>,
|
||||
| ^^^^^^^^^^^^^ help: try: `Arc<std::ffi::OsStr>`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - bad4: Arc<OsString>,
|
||||
LL + bad4: Arc<std::ffi::OsStr>,
|
||||
|
|
||||
|
||||
error: usage of `Arc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:23:17
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:22:17
|
||||
|
|
||||
LL | fn func_bad1(_: Arc<String>) {}
|
||||
| ^^^^^^^^^^^ help: try: `Arc<str>`
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn func_bad1(_: Arc<String>) {}
|
||||
LL + fn func_bad1(_: Arc<str>) {}
|
||||
|
|
||||
|
||||
error: usage of `Arc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:25:17
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:24:17
|
||||
|
|
||||
LL | fn func_bad2(_: Arc<PathBuf>) {}
|
||||
| ^^^^^^^^^^^^ help: try: `Arc<std::path::Path>`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn func_bad2(_: Arc<PathBuf>) {}
|
||||
LL + fn func_bad2(_: Arc<std::path::Path>) {}
|
||||
|
|
||||
|
||||
error: usage of `Arc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:27:17
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:26:17
|
||||
|
|
||||
LL | fn func_bad3(_: Arc<Vec<u8>>) {}
|
||||
| ^^^^^^^^^^^^ help: try: `Arc<[u8]>`
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn func_bad3(_: Arc<Vec<u8>>) {}
|
||||
LL + fn func_bad3(_: Arc<[u8]>) {}
|
||||
|
|
||||
|
||||
error: usage of `Arc<T>` when T is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:29:17
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:28:17
|
||||
|
|
||||
LL | fn func_bad4(_: Arc<OsString>) {}
|
||||
| ^^^^^^^^^^^^^ help: try: `Arc<std::ffi::OsStr>`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn func_bad4(_: Arc<OsString>) {}
|
||||
LL + fn func_bad4(_: Arc<std::ffi::OsStr>) {}
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: usage of `Arc<T>` when `T` is a buffer type
|
||||
--> tests/ui/rc_buffer_arc.rs:34:15
|
||||
|
|
||||
LL | fn foo(_: std::sync::Arc<Vec<u8>>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - fn foo(_: std::sync::Arc<Vec<u8>>) {}
|
||||
LL + fn foo(_: std::sync::Arc<[u8]>) {}
|
||||
|
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue