From c83fd39e0e4a8e9262fc31823303df7bcb522720 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Sun, 24 Jun 2018 23:42:52 +0200 Subject: [PATCH] Resolve conflicts produced by GenericArgs Addresses the move/zip of Lifetimes and Types vectors from hir::PathParameters into the args vector of GenericArgs --- clippy_lints/src/lifetimes.rs | 35 ++++++++++++++-------- clippy_lints/src/methods.rs | 10 +++++-- clippy_lints/src/needless_pass_by_value.rs | 5 +++- clippy_lints/src/ptr.rs | 12 ++++++-- clippy_lints/src/transmute.rs | 5 +++- clippy_lints/src/types.rs | 31 +++++++++++++++---- clippy_lints/src/use_self.rs | 5 +++- clippy_lints/src/utils/hir_utils.rs | 11 +++++-- clippy_lints/src/utils/sugg.rs | 1 + 9 files changed, 86 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index b0fd62089ba4..7e22fda4006c 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -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 ¶ms.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 { 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 }; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 2fe56bcdce15..b5e1780fd0ca 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -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(¶ms.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 diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 7a250f93db59..03a45bc18472 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -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| ¶ms.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, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index fcd56c28218f..78a07eddd4e2 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -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 { diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 2b27ed22c472..c2e981979a18 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -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(); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 70625724040d..ee5611a50a14 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -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` 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 { 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); diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 035471e45202..170db6ceabb6 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -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 }; diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 1cfb5a82f72d..ee6b004dc6cb 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -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)) diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 9482cc6bc0ef..eb2197a5891e 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -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(..) |