Skip to content

Commit 651ca33

Browse files
authored
Detect prefixed attributes as duplicated (#15212)
Fix `duplicated_attributes` lint to detect prefixed attributes like `clippy::lint_name`. Fixes #14942 changelog: [`duplicated_attributes`]: detect duplicated prefixed attributes
2 parents f9ab9d0 + da66180 commit 651ca33

9 files changed

+89
-103
lines changed

clippy_lints/src/attrs/duplicated_attributes.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::DUPLICATED_ATTRIBUTES;
22
use clippy_utils::diagnostics::span_lint_and_then;
33
use itertools::Itertools;
44
use rustc_ast::{Attribute, MetaItem};
5+
use rustc_ast_pretty::pprust::path_to_string;
56
use rustc_data_structures::fx::FxHashMap;
67
use rustc_lint::EarlyContext;
78
use rustc_span::{Span, Symbol, sym};
@@ -35,39 +36,46 @@ fn check_duplicated_attr(
3536
if attr.span.from_expansion() {
3637
return;
3738
}
38-
let Some(ident) = attr.ident() else { return };
39-
let name = ident.name;
40-
if name == sym::doc || name == sym::cfg_attr_trace || name == sym::rustc_on_unimplemented || name == sym::reason {
41-
// FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
42-
// conditions are the same.
43-
// `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected.
44-
return;
45-
}
46-
if let Some(direct_parent) = parent.last()
47-
&& *direct_parent == sym::cfg_trace
48-
&& [sym::all, sym::not, sym::any].contains(&name)
49-
{
50-
// FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
51-
// level `cfg`, we leave.
52-
return;
39+
let attr_path = if let Some(ident) = attr.ident() {
40+
ident.name
41+
} else {
42+
Symbol::intern(&path_to_string(&attr.path))
43+
};
44+
if let Some(ident) = attr.ident() {
45+
let name = ident.name;
46+
if name == sym::doc || name == sym::cfg_attr_trace || name == sym::rustc_on_unimplemented || name == sym::reason
47+
{
48+
// FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
49+
// conditions are the same.
50+
// `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected.
51+
return;
52+
}
53+
if let Some(direct_parent) = parent.last()
54+
&& *direct_parent == sym::cfg_trace
55+
&& [sym::all, sym::not, sym::any].contains(&name)
56+
{
57+
// FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
58+
// level `cfg`, we leave.
59+
return;
60+
}
5361
}
5462
if let Some(value) = attr.value_str() {
5563
emit_if_duplicated(
5664
cx,
5765
attr,
5866
attr_paths,
59-
format!("{}:{name}={value}", parent.iter().join(":")),
67+
format!("{}:{attr_path}={value}", parent.iter().join(":")),
6068
);
6169
} else if let Some(sub_attrs) = attr.meta_item_list() {
62-
parent.push(name);
70+
parent.push(attr_path);
6371
for sub_attr in sub_attrs {
6472
if let Some(meta) = sub_attr.meta_item() {
6573
check_duplicated_attr(cx, meta, attr_paths, parent);
6674
}
6775
}
6876
parent.pop();
6977
} else {
70-
emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}", parent.iter().join(":")));
78+
emit_if_duplicated(cx, attr, attr_paths, format!("{}:{attr_path}", parent.iter().join(":")));
7179
}
7280
}
7381

tests/ui/duplicated_attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//@aux-build:proc_macro_attr.rs
2+
#![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)] //~ ERROR: duplicated attribute
23
#![feature(rustc_attrs)]
3-
#![warn(clippy::duplicated_attributes)]
44
#![cfg(any(unix, windows))]
55
#![allow(dead_code)]
66
#![allow(dead_code)] //~ ERROR: duplicated attribute

tests/ui/duplicated_attributes.stderr

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
error: duplicated attribute
2+
--> tests/ui/duplicated_attributes.rs:2:40
3+
|
4+
LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: first defined here
8+
--> tests/ui/duplicated_attributes.rs:2:9
9+
|
10+
LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
help: remove this attribute
13+
--> tests/ui/duplicated_attributes.rs:2:40
14+
|
15+
LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)]
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
= note: `-D clippy::duplicated-attributes` implied by `-D warnings`
18+
= help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
19+
120
error: duplicated attribute
221
--> tests/ui/duplicated_attributes.rs:6:10
322
|
@@ -14,8 +33,6 @@ help: remove this attribute
1433
|
1534
LL | #![allow(dead_code)]
1635
| ^^^^^^^^^
17-
= note: `-D clippy::duplicated-attributes` implied by `-D warnings`
18-
= help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
1936

2037
error: duplicated attribute
2138
--> tests/ui/duplicated_attributes.rs:14:9
@@ -34,5 +51,5 @@ help: remove this attribute
3451
LL | #[allow(dead_code)]
3552
| ^^^^^^^^^
3653

37-
error: aborting due to 2 previous errors
54+
error: aborting due to 3 previous errors
3855

tests/ui/indexing_slicing_slice.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//@aux-build: proc_macros.rs
22

3-
#![warn(clippy::indexing_slicing)]
43
// We also check the out_of_bounds_indexing lint here, because it lints similar things and
54
// we want to avoid false positives.
65
#![warn(clippy::out_of_bounds_indexing)]

tests/ui/indexing_slicing_slice.stderr

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: slicing may panic
2-
--> tests/ui/indexing_slicing_slice.rs:115:6
2+
--> tests/ui/indexing_slicing_slice.rs:114:6
33
|
44
LL | &x[index..];
55
| ^^^^^^^^^^
@@ -9,47 +9,47 @@ LL | &x[index..];
99
= help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
1010

