mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
Merge pull request #483 from Manishearth/bored
Add lint for unused lifetimes (fixes #459)
This commit is contained in:
commit
3260b501a2
5 changed files with 79 additions and 4 deletions
|
@ -85,6 +85,7 @@ name
|
|||
[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729
|
||||
[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729
|
||||
[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop
|
||||
[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions
|
||||
[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types
|
||||
[while_let_loop](https://github.com/Manishearth/rust-clippy/wiki#while_let_loop) | warn | `loop { if let { ... } else break }` can be written as a `while let` loop
|
||||
[while_let_on_iterator](https://github.com/Manishearth/rust-clippy/wiki#while_let_on_iterator) | warn | using a while-let loop instead of a for loop on an iterator
|
||||
|
|
|
@ -156,6 +156,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||
len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||
len_zero::LEN_ZERO,
|
||||
lifetimes::NEEDLESS_LIFETIMES,
|
||||
lifetimes::UNUSED_LIFETIMES,
|
||||
loops::EMPTY_LOOP,
|
||||
loops::EXPLICIT_COUNTER_LOOP,
|
||||
loops::EXPLICIT_ITER_LOOP,
|
||||
|
|
|
@ -2,9 +2,9 @@ use rustc_front::hir::*;
|
|||
use reexport::*;
|
||||
use rustc::lint::*;
|
||||
use syntax::codemap::Span;
|
||||
use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound};
|
||||
use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl};
|
||||
use rustc::middle::def::Def::{DefTy, DefTrait, DefStruct};
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashSet, HashMap};
|
||||
|
||||
use utils::{in_external_macro, span_lint};
|
||||
|
||||
|
@ -12,12 +12,15 @@ declare_lint!(pub NEEDLESS_LIFETIMES, Warn,
|
|||
"using explicit lifetimes for references in function arguments when elision rules \
|
||||
would allow omitting them");
|
||||
|
||||
declare_lint!(pub UNUSED_LIFETIMES, Warn,
|
||||
"unused lifetimes in function definitions");
|
||||
|
||||
#[derive(Copy,Clone)]
|
||||
pub struct LifetimePass;
|
||||
|
||||
impl LintPass for LifetimePass {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(NEEDLESS_LIFETIMES)
|
||||
lint_array!(NEEDLESS_LIFETIMES, UNUSED_LIFETIMES)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,6 +64,7 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, slf: Option<&ExplicitSelf>,
|
|||
span_lint(cx, NEEDLESS_LIFETIMES, span,
|
||||
"explicit lifetimes given in parameter types where they could be elided");
|
||||
}
|
||||
report_extra_lifetimes(cx, decl, &generics.lifetimes);
|
||||
}
|
||||
|
||||
fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>,
|
||||
|
@ -263,3 +267,24 @@ fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool {
|
|||
}
|
||||
false
|
||||
}
|
||||
|
||||
struct LifetimeChecker(HashMap<Name, Span>);
|
||||
|
||||
impl<'v> Visitor<'v> for LifetimeChecker {
|
||||
|
||||
// for lifetimes as parameters of generics
|
||||
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
||||
self.0.remove(&lifetime.name);
|
||||
}
|
||||
}
|
||||
|
||||
fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl,
|
||||
named_lts: &[LifetimeDef]) {
|
||||
let hs = named_lts.iter().map(|lt| (lt.lifetime.name, lt.lifetime.span)).collect();
|
||||
let mut checker = LifetimeChecker(hs);
|
||||
walk_fn_decl(&mut checker, func);
|
||||
for (_, v) in checker.0 {
|
||||
span_lint(cx, UNUSED_LIFETIMES, v,
|
||||
"this lifetime isn't used in the function definition");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#![plugin(clippy)]
|
||||
|
||||
#![deny(needless_lifetimes)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, unused_lifetimes)]
|
||||
fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { }
|
||||
//~^ERROR explicit lifetimes given
|
||||
|
||||
|
|
48
tests/compile-fail/unused_lt.rs
Normal file
48
tests/compile-fail/unused_lt.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
#![feature(plugin)]
|
||||
#![plugin(clippy)]
|
||||
#![allow(unused, dead_code, needless_lifetimes)]
|
||||
#![deny(unused_lifetimes)]
|
||||
|
||||
fn empty() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn used_lt<'a>(x: &'a u8) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn unused_lt<'a>(x: u8) { //~ ERROR this lifetime
|
||||
|
||||
}
|
||||
|
||||
fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { //~ ERROR this lifetime
|
||||
// 'a is useless here since it's not directly bound
|
||||
}
|
||||
|
||||
fn lt_return<'a, 'b: 'a>(x: &'b u8) -> &'a u8 {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn lt_return_only<'a>() -> &'a u8 {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn unused_lt_blergh<'a>(x: Option<Box<Send+'a>>) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
trait Foo<'a> {
|
||||
fn x(&self, a: &'a u8);
|
||||
}
|
||||
|
||||
impl<'a> Foo<'a> for u8 {
|
||||
fn x(&self, a: &'a u8) {
|
||||
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
|
||||
}
|
Loading…
Reference in a new issue