Skip to content

Commit e74196a

Browse files
Do not trigger ref_patterns lint on automatically derived code (#17250)
Code marked with `#[automatically_derived]` attribute is macro generated and its syntax is out of user's control. Since `ref_patterns` is a lint for clarity, it should not be triggered for auto derived code. Fixed by converting the lint into a late pass lint and checking the auto derived attribute using `in_automatically_derived` utility. changelog: Fix [`ref_patterns`] false positive: shouldn't trigger on `#[automatically_derived]` annotated code fixes #17198 --- Note: I converted the lint into late pass because I found an existing utility `in_automatically_derived` that operates on the HIR, but the util only checks for the impl blocks (which is a subset of the possible auto derived code, I suppose). ```rust /// Checks if the given HIR node is inside an `impl` block with the `automatically_derived` /// attribute. pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool { tcx.hir_parent_owner_iter(id) .filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_)))) .any(|(id, _)| find_attr!(tcx, id.def_id, AutomaticallyDerived)) } ``` So, should I create a new utility for checking all possible nodes for auto derived attribute? Thanks!
2 parents db59d2a + 491d90b commit e74196a

3 files changed

Lines changed: 18 additions & 6 deletions

File tree

clippy_lints/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,6 @@ rustc_lint::early_lint_methods!(
534534
PartialPubFields: partial_pub_fields::PartialPubFields = partial_pub_fields::PartialPubFields,
535535
UnderscoreTyped: let_with_type_underscore::UnderscoreTyped = let_with_type_underscore::UnderscoreTyped,
536536
ExcessiveNesting: excessive_nesting::ExcessiveNesting = excessive_nesting::ExcessiveNesting::new(conf),
537-
RefPatterns: ref_patterns::RefPatterns = ref_patterns::RefPatterns,
538537
NeedlessElse: needless_else::NeedlessElse = needless_else::NeedlessElse,
539538
RawStrings: raw_strings::RawStrings = raw_strings::RawStrings::new(conf),
540539
Visibility: visibility::Visibility = visibility::Visibility,
@@ -862,6 +861,7 @@ rustc_lint::late_lint_methods!(
862861
ByteCharSlice: byte_char_slices::ByteCharSlice = byte_char_slices::ByteCharSlice,
863862
ManualAssertEq: manual_assert_eq::ManualAssertEq = manual_assert_eq::ManualAssertEq,
864863
WithCapacityZero: with_capacity_zero::WithCapacityZero = with_capacity_zero::WithCapacityZero,
864+
RefPatterns: ref_patterns::RefPatterns = ref_patterns::RefPatterns,
865865
// add late passes here, used by `cargo dev new_lint`
866866
]]
867867
);

clippy_lints/src/ref_patterns.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2-
use rustc_ast::ast::{BindingMode, Pat, PatKind};
3-
use rustc_lint::{EarlyContext, EarlyLintPass};
2+
use clippy_utils::in_automatically_derived;
3+
use rustc_hir::{BindingMode, Pat, PatKind};
4+
use rustc_lint::{LateContext, LateLintPass};
45
use rustc_session::declare_lint_pass;
56

67
declare_clippy_lint! {
@@ -29,10 +30,11 @@ declare_clippy_lint! {
2930

3031
declare_lint_pass!(RefPatterns => [REF_PATTERNS]);
3132

32-
impl EarlyLintPass for RefPatterns {
33-
fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
34-
if let PatKind::Ident(BindingMode::REF, _, _) = pat.kind
33+
impl<'tcx> LateLintPass<'tcx> for RefPatterns {
34+
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'tcx>) {
35+
if let PatKind::Binding(BindingMode::REF, _, _, _) = pat.kind
3536
&& !pat.span.from_expansion()
37+
&& !in_automatically_derived(cx.tcx, pat.hir_id)
3638
{
3739
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
3840
span_lint_and_then(cx, REF_PATTERNS, pat.span, "usage of ref pattern", |diag| {

tests/ui/ref_patterns.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,14 @@ fn use_in_binding() {
1919
fn use_in_parameter(ref x: i32) {}
2020
//~^ ref_patterns
2121

22+
struct Foo {}
23+
24+
// shouldn't trigger the lint
25+
#[automatically_derived]
26+
impl Foo {
27+
fn foo() {
28+
if let Some(ref x) = Some(1) {}
29+
}
30+
}
31+
2232
fn main() {}

0 commit comments

Comments
 (0)