1111
error: slicing may panic
12-
--> tests/ui/indexing_slicing_slice.rs:117:6
12+
--> tests/ui/indexing_slicing_slice.rs:116:6
1313
|
1414
LL | &x[..index];
1515
| ^^^^^^^^^^
1616
|
1717
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
1818

1919
error: slicing may panic
20-
--> tests/ui/indexing_slicing_slice.rs:119:6
20+
--> tests/ui/indexing_slicing_slice.rs:118:6
2121
|
2222
LL | &x[index_from..index_to];
2323
| ^^^^^^^^^^^^^^^^^^^^^^^
2424
|
2525
= help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
2626

2727
error: slicing may panic
28-
--> tests/ui/indexing_slicing_slice.rs:121:6
28+
--> tests/ui/indexing_slicing_slice.rs:120:6
2929
|
3030
LL | &x[index_from..][..index_to];
3131
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
3232
|
3333
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
3434

3535
error: slicing may panic
36-
--> tests/ui/indexing_slicing_slice.rs:121:6
36+
--> tests/ui/indexing_slicing_slice.rs:120:6
3737
|
3838
LL | &x[index_from..][..index_to];
3939
| ^^^^^^^^^^^^^^^
4040
|
4141
= help: consider using `.get(n..)` or .get_mut(n..)` instead
4242

4343
error: slicing may panic
44-
--> tests/ui/indexing_slicing_slice.rs:124:6
44+
--> tests/ui/indexing_slicing_slice.rs:123:6
4545
|
4646
LL | &x[5..][..10];
4747
| ^^^^^^^^^^^^
4848
|
4949
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
5050

5151
error: range is out of bounds
52-
--> tests/ui/indexing_slicing_slice.rs:124:8
52+
--> tests/ui/indexing_slicing_slice.rs:123:8
5353
|
5454
LL | &x[5..][..10];
5555
| ^
@@ -58,89 +58,89 @@ LL | &x[5..][..10];
5858
= help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
5959

6060
error: slicing may panic
61-
--> tests/ui/indexing_slicing_slice.rs:127:6
61+
--> tests/ui/indexing_slicing_slice.rs:126:6
6262
|
6363
LL | &x[0..][..3];
6464
| ^^^^^^^^^^^
6565
|
6666
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
6767

6868
error: slicing may panic
69-
--> tests/ui/indexing_slicing_slice.rs:129:6
69+
--> tests/ui/indexing_slicing_slice.rs:128:6
7070
|
7171
LL | &x[1..][..5];
7272
| ^^^^^^^^^^^
7373
|
7474
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
7575

7676
error: range is out of bounds
77-
--> tests/ui/indexing_slicing_slice.rs:137:12
77+
--> tests/ui/indexing_slicing_slice.rs:136:12
7878
|
7979
LL | &y[0..=4];
8080
| ^
8181

8282
error: range is out of bounds
83-
--> tests/ui/indexing_slicing_slice.rs:139:11
83+
--> tests/ui/indexing_slicing_slice.rs:138:11
8484
|
8585
LL | &y[..=4];
8686
| ^
8787

8888
error: slicing may panic
89-
--> tests/ui/indexing_slicing_slice.rs:145:6
89+
--> tests/ui/indexing_slicing_slice.rs:144:6
9090
|
9191
LL | &v[10..100];
9292
| ^^^^^^^^^^
9393
|
9494
= help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
9595

9696
error: slicing may panic
97-
--> tests/ui/indexing_slicing_slice.rs:147:6
97+
--> tests/ui/indexing_slicing_slice.rs:146:6
9898
|
9999
LL | &x[10..][..100];
100100
| ^^^^^^^^^^^^^^
101101
|
102102
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
103103

104104
error: range is out of bounds
105-
--> tests/ui/indexing_slicing_slice.rs:147:8
105+
--> tests/ui/indexing_slicing_slice.rs:146:8
106106
|
107107
LL | &x[10..][..100];
108108
| ^^
109109

110110
error: slicing may panic
111-
--> tests/ui/indexing_slicing_slice.rs:150:6
111+
--> tests/ui/indexing_slicing_slice.rs:149:6
112112
|
113113
LL | &v[10..];
114114
| ^^^^^^^
115115
|
116116
= help: consider using `.get(n..)` or .get_mut(n..)` instead
117117

118118
error: slicing may panic
119-
--> tests/ui/indexing_slicing_slice.rs:152:6
119+
--> tests/ui/indexing_slicing_slice.rs:151:6
120120
|
121121
LL | &v[..100];
122122
| ^^^^^^^^
123123
|
124124
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
125125

126126
error: indexing may panic
127-
--> tests/ui/indexing_slicing_slice.rs:170:5
127+
--> tests/ui/indexing_slicing_slice.rs:169:5
128128
|
129129
LL | map_with_get[true];
130130
| ^^^^^^^^^^^^^^^^^^
131131
|
132132
= help: consider using `.get(n)` or `.get_mut(n)` instead
133133

134134
error: indexing may panic
135-
--> tests/ui/indexing_slicing_slice.rs:174:5
135+
--> tests/ui/indexing_slicing_slice.rs:173:5
136136
|
137137
LL | s[0];
138138
| ^^^^
139139
|
140140
= help: consider using `.get(n)` or `.get_mut(n)` instead
141141

142142
error: indexing may panic
143-
--> tests/ui/indexing_slicing_slice.rs:178:5
143+
--> tests/ui/indexing_slicing_slice.rs:177:5
144144
|
145145
LL | y[0];
146146
| ^^^^

tests/ui/needless_collect_indirect.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#![allow(clippy::uninlined_format_args, clippy::useless_vec)]
2-
#![allow(clippy::needless_if, clippy::uninlined_format_args)]
1+
#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::needless_if)]
32
#![warn(clippy::needless_collect)]
43
//@no-rustfix
54
use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

0 commit comments

Comments
 (0)