From 4673b25bb7173e5e79e3b5c782c9970189435e2a Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 1 Oct 2025 19:42:33 +0200 Subject: [PATCH 1/5] clean-up a bit --- clippy_lints/src/types/rc_buffer.rs | 8 ++++---- tests/ui/rc_buffer.fixed | 1 - tests/ui/rc_buffer.rs | 1 - tests/ui/rc_buffer.stderr | 32 ++++++++++++++--------------- tests/ui/rc_buffer_arc.fixed | 1 - tests/ui/rc_buffer_arc.rs | 1 - tests/ui/rc_buffer_arc.stderr | 32 ++++++++++++++--------------- 7 files changed, 36 insertions(+), 40 deletions(-) diff --git a/clippy_lints/src/types/rc_buffer.rs b/clippy_lints/src/types/rc_buffer.rs index c4fd0fbf87a9..1e89a487741f 100644 --- a/clippy_lints/src/types/rc_buffer.rs +++ b/clippy_lints/src/types/rc_buffer.rs @@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ cx, RC_BUFFER, hir_ty.span, - "usage of `Rc` when T is a buffer type", + "usage of `Rc` when `T` is a buffer type", |diag| { diag.span_suggestion(hir_ty.span, "try", format!("Rc<{alternate}>"), app); }, @@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ cx, RC_BUFFER, hir_ty.span, - "usage of `Rc` when T is a buffer type", + "usage of `Rc` when `T` is a buffer type", |diag| { let mut applicability = app; diag.span_suggestion( @@ -64,7 +64,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ cx, RC_BUFFER, hir_ty.span, - "usage of `Arc` when T is a buffer type", + "usage of `Arc` when `T` is a buffer type", |diag| { diag.span_suggestion(hir_ty.span, "try", format!("Arc<{alternate}>"), app); }, @@ -83,7 +83,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ cx, RC_BUFFER, hir_ty.span, - "usage of `Arc` when T is a buffer type", + "usage of `Arc` when `T` is a buffer type", |diag| { let mut applicability = app; diag.span_suggestion( diff --git a/tests/ui/rc_buffer.fixed b/tests/ui/rc_buffer.fixed index c71a4072b962..93811a0ad2fc 100644 --- a/tests/ui/rc_buffer.fixed +++ b/tests/ui/rc_buffer.fixed @@ -1,5 +1,4 @@ #![warn(clippy::rc_buffer)] -#![allow(dead_code, unused_imports)] use std::cell::RefCell; use std::ffi::OsString; diff --git a/tests/ui/rc_buffer.rs b/tests/ui/rc_buffer.rs index 686c2644da17..a644a29a03c9 100644 --- a/tests/ui/rc_buffer.rs +++ b/tests/ui/rc_buffer.rs @@ -1,5 +1,4 @@ #![warn(clippy::rc_buffer)] -#![allow(dead_code, unused_imports)] use std::cell::RefCell; use std::ffi::OsString; diff --git a/tests/ui/rc_buffer.stderr b/tests/ui/rc_buffer.stderr index 7500523ab4ac..e7000bf506b6 100644 --- a/tests/ui/rc_buffer.stderr +++ b/tests/ui/rc_buffer.stderr @@ -1,5 +1,5 @@ -error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:11:11 +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:10:11 | LL | bad1: Rc, | ^^^^^^^^^^ help: try: `Rc` @@ -7,44 +7,44 @@ LL | bad1: Rc, = note: `-D clippy::rc-buffer` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::rc_buffer)]` -error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:13:11 +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:12:11 | LL | bad2: Rc, | ^^^^^^^^^^^ help: try: `Rc` -error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:15:11 +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:14:11 | LL | bad3: Rc>, | ^^^^^^^^^^^ help: try: `Rc<[u8]>` -error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:17:11 +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:16:11 | LL | bad4: Rc, | ^^^^^^^^^^^^ help: try: `Rc` -error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:24:17 +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:23:17 | LL | fn func_bad1(_: Rc) {} | ^^^^^^^^^^ help: try: `Rc` -error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:26:17 +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:25:17 | LL | fn func_bad2(_: Rc) {} | ^^^^^^^^^^^ help: try: `Rc` -error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:28:17 +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:27:17 | LL | fn func_bad3(_: Rc>) {} | ^^^^^^^^^^^ help: try: `Rc<[u8]>` -error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:30:17 +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:29:17 | LL | fn func_bad4(_: Rc) {} | ^^^^^^^^^^^^ help: try: `Rc` diff --git a/tests/ui/rc_buffer_arc.fixed b/tests/ui/rc_buffer_arc.fixed index 27059e3f2e1f..8e0adec48da7 100644 --- a/tests/ui/rc_buffer_arc.fixed +++ b/tests/ui/rc_buffer_arc.fixed @@ -1,5 +1,4 @@ #![warn(clippy::rc_buffer)] -#![allow(dead_code, unused_imports)] use std::ffi::OsString; use std::path::PathBuf; diff --git a/tests/ui/rc_buffer_arc.rs b/tests/ui/rc_buffer_arc.rs index 5261eae2f26a..1ec8abbdae99 100644 --- a/tests/ui/rc_buffer_arc.rs +++ b/tests/ui/rc_buffer_arc.rs @@ -1,5 +1,4 @@ #![warn(clippy::rc_buffer)] -#![allow(dead_code, unused_imports)] use std::ffi::OsString; use std::path::PathBuf; diff --git a/tests/ui/rc_buffer_arc.stderr b/tests/ui/rc_buffer_arc.stderr index 786715463232..6997a5a28349 100644 --- a/tests/ui/rc_buffer_arc.stderr +++ b/tests/ui/rc_buffer_arc.stderr @@ -1,5 +1,5 @@ -error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:10:11 +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:9:11 | LL | bad1: Arc, | ^^^^^^^^^^^ help: try: `Arc` @@ -7,44 +7,44 @@ LL | bad1: Arc, = note: `-D clippy::rc-buffer` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::rc_buffer)]` -error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:12:11 +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:11:11 | LL | bad2: Arc, | ^^^^^^^^^^^^ help: try: `Arc` -error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:14:11 +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:13:11 | LL | bad3: Arc>, | ^^^^^^^^^^^^ help: try: `Arc<[u8]>` -error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:16:11 +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:15:11 | LL | bad4: Arc, | ^^^^^^^^^^^^^ help: try: `Arc` -error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:23:17 +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:22:17 | LL | fn func_bad1(_: Arc) {} | ^^^^^^^^^^^ help: try: `Arc` -error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:25:17 +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:24:17 | LL | fn func_bad2(_: Arc) {} | ^^^^^^^^^^^^ help: try: `Arc` -error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:27:17 +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:26:17 | LL | fn func_bad3(_: Arc>) {} | ^^^^^^^^^^^^ help: try: `Arc<[u8]>` -error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:29:17 +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:28:17 | LL | fn func_bad4(_: Arc) {} | ^^^^^^^^^^^^^ help: try: `Arc` From 06e8ff7ace60a6df6fd6be1e202f410cb54f10c9 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 1 Oct 2025 19:03:18 +0200 Subject: [PATCH 2/5] fix: return `true` everywhere we emit the lint --- clippy_lints/src/types/rc_buffer.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/types/rc_buffer.rs b/clippy_lints/src/types/rc_buffer.rs index 1e89a487741f..d5835186cba3 100644 --- a/clippy_lints/src/types/rc_buffer.rs +++ b/clippy_lints/src/types/rc_buffer.rs @@ -24,6 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ diag.span_suggestion(hir_ty.span, "try", format!("Rc<{alternate}>"), app); }, ); + true } else { let Some(ty) = qpath_generic_tys(qpath).next() else { return false; @@ -55,7 +56,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ ); }, ); - return true; + true } } else if name == Some(sym::Arc) { if let Some(alternate) = match_buffer_type(cx, qpath) { @@ -69,6 +70,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ diag.span_suggestion(hir_ty.span, "try", format!("Arc<{alternate}>"), app); }, ); + true } else if let Some(ty) = qpath_generic_tys(qpath).next() { let Some(id) = path_def_id(cx, ty) else { return false }; if !cx.tcx.is_diagnostic_item(sym::Vec, id) { @@ -97,11 +99,13 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ ); }, ); - return true; + true + } else { + false } + } else { + false } - - false } fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> { From 6d60568be0889d213f80d827c29c53f2b9f1e1a5 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 1 Oct 2025 19:34:51 +0200 Subject: [PATCH 3/5] refactor: also handle `Vec` in `match_buffer_type` Reduces code repetition --- clippy_lints/src/types/rc_buffer.rs | 88 +++++++---------------------- 1 file changed, 21 insertions(+), 67 deletions(-) diff --git a/clippy_lints/src/types/rc_buffer.rs b/clippy_lints/src/types/rc_buffer.rs index d5835186cba3..cf7cd9fedb3e 100644 --- a/clippy_lints/src/types/rc_buffer.rs +++ b/clippy_lints/src/types/rc_buffer.rs @@ -6,14 +6,15 @@ use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, QPath, TyKind}; use rustc_lint::LateContext; use rustc_span::symbol::sym; +use std::borrow::Cow; 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 mut 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) { + if let Some(alternate) = match_buffer_type(cx, qpath, &mut app) { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( cx, @@ -26,40 +27,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ ); true } else { - let Some(ty) = qpath_generic_tys(qpath).next() else { - return false; - }; - let Some(id) = path_def_id(cx, ty) else { return false }; - if !cx.tcx.is_diagnostic_item(sym::Vec, id) { - 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` 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, - ); - }, - ); - true + false } } else if name == Some(sym::Arc) { - if let Some(alternate) = match_buffer_type(cx, qpath) { + if let Some(alternate) = match_buffer_type(cx, qpath, &mut app) { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( cx, @@ -71,35 +42,6 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ }, ); true - } else if let Some(ty) = qpath_generic_tys(qpath).next() { - let Some(id) = path_def_id(cx, ty) else { return false }; - if !cx.tcx.is_diagnostic_item(sym::Vec, id) { - 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` 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, - ); - }, - ); - true } else { false } @@ -108,13 +50,25 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ } } -fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> { +fn match_buffer_type( + cx: &LateContext<'_>, + qpath: &QPath<'_>, + applicability: &mut Applicability, +) -> Option> { let ty = qpath_generic_tys(qpath).next()?; let id = path_def_id(cx, ty)?; 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) From 771ca3864df5b516f27f718c34a76ee8657ccfc8 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 1 Oct 2025 19:39:38 +0200 Subject: [PATCH 4/5] fix: make the suggestion apply only to the inner type Now we don't touch, and thus don't break, whatever path `Rc`/`Arc` was specified with --- clippy_lints/src/types/rc_buffer.rs | 21 ++++---- tests/ui/rc_buffer.fixed | 5 ++ tests/ui/rc_buffer.rs | 5 ++ tests/ui/rc_buffer.stderr | 77 +++++++++++++++++++++++++---- tests/ui/rc_buffer_arc.fixed | 5 ++ tests/ui/rc_buffer_arc.rs | 5 ++ tests/ui/rc_buffer_arc.stderr | 77 +++++++++++++++++++++++++---- 7 files changed, 167 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/types/rc_buffer.rs b/clippy_lints/src/types/rc_buffer.rs index cf7cd9fedb3e..38084fd8fb28 100644 --- a/clippy_lints/src/types/rc_buffer.rs +++ b/clippy_lints/src/types/rc_buffer.rs @@ -3,26 +3,27 @@ use clippy_utils::source::snippet_with_applicability; use clippy_utils::{path_def_id, qpath_generic_tys}; 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 super::RC_BUFFER; -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { +pub(super) fn check(cx: &LateContext<'_>, hir_ty: &Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { let mut 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, &mut app) { - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + 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, "usage of `Rc` when `T` is a buffer type", |diag| { - diag.span_suggestion(hir_ty.span, "try", format!("Rc<{alternate}>"), app); + diag.span_suggestion_verbose(ty.span, "try", alternate, app); }, ); true @@ -30,15 +31,16 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ false } } else if name == Some(sym::Arc) { - if let Some(alternate) = match_buffer_type(cx, qpath, &mut app) { - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + 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, "usage of `Arc` when `T` is a buffer type", |diag| { - diag.span_suggestion(hir_ty.span, "try", format!("Arc<{alternate}>"), app); + diag.span_suggestion_verbose(ty.span, "try", alternate, app); }, ); true @@ -52,10 +54,9 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ fn match_buffer_type( cx: &LateContext<'_>, - qpath: &QPath<'_>, + ty: &Ty<'_>, applicability: &mut Applicability, ) -> Option> { - let ty = qpath_generic_tys(qpath).next()?; let id = path_def_id(cx, ty)?; let path = match cx.tcx.get_diagnostic_name(id) { Some(sym::OsString) => "std::ffi::OsStr".into(), diff --git a/tests/ui/rc_buffer.fixed b/tests/ui/rc_buffer.fixed index 93811a0ad2fc..a41f98c8fa35 100644 --- a/tests/ui/rc_buffer.fixed +++ b/tests/ui/rc_buffer.fixed @@ -31,4 +31,9 @@ fn func_bad4(_: Rc) {} // does not trigger lint fn func_good1(_: Rc>) {} +mod issue_15802 { + fn foo(_: std::rc::Rc<[u8]>) {} + //~^ rc_buffer +} + fn main() {} diff --git a/tests/ui/rc_buffer.rs b/tests/ui/rc_buffer.rs index a644a29a03c9..879f60647472 100644 --- a/tests/ui/rc_buffer.rs +++ b/tests/ui/rc_buffer.rs @@ -31,4 +31,9 @@ fn func_bad4(_: Rc) {} // does not trigger lint fn func_good1(_: Rc>) {} +mod issue_15802 { + fn foo(_: std::rc::Rc>) {} + //~^ rc_buffer +} + fn main() {} diff --git a/tests/ui/rc_buffer.stderr b/tests/ui/rc_buffer.stderr index e7000bf506b6..e31e9c9c8fdf 100644 --- a/tests/ui/rc_buffer.stderr +++ b/tests/ui/rc_buffer.stderr @@ -2,52 +2,111 @@ error: usage of `Rc` when `T` is a buffer type --> tests/ui/rc_buffer.rs:10:11 | LL | bad1: Rc, - | ^^^^^^^^^^ help: try: `Rc` + | ^^^^^^^^^^ | = note: `-D clippy::rc-buffer` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::rc_buffer)]` +help: try + | +LL - bad1: Rc, +LL + bad1: Rc, + | error: usage of `Rc` when `T` is a buffer type --> tests/ui/rc_buffer.rs:12:11 | LL | bad2: Rc, - | ^^^^^^^^^^^ help: try: `Rc` + | ^^^^^^^^^^^ + | +help: try + | +LL - bad2: Rc, +LL + bad2: Rc, + | error: usage of `Rc` when `T` is a buffer type --> tests/ui/rc_buffer.rs:14:11 | LL | bad3: Rc>, - | ^^^^^^^^^^^ help: try: `Rc<[u8]>` + | ^^^^^^^^^^^ + | +help: try + | +LL - bad3: Rc>, +LL + bad3: Rc<[u8]>, + | error: usage of `Rc` when `T` is a buffer type --> tests/ui/rc_buffer.rs:16:11 | LL | bad4: Rc, - | ^^^^^^^^^^^^ help: try: `Rc` + | ^^^^^^^^^^^^ + | +help: try + | +LL - bad4: Rc, +LL + bad4: Rc, + | error: usage of `Rc` when `T` is a buffer type --> tests/ui/rc_buffer.rs:23:17 | LL | fn func_bad1(_: Rc) {} - | ^^^^^^^^^^ help: try: `Rc` + | ^^^^^^^^^^ + | +help: try + | +LL - fn func_bad1(_: Rc) {} +LL + fn func_bad1(_: Rc) {} + | error: usage of `Rc` when `T` is a buffer type --> tests/ui/rc_buffer.rs:25:17 | LL | fn func_bad2(_: Rc) {} - | ^^^^^^^^^^^ help: try: `Rc` + | ^^^^^^^^^^^ + | +help: try + | +LL - fn func_bad2(_: Rc) {} +LL + fn func_bad2(_: Rc) {} + | error: usage of `Rc` when `T` is a buffer type --> tests/ui/rc_buffer.rs:27:17 | LL | fn func_bad3(_: Rc>) {} - | ^^^^^^^^^^^ help: try: `Rc<[u8]>` + | ^^^^^^^^^^^ + | +help: try + | +LL - fn func_bad3(_: Rc>) {} +LL + fn func_bad3(_: Rc<[u8]>) {} + | error: usage of `Rc` when `T` is a buffer type --> tests/ui/rc_buffer.rs:29:17 | LL | fn func_bad4(_: Rc) {} - | ^^^^^^^^^^^^ help: try: `Rc` + | ^^^^^^^^^^^^ + | +help: try + | +LL - fn func_bad4(_: Rc) {} +LL + fn func_bad4(_: Rc) {} + | + +error: usage of `Rc` when `T` is a buffer type + --> tests/ui/rc_buffer.rs:35:15 + | +LL | fn foo(_: std::rc::Rc>) {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - fn foo(_: std::rc::Rc>) {} +LL + fn foo(_: std::rc::Rc<[u8]>) {} + | -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/rc_buffer_arc.fixed b/tests/ui/rc_buffer_arc.fixed index 8e0adec48da7..36b989ec1b60 100644 --- a/tests/ui/rc_buffer_arc.fixed +++ b/tests/ui/rc_buffer_arc.fixed @@ -30,4 +30,9 @@ fn func_bad4(_: Arc) {} // does not trigger lint fn func_good1(_: Arc>) {} +mod issue_15802 { + fn foo(_: std::sync::Arc<[u8]>) {} + //~^ rc_buffer +} + fn main() {} diff --git a/tests/ui/rc_buffer_arc.rs b/tests/ui/rc_buffer_arc.rs index 1ec8abbdae99..f8e78dc5c18f 100644 --- a/tests/ui/rc_buffer_arc.rs +++ b/tests/ui/rc_buffer_arc.rs @@ -30,4 +30,9 @@ fn func_bad4(_: Arc) {} // does not trigger lint fn func_good1(_: Arc>) {} +mod issue_15802 { + fn foo(_: std::sync::Arc>) {} + //~^ rc_buffer +} + fn main() {} diff --git a/tests/ui/rc_buffer_arc.stderr b/tests/ui/rc_buffer_arc.stderr index 6997a5a28349..043f7a15ec00 100644 --- a/tests/ui/rc_buffer_arc.stderr +++ b/tests/ui/rc_buffer_arc.stderr @@ -2,52 +2,111 @@ error: usage of `Arc` when `T` is a buffer type --> tests/ui/rc_buffer_arc.rs:9:11 | LL | bad1: Arc, - | ^^^^^^^^^^^ help: try: `Arc` + | ^^^^^^^^^^^ | = note: `-D clippy::rc-buffer` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::rc_buffer)]` +help: try + | +LL - bad1: Arc, +LL + bad1: Arc, + | error: usage of `Arc` when `T` is a buffer type --> tests/ui/rc_buffer_arc.rs:11:11 | LL | bad2: Arc, - | ^^^^^^^^^^^^ help: try: `Arc` + | ^^^^^^^^^^^^ + | +help: try + | +LL - bad2: Arc, +LL + bad2: Arc, + | error: usage of `Arc` when `T` is a buffer type --> tests/ui/rc_buffer_arc.rs:13:11 | LL | bad3: Arc>, - | ^^^^^^^^^^^^ help: try: `Arc<[u8]>` + | ^^^^^^^^^^^^ + | +help: try + | +LL - bad3: Arc>, +LL + bad3: Arc<[u8]>, + | error: usage of `Arc` when `T` is a buffer type --> tests/ui/rc_buffer_arc.rs:15:11 | LL | bad4: Arc, - | ^^^^^^^^^^^^^ help: try: `Arc` + | ^^^^^^^^^^^^^ + | +help: try + | +LL - bad4: Arc, +LL + bad4: Arc, + | error: usage of `Arc` when `T` is a buffer type --> tests/ui/rc_buffer_arc.rs:22:17 | LL | fn func_bad1(_: Arc) {} - | ^^^^^^^^^^^ help: try: `Arc` + | ^^^^^^^^^^^ + | +help: try + | +LL - fn func_bad1(_: Arc) {} +LL + fn func_bad1(_: Arc) {} + | error: usage of `Arc` when `T` is a buffer type --> tests/ui/rc_buffer_arc.rs:24:17 | LL | fn func_bad2(_: Arc) {} - | ^^^^^^^^^^^^ help: try: `Arc` + | ^^^^^^^^^^^^ + | +help: try + | +LL - fn func_bad2(_: Arc) {} +LL + fn func_bad2(_: Arc) {} + | error: usage of `Arc` when `T` is a buffer type --> tests/ui/rc_buffer_arc.rs:26:17 | LL | fn func_bad3(_: Arc>) {} - | ^^^^^^^^^^^^ help: try: `Arc<[u8]>` + | ^^^^^^^^^^^^ + | +help: try + | +LL - fn func_bad3(_: Arc>) {} +LL + fn func_bad3(_: Arc<[u8]>) {} + | error: usage of `Arc` when `T` is a buffer type --> tests/ui/rc_buffer_arc.rs:28:17 | LL | fn func_bad4(_: Arc) {} - | ^^^^^^^^^^^^^ help: try: `Arc` + | ^^^^^^^^^^^^^ + | +help: try + | +LL - fn func_bad4(_: Arc) {} +LL + fn func_bad4(_: Arc) {} + | + +error: usage of `Arc` when `T` is a buffer type + --> tests/ui/rc_buffer_arc.rs:34:15 + | +LL | fn foo(_: std::sync::Arc>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - fn foo(_: std::sync::Arc>) {} +LL + fn foo(_: std::sync::Arc<[u8]>) {} + | -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors From 39b5a0539f7cd3097a9250a9eb06d387e91c3025 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 1 Oct 2025 20:27:59 +0200 Subject: [PATCH 5/5] refactor: reduce code duplication further --- clippy_lints/src/types/rc_buffer.rs | 68 ++++++++++++++--------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/types/rc_buffer.rs b/clippy_lints/src/types/rc_buffer.rs index 38084fd8fb28..cba8352c3e44 100644 --- a/clippy_lints/src/types/rc_buffer.rs +++ b/clippy_lints/src/types/rc_buffer.rs @@ -7,51 +7,49 @@ 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: &Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { let mut app = Applicability::Unspecified; - let name = cx.tcx.get_diagnostic_name(def_id); - if name == Some(sym::Rc) { - 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, - "usage of `Rc` when `T` is a buffer type", - |diag| { - diag.span_suggestion_verbose(ty.span, "try", alternate, app); - }, - ); - true - } else { - false - } - } else if name == Some(sym::Arc) { - 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, - "usage of `Arc` when `T` is a buffer type", - |diag| { - diag.span_suggestion_verbose(ty.span, "try", alternate, app); - }, - ); - true - } else { - false - } + 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}` when `T` is a buffer type"), + |diag| { + diag.span_suggestion_verbose(ty.span, "try", alternate, app); + }, + ); + true } else { false } } +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<'_>,