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.
This commit is contained in:
parent
3e66ba73d5
commit
e639e886b2
3 changed files with 56 additions and 34 deletions
|
@ -1431,37 +1431,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
|
|
||||||
/// Warns against some misuses of `#[must_use]`
|
/// Warns against some misuses of `#[must_use]`
|
||||||
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
||||||
if !matches!(
|
if matches!(
|
||||||
target,
|
target,
|
||||||
Target::Fn
|
Target::Fn
|
||||||
| Target::Enum
|
| Target::Enum
|
||||||
| Target::Struct
|
| Target::Struct
|
||||||
| Target::Union
|
| Target::Union
|
||||||
| Target::Method(_)
|
| Target::Method(MethodKind::Trait { body: false } | MethodKind::Inherent)
|
||||||
| Target::ForeignFn
|
| Target::ForeignFn
|
||||||
// `impl Trait` in return position can trip
|
// `impl Trait` in return position can trip
|
||||||
// `unused_must_use` if `Trait` is marked as
|
// `unused_must_use` if `Trait` is marked as
|
||||||
// `#[must_use]`
|
// `#[must_use]`
|
||||||
| Target::Trait
|
| Target::Trait
|
||||||
) {
|
) {
|
||||||
let article = match target {
|
return;
|
||||||
Target::ExternCrate
|
|
||||||
| Target::Enum
|
|
||||||
| Target::Impl
|
|
||||||
| Target::Expression
|
|
||||||
| Target::Arm
|
|
||||||
| Target::AssocConst
|
|
||||||
| Target::AssocTy => "an",
|
|
||||||
_ => "a",
|
|
||||||
};
|
|
||||||
|
|
||||||
self.tcx.emit_node_span_lint(
|
|
||||||
UNUSED_ATTRIBUTES,
|
|
||||||
hir_id,
|
|
||||||
attr.span,
|
|
||||||
errors::MustUseNoEffect { article, target },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `#[must_use]` can be applied to a trait method definition with a default body
|
||||||
|
if let Target::Method(MethodKind::Trait { body: true }) = target
|
||||||
|
&& let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id
|
||||||
|
&& let containing_item = self.tcx.hir().expect_item(parent_def_id)
|
||||||
|
&& let hir::ItemKind::Trait(..) = containing_item.kind
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let article = match target {
|
||||||
|
Target::ExternCrate
|
||||||
|
| Target::Enum
|
||||||
|
| Target::Impl
|
||||||
|
| Target::Expression
|
||||||
|
| Target::Arm
|
||||||
|
| Target::AssocConst
|
||||||
|
| Target::AssocTy => "an",
|
||||||
|
_ => "a",
|
||||||
|
};
|
||||||
|
|
||||||
|
self.tcx.emit_node_span_lint(
|
||||||
|
UNUSED_ATTRIBUTES,
|
||||||
|
hir_id,
|
||||||
|
attr.span,
|
||||||
|
errors::MustUseNoEffect { article, target },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.
|
/// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.
|
||||||
|
|
|
@ -79,6 +79,11 @@ trait Use {
|
||||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||||
impl Use for () {
|
impl Use for () {
|
||||||
type AssocTy = ();
|
type AssocTy = ();
|
||||||
|
|
||||||
|
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||||
|
fn get_four(&self) -> usize {
|
||||||
|
4
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use] //~ ERROR `#[must_use]` has no effect
|
#[must_use] //~ ERROR `#[must_use]` has no effect
|
||||||
|
|
|
@ -76,43 +76,43 @@ LL | #[must_use]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to a trait alias
|
error: `#[must_use]` has no effect when applied to a trait alias
|
||||||
--> $DIR/unused_attributes-must_use.rs:84:1
|
--> $DIR/unused_attributes-must_use.rs:89:1
|
||||||
|
|
|
|
||||||
LL | #[must_use]
|
LL | #[must_use]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to a macro def
|
error: `#[must_use]` has no effect when applied to a macro def
|
||||||
--> $DIR/unused_attributes-must_use.rs:87:1
|
--> $DIR/unused_attributes-must_use.rs:92:1
|
||||||
|
|
|
|
||||||
LL | #[must_use]
|
LL | #[must_use]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to a statement
|
error: `#[must_use]` has no effect when applied to a statement
|
||||||
--> $DIR/unused_attributes-must_use.rs:95:5
|
--> $DIR/unused_attributes-must_use.rs:100:5
|
||||||
|
|
|
|
||||||
LL | #[must_use]
|
LL | #[must_use]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to a closure
|
error: `#[must_use]` has no effect when applied to a closure
|
||||||
--> $DIR/unused_attributes-must_use.rs:99:13
|
--> $DIR/unused_attributes-must_use.rs:104:13
|
||||||
|
|
|
|
||||||
LL | let x = #[must_use]
|
LL | let x = #[must_use]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to an match arm
|
error: `#[must_use]` has no effect when applied to an match arm
|
||||||
--> $DIR/unused_attributes-must_use.rs:121:9
|
--> $DIR/unused_attributes-must_use.rs:126:9
|
||||||
|
|
|
|
||||||
LL | #[must_use]
|
LL | #[must_use]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to a struct field
|
error: `#[must_use]` has no effect when applied to a struct field
|
||||||
--> $DIR/unused_attributes-must_use.rs:129:28
|
--> $DIR/unused_attributes-must_use.rs:134:28
|
||||||
|
|
|
|
||||||
LL | let s = PatternField { #[must_use] foo: 123 };
|
LL | let s = PatternField { #[must_use] foo: 123 };
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to a pattern field
|
error: `#[must_use]` has no effect when applied to a pattern field
|
||||||
--> $DIR/unused_attributes-must_use.rs:130:24
|
--> $DIR/unused_attributes-must_use.rs:135:24
|
||||||
|
|
|
|
||||||
LL | let PatternField { #[must_use] foo } = s;
|
LL | let PatternField { #[must_use] foo } = s;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -129,6 +129,12 @@ error: `#[must_use]` has no effect when applied to an associated type
|
||||||
LL | #[must_use]
|
LL | #[must_use]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[must_use]` has no effect when applied to a provided trait method
|
||||||
|
--> $DIR/unused_attributes-must_use.rs:83:5
|
||||||
|
|
|
||||||
|
LL | #[must_use]
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[must_use]` has no effect when applied to a foreign static item
|
error: `#[must_use]` has no effect when applied to a foreign static item
|
||||||
--> $DIR/unused_attributes-must_use.rs:50:5
|
--> $DIR/unused_attributes-must_use.rs:50:5
|
||||||
|
|
|
|
||||||
|
@ -136,7 +142,7 @@ LL | #[must_use]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: unused `X` that must be used
|
error: unused `X` that must be used
|
||||||
--> $DIR/unused_attributes-must_use.rs:103:5
|
--> $DIR/unused_attributes-must_use.rs:108:5
|
||||||
|
|
|
|
||||||
LL | X;
|
LL | X;
|
||||||
| ^
|
| ^
|
||||||
|
@ -152,7 +158,7 @@ LL | let _ = X;
|
||||||
| +++++++
|
| +++++++
|
||||||
|
|
||||||
error: unused `Y` that must be used
|
error: unused `Y` that must be used
|
||||||
--> $DIR/unused_attributes-must_use.rs:104:5
|
--> $DIR/unused_attributes-must_use.rs:109:5
|
||||||
|
|
|
|
||||||
LL | Y::Z;
|
LL | Y::Z;
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
@ -163,7 +169,7 @@ LL | let _ = Y::Z;
|
||||||
| +++++++
|
| +++++++
|
||||||
|
|
||||||
error: unused `U` that must be used
|
error: unused `U` that must be used
|
||||||
--> $DIR/unused_attributes-must_use.rs:105:5
|
--> $DIR/unused_attributes-must_use.rs:110:5
|
||||||
|
|
|
|
||||||
LL | U { unit: () };
|
LL | U { unit: () };
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
@ -174,7 +180,7 @@ LL | let _ = U { unit: () };
|
||||||
| +++++++
|
| +++++++
|
||||||
|
|
||||||
error: unused return value of `U::method` that must be used
|
error: unused return value of `U::method` that must be used
|
||||||
--> $DIR/unused_attributes-must_use.rs:106:5
|
--> $DIR/unused_attributes-must_use.rs:111:5
|
||||||
|
|
|
|
||||||
LL | U::method();
|
LL | U::method();
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
@ -185,7 +191,7 @@ LL | let _ = U::method();
|
||||||
| +++++++
|
| +++++++
|
||||||
|
|
||||||
error: unused return value of `foo` that must be used
|
error: unused return value of `foo` that must be used
|
||||||
--> $DIR/unused_attributes-must_use.rs:107:5
|
--> $DIR/unused_attributes-must_use.rs:112:5
|
||||||
|
|
|
|
||||||
LL | foo();
|
LL | foo();
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
@ -196,7 +202,7 @@ LL | let _ = foo();
|
||||||
| +++++++
|
| +++++++
|
||||||
|
|
||||||
error: unused return value of `foreign_foo` that must be used
|
error: unused return value of `foreign_foo` that must be used
|
||||||
--> $DIR/unused_attributes-must_use.rs:110:9
|
--> $DIR/unused_attributes-must_use.rs:115:9
|
||||||
|
|
|
|
||||||
LL | foreign_foo();
|
LL | foreign_foo();
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
@ -207,7 +213,7 @@ LL | let _ = foreign_foo();
|
||||||
| +++++++
|
| +++++++
|
||||||
|
|
||||||
error: unused return value of `Use::get_four` that must be used
|
error: unused return value of `Use::get_four` that must be used
|
||||||
--> $DIR/unused_attributes-must_use.rs:118:5
|
--> $DIR/unused_attributes-must_use.rs:123:5
|
||||||
|
|
|
|
||||||
LL | ().get_four();
|
LL | ().get_four();
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
@ -217,5 +223,5 @@ help: use `let _ = ...` to ignore the resulting value
|
||||||
LL | let _ = ().get_four();
|
LL | let _ = ().get_four();
|
||||||
| +++++++
|
| +++++++
|
||||||
|
|
||||||
error: aborting due to 28 previous errors
|
error: aborting due to 29 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue