[`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
--- /dev/null
+//! 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),
+ );
+ }
+}
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;
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);
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,
--- /dev/null
+
+
+
+#![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() {}
--- /dev/null
+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)]
+ | ^^^^^^^^^^^^^^^^^
+