Merge pull request #2871 from flip1995/gen_gen_nightly

The Great Generics Generalisation: Clippy edition
This commit is contained in:
Oliver Schneider 2018-06-25 18:14:48 +02:00 committed by GitHub
commit d4618e0879
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 179 additions and 104 deletions

View File

@ -207,7 +207,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
}
fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool {
if let ItemFn(_, _, _, _, _, eid) = item.node {
if let ItemFn(_, _, _, eid) = item.node {
is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
} else {
true

View File

@ -124,7 +124,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprAgain(_) | ExprBreak(_, _) | ExprRet(_) => self.report_diverging_sub_expr(e),
ExprContinue(_) | ExprBreak(_, _) | ExprRet(_) => self.report_diverging_sub_expr(e),
ExprCall(ref func, _) => {
let typ = self.cx.tables.expr_ty(func);
match typ.sty {

View File

@ -92,8 +92,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
};
let unsafety = match kind {
hir::intravisit::FnKind::ItemFn(_, _, unsafety, _, _, _, _) => unsafety,
hir::intravisit::FnKind::Method(_, sig, _, _) => sig.unsafety,
hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _, _) => unsafety,
hir::intravisit::FnKind::Method(_, sig, _, _) => sig.header.unsafety,
hir::intravisit::FnKind::Closure(_) => return,
};
@ -101,8 +101,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
if !is_impl {
// don't lint extern functions decls, it's not their fault either
match kind {
hir::intravisit::FnKind::Method(_, &hir::MethodSig { abi: Abi::Rust, .. }, _, _) |
hir::intravisit::FnKind::ItemFn(_, _, _, _, Abi::Rust, _, _) => self.check_arg_number(cx, decl, span),
hir::intravisit::FnKind::Method(_, &hir::MethodSig { header: hir::FnHeader { abi: Abi::Rust, .. }, .. }, _, _) |
hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => self.check_arg_number(cx, decl, span),
_ => {},
}
}
@ -113,13 +113,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
if let hir::TraitItemKind::Method(ref sig, ref eid) = item.node {
// don't lint extern functions decls, it's not their fault
if sig.abi == Abi::Rust {
if sig.header.abi == Abi::Rust {
self.check_arg_number(cx, &sig.decl, item.span);
}
if let hir::TraitMethod::Provided(eid) = *eid {
let body = cx.tcx.hir.body(eid);
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, body, item.id);
self.check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.id);
}
}
}

View File

@ -59,7 +59,7 @@ impl LintPass for LifetimePass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(ref decl, _, _, _, ref generics, id) = item.node {
if let ItemFn(ref decl, _, ref generics, id) = item.node {
check_fn_inner(cx, decl, Some(id), generics, item.span);
}
}
@ -101,23 +101,31 @@ fn check_fn_inner<'a, 'tcx>(
}
let mut bounds_lts = Vec::new();
for typ in generics.ty_params() {
let types = generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Type { .. } => Some(param),
GenericParamKind::Lifetime { .. } => None,
});
for typ in types {
for bound in &typ.bounds {
let mut visitor = RefVisitor::new(cx);
walk_ty_param_bound(&mut visitor, bound);
walk_param_bound(&mut visitor, bound);
if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
return;
}
if let TraitTyParamBound(ref trait_ref, _) = *bound {
if let GenericBound::Trait(ref trait_ref, _) = *bound {
let params = &trait_ref
.trait_ref
.path
.segments
.last()
.expect("a path must have at least one segment")
.parameters;
.args;
if let Some(ref params) = *params {
for bound in &params.lifetimes {
let lifetimes = params.args.iter().filter_map(|arg| match arg {
GenericArg::Lifetime(lt) => Some(lt),
GenericArg::Type(_) => None,
});
for bound in lifetimes {
if bound.name.name() != "'static" && !bound.is_elided() {
return;
}
@ -230,9 +238,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()));
}
}
}
@ -295,8 +303,12 @@ 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).parameters {
if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() {
if let Some(ref last_path_segment) = last_path_segment(qpath).args {
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) => {
@ -335,7 +347,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
TyImplTraitExistential(exist_ty_id, _, _) => {
if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(exist_ty_id.id).node {
for bound in &exist_ty.bounds {
if let RegionTyParamBound(_) = *bound {
if let GenericBound::Outlives(_) = *bound {
self.record(&None);
}
}
@ -377,7 +389,7 @@ fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: &
let allowed_lts = allowed_lts_from(&pred.bound_generic_params);
// now walk the bounds
for bound in pred.bounds.iter() {
walk_ty_param_bound(&mut visitor, bound);
walk_param_bound(&mut visitor, bound);
}
// and check that all lifetimes are allowed
match visitor.into_vec() {
@ -418,7 +430,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
// don't want to spuriously remove them
// `'b` in `'a: 'b` is useless unless used elsewhere in
// a non-lifetime bound
if param.is_type_param() {
if let GenericParamKind::Type { .. } = param.kind {
walk_generic_param(self, param)
}
}
@ -428,9 +440,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

@ -640,7 +640,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult {
}
},
ExprBlock(ref b, _) => never_loop_block(b, main_loop_id),
ExprAgain(d) => {
ExprContinue(d) => {
let id = d.target_id
.expect("target id can only be missing in the presence of compilation errors");
if id == main_loop_id {

View File

@ -104,7 +104,7 @@ fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
let arg_segment = [
PathSegment {
name: id,
parameters: None,
args: None,
infer_types: true,
},
];

View File

@ -7,7 +7,7 @@ use std::fmt;
use std::iter;
use syntax::ast;
use syntax::codemap::{Span, BytePos};
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self,
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self,
is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method,
match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet,
span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
@ -336,7 +336,7 @@ declare_clippy_lint! {
///
/// **Known problems:** If the function has side-effects, not calling it will
/// change the semantic of the program, but you shouldn't rely on that anyway.
///
///
/// **Example:**
/// ```rust
/// foo.expect(&format("Err {}: {}", err_code, err_msg))
@ -1020,7 +1020,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
}
}
};
snippet(cx, a.span, "..").into_owned()
}
@ -1077,7 +1077,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
}
let sugg: Cow<_> = snippet(cx, arg.span, "..");
span_lint_and_sugg(
cx,
EXPECT_FUN_CALL,
@ -2091,26 +2091,35 @@ impl SelfKind {
fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool {
single_segment_ty(ty).map_or(false, |seg| {
generics.ty_params().any(|param| {
param.name == seg.name && param.bounds.iter().any(|bound| {
if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound {
let path = &ptr.trait_ref.path;
match_path(path, name) && path.segments.last().map_or(false, |s| {
if let Some(ref params) = s.parameters {
if params.parenthesized {
false
generics.params.iter().any(|param| match param.kind {
hir::GenericParamKind::Type { .. } => {
param.name.name() == seg.name && param.bounds.iter().any(|bound| {
if let hir::GenericBound::Trait(ref ptr, ..) = *bound {
let path = &ptr.trait_ref.path;
match_path(path, name) && path.segments.last().map_or(false, |s| {
if let Some(ref params) = s.args {
if params.parenthesized {
false
} else {
// 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 {
params.types.len() == 1
&& (is_self_ty(&params.types[0]) || is_ty(&*params.types[0], self_ty))
false
}
} else {
false
}
})
} else {
false
}
})
})
} else {
false
}
})
},
_ => false,
})
})
}

View File

@ -558,7 +558,7 @@ fn in_attributes_expansion(expr: &Expr) -> bool {
.ctxt()
.outer()
.expn_info()
.map_or(false, |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_)))
.map_or(false, |info| matches!(info.format, ExpnFormat::MacroAttribute(_)))
}
/// Test whether `def` is a variable defined outside a macro.

View File

@ -189,13 +189,13 @@ impl LintPass for MiscEarly {
impl EarlyLintPass for MiscEarly {
fn check_generics(&mut self, cx: &EarlyContext, gen: &Generics) {
for param in &gen.params {
if let GenericParam::Type(ref ty) = *param {
let name = ty.ident.name.as_str();
if let GenericParamKind::Type { .. } = param.kind {
let name = param.ident.name.as_str();
if constants::BUILTIN_TYPES.contains(&&*name) {
span_lint(
cx,
BUILTIN_TYPE_SHADOW,
ty.ident.span,
param.ident.span,
&format!("This generic shadows the built-in type `{}`", name),
);
}
@ -296,7 +296,7 @@ impl EarlyLintPass for MiscEarly {
}
match expr.node {
ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node {
if let ExprKind::Closure(_, _, ref decl, ref block, _) = closure.node {
if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node {
span_lint_and_then(
cx,
REDUNDANT_CLOSURE_CALL,
@ -327,7 +327,7 @@ impl EarlyLintPass for MiscEarly {
if_chain! {
if let StmtKind::Local(ref local) = w[0].node;
if let Option::Some(ref t) = local.init;
if let ExprKind::Closure(_, _, _, _, _) = t.node;
if let ExprKind::Closure(..) = t.node;
if let PatKind::Ident(_, ident, _) = local.pat.node;
if let StmtKind::Semi(ref second) = w[1].node;
if let ExprKind::Assign(_, ref call) = second.node;

View File

@ -72,8 +72,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
}
match kind {
FnKind::ItemFn(.., abi, _, attrs) => {
if abi != Abi::Rust {
FnKind::ItemFn(.., header, _, attrs) => {
if header.abi != Abi::Rust {
return;
}
for a in attrs {
@ -218,8 +218,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
if let TyPath(QPath::Resolved(_, ref path)) = input.node;
if let Some(elem_ty) = path.segments.iter()
.find(|seg| seg.name == "Vec")
.and_then(|ps| ps.parameters.as_ref())
.map(|params| &params.types[0]);
.and_then(|ps| ps.args.as_ref())
.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

@ -99,11 +99,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
let name = impl_item.name;
let id = impl_item.id;
if sig.constness == hir::Constness::Const {
if sig.header.constness == hir::Constness::Const {
// can't be implemented by default
return;
}
if impl_item.generics.params.iter().any(|gen| gen.is_type_param()) {
if impl_item.generics.params.iter().any(|gen| match gen.kind {
hir::GenericParamKind::Type { .. } => true,
_ => false
}) {
// when the result of `new()` depends on a type parameter we should not require
// an
// impl of `Default`

View File

@ -312,7 +312,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
impl EarlyLintPass for NonExpressiveNames {
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
if let ItemKind::Fn(ref decl, _, _, _, _, ref blk) = item.node {
if let ItemKind::Fn(ref decl, _, _, ref blk) = item.node {
do_check(self, cx, &item.attrs, decl, blk);
}
}

View File

@ -103,7 +103,7 @@ impl LintPass for PointerPass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(ref decl, _, _, _, _, body_id) = item.node {
if let ItemFn(ref decl, _, _, body_id) = item.node {
check_fn(cx, decl, item.id, Some(body_id));
}
}
@ -160,10 +160,15 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
let mut ty_snippet = None;
if_chain! {
if let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node;
if let Some(&PathSegment{parameters: Some(ref parameters), ..}) = path.segments.last();
if parameters.types.len() == 1;
if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
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()")]) {
@ -218,9 +223,12 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
if let TyPath(ref path) = ty.node;
if let QPath::Resolved(None, ref pp) = *path;
if let [ref bx] = *pp.segments;
if let Some(ref params) = bx.parameters;
if let Some(ref params) = bx.args;
if !params.parenthesized;
if let [ref inner] = *params.types;
if let Some(inner) = params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
});
then {
let replacement = snippet_opt(cx, inner.span);
if let Some(r) = replacement {

View File

@ -455,9 +455,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String {
let seg = last_path_segment(path);
if_chain! {
if let Some(ref params) = seg.parameters;
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

@ -84,8 +84,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
}
match kind {
FnKind::ItemFn(.., abi, _, attrs) => {
if abi != Abi::Rust {
FnKind::ItemFn(.., header, _, attrs) => {
if header.abi != Abi::Rust {
return;
}
for a in attrs {

View File

@ -180,9 +180,12 @@ fn check_fn_decl(cx: &LateContext, decl: &FnDecl) {
fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool {
let last = last_path_segment(qpath);
if_chain! {
if let Some(ref params) = last.parameters;
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);
@ -244,24 +247,35 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) {
QPath::Resolved(Some(ref ty), ref p) => {
check_ty(cx, ty, is_local);
for ty in p.segments.iter().flat_map(|seg| {
seg.parameters
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::Resolved(None, ref p) => for ty in p.segments.iter().flat_map(|seg| {
seg.parameters
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.parameters {
for ty in params.types.iter() {
if let Some(ref params) = seg.args {
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);
}
}
@ -288,9 +302,12 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti
if Some(def_id) == cx.tcx.lang_items().owned_box();
if let QPath::Resolved(None, ref path) = *qpath;
if let [ref bx] = *path.segments;
if let Some(ref params) = bx.parameters;
if let Some(ref params) = bx.args;
if !params.parenthesized;
if let [ref inner] = *params.types;
if let Some(inner) = params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
});
then {
if is_any_trait(inner) {
// Ignore `Box<Any>` types, see #1884 for details.
@ -1208,7 +1225,10 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
TyTraitObject(ref param_bounds, _) => {
let has_lifetime_parameters = param_bounds
.iter()
.any(|bound| bound.bound_generic_params.iter().any(|gen| gen.is_lifetime_param()));
.any(|bound| bound.bound_generic_params.iter().any(|gen| match gen.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
}));
if has_lifetime_parameters {
// complex trait bounds like A<'a, 'b>
(50 * self.nest, 1)
@ -1859,7 +1879,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()?.parameters.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

@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel {
impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
match expr.node {
hir::ExprBreak(destination, _) | hir::ExprAgain(destination) => if let Some(label) = destination.label {
hir::ExprBreak(destination, _) | hir::ExprContinue(destination) => if let Some(label) = destination.label {
self.labels.remove(&label.name.as_str());
},
hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => {

View File

@ -58,9 +58,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf {
if let ItemImpl(.., ref item_type, ref refs) = item.node;
if let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node;
then {
let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters;
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

@ -432,7 +432,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
}
// FIXME: implement label printing
},
Expr_::ExprAgain(ref _destination) => {
Expr_::ExprContinue(ref _destination) => {
let destination_pat = self.next("destination");
println!("Again(ref {}) = {};", destination_pat, current);
// FIXME: implement label printing

View File

@ -76,7 +76,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
match (&left.node, &right.node) {
(&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re),
(&ExprAgain(li), &ExprAgain(ri)) => {
(&ExprContinue(li), &ExprContinue(ri)) => {
both(&li.label, &ri.label, |l, r| l.name.as_str() == r.name.as_str())
},
(&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr),
@ -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
}
@ -201,10 +209,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
&& over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r))
}
fn eq_path_parameters(&mut self, left: &PathParameters, right: &PathParameters) -> bool {
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))
@ -224,7 +231,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
if left.name.as_str() != right.name.as_str() {
return false;
}
match (&left.parameters, &right.parameters) {
match (&left.args, &right.args) {
(&None, &None) => true,
(&Some(ref l), &Some(ref r)) => self.eq_path_parameters(l, r),
_ => false,
@ -345,8 +352,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
m.hash(&mut self.s);
self.hash_expr(e);
},
ExprAgain(i) => {
let c: fn(_) -> _ = ExprAgain;
ExprContinue(i) => {
let c: fn(_) -> _ = ExprContinue;
c.hash(&mut self.s);
if let Some(i) = i.label {
self.hash_name(i.name);

View File

@ -300,7 +300,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
print_expr(cx, e, indent + 1);
}
},
hir::ExprAgain(_) => println!("{}Again", ind),
hir::ExprContinue(_) => println!("{}Again", ind),
hir::ExprRet(ref e) => {
println!("{}Ret", ind);
if let Some(ref e) = *e {

View File

@ -57,7 +57,7 @@ pub fn in_constant(cx: &LateContext, id: NodeId) -> bool {
/// Returns true if this `expn_info` was expanded by any macro.
pub fn in_macro(span: Span) -> bool {
span.ctxt().outer().expn_info().map_or(false, |info| {
match info.callee.format {
match info.format {
// don't treat range expressions desugared to structs as "in_macro"
ExpnFormat::CompilerDesugaring(kind) => kind != CompilerDesugaringKind::DotFill,
_ => true,
@ -68,7 +68,7 @@ pub fn in_macro(span: Span) -> bool {
/// Returns true if `expn_info` was expanded by range expressions.
pub fn is_range_expression(span: Span) -> bool {
span.ctxt().outer().expn_info().map_or(false, |info| {
match info.callee.format {
match info.format {
ExpnFormat::CompilerDesugaring(CompilerDesugaringKind::DotFill) => true,
_ => false,
}
@ -84,12 +84,12 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool {
/// this after other checks have already happened.
fn in_macro_ext<'a, T: LintContext<'a>>(cx: &T, info: &ExpnInfo) -> bool {
// no ExpnInfo = no macro
if let ExpnFormat::MacroAttribute(..) = info.callee.format {
if let ExpnFormat::MacroAttribute(..) = info.format {
// these are all plugins
return true;
}
// no span for the callee = external macro
info.callee.span.map_or(true, |span| {
info.def_site.map_or(true, |span| {
// no snippet = external macro or compiler-builtin expansion
cx.sess()
.codemap()
@ -524,7 +524,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI
match node {
Node::NodeBlock(block) => Some(block),
Node::NodeItem(&Item {
node: ItemFn(_, _, _, _, _, eid),
node: ItemFn(_, _, _, eid),
..
}) | Node::NodeImplItem(&ImplItem {
node: ImplItemKind::Method(_, eid),
@ -768,7 +768,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
let span_name_span = span.ctxt()
.outer()
.expn_info()
.map(|ei| (ei.callee.name(), ei.call_site));
.map(|ei| (ei.format.name(), ei.call_site));
match span_name_span {
Some((mac_name, new_span)) if mac_name == name => return Some(new_span),
@ -791,7 +791,7 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
let span_name_span = span.ctxt()
.outer()
.expn_info()
.map(|ei| (ei.callee.name(), ei.call_site));
.map(|ei| (ei.format.name(), ei.call_site));
match span_name_span {
Some((mac_name, new_span)) if mac_name == name => Some(new_span),

View File

@ -52,7 +52,7 @@ impl<'a> Sugg<'a> {
hir::ExprIf(..) |
hir::ExprUnary(..) |
hir::ExprMatch(..) => Sugg::MaybeParen(snippet),
hir::ExprAgain(..) |
hir::ExprContinue(..) |
hir::ExprYield(..) |
hir::ExprArray(..) |
hir::ExprBlock(..) |
@ -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(..) |