Merge pull request #264 from birkenfeld/fix2
lifetimes lint: walk type bounds as well as types (fixes #253, again)
This commit is contained in:
commit
994124521e
2 changed files with 47 additions and 13 deletions
|
@ -1,7 +1,7 @@
|
|||
use syntax::ast::*;
|
||||
use rustc::lint::*;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::visit::{Visitor, walk_ty};
|
||||
use syntax::visit::{Visitor, walk_ty, walk_ty_param_bound};
|
||||
use std::collections::HashSet;
|
||||
|
||||
use utils::{in_external_macro, span_lint};
|
||||
|
@ -68,14 +68,7 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>,
|
|||
// level of the current item.
|
||||
|
||||
// check named LTs
|
||||
let mut allowed_lts = HashSet::new();
|
||||
for lt in named_lts {
|
||||
if lt.bounds.is_empty() {
|
||||
allowed_lts.insert(Named(lt.lifetime.name));
|
||||
}
|
||||
}
|
||||
allowed_lts.insert(Unnamed);
|
||||
allowed_lts.insert(Static);
|
||||
let allowed_lts = allowed_lts_from(named_lts);
|
||||
|
||||
// these will collect all the lifetimes for references in arg/return types
|
||||
let mut input_visitor = RefVisitor(Vec::new());
|
||||
|
@ -142,6 +135,18 @@ fn could_use_elision(func: &FnDecl, slf: Option<&ExplicitSelf>,
|
|||
false
|
||||
}
|
||||
|
||||
fn allowed_lts_from(named_lts: &[LifetimeDef]) -> HashSet<RefLt> {
|
||||
let mut allowed_lts = HashSet::new();
|
||||
for lt in named_lts {
|
||||
if lt.bounds.is_empty() {
|
||||
allowed_lts.insert(Named(lt.lifetime.name));
|
||||
}
|
||||
}
|
||||
allowed_lts.insert(Unnamed);
|
||||
allowed_lts.insert(Static);
|
||||
allowed_lts
|
||||
}
|
||||
|
||||
/// Number of unique lifetimes in the given vector.
|
||||
fn unique_lifetimes(lts: &[RefLt]) -> usize {
|
||||
lts.iter().collect::<HashSet<_>>().len()
|
||||
|
@ -186,17 +191,34 @@ impl<'v> Visitor<'v> for RefVisitor {
|
|||
/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to
|
||||
/// reason about elision.
|
||||
fn has_where_lifetimes(where_clause: &WhereClause) -> bool {
|
||||
let mut where_visitor = RefVisitor(Vec::new());
|
||||
for predicate in &where_clause.predicates {
|
||||
match *predicate {
|
||||
WherePredicate::RegionPredicate(..) => return true,
|
||||
WherePredicate::BoundPredicate(ref pred) => {
|
||||
walk_ty(&mut where_visitor, &pred.bounded_ty);
|
||||
// a predicate like F: Trait or F: for<'a> Trait<'a>
|
||||
let mut visitor = RefVisitor(Vec::new());
|
||||
// walk the type F, it may not contain LT refs
|
||||
walk_ty(&mut visitor, &pred.bounded_ty);
|
||||
if !visitor.0.is_empty() { return true; }
|
||||
// if the bounds define new lifetimes, they are fine to occur
|
||||
let allowed_lts = allowed_lts_from(&pred.bound_lifetimes);
|
||||
// now walk the bounds
|
||||
for bound in pred.bounds.iter() {
|
||||
walk_ty_param_bound(&mut visitor, bound);
|
||||
}
|
||||
// and check that all lifetimes are allowed
|
||||
for lt in visitor.into_vec() {
|
||||
if !allowed_lts.contains(<) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
WherePredicate::EqPredicate(ref pred) => {
|
||||
walk_ty(&mut where_visitor, &pred.ty);
|
||||
let mut visitor = RefVisitor(Vec::new());
|
||||
walk_ty(&mut visitor, &pred.ty);
|
||||
if !visitor.0.is_empty() { return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
!where_visitor.into_vec().is_empty()
|
||||
false
|
||||
}
|
||||
|
|
|
@ -46,6 +46,18 @@ fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) { } // no error, bounde
|
|||
|
||||
fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) where 'b: 'a { } // no error, bounded lifetime
|
||||
|
||||
struct Lt<'a, I: 'static> {
|
||||
x: &'a I
|
||||
}
|
||||
|
||||
fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
||||
where F: Fn(Lt<'a, I>) -> Lt<'a, I> // no error, fn bound references 'a
|
||||
{ unreachable!() }
|
||||
|
||||
fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> //~ERROR explicit lifetimes given
|
||||
where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>
|
||||
{ unreachable!() }
|
||||
|
||||
struct X {
|
||||
x: u8,
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue