Skip to content

Commit e639e88

Browse files
committed
Lint #[must_use] attributes applied to methods in trait impls
The `#[must_use]` attribute has no effect when applied to methods in trait implementations. This case was not linted before.
1 parent 3e66ba7 commit e639e88

File tree

3 files changed

+55
-33
lines changed

3 files changed

+55
-33
lines changed

Diff for: compiler/rustc_passes/src/check_attr.rs

+29-18
Original file line numberDiff line numberDiff line change
@@ -1431,37 +1431,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
14311431

14321432
/// Warns against some misuses of `#[must_use]`
14331433
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
1434-
if !matches!(
1434+
if matches!(
14351435
target,
14361436
Target::Fn
14371437
| Target::Enum
14381438
| Target::Struct
14391439
| Target::Union
1440-
| Target::Method(_)
1440+
| Target::Method(MethodKind::Trait { body: false } | MethodKind::Inherent)
14411441
| Target::ForeignFn
14421442
// `impl Trait` in return position can trip
14431443
// `unused_must_use` if `Trait` is marked as
14441444
// `#[must_use]`
14451445
| Target::Trait
14461446
) {
1447-
let article = match target {
1448-
Target::ExternCrate
1449-
| Target::Enum
1450-
| Target::Impl
1451-
| Target::Expression
1452-
| Target::Arm
1453-
| Target::AssocConst
1454-
| Target::AssocTy => "an",
1455-
_ => "a",
1456-
};
1447+
return;
1448+
}
14571449

1458-
self.tcx.emit_node_span_lint(
1459-
UNUSED_ATTRIBUTES,
1460-
hir_id,
1461-
attr.span,
1462-
errors::MustUseNoEffect { article, target },
1463-
);
1450+
// `#[must_use]` can be applied to a trait method definition with a default body
1451+
if let Target::Method(MethodKind::Trait { body: true }) = target
1452+
&& let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id
1453+
&& let containing_item = self.tcx.hir().expect_item(parent_def_id)
1454+
&& let hir::ItemKind::Trait(..) = containing_item.kind
1455+
{
1456+
return;
14641457
}
1458+
1459+
let article = match target {
1460+
Target::ExternCrate
1461+
| Target::Enum
1462+
| Target::Impl
1463+
| Target::Expression
1464+
| Target::Arm
1465+
| Target::AssocConst
1466+
| Target::AssocTy => "an",
1467+
_ => "a",
1468+
};
1469+
1470+
self.tcx.emit_node_span_lint(
1471+
UNUSED_ATTRIBUTES,
1472+
hir_id,
1473+
attr.span,
1474+
errors::MustUseNoEffect { article, target },
1475+
);
14651476
}
14661477

14671478
/// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.

Diff for: tests/ui/lint/unused/unused_attributes-must_use.rs

