Resolve conflicts produced by GenericArgs

Addresses the move/zip of Lifetimes and Types vectors from hir::PathParameters into the args vector of GenericArgs
This commit is contained in:
flip1995 2018-06-24 23:42:52 +02:00
parent d9a80d2f84
commit c83fd39e0e
No known key found for this signature in database
GPG key ID: 9F184E1164831181
9 changed files with 86 additions and 29 deletions

View file

@ -119,12 +119,15 @@ fn check_fn_inner<'a, 'tcx>(
.expect("a path must have at least one segment")
.args;
if let Some(ref params) = *params {
for bound in &params.lifetimes {
if bound.name.name() != "'static" && !bound.is_elided() {
return;
}
bounds_lts.push(bound);
}
params.args.iter().for_each(|param| match param {
GenericArg::Lifetime(bound) => {
if bound.name.name() != "'static" && !bound.is_elided() {
return;
}
bounds_lts.push(bound);
},
_ => {},
});
}
}
}
@ -233,9 +236,9 @@ fn could_use_elision<'a, 'tcx: 'a>(
fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet<RefLt> {
let mut allowed_lts = HashSet::new();
for par in named_generics.iter() {
if let GenericParam::Lifetime(ref lt) = *par {
if lt.bounds.is_empty() {
allowed_lts.insert(RefLt::Named(lt.lifetime.name.name()));
if let GenericParamKind::Lifetime { .. } = par.kind {
if par.bounds.is_empty() {
allowed_lts.insert(RefLt::Named(par.name.name()));
}
}
}
@ -299,7 +302,11 @@ impl<'v, 't> RefVisitor<'v, 't> {
fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) {
if let Some(ref last_path_segment) = last_path_segment(qpath).args {
if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() {
if !last_path_segment.parenthesized
&& !last_path_segment.args.iter().any(|arg| match arg {
GenericArg::Lifetime(_) => true,
GenericArg::Type(_) => false,
}) {
let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id);
match self.cx.tables.qpath_def(qpath, hir_id) {
Def::TyAlias(def_id) | Def::Struct(def_id) => {
@ -431,9 +438,11 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
}
fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) {
let hs = generics
.lifetimes()
.map(|lt| (lt.lifetime.name.name(), lt.lifetime.span))
let hs = generics.params.iter()
.filter_map(|par| match par.kind {
GenericParamKind::Lifetime { .. } => Some((par.name.name(), par.span)),
_ => None,
})
.collect();
let mut checker = LifetimeChecker { map: hs };

View file

@ -2101,8 +2101,14 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener
if params.parenthesized {
false
} else {
params.types.len() == 1
&& (is_self_ty(&params.types[0]) || is_ty(&*params.types[0], self_ty))
// FIXME(flip1995): messy, improve if there is a better option
// in the compiler
let types: Vec<_> = params.args.iter().filter_map(|arg| match arg {
hir::GenericArg::Type(ty) => Some(ty),
_ => None,
}).collect();
types.len() == 1
&& (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty))
}
} else {
false

View file

@ -219,7 +219,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
if let Some(elem_ty) = path.segments.iter()
.find(|seg| seg.name == "Vec")
.and_then(|ps| ps.args.as_ref())
.map(|params| &params.types[0]);
.map(|params| params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
}).unwrap());
then {
let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_"));
db.span_suggestion(input.span,

View file

@ -161,9 +161,14 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
if_chain! {
if let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node;
if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
if parameters.types.len() == 1;
then {
ty_snippet = snippet_opt(cx, parameters.types[0].span);
let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
_ => None,
}).collect();
if types.len() == 1 {
ty_snippet = snippet_opt(cx, types[0].span);
}
}
};
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
@ -220,7 +225,8 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
if let [ref bx] = *pp.segments;
if let Some(ref params) = bx.args;
if !params.parenthesized;
if let [ref inner] = *params.types;
if let [ref inner] = *params.args;
if let GenericArg::Type(inner) = inner;
then {
let replacement = snippet_opt(cx, inner.span);
if let Some(r) = replacement {

View file

@ -457,7 +457,10 @@ fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String {
if_chain! {
if let Some(ref params) = seg.args;
if !params.parenthesized;
if let Some(to_ty) = params.types.get(1);
if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
}).nth(1);
if let TyRptr(_, ref to_ty) = to_ty.node;
then {
return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string();

View file

@ -182,7 +182,10 @@ fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool
if_chain! {
if let Some(ref params) = last.args;
if !params.parenthesized;
if let Some(ty) = params.types.get(0);
if let Some(ty) = params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
});
if let TyPath(ref qpath) = ty.node;
if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(ty.id)));
if match_def_path(cx.tcx, did, path);
@ -246,7 +249,11 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) {
for ty in p.segments.iter().flat_map(|seg| {
seg.args
.as_ref()
.map_or_else(|| [].iter(), |params| params.types.iter())
.map_or_else(|| [].iter(), |params| params.args.iter())
.filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
})
}) {
check_ty(cx, ty, is_local);
}
@ -254,14 +261,21 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) {
QPath::Resolved(None, ref p) => for ty in p.segments.iter().flat_map(|seg| {
seg.args
.as_ref()
.map_or_else(|| [].iter(), |params| params.types.iter())
.map_or_else(|| [].iter(), |params| params.args.iter())
.filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
})
}) {
check_ty(cx, ty, is_local);
},
QPath::TypeRelative(ref ty, ref seg) => {
check_ty(cx, ty, is_local);
if let Some(ref params) = seg.args {
for ty in params.types.iter() {
for ty in params.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
}) {
check_ty(cx, ty, is_local);
}
}
@ -290,7 +304,8 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti
if let [ref bx] = *path.segments;
if let Some(ref params) = bx.args;
if !params.parenthesized;
if let [ref inner] = *params.types;
if let [ref inner] = *params.args;
if let GenericArg::Type(inner) = inner;
then {
if is_any_trait(inner) {
// Ignore `Box<Any>` types, see #1884 for details.
@ -1862,7 +1877,11 @@ impl<'tcx> ImplicitHasherType<'tcx> {
/// Checks that `ty` is a target type without a BuildHasher.
fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option<Self> {
if let TyPath(QPath::Resolved(None, ref path)) = hir_ty.node {
let params = &path.segments.last().as_ref()?.args.as_ref()?.types;
let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()?
.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
}).collect();
let params_len = params.len();
let ty = hir_ty_to_ty(cx.tcx, hir_ty);

View file

@ -60,7 +60,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf {
then {
let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
let should_check = if let Some(ref params) = *parameters {
!params.parenthesized && params.lifetimes.len() == 0
!params.parenthesized && !params.args.iter().any(|arg| match arg {
GenericArg::Lifetime(_) => true,
GenericArg::Type(_) => false,
})
} else {
true
};

View file

@ -152,6 +152,14 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr)
}
fn eq_generic_arg(&mut self, left: &GenericArg, right: &GenericArg) -> bool {
match (left, right) {
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => self.eq_lifetime(l_lt, r_lt),
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
_ => false,
}
}
fn eq_lifetime(&mut self, left: &Lifetime, right: &Lifetime) -> bool {
left.name == right.name
}
@ -203,8 +211,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
fn eq_path_parameters(&mut self, left: &GenericArgs, right: &GenericArgs) -> bool {
if !(left.parenthesized || right.parenthesized) {
over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r))
&& over(&left.types, &right.types, |l, r| self.eq_ty(l, r))
over(&left.args, &right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work
&& over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r))
} else if left.parenthesized && right.parenthesized {
over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r))

View file

@ -100,6 +100,7 @@ impl<'a> Sugg<'a> {
ast::ExprKind::ObsoleteInPlace(..) |
ast::ExprKind::Unary(..) |
ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
ast::ExprKind::Async(..) |
ast::ExprKind::Block(..) |
ast::ExprKind::Break(..) |
ast::ExprKind::Call(..) |