Check for unused lifetimes in bounds (fixes #489)

This commit is contained in:
Manish Goregaokar 2015-12-10 11:44:12 -05:00
parent b865e30b49
commit b9546599e3
2 changed files with 24 additions and 4 deletions

View file

@ -2,7 +2,7 @@ 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, walk_fn_decl}; use rustc_front::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics};
use rustc::middle::def::Def::{DefTy, DefTrait, DefStruct}; use rustc::middle::def::Def::{DefTy, DefTrait, DefStruct};
use std::collections::{HashSet, HashMap}; use std::collections::{HashSet, HashMap};
@ -64,7 +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); report_extra_lifetimes(cx, decl, &generics);
} }
fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>, fn could_use_elision(cx: &LateContext, func: &FnDecl, slf: Option<&ExplicitSelf>,
@ -276,12 +276,23 @@ impl<'v> Visitor<'v> for LifetimeChecker {
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
self.0.remove(&lifetime.name); self.0.remove(&lifetime.name);
} }
fn visit_lifetime_def(&mut self, _: &'v LifetimeDef) {
// don't actually visit `<'a>` or `<'a: 'b>`
// we've already visited the `'a` declarations and
// don't want to spuriously remove them
// `'b` in `'a: 'b` is useless unless used elsewhere in
// a non-lifetime bound
}
} }
fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl,
named_lts: &[LifetimeDef]) { generics: &Generics) {
let hs = named_lts.iter().map(|lt| (lt.lifetime.name, lt.lifetime.span)).collect(); let hs = generics.lifetimes.iter()
.map(|lt| (lt.lifetime.name, lt.lifetime.span))
.collect();
let mut checker = LifetimeChecker(hs); let mut checker = LifetimeChecker(hs);
walk_generics(&mut checker, generics);
walk_fn_decl(&mut checker, func); walk_fn_decl(&mut checker, func);
for (_, v) in checker.0 { for (_, v) in checker.0 {
span_lint(cx, UNUSED_LIFETIMES, v, span_lint(cx, UNUSED_LIFETIMES, v,

View file

@ -43,6 +43,15 @@ impl<'a> Foo<'a> for u8 {
} }
} }
// test for #489 (used lifetimes in bounds)
pub fn parse<'a, I: Iterator<Item=&'a str>>(_it: &mut I) {
unimplemented!()
}
pub fn parse2<'a, I>(_it: &mut I) where I: Iterator<Item=&'a str>{
unimplemented!()
}
fn main() { fn main() {
} }