Skip to content

Commit

Permalink
Lint for trait methods without bodies
Browse files Browse the repository at this point in the history
As discussed in #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 #47475
  • Loading branch information
etaoins committed Jan 18, 2018
1 parent 9a5f25a commit 5f3c340
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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
Expand Down
61 changes: 61 additions & 0 deletions clippy_lints/src/inline_fn_without_body.rs
@@ -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),
);
}
}
3 changes: 3 additions & 0 deletions clippy_lints/src/lib.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
Binary file added main
Binary file not shown.
18 changes: 18 additions & 0 deletions tests/ui/inline_fn_without_body.rs
@@ -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 changes: 14 additions & 0 deletions tests/ui/inline_fn_without_body.stderr
@@ -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)]
| ^^^^^^^^^^^^^^^^^

0 comments on commit 5f3c340

Please sign in to comment.