mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 15:11:30 +00:00
Add lint for unused lifetimes (fixes #459)
This commit is contained in:
parent
c4e9982dd7
commit
c7b87a06d2
5 changed files with 80 additions and 5 deletions
|
@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code.
|
||||||
[Jump to usage instructions](#usage)
|
[Jump to usage instructions](#usage)
|
||||||
|
|
||||||
##Lints
|
##Lints
|
||||||
There are 81 lints included in this crate:
|
There are 82 lints included in this crate:
|
||||||
|
|
||||||
name | default | meaning
|
name | default | meaning
|
||||||
---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -84,6 +84,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_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
|
[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_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
|
[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_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
|
[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
|
||||||
|
|
|
@ -154,6 +154,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||||
len_zero::LEN_WITHOUT_IS_EMPTY,
|
len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||||
len_zero::LEN_ZERO,
|
len_zero::LEN_ZERO,
|
||||||
lifetimes::NEEDLESS_LIFETIMES,
|
lifetimes::NEEDLESS_LIFETIMES,
|
||||||
|
lifetimes::UNUSED_LIFETIMES,
|
||||||
loops::EMPTY_LOOP,
|
loops::EMPTY_LOOP,
|
||||||
loops::EXPLICIT_COUNTER_LOOP,
|
loops::EXPLICIT_COUNTER_LOOP,
|
||||||
loops::EXPLICIT_ITER_LOOP,
|
loops::EXPLICIT_ITER_LOOP,
|
||||||
|
|
|
@ -2,9 +2,9 @@ use rustc_front::hir::*;
|
||||||
use reexport::*;
|
use reexport::*;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use syntax::codemap::Span;
|
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 rustc::middle::def::Def::{DefTy, DefTrait, DefStruct};
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashSet, HashMap};
|
||||||
|
|
||||||
use utils::{in_external_macro, span_lint};
|
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 \
|
"using explicit lifetimes for references in function arguments when elision rules \
|
||||||
would allow omitting them");
|
would allow omitting them");
|
||||||
|
|
||||||
|
declare_lint!(pub UNUSED_LIFETIMES, Warn,
|
||||||
|
"unused lifetimes in function definitions");
|
||||||
|
|
||||||
#[derive(Copy,Clone)]
|
#[derive(Copy,Clone)]
|
||||||
pub struct LifetimePass;
|
pub struct LifetimePass;
|
||||||
|
|
||||||
impl LintPass for LifetimePass {
|
impl LintPass for LifetimePass {
|
||||||
fn get_lints(&self) -> LintArray {
|
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,
|
span_lint(cx, NEEDLESS_LIFETIMES, span,
|
||||||
"explicit lifetimes given in parameter types where they could be elided");
|
"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>,
|
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
|
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)]
|
#![plugin(clippy)]
|
||||||
|
|
||||||
#![deny(needless_lifetimes)]
|
#![deny(needless_lifetimes)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code, unused_lifetimes)]
|
||||||
fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { }
|
fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) { }
|
||||||
//~^ERROR explicit lifetimes given
|
//~^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