diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index 3299dca09c3a..b4be910c8ad8 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -12,11 +12,11 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::associated_body; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::{self, Ty, UpvarId, UpvarPath}; +use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::def_id::LocalDefId; +use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_span::symbol::kw; -use rustc_span::Span; +use rustc_span::{sym, Span}; use rustc_target::spec::abi::Abi; declare_clippy_lint! { @@ -93,6 +93,16 @@ fn should_skip<'tcx>( is_from_proc_macro(cx, &input) } +fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + if def_id == CRATE_DEF_ID { + false + } else if tcx.has_attr(def_id, sym::cfg) { + true + } else { + inherits_cfg(tcx, tcx.parent_module_from_def_id(def_id)) + } +} + impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { fn check_fn( &mut self, @@ -192,10 +202,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { let show_semver_warning = self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(*fn_def_id); + let mut is_cfged = None; for input in unused { // If the argument is never used mutably, we emit the warning. let sp = input.span; if let rustc_hir::TyKind::Ref(_, inner_ty) = input.kind { + let is_cfged = is_cfged.get_or_insert_with(|| inherits_cfg(cx.tcx, *fn_def_id)); span_lint_hir_and_then( cx, NEEDLESS_PASS_BY_REF_MUT, @@ -212,6 +224,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { if show_semver_warning { diag.warn("changing this function will impact semver compatibility"); } + if *is_cfged { + diag.note("this is cfg-gated and may require further changes"); + } }, ); } diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs index 49f88978bff4..b3933bb9b4a9 100644 --- a/tests/ui/needless_pass_by_ref_mut.rs +++ b/tests/ui/needless_pass_by_ref_mut.rs @@ -184,6 +184,16 @@ fn used_as_path(s: &mut u32) {} #[expect(clippy::needless_pass_by_ref_mut)] fn lint_attr(s: &mut u32) {} +#[cfg(not(feature = "a"))] +// Should warn with note. +fn cfg_warn(s: &mut u32) {} + +#[cfg(not(feature = "a"))] +mod foo { + // Should warn with note. + fn cfg_warn(s: &mut u32) {} +} + fn main() { let mut u = 0; let mut v = vec![0]; diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr index 4ab5b5675cac..977dd5154b08 100644 --- a/tests/ui/needless_pass_by_ref_mut.stderr +++ b/tests/ui/needless_pass_by_ref_mut.stderr @@ -78,5 +78,21 @@ error: this argument is a mutable reference, but not used mutably LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` -error: aborting due to 13 previous errors +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:189:16 + | +LL | fn cfg_warn(s: &mut u32) {} + | ^^^^^^^^ help: consider changing to: `&u32` + | + = note: this is cfg-gated and may require further changes + +error: this argument is a mutable reference, but not used mutably + --> $DIR/needless_pass_by_ref_mut.rs:194:20 + | +LL | fn cfg_warn(s: &mut u32) {} + | ^^^^^^^^ help: consider changing to: `&u32` + | + = note: this is cfg-gated and may require further changes + +error: aborting due to 15 previous errors