Lint for trait methods without bodies
As discussed in rust-lang/rust#47475 the #[inline] attribute is currently allowed on trait methods without bodies (i.e. without a default implementation). This is misleading as it could be interpreted as affecting the implementations of the trait method. Add a lint for any use of #[inline] on a trait method without a body. Fixes rust-lang/rust#47475
This commit is contained in:
parent
9a5f25aab3
commit
5f3c340bfb
@ -583,6 +583,7 @@ All notable changes to this project will be documented in this file.
|
||||
[`ineffective_bit_mask`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#ineffective_bit_mask
|
||||
[`infinite_iter`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#infinite_iter
|
||||
[`inline_always`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_always
|
||||
[`inline_fn_without_body`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#inline_fn_without_body
|
||||
[`int_plus_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#int_plus_one
|
||||
[`integer_arithmetic`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#integer_arithmetic
|
||||
[`invalid_ref`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#invalid_ref
|
||||
|
61
clippy_lints/src/inline_fn_without_body.rs
Normal file
61
clippy_lints/src/inline_fn_without_body.rs
Normal file
@ -0,0 +1,61 @@
|
||||
//! checks for `#[inline]` on trait methods without bodies
|
||||
|
||||
use rustc::lint::*;
|
||||
use rustc::hir::*;
|
||||
use syntax::ast::{Attribute, Name};
|
||||
use utils::span_lint;
|
||||
|
||||
/// **What it does:** Checks for `#[inline]` on trait methods without bodies
|
||||
///
|
||||
/// **Why is this bad?** Only implementations of trait methods may be inlined.
|
||||
/// The inline attribute is ignored for trait methods without bodies.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// trait Animal {
|
||||
/// #[inline]
|
||||
/// fn name(&self) -> &'static str;
|
||||
/// }
|
||||
/// ```
|
||||
declare_lint! {
|
||||
pub INLINE_FN_WITHOUT_BODY,
|
||||
Warn,
|
||||
"use of `#[inline]` on trait methods without bodies"
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Pass;
|
||||
|
||||
impl LintPass for Pass {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(INLINE_FN_WITHOUT_BODY)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
|
||||
match item.node {
|
||||
TraitItemKind::Method(_, TraitMethod::Required(_)) => {
|
||||
check_attrs(cx, &item.name, &item.attrs);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_attrs(cx: &LateContext, name: &Name, attrs: &[Attribute]) {
|
||||
for attr in attrs {
|
||||
if attr.name().map_or(true, |n| n != "inline") {
|
||||
continue;
|
||||
}
|
||||
|
||||
span_lint(
|
||||
cx,
|
||||
INLINE_FN_WITHOUT_BODY,
|
||||
attr.span,
|
||||
&format!("use of `#[inline]` on trait method `{}` which has no body", name),
|
||||
);
|
||||
}
|
||||
}
|
@ -109,6 +109,7 @@ pub mod identity_op;
|
||||
pub mod if_let_redundant_pattern_matching;
|
||||
pub mod if_not_else;
|
||||
pub mod infinite_iter;
|
||||
pub mod inline_fn_without_body;
|
||||
pub mod int_plus_one;
|
||||
pub mod invalid_ref;
|
||||
pub mod is_unit_expr;
|
||||
@ -359,6 +360,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||
reg.register_late_lint_pass(box use_self::UseSelf);
|
||||
reg.register_late_lint_pass(box bytecount::ByteCount);
|
||||
reg.register_late_lint_pass(box infinite_iter::Pass);
|
||||
reg.register_late_lint_pass(box inline_fn_without_body::Pass);
|
||||
reg.register_late_lint_pass(box invalid_ref::InvalidRef);
|
||||
reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default());
|
||||
reg.register_late_lint_pass(box types::ImplicitHasher);
|
||||
@ -477,6 +479,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
||||
identity_op::IDENTITY_OP,
|
||||
if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING,
|
||||
infinite_iter::INFINITE_ITER,
|
||||
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
|
||||
invalid_ref::INVALID_REF,
|
||||
is_unit_expr::UNIT_EXPR,
|
||||
large_enum_variant::LARGE_ENUM_VARIANT,
|
||||
|
18
tests/ui/inline_fn_without_body.rs
Normal file
18
tests/ui/inline_fn_without_body.rs
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
|
||||
#![warn(inline_fn_without_body)]
|
||||
#![allow(inline_always)]
|
||||
trait Foo {
|
||||
#[inline]
|
||||
fn default_inline();
|
||||
|
||||
#[inline(always)]
|
||||
fn always_inline();
|
||||
|
||||
#[inline]
|
||||
fn has_body() {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
14
tests/ui/inline_fn_without_body.stderr
Normal file
14
tests/ui/inline_fn_without_body.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: use of `#[inline]` on trait method `default_inline` which has no body
|
||||
--> $DIR/inline_fn_without_body.rs:7:5
|
||||
|
|
||||
7 | #[inline]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `-D inline-fn-without-body` implied by `-D warnings`
|
||||
|
||||
error: use of `#[inline]` on trait method `always_inline` which has no body
|
||||
--> $DIR/inline_fn_without_body.rs:10:5
|
||||
|
|
||||
10 | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
Loading…
Reference in New Issue
Block a user