Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Lint for trait methods without bodies
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
Showing
6 changed files
with
97 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)] | ||
| ^^^^^^^^^^^^^^^^^ | ||
|