+5
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ trait Use {
7979
#[must_use] //~ ERROR `#[must_use]` has no effect
8080
impl Use for () {
8181
type AssocTy = ();
82+
83+
#[must_use] //~ ERROR `#[must_use]` has no effect
84+
fn get_four(&self) -> usize {
85+
4
86+
}
8287
}
8388

8489
#[must_use] //~ ERROR `#[must_use]` has no effect

Diff for: tests/ui/lint/unused/unused_attributes-must_use.stderr

+21-15
Original file line numberDiff line numberDiff line change
@@ -76,43 +76,43 @@ LL | #[must_use]
7676
| ^^^^^^^^^^^
7777

7878
error: `#[must_use]` has no effect when applied to a trait alias
79-
--> $DIR/unused_attributes-must_use.rs:84:1
79+
--> $DIR/unused_attributes-must_use.rs:89:1
8080
|
8181
LL | #[must_use]
8282
| ^^^^^^^^^^^
8383

8484
error: `#[must_use]` has no effect when applied to a macro def
85-
--> $DIR/unused_attributes-must_use.rs:87:1
85+
--> $DIR/unused_attributes-must_use.rs:92:1
8686
|
8787
LL | #[must_use]
8888
| ^^^^^^^^^^^
8989

9090
error: `#[must_use]` has no effect when applied to a statement
91-
--> $DIR/unused_attributes-must_use.rs:95:5
91+
--> $DIR/unused_attributes-must_use.rs:100:5
9292
|
9393
LL | #[must_use]
9494
| ^^^^^^^^^^^
9595

9696
error: `#[must_use]` has no effect when applied to a closure
97-
--> $DIR/unused_attributes-must_use.rs:99:13
97+
--> $DIR/unused_attributes-must_use.rs:104:13
9898
|
9999
LL | let x = #[must_use]
100100
| ^^^^^^^^^^^
101101

102102
error: `#[must_use]` has no effect when applied to an match arm
103-
--> $DIR/unused_attributes-must_use.rs:121:9
103+
--> $DIR/unused_attributes-must_use.rs:126:9
104104
|
105105
LL | #[must_use]
106106
| ^^^^^^^^^^^
107107

108108
error: `#[must_use]` has no effect when applied to a struct field
109-
--> $DIR/unused_attributes-must_use.rs:129:28
109+
--> $DIR/unused_attributes-must_use.rs:134:28
110110
|
111111
LL | let s = PatternField { #[must_use] foo: 123 };
112112
| ^^^^^^^^^^^
113113

114114
error: `#[must_use]` has no effect when applied to a pattern field
115-
--> $DIR/unused_attributes-must_use.rs:130:24
115+
--> $DIR/unused_attributes-must_use.rs:135:24
116116
|
117117
LL | let PatternField { #[must_use] foo } = s;
118118
| ^^^^^^^^^^^
@@ -129,14 +129,20 @@ error: `#[must_use]` has no effect when applied to an associated type
129129
LL | #[must_use]
130130
| ^^^^^^^^^^^
131131

132+
error: `#[must_use]` has no effect when applied to a provided trait method
133+
--> $DIR/unused_attributes-must_use.rs:83:5
134+
|
135+
LL | #[must_use]
136+
| ^^^^^^^^^^^
137+
132138
error: `#[must_use]` has no effect when applied to a foreign static item
133139
--> $DIR/unused_attributes-must_use.rs:50:5
134140
|
135141
LL | #[must_use]
136142
| ^^^^^^^^^^^
137143

138144
error: unused `X` that must be used
139-
--> $DIR/unused_attributes-must_use.rs:103:5
145+
--> $DIR/unused_attributes-must_use.rs:108:5
140146
|
141147
LL | X;
142148
| ^
@@ -152,7 +158,7 @@ LL | let _ = X;
152158
| +++++++
153159

154160
error: unused `Y` that must be used
155-
--> $DIR/unused_attributes-must_use.rs:104:5
161+
--> $DIR/unused_attributes-must_use.rs:109:5
156162
|
157163
LL | Y::Z;
158164
| ^^^^
@@ -163,7 +169,7 @@ LL | let _ = Y::Z;
163169
| +++++++
164170

165171
error: unused `U` that must be used
166-
--> $DIR/unused_attributes-must_use.rs:105:5
172+
--> $DIR/unused_attributes-must_use.rs:110:5
167173
|
168174
LL | U { unit: () };
169175
| ^^^^^^^^^^^^^^
@@ -174,7 +180,7 @@ LL | let _ = U { unit: () };
174180
| +++++++
175181

176182
error: unused return value of `U::method` that must be used
177-
--> $DIR/unused_attributes-must_use.rs:106:5
183+
--> $DIR/unused_attributes-must_use.rs:111:5
178184
|
179185
LL | U::method();
180186
| ^^^^^^^^^^^
@@ -185,7 +191,7 @@ LL | let _ = U::method();
185191
| +++++++
186192

187193
error: unused return value of `foo` that must be used
188-
--> $DIR/unused_attributes-must_use.rs:107:5
194+
--> $DIR/unused_attributes-must_use.rs:112:5
189195
|
190196
LL | foo();
191197
| ^^^^^
@@ -196,7 +202,7 @@ LL | let _ = foo();
196202
| +++++++
197203

198204
error: unused return value of `foreign_foo` that must be used
199-
--> $DIR/unused_attributes-must_use.rs:110:9
205+
--> $DIR/unused_attributes-must_use.rs:115:9
200206
|
201207
LL | foreign_foo();
202208
| ^^^^^^^^^^^^^
@@ -207,7 +213,7 @@ LL | let _ = foreign_foo();
207213
| +++++++
208214

209215
error: unused return value of `Use::get_four` that must be used
210-
--> $DIR/unused_attributes-must_use.rs:118:5
216+
--> $DIR/unused_attributes-must_use.rs:123:5
211217
|
212218
LL | ().get_four();
213219
| ^^^^^^^^^^^^^
@@ -217,5 +223,5 @@ help: use `let _ = ...` to ignore the resulting value
217223
LL | let _ = ().get_four();
218224
| +++++++
219225

220-
error: aborting due to 28 previous errors
226+
error: aborting due to 29 previous errors
221227

0 commit comments

Comments
 (0)