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:
Ryan Cumming 2018-01-17 20:41:24 +11:00
parent 9a5f25aab3
commit 5f3c340bfb
6 changed files with 97 additions and 0 deletions

View file

@ -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

View 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),
);
}
}

View file

@ -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,

BIN
main Executable file

Binary file not shown.

View 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() {}

View 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)]
| ^^^^^^^^^^^^^^^^^